Salome HOME
Merge branch 'Dev_GroupsRevision'
[modules/shaper.git] / src / ModuleBase / ModuleBase_WidgetMultiSelector.cpp
index e59721ff6a18463d13a9fe7b528017b1a77f22d0..48df5b61bb2a5110692ae7320075bb9bae2fcb3a 100755 (executable)
 //
 
 #include <ModuleBase_WidgetMultiSelector.h>
-#include <ModuleBase_WidgetShapeSelector.h>
+
+#include <ModuleBase_ActionIntParameter.h>
+#include <ModuleBase_Definitions.h>
+#include <ModuleBase_Events.h>
+#include <ModuleBase_IconFactory.h>
+#include <ModuleBase_IModule.h>
 #include <ModuleBase_ISelection.h>
-#include <ModuleBase_IWorkshop.h>
+#include <ModuleBase_ISelectionActivate.h>
 #include <ModuleBase_IPropertyPanel.h>
 #include <ModuleBase_IViewer.h>
+#include <ModuleBase_IWorkshop.h>
+#include <ModuleBase_ListView.h>
 #include <ModuleBase_Tools.h>
-#include <ModuleBase_Definitions.h>
-#include <ModuleBase_IModule.h>
 #include <ModuleBase_ViewerPrs.h>
-#include <ModuleBase_IconFactory.h>
-#include <ModuleBase_Events.h>
+#include <ModuleBase_WidgetShapeSelector.h>
 #include <ModuleBase_ChoiceCtrl.h>
 
 #include <ModelAPI_Data.h>
@@ -49,7 +53,6 @@
 #include <QString>
 #include <QComboBox>
 #include <QEvent>
-#include <QAction>
 #include <QApplication>
 #include <QClipboard>
 #include <QTimer>
 #include <memory>
 #include <string>
 
-const int ATTRIBUTE_SELECTION_INDEX_ROLE = Qt::UserRole + 1;
-
 //#define DEBUG_UNDO_REDO
 
-/**
-* Customization of a List Widget to make it to be placed on full width of container
-*/
-class CustomListWidget : public QListWidget
-{
-public:
-  /// Constructor
-  /// \param theParent a parent widget
-  CustomListWidget( QWidget* theParent )
-    : QListWidget( theParent )
-  {
-  }
-
-  /// Redefinition of virtual method
-  virtual QSize        sizeHint() const
-  {
-    int aHeight = 2*QFontMetrics( font() ).height();
-    QSize aSize = QListWidget::sizeHint();
-    return QSize( aSize.width(), aHeight );
-  }
-
-  /// Redefinition of virtual method
-  virtual QSize        minimumSizeHint() const
-  {
-    int aHeight = 4/*2*/*QFontMetrics( font() ).height();
-    QSize aSize = QListWidget::minimumSizeHint();
-    return QSize( aSize.width(), aHeight );
-  }
-
-#ifndef WIN32
-// The code is necessary only for Linux because
-//it can not update viewport on widget resize
-protected:
-  void resizeEvent(QResizeEvent* theEvent)
-  {
-    QListWidget::resizeEvent(theEvent);
-    QTimer::singleShot(5, viewport(), SLOT(repaint()));
-  }
-#endif
-};
-
 #ifdef DEBUG_UNDO_REDO
 void printHistoryInfo(const QString& theMethodName, int theCurrentHistoryIndex,
   QList<QList<std::shared_ptr<ModuleBase_ViewerPrs> > > theSelectedHistoryValues)
@@ -181,33 +141,18 @@ ModuleBase_WidgetMultiSelector::ModuleBase_WidgetMultiSelector(QWidget* theParen
   }
 
   QString aToolTip = QString::fromStdString(theData->widgetTooltip());
-  myListControl = new CustomListWidget(this);
   QString anObjName = QString::fromStdString(attributeID());
-  myListControl->setObjectName(anObjName);
-  myListControl->setToolTip(aToolTip);
-  myListControl->setSelectionMode(QAbstractItemView::ExtendedSelection);
+  myListView = new ModuleBase_ListView(this, anObjName, aToolTip);
+  connect(myListView->getControl(), SIGNAL(itemSelectionChanged()), SLOT(onListSelection()));
+  connect(myListView, SIGNAL(deleteActionClicked()), SLOT(onDeleteItem()));
 
