notelistmodel.h

develop
zhangshuoshuo 1 month ago
parent a46534035c
commit 798d8d6476

@ -1,170 +1,232 @@
#include "notelistmodel.h"
#include <QDebug>
#include "nodepath.h"
#include <QTimer>
#include <QMimeData>
#include <QDebug> // 包含调试输出头文件
#include "nodepath.h" // 包含节点路径头文件
#include <QTimer> // 包含定时器头文件
#include <QMimeData> // 包含MIME数据头文件
NoteListModel::NoteListModel(QObject *parent) : QAbstractListModel(parent) { }
NoteListModel::~NoteListModel() { }
// 添加笔记
QModelIndex NoteListModel::addNote(const NodeData &note)
{
// 如果笔记不是被钉住的
if (!note.isPinnedNote()) {
// 获取当前行数
const int rowCnt = rowCount();
// 开始插入行
beginInsertRows(QModelIndex(), rowCnt, rowCnt);
// 将笔记添加到笔记列表
m_noteList << note;
// 结束插入行
endInsertRows();
// 发出行插入信号
emit rowsInsertedC({ createIndex(rowCnt, 0) });
// 发出行数变化信号
emit rowCountChanged();
// 返回新笔记的模型索引
return createIndex(rowCnt, 0);
} else {
// 获取被钉住的笔记列表的大小
const int rowCnt = m_pinnedList.size();
// 开始插入行
beginInsertRows(QModelIndex(), rowCnt, rowCnt);
// 将笔记添加到被钉住的笔记列表
m_pinnedList << note;
// 结束插入行
endInsertRows();
// 发出行插入信号
emit rowsInsertedC({ createIndex(rowCnt, 0) });
// 发出行数变化信号
emit rowCountChanged();
// 返回新笔记的模型索引
return createIndex(rowCnt, 0);
}
}
// 在指定行插入笔记
QModelIndex NoteListModel::insertNote(const NodeData &note, int row)
{
{ // 如果笔记是被钉住的
if (note.isPinnedNote()) {
// 如果指定行大于被钉住的笔记列表的大小,则设置为列表的末尾
if (row > m_pinnedList.size()) {
row = m_pinnedList.size();
} else if (row < 0) {
} else if (row < 0) {// 如果指定行小于0则设置为列表的开头
row = 0;
}
// 开始在被钉住的笔记列表的指定行插入一行
beginInsertRows(QModelIndex(), row, row);
// 将笔记插入到被钉住的笔记列表的指定行
m_pinnedList.insert(row, note);
// 结束插入行
endInsertRows();
// 发出新笔记插入信号
emit rowsInsertedC({ createIndex(row, 0) });
// 发出行数变化信号
emit rowCountChanged();
// 返回新笔记的模型索引
return createIndex(row, 0);
} else {
// 如果指定行小于被钉住的笔记列表的大小,则设置为被钉住的笔记列表的末尾
if (row < m_pinnedList.size()) {
row = m_pinnedList.size();
} else if (row > (m_pinnedList.size() + m_noteList.size())) {
// 如果指定行大于笔记列表的总大小,则设置为笔记列表的末尾
row = m_pinnedList.size() + m_noteList.size();
}
// 开始在笔记列表的指定行插入一行
beginInsertRows(QModelIndex(), row, row);
// 将笔记插入到笔记列表的指定行
m_noteList.insert(row - m_pinnedList.size(), note);
// 结束插入行
endInsertRows();
// 发出新笔记插入信号
emit rowsInsertedC({ createIndex(row, 0) });
// 发出行数变化信号
emit rowCountChanged();
// 返回新笔记的模型索引
return createIndex(row, 0);
}
}
// 获取指定模型索引的笔记数据
const NodeData &NoteListModel::getNote(const QModelIndex &index) const
{
// 获取模型索引的行号
auto row = index.row();
// 如果行号小于被钉住的笔记列表的大小,则从被钉住的笔记列表中获取笔记数据
if (row < m_pinnedList.size()) {
return m_pinnedList.at(row);
} else {
} else {// 否则从笔记列表中获取笔记数据
row = row - m_pinnedList.size();
return m_noteList.at(row);
}
}
// 获取指定ID的笔记的模型索引
QModelIndex NoteListModel::getNoteIndex(int id) const
{
{ // 在被钉住的笔记列表中查找ID匹配的笔记
for (int i = 0; i < m_pinnedList.size(); ++i) {
if (m_pinnedList[i].id() == id) {
return createIndex(i, 0);
}
}
// 在笔记列表中查找ID匹配的笔记
for (int i = 0; i < m_noteList.size(); ++i) {
if (m_noteList[i].id() == id) {
return createIndex(i + m_pinnedList.size(), 0);
}
}
}// 如果未找到匹配的笔记,则返回无效的模型索引
return QModelIndex{};
}
// 设置笔记列表和列表视图信息
void NoteListModel::setListNote(const QVector<NodeData> &notes, const ListViewInfo &inf)
{
// 开始重置模型
beginResetModel();
// 清空被钉住的笔记列表
m_pinnedList.clear();
// 清空笔记列表
m_noteList.clear();
// 设置列表视图信息
m_listViewInfo = inf;
// 如果不在标签中且不在回收站文件夹中
if ((!m_listViewInfo.isInTag)
&& (m_listViewInfo.parentFolderId != SpecialNodeID::TrashFolder)) {
// 遍历笔记列表
for (const auto &note : qAsConst(notes)) {
// 如果笔记是被钉住的,则添加到被钉住的笔记列表
if (note.isPinnedNote()) {
m_pinnedList.append(note);
} else {
} else {// 否则添加到笔记列表
m_noteList.append(note);
}
}
} else {
} else { // 否则直接将笔记列表赋值给笔记列表
m_noteList = notes;
}
// 按升序排序
sort(0, Qt::AscendingOrder);
// 结束重置模型
endResetModel();
// 发出行数变化信号
emit rowCountChanged();
}
// 移除指定模型索引列表的笔记
void NoteListModel::removeNotes(const QModelIndexList &noteIndexes)
{
emit requestRemoveNotes(noteIndexes);
emit requestRemoveNotes(noteIndexes);// 发出请求移除笔记信号
}
// 移动行
bool NoteListModel::moveRow(const QModelIndex &sourceParent, int sourceRow,
const QModelIndex &destinationParent, int destinationChild)
{
{// 如果源行号或目标行号超出范围则返回false
if (sourceRow < 0 || sourceRow >= rowCount() || destinationChild < 0
|| destinationChild >= rowCount()) {
return false;
}
}// 如果源行号和目标行号都在被钉住的笔记列表范围内
if (sourceRow < m_pinnedList.size() && destinationChild < m_pinnedList.size()) {
if (beginMoveRows(sourceParent, sourceRow, sourceRow, destinationParent,
destinationChild)) {
destinationChild)) {// 在被钉住的笔记列表中移动笔记
m_pinnedList.move(sourceRow, destinationChild);
// 结束移动行
endMoveRows();
// 发出行即将被移动信号
emit rowsAboutToBeMovedC({ createIndex(sourceRow, 0) });
// 发出行移动后信号
emit rowsMovedC({ createIndex(destinationChild, 0) });
emit rowCountChanged();
// 发出行数变化信号
return true;
}
}
// 如果源行号和目标行号都在笔记列表范围内
if (sourceRow >= m_pinnedList.size() && destinationChild >= m_pinnedList.size()) {
// 调整源行号和目标行号以适应笔记列表的范围
sourceRow = sourceRow - m_pinnedList.size();
destinationChild = destinationChild - m_pinnedList.size();
// 开始移动行
if (beginMoveRows(sourceParent, sourceRow, sourceRow, destinationParent,
destinationChild)) {
// 在笔记列表中移动笔记
m_noteList.move(sourceRow, destinationChild);
endMoveRows();
// 结束移动行
// 发出行即将被移动信号
emit rowsAboutToBeMovedC({ createIndex(sourceRow, 0) });
// 发出行移动后信号
emit rowsMovedC({ createIndex(destinationChild + 1, 0) });
// 发出行数变化信号
emit rowCountChanged();
return true;
}
}
// 如果源行号和目标行号不在同一范围内则返回false
return false;
}
// 清空笔记列表
void NoteListModel::clearNotes()
{
// 开始重置模型
beginResetModel();
// 清空被钉住的笔记列表
m_pinnedList.clear();
// 清空笔记列表
m_noteList.clear();
// 结束重置模型
endResetModel();
// 发出行数变化信号
emit rowCountChanged();
}
// 获取指定模型索引的数据的实现
QVariant NoteListModel::data(const QModelIndex &index, int role) const
{
// 如果模型索引的行号超出范围则返回空的QVariant
if (index.row() < 0 || index.row() >= (m_noteList.count() + m_pinnedList.count())) {
return QVariant();
}
// 如果角色超出范围则返回空的QVariant
if (role < NoteID || role > NoteIsPinned) {
return QVariant();
}
// 获取指定行的笔记数据
const NodeData &note = getRef(index.row());
// 根据角色返回相应的数据
if (role == NoteID) {
return note.id();
} else if (role == NoteFullTitle) {
@ -198,14 +260,16 @@ QVariant NoteListModel::data(const QModelIndex &index, int role) const
return QVariant();
}
// 设置指定模型索引的数据的实现
bool NoteListModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
// 如果模型索引的行号超出范围则返回false
if (index.row() < 0 || index.row() >= (m_noteList.count() + m_pinnedList.count())) {
return false;
}
// 获取指定行的笔记数据的引用
NodeData &note = getRef(index.row());
// 根据角色设置相应的数据
if (role == NoteID) {
note.setId(value.toInt());
} else if (role == NoteFullTitle) {
@ -231,37 +295,44 @@ bool NoteListModel::setData(const QModelIndex &index, const QVariant &value, int
} else {
return false;
}
// 发出数据变化信号
emit dataChanged(this->index(index.row()), this->index(index.row()), QVector<int>(1, role));
return true;
}
// 获取指定模型索引的项标志
Qt::ItemFlags NoteListModel::flags(const QModelIndex &index) const
{
// 如果模型索引无效,则返回启用和可放置的项标志
if (!index.isValid()) {
return Qt::ItemIsEnabled | Qt::ItemIsDropEnabled;
}
// 返回基类的项标志,并添加可编辑、可拖拽和可放置的项标志
return QAbstractListModel::flags(index) | Qt::ItemIsEditable | Qt::ItemIsDragEnabled
| Qt::ItemIsDropEnabled;
}
// 获取行数
int NoteListModel::rowCount(const QModelIndex &parent) const
{
// 忽略parent参数
Q_UNUSED(parent)
// 返回笔记列表和被钉住的笔记列表的总大小
return m_noteList.size() + m_pinnedList.size();
}
// 排序
void NoteListModel::sort(int column, Qt::SortOrder order)
{
// 忽略column和order参数
Q_UNUSED(column)
Q_UNUSED(order)
// 如果在回收站文件夹中
if (m_listViewInfo.parentFolderId == SpecialNodeID::TrashFolder) {
// 按删除日期时间降序排序笔记列表
std::stable_sort(m_noteList.begin(), m_noteList.end(),
[](const NodeData &lhs, const NodeData &rhs) {
return lhs.deletionDateTime() > rhs.deletionDateTime();
});
} else {
} else {// 否则按相对位置升序排序被钉住的笔记列表
std::stable_sort(m_pinnedList.begin(), m_pinnedList.end(),
[this](const NodeData &lhs, const NodeData &rhs) {
if (isInAllNote()) {
@ -270,176 +341,217 @@ void NoteListModel::sort(int column, Qt::SortOrder order)
return lhs.relativePosition() < rhs.relativePosition();
}
});
// 按最后修改日期时间降序排序笔记列表
std::stable_sort(m_noteList.begin(), m_noteList.end(),
[](const NodeData &lhs, const NodeData &rhs) {
return lhs.lastModificationdateTime() > rhs.lastModificationdateTime();
});
}
// 发出数据变化信号
emit dataChanged(index(0), index(rowCount() - 1));
}
// 设置指定模型索引的笔记数据
void NoteListModel::setNoteData(const QModelIndex &index, const NodeData &note)
{
// 如果模型索引无效,则返回
if (!index.isValid()) {
return;
}
auto row = index.row();
auto row = index.row();// 获取模型索引的行号
// 如果行号小于被钉住的笔记列表的大小,则在被钉住的笔记列表中设置笔记数据
if (row < m_pinnedList.size()) {
m_pinnedList[row] = note;
} else {
} else { // 否则在笔记列表中设置笔记数据
row = row - m_pinnedList.size();
m_noteList[row] = note;
}
// 发出数据变化信号
emit dataChanged(this->index(index.row()), this->index(index.row()));
}
// 更新被钉住的笔记的相对位置的实现
void NoteListModel::updatePinnedRelativePosition()
{
// 遍历被钉住的笔记列表
for (int i = 0; i < m_pinnedList.size(); ++i) {
// 如果不在所有笔记中
if (!isInAllNote()) {
// 发出请求更新笔记的相对位置信号
emit requestUpdatePinnedRelPos(m_pinnedList[i].id(), i);
} else {
} else { // 否则发出请求更新笔记的相对位置(在所有笔记中)信号
emit requestUpdatePinnedRelPosAN(m_pinnedList[i].id(), i);
}
}
}
// 检查是否在所有笔记中
bool NoteListModel::isInAllNote() const
{
return (!m_listViewInfo.isInTag)
return (!m_listViewInfo.isInTag)// 如果不在标签中且在根文件夹中则返回true
&& (m_listViewInfo.parentFolderId == SpecialNodeID::RootFolder);
}
// 获取指定行的笔记数据的引用
NodeData &NoteListModel::getRef(int row)
{
// 如果行号小于被钉住的笔记列表的大小,则从被钉住的笔记列表中获取笔记数据的引用
if (row < m_pinnedList.size())
return m_pinnedList[row];
// 否则从笔记列表中获取笔记数据的引用
return m_noteList[row - m_pinnedList.size()];
}
// 获取指定行的笔记数据的常量引用
const NodeData &NoteListModel::getRef(int row) const
{
// 如果行号小于被钉住的笔记列表的大小,则从被钉住的笔记列表中获取笔记数据的常量引用
if (row < m_pinnedList.size())
return m_pinnedList[row];
// 否则从笔记列表中获取笔记数据的常量引用
return m_noteList[row - m_pinnedList.size()];
}
// 移除行
bool NoteListModel::removeRows(int row, int count, const QModelIndex &parent)
{
if (row < 0 || (row + count) > (m_pinnedList.size() + m_noteList.size())) {
if (row < 0 || (row + count) > (m_pinnedList.size() + m_noteList.size())) {// 如果行号或行数超出范围则返回false
return false;
}
beginRemoveRows(parent, row, row + count - 1);
for (int r = row; r < row + count; ++r) {
beginRemoveRows(parent, row, row + count - 1);// 开始移除行
for (int r = row; r < row + count; ++r) {// 遍历要移除的行
// 如果行号小于被钉住的笔记列表的大小,则从被钉住的笔记列表中移除笔记
if (r < m_pinnedList.size()) {
m_pinnedList.takeAt(r);
} else {
} else {// 否则从笔记列表中移除笔记
auto rr = r - m_pinnedList.size();
m_noteList.takeAt(rr);
}
}
}// 结束移除行
endRemoveRows();
emit rowCountChanged();
emit rowCountChanged();// 发出行数变化信号
return true;
}
// 获取支持的拖放操作
Qt::DropActions NoteListModel::supportedDropActions() const
{
return Qt::MoveAction;
return Qt::MoveAction;// 返回移动操作
}
// 获取支持的拖拽操作
Qt::DropActions NoteListModel::supportedDragActions() const
{
return Qt::MoveAction;
return Qt::MoveAction;// 返回移动操作
}
// 获取支持的MIME类型
QStringList NoteListModel::mimeTypes() const
{
return QStringList() << NOTE_MIME;
return QStringList() << NOTE_MIME;// 返回包含笔记MIME类型的列表
}
// 获取指定模型索引列表的MIME数据
QMimeData *NoteListModel::mimeData(const QModelIndexList &indexes) const
{
// 如果模型索引列表为空则返回nullptr
if (indexes.isEmpty()) {
return nullptr;
}
QStringList d;
for (const auto &index : indexes) {
QStringList d;// 创建一个字符串列表来存储笔记ID
for (const auto &index : indexes) {// 遍历模型索引列表
// 获取笔记ID并添加到字符串列表中
auto id = index.data(NoteListModel::NoteID).toInt();
d.append(QString::number(id));
}
if (d.isEmpty()) {
return nullptr;
return nullptr;// 如果字符串列表为空则返回nullptr
}
QMimeData *mimeData = new QMimeData;
mimeData->setData(NOTE_MIME, d.join(QStringLiteral(PATH_SEPARATOR)).toUtf8());
QMimeData *mimeData = new QMimeData;// 创建一个新的QMimeData对象
mimeData->setData(NOTE_MIME, d.join(QStringLiteral(PATH_SEPARATOR)).toUtf8());// 将笔记ID列表设置为MIME数据
return mimeData;
}
// 处理MIME数据的拖放
bool NoteListModel::dropMimeData(const QMimeData *mime, Qt::DropAction action, int row, int column,
const QModelIndex &parent)
{
{// 忽略column参数
Q_UNUSED(column);
// 如果MIME数据不包含笔记MIME类型或操作不是移动操作则返回false
if (!(mime->hasFormat(NOTE_MIME) && action == Qt::MoveAction)) {
return false;
}
// 如果行号为-1则根据parent的有效性确定行号
if (row == -1) {
// valid index: drop onto item
// 如果parent有效则行号为parent的行号
if (parent.isValid()) {
row = parent.row();
} else {
} else { // 否则行号为模型的行数
// invalid index: append at bottom, after last toplevel
row = rowCount(parent);
}
}
// 根据行号确定是否移动到被钉住的笔记列表
bool toPinned = false;
if (row >= m_pinnedList.size()) {
toPinned = false;
} else {
toPinned = true;
}
}// 获取笔记ID列表
auto idl = QString::fromUtf8(mime->data(NOTE_MIME)).split(QStringLiteral(PATH_SEPARATOR));
// 创建一个QSet来存储移动的笔记ID
QSet<int> movedIds;
// 创建一个QModelIndexList来存储移动的笔记的模型索引
QModelIndexList idxe;
// 遍历笔记ID列表
for (const auto &id_s : qAsConst(idl)) {
// 获取笔记ID并添加到模型索引列表中
auto nodeId = id_s.toInt();
idxe.append(getNoteIndex(nodeId));
}
// 发出行即将被移动信号
emit rowsAboutToBeMovedC(idxe);
// 开始重置模型
beginResetModel();
// 如果移动到被钉住的笔记列表
if (toPinned) {
// 遍历移动的笔记的模型索引列表
for (const auto &index : qAsConst(idxe)) {
// 获取笔记数据的引用
auto &note = getRef(index.row());
// 如果笔记不是被钉住的,则设置为被钉住的
if (!note.isPinnedNote()) {
note.setIsPinnedNote(true);
// 发出请求更新笔记的钉住状态信号
emit requestUpdatePinned(note.id(), true);
// 将笔记从笔记列表移动到被钉住的笔记列表的开头
m_pinnedList.prepend(m_noteList.takeAt(index.row() - m_pinnedList.size()));
}
}
// 遍历笔记ID列表
for (const auto &id_s : qAsConst(idl)) {
// 获取笔记ID
auto nodeId = id_s.toInt();
// 遍历被钉住的笔记列表
for (int i = 0; i < m_pinnedList.size(); ++i) {
// 如果找到匹配的笔记,则移动到指定行
if (m_pinnedList[i].id() == nodeId) {
m_pinnedList.move(i, row);
break;
}
}
movedIds.insert(nodeId);
movedIds.insert(nodeId);// 将笔记ID添加到移动的笔记ID集合中
}
} else {
} else { // 否则移动到笔记列表
// 遍历移动的笔记的模型索引列表
for (const auto &index : qAsConst(idxe)) {
// 获取笔记数据的引用
auto &note = getRef(index.row());
// 将笔记ID添加到移动的笔记ID集合中
movedIds.insert(note.id());
// 如果笔记是被钉住的,则设置为不是被钉住的
if (!note.isPinnedNote()) {
continue;
}
note.setIsPinnedNote(false);
// 发出请求更新笔记的钉住状态信号
emit requestUpdatePinned(note.id(), false);
// 根据当前视图确定插入位置
int destinationChild = 0;
if (m_listViewInfo.parentFolderId == SpecialNodeID::TrashFolder) {
// 如果在回收站文件夹中,则按删除日期时间排序
auto lastMod = index.data(NoteDeletionDateTime).toDateTime();
for (destinationChild = 0; destinationChild < m_noteList.size();
++destinationChild) {
@ -447,7 +559,7 @@ bool NoteListModel::dropMimeData(const QMimeData *mime, Qt::DropAction action, i
break;
}
}
} else {
} else {// 否则按最后修改日期时间排序
auto lastMod = index.data(NoteLastModificationDateTime).toDateTime();
for (destinationChild = 0; destinationChild < m_noteList.size();
++destinationChild) {
@ -455,99 +567,141 @@ bool NoteListModel::dropMimeData(const QMimeData *mime, Qt::DropAction action, i
break;
}
}
}
}// 将笔记从被钉住的笔记列表移动到笔记列表的指定位置
m_noteList.insert(destinationChild, m_pinnedList.takeAt(index.row()));
}
}
// 结束重置模型
endResetModel();
// 创建一个QModelIndexList来存储移动后的笔记的模型索引
QModelIndexList destinations;
// 遍历移动的笔记ID集合
for (const auto &id : movedIds) {
// 获取笔记的模型索引并添加到模型索引列表中
auto index = getNoteIndex(id);
if (!index.isValid()) {
continue;
}
destinations.append(index);
}
// 发出选择笔记信号
emit selectNotes(destinations);
// 发出行移动后信号
emit rowsMovedC(destinations);
// 更新被钉住的笔记的相对位置
updatePinnedRelativePosition();
return true;
}
// 获取第一个未被钉住的笔记的模型索引
QModelIndex NoteListModel::getFirstUnpinnedNote() const
{
{// 如果笔记列表不为空,则返回第一个未被钉住的笔记的模型索引
if (!m_noteList.isEmpty()) {
return createIndex(m_pinnedList.size(), 0);
} else {
} else {// 否则返回无效的模型索引
return QModelIndex();
}
}
// 检查是否有被钉住的笔记
bool NoteListModel::hasPinnedNote() const
{
// 如果不在标签中且不在回收站文件夹中
if ((!m_listViewInfo.isInTag)
&& (m_listViewInfo.parentFolderId == SpecialNodeID::TrashFolder)) {
// 回收站文件夹中没有被钉住的笔记返回false
// Trash don't have pinned note
return false;
}
}// 如果被钉住的笔记列表不为空则返回true
return !m_pinnedList.isEmpty();
}
// 设置指定模型索引列表的笔记的钉住状态的实现
void NoteListModel::setNotesIsPinned(const QModelIndexList &indexes, bool isPinned)
{
// 发出请求关闭笔记编辑器信号
emit requestCloseNoteEditor(indexes);
// 创建一个QSet来存储需要移动的笔记ID
QSet<int> needMovingIds;
// 创建一个QModelIndexList来存储需要移动的笔记的模型索引
QModelIndexList needMovingIndexes;
// 遍历模型索引列表
for (const auto &index : indexes) {
// 如果模型索引有效
if (index.isValid()) {
// 获取笔记数据的引用
NodeData &note = getRef(index.row());
// 如果笔记的钉住状态需要改变
if (note.isPinnedNote() != isPinned) {
// 将笔记ID添加到需要移动的笔记ID集合中
needMovingIds.insert(note.id());
// 将模型索引添加到需要移动的笔记的模型索引列表中
needMovingIndexes.append(index);
// 设置笔记的钉住状态
note.setIsPinnedNote(isPinned);
// 发出请求更新笔记的钉住状态信号
emit requestUpdatePinned(note.id(), isPinned);
}
}
}
// 如果设置为被钉住的
if (isPinned) {
// 发出行即将被移动信号
emit rowsAboutToBeMovedC(needMovingIndexes);
// 开始重置模型
beginResetModel();
// 遍历需要移动的笔记ID集合
for (const auto &id : qAsConst(needMovingIds)) {
// 获取笔记的模型索引
auto index = getNoteIndex(id);
if (!index.isValid()) {
continue;
}
// 获取源行号
int sourceRow = index.row();
// 如果源行号超出范围,则继续下一个
if (sourceRow < 0 || sourceRow >= rowCount()) {
continue;
}
// 将笔记从笔记列表移动到被钉住的笔记列表的开头
m_pinnedList.prepend(m_noteList.takeAt(sourceRow - m_pinnedList.size()));
}
// 结束重置模型
endResetModel();
// 创建一个QModelIndexList来存储移动后的笔记的模型索引
QModelIndexList destinations;
for (const auto &id : needMovingIds) {
// 遍历需要移动的笔记ID集合
for (const auto &id : qAsConst(needMovingIds)) {
// 获取笔记的模型索引并添加到模型索引列表中
auto index = getNoteIndex(id);
if (!index.isValid()) {
continue;
}
destinations.append(index);
}
// 发出选择笔记信号
emit selectNotes(destinations);
// 发出行移动后信号
emit rowsMovedC(destinations);
// 发出行数变化信号
emit rowCountChanged();
// 更新被钉住的笔记的相对位置
updatePinnedRelativePosition();
} else {
} else { // 否则设置为不是被钉住的
// 发出行即将被移动信号
emit rowsAboutToBeMovedC(needMovingIndexes);
// 开始重置模型
beginResetModel();
// 遍历需要移动的笔记ID集合
for (const auto &id : qAsConst(needMovingIds)) {
// 获取笔记的模型索引
auto index = getNoteIndex(id);
if (!index.isValid()) {
continue;
}
int destinationChild = 0;
if (m_listViewInfo.parentFolderId == SpecialNodeID::TrashFolder) {
// 如果在回收站文件夹中,则按删除日期时间排序
auto lastMod = index.data(NoteDeletionDateTime).toDateTime();
for (destinationChild = 0; destinationChild < m_noteList.size();
++destinationChild) {
@ -556,7 +710,7 @@ void NoteListModel::setNotesIsPinned(const QModelIndexList &indexes, bool isPinn
break;
}
}
} else {
} else {// 否则按最后修改日期时间排序
auto lastMod = index.data(NoteLastModificationDateTime).toDateTime();
for (destinationChild = 0; destinationChild < m_noteList.size();
++destinationChild) {
@ -565,72 +719,89 @@ void NoteListModel::setNotesIsPinned(const QModelIndexList &indexes, bool isPinn
break;
}
}
}
}// 将笔记从被钉住的笔记列表移动到笔记列表的指定位置
m_noteList.insert(destinationChild, m_pinnedList.takeAt(index.row()));
}
// 结束重置模型
endResetModel();
// 创建一个QModelIndexList来存储移动后的笔记的模型索引
QModelIndexList destinations;
// 遍历需要移动的笔记ID集合
for (const auto &id : needMovingIds) {
// 获取笔记的模型索引并添加到模型索引列表中
auto index = getNoteIndex(id);
if (!index.isValid()) {
continue;
}
destinations.append(index);
}
// 发出选择笔记信号
emit selectNotes(destinations);
// 发出行移动后信号
emit rowsMovedC(destinations);
// 发出行数变化信号
emit rowCountChanged();
// 更新被钉住的笔记的相对位置
updatePinnedRelativePosition();
}
}
// 检查指定模型索引的笔记是否具有标签
bool NoteListModel::noteIsHaveTag(const QModelIndex &index) const
{
{// 如果模型索引无效则返回false
if (index.row() < 0 || index.row() >= (m_noteList.count() + m_pinnedList.count())) {
return false;
}
// 获取模型索引的行号
auto row = index.row();
// 创建一个NodeData对象来存储笔记数据
NodeData note;
// 如果行号小于被钉住的笔记列表的大小,则从被钉住的笔记列表中获取笔记数据
if (row < m_pinnedList.size()) {
note = m_pinnedList[row];
} else {
} else { // 否则从笔记列表中获取笔记数据
row = row - m_pinnedList.size();
note = m_noteList[row];
}
return !note.tagIds().empty();
return !note.tagIds().empty();// 如果笔记的标签列表不为空则返回true
}
// 检查指定模型索引的笔记是否为第一个被钉住的笔记
bool NoteListModel::isFirstPinnedNote(const QModelIndex &index) const
{
// 如果模型索引无效则返回false
if (!index.isValid()) {
return false;
}
// 如果模型索引的行号大于0则返回false
if (index.row() > 0) {
return false;
}
// 获取指定行的笔记数据的常量引用
const NodeData &note = getRef(index.row());
// 如果模型索引的行号为0且笔记是被钉住的则返回true
if (index.row() == 0 && note.isPinnedNote()) {
return true;
}
return false;
}
// 检查指定模型索引的笔记是否为第一个未被钉住的笔记
bool NoteListModel::isFirstUnpinnedNote(const QModelIndex &index) const
{
{// 如果模型索引无效则返回false
if (!index.isValid()) {
return false;
}
// 获取指定行的笔记数据的常量引用
const NodeData &note = getRef(index.row());
if ((index.row() - m_pinnedList.size()) == 0 && !note.isPinnedNote()) {
if ((index.row() - m_pinnedList.size()) == 0 && !note.isPinnedNote()) {// 如果模型索引的行号减去被钉住的笔记列表的大小为0且笔记不是被钉住的则返回true
return true;
}
return false;
}
// 获取第一个被钉住的笔记的模型索引
QModelIndex NoteListModel::getFirstPinnedNote() const
{
if (m_pinnedList.isEmpty()) {
if (m_pinnedList.isEmpty()) {// 如果被钉住的笔记列表不为空,则返回第一个被钉住的笔记的模型索引
return QModelIndex();
}
}// 否则返回无效的模型索引
return createIndex(0, 0);
}

@ -9,80 +9,115 @@ class NoteListModel : public QAbstractListModel
{
Q_OBJECT
public:
// 定义一个枚举类型NoteRoles用于指定模型的角色
enum NoteRoles {
NoteID = Qt::UserRole + 1,
NoteFullTitle,
NoteCreationDateTime,
NoteLastModificationDateTime,
NoteDeletionDateTime,
NoteContent,
NoteScrollbarPos,
NoteTagsList,
NoteIsTemp,
NoteParentName,
NoteTagListScrollbarPos,
NoteIsPinned,
NoteID = Qt::UserRole + 1, // 笔记ID角色
NoteFullTitle, // 笔记完整标题角色
NoteCreationDateTime, // 笔记创建日期时间角色
NoteLastModificationDateTime, // 笔记最后修改日期时间角色
NoteDeletionDateTime, // 笔记删除日期时间角色
NoteContent, // 笔记内容角色
NoteScrollbarPos, // 笔记滚动条位置角色
NoteTagsList, // 笔记标签列表角色
NoteIsTemp, // 笔记是否为临时笔记角色
NoteParentName, // 笔记父级名称角色
NoteTagListScrollbarPos, // 笔记标签列表滚动条位置角色
NoteIsPinned, // 笔记是否被钉住角色
};
explicit NoteListModel(QObject *parent = nullptr);
~NoteListModel();
explicit NoteListModel(QObject *parent = nullptr);// 构造函数,可以指定一个父对象
~NoteListModel();// 析构函数
QModelIndex addNote(const NodeData &note);
QModelIndex insertNote(const NodeData &note, int row);
const NodeData &getNote(const QModelIndex &index) const;
QModelIndex getNoteIndex(int id) const;
void setListNote(const QVector<NodeData> &notes, const ListViewInfo &inf);
void removeNotes(const QModelIndexList &noteIndexes);
QModelIndex addNote(const NodeData &note);// 添加笔记,并返回新笔记的模型索引
QModelIndex insertNote(const NodeData &note, int row);// 在指定行插入笔记,并返回新笔记的模型索引
const NodeData &getNote(const QModelIndex &index) const;// 获取指定模型索引的笔记数据
QModelIndex getNoteIndex(int id) const; // 获取指定ID的笔记的模型索引
void setListNote(const QVector<NodeData> &notes, const ListViewInfo &inf);// 设置笔记列表和列表视图信息
void removeNotes(const QModelIndexList &noteIndexes); // 移除指定模型索引列表的笔记
// 移动行
bool moveRow(const QModelIndex &sourceParent, int sourceRow,
const QModelIndex &destinationParent, int destinationChild);
// 清空笔记列表
void clearNotes();
// 获取指定模型索引的数据
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
// 设置指定模型索引的数据
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
// 获取指定模型索引的项标志
Qt::ItemFlags flags(const QModelIndex &index) const override;
// 获取行数
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
// 排序
void sort(int column, Qt::SortOrder order) override;
// 设置指定模型索引的笔记数据
void setNoteData(const QModelIndex &index, const NodeData &note);
// 获取支持的拖放操作
virtual Qt::DropActions supportedDropActions() const override;
// 获取支持的拖拽操作
virtual Qt::DropActions supportedDragActions() const override;
// 获取支持的MIME类型
virtual QStringList mimeTypes() const override;
// 获取指定模型索引列表的MIME数据
virtual QMimeData *mimeData(const QModelIndexList &indexes) const override;
// 处理MIME数据的拖放
virtual bool dropMimeData(const QMimeData *mime, Qt::DropAction action, int row, int column,
const QModelIndex &parent) override;
// 检查指定模型索引的笔记是否具有标签
bool noteIsHaveTag(const QModelIndex &index) const;
// 检查指定模型索引的笔记是否为第一个被钉住的笔记
bool isFirstPinnedNote(const QModelIndex &index) const;
// 检查指定模型索引的笔记是否为第一个未被钉住的笔记
bool isFirstUnpinnedNote(const QModelIndex &index) const;
// 获取第一个被钉住的笔记的模型索引
QModelIndex getFirstPinnedNote() const;
QModelIndex getFirstUnpinnedNote() const;
// 检查是否有被钉住的笔记
bool hasPinnedNote() const;
// 设置指定模型索引列表的笔记的钉住状态
void setNotesIsPinned(const QModelIndexList &indexes, bool isPinned);
private:
QVector<NodeData> m_noteList;
QVector<NodeData> m_pinnedList;
ListViewInfo m_listViewInfo;
QVector<NodeData> m_noteList; // 笔记列表
QVector<NodeData> m_pinnedList; // 被钉住的笔记列表
ListViewInfo m_listViewInfo; // 列表视图信息
// 更新被钉住的笔记的相对位置
void updatePinnedRelativePosition();
// 检查是否在所有笔记中
bool isInAllNote() const;
// 获取指定行的笔记数据的引用
NodeData &getRef(int row);
// 获取指定行的笔记数据的常量引用
const NodeData &getRef(int row) const;
signals:
// 行数发生变化时发出的信号
void rowCountChanged();
// 请求更新笔记的钉住状态时发出的信号
void requestUpdatePinned(int noteId, bool isPinned);
// 请求更新笔记的相对位置时发出的信号
void requestUpdatePinnedRelPos(int noteId, int pos);
// 请求更新笔记的相对位置(在所有笔记中)时发出的信号
void requestUpdatePinnedRelPosAN(int noteId, int pos);
// 请求移除笔记时发出的信号
void requestRemoveNotes(QModelIndexList index);
// 行插入时发出的信号
void rowsInsertedC(const QModelIndexList &rows);
// 行即将被移动时发出的信号
void rowsAboutToBeMovedC(const QModelIndexList &source);
// 行移动后发出的信号
void rowsMovedC(const QModelIndexList &dest);
// 请求关闭笔记编辑器时发出的信号
void requestCloseNoteEditor(const QModelIndexList &indexes);
// 请求打开笔记编辑器时发出的信号
void requestOpenNoteEditor(const QModelIndexList &indexes);
// 选择笔记时发出的信号
void selectNotes(const QModelIndexList &indexes);
// QAbstractItemModel interface
public:
// 移除行
bool removeRows(int row, int count, const QModelIndex &parent) override;
};

Loading…
Cancel
Save