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