Salome HOME
Merge remote-tracking branch 'origin/Toolbars_Management'
[modules/shaper.git] / src / SHAPERGUI / SHAPERGUI_ToolbarsMgr.cpp
1 // Copyright (C) 2014-2017  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or
18 // email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
19 //
20
21 #include "SHAPERGUI_ToolbarsMgr.h"
22 #include "SHAPERGUI.h"
23
24 #include <CAM_Application.h>
25 #include <SUIT_Desktop.h>
26 #include <SUIT_Session.h>
27 #include <QtxActionToolMgr.h>
28
29 #include <QLayout>
30 #include <QDialogButtonBox>
31 #include <QLabel>
32 #include <QListWidget>
33 #include <QPushButton>
34 #include <QInputDialog>
35 #include <QMessageBox>
36 #include <QMouseEvent>
37
38
39 #define SEPARATOR "------"
40 #define LIST_WIDTH 180
41
42 class SHAPERGUI_CommandIdItem : public QListWidgetItem
43 {
44 public:
45   SHAPERGUI_CommandIdItem(QListWidget* theParent, int theId, SHAPERGUI* theModule)
46     : QListWidgetItem(theParent), myId(theId), myModule(theModule) {}
47
48
49   virtual QVariant data(int theRole) const {
50     QAction* aAction = 0;
51     if (myId != -1)
52       aAction = myModule->action(myId);
53
54     switch (theRole) {
55     case Qt::DisplayRole:
56       if (aAction)
57         return aAction->text();
58       else
59         return SEPARATOR;
60     case Qt::DecorationRole:
61       if (aAction)
62         return aAction->icon();
63       else
64         return QIcon();
65     }
66     return QListWidgetItem::data(theRole);
67   }
68
69
70   int id() const { return myId; }
71
72 private:
73   SHAPERGUI* myModule;
74   int myId;
75 };
76
77
78 //************************************************************************************
79 //************************************************************************************
80 //************************************************************************************
81 SHAPERGUI_ToolbarsDlg::SHAPERGUI_ToolbarsDlg(SHAPERGUI* theModule)
82   : QDialog(theModule->application()->desktop()),
83   myModule(theModule),
84   myResult(theModule->shaperToolbars()),
85   myIsReset(false)
86 {
87   myFreeCommands = theModule->getFreeCommands();
88
89   setWindowTitle(tr("Toolbars"));
90   QVBoxLayout* aMailLayout = new QVBoxLayout(this);
91
92   // Controls part of the dialog
93   QWidget* aControlsWgt = new QWidget(this);
94   QHBoxLayout* aContolsLay = new QHBoxLayout(aControlsWgt);
95   aContolsLay->setContentsMargins(0, 0, 0, 0);
96   aMailLayout->addWidget(aControlsWgt);
97
98   // Right controls
99   QWidget* aListWgt = new QWidget(aControlsWgt);
100   QVBoxLayout* aListLayout = new QVBoxLayout(aListWgt);
101   aListLayout->setContentsMargins(0, 0, 0, 0);
102   aContolsLay->addWidget(aListWgt);
103
104   aListLayout->addWidget(new QLabel(tr("Toolbars:"), aListWgt));
105
106   myToolbarsList = new QListWidget(aListWgt);
107   connect(myToolbarsList, SIGNAL(doubleClicked(const QModelIndex&)),
108     SLOT(onDoubleClick(const QModelIndex&)));
109   aListLayout->addWidget(myToolbarsList);
110
111   QWidget* aFreeItemsWgt = new QWidget(aListWgt);
112   QHBoxLayout* aFreeLayout = new QHBoxLayout(aFreeItemsWgt);
113   aFreeLayout->setContentsMargins(0, 0, 0, 0);
114   aListLayout->addWidget(aFreeItemsWgt);
115
116   aFreeLayout->addWidget(new QLabel(tr("Number of commands out of toolbars:"), aFreeItemsWgt));
117   myFreeNbLbl = new QLabel(aFreeItemsWgt);
118   aFreeLayout->addWidget(myFreeNbLbl);
119
120   // Left controls
121   QWidget* aButtonsWgt = new QWidget(aControlsWgt);
122   QVBoxLayout* aBtnLayout = new QVBoxLayout(aButtonsWgt);
123   aBtnLayout->setContentsMargins(0, 0, 0, 0);
124   aContolsLay->addWidget(aButtonsWgt);
125
126   QPushButton* aAddBtn = new QPushButton(tr("Add..."), aButtonsWgt);
127   aAddBtn->setToolTip(tr("Add a new empty toolbar to the toolbars list"));
128   connect(aAddBtn, SIGNAL(clicked(bool)), SLOT(onAdd()));
129   aBtnLayout->addWidget(aAddBtn);
130
131   QPushButton* aEditBtn = new QPushButton(tr("Edit..."), aButtonsWgt);
132   aEditBtn->setToolTip(tr("Edit currently selected toolbar"));
133   connect(aEditBtn, SIGNAL(clicked(bool)), SLOT(onEdit()));
134   aBtnLayout->addWidget(aEditBtn);
135
136   QPushButton* aDeleteBtn = new QPushButton(tr("Delete"), aButtonsWgt);
137   aDeleteBtn->setToolTip(tr("Delete currently selected toolbar"));
138   connect(aDeleteBtn, SIGNAL(clicked(bool)), SLOT(onDelete()));
139   aBtnLayout->addWidget(aDeleteBtn);
140   aBtnLayout->addStretch(1);
141
142   QPushButton* aResetBtn = new QPushButton(tr("Reset"), aButtonsWgt);
143   aResetBtn->setToolTip(tr("Restore default toolbars structure"));
144   connect(aResetBtn, SIGNAL(clicked(bool)), SLOT(onReset()));
145   aBtnLayout->addWidget(aResetBtn);
146   aBtnLayout->addSpacing(19);
147
148   // Buttons part of the dialog
149   QDialogButtonBox* aButtons =
150     new QDialogButtonBox(QDialogButtonBox::Help | QDialogButtonBox::Ok | QDialogButtonBox::Cancel,
151       Qt::Horizontal, this);
152   aMailLayout->addWidget(aButtons);
153   connect(aButtons, SIGNAL(accepted()), SLOT(accept()));
154   connect(aButtons, SIGNAL(rejected()), SLOT(reject()));
155   connect(aButtons, SIGNAL(helpRequested()), SLOT(onHelp()));
156
157   updateToolbarsList();
158   updateNumber();
159 }
160
161 void SHAPERGUI_ToolbarsDlg::onAdd()
162 {
163   QString aNewToolbar =
164     QInputDialog::getText(this, tr("Create toolbar"), tr("Name of a new toolbar"));
165   if (!(aNewToolbar.isNull() || aNewToolbar.isEmpty())) {
166     if (!myResult.contains(aNewToolbar)) {
167       myResult[aNewToolbar] = QIntList();
168       updateToolbarsList();
169       myIsReset = false;
170     }
171     else {
172       QString aMsg = tr("A tool bar with name %1 already exists").arg(aNewToolbar);
173       QMessageBox::warning(this, tr("Create toolbar"), aMsg);
174     }
175   }
176 }
177
178 void SHAPERGUI_ToolbarsDlg::onEdit()
179 {
180   QList<QListWidgetItem*> aSelected = myToolbarsList->selectedItems();
181   if (aSelected.size() == 1) {
182     QString aToolbarName = aSelected.first()->text();
183     int aPos = aToolbarName.lastIndexOf(" (");
184     aToolbarName = aToolbarName.left(aPos);
185
186     SHAPERGUI_ToolbarItemsDlg aDlg(this, myModule,
187       aToolbarName, myFreeCommands, myResult[aToolbarName]);
188     if (aDlg.exec() == QDialog::Accepted) {
189       myFreeCommands = aDlg.freeItems();
190       myResult[aToolbarName] = aDlg.toolbarItems();
191       updateNumber();
192       updateToolbarsList();
193       myIsReset = false;
194     }
195   }
196 }
197
198 void SHAPERGUI_ToolbarsDlg::onDelete()
199 {
200   QList<QListWidgetItem*> aSelected = myToolbarsList->selectedItems();
201   if (aSelected.size() == 1) {
202     QString aToolbarName = aSelected.first()->text();
203     int aPos = aToolbarName.lastIndexOf(" (");
204     aToolbarName = aToolbarName.left(aPos);
205
206     QString aMsg = tr("Toolbar %1 will be deleted. Continue?").arg(aToolbarName);
207     if (QMessageBox::question(this, tr("Delete toolbar"), aMsg) == QMessageBox::Yes) {
208       myFreeCommands.append(myResult[aToolbarName]);
209       // remove separators from free items
210       myFreeCommands.removeAll(-1);
211       myResult.remove(aToolbarName);
212       updateToolbarsList();
213       updateNumber();
214       myIsReset = false;
215     }
216   }
217 }
218
219 void SHAPERGUI_ToolbarsDlg::updateToolbarsList()
220 {
221   myToolbarsList->clear();
222   QStringList aItems;
223   QMap<QString, QIntList>::const_iterator aIt;
224   for (aIt = myResult.cbegin(); aIt != myResult.cend(); aIt++) {
225     aItems.append(aIt.key() + tr(" (%1 commands)").arg(aIt.value().size() - aIt.value().count(-1)));
226   }
227   myToolbarsList->addItems(aItems);
228 }
229
230
231 void SHAPERGUI_ToolbarsDlg::onDoubleClick(const QModelIndex& theIdx)
232 {
233   if (theIdx.isValid())
234     onEdit();
235 }
236
237 void SHAPERGUI_ToolbarsDlg::updateNumber()
238 {
239   myFreeNbLbl->setText(QString::number(myFreeCommands.size()));
240 }
241
242 void SHAPERGUI_ToolbarsDlg::onReset()
243 {
244   myResult = myModule->defaultToolbars();
245   updateNumber();
246   updateToolbarsList();
247   myIsReset = true;
248 }
249
250 void SHAPERGUI_ToolbarsDlg::onHelp()
251 {
252   SUIT_Application* app = SUIT_Session::session()->activeApplication();
253   if (app)
254     app->onHelpContextModule("SHAPER", "Introduction.html", "toolbars-dialog-box");
255 }
256
257
258 //************************************************************************************
259 //************************************************************************************
260 //************************************************************************************
261 SHAPERGUI_ToolbarItemsDlg::SHAPERGUI_ToolbarItemsDlg(QWidget* theParent,
262   SHAPERGUI* theModule,
263   const QString& theToolbar,
264   const QIntList& theFreeItems,
265   const QIntList& theItemsList)
266   : QDialog(theParent),
267   myModule(theModule)
268 {
269   setWindowTitle(tr("Edit toolbar"));
270
271   QVBoxLayout* aMailLayout = new QVBoxLayout(this);
272
273   // Name of toolbar
274   QWidget* aNameWgt = new QWidget(this);
275   QHBoxLayout* aNameLay = new QHBoxLayout(aNameWgt);
276   aNameLay->setContentsMargins(0, 0, 0, 0);
277   aMailLayout->addWidget(aNameWgt);
278
279   aNameLay->addWidget(new QLabel(tr("Toolbar name:"), aNameWgt));
280   QLabel* aNameLbl = new QLabel(theToolbar, aNameWgt);
281   QFont aFont = aNameLbl->font();
282   aFont.setBold(true);
283   aNameLbl->setFont(aFont);
284   aNameLay->addWidget(aNameLbl);
285   aNameLay->addStretch(1);
286
287   // Lists widget
288   QWidget* aControlsWgt = new QWidget(this);
289   QHBoxLayout* aCtrlLayout = new QHBoxLayout(aControlsWgt);
290   aCtrlLayout->setContentsMargins(0, 0, 0, 0);
291   aMailLayout->addWidget(aControlsWgt);
292
293   // Left list
294   QWidget* aCommandsWgt = new QWidget(aControlsWgt);
295   QVBoxLayout* aCommandsLay = new QVBoxLayout(aCommandsWgt);
296   aCommandsLay->setContentsMargins(0, 0, 0, 0);
297   aCtrlLayout->addWidget(aCommandsWgt);
298
299   aCommandsLay->addWidget(new QLabel(tr("Out of toolbars:"), aCommandsWgt));
300   myCommandsList = new QListWidget(aCommandsWgt);
301   myCommandsList->setSortingEnabled(false);
302
303   myCommandsList->addItem(new SHAPERGUI_CommandIdItem(myCommandsList, -1, myModule));
304   foreach(int aId, theFreeItems) {
305     myCommandsList->addItem(new SHAPERGUI_CommandIdItem(myCommandsList, aId, myModule));
306   }
307   myCommandsList->setMaximumWidth(LIST_WIDTH);
308   aCommandsLay->addWidget(myCommandsList);
309
310   // Middle buttons
311   QWidget* aButtonsWgt = new QWidget(aControlsWgt);
312   QVBoxLayout* aBtnLayout = new QVBoxLayout(aButtonsWgt);
313   aBtnLayout->setContentsMargins(0, 0, 0, 0);
314   aCtrlLayout->addWidget(aButtonsWgt);
315
316   aBtnLayout->addStretch(1);
317   QPushButton* aAddButton = new QPushButton(QIcon(":pictures/arrow-right.png"), "", aButtonsWgt);
318   connect(aAddButton, SIGNAL(clicked(bool)), SLOT(onAddItem()));
319   aBtnLayout->addWidget(aAddButton);
320
321   aBtnLayout->addSpacing(20);
322
323   QPushButton* aDelButton = new QPushButton(QIcon(":pictures/arrow-left.png"), "", aButtonsWgt);
324   connect(aDelButton, SIGNAL(clicked(bool)), SLOT(onDelItem()));
325   aBtnLayout->addWidget(aDelButton);
326   aBtnLayout->addStretch(1);
327
328   // Right list
329   QWidget* aItemsWgt = new QWidget(aControlsWgt);
330   QVBoxLayout* aItemsLay = new QVBoxLayout(aItemsWgt);
331   aItemsLay->setContentsMargins(0, 0, 0, 0);
332   aCtrlLayout->addWidget(aItemsWgt);
333
334   aItemsLay->addWidget(new QLabel(tr("In the toolbar:"), aItemsWgt));
335   myItemsList = new QListWidget(aItemsWgt);
336   myItemsList->setSortingEnabled(false);
337   foreach(int aId, theItemsList) {
338     myItemsList->addItem(new SHAPERGUI_CommandIdItem(myItemsList, aId, myModule));
339   }
340   myItemsList->setMaximumWidth(LIST_WIDTH);
341   myItemsList->viewport()->installEventFilter(this);
342   aItemsLay->addWidget(myItemsList);
343
344   // Buttons of right list
345   QWidget* aBtnWgt = new QWidget(aControlsWgt);
346   QVBoxLayout* aBtnLay = new QVBoxLayout(aBtnWgt);
347   aBtnLay->setContentsMargins(0, 0, 0, 0);
348   aCtrlLayout->addWidget(aBtnWgt);
349
350   aBtnLay->addStretch(1);
351   QPushButton* aUpButton = new QPushButton(QIcon(":pictures/arrow-up.png"), "", aBtnWgt);
352   connect(aUpButton, SIGNAL(clicked(bool)), SLOT(onUp()));
353   aBtnLay->addWidget(aUpButton);
354
355   aBtnLay->addSpacing(20);
356
357   QPushButton* aDownButton = new QPushButton(QIcon(":pictures/arrow-down.png"), "", aBtnWgt);
358   connect(aDownButton, SIGNAL(clicked(bool)), SLOT(onDown()));
359   aBtnLay->addWidget(aDownButton);
360   aBtnLay->addStretch(1);
361
362   // Buttons part of the dialog
363   QDialogButtonBox* aButtons =
364     new QDialogButtonBox(QDialogButtonBox::Help | QDialogButtonBox::Ok | QDialogButtonBox::Cancel,
365       Qt::Horizontal, this);
366   aMailLayout->addWidget(aButtons);
367   connect(aButtons, SIGNAL(accepted()), SLOT(accept()));
368   connect(aButtons, SIGNAL(rejected()), SLOT(reject()));
369   connect(aButtons, SIGNAL(helpRequested()), SLOT(onHelp()));
370 }
371
372 void SHAPERGUI_ToolbarItemsDlg::onAddItem()
373 {
374   QList<QListWidgetItem*> aCurrentList = myCommandsList->selectedItems();
375   if (aCurrentList.size() > 0) {
376     SHAPERGUI_CommandIdItem* aItem = dynamic_cast<SHAPERGUI_CommandIdItem*>(aCurrentList.first());
377     int aId = aItem->id();
378     if (aId != -1) {
379       myCommandsList->removeItemWidget(aItem);
380       delete aItem;
381     }
382     QModelIndex aIdx = myItemsList->currentIndex();
383     aItem = new SHAPERGUI_CommandIdItem(0, aId, myModule);
384     if (aIdx.isValid()) {
385       int aRow = aIdx.row();
386       myItemsList->insertItem(aRow, aItem);
387     }
388     else {
389       myItemsList->addItem(aItem);
390     }
391   }
392 }
393
394 void SHAPERGUI_ToolbarItemsDlg::onDelItem()
395 {
396   QList<QListWidgetItem*> aCurrentList = myItemsList->selectedItems();
397   if (aCurrentList.size() > 0) {
398     SHAPERGUI_CommandIdItem* aItem = dynamic_cast<SHAPERGUI_CommandIdItem*>(aCurrentList.first());
399     int aId = aItem->id();
400     myItemsList->removeItemWidget(aItem);
401     delete aItem;
402     if (aId != -1) {
403       aItem = new SHAPERGUI_CommandIdItem(myCommandsList, aId, myModule);
404       myCommandsList->addItem(aItem);
405     }
406   }
407 }
408
409
410 bool SHAPERGUI_ToolbarItemsDlg::eventFilter(QObject* theObj, QEvent* theEvent)
411 {
412   if (theEvent->type() == QEvent::MouseButtonRelease) {
413     QMouseEvent* aMouseEvent = (QMouseEvent*)theEvent;
414     QModelIndex aIdx = myItemsList->indexAt(aMouseEvent->pos());
415     if (!aIdx.isValid() || aMouseEvent->button() == Qt::RightButton) {
416       myItemsList->setCurrentIndex(QModelIndex());
417     }
418   }
419   return QDialog::eventFilter(theObj, theEvent);
420 }
421
422 void SHAPERGUI_ToolbarItemsDlg::onUp()
423 {
424   QModelIndex aCurrentIdx = myItemsList->currentIndex();
425   if (aCurrentIdx.isValid()) {
426     int aRow = aCurrentIdx.row();
427     if (aRow > 0) {
428       QListWidgetItem* aItem = myItemsList->takeItem(aRow);
429       aRow--;
430       myItemsList->insertItem(aRow, aItem);
431       myItemsList->setCurrentRow(aRow);
432     }
433   }
434 }
435
436 void SHAPERGUI_ToolbarItemsDlg::onDown()
437 {
438   QModelIndex aCurrentIdx = myItemsList->currentIndex();
439   if (aCurrentIdx.isValid()) {
440     int aNb = myItemsList->count();
441     int aRow = aCurrentIdx.row();
442     if (aRow < (aNb - 1)) {
443       QListWidgetItem* aItem = myItemsList->takeItem(aRow);
444       aRow++;
445       myItemsList->insertItem(aRow, aItem);
446       myItemsList->setCurrentRow(aRow);
447     }
448   }
449 }
450
451 QIntList SHAPERGUI_ToolbarItemsDlg::freeItems() const
452 {
453   return getItems(myCommandsList, 1);
454 }
455
456 QIntList SHAPERGUI_ToolbarItemsDlg::toolbarItems() const
457 {
458   return getItems(myItemsList, 0);
459 }
460
461 QIntList SHAPERGUI_ToolbarItemsDlg::getItems(QListWidget* theWidget, int theStart) const
462 {
463   QIntList aList;
464   SHAPERGUI_CommandIdItem* aItem = 0;
465   int aNb = theWidget->count();
466   for (int i = theStart; i < aNb; i++) {
467     aItem = (SHAPERGUI_CommandIdItem*)theWidget->item(i);
468     aList.append(aItem->id());
469   }
470   return aList;
471 }
472
473 void SHAPERGUI_ToolbarItemsDlg::onHelp()
474 {
475   SUIT_Application* app = SUIT_Session::session()->activeApplication();
476   if (app)
477     app->onHelpContextModule("SHAPER", "Introduction.html", "edit-toolbar-dialog-box");
478 }