Salome HOME
PR: Merge V1_2c etape 1
[modules/kernel.git] / src / SALOMEGUI / QAD_DirListDlg.cxx
1 //  SALOME SALOMEGUI : implementation of desktop and GUI kernel
2 //
3 //  Copyright (C) 2003  CEA/DEN, EDF R&D
4 //
5 //
6 //
7 //  File   : QAD_DirListDlg.cxx
8 //  Author : Vadim SANDLER
9 //  Module : SALOME
10 //  $Header$
11
12 using namespace std;
13 #include "QAD_DirListDlg.h"
14 #include "QAD_Desktop.h"
15 #include "QAD_FileDlg.h"
16 #include "QAD_MessageBox.h"
17 #include "QAD_Tools.h"
18 #include <qlayout.h>
19 #include <qlabel.h>
20 #include <qpushbutton.h>
21 #include <qapplication.h>
22
23 #define MIN_WIDTH     400
24 #define MIN_HEIGHT    200
25 #define MARGIN_SIZE    11
26 #define SPACING_SIZE    6
27 #define SPACER_SIZE     5
28
29 /*!
30   Constructor
31 */
32 QAD_DirListDlg::QAD_DirListDlg(QWidget* parent, const char* name) 
33      : QDialog (parent, name, true, WStyle_NormalBorder | WStyle_Customize | WStyle_Title |  WStyle_SysMenu ) 
34 {
35   myEdited       = false;
36   myLastSelected = 0;
37   myEdit         = 0; 
38   myBtn          = 0;
39
40   setCaption(tr("QUICK_DIR_LIST_TLT"));
41   setSizeGripEnabled( true );
42
43   QGridLayout* topLayout = new QGridLayout(this);
44   topLayout->setMargin(MARGIN_SIZE);
45   topLayout->setSpacing(SPACING_SIZE);
46
47   myDirList = new QListBox(this);
48   myDirList->setMinimumSize(MIN_WIDTH, MIN_HEIGHT);
49 //  myDirList->setMaximumSize(MIN_WIDTH, MIN_HEIGHT);
50   myDirList->setSelectionMode(QListBox::Single);
51   myDirList->setHScrollBarMode(QListBox::AlwaysOff);
52   myDirList->horizontalScrollBar()->installEventFilter(this);
53   myDirList->verticalScrollBar()->installEventFilter(this);
54   myDirList->insertItem(tr("EMPTY_DIR"));
55   myDirList->installEventFilter(this);
56
57   QHBoxLayout* ctrlLayout = new QHBoxLayout;
58   ctrlLayout->setMargin(0);
59   ctrlLayout->setSpacing(0);
60
61   QLabel* lab = new QLabel(myDirList, tr("DIRECTORIES_LBL"), this);
62
63   QToolButton* insertBtn = new QToolButton(this);
64   insertBtn->setIconSet(QAD_Desktop::getResourceManager()->loadPixmap("QAD", tr("ICON_DIRLIST_INSERT")));
65   insertBtn->setAutoRaise(true);
66
67   QToolButton* deleteBtn = new QToolButton(this);
68   deleteBtn->setIconSet(QAD_Desktop::getResourceManager()->loadPixmap("QAD", tr("ICON_DIRLIST_DELETE")));
69   deleteBtn->setAutoRaise(true);
70
71   QToolButton* upBtn = new QToolButton(this);
72   upBtn->setIconSet(QAD_Desktop::getResourceManager()->loadPixmap("QAD", tr("ICON_DIRLIST_MOVEUP")));
73   upBtn->setAutoRaise(true);
74
75   QToolButton* downBtn = new QToolButton(this);
76   downBtn->setIconSet(QAD_Desktop::getResourceManager()->loadPixmap("QAD", tr("ICON_DIRLIST_MOVEDOWN")));
77   downBtn->setAutoRaise(true);
78   
79   ctrlLayout->addWidget(lab);
80   ctrlLayout->addItem(new QSpacerItem(SPACER_SIZE, SPACER_SIZE, QSizePolicy::Expanding, QSizePolicy::Minimum));
81   ctrlLayout->addWidget(insertBtn);
82   ctrlLayout->addWidget(deleteBtn);
83   ctrlLayout->addWidget(upBtn);
84   ctrlLayout->addWidget(downBtn);
85
86   QHBoxLayout* btnLayout = new QHBoxLayout;
87   btnLayout->setMargin(0);
88   btnLayout->setSpacing(6);
89
90   QPushButton * okBtn     = new QPushButton(tr("BUT_OK"), this);
91   QPushButton * cancelBtn = new QPushButton(tr("BUT_CANCEL"), this);
92   okBtn->setDefault(true);
93   okBtn->setAutoDefault(true);
94   cancelBtn->setAutoDefault(true);
95
96   btnLayout->addWidget(okBtn);
97   btnLayout->addItem(new QSpacerItem(SPACER_SIZE, SPACER_SIZE, QSizePolicy::Expanding, QSizePolicy::Minimum));
98   btnLayout->addWidget(cancelBtn);
99
100   topLayout->addLayout(ctrlLayout, 0, 0);
101   topLayout->addWidget(myDirList,  1, 0);
102   topLayout->addLayout(btnLayout,  2, 0);
103
104   connect(myDirList, SIGNAL(mouseButtonClicked(int, QListBoxItem*, const QPoint&)), 
105           this, SLOT(onMouseButtonClicked(int, QListBoxItem*, const QPoint&)));
106   connect(myDirList, SIGNAL(doubleClicked(QListBoxItem*)), 
107           this, SLOT(onDblClicked(QListBoxItem*)));
108   
109   connect(insertBtn, SIGNAL(clicked()), this, SLOT(onInsert()));
110   connect(deleteBtn, SIGNAL(clicked()), this, SLOT(onDelete()));
111   connect(upBtn,     SIGNAL(clicked()), this, SLOT(onUp()));
112   connect(downBtn,   SIGNAL(clicked()), this, SLOT(onDown()));
113   connect(okBtn,     SIGNAL(clicked()), this, SLOT(onOk()));
114   connect(cancelBtn, SIGNAL(clicked()), this, SLOT(reject()));
115
116   QAD_Tools::centerWidget(this, parent);
117 }
118
119 /*!
120   Destructor
121 */
122 QAD_DirListDlg::~QAD_DirListDlg() {
123 }
124
125 /*!
126   Gets list of paths
127 */
128 void QAD_DirListDlg::getPathList(QStringList& list) {
129   list.clear();
130   for (unsigned i = 0; i < myDirList->count()-1; i++)
131     list.append(myDirList->text(i));
132 }
133
134 /*!
135   Sets list of paths
136 */
137 void QAD_DirListDlg::setPathList(const QStringList& list) {
138   for (unsigned i = 0; i < list.count(); i++)
139     myDirList->insertItem(list[i], myDirList->count()-1);
140 }
141
142 /*!
143   Validates entered path, returns true if OK
144 */
145 bool QAD_DirListDlg::validate() {
146   if (myEdited) {
147     QString dirPath = myEdit->text().stripWhiteSpace();
148     QDir dir(dirPath);
149     QListBoxItem* found = 0;
150     for (unsigned i = 0; i < myDirList->count()-1; i++) {
151       QDir aDir(myDirList->text(i));
152       if ( aDir.canonicalPath().isNull() && myDirList->text(i) == dir.absPath() ||
153           !aDir.canonicalPath().isNull() && aDir.exists() && aDir.canonicalPath() == dir.canonicalPath()) {
154           found = myDirList->item(i);
155         break;
156       }
157     }
158     if (dirPath.isEmpty()) {
159       if (found) {
160         // it should be last (empty) item in the list - nothing to do
161         return true;
162       }
163       else {
164         // delete directory from the list
165         removeDir(myLastSelected);
166         return true;
167       }
168     }
169     else {
170       if (found) {
171         if (found != myLastSelected) {
172           // it is forbidden to add directory more then once
173           QAD_MessageBox::error1(this, 
174                                  tr("ERR_ERROR"),
175                                  tr("ERR_DIRECTORY_SPECIFIED"), 
176                                  tr("BUT_OK"));
177           myEdit->setFocus();
178           return false;
179         }
180       }
181       else {
182         if (!dir.exists()) {
183           if ( QAD_MessageBox::info2(this, 
184                                      tr("WRN_WARNING"),
185                                      tr("WRN_DIRECTORY_N0T_EXIST").arg(dir.absPath()),
186                                      tr ("BUT_YES"), tr ("BUT_NO"), 
187                                      QAD_YES, QAD_NO, QAD_NO ) == QAD_NO ) {
188             myEdit->setFocus();
189             return false;
190           }
191         }
192         // append
193         appendDir(myLastSelected, dir.absPath());
194       }
195     }
196   }
197   return true;
198 }
199
200 /*!
201   Appends/changes directory
202 */
203 void QAD_DirListDlg::appendDir(QListBoxItem* item, const QString& dir) {
204   int index = myDirList->index(item);
205   if (index >= 0 && index < (int)myDirList->count()) {
206     if (index == (int)myDirList->count()-1) {
207       // it is the last item (new), well, insert it before the last (empty)
208       myDirList->insertItem(dir, myDirList->count()-1);
209     }
210     else {
211       // change item
212       myDirList->changeItem(dir, index);
213     }
214   }
215 }
216
217 /*!
218   Removes directory from list
219 */
220 void QAD_DirListDlg::removeDir(QListBoxItem* item) {
221   // do not remove last item (empty)
222   int index = myDirList->index(item);
223   if (index >= 0 && index < (int)myDirList->count()-1) {
224     delete item;
225     myLastSelected = myDirList->item(index);
226     myDirList->setSelected(myLastSelected, true);
227   }
228 }
229
230 /*!
231   KeyPress event handler, processes <Enter> and <Escape> keys
232 */
233 void QAD_DirListDlg::keyPressEvent(QKeyEvent* event) {
234   if ( myEdited ) {
235     if ( event->key() == Key_Escape ) {
236       delete myEdit;
237       delete myBtn;
238       myEdit = 0;
239       myBtn  = 0;
240       myEdited = false;
241       myDirList->setFocus();
242     }
243     return;
244   }
245   if (event->key() == Key_Return || event->key() == Key_Enter) {
246     accept();
247   }
248   QDialog::keyPressEvent(event);
249 }
250
251 /*!
252   Resize event
253 */
254 void QAD_DirListDlg::resizeEvent(QResizeEvent* event) {
255   QDialog::resizeEvent(event);
256   if ( myEdited ) {
257     myEdit->resize(myDirList->viewport()->width()-myBtn->sizeHint().width(), myEdit->height());
258     myBtn->move(myEdit->width(), myEdit->y());
259   }
260 }
261
262 /*!
263   Called when user clicks inside directories list box
264 */
265 void QAD_DirListDlg::onMouseButtonClicked(int           button, 
266                                           QListBoxItem* item, 
267                                           const QPoint& point) {
268   if (myEdited) {
269     if (!validate()) {
270       myDirList->setCurrentItem(myLastSelected);
271       myDirList->setSelected(myLastSelected, true);
272       return;
273     }
274     delete myEdit;
275     delete myBtn;
276     myEdit = 0;
277     myBtn  = 0;
278     myEdited = false;
279     myDirList->setFocus();
280   }
281   if (item) {
282     myDirList->setCurrentItem(item);
283     myDirList->setSelected(item, true);
284     myDirList->ensureCurrentVisible();
285     qApp->processEvents();
286     if (button == LeftButton && myLastSelected == item) {
287       QRect ir = myDirList->itemRect(myLastSelected);
288       
289       myEdit = new QLineEdit(myDirList->viewport());
290       myBtn  = new QToolButton(myDirList->viewport());
291       myBtn->setText(" ... ");
292       connect(myBtn, SIGNAL(clicked()), this, SLOT(onBtnClicked()));
293       myEdit->setGeometry(0, 
294                           ir.top()-(myEdit->sizeHint().height()-ir.height())/2, 
295                           myDirList->viewport()->width()-myBtn->sizeHint().width(), 
296                           myEdit->sizeHint().height());
297       myBtn->setGeometry (myEdit->width(), 
298                           ir.top()-(myEdit->sizeHint().height()-ir.height())/2, 
299                           myBtn->sizeHint().width(),
300                           myEdit->sizeHint().height());
301       connect(myEdit, SIGNAL(returnPressed()), this, SLOT(onEditFinished()));
302       myEdited = true;
303       myEdit->show();
304       myBtn->show();
305       if (myDirList->index(myLastSelected) != (int)myDirList->count()-1)
306         myEdit->setText(myLastSelected->text());
307       myEdit->selectAll();
308       myEdit->setCursorPosition(myEdit->text().length());
309       myEdit->installEventFilter(this);
310       myEdit->setFocus();
311     }
312   }
313   else {
314     myDirList->clearSelection();
315   }
316   myLastSelected = item;
317 }
318
319 /*!
320   Called when user double-clicks on any item
321 */
322 void QAD_DirListDlg::onDblClicked(QListBoxItem* item) {
323   onMouseButtonClicked(LeftButton, item, QPoint(0,0));
324 }
325
326 /*!
327   <...> (Browse dir) button slot
328 */
329 void QAD_DirListDlg::onBtnClicked() {
330   QString dir = myEdit->text().stripWhiteSpace().isEmpty() ? 
331                 QString::null : 
332                 myEdit->text().stripWhiteSpace();
333   dir = QAD_FileDlg::getExistingDirectory(this, dir, tr("SELECT_DIRECTORY"), true);
334   if (!dir.isEmpty()) {
335     myEdit->setText(dir);
336     myEdit->selectAll();
337     myEdit->setCursorPosition(myEdit->text().length());
338   }
339 }
340
341 /*!
342   Called when user finises editing of path by pressing <Enter>
343 */
344 void QAD_DirListDlg::onEditFinished() {
345   if (myEdit) {
346     if (!validate()) {
347       myDirList->setCurrentItem(myLastSelected);
348       myDirList->setSelected(myLastSelected, true);
349       return;
350     }
351     delete myEdit;
352     delete myBtn;
353     myEdit = 0;
354     myBtn  = 0;
355     myEdited = false;
356     myDirList->setFocus();
357   }
358 }
359
360 /*!
361   Event filter
362 */
363 bool QAD_DirListDlg::eventFilter(QObject* object, QEvent* event) {
364   if ( myEdited ) {
365     if (event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonDblClick) {
366       if (object == myDirList->horizontalScrollBar() || object == myDirList->verticalScrollBar()) {
367         if (!validate()) {
368           myDirList->setCurrentItem(myLastSelected);
369           myDirList->setSelected(myLastSelected, true);
370           return true;
371         }
372         delete myEdit;
373         delete myBtn;
374         myEdit = 0;
375         myBtn  = 0;
376         myEdited = false;
377         myDirList->setFocus();
378       }
379     }
380     else if (event->type() == QEvent::KeyPress) {
381       QKeyEvent* ke = (QKeyEvent*)event;
382       if (ke->key() == Key_Tab)
383         return true;
384       if (object == myDirList) {
385         return true;
386       }
387       else if (object == myEdit) {
388         if ( ke->key() == Key_Up || ke->key() == Key_Down || ke->key() == Key_PageUp || ke->key() == Key_PageDown ||
389              ( ke->key() == Key_Home  || ke->key() == Key_End  || ke->key() == Key_Prior || ke->key() == Key_Next ) && 
390                  (ke->state() & ControlButton) ) {
391           return true;
392         }
393         else if ( ke->key() == Key_Escape ) {
394           delete myEdit;
395           delete myBtn;
396           myEdit = 0;
397           myBtn  = 0;
398           myEdited = false;
399           myDirList->setFocus();
400           return true;
401         }
402       }
403     }
404   }
405   else {
406     if (event->type() == QEvent::KeyPress) {
407       if (object == myDirList) {
408         QKeyEvent* ke = (QKeyEvent*)event;
409         if (ke->key() == Key_Return || ke->key() == Key_Enter) {
410           accept();
411         }
412         else {
413           QChar c(ke->ascii());
414           if (c.isPrint()) {
415             QListBoxItem* item = myDirList->item(myDirList->currentItem());
416             if (item) {
417               myDirList->setCurrentItem(item);
418               myDirList->setSelected(item, true);
419               myDirList->ensureCurrentVisible();
420               myLastSelected = item;
421               qApp->processEvents();
422               QRect ir = myDirList->itemRect(myLastSelected);
423                 
424               myEdit = new QLineEdit(myDirList->viewport());
425               myBtn  = new QToolButton(myDirList->viewport());
426               myBtn->setText(" ... ");
427               connect(myBtn, SIGNAL(clicked()), this, SLOT(onBtnClicked()));
428               myEdit->setGeometry(0, 
429                                   ir.top()-(myEdit->sizeHint().height()-ir.height())/2, 
430                                   myDirList->viewport()->width()-myBtn->sizeHint().width(), 
431                                   myEdit->sizeHint().height());
432               myBtn->setGeometry (myEdit->width(), 
433                                   ir.top()-(myEdit->sizeHint().height()-ir.height())/2, 
434                                   myBtn->sizeHint().width(),
435                                   myEdit->sizeHint().height());
436               connect(myEdit, SIGNAL(returnPressed()), this, SLOT(onEditFinished()));
437               myEdited = true;
438               myEdit->show();
439               myBtn->show();
440               myEdit->setText(c);
441               myEdit->setCursorPosition(myEdit->text().length());
442               myEdit->installEventFilter(this);
443               myEdit->setFocus();
444             }
445           }
446         }
447       }
448     }
449   }
450   return QDialog::eventFilter(object, event);
451 }
452
453 /*!
454   <Insert> button slot
455 */
456 void QAD_DirListDlg::onInsert() {
457   if (!myEdited) {
458     myLastSelected = 0;
459     onMouseButtonClicked(LeftButton, myDirList->item(myDirList->count()-1), QPoint(0,0));
460     onMouseButtonClicked(LeftButton, myDirList->item(myDirList->count()-1), QPoint(0,0));
461   }
462 }
463
464 /*!
465   <Delete> button slot
466 */
467 void QAD_DirListDlg::onDelete() {
468   if (!myEdited && myDirList->currentItem() >=0) {
469     removeDir(myDirList->item(myDirList->currentItem()));
470     myDirList->setFocus();
471   }
472 }
473
474 /*!
475   <Move up> button slot
476 */
477 void QAD_DirListDlg::onUp() {
478   if (!myEdited && myLastSelected) {
479     int index = myDirList->currentItem();
480     if (index > 0 && index < (int)myDirList->count()-1 && myDirList->isSelected(index)) {
481       QString t = myDirList->text(index-1);
482       myDirList->changeItem(myDirList->text(index), index-1);
483       myDirList->changeItem(t, index);
484       myDirList->setCurrentItem(index-1);
485       myLastSelected = myDirList->item(index-1);
486       myDirList->setSelected(myLastSelected, true);
487       myDirList->setFocus();
488     }
489   }
490 }
491
492 /*!
493   <Move down> button slot
494 */
495 void QAD_DirListDlg::onDown() {
496   if (!myEdited && myLastSelected) {
497     int index = myDirList->currentItem();
498     if (index >= 0 && index < (int)myDirList->count()-2 && myDirList->isSelected(index)) {
499       QString t = myDirList->text(index+1);
500       myDirList->changeItem(myDirList->text(index), index+1);
501       myDirList->changeItem(t, index);
502       myDirList->setCurrentItem(index+1);
503       myLastSelected = myDirList->item(index+1);
504       myDirList->setSelected(myLastSelected, true);
505       myDirList->setFocus();
506     }
507   }
508 }
509
510 /*!
511   Purpose  : <OK> button slot
512 */
513 void QAD_DirListDlg::onOk() {
514   if (validate())
515     accept();
516 }