1 // Copyright (C) 2007-2024 CEA, EDF, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 #ifndef SUIT_SHORTCUTMGR_H
24 #define SUIT_SHORTCUTMGR_H
30 #include <QStringList>
44 #pragma warning( disable: 4251 )
47 // Define SHORTCUT_MGR_DBG to enable SUIT_ShortcutMgr debug logging.
48 // #define SHORTCUT_MGR_DBG
49 /*! \returns true, if SUIT_ShortcutMgr debug logging is enabled. */
50 SUIT_EXPORT extern inline bool ShCutDbg() {
51 #ifdef SHORTCUT_MGR_DBG
57 /*! \brief Prints theString to std::wcout, if SUIT_ShortcutMgr debug logging is enabled. */
58 SUIT_EXPORT extern bool ShCutDbg(const QString& theString);
59 /*! \brief Prints theString to std::wcout, if SUIT_ShortcutMgr debug logging is enabled. */
60 SUIT_EXPORT extern bool ShCutDbg(const char* theString);
64 \class SUIT_ShortcutContainer
65 \brief Provides means to keep and edit shortcuts in compliance with the application logics.
66 \ref See SUIT_ShortcutMgr for details.
68 class SUIT_EXPORT SUIT_ShortcutContainer
71 SUIT_ShortcutContainer();
73 /*! \returns IDs of modules, which interfere with the module:
74 if the module is root (theModuleID is empty) - returns all module IDs, otherwise returns ["", theModuleID]. */
75 std::set<QString> getIDsOfInterferingModules(const QString& theModuleID) const;
77 std::set<QString> getIDsOfAllModules() const;
79 /*! \brief Checks for conflicts. If theOverride, modifies incoming and disables all conflicting shortcuts.
80 Redefining a key sequence for the action, if theKeySequence does not conflict with other shortcuts, is not considered as a conflict.
81 \param theModuleID The method has no effect if theModuleID is invalid. \ref See SUIT_ShortcutMgr::isModuleIDValid(const QString&) for details.
82 \param theInModuleActionID The method has no effect if theInModuleActionID is invalid. \ref See SUIT_ShortcutMgr::isInModuleActionIDValid(const QString&).
83 If theInModuleActionID is meta-action ID, the shortcut is set to root module, and theModuleID is ignored.
84 \param theKeySequence Empty theKeySequence does not cause conflicts, in this case
85 a shortcut for the action is disabled: theInModuleActionID is added/retained in the container but mapped to empty key sequence.
86 \param theOverride If true, conflicting shortcuts are disabled.
87 \returns {moduleID, inModuleActionID}[] - Set of conflicting actions if theOverride = false,
88 otherwise set of actions (without incoming one), whose shortcuts have been disabled. */
89 std::set<std::pair<QString, QString>> setShortcut(
91 const QString& theInModuleActionID,
92 const QKeySequence& theKeySequence,
96 /*! \brief Checks for conflicts. Existence of a shortcut with another key sequence for the action,
97 if theKeySequence does not conflict with other shortcuts, is not considered as a conflict.
98 \param theInModuleActionID If theInModuleActionID is meta-action ID, the shortcut is looked for in root module, and theModuleID is ignored.
99 \param theKeySequence Empty theKeySequence does not have conflicts.
100 \returns {moduleID, inModuleActionID}[] - Set of conflicting actions. */
101 std::set<std::pair<QString, QString>> getConflicts(
103 const QString& theInModuleActionID,
104 const QKeySequence& theKeySequence
107 /*! \returns empty key sequence if shortcut for the action is not set.
108 \param theInModuleActionID If theInModuleActionID is meta-action ID, seeks in root module, and theModuleID is ignored.*/
109 const QKeySequence& getKeySequence(QString theModuleID, const QString& theInModuleActionID) const;
111 /*! \returns true, if shortcut for the action is set (even if the mapped key sequence is empty).
112 \param theInModuleActionID If theInModuleActionID is meta-action ID, seeks in root module, and theModuleID is ignored.*/
113 bool hasShortcut(QString theModuleID, const QString& theInModuleActionID) const;
115 /*! \returns {inModuleActionID, keySequence}[] - If the module was not added, the map is empty. */
116 const std::map<QString, QKeySequence>& getModuleShortcutsInversed(const QString& theModuleID) const;
118 /*! \brief Seeks for shortcuts in the module with in-module action IDs, which start with theInModuleActionIDPrefix.
119 \returns {inModuleActionID, keySequence}[] - If the module was not added, the map is empty. */
120 const std::map<QString, QKeySequence> getModuleShortcutsInversed(const QString& theModuleID, const QString& theInModuleActionIDPrefix) const;
122 /*! \brief Merges shortcuts of theOther into this.
123 \param theOverride if true, overrides conflicting shortcuts.
124 If false, and this has no shortcut for an incoming action, and the incoming shortcut conflicts
125 with an existing shortcut, disabled shortcut for the incoming action is set.
126 \param theTreatAbsentIncomingAsDisabled If theOverride == false, theTreatAbsentIncomingAsDisabled is ignored.
127 If theOverride and theTreatAbsentIncomingAsDisabled, and theOther has no shortcut for an action, which exists in this,
128 the existing shortcut in this is set disabled.
129 \returns { moduleID, { inModuleActionID, keySequence }[] }[] - Modiified shortcuts inversed. */
130 std::map<QString, std::map<QString, QKeySequence>> merge(
131 const SUIT_ShortcutContainer& theOther,
133 bool theTreatAbsentIncomingAsDisabled = false
136 /*! \brief Generates human-readable text representation of content. */
137 QString toString() const;
140 /** { moduleID, { keySequence, inModuleActionID }[] }[]. keySequence can not be empty.
141 * Can not contain entries like { <non-root module ID>, { keySequence, <meta-action ID> } }. */
142 std::map<QString, std::map<QKeySequence, QString>> myShortcuts;
144 /** { moduleID, { inModuleActionID, keySequence }[] }[]. keySequence can be empty.
145 * Can not contain entries like { <non-root module ID>, { <meta-action ID>, keySequence } }. */
146 std::map<QString, std::map<QString, QKeySequence>> myShortcutsInversed;
150 /*! \brief GUI-related assets. */
151 struct SUIT_EXPORT SUIT_ActionAssets
153 struct LangDependentAssets
155 static const QString PROP_ID_NAME;
156 static const QString PROP_ID_TOOLTIP;
158 bool fromJSON(const QJsonObject& theJsonObject);
159 void toJSON(QJsonObject& oJsonObject) const;
165 static const QString STRUCT_ID;
166 static const QString PROP_ID_LANG_DEPENDENT_ASSETS;
167 static const QString PROP_ID_ICON_PATH;
169 bool fromJSON(const QJsonObject& theJsonObject);
170 void toJSON(QJsonObject& oJsonObject) const;
171 QString toString() const;
173 QStringList getLangs() const;
174 void clearAllLangsExcept(const QString& theLang);
176 /*! \param theOverride If true, values of theOther override conflicting values of this. */
177 void merge(const SUIT_ActionAssets& theOther, bool theOverride);
179 std::map<QString, LangDependentAssets> myLangDependentAssets;
182 /*! Is not serialized. */
188 \class SUIT_ShortcutMgr
189 \brief Handles action shortcut customization.
191 Register actions under action IDs. Set shortcuts, which are [action ID]<->[key sequence] mappings.
192 Every time an action is registered or a shorcut is set, if there are an action and a shortcut,
193 which are mapped to the same action ID, the action is bound to the key sequence of the shortcut.
194 Action IDs are also used to (de)serialize shortcut settings.
195 Several QActions may be registered under the same ID.
197 Most of actions are intercepted on creation in SUIT_ShortcutMgr:eventFilter(QObject* theObject, QEvent* theEvent).
198 If an intercepted action is instance of QtxAction, it is registered automatically.
199 Since non-QtxActions have no member ID(), SUIT_ShortcutMgr is unable to register them automatically
200 in SUIT_ShortcutMgr::eventFilter(). Thus, every non-QtxAction should be
201 passed to SUIT_ShortcutMgr::registerAction(const QString& theActionID, QAction* theAction).
203 Action ID is application-unique must be composed as <moduleID>/<inModuleActionID>.
204 If an action belongs to a desktop or is available even if no module is active (e.g. 'Save As'),
205 use empty string as <moduleID>. Let's call such actions as root actions.
207 There is a need to keep multiple actions, which do the same from user' perspective,
208 bound to the same key sequence. E.g. 'Front view'. Let's call such set of actions as meta-action.
209 Actions of a meta-action may belong to different modules, and/or there may be several actions
210 of the same meta-action in the same module. <inModuleActionID> of all members of a meta-action
211 must be the same and start with "#".
212 Meta-action is root action when it comes to checking for conflicts.
213 Shortcuts of meta-actions are (de)serialized to the same section of preference files as root shortcuts.
215 <inModuleActionID> can contain several "/". Go to \ref isInModuleActionIDValid(const QString&) for details.
216 You can refer to multiple actions, whose <inModuleActionID> starts with the prefix.
218 Only one module can be active at instance. So a key sequence must be unique within a joined temporary table of
219 root and active module shortcuts. An action is allowed to be bound with only key sequence.
222 Avoid assigning shortcuts to instances of QAction and all its descendants directly.
223 (1) Key sequence being bound directly to any registered/intercepted action with valid ID,
224 if the key sequence does not conflict with shortcuts kept by SUIT_ShortcutMgr,
225 is added to the manager and appears in user preference file. If it does conflict,
226 it is reassigned with a key sequence from preference files or
227 disabled and added to user preference files (if the files have no shortcut for the action).
228 (2) Key sequences being bound directly to non-QtxAction instances are disabled.
230 class SUIT_EXPORT SUIT_ShortcutMgr: public QObject
236 SUIT_ShortcutMgr(const SUIT_ShortcutMgr&) = delete;
237 SUIT_ShortcutMgr& operator=(const SUIT_ShortcutMgr&) = delete;
240 virtual ~SUIT_ShortcutMgr();
243 static const QString ROOT_MODULE_ID;
245 /*! \brief Create new singleton-instance of shortcut manager, if it has not been created. */
248 static SUIT_ShortcutMgr* get();
250 /*! \brief Checks whether the theKeySequence is platform-compatible. */
251 static bool isKeySequenceValid(const QKeySequence& theKeySequence);
253 /*! \returns {false, _ } if theKeySequenceString is invalid. */
254 static std::pair<bool, QKeySequence> toKeySequenceIfValid(const QString& theKeySequenceString);
256 /*! \brief Valid module ID does not contain "/" and equals to result of QString(theModuleID).simplified().
257 Empty module ID is valid - it is root module ID. */
258 static bool isModuleIDValid(const QString& theModuleID);
260 /*! \brief Valid in-module action ID may consist of several tokens, separated by "/":
261 <token_0>/<token_1>...<token_N>/<token_N-1>.
262 Each <token> must be non-empty and be equal to QString(<token>).simplified().
263 Empty or "#" in-module action ID is not valid. */
264 static bool isInModuleActionIDValid(const QString& theInModuleActionID);
266 /*! \returns true, is theInModuleActionID starts with "#". */
267 static bool isInModuleMetaActionID(const QString& theInModuleActionID);
269 /*! \brief Extracts module ID and in-module action ID from application-unique action ID.
270 The theActionID must be composed as <moduleID>/<inModuleActionID>.
271 \returns { _ , "" }, if theActionID is invalid. */
272 static std::pair<QString, QString> splitIntoModuleIDAndInModuleID(const QString& theActionID);
274 /*! See \ref splitIntoModuleIDAndInModuleID(const QString&). */
275 static bool isActionIDValid(const QString& theActionID);
277 /*! \brief Creates application-unique action ID. Reverse to splitIntoModuleIDAndInModuleID.
278 \returns Emppty string, if either theModuleID or theInModuleActionID is invalid*/
279 static QString makeActionID(const QString& theModuleID, const QString& theInModuleActionID);
281 /*! \brief Sets all shortcuts from preferences to theContainer. Incoming shortcuts override existing ones.
282 If the container has shortcut for an action, which is absent in preferences, and the existing shortcut
283 does not conflict with incoming ones, it is untouched.
284 See \ref setShortcutsFromPreferences() for details.
285 \param theDefaultOnly If true, user preferences are ignored and only default preferences are used. */
286 static void fillContainerFromPreferences(SUIT_ShortcutContainer& theContainer, bool theDefaultOnly);
288 /*! \brief Checks the resource manager directly.
289 \returns {assetsExist, assets}. */
290 static std::pair<bool, SUIT_ActionAssets> getActionAssetsFromResources(const QString& theActionID);
292 /*! \returns Language, which is set in resource manager. */
293 static QString getLang();
296 /*! \brief Add theAction to map of managed actions. */
297 void registerAction(const QString& theActionID, QAction* theAction);
299 /*! \brief Add theAction to map of managed actions. QtxAction::ID() is used as action ID. */
300 void registerAction(QtxAction* theAction);
302 /*! \brief Get registered actions. If theInModuleActionID is meta-action ID, seeks in all modules. */
303 std::set<QAction*> getActions(const QString& theModuleID, const QString& theInModuleActionID) const;
305 /*! \brief Get module ID and in-module-ID of theAction.
306 \returns { _ , "" } if theAction is not registered. */
307 std::pair<QString, QString> getModuleIDAndInModuleID(const QAction* theAction) const;
309 /*! Returns true if theAction is registered. */
310 bool hasAction(const QAction* theAction) const;
312 /*! \brief Get action ID of theActon.
313 \returns empty string if theAction is not registered. */
314 QString getActionID(const QAction* theAction) const;
316 /*! \brief Enables/disable actions of the module.
317 Only those actions are affected, whose parent widget is active desktop. */
318 void setActionsOfModuleEnabled(const QString& theModuleID, const bool theEnable = true) const;
320 /*! \brief Enables/disables all registered actions whose in-module action ID begins with theInModuleActionIDPrefix.
321 Only those actions are affected, whose parent widget is active desktop. */
322 void setActionsWithPrefixInIDEnabled(const QString& theInModuleActionIDPrefix, bool theEnable = true) const;
324 [[deprecated("Use setActionsWithPrefixInIDEnabled(const QString&, bool) instead.")]]
325 void setSectionEnabled(const QString& theInModuleActionIDPrefix, bool theEnable = true) const;
327 /*! \brief For all registered actions binds key sequences from myShortcutContainer. */
328 void rebindActionsToKeySequences() const;
330 [[deprecated("Use rebindActionsToKeySequences() instead.")]]
331 void updateShortcuts() const;
333 /*! \brief Checks for conflicts. If theOverride, modifies incoming and disables all conflicting shortcuts.
334 Then binds key sequences with corresponding registered actions. Saves changes to preferences.
336 Redefining a key sequence for the action, if the key sequence does not conflict with other shortcuts, is not considered as a conflict.
337 \param theInModuleActionID The method has no effect if theInModuleActionID is empty.
338 \param theKeySequence Empty theKeySequence does not cause conflicts, in this case
339 a shortcut for the action is disabled: theInModuleActionID is added/retained in the container but mapped to empty key sequence.
340 \param theOverride If true, conflicting shortcuts are disabled.
341 \returns {moduleID, inModuleActionID}[] - Set of conflicting actions if theOverride = false,
342 otherwise set of actions (without incoming one), whose shortcuts have been disabled. */
343 std::set<std::pair<QString, QString>> setShortcut(const QString& theActionID, const QKeySequence& theKeySequence, bool theOverride = false);
344 std::set<std::pair<QString, QString>> setShortcut(const QString& theModuleID, const QString& theInModuleActionID, const QKeySequence& theKeySequence, bool theOverride = false);
346 const SUIT_ShortcutContainer& getShortcutContainer() const;
348 /*! \brief Does not perform validity checks on theModuleID and theInModuleActionID. */
349 void mergeShortcutContainer(const SUIT_ShortcutContainer& theContainer, bool theOverride = true, bool theTreatAbsentIncomingAsDisabled = false);
351 /*! \brief Get a key sequence mapped to the action. */
352 QKeySequence getKeySequence(const QString& theModuleID, const QString& theInModuleActionID) const;
354 /*! \returns {inModuleActionID, keySequence}[] */
355 const std::map<QString, QKeySequence>& getModuleShortcutsInversed(const QString& theModuleID) const;
357 /*! \returns All module IDs, which were added to myShortcutContainer. */
358 std::set<QString> getShortcutModuleIDs() const;
360 /*! \returns IDs of modules, which interfere with the module:
361 if the module is root (theModuleID is empty) - returns all module IDs, otherwise returns ["", theModuleID]. */
362 std::set<QString> getIDsOfInterferingModules(const QString& theModuleID) const;
364 /*! \returns assets, which describe module's header, not its content. */
365 std::shared_ptr<const SUIT_ActionAssets> getModuleAssets(const QString& theModuleID) const;
367 /*! \returns assets, which describe modules' headers, not their content. */
368 std::map<QString, std::shared_ptr<SUIT_ActionAssets>> getModuleAssets() const { return myModuleAssets; }
370 /*! \brief Retrieves module name, if the asset was loaded using \ref setAssetsFromResources(). If theLang is empty, it is effectively current language. */
371 QString getModuleName(const QString& theModuleID, const QString& theLang = "") const;
373 std::shared_ptr<const SUIT_ActionAssets> getActionAssets(const QString& theModuleID, const QString& theInModuleActionID) const;
375 std::shared_ptr<const SUIT_ActionAssets> getActionAssets(const QString& theActionID) const;
377 std::map<QString, std::map<QString, std::shared_ptr<SUIT_ActionAssets>>> getActionAssets() const { return myActionAssets; }
379 /*! \brief Retrieves action name, if the asset was loaded using \ref setAssetsFromResources(). If theLang is empty, it is effectively current language. */
380 QString getActionName(const QString& theModuleID, const QString& theInModuleActionID, const QString& theLang = "") const;
384 \brief Called when the corresponding action is destroyed.
385 Removes destroyed action from maps of registered actions. Preserves shortcut.
386 \param theObject action being destroyed.
388 void onActionDestroyed(QObject* theObject);
391 /*! \brief Overrides QObject::eventFilter().
392 If theEvent is QEvent::ActionAdded and the action is instance of QtxAction, registers it. */
393 virtual bool eventFilter(QObject* theObject, QEvent* theEvent);
395 /*! \brief Does not perform validity checks on theModuleID and theInModuleActionID. */
396 std::set<std::pair<QString, QString>> setShortcutNoIDChecks(const QString& theModuleID, const QString& theInModuleActionID, const QKeySequence& theKeySequence, bool theOverride);
398 /*! \brief Set shortcuts from preference files. The method is intended to be called before any calls to setShortcut() or mergeShortcutContainer().
399 Definition of this method assumes, that shortcut settings are serialized as prerefence entries {name=<inModuleActionID>, val=<keySequence>}
400 in dedicated section for each module, with names of sections being composed as "shortcuts:<moduleID>".
402 E.g. in case of XML file it may look like this:
404 <section name="<module ID>">
406 <parameter name="<in-module action ID>" value="key sequence">
410 <section name="shortcuts:">
411 <parameter name="TOT_DESK_FILE_NEW" value="Ctrl+N"/>
412 <parameter name="TOT_DESK_FILE_OPEN" value="Ctrl+O"/>
413 <parameter name="#General/Show object(s)" value="Ctrl+Alt+S"/>
414 <parameter name="#General/Hide object(s)" value="Ctrl+Alt+H"/>
415 <parameter name="#Viewers/Back view" value="Ctrl+Alt+B"/>
416 <parameter name="#Viewers/Front view" value="Ctrl+Alt+F"/>
418 <section name="shortcuts:GEOM">
419 <parameter name="Isolines/Increase number" value="Meta+I"/>
420 <parameter name="Isolines/Decrease number" value="Meta+D"/>
421 <parameter name="Transparency/Increase" value="Meta+Y"/>
422 <parameter name="Transparency/Decrease" value="Meta+T"/>
425 Empty inModuleActionIDs are ignored.
427 nb! For any theQtxAction you wish user be able to assign it to a shortcut,
428 add theQtxAction.ID() to default resource files (you can map it to no key sequence).*/
429 void setShortcutsFromPreferences();
431 /*! \brief Writes shortcuts to preference files.
432 \param theShortcuts { moduleID, { inModuleActionID, keySequence }[] }[]. Empty inModuleActionIDs are ignored. */
433 static void saveShortcutsToPreferences(const std::map<QString, std::map<QString, QKeySequence>>& theShortcutsInversed);
435 /*! Fills myActionAssets from asset files in theLanguage.
436 \param theLanguage If default, fills assets in current language.
437 If an asset in requested language is not found, seeks for the asset EN in and then in FR.
439 Asset files must be structured like this:
443 "langDependentAssets": {
456 void setAssetsFromResources(QString theLanguage = QString());
459 static SUIT_ShortcutMgr* myShortcutMgr;
461 /** { moduleID, { inModuleActionID, action[] }[] }[]. May contain entries like { <non-root module ID>, { <meta-action ID>, actions[] } }. */
462 std::map<QString, std::map<QString, std::set<QAction*>>> myActions;
464 /** { action, { moduleID, inModuleActionID } }[]. May contain entries like { <non-root module ID>, { <meta-action ID>, actions[] } }. */
465 std::map<QAction*, std::pair<QString, QString>> myActionIDs; // To maintain uniqueness of actions and effectively retrieve IDs of registered actions.
467 /** Can not contain entries like { <non-root module ID>, { <meta-action ID>, actions[] } }. */
468 SUIT_ShortcutContainer myShortcutContainer;
471 Sets of moduleIDs and inModuleActionIDs are equal for myActions and myActionIDs.
472 Sets of moduleIDs and inModuleActionIDs may NOT be equal for myActions and myShortcutContainer.
475 /* { moduleID, {inModuleActionID, assets}[] }[] */
476 std::map<QString, std::map<QString, std::shared_ptr<SUIT_ActionAssets>>> myActionAssets;
478 /* {moduleID, assets}[] */
479 mutable std::map<QString, std::shared_ptr<SUIT_ActionAssets>> myModuleAssets;
484 \class SUIT_SentenceMatcher
485 \brief Approximate string matcher, treats strings as sentences composed of words.
487 class SUIT_EXPORT SUIT_SentenceMatcher
491 Exact word order = false;
493 Case sensitive = false;
494 Query = ""; // matches nothing.
496 SUIT_SentenceMatcher();
498 void setUseExactWordOrder(bool theOn);
499 void setUseFuzzyWords(bool theOn);
500 void setCaseSensitive(bool theOn);
501 inline bool isCaseSensitive() const { return myIsCaseSensitive; };
503 /*! \param theQuery should not be regex. */
504 void setQuery(QString theQuery);
506 inline const QString& getQuery() const { return myQuery; };
508 /*! \returns match metrics. The metrics >= 0. INF means mismatch.
509 The class is unable to differentiate exact match with some approximate matches! */
510 double match(const QString& theInputString) const;
512 /** \brief For debug. */
513 QString toString() const;
516 static bool makePermutatedSentences(const QStringList& theWords, QList<QStringList>& theSentences);
517 static void makeFuzzyWords(const QStringList& theWords, QStringList& theFuzzyWords);
519 /*! \returns number of characters in matched words. The number >= 0. */
520 static int matchWithSentenceIgnoreEndings(const QString& theInputString, const QStringList& theSentence, bool theCaseSensitive);
521 /*! \returns number of characters in matched words. The number >= 0. */
522 static int matchWithSentencesIgnoreEndings(const QString& theInputString, const QList<QStringList>& theSentences, bool theCaseSensitive);
524 /*! \returns number of characters in matched words. The number >= 0. */
525 static int matchAtLeastOneWord(const QString& theInputString, const QStringList& theWords, bool theCaseSensitive);
527 /*! \returns number of characters in matched words. The number >= 0. */
529 const QString& theInputString,
530 const QStringList& theSentence,
531 bool theCaseSensitive
534 /*! \returns number of characters in matched words. The number >= 0. */
536 const QString& theInputString,
537 const QList<QStringList>& theSentences,
538 bool theCaseSensitive
541 bool myUseExactWordOrder; // If false, try to match with sentences, composed of query's words in different orders.
542 bool myUseFuzzyWords; // Try to match with sentences, composed of query's truncated words.
543 bool myIsCaseSensitive;
546 QStringList myWords; // It is also original search sentence.
547 QList<QStringList> myPermutatedSentences;
549 QStringList myFuzzyWords; // Regexes.
550 QList<QStringList> myFuzzyPermutatedSentences;
555 \class SUIT_ActionSearcher
556 \brief Searches in data, provided in action asset files and shortcut preferences.
558 class SUIT_EXPORT SUIT_ActionSearcher
568 class AssetsAndSearchData
571 AssetsAndSearchData(std::shared_ptr<const SUIT_ActionAssets> theAssets = nullptr, double theMatchMetrics = std::numeric_limits<double>::infinity());
573 void setMatchMetrics(double theMatchMetrics);
574 double matchMetrics() const { return myMatchMetrics; };
576 std::shared_ptr<const SUIT_ActionAssets> myAssets;
578 void toJSON(QJsonObject& oJsonObject) const;
579 QString toString() const;
582 /*! \brief Ideally it should be number of weighted character permutations. Now it is just a number of characters in unmatched words. */
583 double myMatchMetrics;
587 Included modules' IDs = { ROOT_MODULE_ID };
588 Include disabled actions = false;
589 Fields to match = { Name, Tooltip };
590 Case sensitive = false;
591 Fuzzy matching = true;
592 Query = ""; // matches everything.
594 SUIT_ActionSearcher();
595 SUIT_ActionSearcher(const SUIT_ActionSearcher&) = delete;
596 SUIT_ActionSearcher& operator=(const SUIT_ActionSearcher&) = delete;
597 virtual ~SUIT_ActionSearcher() = default;
599 /*! \returns true, if set of results is changed. */
600 bool setIncludedModuleIDs(std::set<QString> theIncludedModuleIDs);
602 /*! \returns true, if set of results is changed. */
603 bool includeDisabledActions(bool theOn);
604 inline bool areDisabledActionsIncluded() const {return myIncludeDisabledActions;};
606 /*! \returns true, if set of results is changed. */
607 bool setFieldsToMatch(const std::set<SUIT_ActionSearcher::MatchField>& theFields);
609 /*! \returns true, if set of results is changed. */
610 bool setCaseSensitive(bool theOn);
612 /*! \returns true, if set of results is changed. */
613 bool setQuery(const QString& theQuery);
614 inline const QString& getQuery() const {return myMatcher.getQuery();};
616 const std::map<QString, std::map<QString, SUIT_ActionSearcher::AssetsAndSearchData>>& getSearchResults() const;
620 /*! \brief Applies filter to all actions, provided in asset files for SUIT_ShortcutMgr.
621 \returns { true, _ } if set of results is changed; { _ , true } if matching metrics is changed for at least one result. */
622 std::pair<bool, bool> filter();
624 /*! \brief Applies filter to search results only.
625 \returns { true, _ } if set of results is shrunk; { _ , true } if matching metrics is changed for at least one result. */
626 std::pair<bool, bool> filterResults();
628 /*! \brief Applies filter only to actions, which are not in search results.
629 \returns True, if set of results is extended. */
630 bool extendResults();
632 double matchAction(const QString& theModuleID, const QString& theInModuleActionID, std::shared_ptr<const SUIT_ActionAssets> theAssets);
634 QString toString() const;
637 std::set<QString> myIncludedModuleIDs;
638 bool myIncludeDisabledActions;
640 std::set<SUIT_ActionSearcher::MatchField> myFieldsToMatch;
641 SUIT_SentenceMatcher myMatcher;
643 /* { moduleID, {inModuleActionID, assetsAndSearchData}[] }[]. */
644 std::map<QString, std::map<QString, SUIT_ActionSearcher::AssetsAndSearchData>> mySearchResults;
649 #pragma warning( default: 4251 )