X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FXGUI%2FXGUI_ObjectsBrowser.cpp;h=7eb50de3409ce79f2c8a48199da60345c0a26c93;hb=0ade576714888ca38bd8e4766ad990773ea41124;hp=3851b9fbee9fe2cbde17b715993c6bbeef8167ee;hpb=ed67f7abf2985c7225b7862c076257825a421993;p=modules%2Fshaper.git diff --git a/src/XGUI/XGUI_ObjectsBrowser.cpp b/src/XGUI/XGUI_ObjectsBrowser.cpp index 3851b9fbe..7eb50de34 100644 --- a/src/XGUI/XGUI_ObjectsBrowser.cpp +++ b/src/XGUI/XGUI_ObjectsBrowser.cpp @@ -2,22 +2,30 @@ #include "XGUI_ObjectsBrowser.h" #include "XGUI_Tools.h" +#include "XGUI_DataModel.h" #include #include #include +#include +#include #include -#include #include -#include #include #include #include #include #include #include +#include + +#ifdef WIN32 +#ifdef HAVE_SALOME +#include +#endif +#endif /// Width of second column (minimum acceptable = 27) @@ -42,7 +50,7 @@ public: { QLineEdit* aEditor = dynamic_cast(editor); if (aEditor) { - ModuleBase_IDocumentDataModel* aModel = myTreedView->dataModel(); + XGUI_DataModel* aModel = myTreedView->dataModel(); ObjectPtr aObj = aModel->object(index); if (aObj.get() != NULL) { aEditor->setText(aObj->data()->name().c_str()); @@ -60,21 +68,33 @@ private: XGUI_DataTree::XGUI_DataTree(QWidget* theParent) : QTreeView(theParent) { +#ifdef WIN32 +#ifdef HAVE_SALOME + setStyle(new QWindowsStyle()); +#else + myStyle = new XGUI_TreeViewStyle(); + setStyle(myStyle); +#endif +#endif + setHeaderHidden(true); setEditTriggers(QAbstractItemView::NoEditTriggers); setSelectionBehavior(QAbstractItemView::SelectRows); setSelectionMode(QAbstractItemView::ExtendedSelection); setItemDelegateForColumn(0, new XGUI_TreeViewItemDelegate(this)); + + connect(this, SIGNAL(doubleClicked(const QModelIndex&)), + SLOT(onDoubleClick(const QModelIndex&))); } XGUI_DataTree::~XGUI_DataTree() { } -ModuleBase_IDocumentDataModel* XGUI_DataTree::dataModel() const +XGUI_DataModel* XGUI_DataTree::dataModel() const { - return static_cast(model()); + return static_cast(model()); } void XGUI_DataTree::contextMenuEvent(QContextMenuEvent* theEvent) @@ -84,23 +104,32 @@ void XGUI_DataTree::contextMenuEvent(QContextMenuEvent* theEvent) void XGUI_DataTree::commitData(QWidget* theEditor) { - QLineEdit* aEditor = dynamic_cast(theEditor); - if (aEditor) { - QString aRes = aEditor->text(); - QModelIndexList aIndexList = selectionModel()->selectedIndexes(); - ModuleBase_IDocumentDataModel* aModel = dataModel(); - ObjectPtr aObj = aModel->object(aIndexList.first()); - SessionPtr aMgr = ModelAPI_Session::get(); - aMgr->startOperation("Rename"); - aObj->data()->setName(qPrintable(aRes)); - aMgr->finishOperation(); + static int aEntrance = 0; + if (aEntrance == 0) { + // We have to check number of enter and exit of this function because it can be called recursively by Qt + // in order to avoid double modifying of a data + aEntrance = 1; + QLineEdit* aEditor = dynamic_cast(theEditor); + if (aEditor) { + QString aName = aEditor->text(); + QModelIndexList aIndexList = selectionModel()->selectedIndexes(); + XGUI_DataModel* aModel = dataModel(); + ObjectPtr aObj = aModel->object(aIndexList.first()); + + if (XGUI_Tools::canRename(aObj, aName)) { + SessionPtr aMgr = ModelAPI_Session::get(); + aMgr->startOperation("Rename"); + aObj->data()->setName(qPrintable(aName)); + aMgr->finishOperation(); + } + } } + aEntrance = 0; } void XGUI_DataTree::clear() { - ModuleBase_IDocumentDataModel* aModel = dataModel(); - aModel->clear(); + dataModel()->clear(); reset(); } @@ -111,6 +140,174 @@ void XGUI_DataTree::resizeEvent(QResizeEvent* theEvent) setColumnWidth(0, aSize.width() - SECOND_COL_WIDTH); setColumnWidth(1, SECOND_COL_WIDTH); } + QTreeView::resizeEvent(theEvent); +} + +void XGUI_DataTree::onDoubleClick(const QModelIndex& theIndex) +{ + if (theIndex.column() != 1) + return; + SessionPtr aMgr = ModelAPI_Session::get(); + // When operation is opened then we can not change history + if (aMgr->isOperation()) + return; + XGUI_DataModel* aModel = dataModel(); + if (aModel->flags(theIndex) == 0) + return; + ObjectPtr aObj = aModel->object(theIndex); + + DocumentPtr aDoc = aMgr->activeDocument(); + + std::string aOpName = tr("History change").toStdString(); + if (aObj.get()) { + if (aObj->document() != aDoc) + return; + aMgr->startOperation(aOpName); + aDoc->setCurrentFeature(std::dynamic_pointer_cast(aObj), true); + aMgr->finishOperation(); + } else { + // Ignore clicks on folders outside current document + if ((theIndex.internalId() == -1) && (aDoc != aMgr->moduleDocument())) + // Clicked folder under root but active document is another + return; + if ((theIndex.internalId() != -1) && (aDoc.get() != theIndex.internalPointer())) + // Cliced not on active document folder + return; + + aMgr->startOperation(aOpName); + aDoc->setCurrentFeature(FeaturePtr(), true); + aMgr->finishOperation(); + } + QModelIndex aNewIndex = aModel->lastHistoryIndex(); + QModelIndex aParent = theIndex.parent(); + int aSize = aModel->rowCount(aParent); + for (int i = 0; i < aSize; i++) { + update(aModel->index(i, 0, aParent)); + update(aModel->index(i, 1, aParent)); + } +} + +#if (!defined HAVE_SALOME) && (defined WIN32) +void XGUI_DataTree::drawRow(QPainter* thePainter, + const QStyleOptionViewItem& theOptions, + const QModelIndex& theIndex) const +{ + QStyleOptionViewItemV4 aOptions = theOptions; + myStyle->setIndex(theIndex); + QTreeView::drawRow(thePainter, aOptions, theIndex); +} + +//******************************************************************** +//******************************************************************** +//******************************************************************** +void XGUI_TreeViewStyle::drawPrimitive(PrimitiveElement theElement, + const QStyleOption* theOption, + QPainter* thePainter, const QWidget* theWidget) const +{ + if ((theElement == QStyle::PE_PanelItemViewRow) || (theElement == QStyle::PE_PanelItemViewItem)) { + const QStyleOptionViewItemV4* aOptions = qstyleoption_cast(theOption); + if (myIndex.isValid() && ((myIndex.flags() & Qt::ItemIsSelectable) == 0)) { + QStyle::State aState = aOptions->state; + if ((aState & QStyle::State_MouseOver) != 0) + aState &= ~QStyle::State_MouseOver; + QStyleOptionViewItemV4* aOpt = (QStyleOptionViewItemV4*) aOptions; + aOpt->state = aState; + QWindowsVistaStyle::drawPrimitive(theElement, aOpt, thePainter, theWidget); + } + } + QWindowsVistaStyle::drawPrimitive(theElement, theOption, thePainter, theWidget); +} +#endif + + +//******************************************************************** +//******************************************************************** +//******************************************************************** +XGUI_ActiveDocLbl::XGUI_ActiveDocLbl(const QString& theText, QWidget* theParent ) + : QLabel(theText, theParent), + myPreSelectionStyle(""), + myNeutralStyle(""), + mySelectionStyle(""), + myIsSelected(false) +{ +} + +void XGUI_ActiveDocLbl::setTreeView(QTreeView* theView) +{ + myTreeView = theView; + setFont(myTreeView->font()); + + QPalette aPalet = myTreeView->palette(); + QColor aHighlight = aPalet.highlight().color(); + QColor aHighlightText = aPalet.highlightedText().color(); + + myPreSelectionStyle = "QLabel {background-color: "; + myPreSelectionStyle += "qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 white, stop:1 " + aHighlight.lighter(170).name() + ");"; + myPreSelectionStyle += "border: 1px solid lightblue; border-radius: 2px }"; + + QString aName = aPalet.color(QPalette::Base).name(); + myNeutralStyle = "QLabel { border: 1px solid " + aName + " }"; + + +#if (!defined HAVE_SALOME) && (defined WIN32) + mySelectionStyle = "QLabel {background-color: "; + mySelectionStyle += "qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(236, 245, 255)"; + mySelectionStyle += ", stop:1 rgb(208, 229, 255));"; + mySelectionStyle += "border: 1px solid rgb(132, 172, 221); border-radius: 2px }"; +#else + mySelectionStyle = "QLabel {background-color: " + aHighlight.name(); + mySelectionStyle += "; color : " + aHighlightText.name() + "}"; +#endif + + myTreeView->viewport()->installEventFilter(this); +} + + +#if (!defined HAVE_SALOME) && (defined WIN32) +bool XGUI_ActiveDocLbl::event(QEvent* theEvent) +{ + switch (theEvent->type()) { + case QEvent::Enter: + if (!myIsSelected) + setStyleSheet(myPreSelectionStyle); + break; + case QEvent::Leave: + if (!myIsSelected) + setStyleSheet(myNeutralStyle); + break; + } + return QLabel::event(theEvent); +} +#endif + +bool XGUI_ActiveDocLbl::eventFilter(QObject* theObj, QEvent* theEvent) +{ + if (theObj == myTreeView->viewport()) { + if (theEvent->type() == QEvent::MouseButtonRelease) + unselect(); + } + return QLabel::eventFilter(theObj, theEvent); +} + +static bool MYClearing = false; +void XGUI_ActiveDocLbl::mouseReleaseEvent( QMouseEvent* e) +{ + MYClearing = true; + myIsSelected = true; + setStyleSheet(mySelectionStyle); + // We can not block signals because on + // clear selection the View state will not be updated + myTreeView->clearSelection(); + QLabel::mouseReleaseEvent(e); + MYClearing = false; +} + +void XGUI_ActiveDocLbl::unselect() +{ + if (!MYClearing) { + myIsSelected = false; + setStyleSheet(myNeutralStyle); + } } @@ -124,11 +321,8 @@ XGUI_ObjectsBrowser::XGUI_ObjectsBrowser(QWidget* theParent) ModuleBase_Tools::zeroMargins(aLayout); aLayout->setSpacing(0); - QFrame* aLabelWgt = new QFrame(this); + QWidget* aLabelWgt = new QWidget(this); aLabelWgt->setAutoFillBackground(true); - QPalette aPalet = aLabelWgt->palette(); - aPalet.setColor(QPalette::Window, Qt::white); - aLabelWgt->setPalette(aPalet); aLayout->addWidget(aLabelWgt); QHBoxLayout* aLabelLay = new QHBoxLayout(aLabelWgt); @@ -138,42 +332,46 @@ XGUI_ObjectsBrowser::XGUI_ObjectsBrowser(QWidget* theParent) QLabel* aLbl = new QLabel(aLabelWgt); aLbl->setPixmap(QPixmap(":pictures/assembly.png")); aLbl->setMargin(2); - - aLbl->setAutoFillBackground(true); + // Do not paint background of the label (in order to show icon) + aLbl->setAutoFillBackground(false); aLabelLay->addWidget(aLbl); SessionPtr aMgr = ModelAPI_Session::get(); DocumentPtr aDoc = aMgr->moduleDocument(); - // TODO: Find a name of the root document - myActiveDocLbl = new QLineEdit(tr("Part set"), aLabelWgt); - myActiveDocLbl->setReadOnly(true); - myActiveDocLbl->setFrame(false); - //myActiveDocLbl->setMargin(2); + myActiveDocLbl = new XGUI_ActiveDocLbl(tr("Part set"), aLabelWgt); +// myActiveDocLbl->setReadOnly(true); +// myActiveDocLbl->setFrame(false); myActiveDocLbl->setContextMenuPolicy(Qt::CustomContextMenu); - myActiveDocLbl->installEventFilter(this); - aLabelLay->addWidget(myActiveDocLbl); aLabelLay->setStretch(1, 1); myTreeView = new XGUI_DataTree(this); + myTreeView->setFrameShape(QFrame::NoFrame); aLayout->addWidget(myTreeView); - aLabelWgt->setFrameShape(myTreeView->frameShape()); - aLabelWgt->setFrameShadow(myTreeView->frameShadow()); + QPalette aTreePalet = myTreeView->palette(); + QColor aTreeBack = aTreePalet.color(QPalette::Base); + + QPalette aPalet; + aPalet.setColor(QPalette::Base, aTreeBack); + aPalet.setColor(QPalette::Window, aTreeBack); + aLabelWgt->setPalette(aPalet); + + myDocModel = new XGUI_DataModel(this); + myTreeView->setModel(myDocModel); + + // It has to be done after setting of model + myActiveDocLbl->setTreeView(myTreeView); + + QItemSelectionModel* aSelMod = myTreeView->selectionModel(); + connect(aSelMod, SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)), + this, SLOT(onSelectionChanged(const QItemSelection&, const QItemSelection&))); - connect(myActiveDocLbl, SIGNAL(customContextMenuRequested(const QPoint&)), this, - SLOT(onLabelContextMenuRequested(const QPoint&))); connect(myTreeView, SIGNAL(contextMenuRequested(QContextMenuEvent*)), this, SLOT(onContextMenuRequested(QContextMenuEvent*))); - - // Create internal actions - QAction* aAction = new QAction(QIcon(":pictures/rename_edit.png"), tr("Rename"), this); - aAction->setData("RENAME_CMD"); - connect(aAction, SIGNAL(triggered(bool)), this, SLOT(onEditItem())); - addAction(aAction); } //*************************************************** @@ -181,57 +379,23 @@ XGUI_ObjectsBrowser::~XGUI_ObjectsBrowser() { } -//*************************************************** -bool XGUI_ObjectsBrowser::eventFilter(QObject* obj, QEvent* theEvent) -{ - if (obj == myActiveDocLbl) { - if (!myActiveDocLbl->isReadOnly()) { - // End of editing by mouse click - if (theEvent->type() == QEvent::MouseButtonRelease) { - QMouseEvent* aEvent = (QMouseEvent*) theEvent; - QPoint aPnt = mapFromGlobal(aEvent->globalPos()); - if (childAt(aPnt) != myActiveDocLbl) { - closeDocNameEditing(true); - } - } else if (theEvent->type() == QEvent::KeyRelease) { - QKeyEvent* aEvent = (QKeyEvent*) theEvent; - switch (aEvent->key()) { - case Qt::Key_Return: - case Qt::Key_Enter: // Accept current input - closeDocNameEditing(true); - break; - case Qt::Key_Escape: // Cancel the input - closeDocNameEditing(false); - break; - } - } - } - } - return QWidget::eventFilter(obj, theEvent); -} - -//*************************************************** -void XGUI_ObjectsBrowser::closeDocNameEditing(bool toSave) -{ - myActiveDocLbl->deselect(); - myActiveDocLbl->clearFocus(); - myActiveDocLbl->releaseMouse(); - myActiveDocLbl->setReadOnly(true); - if (toSave) { - // TODO: Save the name of root document - SessionPtr aMgr = ModelAPI_Session::get(); - DocumentPtr aDoc = aMgr->moduleDocument(); - } else { - myActiveDocLbl->setText(myActiveDocLbl->property("OldText").toString()); - } -} //*************************************************** void XGUI_ObjectsBrowser::onContextMenuRequested(QContextMenuEvent* theEvent) { - bool toEnable = mySelectedData.size() == 1; - foreach(QAction* aCmd, actions()) - { + QModelIndexList aIndexes; + QObjectPtrList aSelectedData = selectedObjects(&aIndexes); + bool toEnable = false; + + if (aSelectedData.size() == 1) { + QModelIndex aSelected = myTreeView->indexAt(theEvent->pos()); + if (!aIndexes.contains(aSelected)) + return; // menu is called on non selected item + + Qt::ItemFlags aFlags = dataModel()->flags(aIndexes.first()); + toEnable = ((aFlags & Qt::ItemIsEditable) != 0); + } + foreach(QAction* aCmd, actions()) { aCmd->setEnabled(toEnable); } emit contextMenuRequested(theEvent); @@ -240,12 +404,9 @@ void XGUI_ObjectsBrowser::onContextMenuRequested(QContextMenuEvent* theEvent) //*************************************************** void XGUI_ObjectsBrowser::onLabelContextMenuRequested(const QPoint& thePnt) { - mySelectedData.clear(); + myTreeView->selectionModel()->clearSelection(); //Empty feature pointer means that selected root document - mySelectedData.append(ObjectPtr()); - - foreach(QAction* aCmd, actions()) - { + foreach(QAction* aCmd, actions()) { aCmd->setEnabled(true); } QContextMenuEvent aEvent(QContextMenuEvent::Mouse, thePnt, myActiveDocLbl->mapToGlobal(thePnt)); @@ -255,13 +416,19 @@ void XGUI_ObjectsBrowser::onLabelContextMenuRequested(const QPoint& thePnt) //*************************************************** void XGUI_ObjectsBrowser::onEditItem() { - if (mySelectedData.size() > 0) { - ObjectPtr aFeature = mySelectedData.first(); + QObjectPtrList aSelectedData = selectedObjects(); + if (aSelectedData.size() > 0) { + ObjectPtr aFeature = aSelectedData.first(); if (aFeature) { // Selection happens in TreeView + QObjectPtrList aList; + aList.append(aFeature); + // check whether the object can be deleted. There should not be parts which are not loaded + if (!XGUI_Tools::canRemoveOrRename((QWidget*)parent(), aList)) + return; + // Find index which corresponds the feature QModelIndex aIndex; - foreach(QModelIndex aIdx, selectedIndexes()) - { + foreach(QModelIndex aIdx, selectedIndexes()) { ObjectPtr aFea = dataModel()->object(aIdx); if (dataModel()->object(aIdx)->isSame(aFeature)) { aIndex = aIdx; @@ -272,20 +439,38 @@ void XGUI_ObjectsBrowser::onEditItem() myTreeView->setCurrentIndex(aIndex); myTreeView->edit(aIndex); } - } else { //Selection happens in Upper label - myActiveDocLbl->setReadOnly(false); - myActiveDocLbl->setFocus(); - myActiveDocLbl->selectAll(); - myActiveDocLbl->grabMouse(); - myActiveDocLbl->setProperty("OldText", myActiveDocLbl->text()); + return; + } + } +} + +//*************************************************** +QModelIndexList XGUI_ObjectsBrowser::expandedItems(const QModelIndex& theParent) const +{ + QModelIndexList aIndexes; + QModelIndex aIndex; + for (int i = 0; i < myDocModel->rowCount(); i++) { + aIndex = myDocModel->index(i, 0, theParent); + if (myDocModel->hasChildren(aIndex)) { + if (myTreeView->isExpanded(aIndex)) { + aIndexes.append(aIndex); + QModelIndexList aSubIndexes = expandedItems(aIndex); + if (!aSubIndexes.isEmpty()) + aIndexes.append(aSubIndexes); + } } } + return aIndexes; } //*************************************************** void XGUI_ObjectsBrowser::rebuildDataTree() { + QModelIndexList aIndexList = expandedItems(); myDocModel->rebuildDataTree(); + foreach(QModelIndex aIndex, aIndexList) { + myTreeView->setExpanded(aIndex, true); + } update(); } @@ -308,32 +493,30 @@ void XGUI_ObjectsBrowser::setObjectsSelected(const QObjectPtrList& theObjects) //*************************************************** void XGUI_ObjectsBrowser::clearContent() { - mySelectedData.clear(); myTreeView->clear(); } -void XGUI_ObjectsBrowser::setDataModel(ModuleBase_IDocumentDataModel* theModel) +void XGUI_ObjectsBrowser::onSelectionChanged(const QItemSelection& theSelected, + const QItemSelection& theDeselected) { - myDocModel = theModel; - myTreeView->setModel(myDocModel); - QItemSelectionModel* aSelMod = myTreeView->selectionModel(); - connect(aSelMod, SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)), - this, SLOT(onSelectionChanged(const QItemSelection&, const QItemSelection&))); + emit selectionChanged(); } -void XGUI_ObjectsBrowser::onSelectionChanged(const QItemSelection& theSelected, - const QItemSelection& theDeselected) +QObjectPtrList XGUI_ObjectsBrowser::selectedObjects(QModelIndexList* theIndexes) const { - mySelectedData.clear(); - QModelIndexList aIndexes = myTreeView->selectionModel()->selectedIndexes(); - ModuleBase_IDocumentDataModel* aModel = dataModel(); + QObjectPtrList aList; + QModelIndexList aIndexes = selectedIndexes(); + XGUI_DataModel* aModel = dataModel(); QModelIndexList::const_iterator aIt; for (aIt = aIndexes.constBegin(); aIt != aIndexes.constEnd(); ++aIt) { if ((*aIt).column() == 0) { ObjectPtr aObject = aModel->object(*aIt); - if (aObject) - mySelectedData.append(aObject); + if (aObject) { + aList.append(aObject); + if (theIndexes) + theIndexes->append(*aIt); + } } } - emit selectionChanged(); -} + return aList; +} \ No newline at end of file