Salome HOME
Fix for bug #393: It's impossible to work in Change layer order dialog with keyboard...
[modules/hydro.git] / src / HYDROGUI / HYDROGUI_OrderedListWidget.cxx
1 // Copyright (C) 2007-2013  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
23 #include "HYDROGUI_OrderedListWidget.h"
24
25 #include "HYDROGUI_ListModel.h"
26
27 #include <SUIT_Session.h>
28 #include <SUIT_ResourceMgr.h>
29
30 #include <QLayout>
31 #include <QListView>
32 #include <QPushButton>
33 #include <QSignalMapper>
34 #include <QSortFilterProxyModel>
35
36
37 /**
38   Constructor.
39   @param theParent the parent widget
40 */
41 HYDROGUI_OrderedListWidget::HYDROGUI_OrderedListWidget( QWidget* theParent )
42 : QWidget( theParent )
43 {
44   // Main layout
45   QHBoxLayout* aMainLayout = new QHBoxLayout( this );
46   aMainLayout->setSpacing( 5 );
47
48   // List view
49   myList = new QListView( this );
50   myList->setSelectionMode( QAbstractItemView::ExtendedSelection );
51   // enable drag and drop
52   myList->setDragEnabled( true );
53   myList->setAcceptDrops( true );
54   // configure drag and drop
55   myList->setDropIndicatorShown( true );
56   myList->setDragDropMode( QAbstractItemView::InternalMove );
57
58   // Set the custom model
59   HYDROGUI_ListModel* aModel = new HYDROGUI_ListModel();
60   QSortFilterProxyModel* aFilteredModel = new QSortFilterProxyModel();
61   aFilteredModel->setSourceModel( aModel );
62   aFilteredModel->setFilterKeyColumn( 0 );
63   aFilteredModel->setFilterRole( HYDROGUI_VisibleRole );
64
65   myList->setModel( aFilteredModel );
66
67   // Buttons top, up, down, bottom
68   SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr();
69   myTop = new QPushButton( this );
70   myTop->setIcon( aResMgr->loadPixmap( "HYDRO", tr( "ARROW_TOP_ICO" ) ) );
71   myTop->setIconSize( QSize( 32, 32 ) );
72   myUp = new QPushButton( this );
73   myUp->setIcon( aResMgr->loadPixmap( "HYDRO", tr( "ARROW_UP_ICO" ) ) );
74   myUp->setIconSize( myTop->iconSize() );
75   myDown = new QPushButton( this );
76   myDown->setIcon( aResMgr->loadPixmap( "HYDRO", tr( "ARROW_DOWN_ICO" ) ) );
77   myDown->setIconSize( myTop->iconSize() );
78   myBottom = new QPushButton( this );
79   myBottom->setIcon( aResMgr->loadPixmap( "HYDRO", tr( "ARROW_BOTTOM_ICO" ) ) );
80   myBottom->setIconSize( myTop->iconSize() );
81
82   // Layout
83   // buttons
84   QVBoxLayout* aListButtonsLayout = new QVBoxLayout();
85   aListButtonsLayout->addWidget( myTop );
86   aListButtonsLayout->addWidget( myUp );
87   aListButtonsLayout->addWidget( myDown );
88   aListButtonsLayout->addWidget( myBottom );
89   aListButtonsLayout->addStretch();
90   // main
91   aMainLayout->addWidget( myList );
92   aMainLayout->addLayout( aListButtonsLayout );
93
94   // Connections
95   QSignalMapper* aSignalMapper = new QSignalMapper( this );
96   aSignalMapper->setMapping( myTop, HYDROGUI_ListModel::Top );
97   aSignalMapper->setMapping( myUp, HYDROGUI_ListModel::Up );
98   aSignalMapper->setMapping( myDown, HYDROGUI_ListModel::Down );
99   aSignalMapper->setMapping( myBottom, HYDROGUI_ListModel::Bottom );
100   connect( myTop, SIGNAL( clicked() ), aSignalMapper, SLOT( map() ) );
101   connect( myUp, SIGNAL( clicked() ), aSignalMapper, SLOT( map() ) );
102   connect( myDown, SIGNAL( clicked() ), aSignalMapper, SLOT( map() ) );
103   connect( myBottom, SIGNAL( clicked() ), aSignalMapper, SLOT( map() ) );
104   connect( aSignalMapper, SIGNAL( mapped( int ) ), this, SLOT( onMove( int ) ) );
105
106   connect ( myList->selectionModel(), SIGNAL( selectionChanged( QItemSelection, QItemSelection ) ), 
107             this, SIGNAL( selectionChanged() ) );
108
109   // Initialize
110   setHiddenObjectsShown( true );
111 }
112
113 /**
114   Destructor.
115 */
116 HYDROGUI_OrderedListWidget::~HYDROGUI_OrderedListWidget()
117 {
118 }
119
120 /**
121   Set the list of objects (which supposed to be ordered by the widget).
122   @param theObjects the list of pairs (object; visibility)
123 */
124 void HYDROGUI_OrderedListWidget::setObjects( const HYDROGUI_ListModel::Object2VisibleList& theObjects )
125 {
126   HYDROGUI_ListModel* aModel = getSourceModel();
127   if( aModel ) {
128     aModel->setObjects( theObjects );
129   }
130 }
131
132 /**
133   Returns the ordered list of objects.
134   @return the list of objects
135 */
136 QList<Handle(HYDROData_Entity)> HYDROGUI_OrderedListWidget::getObjects() const
137 {
138   QList<Handle(HYDROData_Entity)> anObjects;
139
140   HYDROGUI_ListModel* aModel = getSourceModel();
141   if( aModel ) {
142     anObjects = aModel->getObjects();
143   }
144
145   return anObjects;
146 }
147
148 /**
149   Set whether the hidden objects are presented in the list.
150   @param theIsToShow if true - the hidden objects will be shown in the list
151 */
152 void HYDROGUI_OrderedListWidget::setHiddenObjectsShown( const bool theIsToShow )
153 {
154   myIsHiddenObjectsShown = theIsToShow; 
155
156   QSortFilterProxyModel* aFilterModel = dynamic_cast<QSortFilterProxyModel*>( myList->model() );
157   QString anExpr = theIsToShow ? "true|false" : "true";
158   aFilterModel->setFilterRegExp( anExpr );
159 }
160
161 /**
162   Get entries of the selected objects.
163   @return the list of entries
164 */
165 QStringList HYDROGUI_OrderedListWidget::getSelectedEntries() const
166
167   QStringList anEntries;
168
169   QSortFilterProxyModel* aFilterModel = 
170     dynamic_cast<QSortFilterProxyModel*>( myList->model() );
171   if( aFilterModel ) {
172     HYDROGUI_ListModel* aSourceModel = 
173       dynamic_cast<HYDROGUI_ListModel*>( aFilterModel->sourceModel() );
174     if ( aSourceModel ) {
175       QModelIndexList aSelectedIndexes = myList->selectionModel()->selectedIndexes();
176       foreach ( const QModelIndex& anIndex, aSelectedIndexes ) {
177         QModelIndex aSourceIndex = aFilterModel->mapToSource( anIndex );
178         QString anEntry = aSourceModel->data( aSourceIndex, HYDROGUI_EntryRole ).toString();
179         anEntries << anEntry;
180       }
181     }
182   }
183
184   return anEntries;
185 }
186
187 /**
188   Set objects with the given entries selected (other objects will deselected).
189   @param theEntries the list of entries
190 */
191 void HYDROGUI_OrderedListWidget::setSelectedEntries( const QStringList& theEntries ) const
192 {
193   QSortFilterProxyModel* aFilterModel = dynamic_cast<QSortFilterProxyModel*>( myList->model() );
194   if( !aFilterModel ) {
195     return;
196   }
197   HYDROGUI_ListModel* aSourceModel = dynamic_cast<HYDROGUI_ListModel*>( aFilterModel->sourceModel() );
198   if ( !aSourceModel ) {
199     return;
200   }
201   QItemSelectionModel* aSelectionModel = myList->selectionModel();
202   if ( !aSelectionModel ) {
203     return;
204   }
205   
206   for ( int aRow = 0 ; aRow < aSourceModel->rowCount() ; aRow++ ) {
207     QModelIndex anIndex = aSourceModel->index( aRow, 0 );
208     if ( !anIndex.isValid() ) {
209       continue;
210     }
211
212     QString anEntry = aSourceModel->data( anIndex, HYDROGUI_EntryRole ).toString();
213
214     bool isToSelect = theEntries.contains( anEntry );
215     QModelIndex aProxyModelIndex = aFilterModel->mapFromSource( anIndex );
216     QItemSelectionModel::SelectionFlags aSelectionFlags =
217       isToSelect ? QItemSelectionModel::Select : QItemSelectionModel::Deselect;
218     aSelectionModel->select( aProxyModelIndex, aSelectionFlags );
219   }
220 }
221
222 /**
223   Slot called on top, up, down and bottom button click.
224   @param theType the move operation type
225 */
226 void HYDROGUI_OrderedListWidget::onMove( int theType )
227 {
228   QSortFilterProxyModel* aFilterModel = dynamic_cast<QSortFilterProxyModel*>( myList->model() );
229   if( aFilterModel ) {
230     HYDROGUI_ListModel* aModel = dynamic_cast<HYDROGUI_ListModel*>( aFilterModel->sourceModel() );
231     if( aModel ) {
232       QModelIndexList aSelectedIndexes = myList->selectionModel()->selectedIndexes();
233       QModelIndexList aSelectedSourceIndexes;
234       foreach ( const QModelIndex& anIndex, aSelectedIndexes ) {
235         aSelectedSourceIndexes << aFilterModel->mapToSource( anIndex );
236       }
237       QList<int> aSelectedIds = aModel->getIds( aSelectedSourceIndexes );
238       aModel->move( aSelectedIds, ( HYDROGUI_ListModel::OpType )theType, 
239                     !myIsHiddenObjectsShown );      
240     }
241   }
242 }
243
244 /**
245   Returns the list source model.
246   @return the source model
247 */
248 HYDROGUI_ListModel* HYDROGUI_OrderedListWidget::getSourceModel() const
249 {
250   HYDROGUI_ListModel* aSourceModel = 0;
251
252   QSortFilterProxyModel* aFilterModel = dynamic_cast<QSortFilterProxyModel*>( myList->model() );
253   if( aFilterModel ) {
254     aSourceModel = dynamic_cast<HYDROGUI_ListModel*>( aFilterModel->sourceModel() );
255   }
256
257   return aSourceModel;
258 }