/*************************************************************************** PmuppGui.cpp Author: Andreas Suter e-mail: andreas.suter@psi.ch ***************************************************************************/ /*************************************************************************** * Copyright (C) 2007-2020 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "mupp_version.h" #include "PmuppGui.h" #include "PGetNormValDialog.h" //---------------------------------------------------------------------------------------------------- /** * @brief PmuppXY::init */ void PmuppXY::init() { fCollectionTag = -1; fXlabel = ""; fYlabel.clear(); } //---------------------------------------------------------------------------------------------------- /** * @brief PmuppXY::setYlabel * @param idx * @param str */ void PmuppXY::setYlabel(int idx, QString str) { if (idx >= fYlabel.size()) return; fYlabel[idx] = str; } //---------------------------------------------------------------------------------------------------- /** * @brief PmuppXY::removeYlabel * @param idx */ void PmuppXY::removeYlabel(int idx) { if (idx >= fYlabel.size()) return; fYlabel.remove(idx); } //---------------------------------------------------------------------------------------------------- /** * @brief PmuppXY::removeYlabel * @param str */ void PmuppXY::removeYlabel(QString str) { for (int i=0; i= fYlabel.size()) return QString(""); return fYlabel[idx]; } //---------------------------------------------------------------------------------------------------- /** * @brief PmuppXY::getXlabelIdx * @return */ int PmuppXY::getXlabelIdx() { QString str = fXlabel; // remove trailing '-)' int idx = fXlabel.lastIndexOf("-)"); if (idx == -1) return -1; str.remove(idx, str.length()-idx); // remove everything up to '(-' idx = fXlabel.indexOf("(-"); if (idx == -1) return -1; idx += 2; str.remove(0, idx); bool ok; idx = str.toInt(&ok); if (!ok) return -1; return idx; } //---------------------------------------------------------------------------------------------------- /** * @brief PmuppXY::getYlabelIdx * @param idx * @return */ int PmuppXY::getYlabelIdx(int idx) { if (idx >= fYlabel.size()) return -1; QString str = fYlabel[idx]; // remove trailing '-)' int iidx = fXlabel.lastIndexOf("-)"); if (iidx == -1) return -1; str.remove(iidx, str.length()-iidx); // remove everything up to '(-' iidx = fXlabel.indexOf("(-"); if (iidx == -1) return -1; iidx += 2; str.remove(0, iidx); bool ok; iidx = str.toInt(&ok); if (!ok) return -1; return iidx; } //---------------------------------------------------------------------------------------------------- /** *

