Salome HOME
Update from BR_V5_DEV 13Feb2009
[modules/gui.git] / src / Qtx / QtxPathListEdit.cxx
1 //  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 //  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 //  This library is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU Lesser General Public
8 //  License as published by the Free Software Foundation; either
9 //  version 2.1 of the License.
10 //
11 //  This library is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 //  Lesser General Public License for more details.
15 //
16 //  You should have received a copy of the GNU Lesser General Public
17 //  License along with this library; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 // File:      QtxPathListEdit.cxx
23 // Author:    Sergey TELKOV
24 //
25 #include "QtxPathListEdit.h"
26
27 #include "QtxPathEdit.h"
28
29 #include <QLayout>
30 #include <QPainter>
31 #include <QListView>
32 #include <QLineEdit>
33 #include <QKeyEvent>
34 #include <QDirModel>
35 #include <QCompleter>
36 #include <QToolButton>
37 #include <QMessageBox>
38 #include <QFileDialog>
39 #include <QItemDelegate>
40 #include <QStringListModel>
41
42 static const char* delete_icon[] = {
43 "16 16 3 1",
44 "` c #810000",
45 "  c none",
46 "# c #ffffff",
47 "                ",
48 "                ",
49 " ``#        ``# ",
50 " ````#     ``#  ",
51 "  ````#   ``#   ",
52 "    ```# `#     ",
53 "     `````#     ",
54 "      ```#      ",
55 "     `````#     ",
56 "    ```# ``#    ",
57 "   ```#   ``#   ",
58 "  ```#     `#   ",
59 "  ```#      `#  ",
60 "   `#        `# ",
61 "                ",
62 "                "
63 };
64
65 static const char* insert_icon[] = {
66 "16 16 5 1",
67 "` c #000000",
68 ". c #ffff00",
69 "# c #9d9da1",
70 "  c none",
71 "b c #ffffff",
72 "                ",
73 "                ",
74 " #  #b #.       ",
75 "  # #.#.` ` `   ",
76 "  .#.b####   `  ",
77 " ### ..         ",
78 "  . # .#     `  ",
79 " #` #.          ",
80 "    #        `  ",
81 "  `             ",
82 "             `  ",
83 "  `             ",
84 "             `  ",
85 "  ` ` ` ` ` `   ",
86 "                ",
87 "                "
88 };
89
90 static const char* movedown_icon[] = {
91 "16 16 2 1",
92 "` c #000000",
93 "  c none",
94 "                ",
95 "                ",
96 "         ```    ",
97 "        ```     ",
98 "       ```      ",
99 "       ```      ",
100 "       ```      ",
101 "       ```      ",
102 "   ```````````  ",
103 "    `````````   ",
104 "     ```````    ",
105 "      `````     ",
106 "       ```      ",
107 "        `       ",
108 "                ",
109 "                "
110 };
111
112 static const char* moveup_icon[] = {
113 "16 16 2 1",
114 "` c #000000",
115 "  c none",
116 "                ",
117 "                ",
118 "        `       ",
119 "       ```      ",
120 "      `````     ",
121 "     ```````    ",
122 "    `````````   ",
123 "   ```````````  ",
124 "       ```      ",
125 "       ```      ",
126 "       ```      ",
127 "       ```      ",
128 "      ```       ",
129 "     ```        ",
130 "                ",
131 "                "
132 };
133
134
135 /*!
136   \class QtxPathListEdit::Editor
137   \brief Path editor widget
138   \internal
139 */
140
141 class QtxPathListEdit::Editor : public QtxPathEdit
142 {
143 public:
144   /*!
145     \brief Constructor
146     \internal
147   */
148   Editor( QWidget* parent = 0 ) : QtxPathEdit( parent )
149   {
150     layout()->setSpacing( 0 );
151     lineEdit()->setFrame( false );
152   }
153
154   /*!
155     \brief Destructor
156     \internal
157   */
158   virtual ~Editor() {}
159 };
160
161 /*!
162   \class QtxPathListEdit::Delegate
163   \brief Custom item delegate for the paths list widget.
164   \internal
165 */
166
167 class QtxPathListEdit::Delegate : public QItemDelegate
168 {
169 public:
170   Delegate( QtxPathListEdit*, QObject* = 0 );
171   virtual ~Delegate();
172
173   virtual QWidget* createEditor( QWidget*, const QStyleOptionViewItem&, const QModelIndex& ) const;
174   virtual void     setModelData( QWidget*, QAbstractItemModel*, const QModelIndex& ) const;
175   virtual void     setEditorData( QWidget*, const QModelIndex& ) const;
176   virtual void     paint( QPainter*, const QStyleOptionViewItem&, const QModelIndex& ) const;
177
178 protected:
179   virtual void     drawFocus( QPainter*, const QStyleOptionViewItem&, const QRect& ) const;
180
181 private:
182   QtxPathListEdit* myPathEdit;
183 };
184
185 /*!
186   \brief Constructor.
187   \internal
188   \param pe path list editor
189   \param parent parent widget
190 */
191 QtxPathListEdit::Delegate::Delegate( QtxPathListEdit* pe, QObject* parent )
192 : QItemDelegate( parent ),
193   myPathEdit( pe )
194 {
195 }
196
197 /*!
198   \brief Destructor.
199   \internal
200 */
201 QtxPathListEdit::Delegate::~Delegate()
202 {
203 }
204
205 /*!
206   \brief Create editor widget.
207   \internal
208   \param parent parent widget
209   \param option style option
210   \param index data model index
211 */
212 QWidget* QtxPathListEdit::Delegate::createEditor( QWidget* parent, const QStyleOptionViewItem& option,
213                                                   const QModelIndex& index ) const
214 {
215   return myPathEdit->createEditor( parent );
216 }
217
218 /*!
219   \brief Set modified data back to the data model.
220   \internal
221   \param editor editor widget
222   \param model data model
223   \param index data model index
224 */
225 void QtxPathListEdit::Delegate::setModelData( QWidget* editor, QAbstractItemModel* model,
226                                               const QModelIndex& index ) const
227 {
228   myPathEdit->setModelData( editor, index );
229 }
230
231 /*!
232   \brief Set data from the data model to the editor.
233   \internal
234   \param editor editor widget
235   \param index data model index
236 */
237 void QtxPathListEdit::Delegate::setEditorData( QWidget* editor, const QModelIndex& index ) const
238 {
239   myPathEdit->setEditorData( editor, index );
240 }
241
242 /*!
243   \brief Customize paint operation.
244   \internal
245   \param painter painter
246   \param option style option
247   \param index data model index
248 */
249 void QtxPathListEdit::Delegate::paint( QPainter* painter, const QStyleOptionViewItem& option,
250                                        const QModelIndex& index ) const
251 {
252   QPalette::ColorGroup cg = option.state & QStyle::State_Enabled ? QPalette::Normal : QPalette::Disabled;
253   if ( cg == QPalette::Normal && !( option.state & QStyle::State_Active ) )
254     cg = QPalette::Inactive;
255
256   if ( option.state & QStyle::State_Selected )
257   {
258     painter->fillRect( option.rect, option.palette.brush( cg, QPalette::Highlight ) );
259     painter->setPen( option.palette.color( cg, QPalette::HighlightedText ) );
260   }
261   else
262     painter->setPen( option.palette.color( cg, QPalette::Text ) );
263
264   QItemDelegate::paint( painter, option, index );
265 }
266
267 /*!
268   \brief Customize drawing selection focus operation.
269   \internal
270   \param painter painter
271   \param option style option
272   \param rect selection rectangle
273 */
274 void QtxPathListEdit::Delegate::drawFocus( QPainter* painter, const QStyleOptionViewItem& option,
275                                            const QRect& rect ) const
276 {
277   QItemDelegate::drawFocus( painter, option, option.rect );
278 }
279
280 /*!
281   \class QtxPathListEdit
282   \brief The QtxPathListEdit class represents a widget for files or 
283   directories paths list preference items editing.
284
285   The path list preference item is represented as the list box widget.
286   It provides such operations like adding new file/directory path to the
287   list, removing selected paths and modifying of already entered ones.
288
289   The widget can be used in two modes: list of files or list of directories.
290   The mode defines the type of the standard browse dialog box which is
291   invoked on the browse button clicking.
292
293   Initial path list value can be set with setPathList() method. Chosen path
294   list can be retrieved with the pathList() method. The widget mode can be set 
295   with setPathType() and retrieved with pathType() method.
296
297   In addition, it is possible to add path items to the list with the insert()
298   method, remove items with the remove() methods, clear all the widget contents
299   with the clear() method. To get the number of entered paths can be retrieved
300   with the count() method. To check if any path already exists in the paths list,
301   use contains() method.
302 */
303
304 /*!
305   \brief Constructor.
306   \param type widget mode (Qtx::PathType)
307   \param parent parent widget
308   \sa pathType(), setPathType()
309 */
310 QtxPathListEdit::QtxPathListEdit( const Qtx::PathType type, QWidget* parent )
311 : QFrame( parent ),
312   myCompleter( 0 ),
313   myType( type ),
314   myDuplicate( false )
315 {
316   initialize();
317 }
318
319 /*!
320   \brief Constructor.
321
322   Qtx::PT_OpenFile mode is used by default.
323
324   \param parent parent widget
325   \sa pathType(), setPathType()
326 */
327 QtxPathListEdit::QtxPathListEdit( QWidget* parent )
328 : QFrame( parent ),
329   myCompleter( 0 ),
330   myType( Qtx::PT_OpenFile ),
331   myDuplicate( false )
332 {
333   initialize();
334 }
335
336 /*!
337   \brief Destructor.
338 */
339 QtxPathListEdit::~QtxPathListEdit()
340 {
341 }
342
343 /*!
344   \brief Get widget mode.
345   \return currently used widget mode (Qtx::PathType)
346   \sa setPathType()
347 */
348 Qtx::PathType QtxPathListEdit::pathType() const
349 {
350   return myType;
351 }
352
353 /*!
354   \brief Set widget mode.
355   \param t new widget mode (Qtx::PathType)
356   \sa pathType()
357 */
358 void QtxPathListEdit::setPathType( const Qtx::PathType t )
359 {
360   if ( myType == t )
361     return;
362
363   myType = t;
364
365   delete myCompleter;
366   myCompleter = 0;
367 }
368
369 /*!
370   \brief Get currently selected paths list.
371   \return files or directories paths list entered by the user
372   \sa setPathList()
373 */
374 QStringList QtxPathListEdit::pathList() const
375 {
376   return myModel->stringList();
377 }
378
379 /*!
380   \brief Set paths list.
381   \param lst files or directories paths list
382   \sa pathList()
383 */
384 void QtxPathListEdit::setPathList( const QStringList& lst )
385 {
386   myModel->setStringList( lst );
387 }
388
389 /*!
390   \brief Check if the duplication of paths is enabled.
391   \return \c true if the duplication is enabled
392 */
393 bool QtxPathListEdit::isDuplicateEnabled() const
394 {
395   return myDuplicate;
396 }
397
398 /*!
399   \brief Enable/disable paths duplication.
400   \param on new flag value
401 */
402 void QtxPathListEdit::setDuplicateEnabled( const bool on )
403 {
404   myDuplicate = on;
405 }
406
407 /*!
408   \brief Get number of currently entered paths.
409   \return current paths number
410 */
411 int QtxPathListEdit::count() const
412 {
413   return myModel->rowCount();
414 }
415
416 /*!
417   \brief Check if the specified \a path already exists in 
418   the paths list.
419   \param path path to be checked
420   \return \c true if the path is already selected by the user 
421   or \c false otherwise
422 */
423 bool QtxPathListEdit::contains( const QString& path ) const
424 {
425   return myModel->stringList().contains( path );
426 }
427
428 /*!
429   \brief Clear paths list.
430 */
431 void QtxPathListEdit::clear()
432 {
433   myModel->removeRows( 0, myModel->rowCount() );
434 }
435
436 /*!
437   \brief Remove path from the paths list.
438   \param idx path index in the list
439 */
440 void QtxPathListEdit::remove( const int idx )
441 {
442   if ( 0 <= idx && idx < myModel->rowCount() )
443     myModel->removeRow( idx );
444 }
445
446 /*!
447   \brief Remove path from the paths list.
448   \param path path to be removed
449 */
450 void QtxPathListEdit::remove( const QString& path )
451 {
452   QModelIndexList indexes = myModel->match( myModel->index( 0, 0 ), Qt::DisplayRole, path,
453                                             myModel->rowCount(), Qt::MatchExactly | Qt::MatchCaseSensitive );
454   while ( !indexes.isEmpty() )
455   {
456     myModel->removeRow( indexes.last().row() );
457     indexes.removeLast();
458   }
459 }
460
461 /*!
462   \brief Add path to the list of paths.
463
464   If the specified index is out of range, the path is added to 
465   the end of the list.
466
467   \param path path to be added
468   \param idx index in the list to which the path should be inserted.
469 */
470 void QtxPathListEdit::insert( const QString& path, const int idx )
471 {
472   int index = idx < 0 ? myModel->rowCount() : qMin( idx, myModel->rowCount() );
473   if ( myModel->insertRow( index ) )
474     myModel->setData( myModel->index( index, 0 ), path, Qt::EditRole );
475 }
476
477 /*
478 bool QtxPathListEdit::validate( const bool quietMode )
479 {
480   if ( myEdited )
481   {
482     QString dirPath = QFileInfo( myEdit->text().stripWhiteSpace() ).filePath();
483     QDir dir(dirPath);
484     QListBoxItem* found = 0;
485     for (unsigned i = 0; i < myList->count()-1; i++) {
486       QDir aDir(myList->text(i));
487       if ( aDir.canonicalPath().isNull() && myList->text(i) == dir.absPath() ||
488           !aDir.canonicalPath().isNull() && aDir.exists() && aDir.canonicalPath() == dir.canonicalPath()) {
489           found = myList->item(i);
490         break;
491       }
492     }
493     if (dirPath.isEmpty()) {
494       if (found) {
495         // it should be last (empty) item in the list - nothing to do
496         return true;
497       }
498       else {
499         // delete directory from the list
500         removeDir(myLastSelected);
501         return true;
502       }
503     }
504     else {
505       if (found) {
506         if (found != myLastSelected) {
507           // it is forbidden to add directory more then once
508           if ( !quietMode )
509             QMessageBox::critical(this, 
510                                   tr("Error"),
511                                   tr("Directory already specified."), 
512                                   tr("Ok"));
513           myEdit->setFocus();
514           return false;
515         }
516       }
517       else {
518         if (!dir.exists()) {
519           if ( !quietMode && QMessageBox::information(this, 
520                                                       tr("Warning"),
521                                                       tr("%1\n\nThe directory doesn't exist.\nAdd directory anyway?").arg(dir.absPath()),
522                                                       tr("Yes"), tr("No"), QString(), 1, 1) == 1) {
523             myEdit->setFocus();
524             return false;
525           }
526         }
527         // append
528         appendDir(myLastSelected, dir.absPath());
529       }
530     }
531   }
532   return true;
533 }
534 */
535
536 /*!
537   \brief Customize child widget events processing.
538   \param o event receiver object
539   \param e event
540   \return \c true if the further event processing should be stopped.
541 */
542 bool QtxPathListEdit::eventFilter( QObject* o, QEvent* e )
543 {
544   if ( e->type() == QEvent::KeyPress )
545   {
546     QKeyEvent* ke = (QKeyEvent*)e;
547     if ( ke->key() == Qt::Key_Delete )
548       onDelete();
549     else if ( ke->key() == Qt::Key_Insert )
550       onInsert();
551     else if ( ke->key() == Qt::Key_Up && ke->modifiers() == Qt::CTRL )
552     {
553       onUp();
554       return true;
555     }
556     else if ( ke->key() == Qt::Key_Down && ke->modifiers() == Qt::CTRL )
557     {
558       onDown();
559       return true;
560     }
561   }
562
563   return QFrame::eventFilter( o, e );
564 }
565
566 /*!
567   \brief Called when <Insert> button is clicked.
568
569   Inserts new empty line to the list and sets input focus to it.
570
571   \param on (not used)
572 */
573 void QtxPathListEdit::onInsert( bool /*on*/ )
574 {
575   int empty = -1;
576   QStringList lst = myModel->stringList();
577   for ( int r = 0; r < lst.count() && empty == -1; r++ )
578   {
579     if ( lst.at( r ).isEmpty() )
580       empty = r;
581   }
582
583   if ( empty == -1 )
584     myModel->insertRows( empty = myModel->rowCount(), 1 );
585
586   QModelIndex idx = myModel->index( empty, 0 );
587   myList->setCurrentIndex( idx );
588   myList->edit( idx );
589 }
590
591 /*!
592   \brief Called when <Delete> button is clicked.
593
594   Removes currently selected path item.
595   
596   \param on (not used)
597 */
598 void QtxPathListEdit::onDelete( bool )
599 {
600   QModelIndex idx = myList->currentIndex();
601   if ( !idx.isValid() )
602     return;
603
604   myModel->removeRow( idx.row() );
605 }
606
607 /*!
608   \brief Called when <Up> button is clicked.
609
610   Move currently selected path item up to one row in the paths list.
611
612   \param on (not used)
613 */
614 void QtxPathListEdit::onUp( bool )
615 {
616   QModelIndex idx = myList->currentIndex();
617   if ( !idx.isValid() || idx.row() < 1 )
618     return;
619
620   QModelIndex toIdx = myModel->index( idx.row() - 1, 0 );
621
622   QVariant val = myModel->data( toIdx, Qt::DisplayRole );
623   myModel->setData( toIdx, myModel->data( idx, Qt::DisplayRole ), Qt::DisplayRole );
624   myModel->setData( idx, val, Qt::DisplayRole );
625
626   myList->setCurrentIndex( toIdx );
627 }
628
629 /*!
630   \brief Called when <Down> button is clicked.
631
632   Move currently selected path item down to one row in the paths list.
633
634   \param on (not used)
635 */
636 void QtxPathListEdit::onDown( bool )
637 {
638   QModelIndex idx = myList->currentIndex();
639   if ( !idx.isValid() || idx.row() >= myModel->rowCount() - 1 )
640     return;
641
642   QModelIndex toIdx = myModel->index( idx.row() + 1, 0 );
643
644   QVariant val = myModel->data( toIdx, Qt::DisplayRole );
645   myModel->setData( toIdx, myModel->data( idx, Qt::DisplayRole ), Qt::DisplayRole );
646   myModel->setData( idx, val, Qt::DisplayRole );
647
648   myList->setCurrentIndex( toIdx );
649 }
650
651 /*!
652   \brief Perform internal widget initialization.
653 */
654 void QtxPathListEdit::initialize()
655 {
656   QVBoxLayout* base = new QVBoxLayout( this );
657   base->setMargin( 0 );
658   base->setSpacing( 5 );
659
660   QWidget* cBox = new QWidget( this );
661   base->addWidget( cBox );
662   
663   QHBoxLayout* cLayout = new QHBoxLayout( cBox );
664   cLayout->setMargin( 0 );
665   cLayout->setSpacing( 0 );
666
667   cLayout->addStretch( 1 );
668
669   QToolButton* insertBtn = new QToolButton( cBox );
670   insertBtn->setIcon( QPixmap( insert_icon ) );
671   cLayout->addWidget( insertBtn );
672
673   QToolButton* deleteBtn = new QToolButton( cBox );
674   deleteBtn->setIcon( QPixmap( delete_icon ) );
675   cLayout->addWidget( deleteBtn );
676
677   QToolButton* upBtn = new QToolButton( cBox );
678   upBtn->setIcon( QPixmap( moveup_icon ) );
679   cLayout->addWidget( upBtn );
680
681   QToolButton* downBtn = new QToolButton( cBox );
682   downBtn->setIcon( QPixmap( movedown_icon ) );
683   cLayout->addWidget( downBtn );
684
685
686   myList = new QListView( this );
687   myList->setAlternatingRowColors( true );
688   myList->setItemDelegate( new Delegate( this, myList ) );
689   myList->setModel( myModel = new QStringListModel( myList ) );
690   myList->setSelectionMode( QListView::SingleSelection );
691   myList->setSelectionBehavior( QListView::SelectRows );
692   myList->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
693   myList->setEditTriggers( QListView::DoubleClicked );
694   myList->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) );
695   myList->installEventFilter( this );
696
697   base->addWidget( myList );
698
699   connect( insertBtn, SIGNAL( clicked( bool ) ), this, SLOT( onInsert( bool ) ) );
700   connect( deleteBtn, SIGNAL( clicked( bool ) ), this, SLOT( onDelete( bool ) ) );
701   connect( upBtn,     SIGNAL( clicked( bool ) ), this, SLOT( onUp( bool ) ) );
702   connect( downBtn,   SIGNAL( clicked( bool ) ), this, SLOT( onDown( bool ) ) );
703 }
704
705 /*!
706   \brief Create editor widget.
707   \param parent parent widget for the editor
708   \return created editor widget
709 */
710 QWidget* QtxPathListEdit::createEditor( QWidget* parent )
711 {
712   QtxPathEdit* edit = new Editor( parent );
713   edit->setPathType( pathType() );
714   return edit;
715 }
716
717 /*!
718   \brief Set modified data from the editor to the list widget.
719   \param editor editor widget
720   \param index data model index
721 */
722 void QtxPathListEdit::setModelData( QWidget* editor, const QModelIndex& index )
723 {
724   QtxPathEdit* edit = ::qobject_cast<QtxPathEdit*>( editor );
725   if ( !edit )
726     return;
727
728   QString path = edit->path().trimmed();
729
730   if ( !isDuplicateEnabled() && !checkDuplicate( path, index.row() ) )
731     return;
732
733   if ( !checkExistance( path ) )
734     return;
735
736   myModel->setData( index, path, Qt::EditRole );
737 }
738
739 /*!
740   \brief Set data to the editor from the list widget when 
741   user starts path edition.
742   \param editor editor widget
743   \param index data model index
744 */
745 void QtxPathListEdit::setEditorData( QWidget* editor, const QModelIndex& index )
746 {
747   QtxPathEdit* edit = ::qobject_cast<QtxPathEdit*>( editor );
748   if ( !edit )
749     return;
750
751   QVariant v = myModel->data( index, Qt::EditRole );
752   edit->setPath( v.toString() );
753 }
754
755 /*!
756   \brief Check if path is correct (exists) and optionally 
757   show the question message box.
758   \param str path to be checked
759   \param msg if \c true and path does not exist, question message box is shown
760   \return \c true if the user confirms the path adding
761 */
762 bool QtxPathListEdit::checkExistance( const QString& str, const bool msg )
763 {
764   if ( pathType() == Qtx::PT_SaveFile )
765     return true;
766
767   bool ok = QFileInfo( str ).exists();
768   if ( !ok && msg )
769     ok = QMessageBox::question( this, tr( "Warning" ), tr( "Path \"%1\" doesn't exist. Add it to list anyway?" ).arg( str ),
770                                 QMessageBox::Yes, QMessageBox::No ) == QMessageBox::Yes;
771
772   if ( ok && QFileInfo( str ).exists() )
773   {
774     switch ( pathType() )
775     {
776     case Qtx::PT_OpenFile:
777       ok = QFileInfo( str ).isFile();
778       if ( !ok && msg )
779         QMessageBox::warning( this, tr( "Error" ), tr( "Location \"%1\" doesn't point to file" ).arg( str ) );
780       break;
781     case Qtx::PT_Directory:
782       ok = QFileInfo( str ).isDir();
783       if ( !ok && msg )
784         QMessageBox::warning( this, tr( "Error" ), tr( "Location \"%1\" doesn't point to directory" ).arg( str ) );
785       break;
786     }
787   }
788
789   return ok;
790 }
791
792 /*!
793   \brief Check if path already exists in the list and optionally
794   show the warning message box.
795   \param str path to be checked
796   \param row row corresponding to the path checked
797   \param msg if \c true and path does not exist, warning message box is shown
798   \return \c true if the user confirms the path adding
799 */
800 bool QtxPathListEdit::checkDuplicate( const QString& str, const int row, const bool msg )
801 {
802   int cur = -1;
803   QStringList lst = myModel->stringList();
804   for ( int r = 0; r < lst.count() && cur == -1; r++ )
805   {
806     if ( r != row && lst.at( r ) == str )
807       cur = r;
808   }
809
810   if ( cur != -1 && msg )
811     QMessageBox::warning( this, tr( "Error" ), tr( "Path \"%1\" already exist in the list" ).arg( str ) );
812    
813   return cur == -1;
814 }