0029018: Documentation - Provide user guide for Qt browser
[occt.git] / tools / DFBrowser / DFBrowser_TreeLevelLine.cxx
1 // Created on: 2017-06-16
2 // Created by: Natalia ERMOLAEVA
3 // Copyright (c) 2017 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement. 
15
16 #include <inspector/DFBrowser_TreeLevelLine.hxx>
17
18 #include <inspector/DFBrowser_SearchLine.hxx>
19 #include <inspector/DFBrowser_Window.hxx>
20 #include <inspector/DFBrowser_TreeLevelLineDelegate.hxx>
21 #include <inspector/DFBrowser_TreeLevelLineModel.hxx>
22
23 #include <inspector/DFBrowserPane_Tools.hxx>
24
25 #include <QAbstractItemModel>
26 #include <QFrame>
27 #include <QGridLayout>
28 #include <QHeaderView>
29 #include <QItemSelectionModel>
30 #include <QPainter>
31 #include <QScrollBar>
32 #include <QTableView>
33 #include <QToolButton>
34 #include <QWidget>
35
36 const int HISTORY_SIZE = 10;
37 const int MARGIN_SIZE = 2;
38
39 // =======================================================================
40 // function : Constructor
41 // purpose :
42 // =======================================================================
43 DFBrowser_TreeLevelLine::DFBrowser_TreeLevelLine (QWidget* theParent)
44 : QObject (theParent), mySelectionProcessingBlocked (false), myCurrentHistoryIndex (-1)
45 {
46   myMainWindow = new QWidget (theParent);
47   QGridLayout* aLayout = new QGridLayout (myMainWindow);
48   aLayout->setContentsMargins (MARGIN_SIZE, MARGIN_SIZE, MARGIN_SIZE, MARGIN_SIZE);
49
50   myBackwardButton = new QToolButton (myMainWindow);
51   myBackwardButton->setIcon (QIcon (":/icons/treeline_backward.png"));
52   myBackwardButton->setToolTip (tr ("Backward"));
53   connect (myBackwardButton, SIGNAL (clicked()), this, SLOT (onActionClicked()));
54   aLayout->addWidget (myBackwardButton, 0, 0);
55
56   myForwardButton = new QToolButton (myMainWindow);
57   myForwardButton->setIcon (QIcon (":/icons/treeline_forward.png"));
58   myForwardButton->setToolTip (tr ("Forward"));
59   connect (myForwardButton, SIGNAL (clicked()), this, SLOT (onActionClicked()));
60   aLayout->addWidget (myForwardButton, 0, 1);
61
62   myTableView = new QTableView (myMainWindow);
63   myTableView->horizontalHeader()->setVisible (false);
64   QHeaderView* aVHeader = myTableView->verticalHeader();
65   aVHeader->setVisible (false);
66   int aDefCellSize = aVHeader->minimumSectionSize() + DFBrowserPane_Tools::HeaderSectionMargin();
67   aVHeader->setDefaultSectionSize (aDefCellSize);
68   aLayout->addWidget (myTableView, 0, 2);
69
70   myTableView->setFixedHeight (aDefCellSize);
71   myTableView->horizontalHeader()->setMinimumSectionSize (5); // it will be resized by context
72   myTableView->setHorizontalScrollMode (QAbstractItemView::ScrollPerItem);
73   myTableView->setHorizontalScrollBarPolicy (Qt::ScrollBarAlwaysOff); //! TEMPORARY
74   myTableView->setShowGrid (false);
75
76   DFBrowser_TreeLevelLineModel* aHModel = new DFBrowser_TreeLevelLineModel (myTableView);
77   myTableView->setModel (aHModel);
78
79   QItemSelectionModel* aSelectionModel = new QItemSelectionModel (aHModel);
80   myTableView->setSelectionMode (QAbstractItemView::SingleSelection);
81   myTableView->setSelectionModel (aSelectionModel);
82   connect (aSelectionModel, SIGNAL (selectionChanged (const QItemSelection&, const QItemSelection&)),
83            this, SLOT (onTableSelectionChanged (const QItemSelection&, const QItemSelection&)));
84
85   // highlight for items
86   myTableView->viewport()->setAttribute (Qt::WA_Hover);
87   myTableView->setItemDelegate (new DFBrowser_TreeLevelLineDelegate (myTableView));
88
89   aLayout->setColumnStretch (2, 1);
90
91   myUpdateButton = new QToolButton (myMainWindow);
92   myUpdateButton->setIcon (QIcon (":/icons/treeline_update.png"));
93   myUpdateButton->setToolTip (tr ("Update Tree Model"));
94   connect (myUpdateButton, SIGNAL (clicked()), this, SLOT (onActionClicked()));
95   aLayout->addWidget (myUpdateButton, 0, 3);
96
97   mySearchLine = new DFBrowser_SearchLine (myMainWindow);
98   aLayout->addWidget (mySearchLine, 0, 4);
99
100   updateActionsState();
101 }
102
103 // =======================================================================
104 // function : clear
105 // purpose :
106 // =======================================================================
107 void DFBrowser_TreeLevelLine::ClearHistory()
108 {
109   myHistoryIndices.clear();
110   setCurrentHistoryIndex (-1);
111 }
112
113 // =======================================================================
114 // function : onSelectionChanged
115 // purpose :
116 // =======================================================================
117 void DFBrowser_TreeLevelLine::OnTreeViewSelectionChanged (const QItemSelection& theSelected,
118                                                           const QItemSelection&)
119 {
120   QModelIndexList aSelectedIndices = theSelected.indexes();
121   QModelIndex aSelectedIndex = DFBrowser_Window::SingleSelected (aSelectedIndices, 0);
122
123   if (!mySelectionProcessingBlocked) // we're processing action click
124     setForwardIndex (aSelectedIndex);
125
126   bool isBlocked = mySelectionProcessingBlocked;
127   // block selection processing in order to avoid circling by processing table selection changing
128   mySelectionProcessingBlocked = true;
129   DFBrowser_TreeLevelLineModel* aModel = dynamic_cast<DFBrowser_TreeLevelLineModel*> (myTableView->model());
130   aModel->Init (aSelectedIndex);
131   myTableView->selectionModel()->clearSelection();
132   myTableView->resizeColumnsToContents();
133
134   myTableView->scrollTo (myTableView->model()->index (0, myTableView->model()->columnCount()-1));
135
136   mySelectionProcessingBlocked = isBlocked;
137 }
138
139 // =======================================================================
140 // function : onTableSelectionChanged
141 // purpose :
142 // =======================================================================
143 void DFBrowser_TreeLevelLine::onTableSelectionChanged (const QItemSelection& theSelected,
144                                                        const QItemSelection&)
145 {
146   if (mySelectionProcessingBlocked)
147     return;
148
149   DFBrowser_TreeLevelLineModel* aTableModel = dynamic_cast<DFBrowser_TreeLevelLineModel*> (myTableView->model());
150   if (!aTableModel)
151     return;
152
153   QModelIndex aSelectedIndex = DFBrowser_Window::SingleSelected (theSelected.indexes(), 0, Qt::Vertical);
154   emit indexSelected (aTableModel->GetTreeViewIndex (aSelectedIndex));
155 }
156
157 // =======================================================================
158 // function : onActionClicked
159 // purpose :
160 // =======================================================================
161 void DFBrowser_TreeLevelLine::onActionClicked()
162 {
163   QToolButton* aSender = (QToolButton*)sender();
164   if (aSender == myBackwardButton || aSender == myForwardButton)
165   {
166     bool aBlocked = mySelectionProcessingBlocked;
167     mySelectionProcessingBlocked = true;
168     QModelIndex anIndex;
169     if (aSender == myBackwardButton)
170     {
171       anIndex = getBackwardIndex();
172       if (anIndex.isValid())
173         setCurrentHistoryIndex (myCurrentHistoryIndex - 1);
174     }
175     else
176     {
177       anIndex = getForwardIndex();
178       if (anIndex.isValid())
179         setCurrentHistoryIndex (myCurrentHistoryIndex + 1);
180     }
181     if (anIndex.isValid())
182       emit indexSelected (anIndex);
183     mySelectionProcessingBlocked = aBlocked;
184   }
185   else if (aSender == myUpdateButton)
186     emit updateClicked();
187 }
188
189 // =======================================================================
190 // function : getBackwardIndex
191 // purpose :
192 // =======================================================================
193 QModelIndex DFBrowser_TreeLevelLine::getBackwardIndex()
194 {
195   return myCurrentHistoryIndex > 0 ? myHistoryIndices[myCurrentHistoryIndex-1] : QModelIndex();
196 }
197
198 // =======================================================================
199 // function : getForwardIndex
200 // purpose :
201 // =======================================================================
202 QModelIndex DFBrowser_TreeLevelLine::getForwardIndex()
203 {
204   return (myCurrentHistoryIndex >= 0 && myCurrentHistoryIndex + 1 < myHistoryIndices.count())
205      ? myHistoryIndices[myCurrentHistoryIndex + 1] : QModelIndex();
206 }
207
208 // =======================================================================
209 // function : setForwardIndex
210 // purpose :
211 // =======================================================================
212 void DFBrowser_TreeLevelLine::setForwardIndex (const QModelIndex& theIndex)
213 {
214   while (myCurrentHistoryIndex != myHistoryIndices.count() - 1)
215     myHistoryIndices.removeLast();
216
217   myHistoryIndices.append (theIndex);
218   if (myHistoryIndices.size() > HISTORY_SIZE)
219     myHistoryIndices.removeFirst();
220
221   setCurrentHistoryIndex (myHistoryIndices.count() - 1);
222 }
223
224 // =======================================================================
225 // function : setCurrentHistoryIndex
226 // purpose :
227 // =======================================================================
228 void DFBrowser_TreeLevelLine::setCurrentHistoryIndex (const int theIndexId)
229 {
230   myCurrentHistoryIndex = theIndexId;
231   updateActionsState();
232 }
233
234 // =======================================================================
235 // function : updateActionsState
236 // purpose :
237 // =======================================================================
238 void DFBrowser_TreeLevelLine::updateActionsState()
239 {
240   if (myCurrentHistoryIndex < 0)
241   {
242     myBackwardButton->setEnabled (false);
243     myForwardButton->setEnabled (false);
244   }
245   else
246   {
247     myBackwardButton->setEnabled (myCurrentHistoryIndex > 0);
248     myForwardButton->setEnabled (myCurrentHistoryIndex < myHistoryIndices.size() - 1);
249   }
250 }