From 77636efbb1cc699c8afd497bca7d9a69cb4d96f2 Mon Sep 17 00:00:00 2001 From: Andreas Suter Date: Sat, 14 Jan 2017 18:19:36 +0100 Subject: [PATCH] allow the user to change the default search data file paths from within musredit > preferences. --- .../PChangeDefaultPathsDialog.cpp | 331 ++++++++++++++++++ src/musredit_qt5/PChangeDefaultPathsDialog.h | 104 ++++++ src/musredit_qt5/PPrefsDialog.cpp | 19 + src/musredit_qt5/PPrefsDialog.h | 3 +- .../forms/PChangeDefaultPathsDialog.ui | 114 ++++++ src/musredit_qt5/forms/PPrefsDialog.ui | 15 +- src/musredit_qt5/musredit.pro | 5 +- 7 files changed, 588 insertions(+), 3 deletions(-) create mode 100644 src/musredit_qt5/PChangeDefaultPathsDialog.cpp create mode 100644 src/musredit_qt5/PChangeDefaultPathsDialog.h create mode 100644 src/musredit_qt5/forms/PChangeDefaultPathsDialog.ui diff --git a/src/musredit_qt5/PChangeDefaultPathsDialog.cpp b/src/musredit_qt5/PChangeDefaultPathsDialog.cpp new file mode 100644 index 00000000..cefe7ad9 --- /dev/null +++ b/src/musredit_qt5/PChangeDefaultPathsDialog.cpp @@ -0,0 +1,331 @@ +/**************************************************************************** + + PChangeDefaultPathsDialog.cpp + + Author: Andreas Suter + e-mail: andreas.suter@psi.ch + +*****************************************************************************/ + +/*************************************************************************** + * Copyright (C) 2010-2017 by Andreas Suter * + * andreas.suter@psi.ch * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include +#include + +#include "PChangeDefaultPathsDialog.h" + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +/** + * @brief PDefaultPathsXMLParser::PDefaultPathsXMLParser + * @param defaultPaths + */ +PDefaultPathsXMLParser::PDefaultPathsXMLParser(PDefaultPaths *defaultPaths) : + fDefaultPaths(defaultPaths) +{ + fKeyWord = eEmpty; +} + +//-------------------------------------------------------------------------- +/** + *

Routine called at the beginning of the XML parsing process. + */ +bool PDefaultPathsXMLParser::startDocument() +{ + return true; +} + +//-------------------------------------------------------------------------- +/** + *

Routine called when a new XML tag is found. Here it is used + * to set a tag for filtering afterwards the content. + * + * \param qName name of the XML tag. + */ +bool PDefaultPathsXMLParser::startElement( const QString&, const QString&, + const QString& qName, + const QXmlAttributes& ) +{ + if (qName == "data_path") { + fKeyWord = eDataPath; + } + + return true; +} + +//-------------------------------------------------------------------------- +/** + *

Routine called when the end XML tag is found. It is used to + * put the filtering tag to 'empty'. + * + * \param qName name of the element. + */ +bool PDefaultPathsXMLParser::endElement( const QString&, const QString&, const QString & ) +{ + fKeyWord = eEmpty; + + return true; +} + +//-------------------------------------------------------------------------- +/** + *

This routine delivers the content of an XML tag. It fills the + * content into the load data structure. + * + * \param str keeps the content of the XML tag. + */ +bool PDefaultPathsXMLParser::characters(const QString& str) +{ + switch (fKeyWord) { + case eDataPath: + fDefaultPaths->appendDefaultPath(str); + break; + default: + break; + } + + return true; +} + +//-------------------------------------------------------------------------- +/** + *

Called at the end of the XML parse process. It checks if default paths + * contain system variables, and if so expand them for the further use. + */ +bool PDefaultPathsXMLParser::endDocument() +{ + return true; +} + +//-------------------------------------------------------------------------- +/** + *

Report XML warnings. + * + * \param exception holds the information of the XML warning + */ +bool PDefaultPathsXMLParser::warning( const QXmlParseException & exception ) +{ + QString msg; + + msg = QString("**WARNING** while parsing musrfit_startup.xml in line no %1\n").arg(exception.lineNumber()); + msg += QString("**WARNING MESSAGE** ") + exception.message(); + + qWarning() << endl << msg << endl; + + QMessageBox::warning(0, "WARNING", msg, QMessageBox::Ok, QMessageBox::NoButton); + + return true; +} + +//-------------------------------------------------------------------------- +/** + *

