소스 검색

Add ctkCheckableComboBox to check model indexes

Julien Finet 14 년 전
부모
커밋
363329d072

+ 3 - 0
Libs/Widgets/CMakeLists.txt

@@ -17,6 +17,8 @@ SET(KIT_SRCS
   ctkAxesWidget.h
   ctkButtonGroup.cpp
   ctkButtonGroup.h
+  ctkCheckableComboBox.cpp
+  ctkCheckableComboBox.h
   ctkCheckableHeaderView.cpp
   ctkCheckableHeaderView.h
   ctkCheckBoxPixmaps.cpp
@@ -154,6 +156,7 @@ SET(KIT_MOC_SRCS
   ctkAxesWidget.h
   ctkAddRemoveComboBox.h
   ctkButtonGroup.h
+  ctkCheckableComboBox.h
   ctkCheckableHeaderView.h
   ctkCheckablePushButton.h
   ctkCheckBoxPixmaps.h

+ 3 - 0
Libs/Widgets/Plugins/CMakeLists.txt

@@ -17,6 +17,8 @@ SET(PLUGIN_SRCS
   ctkActionsWidgetPlugin.h
   ctkAxesWidgetPlugin.cpp
   ctkAxesWidgetPlugin.h
+  ctkCheckableComboBoxPlugin.cpp
+  ctkCheckableComboBoxPlugin.h
   ctkCollapsibleButtonPlugin.cpp
   ctkCollapsibleButtonPlugin.h
   ctkCollapsibleGroupBoxPlugin.cpp
@@ -81,6 +83,7 @@ SET(PLUGIN_MOC_SRCS
 
   ctkActionsWidgetPlugin.h
   ctkAxesWidgetPlugin.h
+  ctkCheckableComboBoxPlugin.h
   ctkCollapsibleButtonPlugin.h
   ctkCollapsibleGroupBoxPlugin.h
   ctkColorPickerButtonPlugin.h

+ 69 - 0
Libs/Widgets/Plugins/ctkCheckableComboBoxPlugin.cpp

@@ -0,0 +1,69 @@
+/*=========================================================================
+
+  Library:   CTK
+
+  Copyright (c) Kitware Inc.
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+      http://www.commontk.org/LICENSE
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+=========================================================================*/
+
+// CTK includes
+#include "ctkCheckableComboBoxPlugin.h"
+#include "ctkCheckableComboBox.h"
+
+//-----------------------------------------------------------------------------
+ctkCheckableComboBoxPlugin::ctkCheckableComboBoxPlugin(QObject* pluginParent)
+  : QObject(pluginParent)
+{
+
+}
+
+//-----------------------------------------------------------------------------
+QWidget *ctkCheckableComboBoxPlugin::createWidget(QWidget* parentForWidget)
+{
+  ctkCheckableComboBox* newWidget = new ctkCheckableComboBox(parentForWidget);
+  return newWidget;
+}
+
+//-----------------------------------------------------------------------------
+QString ctkCheckableComboBoxPlugin::domXml() const
+{
+  return "<widget class=\"ctkCheckableComboBox\" \
+          name=\"CheckableComboBox\">\n"
+          "</widget>\n";
+}
+
+// --------------------------------------------------------------------------
+QIcon ctkCheckableComboBoxPlugin::icon() const
+{
+  return QIcon(":/Icons/combobox.png");
+}
+
+//-----------------------------------------------------------------------------
+QString ctkCheckableComboBoxPlugin::includeFile() const
+{
+  return "ctkCheckableComboBox.h";
+}
+
+//-----------------------------------------------------------------------------
+bool ctkCheckableComboBoxPlugin::isContainer() const
+{
+  return false;
+}
+
+//-----------------------------------------------------------------------------
+QString ctkCheckableComboBoxPlugin::name() const
+{
+  return "ctkCheckableComboBox";
+}

+ 45 - 0
Libs/Widgets/Plugins/ctkCheckableComboBoxPlugin.h

@@ -0,0 +1,45 @@
+/*=========================================================================
+
+  Library:   CTK
+
+  Copyright (c) Kitware Inc.
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+      http://www.commontk.org/LICENSE
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+=========================================================================*/
+
+#ifndef __ctkCheckableComboBoxPlugin_h
+#define __ctkCheckableComboBoxPlugin_h
+
+// CTK includes
+#include "ctkWidgetsAbstractPlugin.h"
+
+class CTK_WIDGETS_PLUGINS_EXPORT ctkCheckableComboBoxPlugin :
+  public QObject,
+  public ctkWidgetsAbstractPlugin
+{
+  Q_OBJECT
+
+public:
+  ctkCheckableComboBoxPlugin(QObject *_parent = 0);
+  
+  QWidget *createWidget(QWidget *_parent);
+  QString  domXml() const; 
+  QIcon    icon() const;
+  QString  includeFile() const;
+  bool     isContainer() const;
+  QString  name() const;
+  
+};
+
+#endif

+ 5 - 5
Libs/Widgets/Plugins/ctkTreeComboBoxPlugin.cpp

@@ -23,17 +23,17 @@
 #include "ctkTreeComboBox.h"
 
 //-----------------------------------------------------------------------------
-ctkTreeComboBoxPlugin::ctkTreeComboBoxPlugin(QObject *_parent)
-        : QObject(_parent)
+ctkTreeComboBoxPlugin::ctkTreeComboBoxPlugin(QObject* pluginParent)
+  : QObject(pluginParent)
 {
 
 }
 
 //-----------------------------------------------------------------------------
-QWidget *ctkTreeComboBoxPlugin::createWidget(QWidget *_parent)
+QWidget *ctkTreeComboBoxPlugin::createWidget(QWidget *parentForWidget)
 {
-  ctkTreeComboBox* _widget = new ctkTreeComboBox(_parent);
-  return _widget;
+  ctkTreeComboBox* newWidget = new ctkTreeComboBox(parentForWidget);
+  return newWidget;
 }
 
 //-----------------------------------------------------------------------------

+ 2 - 0
Libs/Widgets/Plugins/ctkWidgetsPlugins.h

@@ -28,6 +28,7 @@
 #include "ctkWidgetsPluginsExport.h"
 #include "ctkActionsWidgetPlugin.h"
 #include "ctkAxesWidgetPlugin.h"
+#include "ctkCheckableComboBoxPlugin.h"
 #include "ctkCollapsibleButtonPlugin.h"
 #include "ctkCollapsibleGroupBoxPlugin.h"
 #include "ctkColorPickerButtonPlugin.h"
@@ -69,6 +70,7 @@ public:
     QList<QDesignerCustomWidgetInterface *> plugins;
     plugins << new ctkActionsWidgetPlugin
             << new ctkAxesWidgetPlugin
+            << new ctkCheckableComboBoxPlugin
             << new ctkCollapsibleButtonPlugin
             << new ctkCollapsibleGroupBoxPlugin
             << new ctkColorPickerButtonPlugin

+ 2 - 0
Libs/Widgets/Testing/Cpp/CMakeLists.txt

@@ -6,6 +6,7 @@ SET(TEST_SOURCES
   ctkAxesWidgetTest1.cpp
   ctkButtonGroupTest1.cpp
   ctkCheckBoxPixmapsTest1.cpp
+  ctkCheckableComboBoxTest1.cpp
   ctkCheckableHeaderViewTest1.cpp
   ctkCheckableHeaderViewTest2.cpp
   ctkCheckableModelHelperTest2.cpp
@@ -112,6 +113,7 @@ SIMPLE_TEST( ctkAddRemoveComboBoxTest1 )
 SIMPLE_TEST( ctkAxesWidgetTest1 )
 SIMPLE_TEST( ctkButtonGroupTest1 )
 SIMPLE_TEST( ctkCheckBoxPixmapsTest1 )
+SIMPLE_TEST( ctkCheckableComboBoxTest1 )
 SIMPLE_TEST( ctkCheckableHeaderViewTest1 )
 SIMPLE_TEST( ctkCheckableHeaderViewTest2 )
 SIMPLE_TEST( ctkCheckableModelHelperTest2 )

+ 51 - 0
Libs/Widgets/Testing/Cpp/ctkCheckableComboBoxTest1.cpp

@@ -0,0 +1,51 @@
+/*=========================================================================
+
+  Library:   CTK
+
+  Copyright (c) Kitware Inc.
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+      http://www.commontk.org/LICENSE
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+=========================================================================*/
+
+// Qt includes
+#include <QDebug>
+#include <QApplication>
+#include <QTimer>
+
+// CTK includes
+#include <ctkCheckableComboBox.h>
+
+// STD includes
+#include <cstdlib>
+#include <iostream>
+
+//-----------------------------------------------------------------------------
+int ctkCheckableComboBoxTest1(int argc, char * argv [] )
+{
+  QApplication app(argc, argv);
+
+  ctkCheckableComboBox comboBox;
+  comboBox.addItem("toto");
+  comboBox.addItem("tata");
+  comboBox.addItem("titi");
+  comboBox.addItem(comboBox.style()->standardIcon(QStyle::SP_FileIcon),"tutu");
+  
+  comboBox.show();
+  if (argc < 2 || QString(argv[1]) != "-I" )
+    {
+    QTimer::singleShot(200, &app, SLOT(quit()));
+    }
+  
+  return app.exec();
+}

+ 242 - 0
Libs/Widgets/ctkCheckableComboBox.cpp

@@ -0,0 +1,242 @@
+/*=========================================================================
+
+  Library:   CTK
+
+  Copyright (c) Kitware Inc.
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+      http://www.commontk.org/LICENSE
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+=========================================================================*/
+
+// Qt includes
+#include <QApplication>
+#include <QAbstractItemView>
+#include <QCleanlooksStyle>
+#include <QDebug>
+#include <QDesktopWidget>
+#include <QLayout>
+#include <QMouseEvent>
+#include <QMenu>
+#include <QPainter>
+#include <QPointer>
+#include <QPushButton>
+#include <QStyle>
+#include <QStyleOptionButton>
+#include <QStylePainter>
+#include <QToolBar>
+
+// CTK includes
+#include "ctkCheckableComboBox.h"
+#include <ctkCheckableModelHelper.h>
+
+//-----------------------------------------------------------------------------
+class ctkCheckableComboBoxPrivate
+{
+  Q_DECLARE_PUBLIC(ctkCheckableComboBox);
+protected:
+  ctkCheckableComboBox* const q_ptr;
+  QModelIndexList checkedIndexes()const;
+public:
+  ctkCheckableComboBoxPrivate(ctkCheckableComboBox& object);
+  void init();
+
+  void updateCheckedList();
+  
+  ctkCheckableModelHelper* CheckableModelHelper;
+  QModelIndexList          CheckedList;
+};
+
+//-----------------------------------------------------------------------------
+ctkCheckableComboBoxPrivate::ctkCheckableComboBoxPrivate(ctkCheckableComboBox& object)
+  : q_ptr(&object)
+{
+  this->CheckableModelHelper = 0;
+}
+
+//-----------------------------------------------------------------------------
+void ctkCheckableComboBoxPrivate::init()
+{
+  Q_Q(ctkCheckableComboBox);
+  this->CheckableModelHelper = new ctkCheckableModelHelper(Qt::Horizontal, q);
+  this->CheckableModelHelper->setForceCheckability(true);
+  
+  q->setCheckableModel(q->model());
+  q->view()->installEventFilter(q);
+  q->view()->viewport()->installEventFilter(q);
+}
+
+//-----------------------------------------------------------------------------
+void ctkCheckableComboBoxPrivate::updateCheckedList()
+{
+  Q_Q(ctkCheckableComboBox);
+  QModelIndexList newCheckedList = this->checkedIndexes();
+  if (newCheckedList == this->CheckedList)
+    {
+    return;
+    }
+  this->CheckedList = newCheckedList;
+  qDebug() << "change";
+  emit q->checkedIndexesChanged();
+}
+
+//-----------------------------------------------------------------------------
+QModelIndexList ctkCheckableComboBoxPrivate::checkedIndexes()const
+{
+  Q_Q(const ctkCheckableComboBox);
+  return q->model()->match(
+      q->model()->index(0,0), Qt::CheckStateRole, Qt::Checked, -1, Qt::MatchRecursive);
+}
+ 
+//-----------------------------------------------------------------------------
+ctkCheckableComboBox::ctkCheckableComboBox(QWidget* parentWidget)
+  : QComboBox(parentWidget)
+  , d_ptr(new ctkCheckableComboBoxPrivate(*this))
+{
+  Q_D(ctkCheckableComboBox);
+  d->init();
+}
+
+//-----------------------------------------------------------------------------
+ctkCheckableComboBox::~ctkCheckableComboBox()
+{
+}
+
+//-----------------------------------------------------------------------------
+bool ctkCheckableComboBox::eventFilter(QObject *o, QEvent *e)
+{
+  Q_D(ctkCheckableComboBox);
+  switch (e->type())
+    {
+    case QEvent::MouseButtonRelease:
+      {
+      QMouseEvent *m = static_cast<QMouseEvent *>(e);
+      if (this->view()->isVisible() && 
+          this->view()->rect().contains(m->pos()) &&
+          this->view()->currentIndex().isValid()
+          //&& !blockMouseReleaseTimer.isActive()
+          && (this->view()->currentIndex().flags() & Qt::ItemIsEnabled)
+          && (this->view()->currentIndex().flags() & Qt::ItemIsSelectable))
+        {
+        // make the item current, it will then call QComboBox::update (and
+        // repaint) when the current index data is changed (checkstate toggled).
+        this->setCurrentIndex(this->view()->currentIndex().row());
+        d->CheckableModelHelper->toggleCheckState(this->view()->currentIndex());
+        return true;
+        }
+      break;
+      } 
+    default:
+        break;
+    }
+  return this->QComboBox::eventFilter(o, e);
+}
+
+//-----------------------------------------------------------------------------
+void ctkCheckableComboBox::setCheckableModel(QAbstractItemModel* newModel)
+{
+  Q_D(ctkCheckableComboBox);
+  this->disconnect(this->model(), SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&)),
+                   this, SLOT(onDataChanged(const QModelIndex&, const QModelIndex&)));
+  if (newModel != this->model())
+    {
+    this->setModel(newModel);
+    }
+  this->connect(this->model(), SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&)),
+                this, SLOT(onDataChanged(const QModelIndex&, const QModelIndex&)));
+  d->CheckableModelHelper->setModel(newModel);
+  d->updateCheckedList();
+}
+
+//-----------------------------------------------------------------------------
+QAbstractItemModel* ctkCheckableComboBox::checkableModel()const
+{
+  Q_D(const ctkCheckableComboBox);
+  return this->model();
+}
+
+//-----------------------------------------------------------------------------
+QModelIndexList ctkCheckableComboBox::checkedIndexes()const
+{
+  Q_D(const ctkCheckableComboBox);
+  return d->CheckedList;
+}
+
+//-----------------------------------------------------------------------------
+bool ctkCheckableComboBox::allChecked()const
+{
+  Q_D(const ctkCheckableComboBox);
+  return d->CheckableModelHelper->headerCheckState(0) == Qt::Checked;
+}
+
+//-----------------------------------------------------------------------------
+bool ctkCheckableComboBox::noneChecked()const
+{
+  Q_D(const ctkCheckableComboBox);
+  return d->CheckableModelHelper->headerCheckState(0) == Qt::Unchecked;
+}
+
+//-----------------------------------------------------------------------------
+void ctkCheckableComboBox::onDataChanged(const QModelIndex& start, const QModelIndex& end)
+{
+  Q_D(ctkCheckableComboBox);
+  Q_UNUSED(start);
+  Q_UNUSED(end);
+  d->updateCheckedList();
+}
+
+//-----------------------------------------------------------------------------
+void ctkCheckableComboBox::paintEvent(QPaintEvent *)
+{
+  Q_D(ctkCheckableComboBox);
+  QStylePainter painter(this);
+  painter.setPen(palette().color(QPalette::Text));
+
+  // draw the combobox frame, focusrect and selected etc.
+  QStyleOptionComboBox opt;
+  this->initStyleOption(&opt);
+
+  if (this->allChecked())
+    {
+    opt.currentText = "All";
+    opt.currentIcon = QIcon();
+    }
+  else if (this->noneChecked())
+    {
+    opt.currentText = "None";
+    opt.currentIcon = QIcon();
+    }
+  else
+    {
+    //search the checked items
+    QModelIndexList indexes = this->checkedIndexes();
+    if (indexes.count() == 1)
+      {
+      opt.currentText = this->model()->data(indexes[0], Qt::DisplayRole).toString();
+      opt.currentIcon = qvariant_cast<QIcon>(this->model()->data(indexes[0], Qt::DecorationRole));
+      }
+    else
+      {
+      QStringList indexesText;
+      foreach(QModelIndex checkedIndex, indexes)
+        {
+        indexesText << this->model()->data(checkedIndex, Qt::DisplayRole).toString();
+        }
+      opt.currentText = indexesText.join(", ");
+      opt.currentIcon = QIcon();
+      }
+    }
+  painter.drawComplexControl(QStyle::CC_ComboBox, opt);
+
+  // draw the icon and text
+  painter.drawControl(QStyle::CE_ComboBoxLabel, opt);
+}

+ 73 - 0
Libs/Widgets/ctkCheckableComboBox.h

@@ -0,0 +1,73 @@
+/*=========================================================================
+
+  Library:   CTK
+
+  Copyright (c) Kitware Inc.
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+      http://www.commontk.org/LICENSE
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+=========================================================================*/
+
+#ifndef __ctkCheckableComboBox_h
+#define __ctkCheckableComboBox_h
+
+// Qt includes
+#include <QComboBox>
+
+// CTK includes
+#include "ctkWidgetsExport.h"
+
+class ctkCheckableModelHelper;
+class ctkCheckableComboBoxPrivate;
+
+/// Description
+/// ctkCheckableComboBox is a QComboBox that allow its items to be checkable
+class CTK_WIDGETS_EXPORT ctkCheckableComboBox : public QComboBox
+{
+  Q_OBJECT
+
+public:
+  ctkCheckableComboBox(QWidget *parent = 0);
+  virtual ~ctkCheckableComboBox();
+  
+  /// Use setCheckableModel instead of setModel()
+  QAbstractItemModel* checkableModel()const;
+  void setCheckableModel(QAbstractItemModel *model);
+  
+  ctkCheckableModelHelper* checkableModelHelper()const;
+  
+  QModelIndexList checkedIndexes()const;
+  bool allChecked()const;
+  bool noneChecked()const;
+
+  bool eventFilter(QObject *o, QEvent *e);
+  
+signals:
+  void checkedIndexesChanged();
+
+protected slots:
+  void onDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight);
+
+protected:
+  /// Reimplemented for internal reasons
+  virtual void paintEvent(QPaintEvent*);
+
+protected:
+  QScopedPointer<ctkCheckableComboBoxPrivate> d_ptr;
+
+private:
+  Q_DECLARE_PRIVATE(ctkCheckableComboBox);
+  Q_DISABLE_COPY(ctkCheckableComboBox);
+};
+
+#endif