[education/rkward] /: Group pluginmaps by id (unfinished)
Thomas Friedrichsmeier
null at kde.org
Mon May 9 17:11:10 BST 2022
Git commit a51969460065275312e3ad801fe1186a8e498236 by Thomas Friedrichsmeier.
Committed on 07/05/2022 at 22:04.
Pushed by tfry into branch 'master'.
Group pluginmaps by id (unfinished)
M +2 -0 ChangeLog
M +1 -1 rkward/dialogs/rkloadlibsdialog.cpp
M +1 -1 rkward/dialogs/rksetupwizard.cpp
M +1 -1 rkward/misc/rkparsedversion.cpp
M +1 -1 rkward/rbackend/rkrinterface.cpp
M +3 -3 rkward/rkward.cpp
M +156 -146 rkward/settings/rksettingsmoduleplugins.cpp
M +28 -21 rkward/settings/rksettingsmoduleplugins.h
https://invent.kde.org/education/rkward/commit/a51969460065275312e3ad801fe1186a8e498236
diff --git a/ChangeLog b/ChangeLog
index 91a9f838..12f3edba 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,8 +1,10 @@
TODOs:
- More tolerant handshake on Windows? Simply a matter of allowing more time?
- Fix RKWard-app icon on Windows
+ - If stored config is older than 0.6.3, discard it, entirely
- Added functionality to install add-on packages directly from git (formerly available as external plugin rk.gitInstall)
+ - TODO: add a plugintest
- Fixed: Disabling a <row> element in plugins would not make the sub-elements non-required
- Add option to show ANOVA table for linear regression
- Add default preview() function is available to plugins, reducing the code needed to add preview functionality
diff --git a/rkward/dialogs/rkloadlibsdialog.cpp b/rkward/dialogs/rkloadlibsdialog.cpp
index acad7d97..3030fdd2 100644
--- a/rkward/dialogs/rkloadlibsdialog.cpp
+++ b/rkward/dialogs/rkloadlibsdialog.cpp
@@ -1220,7 +1220,7 @@ void RKPluginMapSelectionWidget::apply () {
if (!isChanged()) return;
RK_ASSERT (model);
- RKSettingsModulePlugins::PluginMapList new_list = RKSettingsModulePlugins::setPluginMaps (model->pluginMaps ());
+ auto new_list = RKSettingsModulePlugins::setPluginMaps(model->pluginMaps());
selector->setModel (0); // we don't want any extra change notification for this
model->init (new_list);
selector->setModel (model, 1);
diff --git a/rkward/dialogs/rksetupwizard.cpp b/rkward/dialogs/rksetupwizard.cpp
index 29f68277..141e0575 100644
--- a/rkward/dialogs/rksetupwizard.cpp
+++ b/rkward/dialogs/rksetupwizard.cpp
@@ -153,7 +153,7 @@ RKSetupWizard::RKSetupWizard(QWidget* parent, InvokationReason reason, const QLi
if (RKSettingsModulePlugins::pluginMaps().isEmpty()) {
pluginmaps->setLongLabel(i18n("<p>No plugins are enabled. This is probably not intended.</p>"));
pluginmaps->setStatus(RKSetupWizardItem::Warning, i18n("None selected"));
- pluginmaps->addOption(i18n("Restore defaults"), i18n("Enable the default plugins"), [](RKSetupWizard*) { RKSettingsModulePlugins::registerDefaultPluginMaps(RKSettingsModulePlugins::AddIfDefault); });
+ pluginmaps->addOption(i18n("Restore defaults"), i18n("Enable the default plugins"), [](RKSetupWizard*) { RKSettingsModulePlugins::registerDefaultPluginMaps(RKSettingsModulePlugins::AutoActivate); });
pluginmaps->addOption(i18n("No change"), i18n("Proceed without plugins"), [](RKSetupWizard*) {});
// TODO: Also offer help, if a suspiciously small share of plugins is active? RKSettingsModulePlugins::knownUsablePluginCount();
diff --git a/rkward/misc/rkparsedversion.cpp b/rkward/misc/rkparsedversion.cpp
index 88c34709..f4362ed0 100644
--- a/rkward/misc/rkparsedversion.cpp
+++ b/rkward/misc/rkparsedversion.cpp
@@ -48,6 +48,6 @@ QString RKParsedVersion::toString() const {
if (i > 0) ret.append('.');
}
if (ret.endsWith(QLatin1String(".0"))) ret.chop(2); // HACK: Don't print more than three version parts, unless the fourth is non-zero
- if (!version_suffix.isNull()) ret.append('.' + version_suffix);
+ ret.append(version_suffix);
return ret;
}
diff --git a/rkward/rbackend/rkrinterface.cpp b/rkward/rbackend/rkrinterface.cpp
index 95d6eb29..322071de 100644
--- a/rkward/rbackend/rkrinterface.cpp
+++ b/rkward/rbackend/rkrinterface.cpp
@@ -589,7 +589,7 @@ GenericRRequestResult RInterface::processPlainGenericRequest(const QStringList &
} else if (call == "loadPluginMaps") {
bool force = (calllist.value (1) == "force");
bool reload = (calllist.value (2) == "reload");
- RKSettingsModulePlugins::registerPluginMaps (calllist.mid (3), force ? RKSettingsModulePlugins::ManualAddition : RKSettingsModulePlugins::AddIfNewAndDefault, reload);
+ RKSettingsModulePlugins::registerPluginMaps (calllist.mid (3), force ? RKSettingsModulePlugins::ForceActivate : RKSettingsModulePlugins::AutoActivateIfNew, reload);
} else if (call == "updateInstalledPackagesList") {
RKSessionVars::instance ()->setInstalledPackages (calllist.mid (1));
} else if (call == "showHTML") {
diff --git a/rkward/rkward.cpp b/rkward/rkward.cpp
index c31264e8..4141c057 100644
--- a/rkward/rkward.cpp
+++ b/rkward/rkward.cpp
@@ -324,16 +324,16 @@ void RKWardMainWindow::initPlugins (const QStringList &automatically_added) {
const QString &map = all_maps[i];
RKPluginMapParseResult result = RKComponentMap::getMap ()->addPluginMap (map);
if (!result.valid_plugins) {
- RKSettingsModulePlugins::markPluginMapAsBroken (map);
+ RKSettingsModulePlugins::markPluginMapState(map, RKSettingsModulePlugins::Broken);
completely_broken_maps.append (map);
completely_broken_maps_details.append (result.detailed_problems);
} else if (!result.detailed_problems.isEmpty ()) {
- if (RKSettingsModulePlugins::markPluginMapAsQuirky (map)) {
+ if (RKSettingsModulePlugins::markPluginMapState(map, RKSettingsModulePlugins::Quirky)) {
somewhat_broken_maps.append (map);
somewhat_broken_maps_details.append (result.detailed_problems);
}
} else {
- RKSettingsModulePlugins::markPluginMapAsWorking (map);
+ RKSettingsModulePlugins::markPluginMapState(map, RKSettingsModulePlugins::Working);
}
}
diff --git a/rkward/settings/rksettingsmoduleplugins.cpp b/rkward/settings/rksettingsmoduleplugins.cpp
index 7d1d036b..2f571b91 100644
--- a/rkward/settings/rksettingsmoduleplugins.cpp
+++ b/rkward/settings/rksettingsmoduleplugins.cpp
@@ -35,7 +35,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
#include "../debug.h"
// static members
-QList<RKSettingsModulePlugins::PluginMapStoredInfo> RKSettingsModulePlugins::known_plugin_maps;
+RKSettingsModulePlugins::UniquePluginMapList RKSettingsModulePlugins::known_plugin_maps;
RKConfigValue<RKSettingsModulePlugins::PluginPrefs, int> RKSettingsModulePlugins::interface_pref {"Interface Preferences", RKSettingsModulePlugins::PreferRecommended};
RKConfigValue<bool> RKSettingsModulePlugins::show_code {"Code display default", false};
RKConfigValue<int> RKSettingsModulePlugins::code_size {"Code display size", 250};
@@ -104,7 +104,7 @@ void RKSettingsModulePlugins::applyChanges () {
interface_pref = static_cast<PluginPrefs> (button_group->checkedId ());
}
-RKSettingsModulePlugins::PluginMapList RKSettingsModulePlugins::setPluginMaps (const RKSettingsModulePlugins::PluginMapList &new_list) {
+RKSettingsModulePlugins::UniquePluginMapList RKSettingsModulePlugins::setPluginMaps(const UniquePluginMapList &new_list) {
RK_TRACE (SETTINGS);
known_plugin_maps = new_list;
@@ -119,22 +119,25 @@ void RKSettingsModulePlugins::configurePluginmaps () {
RKLoadLibsDialog::showPluginmapConfig (this, commandChain ());
}
-void savePluginMaps(KConfigGroup &cg, const RKSettingsModulePlugins::PluginMapList &known_plugin_maps) {
+void savePluginMaps(KConfigGroup &cg, const RKSettingsModulePlugins::UniquePluginMapList &known_plugin_maps) {
RK_TRACE(SETTINGS);
cg.deleteGroup("Known Plugin maps"); // always start from scratch to remove cruft from pluginmaps
KConfigGroup pmg = cg.group("Known Plugin maps");
QStringList all_known_maps;
- for (int i = 0; i < known_plugin_maps.size (); ++i) {
- const RKSettingsModulePlugins::PluginMapStoredInfo &inf = known_plugin_maps[i];
- KConfigGroup ppmg = pmg.group (inf.filename);
- ppmg.writeEntry("Active", inf.active);
- ppmg.writeEntry("Broken", inf.broken_in_this_version);
- ppmg.writeEntry("Quirky", inf.quirky_in_this_version);
- ppmg.writeEntry("timestamp", inf.last_modified);
- ppmg.writeEntry("id", inf.id);
- ppmg.writeEntry("priority", inf.priority);
- all_known_maps.append(inf.filename);
+ for (int i = 0; i < known_plugin_maps.size(); ++i) {
+ auto &variants = known_plugin_maps[i].maps;
+ for (int j = 0; j < variants.size(); ++j) {
+ const RKSettingsModulePlugins::PluginMapStoredInfo &inf = variants[j];
+ KConfigGroup ppmg = pmg.group (inf.filename);
+ ppmg.writeEntry("Active", known_plugin_maps[i].active);
+ ppmg.writeEntry("State", (int) inf.state);
+ ppmg.writeEntry("timestamp", inf.last_modified);
+ ppmg.writeEntry("id", inf.id);
+ ppmg.writeEntry("version", inf.version.toString());
+ ppmg.writeEntry("priority", inf.priority);
+ all_known_maps.append(inf.filename);
+ }
}
// NOTE: The group list is always sorted alphabetically, which is why we need a separate list setting for saving info on order.
cg.writeEntry("All known plugin maps", all_known_maps);
@@ -152,43 +155,74 @@ void RKSettingsModulePlugins::syncConfig(KConfig *config, RKConfigBase::ConfigSy
if (a == RKConfigBase::SaveConfig) {
savePluginMaps(cg, known_plugin_maps);
} else {
- if (RKSettingsModuleGeneral::storedConfigVersion () < RKSettingsModuleGeneral::RKWardConfig_0_6_1) {
- QStringList plugin_maps = cg.readEntry ("Plugin Maps", QStringList ());
- QStringList kplugin_maps = cg.readEntry ("All known plugin maps", QStringList ());
- for (int i = 0; i < kplugin_maps.size (); ++i) {
- PluginMapStoredInfo inf (RKSettingsModuleGeneral::checkAdjustLoadedPath (kplugin_maps[i]));
- inf.active = plugin_maps.contains (kplugin_maps[i]); // comparing unadjusted path on purpose!
- // state info will be properly initialized in fixPluginMapLists()
- known_plugin_maps.append (inf);
- }
- } else {
- KConfigGroup pmg = cg.group ("Known Plugin maps");
- QStringList kplugin_maps = cg.readEntry ("All known plugin maps", QStringList ());
- for (int i = 0; i < kplugin_maps.size (); ++i) {
- KConfigGroup ppmg = pmg.group (kplugin_maps[i]); // unadjusted path on purpose!
- PluginMapStoredInfo inf (RKSettingsModuleGeneral::checkAdjustLoadedPath (kplugin_maps[i]));
- inf.active = ppmg.readEntry ("Active", false);
- // Pluginmaps which are broken with one version of RKWard may be alright with other versions. So reset flags, if version has changed.
- inf.broken_in_this_version = ppmg.readEntry ("Broken", false) && !RKSettingsModuleGeneral::rkwardVersionChanged ();
- inf.quirky_in_this_version = ppmg.readEntry ("Quirky", false) && !RKSettingsModuleGeneral::rkwardVersionChanged ();
- inf.last_modified = ppmg.readEntry ("timestamp", QDateTime ());
- inf.id = ppmg.readEntry ("id");
- inf.priority = ppmg.readEntry ("priority", (int) PriorityMedium);
- known_plugin_maps.append (inf);
- }
+ /* Known maps are stored at runtime as a nested list id -> variants, but stored in config as a plain list of variants. This is for historic reasons, but may be too much trouble to change. */
+ KConfigGroup pmg = cg.group ("Known Plugin maps");
+ QStringList kplugin_maps = cg.readEntry ("All known plugin maps", QStringList ());
+ for (int i = 0; i < kplugin_maps.size (); ++i) {
+ KConfigGroup ppmg = pmg.group (kplugin_maps[i]); // unadjusted path on purpose!
+ PluginMapStoredInfo inf (RKSettingsModuleGeneral::checkAdjustLoadedPath (kplugin_maps[i]));
+ // Pluginmaps which are broken with one version of RKWard may be alright with other versions. So reset flags, if version has changed.
+ if (RKSettingsModuleGeneral::rkwardVersionChanged()) inf.state = Working;
+ else inf.state = (PluginMapState) ppmg.readEntry("State", (int) Working);
+ inf.last_modified = ppmg.readEntry ("timestamp", QDateTime ());
+ inf.id = ppmg.readEntry ("id");
+ inf.version = ppmg.readEntry ("version");
+ inf.priority = ppmg.readEntry ("priority", (int) PriorityMedium);
+ addPluginMapToList(inf, ppmg.readEntry("Active", false));
}
if (RKSettingsModuleGeneral::rkwardVersionChanged () || RKSettingsModuleGeneral::installationMoved ()) {
// if it is the first start this version or from a new path, scan the installation for new pluginmaps
// Note that in the case of installationMoved(), checkAdjustLoadedPath() has already kicked in, above, but rescanning is still useful
// e.g. if users have installed to a new location, because they had botched their previous installation
- registerDefaultPluginMaps(AddIfNewAndDefault);
+ registerDefaultPluginMaps(AutoActivateIfNew);
}
fixPluginMapLists (); // removes any maps which don't exist any more
+ }
+}
- if (RKSettingsModuleGeneral::storedConfigVersion () <= RKSettingsModuleGeneral::RKWardConfig_Pre0_5_7) {
- if (code_size == 40) code_size = 250; // previous default untouched.
+bool RKSettingsModulePlugins::addPluginMapToList(const RKSettingsModulePlugins::PluginMapStoredInfo& inf, bool active) {
+ RK_TRACE (SETTINGS);
+ QString id = inf.id;
+ QString filename = inf.filename;
+ for (int i = 0; i < known_plugin_maps.size(); ++i) {
+ UniquePluginMap &unique = known_plugin_maps[i];
+ if (id == unique.id) {
+ PluginMapList &variants = unique.maps;
+ for (int j = 0; j < variants.size(); ++j) {
+ if (variants[j].filename == filename) {
+ variants[j] = inf;
+ return false;
+ }
+ }
+ variants.append(inf);
+ unique.active = unique.active || active;
+ return true;
}
}
+ UniquePluginMap new_entry(id, active);
+ new_entry.maps.append(inf);
+ known_plugin_maps.append(new_entry);
+ return true;
+}
+
+RKSettingsModulePlugins::PluginMapStoredInfo RKSettingsModulePlugins::UniquePluginMap::bestMap() const {
+ RK_TRACE(SETTINGS);
+ RK_ASSERT(!maps.isEmpty());
+
+ PluginMapStoredInfo candidate = maps.first();
+ for (int i = 1; i < maps.size(); ++i) {
+ const PluginMapStoredInfo &other = maps[i];
+ bool other_is_better = true;
+ if (candidate.version > other.version) {
+ other_is_better = false;
+ } else if (candidate.version == other.version && candidate.last_modified > other.last_modified) {
+ other_is_better = false;
+ }
+ if (!other_is_better) {
+ candidate = other;
+ }
+ }
+ return candidate;
}
void RKSettingsModulePlugins::registerDefaultPluginMaps(AddMode add_mode) {
@@ -203,7 +237,7 @@ void RKSettingsModulePlugins::registerDefaultPluginMaps(AddMode add_mode) {
for (int i = 0; i < def_pluginmaps.size (); ++i) {
def_pluginmaps[i] = def_plugindir.absoluteFilePath (def_pluginmaps[i]);
}
- registerPluginMaps (def_pluginmaps, add_mode, false, add_mode == AddIfNewAndDefault);
+ registerPluginMaps (def_pluginmaps, add_mode, false, add_mode == AutoActivateIfNew);
}
int findKnownPluginMap (const QString& filename, const RKSettingsModulePlugins::PluginMapList& haystack) {
@@ -220,7 +254,7 @@ QString RKSettingsModulePlugins::findPluginMapById (const QString &id) {
RK_TRACE (SETTINGS);
for (int i = 0; i < known_plugin_maps.size (); ++i) {
- if (known_plugin_maps[i].id == id) return known_plugin_maps[i].filename;
+ if (known_plugin_maps[i].id == id) return known_plugin_maps[i].bestMap().filename;
}
// for "rkward::" namespace, try a little harded:
if (id.startsWith (QLatin1String ("rkward::"))) {
@@ -231,43 +265,22 @@ QString RKSettingsModulePlugins::findPluginMapById (const QString &id) {
return QString ();
}
-bool RKSettingsModulePlugins::markPluginMapAsBroken (const QString& map) {
+bool RKSettingsModulePlugins::markPluginMapState(const QString& map, PluginMapState state) {
RK_TRACE (SETTINGS);
- int index = findKnownPluginMap (map, known_plugin_maps);
- if (index < 0) {
- RK_ASSERT (index >= 0);
- return false;
- }
- bool ret = !known_plugin_maps[index].broken_in_this_version;
- known_plugin_maps[index].broken_in_this_version = true;
- known_plugin_maps[index].active = false;
- return ret;
-}
-
-bool RKSettingsModulePlugins::markPluginMapAsQuirky (const QString& map) {
- RK_TRACE (SETTINGS);
-
- int index = findKnownPluginMap (map, known_plugin_maps);
- if (index < 0) {
- RK_ASSERT (index >= 0);
- return false;
- }
- bool ret = !known_plugin_maps[index].quirky_in_this_version;
- known_plugin_maps[index].quirky_in_this_version = true;
- return ret;
-}
-
-void RKSettingsModulePlugins::markPluginMapAsWorking (const QString& map) {
- RK_TRACE (SETTINGS);
-
- int index = findKnownPluginMap (map, known_plugin_maps);
- if (index < 0) {
- RK_ASSERT (index >= 0);
- return;
+ for (int i = 0; i < known_plugin_maps.size(); ++i) {
+ auto &variants = known_plugin_maps[i].maps;
+ for (int j = 0; j < variants.size(); ++j) {
+ if (variants[j].filename == map) {
+ bool ret = variants[j].state != state;
+ variants[j].state = state;
+ if (state == Broken) known_plugin_maps[i].active = false;
+ return ret;
+ }
+ }
}
- known_plugin_maps[index].quirky_in_this_version = false;
- known_plugin_maps[index].broken_in_this_version = false;
+ RK_ASSERT(false);
+ return false;
}
QStringList RKSettingsModulePlugins::pluginMaps () {
@@ -275,22 +288,11 @@ QStringList RKSettingsModulePlugins::pluginMaps () {
QStringList ret;
for (int i = 0; i < known_plugin_maps.size (); ++i) {
- if (known_plugin_maps[i].active) ret.append (known_plugin_maps[i].filename);
+ if (known_plugin_maps[i].active) ret.append (known_plugin_maps[i].bestMap().filename);
}
return ret;
}
-// static
-int RKSettingsModulePlugins::uniqueUsablePluginMapCount() {
- RK_TRACE (SETTINGS);
- QSet<QString> ids;
- for (int i = 0; i < known_plugin_maps.size (); ++i) {
- if (known_plugin_maps[i].broken_in_this_version) return false;
- ids.insert(known_plugin_maps[i].id);
- }
- return ids.size();
-}
-
// static
void RKSettingsModulePlugins::registerPluginMaps (const QStringList &maps, AddMode add_mode, bool force_reload, bool suppress_reload) {
RK_TRACE (SETTINGS);
@@ -298,71 +300,78 @@ void RKSettingsModulePlugins::registerPluginMaps (const QStringList &maps, AddMo
QStringList added;
foreach (const QString &map, maps) {
if (map.isEmpty ()) continue;
- int index = findKnownPluginMap (map, known_plugin_maps);
- if (index >= 0) {
- if (known_plugin_maps[index].active) continue;
- if (add_mode == AddIfNewAndDefault) continue;
- } else { // not found
- PluginMapStoredInfo inf (map);
- known_plugin_maps.append (inf);
- index = known_plugin_maps.size () - 1;
+ bool found = false;
+ for (int i = 0; i < known_plugin_maps.size(); ++i) {
+ const PluginMapList &variants = known_plugin_maps[i].maps;
+ for (int j = 0; j < variants.size(); ++j) {
+ const auto &inf = variants[j];
+ if (inf.filename == map) {
+ found = true;
+ if (!known_plugin_maps[i].active) {
+ if (add_mode == ForceActivate || (add_mode == AutoActivate && inf.priority >= PriorityMedium)) {
+ known_plugin_maps[i].active = true;
+ added.append(map);
+ }
+ }
+ break;
+ }
+ }
+ if (found) break;
}
- added.append (map);
- }
- fixPluginMapLists ();
- // activate added (or forced) pluginmaps, *after* the list has been fixed (and info on priority has been read)
- for (int i = 0; i < known_plugin_maps.size (); ++i) {
- PluginMapStoredInfo &inf = known_plugin_maps[i];
- int index = added.indexOf (inf.filename);
- if (index >= 0) {
- if ((add_mode == ManualAddition) || (inf.priority >= PriorityMedium)) inf.active = true;
- else (added.removeAt (index));
+ if (!found) {
+ PluginMapStoredInfo inf = parsePluginMapBasics(map);
+ bool activate = (add_mode == ForceActivate) || (inf.priority >= PriorityMedium);
+ addPluginMapToList(map, activate);
+ if (activate) added.append(map);
}
}
if (suppress_reload) return;
if (force_reload || (!added.isEmpty ())) {
- RKWardMainWindow::getMain ()->initPlugins (added);
+ RKWardMainWindow::getMain ()->initPlugins(added);
}
}
void RKSettingsModulePlugins::fixPluginMapLists () {
- RK_TRACE (SETTINGS);
+ RK_TRACE(SETTINGS);
- // Users who installed versions before 0.6.3, manually, are likely to have all.pluginmap left over. Let's handle this, on the fly.
- const QString obsolete_map = RKCommonFunctions::getRKWardDataDir () + "all.pluginmap";
- for (int i = 0; i < known_plugin_maps.size (); ++i) {
- PluginMapStoredInfo &inf = known_plugin_maps[i];
- QFileInfo info (inf.filename);
- if ((!info.isReadable ()) || (inf.filename == obsolete_map)) {
- known_plugin_maps.removeAt (i);
- --i;
- continue;
- }
+ for (int i = 0; i < known_plugin_maps.size(); ++i) {
+ PluginMapList &variants = known_plugin_maps[i].maps;
+ for (int j = 0; j < variants.size(); ++j) {
+ PluginMapStoredInfo &inf = variants[j];
+ QFileInfo info(inf.filename);
+ if (!info.isReadable()) {
+ variants.removeAt(j);
+ --j;
+ continue;
+ }
- if (info.lastModified () != inf.last_modified) {
- inf.broken_in_this_version = false;
- inf.quirky_in_this_version = false;
- inf.last_modified = info.lastModified ();
- inf.id.clear ();
+ if (info.lastModified () != inf.last_modified || inf.version.isNull()) {
+ inf = parsePluginMapBasics(inf.filename);
+ inf.last_modified = info.lastModified();
+ // TOOD: Handle the case that it might have changed id? Should be remedied on the next config load, anyway, however.
+ }
}
-
- if (inf.id.isEmpty ()) {
- parsePluginMapBasics (inf.filename, &inf.id, &inf.priority);
+ if (variants.isEmpty()) {
+ known_plugin_maps.removeAt(i);
+ --i;
+ continue;
}
}
}
-void RKSettingsModulePlugins::parsePluginMapBasics (const QString &filename, QString *id, int *priority) {
- RK_TRACE (SETTINGS);
- RK_ASSERT (id);
- RK_ASSERT (priority);
+RKSettingsModulePlugins::PluginMapStoredInfo RKSettingsModulePlugins::parsePluginMapBasics(const QString &filename) {
+ RK_TRACE(SETTINGS);
- XMLHelper xml (filename);
- QDomElement de = xml.openXMLFile (DL_WARNING);
- *id = RKPluginMapFile::parseId (de, xml);
- *priority = xml.getMultiChoiceAttribute (de, "priority", "hidden;low;medium;high", (int) PriorityMedium, DL_WARNING);
+ XMLHelper xml(filename);
+ QDomElement de = xml.openXMLFile(DL_WARNING);
+ PluginMapStoredInfo inf(filename);
+ inf.id = RKPluginMapFile::parseId(de, xml);
+ inf.priority = xml.getMultiChoiceAttribute(de, "priority", "hidden;low;medium;high", (int) PriorityMedium, DL_WARNING);
+ auto about = xml.getChildElement(de, "about", DL_WARNING);
+ inf.version = xml.getStringAttribute(about, "version", QString(), DL_WARNING);
+ return inf;
}
QStringList RKSettingsModulePlugins::findPluginMapsRecursive (const QString &basedir) {
@@ -392,7 +401,7 @@ RKSettingsModulePluginsModel::~RKSettingsModulePluginsModel() {
}
}
-void RKSettingsModulePluginsModel::init (const RKSettingsModulePlugins::PluginMapList& known_plugin_maps) {
+void RKSettingsModulePluginsModel::init (const RKSettingsModulePlugins::UniquePluginMapList& known_plugin_maps) {
RK_TRACE (SETTINGS);
beginResetModel ();
plugin_maps = known_plugin_maps;
@@ -422,11 +431,12 @@ QVariant RKSettingsModulePluginsModel::data (const QModelIndex& index, int role)
if (!index.isValid ()) return QVariant ();
int col = index.column ();
- const RKSettingsModulePlugins::PluginMapStoredInfo &inf = plugin_maps[index.row ()];
+ const auto &unique = plugin_maps[index.row()];
+ const auto &inf = unique.bestMap(); // TODO: efficiency
if (role == Qt::BackgroundRole) {
- if (inf.broken_in_this_version) return QColor (Qt::red);
- if (inf.quirky_in_this_version) return QColor (Qt::yellow);
+ if (inf.state == RKSettingsModulePlugins::Broken) return QColor(Qt::red);
+ if (inf.state == RKSettingsModulePlugins::Quirky) return QColor(Qt::yellow);
return (QVariant ());
} else if (role == Qt::ForegroundRole) {
if (inf.priority < RKSettingsModulePlugins::PriorityLow) return QColor (Qt::gray);
@@ -444,7 +454,7 @@ QVariant RKSettingsModulePluginsModel::data (const QModelIndex& index, int role)
if (col == COLUMN_CHECKED) {
if (role == Qt::CheckStateRole) {
if (inf.priority < RKSettingsModulePlugins::PriorityLow) return QVariant ();
- return (inf.active ? Qt::Checked : Qt::Unchecked);
+ return (unique.active ? Qt::Checked : Qt::Unchecked);
}
} else if (col == COLUMN_ID) {
if (role == Qt::DisplayRole) {
@@ -457,10 +467,10 @@ QVariant RKSettingsModulePluginsModel::data (const QModelIndex& index, int role)
}
} else if (col == COLUMN_STATUS) {
if (role == Qt::DisplayRole) {
- if (inf.broken_in_this_version) return i18n ("Broken");
+ if (inf.state == RKSettingsModulePlugins::Broken) return i18n ("Broken");
QString status;
if (RKComponentMap::getMap ()->isPluginMapLoaded (inf.filename)) status = i18n ("Loaded");
- if (inf.quirky_in_this_version) {
+ if (inf.state == RKSettingsModulePlugins::Quirky) {
if (!status.isEmpty ()) status.append (", ");
status.append (i18n ("Quirky"));
}
@@ -475,7 +485,7 @@ Qt::ItemFlags RKSettingsModulePluginsModel::flags (const QModelIndex& index) con
// RK_TRACE (SETTINGS);
Qt::ItemFlags flags = QAbstractTableModel::flags (index);
if (index.isValid () && (index.column () == COLUMN_CHECKED)) {
- if (plugin_maps[index.row ()].priority > RKSettingsModulePlugins::PriorityHidden) flags |= Qt::ItemIsUserCheckable | Qt::ItemIsEditable;
+ if (plugin_maps[index.row()].bestMap().priority > RKSettingsModulePlugins::PriorityHidden) flags |= Qt::ItemIsUserCheckable | Qt::ItemIsEditable;
}
return flags;
}
@@ -525,10 +535,10 @@ void RKSettingsModulePluginsModel::insertNewStrings (int above_row) {
beginInsertRows (QModelIndex (), above_row, files.size ());
for (int i = files.size () - 1; i >= 0; --i) {
- RKSettingsModulePlugins::PluginMapStoredInfo inf (files[i]);
- inf.active = true;
- RKSettingsModulePlugins::parsePluginMapBasics (files[i], &(inf.id), &(inf.priority));
- plugin_maps.insert (above_row, inf);
+ auto inf = RKSettingsModulePlugins::parsePluginMapBasics(files[i]);
+ RKSettingsModulePlugins::UniquePluginMap unique(files[i], true);
+ unique.maps.append(inf);
+ plugin_maps.insert(above_row, unique);
}
endInsertRows ();
}
diff --git a/rkward/settings/rksettingsmoduleplugins.h b/rkward/settings/rksettingsmoduleplugins.h
index 430473ef..7af848fd 100644
--- a/rkward/settings/rksettingsmoduleplugins.h
+++ b/rkward/settings/rksettingsmoduleplugins.h
@@ -41,7 +41,6 @@ public:
/** @returns a list of active plugin maps */
static QStringList pluginMaps ();
- static int uniqueUsablePluginMapCount ();
static PluginPrefs getInterfacePreference () { return interface_pref; };
static bool showCodeByDefault () { return show_code; };
static void setShowCodeByDefault (bool shown) { show_code = shown; };
@@ -50,9 +49,9 @@ public:
static int defaultSidePreviewWidth () { return side_preview_width; };
static void setDefaultSidePreviewWidth (int new_width) { side_preview_width = new_width; }
enum AddMode {
- ManualAddition,
- AddIfDefault,
- AddIfNewAndDefault
+ ForceActivate,
+ AutoActivate,
+ AutoActivateIfNew
};
/** register a list of available plugin-maps (which may or may not already be known). New maps are activated, automatically.
* @param maps Plugin maps (filenames) to add
@@ -63,28 +62,32 @@ public:
static void registerPluginMaps (const QStringList &maps, AddMode add_mode, bool force_reload, bool suppress_reload=false);
/** Looks for the given id among known plugin maps */
static QString findPluginMapById (const QString &id);
- /** marks given map as broken (in this version), and deactivates it. @Returns false is the map was already known to be broken, true otherwise. */
- static bool markPluginMapAsBroken (const QString &map);
- /** marks given map as quirky (in this version). @Returns false is the map was already known to be quirky, true otherwise. */
- static bool markPluginMapAsQuirky (const QString &map);
- /** Clears the broken or quirky flags. E.g. after the map was loaded, successfully */
- static void markPluginMapAsWorking (const QString &map);
enum PluginMapPriority { PriorityHidden = 0, PriorityLow, PriorityMedium, PriorityHigh };
+ enum PluginMapState { Broken, Quirky, Working };
+ /** Marks given map as working, quirky, or broken. @returns true, if the state has changed. Broken maps are also disabled. */
+ static bool markPluginMapState(const QString &map, PluginMapState state);
+
/** Helper struct used by RKSettingsModulePlugins to keep track of plugin map files. */
struct PluginMapStoredInfo {
- PluginMapStoredInfo (const QString &_filename) : filename (_filename), active (false), broken_in_this_version (false), quirky_in_this_version (false) {};
+ PluginMapStoredInfo (const QString &_filename) : filename (_filename), state(Working) {};
QString filename;
- bool active;
- bool broken_in_this_version;
- bool quirky_in_this_version;
+ PluginMapState state;
int priority;
+ RKParsedVersion version;
QString id;
QDateTime last_modified;
};
typedef QList<PluginMapStoredInfo> PluginMapList;
- static PluginMapList knownPluginmaps () { return known_plugin_maps; };
- static void parsePluginMapBasics (const QString &filename, QString *id, int *priority);
+ struct UniquePluginMap {
+ UniquePluginMap(const QString &id, bool active) : id(id), active(active) {};
+ QString id;
+ bool active;
+ PluginMapList maps;
+ PluginMapStoredInfo bestMap() const;
+ };
+ typedef QList<UniquePluginMap> UniquePluginMapList;
+ static UniquePluginMapList knownPluginmaps () { return known_plugin_maps; };
/** Registers the plugin maps that are shipped with RKWard.
* @param force_add All default maps are also activated, even if they were already known, and disabled by the user. */
static void registerDefaultPluginMaps (AddMode add_mode);
@@ -95,7 +98,11 @@ private:
QButtonGroup *button_group;
/** plugin maps which are not necessarily active, but have been encountered, before. @see plugin_maps */
- static PluginMapList known_plugin_maps;
+ static UniquePluginMapList known_plugin_maps;
+friend class RKSettingsModulePluginsModel;
+ static PluginMapStoredInfo parsePluginMapBasics (const QString &filename);
+ /* @returns true, if map was new, false if already known */
+ static bool addPluginMapToList(const PluginMapStoredInfo &inf, bool active);
static RKConfigValue<PluginPrefs,int> interface_pref;
static RKConfigValue<bool> show_code;
@@ -107,7 +114,7 @@ private:
static void fixPluginMapLists ();
friend class RKPluginMapSelectionWidget;
/** Sets the new list of plugins. Potentially removes unreadable ones, and returns the effective list. */
- static PluginMapList setPluginMaps (const PluginMapList &new_list);
+ static UniquePluginMapList setPluginMaps (const UniquePluginMapList &new_list);
};
class RKSettingsModulePluginsModel : public QAbstractTableModel {
@@ -116,13 +123,13 @@ public:
explicit RKSettingsModulePluginsModel (QObject* parent);
virtual ~RKSettingsModulePluginsModel ();
/** (re-)initialize the model */
- void init (const RKSettingsModulePlugins::PluginMapList &known_plugin_maps);
- RKSettingsModulePlugins::PluginMapList pluginMaps () { return plugin_maps; };
+ void init (const RKSettingsModulePlugins::UniquePluginMapList &known_plugin_maps);
+ RKSettingsModulePlugins::UniquePluginMapList pluginMaps () { return plugin_maps; };
public slots:
void swapRows (int rowa, int rowb);
void insertNewStrings (int above_row);
private:
- RKSettingsModulePlugins::PluginMapList plugin_maps;
+ RKSettingsModulePlugins::UniquePluginMapList plugin_maps;
struct PluginMapMetaInfo {
RKComponentAboutData *about;
QList<RKComponentDependency> dependencies;
More information about the rkward-tracker
mailing list