}
return res;
+}
+
+
+
+
+class SUIT_EXPORT SUIT_ActionIDEvolver
+{
+public:
+ struct SUIT_EXPORT Schema
+ {
+ bool fromJSON(const QJsonObject& theJsonObject);
+
+ QString sectionPrefix_evolutionFrom;
+ QString sectionPrefix_evolutionInto;
+
+ /** The map only keeps changes between identification schemes. It means, there is no need to add entries like {theSameActionID: theSameActionID}. */
+ std::map<QString, QString> newActionID_to_oldActionID_map;
+ };
+
+ /** {sectionPrefix_evolutionFrom}[]. Defined from newest to oldest. */
+ static const std::vector<QString> evolutionChronology;
+
+ /*!
+ \param theActionID Action ID in the latest identification schema (as elsewhere in code).
+ \returns {false, _ }, if shortcut is not defined in any outdated shortcut section of user preference files. */
+ std::pair<bool, QKeySequence> getUserDefinedKeySequence(const QString& theActionID) const;
+
+private:
+ void parseSchemas();
+ std::pair<bool, QKeySequence> getUserDefinedKeySequenceInOldSection(const QString& theActionID, const QString& theSectionPrefix) const;
+
+private:
+ /** {sectionPrefix_evolutionFrom, {schema}[] }[]. Sorted from newest to oldest. */
+ std::list<std::pair<QString, std::set<std::shared_ptr<SUIT_ActionIDEvolver::Schema>>> schemas;
+};
+
+const QString SECTION_NAME_ACTION_ID_MIGRATION_SCHEMA_FILE_PATHS = "TODO";
+
+static const std::vector<QString> SUIT_ActionIDEvolver::evolutionChronology = {"shortcuts_vA1.0", "shortcuts"};
+
+
+void SUIT_ActionIDEvolver::parseSchemas() {
+ ShCutDbg() && ShCutDbg("Parsing action ID evolution schemas.");
+
+ if (SUIT_ActionIDEvolver::evolutionChronology.size() < 2) {
+ Warning("SUIT_ActionIDEvolver: evolution chronology is not sufficient.");
+ return;
+ }
+
+ if (SUIT_ActionIDEvolver::evolutionChronology.front() != SECTION_NAME_PREFIX) {
+ Warning("SUIT_ActionIDEvolver: evolution chronology starts with a shortcuts' preference section name prefix, which differs from actual one.");
+ return;
+ }
+
+ for (size_t idx = 0; idx < SUIT_ActionIDEvolver::evolutionChronology.size() - 1; idx++) {
+ schemas.emplace(SUIT_ActionIDEvolver::evolutionChronology[idx], std::set<std::shared_ptr<SUIT_ActionIDEvolver::Schema>>);
+ }
+
+ SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
+ if (!resMgr) {
+ Warning("SUIT_ActionIDEvolver can't retrieve resource manager!");
+ return;
+ }
+
+ QStringList schemaFilePaths = resMgr->parameters(SECTION_NAME_ACTION_ID_MIGRATION_SCHEMA_FILE_PATHS);
+#ifdef SHORTCUT_MGR_DBG
+ ShCutDbg("Action ID evolution schema files: " + schemaFilePaths.join(", ") + ".");
+#endif
+ for (const QString& schemaFilePath : schemaFilePaths) {
+ const QString path = ::SUIT_tools::substituteVars(schemaFilePath);
+ ShCutDbg("Parsing action ID evolution file \"" + path + "\".");
+ QFile schemaFile(path);
+ if (!schemaFile.open(QIODevice::ReadOnly)) {
+ Warning("SUIT_ActionIDEvolver can't open action ID evolution file \"" + path + "\"!");
+ continue;
+ }
+
+ QJsonParseError jsonError;
+ QJsonDocument document = QJsonDocument::fromJson(schemaFile.readAll(), &jsonError);
+ schemaFile.close();
+ if (jsonError.error != QJsonParseError::NoError) {
+ Warning("SUIT_ShortcutMgr: error during parsing of action ID evolution file \"" + path + "\"!");
+ continue;
+ }
+
+ if (document.isObject()) {
+ QJsonObject documentJSONObject = document.object();
+ for (const QString& key : documentJSONObject.keys()) {
+ if (key != "schemas") // TODO
+ continue;
+
+ const auto& schemasJSONValue = documentJSONObject[key];
+ if (!schemasJSONValue.isArray()) {
+ ShCutDbg("Action ID evolution file \"" + path + "\" does not contain array \"" + key + "\".");
+ continue;
+ }
+
+ const auto& schemasJSONArray = schemasJSONValue.toArray();
+ for (const auto& schemaJSONVal : schemasJSONArray) {
+ if (!schemaJSONVal.isObject()) {
+ ShCutDbg("Action ID evolution file \"" + path + "\" contains invalid schema object.");
+ continue;
+ }
+
+ auto schema = std::shared_ptr<SUIT_ActionIDEvolver::Schema>(new SUIT_ActionIDEvolver::Schema());
+ if (!schema->fromJSON(schemaJSONVal.toObject())) {
+ ShCutDbg("Action ID evolution file \"" + path + "\" contains invalid schema object.");
+ continue;
+ }
+
+ if (schema->sectionPrefix_evolutionFrom == schema->sectionPrefix_evolutionInto) {
+ ShCutDbg("Action ID evolution file \"" + path + "\" contains invalid evolution schema (from == into). From/into \"" + schema->sectionPrefix_evolutionFrom + "\".");
+ continue;
+ }
+
+ const auto itEvolutionFrom = std::find(SUIT_ActionIDEvolver::evolutionChronology.begin(), SUIT_ActionIDEvolver::evolutionChronology.end(); schema->sectionPrefix_evolutionFrom);
+ const auto itEvolutionInto = std::find(SUIT_ActionIDEvolver::evolutionChronology.begin(), SUIT_ActionIDEvolver::evolutionChronology.end(); schema->sectionPrefix_evolutionInto);
+ if (itEvolutionFrom == SUIT_ActionIDEvolver::evolutionChronology.end() || itEvolutionInto == SUIT_ActionIDEvolver::evolutionChronology.end()) {
+ ShCutDbg("Action ID evolution file \"" + path + "\" contains evolution schema, which is absent in evolution chronology. From \"" + schema->sectionPrefix_evolutionFrom + "\" into \"" + schema->sectionPrefix_evolutionInto + "\".");
+ continue;
+ }
+
+ {
+ const auto itEvolutionFromNext = ++itEvolutionFrom;
+ if (itEvolutionFromNext != itEvolutionInto) {
+ ShCutDbg("Action ID evolution file \"" + path + "\" contains evolution schema, which is absent in evolution chronology. From \"" + schema->sectionPrefix_evolutionFrom + "\" into \"" + schema->sectionPrefix_evolutionInto + "\".");
+ continue;
+ }
+ }
+
+ schemas[schema->sectionPrefix_evolutionFrom].insert(schema);
+ }
+ }
+ }
+ }
+}
+
+std::pair<bool, QKeySequence> SUIT_ActionIDEvolver::getUserDefinedKeySequence(const QString& theActionID) const {
+ auto result = std::pair<bool, QKeySequence>(false, QKeySequence());
+ for (const auto& sectionPrefixAndSchemas : schemas) {
+ const auto& schemasOfCurrentEvolution = sectionPrefixAndSchemas.second;
+ for (const auto& schemaOfCurrentEvolution : schemasOfCurrentEvolution ) {
+ const auto it = schemaOfCurrentEvolution.newActionID_to_oldActionID_map.find(theActionID);
+ if (it == schemaOfCurrentEvolution.newActionID_to_oldActionID_map.end())
+ continue;
+
+ const QString& olderActionID = it->second;
+ std::pair<bool, QKeySequence> olderKS = getUserDefinedKeySequenceInOldSection(olderActionID, schemaOfCurrentEvolution.sectionPrefix_evolutionFrom);
+ if (olderKS.first) {
+ result = SUIT_ShortcutMgr::toKeySequenceIfValid(olderKS.second);
+ if (result.first)
+ return result; // Even if there are other
+ else
+ ShCutDbg("Old settings file contains invalid key sequence string \"" + olderKS.second + "\". From \"" + schemaOfCurrentEvolution->sectionPrefix_evolutionFrom + "\" into \"" + schemaOfCurrentEvolution->sectionPrefix_evolutionInto + "\".");
+ }
+ }
+ }
}
\ No newline at end of file