0030268: Inspectors - improvements in VInspector plugin
[occt.git] / tools / TreeModel / TreeModel_Tools.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/TreeModel_Tools.hxx>
17 #include <inspector/TreeModel_ModelBase.hxx>
18 #include <inspector/TreeModel_ColumnType.hxx>
19 #include <inspector/TreeModel_VisibilityState.hxx>
20
21 #include <Standard_WarningsDisable.hxx>
22 #include <QAction>
23 #include <QApplication>
24 #include <QFont>
25 #include <QFontMetrics>
26 #include <QHeaderView>
27 #include <QObject>
28 #include <QRegExp>
29 #include <QStringList>
30 #include <QStyle>
31 #include <QTreeView>
32 #include <Standard_WarningsRestore.hxx>
33
34 const int INFO_LENGHT = 60;
35
36 // =======================================================================
37 // function : ToString
38 // purpose :
39 // =======================================================================
40 QString TreeModel_Tools::ToString (const QByteArray& theValue)
41 {
42   char aBuffer[8];
43   QStringList aBytesList;
44   for (int aByteId = 0; aByteId < theValue.size();  aByteId++)
45   {
46     ::sprintf (aBuffer, "#%02X", (unsigned char)theValue.at (aByteId));
47     aBytesList.append (QString (aBuffer));
48   }
49   return QString ("@ByteArray[%1]").arg (aBytesList.join (" "));
50 }
51
52 // =======================================================================
53 // function : ToByteArray
54 // purpose :
55 // =======================================================================
56 QByteArray TreeModel_Tools::ToByteArray (const QString& theValue)
57 {
58   QByteArray aStateArray;
59   if (!theValue.startsWith ("@ByteArray[") || !theValue.endsWith (']'))
60     return aStateArray;
61
62   QString aValue = theValue.mid (11, theValue.size() - 12);
63   QStringList lst = aValue.split (QRegExp ("[\\s|,]"), QString::SkipEmptyParts);
64   for (QStringList::ConstIterator aByteId = lst.begin(); aByteId != lst.end(); ++aByteId)
65   {
66     int aBase = 10;
67     QString aString = *aByteId;
68     if (aString.startsWith ("#"))
69     {
70       aBase = 16;
71       aString = aString.mid (1);
72     }
73     bool isOk = false;
74     int aNum = aString.toInt (&isOk, aBase);
75     if (!isOk || aNum < 0 || aNum > 255)
76       continue;
77     aStateArray.append ((char)aNum);
78   }
79   return aStateArray;
80 }
81
82 // =======================================================================
83 // function : SaveState
84 // purpose :
85 // =======================================================================
86 void TreeModel_Tools::SaveState (QTreeView* theTreeView, QMap<QString, QString>& theItems,
87                                  const QString& thePrefix)
88 {
89   QStringList aColumnWidths, aHiddenColumns;
90   for (int aColumnId = 0; aColumnId < theTreeView->model()->columnCount(); aColumnId++)
91   {
92     if (theTreeView->isColumnHidden (aColumnId))
93     {
94       aHiddenColumns.append (QString::number (aColumnId));
95       aColumnWidths.append (QString());
96     }
97     else
98       aColumnWidths.append (QString::number (theTreeView->columnWidth (aColumnId)));
99   }
100   theItems[thePrefix + "columns_width"] = aColumnWidths.join (",");
101   theItems[thePrefix + "columns_hidden"] = aHiddenColumns.join (",");
102 }
103
104 // =======================================================================
105 // function : RestoreState
106 // purpose :
107 // =======================================================================
108 bool TreeModel_Tools::RestoreState (QTreeView* theTreeView, const QString& theKey, const QString& theValue,
109                                     const QString& thePrefix)
110 {
111   if (theKey == thePrefix + "columns_width")
112   {
113     QStringList aValues = theValue.split (",");
114     for (int aColumnId = 0; aColumnId < theTreeView->model()->columnCount() && aColumnId < aValues.size(); aColumnId++)
115     {
116       bool isOk;
117       int aWidth = aValues.at (aColumnId).toInt (&isOk);
118       if (isOk && !theTreeView->isColumnHidden (aColumnId)) // do not resize hidden columnsa
119         theTreeView->setColumnWidth (aColumnId, aWidth);
120     }
121   }
122   else if (theKey == thePrefix + "columns_hidden")
123   {
124     int aColumnSize = theTreeView->model()->columnCount();
125     QStringList aValues = theValue.split (",", QString::SkipEmptyParts);
126     QList<int> aColumnIds;
127     for (int aValueId = 0; aValueId < aValues.size(); aValueId++)
128     {
129       if (aValueId < aColumnSize)
130         aColumnIds.append (aValues.at (aValueId).toInt());
131     }
132     for (int aColumnId = 0; aColumnId < aColumnSize; aColumnId++)
133     {
134       theTreeView->setColumnHidden (aColumnId, aColumnIds.contains(aColumnId) == true);
135     }
136   }
137   else
138     return false;
139   return true;
140 }
141
142 // =======================================================================
143 // function : SetDefaultHeaderSections
144 // purpose :
145 // =======================================================================
146 void TreeModel_Tools::SetDefaultHeaderSections(QTreeView* theTreeView)
147 {
148   TreeModel_ModelBase* aTreeModel = dynamic_cast<TreeModel_ModelBase*> (theTreeView->model());
149
150   for (int aColumnId = 0, aNbColumns = aTreeModel->columnCount(); aColumnId < aNbColumns; aColumnId++)
151   {
152     TreeModel_HeaderSection aSection = aTreeModel->GetHeaderItem (aColumnId);
153     theTreeView->setColumnWidth (aColumnId, aSection.GetWidth());
154     theTreeView->setColumnHidden (aColumnId, aSection.IsHidden());
155   }
156 }
157
158 // =======================================================================
159 // function : UseVisibilityColumn
160 // purpose :
161 // =======================================================================
162 void TreeModel_Tools::UseVisibilityColumn (QTreeView* theTreeView, const bool theActive)
163 {
164   QHeaderView* aHeader = theTreeView->header();
165 #if QT_VERSION < 0x050000
166   aHeader->setResizeMode (TreeModel_ColumnType_Visibility, QHeaderView::Fixed);
167 #else
168   aHeader->setSectionResizeMode (TreeModel_ColumnType_Visibility, QHeaderView::Fixed);
169 #endif
170   aHeader->moveSection (TreeModel_ColumnType_Name, TreeModel_ColumnType_Visibility);
171
172   TreeModel_ModelBase* aModel = dynamic_cast<TreeModel_ModelBase*> (theTreeView->model());
173   aModel->SetHeaderItem (TreeModel_ColumnType_Visibility,
174     TreeModel_HeaderSection ("Visibility", TreeModel_ModelBase::ColumnVisibilityWidth()));
175   aModel->SetUseVisibilityColumn (theActive);
176 }
177
178 // =======================================================================
179 // function : GetTextWidth
180 // purpose :
181 // =======================================================================
182 int TreeModel_Tools::GetTextWidth (const QString& theText, QObject*)
183 {
184   // TODO: find margins like QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin, 0, (QWidget*)theParent);
185   int aTextMargin = 10;
186   QFontMetrics aFontMetrics (QApplication::font());
187   QRect aBoundingRect = aFontMetrics.boundingRect (theText);
188   return qMax (aBoundingRect.width(), aFontMetrics.width (theText)) + aTextMargin * 2;
189 }
190
191 // =======================================================================
192 // function : CutString
193 // purpose :
194 // =======================================================================
195 QString TreeModel_Tools::CutString (const QString& theText, const int theWidth, const QString& theTail)
196 {
197   if (theText.isEmpty())
198     return theText;
199
200   int aLength = theWidth < 0 ? INFO_LENGHT : theWidth - 3;
201
202   int anIndex = theText.indexOf ('\n');
203   if (anIndex > 0 && anIndex < aLength)
204     aLength = anIndex;
205
206   return aLength < theText.length() ? theText.mid (0, aLength) + theTail : theText;
207 }
208
209 // =======================================================================
210 // function : LightHighlightColor
211 // purpose :
212 // =======================================================================
213 QColor TreeModel_Tools::LightHighlightColor()
214 {
215   QWidget aWidget;
216   QPalette aPalette = aWidget.palette();
217   return aPalette.highlight().color().lighter();
218 }
219
220 // =======================================================================
221 // function : SetExpandedTo
222 // purpose :
223 // =======================================================================
224 void TreeModel_Tools::SetExpandedTo (QTreeView* theTreeView, const QModelIndex& theIndex)
225 {
226   QAbstractItemModel* aModel = theTreeView->model();
227
228   QModelIndex aParent = aModel->parent (theIndex);
229   while (aParent.isValid())
230   {
231     theTreeView->setExpanded (aParent, true);
232     aParent = aModel->parent (aParent);
233   }
234 }
235
236 // =======================================================================
237 // function : setExpanded
238 // purpose :
239 // =======================================================================
240 void TreeModel_Tools::SetExpanded (QTreeView* theTreeView, const QModelIndex& theIndex, const bool isExpanded,
241                                    int& theLevels)
242 {
243   bool isToExpand = theLevels == -1 || theLevels > 0;
244   if (!isToExpand)
245     return;
246
247   theTreeView->setExpanded (theIndex, isExpanded);
248   if (theLevels != -1)
249     theLevels--;
250
251   QAbstractItemModel* aModel = theTreeView->model();
252   for (int aRowId = 0, aRows = aModel->rowCount (theIndex); aRowId < aRows; aRowId++)
253   {
254     int aLevels = theLevels;
255     SetExpanded (theTreeView, aModel->index (aRowId, 0, theIndex), isExpanded, aLevels);
256   }
257 }