|
|
|
@ -14,7 +14,7 @@
|
|
|
|
|
#include <QCursor>
|
|
|
|
|
|
|
|
|
|
#define FIRST_LINE_MAX 80
|
|
|
|
|
|
|
|
|
|
// 构造函数,根据 Qt 版本不同,参数有所不同
|
|
|
|
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
|
|
|
|
|
|
|
|
|
|
NoteEditorLogic::NoteEditorLogic(CustomDocument *textEdit, QLabel *editorDateLabel,
|
|
|
|
@ -40,20 +40,24 @@ NoteEditorLogic::NoteEditorLogic(CustomDocument *textEdit, QLabel *editorDateLab
|
|
|
|
|
m_spacerColor{ 191, 191, 191 },
|
|
|
|
|
m_currentAdaptableEditorPadding{ 0 },
|
|
|
|
|
m_currentMinimumEditorPadding{ 0 }
|
|
|
|
|
{
|
|
|
|
|
{// 连接文本编辑器的文本变化信号
|
|
|
|
|
connect(m_textEdit, &QTextEdit::textChanged, this, &NoteEditorLogic::onTextEditTextChanged);
|
|
|
|
|
// 连接创建或更新笔记请求信号
|
|
|
|
|
connect(this, &NoteEditorLogic::requestCreateUpdateNote, m_dbManager,
|
|
|
|
|
&DBManager::onCreateUpdateRequestedNoteContent, Qt::QueuedConnection);
|
|
|
|
|
// auto save timer
|
|
|
|
|
// auto save timer 自动保存定时器
|
|
|
|
|
m_autoSaveTimer.setSingleShot(true);
|
|
|
|
|
m_autoSaveTimer.setInterval(50);
|
|
|
|
|
connect(&m_autoSaveTimer, &QTimer::timeout, this, [this]() { saveNoteToDB(); });
|
|
|
|
|
// 初始化标签列表模型和委托
|
|
|
|
|
m_tagListModel = new TagListModel{ this };
|
|
|
|
|
m_tagListModel->setTagPool(tagPool);
|
|
|
|
|
m_tagListView->setModel(m_tagListModel);
|
|
|
|
|
m_tagListDelegate = new TagListDelegate{ this };
|
|
|
|
|
m_tagListView->setItemDelegate(m_tagListDelegate);
|
|
|
|
|
// 连接标签池数据更新信号
|
|
|
|
|
connect(tagPool, &TagPool::dataUpdated, this, [this](int) { showTagListForCurrentNote(); });
|
|
|
|
|
// 连接滚动条位置变化信号
|
|
|
|
|
connect(m_textEdit->verticalScrollBar(), &QScrollBar::valueChanged, this, [this](int value) {
|
|
|
|
|
if (m_currentNotes.size() == 1 && m_currentNotes[0].id() != SpecialNodeID::InvalidNodeId) {
|
|
|
|
|
m_currentNotes[0].setScrollBarPosition(value);
|
|
|
|
@ -63,6 +67,7 @@ NoteEditorLogic::NoteEditorLogic(CustomDocument *textEdit, QLabel *editorDateLab
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
|
|
|
|
|
// 连接显示看板视图信号
|
|
|
|
|
connect(this, &NoteEditorLogic::showKanbanView, this, [this]() {
|
|
|
|
|
if (m_kanbanWidget != nullptr) {
|
|
|
|
|
emit setVisibilityOfFrameRightNonEditor(false);
|
|
|
|
@ -76,6 +81,7 @@ NoteEditorLogic::NoteEditorLogic(CustomDocument *textEdit, QLabel *editorDateLab
|
|
|
|
|
emit kanbanShown();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
// 连接隐藏看板视图信号
|
|
|
|
|
connect(this, &NoteEditorLogic::hideKanbanView, this, [this]() {
|
|
|
|
|
if (m_kanbanWidget != nullptr) {
|
|
|
|
|
emit setVisibilityOfFrameRightNonEditor(true);
|
|
|
|
@ -87,17 +93,17 @@ NoteEditorLogic::NoteEditorLogic(CustomDocument *textEdit, QLabel *editorDateLab
|
|
|
|
|
});
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 获取是否启用 Markdown
|
|
|
|
|
bool NoteEditorLogic::markdownEnabled() const
|
|
|
|
|
{
|
|
|
|
|
return m_highlighter->document() != nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 设置是否启用 Markdown
|
|
|
|
|
void NoteEditorLogic::setMarkdownEnabled(bool enabled)
|
|
|
|
|
{
|
|
|
|
|
m_highlighter->setDocument(enabled ? m_textEdit->document() : nullptr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 在编辑器中显示笔记
|
|
|
|
|
void NoteEditorLogic::showNotesInEditor(const QVector<NodeData> ¬es)
|
|
|
|
|
{
|
|
|
|
|
auto currentId = currentEditingNoteId();
|
|
|
|
@ -200,7 +206,7 @@ void NoteEditorLogic::showNotesInEditor(const QVector<NodeData> ¬es)
|
|
|
|
|
highlightSearch();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 文本编辑器内容变化时的处理
|
|
|
|
|
void NoteEditorLogic::onTextEditTextChanged()
|
|
|
|
|
{
|
|
|
|
|
if (currentEditingNoteId() != SpecialNodeID::InvalidNodeId) {
|
|
|
|
@ -234,7 +240,7 @@ void NoteEditorLogic::onTextEditTextChanged()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
|
|
|
|
|
|
|
|
|
|
// 重新排列文本编辑器中的任务
|
|
|
|
|
void NoteEditorLogic::rearrangeTasksInTextEditor(int startLinePosition, int endLinePosition,
|
|
|
|
|
int newLinePosition)
|
|
|
|
|
{
|
|
|
|
@ -269,7 +275,7 @@ void NoteEditorLogic::rearrangeTasksInTextEditor(int startLinePosition, int endL
|
|
|
|
|
|
|
|
|
|
checkForTasksInEditor();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 重新排列文本编辑器中的列
|
|
|
|
|
void NoteEditorLogic::rearrangeColumnsInTextEditor(int startLinePosition, int endLinePosition,
|
|
|
|
|
int newLinePosition)
|
|
|
|
|
{
|
|
|
|
@ -305,7 +311,7 @@ void NoteEditorLogic::rearrangeColumnsInTextEditor(int startLinePosition, int en
|
|
|
|
|
|
|
|
|
|
checkForTasksInEditor();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 获取某行的任务数据
|
|
|
|
|
QMap<QString, int> NoteEditorLogic::getTaskDataInLine(const QString &line)
|
|
|
|
|
{
|
|
|
|
|
QStringList taskExpressions = { "- [ ]", "- [x]", "* [ ]", "* [x]", "- [X]", "* [X]" };
|
|
|
|
@ -325,7 +331,7 @@ QMap<QString, int> NoteEditorLogic::getTaskDataInLine(const QString &line)
|
|
|
|
|
|
|
|
|
|
return taskMatchLineData;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 检查某行的任务
|
|
|
|
|
void NoteEditorLogic::checkTaskInLine(int lineNumber)
|
|
|
|
|
{
|
|
|
|
|
QTextDocument *document = m_textEdit->document();
|
|
|
|
@ -343,7 +349,7 @@ void NoteEditorLogic::checkTaskInLine(int lineNumber)
|
|
|
|
|
cursor.insertText("x");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 取消检查某行的任务
|
|
|
|
|
void NoteEditorLogic::uncheckTaskInLine(int lineNumber)
|
|
|
|
|
{
|
|
|
|
|
QTextDocument *document = m_textEdit->document();
|
|
|
|
@ -361,7 +367,7 @@ void NoteEditorLogic::uncheckTaskInLine(int lineNumber)
|
|
|
|
|
cursor.insertText(" ");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 替换某行之间的文本
|
|
|
|
|
void NoteEditorLogic::replaceTextBetweenLines(int startLinePosition, int endLinePosition,
|
|
|
|
|
QString &newText)
|
|
|
|
|
{
|
|
|
|
@ -373,7 +379,7 @@ void NoteEditorLogic::replaceTextBetweenLines(int startLinePosition, int endLine
|
|
|
|
|
cursor.removeSelectedText();
|
|
|
|
|
cursor.insertText(newText);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 更新任务文本
|
|
|
|
|
void NoteEditorLogic::updateTaskText(int startLinePosition, int endLinePosition,
|
|
|
|
|
const QString &newText)
|
|
|
|
|
{
|
|
|
|
@ -419,7 +425,7 @@ void NoteEditorLogic::updateTaskText(int startLinePosition, int endLinePosition,
|
|
|
|
|
checkForTasksInEditor();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 添加新任务
|
|
|
|
|
void NoteEditorLogic::addNewTask(int startLinePosition, const QString newTaskText)
|
|
|
|
|
{
|
|
|
|
|
QString newText = "\n- [ ] " + newTaskText;
|
|
|
|
@ -435,7 +441,7 @@ void NoteEditorLogic::addNewTask(int startLinePosition, const QString newTaskTex
|
|
|
|
|
|
|
|
|
|
checkForTasksInEditor();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 移除某行之间的文本
|
|
|
|
|
void NoteEditorLogic::removeTextBetweenLines(int startLinePosition, int endLinePosition)
|
|
|
|
|
{
|
|
|
|
|
if (startLinePosition < 0 || endLinePosition < startLinePosition) {
|
|
|
|
@ -453,13 +459,13 @@ void NoteEditorLogic::removeTextBetweenLines(int startLinePosition, int endLineP
|
|
|
|
|
}
|
|
|
|
|
cursor.removeSelectedText();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 移除任务
|
|
|
|
|
void NoteEditorLogic::removeTask(int startLinePosition, int endLinePosition)
|
|
|
|
|
{
|
|
|
|
|
removeTextBetweenLines(startLinePosition, endLinePosition);
|
|
|
|
|
checkForTasksInEditor();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 添加新列
|
|
|
|
|
void NoteEditorLogic::addNewColumn(int startLinePosition, const QString &columnTitle)
|
|
|
|
|
{
|
|
|
|
|
if (startLinePosition < 0)
|
|
|
|
@ -483,7 +489,7 @@ void NoteEditorLogic::addNewColumn(int startLinePosition, const QString &columnT
|
|
|
|
|
|
|
|
|
|
checkForTasksInEditor();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 移除列
|
|
|
|
|
void NoteEditorLogic::removeColumn(int startLinePosition, int endLinePosition)
|
|
|
|
|
{
|
|
|
|
|
removeTextBetweenLines(startLinePosition, endLinePosition);
|
|
|
|
@ -500,7 +506,7 @@ void NoteEditorLogic::removeColumn(int startLinePosition, int endLinePosition)
|
|
|
|
|
|
|
|
|
|
checkForTasksInEditor();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 更新列标题
|
|
|
|
|
void NoteEditorLogic::updateColumnTitle(int lineNumber, const QString &newText)
|
|
|
|
|
{
|
|
|
|
|
QTextDocument *document = m_textEdit->document();
|
|
|
|
@ -531,7 +537,7 @@ void NoteEditorLogic::updateColumnTitle(int lineNumber, const QString &newText)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 向文本编辑器添加无标题列
|
|
|
|
|
void NoteEditorLogic::addUntitledColumnToTextEditor(int startLinePosition)
|
|
|
|
|
{
|
|
|
|
|
QString columnTitle = "# Untitled\n\n";
|
|
|
|
@ -544,7 +550,7 @@ void NoteEditorLogic::addUntitledColumnToTextEditor(int startLinePosition)
|
|
|
|
|
cursor.insertText(columnTitle);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 向 JSON 数据添加新列
|
|
|
|
|
void NoteEditorLogic::appendNewColumn(QJsonArray &data, QJsonObject ¤tColumn,
|
|
|
|
|
QString ¤tTitle, QJsonArray &tasks)
|
|
|
|
|
{
|
|
|
|
@ -571,7 +577,7 @@ void NoteEditorLogic::appendNewColumn(QJsonArray &data, QJsonObject ¤tColu
|
|
|
|
|
// {"checked":false,"text":"todo 2", "taskStartine": 4, "taskEndLine": 4}}]
|
|
|
|
|
// },
|
|
|
|
|
// ])
|
|
|
|
|
bool NoteEditorLogic::checkForTasksInEditor()
|
|
|
|
|
bool NoteEditorLogic::checkForTasksInEditor()// 检查编辑器中的任务
|
|
|
|
|
{
|
|
|
|
|
QStringList lines = m_textEdit->toPlainText().split("\n");
|
|
|
|
|
QJsonArray data;
|
|
|
|
@ -657,13 +663,13 @@ bool NoteEditorLogic::checkForTasksInEditor()
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
// 将字符串转换为 QDateTime
|
|
|
|
|
QDateTime NoteEditorLogic::getQDateTime(const QString &date)
|
|
|
|
|
{
|
|
|
|
|
QDateTime dateTime = QDateTime::fromString(date, Qt::ISODate);
|
|
|
|
|
return dateTime;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 显示当前笔记的标签列表
|
|
|
|
|
void NoteEditorLogic::showTagListForCurrentNote()
|
|
|
|
|
{
|
|
|
|
|
if (currentEditingNoteId() != SpecialNodeID::InvalidNodeId) {
|
|
|
|
@ -678,7 +684,7 @@ void NoteEditorLogic::showTagListForCurrentNote()
|
|
|
|
|
m_tagListView->setVisible(false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool NoteEditorLogic::isInEditMode() const
|
|
|
|
|
bool NoteEditorLogic::isInEditMode() const// 获取是否处于编辑模式
|
|
|
|
|
{
|
|
|
|
|
if (m_currentNotes.size() == 1) {
|
|
|
|
|
return true;
|
|
|
|
@ -686,26 +692,26 @@ bool NoteEditorLogic::isInEditMode() const
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int NoteEditorLogic::currentMinimumEditorPadding() const
|
|
|
|
|
int NoteEditorLogic::currentMinimumEditorPadding() const// 获取当前最小编辑器填充
|
|
|
|
|
{
|
|
|
|
|
return m_currentMinimumEditorPadding;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 设置当前最小编辑器填充
|
|
|
|
|
void NoteEditorLogic::setCurrentMinimumEditorPadding(int newCurrentMinimumEditorPadding)
|
|
|
|
|
{
|
|
|
|
|
m_currentMinimumEditorPadding = newCurrentMinimumEditorPadding;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 获取当前可适应的编辑器填充
|
|
|
|
|
int NoteEditorLogic::currentAdaptableEditorPadding() const
|
|
|
|
|
{
|
|
|
|
|
return m_currentAdaptableEditorPadding;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 设置当前可适应的编辑器填充
|
|
|
|
|
void NoteEditorLogic::setCurrentAdaptableEditorPadding(int newCurrentAdaptableEditorPadding)
|
|
|
|
|
{
|
|
|
|
|
m_currentAdaptableEditorPadding = newCurrentAdaptableEditorPadding;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 获取当前编辑的笔记 ID
|
|
|
|
|
int NoteEditorLogic::currentEditingNoteId() const
|
|
|
|
|
{
|
|
|
|
|
if (isInEditMode()) {
|
|
|
|
@ -713,7 +719,7 @@ int NoteEditorLogic::currentEditingNoteId() const
|
|
|
|
|
}
|
|
|
|
|
return SpecialNodeID::InvalidNodeId;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 将笔记保存到数据库
|
|
|
|
|
void NoteEditorLogic::saveNoteToDB()
|
|
|
|
|
{
|
|
|
|
|
if (currentEditingNoteId() != SpecialNodeID::InvalidNodeId && m_isContentModified
|
|
|
|
@ -722,7 +728,7 @@ void NoteEditorLogic::saveNoteToDB()
|
|
|
|
|
m_isContentModified = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 关闭编辑器
|
|
|
|
|
void NoteEditorLogic::closeEditor()
|
|
|
|
|
{
|
|
|
|
|
if (currentEditingNoteId() != SpecialNodeID::InvalidNodeId) {
|
|
|
|
@ -737,7 +743,7 @@ void NoteEditorLogic::closeEditor()
|
|
|
|
|
m_textEdit->blockSignals(false);
|
|
|
|
|
m_tagListModel->setModelData({});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 笔记标签列表发生变化时的处理
|
|
|
|
|
void NoteEditorLogic::onNoteTagListChanged(int noteId, const QSet<int> &tagIds)
|
|
|
|
|
{
|
|
|
|
|
if (currentEditingNoteId() == noteId) {
|
|
|
|
@ -745,7 +751,7 @@ void NoteEditorLogic::onNoteTagListChanged(int noteId, const QSet<int> &tagIds)
|
|
|
|
|
showTagListForCurrentNote();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 删除当前笔记
|
|
|
|
|
void NoteEditorLogic::deleteCurrentNote()
|
|
|
|
|
{
|
|
|
|
|
if (isTempNote()) {
|
|
|
|
@ -777,7 +783,7 @@ void NoteEditorLogic::deleteCurrentNote()
|
|
|
|
|
* \param str
|
|
|
|
|
* \return
|
|
|
|
|
*/
|
|
|
|
|
QString NoteEditorLogic::getFirstLine(const QString &str)
|
|
|
|
|
QString NoteEditorLogic::getFirstLine(const QString &str)// 获取文本的首行
|
|
|
|
|
{
|
|
|
|
|
QString text = str.trimmed();
|
|
|
|
|
if (text.isEmpty()) {
|
|
|
|
@ -787,7 +793,7 @@ QString NoteEditorLogic::getFirstLine(const QString &str)
|
|
|
|
|
return ts.readLine(FIRST_LINE_MAX);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString NoteEditorLogic::getSecondLine(const QString &str)
|
|
|
|
|
QString NoteEditorLogic::getSecondLine(const QString &str)// 获取文本的第二行
|
|
|
|
|
{
|
|
|
|
|
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
|
|
|
|
|
auto sl = str.split("\n", QString::SkipEmptyParts);
|
|
|
|
@ -809,7 +815,7 @@ QString NoteEditorLogic::getSecondLine(const QString &str)
|
|
|
|
|
QTextStream ts(&text);
|
|
|
|
|
return ts.readLine(FIRST_LINE_MAX);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 设置主题
|
|
|
|
|
void NoteEditorLogic::setTheme(Theme::Value theme, QColor textColor, qreal fontSize)
|
|
|
|
|
{
|
|
|
|
|
m_tagListDelegate->setTheme(theme);
|
|
|
|
@ -839,7 +845,7 @@ void NoteEditorLogic::setTheme(Theme::Value theme, QColor textColor, qreal fontS
|
|
|
|
|
m_textEdit->verticalScrollBar()->setValue(verticalScrollBarValueToRestore);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 获取笔记编辑日期
|
|
|
|
|
QString NoteEditorLogic::getNoteDateEditor(const QString &dateEdited)
|
|
|
|
|
{
|
|
|
|
|
QDateTime dateTimeEdited(getQDateTime(dateEdited));
|
|
|
|
@ -847,7 +853,7 @@ QString NoteEditorLogic::getNoteDateEditor(const QString &dateEdited)
|
|
|
|
|
|
|
|
|
|
return usLocale.toString(dateTimeEdited, QStringLiteral("MMMM d, yyyy, h:mm A"));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 高亮搜索结果
|
|
|
|
|
void NoteEditorLogic::highlightSearch() const
|
|
|
|
|
{
|
|
|
|
|
QString searchString = m_searchEdit->text();
|
|
|
|
@ -869,7 +875,7 @@ void NoteEditorLogic::highlightSearch() const
|
|
|
|
|
m_textEdit->setExtraSelections(extraSelections);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 获取是否是临时笔记
|
|
|
|
|
bool NoteEditorLogic::isTempNote() const
|
|
|
|
|
{
|
|
|
|
|
if (currentEditingNoteId() != SpecialNodeID::InvalidNodeId && m_currentNotes[0].isTempNote()) {
|
|
|
|
|