Salome HOME
[bos #40644][CEA](2024-T1) Feature search.
[modules/gui.git] / src / SUIT / SUIT_ShortcutMgr.cxx
index 8be5094cca35e7cf3bb6ba02a38e435d4d9f2a4f..068414e3f57c43d55c4d3a1ba743940f58a46363 100644 (file)
@@ -1903,7 +1903,7 @@ void SUIT_ShortcutMgr::setAssetsFromResources(QString theLanguage)
         auto itAssets = moduleActionAssets.find(inModuleActionID);
         if (itAssets == moduleActionAssets.end()) {
           auto pAssets = std::shared_ptr<SUIT_ActionAssets>(new SUIT_ActionAssets(actionAssets));
-          itAssets = moduleActionAssets.emplace(actionID, pAssets).first;
+          itAssets = moduleActionAssets.emplace(inModuleActionID, pAssets).first;
         }
         else
           itAssets->second->merge(actionAssets, true);
@@ -1981,18 +1981,17 @@ void SUIT_SentenceMatcher::setUseExactWordOrder(bool theOn)
     return;
 
   myUseExactWordOrder = theOn;
-  if (!myWords || theOn)
+  if (theOn) {
+    myPermutatedSentences.clear();
+    myFuzzyPermutatedSentences.clear();
     return;
-
-  if (!myPermutatedSentences) {
-    myPermutatedSentences.reset(new QList<QStringList>());
-    SUIT_SentenceMatcher::makePermutatedSentences(*myWords, *myPermutatedSentences);
   }
 
-  if (myUseFuzzyWords && !myFuzzyPermutatedSentences) {
-    myFuzzyPermutatedSentences.reset(new QList<QStringList>());
-    SUIT_SentenceMatcher::makePermutatedSentences(*myFuzzyWords, *myFuzzyPermutatedSentences);
-  }
+  if (myPermutatedSentences.isEmpty())
+    SUIT_SentenceMatcher::makePermutatedSentences(myWords, myPermutatedSentences);
+
+  if (myUseFuzzyWords && myFuzzyPermutatedSentences.isEmpty())
+    SUIT_SentenceMatcher::makePermutatedSentences(myFuzzyWords, myFuzzyPermutatedSentences);
 }
 
 void SUIT_SentenceMatcher::setUseFuzzyWords(bool theOn)
@@ -2001,15 +2000,18 @@ void SUIT_SentenceMatcher::setUseFuzzyWords(bool theOn)
     return;
 
   myUseFuzzyWords = theOn;
-  if (!myWords || !theOn || myFuzzyWords)
+  if (myWords.isEmpty() || !theOn) {
+    myFuzzyWords.clear();
+    myFuzzyPermutatedSentences.clear();
     return;
+  }
 
-  myFuzzyWords.reset(new QStringList());
-  SUIT_SentenceMatcher::makeFuzzyWords(*myWords, *myFuzzyWords);
+  myFuzzyWords.clear();
+  SUIT_SentenceMatcher::makeFuzzyWords(myWords, myFuzzyWords);
 
   if (!myUseExactWordOrder) {
-    myFuzzyPermutatedSentences.reset(new QList<QStringList>());
-    SUIT_SentenceMatcher::makePermutatedSentences(*myFuzzyWords, *myFuzzyPermutatedSentences);
+    myFuzzyPermutatedSentences.clear();
+    SUIT_SentenceMatcher::makePermutatedSentences(myFuzzyWords, myFuzzyPermutatedSentences);
   }
 }
 
@@ -2025,46 +2027,22 @@ void SUIT_SentenceMatcher::setQuery(QString theQuery)
     return;
 
   myQuery = theQuery;
-
-  { // Set exact words.
-    if (myWords)
-      myWords->clear();
-    else
-      myWords.reset(new QStringList());
-
-    *myWords = theQuery.split(" ", QString::SkipEmptyParts);
-  }
+  myWords = theQuery.split(" ", QString::SkipEmptyParts);
 
   { // Set permutated sentences.
-    if (myUseExactWordOrder)
-      myPermutatedSentences.reset(nullptr);
-    else {
-      if (!myPermutatedSentences)
-        myPermutatedSentences.reset(new QList<QStringList>());
-
-      SUIT_SentenceMatcher::makePermutatedSentences(*myWords, *myPermutatedSentences);
-    }
+    myPermutatedSentences.clear();
+    if (!myUseExactWordOrder)
+      SUIT_SentenceMatcher::makePermutatedSentences(myWords, myPermutatedSentences);
   }
 
   // Set fuzzy words and sentences.