-  aMainLay->addWidget(myListControl, 2, 0, 1, -1);
+  aMainLay->addWidget(myListView->getControl(), 2, 0, 1, -1);
   aMainLay->setRowStretch(2, 1);
   //aMainLay->addWidget(new QLabel(this)); //FIXME(sbh)???
   //aMainLay->setRowMinimumHeight(3, 20);
   //this->setLayout(aMainLay);
   connect(myTypeCtrl, SIGNAL(valueChanged(int)), this, SLOT(onSelectionTypeChanged()));
 
-  myCopyAction = ModuleBase_Tools::createAction(QIcon(":pictures/copy.png"), tr("Copy"),
-                          myWorkshop->desktop(), this, SLOT(onCopyItem()));
-  myCopyAction->setShortcut(QKeySequence::Copy);
-  myCopyAction->setEnabled(false);
-  myListControl->addAction(myCopyAction);
-
-  myDeleteAction = ModuleBase_Tools::createAction(QIcon(":pictures/delete.png"), tr("Delete"),
-                          myWorkshop->desktop(), this, SLOT(onDeleteItem()));
-  myDeleteAction->setEnabled(false);
-  myListControl->addAction(myDeleteAction);
-
-  myListControl->setContextMenuPolicy(Qt::ActionsContextMenu);
-  connect(myListControl, SIGNAL(itemSelectionChanged()), SLOT(onListSelection()));
-
   myIsNeutralPointClear = theData->getBooleanAttribute("clear_in_neutral_point", true);
 }
 
@@ -223,7 +168,6 @@ void ModuleBase_WidgetMultiSelector::activateCustom()
   myWorkshop->module()->activateCustomPrs(myFeature,
                             ModuleBase_IModule::CustomizeHighlightedObjects, true);
   clearSelectedHistory();
-  myWorkshop->updateCommandStatus();
 }
 
 //********************************************************************
@@ -233,6 +177,19 @@ void ModuleBase_WidgetMultiSelector::deactivate()
 
   myWorkshop->module()->deactivateCustomPrs(ModuleBase_IModule::CustomizeHighlightedObjects, true);
   clearSelectedHistory();
+}
+
+//********************************************************************
+void ModuleBase_WidgetMultiSelector::updateAfterDeactivation()
+{
+  // restore previous Undo/Redo workshop state
+  myWorkshop->updateCommandStatus();
+}
+
+//********************************************************************
+void ModuleBase_WidgetMultiSelector::updateAfterActivation()
+{
+  // fill Undo/Redo actions with current information
   myWorkshop->updateCommandStatus();
 }
 
@@ -365,21 +322,26 @@ bool ModuleBase_WidgetMultiSelector::canProcessAction(ModuleBase_ActionType theA
     }
     break;
     default:
+      aCanProcess = ModuleBase_WidgetSelector::canProcessAction(theActionType, isActionEnabled);
     break;
   }
   return aCanProcess;
 }
 
 //********************************************************************
