mirror of
https://gitee.com/vnotex/vnote.git
synced 2025-07-06 06:19:52 +08:00
Editor: highlight matches of full-text search result in page
This commit is contained in:
parent
647807a918
commit
a055d6e935
@ -62,6 +62,7 @@ VSettingsDialog::VSettingsDialog(QWidget *p_parent)
|
|||||||
addTab(new VReadEditTab(), tr("Read/Edit"));
|
addTab(new VReadEditTab(), tr("Read/Edit"));
|
||||||
addTab(new VNoteManagementTab(), tr("Note Management"));
|
addTab(new VNoteManagementTab(), tr("Note Management"));
|
||||||
addTab(new VMarkdownTab(), tr("Markdown"));
|
addTab(new VMarkdownTab(), tr("Markdown"));
|
||||||
|
addTab(new VMiscTab(), tr("Misc"));
|
||||||
|
|
||||||
m_tabList->setMaximumWidth(m_tabList->sizeHintForColumn(0) + 5);
|
m_tabList->setMaximumWidth(m_tabList->sizeHintForColumn(0) + 5);
|
||||||
|
|
||||||
@ -193,6 +194,15 @@ void VSettingsDialog::loadConfiguration()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Misc Tab.
|
||||||
|
{
|
||||||
|
VMiscTab *miscTab = dynamic_cast<VMiscTab *>(m_tabs->widget(idx++));
|
||||||
|
Q_ASSERT(miscTab);
|
||||||
|
if (!miscTab->loadConfiguration()) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
err:
|
err:
|
||||||
VUtils::showMessage(QMessageBox::Warning, tr("Warning"),
|
VUtils::showMessage(QMessageBox::Warning, tr("Warning"),
|
||||||
@ -249,6 +259,15 @@ void VSettingsDialog::saveConfiguration()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Misc Tab.
|
||||||
|
{
|
||||||
|
VMiscTab *miscTab = dynamic_cast<VMiscTab *>(m_tabs->widget(idx++));
|
||||||
|
Q_ASSERT(miscTab);
|
||||||
|
if (!miscTab->saveConfiguration()) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
accept();
|
accept();
|
||||||
return;
|
return;
|
||||||
err:
|
err:
|
||||||
@ -1354,3 +1373,45 @@ bool VMarkdownTab::saveGraphviz()
|
|||||||
g_config->setGraphvizDot(m_graphvizDotEdit->text());
|
g_config->setGraphvizDot(m_graphvizDotEdit->text());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VMiscTab::VMiscTab(QWidget *p_parent)
|
||||||
|
: QWidget(p_parent)
|
||||||
|
{
|
||||||
|
m_matchesInPageCB = new QCheckBox(tr("Highlight matches of a full-text search in page"),
|
||||||
|
this);
|
||||||
|
|
||||||
|
QFormLayout *mainLayout = new QFormLayout();
|
||||||
|
mainLayout->addRow(m_matchesInPageCB);
|
||||||
|
|
||||||
|
setLayout(mainLayout);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VMiscTab::loadConfiguration()
|
||||||
|
{
|
||||||
|
if (!loadMatchesInPage()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VMiscTab::saveConfiguration()
|
||||||
|
{
|
||||||
|
if (!saveMatchesInPage()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VMiscTab::loadMatchesInPage()
|
||||||
|
{
|
||||||
|
m_matchesInPageCB->setChecked(g_config->getHighlightMatchesInPage());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VMiscTab::saveMatchesInPage()
|
||||||
|
{
|
||||||
|
g_config->setHighlightMatchesInPage(m_matchesInPageCB->isChecked());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
@ -227,6 +227,22 @@ private:
|
|||||||
VLineEdit *m_graphvizDotEdit;
|
VLineEdit *m_graphvizDotEdit;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class VMiscTab : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit VMiscTab(QWidget *p_parent = 0);
|
||||||
|
bool loadConfiguration();
|
||||||
|
bool saveConfiguration();
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool loadMatchesInPage();
|
||||||
|
bool saveMatchesInPage();
|
||||||
|
|
||||||
|
// Highlight matches in page.
|
||||||
|
QCheckBox *m_matchesInPageCB;
|
||||||
|
};
|
||||||
|
|
||||||
class VSettingsDialog : public QDialog
|
class VSettingsDialog : public QDialog
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -262,6 +262,9 @@ multiple_keyboard_layout=true
|
|||||||
; Whether insert new note in front
|
; Whether insert new note in front
|
||||||
insert_new_note_in_front=false
|
insert_new_note_in_front=false
|
||||||
|
|
||||||
|
; Whether highlight matches in page when activating a search result item
|
||||||
|
highlight_matches_in_page=true
|
||||||
|
|
||||||
[editor]
|
[editor]
|
||||||
; Auto indent as previous line
|
; Auto indent as previous line
|
||||||
auto_indent=true
|
auto_indent=true
|
||||||
|
@ -1526,12 +1526,21 @@ const QTreeWidgetItem *VUtils::topLevelTreeItem(const QTreeWidgetItem *p_item)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (p_item->parent()) {
|
if (p_item->parent()) {
|
||||||
return p_item->parent();
|
return topLevelTreeItem(p_item->parent());
|
||||||
} else {
|
} else {
|
||||||
return p_item;
|
return p_item;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int VUtils::childIndexOfTreeItem(const QTreeWidgetItem *p_item)
|
||||||
|
{
|
||||||
|
if (p_item->parent()) {
|
||||||
|
return p_item->parent()->indexOfChild(const_cast<QTreeWidgetItem *>(p_item));
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QImage VUtils::imageFromFile(const QString &p_filePath)
|
QImage VUtils::imageFromFile(const QString &p_filePath)
|
||||||
{
|
{
|
||||||
QImage img;
|
QImage img;
|
||||||
|
@ -333,6 +333,8 @@ public:
|
|||||||
|
|
||||||
static const QTreeWidgetItem *topLevelTreeItem(const QTreeWidgetItem *p_item);
|
static const QTreeWidgetItem *topLevelTreeItem(const QTreeWidgetItem *p_item);
|
||||||
|
|
||||||
|
static int childIndexOfTreeItem(const QTreeWidgetItem *p_item);
|
||||||
|
|
||||||
// Read QImage from local file @p_filePath.
|
// Read QImage from local file @p_filePath.
|
||||||
// Directly calling QImage(p_filePath) will judge the image format from the suffix,
|
// Directly calling QImage(p_filePath) will judge the image format from the suffix,
|
||||||
// resulting a null image in wrong suffix case.
|
// resulting a null image in wrong suffix case.
|
||||||
|
@ -320,6 +320,9 @@ void VConfigManager::initialize()
|
|||||||
m_insertNewNoteInFront = getConfigFromSettings("global",
|
m_insertNewNoteInFront = getConfigFromSettings("global",
|
||||||
"insert_new_note_in_front").toBool();
|
"insert_new_note_in_front").toBool();
|
||||||
|
|
||||||
|
m_highlightMatchesInPage = getConfigFromSettings("global",
|
||||||
|
"highlight_matches_in_page").toBool();
|
||||||
|
|
||||||
initEditorConfigs();
|
initEditorConfigs();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -484,6 +484,9 @@ public:
|
|||||||
const QString &getQuickAccess() const;
|
const QString &getQuickAccess() const;
|
||||||
void setQuickAccess(const QString &p_path);
|
void setQuickAccess(const QString &p_path);
|
||||||
|
|
||||||
|
bool getHighlightMatchesInPage() const;
|
||||||
|
void setHighlightMatchesInPage(bool p_enabled);
|
||||||
|
|
||||||
// All the themes.
|
// All the themes.
|
||||||
QList<QString> getThemes() const;
|
QList<QString> getThemes() const;
|
||||||
|
|
||||||
@ -923,6 +926,9 @@ private:
|
|||||||
// Absolute path of quick access note.
|
// Absolute path of quick access note.
|
||||||
QString m_quickAccess;
|
QString m_quickAccess;
|
||||||
|
|
||||||
|
// Whether highlight matches in page when activating a search item.
|
||||||
|
bool m_highlightMatchesInPage;
|
||||||
|
|
||||||
// The theme name.
|
// The theme name.
|
||||||
QString m_theme;
|
QString m_theme;
|
||||||
|
|
||||||
@ -2613,4 +2619,19 @@ inline void VConfigManager::setQuickAccess(const QString &p_path)
|
|||||||
m_quickAccess = p_path;
|
m_quickAccess = p_path;
|
||||||
setConfigToSettings("global", "quick_access", m_quickAccess);
|
setConfigToSettings("global", "quick_access", m_quickAccess);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool VConfigManager::getHighlightMatchesInPage() const
|
||||||
|
{
|
||||||
|
return m_highlightMatchesInPage;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void VConfigManager::setHighlightMatchesInPage(bool p_enabled)
|
||||||
|
{
|
||||||
|
if (m_highlightMatchesInPage == p_enabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_highlightMatchesInPage = p_enabled;
|
||||||
|
setConfigToSettings("global", "highlight_matches_in_page", m_highlightMatchesInPage);
|
||||||
|
}
|
||||||
#endif // VCONFIGMANAGER_H
|
#endif // VCONFIGMANAGER_H
|
||||||
|
126
src/veditor.cpp
126
src/veditor.cpp
@ -371,6 +371,69 @@ QList<QTextCursor> VEditor::findTextAll(const QString &p_text,
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void mergeResult(QList<QTextCursor> &p_result, const QList<QTextCursor> &p_part)
|
||||||
|
{
|
||||||
|
if (p_result.isEmpty()) {
|
||||||
|
p_result = p_part;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int idx = 0;
|
||||||
|
for (auto const & cur : p_part) {
|
||||||
|
// Find position to insert into @p_result.
|
||||||
|
while (idx < p_result.size()) {
|
||||||
|
const QTextCursor &toCur = p_result[idx];
|
||||||
|
if (cur.selectionEnd() <= toCur.selectionStart()) {
|
||||||
|
// Insert it before toCur.
|
||||||
|
p_result.insert(idx, cur);
|
||||||
|
++idx;
|
||||||
|
break;
|
||||||
|
} else if (cur.selectionStart() < toCur.selectionEnd()) {
|
||||||
|
// Interleave. Abandon it.
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
++idx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert to the end.
|
||||||
|
if (idx >= p_result.size()) {
|
||||||
|
p_result.append(cur);
|
||||||
|
idx = p_result.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<QTextCursor> VEditor::findTextAll(const VSearchToken &p_token,
|
||||||
|
int p_start,
|
||||||
|
int p_end)
|
||||||
|
{
|
||||||
|
QList<QTextCursor> results;
|
||||||
|
if (p_token.isEmpty()) {
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
QTextDocument::FindFlags flags;
|
||||||
|
if (p_token.m_caseSensitivity == Qt::CaseSensitive) {
|
||||||
|
flags |= QTextDocument::FindCaseSensitively;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p_token.m_type == VSearchToken::RawString) {
|
||||||
|
for (auto const & wd : p_token.m_keywords) {
|
||||||
|
QList<QTextCursor> part = findTextAllInRange(m_document, wd, flags, p_start, p_end);
|
||||||
|
mergeResult(results, part);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Regular expression.
|
||||||
|
for (auto const & reg : p_token.m_regs) {
|
||||||
|
QList<QTextCursor> part = findTextAllInRange(m_document, reg, flags, p_start, p_end);
|
||||||
|
mergeResult(results, part);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
const QList<QTextCursor> &VEditor::findTextAllCached(const QString &p_text,
|
const QList<QTextCursor> &VEditor::findTextAllCached(const QString &p_text,
|
||||||
uint p_options,
|
uint p_options,
|
||||||
int p_start,
|
int p_start,
|
||||||
@ -391,6 +454,25 @@ const QList<QTextCursor> &VEditor::findTextAllCached(const QString &p_text,
|
|||||||
return m_findInfo.m_result;
|
return m_findInfo.m_result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const QList<QTextCursor> &VEditor::findTextAllCached(const VSearchToken &p_token,
|
||||||
|
int p_start,
|
||||||
|
int p_end)
|
||||||
|
{
|
||||||
|
if (p_token.isEmpty()) {
|
||||||
|
m_findInfo.clear();
|
||||||
|
return m_findInfo.m_result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_findInfo.isCached(p_token, p_start, p_end)) {
|
||||||
|
return m_findInfo.m_result;
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<QTextCursor> result = findTextAll(p_token, p_start, p_end);
|
||||||
|
m_findInfo.update(p_token, p_start, p_end, result);
|
||||||
|
|
||||||
|
return m_findInfo.m_result;
|
||||||
|
}
|
||||||
|
|
||||||
void VEditor::highlightSelectedWord()
|
void VEditor::highlightSelectedWord()
|
||||||
{
|
{
|
||||||
QList<QTextEdit::ExtraSelection> &selects = m_extraSelections[(int)SelectionId::SelectedWord];
|
QList<QTextEdit::ExtraSelection> &selects = m_extraSelections[(int)SelectionId::SelectedWord];
|
||||||
@ -613,6 +695,48 @@ bool VEditor::findText(const QString &p_text,
|
|||||||
p_useLeftSideOfCursor);
|
p_useLeftSideOfCursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool VEditor::findText(const VSearchToken &p_token, bool p_forward, bool p_fromStart)
|
||||||
|
{
|
||||||
|
clearIncrementalSearchedWordHighlight();
|
||||||
|
|
||||||
|
if (p_token.isEmpty()) {
|
||||||
|
m_findInfo.clear();
|
||||||
|
clearSearchedWordHighlight();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QList<QTextCursor> &result = findTextAllCached(p_token);
|
||||||
|
|
||||||
|
if (result.isEmpty()) {
|
||||||
|
clearSearchedWordHighlight();
|
||||||
|
|
||||||
|
emit m_object->statusMessage(QObject::tr("No match found"));
|
||||||
|
} else {
|
||||||
|
// Locate to the right match and update current cursor.
|
||||||
|
QTextCursor cursor = textCursorW();
|
||||||
|
int pos = p_fromStart ? (m_document->characterCount() + 1) : cursor.position();
|
||||||
|
bool wrapped = false;
|
||||||
|
int idx = selectCursor(result, pos, p_forward, wrapped);
|
||||||
|
const QTextCursor &tcursor = result.at(idx);
|
||||||
|
if (wrapped && !p_fromStart) {
|
||||||
|
showWrapLabel();
|
||||||
|
}
|
||||||
|
|
||||||
|
cursor.setPosition(tcursor.selectionStart(), QTextCursor::MoveAnchor);
|
||||||
|
setTextCursorW(cursor);
|
||||||
|
|
||||||
|
highlightSearchedWord(result);
|
||||||
|
|
||||||
|
highlightSearchedWordUnderCursor(tcursor);
|
||||||
|
|
||||||
|
emit m_object->statusMessage(QObject::tr("Match found: %2 of %3")
|
||||||
|
.arg(idx + 1)
|
||||||
|
.arg(result.size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return !result.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
bool VEditor::findTextInRange(const QString &p_text,
|
bool VEditor::findTextInRange(const QString &p_text,
|
||||||
uint p_options,
|
uint p_options,
|
||||||
bool p_forward,
|
bool p_forward,
|
||||||
@ -1463,7 +1587,7 @@ void VEditor::nextMatch(bool p_forward)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (m_findInfo.m_useToken) {
|
if (m_findInfo.m_useToken) {
|
||||||
// TODO
|
findText(m_findInfo.m_token, p_forward, false);
|
||||||
} else {
|
} else {
|
||||||
findTextInRange(m_findInfo.m_text,
|
findTextInRange(m_findInfo.m_text,
|
||||||
m_findInfo.m_options,
|
m_findInfo.m_options,
|
||||||
|
@ -84,6 +84,8 @@ public:
|
|||||||
QTextCursor::MoveMode p_moveMode = QTextCursor::MoveAnchor,
|
QTextCursor::MoveMode p_moveMode = QTextCursor::MoveAnchor,
|
||||||
bool p_useLeftSideOfCursor = false);
|
bool p_useLeftSideOfCursor = false);
|
||||||
|
|
||||||
|
bool findText(const VSearchToken &p_token, bool p_forward, bool p_fromStart);
|
||||||
|
|
||||||
// Constrain the scope.
|
// Constrain the scope.
|
||||||
bool findTextInRange(const QString &p_text,
|
bool findTextInRange(const QString &p_text,
|
||||||
uint p_options,
|
uint p_options,
|
||||||
@ -327,6 +329,17 @@ private:
|
|||||||
&& m_end == p_end;
|
&& m_end == p_end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isCached(const VSearchToken &p_token,
|
||||||
|
int p_start = 0,
|
||||||
|
int p_end = -1) const
|
||||||
|
{
|
||||||
|
return m_cacheValid
|
||||||
|
&& m_useToken
|
||||||
|
&& m_token == p_token
|
||||||
|
&& m_start == p_start
|
||||||
|
&& m_end == p_end;
|
||||||
|
}
|
||||||
|
|
||||||
void update(const QString &p_text,
|
void update(const QString &p_text,
|
||||||
uint p_options,
|
uint p_options,
|
||||||
int p_start,
|
int p_start,
|
||||||
@ -347,10 +360,29 @@ private:
|
|||||||
m_token.clear();
|
m_token.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void update(const VSearchToken &p_token,
|
||||||
|
int p_start,
|
||||||
|
int p_end,
|
||||||
|
const QList<QTextCursor> &p_result)
|
||||||
|
{
|
||||||
|
m_start = p_start;
|
||||||
|
m_end = p_end;
|
||||||
|
|
||||||
|
m_useToken = true;
|
||||||
|
|
||||||
|
m_token = p_token;
|
||||||
|
|
||||||
|
m_cacheValid = true;
|
||||||
|
m_result = p_result;
|
||||||
|
|
||||||
|
m_text.clear();
|
||||||
|
m_options = 0;
|
||||||
|
}
|
||||||
|
|
||||||
bool isNull() const
|
bool isNull() const
|
||||||
{
|
{
|
||||||
if (m_useToken) {
|
if (m_useToken) {
|
||||||
return m_token.tokenSize() == 0;
|
return m_token.isEmpty();
|
||||||
} else {
|
} else {
|
||||||
return m_text.isEmpty();
|
return m_text.isEmpty();
|
||||||
}
|
}
|
||||||
@ -396,11 +428,19 @@ private:
|
|||||||
int p_start = 0,
|
int p_start = 0,
|
||||||
int p_end = -1);
|
int p_end = -1);
|
||||||
|
|
||||||
|
QList<QTextCursor> findTextAll(const VSearchToken &p_token,
|
||||||
|
int p_start = 0,
|
||||||
|
int p_end = -1);
|
||||||
|
|
||||||
const QList<QTextCursor> &findTextAllCached(const QString &p_text,
|
const QList<QTextCursor> &findTextAllCached(const QString &p_text,
|
||||||
uint p_options,
|
uint p_options,
|
||||||
int p_start = 0,
|
int p_start = 0,
|
||||||
int p_end = -1);
|
int p_end = -1);
|
||||||
|
|
||||||
|
const QList<QTextCursor> &findTextAllCached(const VSearchToken &p_token,
|
||||||
|
int p_start = 0,
|
||||||
|
int p_end = -1);
|
||||||
|
|
||||||
// Highlight @p_cursor as the incremental searched keyword.
|
// Highlight @p_cursor as the incremental searched keyword.
|
||||||
void highlightIncrementalSearchedWord(const QTextCursor &p_cursor);
|
void highlightIncrementalSearchedWord(const QTextCursor &p_cursor);
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include "utils/vvim.h"
|
#include "utils/vvim.h"
|
||||||
#include "vedittabinfo.h"
|
#include "vedittabinfo.h"
|
||||||
#include "vwordcountinfo.h"
|
#include "vwordcountinfo.h"
|
||||||
|
#include "vsearchconfig.h"
|
||||||
|
|
||||||
class VEditArea;
|
class VEditArea;
|
||||||
class VSnippet;
|
class VSnippet;
|
||||||
@ -59,6 +60,10 @@ public:
|
|||||||
virtual void findText(const QString &p_text, uint p_options, bool p_peek,
|
virtual void findText(const QString &p_text, uint p_options, bool p_peek,
|
||||||
bool p_forward = true) = 0;
|
bool p_forward = true) = 0;
|
||||||
|
|
||||||
|
virtual void findText(const VSearchToken &p_token,
|
||||||
|
bool p_forward = true,
|
||||||
|
bool p_fromStart = false) = 0;
|
||||||
|
|
||||||
// Replace @p_text with @p_replaceText in current note.
|
// Replace @p_text with @p_replaceText in current note.
|
||||||
virtual void replaceText(const QString &p_text, uint p_options,
|
virtual void replaceText(const QString &p_text, uint p_options,
|
||||||
const QString &p_replaceText, bool p_findNext) = 0;
|
const QString &p_replaceText, bool p_findNext) = 0;
|
||||||
|
@ -224,6 +224,17 @@ void VHtmlTab::findText(const QString &p_text, uint p_options, bool p_peek,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VHtmlTab::findText(const VSearchToken &p_token,
|
||||||
|
bool p_forward,
|
||||||
|
bool p_fromStart)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
Q_UNUSED(p_token);
|
||||||
|
Q_UNUSED(p_forward);
|
||||||
|
Q_UNUSED(p_fromStart);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
void VHtmlTab::replaceText(const QString &p_text, uint p_options,
|
void VHtmlTab::replaceText(const QString &p_text, uint p_options,
|
||||||
const QString &p_replaceText, bool p_findNext)
|
const QString &p_replaceText, bool p_findNext)
|
||||||
{
|
{
|
||||||
|
@ -34,6 +34,10 @@ public:
|
|||||||
void findText(const QString &p_text, uint p_options, bool p_peek,
|
void findText(const QString &p_text, uint p_options, bool p_peek,
|
||||||
bool p_forward = true) Q_DECL_OVERRIDE;
|
bool p_forward = true) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
void findText(const VSearchToken &p_token,
|
||||||
|
bool p_forward = true,
|
||||||
|
bool p_fromStart = false) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
// Replace @p_text with @p_replaceText in current note.
|
// Replace @p_text with @p_replaceText in current note.
|
||||||
void replaceText(const QString &p_text, uint p_options,
|
void replaceText(const QString &p_text, uint p_options,
|
||||||
const QString &p_replaceText, bool p_findNext) Q_DECL_OVERRIDE;
|
const QString &p_replaceText, bool p_findNext) Q_DECL_OVERRIDE;
|
||||||
|
@ -701,6 +701,18 @@ void VMdTab::findText(const QString &p_text, uint p_options, bool p_peek,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VMdTab::findText(const VSearchToken &p_token,
|
||||||
|
bool p_forward,
|
||||||
|
bool p_fromStart)
|
||||||
|
{
|
||||||
|
if (m_isEditMode) {
|
||||||
|
m_editor->findText(p_token, p_forward, p_fromStart);
|
||||||
|
} else {
|
||||||
|
// TODO
|
||||||
|
Q_ASSERT(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void VMdTab::replaceText(const QString &p_text, uint p_options,
|
void VMdTab::replaceText(const QString &p_text, uint p_options,
|
||||||
const QString &p_replaceText, bool p_findNext)
|
const QString &p_replaceText, bool p_findNext)
|
||||||
{
|
{
|
||||||
|
@ -50,6 +50,10 @@ public:
|
|||||||
void findText(const QString &p_text, uint p_options, bool p_peek,
|
void findText(const QString &p_text, uint p_options, bool p_peek,
|
||||||
bool p_forward = true) Q_DECL_OVERRIDE;
|
bool p_forward = true) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
void findText(const VSearchToken &p_token,
|
||||||
|
bool p_forward = true,
|
||||||
|
bool p_fromStart = false) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
// Replace @p_text with @p_replaceText in current note.
|
// Replace @p_text with @p_replaceText in current note.
|
||||||
void replaceText(const QString &p_text, uint p_options,
|
void replaceText(const QString &p_text, uint p_options,
|
||||||
const QString &p_replaceText, bool p_findNext) Q_DECL_OVERRIDE;
|
const QString &p_replaceText, bool p_findNext) Q_DECL_OVERRIDE;
|
||||||
|
@ -487,7 +487,8 @@ VSearchResultItem *VSearch::searchForOutline(const VFile *p_file) const
|
|||||||
item = new VSearchResultItem(VSearchResultItem::Note,
|
item = new VSearchResultItem(VSearchResultItem::Note,
|
||||||
VSearchResultItem::OutlineIndex,
|
VSearchResultItem::OutlineIndex,
|
||||||
p_file->getName(),
|
p_file->getName(),
|
||||||
p_file->fetchPath());
|
p_file->fetchPath(),
|
||||||
|
m_config);
|
||||||
}
|
}
|
||||||
|
|
||||||
VSearchResultSubItem sitem(it.m_index, it.m_name);
|
VSearchResultSubItem sitem(it.m_index, it.m_name);
|
||||||
@ -600,7 +601,8 @@ VSearchResultItem *VSearch::searchForContent(const VFile *p_file) const
|
|||||||
item = new VSearchResultItem(VSearchResultItem::Note,
|
item = new VSearchResultItem(VSearchResultItem::Note,
|
||||||
VSearchResultItem::LineNumber,
|
VSearchResultItem::LineNumber,
|
||||||
p_file->getName(),
|
p_file->getName(),
|
||||||
p_file->fetchPath());
|
p_file->fetchPath(),
|
||||||
|
m_config);
|
||||||
}
|
}
|
||||||
|
|
||||||
VSearchResultSubItem sitem(lineNum, lineText);
|
VSearchResultSubItem sitem(lineNum, lineText);
|
||||||
|
@ -165,6 +165,26 @@ struct VSearchToken
|
|||||||
return m_type == Type::RawString ? m_keywords.size() : m_regs.size();
|
return m_type == Type::RawString ? m_keywords.size() : m_regs.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isEmpty() const
|
||||||
|
{
|
||||||
|
return tokenSize() == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const VSearchToken &p_other) const
|
||||||
|
{
|
||||||
|
if (m_type != p_other.m_type
|
||||||
|
|| m_op != p_other.m_op
|
||||||
|
|| m_caseSensitivity != p_other.m_caseSensitivity
|
||||||
|
|| m_keywords.size() != p_other.m_keywords.size()
|
||||||
|
|| m_numOfMatches != p_other.m_numOfMatches
|
||||||
|
|| m_regs.size() != p_other.m_regs.size()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_keywords == p_other.m_keywords
|
||||||
|
&& m_regs == p_other.m_regs;
|
||||||
|
}
|
||||||
|
|
||||||
VSearchToken::Type m_type;
|
VSearchToken::Type m_type;
|
||||||
|
|
||||||
VSearchToken::Operator m_op;
|
VSearchToken::Operator m_op;
|
||||||
@ -484,11 +504,13 @@ struct VSearchResultItem
|
|||||||
VSearchResultItem(VSearchResultItem::ItemType p_type,
|
VSearchResultItem(VSearchResultItem::ItemType p_type,
|
||||||
VSearchResultItem::MatchType p_matchType,
|
VSearchResultItem::MatchType p_matchType,
|
||||||
const QString &p_text,
|
const QString &p_text,
|
||||||
const QString &p_path)
|
const QString &p_path,
|
||||||
|
const QSharedPointer<VSearchConfig> &p_config = nullptr)
|
||||||
: m_type(p_type),
|
: m_type(p_type),
|
||||||
m_matchType(p_matchType),
|
m_matchType(p_matchType),
|
||||||
m_text(p_text),
|
m_text(p_text),
|
||||||
m_path(p_path)
|
m_path(p_path),
|
||||||
|
m_config(p_config)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -518,6 +540,9 @@ struct VSearchResultItem
|
|||||||
|
|
||||||
// Matched places within this item.
|
// Matched places within this item.
|
||||||
QList<VSearchResultSubItem> m_matches;
|
QList<VSearchResultSubItem> m_matches;
|
||||||
|
|
||||||
|
// Search config to search for this item.
|
||||||
|
QSharedPointer<VSearchConfig> m_config;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -14,10 +14,12 @@ VSearchEngineWorker::VSearchEngineWorker(QObject *p_parent)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void VSearchEngineWorker::setData(const QStringList &p_files,
|
void VSearchEngineWorker::setData(const QStringList &p_files,
|
||||||
const VSearchToken &p_token)
|
const VSearchToken &p_token,
|
||||||
|
const QSharedPointer<VSearchConfig> &p_config)
|
||||||
{
|
{
|
||||||
m_files = p_files;
|
m_files = p_files;
|
||||||
m_token = p_token;
|
m_token = p_token;
|
||||||
|
m_config = p_config;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VSearchEngineWorker::stop()
|
void VSearchEngineWorker::stop()
|
||||||
@ -104,7 +106,8 @@ VSearchResultItem *VSearchEngineWorker::searchFile(const QString &p_fileName)
|
|||||||
item = new VSearchResultItem(VSearchResultItem::Note,
|
item = new VSearchResultItem(VSearchResultItem::Note,
|
||||||
VSearchResultItem::LineNumber,
|
VSearchResultItem::LineNumber,
|
||||||
VUtils::fileNameFromPath(p_fileName),
|
VUtils::fileNameFromPath(p_fileName),
|
||||||
p_fileName);
|
p_fileName,
|
||||||
|
m_config);
|
||||||
}
|
}
|
||||||
|
|
||||||
VSearchResultSubItem sitem(lineNum, line);
|
VSearchResultSubItem sitem(lineNum, line);
|
||||||
@ -188,7 +191,8 @@ void VSearchEngine::search(const QSharedPointer<VSearchConfig> &p_config,
|
|||||||
|
|
||||||
VSearchEngineWorker *th = new VSearchEngineWorker(this);
|
VSearchEngineWorker *th = new VSearchEngineWorker(this);
|
||||||
th->setData(m_result->m_secondPhaseItems.mid(start, len),
|
th->setData(m_result->m_secondPhaseItems.mid(start, len),
|
||||||
p_config->m_contentToken);
|
p_config->m_contentToken,
|
||||||
|
p_config);
|
||||||
connect(th, &VSearchEngineWorker::finished,
|
connect(th, &VSearchEngineWorker::finished,
|
||||||
this, &VSearchEngine::handleWorkerFinished);
|
this, &VSearchEngine::handleWorkerFinished);
|
||||||
connect(th, &VSearchEngineWorker::resultItemsReady,
|
connect(th, &VSearchEngineWorker::resultItemsReady,
|
||||||
|
@ -22,7 +22,8 @@ public:
|
|||||||
explicit VSearchEngineWorker(QObject *p_parent = nullptr);
|
explicit VSearchEngineWorker(QObject *p_parent = nullptr);
|
||||||
|
|
||||||
void setData(const QStringList &p_files,
|
void setData(const QStringList &p_files,
|
||||||
const VSearchToken &p_token);
|
const VSearchToken &p_token,
|
||||||
|
const QSharedPointer<VSearchConfig> &p_config);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void stop();
|
void stop();
|
||||||
@ -46,6 +47,8 @@ private:
|
|||||||
|
|
||||||
VSearchToken m_token;
|
VSearchToken m_token;
|
||||||
|
|
||||||
|
QSharedPointer<VSearchConfig> m_config;
|
||||||
|
|
||||||
VSearchState m_state;
|
VSearchState m_state;
|
||||||
|
|
||||||
QString m_error;
|
QString m_error;
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include "vhistorylist.h"
|
#include "vhistorylist.h"
|
||||||
#include "vexplorer.h"
|
#include "vexplorer.h"
|
||||||
#include "vuniversalentry.h"
|
#include "vuniversalentry.h"
|
||||||
|
#include "vsearchue.h"
|
||||||
|
|
||||||
extern VNote *g_vnote;
|
extern VNote *g_vnote;
|
||||||
|
|
||||||
@ -268,40 +269,5 @@ void VSearchResultTree::activateItem(const QTreeWidgetItem *p_item) const
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QSharedPointer<VSearchResultItem> &resItem = itemResultData(p_item);
|
VSearchUE::activateItem(itemResultData(p_item), VUtils::childIndexOfTreeItem(p_item));
|
||||||
switch (resItem->m_type) {
|
|
||||||
case VSearchResultItem::Note:
|
|
||||||
{
|
|
||||||
QStringList files(resItem->m_path);
|
|
||||||
g_mainWin->openFiles(files);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case VSearchResultItem::Folder:
|
|
||||||
{
|
|
||||||
VDirectory *dir = g_vnote->getInternalDirectory(resItem->m_path);
|
|
||||||
if (dir) {
|
|
||||||
g_mainWin->locateDirectory(dir);
|
|
||||||
} else {
|
|
||||||
// External directory.
|
|
||||||
g_mainWin->showExplorerPanel(true);
|
|
||||||
g_mainWin->getExplorer()->setRootDirectory(resItem->m_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case VSearchResultItem::Notebook:
|
|
||||||
{
|
|
||||||
VNotebook *nb = g_vnote->getNotebook(resItem->m_path);
|
|
||||||
if (nb) {
|
|
||||||
g_mainWin->locateNotebook(nb);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -18,11 +18,14 @@
|
|||||||
#include "veditarea.h"
|
#include "veditarea.h"
|
||||||
#include "vexplorer.h"
|
#include "vexplorer.h"
|
||||||
#include "vuniversalentry.h"
|
#include "vuniversalentry.h"
|
||||||
|
#include "vconfigmanager.h"
|
||||||
|
|
||||||
extern VNote *g_vnote;
|
extern VNote *g_vnote;
|
||||||
|
|
||||||
extern VMainWindow *g_mainWin;
|
extern VMainWindow *g_mainWin;
|
||||||
|
|
||||||
|
extern VConfigManager *g_config;
|
||||||
|
|
||||||
#define ITEM_NUM_TO_UPDATE_WIDGET 20
|
#define ITEM_NUM_TO_UPDATE_WIDGET 20
|
||||||
|
|
||||||
VSearchUE::VSearchUE(QObject *p_parent)
|
VSearchUE::VSearchUE(QObject *p_parent)
|
||||||
@ -908,13 +911,47 @@ const QSharedPointer<VSearchResultItem> &VSearchUE::itemResultData(const QTreeWi
|
|||||||
return m_data[idx];
|
return m_data[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
void VSearchUE::activateItem(const QSharedPointer<VSearchResultItem> &p_item)
|
void VSearchUE::activateItem(const QSharedPointer<VSearchResultItem> &p_item, int p_matchIndex)
|
||||||
{
|
{
|
||||||
switch (p_item->m_type) {
|
switch (p_item->m_type) {
|
||||||
case VSearchResultItem::Note:
|
case VSearchResultItem::Note:
|
||||||
{
|
{
|
||||||
|
bool highlightPage = false;
|
||||||
|
bool jumpTitle = false;
|
||||||
|
if (!p_item->m_matches.isEmpty() && p_item->m_config) {
|
||||||
|
if (p_item->m_config->m_object == VSearchConfig::Content) {
|
||||||
|
highlightPage = g_config->getHighlightMatchesInPage();
|
||||||
|
} else if (p_item->m_config->m_object == VSearchConfig::Outline) {
|
||||||
|
jumpTitle = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QStringList files(p_item->m_path);
|
QStringList files(p_item->m_path);
|
||||||
g_mainWin->openFiles(files);
|
OpenFileMode mode = highlightPage ? OpenFileMode::Edit : OpenFileMode::Read;
|
||||||
|
bool forceMode = highlightPage;
|
||||||
|
QVector<VFile *> openedFiles = g_mainWin->openFiles(files,
|
||||||
|
false,
|
||||||
|
mode,
|
||||||
|
forceMode);
|
||||||
|
if (openedFiles.size() == 1) {
|
||||||
|
VEditTab *tab = g_mainWin->getCurrentTab();
|
||||||
|
if (tab->getFile() != openedFiles.first()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (highlightPage) {
|
||||||
|
tab->findText(p_item->m_config->m_contentToken, true, true);
|
||||||
|
} else if (jumpTitle) {
|
||||||
|
if (p_matchIndex >= p_item->m_matches.size()) {
|
||||||
|
p_matchIndex = p_item->m_matches.size() - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
VHeaderPointer header(tab->getFile(),
|
||||||
|
p_item->m_matches[p_matchIndex].m_lineNumber);
|
||||||
|
tab->scrollToHeader(header);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -923,6 +960,10 @@ void VSearchUE::activateItem(const QSharedPointer<VSearchResultItem> &p_item)
|
|||||||
VDirectory *dir = g_vnote->getInternalDirectory(p_item->m_path);
|
VDirectory *dir = g_vnote->getInternalDirectory(p_item->m_path);
|
||||||
if (dir) {
|
if (dir) {
|
||||||
g_mainWin->locateDirectory(dir);
|
g_mainWin->locateDirectory(dir);
|
||||||
|
} else {
|
||||||
|
// External directory.
|
||||||
|
g_mainWin->showExplorerPanel(true);
|
||||||
|
g_mainWin->getExplorer()->setRootDirectory(p_item->m_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -961,7 +1002,7 @@ void VSearchUE::activateItem(QTreeWidgetItem *p_item, int p_col)
|
|||||||
}
|
}
|
||||||
|
|
||||||
emit requestHideUniversalEntry();
|
emit requestHideUniversalEntry();
|
||||||
activateItem(itemResultData(p_item));
|
activateItem(itemResultData(p_item), VUtils::childIndexOfTreeItem(p_item));
|
||||||
}
|
}
|
||||||
|
|
||||||
void VSearchUE::selectNextItem(int p_id, bool p_forward)
|
void VSearchUE::selectNextItem(int p_id, bool p_forward)
|
||||||
|
@ -93,7 +93,7 @@ public:
|
|||||||
|
|
||||||
QString currentItemFolder(int p_id) Q_DECL_OVERRIDE;
|
QString currentItemFolder(int p_id) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
static void activateItem(const QSharedPointer<VSearchResultItem> &p_item);
|
static void activateItem(const QSharedPointer<VSearchResultItem> &p_item, int p_matchIndex = 0);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void init() Q_DECL_OVERRIDE;
|
void init() Q_DECL_OVERRIDE;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user