Report recoverable XML errors. + * + * \param exception holds the information of the XML recoverable errors. + */ +bool PDefaultPathsXMLParser::error( const QXmlParseException & exception ) +{ + QString msg; + + msg = QString("**ERROR** while parsing musrfit_startup.xml in line no %1\n").arg(exception.lineNumber()); + msg += QString("**ERROR MESSAGE** ") + exception.message(); + + qWarning() << endl << msg << endl; + + QMessageBox::critical(0, "ERROR", msg, QMessageBox::Ok, QMessageBox::NoButton); + + return true; +} + +//-------------------------------------------------------------------------- +/** + *

Report fatal XML errors. + * + * \param exception holds the information of the XML fatal errors. + */ +bool PDefaultPathsXMLParser::fatalError( const QXmlParseException & exception ) +{ + QString msg; + + msg = QString("**FATAL ERROR** while parsing musrfit_startup.xml in line no %1\n").arg(exception.lineNumber()); + msg += QString("**FATAL ERROR MESSAGE** ") + exception.message(); + + qWarning() << endl << msg << endl; + + QMessageBox::critical(0, "FATAL ERROR", msg, QMessageBox::Ok, QMessageBox::NoButton); + + return true; +} + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +PDefaultPaths::PDefaultPaths() : QObject() +{ + fValid = true; + + // XML Parser part + // 1st: check local directory + QString path = QString("./"); + QString fln = QString("musrfit_startup.xml"); + QString pathFln = path + fln; + QProcessEnvironment procEnv = QProcessEnvironment::systemEnvironment(); + if (!QFile::exists(pathFln)) { + // 2nd: check $HOME/.musrfit/musrfit_startup.xml + path = procEnv.value("HOME", ""); + pathFln = path + "/.musrfit/" + fln; + if (!QFile::exists(pathFln)) { + // 3rd: check $MUSRFITPATH/musrfit_startup.xml + path = procEnv.value("MUSRFITPATH", ""); + pathFln = path + "/" + fln; + if (!QFile::exists(pathFln)) { + // 4th: check $ROOTSYS/bin/musrfit_startup.xml + path = procEnv.value("ROOTSYS", ""); + pathFln = path + "/bin/" + fln; + } + } + } + fPrefPathName = pathFln; + + // read musrfit_startup.xml and extract default data file search paths + PDefaultPathsXMLParser handler(this); + QFile xmlFile(fPrefPathName); + QXmlInputSource source( &xmlFile ); + QXmlSimpleReader reader; + reader.setContentHandler( &handler ); + reader.setErrorHandler( &handler ); + if (!reader.parse( source )) { + fValid = false; + QMessageBox::critical(0, "ERROR", + "Error parsing musrfit_startup.xml settings file.\nProbably a few things will not work porperly.\nPlease fix this first.", + QMessageBox::Ok, QMessageBox::NoButton); + return; + } +} + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +/** + *

Constructor. + * + * \param fAdmin keeps all the needed flags + */ +PChangeDefaultPathsDialog::PChangeDefaultPathsDialog() +{ + fDefaultPath = 0; + fDefaultPath = new PDefaultPaths(); + if (!fDefaultPath->isValid()) + return; + + QStringList *strList = fDefaultPath->getDefaultPathList(); + if (strList == 0) + return; + + setupUi(this); + + setModal(true); + + // populate default search paths + for (int i=0; icount(); i++) { + fSearchPath_listWidget->addItem(strList->at(i)); + } + + QObject::connect(fDelete_pushButton, SIGNAL(clicked()), this, SLOT(deleteItem())); + QObject::connect(fAdd_pushButton, SIGNAL(clicked()), this, SLOT(addItem())); + QObject::connect(buttonBox, SIGNAL(accepted()), this, SLOT(saveDefaultPathList())); +} + +//---------------------------------------------------------------------------------------------------- +/** + * @brief PChangeDefaultPathsDialog::addItem + */ +void PChangeDefaultPathsDialog::addItem() +{ + // call QFileDialog in order to get the proper directory + QString dirName = QFileDialog::getExistingDirectory(this, tr("Data File Directory"), "", + QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); + if (dirName == "") + return; + + // insert the new directory in fSearchPath_listWidget + QListWidgetItem *item = new QListWidgetItem; + if (item == 0) { + QMessageBox::critical(this, "ERROR", "Couldn't invoke QListWidgetItem! Won't do anything."); + return; + } + item->setText(dirName); + fSearchPath_listWidget->insertItem(fSearchPath_listWidget->currentRow()+1, item); +} + +//---------------------------------------------------------------------------------------------------- +/** + * @brief PChangeDefaultPathsDialog::deleteItem + */ +void PChangeDefaultPathsDialog::deleteItem() +{ + QListWidgetItem *item = fSearchPath_listWidget->takeItem(fSearchPath_listWidget->currentRow()); + if (item != 0) + delete item; +} + +//---------------------------------------------------------------------------------------------------- +/** + * @brief PChangeDefaultPathsDialog::saveDefaultPathList + */ +void PChangeDefaultPathsDialog::saveDefaultPathList() +{ + // read the used musrfit_startup.xml + QFile fileIn(fDefaultPath->getPrefPathName()); + if (!fileIn.open(QIODevice::ReadOnly | QIODevice::Text)) { + QMessageBox::critical(this, "ERROR", QString("Cannot read '%1'. Won't do anything.").arg(fDefaultPath->getPrefPathName())); + return; + } + QTextStream in(&fileIn); + QStringList fileContent; + while (!in.atEnd()) { + fileContent << in.readLine(); + } + fileIn.close(); + + // write the new musrfit_startup.xml + QFile fileOut(fDefaultPath->getPrefPathName()); + if (!fileOut.open(QIODevice::WriteOnly | QIODevice::Text)) { + QMessageBox::critical(this, "ERROR", QString("Cannot write to '%1'.").arg(fDefaultPath->getPrefPathName())); + return; + } + QTextStream out(&fileOut); + QString str; + bool first = true; + for (int i=0; i")) { + out << fileContent[i] << endl; + } else { + if (first) { + first = false; + for (int j=0; jcount(); j++) + out << " " << fSearchPath_listWidget->item(j)->text() << "" << endl; + } + } + } + fileOut.close(); +} + +//---------------------------------------------------------------------------------------------------- +// END +//---------------------------------------------------------------------------------------------------- diff --git a/src/musredit_qt5/PChangeDefaultPathsDialog.h b/src/musredit_qt5/PChangeDefaultPathsDialog.h new file mode 100644 index 00000000..f6603825 --- /dev/null +++ b/src/musredit_qt5/PChangeDefaultPathsDialog.h @@ -0,0 +1,104 @@ +/**************************************************************************** + + PChangeDefaultPathsDialog.h + + Author: Andreas Suter + e-mail: andreas.suter@psi.ch + +*****************************************************************************/ + +/*************************************************************************** + * Copyright (C) 2010-2017 by Andreas Suter * + * andreas.suter@psi.ch * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef _PCHANGEDEFAULTPATHSDIALOG_H_ +#define _PCHANGEDEFAULTPATHSDIALOG_H_ + +#include +#include +#include + +#include "ui_PChangeDefaultPathsDialog.h" + +class PDefaultPaths; + +//--------------------------------------------------------------------------- +class PDefaultPathsXMLParser : public QXmlDefaultHandler +{ + public: + PDefaultPathsXMLParser(PDefaultPaths *defaultPaths); + virtual ~PDefaultPathsXMLParser() {} + + private: + enum EAdminKeyWords {eEmpty, eDataPath}; + + bool startDocument(); + bool startElement( const QString&, const QString&, const QString& , + const QXmlAttributes& ); + bool endElement( const QString&, const QString&, const QString& ); + + bool characters(const QString&); + bool endDocument(); + + bool warning( const QXmlParseException & exception ); + bool error( const QXmlParseException & exception ); + bool fatalError( const QXmlParseException & exception ); + + EAdminKeyWords fKeyWord; ///< key word tag to know how to handle the content + PDefaultPaths *fDefaultPaths; ///< keeps the default search paths for the data files +}; + +//--------------------------------------------------------------------------- +class PDefaultPaths : public QObject +{ + public: + PDefaultPaths(); + virtual ~PDefaultPaths() {} + + virtual bool isValid() { return fValid; } + virtual void appendDefaultPath(QString str) { fDefaultPath << str; } + virtual QStringList *getDefaultPathList() { return &fDefaultPath; } + virtual QString getPrefPathName() { return fPrefPathName; } + + private: + friend class PDefaultPathsXMLParser; + + bool fValid; + QString fPrefPathName; + QStringList fDefaultPath; +}; + +//--------------------------------------------------------------------------- +class PChangeDefaultPathsDialog : public QDialog, private Ui::PChangeDefaultPathsDialog +{ + Q_OBJECT + + public: + PChangeDefaultPathsDialog(); + + private slots: + void deleteItem(); + void addItem(); + void saveDefaultPathList(); + + private: + PDefaultPaths *fDefaultPath; +}; + +#endif // _PCHANGEDEFAULTPATHSDIALOG_H_ diff --git a/src/musredit_qt5/PPrefsDialog.cpp b/src/musredit_qt5/PPrefsDialog.cpp index 1b40a423..48ceca65 100644 --- a/src/musredit_qt5/PPrefsDialog.cpp +++ b/src/musredit_qt5/PPrefsDialog.cpp @@ -27,6 +27,7 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ +#include "PChangeDefaultPathsDialog.h" #include "PPrefsDialog.h" //---------------------------------------------------------------------------------------------------- @@ -66,6 +67,8 @@ PPrefsDialog::PPrefsDialog(PAdmin *admin) : fAdmin(admin) fTimeout_lineEdit->setText(QString("%1").arg(fAdmin->getTimeout())); fTimeout_lineEdit->setValidator(new QIntValidator(fTimeout_lineEdit)); + + QObject::connect(fDefaultPath_pushButton, SIGNAL(clicked()), this, SLOT(handleDefaultPaths())); } //---------------------------------------------------------------------------------------------------- @@ -106,6 +109,22 @@ void PPrefsDialog::dumpRoot() fDumpAscii_checkBox->setChecked(false); } +//---------------------------------------------------------------------------------------------------- +/** + *

SLOT: called when the QPushButton 'Change Default Search Paths' is clicked. Will call a + * dialog which allows to deal with the default search paths to look for data files. + */ +void PPrefsDialog::handleDefaultPaths() +{ + PChangeDefaultPathsDialog *dlg = new PChangeDefaultPathsDialog(); + + if (dlg->exec() == QDialog::Accepted) { + + } + + delete dlg; +} + //---------------------------------------------------------------------------------------------------- // END //---------------------------------------------------------------------------------------------------- diff --git a/src/musredit_qt5/PPrefsDialog.h b/src/musredit_qt5/PPrefsDialog.h index edba329f..ffaca305 100644 --- a/src/musredit_qt5/PPrefsDialog.h +++ b/src/musredit_qt5/PPrefsDialog.h @@ -8,7 +8,7 @@ *****************************************************************************/ /*************************************************************************** - * Copyright (C) 2010-2016 by Andreas Suter * + * Copyright (C) 2010-2017 by Andreas Suter * * andreas.suter@psi.ch * * * * This program is free software; you can redistribute it and/or modify * @@ -59,6 +59,7 @@ class PPrefsDialog : public QDialog, private Ui::PPrefsDialog public slots: void dumpAscii(); void dumpRoot(); + void handleDefaultPaths(); private: PAdmin *fAdmin; diff --git a/src/musredit_qt5/forms/PChangeDefaultPathsDialog.ui b/src/musredit_qt5/forms/PChangeDefaultPathsDialog.ui new file mode 100644 index 00000000..08f553af --- /dev/null +++ b/src/musredit_qt5/forms/PChangeDefaultPathsDialog.ui @@ -0,0 +1,114 @@ + + + PChangeDefaultPathsDialog + + + + 0 + 0 + 528 + 363 + + + + + 0 + 0 + + + + Dialog + + + + + 9 + 10 + 512 + 341 + + + + + + + + + + + + Qt::Horizontal + + + + 328 + 20 + + + + + + + + Add + + + + + + + Delete + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + + buttonBox + accepted() + PChangeDefaultPathsDialog + accept() + + + 228 + 332 + + + 157 + 274 + + + + + buttonBox + rejected() + PChangeDefaultPathsDialog + reject() + + + 296 + 338 + + + 286 + 274 + + + + + diff --git a/src/musredit_qt5/forms/PPrefsDialog.ui b/src/musredit_qt5/forms/PPrefsDialog.ui index a92e1c0f..e6696cb4 100644 --- a/src/musredit_qt5/forms/PPrefsDialog.ui +++ b/src/musredit_qt5/forms/PPrefsDialog.ui @@ -33,7 +33,7 @@ - 3 + 0 @@ -74,6 +74,19 @@ + + + + 10 + 50 + 421 + 31 + + + + Change Default Search Paths + + diff --git a/src/musredit_qt5/musredit.pro b/src/musredit_qt5/musredit.pro index b2507e97..60e76284 100644 --- a/src/musredit_qt5/musredit.pro +++ b/src/musredit_qt5/musredit.pro @@ -104,6 +104,7 @@ HEADERS = musredit.h \ PGetFourierBlockDialog.h \ PGetPlotBlockDialog.h \ PMsr2DataDialog.h \ + PChangeDefaultPathsDialog.h \ PMusrEditAbout.h SOURCES = PHelp.cpp \ @@ -128,6 +129,7 @@ SOURCES = PHelp.cpp \ PGetFourierBlockDialog.cpp \ PGetPlotBlockDialog.cpp \ PMsr2DataDialog.cpp \ + PChangeDefaultPathsDialog.cpp \ PMusrEditAbout.cpp \ main.cpp @@ -147,7 +149,8 @@ FORMS = forms/PFindDialog.ui \ forms/PGetNonMusrRunBlockDialog.ui \ forms/PGetFourierBlockDialog.ui \ forms/PGetPlotBlockDialog.ui \ - forms/PMsr2DataDialog.ui + forms/PMsr2DataDialog.ui \ + forms/PChangeDefaultPathsDialog.ui RESOURCES = musredit.qrc