Optika GUI Toolik Version of the Day
Optika_metawindow.cpp
Go to the documentation of this file.
00001 // @HEADER
00002 // ***********************************************************************
00003 // 
00004 //         Optika: A Tool For Developing Parameter Obtaining GUIs
00005 //                Copyright (2009) Sandia Corporation
00006 // 
00007 // Under terms of Contract DE-AC04-94AL85000, with Sandia Corporation, the 
00008 // U.S. Government retains certain rights in this software.
00009 // 
00010 // This library is free software; you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as
00012 // published by the Free Software Foundation; either version 2.1 of the
00013 // License, or (at your option) any later version.
00014 //  
00015 // This library is distributed in the hope that it will be useful, but
00016 // WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018 // Lesser General Public License for more details.
00019 //  
00020 // You should have received a copy of the GNU Lesser General Public
00021 // License along with this library; if not, write to the Free Software
00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00023 // USA
00024 // Questions? Contact Kurtis Nusbaum (klnusbaum@gmail.com) 
00025 // 
00026 // ***********************************************************************
00027 // @HEADER
00028 #include "Optika_metawindow.hpp"
00029 #include "Optika_Version.hpp"
00030 #include <QLineEdit>
00031 #include <QLabel>
00032 #include <QPushButton>
00033 #include <QFileDialog>
00034 #include <QMessageBox> 
00035 #include <QAction>
00036 #include <QMenu>
00037 #include <QMenuBar>
00038 #include <QtGui>
00039 #include <QIcon>
00040 #include <iostream>
00041 #include <algorithm>
00042 #include <QSettings>
00043 namespace Optika{
00044 
00045 
00046 const int numRecentDocuments = 7; 
00047 
00048 SearchWidget::SearchWidget(TreeModel *treeModel, TreeView *treeView, QWidget *parent):
00049   QDialog(parent),
00050   treeModel(treeModel),
00051   treeView(treeView)
00052 {
00053   matchesLabel = new QLabel(tr("Matches"));
00054   searchButton = new QPushButton(tr("Search"));
00055   connect(searchButton, SIGNAL(clicked(bool)), this, SLOT(search()));
00056   closeButton = new QPushButton(tr("Close"));
00057   connect(closeButton, SIGNAL(clicked(bool)), this, SLOT(hide()));
00058   nextButton = new QPushButton(tr("Next"));
00059   connect(nextButton, SIGNAL(clicked(bool)), this, SLOT(next()));
00060   previousButton = new QPushButton(tr("Previous"));
00061   connect(previousButton, SIGNAL(clicked(bool)), this, SLOT(previous()));
00062   searchTermsEdit = new QLineEdit(tr("Enter Search Terms Here"));
00063   QGridLayout *layout = new QGridLayout(this);
00064   layout->addWidget(searchTermsEdit,0,0);
00065   layout->addWidget(searchButton,0,1);
00066   layout->addWidget(nextButton,0,3);
00067   layout->addWidget(previousButton,0,2);
00068   layout->addWidget(closeButton,2,3);
00069   layout->addWidget(matchesLabel,3,0);
00070   setLayout(layout);
00071   nextButton->setDisabled(true);
00072   previousButton->setDisabled(true);
00073   setSizeGripEnabled(true);
00074   setWindowTitle(tr("Search..."));
00075 }
00076 
00077 void SearchWidget::search(){
00078   currentSearchResults = treeModel->match(treeModel->index(0,0,QModelIndex()), Qt::DisplayRole, searchTermsEdit->text(), 
00079   -1, Qt::MatchWrap | Qt::MatchContains | Qt::MatchRecursive);
00080   currentSearchResults = removeHiddenItems(currentSearchResults);
00081   currentSearchIterator = currentSearchResults.begin(); 
00082   int searchSize = currentSearchResults.size();
00083   matchesLabel->setText("Matches ("+ QString::number(searchSize) + ")");
00084   if(searchSize <= 0){
00085     nextButton->setDisabled(true);
00086     previousButton->setDisabled(true);
00087   }
00088   else if(searchSize == 1){
00089     nextButton->setDisabled(true);
00090     previousButton->setDisabled(true);
00091     treeView->setCurrentIndex(*currentSearchIterator);
00092   }
00093   else{
00094     nextButton->setDisabled(false);
00095     previousButton->setDisabled(false);
00096     treeView->setCurrentIndex(*currentSearchIterator);
00097   }
00098 }
00099 
00100 void SearchWidget::next(){
00101   currentSearchIterator++;
00102   if(currentSearchIterator == currentSearchResults.end()){
00103     currentSearchIterator = currentSearchResults.begin();
00104   }
00105   treeView->setCurrentIndex(*currentSearchIterator);
00106 }
00107 
00108 void SearchWidget::previous(){
00109   currentSearchIterator--;
00110   if(currentSearchIterator == currentSearchResults.begin()-1){
00111     currentSearchIterator = currentSearchResults.end() -1;
00112   }
00113   treeView->setCurrentIndex(*currentSearchIterator);
00114 }
00115 
00116 QModelIndexList SearchWidget::removeHiddenItems(QModelIndexList& items){
00117   QModelIndexList toReturn;
00118   for(QModelIndexList::iterator it = items.begin(); it != items.end(); ++it){
00119     if(!treeView->isRowHidden(it->row(), it->parent())){
00120       toReturn.append(*it);
00121     }
00122   }
00123   return toReturn;
00124 }
00125 
00126 MetaWindow::MetaWindow(
00127   RCP<ParameterList> validParameters, 
00128   RCP<DependencySheet> dependencySheet, 
00129   void (*customFunc)(RCP<const ParameterList>), 
00130   QString fileName,
00131   const std::string actionButtonText)
00132 {
00133   model = new TreeModel(validParameters, dependencySheet, fileName, this);
00134   initilization(customFunc, actionButtonText);
00135 } 
00136 
00137 
00138 MetaWindow::~MetaWindow(){
00139   saveSettings();
00140 }
00141 
00142 void MetaWindow::closeEvent(QCloseEvent *event){
00143   if(!model->isSaved()){
00144     if(saveCurrentUnsavedFile()){
00145       saveSettings();
00146       event->accept();
00147     }
00148     else{
00149       event->ignore();
00150     }
00151   }
00152   else{
00153     saveSettings();
00154     event->accept();
00155   }
00156 }
00157 
00158 void MetaWindow::initilization(
00159   void (*customFunc)(RCP<const ParameterList>),
00160   const std::string actionButtonText)
00161 {
00162   this->customFunc = customFunc;
00163   delegate = new Delegate(this);
00164   view = new TreeView(model, delegate, this);
00165   view->setEditTriggers(QAbstractItemView::DoubleClicked | QAbstractItemView::SelectedClicked);
00166   searchWidget = new SearchWidget(model, view, this);
00167   searchWidget->hide();
00168   actionButton = NULL;
00169   if(actionButtonText != ""){
00170     actionButton = new QPushButton(tr("Submit"), this);
00171   }
00172   else{
00173     actionButton = 
00174       new QPushButton(QString::fromStdString(actionButtonText), this); 
00175   }
00176   QWidget *centerWidget = new QWidget(this);
00177   QGridLayout *centerWidgetLayout = new QGridLayout(centerWidget);
00178   centerWidgetLayout->addWidget(view,0,0);
00179   connect(actionButton, SIGNAL(clicked(bool)), this, SLOT(doAction()));
00180   centerWidgetLayout->addWidget(actionButton,1,0,Qt::AlignRight);
00181   centerWidget->setLayout(centerWidgetLayout);
00182   setCentralWidget(centerWidget);
00183 
00184   createActions();
00185   createMenus();
00186   resize(800,600);
00187   currentLoadDir = QDir::homePath();
00188   currentSaveDir = QDir::homePath();
00189   loadLastSettings();
00190   setWindowTitle(tr("Parameter Input"));
00191   view->show();
00192   view->header()->resizeSections(QHeaderView::ResizeToContents);
00193   view->header()->setMovable(false);
00194 }
00195 
00196 void MetaWindow::createMenus(){
00197 //  recentMenu = new QMenu(tr("Recent Solvers"));
00198 //  QAction *noRecentAct = new QAction(tr("No Recent Documents"),this);
00199 //  noRecentAct->setEnabled(false);
00200 //  recentMenu->addAction(noRecentAct);
00201   fileMenu = menuBar()->addMenu(tr("File"));
00202   fileMenu->addAction(resetAct);
00203   //fileMenu->addMenu(recentMenu);
00204   fileMenu->addSeparator();
00205   fileMenu->addAction(saveAct);
00206   fileMenu->addAction(saveAsAct);
00207   fileMenu->addAction(loadAct);
00208   fileMenu->addSeparator();
00209   fileMenu->addAction(quitAct);
00210   helpMenu = menuBar()->addMenu(tr("Help"));
00211   helpMenu->addAction(aboutAct);
00212   helpMenu->addAction(searchAct);
00213 }
00214 
00215 void MetaWindow::createActions(){
00216   resetAct = new QAction(tr("&Reset"),this);
00217   resetAct->setShortcut(tr("Ctrl+R"));
00218   resetAct->setStatusTip(tr("Reset the list to its original state."));
00219   connect(resetAct, SIGNAL(triggered()), this, SLOT(resetModel()));
00220 
00221   saveAct = new QAction(tr("&Save"),this);
00222   saveAct->setShortcut(tr("Ctrl+S"));
00223   saveAct->setStatusTip(tr("Save the current file."));
00224   connect(saveAct, SIGNAL(triggered()), this, SLOT(saveFile()));
00225 
00226   saveAsAct = new QAction(tr("Save As..."),this);
00227   saveAsAct->setStatusTip(tr("Save the current file to a specified file name."));
00228   connect(saveAsAct, SIGNAL(triggered()), this, SLOT(saveFileAs()));
00229 
00230   loadAct = new QAction(tr("&Load"),this);
00231   loadAct->setShortcut(tr("Ctrl+L"));
00232   loadAct->setStatusTip(tr("Load input file"));
00233   connect(loadAct, SIGNAL(triggered()), this, SLOT(loadFile()));
00234 
00235   quitAct = new QAction(tr("&Quit"),this);
00236   quitAct->setShortcut(tr("Ctrl+Q"));
00237   quitAct->setStatusTip(tr("Quit"));
00238   connect(quitAct, SIGNAL(triggered()), this, SLOT(close()));
00239 
00240   aboutAct = new QAction(tr("About"),this);
00241   searchAct = new QAction(tr("Search For Parameter/Parameter List"), this);
00242   searchAct->setToolTip("Search for a particular Parameter or ParameterList");
00243   connect(aboutAct, SIGNAL(triggered()), this, SLOT(showAbout()));
00244   connect(searchAct, SIGNAL(triggered()), this, SLOT(initiateSearch()));
00245 }
00246 
00247 void MetaWindow::load(){
00248   QString fileName = QFileDialog::getOpenFileName(this, tr("Load..."), currentLoadDir, tr("Xml (*.xml)"));
00249   if(fileName != ""){
00250     model->readInput(fileName);
00251     currentLoadDir = fileName.section("/",0,-2);
00252     addRecentDocument(fileName);
00253   }
00254 }
00255 
00256 void MetaWindow::loadLastSettings(){
00257   QSettings settings(QSettings::UserScope, "Sandia", "Optika");
00258   currentSaveDir = 
00259     settings.value(lastSaveDirSetting(), currentSaveDir).toString();
00260   currentLoadDir = 
00261     settings.value(lastLoadDirSetting(), currentLoadDir).toString();
00262   resize(settings.value(xresSetting(), width()).toInt(),
00263     settings.value(yresSetting(), height()).toInt());
00264   move(settings.value(xposSetting(), x()).toInt(),
00265     settings.value(yposSetting(), y()).toInt());
00266 }
00267 
00268 
00269 void MetaWindow::saveSettings(){
00270   QSettings settings(QSettings::UserScope, "Sandia", "Optika");
00271 
00272   settings.setValue(lastSaveDirSetting(), currentSaveDir);
00273   settings.setValue(lastLoadDirSetting(), currentLoadDir);
00274   settings.setValue(xresSetting(), width());
00275   settings.setValue(yresSetting(), height());
00276   settings.setValue(xposSetting(), x());
00277   settings.setValue(yposSetting(), y());
00278 }
00279   
00280 
00281 void MetaWindow::addRecentDocument(QString recentDocument){
00282   recentDocsList.prepend(recentDocument);
00283   if(recentDocsList.size() > numRecentDocuments){
00284     recentDocsList.removeLast();
00285   }
00286 //  updateRecentDocsMenu();
00287 }
00288 
00289 void MetaWindow::updateRecentDocsMenu(){
00290   recentMenu->clear();
00291   for(int i=0; i<recentDocsList.size(); ++i){
00292     QAction *recentDocAct = new QAction(recentDocsList.at(i).section("/",-1,-1),this);
00293     connect(recentDocAct, SIGNAL(triggered()), this, SLOT(loadRecentDoc()));
00294     recentMenu->addAction(recentDocAct);
00295   }
00296 }
00297 
00298 void MetaWindow::resetModel(){
00299   if(!model->isSaved()){
00300     saveCurrentUnsavedFile();
00301   }
00302   model->reset();
00303 }
00304 
00305 bool MetaWindow::saveFileAs(){
00306   QString fileName = QFileDialog::getSaveFileName(this, tr("Save To..."), currentSaveDir, tr("XML (*.xml)"));
00307   if(fileName.toStdString() != ""){
00308     if(!fileName.endsWith(".xml")){
00309       fileName = fileName.append(".xml");
00310     }
00311     if(model->writeOutput(fileName)){
00312       currentSaveDir = fileName.section("/",0,-2);
00313       addRecentDocument(fileName);    
00314       return true;
00315     }
00316   }
00317   return false;
00318 }
00319 
00320 void MetaWindow::saveFile(){
00321   QString currentFileName = model->getSaveFileName();
00322   if(currentFileName != ""){
00323     model->writeOutput(currentFileName);
00324   }
00325   else{
00326     saveFileAs();
00327   }
00328 }
00329 
00330 
00331 void MetaWindow::loadFile(){
00332   if(!model->isSaved()){
00333     saveCurrentUnsavedFile();
00334   }
00335   load();
00336 }
00337 
00338 bool MetaWindow::saveCurrentUnsavedFile(){
00339     QMessageBox saveQuestion(QMessageBox::Question, 
00340     tr("Save?"),
00341     tr("These choices have not been saved since you last made changes. Would you like to save them now?"), 
00342     QMessageBox::Yes | QMessageBox::No,
00343     this);
00344     saveQuestion.setDefaultButton(QMessageBox::Yes);
00345     int shouldSave = saveQuestion.exec(); 
00346     if(shouldSave == QMessageBox::Yes){
00347       return saveFileAs();
00348     }
00349     return true;
00350 }
00351 
00352 void MetaWindow::loadRecentDoc(){
00353   QString docName = dynamic_cast<QAction*>(sender())->text();
00354   int i =0;
00355   for(; i<recentDocsList.size();++i){
00356     if(recentDocsList.at(i).contains(docName)){
00357       break;
00358     }
00359   }
00360   if(!model->isSaved()){
00361     if(saveCurrentUnsavedFile()){
00362       model->readInput(recentDocsList.at(i));
00363     }
00364   }
00365 }
00366 
00367 void MetaWindow::showAbout(){
00368   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";
00369   QMessageBox::about(this,
00370   "Optika Input Obtainer\n",
00371   aboutString);
00372 }
00373 
00374 void MetaWindow::initiateSearch(){
00375   searchWidget->show();
00376 }
00377 
00378 void MetaWindow::doAction(){
00379   if(customFunc == 0){
00380     close();
00381   }
00382   else{
00383     (*customFunc)(model->getCurrentParameters()); 
00384   }
00385 }
00386 
00387 void MetaWindow::setAboutInfo(QString aboutInfo){
00388   this->aboutInfo = aboutInfo;
00389 }
00390 
00391 QString MetaWindow::getAboutInfo(){
00392   return aboutInfo;
00393 }
00394 
00395 void MetaWindow::setActionButtonText(QString newText){
00396   actionButton->setText(newText);
00397 }
00398 
00399 QString MetaWindow::getActionButtonText(){
00400   return actionButton->text();
00401 }
00402 
00403 
00404 } //namespace Optika
00405 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends Defines