-bool ModuleBase_WidgetMultiSelector::processAction(ModuleBase_ActionType theActionType)
+bool ModuleBase_WidgetMultiSelector::processAction(ModuleBase_ActionType theActionType,
+                                                   const ActionParamPtr& theParam)
 {
   switch (theActionType) {
     case ActionUndo:
     case ActionRedo: {
+      ActionIntParamPtr aParam =
+        std::dynamic_pointer_cast<ModuleBase_ActionIntParameter>(theParam);
+      int aNb = aParam->value();
       if (theActionType == ActionUndo)
-        myCurrentHistoryIndex--;
+        myCurrentHistoryIndex -= aNb;
       else
-        myCurrentHistoryIndex++;
+        myCurrentHistoryIndex += aNb;
       QList<ModuleBase_ViewerPrsPtr> aSelected = mySelectedHistoryValues[myCurrentHistoryIndex];
       // equal vertices should not be used here
       ModuleBase_ISelection::filterSelectionOnEqualPoints(aSelected);
@@ -395,17 +357,10 @@ bool ModuleBase_WidgetMultiSelector::processAction(ModuleBase_ActionType theActi
       return true;
     }
     default:
-      return ModuleBase_ModelWidget::processAction(theActionType);
+      return ModuleBase_ModelWidget::processAction(theActionType, theParam);
   }
 }
 
-//********************************************************************
-bool ModuleBase_WidgetMultiSelector::activateSelectionAndFilters(bool toActivate)
-{
-  myWorkshop->updateCommandStatus(); // update enable state of Undo/Redo application actions
-  return ModuleBase_WidgetSelector::activateSelectionAndFilters(toActivate);
-}
-
 //********************************************************************
 bool ModuleBase_WidgetMultiSelector::isValidSelectionCustom(const ModuleBase_ViewerPrsPtr& thePrs)
 {
@@ -443,7 +398,7 @@ bool ModuleBase_WidgetMultiSelector::processDelete()
   std::set<int> anAttributeIds;
   getSelectedAttributeIndices(anAttributeIds);
 
-  QModelIndexList aIndexes = myListControl->selectionModel()->selectedIndexes();
+  QModelIndexList anIndices = myListView->getControl()->selectionModel()->selectedIndexes();
 
   // refill attribute by the items which indices are not in the list of ids
   bool aDone = false;
@@ -480,17 +435,8 @@ bool ModuleBase_WidgetMultiSelector::processDelete()
   }
 
   // Restore selection
-  int aRows = myListControl->model()->rowCount();
-  if (aRows > 0) {
-    foreach(QModelIndex aIndex, aIndexes) {
-      if (aIndex.row() < aRows)
-        myListControl->selectionModel()->select(aIndex, QItemSelectionModel::Select);
-      else {
-        QModelIndex aIdx = myListControl->model()->index(aRows - 1, 0);
-        myListControl->selectionModel()->select(aIdx, QItemSelectionModel::Select);
-      }
-    }
-  }
+  myListView->restoreSelection(anIndices);
+
   appendSelectionInHistory();
   return aDone;
 }
@@ -499,14 +445,20 @@ bool ModuleBase_WidgetMultiSelector::processDelete()
 QList<QWidget*> ModuleBase_WidgetMultiSelector::getControls() const
 {
   QList<QWidget*> result;
-  result << myListControl;
+  result << myListView->getControl();
   return result;
 }
 
 //********************************************************************
 void ModuleBase_WidgetMultiSelector::onSelectionTypeChanged()
 {
-  activateSelectionAndFilters(true);
+  // Clear current selection in order to avoid updating of object browser with obsolete indexes
+  // which can appear because of results deletetion after changing a type of selection
+  QList<ModuleBase_ViewerPrsPtr> aEmptyList;
+  myWorkshop->setSelected(aEmptyList);
+
+  updateSelectionModesAndFilters(true);
+  myWorkshop->selectionActivate()->updateSelectionModes();
 
   if (!myFeature)
     return;
@@ -550,7 +502,7 @@ void ModuleBase_WidgetMultiSelector::onSelectionTypeChanged()
 }
 
 //********************************************************************
-void ModuleBase_WidgetMultiSelector::onSelectionChanged()
+bool ModuleBase_WidgetMultiSelector::processSelection()
 {
   if (!myIsNeutralPointClear) {
     QList<ModuleBase_ViewerPrsPtr> aSelected = getFilteredSelected();
@@ -562,13 +514,14 @@ void ModuleBase_WidgetMultiSelector::onSelectionChanged()
         static Events_ID anEvent = Events_Loop::eventByName(EVENT_UPDATE_BY_WIDGET_SELECTION);
         ModelAPI_EventCreator::get()->sendUpdated(myFeature, anEvent);
         Events_Loop::loop()->flush(anEvent);
-        return;
+        return true;
       }
     }
   }
   appendFirstSelectionInHistory();
-  ModuleBase_WidgetSelector::onSelectionChanged();
+  bool aDone = ModuleBase_WidgetSelector::processSelection();
   appendSelectionInHistory();