-  if (myUseFuzzyWords) {
-    if (!myFuzzyWords)
-      myFuzzyWords.reset(new QStringList());
-
-    SUIT_SentenceMatcher::makeFuzzyWords(*myWords, *myFuzzyWords);
+  myFuzzyWords.clear();
+  myFuzzyPermutatedSentences.clear();
 
-    if (myUseExactWordOrder)
-      myFuzzyPermutatedSentences.reset(nullptr);
-    else {
-      if (!myFuzzyPermutatedSentences)
-        myFuzzyPermutatedSentences.reset(new QList<QStringList>());
-
-      SUIT_SentenceMatcher::makePermutatedSentences(*myFuzzyWords, *myFuzzyPermutatedSentences);
-    }
-  }
-  else {
-    myFuzzyWords.reset(nullptr);
-    myFuzzyPermutatedSentences.reset(nullptr);
+  if (myUseFuzzyWords) {
+    SUIT_SentenceMatcher::makeFuzzyWords(myWords, myFuzzyWords);
+    if (!myUseExactWordOrder)
+      SUIT_SentenceMatcher::makePermutatedSentences(myFuzzyWords, myFuzzyPermutatedSentences);
   }
 }
 
@@ -2072,23 +2050,23 @@ size_t SUIT_SentenceMatcher::match(const QString& theInputString) const
 {
   size_t n = 0;
   if (myUseExactWordOrder) {
-    n = SUIT_SentenceMatcher::match(theInputString, *myWords, myIsCaseSensitive);
+    n = SUIT_SentenceMatcher::match(theInputString, myWords, myIsCaseSensitive);
     if (n > 0)
       return n;
 
     if (myUseFuzzyWords) {
-      n = SUIT_SentenceMatcher::match(theInputString, *myFuzzyWords, myIsCaseSensitive);
+      n = SUIT_SentenceMatcher::match(theInputString, myFuzzyWords, myIsCaseSensitive);
       if (n > 0)
         return n;
     }
   }
   else /* if match with permutated query sentences */ {
-    n = SUIT_SentenceMatcher::match(theInputString, *myPermutatedSentences, myIsCaseSensitive);
+    n = SUIT_SentenceMatcher::match(theInputString, myPermutatedSentences, myIsCaseSensitive);
     if (n > 0)
       return n;
 
     if (myUseFuzzyWords) {
-      n = SUIT_SentenceMatcher::match(theInputString, *myFuzzyPermutatedSentences, myIsCaseSensitive);
+      n = SUIT_SentenceMatcher::match(theInputString, myFuzzyPermutatedSentences, myIsCaseSensitive);
       if (n > 0)
         return n;
     }
@@ -2097,6 +2075,29 @@ size_t SUIT_SentenceMatcher::match(const QString& theInputString) const
   return n;
 }
 
+QString SUIT_SentenceMatcher::toString() const
+{
+  QString res = QString("myUseExactWordOrder: ") + (myUseExactWordOrder ? "true" : "false") + ";\n";
+  res += QString("myUseFuzzyWords: ") + (myUseFuzzyWords ? "true" : "false") + ";\n";
+  res += QString("myIsCaseSensitive: ") + (myIsCaseSensitive ? "true" : "false") + ";\n";
+  res += QString("myQuery: ") + myQuery + ";\n";
+  res += QString("myWords: ") + myWords.join(", ") + ";\n";
+  res += QString("myFuzzyWords: ") + myFuzzyWords.join(", ") + ";\n";
+
+  res += "myPermutatedSentences:\n";
+  for (const auto& sentence : myPermutatedSentences) {
+    res += "\t" + sentence.join(", ") + ";\n";
+  }
+
+  res += "myFuzzyPermutatedSentences:\n";
+  for (const auto& sentence : myFuzzyPermutatedSentences) {
+    res += "\t" + sentence.join(", ") + ";\n";
+  }
+
+  res += ".";
+  return res;
+}
+
 /*static*/ bool SUIT_SentenceMatcher::makePermutatedSentences(const QStringList& theWords, QList<QStringList>& theSentences)
 {
   theSentences.clear();
@@ -2187,7 +2188,7 @@ size_t SUIT_SentenceMatcher::match(const QString& theInputString) const
   if (n > 0)
     return n;
 
-  if (theSentences.size())
+  if (theSentences.size() > 0)
     return SUIT_SentenceMatcher::matchAtLeastOneWord(theInputString, theSentences[0], theCaseSensitive);
   else
     return 0;
@@ -2198,6 +2199,25 @@ SUIT_ActionSearcher::AssetsAndSearchData::AssetsAndSearchData(std::shared_ptr<SU
 : myAssets(theAssets), myNumOfMatchingWords(theNumOfMatchingWords)
 {}
 
+void SUIT_ActionSearcher::AssetsAndSearchData::toJSON(QJsonObject& oJsonObject) const
+{
+  oJsonObject["myNumOfMatchingWords"] = int(myNumOfMatchingWords);
+
+  if (myAssets) {
+    QJsonObject assetsJSON;
+    myAssets->toJSON(assetsJSON);
+    oJsonObject["myAssets"] = assetsJSON;
+  }
+}
+
+QString SUIT_ActionSearcher::AssetsAndSearchData::toString() const
+{
+  QJsonObject json;
+  toJSON(json);
+  QJsonDocument doc(json);
+  return QString(doc.toJson(QJsonDocument::Indented));
+}
+
 SUIT_ActionSearcher::SUIT_ActionSearcher()
 {
   myIncludedModuleIDs = { SUIT_ShortcutMgr::ROOT_MODULE_ID };
@@ -2210,17 +2230,19 @@ SUIT_ActionSearcher::SUIT_ActionSearcher()
 
 bool SUIT_ActionSearcher::setIncludedModuleIDs(std::set<QString> theIncludedModuleIDs)
 {
+  ShCutDbg("SUIT_ActionSearcher::setIncludedModuleIDs");
+
   if (myIncludedModuleIDs == theIncludedModuleIDs)
     return false;
 
   myIncludedModuleIDs = theIncludedModuleIDs;
 
   bool res = false;
-  // Erase search results with excluded modules. Erase IDs of modules, which are already in search results, from theIncludedModuleIDs.
+  // Erase search results from excluded modules. Erase IDs of modules, which are already in search results, from theIncludedModuleIDs.
   for (auto itFound = mySearchResults.begin(); itFound != mySearchResults.end(); ) {
     const auto itModuleID = theIncludedModuleIDs.find(itFound->first);
     if (itModuleID == theIncludedModuleIDs.end()) {
-      mySearchResults.erase(itFound);
+      itFound = mySearchResults.erase(itFound);
       res = true;
     }
     else {
@@ -2247,20 +2269,28 @@ bool SUIT_ActionSearcher::setIncludedModuleIDs(std::set<QString> theIncludedModu
     }
   }
 
+  ShCutDbg() && ShCutDbg(toString());
+
   return res;
 }
 
 bool SUIT_ActionSearcher::includeDisabledActions(bool theOn)
 {
+  ShCutDbg("SUIT_ActionSearcher::includeDisabledActions");
+
   if (myIncludeDisabledActions == theOn)
     return false;
 
   myIncludeDisabledActions = theOn;
 
+  bool res;
   if (myIncludeDisabledActions)
-    return extendResults();
+    res = extendResults();
   else
-    return filterResults().first;
+    res = filterResults().first;
+
+  ShCutDbg() && ShCutDbg(toString());
+  return res;
 }
 
 bool SUIT_ActionSearcher::setFieldsToMatch(const std::set<SUIT_ActionSearcher::MatchField>& theFields)
@@ -2292,12 +2322,16 @@ bool SUIT_ActionSearcher::setFieldsToMatch(const std::set<SUIT_ActionSearcher::M
 
   myFieldsToMatch = theFields;
 
+  bool res;
   if (narrows)
-    return filterResults().first;
+    res = filterResults().first;
   else if (extends)
-    return extendResults();
+    res = extendResults();
   else
-    return filter().first;
+    res = filter().first;
+
+  ShCutDbg() && ShCutDbg(toString());
+  return res;
 }
 
 bool SUIT_ActionSearcher::setCaseSensitive(bool theOn)
@@ -2307,19 +2341,27 @@ bool SUIT_ActionSearcher::setCaseSensitive(bool theOn)
 
   myMatcher.setCaseSensitive(theOn);
 
+  bool res;
   if (theOn)
-    return filterResults().first;
+    res = filterResults().first;
   else
-    return extendResults();
+    res = extendResults();
+
+  ShCutDbg() && ShCutDbg(toString());
+  return res;
 }
 
 bool SUIT_ActionSearcher::setQuery(const QString& theQuery)
 {
+  ShCutDbg("SUIT_ActionSearcher::setQuery");
+
   if (theQuery.simplified() == myMatcher.getQuery().simplified())
     return false;
 
   myMatcher.setQuery(theQuery);
-  return filter().first;
+  bool res = filter().first;
+  ShCutDbg() && ShCutDbg(toString());
+  return res;
 }
 
 const std::map<QString, std::map<QString, SUIT_ActionSearcher::AssetsAndSearchData>>& SUIT_ActionSearcher::getSearchResults() const
@@ -2329,6 +2371,8 @@ const std::map<QString, std::map<QString, SUIT_ActionSearcher::AssetsAndSearchDa
 
 std::pair<bool, bool> SUIT_ActionSearcher::filter()
 {
+  ShCutDbg("SUIT_ActionSearcher::filter()");
+
   auto res = std::pair<bool, bool>(false, false);
 
   for (const auto& moduleIDAndAssets : SUIT_ShortcutMgr::get()->getActionAssets()) {
@@ -2389,7 +2433,7 @@ std::pair<bool, bool> SUIT_ActionSearcher::filterResults()
       SUIT_ActionSearcher::AssetsAndSearchData& assetsAndSearchData = itActionIDAndAssets->second;
       const size_t n = matchAction(moduleID, inModuleActionID, assetsAndSearchData.myAssets);
       if (n == 0) {
-        actionIDsAndAssets.erase(itActionIDAndAssets);
+        itActionIDAndAssets = actionIDsAndAssets.erase(itActionIDAndAssets);
         res.first = true;
       }
       else {
@@ -2402,7 +2446,7 @@ std::pair<bool, bool> SUIT_ActionSearcher::filterResults()
     }
 
     if (actionIDsAndAssets.empty())
-      mySearchResults.erase(itFoundModuleIDAndAssets);
+      itFoundModuleIDAndAssets = mySearchResults.erase(itFoundModuleIDAndAssets);
     else
       itFoundModuleIDAndAssets++;
   }
@@ -2412,6 +2456,8 @@ std::pair<bool, bool> SUIT_ActionSearcher::filterResults()
 
 bool SUIT_ActionSearcher::extendResults()
 {
+  ShCutDbg("SUIT_ActionSearcher::extendResults()");
+
   bool res = false;
   for (const auto& moduleIDAndAssets : SUIT_ShortcutMgr::get()->getActionAssets()) {
     const auto& moduleID = moduleIDAndAssets.first;
@@ -2430,8 +2476,10 @@ bool SUIT_ActionSearcher::extendResults()
           continue; // Action is already in search results.
       }
 
+      ShCutDbg() && ShCutDbg("SUIT_ActionSearcher::extendResults(): " + moduleID + "/" + inModuleActionID + "." );
       const size_t n = matchAction(moduleID, inModuleActionID, actionIDAndAssets.second);
       if (n > 0) {
+        ShCutDbg("SUIT_ActionSearcher::extendResults(): match");
         if (itFoundModuleIDAndAssets == mySearchResults.end())
           itFoundModuleIDAndAssets = mySearchResults.emplace(moduleID, std::map<QString, SUIT_ActionSearcher::AssetsAndSearchData>()).first;
 
@@ -2445,6 +2493,11 @@ bool SUIT_ActionSearcher::extendResults()
 
 size_t SUIT_ActionSearcher::matchAction(const QString& theModuleID, const QString& theInModuleActionID, std::shared_ptr<SUIT_ActionAssets> theAssets)
 {
+  if (!theAssets) {
+    ShCutDbg("WARNING: SUIT_ActionSearcher::matchAction: theAssets is nullptr.");
+    return 0;
+  }
+
   if (!myIncludeDisabledActions) {
     const auto& actions = SUIT_ShortcutMgr::get()->getActions(theModuleID, theInModuleActionID);
     const bool actionEnabled = std::find_if(actions.begin(), actions.end(), [](const QAction* const theAction){ return theAction->isEnabled(); } ) != actions.end();
@@ -2476,4 +2529,40 @@ size_t SUIT_ActionSearcher::matchAction(const QString& theModuleID, const QStrin
   }
 
   return false;
+}
+
+QString SUIT_ActionSearcher::toString() const
+{
+  QString res;
+
+  res += "myMatcher: {\n";
+  res += myMatcher.toString();
+  res += "};\n";
+
+  res += "myIncludedModuleIDs: ";
+  for (const QString& moduleID : myIncludedModuleIDs) {
+    res += moduleID + ", ";
+  }
+  res += ";\n";
+
+  res += QString("myIncludeDisabledActions: ") + (myIncludeDisabledActions ? "true" : "false") + ";\n";
+
+  res += "myFieldsToMatch: ";
+  for (const auto& field : myFieldsToMatch) {
+    res += QString::number(int(field)) + ", ";
+  }
+  res += ";\n";
+
+  res += "mySearchResults:\n";
+  for (const auto& moduleIDAndAssets : mySearchResults ) {
+    res += "\tModule ID: " + moduleIDAndAssets.first + ":\n";
+    for (const auto& actionIDAndAssets : moduleIDAndAssets.second) {
+      const auto& assetsAndSearchData = actionIDAndAssets.second;
+      res += "\t\tAction ID: " + actionIDAndAssets.first + ": {";
+      res += "\t\t: " + actionIDAndAssets.second.toString();
+      res += "\t\t}";
+    }
+  }
+
+  return res;
 }
\ No newline at end of file