Settings: refine searching

This commit is contained in:
Le Tan 2021-12-10 20:34:07 +08:00
parent 301dace730
commit f50a834ae7
14 changed files with 133 additions and 45 deletions

View File

@ -241,7 +241,7 @@ namespace vnotex
InplacePreviewSources m_inplacePreviewSources = InplacePreviewSource::NoInplacePreview; InplacePreviewSources m_inplacePreviewSources = InplacePreviewSource::NoInplacePreview;
// View mode in edit mode. // View mode in edit mode.
EditViewMode m_editViewMode = EditViewMode::EditOnly; EditViewMode m_editViewMode = EditViewMode::EditPreview;
}; };
} }

View File

@ -360,7 +360,7 @@
"//comment" : "imagelink/codeblock/math", "//comment" : "imagelink/codeblock/math",
"inplace_preview_sources" : "imagelink;codeblock;math", "inplace_preview_sources" : "imagelink;codeblock;math",
"//comment" : "view mode of edit mode: editonly/editpreview", "//comment" : "view mode of edit mode: editonly/editpreview",
"edit_view_mode" : "editonly" "edit_view_mode" : "editpreview"
}, },
"image_host" : { "image_host" : {
"hosts" : [ "hosts" : [

View File

@ -18,6 +18,10 @@ QWidget[DialogCentralWidget="true"] {
border: none; border: none;
} }
QWidget[HitSettingWidget="true"] {
border: 2px solid @widgets#qwidget#info#border;
}
/* All widgets */ /* All widgets */
*[State="info"] { *[State="info"] {
border: 1px solid @widgets#qwidget#info#border; border: 1px solid @widgets#qwidget#info#border;

View File

@ -8,6 +8,10 @@
* - $2px: 2 will be scaled by multiplying current display scaled factor. * - $2px: 2 will be scaled by multiplying current display scaled factor.
*/ */
QWidget[HitSettingWidget="true"] {
border: 2px solid @base#info#fg;
}
/* All widgets */ /* All widgets */
*[State="info"] { *[State="info"] {
border: 1px solid @base#info#fg; border: 1px solid @base#info#fg;

View File

@ -18,6 +18,10 @@ QWidget[DialogCentralWidget="true"] {
border: none; border: none;
} }
QWidget[HitSettingWidget="true"] {
border: 2px solid @widgets#qwidget#info#border;
}
/* All widgets */ /* All widgets */
*[State="info"] { *[State="info"] {
border: 1px solid @widgets#qwidget#info#border; border: 1px solid @widgets#qwidget#info#border;
@ -31,10 +35,6 @@ QWidget[DialogCentralWidget="true"] {
border: 1px solid @widgets#qwidget#error#border; border: 1px solid @widgets#qwidget#error#border;
} }
[HitSettingWidget="true"] {
border: 4px solid @widgets#qwidget#info#border;
}
/* QAbstractScrollArea */ /* QAbstractScrollArea */
QAbstractScrollArea { QAbstractScrollArea {
border: 1px solid @widgets#qabstractscrollarea#border; border: 1px solid @widgets#qabstractscrollarea#border;

View File

@ -5,10 +5,16 @@
#include <QStackedLayout> #include <QStackedLayout>
#include <QScrollArea> #include <QScrollArea>
#include <QScrollBar> #include <QScrollBar>
#include <QDebug>
#include <QTimer>
#include <QColor>
#include <widgets/treewidget.h> #include <widgets/treewidget.h>
#include <widgets/lineedit.h> #include <widgets/lineedit.h>
#include <widgets/widgetsfactory.h> #include <widgets/widgetsfactory.h>
#include <widgets/propertydefs.h>
#include <utils/widgetutils.h>
#include <core/vnotex.h>
#include "generalpage.h" #include "generalpage.h"
#include "miscpage.h" #include "miscpage.h"
@ -22,14 +28,6 @@
#include "vipage.h" #include "vipage.h"
#include "notemanagementpage.h" #include "notemanagementpage.h"
#include <QDebug>
#include <QTimer>
#include <QColor>
#include "settingspage.h"
#include "utils/widgetutils.h"
#include "../../propertydefs.h"
#include <core/vnotex.h>
using namespace vnotex; using namespace vnotex;
SettingsDialog::SettingsDialog(QWidget *p_parent) SettingsDialog::SettingsDialog(QWidget *p_parent)
@ -72,24 +70,20 @@ void SettingsDialog::setupPageExplorer(QBoxLayout *p_layout, QWidget *p_parent)
{ {
auto layout = new QVBoxLayout(); auto layout = new QVBoxLayout();
m_searchTimer = new QTimer(this);
m_searchTimer->setSingleShot(true);
m_searchTimer->setInterval(500);
connect(m_searchTimer, &QTimer::timeout,
this, &SettingsDialog::search);
m_searchEdit = WidgetsFactory::createLineEdit(p_parent); m_searchEdit = WidgetsFactory::createLineEdit(p_parent);
m_searchEdit->setPlaceholderText(tr("Search")); m_searchEdit->setPlaceholderText(tr("Search"));
m_searchEdit->setClearButtonEnabled(true);
layout->addWidget(m_searchEdit); layout->addWidget(m_searchEdit);
connect(m_searchEdit, &QLineEdit::textChanged, connect(m_searchEdit, &QLineEdit::textChanged,
this, [this]() { QTimer::singleShot(500, this, [this](){ m_searchTimer, QOverload<>::of(&QTimer::start));
forEachPage([this](SettingsPage *p_page) {
bool hit = p_page->search(m_searchEdit->text());
if (hit) {
qDebug() << p_page->title();
// 目前只能找到tree的 通过 外观 笔记管理快速访问与编辑器好像没有加入到tree的搜索中
// 不知道如何找到item并且高亮
}
return hit;
});
});
});
m_pageExplorer = new TreeWidget(TreeWidget::None, p_parent); m_pageExplorer = new TreeWidget(TreeWidget::EnhancedStyle, p_parent);
TreeWidget::setupSingleColumnHeaderlessTree(m_pageExplorer, false, false); TreeWidget::setupSingleColumnHeaderlessTree(m_pageExplorer, false, false);
TreeWidget::showHorizontalScrollbar(m_pageExplorer); TreeWidget::showHorizontalScrollbar(m_pageExplorer);
m_pageExplorer->setMinimumWidth(128); m_pageExplorer->setMinimumWidth(128);
@ -276,7 +270,7 @@ bool SettingsDialog::savePages()
void SettingsDialog::forEachPage(const std::function<bool(SettingsPage *)> &p_func) void SettingsDialog::forEachPage(const std::function<bool(SettingsPage *)> &p_func)
{ {
for (int i = 0; i < m_pageLayout->count(); ++i) { for (int i = 0; i < m_pageLayout->count(); ++i) {
auto page = dynamic_cast<SettingsPage *>(m_pageLayout->widget(i)); auto page = static_cast<SettingsPage *>(m_pageLayout->widget(i));
if (!p_func(page)) { if (!p_func(page)) {
break; break;
} }
@ -300,3 +294,17 @@ QTreeWidgetItem *SettingsDialog::addSubPage(SettingsPage *p_page, QTreeWidgetIte
setupPage(subItem, p_page); setupPage(subItem, p_page);
return subItem; return subItem;
} }
void SettingsDialog::search()
{
auto keywords = m_searchEdit->text().trimmed();
TreeWidget::forEachItem(m_pageExplorer, [this, keywords](QTreeWidgetItem *item) {
auto page = itemPage(item);
if (page->search(keywords)) {
m_pageExplorer->mark(item, 0);
} else {
m_pageExplorer->unmark(item, 0);
}
return true;
});
}

View File

@ -5,14 +5,15 @@
#include <functional> #include <functional>
class QTreeWidget;
class QStackedLayout; class QStackedLayout;
class QLineEdit; class QLineEdit;
class QTreeWidgetItem; class QTreeWidgetItem;
class QScrollArea; class QScrollArea;
class QTimer;
namespace vnotex namespace vnotex
{ {
class TreeWidget;
class SettingsPage; class SettingsPage;
class SettingsDialog : public Dialog class SettingsDialog : public Dialog
@ -50,9 +51,11 @@ namespace vnotex
QTreeWidgetItem *addSubPage(SettingsPage *p_page, QTreeWidgetItem *p_parentItem); QTreeWidgetItem *addSubPage(SettingsPage *p_page, QTreeWidgetItem *p_parentItem);
void search();
QLineEdit *m_searchEdit = nullptr; QLineEdit *m_searchEdit = nullptr;
QTreeWidget *m_pageExplorer = nullptr; TreeWidget *m_pageExplorer = nullptr;
QScrollArea *m_scrollArea = nullptr; QScrollArea *m_scrollArea = nullptr;
@ -61,6 +64,8 @@ namespace vnotex
bool m_changesUnsaved = false; bool m_changesUnsaved = false;
bool m_ready = false; bool m_ready = false;
QTimer *m_searchTimer = nullptr;
}; };
} }

View File

@ -1,10 +1,10 @@
#include "settingspage.h" #include "settingspage.h"
#include "utils/widgetutils.h"
#include "../../propertydefs.h" #include <utils/widgetutils.h>
#include <widgets/propertydefs.h>
using namespace vnotex; using namespace vnotex;
SettingsPage::SettingsPage(QWidget *p_parent) SettingsPage::SettingsPage(QWidget *p_parent)
: QWidget(p_parent) : QWidget(p_parent)
{ {
@ -17,21 +17,35 @@ SettingsPage::~SettingsPage()
bool SettingsPage::search(const QString &p_key) bool SettingsPage::search(const QString &p_key)
{ {
bool hit = false; bool hit = false;
if (!p_key.isEmpty() && title().contains(p_key, Qt::CaseInsensitive)) {
hit = true;
}
for (const auto& item : m_searchItems) { for (const auto& item : m_searchItems) {
if (item.m_words.contains(p_key, Qt::CaseInsensitive)) { if (!p_key.isEmpty() && item.m_words.contains(p_key, Qt::CaseInsensitive)) {
// Continue to search all the matched targets. // Continue to search all the matched targets.
hit = true; hit = true;
searchHit(item.m_target, true); searchHit(item.m_target, true);
} else {
searchHit(item.m_target, false);
} }
} }
return hit; return hit;
} }
void SettingsPage::searchHit(QWidget *p_target, bool hit) void SettingsPage::searchHit(QWidget *p_target, bool p_hit)
{ {
Q_UNUSED(p_target); if (!p_target) {
WidgetUtils::setPropertyDynamically(p_target, PropertyDefs::c_hitSettingWidght, hit); return;
}
if (p_target->property(PropertyDefs::c_hitSettingWidget).toBool() == p_hit) {
return;
}
WidgetUtils::setPropertyDynamically(p_target, PropertyDefs::c_hitSettingWidget, p_hit);
} }
void SettingsPage::addSearchItem(const QString &p_words, QWidget *p_target) void SettingsPage::addSearchItem(const QString &p_words, QWidget *p_target)

View File

@ -34,7 +34,7 @@ namespace vnotex
virtual bool saveInternal() = 0; virtual bool saveInternal() = 0;
// Subclass could override this method to highlight matched target. // Subclass could override this method to highlight matched target.
virtual void searchHit(QWidget *p_target, bool hit); virtual void searchHit(QWidget *p_target, bool p_hit);
void addSearchItem(const QString &p_words, QWidget *p_target); void addSearchItem(const QString &p_words, QWidget *p_target);

View File

@ -26,4 +26,4 @@ const char *PropertyDefs::c_dockWidgetIndex = "DockIndex";
const char *PropertyDefs::c_dockWidgetTitle = "DockTitle"; const char *PropertyDefs::c_dockWidgetTitle = "DockTitle";
const char *PropertyDefs::c_hitSettingWidght = "HitSettingWidget"; const char *PropertyDefs::c_hitSettingWidget = "HitSettingWidget";

View File

@ -34,7 +34,7 @@ namespace vnotex
static const char *c_dockWidgetTitle; static const char *c_dockWidgetTitle;
static const char *c_hitSettingWidght; static const char *c_hitSettingWidget;
}; };
} }

View File

@ -67,6 +67,10 @@ namespace vnotex
QSize sizeHint(const QStyleOptionViewItem &p_option, const QModelIndex &p_index) const Q_DECL_OVERRIDE; QSize sizeHint(const QStyleOptionViewItem &p_option, const QModelIndex &p_index) const Q_DECL_OVERRIDE;
static QBrush s_highlightForeground;
static QBrush s_highlightBackground;
private: private:
void initialize(); void initialize();
@ -82,10 +86,6 @@ namespace vnotex
QTextDocument *m_document = nullptr; QTextDocument *m_document = nullptr;
SimpleSegmentHighlighter *m_highlighter = nullptr; SimpleSegmentHighlighter *m_highlighter = nullptr;
static QBrush s_highlightForeground;
static QBrush s_highlightBackground;
}; };
} }

View File

@ -223,3 +223,45 @@ void TreeWidget::dropEvent(QDropEvent *p_event)
emit itemMoved(dragItems[0]); emit itemMoved(dragItems[0]);
} }
} }
void TreeWidget::forEachItem(const QTreeWidget *p_widget, const std::function<bool(QTreeWidgetItem *p_item)> &p_func)
{
const int cnt = p_widget->topLevelItemCount();
for (int i = 0; i < cnt; ++i) {
if (!forEachItem(p_widget->topLevelItem(i), p_func)) {
break;
}
}
}
bool TreeWidget::forEachItem(QTreeWidgetItem *p_item, const std::function<bool(QTreeWidgetItem *p_item)> &p_func)
{
if (!p_item) {
return true;
}
if (!p_func(p_item)) {
return false;
}
const int cnt = p_item->childCount();
for (int i = 0; i < cnt; ++i) {
if (!forEachItem(p_item->child(i), p_func)) {
return false;
}
}
return true;
}
void TreeWidget::mark(QTreeWidgetItem *p_item, int p_column)
{
p_item->setData(p_column, Qt::ForegroundRole, StyledItemDelegate::s_highlightForeground);
p_item->setData(p_column, Qt::BackgroundRole, StyledItemDelegate::s_highlightBackground);
}
void TreeWidget::unmark(QTreeWidgetItem *p_item, int p_column)
{
p_item->setData(p_column, Qt::ForegroundRole, QVariant());
p_item->setData(p_column, Qt::BackgroundRole, QVariant());
}

View File

@ -22,6 +22,10 @@ namespace vnotex
TreeWidget(TreeWidget::Flags p_flags, QWidget *p_parent = nullptr); TreeWidget(TreeWidget::Flags p_flags, QWidget *p_parent = nullptr);
void mark(QTreeWidgetItem *p_item, int p_column);
void unmark(QTreeWidgetItem *p_item, int p_column);
static void setupSingleColumnHeaderlessTree(QTreeWidget *p_widget, bool p_contextMenu, bool p_extendedSelection); static void setupSingleColumnHeaderlessTree(QTreeWidget *p_widget, bool p_contextMenu, bool p_extendedSelection);
static void showHorizontalScrollbar(QTreeWidget *p_tree); static void showHorizontalScrollbar(QTreeWidget *p_tree);
@ -35,6 +39,9 @@ namespace vnotex
static QVector<QTreeWidgetItem *> getVisibleItems(const QTreeWidget *p_widget); static QVector<QTreeWidgetItem *> getVisibleItems(const QTreeWidget *p_widget);
// @p_func: return false to abort the iteration.
static void forEachItem(const QTreeWidget *p_widget, const std::function<bool(QTreeWidgetItem *p_item)> &p_func);
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);
@ -55,6 +62,10 @@ namespace vnotex
static QTreeWidgetItem *lastItemOfTree(QTreeWidgetItem *p_item); static QTreeWidgetItem *lastItemOfTree(QTreeWidgetItem *p_item);
// @p_func: return false to abort the iteration.
// Return false to abort the ieration.
static bool forEachItem(QTreeWidgetItem *p_item, const std::function<bool(QTreeWidgetItem *p_item)> &p_func);
Flags m_flags = Flag::None; Flags m_flags = Flag::None;
}; };