777 lines
25 KiB
C++
777 lines
25 KiB
C++
/****************************************************************************
|
|
|
|
PmuppAdmin.cpp
|
|
|
|
Author: Andreas Suter
|
|
e-mail: andreas.suter@psi.ch
|
|
|
|
*****************************************************************************/
|
|
|
|
/***************************************************************************
|
|
* Copyright (C) 2010-2025 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. *
|
|
***************************************************************************/
|
|
|
|
/**
|
|
* @file PmuppAdmin.cpp
|
|
*
|
|
* @brief Implementation of mupp configuration and administration classes.
|
|
*
|
|
* This file implements the configuration management system for mupp, including:
|
|
* - XML parsing of the mupp_startup.xml configuration file
|
|
* - Recent file history management
|
|
* - Plot appearance settings (colors and markers)
|
|
* - Theme preferences for UI elements
|
|
* - Automatic creation of default configuration files
|
|
*
|
|
* The implementation provides:
|
|
* - PmuppColor: RGB color storage and manipulation
|
|
* - PmuppAdminXMLParser: XML configuration file parsing
|
|
* - PmuppAdmin: Main configuration manager with file search hierarchy
|
|
*
|
|
* Configuration file handling:
|
|
* - Searches multiple standard locations for configuration
|
|
* - Creates default configuration if none found
|
|
* - Automatically saves recent file history on exit
|
|
* - Validates configuration values (marker codes, RGB ranges)
|
|
*/
|
|
|
|
#include <cstdlib>
|
|
#include <iostream>
|
|
|
|
#include <QMessageBox>
|
|
#include <QString>
|
|
#include <QStringView>
|
|
#include <QFile>
|
|
#include <QTextStream>
|
|
#include <QVector>
|
|
#include <QDir>
|
|
#include <QProcessEnvironment>
|
|
#include <QSysInfo>
|
|
|
|
#include <QtDebug>
|
|
|
|
#include "PmuppAdmin.h"
|
|
|
|
//--------------------------------------------------------------------------
|
|
// implementation of PmuppColor class
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* @brief Default constructor for PmuppColor.
|
|
*
|
|
* Initializes a color with an "UnDef" name and invalid RGB values (-1).
|
|
* Invalid values indicate the color has not been properly initialized.
|
|
*/
|
|
PmuppColor::PmuppColor()
|
|
{
|
|
fName = "UnDef";
|
|
fRed = -1;
|
|
fGreen = -1;
|
|
fBlue = -1;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* @brief Sets the RGB color values with validation.
|
|
*
|
|
* Sets the red, green, and blue components of the color. Each component
|
|
* is validated to be in the range [0, 255]. Values outside this range
|
|
* are ignored and the corresponding component remains unchanged.
|
|
*
|
|
* @param r red component (0-255)
|
|
* @param g green component (0-255)
|
|
* @param b blue component (0-255)
|
|
*/
|
|
void PmuppColor::setRGB(const int r, const int g, const int b)
|
|
{
|
|
if ((r>=0) && (r<=255))
|
|
fRed = r;
|
|
if ((g>=0) && (g<=255))
|
|
fGreen = g;
|
|
if ((b>=0) && (b<=255))
|
|
fBlue = b;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// implementation of PmuppAdminXMLParser class
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* @brief Constructor for XML parser.
|
|
*
|
|
* Initializes the XML parser and attempts to open and parse the
|
|
* specified configuration file. The parsed data is stored in the
|
|
* provided PmuppAdmin object.
|
|
*
|
|
* @param fln path to the mupp_startup.xml configuration file
|
|
* @param admin pointer to the PmuppAdmin instance to populate with parsed data
|
|
*/
|
|
PmuppAdminXMLParser::PmuppAdminXMLParser(const QString& fln, PmuppAdmin *admin) : fAdmin(admin)
|
|
{
|
|
fValid = false;
|
|
fKeyWord = eEmpty;
|
|
|
|
QFile file(fln);
|
|
if (!file.open(QFile::ReadOnly | QFile::Text)) {
|
|
// warning and create default - STILL MISSING
|
|
}
|
|
|
|
fValid = parse(&file);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* @brief Parses the mupp startup XML file.
|
|
*
|
|
* This method uses Qt's QXmlStreamReader to parse the configuration file.
|
|
* It processes each XML element sequentially, calling appropriate handler
|
|
* methods (startElement, characters, endElement) based on the element type.
|
|
*
|
|
* The parser is event-driven and maintains state through the fKeyWord
|
|
* enumeration to determine how to process element content.
|
|
*
|
|
* @param device QIODevice (typically QFile) containing the XML data
|
|
*
|
|
* @return true if parsing succeeds without errors, false otherwise
|
|
*/
|
|
bool PmuppAdminXMLParser::parse(QIODevice *device)
|
|
{
|
|
fXml.setDevice(device);
|
|
|
|
bool expectChars = false;
|
|
while (!fXml.atEnd()) {
|
|
fXml.readNext();
|
|
if (fXml.isStartDocument()) {
|
|
startDocument();
|
|
} else if (fXml.isStartElement()) {
|
|
startElement();
|
|
expectChars = true;
|
|
} else if (fXml.isCharacters() && expectChars) {
|
|
characters();
|
|
} else if (fXml.isEndElement()) {
|
|
endElement();
|
|
expectChars = false;
|
|
} else if (fXml.isEndDocument()) {
|
|
endDocument();
|
|
}
|
|
}
|
|
if (fXml.hasError()) {
|
|
QString msg;
|
|
msg = QString("%1 Line %2, column %3").arg(fXml.errorString()).arg(fXml.lineNumber()).arg(fXml.columnNumber());
|
|
QMessageBox::critical(0, "**ERROR**", msg, QMessageBox::Ok, QMessageBox::NoButton);
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* @brief Handler called at the start of XML document parsing.
|
|
*
|
|
* This is invoked when the XML parser encounters the document start.
|
|
* Currently performs no actions but provides a hook for future initialization.
|
|
*
|
|
* @return always returns true
|
|
*/
|
|
bool PmuppAdminXMLParser::startDocument()
|
|
{
|
|
// nothing to be done here for now
|
|
return true;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* @brief Handler called when a new XML element is encountered.
|
|
*
|
|
* This method is invoked when the parser encounters an opening XML tag.
|
|
* It identifies the element type and sets the fKeyWord state accordingly,
|
|
* which determines how the element's content will be processed in the
|
|
* characters() method.
|
|
*
|
|
* Recognized elements:
|
|
* - path_file_name: Recent file entry
|
|
* - ignore_theme_auto_detection: Theme detection override
|
|
* - dark_theme_icon_menu: Menu icon theme
|
|
* - dark_theme_icon_toolbar: Toolbar icon theme
|
|
* - marker: Plot marker definition
|
|
* - color: RGB color definition
|
|
*
|
|
* @return always returns true
|
|
*/
|
|
bool PmuppAdminXMLParser::startElement()
|
|
{
|
|
QString qName = fXml.name().toString();
|
|
|
|
if (qName == "path_file_name") {
|
|
fKeyWord = eRecentFile;
|
|
} else if (qName == "ignore_theme_auto_detection") {
|
|
fKeyWord = eIgnoreThemeAutoDetection;
|
|
} else if (qName == "dark_theme_icon_menu") {
|
|
fKeyWord = eDarkThemeIconsMenu;
|
|
} else if (qName == "dark_theme_icon_toolbar") {
|
|
fKeyWord = eDarkThemeIconsToolbar;
|
|
} else if (qName == "marker") {
|
|
fKeyWord = eMarker;
|
|
} else if (qName == "color") {
|
|
fKeyWord = eColor;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* @brief Handler called when an XML closing tag is encountered.
|
|
*
|
|
* This method is invoked when the parser encounters a closing XML tag.
|
|
* It resets the fKeyWord state to eEmpty, ending the current element's
|
|
* context for content processing.
|
|
*
|
|
* @return always returns true
|
|
*/
|
|
bool PmuppAdminXMLParser::endElement()
|
|
{
|
|
fKeyWord = eEmpty;
|
|
|
|
return true;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* @brief Handler called to process XML element content.
|
|
*
|
|
* This method processes the text content between XML opening and closing
|
|
* tags. The content interpretation depends on the current fKeyWord state
|
|
* (set by startElement).
|
|
*
|
|
* Content processing by element type:
|
|
* - eRecentFile: Adds file path to recent files list
|
|
* - eIgnoreThemeAutoDetection: Sets theme auto-detection flag (yes/no/true/false)
|
|
* - eDarkThemeIconsMenu: Sets menu icon theme preference
|
|
* - eDarkThemeIconsToolbar: Sets toolbar icon theme preference
|
|
* - eMarker: Parses marker definition (code[,size])
|
|
* - eColor: Parses RGB color definition (r,g,b[,name])
|
|
*
|
|
* @return true if content is valid, false on parsing errors
|
|
*/
|
|
bool PmuppAdminXMLParser::characters()
|
|
{
|
|
QString str = fXml.text().toString();
|
|
if (str.isEmpty())
|
|
return true;
|
|
|
|
bool ok;
|
|
int ival, r, g, b;
|
|
double dval;
|
|
QString name("");
|
|
QStringList tok;
|
|
|
|
switch (fKeyWord) {
|
|
case eRecentFile:
|
|
fAdmin->addRecentFile(QString(str.toLatin1()).trimmed());
|
|
break;
|
|
case eIgnoreThemeAutoDetection:
|
|
if ((str == "yes") || (str == "y") || (str == "1") || (str == "true"))
|
|
fAdmin->setIgnoreThemeAutoDetection(true);
|
|
else
|
|
fAdmin->setIgnoreThemeAutoDetection(false);
|
|
break;
|
|
case eDarkThemeIconsMenu:
|
|
if ((str == "yes") || (str == "y") || (str == "1") || (str == "true"))
|
|
fAdmin->setThemeIconsMenu(true);
|
|
else
|
|
fAdmin->setThemeIconsMenu(false);
|
|
break;
|
|
case eDarkThemeIconsToolbar:
|
|
if ((str == "yes") || (str == "y") || (str == "1") || (str == "true"))
|
|
fAdmin->setThemeIconsToolbar(true);
|
|
else
|
|
fAdmin->setThemeIconsToolbar(false);
|
|
break;
|
|
case eMarker:
|
|
tok = str.split(",", Qt::SkipEmptyParts);
|
|
|
|
if ((tok.count() != 1) && (tok.count() != 2)) {
|
|
return false;
|
|
}
|
|
|
|
ival = tok[0].toInt(&ok);
|
|
if (!ok)
|
|
return false;
|
|
|
|
dval = 1.0;
|
|
if (tok.count() == 2) {
|
|
dval = tok[1].toDouble(&ok);
|
|
if (!ok)
|
|
return false;
|
|
}
|
|
fAdmin->setMarker(ival, dval);
|
|
break;
|
|
case eColor:
|
|
tok = str.split(",", Qt::SkipEmptyParts);
|
|
|
|
if ((tok.count() != 3) && (tok.count() != 4)) {
|
|
return false;
|
|
}
|
|
ival = tok[0].toInt(&ok);
|
|
if (!ok)
|
|
return false;
|
|
r = ival;
|
|
ival = tok[1].toInt(&ok);
|
|
if (!ok)
|
|
return false;
|
|
g = ival;
|
|
ival = tok[2].toInt(&ok);
|
|
if (!ok)
|
|
return false;
|
|
b = ival;
|
|
if (tok.count() == 4)
|
|
name = tok[3];
|
|
fAdmin->setColor(r, g, b, name);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* @brief Handler called at the end of XML document parsing.
|
|
*
|
|
* This is invoked when the parser reaches the end of the XML document.
|
|
* Currently performs no post-processing but provides a hook for future
|
|
* finalization tasks such as path expansion or validation.
|
|
*
|
|
* @return always returns true
|
|
*/
|
|
bool PmuppAdminXMLParser::endDocument()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// implementation of PmuppAdmin class
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* @brief Constructor for PmuppAdmin.
|
|
*
|
|
* Initializes the administration object and searches for a configuration
|
|
* file in multiple standard locations. The search proceeds in order:
|
|
* 1. Current directory (./mupp_startup.xml)
|
|
* 2. User home directory ($HOME/.musrfit/mupp/mupp_startup.xml)
|
|
* 3. MUSRFITPATH directory ($MUSRFITPATH/mupp_startup.xml)
|
|
* 4. ROOTSYS directory ($ROOTSYS/bin/mupp_startup.xml)
|
|
*
|
|
* If no configuration file is found, creates a default one in the user's
|
|
* home directory using the embedded resource template.
|
|
*
|
|
* The constructor loads all configuration settings including recent files,
|
|
* markers, colors, and theme preferences via the PmuppAdminXMLParser.
|
|
*/
|
|
PmuppAdmin::PmuppAdmin() : QObject()
|
|
{
|
|
// XML Parser part
|
|
// 1st: check local directory
|
|
QString path = QString("./");
|
|
QString fln = QString("mupp_startup.xml");
|
|
QString pathFln = path + fln;
|
|
QProcessEnvironment procEnv = QProcessEnvironment::systemEnvironment();
|
|
if (!QFile::exists(pathFln)) {
|
|
// 2nd: check $HOME/.musrfit/mupp/mupp_startup.xml
|
|
path = procEnv.value("HOME", "");
|
|
pathFln = path + "/.musrfit/mupp/" + fln;
|
|
if (!QFile::exists(pathFln)) {
|
|
// 3rd: check $MUSRFITPATH/mupp_startup.xml
|
|
path = procEnv.value("MUSRFITPATH", "");
|
|
pathFln = path + "/" + fln;
|
|
if (!QFile::exists(pathFln)) {
|
|
// 4th: check $ROOTSYS/bin/mupp_startup.xml
|
|
path = procEnv.value("ROOTSYS", "");
|
|
pathFln = path + "/bin/" + fln;
|
|
if (!QFile::exists(pathFln)) {
|
|
// 5th: not found anywhere hence create it
|
|
path = procEnv.value("HOME", "");
|
|
pathFln = path + "/.musrfit/mupp/" + fln;
|
|
createMuppStartupFile();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (QFile::exists(pathFln)) { // administration file present
|
|
PmuppAdminXMLParser handler(pathFln, this);
|
|
if (!handler.isValid()) {
|
|
QMessageBox::critical(0, "**ERROR**",
|
|
"Error parsing mupp_startup.xml settings file.\nProbably a few things will not work porperly.\nPlease fix this first.",
|
|
QMessageBox::Ok, QMessageBox::NoButton);
|
|
return;
|
|
}
|
|
} else {
|
|
QMessageBox::critical(0, "**ERROR**",
|
|
"Couldn't find the mupp_startup.xml settings file.\nProbably a few things will not work porperly.\nPlease fix this first.",
|
|
QMessageBox::Ok, QMessageBox::NoButton);
|
|
return;
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* @brief Destructor for PmuppAdmin.
|
|
*
|
|
* Saves the current recent file list to the configuration file before
|
|
* destruction. This ensures that the file history is preserved across
|
|
* application sessions.
|
|
*/
|
|
PmuppAdmin::~PmuppAdmin()
|
|
{
|
|
saveRecentFiles();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* @brief Adds a file to the recent files list.
|
|
*
|
|
* Adds a file path to the front of the recent files ring buffer. If the
|
|
* file is already in the list, it is not added again (no duplicates).
|
|
* The list is limited to MAX_RECENT_FILES entries; older entries are
|
|
* removed when the limit is exceeded.
|
|
*
|
|
* @param str the full path and filename to add to recent files
|
|
*/
|
|
void PmuppAdmin::addRecentFile(const QString str)
|
|
{
|
|
// check if file name is not already present
|
|
for (int i=0; i<fRecentFile.size(); i++) {
|
|
if (str == fRecentFile[i])
|
|
return;
|
|
}
|
|
|
|
fRecentFile.push_front(str);
|
|
if (fRecentFile.size() > MAX_RECENT_FILES)
|
|
fRecentFile.resize(MAX_RECENT_FILES);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* @brief Retrieves a recent file path by index.
|
|
*
|
|
* Returns the file path at the specified position in the recent files list.
|
|
* Index 0 refers to the most recently accessed file.
|
|
*
|
|
* @param idx zero-based index into the recent files list (0 is most recent)
|
|
*
|
|
* @return the file path if index is valid, or an empty string otherwise
|
|
*/
|
|
QString PmuppAdmin::getRecentFile(int idx)
|
|
{
|
|
QString str("");
|
|
|
|
if ((idx >= 0) && (idx < fRecentFile.size()))
|
|
str = fRecentFile[idx];
|
|
|
|
return str;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* @brief Retrieves a marker definition by index.
|
|
*
|
|
* Returns the marker at the specified index in the marker list.
|
|
* Markers are used to define the visual appearance of data points in plots.
|
|
*
|
|
* @param idx zero-based index into the marker list
|
|
*
|
|
* @return the marker definition if index is valid, or a default marker otherwise
|
|
*/
|
|
PmuppMarker PmuppAdmin::getMarker(int idx) {
|
|
PmuppMarker marker;
|
|
|
|
if (idx >= fMarker.size())
|
|
return marker;
|
|
|
|
return fMarker[idx];
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* @brief Retrieves a color by name.
|
|
*
|
|
* Searches for a color with the specified name and returns its RGB values.
|
|
* If the color is not found, all RGB components are set to -1.
|
|
*
|
|
* @param name the name of the color to retrieve
|
|
* @param r output parameter: red component (0-255, or -1 if not found)
|
|
* @param g output parameter: green component (0-255, or -1 if not found)
|
|
* @param b output parameter: blue component (0-255, or -1 if not found)
|
|
*/
|
|
void PmuppAdmin::getColor(QString name, int &r, int &g, int &b)
|
|
{
|
|
int idx=-1;
|
|
for (int i=0; i<fColor.size(); i++) {
|
|
if (fColor[i].getName() == name) {
|
|
idx = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (idx == -1) {
|
|
r = -1;
|
|
g = -1;
|
|
b = -1;
|
|
} else {
|
|
fColor[idx].getRGB(r, g, b);
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* @brief Retrieves a color by index.
|
|
*
|
|
* Returns the RGB values of the color at the specified index in the
|
|
* color list. If the index is out of range, all RGB components are
|
|
* set to -1.
|
|
*
|
|
* @param idx zero-based index into the color list
|
|
* @param r output parameter: red component (0-255, or -1 if invalid index)
|
|
* @param g output parameter: green component (0-255, or -1 if invalid index)
|
|
* @param b output parameter: blue component (0-255, or -1 if invalid index)
|
|
*/
|
|
void PmuppAdmin::getColor(int idx, int &r, int &g, int &b)
|
|
{
|
|
if ((idx<=0) || (idx>fColor.size())) {
|
|
r = -1;
|
|
g = -1;
|
|
b = -1;
|
|
} else {
|
|
fColor[idx].getRGB(r, g, b);
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* @brief Adds a marker definition to the configuration.
|
|
*
|
|
* Creates a new marker with the specified code and size, validates it,
|
|
* and adds it to the marker list. Marker codes must be in the range 1-49
|
|
* (following ROOT conventions). Invalid markers are rejected with a warning.
|
|
*
|
|
* @param marker the marker code (1-49, ROOT style marker codes)
|
|
* @param size the marker size multiplier
|
|
*/
|
|
void PmuppAdmin::setMarker(const int marker, const double size)
|
|
{
|
|
PmuppMarker markerObj;
|
|
|
|
// make sure marker is in proper range
|
|
if ((marker<1) || (marker>49)) {
|
|
QMessageBox::warning(0, "WARNING", QString("Found Marker (%1) not in the expected range.\nWill ignore it.").arg(marker));
|
|
return;
|
|
}
|
|
markerObj.setMarker(marker);
|
|
markerObj.setMarkerSize(size);
|
|
|
|
fMarker.push_back(markerObj);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* @brief Adds a color definition to the configuration.
|
|
*
|
|
* Creates a new color with the specified RGB values and optional name,
|
|
* validates it, and adds it to the color list. RGB values must be in
|
|
* the range 0-255. Invalid colors are rejected with a warning.
|
|
*
|
|
* @param r red component (0-255)
|
|
* @param g green component (0-255)
|
|
* @param b blue component (0-255)
|
|
* @param name optional name for the color (empty by default)
|
|
*/
|
|
void PmuppAdmin::setColor(const int r, const int g, const int b, QString name)
|
|
{
|
|
if (((r<0) || (r>255)) ||
|
|
((g<0) || (g>255)) ||
|
|
((b<0) || (b>255))) {
|
|
QMessageBox::warning(0, "WARNING", QString("Found Color (%1,%2,%3) not in the expected range.\nWill ignore it.").arg(r).arg(g).arg(b));
|
|
return;
|
|
}
|
|
|
|
PmuppColor color;
|
|
color.setName(name);
|
|
color.setRGB(r,g,b);
|
|
|
|
fColor.push_back(color);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* @brief Saves the recent files list to the configuration file.
|
|
*
|
|
* Updates the mupp_startup.xml file with the current recent file list.
|
|
* The method first searches for a local configuration file in the current
|
|
* directory; if not found, it uses the user's home directory version
|
|
* ($HOME/.musrfit/mupp/mupp_startup.xml).
|
|
*
|
|
* The implementation:
|
|
* 1. Reads the entire configuration file into memory
|
|
* 2. Removes all existing \<path_file_name\> entries
|
|
* 3. Inserts current recent files list
|
|
* 4. Writes the updated configuration back to disk
|
|
*
|
|
* This preserves all other configuration settings while updating only
|
|
* the recent file history.
|
|
*/
|
|
void PmuppAdmin::saveRecentFiles()
|
|
{
|
|
// check if mupp_startup.xml is present in the current directory, and if yes, use this file to
|
|
// save the recent file names otherwise use the "master" mupp_startup.xml
|
|
|
|
QString str("");
|
|
QString fln = QString("./mupp_startup.xml");
|
|
if (!QFile::exists(fln)) {
|
|
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
|
|
fln = QString("%1/.musrfit/mupp/mupp_startup.xml").arg(env.value("HOME"));
|
|
}
|
|
|
|
if (QFile::exists(fln)) { // administration file present
|
|
QVector<QString> data;
|
|
QFile file(fln);
|
|
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
|
std::cerr << std::endl << ">> PmuppAdmin::saveRecentFile: **ERROR** Cannot open " << fln.toLatin1().data() << " for reading." << std::endl;
|
|
return;
|
|
}
|
|
QTextStream fin(&file);
|
|
while (!fin.atEnd()) {
|
|
data.push_back(fin.readLine());
|
|
}
|
|
file.close();
|
|
|
|
// remove <path_file_name> from data
|
|
for (QVector<QString>::iterator it = data.begin(); it != data.end(); ++it) {
|
|
if (it->contains("<path_file_name>")) {
|
|
it = data.erase(it);
|
|
--it;
|
|
}
|
|
}
|
|
|
|
// add recent files
|
|
int i;
|
|
for (i=0; i<data.size(); i++) {
|
|
if (data[i].contains("<recent_files>"))
|
|
break;
|
|
}
|
|
|
|
if (i == data.size()) {
|
|
std::cerr << std::endl << ">> PmuppAdmin::saveRecentFile: **ERROR** " << fln.toLatin1().data() << " seems to be corrupt." << std::endl;
|
|
return;
|
|
}
|
|
i++;
|
|
for (int j=0; j<fRecentFile.size(); j++) {
|
|
str = " <path_file_name>" + fRecentFile[j] + "</path_file_name>";
|
|
data.insert(i++, str);
|
|
}
|
|
|
|
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
|
std::cerr << std::endl << ">> PmuppAdmin::saveRecentFile: **ERROR** Cannot open " << fln.toLatin1().data() << " for reading." << std::endl;
|
|
return;
|
|
}
|
|
fin.setDevice(&file);
|
|
for (int i=0; i<data.size(); i++) {
|
|
fin << data[i] << Qt::endl;
|
|
}
|
|
file.close();
|
|
} else {
|
|
QString msg("Failed to write mupp_startup.xml. Neither a local nor a global copy found.");
|
|
QMessageBox::warning(0, "WARNING", msg, QMessageBox::Ok, QMessageBox::NoButton);
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
/**
|
|
* @brief Creates a default mupp_startup.xml configuration file.
|
|
*
|
|
* This method is called when no configuration file is found in any of
|
|
* the standard locations. It creates a new default configuration file
|
|
* in the user's home directory ($HOME/.musrfit/mupp/mupp_startup.xml).
|
|
*
|
|
* The implementation:
|
|
* 1. Creates the directory $HOME/.musrfit/mupp if it doesn't exist
|
|
* 2. Loads the default template from embedded resources (mupp_startup.xml.in)
|
|
* 3. Writes the template to the user's home directory
|
|
*
|
|
* The default configuration includes standard marker styles, color
|
|
* definitions, and empty recent file list, providing a working baseline
|
|
* for new users or clean installations.
|
|
*/
|
|
void PmuppAdmin::createMuppStartupFile()
|
|
{
|
|
// get $HOME
|
|
QProcessEnvironment procEnv = QProcessEnvironment::systemEnvironment();
|
|
QString pathName = procEnv.value("HOME", "");
|
|
pathName += "/.musrfit/mupp";
|
|
|
|
// check if the directory $HOME/.musrfit/mupp exists if not create it
|
|
QDir dir(pathName);
|
|
if (!dir.exists()) {
|
|
// directory $HOME/.musrfit/mupp does not exist hence create it
|
|
dir.mkpath(pathName);
|
|
}
|
|
|
|
// create default mupp_startup.xml file in $HOME/.musrfit/mupp
|
|
pathName += "/mupp_startup.xml";
|
|
|
|
// get the default mupp_startup.xml.in from the internal resources
|
|
QFile fres(":/mupp_startup.xml.in");
|
|
if (!fres.exists()) {
|
|
QString msg = QString("Neither couldn't find nor create mupp_startup.xml. Things are likely not to work.");
|
|
QMessageBox::critical(0, "ERROR", msg);
|
|
return;
|
|
}
|
|
|
|
if (!fres.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
|
QString msg = QString("Couldn't open internal resource file mupp_startup.xml.in. Things are likely not to work.");
|
|
QMessageBox::critical(0, "ERROR", msg);
|
|
return;
|
|
}
|
|
// text stream for fres
|
|
QTextStream fin(&fres);
|
|
|
|
// mupp_startup.xml default file
|
|
QFile file(pathName);
|
|
|
|
if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
|
|
return;
|
|
|
|
// text stream for file
|
|
QTextStream fout(&file);
|
|
|
|
QString line;
|
|
while (!fin.atEnd()) {
|
|
line = fin.readLine();
|
|
fout << line << Qt::endl;
|
|
}
|
|
|
|
file.close();
|
|
fres.close();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// END
|
|
//--------------------------------------------------------------------------
|