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 namespace Optika{
00043 
00044 
00045 const int numRecentDocuments = 7; 
00046 
00047 SearchWidget::SearchWidget(TreeModel *treeModel, TreeView *treeView, QWidget *parent):
00048   QDialog(parent),
00049   treeModel(treeModel),
00050   treeView(treeView)
00051 {
00052   matchesLabel = new QLabel(tr("Matches"));
00053   searchButton = new QPushButton(tr("Search"));
00054   connect(searchButton, SIGNAL(clicked(bool)), this, SLOT(search()));
00055   closeButton = new QPushButton(tr("Close"));
00056   connect(closeButton, SIGNAL(clicked(bool)), this, SLOT(hide()));
00057   nextButton = new QPushButton(tr("Next"));
00058   connect(nextButton, SIGNAL(clicked(bool)), this, SLOT(next()));
00059   previousButton = new QPushButton(tr("Previous"));
00060   connect(previousButton, SIGNAL(clicked(bool)), this, SLOT(previous()));
00061   searchTermsEdit = new QLineEdit(tr("Enter Search Terms Here"));
00062   QGridLayout *layout = new QGridLayout(this);
00063   layout->addWidget(searchTermsEdit,0,0);
00064   layout->addWidget(searchButton,0,1);
00065   layout->addWidget(nextButton,0,3);
00066   layout->addWidget(previousButton,0,2);
00067   layout->addWidget(closeButton,2,3);
00068   layout->addWidget(matchesLabel,3,0);
00069   setLayout(layout);
00070   nextButton->setDisabled(true);
00071   previousButton->setDisabled(true);
00072   setSizeGripEnabled(true);
00073   setWindowTitle(tr("Search..."));
00074 }
00075 
00076 void SearchWidget::search(){
00077   currentSearchResults = treeModel->match(treeModel->index(0,0,QModelIndex()), Qt::DisplayRole, searchTermsEdit->text(), 
00078   -1, Qt::MatchWrap | Qt::MatchContains | Qt::MatchRecursive);
00079   currentSearchResults = removeHiddenItems(currentSearchResults);
00080   currentSearchIterator = currentSearchResults.begin(); 
00081   int searchSize = currentSearchResults.size();
00082   matchesLabel->setText("Matches ("+ QString::number(searchSize) + ")");
00083   if(searchSize <= 0){
00084     nextButton->setDisabled(true);
00085     previousButton->setDisabled(true);
00086   }
00087   else if(searchSize == 1){
00088     nextButton->setDisabled(true);
00089     previousButton->setDisabled(true);
00090     treeView->setCurrentIndex(*currentSearchIterator);
00091   }
00092   else{
00093     nextButton->setDisabled(false);
00094     previousButton->setDisabled(false);
00095     treeView->setCurrentIndex(*currentSearchIterator);
00096   }
00097 }
00098 
00099 void SearchWidget::next(){
00100   currentSearchIterator++;
00101   if(currentSearchIterator == currentSearchResults.end()){
00102     currentSearchIterator = currentSearchResults.begin();
00103   }
00104   treeView->setCurrentIndex(*currentSearchIterator);
00105 }
00106 
00107 void SearchWidget::previous(){
00108   currentSearchIterator--;
00109   if(currentSearchIterator == currentSearchResults.begin()-1){
00110     currentSearchIterator = currentSearchResults.end() -1;
00111   }
00112   treeView->setCurrentIndex(*currentSearchIterator);
00113 }
00114 
00115 QModelIndexList SearchWidget::removeHiddenItems(QModelIndexList& items){
00116   QModelIndexList toReturn;
00117   for(QModelIndexList::iterator it = items.begin(); it != items.end(); ++it){
00118     if(!treeView->isRowHidden(it->row(), it->parent())){
00119       toReturn.append(*it);
00120     }
00121   }
00122   return toReturn;
00123 }
00124 
00125 MetaWindow::MetaWindow(Teuchos::RCP<Teuchos::ParameterList> validParameters, QString fileName){
00126   model = new TreeModel(validParameters, fileName);
00127   initilization();
00128 }
00129 
00130 MetaWindow::MetaWindow(Teuchos::RCP<Teuchos::ParameterList> validParameters, void (*customFunc)(Teuchos::RCP<const Teuchos::ParameterList>), QString fileName){
00131   model = new TreeModel(validParameters, fileName);
00132   initilization(customFunc);
00133 }
00134 
00135 MetaWindow::MetaWindow(Teuchos::RCP<Teuchos::ParameterList> validParameters, Teuchos::RCP<DependencySheet> dependencySheet, QString fileName){
00136   model = new TreeModel(validParameters, dependencySheet, fileName);
00137   initilization();
00138 } 
00139 
00140 MetaWindow::MetaWindow(Teuchos::RCP<Teuchos::ParameterList> validParameters, Teuchos::RCP<DependencySheet> dependencySheet, void (*customFunc)(Teuchos::RCP<const Teuchos::ParameterList>), QString fileName){
00141   model = new TreeModel(validParameters, dependencySheet, fileName);
00142   initilization(customFunc);
00143 } 
00144 
00145 MetaWindow::~MetaWindow(){
00146   saveSettings();
00147 }
00148 
00149 void MetaWindow::closeEvent(QCloseEvent *event){
00150   if(!model->isSaved()){
00151     if(saveCurrentUnsavedFile()){
00152       saveSettings();
00153       event->accept();
00154     }
00155     else{
00156       event->ignore();
00157     }
00158   }
00159   else{
00160     saveSettings();
00161     event->accept();
00162   }
00163 }
00164 
00165 void MetaWindow::initilization(void (*customFunc)(Teuchos::RCP<const Teuchos::ParameterList>)){
00166   this->customFunc = customFunc;
00167   delegate = new Delegate;
00168   view = new TreeView(model, delegate);
00169   view->setEditTriggers(QAbstractItemView::DoubleClicked | QAbstractItemView::SelectedClicked);
00170   searchWidget = new SearchWidget(model, view, this);
00171   searchWidget->hide();
00172   QPushButton *submitButton = new QPushButton(tr("Submit"), this);
00173   connect(submitButton, SIGNAL(clicked(bool)), this, SLOT(submit()));
00174   QWidget *centerWidget = new QWidget(this);
00175   QGridLayout *centerWidgetLayout = new QGridLayout(centerWidget);
00176   centerWidgetLayout->addWidget(view,0,0);
00177   centerWidgetLayout->addWidget(submitButton,1,0,Qt::AlignRight);
00178   centerWidget->setLayout(centerWidgetLayout);
00179   setCentralWidget(centerWidget);
00180   createActions();
00181   createMenus();
00182   resize(800,600);
00183   currentLoadDir = QDir::homePath();
00184   currentSaveDir = QDir::homePath();
00185   loadLastSettings();
00186   setWindowTitle(tr("Parameter Input"));
00187   view->show();
00188   view->header()->resizeSections(QHeaderView::ResizeToContents);
00189   view->header()->setMovable(false);
00190 }
00191 
00192 void MetaWindow::createMenus(){
00193 //  recentMenu = new QMenu(tr("Recent Solvers"));
00194 //  QAction *noRecentAct = new QAction(tr("No Recent Documents"),this);
00195 //  noRecentAct->setEnabled(false);
00196 //  recentMenu->addAction(noRecentAct);
00197   fileMenu = menuBar()->addMenu(tr("File"));
00198   fileMenu->addAction(resetAct);
00199   //fileMenu->addMenu(recentMenu);
00200   fileMenu->addSeparator();
00201   fileMenu->addAction(saveAct);
00202   fileMenu->addAction(saveAsAct);
00203   fileMenu->addAction(loadAct);
00204   fileMenu->addSeparator();
00205   fileMenu->addAction(quitAct);
00206   helpMenu = menuBar()->addMenu(tr("Help"));
00207   helpMenu->addAction(aboutAct);
00208   helpMenu->addAction(searchAct);
00209 }
00210 
00211 void MetaWindow::createActions(){
00212   resetAct = new QAction(tr("&Reset"),this);
00213   resetAct->setShortcut(tr("Ctrl+R"));
00214   resetAct->setStatusTip(tr("Reset the list to its original state."));
00215   connect(resetAct, SIGNAL(triggered()), this, SLOT(resetModel()));
00216 
00217   saveAct = new QAction(tr("&Save"),this);
00218   saveAct->setShortcut(tr("Ctrl+S"));
00219   saveAct->setStatusTip(tr("Save the current file."));
00220   connect(saveAct, SIGNAL(triggered()), this, SLOT(saveFile()));
00221 
00222   saveAsAct = new QAction(tr("Save As..."),this);
00223   saveAsAct->setStatusTip(tr("Save the current file to a specified file name."));
00224   connect(saveAsAct, SIGNAL(triggered()), this, SLOT(saveFileAs()));
00225 
00226   loadAct = new QAction(tr("&Load"),this);
00227   loadAct->setShortcut(tr("Ctrl+L"));
00228   loadAct->setStatusTip(tr("Load input file"));
00229   connect(loadAct, SIGNAL(triggered()), this, SLOT(loadFile()));
00230 
00231   quitAct = new QAction(tr("&Quit"),this);
00232   quitAct->setShortcut(tr("Ctrl+Q"));
00233   quitAct->setStatusTip(tr("Quit"));
00234   connect(quitAct, SIGNAL(triggered()), this, SLOT(close()));
00235 
00236   aboutAct = new QAction(tr("About"),this);
00237   searchAct = new QAction(tr("Search For Parameter/Parameter List"), this);
00238   searchAct->setToolTip("Search for a particular Parameter or ParameterList");
00239   connect(aboutAct, SIGNAL(triggered()), this, SLOT(showAbout()));
00240   connect(searchAct, SIGNAL(triggered()), this, SLOT(initiateSearch()));
00241 }
00242 
00243 void MetaWindow::load(){
00244   QString fileName = QFileDialog::getOpenFileName(this, tr("Load..."), currentLoadDir, tr("Xml (*.xml)"));
00245   if(fileName != ""){
00246     model->readInput(fileName);
00247     currentLoadDir = fileName.section("/",0,-2);
00248     addRecentDocument(fileName);
00249   }
00250 }
00251 
00252 void MetaWindow::loadLastSettings(){
00253   QFile *file = new QFile("settings.xml");
00254   if(file->open(QIODevice::ReadOnly)){
00255     QXmlStreamReader xmlReader(file);
00256     while(!xmlReader.isEndDocument()){
00257       if(xmlReader.isStartElement()){
00258         if(xmlReader.name() == "lastsavedir"){
00259           QString tempCurSave = xmlReader.readElementText();
00260           if(tempCurSave != ""){
00261             currentSaveDir = tempCurSave;
00262           }
00263         }
00264         else if(xmlReader.name() == "lastloaddir"){
00265           QString tempCurLoad = xmlReader.readElementText();
00266           if(tempCurLoad != ""){
00267             currentLoadDir = tempCurLoad;
00268           }
00269         }
00270         else if(xmlReader.name() == "xres"){
00271           QString theWidth = xmlReader.readElementText();
00272           if(theWidth != ""){
00273             resize(theWidth.toInt(), height());
00274           }
00275         }
00276         else if(xmlReader.name() == "yres"){
00277           QString theHeight = xmlReader.readElementText();
00278           if(theHeight != ""){
00279             resize(width(), theHeight.toInt());
00280           }
00281         }
00282         else if(xmlReader.name() == "xpos"){
00283           QString xpos = xmlReader.readElementText();
00284           if(xpos != ""){
00285             move(xpos.toInt(), y());
00286           }
00287         }
00288         else if(xmlReader.name() == "ypos"){
00289           QString ypos = xmlReader.readElementText();
00290           if(ypos != ""){
00291             move(x(), ypos.toInt());
00292           }
00293         }
00294         else if(xmlReader.name() == "recentdoc"){
00295           addRecentDocument(xmlReader.readElementText());
00296         }
00297       }
00298       xmlReader.readNext();
00299     }
00300     file->close();
00301   }
00302   delete file;
00303 }
00304 
00305 
00306 void MetaWindow::saveSettings(){
00307   QFile *file = new QFile("settings.xml");
00308   file->open(QIODevice::WriteOnly);
00309   QXmlStreamWriter xmlWriter(file);
00310 
00311   xmlWriter.setAutoFormatting(true);
00312   xmlWriter.writeStartDocument();
00313   xmlWriter.writeStartElement("settings");
00314     xmlWriter.writeStartElement("lastsavedir");
00315     xmlWriter.writeCharacters(currentSaveDir);
00316     xmlWriter.writeEndElement();
00317     xmlWriter.writeStartElement("lastloaddir");
00318     xmlWriter.writeCharacters(currentLoadDir);
00319     xmlWriter.writeEndElement();
00320     xmlWriter.writeStartElement("xres");
00321     xmlWriter.writeCharacters(QString::number(width()));
00322     xmlWriter.writeEndElement();
00323     xmlWriter.writeStartElement("yres");
00324     xmlWriter.writeCharacters(QString::number(height()));
00325     xmlWriter.writeEndElement();
00326     xmlWriter.writeStartElement("xpos");
00327     xmlWriter.writeCharacters(QString::number(x()));
00328     xmlWriter.writeEndElement();
00329     xmlWriter.writeStartElement("ypos");
00330     xmlWriter.writeCharacters(QString::number(y()));
00331     xmlWriter.writeEndElement();
00332     for(int i =0; i<recentDocsList.size(); ++i){
00333       xmlWriter.writeStartElement("recentdoc");
00334         xmlWriter.writeCharacters(recentDocsList.at(i));
00335       xmlWriter.writeEndElement();
00336     }
00337   xmlWriter.writeEndElement();
00338   xmlWriter.writeEndDocument();
00339 
00340   file->close();
00341   delete file;
00342 }
00343   
00344 
00345 void MetaWindow::addRecentDocument(QString recentDocument){
00346   recentDocsList.prepend(recentDocument);
00347   if(recentDocsList.size() > numRecentDocuments){
00348     recentDocsList.removeLast();
00349   }
00350 //  updateRecentDocsMenu();
00351 }
00352 
00353 void MetaWindow::updateRecentDocsMenu(){
00354   recentMenu->clear();
00355   for(int i=0; i<recentDocsList.size(); ++i){
00356     QAction *recentDocAct = new QAction(recentDocsList.at(i).section("/",-1,-1),this);
00357     connect(recentDocAct, SIGNAL(triggered()), this, SLOT(loadRecentDoc()));
00358     recentMenu->addAction(recentDocAct);
00359   }
00360 }
00361 
00362 void MetaWindow::resetModel(){
00363   if(!model->isSaved()){
00364     saveCurrentUnsavedFile();
00365   }
00366   model->reset();
00367 }
00368 
00369 bool MetaWindow::saveFileAs(){
00370   QString fileName = QFileDialog::getSaveFileName(this, tr("Save To..."), currentSaveDir, tr("XML (*.xml)"));
00371   if(fileName.toStdString() != ""){
00372     if(!fileName.endsWith(".xml")){
00373       fileName = fileName.append(".xml");
00374     }
00375     if(model->writeOutput(fileName)){
00376       currentSaveDir = fileName.section("/",0,-2);
00377       addRecentDocument(fileName);    
00378       return true;
00379     }
00380   }
00381   return false;
00382 }
00383 
00384 void MetaWindow::saveFile(){
00385   QString currentFileName = model->getSaveFileName();
00386   if(currentFileName != ""){
00387     model->writeOutput(currentFileName);
00388   }
00389   else{
00390     saveFileAs();
00391   }
00392 }
00393 
00394 
00395 void MetaWindow::loadFile(){
00396   if(!model->isSaved()){
00397     saveCurrentUnsavedFile();
00398   }
00399   load();
00400 }
00401 
00402 bool MetaWindow::saveCurrentUnsavedFile(){
00403     QMessageBox saveQuestion(QMessageBox::Question, 
00404     tr("Save?"),
00405     tr("These choices have not been saved since you last made changes. Would you like to save them now?"), 
00406     QMessageBox::Yes | QMessageBox::No,
00407     this);
00408     saveQuestion.setDefaultButton(QMessageBox::Yes);
00409     int shouldSave = saveQuestion.exec(); 
00410     if(shouldSave == QMessageBox::Yes){
00411       return saveFileAs();
00412     }
00413     return true;
00414 }
00415 
00416 void MetaWindow::loadRecentDoc(){
00417   QString docName = dynamic_cast<QAction*>(sender())->text();
00418   int i =0;
00419   for(; i<recentDocsList.size();++i){
00420     if(recentDocsList.at(i).contains(docName)){
00421       break;
00422     }
00423   }
00424   if(!model->isSaved()){
00425     if(saveCurrentUnsavedFile()){
00426       model->readInput(recentDocsList.at(i));
00427     }
00428   }
00429 }
00430 
00431 void MetaWindow::showAbout(){
00432   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";
00433   QMessageBox::about(this,
00434   "Optika Input Obtainer\n",
00435   aboutString);
00436 }
00437 
00438 void MetaWindow::initiateSearch(){
00439   searchWidget->show();
00440 }
00441 
00442 void MetaWindow::submit(){
00443   if(customFunc == 0){
00444     close();
00445   }
00446   else{
00447     (*customFunc)(model->getCurrentParameters()); 
00448   }
00449 }
00450 
00451 void MetaWindow::setAboutInfo(QString aboutInfo){
00452   this->aboutInfo = aboutInfo;
00453 }
00454 
00455 QString MetaWindow::getAboutInfo(){
00456   return aboutInfo;
00457 }
00458 
00459 }
00460 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends
Generated on Wed Apr 13 10:05:58 2011 for Optika GUI Toolik by  doxygen 1.6.3