mirror of
https://gitee.com/vnotex/vnote.git
synced 2025-07-05 05:49:53 +08:00
LocationList: fix the recently introduced regression when highlighting segments of text
This commit is contained in:
parent
5ba425ae95
commit
9cf015a676
@ -133,6 +133,8 @@ namespace vnotex
|
|||||||
int m_length = -1;
|
int m_length = -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE(Segment);
|
||||||
|
|
||||||
} // ns vnotex
|
} // ns vnotex
|
||||||
|
|
||||||
Q_DECLARE_OPERATORS_FOR_FLAGS(vnotex::FindOptions);
|
Q_DECLARE_OPERATORS_FOR_FLAGS(vnotex::FindOptions);
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "vnotex.h"
|
#include "vnotex.h"
|
||||||
#include "notebookmgr.h"
|
#include "notebookmgr.h"
|
||||||
#include <notebook/notebook.h>
|
#include <notebook/notebook.h>
|
||||||
|
#include <notebookbackend/inotebookbackend.h>
|
||||||
|
|
||||||
using namespace vnotex;
|
using namespace vnotex;
|
||||||
|
|
||||||
@ -59,9 +60,11 @@ void HistoryMgr::loadHistory()
|
|||||||
const auto ¬ebooks = VNoteX::getInst().getNotebookMgr().getNotebooks();
|
const auto ¬ebooks = VNoteX::getInst().getNotebookMgr().getNotebooks();
|
||||||
for (const auto &nb : notebooks) {
|
for (const auto &nb : notebooks) {
|
||||||
const auto &history = nb->getHistory();
|
const auto &history = nb->getHistory();
|
||||||
|
const auto &backend = nb->getBackend();
|
||||||
for (const auto &item : history) {
|
for (const auto &item : history) {
|
||||||
auto fullItem = QSharedPointer<HistoryItemFull>::create();
|
auto fullItem = QSharedPointer<HistoryItemFull>::create();
|
||||||
fullItem->m_item = item;
|
fullItem->m_item = item;
|
||||||
|
fullItem->m_item.m_path = backend->getFullPath(item.m_path);
|
||||||
fullItem->m_notebookName = nb->getName();
|
fullItem->m_notebookName = nb->getName();
|
||||||
m_history.push_back(fullItem);
|
m_history.push_back(fullItem);
|
||||||
}
|
}
|
||||||
|
@ -96,8 +96,8 @@ namespace vnotex
|
|||||||
auto arr = read(p_default, p_user, p_key).toArray();
|
auto arr = read(p_default, p_user, p_key).toArray();
|
||||||
QStringList res;
|
QStringList res;
|
||||||
res.reserve(arr.size());
|
res.reserve(arr.size());
|
||||||
for (const auto &ele : arr) {
|
for (int i = 0; i < arr.size(); ++i) {
|
||||||
res.push_back(ele.toString());
|
res.push_back(arr[i].toString());
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@ -108,8 +108,8 @@ namespace vnotex
|
|||||||
auto arr = p_obj.value(p_key).toArray();
|
auto arr = p_obj.value(p_key).toArray();
|
||||||
QStringList res;
|
QStringList res;
|
||||||
res.reserve(arr.size());
|
res.reserve(arr.size());
|
||||||
for (const auto &ele : arr) {
|
for (int i = 0; i < arr.size(); ++i) {
|
||||||
res.push_back(ele.toString());
|
res.push_back(arr[i].toString());
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,7 @@ namespace vnotex
|
|||||||
{
|
{
|
||||||
Line() = default;
|
Line() = default;
|
||||||
|
|
||||||
Line(int p_lineNumber, const QString &p_text, const QVector<Segment> &p_segments)
|
Line(int p_lineNumber, const QString &p_text, const QList<Segment> &p_segments)
|
||||||
: m_lineNumber(p_lineNumber),
|
: m_lineNumber(p_lineNumber),
|
||||||
m_text(p_text),
|
m_text(p_text),
|
||||||
m_segments(p_segments)
|
m_segments(p_segments)
|
||||||
@ -51,10 +51,10 @@ namespace vnotex
|
|||||||
|
|
||||||
QString m_text;
|
QString m_text;
|
||||||
|
|
||||||
QVector<Segment> m_segments;
|
QList<Segment> m_segments;
|
||||||
};
|
};
|
||||||
|
|
||||||
void addLine(int p_lineNumber, const QString &p_text, const QVector<Segment> &p_segments)
|
void addLine(int p_lineNumber, const QString &p_text, const QList<Segment> &p_segments)
|
||||||
{
|
{
|
||||||
m_lines.push_back(Line(p_lineNumber, p_text, p_segments));
|
m_lines.push_back(Line(p_lineNumber, p_text, p_segments));
|
||||||
}
|
}
|
||||||
|
@ -70,7 +70,7 @@ void BundleNotebook::addHistory(const HistoryItem &p_item)
|
|||||||
{
|
{
|
||||||
HistoryItem item(p_item);
|
HistoryItem item(p_item);
|
||||||
item.m_path = getBackend()->getRelativePath(item.m_path);
|
item.m_path = getBackend()->getRelativePath(item.m_path);
|
||||||
HistoryMgr::insertHistoryItem(m_history, p_item);
|
HistoryMgr::insertHistoryItem(m_history, item);
|
||||||
|
|
||||||
updateNotebookConfig();
|
updateNotebookConfig();
|
||||||
}
|
}
|
||||||
|
@ -236,10 +236,6 @@
|
|||||||
"locationlist" : {
|
"locationlist" : {
|
||||||
"node_icon" : {
|
"node_icon" : {
|
||||||
"fg" : "@base#icon#fg"
|
"fg" : "@base#icon#fg"
|
||||||
},
|
|
||||||
"text_highlight" : {
|
|
||||||
"fg" : "@base#master#fg",
|
|
||||||
"bg" : "@base#master#bg"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"viewsplit" : {
|
"viewsplit" : {
|
||||||
@ -621,6 +617,16 @@
|
|||||||
"fg" : "@palette#bg2_9",
|
"fg" : "@palette#bg2_9",
|
||||||
"border" : "@palette#bg2_9"
|
"border" : "@palette#bg2_9"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"styleditemdelegate" : {
|
||||||
|
"separator" : {
|
||||||
|
"fg" : "@base#normal#fg",
|
||||||
|
"bg" : "@widgets#separator#bg"
|
||||||
|
},
|
||||||
|
"highlight" : {
|
||||||
|
"fg" : "@base#master#fg",
|
||||||
|
"bg" : "@base#master#bg"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -99,10 +99,6 @@
|
|||||||
"locationlist" : {
|
"locationlist" : {
|
||||||
"node_icon" : {
|
"node_icon" : {
|
||||||
"fg" : "@base#icon#fg"
|
"fg" : "@base#icon#fg"
|
||||||
},
|
|
||||||
"text_highlight" : {
|
|
||||||
"fg" : "@base#master#fg",
|
|
||||||
"bg" : "@base#master#bg"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"viewsplit" : {
|
"viewsplit" : {
|
||||||
@ -134,6 +130,16 @@
|
|||||||
"fg" : "@base#master#bg",
|
"fg" : "@base#master#bg",
|
||||||
"border" : "@base#master#bg"
|
"border" : "@base#master#bg"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"styleditemdelegate" : {
|
||||||
|
"separator" : {
|
||||||
|
"fg" : "@base#normal#fg",
|
||||||
|
"bg" : "@base#normal#border"
|
||||||
|
},
|
||||||
|
"highlight" : {
|
||||||
|
"fg" : "@base#master#fg",
|
||||||
|
"bg" : "@base#master#bg"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -232,10 +232,6 @@
|
|||||||
"locationlist" : {
|
"locationlist" : {
|
||||||
"node_icon" : {
|
"node_icon" : {
|
||||||
"fg" : "@base#icon#fg"
|
"fg" : "@base#icon#fg"
|
||||||
},
|
|
||||||
"text_highlight" : {
|
|
||||||
"fg" : "@base#master#fg",
|
|
||||||
"bg" : "@base#master#bg"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"viewsplit" : {
|
"viewsplit" : {
|
||||||
@ -617,6 +613,16 @@
|
|||||||
"fg" : "@base#master#bg",
|
"fg" : "@base#master#bg",
|
||||||
"border" : "@base#master#bg"
|
"border" : "@base#master#bg"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"styleditemdelegate" : {
|
||||||
|
"separator" : {
|
||||||
|
"fg" : "@base#normal#fg",
|
||||||
|
"bg" : "@widgets#separator#bg"
|
||||||
|
},
|
||||||
|
"highlight" : {
|
||||||
|
"fg" : "@base#master#fg",
|
||||||
|
"bg" : "@base#master#bg"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -97,7 +97,7 @@ void FileSearchEngineWorker::searchFile(const QString &p_filePath, const QString
|
|||||||
|
|
||||||
const auto lineText = ins.readLine();
|
const auto lineText = ins.readLine();
|
||||||
bool matched = false;
|
bool matched = false;
|
||||||
QVector<Segment> segments;
|
QList<Segment> segments;
|
||||||
if (!shouldStartBatchMode) {
|
if (!shouldStartBatchMode) {
|
||||||
matched = m_token.matched(lineText, &segments);
|
matched = m_token.matched(lineText, &segments);
|
||||||
} else {
|
} else {
|
||||||
@ -172,6 +172,9 @@ void FileSearchEngine::search(const QSharedPointer<SearchOption> &p_option,
|
|||||||
const int step = totalSize / numThread;
|
const int step = totalSize / numThread;
|
||||||
int remain = totalSize % numThread;
|
int remain = totalSize % numThread;
|
||||||
int start = 0;
|
int start = 0;
|
||||||
|
|
||||||
|
qDebug() << "start async file search" << totalSize << numThread;
|
||||||
|
|
||||||
for (int i = 0; i < numThread && start < totalSize; ++i) {
|
for (int i = 0; i < numThread && start < totalSize; ++i) {
|
||||||
int len = step;
|
int len = step;
|
||||||
if (remain) {
|
if (remain) {
|
||||||
|
@ -294,7 +294,7 @@ bool Searcher::searchContent(const File *p_file)
|
|||||||
if (idx > pos) {
|
if (idx > pos) {
|
||||||
QString lineText = content.mid(pos, idx - pos);
|
QString lineText = content.mid(pos, idx - pos);
|
||||||
bool matched = false;
|
bool matched = false;
|
||||||
QVector<Segment> segments;
|
QList<Segment> segments;
|
||||||
if (!shouldStartBatchMode) {
|
if (!shouldStartBatchMode) {
|
||||||
matched = m_token.matched(lineText, &segments);
|
matched = m_token.matched(lineText, &segments);
|
||||||
} else {
|
} else {
|
||||||
@ -480,17 +480,21 @@ bool Searcher::firstPhaseSearch(Notebook *p_notebook, QVector<SearchSecondPhaseI
|
|||||||
bool Searcher::secondPhaseSearch(const QVector<SearchSecondPhaseItem> &p_secondPhaseItems)
|
bool Searcher::secondPhaseSearch(const QVector<SearchSecondPhaseItem> &p_secondPhaseItems)
|
||||||
{
|
{
|
||||||
Q_ASSERT(!p_secondPhaseItems.isEmpty());
|
Q_ASSERT(!p_secondPhaseItems.isEmpty());
|
||||||
|
|
||||||
|
emit logRequested(tr("Start second-phase search: %n files(s)", "", p_secondPhaseItems.size()));
|
||||||
qDebug() << "secondPhaseSearch" << p_secondPhaseItems.size();
|
qDebug() << "secondPhaseSearch" << p_secondPhaseItems.size();
|
||||||
|
|
||||||
createSearchEngine();
|
createSearchEngine();
|
||||||
|
|
||||||
m_engine->search(m_option, m_token, p_secondPhaseItems);
|
|
||||||
connect(m_engine.data(), &ISearchEngine::finished,
|
connect(m_engine.data(), &ISearchEngine::finished,
|
||||||
this, &Searcher::finished);
|
this, &Searcher::finished);
|
||||||
connect(m_engine.data(), &ISearchEngine::logRequested,
|
connect(m_engine.data(), &ISearchEngine::logRequested,
|
||||||
this, &Searcher::logRequested);
|
this, &Searcher::logRequested);
|
||||||
connect(m_engine.data(), &ISearchEngine::resultItemsAdded,
|
connect(m_engine.data(), &ISearchEngine::resultItemsAdded,
|
||||||
this, &Searcher::resultItemsAdded);
|
this, &Searcher::resultItemsAdded);
|
||||||
|
|
||||||
|
m_engine->search(m_option, m_token, p_secondPhaseItems);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ QSharedPointer<SearchResultItem> SearchResultItem::createBufferItem(const QStrin
|
|||||||
const QString &p_displayPath,
|
const QString &p_displayPath,
|
||||||
int p_lineNumber,
|
int p_lineNumber,
|
||||||
const QString &p_text,
|
const QString &p_text,
|
||||||
const QVector<Segment> &p_segments)
|
const QList<Segment> &p_segments)
|
||||||
{
|
{
|
||||||
auto item = createBufferItem(p_targetPath, p_displayPath);
|
auto item = createBufferItem(p_targetPath, p_displayPath);
|
||||||
item->m_location.addLine(p_lineNumber, p_text, p_segments);
|
item->m_location.addLine(p_lineNumber, p_text, p_segments);
|
||||||
@ -27,7 +27,7 @@ QSharedPointer<SearchResultItem> SearchResultItem::createFileItem(const QString
|
|||||||
const QString &p_displayPath,
|
const QString &p_displayPath,
|
||||||
int p_lineNumber,
|
int p_lineNumber,
|
||||||
const QString &p_text,
|
const QString &p_text,
|
||||||
const QVector<Segment> &p_segments)
|
const QList<Segment> &p_segments)
|
||||||
{
|
{
|
||||||
auto item = createFileItem(p_targetPath, p_displayPath);
|
auto item = createFileItem(p_targetPath, p_displayPath);
|
||||||
item->m_location.addLine(p_lineNumber, p_text, p_segments);
|
item->m_location.addLine(p_lineNumber, p_text, p_segments);
|
||||||
@ -64,7 +64,7 @@ QSharedPointer<SearchResultItem> SearchResultItem::createNotebookItem(const QStr
|
|||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SearchResultItem::addLine(int p_lineNumber, const QString &p_text, const QVector<Segment> &p_segments)
|
void SearchResultItem::addLine(int p_lineNumber, const QString &p_text, const QList<Segment> &p_segments)
|
||||||
{
|
{
|
||||||
m_location.addLine(p_lineNumber, p_text, p_segments);
|
m_location.addLine(p_lineNumber, p_text, p_segments);
|
||||||
}
|
}
|
||||||
|
@ -17,13 +17,13 @@ namespace vnotex
|
|||||||
return p_dbg;
|
return p_dbg;
|
||||||
}
|
}
|
||||||
|
|
||||||
void addLine(int p_lineNumber, const QString &p_text, const QVector<Segment> &p_segments);
|
void addLine(int p_lineNumber, const QString &p_text, const QList<Segment> &p_segments);
|
||||||
|
|
||||||
static QSharedPointer<SearchResultItem> createBufferItem(const QString &p_targetPath,
|
static QSharedPointer<SearchResultItem> createBufferItem(const QString &p_targetPath,
|
||||||
const QString &p_displayPath,
|
const QString &p_displayPath,
|
||||||
int p_lineNumber,
|
int p_lineNumber,
|
||||||
const QString &p_text,
|
const QString &p_text,
|
||||||
const QVector<Segment> &p_segments);
|
const QList<Segment> &p_segments);
|
||||||
|
|
||||||
static QSharedPointer<SearchResultItem> createBufferItem(const QString &p_targetPath,
|
static QSharedPointer<SearchResultItem> createBufferItem(const QString &p_targetPath,
|
||||||
const QString &p_displayPath);
|
const QString &p_displayPath);
|
||||||
@ -32,7 +32,7 @@ namespace vnotex
|
|||||||
const QString &p_displayPath,
|
const QString &p_displayPath,
|
||||||
int p_lineNumber,
|
int p_lineNumber,
|
||||||
const QString &p_text,
|
const QString &p_text,
|
||||||
const QVector<Segment> &p_segments);
|
const QList<Segment> &p_segments);
|
||||||
|
|
||||||
static QSharedPointer<SearchResultItem> createFileItem(const QString &p_targetPath,
|
static QSharedPointer<SearchResultItem> createFileItem(const QString &p_targetPath,
|
||||||
const QString &p_displayPath);
|
const QString &p_displayPath);
|
||||||
|
@ -31,7 +31,7 @@ void SearchToken::append(const QRegularExpression &p_regExp)
|
|||||||
m_regularExpressions.append(p_regExp);
|
m_regularExpressions.append(p_regExp);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SearchToken::matched(const QString &p_text, QVector<Segment> *p_segments) const
|
bool SearchToken::matched(const QString &p_text, QList<Segment> *p_segments) const
|
||||||
{
|
{
|
||||||
const int consSize = constraintSize();
|
const int consSize = constraintSize();
|
||||||
if (consSize == 0) {
|
if (consSize == 0) {
|
||||||
@ -90,7 +90,7 @@ void SearchToken::startBatchMode()
|
|||||||
m_matchedConstraintsCountInBatchMode = 0;
|
m_matchedConstraintsCountInBatchMode = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SearchToken::matchedInBatchMode(const QString &p_text, QVector<Segment> *p_segments)
|
bool SearchToken::matchedInBatchMode(const QString &p_text, QList<Segment> *p_segments)
|
||||||
{
|
{
|
||||||
bool isMatched = false;
|
bool isMatched = false;
|
||||||
const int consSize = m_matchedConstraintsInBatchMode.size();
|
const int consSize = m_matchedConstraintsInBatchMode.size();
|
||||||
|
@ -35,7 +35,7 @@ namespace vnotex
|
|||||||
void append(const QRegularExpression &p_regExp);
|
void append(const QRegularExpression &p_regExp);
|
||||||
|
|
||||||
// Whether @p_text is matched.
|
// Whether @p_text is matched.
|
||||||
bool matched(const QString &p_text, QVector<Segment> *p_segments = nullptr) const;
|
bool matched(const QString &p_text, QList<Segment> *p_segments = nullptr) const;
|
||||||
|
|
||||||
int constraintSize() const;
|
int constraintSize() const;
|
||||||
|
|
||||||
@ -48,7 +48,7 @@ namespace vnotex
|
|||||||
|
|
||||||
// Match one string in batch mode.
|
// Match one string in batch mode.
|
||||||
// Return true if @p_text is matched.
|
// Return true if @p_text is matched.
|
||||||
bool matchedInBatchMode(const QString &p_text, QVector<Segment> *p_segments = nullptr);
|
bool matchedInBatchMode(const QString &p_text, QList<Segment> *p_segments = nullptr);
|
||||||
|
|
||||||
bool readyToEndBatchMode() const;
|
bool readyToEndBatchMode() const;
|
||||||
|
|
||||||
|
@ -118,21 +118,6 @@ void SelectDialog::keyPressEvent(QKeyEvent *p_event)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// On Mac OS X, it is `Command+O` to activate an item, instead of Return.
|
|
||||||
#if defined(Q_OS_MACOS) || defined(Q_OS_MAC)
|
|
||||||
{
|
|
||||||
const int key = p_event->key();
|
|
||||||
if (key == Qt::Key_Return || key == Qt::Key_Enter) {
|
|
||||||
p_event->accept();
|
|
||||||
if (auto item = m_list->currentItem()) {
|
|
||||||
selectionChosen(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
QDialog::keyPressEvent(p_event);
|
QDialog::keyPressEvent(p_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,25 +2,26 @@
|
|||||||
|
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QHBoxLayout>
|
#include <QStackedLayout>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
using namespace vnotex;
|
using namespace vnotex;
|
||||||
|
|
||||||
StatusWidget::StatusWidget(QWidget *p_parent)
|
StatusWidget::StatusWidget(QWidget *p_parent)
|
||||||
: QWidget(p_parent)
|
: QWidget(p_parent)
|
||||||
{
|
{
|
||||||
auto layout = new QHBoxLayout(this);
|
m_mainLayout = new QStackedLayout(this);
|
||||||
layout->setContentsMargins(0, 0, 0, 0);
|
m_mainLayout->setContentsMargins(0, 0, 0, 0);
|
||||||
layout->setSpacing(0);
|
m_mainLayout->setSpacing(0);
|
||||||
|
|
||||||
m_messageLabel = new QLabel(this);
|
m_messageLabel = new QLabel(this);
|
||||||
m_messageLabel->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
|
m_messageLabel->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
|
||||||
layout->addWidget(m_messageLabel);
|
m_mainLayout->addWidget(m_messageLabel);
|
||||||
|
|
||||||
m_messageTimer = new QTimer(this);
|
m_messageTimer = new QTimer(this);
|
||||||
m_messageTimer->setSingleShot(true);
|
m_messageTimer->setSingleShot(true);
|
||||||
connect(m_messageTimer, &QTimer::timeout,
|
connect(m_messageTimer, &QTimer::timeout,
|
||||||
m_messageLabel, &QLabel::clear);
|
this, &StatusWidget::clearMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
StatusWidget::~StatusWidget()
|
StatusWidget::~StatusWidget()
|
||||||
@ -32,13 +33,42 @@ StatusWidget::~StatusWidget()
|
|||||||
|
|
||||||
void StatusWidget::showMessage(const QString &p_msg, int p_milliseconds)
|
void StatusWidget::showMessage(const QString &p_msg, int p_milliseconds)
|
||||||
{
|
{
|
||||||
|
if (p_msg.isEmpty()) {
|
||||||
|
clearMessage();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
m_messageLabel->setText(p_msg);
|
m_messageLabel->setText(p_msg);
|
||||||
|
m_mainLayout->setCurrentWidget(m_messageLabel);
|
||||||
|
|
||||||
|
if (p_milliseconds > 0) {
|
||||||
m_messageTimer->start(p_milliseconds);
|
m_messageTimer->start(p_milliseconds);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void StatusWidget::setEditorStatusWidget(const QSharedPointer<QWidget> &p_editorWidget)
|
void StatusWidget::setEditorStatusWidget(const QSharedPointer<QWidget> &p_editorWidget)
|
||||||
{
|
{
|
||||||
Q_ASSERT(!m_editorWidget);
|
Q_ASSERT(!m_editorWidget);
|
||||||
m_editorWidget = p_editorWidget;
|
m_editorWidget = p_editorWidget;
|
||||||
layout()->addWidget(m_editorWidget.data());
|
m_mainLayout->addWidget(m_editorWidget.data());
|
||||||
|
m_mainLayout->setCurrentWidget(m_editorWidget.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
void StatusWidget::resizeEvent(QResizeEvent *p_event)
|
||||||
|
{
|
||||||
|
QWidget::resizeEvent(p_event);
|
||||||
|
|
||||||
|
int maxWidth = width() - 10;
|
||||||
|
if (maxWidth <= 0) {
|
||||||
|
maxWidth = width();
|
||||||
|
}
|
||||||
|
m_messageLabel->setMaximumWidth(maxWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
void StatusWidget::clearMessage()
|
||||||
|
{
|
||||||
|
m_messageLabel->clear();
|
||||||
|
if (m_editorWidget) {
|
||||||
|
m_mainLayout->setCurrentWidget(m_editorWidget.data());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
class QLabel;
|
class QLabel;
|
||||||
class QTimer;
|
class QTimer;
|
||||||
|
class QStackedLayout;
|
||||||
|
|
||||||
namespace vnotex
|
namespace vnotex
|
||||||
{
|
{
|
||||||
@ -22,7 +23,14 @@ namespace vnotex
|
|||||||
|
|
||||||
void setEditorStatusWidget(const QSharedPointer<QWidget> &p_editorWidget);
|
void setEditorStatusWidget(const QSharedPointer<QWidget> &p_editorWidget);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void resizeEvent(QResizeEvent *p_event) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void clearMessage();
|
||||||
|
|
||||||
|
QStackedLayout *m_mainLayout = nullptr;
|
||||||
|
|
||||||
QLabel *m_messageLabel = nullptr;
|
QLabel *m_messageLabel = nullptr;
|
||||||
|
|
||||||
QTimer *m_messageTimer = nullptr;
|
QTimer *m_messageTimer = nullptr;
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
#include <core/notebookmgr.h>
|
#include <core/notebookmgr.h>
|
||||||
#include <core/fileopenparameters.h>
|
#include <core/fileopenparameters.h>
|
||||||
|
|
||||||
|
|
||||||
#include "titlebar.h"
|
#include "titlebar.h"
|
||||||
#include "listwidget.h"
|
#include "listwidget.h"
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
@ -40,7 +39,7 @@ void HistoryPanel::setupUI()
|
|||||||
mainLayout->addWidget(m_titleBar);
|
mainLayout->addWidget(m_titleBar);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_historyList = new ListWidget(this);
|
m_historyList = new ListWidget(true, this);
|
||||||
m_historyList->setContextMenuPolicy(Qt::CustomContextMenu);
|
m_historyList->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||||
m_historyList->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
m_historyList->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||||||
connect(m_historyList, &QListWidget::customContextMenuRequested,
|
connect(m_historyList, &QListWidget::customContextMenuRequested,
|
||||||
|
257
src/widgets/itemproxystyle.cpp
Normal file
257
src/widgets/itemproxystyle.cpp
Normal file
@ -0,0 +1,257 @@
|
|||||||
|
#include "itemproxystyle.h"
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QStyleOptionViewItem>
|
||||||
|
#include <QTextOption>
|
||||||
|
#include <QTextLayout>
|
||||||
|
|
||||||
|
#include "styleditemdelegate.h"
|
||||||
|
|
||||||
|
using namespace vnotex;
|
||||||
|
|
||||||
|
ItemProxyStyle::ItemProxyStyle(QStyle *p_style)
|
||||||
|
: QProxyStyle(p_style)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void ItemProxyStyle::drawControl(QStyle::ControlElement p_element,
|
||||||
|
const QStyleOption *p_option,
|
||||||
|
QPainter *p_painter,
|
||||||
|
const QWidget *p_widget) const
|
||||||
|
{
|
||||||
|
if (p_element == QStyle::CE_ItemViewItem) {
|
||||||
|
if (drawItemViewItem(p_option, p_painter, p_widget)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QProxyStyle::drawControl(p_element, p_option, p_painter, p_widget);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ItemProxyStyle::drawItemViewItem(const QStyleOption *p_option, QPainter *p_painter, const QWidget *p_widget) const
|
||||||
|
{
|
||||||
|
const QStyleOptionViewItem *vopt = qstyleoption_cast<const QStyleOptionViewItem *>(p_option);
|
||||||
|
if (!vopt) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto value = vopt->index.data(HighlightsRole);
|
||||||
|
if (!value.canConvert<QList<Segment>>()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto segments = value.value<QList<Segment>>();
|
||||||
|
if (segments.isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copied from qtbase/src/widgets/styles/qcommonstyle.cpp.
|
||||||
|
|
||||||
|
p_painter->save();
|
||||||
|
p_painter->setClipRect(vopt->rect);
|
||||||
|
QRect checkRect = proxy()->subElementRect(SE_ItemViewItemCheckIndicator, vopt, p_widget);
|
||||||
|
QRect iconRect = proxy()->subElementRect(SE_ItemViewItemDecoration, vopt, p_widget);
|
||||||
|
QRect textRect = proxy()->subElementRect(SE_ItemViewItemText, vopt, p_widget);
|
||||||
|
|
||||||
|
// Draw the background.
|
||||||
|
proxy()->drawPrimitive(PE_PanelItemViewItem, vopt, p_painter, p_widget);
|
||||||
|
|
||||||
|
// Draw the check mark.
|
||||||
|
if (vopt->features & QStyleOptionViewItem::HasCheckIndicator) {
|
||||||
|
QStyleOptionViewItem option(*vopt);
|
||||||
|
option.rect = checkRect;
|
||||||
|
option.state = option.state & ~QStyle::State_HasFocus;
|
||||||
|
switch (vopt->checkState) {
|
||||||
|
case Qt::Unchecked:
|
||||||
|
option.state |= QStyle::State_Off;
|
||||||
|
break;
|
||||||
|
case Qt::PartiallyChecked:
|
||||||
|
option.state |= QStyle::State_NoChange;
|
||||||
|
break;
|
||||||
|
case Qt::Checked:
|
||||||
|
option.state |= QStyle::State_On;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
proxy()->drawPrimitive(QStyle::PE_IndicatorItemViewItemCheck, &option, p_painter, p_widget);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw the icon.
|
||||||
|
QIcon::Mode mode = QIcon::Normal;
|
||||||
|
if (!(vopt->state & QStyle::State_Enabled)) {
|
||||||
|
mode = QIcon::Disabled;
|
||||||
|
} else if (vopt->state & QStyle::State_Selected) {
|
||||||
|
mode = QIcon::Selected;
|
||||||
|
}
|
||||||
|
QIcon::State state = vopt->state & QStyle::State_Open ? QIcon::On : QIcon::Off;
|
||||||
|
vopt->icon.paint(p_painter, iconRect, vopt->decorationAlignment, mode, state);
|
||||||
|
|
||||||
|
// Draw the text.
|
||||||
|
if (!vopt->text.isEmpty()) {
|
||||||
|
QPalette::ColorGroup cg = vopt->state & QStyle::State_Enabled ? QPalette::Normal : QPalette::Disabled;
|
||||||
|
if (cg == QPalette::Normal && !(vopt->state & QStyle::State_Active)) {
|
||||||
|
cg = QPalette::Inactive;
|
||||||
|
}
|
||||||
|
if (vopt->state & QStyle::State_Selected) {
|
||||||
|
p_painter->setPen(vopt->palette.color(cg, QPalette::HighlightedText));
|
||||||
|
} else {
|
||||||
|
p_painter->setPen(vopt->palette.color(cg, QPalette::Text));
|
||||||
|
}
|
||||||
|
if (vopt->state & QStyle::State_Editing) {
|
||||||
|
p_painter->setPen(vopt->palette.color(cg, QPalette::Text));
|
||||||
|
p_painter->drawRect(textRect.adjusted(0, 0, -1, -1));
|
||||||
|
}
|
||||||
|
|
||||||
|
viewItemDrawText(p_painter, vopt, textRect);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw the focus rect.
|
||||||
|
if (vopt->state & QStyle::State_HasFocus) {
|
||||||
|
QStyleOptionFocusRect o;
|
||||||
|
o.QStyleOption::operator=(*vopt);
|
||||||
|
o.rect = proxy()->subElementRect(SE_ItemViewItemFocusRect, vopt, p_widget);
|
||||||
|
o.state |= QStyle::State_KeyboardFocusChange;
|
||||||
|
o.state |= QStyle::State_Item;
|
||||||
|
QPalette::ColorGroup cg = (vopt->state & QStyle::State_Enabled) ? QPalette::Normal : QPalette::Disabled;
|
||||||
|
o.backgroundColor = vopt->palette.color(cg, (vopt->state & QStyle::State_Selected) ? QPalette::Highlight : QPalette::Window);
|
||||||
|
proxy()->drawPrimitive(QStyle::PE_FrameFocusRect, &o, p_painter, p_widget);
|
||||||
|
}
|
||||||
|
|
||||||
|
p_painter->restore();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static QSizeF viewItemTextLayout(QTextLayout &textLayout, int lineWidth, int maxHeight = -1, int *lastVisibleLine = nullptr)
|
||||||
|
{
|
||||||
|
if (lastVisibleLine)
|
||||||
|
*lastVisibleLine = -1;
|
||||||
|
qreal height = 0;
|
||||||
|
qreal widthUsed = 0;
|
||||||
|
textLayout.beginLayout();
|
||||||
|
int i = 0;
|
||||||
|
while (true) {
|
||||||
|
QTextLine line = textLayout.createLine();
|
||||||
|
if (!line.isValid())
|
||||||
|
break;
|
||||||
|
line.setLineWidth(lineWidth);
|
||||||
|
line.setPosition(QPointF(0, height));
|
||||||
|
height += line.height();
|
||||||
|
widthUsed = qMax(widthUsed, line.naturalTextWidth());
|
||||||
|
// we assume that the height of the next line is the same as the current one
|
||||||
|
if (maxHeight > 0 && lastVisibleLine && height + line.height() > maxHeight) {
|
||||||
|
const QTextLine nextLine = textLayout.createLine();
|
||||||
|
*lastVisibleLine = nextLine.isValid() ? i : -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
textLayout.endLayout();
|
||||||
|
return QSizeF(widthUsed, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ItemProxyStyle::viewItemDrawText(QPainter *p_painter, const QStyleOptionViewItem *p_option, const QRect &p_rect) const
|
||||||
|
{
|
||||||
|
// Copied from qtbase/src/widgets/styles/qcommonstyle.cpp.
|
||||||
|
|
||||||
|
const QWidget *widget = p_option->widget;
|
||||||
|
const int textMargin = proxy()->pixelMetric(QStyle::PM_FocusFrameHMargin, 0, widget) + 1;
|
||||||
|
// Remove width padding.
|
||||||
|
QRect textRect = p_rect.adjusted(textMargin, 0, -textMargin, 0);
|
||||||
|
const bool wrapText = p_option->features & QStyleOptionViewItem::WrapText;
|
||||||
|
QTextOption textOption;
|
||||||
|
textOption.setWrapMode(wrapText ? QTextOption::WordWrap : QTextOption::ManualWrap);
|
||||||
|
textOption.setTextDirection(p_option->direction);
|
||||||
|
textOption.setAlignment(QStyle::visualAlignment(p_option->direction, p_option->displayAlignment));
|
||||||
|
QPointF paintPosition;
|
||||||
|
const QString newText = calculateElidedText(p_option->text,
|
||||||
|
textOption,
|
||||||
|
p_option->font,
|
||||||
|
textRect,
|
||||||
|
p_option->displayAlignment,
|
||||||
|
p_option->textElideMode,
|
||||||
|
0,
|
||||||
|
true,
|
||||||
|
&paintPosition);
|
||||||
|
QTextLayout textLayout(newText, p_option->font);
|
||||||
|
textLayout.setTextOption(textOption);
|
||||||
|
viewItemTextLayout(textLayout, textRect.width());
|
||||||
|
textLayout.draw(p_painter, paintPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ItemProxyStyle::calculateElidedText(const QString &text, const QTextOption &textOption,
|
||||||
|
const QFont &font, const QRect &textRect, const Qt::Alignment valign,
|
||||||
|
Qt::TextElideMode textElideMode, int flags,
|
||||||
|
bool lastVisibleLineShouldBeElided, QPointF *paintStartPosition) const
|
||||||
|
{
|
||||||
|
// Copied from qtbase/src/widgets/styles/qcommonstyle.cpp.
|
||||||
|
|
||||||
|
QTextLayout textLayout(text, font);
|
||||||
|
textLayout.setTextOption(textOption);
|
||||||
|
// In AlignVCenter mode when more than one line is displayed and the height only allows
|
||||||
|
// some of the lines it makes no sense to display those. From a users perspective it makes
|
||||||
|
// more sense to see the start of the text instead something inbetween.
|
||||||
|
const bool vAlignmentOptimization = paintStartPosition && valign.testFlag(Qt::AlignVCenter);
|
||||||
|
int lastVisibleLine = -1;
|
||||||
|
viewItemTextLayout(textLayout, textRect.width(), vAlignmentOptimization ? textRect.height() : -1, &lastVisibleLine);
|
||||||
|
const QRectF boundingRect = textLayout.boundingRect();
|
||||||
|
// don't care about LTR/RTL here, only need the height
|
||||||
|
const QRect layoutRect = QStyle::alignedRect(Qt::LayoutDirectionAuto, valign,
|
||||||
|
boundingRect.size().toSize(), textRect);
|
||||||
|
if (paintStartPosition)
|
||||||
|
*paintStartPosition = QPointF(textRect.x(), layoutRect.top());
|
||||||
|
QString ret;
|
||||||
|
qreal height = 0;
|
||||||
|
const int lineCount = textLayout.lineCount();
|
||||||
|
for (int i = 0; i < lineCount; ++i) {
|
||||||
|
const QTextLine line = textLayout.lineAt(i);
|
||||||
|
height += line.height();
|
||||||
|
// above visible rect
|
||||||
|
if (height + layoutRect.top() <= textRect.top()) {
|
||||||
|
if (paintStartPosition)
|
||||||
|
paintStartPosition->ry() += line.height();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const int start = line.textStart();
|
||||||
|
const int length = line.textLength();
|
||||||
|
const bool drawElided = line.naturalTextWidth() > textRect.width();
|
||||||
|
bool elideLastVisibleLine = lastVisibleLine == i;
|
||||||
|
if (!drawElided && i + 1 < lineCount && lastVisibleLineShouldBeElided) {
|
||||||
|
const QTextLine nextLine = textLayout.lineAt(i + 1);
|
||||||
|
const int nextHeight = height + nextLine.height() / 2;
|
||||||
|
// elide when less than the next half line is visible
|
||||||
|
if (nextHeight + layoutRect.top() > textRect.height() + textRect.top())
|
||||||
|
elideLastVisibleLine = true;
|
||||||
|
}
|
||||||
|
QString text = textLayout.text().mid(start, length);
|
||||||
|
if (drawElided || elideLastVisibleLine) {
|
||||||
|
Q_ASSERT(false);
|
||||||
|
if (elideLastVisibleLine) {
|
||||||
|
if (text.endsWith(QChar::LineSeparator))
|
||||||
|
text.chop(1);
|
||||||
|
text += QChar(0x2026);
|
||||||
|
}
|
||||||
|
/* TODO: QStackTextEngine is a private class.
|
||||||
|
const QStackTextEngine engine(text, font);
|
||||||
|
ret += engine.elidedText(textElideMode, textRect.width(), flags);
|
||||||
|
*/
|
||||||
|
Q_UNUSED(flags);
|
||||||
|
Q_UNUSED(textElideMode);
|
||||||
|
ret += text;
|
||||||
|
// no newline for the last line (last visible or real)
|
||||||
|
// sometimes drawElided is true but no eliding is done so the text ends
|
||||||
|
// with QChar::LineSeparator - don't add another one. This happened with
|
||||||
|
// arabic text in the testcase for QTBUG-72805
|
||||||
|
if (i < lineCount - 1 &&
|
||||||
|
!ret.endsWith(QChar::LineSeparator))
|
||||||
|
ret += QChar::LineSeparator;
|
||||||
|
} else {
|
||||||
|
ret += text;
|
||||||
|
}
|
||||||
|
// below visible text, can stop
|
||||||
|
if ((height + layoutRect.top() >= textRect.bottom()) ||
|
||||||
|
(lastVisibleLine >= 0 && lastVisibleLine == i))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
35
src/widgets/itemproxystyle.h
Normal file
35
src/widgets/itemproxystyle.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#ifndef ITEMPROXYSTYLE_H
|
||||||
|
#define ITEMPROXYSTYLE_H
|
||||||
|
|
||||||
|
#include <QProxyStyle>
|
||||||
|
|
||||||
|
class QStyleOptionViewItem;
|
||||||
|
class QTextOption;
|
||||||
|
|
||||||
|
namespace vnotex
|
||||||
|
{
|
||||||
|
// Draw item with text segments highlighted.
|
||||||
|
class ItemProxyStyle : public QProxyStyle
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit ItemProxyStyle(QStyle *p_style = nullptr);
|
||||||
|
|
||||||
|
void drawControl(QStyle::ControlElement p_element,
|
||||||
|
const QStyleOption *p_option,
|
||||||
|
QPainter *p_painter,
|
||||||
|
const QWidget *p_widget = nullptr) const Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool drawItemViewItem(const QStyleOption *p_option, QPainter *p_painter, const QWidget *p_widget) const;
|
||||||
|
|
||||||
|
void viewItemDrawText(QPainter *p_painter, const QStyleOptionViewItem *p_option, const QRect &p_rect) const;
|
||||||
|
|
||||||
|
QString calculateElidedText(const QString &text, const QTextOption &textOption,
|
||||||
|
const QFont &font, const QRect &textRect, const Qt::Alignment valign,
|
||||||
|
Qt::TextElideMode textElideMode, int flags,
|
||||||
|
bool lastVisibleLineShouldBeElided, QPointF *paintStartPosition) const;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // ITEMPROXYSTYLE_H
|
@ -115,9 +115,23 @@ void LineEdit::setInputMethodEnabled(bool p_enabled)
|
|||||||
if (m_inputMethodEnabled != p_enabled) {
|
if (m_inputMethodEnabled != p_enabled) {
|
||||||
m_inputMethodEnabled = p_enabled;
|
m_inputMethodEnabled = p_enabled;
|
||||||
|
|
||||||
|
updateInputMethod();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LineEdit::showEvent(QShowEvent *p_event)
|
||||||
|
{
|
||||||
|
QLineEdit::showEvent(p_event);
|
||||||
|
|
||||||
|
if (!m_inputMethodEnabled) {
|
||||||
|
updateInputMethod();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LineEdit::updateInputMethod() const
|
||||||
|
{
|
||||||
QInputMethod *im = QGuiApplication::inputMethod();
|
QInputMethod *im = QGuiApplication::inputMethod();
|
||||||
im->reset();
|
im->reset();
|
||||||
// Ask input method to query current state, which will call inputMethodQuery().
|
// Ask input method to query current state, which will call inputMethodQuery().
|
||||||
im->update(Qt::ImEnabled);
|
im->update(Qt::ImEnabled);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
@ -23,7 +23,11 @@ namespace vnotex
|
|||||||
protected:
|
protected:
|
||||||
void keyPressEvent(QKeyEvent *p_event) Q_DECL_OVERRIDE;
|
void keyPressEvent(QKeyEvent *p_event) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
void showEvent(QShowEvent *p_event) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void updateInputMethod() const;
|
||||||
|
|
||||||
// Whether enable input method.
|
// Whether enable input method.
|
||||||
bool m_inputMethodEnabled = true;
|
bool m_inputMethodEnabled = true;
|
||||||
};
|
};
|
||||||
|
@ -1,13 +1,47 @@
|
|||||||
#include "listwidget.h"
|
#include "listwidget.h"
|
||||||
|
|
||||||
#include <QKeyEvent>
|
#include <QKeyEvent>
|
||||||
|
|
||||||
|
#include <core/vnotex.h>
|
||||||
|
#include <core/thememgr.h>
|
||||||
#include <utils/widgetutils.h>
|
#include <utils/widgetutils.h>
|
||||||
|
#include "styleditemdelegate.h"
|
||||||
|
|
||||||
using namespace vnotex;
|
using namespace vnotex;
|
||||||
|
|
||||||
|
QBrush ListWidget::s_separatorForeground;
|
||||||
|
|
||||||
|
QBrush ListWidget::s_separatorBackground;
|
||||||
|
|
||||||
ListWidget::ListWidget(QWidget *p_parent)
|
ListWidget::ListWidget(QWidget *p_parent)
|
||||||
: QListWidget(p_parent)
|
: QListWidget(p_parent)
|
||||||
{
|
{
|
||||||
|
initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
ListWidget::ListWidget(bool p_enhancedStyle, QWidget *p_parent)
|
||||||
|
: QListWidget(p_parent)
|
||||||
|
{
|
||||||
|
initialize();
|
||||||
|
|
||||||
|
if (p_enhancedStyle) {
|
||||||
|
auto delegate = new StyledItemDelegate(QSharedPointer<StyledItemDelegateListWidget>::create(this),
|
||||||
|
StyledItemDelegate::None,
|
||||||
|
this);
|
||||||
|
setItemDelegate(delegate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ListWidget::initialize()
|
||||||
|
{
|
||||||
|
static bool initialized = false;
|
||||||
|
if (!initialized) {
|
||||||
|
initialized = true;
|
||||||
|
|
||||||
|
const auto &themeMgr = VNoteX::getInst().getThemeMgr();
|
||||||
|
s_separatorForeground = QColor(themeMgr.paletteColor(QStringLiteral("widgets#styleditemdelegate#separator#fg")));
|
||||||
|
s_separatorBackground = QColor(themeMgr.paletteColor(QStringLiteral("widgets#styleditemdelegate#separator#bg")));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ListWidget::keyPressEvent(QKeyEvent *p_event)
|
void ListWidget::keyPressEvent(QKeyEvent *p_event)
|
||||||
@ -16,6 +50,16 @@ void ListWidget::keyPressEvent(QKeyEvent *p_event)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// On Mac OS X, it is `Command+O` to activate an item, instead of Return.
|
||||||
|
#if defined(Q_OS_MACOS) || defined(Q_OS_MAC)
|
||||||
|
if (p_event->key() == Qt::Key_Return) {
|
||||||
|
if (auto item = currentItem()) {
|
||||||
|
emit itemActivated(item);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
QListWidget::keyPressEvent(p_event);
|
QListWidget::keyPressEvent(p_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,12 +88,14 @@ QVector<QListWidgetItem *> ListWidget::getVisibleItems(const QListWidget *p_widg
|
|||||||
|
|
||||||
QListWidgetItem *ListWidget::createSeparatorItem(const QString &p_text)
|
QListWidgetItem *ListWidget::createSeparatorItem(const QString &p_text)
|
||||||
{
|
{
|
||||||
QListWidgetItem *item = new QListWidgetItem(p_text, nullptr, c_separatorType);
|
QListWidgetItem *item = new QListWidgetItem(p_text, nullptr, ItemTypeSeparator);
|
||||||
|
item->setData(Qt::ForegroundRole, s_separatorForeground);
|
||||||
|
item->setData(Qt::BackgroundRole, s_separatorBackground);
|
||||||
item->setFlags(Qt::NoItemFlags);
|
item->setFlags(Qt::NoItemFlags);
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ListWidget::isSeparatorItem(const QListWidgetItem *p_item)
|
bool ListWidget::isSeparatorItem(const QListWidgetItem *p_item)
|
||||||
{
|
{
|
||||||
return p_item->type() == c_separatorType;
|
return p_item->type() == ItemTypeSeparator;
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,8 @@ namespace vnotex
|
|||||||
public:
|
public:
|
||||||
explicit ListWidget(QWidget *p_parent = nullptr);
|
explicit ListWidget(QWidget *p_parent = nullptr);
|
||||||
|
|
||||||
|
ListWidget(bool p_enhancedStyle, QWidget *p_parent = nullptr);
|
||||||
|
|
||||||
static QVector<QListWidgetItem *> getVisibleItems(const QListWidget *p_widget);
|
static QVector<QListWidgetItem *> getVisibleItems(const QListWidget *p_widget);
|
||||||
|
|
||||||
static QListWidgetItem *createSeparatorItem(const QString &p_text);
|
static QListWidgetItem *createSeparatorItem(const QString &p_text);
|
||||||
@ -22,7 +24,16 @@ namespace vnotex
|
|||||||
void keyPressEvent(QKeyEvent *p_event) Q_DECL_OVERRIDE;
|
void keyPressEvent(QKeyEvent *p_event) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static const int c_separatorType = 2000;
|
enum
|
||||||
|
{
|
||||||
|
ItemTypeSeparator = 2000
|
||||||
|
};
|
||||||
|
|
||||||
|
void initialize();
|
||||||
|
|
||||||
|
static QBrush s_separatorForeground;
|
||||||
|
|
||||||
|
static QBrush s_separatorBackground;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "treewidget.h"
|
#include "treewidget.h"
|
||||||
#include "widgetsfactory.h"
|
#include "widgetsfactory.h"
|
||||||
#include "titlebar.h"
|
#include "titlebar.h"
|
||||||
|
#include "styleditemdelegate.h"
|
||||||
|
|
||||||
#include <core/vnotex.h>
|
#include <core/vnotex.h>
|
||||||
#include <core/thememgr.h>
|
#include <core/thememgr.h>
|
||||||
@ -24,20 +25,10 @@ QIcon LocationList::s_folderIcon;
|
|||||||
|
|
||||||
QIcon LocationList::s_notebookIcon;
|
QIcon LocationList::s_notebookIcon;
|
||||||
|
|
||||||
QString LocationList::s_textHighlightForeground;
|
|
||||||
|
|
||||||
QString LocationList::s_textHighlightBackground;
|
|
||||||
|
|
||||||
LocationList::LocationList(QWidget *p_parent)
|
LocationList::LocationList(QWidget *p_parent)
|
||||||
: QFrame(p_parent)
|
: QFrame(p_parent)
|
||||||
{
|
{
|
||||||
setupUI();
|
setupUI();
|
||||||
|
|
||||||
if (s_textHighlightForeground.isEmpty()) {
|
|
||||||
const auto &themeMgr = VNoteX::getInst().getThemeMgr();
|
|
||||||
s_textHighlightForeground = themeMgr.paletteColor(QStringLiteral("widgets#locationlist#text_highlight#fg"));
|
|
||||||
s_textHighlightBackground = themeMgr.paletteColor(QStringLiteral("widgets#locationlist#text_highlight#bg"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LocationList::setupUI()
|
void LocationList::setupUI()
|
||||||
@ -50,11 +41,10 @@ void LocationList::setupUI()
|
|||||||
mainLayout->addWidget(m_titleBar);
|
mainLayout->addWidget(m_titleBar);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_tree = new TreeWidget(TreeWidget::Flag::None, this);
|
m_tree = new TreeWidget(TreeWidget::Flag::EnhancedStyle, this);
|
||||||
// When updated, pay attention to the Columns enum.
|
// When updated, pay attention to the Columns enum.
|
||||||
m_tree->setHeaderLabels(QStringList() << tr("Path") << tr("Line") << tr("Text"));
|
m_tree->setHeaderLabels(QStringList() << tr("Path") << tr("Line") << tr("Text"));
|
||||||
TreeWidget::showHorizontalScrollbar(m_tree);
|
TreeWidget::showHorizontalScrollbar(m_tree);
|
||||||
m_tree->header()->setSectionResizeMode(QHeaderView::Interactive);
|
|
||||||
connect(m_tree, &QTreeWidget::itemActivated,
|
connect(m_tree, &QTreeWidget::itemActivated,
|
||||||
this, [this](QTreeWidgetItem *p_item, int p_col) {
|
this, [this](QTreeWidgetItem *p_item, int p_col) {
|
||||||
Q_UNUSED(p_col);
|
Q_UNUSED(p_col);
|
||||||
@ -135,36 +125,15 @@ void LocationList::setItemLocationLineAndText(QTreeWidgetItem *p_item, const Com
|
|||||||
p_item->setText(Columns::LineColumn, QString::number(p_line.m_lineNumber + 1));
|
p_item->setText(Columns::LineColumn, QString::number(p_line.m_lineNumber + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p_line.m_segments.isEmpty()) {
|
// Truncate the text.
|
||||||
p_item->setText(Columns::TextColumn, p_line.m_text);
|
if (p_line.m_text.size() > 500) {
|
||||||
|
p_item->setText(Columns::TextColumn, p_line.m_text.left(500));
|
||||||
} else {
|
} else {
|
||||||
auto segments = p_line.m_segments;
|
p_item->setText(Columns::TextColumn, p_line.m_text);
|
||||||
std::sort(segments.begin(), segments.end());
|
|
||||||
|
|
||||||
// Use \n as a marker for < and use \r for >.
|
|
||||||
QString text(p_line.m_text);
|
|
||||||
int lastOffset = text.size();
|
|
||||||
for (int i = segments.size() - 1; i >= 0; --i) {
|
|
||||||
Q_ASSERT(segments[i].m_length > 0);
|
|
||||||
if (segments[i].m_offset + segments[i].m_length > lastOffset) {
|
|
||||||
// Interset.
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lastOffset = segments[i].m_offset;
|
if (!p_line.m_segments.isEmpty()) {
|
||||||
text.insert(segments[i].m_offset + segments[i].m_length, QStringLiteral("\n/span\r"));
|
p_item->setData(Columns::TextColumn, HighlightsRole, QVariant::fromValue(p_line.m_segments));
|
||||||
text.insert(segments[i].m_offset,
|
|
||||||
QString("\nspan style='color:%1;background-color:%2'\r").arg(s_textHighlightForeground, s_textHighlightBackground));
|
|
||||||
}
|
|
||||||
|
|
||||||
text = text.toHtmlEscaped();
|
|
||||||
text.replace(QLatin1Char('\n'), QLatin1Char('<'));
|
|
||||||
text.replace(QLatin1Char('\r'), QLatin1Char('>'));
|
|
||||||
|
|
||||||
auto label = new QLabel(m_tree);
|
|
||||||
label->setTextFormat(Qt::RichText);
|
|
||||||
label->setText(text);
|
|
||||||
m_tree->setItemWidget(p_item, Columns::TextColumn, label);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,9 +141,8 @@ void LocationList::addLocation(const ComplexLocation &p_location)
|
|||||||
{
|
{
|
||||||
auto item = new QTreeWidgetItem(m_tree);
|
auto item = new QTreeWidgetItem(m_tree);
|
||||||
item->setText(Columns::PathColumn, p_location.m_displayPath);
|
item->setText(Columns::PathColumn, p_location.m_displayPath);
|
||||||
item->setData(Columns::PathColumn, Qt::UserRole, p_location.m_path);
|
|
||||||
|
|
||||||
item->setIcon(Columns::PathColumn, getItemIcon(p_location.m_type));
|
item->setIcon(Columns::PathColumn, getItemIcon(p_location.m_type));
|
||||||
|
item->setData(Columns::PathColumn, Qt::UserRole, p_location.m_path);
|
||||||
|
|
||||||
if (p_location.m_lines.size() == 1) {
|
if (p_location.m_lines.size() == 1) {
|
||||||
setItemLocationLineAndText(item, p_location.m_lines[0]);
|
setItemLocationLineAndText(item, p_location.m_lines[0]);
|
||||||
|
@ -68,10 +68,6 @@ namespace vnotex
|
|||||||
static QIcon s_folderIcon;
|
static QIcon s_folderIcon;
|
||||||
|
|
||||||
static QIcon s_notebookIcon;
|
static QIcon s_notebookIcon;
|
||||||
|
|
||||||
static QString s_textHighlightForeground;
|
|
||||||
|
|
||||||
static QString s_textHighlightBackground;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -250,7 +250,6 @@ void MarkdownViewWindow::setupToolBar()
|
|||||||
auto toolBar = createToolBar(this);
|
auto toolBar = createToolBar(this);
|
||||||
|
|
||||||
const auto &editorConfig = ConfigMgr::getInst().getEditorConfig();
|
const auto &editorConfig = ConfigMgr::getInst().getEditorConfig();
|
||||||
const auto &markdownEditorConfig = editorConfig.getMarkdownEditorConfig();
|
|
||||||
|
|
||||||
const int iconSize = editorConfig.getToolBarIconSize();
|
const int iconSize = editorConfig.getToolBarIconSize();
|
||||||
toolBar->setIconSize(QSize(iconSize, iconSize));
|
toolBar->setIconSize(QSize(iconSize, iconSize));
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
#include "notebooknodeexplorer.h"
|
#include "notebooknodeexplorer.h"
|
||||||
|
|
||||||
#include <QTreeWidget>
|
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
#include <QSplitter>
|
#include <QSplitter>
|
||||||
#include <QTreeWidget>
|
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
#include <QSet>
|
#include <QSet>
|
||||||
|
@ -313,6 +313,8 @@ void SearchPanel::startSearch()
|
|||||||
|
|
||||||
void SearchPanel::handleSearchFinished(SearchState p_state)
|
void SearchPanel::handleSearchFinished(SearchState p_state)
|
||||||
{
|
{
|
||||||
|
qDebug() << "handleSearchFinished" << (int)p_state;
|
||||||
|
|
||||||
Q_ASSERT(m_searchOngoing);
|
Q_ASSERT(m_searchOngoing);
|
||||||
Q_ASSERT(p_state != SearchState::Idle);
|
Q_ASSERT(p_state != SearchState::Idle);
|
||||||
|
|
||||||
|
35
src/widgets/simplesegmenthighlighter.cpp
Normal file
35
src/widgets/simplesegmenthighlighter.cpp
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#include "simplesegmenthighlighter.h"
|
||||||
|
|
||||||
|
#include <QTextDocument>
|
||||||
|
|
||||||
|
using namespace vnotex;
|
||||||
|
|
||||||
|
SimpleSegmentHighlighter::SimpleSegmentHighlighter(QTextDocument *p_parent)
|
||||||
|
: QSyntaxHighlighter(p_parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void SimpleSegmentHighlighter::highlightBlock(const QString &p_text)
|
||||||
|
{
|
||||||
|
if (m_segments.isEmpty() || !m_highlightFormat.isValid()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int len = p_text.size();
|
||||||
|
for (const auto &seg : m_segments) {
|
||||||
|
if (seg.m_offset >= 0 && seg.m_offset < len) {
|
||||||
|
setFormat(seg.m_offset, qMin(seg.m_length, len - seg.m_offset), m_highlightFormat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SimpleSegmentHighlighter::setSegments(const QList<Segment> &p_segments)
|
||||||
|
{
|
||||||
|
m_segments = p_segments;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SimpleSegmentHighlighter::setHighlightFormat(const QBrush &p_foreground, const QBrush &p_background)
|
||||||
|
{
|
||||||
|
m_highlightFormat.setForeground(p_foreground);
|
||||||
|
m_highlightFormat.setBackground(p_background);
|
||||||
|
}
|
31
src/widgets/simplesegmenthighlighter.h
Normal file
31
src/widgets/simplesegmenthighlighter.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#ifndef SIMPLESEGMENTHIGHLIGHTER_H
|
||||||
|
#define SIMPLESEGMENTHIGHLIGHTER_H
|
||||||
|
|
||||||
|
#include <QSyntaxHighlighter>
|
||||||
|
#include <QList>
|
||||||
|
|
||||||
|
#include <core/global.h>
|
||||||
|
|
||||||
|
namespace vnotex
|
||||||
|
{
|
||||||
|
class SimpleSegmentHighlighter : public QSyntaxHighlighter
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit SimpleSegmentHighlighter(QTextDocument *p_parent);
|
||||||
|
|
||||||
|
void setSegments(const QList<Segment> &p_segments);
|
||||||
|
|
||||||
|
void setHighlightFormat(const QBrush &p_foreground, const QBrush &p_background);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void highlightBlock(const QString &p_text) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QTextCharFormat m_highlightFormat;
|
||||||
|
|
||||||
|
QList<Segment> m_segments;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // SIMPLESEGMENTHIGHLIGHTER_H
|
158
src/widgets/styleditemdelegate.cpp
Normal file
158
src/widgets/styleditemdelegate.cpp
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
#include "styleditemdelegate.h"
|
||||||
|
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QListWidgetItem>
|
||||||
|
#include <QTextDocument>
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QStyle>
|
||||||
|
#include <QAbstractTextDocumentLayout>
|
||||||
|
|
||||||
|
#include <core/vnotex.h>
|
||||||
|
#include <core/thememgr.h>
|
||||||
|
#include "listwidget.h"
|
||||||
|
#include "treewidget.h"
|
||||||
|
#include "simplesegmenthighlighter.h"
|
||||||
|
|
||||||
|
using namespace vnotex;
|
||||||
|
|
||||||
|
StyledItemDelegateListWidget::StyledItemDelegateListWidget(const ListWidget *p_listWidget)
|
||||||
|
: m_listWidget(p_listWidget)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
StyledItemDelegateTreeWidget::StyledItemDelegateTreeWidget(const TreeWidget *p_treeWidget)
|
||||||
|
: m_treeWidget(p_treeWidget)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QBrush StyledItemDelegate::s_highlightForeground;
|
||||||
|
|
||||||
|
QBrush StyledItemDelegate::s_highlightBackground;
|
||||||
|
|
||||||
|
StyledItemDelegate::StyledItemDelegate(const QSharedPointer<StyledItemDelegateInterface> &p_interface,
|
||||||
|
DelegateFlags p_flags,
|
||||||
|
QObject *p_parent)
|
||||||
|
: QStyledItemDelegate(p_parent),
|
||||||
|
m_interface(p_interface),
|
||||||
|
m_flags(p_flags)
|
||||||
|
{
|
||||||
|
initialize();
|
||||||
|
|
||||||
|
if (m_flags & DelegateFlag::Highlights) {
|
||||||
|
m_document = new QTextDocument(this);
|
||||||
|
m_highlighter = new SimpleSegmentHighlighter(m_document);
|
||||||
|
m_highlighter->setHighlightFormat(s_highlightForeground, s_highlightBackground);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void StyledItemDelegate::initialize()
|
||||||
|
{
|
||||||
|
static bool initialized = false;
|
||||||
|
if (!initialized) {
|
||||||
|
initialized = true;
|
||||||
|
|
||||||
|
const auto &themeMgr = VNoteX::getInst().getThemeMgr();
|
||||||
|
s_highlightForeground = QColor(themeMgr.paletteColor(QStringLiteral("widgets#styleditemdelegate#highlight#fg")));
|
||||||
|
s_highlightBackground = QColor(themeMgr.paletteColor(QStringLiteral("widgets#styleditemdelegate#highlight#bg")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void StyledItemDelegate::paint(QPainter *p_painter,
|
||||||
|
const QStyleOptionViewItem &p_option,
|
||||||
|
const QModelIndex &p_index) const
|
||||||
|
{
|
||||||
|
// [Qt's BUG] Qt does not draw the background from Qt::BackgroundRole. Do it manually.
|
||||||
|
auto bgBrushVal = p_index.data(Qt::BackgroundRole);
|
||||||
|
if (bgBrushVal.canConvert<QBrush>()) {
|
||||||
|
auto brush = qvariant_cast<QBrush>(bgBrushVal);
|
||||||
|
if (brush.style() != Qt::NoBrush) {
|
||||||
|
p_painter->fillRect(p_option.rect, brush);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_flags & DelegateFlag::Highlights) {
|
||||||
|
const auto value = p_index.data(HighlightsRole);
|
||||||
|
if (value.canConvert<QList<Segment>>()) {
|
||||||
|
auto segments = value.value<QList<Segment>>();
|
||||||
|
if (!segments.isEmpty()) {
|
||||||
|
paintWithHighlights(p_painter, p_option, p_index, segments);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QStyledItemDelegate::paint(p_painter, p_option, p_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void drawContents(const QStyleOptionViewItem &p_option,
|
||||||
|
QTextDocument *p_doc,
|
||||||
|
QPainter *p_painter,
|
||||||
|
const QRectF &p_rect)
|
||||||
|
{
|
||||||
|
// From qtbase/src/gui/text/qtextdocument.cpp.
|
||||||
|
|
||||||
|
p_painter->save();
|
||||||
|
|
||||||
|
QAbstractTextDocumentLayout::PaintContext ctx;
|
||||||
|
if (p_rect.isValid()) {
|
||||||
|
p_painter->setClipRect(p_rect);
|
||||||
|
ctx.clip = p_rect;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update palette.
|
||||||
|
ctx.palette.setBrush(QPalette::Text, p_option.palette.brush(QPalette::Text));
|
||||||
|
|
||||||
|
p_doc->documentLayout()->draw(p_painter, ctx);
|
||||||
|
|
||||||
|
p_painter->restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
void StyledItemDelegate::paintWithHighlights(QPainter *p_painter,
|
||||||
|
const QStyleOptionViewItem &p_option,
|
||||||
|
const QModelIndex &p_index,
|
||||||
|
const QList<Segment> &p_segments) const
|
||||||
|
{
|
||||||
|
QStyleOptionViewItem opt(p_option);
|
||||||
|
initStyleOption(&opt, p_index);
|
||||||
|
|
||||||
|
m_highlighter->setSegments(p_segments);
|
||||||
|
m_document->clear();
|
||||||
|
m_document->setDefaultFont(opt.font);
|
||||||
|
m_document->setPlainText(opt.text);
|
||||||
|
|
||||||
|
p_painter->save();
|
||||||
|
|
||||||
|
// Draw the item without text.
|
||||||
|
opt.text = "";
|
||||||
|
auto style = opt.widget ? opt.widget->style() : QApplication::style();
|
||||||
|
style->drawControl(QStyle::CE_ItemViewItem, &opt, p_painter, opt.widget);
|
||||||
|
|
||||||
|
// Draw the text via QTextDocument.
|
||||||
|
p_painter->translate(opt.rect.left(), opt.rect.top());
|
||||||
|
const QRect clip(0, 0, opt.rect.width(), opt.rect.height());
|
||||||
|
drawContents(opt, m_document, p_painter, clip);
|
||||||
|
|
||||||
|
p_painter->restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
QSize StyledItemDelegate::sizeHint(const QStyleOptionViewItem &p_option, const QModelIndex &p_index) const
|
||||||
|
{
|
||||||
|
if (m_flags & DelegateFlag::Highlights) {
|
||||||
|
const auto value = p_index.data(HighlightsRole);
|
||||||
|
if (value.canConvert<QList<Segment>>()) {
|
||||||
|
auto segments = value.value<QList<Segment>>();
|
||||||
|
if (!segments.isEmpty()) {
|
||||||
|
QStyleOptionViewItem opt(p_option);
|
||||||
|
initStyleOption(&opt, p_index);
|
||||||
|
|
||||||
|
m_document->setPlainText(opt.text);
|
||||||
|
return QSize(m_document->idealWidth(), m_document->size().height());
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return QStyledItemDelegate::sizeHint(p_option, p_index);
|
||||||
|
}
|
98
src/widgets/styleditemdelegate.h
Normal file
98
src/widgets/styleditemdelegate.h
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
#ifndef STYLEDITEMDELEGATE_H
|
||||||
|
#define STYLEDITEMDELEGATE_H
|
||||||
|
|
||||||
|
#include <QStyledItemDelegate>
|
||||||
|
#include <QSharedPointer>
|
||||||
|
#include <QBrush>
|
||||||
|
#include <QList>
|
||||||
|
|
||||||
|
#include <core/global.h>
|
||||||
|
|
||||||
|
class QTextDocument;
|
||||||
|
|
||||||
|
namespace vnotex
|
||||||
|
{
|
||||||
|
class ListWidget;
|
||||||
|
class TreeWidget;
|
||||||
|
class SimpleSegmentHighlighter;
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
HighlightsRole = 0x0101
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class StyledItemDelegateInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~StyledItemDelegateInterface() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class StyledItemDelegateListWidget : public StyledItemDelegateInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit StyledItemDelegateListWidget(const ListWidget *p_listWidget);
|
||||||
|
|
||||||
|
private:
|
||||||
|
const ListWidget *m_listWidget = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class StyledItemDelegateTreeWidget : public StyledItemDelegateInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit StyledItemDelegateTreeWidget(const TreeWidget *p_treeWidget);
|
||||||
|
|
||||||
|
private:
|
||||||
|
const TreeWidget *m_treeWidget = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Template is not supported with QObject.
|
||||||
|
class StyledItemDelegate : public QStyledItemDelegate
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
enum DelegateFlag
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
Highlights = 0x1
|
||||||
|
};
|
||||||
|
Q_DECLARE_FLAGS(DelegateFlags, DelegateFlag);
|
||||||
|
|
||||||
|
StyledItemDelegate(const QSharedPointer<StyledItemDelegateInterface> &p_interface,
|
||||||
|
DelegateFlags p_flags = DelegateFlag::None,
|
||||||
|
QObject *p_parent = nullptr);
|
||||||
|
|
||||||
|
void paint(QPainter *p_painter,
|
||||||
|
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;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void initialize();
|
||||||
|
|
||||||
|
void paintWithHighlights(QPainter *p_painter,
|
||||||
|
const QStyleOptionViewItem &p_option,
|
||||||
|
const QModelIndex &p_index,
|
||||||
|
const QList<Segment> &p_segments) const;
|
||||||
|
|
||||||
|
QSharedPointer<StyledItemDelegateInterface> m_interface;
|
||||||
|
|
||||||
|
DelegateFlags m_flags = DelegateFlag::None;
|
||||||
|
|
||||||
|
QTextDocument *m_document = nullptr;
|
||||||
|
|
||||||
|
SimpleSegmentHighlighter *m_highlighter = nullptr;
|
||||||
|
|
||||||
|
static QBrush s_highlightForeground;
|
||||||
|
|
||||||
|
static QBrush s_highlightBackground;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_DECLARE_OPERATORS_FOR_FLAGS(vnotex::StyledItemDelegate::DelegateFlags)
|
||||||
|
|
||||||
|
#endif // STYLEDITEMDELEGATE_H
|
@ -6,6 +6,7 @@
|
|||||||
#include <QDropEvent>
|
#include <QDropEvent>
|
||||||
|
|
||||||
#include <utils/widgetutils.h>
|
#include <utils/widgetutils.h>
|
||||||
|
#include "styleditemdelegate.h"
|
||||||
|
|
||||||
using namespace vnotex;
|
using namespace vnotex;
|
||||||
|
|
||||||
@ -18,6 +19,11 @@ TreeWidget::TreeWidget(TreeWidget::Flags p_flags, QWidget *p_parent)
|
|||||||
: QTreeWidget(p_parent),
|
: QTreeWidget(p_parent),
|
||||||
m_flags(p_flags)
|
m_flags(p_flags)
|
||||||
{
|
{
|
||||||
|
if (m_flags & Flag::EnhancedStyle) {
|
||||||
|
auto interface = QSharedPointer<StyledItemDelegateTreeWidget>::create(this);
|
||||||
|
auto delegate = new StyledItemDelegate(interface, StyledItemDelegate::Highlights, this);
|
||||||
|
setItemDelegate(delegate);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TreeWidget::mousePressEvent(QMouseEvent *p_event)
|
void TreeWidget::mousePressEvent(QMouseEvent *p_event)
|
||||||
@ -92,22 +98,15 @@ void TreeWidget::keyPressEvent(QKeyEvent *p_event)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (p_event->key()) {
|
// On Mac OS X, it is `Command+O` to activate an item, instead of Return.
|
||||||
case Qt::Key_Return:
|
#if defined(Q_OS_MACOS) || defined(Q_OS_MAC)
|
||||||
Q_FALLTHROUGH();
|
if (p_event->key() == Qt::Key_Return) {
|
||||||
case Qt::Key_Enter:
|
if (auto item = currentItem()) {
|
||||||
{
|
emit itemActivated(item, currentColumn());
|
||||||
auto item = currentItem();
|
|
||||||
if (item && item->childCount() > 0) {
|
|
||||||
item->setExpanded(!item->isExpanded());
|
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
QTreeWidget::keyPressEvent(p_event);
|
QTreeWidget::keyPressEvent(p_event);
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,8 @@ namespace vnotex
|
|||||||
enum Flag
|
enum Flag
|
||||||
{
|
{
|
||||||
None = 0,
|
None = 0,
|
||||||
ClickSpaceToClearSelection = 0x1
|
ClickSpaceToClearSelection = 0x1,
|
||||||
|
EnhancedStyle = 0x2
|
||||||
};
|
};
|
||||||
Q_DECLARE_FLAGS(Flags, Flag)
|
Q_DECLARE_FLAGS(Flags, Flag)
|
||||||
|
|
||||||
|
@ -170,6 +170,13 @@ namespace vnotex
|
|||||||
|
|
||||||
virtual void handleFindAndReplaceWidgetOpened();
|
virtual void handleFindAndReplaceWidgetOpened();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool eventFilter(QObject *p_obj, QEvent *p_event) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
void wheelEvent(QWheelEvent *p_event) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
void keyPressEvent(QKeyEvent *p_event) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void setCentralWidget(QWidget *p_widget);
|
void setCentralWidget(QWidget *p_widget);
|
||||||
|
|
||||||
@ -181,12 +188,6 @@ namespace vnotex
|
|||||||
|
|
||||||
void setStatusWidget(const QSharedPointer<StatusWidget> &p_widget);
|
void setStatusWidget(const QSharedPointer<StatusWidget> &p_widget);
|
||||||
|
|
||||||
bool eventFilter(QObject *p_obj, QEvent *p_event) Q_DECL_OVERRIDE;
|
|
||||||
|
|
||||||
void wheelEvent(QWheelEvent *p_event) Q_DECL_OVERRIDE;
|
|
||||||
|
|
||||||
void keyPressEvent(QKeyEvent *p_event) Q_DECL_OVERRIDE;
|
|
||||||
|
|
||||||
// Provide some common actions of tool bar for ViewWindow.
|
// Provide some common actions of tool bar for ViewWindow.
|
||||||
QAction *addAction(QToolBar *p_toolBar, ViewWindowToolBarHelper::Action p_action);
|
QAction *addAction(QToolBar *p_toolBar, ViewWindowToolBarHelper::Action p_action);
|
||||||
|
|
||||||
|
@ -50,6 +50,7 @@ SOURCES += \
|
|||||||
$$PWD/floatingwidget.cpp \
|
$$PWD/floatingwidget.cpp \
|
||||||
$$PWD/fullscreentoggleaction.cpp \
|
$$PWD/fullscreentoggleaction.cpp \
|
||||||
$$PWD/historypanel.cpp \
|
$$PWD/historypanel.cpp \
|
||||||
|
$$PWD/itemproxystyle.cpp \
|
||||||
$$PWD/lineedit.cpp \
|
$$PWD/lineedit.cpp \
|
||||||
$$PWD/lineeditdelegate.cpp \
|
$$PWD/lineeditdelegate.cpp \
|
||||||
$$PWD/lineeditwithsnippet.cpp \
|
$$PWD/lineeditwithsnippet.cpp \
|
||||||
@ -67,7 +68,9 @@ SOURCES += \
|
|||||||
$$PWD/quickselector.cpp \
|
$$PWD/quickselector.cpp \
|
||||||
$$PWD/searchinfoprovider.cpp \
|
$$PWD/searchinfoprovider.cpp \
|
||||||
$$PWD/searchpanel.cpp \
|
$$PWD/searchpanel.cpp \
|
||||||
|
$$PWD/simplesegmenthighlighter.cpp \
|
||||||
$$PWD/snippetpanel.cpp \
|
$$PWD/snippetpanel.cpp \
|
||||||
|
$$PWD/styleditemdelegate.cpp \
|
||||||
$$PWD/systemtrayhelper.cpp \
|
$$PWD/systemtrayhelper.cpp \
|
||||||
$$PWD/textviewwindow.cpp \
|
$$PWD/textviewwindow.cpp \
|
||||||
$$PWD/toolbarhelper.cpp \
|
$$PWD/toolbarhelper.cpp \
|
||||||
@ -157,6 +160,7 @@ HEADERS += \
|
|||||||
$$PWD/floatingwidget.h \
|
$$PWD/floatingwidget.h \
|
||||||
$$PWD/fullscreentoggleaction.h \
|
$$PWD/fullscreentoggleaction.h \
|
||||||
$$PWD/historypanel.h \
|
$$PWD/historypanel.h \
|
||||||
|
$$PWD/itemproxystyle.h \
|
||||||
$$PWD/lineedit.h \
|
$$PWD/lineedit.h \
|
||||||
$$PWD/lineeditdelegate.h \
|
$$PWD/lineeditdelegate.h \
|
||||||
$$PWD/lineeditwithsnippet.h \
|
$$PWD/lineeditwithsnippet.h \
|
||||||
@ -175,7 +179,9 @@ HEADERS += \
|
|||||||
$$PWD/quickselector.h \
|
$$PWD/quickselector.h \
|
||||||
$$PWD/searchinfoprovider.h \
|
$$PWD/searchinfoprovider.h \
|
||||||
$$PWD/searchpanel.h \
|
$$PWD/searchpanel.h \
|
||||||
|
$$PWD/simplesegmenthighlighter.h \
|
||||||
$$PWD/snippetpanel.h \
|
$$PWD/snippetpanel.h \
|
||||||
|
$$PWD/styleditemdelegate.h \
|
||||||
$$PWD/systemtrayhelper.h \
|
$$PWD/systemtrayhelper.h \
|
||||||
$$PWD/textviewwindow.h \
|
$$PWD/textviewwindow.h \
|
||||||
$$PWD/textviewwindowhelper.h \
|
$$PWD/textviewwindowhelper.h \
|
||||||
|
Loading…
x
Reference in New Issue
Block a user