Constructor * * \param fln file names to be loaded * \param parent pointer to the parent object * \param f qt windows flags */ PmuppGui::PmuppGui( QStringList fln, QWidget *parent, Qt::WindowFlags f ) : QMainWindow( parent, f ) { QDateTime dt = QDateTime::currentDateTime(); fDatime = dt.toTime_t(); fMuppInstance = -1; fMuppPlot = nullptr; fNormalizeAction = nullptr; fNormalize = false; fNormVal = 0.0; fMacroPath = QString("./"); fMacroName = QString(""); readCmdHistory(); fAdmin = new PmuppAdmin(); fParamDataHandler = new PParamDataHandler(); bool dataAtStartup = false; if (fln.size() > 0) { if (fln[0].contains(".msr")) { // get collection Name QString collName = QString("collName0"); fParamDataHandler->NewCollection(collName); } QString errorMsg(""); if (!fParamDataHandler->ReadParamFile(fln, errorMsg)) { QMessageBox::critical(this, "ERROR", errorMsg); } else { dataAtStartup = true; // delay to deal with the data sets until the GUI is ready to do so } } getTheme(); QString iconName(""); if (fDarkTheme) iconName = QString(":/icons/mupp-dark.svg"); else iconName = QString(":/icons/mupp-plain.svg"); setWindowIcon( QIcon( QPixmap(iconName) ) ); // setup menus setupFileActions(); setupToolActions(); setupHelpActions(); // create central widget fCentralWidget = new QWidget(this); // setup widgets fBoxLayout_Main = new QBoxLayout(QBoxLayout::TopToBottom); fBoxLayout_Main->setGeometry(QRect(10, 40, 600, 500)); fBoxLayout_Top = new QBoxLayout(QBoxLayout::LeftToRight); fGridLayout_Left = new QGridLayout(); fGridLayout_Right = new QGridLayout(); fBoxLayout_Cmd = new QBoxLayout(QBoxLayout::LeftToRight); // label for the collection/parameter list widgets fColLabel = new QLabel(this); fColLabel->setText("Collection -> Parameter"); fColLabel->setMaximumHeight(15); // central widget for the collection/parameter list widgets fColParamSplitter = new QSplitter(Qt::Horizontal, this); fColParamSplitter->setMinimumSize(550,330); fColList = new QListWidget(this); fColList->setSelectionMode(QAbstractItemView::ExtendedSelection); fParamList = new QListWidget(this); // the next two lines enable drag and drop facility (drag) fParamList->setSelectionMode(QAbstractItemView::SingleSelection); fParamList->setDragEnabled(true); fColParamSplitter->addWidget(fColList); fColParamSplitter->addWidget(fParamList); fRemoveCollection = new QPushButton("Remove Collection", this); fRefreshCollection = new QPushButton("Refresh Collection", this); fGridLayout_Left->addWidget(fColLabel, 1, 1, 1, 2); fGridLayout_Left->addWidget(fColParamSplitter, 2, 1, 1, 2); fGridLayout_Left->addWidget(fRemoveCollection, 3, 1); fGridLayout_Left->addWidget(fRefreshCollection, 3, 2); // X-axis fXaxisLabel = new QLabel("x-axis"); fViewX = new QListWidget(this); // the next two lines enable drag and drop facility (copy drop) fViewX->viewport()->setAcceptDrops(true); fViewX->setDropIndicatorShown(true); fAddX = new QPushButton("add X", this); fRemoveX = new QPushButton("remove X", this); // Y-axis fYaxisLabel = new QLabel("y-axis"); fViewY = new QListWidget(this); // the next two lines enable drag and drop facility (copy drop) fViewY->viewport()->setAcceptDrops(true); fViewY->setDropIndicatorShown(true); fAddY = new QPushButton("add Y", this); fRemoveY = new QPushButton("remove Y", this); // 2 column button's for the right grid fAddDitto = new QPushButton("Add Ditto", this); fPlot = new QPushButton("Plot", this); fGridLayout_Right->addWidget(fXaxisLabel, 1, 1); fGridLayout_Right->addWidget(fYaxisLabel, 1, 2); fGridLayout_Right->addWidget(fViewX, 2, 1); fGridLayout_Right->addWidget(fViewY, 2, 2); fGridLayout_Right->addWidget(fAddX, 3, 1); fGridLayout_Right->addWidget(fAddY, 3, 2); fGridLayout_Right->addWidget(fRemoveX, 4, 1); fGridLayout_Right->addWidget(fRemoveY, 4, 2); fGridLayout_Right->addWidget(fAddDitto, 5, 1, 1, 2); fGridLayout_Right->addWidget(fPlot, 6, 1, 1, 2); fBoxLayout_Top->addLayout(fGridLayout_Left); fBoxLayout_Top->addLayout(fGridLayout_Right); fCmdLineHistory = new QPlainTextEdit(this); fCmdLineHistory->setReadOnly(true); fCmdLineHistory->setMaximumBlockCount(50); // fill cmd history for (int i=0; iinsertPlainText(QString("%1\n").arg(fCmdHistory[i])); fCmdLine = new QLineEdit(this); fCmdLine->installEventFilter(this); fCmdLine->setText("$ "); fCmdLine->setFocus(); // sets the keyboard focus fExitButton = new QPushButton("E&xit", this); QVBoxLayout *cmdLayout = new QVBoxLayout; QLabel *cmdLabel = new QLabel("History:"); cmdLayout->addWidget(cmdLabel); cmdLayout->addWidget(fCmdLineHistory); cmdLayout->addWidget(fCmdLine); fBoxLayout_Cmd = new QBoxLayout(QBoxLayout::LeftToRight); fBoxLayout_Cmd->addLayout(cmdLayout); fBoxLayout_Cmd->addWidget(fExitButton); fBoxLayout_Cmd->setAlignment(fCmdLine, Qt::AlignBottom); fBoxLayout_Cmd->setAlignment(fExitButton, Qt::AlignBottom); fCmdSplitter = new QSplitter(Qt::Vertical, this); QWidget *topWidget = new QWidget(this); // only needed since splitter needs a QWidget topWidget->setLayout(fBoxLayout_Top); QWidget *cmdWidget = new QWidget(this); // only needed since splitter needs a QWidget cmdWidget->setLayout(fBoxLayout_Cmd); fCmdSplitter->addWidget(topWidget); fCmdSplitter->addWidget(cmdWidget); fBoxLayout_Main->addWidget(fCmdSplitter); // establish all the necessary signal/slots connect(fRefreshCollection, SIGNAL( pressed() ), this, SLOT( refresh() )); connect(fRemoveCollection, SIGNAL( pressed() ), this, SLOT( remove() )); connect(fAddX, SIGNAL( pressed() ), this, SLOT( addX() )); connect(fAddY, SIGNAL( pressed() ), this, SLOT( addY() )); connect(fRemoveX, SIGNAL( pressed() ), this, SLOT( removeX() )); connect(fRemoveY, SIGNAL( pressed() ), this, SLOT( removeY() )); connect(fAddDitto, SIGNAL( pressed() ), this, SLOT( addDitto() )); connect(fPlot, SIGNAL( pressed()), this, SLOT( plot()) ); connect(fCmdLine, SIGNAL ( returnPressed() ), this, SLOT( handleCmds() )); connect(fExitButton, SIGNAL( pressed() ), this, SLOT( aboutToQuit() )); connect(fColList, SIGNAL( currentRowChanged(int) ), this, SLOT( updateParamList(int) )); connect(fColList, SIGNAL( itemDoubleClicked(QListWidgetItem*) ), this, SLOT( editCollName(QListWidgetItem*) )); connect(fViewX, SIGNAL( currentRowChanged(int) ), this, SLOT( refreshY() )); connect(fViewX, SIGNAL( itemChanged(QListWidgetItem*) ), this, SLOT( dropOnViewX(QListWidgetItem*) )); connect(fViewY, SIGNAL( itemChanged(QListWidgetItem*) ), this, SLOT( dropOnViewY(QListWidgetItem*) )); // deal with parameter data specifics if (dataAtStartup) handleNewData(); connect(fParamDataHandler, SIGNAL( newData() ), this, SLOT( handleNewData() )); fCentralWidget->setLayout(fBoxLayout_Main); setCentralWidget(fCentralWidget); // in case there is no db/dat file list given open the db/dat file open menu automatically. if (fln.size() == 0) { fileOpen(); if (fParamDataHandler->GetNoOfCollections() == 0) { // file open dialog has been cancelled exit(0); } } } //---------------------------------------------------------------------------------------------------- /** * @brief PmuppGui::~PmuppGui */ PmuppGui::~PmuppGui() { // all relevant clean up job are done in ::aboutToQuit() } //---------------------------------------------------------------------------------------------------- /** * @brief PmuppGui::aboutToQuit */ void PmuppGui::aboutToQuit() { // kill mupp_plot if active if (fMuppPlot) { if (fMuppPlot->state() != QProcess::NotRunning) { fMuppPlot->terminate(); } } // remove message queue key_t key; int flags, msqid; // generate the ICP message queue key key = ftok(QCoreApplication::applicationFilePath().toLatin1().data(), 1); if (key != -1) { // set the necessary IPC message queue flags flags = IPC_CREAT; // open the message queue msqid = msgget(key, flags | S_IRUSR | S_IWUSR); if (msqid != -1) { if (msgctl(msqid, IPC_RMID, NULL) == -1) { std::cerr << "**ERROR** couldn't removed the message queue (msqid=" << msqid << ")." << std::endl << std::endl; } } } // clean up temporary plot files QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); if (fMuppInstance != -1) { QString pathName = QString("%1/.musrfit/mupp/_mupp_%2.dat").arg(env.value("HOME")).arg(fDatime); QFile::remove(pathName); pathName = QString("%1/.musrfit/mupp/_mupp_ftok_%2.dat").arg(env.value("HOME")).arg(fMuppInstance); QFile::remove(pathName); } // needed for clean up and to save the cmd history writeCmdHistory(); if (fParamDataHandler) { delete fParamDataHandler; fParamDataHandler = 0; } if (fAdmin) { delete fAdmin; fAdmin = 0; } exit(0); } //---------------------------------------------------------------------------------------------------- /** * @brief PmuppGui::setupFileActions */ void PmuppGui::setupFileActions() { QToolBar *tb = new QToolBar( this ); tb->setWindowTitle( "File Actions" ); addToolBar( tb ); QMenu *menu = new QMenu( tr( "F&ile" ), this ); menuBar()->addMenu( menu ); QAction *a; QString iconName(""); if (fDarkTheme) iconName = QString(":/icons/document-open-dark.svg"); else iconName = QString(":/icons/document-open-plain.svg"); a = new QAction( QIcon( QPixmap(iconName) ), tr( "&Open..." ), this ); a->setShortcut( tr("Ctrl+O") ); a->setStatusTip( tr("Open a musrfit parameter file.") ); connect( a, SIGNAL( triggered() ), this, SLOT( fileOpen() ) ); menu->addAction(a); if (!fDarkToolBarIcon) { // tool bar icon is not dark, even though the theme is (ubuntu) iconName = QString(":/icons/document-open-plain.svg"); a = new QAction( QIcon( QPixmap(iconName) ), tr( "&New..." ), this ); connect( a, SIGNAL( triggered() ), this, SLOT( fileOpen() ) ); } tb->addAction(a); fRecentFilesMenu = menu->addMenu( tr("Recent Files") ); for (int i=0; isetVisible(false); connect( fRecentFilesAction[i], SIGNAL(triggered()), this, SLOT(fileOpenRecent())); fRecentFilesMenu->addAction(fRecentFilesAction[i]); } fillRecentFiles(); a = new QAction( tr( "E&xit" ), this ); a->setShortcut( tr("Ctrl+Q") ); a->setStatusTip( tr("Exit Program") ); connect( a, SIGNAL( triggered() ), this, SLOT( fileExit() ) ); menu->addAction(a); } //---------------------------------------------------------------------------------------------------- /** * @brief PmuppGui::setupToolActions */ void PmuppGui::setupToolActions() { QMenu *menu = new QMenu( tr( "&Tools" ), this ); menuBar()->addMenu( menu ); QAction *a; a = new QAction(tr( "Plot ..." ), this ); a->setStatusTip( tr("Plot x/y parameters") ); connect( a, SIGNAL( triggered() ), this, SLOT( plot() ) ); menu->addAction(a); a = new QAction(tr( "Create ROOT Macro ..." ), this ); a->setStatusTip( tr("Creates a ROOT Macro with the given x/y parameters") ); connect( a, SIGNAL( triggered() ), this, SLOT( createMacro() ) ); menu->addAction(a); menu->addSeparator(); a = new QAction(tr( "Dump Collections ..." ), this ); a->setStatusTip( tr("Dump all collections") ); connect( a, SIGNAL( triggered() ), this, SLOT( toolDumpCollections() ) ); menu->addAction(a); a = new QAction(tr( "Dump XY ..." ), this ); a->setStatusTip( tr("Dump XY parameter list") ); connect( a, SIGNAL( triggered() ), this, SLOT( toolDumpXY() ) ); menu->addAction(a); menu->addSeparator(); fNormalizeAction = new QAction(tr( "Normalize" ), this); fNormalizeAction->setStatusTip( tr("Plot Data Normalized (y-axis)") ); fNormalizeAction->setCheckable(true); connect( fNormalizeAction, SIGNAL( changed() ), this, SLOT( normalize() ) ); menu->addAction(fNormalizeAction); a = new QAction(tr( "Normalize by Value" ), this); a->setStatusTip( tr("Normalize by Value") ); connect( a, SIGNAL( triggered() ), this, SLOT( normVal() ) ); menu->addAction(a); } //---------------------------------------------------------------------------------------------------- /** * @brief PmuppGui::setupHelpActions */ void PmuppGui::setupHelpActions() { QMenu *menu = new QMenu( tr( "&Help" ), this ); menuBar()->addMenu( menu ); QAction *a; /* a = new QAction(tr( "Contents ..." ), this ); a->setStatusTip( tr("Help Contents") ); connect( a, SIGNAL( triggered() ), this, SLOT( helpContents() )); menu->addAction(a); */ a = new QAction( tr( "Cmd's" ), this ); a->setStatusTip( tr( "Lists the command line commands" ) ); connect( a, SIGNAL( triggered() ), this, SLOT( helpCmds() )); menu->addAction(a); a = new QAction( tr( "Author(s) ..." ), this ); a->setStatusTip( tr( "About the Author(s)") ); connect( a, SIGNAL( triggered() ), this, SLOT( helpAbout() )); menu->addAction(a); a = new QAction( tr( "About Qt..." ), this ); a->setStatusTip( tr( "Help About Qt") ); connect( a, SIGNAL( triggered() ), this, SLOT( helpAboutQt() )); menu->addAction(a); } //---------------------------------------------------------------------------------------------------- /** * @brief PmuppGui::fileOpen */ void PmuppGui::fileOpen() { QStringList list = QFileDialog::getOpenFileNames( this, "muSR Parameter Files", "./", "db-files (*.db);; All Params (*.msr *.db *.dat);; Msr-Files (*.msr);; dat-Files (*.dat);; All (*)"); if (list.count() == 0) return; bool msrPresent = false; bool dbPresent = false; for (int i=0; iReadParamFile(list, errorMsg)) { QMessageBox::critical(this, "ERROR", errorMsg); return; } // populate the recent files if (msrPresent || dbPresent) { for (int i=0; iaddRecentFile(list[i]); // keep it in admin fillRecentFiles(); // update menu } } } //---------------------------------------------------------------------------------------------------- /** * @brief PmuppGui::fileOpenRecent */ void PmuppGui::fileOpenRecent() { QAction *action = qobject_cast(sender()); if (action) { QStringList fln; fln << action->text(); QString errorMsg(""); if (!fParamDataHandler->ReadParamFile(fln, errorMsg)) { QMessageBox::critical(this, "ERROR", errorMsg); return; } } } //---------------------------------------------------------------------------------------------------- /** * @brief PmuppGui::fileExit */ void PmuppGui::fileExit() { aboutToQuit(); } //---------------------------------------------------------------------------------------------------- /** * @brief PmuppGui::toolDump */ void PmuppGui::toolDumpCollections() { if (fParamDataHandler->GetNoOfCollections()) { fParamDataHandler->Dump(); } else { QMessageBox::warning(this, "dump collections", "no collections present"); } } //---------------------------------------------------------------------------------------------------- void PmuppGui::toolDumpXY() { if (fXY.size() > 0) { for (int i=0; i<-><-><-><-><-><-><-><-><->"; qInfo() << i << ": collection tag: " << fXY[i].getCollectionTag(); qInfo() << " x-param: " << fXY[i].getXlabel(); for (int j=0; jisChecked(); } //---------------------------------------------------------------------------------------------------- void PmuppGui::normVal() { PGetNormValDialog *dlg = new PGetNormValDialog(fNormVal); if (dlg == nullptr) { QMessageBox::critical(this, "**ERROR**", "Couldn't invoke dialog, sorry :-(", QMessageBox::Ok, QMessageBox::NoButton); return; } dlg->exec(); if (dlg->result() != QDialog::Accepted) { delete dlg; return; } fNormVal = dlg->getValue(); delete dlg; } //---------------------------------------------------------------------------------------------------- /** * @brief PmuppGui::helpCmds */ void PmuppGui::helpCmds() { QMessageBox::information(this, "cmd help", "help: this help.
"\ "ditto: addX/Y for the new selection as for the previous ones.
"\ "dump collections: dumps all currently loaded collections.
"\ "dump XY: dumps X/Y tree.
"\ "exit/quit: close mupp.
"\ "load: calls the open file dialog.
"\ "norm <flag>: normalize plots to maximum if <flag> is true
"\ "macro <fln>: saves the X/Y data as a ROOT macro (*.C).
"\ "path <macroPath>: sets the path to the place where the macros will be saved.
"\ "plot: plot the X/Y data.
"\ "refresh: refresh the currently selected collection.
"\ "select <nn>: select collection in GUI.
"\ "    <nn> is either the collection name or the row number.
"\ "x <param_name> / y <param_name>: add the parameter to the select axis.
"\ "rmx <param_name> / rmy <param_name>: remove the parameter of the select axis.
"\ "flush: flush the history buffer."); } //---------------------------------------------------------------------------------------------------- /** * @brief PmuppGui::helpAbout */ void PmuppGui::helpAbout() { QMessageBox::information(this, "about", QString("mupp: created by Andreas Suter.\nVersion: %1\nBranch: %2\nHash: %3").arg(MUPP_VERSION).arg(GIT_BRANCH).arg(GIT_COMMIT_HASH)); } //---------------------------------------------------------------------------------------------------- /** * @brief PmuppGui::helpAboutQt */ void PmuppGui::helpAboutQt() { QMessageBox::aboutQt(this); } //---------------------------------------------------------------------------------------------------- /** * @brief PmuppGui::eventFilter * @param o * @param e * @return */ bool PmuppGui::eventFilter(QObject *o, QEvent *e) { static int idx = fCmdHistory.size(); if (e->type() == QEvent::KeyPress) { QKeyEvent *k = static_cast(e); int key = k->key(); if (key == Qt::Key_Up) { if (idx > 0) idx--; if (idx < fCmdHistory.size()) fCmdLine->setText(fCmdHistory[idx]); } else if (key == Qt::Key_Down) { if (idx < fCmdHistory.size()) idx++; if (idx < fCmdHistory.size()) fCmdLine->setText(fCmdHistory[idx]); else fCmdLine->setText("$ "); } else if (key == Qt::Key_Return) { QString cmd = fCmdLine->text(); bool found = false; for (int i=0; i= 50) fCmdHistory.removeFirst(); fCmdHistory.push_back(cmd); fCmdLineHistory->insertPlainText(QString("%1\n").arg(cmd)); } } return false; } // make sure the base class can handle all the events not handled here return QMainWindow::eventFilter(o, e); } //---------------------------------------------------------------------------------------------------- /** * @brief PmuppGui::getTheme */ void PmuppGui::getTheme() { fDarkTheme = false; // true if theme is dark fDarkToolBarIcon = false; // needed for ubuntu dark since there the menu icons are dark, however the toolbar icons are plain! QString str = QIcon::themeName(); if (str.isEmpty()) { if (fAdmin->isDarkTheme()) { fDarkTheme = true; fDarkToolBarIcon = true; } return; } if (str.contains("dark", Qt::CaseInsensitive)) { fDarkTheme = true; if (str.contains("ubuntu", Qt::CaseInsensitive)) { fDarkToolBarIcon = false; } else { fDarkToolBarIcon = true; } } } //---------------------------------------------------------------------------------------------------- /** *

fill the recent file list in the menu. */ void PmuppGui::fillRecentFiles() { for (int i=0; igetNumRecentFiles(); i++) { fRecentFilesAction[i]->setText(fAdmin->getRecentFile(i)); fRecentFilesAction[i]->setVisible(true); } } //---------------------------------------------------------------------------------------------------- /** * @brief PmuppGui::readCmdHistory */ void PmuppGui::readCmdHistory() { QProcessEnvironment procEnv = QProcessEnvironment::systemEnvironment(); QString home = procEnv.value("HOME", ""); if (home.isEmpty()) return; QString pathName = home + "/.musrfit/mupp/mupp_history.txt"; QFile file(pathName); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { std::cerr << std::endl; std::cerr << "***********" << std::endl; std::cerr << "**WARNING** readCmdHistory(): couldn't open mupp_history.txt for reading ..." << std::endl;; std::cerr << "***********" << std::endl; return; } QTextStream fin(&file); fCmdHistory.clear(); QString line; while (!fin.atEnd()) { line = fin.readLine(); if (line.startsWith("%") || line.isEmpty()) continue; fCmdHistory.push_back(line); } } //---------------------------------------------------------------------------------------------------- void PmuppGui::writeCmdHistory() { QProcessEnvironment procEnv = QProcessEnvironment::systemEnvironment(); QString home = procEnv.value("HOME", ""); if (home.isEmpty()) return; QString pathName = home + "/.musrfit/mupp/"; QDir dir(pathName); if (!dir.exists()) { // directory $HOME/.musrfit/mupp does not exist hence create it dir.mkpath(pathName); } pathName += "mupp_history.txt"; QFile file(pathName); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) return; QTextStream fout(&file); // write header QDateTime dt = QDateTime::currentDateTime(); fout << "% mupp history file" << endl; fout << "% " << dt.toString("HH:mm:ss - yy/MM/dd") << endl; // write history for (int i=0; icurrentItem(); if (item == 0) return; QString label = item->text(); QString pathName(""); int collIdx=-1; for (int i=0; iGetNoOfCollections(); i++) { if (fParamDataHandler->GetCollection(i)->GetName() == label) { // found collection pathName = fParamDataHandler->GetCollection(i)->GetPathName(); collIdx = i; break; } } // re-load collection PmuppCollection coll; bool ok=false; if (pathName.endsWith(".db")) { QString errorMsg(""); coll = fParamDataHandler->ReadDbFile(pathName, ok, errorMsg); if (!ok) { QMessageBox::critical(this, "ERROR - REFRESH", QString("Couldn't refresh %1\nFile corrupted?!\n").arg(fParamDataHandler->GetCollection(collIdx)->GetName())+ errorMsg); return; } } else if (pathName.endsWith(".dat")) { QString errorMsg(""); coll = fParamDataHandler->ReadColumnParamFile(pathName, ok, errorMsg); if (!ok) { QMessageBox::critical(this, "ERROR - REFRESH", QString("Couldn't refresh %1\nFile corrupted?!\n").arg(fParamDataHandler->GetCollection(collIdx)->GetName())+ errorMsg); return; } } else { QMessageBox::critical(this, "ERROR - REFRESH", QString("Couldn't refresh %1").arg(fParamDataHandler->GetCollection(collIdx)->GetName())); return; } QString collName = pathName; int pos = collName.lastIndexOf("/"); collName.remove(0, pos+1); coll.SetName(collName); coll.SetPathName(pathName); fParamDataHandler->ReplaceCollection(coll, collIdx); // update the parameter list (GUI) updateParamList(collIdx); // update XY list (GUI) updateXYListGui(); } //---------------------------------------------------------------------------------------------------- /** * @brief PmuppGui::remove */ void PmuppGui::remove() { // get current collection QListWidgetItem *item = fColList->currentItem(); if (item == 0) return; QString collName = item->text(); // remove it from the list widget but keep the index for further use int idx = fColList->row(item); fColList->removeItemWidget(item); delete item; // remove it from the collection handler fParamDataHandler->RemoveCollection(collName); // next it is necessary to update the XY-parameter list updateXYList(fColList->currentRow()); // if there no collections left remove all the parameters from the X/Y list // remove all fXY as well if (fColList->count() == 0) { fViewX->clear(); fViewY->clear(); fXY.clear(); return; } // select the row before the delete one if possible if (idx > 0) idx -= 1; fColList->setCurrentRow(idx, QItemSelectionModel::Select); // update the parameter list (GUI) updateParamList(idx); // update XY list (GUI) updateXYListGui(); } //---------------------------------------------------------------------------------------------------- /** * @brief PmuppGui::addX */ void PmuppGui::addX(QString param) { QString paramName(""); if (!param.isEmpty()) { // check that param exists if (fParamList->findItems(param, Qt::MatchCaseSensitive).empty()) { QMessageBox::critical(this, "**ERROR**", QString("Parameter X '%1' not found").arg(param)); return; } paramName = param; } else { // get the parameter name from the parameter list widget QListWidgetItem *item = fParamList->currentItem(); if (item == 0) return; paramName = item->text(); } int idx = fColList->currentRow(); QString xLabel = QString("%1 (-%2-)").arg(paramName).arg(idx); // check if it is not already present for (int i=0; icount(); i++) { if (fViewX->item(i)->text() == xLabel) return; } // set the parameter name on the view X list widget fViewX->addItem(xLabel); fViewX->setCurrentRow(fViewX->count()-1); // add the item to the XY list PmuppXY xyItem; xyItem.setCollectionTag(idx); xyItem.setXlabel(xLabel); fXY.push_back(xyItem); } //---------------------------------------------------------------------------------------------------- /** * @brief PmuppGui::addY */ void PmuppGui::addY(QString param) { QString paramName(""); if (!param.isEmpty()) { // check that param exists if (fParamList->findItems(param, Qt::MatchCaseSensitive).empty()) { QMessageBox::critical(this, "**ERROR**", QString("Parameter Y '%1' not found").arg(param)); return; } paramName = param; } else { // get the parameter name from the parameter list widget QListWidgetItem *item = fParamList->currentItem(); if (item == 0) return; paramName = item->text(); } int idx = fColList->currentRow(); QString yLabel = QString("%1 (-%2-)").arg(paramName).arg(idx); // make sure that any x-parameter selection is already present if (fViewX->count() == 0) { QMessageBox::warning(this, "**WARNING**", "It is compulsory to have at least one x-parameter set\nbefore trying to add a y-parameter."); return; } // check if collection of x- and y-parameter selection correspond idx=getXlabelIndex(fViewX->currentItem()->text()); if (idx == -1) return; if (fXY[idx].getCollectionTag() != fColList->currentRow()) { QMessageBox::warning(this, "**WARNING**", "x/y parameters need to originate from the same collection."); return; } // check if it is not already present for (int i=0; icount(); i++) { if (fViewY->item(i)->text() == yLabel) return; } // set the parameter name on the view Y list widget fViewY->addItem(yLabel); // add the item to the XY list idx=getXlabelIndex(fViewX->currentItem()->text()); if (idx == -1) return; fXY[idx].addYlabel(yLabel); } //---------------------------------------------------------------------------------------------------- /** * @brief PmuppGui::removeX */ void PmuppGui::removeX(QString param) { QListWidgetItem *item = fViewX->currentItem(); if (item == 0) return; int idx; if (!param.isEmpty()) { idx=fColList->currentRow(); param = QString("%1 (-%2-)").arg(param).arg(idx); idx=getXlabelIndex(param); } else { idx=getXlabelIndex(item->text()); } if (idx == -1) return; fXY.remove(idx); fViewX->removeItemWidget(item); delete item; } //---------------------------------------------------------------------------------------------------- /** * @brief PmuppGui::removeY */ void PmuppGui::removeY(QString param) { QListWidgetItem *item = fViewY->currentItem(); if (item == 0) return; // find y in XY and remove it QString xLabel = fViewX->currentItem()->text(); QString yLabel = item->text(); if (!param.isEmpty()) { yLabel = param; } int idx = getXlabelIndex(xLabel); if (idx == -1) return; fXY[idx].removeYlabel(yLabel); fViewY->removeItemWidget(item); delete item; } //---------------------------------------------------------------------------------------------------- /** * @brief PmuppGui::addDitto */ void PmuppGui::addDitto() { if (fXY.size() == 0) { QMessageBox::critical(this, "ERROR", "No x/y items present.\nTherefore nothing to be done."); return; } if (!allXYEqual()) { QMessageBox::critical(this, "ERROR", "Multiple unequal sets of x/y items present.\nDo not know how to handle."); return; } // get the selected items from the collection QList items = fColList->selectedItems(); if (items.count() == 0) { // no selections present hence drop out return; } // verify that all selected items have corresponding x/y values bool ok=false; PmuppCollection muCol; PmuppRun muRun; for (int i=0; iGetCollection(items[i]->text(), ok); if (!ok) return; muRun = muCol.GetRun(0); // check x-values if (!findValue(muRun, kXaxis)) return; // check y-values if (!findValue(muRun, kYaxis)) return; } // populate all necessary x- and y-values for all selected collections PmuppXY muXY = fXY[0]; int idx; for (int i=0; irow(items[i]); if (indexAlreadyPresent(idx)) continue; replaceIndex(muXY, idx); fXY.push_back(muXY); // add x-axis view fViewX->addItem(muXY.getXlabel()); fViewX->setCurrentRow(fViewX->count()-1); } // un-select the collecion list fColList->clearSelection(); } //---------------------------------------------------------------------------------------------------- /** * @brief PmuppGui::findValue * @param run * @param tag * @return */ bool PmuppGui::findValue(PmuppRun &run, EAxis tag) { bool result = false; if (tag == kXaxis) { for (int i=0; i (-#-)' and // all