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;
// 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",
"inplace_preview_sources" : "imagelink;codeblock;math",
"//comment" : "view mode of edit mode: editonly/editpreview",
"edit_view_mode" : "editonly"
"edit_view_mode" : "editpreview"
},
"image_host" : {
"hosts" : [

View File

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

View File

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

View File

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

View File

@ -5,10 +5,16 @@
#include <QStackedLayout>
#include <QScrollArea>
#include <QScrollBar>
#include <QDebug>
#include <QTimer>
#include <QColor>
#include <widgets/treewidget.h>
#include <widgets/lineedit.h>
#include <widgets/widgetsfactory.h>
#include <widgets/propertydefs.h>
#include <utils/widgetutils.h>
#include <core/vnotex.h>
#include "generalpage.h"
#include "miscpage.h"
@ -22,14 +28,6 @@
#include "vipage.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;
SettingsDialog::SettingsDialog(QWidget *p_parent)
@ -72,24 +70,20 @@ void SettingsDialog::setupPageExplorer(QBoxLayout *p_layout, QWidget *p_parent)
{
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->setPlaceholderText(tr("Search"));
m_searchEdit->setClearButtonEnabled(true);
layout->addWidget(m_searchEdit);
connect(m_searchEdit, &QLineEdit::textChanged,
this, [this]() { QTimer::singleShot(500, this, [this](){
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_searchTimer, QOverload<>::of(&QTimer::start));
m_pageExplorer = new TreeWidget(TreeWidget::None, p_parent);
m_pageExplorer = new TreeWidget(TreeWidget::EnhancedStyle, p_parent);
TreeWidget::setupSingleColumnHeaderlessTree(m_pageExplorer, false, false);
TreeWidget::showHorizontalScrollbar(m_pageExplorer);
m_pageExplorer->setMinimumWidth(128);
@ -276,7 +270,7 @@ bool SettingsDialog::savePages()
void SettingsDialog::forEachPage(const std::function<bool(SettingsPage *)> &p_func)
{
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)) {
break;
}
@ -300,3 +294,17 @@ QTreeWidgetItem *SettingsDialog::addSubPage(SettingsPage *p_page, QTreeWidgetIte
setupPage(subItem, p_page);
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>
class QTreeWidget;
class QStackedLayout;
class QLineEdit;
class QTreeWidgetItem;
class QScrollArea;
class QTimer;
namespace vnotex
{
class TreeWidget;
class SettingsPage;
class SettingsDialog : public Dialog
@ -50,9 +51,11 @@ namespace vnotex
QTreeWidgetItem *addSubPage(SettingsPage *p_page, QTreeWidgetItem *p_parentItem);
void search();
QLineEdit *m_searchEdit = nullptr;
QTreeWidget *m_pageExplorer = nullptr;
TreeWidget *m_pageExplorer = nullptr;
QScrollArea *m_scrollArea = nullptr;
@ -61,6 +64,8 @@ namespace vnotex
bool m_changesUnsaved = false;
bool m_ready = false;
QTimer *m_searchTimer = nullptr;
};
}

View File

@ -1,10 +1,10 @@
#include "settingspage.h"
#include "utils/widgetutils.h"
#include "../../propertydefs.h"
#include <utils/widgetutils.h>
#include <widgets/propertydefs.h>
using namespace vnotex;
SettingsPage::SettingsPage(QWidget *p_parent)
: QWidget(p_parent)
{
@ -17,21 +17,35 @@ SettingsPage::~SettingsPage()
bool SettingsPage::search(const QString &p_key)
{
bool hit = false;
if (!p_key.isEmpty() && title().contains(p_key, Qt::CaseInsensitive)) {
hit = true;
}
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.
hit = true;
searchHit(item.m_target, true);
} else {
searchHit(item.m_target, false);
}
}
return hit;
}
void SettingsPage::searchHit(QWidget *p_target, bool hit)
void SettingsPage::searchHit(QWidget *p_target, bool p_hit)
{
Q_UNUSED(p_target);
WidgetUtils::setPropertyDynamically(p_target, PropertyDefs::c_hitSettingWidght, hit);
if (!p_target) {
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)

View File

@ -34,7 +34,7 @@ namespace vnotex
virtual bool saveInternal() = 0;
// 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);

View File

@ -26,4 +26,4 @@ const char *PropertyDefs::c_dockWidgetIndex = "DockIndex";
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_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;
static QBrush s_highlightForeground;
static QBrush s_highlightBackground;
private:
void initialize();
@ -82,10 +86,6 @@ namespace vnotex
QTextDocument *m_document = 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]);
}
}
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);
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 showHorizontalScrollbar(QTreeWidget *p_tree);
@ -35,6 +39,9 @@ namespace vnotex
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:
// Emit when single item is selected and Drag&Drop to move internally.
void itemMoved(QTreeWidgetItem *p_item);
@ -55,6 +62,10 @@ namespace vnotex
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;
};