+  return aDone;
 }
 
 void ModuleBase_WidgetMultiSelector::appendFirstSelectionInHistory()
@@ -613,7 +566,7 @@ void ModuleBase_WidgetMultiSelector::updateFocus()
 {
   // Set focus to List control in order to make possible
   // to use Tab key for transfer the focus to next widgets
-  ModuleBase_Tools::setFocus(myListControl,
+  ModuleBase_Tools::setFocus(myListView->getControl(),
                              "ModuleBase_WidgetMultiSelector::onSelectionTypeChanged()");
 }
 
@@ -670,12 +623,11 @@ void ModuleBase_WidgetMultiSelector::setCurrentShapeType(const int theShapeType)
   foreach (QString aShapeTypeName, myShapeTypes) {
     int aRefType = ModuleBase_Tools::shapeType(aShapeTypeName);
     if(aRefType == theShapeType && idx != myTypeCtrl->value()) {
-      bool aWasActivated = activateSelectionAndFilters(false);
+      updateSelectionModesAndFilters(false);
       bool isBlocked = myTypeCtrl->blockSignals(true);
       myTypeCtrl->setValue(idx);
       myTypeCtrl->blockSignals(isBlocked);
-      if (aWasActivated)
-        activateSelectionAndFilters(true);
+      updateSelectionModesAndFilters(true);
       break;
     }
     idx++;
@@ -692,7 +644,7 @@ QList<ModuleBase_ViewerPrsPtr> ModuleBase_WidgetMultiSelector::getAttributeSelec
 //********************************************************************
 void ModuleBase_WidgetMultiSelector::updateSelectionList()
 {
-  myListControl->clear();
+  myListView->getControl()->clear();
 
   DataPtr aData = myFeature->data();
   AttributePtr anAttribute = aData->attribute(attributeID());
@@ -701,9 +653,7 @@ void ModuleBase_WidgetMultiSelector::updateSelectionList()
     AttributeSelectionListPtr aSelectionListAttr = aData->selectionList(attributeID());
     for (int i = 0; i < aSelectionListAttr->size(); i++) {
       AttributeSelectionPtr aAttr = aSelectionListAttr->value(i);
-      QListWidgetItem* anItem = new QListWidgetItem(aAttr->namingName().c_str(), myListControl);
-      anItem->setData(ATTRIBUTE_SELECTION_INDEX_ROLE, i);
-      myListControl->addItem(anItem);
+      myListView->addItem(aAttr->namingName().c_str(), i);
     }
   }
   else if (aType == ModelAPI_AttributeRefList::typeId()) {
@@ -711,10 +661,7 @@ void ModuleBase_WidgetMultiSelector::updateSelectionList()
     for (int i = 0; i < aRefListAttr->size(); i++) {
       ObjectPtr anObject = aRefListAttr->object(i);
       if (anObject.get()) {
-        QListWidgetItem* anItem = new QListWidgetItem(anObject->data()->name().c_str(),
-                                                      myListControl);
-        anItem->setData(ATTRIBUTE_SELECTION_INDEX_ROLE, i);
-        myListControl->addItem(anItem);
+        myListView->addItem(anObject->data()->name().c_str(), i);
       }
     }
   }
@@ -733,14 +680,12 @@ void ModuleBase_WidgetMultiSelector::updateSelectionList()
           aName = anObject->data()->name().c_str();
         }
       }
-      QListWidgetItem* anItem = new QListWidgetItem(aName, myListControl);
-      anItem->setData(ATTRIBUTE_SELECTION_INDEX_ROLE, i);
-      myListControl->addItem(anItem);
+      myListView->addItem(aName, i);
     }
   }
 
   // We have to call repaint because sometimes the List control is not updated
-  myListControl->repaint();
+  myListView->getControl()->repaint();
 }
 
 //********************************************************************
@@ -768,29 +713,13 @@ void ModuleBase_WidgetMultiSelector::clearSelection()
 
   QList<ModuleBase_ViewerPrsPtr> anEmptyList;
   // This method will call Selection changed event which will call onSelectionChanged
