mirror of
https://github.com/lucaspalomodevelop/meshlab.git
synced 2026-03-13 00:07:24 +00:00
new deterministic searcher
This commit is contained in:
parent
6e3df79048
commit
17640937f4
@ -65,6 +65,7 @@ set(HEADERS
|
||||
plugins/interfaces/filter_plugin.h
|
||||
plugins/interfaces/io_plugin.h
|
||||
plugins/interfaces/render_plugin.h
|
||||
plugins/action_searcher.h
|
||||
plugins/meshlab_plugin_type.h
|
||||
plugins/plugin_manager.h
|
||||
python/function.h
|
||||
@ -81,8 +82,7 @@ set(HEADERS
|
||||
ml_selection_buffers.h
|
||||
ml_thread_safe_memory_info.h
|
||||
mlapplication.h
|
||||
mlexception.h
|
||||
searcher.h)
|
||||
mlexception.h)
|
||||
|
||||
set(SOURCES
|
||||
ml_document/helpers/mesh_document_state_data.cpp
|
||||
@ -107,6 +107,7 @@ set(SOURCES
|
||||
plugins/interfaces/decorate_plugin.cpp
|
||||
plugins/interfaces/filter_plugin.cpp
|
||||
plugins/interfaces/io_plugin.cpp
|
||||
plugins/action_searcher.cpp
|
||||
plugins/meshlab_plugin_type.cpp
|
||||
plugins/plugin_manager.cpp
|
||||
python/function.cpp
|
||||
@ -121,8 +122,7 @@ set(SOURCES
|
||||
filterscript.cpp
|
||||
ml_selection_buffers.cpp
|
||||
ml_thread_safe_memory_info.cpp
|
||||
mlapplication.cpp
|
||||
searcher.cpp)
|
||||
mlapplication.cpp)
|
||||
|
||||
set(RESOURCES meshlab-common.qrc)
|
||||
|
||||
|
||||
176
src/common/plugins/action_searcher.cpp
Normal file
176
src/common/plugins/action_searcher.cpp
Normal file
@ -0,0 +1,176 @@
|
||||
/*****************************************************************************
|
||||
* MeshLab o o *
|
||||
* A versatile mesh processing toolbox o o *
|
||||
* _ O _ *
|
||||
* Copyright(C) 2005-2022 \/)\/ *
|
||||
* Visual Computing Lab /\/| *
|
||||
* ISTI - Italian National Research Council | *
|
||||
* \ *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) *
|
||||
* for more details. *
|
||||
* *
|
||||
****************************************************************************/
|
||||
|
||||
#include "action_searcher.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <QRegExp>
|
||||
|
||||
#include "interfaces/filter_plugin.h"
|
||||
|
||||
ActionSearcher::ActionSearcher()
|
||||
{
|
||||
}
|
||||
|
||||
void ActionSearcher::clear()
|
||||
{
|
||||
titleActionsMap.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Adds the given action to the ActionSearcher, allowing queries to it.
|
||||
* @param action
|
||||
*/
|
||||
void ActionSearcher::addAction(QAction *action, bool usePythonFilterNames)
|
||||
{
|
||||
if (action != nullptr) {
|
||||
if (!usePythonFilterNames) {
|
||||
// add title to the action map
|
||||
QString title = action->text();
|
||||
title = title.toLower();
|
||||
title.remove(ignexp);
|
||||
QStringList res = title.split(sepexp, Qt::SkipEmptyParts);
|
||||
res.removeDuplicates();
|
||||
addSubStrings(res);
|
||||
for (const QString& str : qAsConst(res)) {
|
||||
titleActionsMap[str].push_back(action);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// if the action is a filter, we should add also the python name to the search
|
||||
QObject* parent = action->parent();
|
||||
FilterPlugin* fp = qobject_cast<FilterPlugin*>(parent);
|
||||
if (fp) {
|
||||
QString title = fp->pythonFilterName(action);
|
||||
title.replace("_", " ");
|
||||
title.remove(ignexp);
|
||||
QStringList res = title.split(sepexp, Qt::SkipEmptyParts);
|
||||
res.removeDuplicates();
|
||||
addSubStrings(res);
|
||||
for (const QString& str : qAsConst(res)) {
|
||||
titleActionsMap[str].push_back(action);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// add info to the action map
|
||||
QString info = action->toolTip();
|
||||
info = info.toLower();
|
||||
info.remove(ignexp);
|
||||
QStringList res = info.split(sepexp, Qt::SkipEmptyParts);
|
||||
res.removeDuplicates();
|
||||
addSubStrings(res);
|
||||
for (const QString& str : qAsConst(res)) {
|
||||
infoActionsMap[str].push_back(action);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Performs a query using the inputString and returns an array containing the best matching
|
||||
* actions matching to the input string.
|
||||
*
|
||||
* The array will have maximum size equal to maxNumberactions.
|
||||
* @param inputString: query string
|
||||
* @param maxNumberActions: maximum size of the output array
|
||||
* @return array containing the best matching actions
|
||||
*/
|
||||
std::vector<QAction *> ActionSearcher::bestMatchingActions(QString inputString, int maxNumberActions) const
|
||||
{
|
||||
std::vector<QAction *> res;
|
||||
|
||||
// clean the input string
|
||||
inputString = inputString.toLower();
|
||||
inputString.replace("_", " "); // to allow python search
|
||||
inputString.remove(ignexp);
|
||||
|
||||
// split the input string
|
||||
QStringList inputList = inputString.split(sepexp, Qt::SkipEmptyParts);
|
||||
inputList.removeDuplicates();
|
||||
|
||||
const float bonuspertitleword = 1.0f / std::pow(10,inputList.size());
|
||||
|
||||
// store the ranking for each action
|
||||
std::map<QAction*, float> actionRanking;
|
||||
|
||||
// for each input string
|
||||
for (const QString& str : qAsConst(inputList)) {
|
||||
auto it = titleActionsMap.find(str);
|
||||
// if matches in a title of an action
|
||||
if (it != titleActionsMap.end()) {
|
||||
for (QAction* act : it->second) { // for each matching action, increment its ranking
|
||||
actionRanking[act] += bonuspertitleword;
|
||||
}
|
||||
}
|
||||
it = infoActionsMap.find(str);
|
||||
// if matches in a info of an action
|
||||
if (it != infoActionsMap.end()) {
|
||||
for (QAction* act : it->second) { // for each matching action, increment its ranking
|
||||
actionRanking[act]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::map<float, std::vector<QAction*>> rankingMap; // flipped map of actionRanking
|
||||
// populate the flipped map
|
||||
for (const auto& p : actionRanking) {
|
||||
// for each ranking, push another action havint that ranking
|
||||
rankingMap[p.second].push_back(p.first);
|
||||
}
|
||||
// at the end, the map will store the actions stored by ranking
|
||||
|
||||
int count = 0; // used to stop the number of inserted actions in the resulting vector
|
||||
|
||||
// reverse iteration: start from the biggest ranking
|
||||
for (auto it = rankingMap.rbegin(); it != rankingMap.rend() && count < maxNumberActions; ++it) {
|
||||
auto v1 = it->second;
|
||||
// need to sort properly actions having the same ranking, since they would be sorted using
|
||||
// memory addresses, that are not deterministic: we use action titles
|
||||
std::sort(v1.begin(), v1.end(), ActionComparator());
|
||||
// insert the sorted actions to the result vector
|
||||
res.insert(res.end(), v1.begin(), v1.end());
|
||||
count += it->second.size();
|
||||
}
|
||||
// if at the end the number exceeded the maximum number, we truncate the array
|
||||
if (count >= maxNumberActions) {
|
||||
res.resize(maxNumberActions);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void ActionSearcher::addSubStrings(QStringList &res)
|
||||
{
|
||||
QStringList resWithPrefix;
|
||||
foreach(QString str, res)
|
||||
{
|
||||
QString strPref = str;
|
||||
resWithPrefix.push_back(strPref);
|
||||
for(int i=0;i<str.length()-3;++i)
|
||||
{
|
||||
strPref.chop(1);
|
||||
resWithPrefix.push_back(strPref);
|
||||
}
|
||||
}
|
||||
resWithPrefix.removeDuplicates();
|
||||
res = resWithPrefix;
|
||||
}
|
||||
62
src/common/plugins/action_searcher.h
Normal file
62
src/common/plugins/action_searcher.h
Normal file
@ -0,0 +1,62 @@
|
||||
/*****************************************************************************
|
||||
* MeshLab o o *
|
||||
* A versatile mesh processing toolbox o o *
|
||||
* _ O _ *
|
||||
* Copyright(C) 2005-2022 \/)\/ *
|
||||
* Visual Computing Lab /\/| *
|
||||
* ISTI - Italian National Research Council | *
|
||||
* \ *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) *
|
||||
* for more details. *
|
||||
* *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef ACTION_SEARCHER_H
|
||||
#define ACTION_SEARCHER_H
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <QString>
|
||||
#include <QAction>
|
||||
|
||||
class ActionSearcher
|
||||
{
|
||||
public:
|
||||
ActionSearcher();
|
||||
|
||||
void clear();
|
||||
void addAction(QAction* action, bool usePythonFilterNames = false);
|
||||
|
||||
std::vector<QAction*> bestMatchingActions(QString inputString, int maxNumberActions) const;
|
||||
|
||||
private:
|
||||
const QRegExp sepexp = QRegExp("\\W+");
|
||||
const QRegExp ignexp = QRegExp(
|
||||
"\\b(an|the|of|it|as|in|by|and|or|for)\\b|\\b[a-z]\\b|'s\\b|\\.|<[^>]*>");
|
||||
|
||||
// map that stores, for each string, all the actions that store that string in their titles
|
||||
std::map<QString, std::vector<QAction*>> titleActionsMap;
|
||||
|
||||
// map that stores, for each stirng, all the actions that store that stirng in their info
|
||||
std::map<QString, std::vector<QAction*>> infoActionsMap;
|
||||
|
||||
struct ActionComparator {
|
||||
bool operator()(QAction* a1, QAction* a2) {
|
||||
return a1->text() < a2->text();
|
||||
}
|
||||
};
|
||||
|
||||
static void addSubStrings(QStringList& res);
|
||||
};
|
||||
|
||||
#endif // ACTION_SEARCHER_H
|
||||
@ -1,151 +0,0 @@
|
||||
#include "searcher.h"
|
||||
#include "mlexception.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
WordActionsMap::WordActionsMap()
|
||||
:wordacts()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void WordActionsMap::addWordsPerAction(QAction& act,const QStringList& words)
|
||||
{
|
||||
foreach(QString word,words)
|
||||
wordacts[word].push_back(&act);
|
||||
}
|
||||
|
||||
void WordActionsMap::removeActionReferences(QAction& act )
|
||||
{
|
||||
for(QMap<QString,QList<QAction*> >::iterator it = wordacts.begin();it != wordacts.end();++it)
|
||||
it.value().removeAll(&act);
|
||||
}
|
||||
|
||||
bool WordActionsMap::getActionsPerWord( const QString& word,QList<QAction*>& res ) const
|
||||
{
|
||||
QMap< QString,QList<QAction*> >::const_iterator it = wordacts.find(word);
|
||||
if (it != wordacts.end())
|
||||
{
|
||||
res = it.value();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void WordActionsMap::clear()
|
||||
{
|
||||
wordacts.clear();
|
||||
}
|
||||
|
||||
WordActionsMapAccessor::WordActionsMapAccessor()
|
||||
:map(),sepexp(),ignexp()
|
||||
{
|
||||
sepexp.setPattern("\\W+");
|
||||
ignexp.setPattern("\\b(an|the|of|it|as|in|by|and|or|for)\\b|\\b[a-z]\\b|'s\\b|\\.|<[^>]*>");
|
||||
}
|
||||
|
||||
void WordActionsMapAccessor::addWordsPerAction(QAction& act,const QString& st )
|
||||
{
|
||||
QStringList wlist;
|
||||
purifiedSplit(st,wlist);
|
||||
addSubStrings(wlist);
|
||||
map.addWordsPerAction(act,wlist);
|
||||
}
|
||||
|
||||
int WordActionsMapAccessor::rankedMatchesPerInputString( const QString& input,RankedMatches& rm ) const
|
||||
{
|
||||
QStringList inputlist;
|
||||
purifiedSplit(input,inputlist);
|
||||
return rm.computeRankedMatches(inputlist,map);
|
||||
}
|
||||
|
||||
void WordActionsMapAccessor::purifiedSplit( const QString& input,QStringList& res ) const
|
||||
{
|
||||
res.clear();
|
||||
QString tmp = input;
|
||||
tmp = tmp.toLower();
|
||||
tmp.remove(ignexp);
|
||||
res = tmp.split(sepexp,QString::SkipEmptyParts);
|
||||
res.removeDuplicates();
|
||||
}
|
||||
|
||||
void WordActionsMapAccessor::addSubStrings( QStringList& res ) const
|
||||
{
|
||||
QStringList resWithPrefix;
|
||||
foreach(QString str, res)
|
||||
{
|
||||
QString strPref = str;
|
||||
resWithPrefix.push_back(strPref);
|
||||
for(int i=0;i<str.length()-3;++i)
|
||||
{
|
||||
strPref.chop(1);
|
||||
resWithPrefix.push_back(strPref);
|
||||
}
|
||||
}
|
||||
resWithPrefix.removeDuplicates();
|
||||
res = resWithPrefix;
|
||||
}
|
||||
|
||||
RankedMatches::RankedMatches()
|
||||
:ranking()
|
||||
{
|
||||
}
|
||||
|
||||
int RankedMatches::computeRankedMatches( const QStringList& inputst,const WordActionsMap& map, bool matchesontitlearemoreimportant)
|
||||
{
|
||||
QMap<QAction*, float> wordmatchesperaction;
|
||||
ranking.clear();
|
||||
int inputstsize = inputst.size();
|
||||
ranking.resize(inputstsize);
|
||||
float bonuspertitleword = 0.0f;
|
||||
if (matchesontitlearemoreimportant)
|
||||
bonuspertitleword = 1.0f / std::pow(10,inputstsize);
|
||||
foreach(const QString& st,inputst)
|
||||
{
|
||||
QList<QAction*> res;
|
||||
bool found = map.getActionsPerWord(st,res);
|
||||
if (found)
|
||||
{
|
||||
foreach(QAction* act, res)
|
||||
{
|
||||
++wordmatchesperaction[act];
|
||||
QString title = act->text().toLower().trimmed();
|
||||
if (title.contains(st))
|
||||
wordmatchesperaction[act] = wordmatchesperaction[act] + bonuspertitleword;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QMap<float, QList<QAction*> > rankedmatches;
|
||||
for (QMap<QAction*, float>::iterator it = wordmatchesperaction.begin(); it != wordmatchesperaction.end(); ++it)
|
||||
rankedmatches[it.value()].push_back(it.key());
|
||||
|
||||
int maxindex = -1;
|
||||
for(QMap<float,QList<QAction*> >::iterator it = rankedmatches.end() - 1;it != rankedmatches.begin() - 1;--it)
|
||||
{
|
||||
int index = std::floor(it.key()) - 1;
|
||||
if (index >= ranking.size())
|
||||
{
|
||||
throw InvalidInvariantException("WARNING! Index contained in wordmatchesperaction it's out-of-bound.");
|
||||
return 0;
|
||||
}
|
||||
if (index > maxindex)
|
||||
maxindex = index;
|
||||
ranking[index].append(it.value());
|
||||
}
|
||||
return maxindex + 1;
|
||||
}
|
||||
|
||||
void RankedMatches::getActionsWithNMatches( const int n,QList<QAction*>& res )
|
||||
{
|
||||
res.clear();
|
||||
int index = n -1;
|
||||
if ((index >= ranking.size()) || (n < 1))
|
||||
{
|
||||
throw InvalidInvariantException(QString("WARNING! Parameter n MUST be in the range [1..") + QString::number(ranking.size()) + "].");
|
||||
return;
|
||||
}
|
||||
res = ranking[index];
|
||||
}
|
||||
|
||||
|
||||
@ -1,58 +0,0 @@
|
||||
#ifndef SEARCHER_H
|
||||
#define SEARCHER_H
|
||||
|
||||
#include<QString>
|
||||
#include<QMap>
|
||||
#include<QList>
|
||||
#include<QAction>
|
||||
#include<QRegExp>
|
||||
#include<QVector>
|
||||
#include<QSet>
|
||||
|
||||
class WordActionsMap
|
||||
{
|
||||
public:
|
||||
WordActionsMap();
|
||||
void addWordsPerAction(QAction& act,const QStringList& words);
|
||||
void removeActionReferences(QAction& act);
|
||||
bool getActionsPerWord( const QString& word,QList<QAction*>& res ) const;
|
||||
void clear();
|
||||
private:
|
||||
QMap<QString,QList<QAction*> > wordacts;
|
||||
};
|
||||
|
||||
class RankedMatches;
|
||||
|
||||
class WordActionsMapAccessor
|
||||
{
|
||||
public:
|
||||
WordActionsMapAccessor();
|
||||
void addWordsPerAction(QAction& act,const QString& st);
|
||||
inline void removeActionReferences(QAction& act) {map.removeActionReferences(act);}
|
||||
inline void setSeparator(const QRegExp& sep) {sepexp = sep;}
|
||||
inline void setIgnoredWords(const QRegExp& ign) {ignexp = ign;}
|
||||
int rankedMatchesPerInputString(const QString& input,RankedMatches& rm) const;
|
||||
inline QRegExp separtor() const {return sepexp;}
|
||||
inline QRegExp ignored() const {return ignexp;}
|
||||
void clear() {map.clear(); sepexp = QRegExp(); ignexp = QRegExp();}
|
||||
|
||||
private:
|
||||
void purifiedSplit(const QString& input,QStringList& res) const;
|
||||
void addSubStrings(QStringList& res) const;
|
||||
WordActionsMap map;
|
||||
QRegExp sepexp;
|
||||
QRegExp ignexp;
|
||||
};
|
||||
|
||||
class RankedMatches
|
||||
{
|
||||
public:
|
||||
RankedMatches();
|
||||
void getActionsWithNMatches(const int n,QList<QAction*>& res);
|
||||
private:
|
||||
friend int WordActionsMapAccessor::rankedMatchesPerInputString(const QString& input,RankedMatches& rm) const;
|
||||
int computeRankedMatches(const QStringList& inputst,const WordActionsMap& map,bool matchesontitlearemoreimportant = true);
|
||||
QVector<QList<QAction*> > ranking;
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -8,7 +8,7 @@
|
||||
#include <QStyle>
|
||||
#include <QDebug>
|
||||
|
||||
SearchMenu::SearchMenu(const WordActionsMapAccessor& wm,const int max,QWidget* parent,const int fixedwidth)
|
||||
SearchMenu::SearchMenu(const ActionSearcher& wm,const int max,QWidget* parent,const int fixedwidth)
|
||||
:MenuWithToolTip(QString(),parent),searchline(NULL),wama(wm),maxres(max),fixedwidthsize(fixedwidth)
|
||||
{
|
||||
searchline = new MenuLineEdit(this);
|
||||
@ -24,29 +24,14 @@ SearchMenu::SearchMenu(const WordActionsMapAccessor& wm,const int max,QWidget* p
|
||||
|
||||
void SearchMenu::getResults(const QString& text,QList<QAction*>& result)
|
||||
{
|
||||
try
|
||||
{
|
||||
RankedMatches rm;
|
||||
int ii = wama.rankedMatchesPerInputString(text,rm);
|
||||
int inserted = 0;
|
||||
while(ii > 0)
|
||||
{
|
||||
QList<QAction*> myacts;
|
||||
rm.getActionsWithNMatches(ii,myacts);
|
||||
if (inserted + myacts.size() > maxres)
|
||||
myacts = myacts.mid(0,myacts.size() - (inserted + myacts.size() - maxres));
|
||||
result.append(myacts);
|
||||
QAction* sep = new QAction(this);
|
||||
sep->setSeparator(true);
|
||||
result.append(sep);
|
||||
inserted += myacts.size();
|
||||
--ii;
|
||||
}
|
||||
}
|
||||
catch(InvalidInvariantException& e)
|
||||
{
|
||||
qDebug() << "WARNING!!!!!!!!!!!!!!!!!!!" << e.what() << "\n";
|
||||
}
|
||||
std::vector<QAction*> rm = wama.bestMatchingActions(text, 15);
|
||||
|
||||
for (QAction* act : rm) {
|
||||
result.append(act);
|
||||
}
|
||||
QAction* sep = new QAction(this);
|
||||
sep->setSeparator(true);
|
||||
result.append(sep);
|
||||
}
|
||||
|
||||
void SearchMenu::updateGUI( const QList<QAction*>& results )
|
||||
|
||||
@ -20,7 +20,7 @@
|
||||
#include <QPushButton>
|
||||
#include <QLabel>
|
||||
#include <QSlider>
|
||||
#include "../common/searcher.h"
|
||||
#include "../common/plugins/action_searcher.h"
|
||||
#include <QToolTip>
|
||||
#include <QSyntaxHighlighter>
|
||||
#include <QProxyStyle>
|
||||
@ -75,7 +75,7 @@ class SearchMenu : public MenuWithToolTip
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
SearchMenu(const WordActionsMapAccessor& wm,const int max,QWidget* parent,const int fixedwidth = -1);
|
||||
SearchMenu(const ActionSearcher& wm,const int max,QWidget* parent,const int fixedwidth = -1);
|
||||
int& searchLineWidth();
|
||||
void clearResults();
|
||||
QSize sizeHint () const;
|
||||
@ -84,7 +84,7 @@ protected:
|
||||
void resizeEvent ( QResizeEvent * event);
|
||||
private:
|
||||
MenuLineEdit* searchline;
|
||||
const WordActionsMapAccessor& wama;
|
||||
const ActionSearcher& wama;
|
||||
int maxres;
|
||||
int fixedwidthsize;
|
||||
|
||||
|
||||
@ -361,7 +361,7 @@ public:
|
||||
QMenu* rasterLayerMenu() { return filterMenuRasterLayer; }
|
||||
|
||||
private:
|
||||
WordActionsMapAccessor wama;
|
||||
ActionSearcher wama;
|
||||
//////// ToolBars ///////////////
|
||||
QToolBar* mainToolBar;
|
||||
QToolBar* decoratorToolBar;
|
||||
|
||||
@ -36,7 +36,6 @@
|
||||
#include <QWidgetAction>
|
||||
#include <QMessageBox>
|
||||
#include "mainwindow.h"
|
||||
#include <common/searcher.h>
|
||||
#include <common/mlapplication.h>
|
||||
#include <common/mlexception.h>
|
||||
#include <common/globals.h>
|
||||
@ -692,8 +691,7 @@ void MainWindow::initMenuForSearching(QMenu* menu)
|
||||
|
||||
void MainWindow::initItemForSearching(QAction* act)
|
||||
{
|
||||
QString tx = act->text() + " " + act->toolTip();
|
||||
wama.addWordsPerAction(*act, tx);
|
||||
wama.addAction(act);
|
||||
}
|
||||
|
||||
QString MainWindow::getDecoratedFileName(const QString& name)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user