Optika GUI Toolik  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Optika_metawindow.cpp
Go to the documentation of this file.
1 // @HEADER
2 // ***********************************************************************
3 //
4 // Optika: A Tool For Developing Parameter Obtaining GUIs
5 // Copyright (2009) Sandia Corporation
6 //
7 // Under terms of Contract DE-AC04-94AL85000, with Sandia Corporation, the
8 // U.S. Government retains certain rights in this software.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact Kurtis Nusbaum (klnusbaum@gmail.com)
38 //
39 // ***********************************************************************
40 // @HEADER
41 #include "Optika_metawindow.hpp"
42 #include "Optika_Version.hpp"
43 #include <QLineEdit>
44 #include <QLabel>
45 #include <QPushButton>
46 #include <QFileDialog>
47 #include <QMessageBox>
48 #include <QAction>
49 #include <QMenu>
50 #include <QMenuBar>
51 #include <QtGui>
52 #include <QIcon>
53 #include <iostream>
54 #include <algorithm>
55 #include <QSettings>
56 namespace Optika{
57 
58 
59 const int numRecentDocuments = 7;
60 
61 SearchWidget::SearchWidget(TreeModel *treeModel, TreeView *treeView, QWidget *parent):
62  QDialog(parent),
63  treeModel(treeModel),
64  treeView(treeView)
65 {
66  matchesLabel = new QLabel(tr("Matches"));
67  searchButton = new QPushButton(tr("Search"));
68  connect(searchButton, SIGNAL(clicked(bool)), this, SLOT(search()));
69  closeButton = new QPushButton(tr("Close"));
70  connect(closeButton, SIGNAL(clicked(bool)), this, SLOT(hide()));
71  nextButton = new QPushButton(tr("Next"));
72  connect(nextButton, SIGNAL(clicked(bool)), this, SLOT(next()));
73  previousButton = new QPushButton(tr("Previous"));
74  connect(previousButton, SIGNAL(clicked(bool)), this, SLOT(previous()));
75  searchTermsEdit = new QLineEdit(tr("Enter Search Terms Here"));
76  QGridLayout *layout = new QGridLayout(this);
77  layout->addWidget(searchTermsEdit,0,0);
78  layout->addWidget(searchButton,0,1);
79  layout->addWidget(nextButton,0,3);
80  layout->addWidget(previousButton,0,2);
81  layout->addWidget(closeButton,2,3);
82  layout->addWidget(matchesLabel,3,0);
83  setLayout(layout);
84  nextButton->setDisabled(true);
85  previousButton->setDisabled(true);
86  setSizeGripEnabled(true);
87  setWindowTitle(tr("Search..."));
88 }
89 
91  currentSearchResults = treeModel->match(treeModel->index(0,0,QModelIndex()), Qt::DisplayRole, searchTermsEdit->text(),
92  -1, Qt::MatchWrap | Qt::MatchContains | Qt::MatchRecursive);
95  int searchSize = currentSearchResults.size();
96  matchesLabel->setText("Matches ("+ QString::number(searchSize) + ")");
97  if(searchSize <= 0){
98  nextButton->setDisabled(true);
99  previousButton->setDisabled(true);
100  }
101  else if(searchSize == 1){
102  nextButton->setDisabled(true);
103  previousButton->setDisabled(true);
104  treeView->setCurrentIndex(*currentSearchIterator);
105  }
106  else{
107  nextButton->setDisabled(false);
108  previousButton->setDisabled(false);
109  treeView->setCurrentIndex(*currentSearchIterator);
110  }
111 }
112 
117  }
118  treeView->setCurrentIndex(*currentSearchIterator);
119 }
120 
125  }
126  treeView->setCurrentIndex(*currentSearchIterator);
127 }
128 
129 QModelIndexList SearchWidget::removeHiddenItems(QModelIndexList& items){
130  QModelIndexList toReturn;
131  for(QModelIndexList::iterator it = items.begin(); it != items.end(); ++it){
132  if(!treeView->isRowHidden(it->row(), it->parent())){
133  toReturn.append(*it);
134  }
135  }
136  return toReturn;
137 }
138 
140  RCP<ParameterList> validParameters,
141  RCP<DependencySheet> dependencySheet,
142  void (*customFunc)(RCP<const ParameterList>),
143  QString fileName,
144  const std::string actionButtonText,
145  const std::string actionNoSaveButtonText)
146 {
147  model = new TreeModel(validParameters, dependencySheet, fileName, this);
148  initilization(customFunc, actionButtonText, actionNoSaveButtonText);
149 }
150 
151 
153  saveSettings();
154 }
155 
156 void MetaWindow::closeEvent(QCloseEvent *event){
157  if(!model->isSaved()){
159  saveSettings();
160  event->accept();
161  }
162  else{
163  event->ignore();
164  }
165  }
166  else{
167  saveSettings();
168  event->accept();
169  }
170 }
171 
173  void (*customFunc)(RCP<const ParameterList>),
174  const std::string actionButtonText,
175  const std::string actionNoSaveButtonText)
176 {
177  this->customFunc = customFunc;
178  delegate = new Delegate(this);
179  view = new TreeView(model, delegate, this);
180  view->setEditTriggers(QAbstractItemView::DoubleClicked | QAbstractItemView::SelectedClicked);
181  searchWidget = new SearchWidget(model, view, this);
182  searchWidget->hide();
183  actionButton = NULL;
184  actionNoSaveButton = NULL;
185  if(actionButtonText != ""){
186  actionButton =
187  new QPushButton(QString::fromStdString(actionButtonText), this);
188  }
189  else{
190  actionButton = new QPushButton(tr("Submit"), this);
191  }
192  if(actionNoSaveButtonText != ""){
193  actionNoSaveButton = new QPushButton(QString::fromStdString(actionNoSaveButtonText), this);
194  }
195  QWidget *centerWidget = new QWidget(this);
196  QGridLayout *centerWidgetLayout = new QGridLayout(centerWidget);
197  centerWidgetLayout->addWidget(view,0,0);
198  connect(actionButton, SIGNAL(clicked(bool)), this, SLOT(doAction()));
199  if(actionNoSaveButton){
200  centerWidgetLayout->addWidget(actionButton,1,0,Qt::AlignLeft);
201  connect(actionNoSaveButton, SIGNAL(clicked(bool)), this, SLOT(doActionNoSave()));
202  centerWidgetLayout->addWidget(actionNoSaveButton,1,0,Qt::AlignRight);
203  }
204  else
205  centerWidgetLayout->addWidget(actionButton,1,0,Qt::AlignRight);
206  centerWidget->setLayout(centerWidgetLayout);
207  setCentralWidget(centerWidget);
208 
209  createActions();
210  createMenus();
211  resize(800,600);
212  currentLoadDir = QDir::homePath();
213  currentSaveDir = QDir::homePath();
215  setWindowTitle(tr("Parameter Input"));
216  view->show();
217  view->header()->resizeSections(QHeaderView::ResizeToContents);
218  view->header()->setMovable(false);
219 }
220 
222 // recentMenu = new QMenu(tr("Recent Solvers"));
223 // QAction *noRecentAct = new QAction(tr("No Recent Documents"),this);
224 // noRecentAct->setEnabled(false);
225 // recentMenu->addAction(noRecentAct);
226  fileMenu = menuBar()->addMenu(tr("File"));
227  fileMenu->addAction(resetAct);
228  //fileMenu->addMenu(recentMenu);
229  fileMenu->addSeparator();
230  fileMenu->addAction(saveAct);
231  fileMenu->addAction(saveAsAct);
232  fileMenu->addAction(loadAct);
233  fileMenu->addSeparator();
234  fileMenu->addAction(quitAct);
235  helpMenu = menuBar()->addMenu(tr("Help"));
236  helpMenu->addAction(aboutAct);
237  helpMenu->addAction(searchAct);
238 }
239 
241  resetAct = new QAction(tr("&Reset"),this);
242  resetAct->setShortcut(tr("Ctrl+R"));
243  resetAct->setStatusTip(tr("Reset the list to its original state."));
244  connect(resetAct, SIGNAL(triggered()), this, SLOT(resetModel()));
245 
246  saveAct = new QAction(tr("&Save"),this);
247  saveAct->setShortcut(tr("Ctrl+S"));
248  saveAct->setStatusTip(tr("Save the current file."));
249  connect(saveAct, SIGNAL(triggered()), this, SLOT(saveFile()));
250 
251  saveAsAct = new QAction(tr("Save As..."),this);
252  saveAsAct->setStatusTip(tr("Save the current file to a specified file name."));
253  connect(saveAsAct, SIGNAL(triggered()), this, SLOT(saveFileAs()));
254 
255  loadAct = new QAction(tr("&Load"),this);
256  loadAct->setShortcut(tr("Ctrl+L"));
257  loadAct->setStatusTip(tr("Load input file"));
258  connect(loadAct, SIGNAL(triggered()), this, SLOT(loadFile()));
259 
260  quitAct = new QAction(tr("&Quit"),this);
261  quitAct->setShortcut(tr("Ctrl+Q"));
262  quitAct->setStatusTip(tr("Quit"));
263  connect(quitAct, SIGNAL(triggered()), this, SLOT(close()));
264 
265  aboutAct = new QAction(tr("About"),this);
266  searchAct = new QAction(tr("Search For Parameter/Parameter List"), this);
267  searchAct->setToolTip("Search for a particular Parameter or ParameterList");
268  connect(aboutAct, SIGNAL(triggered()), this, SLOT(showAbout()));
269  connect(searchAct, SIGNAL(triggered()), this, SLOT(initiateSearch()));
270 }
271 
273  QString fileName = QFileDialog::getOpenFileName(this, tr("Load..."), currentLoadDir, tr("Xml (*.xml)"));
274  if(fileName != ""){
275  model->readInput(fileName);
276  currentLoadDir = fileName.section("/",0,-2);
277  addRecentDocument(fileName);
278  }
279 }
280 
282  QSettings settings(QSettings::UserScope, "Sandia", "Optika");
283  currentSaveDir =
284  settings.value(lastSaveDirSetting(), currentSaveDir).toString();
285  currentLoadDir =
286  settings.value(lastLoadDirSetting(), currentLoadDir).toString();
287  resize(settings.value(xresSetting(), width()).toInt(),
288  settings.value(yresSetting(), height()).toInt());
289  move(settings.value(xposSetting(), x()).toInt(),
290  settings.value(yposSetting(), y()).toInt());
291 }
292 
293 
295  QSettings settings(QSettings::UserScope, "Sandia", "Optika");
296 
297  settings.setValue(lastSaveDirSetting(), currentSaveDir);
298  settings.setValue(lastLoadDirSetting(), currentLoadDir);
299  settings.setValue(xresSetting(), width());
300  settings.setValue(yresSetting(), height());
301  settings.setValue(xposSetting(), x());
302  settings.setValue(yposSetting(), y());
303 }
304 
305 
306 void MetaWindow::addRecentDocument(QString recentDocument){
307  recentDocsList.prepend(recentDocument);
308  if(recentDocsList.size() > numRecentDocuments){
309  recentDocsList.removeLast();
310  }
311 // updateRecentDocsMenu();
312 }
313 
315  recentMenu->clear();
316  for(int i=0; i<recentDocsList.size(); ++i){
317  QAction *recentDocAct = new QAction(recentDocsList.at(i).section("/",-1,-1),this);
318  connect(recentDocAct, SIGNAL(triggered()), this, SLOT(loadRecentDoc()));
319  recentMenu->addAction(recentDocAct);
320  }
321 }
322 
324  if(!model->isSaved()){
326  }
327  model->reset();
328 }
329 
331  QString fileName = QFileDialog::getSaveFileName(this, tr("Save To..."), currentSaveDir, tr("XML (*.xml)"));
332  if(fileName.toStdString() != ""){
333  if(!fileName.endsWith(".xml")){
334  fileName = fileName.append(".xml");
335  }
336  if(model->writeOutput(fileName)){
337  currentSaveDir = fileName.section("/",0,-2);
338  addRecentDocument(fileName);
339  return true;
340  }
341  }
342  return false;
343 }
344 
346  QString currentFileName = model->getSaveFileName();
347  if(currentFileName != ""){
348  model->writeOutput(currentFileName);
349  }
350  else{
351  saveFileAs();
352  }
353 }
354 
355 
357  if(!model->isSaved()){
359  }
360  load();
361 }
362 
364  QMessageBox saveQuestion(QMessageBox::Question,
365  tr("Save?"),
366  tr("These choices have not been saved since you last made changes. Would you like to save them now?"),
367  QMessageBox::Yes | QMessageBox::No,
368  this);
369  saveQuestion.setDefaultButton(QMessageBox::Yes);
370  int shouldSave = saveQuestion.exec();
371  if(shouldSave == QMessageBox::Yes){
372  return saveFileAs();
373  }
374  return true;
375 }
376 
378  QString docName = dynamic_cast<QAction*>(sender())->text();
379  int i =0;
380  for(; i<recentDocsList.size();++i){
381  if(recentDocsList.at(i).contains(docName)){
382  break;
383  }
384  }
385  if(!model->isSaved()){
388  }
389  }
390 }
391 
393  QString aboutString = aboutInfo + "\nThis input obtainer was generated by Kurtis Nusbaum's Optika package, part of the Trilinos Project.\n\nVersion: " + QString::fromStdString(Optika_Version()) + "\nWebsite: trilinos.sandia.gov/packages/optika\nLicense: LGPL\nContact: klnusbaum@gmail.com";
394  QMessageBox::about(this,
395  "Optika Input Obtainer\n",
396  aboutString);
397 }
398 
400  searchWidget->show();
401 }
402 
404  if(customFunc == 0){
405  close();
406  }
407  else{
408  (*customFunc)(model->getCurrentParameters());
409  }
410 }
411 
413  model->setIsSaved();
414  doAction();
415 }
416 
417 void MetaWindow::setAboutInfo(QString aboutInfo){
418  this->aboutInfo = aboutInfo;
419 }
420 
422  return aboutInfo;
423 }
424 
425 void MetaWindow::setActionButtonText(QString newText){
426  actionButton->setText(newText);
427 }
428 
430  return actionButton->text();
431 }
432 
433 
434 } //namespace Optika
435 
void initiateSearch()
Starts a search for a parituclar Parameter or ParameterList.
bool saveCurrentUnsavedFile()
Asks the user whether or not they would like to currently save the file they are working on...
void loadRecentDoc()
Loads a document from the set of recent documents.
QString getActionButtonText()
Gets the text being displayed int he action button.
QAction * resetAct
Various actions.
static QString xresSetting()
Gets the name of the xres setting.
void reset()
Resets all the inputs to their default values.
SearchWidget(TreeModel *treeModel, TreeView *treeView, QWidget *parent=0)
Constructs a SearchWidget.
void resetModel()
Resets the treemodel to its default state.
QString getAboutInfo()
Gets the information to be added to the about dialog of the GUI.
~MetaWindow()
Deconstructer for the metawindow.
void createActions()
Creates all necessary actions used in the menut items.
QString getSaveFileName()
Gets the name of the save file with which the TreeModel is associated.
QPushButton * actionButton
The button the user pushes that either closes the MetaWindow or runs the custom function.
void initilization(void(*customFunc)(RCP< const ParameterList >)=0, const std::string actionButtonText="submit", const std::string actionNoSaveButtonText="")
Common initialization shared by all constructors.
A small widget that searchs through a parameter list for a particular name of either a parameter or a...
void doAction()
What should happen when the user clicks the action button.
void doActionNoSave()
What should happen when the user clicks the actionNoSave button.
void setIsSaved()
Set save state to true.
RCP< const ParameterList > getCurrentParameters()
Get a ParameterList containing all of the parameters at their current settings.
static QString lastLoadDirSetting()
Gets the name of the last load directory setting.
QModelIndexList removeHiddenItems(QModelIndexList &items)
Removes any indicies in a QModelIndexList that correspond to a hidden item.
MetaWindow(RCP< ParameterList > validParameters, RCP< DependencySheet > dependencySheet=null, void(*customFunc)(RCP< const ParameterList >)=NULL, QString fileName=QString(), const std::string actionButtonText="submit", const std::string actionNoSaveButtonText="")
Constructs a MainWindow object.
void updateRecentDocsMenu()
Currently under developement.
QPushButton * searchButton
Widgets comprising a search widget.
void saveFile()
Saves the current solver to the file the user has already specified.
static QString yresSetting()
Gets the name of the yres setting.
void addRecentDocument(QString recentDocument)
Currently under developement.
bool writeOutput(QString fileName)
Writes out the state of the current parameters in xml format.
void createMenus()
Creates all the menus for the metawindow.
void setActionButtonText(QString newText)
Sets the action button text.
void loadLastSettings()
Loads the last state of the MetaWindow (things like window size and screen position).
QString aboutInfo
Any additional about information that should be displayed in the about dialog.
static QString xposSetting()
Gets the name of the xpos setting.
bool saveFileAs()
Saves the parameter list settings to a user specified file.
QList< QModelIndex > currentSearchResults
The results of the search last performed.
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const
SearchWidget * searchWidget
Widgets comprising the MetaWindow.
void previous()
Highlights the previous result in the list of results that are set by the search function.
void readInput(QString fileName)
Reads an xml file that describes the state of current parameters in xml format.
Optika version information.
QMenu * fileMenu
Various menus.
Class used to view TreeModels.
TreeView * view
The TreeView being used in the metawindow.
void load()
Loads previous parameter settings.
QStringList recentDocsList
A list of recently used documents.
QString currentLoadDir
Load and save directory paths.
QPushButton * actionNoSaveButton
The button the user pushes that does the does not save.
const int numRecentDocuments
void next()
Highlights the next result in the list of results that are set by the search function.
Delegate * delegate
The deleages being used to modify any input values.
The main window users interact with along with a small search widget used in the main window...
void setAboutInfo(QString aboutInfo)
Adds the information specified to the about dialog of the GUI.
bool isSaved()
Determines wether or not the current state of TreeModel has been saved.
static QString yposSetting()
Gets the name of the ypos setting.
void closeEvent(QCloseEvent *event)
Handles any QCloseEvents for the metawindow.
std::string Optika_Version()
Return a string describing the version of Optika.
void(* customFunc)(RCP< const ParameterList >)
The custom function to run when the user clicks the action button.
TreeModel * model
The TreeModel being used to display the inputs.
void showAbout()
Shows information about the program.
void search()
Searches the for a parameter or parameter list containing the string enterd in the search terms box...
void saveSettings()
Saves the state of the MetaWindow (things like window size and screen position).
TreeModel is a type of QAbstractItemModel that has a Tree like structure.
static QString lastSaveDirSetting()
Gets the name of the last saved directory setting.
The delegate used for the Optika package. For non-documented functions please refer to the Qt API...
void loadFile()
Loads a solver the user was previously working on and had saved.
QList< QModelIndex >::const_iterator currentSearchIterator
An iterator over the results of the last search performed.