Krita Source Code Documentation
Loading...
Searching...
No Matches
CommentModel.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2020 Saurabh Kumar <saurabhk660@gmail.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
7#include "CommentModel.h"
8
9#include <QDebug>
10#include <QMimeData>
11#include <QRegularExpression>
12#include <QIODevice>
13
14#include <kis_icon.h>
15
17 : QAbstractListModel(parent)
18{
19 //initialize variables
20}
21
22int StoryboardCommentModel::rowCount(const QModelIndex &parent) const
23{
24 if (parent.isValid()) return 0;
25 return m_commentList.count();
26}
27
28QVariant StoryboardCommentModel::data(const QModelIndex &index, int role) const
29{
30
31 if (!index.isValid()) {
32 return QVariant();
33 }
34 if (index.row() >= m_commentList.size()) {
35 return QVariant();
36 }
37 if (role == Qt::DisplayRole || role == Qt::EditRole) {
38 return m_commentList.at(index.row()).name;
39 }
40 if (role == Qt::DecorationRole) {
41 if (m_commentList.at(index.row()).visibility) {
42 return KisIconUtils::loadIcon("visible");
43 }
44 else {
45 return KisIconUtils::loadIcon("novisible");
46 }
47 }
48 return QVariant();
49
50}
51
52bool StoryboardCommentModel::setData(const QModelIndex & index, const QVariant & value, int role)
53{
54 if (index.isValid() && (role == Qt::EditRole || role == Qt::DisplayRole)) {
55 // POST KRITA/5.0 TODO -- we should be storing this as a map, not an array!
56 // We only want 1 comment field per comment track title. A data change would
57 // be appropriate here.
58 QStringList nameList;
59 Q_FOREACH(const StoryboardComment& comment, m_commentList) {
60 nameList << comment.name;
61 }
62
63
64 QString desiredName = value.toString();
65 int splitPoint = desiredName.length();
66 while (desiredName.at(splitPoint - 1).isDigit()) {
67 splitPoint--;
68 }
69
70 const QString prefix = desiredName.left(splitPoint);
71 int existingNames = prefix.mid(splitPoint).toInt();
72
73 while(nameList.contains(desiredName)) {
74 existingNames++;
75 desiredName = prefix + QString::number(existingNames);
76 }
77
78 m_commentList[index.row()].name = desiredName;
79 Q_EMIT dataChanged(index, index);
80 Q_EMIT sigCommentListChanged();
81 return true;
82 }
83
84 if (index.isValid() && role == Qt::DecorationRole) {
85 m_commentList[index.row()].visibility = !m_commentList[index.row()].visibility;
86 Q_EMIT dataChanged(index, index);
87 Q_EMIT sigCommentListChanged();
88 return true;
89 }
90 return false;
91}
92
93Qt::ItemFlags StoryboardCommentModel::flags(const QModelIndex & index) const
94{
95 if (!index.isValid()) {
96 return Qt::ItemIsDropEnabled;
97 }
98 return Qt::ItemIsDragEnabled | Qt::ItemIsSelectable |
99 Qt::ItemIsEditable | Qt::ItemIsEnabled ;
100}
101
102bool StoryboardCommentModel::insertRows(int position, int rows, const QModelIndex &/*parent*/)
103{
104 beginInsertRows(QModelIndex(), position, position+rows-1);
105
106 for (int row = 0; row < rows; ++row) {
107 StoryboardComment newcomment;
108 newcomment.name = "Comment";
109 newcomment.visibility = true;
110
111 if (position < 0 || position > m_commentList.size()) {
112 return false;
113 }
114 m_commentList.insert(position, newcomment);
115 }
116
117 endInsertRows();
118 Q_EMIT sigCommentListChanged();
119 return true;
120}
121
122bool StoryboardCommentModel::removeRows(int position, int rows, const QModelIndex &/*parent*/)
123{
124 if (rows <= 0) {
125 return false;
126 }
127 beginRemoveRows(QModelIndex(), position, position+rows-1);
128
129 for (int row = 0; row < rows; ++row) {
130 if (position < 0 || position >= m_commentList.size()) {
131 return false;
132 }
133 m_commentList.removeAt(position);
134 }
135 endRemoveRows();
136 Q_EMIT sigCommentListChanged();
137 return true;
138}
139
140bool StoryboardCommentModel::moveRows(const QModelIndex &sourceParent, int sourceRow, int count,
141 const QModelIndex &destinationParent, int destinationChild)
142{
143 if (destinationChild == sourceRow || destinationChild == sourceRow + 1) {
144 return false;
145 }
146 if (destinationChild > sourceRow + count - 1) {
147 //we adjust for the upward shift, see qt doc for why this is needed
148 beginMoveRows(sourceParent, sourceRow, sourceRow + count - 1, destinationParent, destinationChild + count - 1);
149 destinationChild = destinationChild - count;
150 }
151 else {
152 beginMoveRows(sourceParent, sourceRow, sourceRow + count - 1, destinationParent, destinationChild);
153 }
154 for (int row = 0; row < count; row++) {
155 if (sourceRow < 0 || sourceRow >= m_commentList.size()) {
156 return false;
157 }
158 if (destinationChild + row < 0 || destinationChild + row >= m_commentList.size()) {
159 return false;
160 }
161 m_commentList.move(sourceRow, destinationChild + row);
162 }
163 endMoveRows();
164 Q_EMIT sigCommentListChanged();
165 return true;
166}
167
169{
170 QStringList types;
171 types << QLatin1String("application/x-krita-storyboard");
172 return types;
173}
174
175QMimeData *StoryboardCommentModel::mimeData(const QModelIndexList &indexes) const
176{
177 QMimeData *mimeData = new QMimeData();
178 QByteArray encodeData;
179
180 QDataStream stream(&encodeData, QIODevice::WriteOnly);
181
182 //take the row number of the index where drag started
183 foreach (QModelIndex index, indexes) {
184 if (index.isValid()) {
185 int row = index.row();
186 stream << row;
187 }
188 }
189
190 mimeData->setData("application/x-krita-storyboard", encodeData); //default mimetype
191 return mimeData;
192}
193
194bool StoryboardCommentModel::dropMimeData(const QMimeData *data, Qt::DropAction action,
195 int row, int /*column*/, const QModelIndex &parent)
196{
197 if (action == Qt::IgnoreAction) {
198 return false;
199 }
200 if (action == Qt::MoveAction && data->hasFormat("application/x-krita-storyboard")) {
201 QByteArray bytes = data->data("application/x-krita-storyboard");
202 QDataStream stream(&bytes, QIODevice::ReadOnly);
203
204 if (parent.isValid()) {
205 return false;
206 }
207 int sourceRow;
208 QModelIndexList moveRowIndexes;
209 while (!stream.atEnd()) {
210 stream >> sourceRow;
211 QModelIndex index = createIndex(sourceRow, 0);
212 moveRowIndexes.append(index);
213 }
214 moveRows(QModelIndex(), moveRowIndexes.at(0).row(), moveRowIndexes.count(), parent, row);
215
216 //returning true deletes the source row
217 return false;
218 }
219 return false;
220}
221
223{
224 return Qt::CopyAction | Qt::MoveAction;
225}
226
228{
229 return Qt::CopyAction | Qt::MoveAction;
230}
231
233{
234 beginResetModel();
235 m_commentList = list;
236 Q_EMIT dataChanged(QModelIndex(), QModelIndex());
237 endResetModel();
238}
239
float value(const T *src, size_t ch)
Qt::DropActions supportedDropActions() const override
void sigCommentListChanged()
Emitted whenever m_items is changed. it is used to keep the StoryboardItemList in KisDocument in sync...
QVector< StoryboardComment > getData()
returns a list of comments
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
Qt::DropActions supportedDragActions() const override
Qt::ItemFlags flags(const QModelIndex &index) const override
QStringList mimeTypes() const override
bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole) override
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override
QVector< StoryboardComment > m_commentList
void resetData(QVector< StoryboardComment > list)
resets m_commentList to list.
int rowCount(const QModelIndex &parent=QModelIndex()) const override
StoryboardCommentModel(QObject *parent=0)
bool insertRows(int position, int rows, const QModelIndex &index=QModelIndex()) override
bool removeRows(int position, int rows, const QModelIndex &index=QModelIndex()) override
QMimeData * mimeData(const QModelIndexList &indexes) const override
bool moveRows(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild) override
void encodeData(Imf::OutputFile &file, const QList< ExrPaintLayerSaveInfo > &informationObjects, int width, int height)
QIcon loadIcon(const QString &name)