File indexing completed on 2024-06-16 04:16:19

0001 /*
0002  *  SPDX-FileCopyrightText: 2020 Saurabh Kumar <saurabhk660@gmail.com>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #include "CommentModel.h"
0008 
0009 #include <QDebug>
0010 #include <QMimeData>
0011 #include <QRegularExpression>
0012 
0013 #include <kis_icon.h>
0014 
0015 StoryboardCommentModel::StoryboardCommentModel(QObject *parent)
0016         : QAbstractListModel(parent) 
0017 {
0018     //initialize variables
0019 }
0020 
0021 int StoryboardCommentModel::rowCount(const QModelIndex &parent) const
0022 {
0023     if (parent.isValid()) return 0;
0024    return m_commentList.count();
0025 }
0026 
0027 QVariant StoryboardCommentModel::data(const QModelIndex &index, int role) const
0028 {
0029     
0030     if (!index.isValid()) {
0031         return QVariant();
0032     }
0033     if (index.row() >= m_commentList.size()) {
0034         return QVariant();
0035     }
0036     if (role == Qt::DisplayRole || role == Qt::EditRole) {
0037         return m_commentList.at(index.row()).name;
0038     }
0039     if (role == Qt::DecorationRole) {
0040         if (m_commentList.at(index.row()).visibility) {
0041             return KisIconUtils::loadIcon("visible");
0042         }
0043         else {
0044             return KisIconUtils::loadIcon("novisible");
0045         }
0046     }
0047     return QVariant();
0048     
0049 }
0050 
0051 bool StoryboardCommentModel::setData(const QModelIndex & index, const QVariant & value, int role)
0052 {
0053     if (index.isValid() && (role == Qt::EditRole || role == Qt::DisplayRole)) {
0054         // POST KRITA/5.0 TODO -- we should be storing this as a map, not an array!
0055         // We only want 1 comment field per comment track title. A data change would
0056         // be appropriate here.
0057         QStringList nameList;
0058         Q_FOREACH(const StoryboardComment& comment, m_commentList) {
0059             nameList << comment.name;
0060         }
0061 
0062 
0063         QString desiredName = value.toString();
0064         int splitPoint = desiredName.length();
0065         while (desiredName.at(splitPoint - 1).isDigit()) {
0066             splitPoint--;
0067         }
0068 
0069         const QString prefix = desiredName.left(splitPoint);
0070         int existingNames = prefix.mid(splitPoint).toInt();
0071 
0072         while(nameList.contains(desiredName)) {
0073             existingNames++;
0074             desiredName = prefix + QString::number(existingNames);
0075         }
0076 
0077         m_commentList[index.row()].name = desiredName;
0078         emit dataChanged(index, index);
0079         emit sigCommentListChanged();
0080         return true;
0081     }
0082     
0083     if (index.isValid() && role == Qt::DecorationRole) {
0084         m_commentList[index.row()].visibility = !m_commentList[index.row()].visibility;
0085         emit dataChanged(index, index);
0086         emit sigCommentListChanged();
0087         return true;
0088     }
0089     return false;
0090 }
0091 
0092 Qt::ItemFlags StoryboardCommentModel::flags(const QModelIndex & index) const
0093 {
0094     if (!index.isValid()) {
0095         return Qt::ItemIsDropEnabled;
0096     }
0097     return Qt::ItemIsDragEnabled | Qt::ItemIsSelectable |
0098            Qt::ItemIsEditable | Qt::ItemIsEnabled ;
0099 }
0100 
0101 bool StoryboardCommentModel::insertRows(int position, int rows, const QModelIndex &/*parent*/)
0102 {
0103     beginInsertRows(QModelIndex(), position, position+rows-1);
0104 
0105     for (int row = 0; row < rows; ++row) {
0106         StoryboardComment newcomment;
0107         newcomment.name = "Comment";
0108         newcomment.visibility = true;
0109 
0110         if (position < 0 || position > m_commentList.size()) {
0111             return false;
0112         }
0113         m_commentList.insert(position, newcomment);
0114     }
0115 
0116     endInsertRows();
0117     emit sigCommentListChanged();
0118     return true;
0119 }
0120 
0121 bool StoryboardCommentModel::removeRows(int position, int rows, const QModelIndex &/*parent*/)
0122 {
0123     if (rows <= 0) {
0124         return false;
0125     }
0126     beginRemoveRows(QModelIndex(), position, position+rows-1);
0127 
0128     for (int row = 0; row < rows; ++row) {
0129         if (position < 0 || position >= m_commentList.size()) {
0130             return false;
0131         }
0132         m_commentList.removeAt(position);
0133     }
0134     endRemoveRows();
0135     emit sigCommentListChanged();
0136     return true;
0137 }
0138 
0139 bool StoryboardCommentModel::moveRows(const QModelIndex &sourceParent, int sourceRow, int count,
0140                             const QModelIndex &destinationParent, int destinationChild)
0141 {
0142     if (destinationChild == sourceRow || destinationChild == sourceRow + 1) {
0143         return false;
0144     }
0145     if (destinationChild > sourceRow + count - 1) {
0146         //we adjust for the upward shift, see qt doc for why this is needed
0147         beginMoveRows(sourceParent, sourceRow, sourceRow + count - 1, destinationParent, destinationChild + count - 1);
0148         destinationChild = destinationChild - count;
0149     }
0150     else {
0151         beginMoveRows(sourceParent, sourceRow, sourceRow + count - 1, destinationParent, destinationChild);
0152     }
0153     for (int row = 0; row < count; row++) {
0154         if (sourceRow < 0 || sourceRow >= m_commentList.size()) {
0155             return false;
0156         }
0157         if (destinationChild + row < 0 || destinationChild + row >= m_commentList.size()) {
0158             return false;
0159         }
0160         m_commentList.move(sourceRow, destinationChild + row);
0161     }
0162     endMoveRows();
0163     emit sigCommentListChanged();
0164     return true;
0165 }
0166 
0167 QStringList StoryboardCommentModel::mimeTypes() const
0168 {
0169     QStringList types;
0170     types << QLatin1String("application/x-krita-storyboard");
0171     return types;
0172 }
0173 
0174 QMimeData *StoryboardCommentModel::mimeData(const QModelIndexList &indexes) const
0175 {
0176     QMimeData *mimeData = new QMimeData();
0177     QByteArray encodeData;
0178 
0179     QDataStream stream(&encodeData, QIODevice::WriteOnly);
0180 
0181     //take the row number of the index where drag started
0182     foreach (QModelIndex index, indexes) {
0183         if (index.isValid()) {
0184             int row = index.row();
0185             stream << row;
0186         }
0187     }
0188 
0189     mimeData->setData("application/x-krita-storyboard", encodeData); //default mimetype
0190     return mimeData;
0191 }
0192 
0193 bool StoryboardCommentModel::dropMimeData(const QMimeData *data, Qt::DropAction action,
0194                                           int row, int /*column*/, const QModelIndex &parent)
0195 {
0196     if (action == Qt::IgnoreAction) {
0197         return false;
0198     }
0199     if (action == Qt::MoveAction && data->hasFormat("application/x-krita-storyboard")) {
0200         QByteArray bytes = data->data("application/x-krita-storyboard");
0201         QDataStream stream(&bytes, QIODevice::ReadOnly);
0202 
0203         if (parent.isValid()) {
0204             return false;
0205         }
0206         int sourceRow;
0207         QModelIndexList moveRowIndexes;
0208         while (!stream.atEnd()) {
0209             stream >> sourceRow;
0210             QModelIndex index = createIndex(sourceRow, 0);
0211             moveRowIndexes.append(index);
0212         }
0213         moveRows(QModelIndex(), moveRowIndexes.at(0).row(), moveRowIndexes.count(), parent, row);
0214 
0215         //returning true deletes the source row
0216         return false;
0217     }
0218     return false;
0219 }
0220 
0221 Qt::DropActions StoryboardCommentModel::supportedDropActions() const
0222 {
0223     return Qt::CopyAction | Qt::MoveAction;
0224 }
0225 
0226 Qt::DropActions StoryboardCommentModel::supportedDragActions() const
0227 {
0228     return Qt::CopyAction | Qt::MoveAction;
0229 }
0230 
0231 void StoryboardCommentModel::resetData(QVector<StoryboardComment> list)
0232 {
0233     beginResetModel();
0234     m_commentList = list;
0235     emit dataChanged(QModelIndex(), QModelIndex());
0236     endResetModel();
0237 }
0238 
0239 QVector<StoryboardComment> StoryboardCommentModel::getData()
0240 {
0241     return m_commentList;
0242 }