diff --git a/plugins/dockers/storyboarddocker/CMakeLists.txt b/plugins/dockers/storyboarddocker/CMakeLists.txt index 00a42f89c6..bd05bf38e2 100644 --- a/plugins/dockers/storyboarddocker/CMakeLists.txt +++ b/plugins/dockers/storyboarddocker/CMakeLists.txt @@ -1,34 +1,34 @@ -#add_subdirectory(tests) +add_subdirectory(tests) set(KRITA_STORYBOARDDOCKER_SOURCES commentModel.cpp storyboarddocker.cpp storyboarddocker_dock.cpp commentDelegate.cpp storyboardModel.cpp storyboardItem.cpp storyboardDelegate.cpp storyboardView.cpp ) set(KRITA_STORYBOARDDOCKER_PART_HEADERS commentModel.h storyboarddocker.h storyboarddocker_dock.h commentDelegate.h storyboardModel.h storyboardItem.h storyboardDelegate.h storyboardView.h ) ki18n_wrap_ui(KRITA_STORYBOARDDOCKER_SOURCES wdgstoryboarddock.ui wdgarrangemenu.ui wdgcommentmenu.ui ) add_library(kritastoryboarddocker MODULE ${KRITA_STORYBOARDDOCKER_SOURCES} ${KRITA_STORYBOARDDOCKER_PART_HEADERS} ) target_link_libraries(kritastoryboarddocker kritaui) install(TARGETS kritastoryboarddocker DESTINATION ${KRITA_PLUGIN_INSTALL_DIR}) diff --git a/plugins/dockers/storyboarddocker/commentModel.cpp b/plugins/dockers/storyboarddocker/commentModel.cpp index 801f70ffb9..bbdd8c587b 100644 --- a/plugins/dockers/storyboarddocker/commentModel.cpp +++ b/plugins/dockers/storyboarddocker/commentModel.cpp @@ -1,194 +1,194 @@ /* * Copyright (c) 2020 Saurabh Kumar * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "commentModel.h" #include #include #include CommentModel::CommentModel(QObject *parent) : QAbstractListModel(parent) { //initialize variables } int CommentModel::rowCount(const QModelIndex &parent) const { return m_commentList.count(); } QVariant CommentModel::data(const QModelIndex &index, int role) const { if(!index.isValid()) return QVariant(); if(index.row() >= m_commentList.size()) return QVariant(); if (role == Qt::DisplayRole || role == Qt::EditRole) { return m_commentList.at(index.row()).name; } if (role == Qt::DecorationRole) { if (m_commentList.at(index.row()).visibility){ return KisIconUtils::loadIcon("visible"); } else { return KisIconUtils::loadIcon("novisible"); } } return QVariant(); } bool CommentModel::setData(const QModelIndex & index, const QVariant & value, int role) { if (index.isValid() && (role == Qt::EditRole || role == Qt::DisplayRole)) { m_commentList[index.row()].name = value.toString(); emit dataChanged(index, index); return true; } if (index.isValid() && role == Qt::DecorationRole){ m_commentList[index.row()].visibility = !m_commentList[index.row()].visibility; emit dataChanged(index, index); return true; } return false; } Qt::ItemFlags CommentModel::flags(const QModelIndex & index) const { if(!index.isValid()) return Qt::ItemIsDropEnabled; return Qt::ItemIsDragEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled ; } bool CommentModel::insertRows(int position, int rows, const QModelIndex &parent) { beginInsertRows(QModelIndex(), position, position+rows-1); for (int row = 0; row < rows; ++row) { Comment newcomment; //maybe set a default name like comment 1 newcomment.name = ""; newcomment.visibility = true; - if (position < 0 && position>=m_commentList.size()) return false; + if (position < 0 || position > m_commentList.size()) return false; m_commentList.insert(position, newcomment); } endInsertRows(); return true; } bool CommentModel::removeRows(int position, int rows, const QModelIndex &parent) { beginRemoveRows(QModelIndex(), position, position+rows-1); for (int row = 0; row < rows; ++row) { if (position < 0 || position >= m_commentList.size()) return false; m_commentList.removeAt(position); } endRemoveRows(); return true; } bool CommentModel::moveRows(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild) { if (destinationChild == sourceRow || destinationChild == sourceRow + 1){ return false; } if (destinationChild > sourceRow + count - 1){ //we adjust for the upward shift, see qt doc for why this is needed beginMoveRows(sourceParent, sourceRow, sourceRow + count - 1, destinationParent, destinationChild + count - 1); destinationChild = destinationChild - count; } else { beginMoveRows(sourceParent, sourceRow, sourceRow + count - 1, destinationParent, destinationChild); } for (int row = 0; row < count; row++){ if (sourceRow < 0 || sourceRow >= m_commentList.size()) return false; if (destinationChild + row < 0 || destinationChild + row >= m_commentList.size()) return false; m_commentList.move(sourceRow, destinationChild + row); } endMoveRows(); return true; } QMimeData *CommentModel::mimeData(const QModelIndexList &indexes) const { QMimeData *mimeData = new QMimeData(); QByteArray encodeData; QDataStream stream(&encodeData, QIODevice::WriteOnly); //take the row number of the index where drag started foreach (QModelIndex index, indexes){ if (index.isValid()) { int row = index.row(); stream << row; } } mimeData->setData("application/x-qabstractitemmodeldatalist", encodeData); //default mimetype return mimeData; } bool CommentModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) { if (action == Qt::IgnoreAction) return false; if (action == Qt::MoveAction && data->hasFormat("application/x-qabstractitemmodeldatalist")){ QByteArray bytes = data->data("application/x-qabstractitemmodeldatalist"); QDataStream stream(&bytes, QIODevice::ReadOnly); if (parent.isValid()){ return false; } int sourceRow; QModelIndexList moveRowIndexes; while (!stream.atEnd()) { stream >> sourceRow; QModelIndex index = createIndex(sourceRow, 0); moveRowIndexes.append(index); } moveRows(QModelIndex(), moveRowIndexes.at(0).row(), moveRowIndexes.count(), parent, row); //returning true deletes the source row return false; } return false; } Qt::DropActions CommentModel::supportedDropActions() const { return Qt::CopyAction | Qt::MoveAction; } Qt::DropActions CommentModel::supportedDragActions() const { return Qt::CopyAction | Qt::MoveAction; } diff --git a/plugins/dockers/storyboarddocker/commentModel.h b/plugins/dockers/storyboarddocker/commentModel.h index 41ba1b578b..b22053283c 100644 --- a/plugins/dockers/storyboarddocker/commentModel.h +++ b/plugins/dockers/storyboarddocker/commentModel.h @@ -1,63 +1,64 @@ /* * Copyright (c) 2020 Saurabh Kumar * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef COMMENT_MODEL #define COMMENT_MODEL #include +#include class StoryboardModel; struct Comment { QString name; bool visibility; }; /* This model manages the comment data of StoryboardModel */ -class CommentModel : public QAbstractListModel +class KRITAUI_EXPORT CommentModel : public QAbstractListModel { Q_OBJECT public: CommentModel(QObject *parent = 0); int rowCount(const QModelIndex &parent = QModelIndex()) const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; Qt::ItemFlags flags(const QModelIndex &index) const override; bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; bool insertRows(int position, int rows, const QModelIndex &index = QModelIndex()); bool removeRows(int position, int rows, const QModelIndex &index = QModelIndex()); bool moveRows(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild); QMimeData *mimeData(const QModelIndexList &indexes) const; bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent); Qt::DropActions supportedDropActions() const override; Qt::DropActions supportedDragActions() const override; private: QVector m_commentList; friend class StoryboardModel; }; #endif \ No newline at end of file diff --git a/plugins/dockers/storyboarddocker/storyboardModel.cpp b/plugins/dockers/storyboarddocker/storyboardModel.cpp index eb7706a9b4..7cbe9d30fd 100644 --- a/plugins/dockers/storyboarddocker/storyboardModel.cpp +++ b/plugins/dockers/storyboarddocker/storyboardModel.cpp @@ -1,438 +1,446 @@ /* * Copyright (c) 2020 Saurabh Kumar * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "storyboardModel.h" #include #include #include StoryboardModel::StoryboardModel(QObject *parent) : QAbstractItemModel(parent) , m_commentCount(0) { connect(this, SIGNAL(rowsInserted(const QModelIndex, int, int)), this, SLOT(slotInsertChildRows(const QModelIndex, int, int))); } QModelIndex StoryboardModel::index(int row, int column, const QModelIndex &parent) const { if (!hasIndex(row, column, parent)) return QModelIndex(); if (row < 0 || row >= rowCount(parent)) return QModelIndex(); if (column !=0) return QModelIndex(); //1st level node has invalid parent if (!parent.isValid()){ return createIndex(row, column, m_items.at(row)); } else if (!parent.parent().isValid()){ StoryboardItem *parentItem = static_cast(parent.internalPointer()); StoryboardChild *childItem = parentItem->child(row); if (childItem) return createIndex(row, column, childItem); } return QModelIndex(); } QModelIndex StoryboardModel::parent(const QModelIndex &index) const { if (!index.isValid()) return QModelIndex(); { //no parent for 1st level node StoryboardItem *childItem = static_cast(index.internalPointer()); if (m_items.contains(childItem)){ return QModelIndex(); } } //return parent only for 2nd level nodes StoryboardChild *childItem = static_cast(index.internalPointer()); StoryboardItem *parentItem = childItem->parent(); int indexOfParent = m_items.indexOf(const_cast(parentItem)); return createIndex(indexOfParent, 0, parentItem); } int StoryboardModel::rowCount(const QModelIndex &parent) const { if (!parent.isValid()) return m_items.count(); else if (!parent.parent().isValid()){ StoryboardItem *parentItem = static_cast(parent.internalPointer()); return parentItem->childCount(); } return 0; //2nd level nodes have no child } int StoryboardModel::columnCount(const QModelIndex &parent) const { if (!parent.isValid()){ return 1; } //1st level nodes have 1 column if (!parent.parent().isValid()){ return 1; } //end level nodes have no child return 0; } QVariant StoryboardModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) return QVariant(); //return data only for the storyboardChild i.e. 2nd level nodes if (!index.parent().isValid()){ return QVariant(); } if (role == Qt::DisplayRole || role == Qt::EditRole || role == Qt::UserRole) { StoryboardChild *child = static_cast(index.internalPointer()); if (index.row() > 3){ if (role == Qt::UserRole){ //scroll bar position CommentBox commentBox = qvariant_cast(child->data()); return commentBox.scrollValue; } else { CommentBox commentBox = qvariant_cast(child->data()); return commentBox.content; } } return child->data(); } return QVariant(); } bool StoryboardModel::setData(const QModelIndex & index, const QVariant & value, int role) { if (index.isValid() && (role == Qt::EditRole || role == Qt::DisplayRole)) { if (!index.parent().isValid()) return false; StoryboardChild *child = static_cast(index.internalPointer()); if (child){ int fps = 24; - if(index.row() == 3 && value.toInt() >= fps){ //TODO : set fps + if ((index.row() <= 3 && index.row() != 1) && value.toInt() < 0) return false; + if (index.row() == 3 && value.toInt() >= fps){ //TODO : set fps QModelIndex secondIndex = index.siblingAtRow(2); setData(secondIndex, secondIndex.data().toInt() + value.toInt() / fps, role); child->setData(value.toInt() % fps); } else if (index.row() > 3){ CommentBox commentBox = qvariant_cast(child->data()); commentBox.content = value.toString(); child->setData(QVariant::fromValue(commentBox)); } else { child->setData(value); } emit dataChanged(index, index); return true; } } return false; } bool StoryboardModel::setCommentScrollData(const QModelIndex & index, const QVariant & value) { StoryboardChild *child = static_cast(index.internalPointer()); if (child){ CommentBox commentBox = qvariant_cast(child->data()); commentBox.scrollValue = value.toInt(); child->setData(QVariant::fromValue(commentBox)); return true; } return false; } Qt::ItemFlags StoryboardModel::flags(const QModelIndex & index) const { if(!index.isValid()) return Qt::ItemIsDropEnabled; //1st level nodes if (!index.parent().isValid()) return Qt::ItemIsDragEnabled | Qt::ItemIsSelectable | Qt::ItemIsEnabled; //2nd level nodes return Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemNeverHasChildren; } bool StoryboardModel::insertRows(int position, int rows, const QModelIndex &parent) { if (!parent.isValid()){ + if (position < 0 || position > m_items.count()) return false; beginInsertRows(QModelIndex(), position, position+rows-1); for (int row = 0; row < rows; ++row) { StoryboardItem *newItem = new StoryboardItem(); m_items.insert(position, newItem); } endInsertRows(); return true; } else if (!parent.parent().isValid()){ //insert 2nd level nodes StoryboardItem *item = static_cast(parent.internalPointer()); + + if (position < 0 || position > item->childCount()) return false; beginInsertRows(parent, position, position+rows-1); for (int row = 0; row < rows; ++row) { item->insertChild(position, QVariant()); } endInsertRows(); return true; } //we can't insert to 2nd level nodes as they are leaf nodes return false; } bool StoryboardModel::removeRows(int position, int rows, const QModelIndex &parent) { //remove 1st level nodes if (!parent.isValid()){ + + if (position < 0 || position >= m_items.count()) return false; beginRemoveRows(QModelIndex(), position, position+rows-1); for (int row = position + rows - 1; row >= position; row--){ //deleting all the child nodes QModelIndex currentIndex = index(row, 0); removeRows(0, rowCount(currentIndex), currentIndex); //deleting the actual parent node delete m_items.at(row); m_items.removeAt(row); } endRemoveRows(); return true; } else if (!parent.parent().isValid()){ //remove 2nd level nodes StoryboardItem *item = static_cast(parent.internalPointer()); + + if (position < 0 || position >= item->childCount()) return false; if (m_items.contains(item)){ beginRemoveRows(parent, position, position+rows-1); for (int row = 0; row < rows; ++row) { item->removeChild(position); } endRemoveRows(); return true; } } //2nd level node has no child return false; } bool StoryboardModel::moveRows(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild) { if (sourceParent != destinationParent){ return false; } if (destinationChild == sourceRow || destinationChild == sourceRow + 1){ return false; } if (destinationChild > sourceRow + count - 1){ //we adjust for the upward shift, see qt doc for why this is needed beginMoveRows(sourceParent, sourceRow, sourceRow + count - 1, destinationParent, destinationChild + count - 1); destinationChild = destinationChild - count; } else { beginMoveRows(sourceParent, sourceRow, sourceRow + count - 1, destinationParent, destinationChild); } //for moves within the 1st level nodes for comment nodes if (sourceParent == destinationParent && sourceParent.isValid() && !sourceParent.parent().isValid()){ const QModelIndex parent = sourceParent; for (int row = 0; row < count; row++){ if (sourceRow < 4 || sourceRow >= rowCount(parent)) return false; if (destinationChild + row < 4 || destinationChild + row >= rowCount(parent)) return false; StoryboardItem *item = static_cast(parent.internalPointer()); item->moveChild(sourceRow, destinationChild + row); } endMoveRows(); return true; } else if (!sourceParent.isValid()){ //for moves of 1st level nodes for (int row = 0; row < count; row++){ if (sourceRow < 0 || sourceRow >= rowCount()) return false; if (destinationChild + row < 0 || destinationChild + row >= rowCount()) return false; m_items.move(sourceRow, destinationChild + row); } endMoveRows(); return true; } else { return false; } } QMimeData *StoryboardModel::mimeData(const QModelIndexList &indexes) const { QMimeData *mimeData = new QMimeData(); QByteArray encodeData; QDataStream stream(&encodeData, QIODevice::WriteOnly); //take the row number of the index where drag started foreach (QModelIndex index, indexes){ if (index.isValid()) { int row = index.row(); stream << row; } } mimeData->setData("application/x-qabstractitemmodeldatalist", encodeData); //default mimetype return mimeData; } bool StoryboardModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) { if (action == Qt::IgnoreAction) return false; if (action == Qt::MoveAction && data->hasFormat("application/x-qabstractitemmodeldatalist")){ QByteArray bytes = data->data("application/x-qabstractitemmodeldatalist"); QDataStream stream(&bytes, QIODevice::ReadOnly); if (parent.isValid()){ return false; } int sourceRow; QModelIndexList moveRowIndexes; while (!stream.atEnd()) { stream >> sourceRow; QModelIndex index = createIndex(sourceRow, 0); moveRowIndexes.append(index); } moveRows(QModelIndex(), moveRowIndexes.at(0).row(), moveRowIndexes.count(), parent, row); //returning true deletes the source row return false; } return false; } Qt::DropActions StoryboardModel::supportedDropActions() const { return Qt::CopyAction | Qt::MoveAction; } Qt::DropActions StoryboardModel::supportedDragActions() const { return Qt::CopyAction | Qt::MoveAction; } int StoryboardModel::visibleCommentCount() const { int visibleComments = 0; foreach(Comment comment, m_commentList){ if (comment.visibility){ visibleComments++; } } return visibleComments; } int StoryboardModel::visibleCommentsUpto(QModelIndex index) const { int commentRow = index.row() - 4; int visibleComments = 0; for (int row = 0; row < commentRow; row++){ if (m_commentList.at(row).visibility){ visibleComments++; } } return visibleComments; } void StoryboardModel::setCommentModel(CommentModel *commentModel) { m_commentModel = commentModel; connect(m_commentModel, SIGNAL(dataChanged(const QModelIndex ,const QModelIndex)), this, SLOT(slotCommentDataChanged())); connect(m_commentModel, SIGNAL(rowsRemoved(const QModelIndex ,int, int)), this, SLOT(slotCommentRowRemoved(const QModelIndex ,int, int))); connect(m_commentModel, SIGNAL(rowsInserted(const QModelIndex, int, int)), this, SLOT(slotCommentRowInserted(const QModelIndex, int, int))); connect(m_commentModel, SIGNAL(rowsMoved(const QModelIndex, int, int, const QModelIndex, int)), this, SLOT(slotCommentRowMoved(const QModelIndex, int, int, const QModelIndex, int))); } Comment StoryboardModel::getComment(int row) const { return m_commentList.at(row); } void StoryboardModel::slotCommentDataChanged() { m_commentList = m_commentModel->m_commentList; emit(layoutChanged()); } void StoryboardModel::slotCommentRowInserted(const QModelIndex parent, int first, int last) { int numItems = rowCount(); for(int row = 0; row < numItems; row++){ QModelIndex parentIndex = index(row, 0); insertRows(4 + first, last - first + 1, parentIndex); //four indices are already there } slotCommentDataChanged(); } void StoryboardModel::slotCommentRowRemoved(const QModelIndex parent, int first, int last) { int numItems = rowCount(); for(int row = 0; row < numItems; row++){ QModelIndex parentIndex = index(row, 0); removeRows(4 + first, last - first + 1, parentIndex); } slotCommentDataChanged(); } void StoryboardModel::slotCommentRowMoved(const QModelIndex &sourceParent, int start, int end, const QModelIndex &destinationParent, int destinationRow) { int numItems = rowCount(); for(int row = 0; row < numItems; row++){ QModelIndex parentIndex = index(row, 0); moveRows(parentIndex, start + 4, end - start + 1, parentIndex, destinationRow + 4); } slotCommentDataChanged(); } void StoryboardModel::slotInsertChildRows(const QModelIndex parent, int first, int last) { if (!parent.isValid()){ int rows = last - first + 1; for (int row = 0; row < rows; ++row) { QModelIndex parentIndex = index(first + row, 0); insertRows(0, 4 + m_commentList.count(), parentIndex); setData (index (0, 0, parentIndex), m_lastFrame); m_lastFrame++; QString sceneName = "scene " + QString::number(m_lastScene); setData (index (1, 0, parentIndex), sceneName); m_lastScene++; setData (index (2, 0, parentIndex), 20); setData (index (3, 0, parentIndex), 20); } } } diff --git a/plugins/dockers/storyboarddocker/storyboardModel.h b/plugins/dockers/storyboarddocker/storyboardModel.h index 85f613fb6e..27deb11e38 100644 --- a/plugins/dockers/storyboarddocker/storyboardModel.h +++ b/plugins/dockers/storyboarddocker/storyboardModel.h @@ -1,104 +1,105 @@ /* * Copyright (c) 2020 Saurabh Kumar * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef STORYBOARD_MODEL #define STORYBOARD_MODEL #include #include #include "storyboardItem.h" #include "commentModel.h" +#include /* The main storyboard model. */ class CommentBox { public: CommentBox() : content("") , scrollValue(0) {} CommentBox(const CommentBox& other) : content(other.content) , scrollValue(other.scrollValue) {} ~CommentBox() {} QVariant content; QVariant scrollValue; }; Q_DECLARE_METATYPE(CommentBox) -class StoryboardModel : public QAbstractItemModel +class KRITAUI_EXPORT StoryboardModel : public QAbstractItemModel { Q_OBJECT public: //if we don't need this constructor change it StoryboardModel(QObject *parent = nullptr); QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override; QModelIndex parent(const QModelIndex &index) const override; int rowCount(const QModelIndex &parent = QModelIndex()) const override; int columnCount(const QModelIndex &parent = QModelIndex()) const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; bool setCommentScrollData(const QModelIndex & index, const QVariant & value); Qt::ItemFlags flags(const QModelIndex &index) const override; //for removing and inserting rows bool insertRows(int position, int rows, const QModelIndex &index = QModelIndex()); bool removeRows(int position, int rows, const QModelIndex &index = QModelIndex()); bool moveRows(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild); //for drag and drop QMimeData *mimeData(const QModelIndexList &indexes) const; bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent); Qt::DropActions supportedDropActions() const override; Qt::DropActions supportedDragActions() const override; //these function access the value from the comment model int visibleCommentCount() const; int visibleCommentsUpto(QModelIndex index) const; void setCommentModel(CommentModel *commentModel); Comment getComment(int row) const; private Q_SLOTS: void slotCommentDataChanged(); void slotCommentRowInserted(const QModelIndex, int, int); void slotCommentRowRemoved(const QModelIndex, int, int); void slotCommentRowMoved(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild); void slotInsertChildRows(const QModelIndex parent, int first, int last); private: QVector m_items; int m_commentCount = 0; QVector m_commentList; CommentModel *m_commentModel; int m_lastFrame = 0; int m_lastScene = 0; }; #endif \ No newline at end of file diff --git a/plugins/dockers/storyboarddocker/tests/CMakeLists.txt b/plugins/dockers/storyboarddocker/tests/CMakeLists.txt index de932c2a0b..a8ddd42b7f 100644 --- a/plugins/dockers/storyboarddocker/tests/CMakeLists.txt +++ b/plugins/dockers/storyboarddocker/tests/CMakeLists.txt @@ -1,19 +1,18 @@ set( EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR} ) include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/.. ${CMAKE_SOURCE_DIR}/libs/ui/tests ${CMAKE_CURRENT_BINARY_DIR}/.. ) +include(ECMAddTests) + macro_add_unittest_definitions() ecm_add_test( - storyboardModelTest.cpp - ../storyboardModel.cpp - ../commentModel.cpp - ${CMAKE_SOURCE_DIR}/libs/ui/tests/modeltest.cpp + storyboardModelTest.cpp TEST_NAME kritastoryboardmodeltest NAME_PREFIX "plugins-dockers-storyboarddocker-" LINK_LIBRARIES kritastoryboarddocker kritaui Qt5::Test ) \ No newline at end of file diff --git a/plugins/dockers/storyboarddocker/tests/storyboardModelTest.cpp b/plugins/dockers/storyboarddocker/tests/storyboardModelTest.cpp index 61b049c2c1..66e9f275c2 100644 --- a/plugins/dockers/storyboarddocker/tests/storyboardModelTest.cpp +++ b/plugins/dockers/storyboarddocker/tests/storyboardModelTest.cpp @@ -1,169 +1,177 @@ /* * Copyright (c) 2020 Saurabh Kumar * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "storyboardModelTest.h" #include #include -#include "storyboardModel.h" -#include "commentModel.h" +#include +#include void StoryboardModelTest::init() { - m_commentModel = new CommentModel(0); - m_storyboardModel = new StoryboardModel(0); + m_commentModel = new CommentModel(this); + m_storyboardModel = new StoryboardModel(this); + m_storyboardModel->setCommentModel(m_commentModel); m_commentModel->insertRows(m_commentModel->rowCount(),1); + m_storyboardModel->insertRows(m_storyboardModel->rowCount(),1); QCOMPARE(m_commentModel->rowCount(), 1); } void StoryboardModelTest::cleanup() { + m_storyboardModel->removeRows(0, m_storyboardModel->rowCount()); + m_commentModel->removeRows(0, m_commentModel->rowCount()); + delete m_storyboardModel; delete m_commentModel; } + void StoryboardModelTest::testAddComment() { - auto tester = new QAbstractItemModelTester(m_storyboardModel, 0); - auto tester = new QAbstractItemModelTester(m_commentModel, 0); + auto sbTester = new QAbstractItemModelTester(m_storyboardModel, this); + auto commentTester = new QAbstractItemModelTester(m_commentModel, this); + Q_UNUSED(sbTester); + Q_UNUSED(commentTester); - int commentStoryboard = m_storyboardModel->commentCount(); + int rowStoryboard = m_storyboardModel->rowCount(m_storyboardModel->index(0,0)); int rowsComment = m_commentModel->rowCount(); - QCOMPARE(commentStoryboard, rowsComment); + QCOMPARE(rowStoryboard, rowsComment + 4); m_commentModel->insertRows(m_commentModel->rowCount(),1); QCOMPARE(rowsComment + 1, m_commentModel->rowCount()); - QCOMPARE(m_storyboardModel->commentCount(), m_commentModel->rowCount()); + QCOMPARE(m_storyboardModel->rowCount(m_storyboardModel->index(0,0)), m_commentModel->rowCount() + 4); //add at an invalid position m_commentModel->insertRows(-1, 1); QCOMPARE(rowsComment + 1, m_commentModel->rowCount()); - QCOMPARE(m_storyboardModel->commentCount(), m_commentModel->rowCount()); - + QCOMPARE(m_storyboardModel->rowCount(m_storyboardModel->index(0,0)), m_commentModel->rowCount() + 4); } void StoryboardModelTest::testRemoveComment() { - auto tester = new QAbstractItemModelTester(m_storyboardModel, 0); - auto tester = new QAbstractItemModelTester(m_commentModel, 0); - int commentStoryboard = m_storyboardModel->commentCount(); + auto sbTester = new QAbstractItemModelTester(m_storyboardModel, this); + auto commentTester = new QAbstractItemModelTester(m_commentModel, this); + Q_UNUSED(sbTester); + Q_UNUSED(commentTester); + + int rowStoryboard = m_storyboardModel->rowCount(m_storyboardModel->index(0,0)); int rowsComment = m_commentModel->rowCount(); - QCOMPARE(commentStoryboard, rowsComment); + QCOMPARE(rowStoryboard, rowsComment + 4); - m_commentModel->removeRows(m_commentModel->rowCount(),1); + m_commentModel->removeRows(m_commentModel->rowCount() - 1,1); QCOMPARE(rowsComment - 1, m_commentModel->rowCount()); - QCOMPARE(m_storyboardModel->commentCount(), m_commentModel->rowCount()); + QCOMPARE(m_storyboardModel->rowCount(m_storyboardModel->index(0,0)), m_commentModel->rowCount() + 4); m_commentModel->removeRows(-1,1); QCOMPARE(rowsComment - 1, m_commentModel->rowCount()); - QCOMPARE(m_storyboardModel->commentCount(), m_commentModel->rowCount()); + QCOMPARE(m_storyboardModel->rowCount(m_storyboardModel->index(0,0)), m_commentModel->rowCount() + 4); } void StoryboardModelTest::testCommentNameChanged() { - auto tester = new QAbstractItemModelTester(m_commentModel, 0); - QModelIndex index = m_commentModel->createIndex(m_commentModel->rowCount(),m_commentModel->columnCount()); + auto tester = new QAbstractItemModelTester(m_commentModel, this); + Q_UNUSED(tester); + QModelIndex index = m_commentModel->index(m_commentModel->rowCount() - 1, 0); QVariant value = QVariant(QString("newValue")); m_commentModel->setData(index, value); QCOMPARE(QString("newValue"), m_commentModel->data(index)); } -void StoryboardModelTest::testCommentVisibilityChanged() -{ - QModelIndex index = m_commentModel->createIndex(m_commentModel->rowCount(),m_commentModel->columnCount()); - QIcon prevIcon = m_commentModel->data(index, Qt::DecorationRole); - m_commentModel->setData(index, true, Qt::DecorationRole); - QIcon currIcon = m_commentModel->data(index, Qt::DecorationRole); - - QVERIFY(prevIcon != currIcon); -} - void StoryboardModelTest::testFrameAdded() { int rows = m_storyboardModel->rowCount(); auto tester = new QAbstractItemModelTester(m_storyboardModel, 0); + Q_UNUSED(tester); m_storyboardModel->insertRows(m_storyboardModel->rowCount(),1); QCOMPARE(rows + 1, m_storyboardModel->rowCount()); } + void StoryboardModelTest::testFrameRemoved() { int rows = m_storyboardModel->rowCount(); auto tester = new QAbstractItemModelTester(m_storyboardModel, 0); - m_storyboardModel->removeRows(m_storyboardModel->rowCount(),1); + Q_UNUSED(tester); + m_storyboardModel->removeRows(m_storyboardModel->rowCount() - 1,1); QCOMPARE(rows-1, m_storyboardModel->rowCount()); } void StoryboardModelTest::testFrameChanged() { auto tester = new QAbstractItemModelTester(m_storyboardModel, 0); - QModelIndex index = m_commentModel->createIndex(m_storyboardModel->rowCount(), 1); + Q_UNUSED(tester); + QModelIndex parentIndex = m_storyboardModel->index(m_storyboardModel->rowCount() - 1, 0); + QModelIndex frameIndex = m_storyboardModel->index(0, 0, parentIndex); QVariant value = QVariant(100); - m_stroyboardModel->setData(index, value, Qt::EditRole); + m_storyboardModel->setData(frameIndex, value, Qt::EditRole); - QCOMPARE(m_stroyboardModel->data(index), 100); + QCOMPARE(m_storyboardModel->data(frameIndex).toInt(), 100); //invalid value shouldn't change anything - QVariant value = QVariant(-100); - m_stroyboardModel->setData(index, value, Qt::EditRole); - - QVERIFY(m_stroyboardModel->data(index), 100); - + QVariant invalidValue = QVariant(-100); + m_storyboardModel->setData(frameIndex, invalidValue, Qt::EditRole); + QCOMPARE(m_storyboardModel->data(frameIndex).toInt(), 100); } void StoryboardModelTest::testDurationChanged() { auto tester = new QAbstractItemModelTester(m_storyboardModel, 0); - QModelIndex index = m_commentModel->createIndex(m_storyboardModel->rowCount(), 2); + Q_UNUSED(tester); + QModelIndex parentIndex = m_storyboardModel->index(m_storyboardModel->rowCount() - 1, 0); + QModelIndex secIndex = m_storyboardModel->index(2, 0, parentIndex); QVariant value = QVariant(100); - m_stroyboardModel->setData(index, value, Qt::EditRole); + m_storyboardModel->setData(secIndex, value, Qt::EditRole); - QCOMPARE(m_stroyboardModel->data(index), 100); + QCOMPARE(m_storyboardModel->data(secIndex).toInt(), 100); //invalid value shouldn't change anything - QVariant value = QVariant(-1); - m_stroyboardModel->setData(index, value, Qt::EditRole); + QVariant invalidValue = QVariant(-100); + m_storyboardModel->setData(secIndex, invalidValue, Qt::EditRole); - QVERIFY(m_stroyboardModel->data(index), 100); + QCOMPARE(m_storyboardModel->data(secIndex).toInt(), 100); } void StoryboardModelTest::testCommentChanged() { auto tester = new QAbstractItemModelTester(m_storyboardModel, 0); - QModelIndex index = m_commentModel->createIndex(m_storyboardModel->rowCount(),4); + Q_UNUSED(tester); + QModelIndex parentIndex = m_storyboardModel->index(m_storyboardModel->rowCount() - 1, 0); + QModelIndex commentIndex = m_storyboardModel->index(4, 0, parentIndex); QVariant value = QVariant(QString("newComment")); - m_stroyboardModel->setData(index, value, Qt::EditRole); + m_storyboardModel->setData(commentIndex, value, Qt::EditRole); - QCOMPARE(m_stroyboardModel->data(index,Qt::EditRole), QString("newComment")); + QCOMPARE(m_storyboardModel->data(commentIndex).toString(), "newComment"); } QTEST_MAIN(StoryboardModelTest) diff --git a/plugins/dockers/storyboarddocker/tests/storyboardModelTest.h b/plugins/dockers/storyboarddocker/tests/storyboardModelTest.h index 952bc683b7..a7d3aa1949 100644 --- a/plugins/dockers/storyboarddocker/tests/storyboardModelTest.h +++ b/plugins/dockers/storyboarddocker/tests/storyboardModelTest.h @@ -1,53 +1,52 @@ /* * Copyright (c) 2020 Saurabh Kumar * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __STORYBOARD_MODEL_TEST_H #define __STORYBOARD_MODEL_TEST_H #include class CommentModel; class StoryboardModel; class StoryboardModelTest : public QObject { Q_OBJECT private Q_SLOTS: void init(); void cleanup(); //interaction with comment model - void testAddComment() + void testAddComment(); void testRemoveComment(); void testCommentNameChanged(); - void testCommentVisibilityChanged(); //"storyboard model only" tests void testFrameAdded(); void testFrameRemoved(); void testFrameChanged(); void testDurationChanged(); void testCommentChanged(); private: CommentModel *m_commentModel; StoryboardModel *m_storyboardModel; }; #endif /* __STORYBOARD_MODEL_TEST_H */