Files
GoldenCheetah/src/FileIO/FixPySettings.cpp
Joachim Kohlhammer 000a76983d "Automated only"-flagging for DataProcessors
* Options > Data Fields > Processors & Automation (renamed from
  "Processing")
  * Modernized the UI
  * Added UI to set Automation (None, On Import, On Save) for all
    processors
  * Added UI to set Automated execution only for all processors
  * Showing the processors description
  * Showing the processors setting (if available) in a more userfriendly
    way
  * Added option to add / delete / edit custom Python processors
  * Enabled editing of Python processors via double click
  * Added option to hide code processors
* Removed the submenu to manage Python Fixes from the Edit-menu
* Renamed the Edit-menu to "Process"
* Hiding "automated only"-processors from Process-menu and
  Batchprocessing-dialog
* DataProcessors
  * Turned configuration of all core processors into forms
  * Changed the technical name of all core processors to match their
    classname
  * Added legacy technical name to all core processors to support existing
    scripts
  * Moved description from config-class to DataProcessor
  * Implemented a migration path for existing persisted processor
    configurations
* GSettings
  * Added method to remove settings by key
2024-11-26 20:04:33 -03:00

246 lines
6.9 KiB
C++

#include <QDir>
#include <QFile>
#include <QTextStream>
#include <QSettings>
#include "FixPySettings.h"
#include "Settings.h"
#include "MainWindow.h"
#include "FixPyDataProcessor.h"
FixPySettings::FixPySettings()
: isInitialied(false), scripts()
{
}
FixPySettings::~FixPySettings()
{
qDeleteAll(scripts);
}
QList<FixPyScript *> FixPySettings::getScripts()
{
if (!isInitialied) {
initialize();
}
return scripts;
}
FixPyScript *FixPySettings::getScript(QString name)
{
foreach (FixPyScript *s, getScripts()) {
if (s->name == name) {
return s;
}
}
return nullptr;
}
FixPyScript *FixPySettings::createScript(QString name)
{
FixPyScript *script = new FixPyScript;
script->name = name;
FixPyDataProcessor *fixPyDp = new FixPyDataProcessor(script);
DataProcessorFactory::instance().registerProcessor(fixPyDp);
scripts.append(script);
return script;
}
void FixPySettings::deleteScript(QString name)
{
DataProcessorFactory::instance().unregisterProcessor(name);
QList<FixPyScript *> scripts = getScripts();
for (int i = 0; i < scripts.size(); i++) {
FixPyScript *script = scripts[i];
if (script->name == name) {
this->scripts.removeAt(i);
QSettings iniSettings(gcroot + "/" + PYFIXES_DIR_NAME + "/" + PYFIXES_SETTINGS_FILE_NAME, QSettings::IniFormat);
iniSettings.remove(script->iniKey);
iniSettings.sync();
QFile pyFile(gcroot + "/" + PYFIXES_DIR_NAME + "/" + script->path);
pyFile.remove();
appsettings->remove(DataProcessor::configKeyAutomation(name));
appsettings->remove(DataProcessor::configKeyAutomatedOnly(name));
delete script;
return;
}
}
}
void FixPySettings::save()
{
QSettings iniSettings(gcroot + "/" + PYFIXES_DIR_NAME + "/" + PYFIXES_SETTINGS_FILE_NAME, QSettings::IniFormat);
// delete old py files first and move automation keys to new name
foreach (FixPyScript *script, getScripts()) {
if (!script->oldPath.isEmpty()) {
QFile oldPyFixFile(gcroot + "/" + PYFIXES_DIR_NAME + "/" + script->oldPath);
oldPyFixFile.remove();
script->oldPath = QString();
}
if (! script->oldName.isEmpty()) {
DataProcessorFactory::instance().unregisterProcessor(script->oldName);
QVariant automation = appsettings->value(nullptr, DataProcessor::configKeyAutomation(script->oldName), QVariant());
QVariant automatedOnly = appsettings->value(nullptr, DataProcessor::configKeyAutomatedOnly(script->oldName), QVariant());
if (automation.isValid()) {
appsettings->remove(DataProcessor::configKeyAutomation(script->oldName));
appsettings->setValue(DataProcessor::configKeyAutomation(script->name), automation);
}
if (automatedOnly.isValid()) {
appsettings->remove(DataProcessor::configKeyAutomatedOnly(script->oldName));
appsettings->setValue(DataProcessor::configKeyAutomatedOnly(script->name), automatedOnly);
}
FixPyDataProcessor *fixPyDp = new FixPyDataProcessor(script);
DataProcessorFactory::instance().registerProcessor(fixPyDp);
script->oldName = QString();
}
}
int key = getMaxKey();
foreach (FixPyScript *script, getScripts()) {
if (script->iniKey.isEmpty()) {
script->iniKey = QString("f%1").arg(++key);
script->changed = true;
}
if (script->changed) {
iniSettings.setValue(script->iniKey + "/name", script->name);
iniSettings.setValue(script->iniKey + "/path", script->path);
QFile pyFile(gcroot + "/" + PYFIXES_DIR_NAME + "/" + script->path);
if (!pyFile.open(QIODevice::WriteOnly | QIODevice::Text)){
continue;
}
QTextStream out(&pyFile);
out << script->source;
script->changed = false;
}
}
iniSettings.sync();
}
void FixPySettings::initialize()
{
if (isInitialied || !appsettings->value(nullptr, GC_EMBED_PYTHON, true).toBool()) {
return;
}
isInitialied = true;
QDir gcPath(gcroot);
if (!gcPath.exists(PYFIXES_DIR_NAME)) {
gcPath.mkpath(PYFIXES_DIR_NAME);
}
QSettings iniSettings(gcroot + "/" + PYFIXES_DIR_NAME + "/" + PYFIXES_SETTINGS_FILE_NAME, QSettings::IniFormat);
iniSettings.sync();
QDir pyfixesDir(gcroot + "/" + PYFIXES_DIR_NAME);
QStringList pyFilters;
pyFilters << "*.py";
QStringList pyFixFiles = pyfixesDir.entryList(pyFilters, QDir::Files);
foreach (QString group, iniSettings.childGroups()) {
QString fixName = iniSettings.value(group + "/name").toString();
QString fixPath = iniSettings.value(group + "/path").toString();
if (fixName.isNull() || fixName.isEmpty()) {
fixName = fixPath;
}
int pyFixFileIdx = pyFixFiles.indexOf(fixPath);
if (pyFixFileIdx == -1) {
continue;
}
if (!readPyFixFile(fixName, fixPath, group)) {
pyFixFiles.removeAt(pyFixFileIdx);
continue;
}
pyFixFiles.removeAt(pyFixFileIdx);
}
// read remaining files not listed in ini
foreach (QString pyFixFile, pyFixFiles) {
QString fixName(pyFixFile);
fixName.chop(3);
// find unique name
for (int i = 0; i < scripts.size(); i++) {
if (scripts[i]->name == fixName) {
fixName = "_" + fixName;
i = 0;
}
}
readPyFixFile(fixName, pyFixFile, QString());
}
save();
}
void FixPySettings::disableFixPy()
{
if (!isInitialied) return;
isInitialied = false;
foreach (FixPyScript *s, scripts) {
DataProcessorFactory::instance().unregisterProcessor(s->name);
}
qDeleteAll(scripts);
scripts.clear();
}
bool FixPySettings::readPyFixFile(QString fixName, QString fixPath, QString iniKey)
{
QFile pyFile(gcroot + "/" + PYFIXES_DIR_NAME + "/" + fixPath);
if (!pyFile.open(QIODevice::ReadOnly | QIODevice::Text)){
return false;
}
QTextStream in(&pyFile);
QString fixSource = in.readAll();
FixPyScript *script = createScript(fixName);
script->path = fixPath;
script->source = fixSource;
script->iniKey = iniKey;
return true;
}
int FixPySettings::getMaxKey()
{
int maxKey = -1;
foreach (FixPyScript *fixScript, getScripts()) {
QString iniKey = fixScript->iniKey;
if (iniKey.length() < 2) {
continue;
}
QString keyStr = iniKey.remove(0, 1);
bool ok;
int keyNo = keyStr.toInt(&ok);
if (!ok) {
continue;
}
if (keyNo > maxKey) {
maxKey = keyNo;
}
}
return maxKey;
}
FixPySettings *fixPySettings = new FixPySettings;