-  // To clear mySelection, myListControl and storeValue()
+  // To clear mySelection, myListView and storeValue()
   // So, we don't need to call it
   myWorkshop->setSelected(anEmptyList);
 
   myIsNeutralPointClear = isClearInNeutralPoint;
 }
 
-//********************************************************************
-void ModuleBase_WidgetMultiSelector::onCopyItem()
-{
-  QList<QListWidgetItem*> aItems = myListControl->selectedItems();
-  QString aRes;
-  foreach(QListWidgetItem* aItem, aItems) {
-    if (!aRes.isEmpty())
-      aRes += "\n";
-    aRes += aItem->text();
-  }
-  if (!aRes.isEmpty()) {
-    QClipboard *clipboard = QApplication::clipboard();
-    clipboard->setText(aRes);
-  }
-}
-
 //********************************************************************
 void ModuleBase_WidgetMultiSelector::onDeleteItem()
 {
@@ -800,10 +729,6 @@ void ModuleBase_WidgetMultiSelector::onDeleteItem()
 //********************************************************************
 void ModuleBase_WidgetMultiSelector::onListSelection()
 {
-  QList<QListWidgetItem*> aItems = myListControl->selectedItems();
-  myCopyAction->setEnabled(!aItems.isEmpty());
-  myDeleteAction->setEnabled(!aItems.isEmpty());
-
   myWorkshop->module()->customizeObject(myFeature, ModuleBase_IModule::CustomizeHighlightedObjects,
                                         true);
 }
@@ -811,12 +736,7 @@ void ModuleBase_WidgetMultiSelector::onListSelection()
 //********************************************************************
 void ModuleBase_WidgetMultiSelector::getSelectedAttributeIndices(std::set<int>& theAttributeIds)
 {
-  QList<QListWidgetItem*> aItems = myListControl->selectedItems();
-  foreach(QListWidgetItem* anItem, aItems) {
-    int anIndex = anItem->data(ATTRIBUTE_SELECTION_INDEX_ROLE).toInt();
-    if (theAttributeIds.find(anIndex) == theAttributeIds.end())
-      theAttributeIds.insert(anIndex);
-  }
+  myListView->getSelectedIndices(theAttributeIds);
 }
 
 void ModuleBase_WidgetMultiSelector::convertIndicesToViewerSelection(std::set<int> theAttributeIds,
@@ -1002,3 +922,47 @@ bool ModuleBase_WidgetMultiSelector::findInSelection(const ObjectPtr& theObject,
   }
   return aFound;
 }
+
+QList<ActionInfo>
+  ModuleBase_WidgetMultiSelector::actionsList(ModuleBase_ActionType theActionType) const
+{
+  QList<ActionInfo> aList;
+  if (myCurrentHistoryIndex > -1) {
+    int i = 0;
+    QString aTitle("Selection %1 items");
+    QString aTit("Selection %1 item");
+    QIcon aIcon(":pictures/selection.png");
+    int aNb;
+    switch (theActionType) {
+    case ActionUndo:
+      i = 1;
+      while (i <= myCurrentHistoryIndex) {
+        aNb = mySelectedHistoryValues.at(i).count();
+        if (aNb == 1) {
+          ActionInfo aInfo(aIcon, aTit.arg(aNb));
+          aList.insert(0, aInfo);
+        } else {
+          ActionInfo aInfo(aIcon, aTitle.arg(aNb));
+          aList.insert(0, aInfo);
+        }
+        i++;
+      }
+      break;
+    case ActionRedo:
+      i = mySelectedHistoryValues.length() - 1;
+      while (i > myCurrentHistoryIndex) {
+        aNb = mySelectedHistoryValues.at(i).count();
+        if (aNb == 1) {
+          ActionInfo aInfo(aIcon, aTit.arg(mySelectedHistoryValues.at(i).count()));
+          aList.insert(0, aInfo);
+        } else {
+          ActionInfo aInfo(aIcon, aTitle.arg(mySelectedHistoryValues.at(i).count()));
+          aList.insert(0, aInfo);
+        }
+        i--;
+      }
+      break;
+    }
+  }
+  return aList;
+}
\ No newline at end of file