File indexing completed on 2024-04-28 05:35:28
0001 /* 0002 SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "historymodel.h" 0008 #include "historyimageitem.h" 0009 #include "historystringitem.h" 0010 #include "historyurlitem.h" 0011 0012 HistoryModel::HistoryModel(QObject *parent) 0013 : QAbstractListModel(parent) 0014 , m_maxSize(0) 0015 , m_displayImages(true) 0016 { 0017 } 0018 0019 HistoryModel::~HistoryModel() 0020 { 0021 clear(); 0022 } 0023 0024 void HistoryModel::clear() 0025 { 0026 QMutexLocker lock(&m_mutex); 0027 beginResetModel(); 0028 m_items.clear(); 0029 endResetModel(); 0030 } 0031 0032 void HistoryModel::setMaxSize(int size) 0033 { 0034 if (m_maxSize == size) { 0035 return; 0036 } 0037 QMutexLocker lock(&m_mutex); 0038 m_maxSize = size; 0039 if (m_items.count() > m_maxSize) { 0040 removeRows(m_maxSize, m_items.count() - m_maxSize); 0041 } 0042 } 0043 0044 int HistoryModel::rowCount(const QModelIndex &parent) const 0045 { 0046 if (parent.isValid()) { 0047 return 0; 0048 } 0049 return m_items.count(); 0050 } 0051 0052 QVariant HistoryModel::data(const QModelIndex &index, int role) const 0053 { 0054 if (!index.isValid() || index.row() >= m_items.count() || index.column() != 0) { 0055 return QVariant(); 0056 } 0057 0058 std::shared_ptr<HistoryItem> item = m_items.at(index.row()); 0059 0060 switch (role) { 0061 case Qt::DisplayRole: 0062 return item->text(); 0063 case Qt::DecorationRole: 0064 return item->image(); 0065 case HistoryItemConstPtrRole: 0066 return QVariant::fromValue<HistoryItemConstPtr>(std::const_pointer_cast<const HistoryItem>(item)); 0067 case UuidRole: 0068 return item->uuid(); 0069 case TypeRole: 0070 return QVariant::fromValue<HistoryItemType>(item->type()); 0071 case Base64UuidRole: 0072 return item->uuid().toBase64(); 0073 case TypeIntRole: 0074 return int(item->type()); 0075 } 0076 return QVariant(); 0077 } 0078 0079 bool HistoryModel::removeRows(int row, int count, const QModelIndex &parent) 0080 { 0081 if (parent.isValid()) { 0082 return false; 0083 } 0084 if ((row + count) > m_items.count()) { 0085 return false; 0086 } 0087 QMutexLocker lock(&m_mutex); 0088 beginRemoveRows(QModelIndex(), row, row + count - 1); 0089 for (int i = 0; i < count; ++i) { 0090 m_items.removeAt(row); 0091 } 0092 endRemoveRows(); 0093 return true; 0094 } 0095 0096 bool HistoryModel::remove(const QByteArray &uuid) 0097 { 0098 QModelIndex index = indexOf(uuid); 0099 if (!index.isValid()) { 0100 return false; 0101 } 0102 return removeRow(index.row(), QModelIndex()); 0103 } 0104 0105 QModelIndex HistoryModel::indexOf(const QByteArray &uuid) const 0106 { 0107 for (int i = 0; i < m_items.count(); ++i) { 0108 if (m_items.at(i)->uuid() == uuid) { 0109 return index(i); 0110 } 0111 } 0112 return QModelIndex(); 0113 } 0114 0115 QModelIndex HistoryModel::indexOf(const HistoryItem *item) const 0116 { 0117 if (!item) { 0118 return QModelIndex(); 0119 } 0120 return indexOf(item->uuid()); 0121 } 0122 0123 void HistoryModel::insert(const std::shared_ptr<HistoryItem> &item) 0124 { 0125 if (!item) { 0126 return; 0127 } 0128 0129 if (m_maxSize == 0) { 0130 // special case - cannot insert any items 0131 return; 0132 } 0133 0134 QMutexLocker lock(&m_mutex); 0135 0136 const QModelIndex existingItem = indexOf(item.get()); 0137 if (existingItem.isValid()) { 0138 // move to top 0139 moveToTop(existingItem.row()); 0140 return; 0141 } 0142 0143 beginInsertRows(QModelIndex(), 0, 0); 0144 item->setModel(this); 0145 m_items.prepend(item); 0146 endInsertRows(); 0147 0148 if (m_items.count() > m_maxSize) { 0149 beginRemoveRows(QModelIndex(), m_items.count() - 1, m_items.count() - 1); 0150 m_items.removeLast(); 0151 endRemoveRows(); 0152 } 0153 } 0154 0155 void HistoryModel::clearAndBatchInsert(const QList<HistoryItemPtr> &items) 0156 { 0157 if (m_maxSize == 0) { 0158 // special case - cannot insert any items 0159 return; 0160 } 0161 0162 if (items.empty()) { 0163 // special case - nothing to insert, so just clear. 0164 clear(); 0165 return; 0166 } 0167 0168 QMutexLocker lock(&m_mutex); 0169 0170 beginResetModel(); 0171 m_items.clear(); 0172 0173 // The last row is either items.size() - 1 or m_maxSize - 1. 0174 const int numOfItemsToBeInserted = std::min(static_cast<int>(items.size()), m_maxSize); 0175 m_items.reserve(numOfItemsToBeInserted); 0176 0177 for (int i = 0; i < numOfItemsToBeInserted; i++) { 0178 if (!items[i]) { 0179 continue; 0180 } 0181 0182 items[i]->setModel(this); 0183 m_items.append(items[i]); 0184 } 0185 0186 endResetModel(); 0187 } 0188 0189 void HistoryModel::moveToTop(const QByteArray &uuid) 0190 { 0191 const QModelIndex existingItem = indexOf(uuid); 0192 if (!existingItem.isValid()) { 0193 return; 0194 } 0195 moveToTop(existingItem.row()); 0196 } 0197 0198 void HistoryModel::moveToTop(int row) 0199 { 0200 if (row == 0 || row >= m_items.count()) { 0201 return; 0202 } 0203 QMutexLocker lock(&m_mutex); 0204 beginMoveRows(QModelIndex(), row, row, QModelIndex(), 0); 0205 m_items.move(row, 0); 0206 endMoveRows(); 0207 } 0208 0209 void HistoryModel::moveTopToBack() 0210 { 0211 if (m_items.count() < 2) { 0212 return; 0213 } 0214 QMutexLocker lock(&m_mutex); 0215 beginMoveRows(QModelIndex(), 0, 0, QModelIndex(), m_items.count()); 0216 auto item = m_items.takeFirst(); 0217 m_items.append(item); 0218 endMoveRows(); 0219 } 0220 0221 void HistoryModel::moveBackToTop() 0222 { 0223 moveToTop(m_items.count() - 1); 0224 } 0225 0226 QHash<int, QByteArray> HistoryModel::roleNames() const 0227 { 0228 QHash<int, QByteArray> hash; 0229 hash.insert(Qt::DisplayRole, QByteArrayLiteral("DisplayRole")); 0230 hash.insert(Qt::DecorationRole, QByteArrayLiteral("DecorationRole")); 0231 hash.insert(Base64UuidRole, QByteArrayLiteral("UuidRole")); 0232 hash.insert(TypeIntRole, QByteArrayLiteral("TypeRole")); 0233 return hash; 0234 }