Editor: highlight matches of full-text search result in page

This commit is contained in:
Le Tan 2018-09-10 20:26:51 +08:00
parent 647807a918
commit a055d6e935
21 changed files with 407 additions and 51 deletions

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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.

View File

@ -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();
} }

View File

@ -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

View File

@ -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,

View File

@ -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);

View File

@ -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;

View File

@ -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)
{ {

View File

@ -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;

View File

@ -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)
{ {

View File

@ -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;

View File

@ -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);

View File

@ -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;
}; };

View File

@ -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,

View File

@ -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;

View File

@ -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;
}
} }

View File

@ -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)

View File

@ -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;