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/TInspector_OpenFileDialog.hxx>
17 
18 #include <inspector/TInspector_OpenButton.hxx>
19 #include <inspector/TInspector_OpenFileViewModel.hxx>
20 
21 #include <inspector/TInspector_Communicator.hxx>
22 
23 #include <Standard_WarningsDisable.hxx>
24 #include <QApplication>
25 #include <QCompleter>
26 #include <QDir>
27 #include <QFileDialog>
28 #include <QFileSystemModel>
29 #include <QItemSelectionModel>
30 #include <QGroupBox>
31 #include <QHBoxLayout>
32 #include <QHeaderView>
33 #include <QLabel>
34 #include <QLineEdit>
35 #include <QScrollBar>
36 #include <QTableView>
37 #include <QToolButton>
38 #include <QPushButton>
39 #include <QVBoxLayout>
40 #include <QWidget>
41 #include <Standard_WarningsRestore.hxx>
42 
43 static const int ICON_SIZE = 40;
44 
45 static const int OPEN_DIALOG_WIDTH = 550;
46 static const int OPEN_DIALOG_HEIGHT = 200;
47 
48 static const int MARGIN_DIALOG = 4;
49 static const int SPACING_DIALOG = 2;
50 
51 static const int RECENT_FILES_CACHE_SIZE = 10;
52 
53 TInspector_Communicator* MyCommunicator;
54 
55 // =======================================================================
56 // function : changeMargins
57 // purpose :
58 // =======================================================================
changeMargins(QBoxLayout * theLayout)59 void changeMargins (QBoxLayout* theLayout)
60 {
61   theLayout->setContentsMargins (MARGIN_DIALOG, MARGIN_DIALOG, MARGIN_DIALOG, MARGIN_DIALOG);
62   theLayout->setSpacing (SPACING_DIALOG);
63 }
64 
65 // =======================================================================
66 // function : Constructor
67 // purpose :
68 // =======================================================================
TInspector_OpenFileDialog(QWidget * theParent,const QStringList & theRecentlyOpenedFiles)69 TInspector_OpenFileDialog::TInspector_OpenFileDialog (QWidget* theParent, const QStringList& theRecentlyOpenedFiles)
70 : QDialog (theParent), myRecentlyOpenedFiles (theRecentlyOpenedFiles)
71 {
72   setWindowTitle (tr ("Open File"));
73 
74   QVBoxLayout* aDialogLay = new QVBoxLayout (this);
75   changeMargins (aDialogLay);
76 
77   // Samples View
78   QGroupBox* aSamplesBox = new QGroupBox (this);
79   aSamplesBox->setTitle (tr ("Recent files"));
80   aDialogLay->addWidget (aSamplesBox);
81   QVBoxLayout* aSampleLay = new QVBoxLayout (aSamplesBox);
82   changeMargins (aSampleLay);
83   mySamplesView = createTableView (theRecentlyOpenedFiles);
84   aSampleLay->addWidget (mySamplesView);
85 
86   // Select file
87   QGroupBox* aSelectFileBox = new QGroupBox (this);
88   aSelectFileBox->setTitle (tr ("Select file"));
89   aDialogLay->addWidget (aSelectFileBox);
90   QGridLayout* aSelectFileLay = new QGridLayout (aSelectFileBox);
91   aSelectFileLay->setContentsMargins (MARGIN_DIALOG, MARGIN_DIALOG, MARGIN_DIALOG, MARGIN_DIALOG);
92 
93   mySelectedName = new QLineEdit (aSelectFileBox);
94   QCompleter* aCompleter = new QCompleter();
95   QFileSystemModel* aFileSystemModel = new QFileSystemModel;
96   aFileSystemModel->setRootPath (QDir::rootPath());
97   aCompleter->setModel (aFileSystemModel);
98   mySelectedName->setCompleter (aCompleter);
99   aSelectFileLay->addWidget (mySelectedName, 1, 0);
100 
101   QToolButton* aSelectFileBtn = new QToolButton (aSelectFileBox);
102   aSelectFileBtn->setIcon (QIcon (":folder_open.png"));
103   aSelectFileLay->addWidget (aSelectFileBtn, 1, 1);
104 
105   connect (aSelectFileBtn, SIGNAL (clicked()), this, SLOT (onSelectClicked()));
106   connect (mySelectedName, SIGNAL (returnPressed()), this, SLOT (onApplySelectClicked()));
107 
108   resize (OPEN_DIALOG_WIDTH, OPEN_DIALOG_HEIGHT);
109 }
110 
111 // =======================================================================
112 // function : OpenFile
113 // purpose :
114 // =======================================================================
OpenFile(QWidget * theParent,const QStringList & theRecentlyOpenedFiles)115 QString TInspector_OpenFileDialog::OpenFile (QWidget* theParent, const QStringList& theRecentlyOpenedFiles)
116 {
117   QString aFileName;
118   TInspector_OpenFileDialog* aDialog = new TInspector_OpenFileDialog (theParent, theRecentlyOpenedFiles);
119   if (aDialog->exec() == QDialog::Accepted)
120     aFileName = aDialog->GetFileName();
121 
122   return aFileName;
123 }
124 
125 // =======================================================================
126 // function : Communicator
127 // purpose :
128 // =======================================================================
Communicator()129 TInspector_Communicator* TInspector_OpenFileDialog::Communicator()
130 {
131   if (!MyCommunicator)
132     MyCommunicator = new TInspector_Communicator();
133   return MyCommunicator;
134 }
135 
136 // =======================================================================
137 // function : GetPluginRecentlyOpenedFiles
138 // purpose :
139 // =======================================================================
GetPluginRecentlyOpenedFiles(const TCollection_AsciiString & thePluginName,TInspector_Communicator * theCommunicator,QStringList & theFileNames)140 void TInspector_OpenFileDialog::GetPluginRecentlyOpenedFiles (const TCollection_AsciiString& thePluginName,
141                                                                  TInspector_Communicator* theCommunicator,
142                                                                  QStringList& theFileNames)
143 {
144   Handle(TInspectorAPI_PluginParameters) aParameters = theCommunicator->GetPluginParameters();
145   TInspectorAPI_PreferencesDataMap aPreferencesItem;
146   aParameters->GetPreferences (thePluginName, aPreferencesItem);
147 
148   for (TInspectorAPI_IteratorOfPreferencesDataMap anItemIt (aPreferencesItem); anItemIt.More(); anItemIt.Next())
149   {
150     if (!anItemIt.Key().IsEqual("recently_opened_files"))
151       continue;
152     theFileNames = QString(anItemIt.Value().ToCString()).split(";", QString::SkipEmptyParts);
153     if (theFileNames.size() > RECENT_FILES_CACHE_SIZE)
154       for (int i = 0; i < theFileNames.size() - RECENT_FILES_CACHE_SIZE; i++)
155         theFileNames.removeFirst();
156     break;
157   }
158 }
159 
160 // =======================================================================
161 // function : SetPluginRecentlyOpenedFiles
162 // purpose :
163 // =======================================================================
SetPluginRecentlyOpenedFiles(const TCollection_AsciiString & thePluginName,TInspector_Communicator * theCommunicator,QStringList & theFileNames)164 void TInspector_OpenFileDialog::SetPluginRecentlyOpenedFiles (const TCollection_AsciiString& thePluginName,
165                                                                  TInspector_Communicator* theCommunicator,
166                                                                  QStringList& theFileNames)
167 {
168   Handle(TInspectorAPI_PluginParameters) aParameters = theCommunicator->GetPluginParameters();
169 
170   TInspectorAPI_PreferencesDataMap aPreferencesItem;
171   aParameters->GetPreferences (thePluginName, aPreferencesItem);
172   aPreferencesItem.Bind ("recently_opened_files", TCollection_AsciiString (theFileNames.join (";").toUtf8().data()));
173 
174   aParameters->SetPreferences (thePluginName, aPreferencesItem);
175 }
176 
177 // =======================================================================
178 // function : onSampleSelectionChanged
179 // purpose :
180 // =======================================================================
onSampleSelectionChanged(const QItemSelection & theSelected,const QItemSelection &)181 void TInspector_OpenFileDialog::onSampleSelectionChanged (const QItemSelection& theSelected,
182                                                              const QItemSelection&)
183 {
184   QItemSelectionModel* aSelectionModel = (QItemSelectionModel*)sender();
185   if (!aSelectionModel)
186     return;
187   if (theSelected.isEmpty())
188     return;
189 
190   QModelIndex anIndex = theSelected.first().indexes().first();
191   if (!anIndex.isValid())
192     return;
193 
194   myFileName = aSelectionModel->model()->data (anIndex, Qt::ToolTipRole).toString();
195   accept();
196 }
197 
198 // =======================================================================
199 // function : onSelectClicked
200 // purpose :
201 // =======================================================================
onSelectClicked()202 void TInspector_OpenFileDialog::onSelectClicked()
203 {
204   QString anEnteredPath;
205   QString aDirName = mySelectedName->text();
206   if (!aDirName.isEmpty())
207   {
208     QDir aDir (aDirName);
209     if (aDir.exists())
210       anEnteredPath = aDirName;
211   }
212 
213   QString aFileName = QFileDialog::getOpenFileName (0, "Open document", anEnteredPath);
214 
215   if (aFileName.isEmpty())
216     return; // do nothing, left the previous value
217 
218 
219   myFileName = aFileName;
220   accept();
221 }
222 
223 // =======================================================================
224 // function : onApplySelectClicked
225 // purpose :
226 // =======================================================================
onApplySelectClicked()227 void TInspector_OpenFileDialog::onApplySelectClicked()
228 {
229   QString aFileName = mySelectedName->text();
230 
231   QFileInfo aFileInfo (aFileName);
232   if (!aFileInfo.exists() || !aFileInfo.isFile())
233     return;
234 
235   myFileName = mySelectedName->text();
236   accept();
237 }
238 
239 // =======================================================================
240 // function : createTableView
241 // purpose :
242 // =======================================================================
createTableView(const QStringList & theFileNames)243 QTableView* TInspector_OpenFileDialog::createTableView (const QStringList& theFileNames)
244 {
245   QTableView* aTableView = new QTableView (this);
246   aTableView->setFrameStyle (QFrame::NoFrame);
247   QPalette aPalette = aTableView->viewport()->palette();
248   QColor aWindowColor = aPalette.color (QPalette::Window);
249   aPalette.setBrush (QPalette::Base, aWindowColor);
250   aTableView->viewport()->setPalette (aPalette);
251 
252   aTableView->horizontalHeader()->setVisible (false);
253   aTableView->verticalHeader()->setVisible (false);
254   aTableView->setGridStyle (Qt::NoPen);
255   aTableView->setModel (createModel (theFileNames));
256   aTableView->setItemDelegateForRow (0, new TInspectorEXE_OpenFileItemDelegate (aTableView,
257                                                           aPalette.color (QPalette::Highlight)));
258   aTableView->viewport()->setAttribute (Qt::WA_Hover);
259   int aCellHeight = ICON_SIZE + aTableView->verticalHeader()->defaultSectionSize();
260   aTableView->setRowHeight (0, aCellHeight);
261   int aScrollHeight = aTableView->horizontalScrollBar()->sizeHint().height();
262   aTableView->setMinimumHeight (aCellHeight + aScrollHeight);
263   QItemSelectionModel* aSelectionModel = new QItemSelectionModel (aTableView->model());
264   connect (aSelectionModel, SIGNAL (selectionChanged (const QItemSelection&, const QItemSelection&)),
265            this, SLOT (onSampleSelectionChanged (const QItemSelection&, const QItemSelection&)));
266   aTableView->setSelectionModel (aSelectionModel);
267 
268   return aTableView;
269 }
270 
271 // =======================================================================
272 // function : createModel
273 // purpose :
274 // =======================================================================
createModel(const QStringList & theFileNames)275 QAbstractItemModel* TInspector_OpenFileDialog::createModel (const QStringList& theFileNames)
276 {
277   TInspector_OpenFileViewModel* aModel = new TInspector_OpenFileViewModel (this);
278   aModel->Init (theFileNames);
279   return aModel;
280 }
281