diff --git a/src/resources/icons/tag.svg b/src/resources/icons/tag.svg
new file mode 100644
index 00000000..743e07a3
--- /dev/null
+++ b/src/resources/icons/tag.svg
@@ -0,0 +1,11 @@
+
+
+
+
diff --git a/src/resources/icons/tag_explorer.svg b/src/resources/icons/tag_explorer.svg
new file mode 100644
index 00000000..05fa0e67
--- /dev/null
+++ b/src/resources/icons/tag_explorer.svg
@@ -0,0 +1,12 @@
+
+
+
+
diff --git a/src/src.pro b/src/src.pro
index e7264796..c2e8159e 100644
--- a/src/src.pro
+++ b/src/src.pro
@@ -139,7 +139,8 @@ SOURCES += main.cpp\
utils/vprocessutils.cpp \
vtagpanel.cpp \
valltagspanel.cpp \
- vtaglabel.cpp
+ vtaglabel.cpp \
+ vtagexplorer.cpp
HEADERS += vmainwindow.h \
vdirectorytree.h \
@@ -272,7 +273,8 @@ HEADERS += vmainwindow.h \
utils/vprocessutils.h \
vtagpanel.h \
valltagspanel.h \
- vtaglabel.h
+ vtaglabel.h \
+ vtagexplorer.h
RESOURCES += \
vnote.qrc \
diff --git a/src/vconfigmanager.h b/src/vconfigmanager.h
index 116cd9d4..df79b8e3 100644
--- a/src/vconfigmanager.h
+++ b/src/vconfigmanager.h
@@ -194,6 +194,9 @@ public:
const QByteArray getNotebookSplitterState() const;
void setNotebookSplitterState(const QByteArray &p_state);
+ const QByteArray getTagExplorerSplitterState() const;
+ void setTagExplorerSplitterState(const QByteArray &p_state);
+
bool getFindCaseSensitive() const;
void setFindCaseSensitive(bool p_enabled);
@@ -1304,6 +1307,19 @@ inline void VConfigManager::setNotebookSplitterState(const QByteArray &p_state)
p_state);
}
+inline const QByteArray VConfigManager::getTagExplorerSplitterState() const
+{
+ return getConfigFromSessionSettings("geometry",
+ "tag_explorer_splitter_state").toByteArray();
+}
+
+inline void VConfigManager::setTagExplorerSplitterState(const QByteArray &p_state)
+{
+ setConfigToSessionSettings("geometry",
+ "tag_explorer_splitter_state",
+ p_state);
+}
+
inline bool VConfigManager::getFindCaseSensitive() const
{
return m_findCaseSensitive;
diff --git a/src/vhistorylist.cpp b/src/vhistorylist.cpp
index fd1ca7d0..df155292 100644
--- a/src/vhistorylist.cpp
+++ b/src/vhistorylist.cpp
@@ -460,7 +460,7 @@ void VHistoryList::openItem(const QListWidgetItem *p_item) const
g_mainWin->openFiles(files);
}
-void VHistoryList::locateCurrentItem()
+void VHistoryList::locateCurrentItem() const
{
auto item = m_itemList->currentItem();
if (!item) {
diff --git a/src/vhistorylist.h b/src/vhistorylist.h
index 4dc1d013..480973a3 100644
--- a/src/vhistorylist.h
+++ b/src/vhistorylist.h
@@ -48,7 +48,7 @@ private slots:
void unpinSelectedItems();
- void locateCurrentItem();
+ void locateCurrentItem() const;
// Add selected files to Cart.
void addFileToCart() const;
diff --git a/src/vmainwindow.cpp b/src/vmainwindow.cpp
index 552e589b..58a72b67 100644
--- a/src/vmainwindow.cpp
+++ b/src/vmainwindow.cpp
@@ -48,6 +48,7 @@
#include "vhistorylist.h"
#include "vexplorer.h"
#include "vlistue.h"
+#include "vtagexplorer.h"
extern VConfigManager *g_config;
@@ -291,6 +292,13 @@ void VMainWindow::setupNaviBox()
m_naviBox->addItem(m_explorer,
":/resources/icons/explorer.svg",
tr("Explorer"));
+
+ m_tagExplorer = new VTagExplorer();
+ m_naviBox->addItem(m_tagExplorer,
+ ":/resources/icons/tag_explorer.svg",
+ tr("Tags"));
+ connect(m_notebookSelector, &VNotebookSelector::curNotebookChanged,
+ m_tagExplorer, &VTagExplorer::setNotebook);
}
void VMainWindow::setupNotebookPanel()
@@ -2177,17 +2185,18 @@ void VMainWindow::saveStateAndGeometry()
g_config->setSearchDockChecked(m_searchDock->isVisible());
g_config->setNotebookSplitterState(m_nbSplitter->saveState());
g_config->setMainSplitterState(m_mainSplitter->saveState());
+ m_tagExplorer->saveStateAndGeometry();
g_config->setNaviBoxCurrentIndex(m_naviBox->currentIndex());
}
void VMainWindow::restoreStateAndGeometry()
{
- const QByteArray &geometry = g_config->getMainWindowGeometry();
+ const QByteArray geometry = g_config->getMainWindowGeometry();
if (!geometry.isEmpty()) {
restoreGeometry(geometry);
}
- const QByteArray &state = g_config->getMainWindowState();
+ const QByteArray state = g_config->getMainWindowState();
if (!state.isEmpty()) {
restoreState(state);
}
@@ -2195,12 +2204,12 @@ void VMainWindow::restoreStateAndGeometry()
m_toolDock->setVisible(g_config->getToolsDockChecked());
m_searchDock->setVisible(g_config->getSearchDockChecked());
- const QByteArray &splitterState = g_config->getMainSplitterState();
+ const QByteArray splitterState = g_config->getMainSplitterState();
if (!splitterState.isEmpty()) {
m_mainSplitter->restoreState(splitterState);
}
- const QByteArray &nbSplitterState = g_config->getNotebookSplitterState();
+ const QByteArray nbSplitterState = g_config->getNotebookSplitterState();
if (!nbSplitterState.isEmpty()) {
m_nbSplitter->restoreState(nbSplitterState);
}
diff --git a/src/vmainwindow.h b/src/vmainwindow.h
index b680000c..2cfdea1a 100644
--- a/src/vmainwindow.h
+++ b/src/vmainwindow.h
@@ -44,6 +44,7 @@ class QPrinter;
class VUniversalEntry;
class VHistoryList;
class VExplorer;
+class VTagExplorer;
enum class PanelViewState
{
@@ -462,6 +463,8 @@ private:
VExplorer *m_explorer;
+ VTagExplorer *m_tagExplorer;
+
// Interval of the shared memory timer in ms.
static const int c_sharedMemTimerInterval;
};
diff --git a/src/vnote.qrc b/src/vnote.qrc
index 39e27a03..35a8dacf 100644
--- a/src/vnote.qrc
+++ b/src/vnote.qrc
@@ -259,5 +259,7 @@
resources/themes/v_detorte/v_detorte_codeblock.css
resources/themes/v_detorte/v_detorte_mermaid.css
resources/icons/tags.svg
+ resources/icons/tag_explorer.svg
+ resources/icons/tag.svg
diff --git a/src/vnotebook.cpp b/src/vnotebook.cpp
index 50bf81a0..227defcc 100644
--- a/src/vnotebook.cpp
+++ b/src/vnotebook.cpp
@@ -442,3 +442,18 @@ bool VNotebook::addTag(const QString &p_tag)
return true;
}
+
+void VNotebook::removeTag(const QString &p_tag)
+{
+ if (p_tag.isEmpty() || m_tags.isEmpty()) {
+ return;
+ }
+
+ int nr = m_tags.removeAll(p_tag);
+ if (nr > 0) {
+ if (!writeConfigNotebook()) {
+ qWarning() << "fail to update config of notebook" << m_name
+ << "in directory" << m_path;
+ }
+ }
+}
diff --git a/src/vnotebook.h b/src/vnotebook.h
index d5bdcde6..5d94d13e 100644
--- a/src/vnotebook.h
+++ b/src/vnotebook.h
@@ -60,6 +60,8 @@ public:
bool addTag(const QString &p_tag);
+ void removeTag(const QString &p_tag);
+
bool hasTag(const QString &p_tag) const;
static VNotebook *createNotebook(const QString &p_name,
diff --git a/src/vtagexplorer.cpp b/src/vtagexplorer.cpp
new file mode 100644
index 00000000..a0500623
--- /dev/null
+++ b/src/vtagexplorer.cpp
@@ -0,0 +1,497 @@
+#include "vtagexplorer.h"
+
+#include
+
+#include "utils/viconutils.h"
+#include "vmainwindow.h"
+#include "vlistwidget.h"
+#include "vnotebook.h"
+#include "vconfigmanager.h"
+#include "vsearch.h"
+#include "vnote.h"
+#include "vcart.h"
+#include "vhistorylist.h"
+#include "vnotefile.h"
+#include "utils/vutils.h"
+
+extern VMainWindow *g_mainWin;
+
+extern VConfigManager *g_config;
+
+extern VNote *g_vnote;
+
+#define MAX_DISPLAY_LENGTH 10
+
+VTagExplorer::VTagExplorer(QWidget *p_parent)
+ : QWidget(p_parent),
+ m_uiInitialized(false),
+ m_notebook(NULL),
+ m_notebookChanged(true),
+ m_search(NULL)
+{
+}
+
+void VTagExplorer::setupUI()
+{
+ if (m_uiInitialized) {
+ return;
+ }
+
+ m_uiInitialized = true;
+
+ m_notebookLabel = new QLabel(tr("Tags"), this);
+ m_notebookLabel->setProperty("TitleLabel", true);
+
+ m_tagList = new VListWidget(this);
+ m_tagList->setAttribute(Qt::WA_MacShowFocusRect, false);
+ connect(m_tagList, &QListWidget::itemActivated,
+ this, [this](const QListWidgetItem *p_item) {
+ QString tag;
+ if (p_item) {
+ tag = p_item->text();
+ }
+
+ bool ret = activateTag(tag);
+ if (ret && !tag.isEmpty() && m_fileList->count() == 0) {
+ promptToRemoveEmptyTag(tag);
+ }
+ });
+
+ m_tagLabel = new QLabel(tr("Notes"), this);
+ m_tagLabel->setProperty("TitleLabel", true);
+
+ m_fileList = new VListWidget(this);
+ m_fileList->setAttribute(Qt::WA_MacShowFocusRect, false);
+ m_fileList->setContextMenuPolicy(Qt::CustomContextMenu);
+ m_fileList->setSelectionMode(QAbstractItemView::ExtendedSelection);
+ connect(m_fileList, &QListWidget::itemActivated,
+ this, &VTagExplorer::openFileItem);
+ connect(m_fileList, &QListWidget::customContextMenuRequested,
+ this, &VTagExplorer::handleFileListContextMenuRequested);
+
+ QWidget *fileWidget = new QWidget(this);
+ QVBoxLayout *fileLayout = new QVBoxLayout();
+ fileLayout->addWidget(m_tagLabel);
+ fileLayout->addWidget(m_fileList);
+ fileLayout->setContentsMargins(0, 0, 0, 0);
+ fileWidget->setLayout(fileLayout);
+
+ m_splitter = new QSplitter(this);
+ m_splitter->setOrientation(Qt::Vertical);
+ m_splitter->setObjectName("TagExplorerSplitter");
+ m_splitter->addWidget(m_tagList);
+ m_splitter->addWidget(fileWidget);
+ m_splitter->setStretchFactor(0, 0);
+ m_splitter->setStretchFactor(1, 1);
+
+ QVBoxLayout *mainLayout = new QVBoxLayout();
+ mainLayout->addWidget(m_notebookLabel);
+ mainLayout->addWidget(m_splitter);
+ mainLayout->setContentsMargins(0, 0, 0, 0);
+
+ setLayout(mainLayout);
+
+ restoreStateAndGeometry();
+}
+
+void VTagExplorer::showEvent(QShowEvent *p_event)
+{
+ setupUI();
+ QWidget::showEvent(p_event);
+
+ updateContent();
+}
+
+void VTagExplorer::focusInEvent(QFocusEvent *p_event)
+{
+ setupUI();
+ QWidget::focusInEvent(p_event);
+ m_tagList->setFocus();
+}
+
+void VTagExplorer::setNotebook(VNotebook *p_notebook)
+{
+ if (p_notebook == m_notebook) {
+ return;
+ }
+
+ setupUI();
+
+ m_notebook = p_notebook;
+ m_notebookChanged = true;
+
+ if (!isVisible()) {
+ return;
+ }
+
+ updateContent();
+}
+
+void VTagExplorer::updateContent()
+{
+ if (m_notebook) {
+ updateNotebookLabel();
+ const QStringList &tags = m_notebook->getTags();
+ if (m_notebookChanged || tagListObsolete(tags)) {
+ updateTagList(tags);
+ }
+ } else {
+ clear();
+ }
+
+ m_notebookChanged = false;
+}
+
+void VTagExplorer::clear()
+{
+ setupUI();
+
+ m_fileList->clearAll();
+ m_tagList->clearAll();
+ updateTagLabel("");
+ updateNotebookLabel();
+}
+
+void VTagExplorer::updateNotebookLabel()
+{
+ QString text = tr("Tags");
+ QString tooltip;
+ if (m_notebook) {
+ QString name = m_notebook->getName();
+ tooltip = name;
+
+ if (name.size() > MAX_DISPLAY_LENGTH) {
+ name = name.left(MAX_DISPLAY_LENGTH) + QStringLiteral("...");
+ }
+
+ text = tr("Tags (%1)").arg(name);
+ }
+
+ m_notebookLabel->setText(text);
+ m_notebookLabel->setToolTip(tooltip);
+}
+
+bool VTagExplorer::tagListObsolete(const QStringList &p_tags) const
+{
+ if (m_tagList->count() != p_tags.size()) {
+ return true;
+ }
+
+ for (int i = 0; i < p_tags.size(); ++i) {
+ if (p_tags[i] != m_tagList->item(i)->text()) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void VTagExplorer::updateTagLabel(const QString &p_tag)
+{
+ QString text = tr("Notes");
+ QString tooltip;
+ if (!p_tag.isEmpty()) {
+ QString name = p_tag;
+ tooltip = name;
+
+ if (name.size() > MAX_DISPLAY_LENGTH) {
+ name = name.left(MAX_DISPLAY_LENGTH) + QStringLiteral("...");
+ }
+
+ text = tr("Notes (%1)").arg(name);
+ }
+
+ m_tagLabel->setText(text);
+ m_tagLabel->setToolTip(tooltip);
+}
+
+bool VTagExplorer::activateTag(const QString &p_tag)
+{
+ updateTagLabel(p_tag);
+
+ m_fileList->clearAll();
+
+ if (p_tag.isEmpty()) {
+ return false;
+ }
+
+ // Search this tag within current notebook.
+ g_mainWin->showStatusMessage(tr("Searching for tag \"%1\"").arg(p_tag));
+
+ QVector notebooks;
+ notebooks.append(m_notebook);
+ getVSearch()->clear();
+ QSharedPointer config(new VSearchConfig(VSearchConfig::CurrentNotebook,
+ VSearchConfig::Tag,
+ VSearchConfig::Note,
+ VSearchConfig::Internal,
+ VSearchConfig::NoneOption,
+ p_tag,
+ QString()));
+ getVSearch()->setConfig(config);
+ QSharedPointer result = getVSearch()->search(notebooks);
+
+ bool ret = result->m_state == VSearchState::Success;
+ handleSearchFinished(result);
+
+ return ret;
+}
+
+void VTagExplorer::updateTagList(const QStringList &p_tags)
+{
+ // Clear.
+ m_tagList->clearAll();
+ activateTag("");
+
+ for (auto const & tag : p_tags) {
+ addTagItem(tag);
+ }
+
+ if (m_tagList->count() > 0) {
+ m_tagList->setCurrentRow(0, QItemSelectionModel::ClearAndSelect);
+ }
+}
+
+void VTagExplorer::addTagItem(const QString &p_tag)
+{
+ QListWidgetItem *item = new QListWidgetItem(VIconUtils::treeViewIcon(":/resources/icons/tag.svg"),
+ p_tag);
+ item->setToolTip(p_tag);
+
+ m_tagList->addItem(item);
+}
+
+void VTagExplorer::saveStateAndGeometry()
+{
+ if (!m_uiInitialized) {
+ return;
+ }
+
+ g_config->setTagExplorerSplitterState(m_splitter->saveState());
+}
+
+void VTagExplorer::restoreStateAndGeometry()
+{
+ const QByteArray state = g_config->getTagExplorerSplitterState();
+ if (!state.isEmpty()) {
+ m_splitter->restoreState(state);
+ }
+}
+
+void VTagExplorer::initVSearch()
+{
+ m_search = new VSearch(this);
+ connect(m_search, &VSearch::resultItemAdded,
+ this, &VTagExplorer::handleSearchItemAdded);
+ connect(m_search, &VSearch::resultItemsAdded,
+ this, &VTagExplorer::handleSearchItemsAdded);
+ connect(m_search, &VSearch::finished,
+ this, &VTagExplorer::handleSearchFinished);
+
+ m_noteIcon = VIconUtils::treeViewIcon(":/resources/icons/note_item.svg");
+}
+
+void VTagExplorer::handleSearchItemAdded(const QSharedPointer &p_item)
+{
+ appendItemToFileList(p_item);
+}
+
+void VTagExplorer::appendItemToFileList(const QSharedPointer &p_item)
+{
+ Q_ASSERT(p_item->m_type == VSearchResultItem::Note);
+
+ QListWidgetItem *item = new QListWidgetItem(m_noteIcon,
+ p_item->m_text.isEmpty() ? p_item->m_path : p_item->m_text);
+ item->setData(Qt::UserRole, p_item->m_path);
+ item->setToolTip(p_item->m_path);
+ m_fileList->addItem(item);
+}
+
+void VTagExplorer::handleSearchItemsAdded(const QList > &p_items)
+{
+ for (auto const & it : p_items) {
+ appendItemToFileList(it);
+ }
+}
+
+void VTagExplorer::handleSearchFinished(const QSharedPointer &p_result)
+{
+ Q_ASSERT(p_result->m_state != VSearchState::Idle);
+ QString msg;
+ switch (p_result->m_state) {
+ case VSearchState::Busy:
+ // Only synchronized search.
+ Q_ASSERT(false);
+ msg = tr("Invalid busy state when searching for tag");
+ break;
+
+ case VSearchState::Success:
+ qDebug() << "search succeeded";
+ msg = tr("Search for tag succeeded");
+ break;
+
+ case VSearchState::Fail:
+ qDebug() << "search failed";
+ msg = tr("Search for tag failed");
+ break;
+
+ case VSearchState::Cancelled:
+ qDebug() << "search cancelled";
+ msg = tr("Search for tag calcelled");
+ break;
+
+ default:
+ break;
+ }
+
+ m_search->clear();
+
+ if (!msg.isEmpty()) {
+ g_mainWin->showStatusMessage(msg);
+ }
+}
+
+void VTagExplorer::openFileItem(QListWidgetItem *p_item) const
+{
+ if (!p_item) {
+ return;
+ }
+
+ QStringList files;
+ files << getFilePath(p_item);
+ g_mainWin->openFiles(files);
+}
+
+void VTagExplorer::openSelectedFileItems() const
+{
+ QStringList files;
+ QList selectedItems = m_fileList->selectedItems();
+ for (auto it : selectedItems) {
+ files << getFilePath(it);
+ }
+
+ if (!files.isEmpty()) {
+ g_mainWin->openFiles(files);
+ }
+}
+
+QString VTagExplorer::getFilePath(const QListWidgetItem *p_item) const
+{
+ return p_item->data(Qt::UserRole).toString();
+}
+
+void VTagExplorer::handleFileListContextMenuRequested(QPoint p_pos)
+{
+ QListWidgetItem *item = m_fileList->itemAt(p_pos);
+ if (!item) {
+ return;
+ }
+
+ QMenu menu(this);
+ menu.setToolTipsVisible(true);
+
+ QAction *openAct = new QAction(tr("&Open"), &menu);
+ openAct->setToolTip(tr("Open selected notes"));
+ connect(openAct, &QAction::triggered,
+ this, &VTagExplorer::openSelectedFileItems);
+ menu.addAction(openAct);
+
+ QList selectedItems = m_fileList->selectedItems();
+ if (selectedItems.size() == 1) {
+ QAction *locateAct = new QAction(VIconUtils::menuIcon(":/resources/icons/locate_note.svg"),
+ tr("&Locate To Folder"),
+ &menu);
+ locateAct->setToolTip(tr("Locate the folder of current note"));
+ connect(locateAct, &QAction::triggered,
+ this, &VTagExplorer::locateCurrentFileItem);
+ menu.addAction(locateAct);
+ }
+
+ menu.addSeparator();
+
+ QAction *addToCartAct = new QAction(VIconUtils::menuIcon(":/resources/icons/cart.svg"),
+ tr("Add To Cart"),
+ &menu);
+ addToCartAct->setToolTip(tr("Add selected notes to Cart for further processing"));
+ connect(addToCartAct, &QAction::triggered,
+ this, &VTagExplorer::addFileToCart);
+ menu.addAction(addToCartAct);
+
+ QAction *pinToHistoryAct = new QAction(VIconUtils::menuIcon(":/resources/icons/pin.svg"),
+ tr("Pin To History"),
+ &menu);
+ pinToHistoryAct->setToolTip(tr("Pin selected notes to History"));
+ connect(pinToHistoryAct, &QAction::triggered,
+ this, &VTagExplorer::pinFileToHistory);
+ menu.addAction(pinToHistoryAct);
+
+ menu.exec(m_fileList->mapToGlobal(p_pos));
+}
+
+void VTagExplorer::locateCurrentFileItem() const
+{
+ auto item = m_fileList->currentItem();
+ if (!item) {
+ return;
+ }
+
+ VFile *file = g_vnote->getInternalFile(getFilePath(item));
+ if (file) {
+ g_mainWin->locateFile(file);
+ }
+}
+
+void VTagExplorer::addFileToCart() const
+{
+ QList items = m_fileList->selectedItems();
+ VCart *cart = g_mainWin->getCart();
+
+ for (int i = 0; i < items.size(); ++i) {
+ cart->addFile(getFilePath(items[i]));
+ }
+
+ g_mainWin->showStatusMessage(tr("%1 %2 added to Cart")
+ .arg(items.size())
+ .arg(items.size() > 1 ? tr("notes") : tr("note")));
+}
+
+void VTagExplorer::pinFileToHistory() const
+{
+ QList items = m_fileList->selectedItems();
+
+ QStringList files;
+ for (int i = 0; i < items.size(); ++i) {
+ files << getFilePath(items[i]);
+ }
+
+ g_mainWin->getHistoryList()->pinFiles(files);
+
+ g_mainWin->showStatusMessage(tr("%1 %2 pinned to History")
+ .arg(items.size())
+ .arg(items.size() > 1 ? tr("notes") : tr("note")));
+}
+
+void VTagExplorer::promptToRemoveEmptyTag(const QString &p_tag)
+{
+ Q_ASSERT(!p_tag.isEmpty());
+
+ int ret = VUtils::showMessage(QMessageBox::Warning,
+ tr("Warning"),
+ tr("Empty tag detected! Do you want to remove it?"),
+ tr("The tag %2 seems not to "
+ "be assigned to any note currently.")
+ .arg(g_config->c_dataTextStyle)
+ .arg(p_tag),
+ QMessageBox::Ok | QMessageBox::Cancel,
+ QMessageBox::Cancel,
+ this,
+ MessageBoxType::Danger);
+
+ if (ret == QMessageBox::Cancel) {
+ return;
+ }
+
+ // Remove the tag from m_notebook.
+ m_notebook->removeTag(p_tag);
+ updateContent();
+}
diff --git a/src/vtagexplorer.h b/src/vtagexplorer.h
new file mode 100644
index 00000000..e2e5e03a
--- /dev/null
+++ b/src/vtagexplorer.h
@@ -0,0 +1,113 @@
+#ifndef VTAGEXPLORER_H
+#define VTAGEXPLORER_H
+
+#include
+#include
+
+#include "vsearchconfig.h"
+
+class QLabel;
+class VListWidget;
+class QListWidgetItem;
+class QSplitter;
+class VNotebook;
+class VSearch;
+
+class VTagExplorer : public QWidget
+{
+ Q_OBJECT
+public:
+ explicit VTagExplorer(QWidget *p_parent = nullptr);
+
+ void clear();
+
+ void setNotebook(VNotebook *p_notebook);
+
+ void saveStateAndGeometry();
+
+protected:
+ void showEvent(QShowEvent *p_event) Q_DECL_OVERRIDE;
+
+ void focusInEvent(QFocusEvent *p_event) Q_DECL_OVERRIDE;
+
+private slots:
+ void handleSearchItemAdded(const QSharedPointer &p_item);
+
+ void handleSearchItemsAdded(const QList > &p_items);
+
+ void handleSearchFinished(const QSharedPointer &p_result);
+
+ void openFileItem(QListWidgetItem *p_item) const;
+
+ void openSelectedFileItems() const;
+
+ void locateCurrentFileItem() const;
+
+ void addFileToCart() const;
+
+ void pinFileToHistory() const;
+
+ void handleFileListContextMenuRequested(QPoint p_pos);
+
+private:
+ void setupUI();
+
+ void updateNotebookLabel();
+
+ void updateTagLabel(const QString &p_tag);
+
+ bool tagListObsolete(const QStringList &p_tags) const;
+
+ void updateTagList(const QStringList &p_tags);
+
+ void updateContent();
+
+ // Return ture if succeeded.
+ bool activateTag(const QString &p_tag);
+
+ void addTagItem(const QString &p_tag);
+
+ void restoreStateAndGeometry();
+
+ VSearch *getVSearch() const;
+
+ void initVSearch();
+
+ void appendItemToFileList(const QSharedPointer &p_item);
+
+ QString getFilePath(const QListWidgetItem *p_item) const;
+
+ void promptToRemoveEmptyTag(const QString &p_tag);
+
+ bool m_uiInitialized;
+
+ QLabel *m_notebookLabel;
+
+ QLabel *m_tagLabel;
+
+ VListWidget *m_tagList;
+
+ VListWidget *m_fileList;
+
+ QSplitter *m_splitter;
+
+ VNotebook *m_notebook;
+
+ bool m_notebookChanged;
+
+ QIcon m_noteIcon;
+
+ VSearch *m_search;
+};
+
+inline VSearch *VTagExplorer::getVSearch() const
+{
+ if (m_search) {
+ return m_search;
+ }
+
+ const_cast(this)->initVSearch();
+ return m_search;
+}
+
+#endif // VTAGEXPLORER_H