mirror of
https://gitee.com/vnotex/vnote.git
synced 2025-07-05 05:49:53 +08:00
UnitedEntry: support United Entry
This commit is contained in:
parent
2908148c00
commit
dba9fb30e8
@ -27,7 +27,7 @@ CommandLineOptions::ParseResult CommandLineOptions::parse(const QStringList &p_a
|
|||||||
{
|
{
|
||||||
QCommandLineOption webRemoteDebuggingPortOpt("remote-debugging-port",
|
QCommandLineOption webRemoteDebuggingPortOpt("remote-debugging-port",
|
||||||
MainWindow::tr("WebEngine remote debugging port."),
|
MainWindow::tr("WebEngine remote debugging port."),
|
||||||
"port_number");
|
MainWindow::tr("port_number"));
|
||||||
webRemoteDebuggingPortOpt.setFlags(QCommandLineOption::HiddenFromHelp);
|
webRemoteDebuggingPortOpt.setFlags(QCommandLineOption::HiddenFromHelp);
|
||||||
parser.addOption(webRemoteDebuggingPortOpt);
|
parser.addOption(webRemoteDebuggingPortOpt);
|
||||||
|
|
||||||
|
@ -88,6 +88,8 @@ void CoreConfig::init(const QJsonObject &p_app,
|
|||||||
}
|
}
|
||||||
|
|
||||||
loadFileTypeSuffixes(appObj, userObj);
|
loadFileTypeSuffixes(appObj, userObj);
|
||||||
|
|
||||||
|
loadUnitedEntry(appObj, userObj);
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonObject CoreConfig::toJson() const
|
QJsonObject CoreConfig::toJson() const
|
||||||
@ -105,6 +107,7 @@ QJsonObject CoreConfig::toJson() const
|
|||||||
obj[QStringLiteral("per_notebook_history")] = m_perNotebookHistoryEnabled;
|
obj[QStringLiteral("per_notebook_history")] = m_perNotebookHistoryEnabled;
|
||||||
obj[QStringLiteral("line_ending")] = lineEndingPolicyToString(m_lineEnding);
|
obj[QStringLiteral("line_ending")] = lineEndingPolicyToString(m_lineEnding);
|
||||||
obj[QStringLiteral("file_type_suffixes")] = saveFileTypeSuffixes();
|
obj[QStringLiteral("file_type_suffixes")] = saveFileTypeSuffixes();
|
||||||
|
obj[QStringLiteral("united_entry")] = saveUnitedEntry();
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -297,6 +300,25 @@ QJsonArray CoreConfig::saveFileTypeSuffixes() const
|
|||||||
return arr;
|
return arr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CoreConfig::loadUnitedEntry(const QJsonObject &p_app, const QJsonObject &p_user)
|
||||||
|
{
|
||||||
|
QJsonObject unitedObj;
|
||||||
|
if (p_user.contains(QStringLiteral("united_entry"))) {
|
||||||
|
unitedObj = p_user[QStringLiteral("united_entry")].toObject();
|
||||||
|
} else {
|
||||||
|
unitedObj = p_app[QStringLiteral("united_entry")].toObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_unitedEntryAlias = unitedObj[QStringLiteral("alias")].toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonObject CoreConfig::saveUnitedEntry() const
|
||||||
|
{
|
||||||
|
QJsonObject unitedObj;
|
||||||
|
unitedObj[QStringLiteral("alias")] = m_unitedEntryAlias;
|
||||||
|
return unitedObj;
|
||||||
|
}
|
||||||
|
|
||||||
const QVector<CoreConfig::FileTypeSuffix> &CoreConfig::getFileTypeSuffixes() const
|
const QVector<CoreConfig::FileTypeSuffix> &CoreConfig::getFileTypeSuffixes() const
|
||||||
{
|
{
|
||||||
return m_fileTypeSuffixes;
|
return m_fileTypeSuffixes;
|
||||||
@ -321,3 +343,13 @@ const QStringList *CoreConfig::findFileTypeSuffix(const QString &p_name) const
|
|||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const QJsonArray &CoreConfig::getUnitedEntryAlias() const
|
||||||
|
{
|
||||||
|
return m_unitedEntryAlias;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CoreConfig::setUnitedEntryAlias(const QJsonArray &p_alias)
|
||||||
|
{
|
||||||
|
updateConfig(m_unitedEntryAlias, p_alias, this);
|
||||||
|
}
|
||||||
|
@ -68,6 +68,7 @@ namespace vnotex
|
|||||||
MoveOneSplitUp,
|
MoveOneSplitUp,
|
||||||
MoveOneSplitRight,
|
MoveOneSplitRight,
|
||||||
OpenLastClosedFile,
|
OpenLastClosedFile,
|
||||||
|
UnitedEntry,
|
||||||
MaxShortcut
|
MaxShortcut
|
||||||
};
|
};
|
||||||
Q_ENUM(Shortcut)
|
Q_ENUM(Shortcut)
|
||||||
@ -133,6 +134,9 @@ namespace vnotex
|
|||||||
|
|
||||||
const QStringList *findFileTypeSuffix(const QString &p_name) const;
|
const QStringList *findFileTypeSuffix(const QString &p_name) const;
|
||||||
|
|
||||||
|
const QJsonArray &getUnitedEntryAlias() const;
|
||||||
|
void setUnitedEntryAlias(const QJsonArray &p_alias);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class MainConfig;
|
friend class MainConfig;
|
||||||
|
|
||||||
@ -146,6 +150,10 @@ namespace vnotex
|
|||||||
|
|
||||||
QJsonArray saveFileTypeSuffixes() const;
|
QJsonArray saveFileTypeSuffixes() const;
|
||||||
|
|
||||||
|
void loadUnitedEntry(const QJsonObject &p_app, const QJsonObject &p_user);
|
||||||
|
|
||||||
|
QJsonObject saveUnitedEntry() const;
|
||||||
|
|
||||||
// Theme name.
|
// Theme name.
|
||||||
QString m_theme;
|
QString m_theme;
|
||||||
|
|
||||||
@ -181,6 +189,8 @@ namespace vnotex
|
|||||||
|
|
||||||
QVector<FileTypeSuffix> m_fileTypeSuffixes;
|
QVector<FileTypeSuffix> m_fileTypeSuffixes;
|
||||||
|
|
||||||
|
QJsonArray m_unitedEntryAlias;
|
||||||
|
|
||||||
static QStringList s_availableLocales;
|
static QStringList s_availableLocales;
|
||||||
};
|
};
|
||||||
} // ns vnotex
|
} // ns vnotex
|
||||||
|
@ -20,9 +20,7 @@
|
|||||||
using namespace vnotex;
|
using namespace vnotex;
|
||||||
|
|
||||||
VNoteX::VNoteX(QObject *p_parent)
|
VNoteX::VNoteX(QObject *p_parent)
|
||||||
: QObject(p_parent),
|
: QObject(p_parent)
|
||||||
m_mainWindow(nullptr),
|
|
||||||
m_notebookMgr(nullptr)
|
|
||||||
{
|
{
|
||||||
m_instanceId = QRandomGenerator::global()->generate64();
|
m_instanceId = QRandomGenerator::global()->generate64();
|
||||||
|
|
||||||
|
@ -132,19 +132,19 @@ namespace vnotex
|
|||||||
|
|
||||||
void initQuickAccess();
|
void initQuickAccess();
|
||||||
|
|
||||||
MainWindow *m_mainWindow;
|
MainWindow *m_mainWindow = nullptr;
|
||||||
|
|
||||||
// QObject managed.
|
// QObject managed.
|
||||||
ThemeMgr *m_themeMgr;
|
ThemeMgr *m_themeMgr = nullptr;
|
||||||
|
|
||||||
// QObject managed.
|
// QObject managed.
|
||||||
TaskMgr *m_taskMgr;
|
TaskMgr *m_taskMgr = nullptr;
|
||||||
|
|
||||||
// QObject managed.
|
// QObject managed.
|
||||||
NotebookMgr *m_notebookMgr;
|
NotebookMgr *m_notebookMgr = nullptr;
|
||||||
|
|
||||||
// QObject managed.
|
// QObject managed.
|
||||||
BufferMgr *m_bufferMgr;
|
BufferMgr *m_bufferMgr = nullptr;
|
||||||
|
|
||||||
// Used to identify app's instance.
|
// Used to identify app's instance.
|
||||||
ID m_instanceId = 0;
|
ID m_instanceId = 0;
|
||||||
|
@ -46,6 +46,8 @@ void WidgetConfig::init(const QJsonObject &p_app,
|
|||||||
m_tagExplorerTwoColumnsEnabled = READBOOL(QStringLiteral("tag_explorer_two_columns_enabled"));
|
m_tagExplorerTwoColumnsEnabled = READBOOL(QStringLiteral("tag_explorer_two_columns_enabled"));
|
||||||
|
|
||||||
m_newNoteDefaultFileType = READINT(QStringLiteral("new_note_default_file_type"));
|
m_newNoteDefaultFileType = READINT(QStringLiteral("new_note_default_file_type"));
|
||||||
|
|
||||||
|
m_unitedEntryExpandAllEnabled = READBOOL(QStringLiteral("united_entry_expand_all"));
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonObject WidgetConfig::toJson() const
|
QJsonObject WidgetConfig::toJson() const
|
||||||
@ -68,6 +70,7 @@ QJsonObject WidgetConfig::toJson() const
|
|||||||
QStringLiteral("main_window_keep_docks_expanding_content_area"),
|
QStringLiteral("main_window_keep_docks_expanding_content_area"),
|
||||||
m_mainWindowKeepDocksExpandingContentArea);
|
m_mainWindowKeepDocksExpandingContentArea);
|
||||||
obj[QStringLiteral("new_note_default_file_type")] = m_newNoteDefaultFileType;
|
obj[QStringLiteral("new_note_default_file_type")] = m_newNoteDefaultFileType;
|
||||||
|
obj[QStringLiteral("united_entry_expand_all")] = m_unitedEntryExpandAllEnabled;
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,3 +203,13 @@ void WidgetConfig::setNewNoteDefaultFileType(int p_type)
|
|||||||
{
|
{
|
||||||
updateConfig(m_newNoteDefaultFileType, p_type, this);
|
updateConfig(m_newNoteDefaultFileType, p_type, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool WidgetConfig::getUnitedEntryExpandAllEnabled() const
|
||||||
|
{
|
||||||
|
return m_unitedEntryExpandAllEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WidgetConfig::setUnitedEntryExpandAllEnabled(bool p_enabled)
|
||||||
|
{
|
||||||
|
updateConfig(m_unitedEntryExpandAllEnabled, p_enabled, this);
|
||||||
|
}
|
||||||
|
@ -57,6 +57,9 @@ namespace vnotex
|
|||||||
int getNewNoteDefaultFileType() const;
|
int getNewNoteDefaultFileType() const;
|
||||||
void setNewNoteDefaultFileType(int p_type);
|
void setNewNoteDefaultFileType(int p_type);
|
||||||
|
|
||||||
|
bool getUnitedEntryExpandAllEnabled() const;
|
||||||
|
void setUnitedEntryExpandAllEnabled(bool p_enabled);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int m_outlineAutoExpandedLevel = 6;
|
int m_outlineAutoExpandedLevel = 6;
|
||||||
|
|
||||||
@ -85,6 +88,8 @@ namespace vnotex
|
|||||||
bool m_tagExplorerTwoColumnsEnabled = false;
|
bool m_tagExplorerTwoColumnsEnabled = false;
|
||||||
|
|
||||||
int m_newNoteDefaultFileType = 0;
|
int m_newNoteDefaultFileType = 0;
|
||||||
|
|
||||||
|
bool m_unitedEntryExpandAllEnabled = false;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
<file>icons/new_notebook.svg</file>
|
<file>icons/new_notebook.svg</file>
|
||||||
<file>icons/notebook_menu.svg</file>
|
<file>icons/notebook_menu.svg</file>
|
||||||
<file>icons/task_menu.svg</file>
|
<file>icons/task_menu.svg</file>
|
||||||
|
<file>icons/united_entry.svg</file>
|
||||||
<file>icons/advanced_settings.svg</file>
|
<file>icons/advanced_settings.svg</file>
|
||||||
<file>icons/new_notebook_from_folder.svg</file>
|
<file>icons/new_notebook_from_folder.svg</file>
|
||||||
<file>icons/discard_editor.svg</file>
|
<file>icons/discard_editor.svg</file>
|
||||||
@ -36,6 +37,7 @@
|
|||||||
<file>icons/notebook_default.svg</file>
|
<file>icons/notebook_default.svg</file>
|
||||||
<file>icons/file_node.svg</file>
|
<file>icons/file_node.svg</file>
|
||||||
<file>icons/folder_node.svg</file>
|
<file>icons/folder_node.svg</file>
|
||||||
|
<file>icons/other_item.svg</file>
|
||||||
<file>icons/manage_notebooks.svg</file>
|
<file>icons/manage_notebooks.svg</file>
|
||||||
<file>icons/up_level.svg</file>
|
<file>icons/up_level.svg</file>
|
||||||
<file>icons/properties.svg</file>
|
<file>icons/properties.svg</file>
|
||||||
|
2
src/data/core/icons/other_item.svg
Normal file
2
src/data/core/icons/other_item.svg
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1648451502935" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="9398" width="512" height="512" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><style type="text/css">@font-face { font-family: feedback-iconfont; src: url("//at.alicdn.com/t/font_1031158_u69w8yhxdu.woff2?t=1630033759944") format("woff2"), url("//at.alicdn.com/t/font_1031158_u69w8yhxdu.woff?t=1630033759944") format("woff"), url("//at.alicdn.com/t/font_1031158_u69w8yhxdu.ttf?t=1630033759944") format("truetype"); }
|
||||||
|
</style></defs><path d="M692.071703 329.86173c-48.372707-48.387034-112.705921-75.023694-181.146687-75.023694-68.440765 0-132.747373 26.63666-181.148733 75.023694-48.400337 48.374754-75.022671 112.707968-75.022671 181.123151s26.623357 132.74635 75.022671 181.146687c48.374754 48.402383 112.707968 75.023694 181.148733 75.023694 68.441788 0 132.745327-26.647917 181.146687-75.023694 48.427966-48.373731 75.024717-112.706945 75.024717-181.146687C767.096421 442.544115 740.447481 378.237507 692.071703 329.86173z" p-id="9399" fill="#000000"></path></svg>
|
After Width: | Height: | Size: 1.2 KiB |
1
src/data/core/icons/united_entry.svg
Normal file
1
src/data/core/icons/united_entry.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1646971542356" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="10326" width="512" height="512" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><style type="text/css"></style></defs><path d="M960 447.968c0-211.744-200.96-384-448-384s-448 172.256-448 384c0 116.48 63.008 226.048 172.896 300.672 14.656 9.984 34.528 6.144 44.448-8.512 9.952-14.624 6.112-34.528-8.512-44.448C180.8 633.184 128 542.912 128 447.968c0-176.448 172.256-320 384-320s384 143.552 384 320-172.256 320-384 320c-1.984 0-3.68 0.768-5.536 1.12-15.168-2.688-30.528 5.184-35.808 20.224-6.112 17.344-46.368 46.624-94.112 73.76 17.472-58.208 9.088-70.688 3.52-78.976a36.034 36.034 0 0 0-29.92-15.936c-17.664 0-32 14.304-32 32 0 5.824 1.536 11.264 4.256 15.936-3.232 18.24-17.216 60.864-33.088 99.872-4.928 12.096-1.984 25.984 7.36 35.072a32.049 32.049 0 0 0 22.272 8.992c4.384 0 8.8-0.896 12.992-2.752 36.48-16.256 147.616-69.152 187.584-125.632C763.072 828.16 960 657.536 960 447.968z" p-id="10327" fill="#000000"></path><path d="M726.624 273.696c-12.512-12.512-32.736-12.512-45.248 0L545.024 410.048c-19.936-12.288-42.784-19.2-66.848-19.2-34.208 0-66.336 13.312-90.496 37.472-49.888 49.888-49.888 131.104 0 181.056 24.16 24.16 56.32 37.472 90.496 37.472 34.208 0 66.336-13.312 90.496-37.472 24.192-24.192 37.536-56.352 37.504-90.592-0.032-22.336-6.24-43.552-16.928-62.496L641.536 404l39.84 39.84c6.24 6.24 14.432 9.376 22.624 9.376s16.384-3.136 22.624-9.376c12.512-12.512 12.512-32.736 0-45.248l-39.84-39.84 39.84-39.84c12.512-12.48 12.512-32.736 0-45.216z m-203.2 290.432c-24.16 24.096-66.368 24.128-90.496 0.032-24.96-25.024-24.96-65.632 0-90.592 12.064-12.064 28.128-18.72 45.248-18.72 17.12 0 33.184 6.656 45.248 18.72 12.096 12.096 18.752 28.16 18.752 45.28s-6.624 33.184-18.752 45.28z" p-id="10328" fill="#000000"></path></svg>
|
After Width: | Height: | Size: 1.9 KiB |
@ -59,7 +59,8 @@
|
|||||||
"MoveOneSplitDown" : "Ctrl+G, Shift+J",
|
"MoveOneSplitDown" : "Ctrl+G, Shift+J",
|
||||||
"MoveOneSplitUp" : "Ctrl+G, Shift+K",
|
"MoveOneSplitUp" : "Ctrl+G, Shift+K",
|
||||||
"MoveOneSplitRight" : "Ctrl+G, Shift+L",
|
"MoveOneSplitRight" : "Ctrl+G, Shift+L",
|
||||||
"OpenLastClosedFile" : "Ctrl+Shift+T"
|
"OpenLastClosedFile" : "Ctrl+Shift+T",
|
||||||
|
"UnitedEntry" : "Ctrl+G, G"
|
||||||
},
|
},
|
||||||
"file_type_suffixes" : [
|
"file_type_suffixes" : [
|
||||||
{
|
{
|
||||||
@ -98,7 +99,71 @@
|
|||||||
"history_max_count" : 100,
|
"history_max_count" : 100,
|
||||||
"per_notebook_history" : false,
|
"per_notebook_history" : false,
|
||||||
"//comment" : "Line ending policy for config files, platform/lf/crlf/cr",
|
"//comment" : "Line ending policy for config files, platform/lf/crlf/cr",
|
||||||
"line_ending" : "lf"
|
"line_ending" : "lf",
|
||||||
|
"united_entry" : {
|
||||||
|
"alias" : [
|
||||||
|
{
|
||||||
|
"name" : "q",
|
||||||
|
"description" : "Search for folders/files by name in all notebooks",
|
||||||
|
"value" : "find --scope all_notebook --object name --target file --target folder"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name" : "a",
|
||||||
|
"description" : "Search for files by content in all notebooks",
|
||||||
|
"value" : "find --scope all_notebook --object content --target file"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name" : "z",
|
||||||
|
"description" : "Search for files by tag in all notebooks",
|
||||||
|
"value" : "find --scope all_notebook --object tag --target file"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name" : "w",
|
||||||
|
"description" : "Search for notebooks by name in all notebooks",
|
||||||
|
"value" : "find --scope all_notebook --object name --target notebook"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name" : "e",
|
||||||
|
"description" : "Search for folders/files by name in current notebook",
|
||||||
|
"value" : "find --scope notebook --object name --target file --target folder"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name" : "d",
|
||||||
|
"description" : "Search for files by content in current notebook",
|
||||||
|
"value" : "find --scope notebook --object content --target file"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name" : "c",
|
||||||
|
"description" : "Search for files by tag in current notebook",
|
||||||
|
"value" : "find --scope notebook --object tag --target file"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name" : "r",
|
||||||
|
"description" : "Search for folders/files by name in current folder",
|
||||||
|
"value" : "find --scope folder --object name --target file --target folder"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name" : "f",
|
||||||
|
"description" : "Search for files by content in current folder",
|
||||||
|
"value" : "find --scope folder --object content --target file"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name" : "v",
|
||||||
|
"description" : "Search for files by tag in current folder",
|
||||||
|
"value" : "find --scope folder --object tag --target file"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name" : "t",
|
||||||
|
"description" : "Search for files by name in buffers",
|
||||||
|
"value" : "find --scope buffer --object name --target file"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name" : "g",
|
||||||
|
"description" : "Search for files by content in buffers",
|
||||||
|
"value" : "find --scope buffer --object content --target file"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"editor" : {
|
"editor" : {
|
||||||
"core": {
|
"core": {
|
||||||
@ -131,7 +196,7 @@
|
|||||||
"TypeMath" : "Ctrl+.",
|
"TypeMath" : "Ctrl+.",
|
||||||
"TypeMathBlock" : "Ctrl+G, .",
|
"TypeMathBlock" : "Ctrl+G, .",
|
||||||
"TypeQuote" : "",
|
"TypeQuote" : "",
|
||||||
"TypeLink" : "",
|
"TypeLink" : "Ctrl+,",
|
||||||
"TypeImage" : "",
|
"TypeImage" : "",
|
||||||
"TypeTable" : "Ctrl+/",
|
"TypeTable" : "Ctrl+/",
|
||||||
"TypeMark" : "Ctrl+G, M",
|
"TypeMark" : "Ctrl+G, M",
|
||||||
@ -418,6 +483,7 @@
|
|||||||
"main_window_keep_docks_expanding_content_area": ["OutlineDock.vnotex"],
|
"main_window_keep_docks_expanding_content_area": ["OutlineDock.vnotex"],
|
||||||
"snippet_panel_builtin_snippets_visible" : true,
|
"snippet_panel_builtin_snippets_visible" : true,
|
||||||
"tag_explorer_two_columns_enabled" : true,
|
"tag_explorer_two_columns_enabled" : true,
|
||||||
"new_note_default_file_type" : 0
|
"new_note_default_file_type" : 0,
|
||||||
|
"united_entry_expand_all" : false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -469,12 +469,12 @@ QLineEdit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
QLineEdit:focus {
|
QLineEdit:focus {
|
||||||
border: 2px solid @widgets#qlineedit#focus#border;
|
border: 1px solid @widgets#qlineedit#focus#border;
|
||||||
background-color: @widgets#qlineedit#focus#bg;
|
background-color: @widgets#qlineedit#focus#bg;
|
||||||
}
|
}
|
||||||
|
|
||||||
QLineEdit:hover {
|
QLineEdit:hover {
|
||||||
border: 2px solid @widgets#qlineedit#hover#border;
|
border: 1px solid @widgets#qlineedit#hover#border;
|
||||||
background-color: @widgets#qlineedit#hover#bg;
|
background-color: @widgets#qlineedit#hover#bg;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1174,3 +1174,7 @@ vnotex--ViewSplit QTabBar[ViewSplitFlash="true"]::tab:selected {
|
|||||||
vte--VTextEdit {
|
vte--VTextEdit {
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vnotex--EntryPopup {
|
||||||
|
border: 1px solid @widgets#unitedentry#popup#border;
|
||||||
|
}
|
||||||
|
@ -647,6 +647,17 @@
|
|||||||
"fg" : "@base#master#fg",
|
"fg" : "@base#master#fg",
|
||||||
"bg" : "@base#master#bg"
|
"bg" : "@base#master#bg"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"unitedentry" : {
|
||||||
|
"icon" : {
|
||||||
|
"fg" : "@base#icon#fg",
|
||||||
|
"busy" : {
|
||||||
|
"fg" : "@base#master#bg"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"popup" : {
|
||||||
|
"border" : "@base#normal#border"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -127,3 +127,7 @@ vnotex--MainWindow QLabel#MainWindowTipsLabel {
|
|||||||
vnotex--ViewSplit QTabBar[ViewSplitFlash="true"]::tab:selected {
|
vnotex--ViewSplit QTabBar[ViewSplitFlash="true"]::tab:selected {
|
||||||
background-color: @widgets#viewsplit#flash#bg;
|
background-color: @widgets#viewsplit#flash#bg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vnotex--EntryPopup {
|
||||||
|
border: 1px solid @widgets#unitedentry#popup#border;
|
||||||
|
}
|
||||||
|
@ -153,6 +153,17 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"unitedentry" : {
|
||||||
|
"icon" : {
|
||||||
|
"fg" : "@base#icon#fg",
|
||||||
|
"busy" : {
|
||||||
|
"fg" : "@base#info#fg"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"popup" : {
|
||||||
|
"border" : "@base#normal#border"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -469,12 +469,12 @@ QLineEdit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
QLineEdit:focus {
|
QLineEdit:focus {
|
||||||
border: 2px solid @widgets#qlineedit#focus#border;
|
border: 1px solid @widgets#qlineedit#focus#border;
|
||||||
background-color: @widgets#qlineedit#focus#bg;
|
background-color: @widgets#qlineedit#focus#bg;
|
||||||
}
|
}
|
||||||
|
|
||||||
QLineEdit:hover {
|
QLineEdit:hover {
|
||||||
border: 2px solid @widgets#qlineedit#hover#border;
|
border: 1px solid @widgets#qlineedit#hover#border;
|
||||||
background-color: @widgets#qlineedit#hover#bg;
|
background-color: @widgets#qlineedit#hover#bg;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1174,3 +1174,7 @@ vnotex--ViewSplit QTabBar[ViewSplitFlash="true"]::tab:selected {
|
|||||||
vte--VTextEdit {
|
vte--VTextEdit {
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vnotex--EntryPopup {
|
||||||
|
border: 1px solid @widgets#unitedentry#popup#border;
|
||||||
|
}
|
||||||
|
@ -643,6 +643,17 @@
|
|||||||
"fg" : "@base#master#fg",
|
"fg" : "@base#master#fg",
|
||||||
"bg" : "@base#master#bg"
|
"bg" : "@base#master#bg"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"unitedentry" : {
|
||||||
|
"icon" : {
|
||||||
|
"fg" : "@base#icon#fg",
|
||||||
|
"busy" : {
|
||||||
|
"fg" : "@base#master#bg"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"popup" : {
|
||||||
|
"border" : "@base#normal#border"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -465,12 +465,12 @@ QLineEdit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
QLineEdit:focus {
|
QLineEdit:focus {
|
||||||
border: 2px solid @widgets#qlineedit#focus#border;
|
border: 1px solid @widgets#qlineedit#focus#border;
|
||||||
background-color: @widgets#qlineedit#focus#bg;
|
background-color: @widgets#qlineedit#focus#bg;
|
||||||
}
|
}
|
||||||
|
|
||||||
QLineEdit:hover {
|
QLineEdit:hover {
|
||||||
border: 2px solid @widgets#qlineedit#hover#border;
|
border: 1px solid @widgets#qlineedit#hover#border;
|
||||||
background-color: @widgets#qlineedit#hover#bg;
|
background-color: @widgets#qlineedit#hover#bg;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1170,3 +1170,7 @@ vnotex--ViewSplit QTabBar[ViewSplitFlash="true"]::tab:selected {
|
|||||||
vte--VTextEdit {
|
vte--VTextEdit {
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vnotex--EntryPopup {
|
||||||
|
border: 1px solid @widgets#unitedentry#popup#border;
|
||||||
|
}
|
||||||
|
@ -648,6 +648,17 @@
|
|||||||
"fg" : "@base#master#fg",
|
"fg" : "@base#master#fg",
|
||||||
"bg" : "@base#master#bg"
|
"bg" : "@base#master#bg"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"unitedentry" : {
|
||||||
|
"icon" : {
|
||||||
|
"fg" : "@base#icon#fg",
|
||||||
|
"busy" : {
|
||||||
|
"fg" : "@base#master#bg"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"popup" : {
|
||||||
|
"border" : "@base#normal#border"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -465,12 +465,12 @@ QLineEdit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
QLineEdit:focus {
|
QLineEdit:focus {
|
||||||
border: 2px solid @widgets#qlineedit#focus#border;
|
border: 1px solid @widgets#qlineedit#focus#border;
|
||||||
background-color: @widgets#qlineedit#focus#bg;
|
background-color: @widgets#qlineedit#focus#bg;
|
||||||
}
|
}
|
||||||
|
|
||||||
QLineEdit:hover {
|
QLineEdit:hover {
|
||||||
border: 2px solid @widgets#qlineedit#hover#border;
|
border: 1px solid @widgets#qlineedit#hover#border;
|
||||||
background-color: @widgets#qlineedit#hover#bg;
|
background-color: @widgets#qlineedit#hover#bg;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1170,3 +1170,7 @@ vnotex--ViewSplit QTabBar[ViewSplitFlash="true"]::tab:selected {
|
|||||||
vte--VTextEdit {
|
vte--VTextEdit {
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vnotex--EntryPopup {
|
||||||
|
border: 1px solid @widgets#unitedentry#popup#border;
|
||||||
|
}
|
||||||
|
@ -648,6 +648,17 @@
|
|||||||
"fg" : "@base#master#fg",
|
"fg" : "@base#master#fg",
|
||||||
"bg" : "@base#master#bg"
|
"bg" : "@base#master#bg"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"unitedentry" : {
|
||||||
|
"icon" : {
|
||||||
|
"fg" : "@base#icon#fg",
|
||||||
|
"busy" : {
|
||||||
|
"fg" : "@base#master#bg"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"popup" : {
|
||||||
|
"border" : "@base#normal#border"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -465,12 +465,12 @@ QLineEdit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
QLineEdit:focus {
|
QLineEdit:focus {
|
||||||
border: 2px solid @widgets#qlineedit#focus#border;
|
border: 1px solid @widgets#qlineedit#focus#border;
|
||||||
background-color: @widgets#qlineedit#focus#bg;
|
background-color: @widgets#qlineedit#focus#bg;
|
||||||
}
|
}
|
||||||
|
|
||||||
QLineEdit:hover {
|
QLineEdit:hover {
|
||||||
border: 2px solid @widgets#qlineedit#hover#border;
|
border: 1px solid @widgets#qlineedit#hover#border;
|
||||||
background-color: @widgets#qlineedit#hover#bg;
|
background-color: @widgets#qlineedit#hover#bg;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1170,3 +1170,7 @@ vnotex--ViewSplit QTabBar[ViewSplitFlash="true"]::tab:selected {
|
|||||||
vte--VTextEdit {
|
vte--VTextEdit {
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vnotex--EntryPopup {
|
||||||
|
border: 1px solid @widgets#unitedentry#popup#border;
|
||||||
|
}
|
||||||
|
@ -647,6 +647,17 @@
|
|||||||
"fg" : "@base#master#fg",
|
"fg" : "@base#master#fg",
|
||||||
"bg" : "@base#master#bg"
|
"bg" : "@base#master#bg"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"unitedentry" : {
|
||||||
|
"icon" : {
|
||||||
|
"fg" : "@base#icon#fg",
|
||||||
|
"busy" : {
|
||||||
|
"fg" : "@base#master#bg"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"popup" : {
|
||||||
|
"border" : "@base#normal#border"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
30
src/search/isearchinfoprovider.h
Normal file
30
src/search/isearchinfoprovider.h
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#ifndef ISEARCHINFOPROVIDER_H
|
||||||
|
#define ISEARCHINFOPROVIDER_H
|
||||||
|
|
||||||
|
#include <QList>
|
||||||
|
#include <QVector>
|
||||||
|
|
||||||
|
namespace vnotex
|
||||||
|
{
|
||||||
|
class Node;
|
||||||
|
class Notebook;
|
||||||
|
class Buffer;
|
||||||
|
|
||||||
|
class ISearchInfoProvider
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ISearchInfoProvider() = default;
|
||||||
|
|
||||||
|
virtual ~ISearchInfoProvider() = default;
|
||||||
|
|
||||||
|
virtual QList<Buffer *> getBuffers() const = 0;
|
||||||
|
|
||||||
|
virtual Node *getCurrentFolder() const = 0;
|
||||||
|
|
||||||
|
virtual Notebook *getCurrentNotebook() const = 0;
|
||||||
|
|
||||||
|
virtual QVector<Notebook *> getNotebooks() const = 0;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // ISEARCHINFOPROVIDER_H
|
@ -3,8 +3,10 @@ QT += widgets
|
|||||||
HEADERS += \
|
HEADERS += \
|
||||||
$$PWD/filesearchengine.h \
|
$$PWD/filesearchengine.h \
|
||||||
$$PWD/isearchengine.h \
|
$$PWD/isearchengine.h \
|
||||||
|
$$PWD/isearchinfoprovider.h \
|
||||||
$$PWD/searchdata.h \
|
$$PWD/searchdata.h \
|
||||||
$$PWD/searcher.h \
|
$$PWD/searcher.h \
|
||||||
|
$$PWD/searchhelper.h \
|
||||||
$$PWD/searchresultitem.h \
|
$$PWD/searchresultitem.h \
|
||||||
$$PWD/searchtoken.h
|
$$PWD/searchtoken.h
|
||||||
|
|
||||||
@ -12,6 +14,7 @@ SOURCES += \
|
|||||||
$$PWD/filesearchengine.cpp \
|
$$PWD/filesearchengine.cpp \
|
||||||
$$PWD/searchdata.cpp \
|
$$PWD/searchdata.cpp \
|
||||||
$$PWD/searcher.cpp \
|
$$PWD/searcher.cpp \
|
||||||
|
$$PWD/searchhelper.cpp \
|
||||||
$$PWD/searchresultitem.cpp \
|
$$PWD/searchresultitem.cpp \
|
||||||
$$PWD/searchtoken.cpp
|
$$PWD/searchtoken.cpp
|
||||||
|
|
||||||
|
@ -45,3 +45,8 @@ bool SearchOption::operator==(const SearchOption &p_other) const
|
|||||||
&& m_engine == p_other.m_engine
|
&& m_engine == p_other.m_engine
|
||||||
&& m_findOptions == p_other.m_findOptions;
|
&& m_findOptions == p_other.m_findOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SearchOption::strictEquals(const SearchOption &p_other) const
|
||||||
|
{
|
||||||
|
return (*this == p_other) && m_keyword == p_other.m_keyword;
|
||||||
|
}
|
||||||
|
@ -87,6 +87,8 @@ namespace vnotex
|
|||||||
|
|
||||||
bool operator==(const SearchOption &p_other) const;
|
bool operator==(const SearchOption &p_other) const;
|
||||||
|
|
||||||
|
bool strictEquals(const SearchOption &p_other) const;
|
||||||
|
|
||||||
QString m_keyword;
|
QString m_keyword;
|
||||||
|
|
||||||
QString m_filePattern;
|
QString m_filePattern;
|
||||||
|
99
src/search/searchhelper.cpp
Normal file
99
src/search/searchhelper.cpp
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
#include "searchhelper.h"
|
||||||
|
|
||||||
|
#include <search/isearchinfoprovider.h>
|
||||||
|
|
||||||
|
using namespace vnotex;
|
||||||
|
|
||||||
|
bool SearchHelper::isSearchOptionValid(const SearchOption &p_option, QString &p_msg)
|
||||||
|
{
|
||||||
|
if (p_option.m_keyword.isEmpty()) {
|
||||||
|
p_msg = Searcher::tr("Invalid keyword");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p_option.m_objects == SearchObject::ObjectNone) {
|
||||||
|
p_msg = Searcher::tr("No object specified");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p_option.m_targets == SearchTarget::TargetNone) {
|
||||||
|
p_msg = Searcher::tr("No target specified");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p_option.m_findOptions & FindOption::FuzzySearch
|
||||||
|
&& p_option.m_objects & SearchObject::SearchContent) {
|
||||||
|
p_msg = Searcher::tr("Fuzzy search is not allowed when searching content");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
p_msg.clear();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
SearchState SearchHelper::searchOnProvider(Searcher *p_searcher,
|
||||||
|
const QSharedPointer<SearchOption> &p_option,
|
||||||
|
const QSharedPointer<ISearchInfoProvider> &p_provider,
|
||||||
|
QString &p_msg)
|
||||||
|
{
|
||||||
|
p_msg.clear();
|
||||||
|
|
||||||
|
if (!isSearchOptionValid(*p_option, p_msg)) {
|
||||||
|
return SearchState::Failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
SearchState state = SearchState::Finished;
|
||||||
|
|
||||||
|
switch (p_option->m_scope) {
|
||||||
|
case SearchScope::Buffers:
|
||||||
|
{
|
||||||
|
auto buffers = p_provider->getBuffers();
|
||||||
|
if (buffers.isEmpty()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
state = p_searcher->search(p_option, buffers);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SearchScope::CurrentFolder:
|
||||||
|
{
|
||||||
|
auto notebook = p_provider->getCurrentNotebook();
|
||||||
|
if (!notebook) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
auto folder = p_provider->getCurrentFolder();
|
||||||
|
if (!folder) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
state = p_searcher->search(p_option, folder);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SearchScope::CurrentNotebook:
|
||||||
|
{
|
||||||
|
auto notebook = p_provider->getCurrentNotebook();
|
||||||
|
if (!notebook) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector<Notebook *> notebooks;
|
||||||
|
notebooks.push_back(notebook);
|
||||||
|
state = p_searcher->search(p_option, notebooks);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SearchScope::AllNotebooks:
|
||||||
|
{
|
||||||
|
auto notebooks = p_provider->getNotebooks();
|
||||||
|
if (notebooks.isEmpty()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
state = p_searcher->search(p_option, notebooks);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}
|
28
src/search/searchhelper.h
Normal file
28
src/search/searchhelper.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#ifndef SEARCHHELPER_H
|
||||||
|
#define SEARCHHELPER_H
|
||||||
|
|
||||||
|
#include <QSharedPointer>
|
||||||
|
|
||||||
|
#include "searchdata.h"
|
||||||
|
#include "searcher.h"
|
||||||
|
|
||||||
|
namespace vnotex
|
||||||
|
{
|
||||||
|
class ISearchInfoProvider;
|
||||||
|
|
||||||
|
class SearchHelper
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SearchHelper() = delete;
|
||||||
|
|
||||||
|
static SearchState searchOnProvider(Searcher *p_searcher,
|
||||||
|
const QSharedPointer<SearchOption> &p_option,
|
||||||
|
const QSharedPointer<ISearchInfoProvider> &p_provider,
|
||||||
|
QString &p_msg);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static bool isSearchOptionValid(const SearchOption &p_option, QString &p_msg);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // SEARCHHELPER_H
|
@ -8,8 +8,6 @@
|
|||||||
|
|
||||||
using namespace vnotex;
|
using namespace vnotex;
|
||||||
|
|
||||||
QScopedPointer<QCommandLineParser> SearchToken::s_parser;
|
|
||||||
|
|
||||||
void SearchToken::clear()
|
void SearchToken::clear()
|
||||||
{
|
{
|
||||||
m_type = Type::PlainText;
|
m_type = Type::PlainText;
|
||||||
@ -157,31 +155,40 @@ bool SearchToken::isEmpty() const
|
|||||||
return constraintSize() == 0;
|
return constraintSize() == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SearchToken::createCommandLineParser()
|
QCommandLineParser *SearchToken::getCommandLineParser()
|
||||||
{
|
{
|
||||||
if (s_parser) {
|
static QScopedPointer<QCommandLineParser> parser;
|
||||||
return;
|
|
||||||
|
if (parser) {
|
||||||
|
return parser.data();
|
||||||
}
|
}
|
||||||
|
|
||||||
s_parser.reset(new QCommandLineParser());
|
parser.reset(new QCommandLineParser());
|
||||||
s_parser->setApplicationDescription(SearchPanel::tr("Full-text search."));
|
parser->setApplicationDescription(SearchPanel::tr("Full-text search."));
|
||||||
|
|
||||||
|
parser->addPositionalArgument("keywords", SearchPanel::tr("Keywords to search for."));
|
||||||
|
|
||||||
|
addSearchOptionsToCommand(parser.data());
|
||||||
|
|
||||||
|
return parser.data();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SearchToken::addSearchOptionsToCommand(QCommandLineParser *p_parser)
|
||||||
|
{
|
||||||
QCommandLineOption caseSensitiveOpt(QStringList() << "c" << "case-sensitive", SearchPanel::tr("Search in case sensitive."));
|
QCommandLineOption caseSensitiveOpt(QStringList() << "c" << "case-sensitive", SearchPanel::tr("Search in case sensitive."));
|
||||||
s_parser->addOption(caseSensitiveOpt);
|
p_parser->addOption(caseSensitiveOpt);
|
||||||
|
|
||||||
QCommandLineOption regularExpressionOpt(QStringList() << "r" << "regular-expression", SearchPanel::tr("Search by regular expression."));
|
QCommandLineOption regularExpressionOpt(QStringList() << "r" << "regular-expression", SearchPanel::tr("Search by regular expression."));
|
||||||
s_parser->addOption(regularExpressionOpt);
|
p_parser->addOption(regularExpressionOpt);
|
||||||
|
|
||||||
QCommandLineOption wholeWordOnlyOpt(QStringList() << "w" << "whole-word-only", SearchPanel::tr("Search whole word only."));
|
QCommandLineOption wholeWordOnlyOpt(QStringList() << "w" << "whole-word-only", SearchPanel::tr("Search whole word only."));
|
||||||
s_parser->addOption(wholeWordOnlyOpt);
|
p_parser->addOption(wholeWordOnlyOpt);
|
||||||
|
|
||||||
QCommandLineOption fuzzySearchOpt(QStringList() << "f" << "fuzzy-search", SearchPanel::tr("Do a fuzzy search (not applicable to content search)."));
|
QCommandLineOption fuzzySearchOpt(QStringList() << "f" << "fuzzy-search", SearchPanel::tr("Do a fuzzy search (not applicable to content search)."));
|
||||||
s_parser->addOption(fuzzySearchOpt);
|
p_parser->addOption(fuzzySearchOpt);
|
||||||
|
|
||||||
QCommandLineOption orOpt(QStringList() << "o" << "or", SearchPanel::tr("Do an OR combination of keywords."));
|
QCommandLineOption orOpt(QStringList() << "o" << "or", SearchPanel::tr("Do an OR combination of keywords."));
|
||||||
s_parser->addOption(orOpt);
|
p_parser->addOption(orOpt);
|
||||||
|
|
||||||
s_parser->addPositionalArgument("keywords", SearchPanel::tr("Keywords to search."));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SearchToken::compile(const QString &p_keyword, FindOptions p_options, SearchToken &p_token)
|
bool SearchToken::compile(const QString &p_keyword, FindOptions p_options, SearchToken &p_token)
|
||||||
@ -193,7 +200,7 @@ bool SearchToken::compile(const QString &p_keyword, FindOptions p_options, Searc
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
createCommandLineParser();
|
auto parser = getCommandLineParser();
|
||||||
|
|
||||||
auto caseSensitivity = p_options & FindOption::CaseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive;
|
auto caseSensitivity = p_options & FindOption::CaseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive;
|
||||||
bool isRegularExpression = p_options & FindOption::RegularExpression;
|
bool isRegularExpression = p_options & FindOption::RegularExpression;
|
||||||
@ -203,25 +210,25 @@ bool SearchToken::compile(const QString &p_keyword, FindOptions p_options, Searc
|
|||||||
auto args = ProcessUtils::parseCombinedArgString(p_keyword);
|
auto args = ProcessUtils::parseCombinedArgString(p_keyword);
|
||||||
// The parser needs the first arg to be the application name.
|
// The parser needs the first arg to be the application name.
|
||||||
args.prepend("vnotex");
|
args.prepend("vnotex");
|
||||||
if (!s_parser->parse(args))
|
if (!parser->parse(args))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s_parser->isSet("c")) {
|
if (parser->isSet("c")) {
|
||||||
caseSensitivity = Qt::CaseSensitive;
|
caseSensitivity = Qt::CaseSensitive;
|
||||||
}
|
}
|
||||||
if (s_parser->isSet("r")) {
|
if (parser->isSet("r")) {
|
||||||
isRegularExpression = true;
|
isRegularExpression = true;
|
||||||
}
|
}
|
||||||
if (s_parser->isSet("w")) {
|
if (parser->isSet("w")) {
|
||||||
isWholeWordOnly = true;
|
isWholeWordOnly = true;
|
||||||
}
|
}
|
||||||
if (s_parser->isSet("f")) {
|
if (parser->isSet("f")) {
|
||||||
isFuzzySearch = true;
|
isFuzzySearch = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
args = s_parser->positionalArguments();
|
args = parser->positionalArguments();
|
||||||
if (args.isEmpty()) {
|
if (args.isEmpty()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -232,7 +239,7 @@ bool SearchToken::compile(const QString &p_keyword, FindOptions p_options, Searc
|
|||||||
} else {
|
} else {
|
||||||
p_token.m_type = Type::PlainText;
|
p_token.m_type = Type::PlainText;
|
||||||
}
|
}
|
||||||
p_token.m_operator = s_parser->isSet("o") ? Operator::Or : Operator::And;
|
p_token.m_operator = parser->isSet("o") ? Operator::Or : Operator::And;
|
||||||
|
|
||||||
auto patternOptions = caseSensitivity == Qt::CaseInsensitive ? QRegularExpression::CaseInsensitiveOption
|
auto patternOptions = caseSensitivity == Qt::CaseInsensitive ? QRegularExpression::CaseInsensitiveOption
|
||||||
: QRegularExpression::NoPatternOption;
|
: QRegularExpression::NoPatternOption;
|
||||||
@ -266,8 +273,8 @@ bool SearchToken::compile(const QString &p_keyword, FindOptions p_options, Searc
|
|||||||
|
|
||||||
QString SearchToken::getHelpText()
|
QString SearchToken::getHelpText()
|
||||||
{
|
{
|
||||||
createCommandLineParser();
|
auto parser = getCommandLineParser();
|
||||||
auto text = s_parser->helpText();
|
auto text = parser->helpText();
|
||||||
// Skip the first line containing the application name.
|
// Skip the first line containing the application name.
|
||||||
return text.mid(text.indexOf('\n') + 1);
|
return text.mid(text.indexOf('\n') + 1);
|
||||||
}
|
}
|
||||||
|
@ -62,8 +62,10 @@ namespace vnotex
|
|||||||
|
|
||||||
static QString getHelpText();
|
static QString getHelpText();
|
||||||
|
|
||||||
|
static void addSearchOptionsToCommand(QCommandLineParser *p_parser);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void createCommandLineParser();
|
static QCommandLineParser *getCommandLineParser();
|
||||||
|
|
||||||
Type m_type = Type::PlainText;
|
Type m_type = Type::PlainText;
|
||||||
|
|
||||||
@ -79,8 +81,6 @@ namespace vnotex
|
|||||||
QBitArray m_matchedConstraintsInBatchMode;
|
QBitArray m_matchedConstraintsInBatchMode;
|
||||||
|
|
||||||
int m_matchedConstraintsCountInBatchMode = 0;
|
int m_matchedConstraintsCountInBatchMode = 0;
|
||||||
|
|
||||||
static QScopedPointer<QCommandLineParser> s_parser;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,6 +62,8 @@ include($$PWD/core/core.pri)
|
|||||||
|
|
||||||
include($$PWD/widgets/widgets.pri)
|
include($$PWD/widgets/widgets.pri)
|
||||||
|
|
||||||
|
include($$PWD/unitedentry/unitedentry.pri)
|
||||||
|
|
||||||
RESOURCES += \
|
RESOURCES += \
|
||||||
$$PWD/data/core/core.qrc
|
$$PWD/data/core/core.qrc
|
||||||
|
|
||||||
|
86
src/unitedentry/entrypopup.cpp
Normal file
86
src/unitedentry/entrypopup.cpp
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
#include "entrypopup.h"
|
||||||
|
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QWindow>
|
||||||
|
|
||||||
|
using namespace vnotex;
|
||||||
|
|
||||||
|
EntryPopup::EntryPopup(QWidget *p_parent)
|
||||||
|
: QFrame(p_parent)
|
||||||
|
{
|
||||||
|
Q_ASSERT(p_parent);
|
||||||
|
auto layout = new QVBoxLayout(this);
|
||||||
|
Q_UNUSED(layout);
|
||||||
|
|
||||||
|
setWindowFlags(Qt::ToolTip);
|
||||||
|
setFocusPolicy(Qt::FocusPolicy::ClickFocus);
|
||||||
|
}
|
||||||
|
|
||||||
|
EntryPopup::~EntryPopup()
|
||||||
|
{
|
||||||
|
if (m_widget) {
|
||||||
|
takeWidget(m_widget.data());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EntryPopup::setWidget(const QSharedPointer<QWidget> &p_widget)
|
||||||
|
{
|
||||||
|
Q_ASSERT(p_widget);
|
||||||
|
|
||||||
|
if (p_widget == m_widget) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_widget) {
|
||||||
|
takeWidget(m_widget.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
layout()->addWidget(p_widget.data());
|
||||||
|
m_widget = p_widget;
|
||||||
|
m_widget->show();
|
||||||
|
|
||||||
|
updateGeometryToContents();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EntryPopup::takeWidget(QWidget *p_widget)
|
||||||
|
{
|
||||||
|
layout()->removeWidget(p_widget);
|
||||||
|
p_widget->hide();
|
||||||
|
p_widget->setParent(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EntryPopup::showEvent(QShowEvent *p_event)
|
||||||
|
{
|
||||||
|
QFrame::showEvent(p_event);
|
||||||
|
|
||||||
|
updateGeometryToContents();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EntryPopup::updateGeometryToContents()
|
||||||
|
{
|
||||||
|
adjustSize();
|
||||||
|
|
||||||
|
auto pa = parentWidget();
|
||||||
|
auto pos = pa->mapToGlobal(QPoint(0, pa->height()));
|
||||||
|
setGeometry(QRect(pos, preferredSize()));
|
||||||
|
|
||||||
|
if (m_widget) {
|
||||||
|
m_widget->updateGeometry();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QSize EntryPopup::preferredSize() const
|
||||||
|
{
|
||||||
|
const int minWidth = 400;
|
||||||
|
const int minHeight = 300;
|
||||||
|
|
||||||
|
auto pa = parentWidget();
|
||||||
|
int w = pa->width();
|
||||||
|
int h = sizeHint().height();
|
||||||
|
if (auto win = pa->window()) {
|
||||||
|
w = qMax(w, qMin(win->width() - 500, 900));
|
||||||
|
h = qMax(h, qMin(win->height() - 500, 800));
|
||||||
|
}
|
||||||
|
return QSize(qMax(minWidth, w), qMax(h, minHeight));
|
||||||
|
}
|
34
src/unitedentry/entrypopup.h
Normal file
34
src/unitedentry/entrypopup.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#ifndef ENTRYPOPUP_H
|
||||||
|
#define ENTRYPOPUP_H
|
||||||
|
|
||||||
|
#include <QFrame>
|
||||||
|
#include <QSharedPointer>
|
||||||
|
|
||||||
|
namespace vnotex
|
||||||
|
{
|
||||||
|
class EntryPopup : public QFrame
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit EntryPopup(QWidget *p_parent = nullptr);
|
||||||
|
|
||||||
|
~EntryPopup();
|
||||||
|
|
||||||
|
void setWidget(const QSharedPointer<QWidget> &p_widget);
|
||||||
|
|
||||||
|
void updateGeometryToContents();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void showEvent(QShowEvent *p_event) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QSize preferredSize() const;
|
||||||
|
|
||||||
|
void takeWidget(QWidget *p_widget);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QSharedPointer<QWidget> m_widget = nullptr;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // ENTRYPOPUP_H
|
29
src/unitedentry/entrywidgetfactory.cpp
Normal file
29
src/unitedentry/entrywidgetfactory.cpp
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#include "entrywidgetfactory.h"
|
||||||
|
|
||||||
|
#include <QLabel>
|
||||||
|
|
||||||
|
#include <widgets/widgetsfactory.h>
|
||||||
|
#include <widgets/treewidget.h>
|
||||||
|
|
||||||
|
using namespace vnotex;
|
||||||
|
|
||||||
|
QSharedPointer<QTreeWidget> EntryWidgetFactory::createTreeWidget(int p_columnCount)
|
||||||
|
{
|
||||||
|
auto tree = QSharedPointer<TreeWidget>::create(TreeWidget::Flag::EnhancedStyle, nullptr);
|
||||||
|
tree->setColumnCount(p_columnCount);
|
||||||
|
tree->setHeaderHidden(true);
|
||||||
|
TreeWidget::showHorizontalScrollbar(tree.data());
|
||||||
|
return tree;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSharedPointer<QLabel> EntryWidgetFactory::createLabel(const QString &p_info)
|
||||||
|
{
|
||||||
|
auto label = QSharedPointer<QLabel>::create(p_info, nullptr);
|
||||||
|
label->setAlignment(Qt::AlignTop | Qt::AlignLeft);
|
||||||
|
|
||||||
|
auto fnt = label->font();
|
||||||
|
fnt.setPointSize(fnt.pointSize() + 2);
|
||||||
|
label->setFont(fnt);
|
||||||
|
|
||||||
|
return label;
|
||||||
|
}
|
23
src/unitedentry/entrywidgetfactory.h
Normal file
23
src/unitedentry/entrywidgetfactory.h
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#ifndef ENTRYWIDGETFACTORY_H
|
||||||
|
#define ENTRYWIDGETFACTORY_H
|
||||||
|
|
||||||
|
#include <QSharedPointer>
|
||||||
|
|
||||||
|
class QTreeWidget;
|
||||||
|
class QLabel;
|
||||||
|
class QString;
|
||||||
|
|
||||||
|
namespace vnotex
|
||||||
|
{
|
||||||
|
class EntryWidgetFactory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
EntryWidgetFactory() = delete;
|
||||||
|
|
||||||
|
static QSharedPointer<QTreeWidget> createTreeWidget(int p_columnCount);
|
||||||
|
|
||||||
|
static QSharedPointer<QLabel> createLabel(const QString &p_info);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // ENTRYWIDGETFACTORY_H
|
346
src/unitedentry/findunitedentry.cpp
Normal file
346
src/unitedentry/findunitedentry.cpp
Normal file
@ -0,0 +1,346 @@
|
|||||||
|
#include "findunitedentry.h"
|
||||||
|
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QCommandLineOption>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
#include <utils/processutils.h>
|
||||||
|
#include <search/searchtoken.h>
|
||||||
|
#include <search/searchdata.h>
|
||||||
|
#include <search/isearchinfoprovider.h>
|
||||||
|
#include <search/searchresultitem.h>
|
||||||
|
#include <search/searcher.h>
|
||||||
|
#include <search/searchhelper.h>
|
||||||
|
#include <search/searchtoken.h>
|
||||||
|
#include <core/fileopenparameters.h>
|
||||||
|
#include <core/vnotex.h>
|
||||||
|
#include <widgets/treewidget.h>
|
||||||
|
#include "unitedentryhelper.h"
|
||||||
|
#include "entrywidgetfactory.h"
|
||||||
|
#include "unitedentrymgr.h"
|
||||||
|
|
||||||
|
using namespace vnotex;
|
||||||
|
|
||||||
|
FindUnitedEntry::FindUnitedEntry(const QSharedPointer<ISearchInfoProvider> &p_provider,
|
||||||
|
const UnitedEntryMgr *p_mgr,
|
||||||
|
QObject *p_parent)
|
||||||
|
: IUnitedEntry("find",
|
||||||
|
tr("Search for files in notebooks"),
|
||||||
|
p_mgr,
|
||||||
|
p_parent),
|
||||||
|
m_provider(p_provider)
|
||||||
|
{
|
||||||
|
m_processTimer = new QTimer(this);
|
||||||
|
m_processTimer->setSingleShot(true);
|
||||||
|
m_processTimer->setInterval(500);
|
||||||
|
connect(m_processTimer, &QTimer::timeout,
|
||||||
|
this, &FindUnitedEntry::doProcessInternal);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FindUnitedEntry::initOnFirstProcess()
|
||||||
|
{
|
||||||
|
m_parser.setApplicationDescription(tr("Search for files in notebooks with advanced options for scope, object, target and so on."));
|
||||||
|
|
||||||
|
m_parser.addPositionalArgument("keywords", tr("Keywords to search for."));
|
||||||
|
|
||||||
|
QCommandLineOption scopeOpt({"s", "scope"},
|
||||||
|
tr("Search scope. Possible values: buffer/folder/notebook/all_notebook."),
|
||||||
|
tr("search_scope"),
|
||||||
|
"notebook");
|
||||||
|
m_parser.addOption(scopeOpt);
|
||||||
|
|
||||||
|
QCommandLineOption objectOpt({"b", "object"},
|
||||||
|
tr("Search objects. Possible values: name/content/tag/path."),
|
||||||
|
tr("search_objects"));
|
||||||
|
objectOpt.setDefaultValues({"name", "content"});
|
||||||
|
m_parser.addOption(objectOpt);
|
||||||
|
|
||||||
|
QCommandLineOption targetOpt({"t", "target"},
|
||||||
|
tr("Search targets. Possible values: file/folder/notebook."),
|
||||||
|
tr("search_targets"));
|
||||||
|
targetOpt.setDefaultValues({"file", "folder"});
|
||||||
|
m_parser.addOption(targetOpt);
|
||||||
|
|
||||||
|
QCommandLineOption patternOpt({"p", "pattern"},
|
||||||
|
tr("Wildcard pattern of files to search."),
|
||||||
|
tr("file_pattern"));
|
||||||
|
m_parser.addOption(patternOpt);
|
||||||
|
|
||||||
|
SearchToken::addSearchOptionsToCommand(&m_parser);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FindUnitedEntry::processInternal(const QString &p_args,
|
||||||
|
const std::function<void(const QSharedPointer<QWidget> &)> &p_popupWidgetFunc)
|
||||||
|
{
|
||||||
|
// Do another timer delay here since it is a very expensive operation.
|
||||||
|
m_processTimer->stop();
|
||||||
|
|
||||||
|
Q_ASSERT(!isOngoing());
|
||||||
|
|
||||||
|
setOngoing(true);
|
||||||
|
|
||||||
|
auto args = ProcessUtils::parseCombinedArgString(p_args);
|
||||||
|
// The parser needs the first arg to be the application name.
|
||||||
|
args.prepend(name());
|
||||||
|
bool ret = m_parser.parse(args);
|
||||||
|
const auto positionalArgs = m_parser.positionalArguments();
|
||||||
|
if (!ret) {
|
||||||
|
auto label = EntryWidgetFactory::createLabel(m_parser.errorText());
|
||||||
|
p_popupWidgetFunc(label);
|
||||||
|
finish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (positionalArgs.isEmpty()) {
|
||||||
|
auto label = EntryWidgetFactory::createLabel(getHelpText());
|
||||||
|
p_popupWidgetFunc(label);
|
||||||
|
finish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto opt = collectOptions();
|
||||||
|
if (m_searchOption && m_searchOption->strictEquals(*opt)) {
|
||||||
|
// Reuse last result.
|
||||||
|
p_popupWidgetFunc(m_resultTree);
|
||||||
|
finish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_searchOption = opt;
|
||||||
|
|
||||||
|
m_searchTokenOfSession.clear();
|
||||||
|
|
||||||
|
prepareResultTree();
|
||||||
|
|
||||||
|
p_popupWidgetFunc(m_resultTree);
|
||||||
|
|
||||||
|
m_processTimer->start();
|
||||||
|
}
|
||||||
|
|
||||||
|
QSharedPointer<SearchOption> FindUnitedEntry::collectOptions() const
|
||||||
|
{
|
||||||
|
auto opt = QSharedPointer<SearchOption>::create();
|
||||||
|
|
||||||
|
opt->m_engine = SearchEngine::Internal;
|
||||||
|
|
||||||
|
opt->m_keyword = m_parser.positionalArguments().join(QLatin1Char(' '));
|
||||||
|
Q_ASSERT(!opt->m_keyword.isEmpty());
|
||||||
|
|
||||||
|
opt->m_filePattern = m_parser.value("p");
|
||||||
|
|
||||||
|
{
|
||||||
|
SearchScope scope = SearchScope::CurrentNotebook;
|
||||||
|
const auto scopeStr = m_parser.value("s");
|
||||||
|
if (scopeStr == QStringLiteral("buffer")) {
|
||||||
|
scope = SearchScope::Buffers;
|
||||||
|
} else if (scopeStr == QStringLiteral("folder")) {
|
||||||
|
scope = SearchScope::CurrentFolder;
|
||||||
|
} else if (scopeStr == QStringLiteral("notebook")) {
|
||||||
|
scope = SearchScope::CurrentNotebook;
|
||||||
|
} else if (scopeStr == QStringLiteral("all_notebook")) {
|
||||||
|
scope = SearchScope::AllNotebooks;
|
||||||
|
}
|
||||||
|
opt->m_scope = scope;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
SearchObjects objects = SearchObject::ObjectNone;
|
||||||
|
const auto objectStrs = m_parser.values("b");
|
||||||
|
for (const auto &str : objectStrs) {
|
||||||
|
if (str == QStringLiteral("name")) {
|
||||||
|
objects |= SearchObject::SearchName;
|
||||||
|
} else if (str == QStringLiteral("content")) {
|
||||||
|
objects |= SearchObject::SearchContent;
|
||||||
|
} else if (str == QStringLiteral("tag")) {
|
||||||
|
objects |= SearchObject::SearchTag;
|
||||||
|
} else if (str == QStringLiteral("path")) {
|
||||||
|
objects |= SearchObject::SearchPath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
opt->m_objects = objects;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
SearchTargets targets = SearchTarget::TargetNone;
|
||||||
|
auto targetStrs = m_parser.values("t");
|
||||||
|
for (const auto &str : targetStrs) {
|
||||||
|
if (str == QStringLiteral("file")) {
|
||||||
|
targets |= SearchTarget::SearchFile;
|
||||||
|
} else if (str == QStringLiteral("folder")) {
|
||||||
|
targets |= SearchTarget::SearchFolder;
|
||||||
|
} else if (str == QStringLiteral("notebook")) {
|
||||||
|
targets |= SearchTarget::SearchNotebook;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
opt->m_targets = targets;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
FindOptions options = FindOption::FindNone;
|
||||||
|
if (m_parser.isSet("c")) {
|
||||||
|
options |= FindOption::CaseSensitive;
|
||||||
|
}
|
||||||
|
if (m_parser.isSet("r")) {
|
||||||
|
options |= FindOption::RegularExpression;
|
||||||
|
}
|
||||||
|
if (m_parser.isSet("w")) {
|
||||||
|
options |= FindOption::WholeWordOnly;
|
||||||
|
}
|
||||||
|
if (m_parser.isSet("f")) {
|
||||||
|
options |= FindOption::FuzzySearch;
|
||||||
|
}
|
||||||
|
opt->m_findOptions = options;
|
||||||
|
}
|
||||||
|
|
||||||
|
return opt;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString FindUnitedEntry::getHelpText() const
|
||||||
|
{
|
||||||
|
auto text = m_parser.helpText();
|
||||||
|
// Skip the first line containing the application name.
|
||||||
|
return text.mid(text.indexOf('\n') + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
Searcher *FindUnitedEntry::getSearcher()
|
||||||
|
{
|
||||||
|
if (!m_searcher) {
|
||||||
|
m_searcher = new Searcher(this);
|
||||||
|
connect(m_searcher, &Searcher::resultItemAdded,
|
||||||
|
this, [this](const QSharedPointer<SearchResultItem> &p_item) {
|
||||||
|
addLocation(p_item->m_location);
|
||||||
|
});
|
||||||
|
connect(m_searcher, &Searcher::resultItemsAdded,
|
||||||
|
this, [this](const QVector<QSharedPointer<SearchResultItem>> &p_items) {
|
||||||
|
for (const auto &item : p_items) {
|
||||||
|
addLocation(item->m_location);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
connect(m_searcher, &Searcher::finished,
|
||||||
|
this, &FindUnitedEntry::handleSearchFinished);
|
||||||
|
}
|
||||||
|
return m_searcher;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FindUnitedEntry::handleSearchFinished(SearchState p_state)
|
||||||
|
{
|
||||||
|
if (p_state != SearchState::Busy) {
|
||||||
|
getSearcher()->clear();
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FindUnitedEntry::prepareResultTree()
|
||||||
|
{
|
||||||
|
if (!m_resultTree) {
|
||||||
|
m_resultTree = EntryWidgetFactory::createTreeWidget(1);
|
||||||
|
connect(m_resultTree.data(), &QTreeWidget::itemActivated,
|
||||||
|
this, &FindUnitedEntry::handleItemActivated);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_resultTree->clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FindUnitedEntry::addLocation(const ComplexLocation &p_location)
|
||||||
|
{
|
||||||
|
auto item = new QTreeWidgetItem(m_resultTree.data());
|
||||||
|
item->setText(0, p_location.m_displayPath);
|
||||||
|
item->setIcon(0, UnitedEntryHelper::itemIcon(UnitedEntryHelper::locationTypeToItemType(p_location.m_type)));
|
||||||
|
item->setData(0, Qt::UserRole, p_location.m_path);
|
||||||
|
item->setToolTip(0, p_location.m_path);
|
||||||
|
|
||||||
|
// Add sub items.
|
||||||
|
for (const auto &line : p_location.m_lines) {
|
||||||
|
auto subItem = new QTreeWidgetItem(item);
|
||||||
|
|
||||||
|
// Truncate the text.
|
||||||
|
if (line.m_text.size() > 500) {
|
||||||
|
subItem->setText(0, line.m_text.left(500));
|
||||||
|
} else {
|
||||||
|
subItem->setText(0, line.m_text);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!line.m_segments.isEmpty()) {
|
||||||
|
subItem->setData(0, HighlightsRole, QVariant::fromValue(line.m_segments));
|
||||||
|
}
|
||||||
|
|
||||||
|
subItem->setData(0, Qt::UserRole, line.m_lineNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_mgr->getExpandAllEnabled()) {
|
||||||
|
item->setExpanded(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_resultTree->topLevelItemCount() == 1) {
|
||||||
|
m_resultTree->setCurrentItem(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FindUnitedEntry::doProcessInternal()
|
||||||
|
{
|
||||||
|
if (isAskedToStop()) {
|
||||||
|
finish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString msg;
|
||||||
|
auto state = SearchHelper::searchOnProvider(getSearcher(), m_searchOption, m_provider, msg);
|
||||||
|
if (!msg.isEmpty()) {
|
||||||
|
qWarning() << msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
handleSearchFinished(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FindUnitedEntry::stop()
|
||||||
|
{
|
||||||
|
IUnitedEntry::stop();
|
||||||
|
|
||||||
|
if (m_processTimer->isActive()) {
|
||||||
|
m_processTimer->stop();
|
||||||
|
// Let it go finished.
|
||||||
|
doProcessInternal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FindUnitedEntry::finish()
|
||||||
|
{
|
||||||
|
setOngoing(false);
|
||||||
|
emit finished();
|
||||||
|
}
|
||||||
|
|
||||||
|
QSharedPointer<QWidget> FindUnitedEntry::currentPopupWidget() const
|
||||||
|
{
|
||||||
|
return m_resultTree;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FindUnitedEntry::handleItemActivated(QTreeWidgetItem *p_item, int p_column)
|
||||||
|
{
|
||||||
|
Q_UNUSED(p_column);
|
||||||
|
|
||||||
|
if (!m_searchTokenOfSession) {
|
||||||
|
if (m_searchOption->m_objects & SearchObject::SearchContent) {
|
||||||
|
m_searchTokenOfSession = QSharedPointer<SearchToken>::create(getSearcher()->getToken());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: decode the path of location and handle different types of destination.
|
||||||
|
auto paras = QSharedPointer<FileOpenParameters>::create();
|
||||||
|
|
||||||
|
QString itemPath;
|
||||||
|
auto pa = p_item->parent();
|
||||||
|
if (pa) {
|
||||||
|
itemPath = pa->data(0, Qt::UserRole).toString();
|
||||||
|
paras->m_lineNumber = p_item->data(0, Qt::UserRole).toInt();
|
||||||
|
} else {
|
||||||
|
itemPath = p_item->data(0, Qt::UserRole).toString();
|
||||||
|
// Use the first line number if there is any.
|
||||||
|
if (p_item->childCount() > 0) {
|
||||||
|
auto childItem = p_item->child(0);
|
||||||
|
paras->m_lineNumber = childItem->data(0, Qt::UserRole).toInt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
paras->m_searchToken = m_searchTokenOfSession;
|
||||||
|
emit VNoteX::getInst().openFileRequested(itemPath, paras);
|
||||||
|
}
|
75
src/unitedentry/findunitedentry.h
Normal file
75
src/unitedentry/findunitedentry.h
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
#ifndef FINDUNITEDENTRY_H
|
||||||
|
#define FINDUNITEDENTRY_H
|
||||||
|
|
||||||
|
#include "iunitedentry.h"
|
||||||
|
|
||||||
|
#include <QCommandLineParser>
|
||||||
|
#include <QSharedPointer>
|
||||||
|
|
||||||
|
#include <search/searchdata.h>
|
||||||
|
|
||||||
|
class QTreeWidget;
|
||||||
|
class QTreeWidgetItem;
|
||||||
|
class QTimer;
|
||||||
|
|
||||||
|
namespace vnotex
|
||||||
|
{
|
||||||
|
class Searcher;
|
||||||
|
class ISearchInfoProvider;
|
||||||
|
struct ComplexLocation;
|
||||||
|
class SearchToken;
|
||||||
|
|
||||||
|
class FindUnitedEntry : public IUnitedEntry
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
FindUnitedEntry(const QSharedPointer<ISearchInfoProvider> &p_provider,
|
||||||
|
const UnitedEntryMgr *p_mgr,
|
||||||
|
QObject *p_parent = nullptr);
|
||||||
|
|
||||||
|
void stop() Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
QSharedPointer<QWidget> currentPopupWidget() const Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void initOnFirstProcess() Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
void processInternal(const QString &p_args,
|
||||||
|
const std::function<void(const QSharedPointer<QWidget> &)> &p_popupWidgetFunc) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString getHelpText() const;
|
||||||
|
|
||||||
|
QSharedPointer<SearchOption> collectOptions() const;
|
||||||
|
|
||||||
|
Searcher *getSearcher();
|
||||||
|
|
||||||
|
void handleSearchFinished(SearchState p_state);
|
||||||
|
|
||||||
|
void prepareResultTree();
|
||||||
|
|
||||||
|
void addLocation(const ComplexLocation &p_location);
|
||||||
|
|
||||||
|
void doProcessInternal();
|
||||||
|
|
||||||
|
void finish();
|
||||||
|
|
||||||
|
void handleItemActivated(QTreeWidgetItem *p_item, int p_column);
|
||||||
|
|
||||||
|
QSharedPointer<ISearchInfoProvider> m_provider;
|
||||||
|
|
||||||
|
QCommandLineParser m_parser;
|
||||||
|
|
||||||
|
Searcher *m_searcher = nullptr;
|
||||||
|
|
||||||
|
QSharedPointer<QTreeWidget> m_resultTree;
|
||||||
|
|
||||||
|
QTimer *m_processTimer = nullptr;
|
||||||
|
|
||||||
|
QSharedPointer<SearchOption> m_searchOption;
|
||||||
|
|
||||||
|
QSharedPointer<SearchToken> m_searchTokenOfSession;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // FINDUNITEDENTRY_H
|
48
src/unitedentry/helpunitedentry.cpp
Normal file
48
src/unitedentry/helpunitedentry.cpp
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
#include "helpunitedentry.h"
|
||||||
|
|
||||||
|
#include <widgets/treewidget.h>
|
||||||
|
|
||||||
|
#include "entrywidgetfactory.h"
|
||||||
|
|
||||||
|
using namespace vnotex;
|
||||||
|
|
||||||
|
HelpUnitedEntry::HelpUnitedEntry(const UnitedEntryMgr *p_mgr, QObject *p_parent)
|
||||||
|
: IUnitedEntry("help",
|
||||||
|
tr("Help information about United Entry"),
|
||||||
|
p_mgr,
|
||||||
|
p_parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QSharedPointer<QWidget> HelpUnitedEntry::currentPopupWidget() const
|
||||||
|
{
|
||||||
|
return m_infoTree;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HelpUnitedEntry::initOnFirstProcess()
|
||||||
|
{
|
||||||
|
m_infoTree = EntryWidgetFactory::createTreeWidget(2);
|
||||||
|
m_infoTree->setHeaderHidden(false);
|
||||||
|
m_infoTree->setHeaderLabels(QStringList() << tr("Shortcut") << tr("Description"));
|
||||||
|
|
||||||
|
QVector<QStringList> shortcuts = {{"Esc/Ctrl+[", tr("Close United Entry")},
|
||||||
|
{"Up/Ctrl+K", tr("Go to previous item")},
|
||||||
|
{"Down/Ctrl+J", tr("Go to next item")},
|
||||||
|
{"Ctrl+L", tr("Go to the item one level up")},
|
||||||
|
{"Ctrl+I", tr("Expand/Collapse current item")},
|
||||||
|
{"Ctrl+B", tr("Expand/Collapse all the items")},
|
||||||
|
{"Enter", tr("Activate current item")},
|
||||||
|
{"Ctrl+E", tr("Clear the input except the entry name")},
|
||||||
|
{"Ctrl+F", tr("Select the entry name")},
|
||||||
|
{"Ctrl+D", tr("Stop current entry")}};
|
||||||
|
for (const auto &shortcut : shortcuts) {
|
||||||
|
m_infoTree->addTopLevelItem(new QTreeWidgetItem(shortcut));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HelpUnitedEntry::processInternal(const QString &p_args,
|
||||||
|
const std::function<void(const QSharedPointer<QWidget> &)> &p_popupWidgetFunc)
|
||||||
|
{
|
||||||
|
Q_UNUSED(p_args);
|
||||||
|
p_popupWidgetFunc(m_infoTree);
|
||||||
|
}
|
31
src/unitedentry/helpunitedentry.h
Normal file
31
src/unitedentry/helpunitedentry.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#ifndef HELPUNITEDENTRY_H
|
||||||
|
#define HELPUNITEDENTRY_H
|
||||||
|
|
||||||
|
#include "iunitedentry.h"
|
||||||
|
|
||||||
|
#include <QSharedPointer>
|
||||||
|
|
||||||
|
class QTreeWidget;
|
||||||
|
|
||||||
|
namespace vnotex
|
||||||
|
{
|
||||||
|
class HelpUnitedEntry : public IUnitedEntry
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
HelpUnitedEntry(const UnitedEntryMgr *p_mgr, QObject *p_parent = nullptr);
|
||||||
|
|
||||||
|
QSharedPointer<QWidget> currentPopupWidget() const Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void initOnFirstProcess() Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
void processInternal(const QString &p_args,
|
||||||
|
const std::function<void(const QSharedPointer<QWidget> &)> &p_popupWidgetFunc) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QSharedPointer<QTreeWidget> m_infoTree;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // HELPUNITEDENTRY_H
|
138
src/unitedentry/iunitedentry.cpp
Normal file
138
src/unitedentry/iunitedentry.cpp
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
#include "iunitedentry.h"
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
#include <QCoreApplication>
|
||||||
|
#include <QKeyEvent>
|
||||||
|
|
||||||
|
#include <widgets/treewidget.h>
|
||||||
|
|
||||||
|
using namespace vnotex;
|
||||||
|
|
||||||
|
IUnitedEntry::IUnitedEntry(const QString &p_name,
|
||||||
|
const QString &p_description,
|
||||||
|
const UnitedEntryMgr *p_mgr,
|
||||||
|
QObject *p_parent)
|
||||||
|
: QObject(p_parent),
|
||||||
|
m_name(p_name),
|
||||||
|
m_description(p_description),
|
||||||
|
m_mgr(p_mgr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString &IUnitedEntry::name() const
|
||||||
|
{
|
||||||
|
return m_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString IUnitedEntry::description() const
|
||||||
|
{
|
||||||
|
return m_description;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IUnitedEntry::process(const QString &p_args,
|
||||||
|
const std::function<void(const QSharedPointer<QWidget> &)> &p_popupWidgetFunc)
|
||||||
|
{
|
||||||
|
if (!m_initialized) {
|
||||||
|
m_initialized = true;
|
||||||
|
|
||||||
|
initOnFirstProcess();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_askedToStop.store(0);
|
||||||
|
|
||||||
|
return processInternal(p_args, p_popupWidgetFunc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IUnitedEntry::stop()
|
||||||
|
{
|
||||||
|
m_askedToStop.store(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IUnitedEntry::isAskedToStop() const
|
||||||
|
{
|
||||||
|
return m_askedToStop.load() == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IUnitedEntry::setOngoing(bool p_ongoing)
|
||||||
|
{
|
||||||
|
m_ongoing = p_ongoing;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IUnitedEntry::isOngoing() const
|
||||||
|
{
|
||||||
|
return m_ongoing;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IUnitedEntry::handleAction(Action p_act)
|
||||||
|
{
|
||||||
|
auto widget = currentPopupWidget();
|
||||||
|
if (!widget) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
handleActionCommon(p_act, widget.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
void IUnitedEntry::handleActionCommon(Action p_act, QWidget *p_widget)
|
||||||
|
{
|
||||||
|
switch (p_act)
|
||||||
|
{
|
||||||
|
case Action::NextItem:
|
||||||
|
{
|
||||||
|
auto eve = new QKeyEvent(QEvent::KeyPress, Qt::Key_Down, Qt::NoModifier);
|
||||||
|
QCoreApplication::postEvent(p_widget, eve);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Action::PreviousItem:
|
||||||
|
{
|
||||||
|
auto eve = new QKeyEvent(QEvent::KeyPress, Qt::Key_Up, Qt::NoModifier);
|
||||||
|
QCoreApplication::postEvent(p_widget, eve);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Action::Activate:
|
||||||
|
{
|
||||||
|
auto eve = new QKeyEvent(QEvent::KeyPress, Qt::Key_Enter, Qt::NoModifier);
|
||||||
|
QCoreApplication::postEvent(p_widget, eve);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Action::LevelUp:
|
||||||
|
{
|
||||||
|
auto treeWidget = dynamic_cast<QTreeWidget *>(p_widget);
|
||||||
|
if (treeWidget) {
|
||||||
|
TreeWidget::selectParentItem(treeWidget);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Action::ExpandCollapse:
|
||||||
|
{
|
||||||
|
auto treeWidget = dynamic_cast<QTreeWidget *>(p_widget);
|
||||||
|
if (treeWidget) {
|
||||||
|
auto item = treeWidget->currentItem();
|
||||||
|
if (item) {
|
||||||
|
item->setExpanded(!item->isExpanded());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Action::ExpandCollapseAll:
|
||||||
|
{
|
||||||
|
auto treeWidget = dynamic_cast<QTreeWidget *>(p_widget);
|
||||||
|
if (treeWidget) {
|
||||||
|
if (TreeWidget::isExpanded(treeWidget)) {
|
||||||
|
treeWidget->collapseAll();
|
||||||
|
} else {
|
||||||
|
treeWidget->expandAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
Q_ASSERT(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
79
src/unitedentry/iunitedentry.h
Normal file
79
src/unitedentry/iunitedentry.h
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
#ifndef IUNITEDENTRY_H
|
||||||
|
#define IUNITEDENTRY_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
#include <QAtomicInt>
|
||||||
|
|
||||||
|
namespace vnotex
|
||||||
|
{
|
||||||
|
class UnitedEntryMgr;
|
||||||
|
|
||||||
|
// Interface of a UnitedEntry.
|
||||||
|
class IUnitedEntry : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
enum class Action
|
||||||
|
{
|
||||||
|
NextItem,
|
||||||
|
PreviousItem,
|
||||||
|
Activate,
|
||||||
|
LevelUp,
|
||||||
|
ExpandCollapse,
|
||||||
|
ExpandCollapseAll
|
||||||
|
};
|
||||||
|
|
||||||
|
IUnitedEntry(const QString &p_name,
|
||||||
|
const QString &p_description,
|
||||||
|
const UnitedEntryMgr *p_mgr,
|
||||||
|
QObject *p_parent = nullptr);
|
||||||
|
|
||||||
|
const QString &name() const;
|
||||||
|
|
||||||
|
virtual QString description() const;
|
||||||
|
|
||||||
|
void process(const QString &p_args,
|
||||||
|
const std::function<void(const QSharedPointer<QWidget> &)> &p_popupWidgetFunc);
|
||||||
|
|
||||||
|
virtual bool isOngoing() const;
|
||||||
|
|
||||||
|
virtual void stop();
|
||||||
|
|
||||||
|
virtual void handleAction(Action p_act);
|
||||||
|
|
||||||
|
virtual QSharedPointer<QWidget> currentPopupWidget() const = 0;
|
||||||
|
|
||||||
|
static void handleActionCommon(Action p_act, QWidget *p_widget);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void finished();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void initOnFirstProcess() = 0;
|
||||||
|
|
||||||
|
virtual void processInternal(const QString &p_args,
|
||||||
|
const std::function<void(const QSharedPointer<QWidget> &)> &p_popupWidgetFunc) = 0;
|
||||||
|
|
||||||
|
bool isAskedToStop() const;
|
||||||
|
|
||||||
|
virtual void setOngoing(bool p_ongoing);
|
||||||
|
|
||||||
|
const UnitedEntryMgr *m_mgr = nullptr;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool m_initialized = false;
|
||||||
|
|
||||||
|
QString m_name;
|
||||||
|
|
||||||
|
QString m_description;
|
||||||
|
|
||||||
|
QAtomicInt m_askedToStop = 0;
|
||||||
|
|
||||||
|
bool m_ongoing = false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // IUNITEDENTRY_H
|
487
src/unitedentry/unitedentry.cpp
Normal file
487
src/unitedentry/unitedentry.cpp
Normal file
@ -0,0 +1,487 @@
|
|||||||
|
#include "unitedentry.h"
|
||||||
|
|
||||||
|
#include <QHBoxLayout>
|
||||||
|
#include <QSizePolicy>
|
||||||
|
#include <QAction>
|
||||||
|
#include <QFocusEvent>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QKeySequence>
|
||||||
|
#include <QShortcut>
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <QTreeWidget>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QFont>
|
||||||
|
#include <QMenu>
|
||||||
|
|
||||||
|
#include <widgets/lineeditwithsnippet.h>
|
||||||
|
#include <widgets/widgetsfactory.h>
|
||||||
|
#include <widgets/propertydefs.h>
|
||||||
|
#include <widgets/mainwindow.h>
|
||||||
|
#include <core/configmgr.h>
|
||||||
|
#include <core/coreconfig.h>
|
||||||
|
#include <core/widgetconfig.h>
|
||||||
|
#include <core/thememgr.h>
|
||||||
|
#include <core/vnotex.h>
|
||||||
|
#include <utils/widgetutils.h>
|
||||||
|
#include <utils/iconutils.h>
|
||||||
|
|
||||||
|
#include "entrypopup.h"
|
||||||
|
#include "entrywidgetfactory.h"
|
||||||
|
#include "unitedentrymgr.h"
|
||||||
|
#include "iunitedentry.h"
|
||||||
|
#include "unitedentryhelper.h"
|
||||||
|
|
||||||
|
using namespace vnotex;
|
||||||
|
|
||||||
|
UnitedEntry::UnitedEntry(QWidget *p_parent)
|
||||||
|
: QWidget(p_parent)
|
||||||
|
{
|
||||||
|
m_processTimer = new QTimer(this);
|
||||||
|
m_processTimer->setSingleShot(true);
|
||||||
|
m_processTimer->setInterval(300);
|
||||||
|
connect(m_processTimer, &QTimer::timeout,
|
||||||
|
this, &UnitedEntry::processInput);
|
||||||
|
|
||||||
|
setupUI();
|
||||||
|
|
||||||
|
connect(qApp, &QApplication::focusChanged,
|
||||||
|
this, &UnitedEntry::handleFocusChanged);
|
||||||
|
|
||||||
|
connect(&UnitedEntryMgr::getInst(), &UnitedEntryMgr::entryFinished,
|
||||||
|
this, &UnitedEntry::handleEntryFinished);
|
||||||
|
}
|
||||||
|
|
||||||
|
UnitedEntry::~UnitedEntry()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnitedEntry::setupUI()
|
||||||
|
{
|
||||||
|
auto mainLayout = new QHBoxLayout(this);
|
||||||
|
mainLayout->setContentsMargins(0, 0, 0, 0);
|
||||||
|
|
||||||
|
setSizePolicy(QSizePolicy::Policy::Preferred, QSizePolicy::Policy::Fixed);
|
||||||
|
|
||||||
|
// Shortcut.
|
||||||
|
const auto shortcut = ConfigMgr::getInst().getCoreConfig().getShortcut(CoreConfig::Shortcut::UnitedEntry);
|
||||||
|
const QKeySequence kseq(shortcut);
|
||||||
|
const auto shortcutText = kseq.isEmpty() ? QString() : kseq.toString(QKeySequence::NativeText);
|
||||||
|
if (!kseq.isEmpty()) {
|
||||||
|
auto sc = WidgetUtils::createShortcut(shortcut, this, Qt::ShortcutContext::ApplicationShortcut);
|
||||||
|
if (sc) {
|
||||||
|
connect(sc, &QShortcut::activated,
|
||||||
|
this, [this]() {
|
||||||
|
if (m_lineEdit->hasFocus()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool popupVisible = m_popup->isVisible();
|
||||||
|
if (popupVisible) {
|
||||||
|
// Make m_lineEdit->setFocus() work.
|
||||||
|
m_popup->hide();
|
||||||
|
}
|
||||||
|
m_lineEdit->setFocus();
|
||||||
|
if (popupVisible) {
|
||||||
|
m_popup->show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setToolTip(shortcutText.isEmpty() ? tr("United Entry") : tr("United Entry (%1)").arg(shortcutText));
|
||||||
|
|
||||||
|
// Line edit.
|
||||||
|
m_lineEdit = WidgetsFactory::createLineEditWithSnippet(this);
|
||||||
|
mainLayout->addWidget(m_lineEdit);
|
||||||
|
m_lineEdit->setToolTip(QString());
|
||||||
|
m_lineEdit->setPlaceholderText(shortcutText.isEmpty() ? tr("Type to command") : tr("Type to command (%1)").arg(shortcutText));
|
||||||
|
m_lineEdit->setClearButtonEnabled(true);
|
||||||
|
m_lineEdit->setSizePolicy(QSizePolicy::Policy::Preferred, QSizePolicy::Policy::Fixed);
|
||||||
|
connect(m_lineEdit, &QLineEdit::textChanged,
|
||||||
|
m_processTimer, QOverload<void>::of(&QTimer::start));
|
||||||
|
setFocusProxy(m_lineEdit);
|
||||||
|
|
||||||
|
// Popup.
|
||||||
|
m_popup = new EntryPopup(this);
|
||||||
|
m_popup->installEventFilter(this);
|
||||||
|
m_popup->hide();
|
||||||
|
|
||||||
|
setupIcons();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnitedEntry::setupIcons()
|
||||||
|
{
|
||||||
|
const auto &themeMgr = VNoteX::getInst().getThemeMgr();
|
||||||
|
const auto fg = themeMgr.paletteColor("widgets#unitedentry#icon#fg");
|
||||||
|
// Use QIcon::Disabled as the busy state.
|
||||||
|
const auto busyFg = themeMgr.paletteColor("widgets#unitedentry#icon#busy#fg");
|
||||||
|
QVector<IconUtils::OverriddenColor> colors;
|
||||||
|
colors.push_back(IconUtils::OverriddenColor(fg, QIcon::Normal));
|
||||||
|
colors.push_back(IconUtils::OverriddenColor(busyFg, QIcon::Disabled));
|
||||||
|
|
||||||
|
const auto icon = IconUtils::fetchIcon(themeMgr.getIconFile("united_entry.svg"), colors);
|
||||||
|
m_iconAction = m_lineEdit->addAction(icon, QLineEdit::ActionPosition::LeadingPosition);
|
||||||
|
m_iconAction->setText(tr("Options"));
|
||||||
|
|
||||||
|
// Menu.
|
||||||
|
auto menu = WidgetsFactory::createMenu(this);
|
||||||
|
m_iconAction->setMenu(menu);
|
||||||
|
|
||||||
|
{
|
||||||
|
auto expandAct = menu->addAction(tr("Expand All"),
|
||||||
|
this,
|
||||||
|
[this](bool checked) {
|
||||||
|
ConfigMgr::getInst().getWidgetConfig().setUnitedEntryExpandAllEnabled(checked);
|
||||||
|
UnitedEntryMgr::getInst().setExpandAllEnabled(checked);
|
||||||
|
});
|
||||||
|
expandAct->setCheckable(true);
|
||||||
|
expandAct->setChecked(ConfigMgr::getInst().getWidgetConfig().getUnitedEntryExpandAllEnabled());
|
||||||
|
UnitedEntryMgr::getInst().setExpandAllEnabled(expandAct->isChecked());
|
||||||
|
}
|
||||||
|
|
||||||
|
connect(m_iconAction, &QAction::triggered,
|
||||||
|
this, [this]() {
|
||||||
|
auto pos = mapToGlobal(QPoint(0, height()));
|
||||||
|
auto menu = m_iconAction->menu();
|
||||||
|
menu->exec(pos);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnitedEntry::activateUnitedEntry()
|
||||||
|
{
|
||||||
|
if (m_activated) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!UnitedEntryMgr::getInst().isInitialized()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_activated = true;
|
||||||
|
|
||||||
|
setSizePolicy(QSizePolicy::Policy::MinimumExpanding, QSizePolicy::Policy::Fixed);
|
||||||
|
|
||||||
|
m_lineEdit->selectAll();
|
||||||
|
m_lineEdit->setFocus();
|
||||||
|
|
||||||
|
m_processTimer->start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnitedEntry::deactivateUnitedEntry()
|
||||||
|
{
|
||||||
|
if (!m_activated) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_activated = false;
|
||||||
|
m_previousFocusWidget = nullptr;
|
||||||
|
|
||||||
|
setSizePolicy(QSizePolicy::Policy::Preferred, QSizePolicy::Policy::Fixed);
|
||||||
|
|
||||||
|
m_popup->hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnitedEntry::handleFocusChanged(QWidget *p_old, QWidget *p_now)
|
||||||
|
{
|
||||||
|
if (p_now == m_lineEdit) {
|
||||||
|
activateUnitedEntry();
|
||||||
|
if (!m_previousFocusWidget && p_old != this && !WidgetUtils::isOrAncestorOf(this, p_old)) {
|
||||||
|
m_previousFocusWidget = p_old;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_activated) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!p_now || (p_now != this && !WidgetUtils::isOrAncestorOf(this, p_now))) {
|
||||||
|
deactivateUnitedEntry();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnitedEntry::keyPressEvent(QKeyEvent *p_event)
|
||||||
|
{
|
||||||
|
const int key = p_event->key();
|
||||||
|
const int modifiers = p_event->modifiers();
|
||||||
|
IUnitedEntry::Action act = IUnitedEntry::Action::NextItem;
|
||||||
|
switch (key) {
|
||||||
|
case Qt::Key_BracketLeft:
|
||||||
|
if (!WidgetUtils::isViControlModifier(modifiers)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Q_FALLTHROUGH();
|
||||||
|
case Qt::Key_Escape:
|
||||||
|
exitUnitedEntry();
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Up/Down Ctrl+K/J to navigate to previous/next item.
|
||||||
|
case Qt::Key_Up:
|
||||||
|
act = IUnitedEntry::Action::PreviousItem;
|
||||||
|
Q_FALLTHROUGH();
|
||||||
|
case Qt::Key_Down:
|
||||||
|
if (m_lastEntry) {
|
||||||
|
m_lastEntry->handleAction(act);
|
||||||
|
} else if (m_entryListWidget && m_entryListWidget->isVisible()) {
|
||||||
|
IUnitedEntry::handleActionCommon(act, m_entryListWidget.data());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Qt::Key_K:
|
||||||
|
act = IUnitedEntry::Action::PreviousItem;
|
||||||
|
Q_FALLTHROUGH();
|
||||||
|
case Qt::Key_J:
|
||||||
|
if (WidgetUtils::isViControlModifier(modifiers)) {
|
||||||
|
if (m_lastEntry) {
|
||||||
|
m_lastEntry->handleAction(act);
|
||||||
|
} else if (m_entryListWidget && m_entryListWidget->isVisible()) {
|
||||||
|
IUnitedEntry::handleActionCommon(act, m_entryListWidget.data());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Qt::Key_Enter:
|
||||||
|
Q_FALLTHROUGH();
|
||||||
|
case Qt::Key_Return:
|
||||||
|
if (m_lastEntry) {
|
||||||
|
m_lastEntry->handleAction(IUnitedEntry::Action::Activate);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Qt::Key_E:
|
||||||
|
if (WidgetUtils::isViControlModifier(modifiers)) {
|
||||||
|
// Eliminate input till the entry name.
|
||||||
|
const auto text = m_lineEdit->evaluatedText();
|
||||||
|
const auto entry = UnitedEntryHelper::parseUserEntry(text);
|
||||||
|
if (!entry.m_name.isEmpty()) {
|
||||||
|
m_lineEdit->setText(entry.m_name + QLatin1Char(' '));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Qt::Key_F:
|
||||||
|
if (WidgetUtils::isViControlModifier(modifiers)) {
|
||||||
|
// Select the entry name.
|
||||||
|
const auto text = m_lineEdit->evaluatedText();
|
||||||
|
const auto entry = UnitedEntryHelper::parseUserEntry(text);
|
||||||
|
if (!entry.m_name.isEmpty()) {
|
||||||
|
m_lineEdit->setSelection(0, entry.m_name.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Qt::Key_D:
|
||||||
|
if (WidgetUtils::isViControlModifier(modifiers)) {
|
||||||
|
// Stop the entry.
|
||||||
|
if (m_lastEntry) {
|
||||||
|
m_lastEntry->stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Qt::Key_L:
|
||||||
|
if (WidgetUtils::isViControlModifier(modifiers)) {
|
||||||
|
// Go up one level.
|
||||||
|
if (m_lastEntry) {
|
||||||
|
m_lastEntry->handleAction(IUnitedEntry::Action::LevelUp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Qt::Key_I:
|
||||||
|
if (WidgetUtils::isViControlModifier(modifiers)) {
|
||||||
|
// Expand/Collapse the item.
|
||||||
|
if (m_lastEntry) {
|
||||||
|
m_lastEntry->handleAction(IUnitedEntry::Action::ExpandCollapse);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Qt::Key_B:
|
||||||
|
if (WidgetUtils::isViControlModifier(modifiers)) {
|
||||||
|
// Expand/Collapse all the items.
|
||||||
|
if (m_lastEntry) {
|
||||||
|
m_lastEntry->handleAction(IUnitedEntry::Action::ExpandCollapseAll);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
QWidget::keyPressEvent(p_event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnitedEntry::clear()
|
||||||
|
{
|
||||||
|
m_lineEdit->setFocus();
|
||||||
|
m_lineEdit->clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnitedEntry::processInput()
|
||||||
|
{
|
||||||
|
m_hasPending = false;
|
||||||
|
|
||||||
|
if (!m_activated) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_iconAction->menu()->isVisible()) {
|
||||||
|
// Do not display the popup which will hide the menu.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_lastEntry && m_lastEntry->isOngoing()) {
|
||||||
|
m_hasPending = true;
|
||||||
|
m_lastEntry->stop();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto text = m_lineEdit->evaluatedText();
|
||||||
|
const auto entry = UnitedEntryHelper::parseUserEntry(text);
|
||||||
|
if (entry.m_name.isEmpty()) {
|
||||||
|
filterEntryListWidgetEntries(entry.m_name);
|
||||||
|
popupWidget(getEntryListWidget());
|
||||||
|
m_lastEntry.clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter the help widget if space after entry name is not entered yet.
|
||||||
|
if (entry.m_name == text.trimmed() && !text.back().isSpace()) {
|
||||||
|
if (filterEntryListWidgetEntries(entry.m_name)) {
|
||||||
|
popupWidget(getEntryListWidget());
|
||||||
|
m_lastEntry.clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!m_lastEntry || m_lastEntry->name() == entry.m_name) {
|
||||||
|
m_lastEntry = UnitedEntryMgr::getInst().findEntry(entry.m_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_lastEntry) {
|
||||||
|
// Found.
|
||||||
|
setBusy(true);
|
||||||
|
m_lastEntry->process(entry.m_args, std::bind(&UnitedEntry::popupWidget, this, std::placeholders::_1));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// No entry found.
|
||||||
|
popupWidget(getInfoWidget(tr("Unknown entry: %1").arg(entry.m_name)));
|
||||||
|
m_lastEntry.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnitedEntry::popupWidget(const QSharedPointer<QWidget> &p_widget)
|
||||||
|
{
|
||||||
|
m_popup->setWidget(p_widget);
|
||||||
|
m_popup->show();
|
||||||
|
}
|
||||||
|
|
||||||
|
const QSharedPointer<QTreeWidget> &UnitedEntry::getEntryListWidget()
|
||||||
|
{
|
||||||
|
if (!m_entryListWidget) {
|
||||||
|
m_entryListWidget = EntryWidgetFactory::createTreeWidget(2);
|
||||||
|
m_entryListWidget->setHeaderHidden(false);
|
||||||
|
m_entryListWidget->setHeaderLabels(QStringList() << tr("Entry") << tr("Description"));
|
||||||
|
|
||||||
|
const auto entries = UnitedEntryMgr::getInst().getEntries();
|
||||||
|
for (const auto &entry : entries) {
|
||||||
|
m_entryListWidget->addTopLevelItem(new QTreeWidgetItem({entry->name(), entry->description()}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_entryListWidget;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSharedPointer<QLabel> UnitedEntry::getInfoWidget(const QString &p_info)
|
||||||
|
{
|
||||||
|
return EntryWidgetFactory::createLabel(p_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnitedEntry::resizeEvent(QResizeEvent *p_event)
|
||||||
|
{
|
||||||
|
QWidget::resizeEvent(p_event);
|
||||||
|
|
||||||
|
updatePopupGeometry();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnitedEntry::updatePopupGeometry()
|
||||||
|
{
|
||||||
|
m_popup->updateGeometryToContents();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UnitedEntry::filterEntryListWidgetEntries(const QString &p_name)
|
||||||
|
{
|
||||||
|
const auto &entryListWidget = getEntryListWidget();
|
||||||
|
|
||||||
|
if (p_name.isEmpty()) {
|
||||||
|
for (int i = 0; i < entryListWidget->topLevelItemCount(); ++i) {
|
||||||
|
entryListWidget->topLevelItem(i)->setHidden(false);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto items = entryListWidget->findItems(p_name, Qt::MatchStartsWith);
|
||||||
|
for (int i = 0; i < entryListWidget->topLevelItemCount(); ++i) {
|
||||||
|
entryListWidget->topLevelItem(i)->setHidden(true);
|
||||||
|
}
|
||||||
|
for (const auto &item : items) {
|
||||||
|
item->setHidden(false);
|
||||||
|
}
|
||||||
|
return !items.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnitedEntry::handleEntryFinished(IUnitedEntry *p_entry)
|
||||||
|
{
|
||||||
|
if (p_entry != m_lastEntry.data()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setBusy(false);
|
||||||
|
|
||||||
|
if (m_hasPending) {
|
||||||
|
m_processTimer->start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnitedEntry::setBusy(bool p_busy)
|
||||||
|
{
|
||||||
|
m_iconAction->setEnabled(!p_busy);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UnitedEntry::eventFilter(QObject *p_watched, QEvent *p_event)
|
||||||
|
{
|
||||||
|
if (p_watched == m_popup) {
|
||||||
|
if (p_event->type() == QEvent::KeyPress) {
|
||||||
|
auto eve = static_cast<QKeyEvent *>(p_event);
|
||||||
|
switch (eve->key()) {
|
||||||
|
case Qt::Key_BracketLeft:
|
||||||
|
if (!WidgetUtils::isViControlModifier(eve->modifiers())) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Q_FALLTHROUGH();
|
||||||
|
case Qt::Key_Escape:
|
||||||
|
exitUnitedEntry();
|
||||||
|
// Need to call deactivateUnitedEntry() again since focusChanged is not triggered.
|
||||||
|
deactivateUnitedEntry();
|
||||||
|
return true;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return QWidget::eventFilter(p_watched, p_event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnitedEntry::exitUnitedEntry()
|
||||||
|
{
|
||||||
|
if (m_previousFocusWidget) {
|
||||||
|
// Deactivate and focus previous widget.
|
||||||
|
m_previousFocusWidget->setFocus();
|
||||||
|
} else {
|
||||||
|
VNoteX::getInst().getMainWindow()->setFocus();
|
||||||
|
}
|
||||||
|
}
|
85
src/unitedentry/unitedentry.h
Normal file
85
src/unitedentry/unitedentry.h
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
#ifndef UNITEDENTRY_H
|
||||||
|
#define UNITEDENTRY_H
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
#include <QSharedPointer>
|
||||||
|
|
||||||
|
class QAction;
|
||||||
|
class QTimer;
|
||||||
|
class QTreeWidget;
|
||||||
|
class QLabel;
|
||||||
|
|
||||||
|
namespace vnotex
|
||||||
|
{
|
||||||
|
class LineEditWithSnippet;
|
||||||
|
class EntryPopup;
|
||||||
|
class IUnitedEntry;
|
||||||
|
|
||||||
|
class UnitedEntry : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit UnitedEntry(QWidget *p_parent = nullptr);
|
||||||
|
|
||||||
|
~UnitedEntry();
|
||||||
|
|
||||||
|
bool eventFilter(QObject *p_watched, QEvent *p_event) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void keyPressEvent(QKeyEvent *p_event) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
void resizeEvent(QResizeEvent *p_event) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void setupUI();
|
||||||
|
|
||||||
|
void setupIcons();
|
||||||
|
|
||||||
|
void activateUnitedEntry();
|
||||||
|
|
||||||
|
void deactivateUnitedEntry();
|
||||||
|
|
||||||
|
void handleFocusChanged(QWidget *p_old, QWidget *p_now);
|
||||||
|
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
void processInput();
|
||||||
|
|
||||||
|
const QSharedPointer<QTreeWidget> &getEntryListWidget();
|
||||||
|
|
||||||
|
QSharedPointer<QLabel> getInfoWidget(const QString &p_info);
|
||||||
|
|
||||||
|
void updatePopupGeometry();
|
||||||
|
|
||||||
|
void popupWidget(const QSharedPointer<QWidget> &p_widget);
|
||||||
|
|
||||||
|
// Return true if there is any entry visible.
|
||||||
|
bool filterEntryListWidgetEntries(const QString &p_name);
|
||||||
|
|
||||||
|
void handleEntryFinished(IUnitedEntry *p_entry);
|
||||||
|
|
||||||
|
void setBusy(bool p_busy);
|
||||||
|
|
||||||
|
void exitUnitedEntry();
|
||||||
|
|
||||||
|
LineEditWithSnippet *m_lineEdit = nullptr;
|
||||||
|
|
||||||
|
EntryPopup *m_popup = nullptr;
|
||||||
|
|
||||||
|
QAction *m_iconAction = nullptr;
|
||||||
|
|
||||||
|
bool m_activated = false;
|
||||||
|
|
||||||
|
QWidget *m_previousFocusWidget = nullptr;
|
||||||
|
|
||||||
|
QTimer *m_processTimer = nullptr;
|
||||||
|
|
||||||
|
QSharedPointer<QTreeWidget> m_entryListWidget = nullptr;
|
||||||
|
|
||||||
|
QSharedPointer<IUnitedEntry> m_lastEntry;
|
||||||
|
|
||||||
|
bool m_hasPending = false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // UNITEDENTRY_H
|
24
src/unitedentry/unitedentry.pri
Normal file
24
src/unitedentry/unitedentry.pri
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
QT += widgets
|
||||||
|
|
||||||
|
HEADERS += \
|
||||||
|
$$PWD/entrypopup.h \
|
||||||
|
$$PWD/entrywidgetfactory.h \
|
||||||
|
$$PWD/findunitedentry.h \
|
||||||
|
$$PWD/helpunitedentry.h \
|
||||||
|
$$PWD/iunitedentry.h \
|
||||||
|
$$PWD/unitedentry.h \
|
||||||
|
$$PWD/unitedentryalias.h \
|
||||||
|
$$PWD/unitedentryhelper.h \
|
||||||
|
$$PWD/unitedentrymgr.h
|
||||||
|
|
||||||
|
SOURCES += \
|
||||||
|
$$PWD/entrypopup.cpp \
|
||||||
|
$$PWD/entrywidgetfactory.cpp \
|
||||||
|
$$PWD/findunitedentry.cpp \
|
||||||
|
$$PWD/helpunitedentry.cpp \
|
||||||
|
$$PWD/iunitedentry.cpp \
|
||||||
|
$$PWD/unitedentry.cpp \
|
||||||
|
$$PWD/unitedentryalias.cpp \
|
||||||
|
$$PWD/unitedentryhelper.cpp \
|
||||||
|
$$PWD/unitedentrymgr.cpp
|
||||||
|
|
99
src/unitedentry/unitedentryalias.cpp
Normal file
99
src/unitedentry/unitedentryalias.cpp
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
#include "unitedentryalias.h"
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QLabel>
|
||||||
|
|
||||||
|
#include "unitedentrymgr.h"
|
||||||
|
#include "entrywidgetfactory.h"
|
||||||
|
|
||||||
|
using namespace vnotex;
|
||||||
|
|
||||||
|
UnitedEntryAlias::UnitedEntryAlias(const QString &p_name,
|
||||||
|
const QString &p_description,
|
||||||
|
const QString &p_value,
|
||||||
|
const UnitedEntryMgr *p_mgr,
|
||||||
|
QObject *p_parent)
|
||||||
|
: IUnitedEntry(p_name, p_description, p_mgr, p_parent),
|
||||||
|
m_value(p_value)
|
||||||
|
{
|
||||||
|
m_alias = UnitedEntryHelper::parseUserEntry(m_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
UnitedEntryAlias::UnitedEntryAlias(const QJsonObject &p_obj,
|
||||||
|
const UnitedEntryMgr *p_mgr,
|
||||||
|
QObject *p_parent)
|
||||||
|
: UnitedEntryAlias(p_obj[QStringLiteral("name")].toString(),
|
||||||
|
p_obj[QStringLiteral("description")].toString(),
|
||||||
|
p_obj[QStringLiteral("value")].toString(),
|
||||||
|
p_mgr,
|
||||||
|
p_parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QString UnitedEntryAlias::description() const
|
||||||
|
{
|
||||||
|
return tr("[Alias] ") + IUnitedEntry::description();
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonObject UnitedEntryAlias::toJson() const
|
||||||
|
{
|
||||||
|
QJsonObject obj;
|
||||||
|
obj[QStringLiteral("name")] = name();
|
||||||
|
obj[QStringLiteral("description")] = description();
|
||||||
|
obj[QStringLiteral("value")] = m_value;
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnitedEntryAlias::initOnFirstProcess()
|
||||||
|
{
|
||||||
|
m_realEntry = m_mgr->findEntry(m_alias.m_name).data();
|
||||||
|
if (!m_realEntry) {
|
||||||
|
qWarning() << "invalid UnitedEntry alias" << name() << m_value;
|
||||||
|
} else {
|
||||||
|
connect(m_realEntry, &IUnitedEntry::finished,
|
||||||
|
this, &IUnitedEntry::finished);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnitedEntryAlias::processInternal(const QString &p_args,
|
||||||
|
const std::function<void(const QSharedPointer<QWidget> &)> &p_popupWidgetFunc)
|
||||||
|
{
|
||||||
|
if (!m_realEntry) {
|
||||||
|
auto label = EntryWidgetFactory::createLabel(tr("Invalid UnitedEntry alias: %1").arg(m_value));
|
||||||
|
p_popupWidgetFunc(label);
|
||||||
|
emit finished();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_realEntry->process(m_alias.m_args + " " + p_args, p_popupWidgetFunc);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UnitedEntryAlias::isOngoing() const
|
||||||
|
{
|
||||||
|
if (m_realEntry) {
|
||||||
|
return m_realEntry->isOngoing();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnitedEntryAlias::setOngoing(bool p_ongoing)
|
||||||
|
{
|
||||||
|
Q_UNUSED(p_ongoing);
|
||||||
|
Q_ASSERT(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnitedEntryAlias::handleAction(Action p_act)
|
||||||
|
{
|
||||||
|
if (m_realEntry) {
|
||||||
|
m_realEntry->handleAction(p_act);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QSharedPointer<QWidget> UnitedEntryAlias::currentPopupWidget() const
|
||||||
|
{
|
||||||
|
if (m_realEntry) {
|
||||||
|
return m_realEntry->currentPopupWidget();
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
56
src/unitedentry/unitedentryalias.h
Normal file
56
src/unitedentry/unitedentryalias.h
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
#ifndef UNITEDENTRYALIAS_H
|
||||||
|
#define UNITEDENTRYALIAS_H
|
||||||
|
|
||||||
|
#include "iunitedentry.h"
|
||||||
|
|
||||||
|
#include <QJsonObject>
|
||||||
|
|
||||||
|
#include "unitedentryhelper.h"
|
||||||
|
|
||||||
|
namespace vnotex
|
||||||
|
{
|
||||||
|
class UnitedEntryMgr;
|
||||||
|
|
||||||
|
// UnitedEntry which points to another UnitedEntry.
|
||||||
|
class UnitedEntryAlias : public IUnitedEntry
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
UnitedEntryAlias(const QString &p_name,
|
||||||
|
const QString &p_description,
|
||||||
|
const QString &p_value,
|
||||||
|
const UnitedEntryMgr *p_mgr,
|
||||||
|
QObject *p_parent = nullptr);
|
||||||
|
|
||||||
|
UnitedEntryAlias(const QJsonObject &p_obj,
|
||||||
|
const UnitedEntryMgr *p_mgr,
|
||||||
|
QObject *p_parent = nullptr);
|
||||||
|
|
||||||
|
QJsonObject toJson() const;
|
||||||
|
|
||||||
|
QString description() const Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
bool isOngoing() const Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
void handleAction(Action p_act) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
QSharedPointer<QWidget> currentPopupWidget() const Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void initOnFirstProcess() Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
void processInternal(const QString &p_args,
|
||||||
|
const std::function<void(const QSharedPointer<QWidget> &)> &p_popupWidgetFunc) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
void setOngoing(bool p_ongoing) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString m_value;
|
||||||
|
|
||||||
|
UnitedEntryHelper::UserEntry m_alias;
|
||||||
|
|
||||||
|
IUnitedEntry *m_realEntry = nullptr;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // UNITEDENTRYALIAS_H
|
70
src/unitedentry/unitedentryhelper.cpp
Normal file
70
src/unitedentry/unitedentryhelper.cpp
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
#include "unitedentryhelper.h"
|
||||||
|
|
||||||
|
#include <QIcon>
|
||||||
|
|
||||||
|
#include <core/vnotex.h>
|
||||||
|
#include <core/thememgr.h>
|
||||||
|
#include <utils/iconutils.h>
|
||||||
|
|
||||||
|
using namespace vnotex;
|
||||||
|
|
||||||
|
UnitedEntryHelper::UserEntry UnitedEntryHelper::parseUserEntry(const QString &p_text)
|
||||||
|
{
|
||||||
|
UserEntry entry;
|
||||||
|
|
||||||
|
const auto text = p_text.trimmed();
|
||||||
|
|
||||||
|
if (text.isEmpty()) {
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
int idx = text.indexOf(QLatin1Char(' '));
|
||||||
|
if (idx == -1) {
|
||||||
|
entry.m_name = text.toLower();
|
||||||
|
} else {
|
||||||
|
entry.m_name = text.left(idx).toLower();
|
||||||
|
entry.m_args = text.mid(idx).trimmed();
|
||||||
|
}
|
||||||
|
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QIcon &UnitedEntryHelper::itemIcon(ItemType p_type)
|
||||||
|
{
|
||||||
|
static QIcon icons[ItemType::MaxItemType];
|
||||||
|
|
||||||
|
if (icons[0].isNull()) {
|
||||||
|
// Init.
|
||||||
|
const QString nodeIconFgName = "base#icon#fg";
|
||||||
|
const auto &themeMgr = VNoteX::getInst().getThemeMgr();
|
||||||
|
const auto fg = themeMgr.paletteColor(nodeIconFgName);
|
||||||
|
|
||||||
|
icons[ItemType::Buffer] = IconUtils::fetchIcon(themeMgr.getIconFile("buffer.svg"), fg);
|
||||||
|
icons[ItemType::File] = IconUtils::fetchIcon(themeMgr.getIconFile("file_node.svg"), fg);
|
||||||
|
icons[ItemType::Folder] = IconUtils::fetchIcon(themeMgr.getIconFile("folder_node.svg"), fg);
|
||||||
|
icons[ItemType::Notebook] = IconUtils::fetchIcon(themeMgr.getIconFile("notebook_default.svg"), fg);
|
||||||
|
icons[ItemType::Other] = IconUtils::fetchIcon(themeMgr.getIconFile("other_item.svg"), fg);
|
||||||
|
}
|
||||||
|
|
||||||
|
return icons[p_type];
|
||||||
|
}
|
||||||
|
|
||||||
|
UnitedEntryHelper::ItemType UnitedEntryHelper::locationTypeToItemType(LocationType p_type)
|
||||||
|
{
|
||||||
|
switch (p_type) {
|
||||||
|
case LocationType::Buffer:
|
||||||
|
return ItemType::Buffer;
|
||||||
|
|
||||||
|
case LocationType::File:
|
||||||
|
return ItemType::File;
|
||||||
|
|
||||||
|
case LocationType::Folder:
|
||||||
|
return ItemType::Folder;
|
||||||
|
|
||||||
|
case LocationType::Notebook:
|
||||||
|
return ItemType::Notebook;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return ItemType::Other;
|
||||||
|
}
|
||||||
|
}
|
43
src/unitedentry/unitedentryhelper.h
Normal file
43
src/unitedentry/unitedentryhelper.h
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
#ifndef UNITEDENTRYHELPER_H
|
||||||
|
#define UNITEDENTRYHELPER_H
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
#include <core/location.h>
|
||||||
|
|
||||||
|
class QIcon;
|
||||||
|
|
||||||
|
namespace vnotex
|
||||||
|
{
|
||||||
|
class UnitedEntryHelper
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
struct UserEntry
|
||||||
|
{
|
||||||
|
QString m_name;
|
||||||
|
|
||||||
|
QString m_args;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ItemType
|
||||||
|
{
|
||||||
|
Buffer,
|
||||||
|
File,
|
||||||
|
Folder,
|
||||||
|
Notebook,
|
||||||
|
Other,
|
||||||
|
MaxItemType
|
||||||
|
};
|
||||||
|
|
||||||
|
UnitedEntryHelper() = delete;
|
||||||
|
|
||||||
|
static UserEntry parseUserEntry(const QString &p_text);
|
||||||
|
|
||||||
|
static const QIcon &itemIcon(ItemType p_type);
|
||||||
|
|
||||||
|
static ItemType locationTypeToItemType(LocationType p_type);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // UNITEDENTRYHELPER_H
|
80
src/unitedentry/unitedentrymgr.cpp
Normal file
80
src/unitedentry/unitedentrymgr.cpp
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
#include "unitedentrymgr.h"
|
||||||
|
|
||||||
|
#include "findunitedentry.h"
|
||||||
|
#include "helpunitedentry.h"
|
||||||
|
#include "unitedentryalias.h"
|
||||||
|
|
||||||
|
#include <core/configmgr.h>
|
||||||
|
#include <core/coreconfig.h>
|
||||||
|
#include <core/vnotex.h>
|
||||||
|
#include <widgets/searchinfoprovider.h>
|
||||||
|
|
||||||
|
using namespace vnotex;
|
||||||
|
|
||||||
|
UnitedEntryMgr::UnitedEntryMgr(QObject *p_parent)
|
||||||
|
: QObject(p_parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnitedEntryMgr::init()
|
||||||
|
{
|
||||||
|
if (m_initialized) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_initialized = true;
|
||||||
|
|
||||||
|
// Built-in entries.
|
||||||
|
const auto mainWindow = VNoteX::getInst().getMainWindow();
|
||||||
|
addEntry(QSharedPointer<FindUnitedEntry>::create(SearchInfoProvider::create(mainWindow), this));
|
||||||
|
|
||||||
|
addEntry(QSharedPointer<HelpUnitedEntry>::create(this));
|
||||||
|
|
||||||
|
// Alias from config.
|
||||||
|
const auto &config = ConfigMgr::getInst().getCoreConfig();
|
||||||
|
const auto &aliasArr = config.getUnitedEntryAlias();
|
||||||
|
for (int i = 0; i < aliasArr.size(); ++i) {
|
||||||
|
auto entry = QSharedPointer<UnitedEntryAlias>::create(aliasArr[i].toObject(), this);
|
||||||
|
addEntry(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnitedEntryMgr::addEntry(const QSharedPointer<IUnitedEntry> &p_entry)
|
||||||
|
{
|
||||||
|
Q_ASSERT(!m_entries.contains(p_entry->name()));
|
||||||
|
m_entries.insert(p_entry->name(), p_entry);
|
||||||
|
connect(p_entry.data(), &IUnitedEntry::finished,
|
||||||
|
this, [this]() {
|
||||||
|
emit entryFinished(reinterpret_cast<IUnitedEntry *>(sender()));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<QSharedPointer<IUnitedEntry>> UnitedEntryMgr::getEntries() const
|
||||||
|
{
|
||||||
|
return m_entries.values();
|
||||||
|
}
|
||||||
|
|
||||||
|
QSharedPointer<IUnitedEntry> UnitedEntryMgr::findEntry(const QString &p_name) const
|
||||||
|
{
|
||||||
|
auto it = m_entries.find(p_name);
|
||||||
|
if (it == m_entries.end()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return it.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UnitedEntryMgr::isInitialized() const
|
||||||
|
{
|
||||||
|
return m_initialized;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UnitedEntryMgr::getExpandAllEnabled() const
|
||||||
|
{
|
||||||
|
return m_expandAllEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnitedEntryMgr::setExpandAllEnabled(bool p_enabled)
|
||||||
|
{
|
||||||
|
m_expandAllEnabled = p_enabled;
|
||||||
|
}
|
52
src/unitedentry/unitedentrymgr.h
Normal file
52
src/unitedentry/unitedentrymgr.h
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
#ifndef UNITEDENTRYMGR_H
|
||||||
|
#define UNITEDENTRYMGR_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QSharedPointer>
|
||||||
|
#include <QMap>
|
||||||
|
|
||||||
|
#include <core/noncopyable.h>
|
||||||
|
|
||||||
|
namespace vnotex
|
||||||
|
{
|
||||||
|
class IUnitedEntry;
|
||||||
|
|
||||||
|
class UnitedEntryMgr : public QObject, private Noncopyable
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
static UnitedEntryMgr &getInst()
|
||||||
|
{
|
||||||
|
static UnitedEntryMgr inst;
|
||||||
|
inst.init();
|
||||||
|
return inst;
|
||||||
|
}
|
||||||
|
|
||||||
|
void init();
|
||||||
|
|
||||||
|
QList<QSharedPointer<IUnitedEntry>> getEntries() const;
|
||||||
|
|
||||||
|
QSharedPointer<IUnitedEntry> findEntry(const QString &p_name) const;
|
||||||
|
|
||||||
|
bool isInitialized() const;
|
||||||
|
|
||||||
|
bool getExpandAllEnabled() const;
|
||||||
|
void setExpandAllEnabled(bool p_enabled);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void entryFinished(IUnitedEntry *p_entry);
|
||||||
|
|
||||||
|
private:
|
||||||
|
explicit UnitedEntryMgr(QObject *p_parent = nullptr);
|
||||||
|
|
||||||
|
void addEntry(const QSharedPointer<IUnitedEntry> &p_entry);
|
||||||
|
|
||||||
|
bool m_initialized = false;
|
||||||
|
|
||||||
|
QMap<QString, QSharedPointer<IUnitedEntry>> m_entries;
|
||||||
|
|
||||||
|
bool m_expandAllEnabled = false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // UNITEDENTRYMGR_H
|
@ -2,6 +2,7 @@
|
|||||||
#define ASYNCWORKER_H
|
#define ASYNCWORKER_H
|
||||||
|
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
|
|
||||||
#include <QAtomicInt>
|
#include <QAtomicInt>
|
||||||
|
|
||||||
namespace vnotex
|
namespace vnotex
|
||||||
|
@ -468,3 +468,23 @@ void WidgetUtils::clearLayout(QFormLayout *p_layout)
|
|||||||
p_layout->removeRow(i);
|
p_layout->removeRow(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Different from QWidget::isAncestorOf(): unnecessary to be within the same window.
|
||||||
|
bool WidgetUtils::isOrAncestorOf(const QWidget *p_widget, const QWidget *p_child)
|
||||||
|
{
|
||||||
|
Q_ASSERT(p_widget);
|
||||||
|
|
||||||
|
if (!p_child) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QWidget *pa = p_child;
|
||||||
|
while (pa) {
|
||||||
|
if (pa == p_widget) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
pa = pa->parentWidget();
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
@ -93,6 +93,8 @@ namespace vnotex
|
|||||||
|
|
||||||
static void clearLayout(QFormLayout *p_layout);
|
static void clearLayout(QFormLayout *p_layout);
|
||||||
|
|
||||||
|
static bool isOrAncestorOf(const QWidget *p_widget, const QWidget *p_child);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void resizeToHideScrollBar(QScrollArea *p_scroll, bool p_vertical, bool p_horizontal);
|
static void resizeToHideScrollBar(QScrollArea *p_scroll, bool p_vertical, bool p_horizontal);
|
||||||
};
|
};
|
||||||
|
@ -135,3 +135,8 @@ void LineEdit::updateInputMethod() const
|
|||||||
// Ask input method to query current state, which will call inputMethodQuery().
|
// Ask input method to query current state, which will call inputMethodQuery().
|
||||||
im->update(Qt::ImEnabled);
|
im->update(Qt::ImEnabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QRect LineEdit::cursorRect() const
|
||||||
|
{
|
||||||
|
return QLineEdit::cursorRect();
|
||||||
|
}
|
||||||
|
@ -18,6 +18,8 @@ namespace vnotex
|
|||||||
|
|
||||||
void setInputMethodEnabled(bool p_enabled);
|
void setInputMethodEnabled(bool p_enabled);
|
||||||
|
|
||||||
|
QRect cursorRect() const;
|
||||||
|
|
||||||
static void selectBaseName(QLineEdit *p_lineEdit);
|
static void selectBaseName(QLineEdit *p_lineEdit);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -140,6 +140,7 @@ void LocationList::addLocation(const ComplexLocation &p_location)
|
|||||||
item->setText(Columns::PathColumn, p_location.m_displayPath);
|
item->setText(Columns::PathColumn, p_location.m_displayPath);
|
||||||
item->setIcon(Columns::PathColumn, getItemIcon(p_location.m_type));
|
item->setIcon(Columns::PathColumn, getItemIcon(p_location.m_type));
|
||||||
item->setData(Columns::PathColumn, Qt::UserRole, p_location.m_path);
|
item->setData(Columns::PathColumn, Qt::UserRole, p_location.m_path);
|
||||||
|
item->setToolTip(Columns::PathColumn, p_location.m_path);
|
||||||
|
|
||||||
if (p_location.m_lines.size() == 1) {
|
if (p_location.m_lines.size() == 1) {
|
||||||
setItemLocationLineAndText(item, p_location.m_lines[0]);
|
setItemLocationLineAndText(item, p_location.m_lines[0]);
|
||||||
|
@ -551,6 +551,12 @@ void MainWindow::focusViewArea()
|
|||||||
m_viewArea->focus();
|
m_viewArea->focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NotebookExplorer *MainWindow::getNotebookExplorer() const
|
||||||
|
{
|
||||||
|
Q_ASSERT(m_notebookExplorer);
|
||||||
|
return m_notebookExplorer;
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::setupToolBar()
|
void MainWindow::setupToolBar()
|
||||||
{
|
{
|
||||||
const int sz = ConfigMgr::getInst().getCoreConfig().getToolBarIconSize();
|
const int sz = ConfigMgr::getInst().getCoreConfig().getToolBarIconSize();
|
||||||
|
@ -53,6 +53,8 @@ namespace vnotex
|
|||||||
|
|
||||||
ViewArea *getViewArea() const;
|
ViewArea *getViewArea() const;
|
||||||
|
|
||||||
|
NotebookExplorer *getNotebookExplorer() const;
|
||||||
|
|
||||||
void setContentAreaExpanded(bool p_expanded);
|
void setContentAreaExpanded(bool p_expanded);
|
||||||
// Should be called after MainWindow is shown.
|
// Should be called after MainWindow is shown.
|
||||||
bool isContentAreaExpanded() const;
|
bool isContentAreaExpanded() const;
|
||||||
|
@ -1,17 +1,19 @@
|
|||||||
#include "searchinfoprovider.h"
|
#include "searchinfoprovider.h"
|
||||||
|
|
||||||
|
#include <core/vnotex.h>
|
||||||
#include "viewarea.h"
|
#include "viewarea.h"
|
||||||
#include "notebookexplorer.h"
|
#include "notebookexplorer.h"
|
||||||
#include "notebookmgr.h"
|
#include "notebookmgr.h"
|
||||||
|
#include "mainwindow.h"
|
||||||
|
|
||||||
using namespace vnotex;
|
using namespace vnotex;
|
||||||
|
|
||||||
SearchInfoProvider::SearchInfoProvider(const ViewArea *p_viewArea,
|
SearchInfoProvider::SearchInfoProvider(const ViewArea *p_viewArea,
|
||||||
const NotebookExplorer *p_notebookExplorer,
|
const NotebookExplorer *p_notebookExplorer,
|
||||||
const NotebookMgr *p_notebookMgr)
|
const NotebookMgr *p_notebookMgr)
|
||||||
: m_viewArea(p_viewArea),
|
: m_viewArea(p_viewArea),
|
||||||
m_notebookExplorer(p_notebookExplorer),
|
m_notebookExplorer(p_notebookExplorer),
|
||||||
m_notebookMgr(p_notebookMgr)
|
m_notebookMgr(p_notebookMgr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,3 +43,10 @@ QVector<Notebook *> SearchInfoProvider::getNotebooks() const
|
|||||||
|
|
||||||
return nbs;
|
return nbs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QSharedPointer<SearchInfoProvider> SearchInfoProvider::create(const MainWindow *p_mainWindow)
|
||||||
|
{
|
||||||
|
return QSharedPointer<SearchInfoProvider>::create(p_mainWindow->getViewArea(),
|
||||||
|
p_mainWindow->getNotebookExplorer(),
|
||||||
|
&VNoteX::getInst().getNotebookMgr());
|
||||||
|
}
|
||||||
|
@ -1,13 +1,16 @@
|
|||||||
#ifndef SEARCHINFOPROVIDER_H
|
#ifndef SEARCHINFOPROVIDER_H
|
||||||
#define SEARCHINFOPROVIDER_H
|
#define SEARCHINFOPROVIDER_H
|
||||||
|
|
||||||
#include "searchpanel.h"
|
#include <search/isearchinfoprovider.h>
|
||||||
|
|
||||||
|
#include <QSharedPointer>
|
||||||
|
|
||||||
namespace vnotex
|
namespace vnotex
|
||||||
{
|
{
|
||||||
class ViewArea;
|
class ViewArea;
|
||||||
class NotebookExplorer;
|
class NotebookExplorer;
|
||||||
class NotebookMgr;
|
class NotebookMgr;
|
||||||
|
class MainWindow;
|
||||||
|
|
||||||
class SearchInfoProvider : public ISearchInfoProvider
|
class SearchInfoProvider : public ISearchInfoProvider
|
||||||
{
|
{
|
||||||
@ -24,6 +27,8 @@ namespace vnotex
|
|||||||
|
|
||||||
QVector<Notebook *> getNotebooks() const Q_DECL_OVERRIDE;
|
QVector<Notebook *> getNotebooks() const Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
static QSharedPointer<SearchInfoProvider> create(const MainWindow *p_mainWindow);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const ViewArea *m_viewArea = nullptr;
|
const ViewArea *m_viewArea = nullptr;
|
||||||
|
|
||||||
|
@ -29,6 +29,8 @@
|
|||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
#include <search/searchtoken.h>
|
#include <search/searchtoken.h>
|
||||||
#include <search/searchresultitem.h>
|
#include <search/searchresultitem.h>
|
||||||
|
#include <search/isearchinfoprovider.h>
|
||||||
|
#include <search/searchhelper.h>
|
||||||
#include <utils/widgetutils.h>
|
#include <utils/widgetutils.h>
|
||||||
#include "locationlist.h"
|
#include "locationlist.h"
|
||||||
|
|
||||||
@ -305,7 +307,11 @@ void SearchPanel::startSearch()
|
|||||||
|
|
||||||
saveFields(*m_option);
|
saveFields(*m_option);
|
||||||
|
|
||||||
auto state = search(m_option);
|
QString msg;
|
||||||
|
auto state = SearchHelper::searchOnProvider(getSearcher(), m_option, m_provider, msg);
|
||||||
|
if (!msg.isEmpty()) {
|
||||||
|
appendLog(msg);
|
||||||
|
}
|
||||||
|
|
||||||
// On end.
|
// On end.
|
||||||
handleSearchFinished(state);
|
handleSearchFinished(state);
|
||||||
@ -313,8 +319,6 @@ void SearchPanel::startSearch()
|
|||||||
|
|
||||||
void SearchPanel::handleSearchFinished(SearchState p_state)
|
void SearchPanel::handleSearchFinished(SearchState p_state)
|
||||||
{
|
{
|
||||||
qDebug() << "handleSearchFinished" << (int)p_state;
|
|
||||||
|
|
||||||
Q_ASSERT(m_searchOngoing);
|
Q_ASSERT(m_searchOngoing);
|
||||||
Q_ASSERT(p_state != SearchState::Idle);
|
Q_ASSERT(p_state != SearchState::Idle);
|
||||||
|
|
||||||
@ -420,94 +424,6 @@ void SearchPanel::saveFields(SearchOption &p_option)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SearchState SearchPanel::search(const QSharedPointer<SearchOption> &p_option)
|
|
||||||
{
|
|
||||||
if (!isSearchOptionValid(*p_option)) {
|
|
||||||
return SearchState::Failed;
|
|
||||||
}
|
|
||||||
|
|
||||||
SearchState state = SearchState::Finished;
|
|
||||||
|
|
||||||
switch (p_option->m_scope) {
|
|
||||||
case SearchScope::Buffers:
|
|
||||||
{
|
|
||||||
auto buffers = m_provider->getBuffers();
|
|
||||||
if (buffers.isEmpty()) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
state = getSearcher()->search(p_option, buffers);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case SearchScope::CurrentFolder:
|
|
||||||
{
|
|
||||||
auto notebook = m_provider->getCurrentNotebook();
|
|
||||||
if (!notebook) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
auto folder = m_provider->getCurrentFolder();
|
|
||||||
if (!folder) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
state = getSearcher()->search(p_option, folder);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case SearchScope::CurrentNotebook:
|
|
||||||
{
|
|
||||||
auto notebook = m_provider->getCurrentNotebook();
|
|
||||||
if (!notebook) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
QVector<Notebook *> notebooks;
|
|
||||||
notebooks.push_back(notebook);
|
|
||||||
state = getSearcher()->search(p_option, notebooks);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case SearchScope::AllNotebooks:
|
|
||||||
{
|
|
||||||
auto notebooks = m_provider->getNotebooks();
|
|
||||||
if (notebooks.isEmpty()) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
state = getSearcher()->search(p_option, notebooks);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SearchPanel::isSearchOptionValid(const SearchOption &p_option)
|
|
||||||
{
|
|
||||||
if (p_option.m_keyword.isEmpty()) {
|
|
||||||
appendLog(tr("Invalid keyword"));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p_option.m_objects == SearchObject::ObjectNone) {
|
|
||||||
appendLog(tr("No object specified"));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p_option.m_targets == SearchTarget::TargetNone) {
|
|
||||||
appendLog(tr("No target specified"));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p_option.m_findOptions & FindOption::FuzzySearch
|
|
||||||
&& p_option.m_objects & SearchObject::SearchContent) {
|
|
||||||
appendLog(tr("Fuzzy search is not allowed when searching content"));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
Searcher *SearchPanel::getSearcher()
|
Searcher *SearchPanel::getSearcher()
|
||||||
{
|
{
|
||||||
if (!m_searcher) {
|
if (!m_searcher) {
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
#include <QFrame>
|
#include <QFrame>
|
||||||
#include <QSharedPointer>
|
#include <QSharedPointer>
|
||||||
#include <QList>
|
|
||||||
|
|
||||||
#include <search/searchdata.h>
|
#include <search/searchdata.h>
|
||||||
#include <search/searcher.h>
|
#include <search/searcher.h>
|
||||||
@ -21,28 +20,10 @@ class QVBoxLayout;
|
|||||||
namespace vnotex
|
namespace vnotex
|
||||||
{
|
{
|
||||||
class TitleBar;
|
class TitleBar;
|
||||||
class Buffer;
|
|
||||||
class Node;
|
|
||||||
class Notebook;
|
|
||||||
class LocationList;
|
class LocationList;
|
||||||
struct Location;
|
struct Location;
|
||||||
class SearchToken;
|
class SearchToken;
|
||||||
|
class ISearchInfoProvider;
|
||||||
class ISearchInfoProvider
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ISearchInfoProvider() = default;
|
|
||||||
|
|
||||||
virtual ~ISearchInfoProvider() = default;
|
|
||||||
|
|
||||||
virtual QList<Buffer *> getBuffers() const = 0;
|
|
||||||
|
|
||||||
virtual Node *getCurrentFolder() const = 0;
|
|
||||||
|
|
||||||
virtual Notebook *getCurrentNotebook() const = 0;
|
|
||||||
|
|
||||||
virtual QVector<Notebook *> getNotebooks() const = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class SearchPanel : public QFrame
|
class SearchPanel : public QFrame
|
||||||
{
|
{
|
||||||
@ -85,10 +66,6 @@ namespace vnotex
|
|||||||
|
|
||||||
void clearLog();
|
void clearLog();
|
||||||
|
|
||||||
SearchState search(const QSharedPointer<SearchOption> &p_option);
|
|
||||||
|
|
||||||
bool isSearchOptionValid(const SearchOption &p_option);
|
|
||||||
|
|
||||||
Searcher *getSearcher();
|
Searcher *getSearcher();
|
||||||
|
|
||||||
void prepareLocationList();
|
void prepareLocationList();
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#include <core/htmltemplatehelper.h>
|
#include <core/htmltemplatehelper.h>
|
||||||
#include <core/exception.h>
|
#include <core/exception.h>
|
||||||
#include <task/taskmgr.h>
|
#include <task/taskmgr.h>
|
||||||
|
#include <unitedentry/unitedentry.h>
|
||||||
#include "propertydefs.h"
|
#include "propertydefs.h"
|
||||||
#include "dialogs/settings/settingsdialog.h"
|
#include "dialogs/settings/settingsdialog.h"
|
||||||
#include "dialogs/updater.h"
|
#include "dialogs/updater.h"
|
||||||
@ -279,6 +280,35 @@ QToolBar *ToolBarHelper::setupQuickAccessToolBar(MainWindow *p_win, QToolBar *p_
|
|||||||
tb->addWidget(toolBtn);
|
tb->addWidget(toolBtn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Task.
|
||||||
|
{
|
||||||
|
auto act = tb->addAction(generateIcon("task_menu.svg"), MainWindow::tr("Task"));
|
||||||
|
auto btn = dynamic_cast<QToolButton *>(tb->widgetForAction(act));
|
||||||
|
btn->setPopupMode(QToolButton::InstantPopup);
|
||||||
|
btn->setProperty(PropertyDefs::c_toolButtonWithoutMenuIndicator, true);
|
||||||
|
|
||||||
|
auto taskMenu = WidgetsFactory::createMenu(tb);
|
||||||
|
setupTaskActionMenu(taskMenu);
|
||||||
|
btn->setMenu(taskMenu);
|
||||||
|
MainWindow::connect(taskMenu, &QMenu::triggered,
|
||||||
|
taskMenu, [](QAction *act) {
|
||||||
|
auto task = reinterpret_cast<Task *>(act->data().toULongLong());
|
||||||
|
if (task) {
|
||||||
|
task->run();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
MainWindow::connect(&VNoteX::getInst().getTaskMgr(), &TaskMgr::tasksUpdated,
|
||||||
|
taskMenu, [taskMenu]() {
|
||||||
|
setupTaskMenu(taskMenu);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// United Entry.
|
||||||
|
{
|
||||||
|
auto ueEdit = new UnitedEntry(tb);
|
||||||
|
tb->addWidget(ueEdit);
|
||||||
|
}
|
||||||
|
|
||||||
return tb;
|
return tb;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -361,36 +391,6 @@ void ToolBarHelper::addTaskMenu(QMenu *p_menu, Task *p_task)
|
|||||||
WidgetUtils::addActionShortcut(action, p_task->getShortcut());
|
WidgetUtils::addActionShortcut(action, p_task->getShortcut());
|
||||||
}
|
}
|
||||||
|
|
||||||
QToolBar *ToolBarHelper::setupTaskToolBar(MainWindow *p_win, QToolBar *p_toolBar)
|
|
||||||
{
|
|
||||||
auto tb = p_toolBar;
|
|
||||||
if (!tb) {
|
|
||||||
tb = createToolBar(p_win, MainWindow::tr("Task"), "TaskToolBar");
|
|
||||||
}
|
|
||||||
|
|
||||||
auto act = tb->addAction(generateIcon("task_menu.svg"), MainWindow::tr("Task"));
|
|
||||||
auto btn = dynamic_cast<QToolButton *>(tb->widgetForAction(act));
|
|
||||||
btn->setPopupMode(QToolButton::InstantPopup);
|
|
||||||
btn->setProperty(PropertyDefs::c_toolButtonWithoutMenuIndicator, true);
|
|
||||||
|
|
||||||
auto taskMenu = WidgetsFactory::createMenu(tb);
|
|
||||||
setupTaskActionMenu(taskMenu);
|
|
||||||
btn->setMenu(taskMenu);
|
|
||||||
MainWindow::connect(taskMenu, &QMenu::triggered,
|
|
||||||
taskMenu, [](QAction *act) {
|
|
||||||
auto task = reinterpret_cast<Task *>(act->data().toULongLong());
|
|
||||||
if (task) {
|
|
||||||
task->run();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
MainWindow::connect(&VNoteX::getInst().getTaskMgr(), &TaskMgr::tasksUpdated,
|
|
||||||
taskMenu, [taskMenu]() {
|
|
||||||
setupTaskMenu(taskMenu);
|
|
||||||
});
|
|
||||||
|
|
||||||
return tb;
|
|
||||||
}
|
|
||||||
|
|
||||||
QToolBar *ToolBarHelper::setupSettingsToolBar(MainWindow *p_win, QToolBar *p_toolBar)
|
QToolBar *ToolBarHelper::setupSettingsToolBar(MainWindow *p_win, QToolBar *p_toolBar)
|
||||||
{
|
{
|
||||||
auto tb = p_toolBar;
|
auto tb = p_toolBar;
|
||||||
@ -453,8 +453,6 @@ void ToolBarHelper::setupToolBars(MainWindow *p_mainWindow)
|
|||||||
|
|
||||||
setupQuickAccessToolBar(p_mainWindow, nullptr);
|
setupQuickAccessToolBar(p_mainWindow, nullptr);
|
||||||
|
|
||||||
setupTaskToolBar(p_mainWindow, nullptr);
|
|
||||||
|
|
||||||
setupSettingsToolBar(p_mainWindow, nullptr);
|
setupSettingsToolBar(p_mainWindow, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -466,7 +464,6 @@ void ToolBarHelper::setupToolBars(MainWindow *p_mainWindow, QToolBar *p_toolBar)
|
|||||||
|
|
||||||
setupFileToolBar(p_mainWindow, p_toolBar);
|
setupFileToolBar(p_mainWindow, p_toolBar);
|
||||||
setupQuickAccessToolBar(p_mainWindow, p_toolBar);
|
setupQuickAccessToolBar(p_mainWindow, p_toolBar);
|
||||||
setupTaskToolBar(p_mainWindow, p_toolBar);
|
|
||||||
setupSettingsToolBar(p_mainWindow, p_toolBar);
|
setupSettingsToolBar(p_mainWindow, p_toolBar);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,8 +40,6 @@ namespace vnotex
|
|||||||
|
|
||||||
static void addTaskMenu(QMenu *p_menu, Task *p_task);
|
static void addTaskMenu(QMenu *p_menu, Task *p_task);
|
||||||
|
|
||||||
static QToolBar *setupTaskToolBar(MainWindow *p_win, QToolBar *p_toolBar);
|
|
||||||
|
|
||||||
static QToolBar *setupSettingsToolBar(MainWindow *p_win, QToolBar *p_toolBar);
|
static QToolBar *setupSettingsToolBar(MainWindow *p_win, QToolBar *p_toolBar);
|
||||||
|
|
||||||
static void updateQuickAccessMenu(QMenu *p_menu);
|
static void updateQuickAccessMenu(QMenu *p_menu);
|
||||||
|
@ -282,3 +282,46 @@ void TreeWidget::expandRecursively(QTreeWidgetItem *p_item)
|
|||||||
expandRecursively(p_item->child(i));
|
expandRecursively(p_item->child(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TreeWidget::selectParentItem(QTreeWidget *p_widget)
|
||||||
|
{
|
||||||
|
auto item = p_widget->currentItem();
|
||||||
|
if (item) {
|
||||||
|
auto pitem = item->parent();
|
||||||
|
if (pitem) {
|
||||||
|
p_widget->setCurrentItem(pitem, 0, QItemSelectionModel::ClearAndSelect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isItemTreeExpanded(const QTreeWidgetItem *p_item)
|
||||||
|
{
|
||||||
|
if (!p_item) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p_item->isHidden() || !p_item->isExpanded()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cnt = p_item->childCount();
|
||||||
|
for (int i = 0; i < cnt; ++i) {
|
||||||
|
if (!isItemTreeExpanded(p_item->child(i))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TreeWidget::isExpanded(const QTreeWidget *p_widget)
|
||||||
|
{
|
||||||
|
int cnt = p_widget->topLevelItemCount();
|
||||||
|
for (int i = 0; i < cnt; ++i) {
|
||||||
|
if (!isItemTreeExpanded(p_widget->topLevelItem(i))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
@ -44,6 +44,10 @@ namespace vnotex
|
|||||||
|
|
||||||
static void expandRecursively(QTreeWidgetItem *p_item);
|
static void expandRecursively(QTreeWidgetItem *p_item);
|
||||||
|
|
||||||
|
static void selectParentItem(QTreeWidget *p_widget);
|
||||||
|
|
||||||
|
static bool isExpanded(const QTreeWidget *p_widget);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
// Emit when single item is selected and Drag&Drop to move internally.
|
// Emit when single item is selected and Drag&Drop to move internally.
|
||||||
void itemMoved(QTreeWidgetItem *p_item);
|
void itemMoved(QTreeWidgetItem *p_item);
|
||||||
|
@ -27,3 +27,5 @@ include($$SRC_FOLDER/task/task.pri)
|
|||||||
include($$SRC_FOLDER/core/core.pri)
|
include($$SRC_FOLDER/core/core.pri)
|
||||||
|
|
||||||
include($$SRC_FOLDER/widgets/widgets.pri)
|
include($$SRC_FOLDER/widgets/widgets.pri)
|
||||||
|
|
||||||
|
include($$SRC_FOLDER/unitedentry/unitedentry.pri)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user