diff --git a/plugins/dockers/storyboarddocker/commentDelegate.cpp b/plugins/dockers/storyboarddocker/commentDelegate.cpp index e4501a7d0f..95a1415b86 100644 --- a/plugins/dockers/storyboarddocker/commentDelegate.cpp +++ b/plugins/dockers/storyboarddocker/commentDelegate.cpp @@ -1,134 +1,133 @@ /* * 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 "commentDelegate.h" #include #include #include #include #include #include #include #include -#include "commentModel.h" CommentDelegate::CommentDelegate(QObject *parent) : QStyledItemDelegate(parent) { } CommentDelegate::~CommentDelegate() { } void CommentDelegate::paint(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const { p->save(); { QStyle *style = option.widget ? option.widget->style() : QApplication::style(); style->drawPrimitive(QStyle::PE_PanelItemViewItem, &option, p, option.widget); p->setFont(option.font); { QIcon icon =index.model()->data(index, Qt::DecorationRole).value(); QRect r = option.rect; r.setSize(QSize(22, 22)); icon.paint(p, r); } { QRect r = option.rect; r.translate(25, 0); QString value = index.model()->data(index, Qt::DisplayRole).toString(); p->drawText(r, Qt::AlignLeft | Qt::AlignVCenter, value); } } p->restore(); } QSize CommentDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const { Q_UNUSED(index); return QSize(option.rect.width(), 22); } QWidget *CommentDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option , const QModelIndex &index) const { QLineEdit *editor = new QLineEdit(parent); return editor; } bool CommentDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) { QStyleOptionViewItem newOption = option; if ((event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonDblClick) && (index.flags() & Qt::ItemIsEnabled)) { QMouseEvent *mouseEvent = static_cast(event); QRect visibilityRect = option.rect; visibilityRect.setSize(QSize(22, 22)); const bool visibilityClicked = visibilityRect.isValid() && visibilityRect.contains(mouseEvent->pos()); const bool leftButton = mouseEvent->buttons() & Qt::LeftButton; if (leftButton && visibilityClicked) { - model->setData(index, true, CommentModel::VisibilityRole); + model->setData(index, true, Qt::DecorationRole); return true; } } return false; } //set the existing data in the editor void CommentDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const { QString value = index.model()->data(index, Qt::EditRole).toString(); QLineEdit *lineEdit = static_cast(editor); lineEdit->setText(value); } void CommentDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const { QLineEdit *lineEdit = static_cast(editor); QString value = lineEdit->text(); //don't add empty string model->setData(index, value, Qt::EditRole); //do we need to emit closeEditor() ??? } void CommentDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const { editor->setGeometry(option.rect); qDebug()<<"setting geometry"; } \ No newline at end of file diff --git a/plugins/dockers/storyboarddocker/commentModel.cpp b/plugins/dockers/storyboarddocker/commentModel.cpp index 11bcd5bcf2..cf3582a50c 100644 --- a/plugins/dockers/storyboarddocker/commentModel.cpp +++ b/plugins/dockers/storyboarddocker/commentModel.cpp @@ -1,127 +1,129 @@ /* * 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 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) { qDebug()<<"attempting data set"<=m_commentList.size()) return false; m_commentList.insert(position, newcomment); } endInsertRows(); return true; } bool CommentModel::removeRows(int position, int rows, const QModelIndex &parent) { qDebug()<<"row removed"; beginRemoveRows(QModelIndex(), position, position+rows-1); for (int row = 0; row < rows; ++row) { - m_commentList.removeAt(position); + if (position < 0 && position>=m_commentList.size()) return false; + m_commentList.removeAt(position); } endRemoveRows(); return true; } 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 83d9970290..8a0fff16d8 100644 --- a/plugins/dockers/storyboarddocker/commentModel.h +++ b/plugins/dockers/storyboarddocker/commentModel.h @@ -1,64 +1,58 @@ /* * 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 struct Comment { QString name; bool visibility; }; /* This model manages the comment data of StoryboardModel */ class CommentModel : public QAbstractListModel { Q_OBJECT public: - - enum ItemDataRole - { - VisibilityRole = Qt::UserRole + 1, - }; - 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()); Qt::DropActions supportedDropActions() const override; Qt::DropActions supportedDragActions() const override; private: QVector m_commentList; }; #endif \ No newline at end of file diff --git a/plugins/dockers/storyboarddocker/storyboarddocker_dock.cpp b/plugins/dockers/storyboarddocker/storyboarddocker_dock.cpp index f93a626547..d20755c574 100644 --- a/plugins/dockers/storyboarddocker/storyboarddocker_dock.cpp +++ b/plugins/dockers/storyboarddocker/storyboarddocker_dock.cpp @@ -1,227 +1,227 @@ /* * Copyright (c) 2020 Saurabh Kumar * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2 of the License, or * (at your option) any later version. * * This library 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 "storyboarddocker_dock.h" #include "commentDelegate.h" #include "commentModel.h" #include #include #include #include #include #include #include #include #include #include #include "ui_wdgstoryboarddock.h" #include "ui_wdgcommentmenu.h" #include "ui_wdgarrangemenu.h" class CommentMenu: public QMenu { Q_OBJECT public: CommentMenu(QWidget *parent) : QMenu(parent) , m_menuUI(new Ui_WdgCommentMenu()) , model(new CommentModel(this)) , delegate(new CommentDelegate(this)) { QWidget* commentWidget = new QWidget(this); m_menuUI->setupUi(commentWidget); m_menuUI->fieldListView->setDragEnabled(true); m_menuUI->fieldListView->setAcceptDrops(true); m_menuUI->fieldListView->setDropIndicatorShown(true); m_menuUI->fieldListView->setDragDropMode(QAbstractItemView::InternalMove); m_menuUI->fieldListView->setModel(model); m_menuUI->fieldListView->setItemDelegate(delegate); m_menuUI->fieldListView->setEditTriggers(QAbstractItemView::AnyKeyPressed | QAbstractItemView::DoubleClicked ); m_menuUI->btnAddField->setIcon(KisIconUtils::loadIcon("list-add")); m_menuUI->btnDeleteField->setIcon(KisIconUtils::loadIcon("trash-empty")); m_menuUI->btnAddField->setIconSize(QSize(22, 22)); m_menuUI->btnDeleteField->setIconSize(QSize(22, 22)); connect(m_menuUI->btnAddField, SIGNAL(clicked()), this, SLOT(slotaddItem())); connect(m_menuUI->btnDeleteField, SIGNAL(clicked()), this, SLOT(slotdeleteItem())); KisAction *commentAction = new KisAction(commentWidget); commentAction->setDefaultWidget(commentWidget); this->addAction(commentAction); } private Q_SLOTS: void slotaddItem() { - int row = model->rowCount(); + int row = m_menuUI->fieldListView->currentIndex().row()+1; model->insertRows(row, 1); QModelIndex index = model->index(row); m_menuUI->fieldListView->setCurrentIndex(index); m_menuUI->fieldListView->edit(index); } void slotdeleteItem() { model->removeRows(m_menuUI->fieldListView->currentIndex().row(), 1); } private: QScopedPointer m_menuUI; CommentModel *model; CommentDelegate *delegate; }; class ArrangeMenu: public QMenu { public: ArrangeMenu(QWidget *parent) : QMenu(parent) , m_menuUI(new Ui_WdgArrangeMenu()) , modeGroup(new QButtonGroup(this)) , viewGroup(new QButtonGroup(this)) { QWidget* arrangeWidget = new QWidget(this); m_menuUI->setupUi(arrangeWidget); modeGroup->addButton(m_menuUI->btnColumnMode, Qt::FlatCap); modeGroup->addButton(m_menuUI->btnRowMode, Qt::FlatCap); modeGroup->addButton(m_menuUI->btnGridMode, Qt::FlatCap); viewGroup->addButton(m_menuUI->btnAllView, Qt::FlatCap); viewGroup->addButton(m_menuUI->btnThumbnailsView, Qt::FlatCap); viewGroup->addButton(m_menuUI->btnCommentsView, Qt::FlatCap); KisAction *arrangeAction = new KisAction(arrangeWidget); arrangeAction->setDefaultWidget(arrangeWidget); this->addAction(arrangeAction); } QButtonGroup* getModeGroup(){ return modeGroup;} QButtonGroup* getViewGroup(){ return viewGroup;} private: QScopedPointer m_menuUI; QButtonGroup *modeGroup; QButtonGroup *viewGroup; }; StoryboardDockerDock::StoryboardDockerDock( ) : QDockWidget(i18n("Storyboard")) , m_ui(new Ui_WdgStoryboardDock()) { QWidget* mainWidget = new QWidget(this); setWidget(mainWidget); m_ui->setupUi(mainWidget); m_exportMenu = new QMenu(this); m_ui->btnExport->setMenu(m_exportMenu); m_ui->btnExport->setPopupMode(QToolButton::MenuButtonPopup); m_exportAsPdfAction = new KisAction("Export as PDF", m_exportMenu); m_exportMenu->addAction(m_exportAsPdfAction); m_exportAsSvgAction = new KisAction("Export as SVG"); m_exportMenu->addAction(m_exportAsSvgAction); connect(m_exportAsPdfAction, SIGNAL(triggered()), this, SLOT(slotExportAsPdf())); connect(m_exportAsSvgAction, SIGNAL(triggered()), this, SLOT(slotExportAsSvg())); m_commentMenu = new CommentMenu(this); m_ui->btnComment->setMenu(m_commentMenu); m_ui->btnComment->setPopupMode(QToolButton::MenuButtonPopup); m_lockAction = new KisAction(KisIconUtils::loadIcon("unlocked"), "Lock", m_ui->btnLock); m_lockAction->setCheckable(true); m_ui->btnLock->setDefaultAction(m_lockAction); m_ui->btnLock->setIconSize(QSize(22, 22)); connect(m_lockAction, SIGNAL(toggled(bool)), this, SLOT(slotLockClicked(bool))); m_arrangeMenu = new ArrangeMenu(this); m_ui->btnArrange->setMenu(m_arrangeMenu); m_ui->btnArrange->setPopupMode(QToolButton::InstantPopup); m_ui->btnArrange->setIcon(KisIconUtils::loadIcon("view-choose")); m_ui->btnArrange->setIconSize(QSize(22, 22)); m_modeGroup = m_arrangeMenu->getModeGroup(); m_viewGroup = m_arrangeMenu->getViewGroup(); connect(m_modeGroup, SIGNAL(buttonClicked(QAbstractButton*)), this, SLOT(slotModeChanged(QAbstractButton*))); connect(m_viewGroup, SIGNAL(buttonClicked(QAbstractButton*)), this, SLOT(slotViewChanged(QAbstractButton*))); } StoryboardDockerDock::~StoryboardDockerDock() { } void StoryboardDockerDock::setCanvas(KoCanvasBase *canvas) { } void StoryboardDockerDock::setViewManager(KisViewManager* kisview) { } void StoryboardDockerDock::slotExportAsPdf() { qDebug()<<"export as pdf"; slotExport("pdf"); } void StoryboardDockerDock::slotExportAsSvg() { qDebug()<<"export as svg"; slotExport("svg"); } void StoryboardDockerDock::slotExport(QString mode) { qDebug()<<"mode is "<setIcon(KisIconUtils::loadIcon("locked")); } else{ m_lockAction->setIcon(KisIconUtils::loadIcon("unlocked")); } } void StoryboardDockerDock::slotModeChanged(QAbstractButton* button) { qDebug()<<"Mode changed to "<text(); } void StoryboardDockerDock::slotViewChanged(QAbstractButton* button) { qDebug()<<"View changed to "<text(); } #include "storyboarddocker_dock.moc" \ No newline at end of file diff --git a/plugins/dockers/storyboarddocker/tests/storyboardModelTest.cpp b/plugins/dockers/storyboarddocker/tests/storyboardModelTest.cpp index 3bb7ff7956..61b049c2c1 100644 --- a/plugins/dockers/storyboarddocker/tests/storyboardModelTest.cpp +++ b/plugins/dockers/storyboarddocker/tests/storyboardModelTest.cpp @@ -1,125 +1,169 @@ /* * 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" void StoryboardModelTest::init() { m_commentModel = new CommentModel(0); m_storyboardModel = new StoryboardModel(0); - QCOMPARE(m_storyboardModel->columnCount(), 1); - m_commentModel->insertRows(m_storyboardModel->rowCount(),1); + m_commentModel->insertRows(m_commentModel->rowCount(),1); QCOMPARE(m_commentModel->rowCount(), 1); } void StoryboardModelTest::cleanup() { delete m_storyboardModel; delete m_commentModel; } void StoryboardModelTest::testAddComment() { + + auto tester = new QAbstractItemModelTester(m_storyboardModel, 0); + auto tester = new QAbstractItemModelTester(m_commentModel, 0); + int commentStoryboard = m_storyboardModel->commentCount(); int rowsComment = m_commentModel->rowCount(); QCOMPARE(commentStoryboard, rowsComment); m_commentModel->insertRows(m_commentModel->rowCount(),1); - auto tester = new QAbstractItemModelTester(m_storyboardModel, 0); - auto tester = new QAbstractItemModelTester(m_commentModel, 0); QCOMPARE(rowsComment + 1, m_commentModel->rowCount()); + QCOMPARE(m_storyboardModel->commentCount(), m_commentModel->rowCount()); + + //add at an invalid position + m_commentModel->insertRows(-1, 1); + QCOMPARE(rowsComment + 1, m_commentModel->rowCount()); QCOMPARE(m_storyboardModel->commentCount(), m_commentModel->rowCount()); + } void StoryboardModelTest::testRemoveComment() { + + auto tester = new QAbstractItemModelTester(m_storyboardModel, 0); + auto tester = new QAbstractItemModelTester(m_commentModel, 0); int commentStoryboard = m_storyboardModel->commentCount(); int rowsComment = m_commentModel->rowCount(); QCOMPARE(commentStoryboard, rowsComment); m_commentModel->removeRows(m_commentModel->rowCount(),1); - auto tester = new QAbstractItemModelTester(m_storyboardModel, 0); - auto tester = new QAbstractItemModelTester(m_commentModel, 0); + QCOMPARE(rowsComment - 1, m_commentModel->rowCount()); + QCOMPARE(m_storyboardModel->commentCount(), m_commentModel->rowCount()); + + m_commentModel->removeRows(-1,1); QCOMPARE(rowsComment - 1, m_commentModel->rowCount()); QCOMPARE(m_storyboardModel->commentCount(), m_commentModel->rowCount()); } void StoryboardModelTest::testCommentNameChanged() { + auto tester = new QAbstractItemModelTester(m_commentModel, 0); QModelIndex index = m_commentModel->createIndex(m_commentModel->rowCount(),m_commentModel->columnCount()); QVariant value = QVariant(QString("newValue")); m_commentModel->setData(index, value); - auto tester = new QAbstractItemModelTester(m_commentModel, 0); + + 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() { - m_storyboardModel->insertRows(m_storyboardModel->rowCount(),1); + int rows = m_storyboardModel->rowCount(); auto tester = new QAbstractItemModelTester(m_storyboardModel, 0); + m_storyboardModel->insertRows(m_storyboardModel->rowCount(),1); + + QCOMPARE(rows + 1, m_storyboardModel->rowCount()); } void StoryboardModelTest::testFrameRemoved() { - m_storyboardModel->removeRows(m_storyboardModel->rowCount(),1); + int rows = m_storyboardModel->rowCount(); auto tester = new QAbstractItemModelTester(m_storyboardModel, 0); + m_storyboardModel->removeRows(m_storyboardModel->rowCount(),1); + + QCOMPARE(rows-1, m_storyboardModel->rowCount()); } void StoryboardModelTest::testFrameChanged() { - QModelIndex index = m_commentModel->createIndex(m_storyboardModel->rowCount(),m_storyboardModel->columnCount()); - QVariant value = QVariant(100); - m_stroyboardModel->setData(index, value, StoryboardModel::FrameRole); + auto tester = new QAbstractItemModelTester(m_storyboardModel, 0); - //should we have multiple custom roles to differentiate between what data is coming in?? + QModelIndex index = m_commentModel->createIndex(m_storyboardModel->rowCount(), 1); + QVariant value = QVariant(100); + m_stroyboardModel->setData(index, value, Qt::EditRole); + + QCOMPARE(m_stroyboardModel->data(index), 100); + + //invalid value shouldn't change anything + QVariant value = QVariant(-100); + m_stroyboardModel->setData(index, value, Qt::EditRole); + + QVERIFY(m_stroyboardModel->data(index), 100); + + } void StoryboardModelTest::testDurationChanged() { - QModelIndex index = m_commentModel->createIndex(m_storyboardModel->rowCount(),m_storyboardModel->columnCount()); - QVariant value = QVariant(100); - m_stroyboardModel->setData(index, value, StoryboardModel::DurationRole); auto tester = new QAbstractItemModelTester(m_storyboardModel, 0); + QModelIndex index = m_commentModel->createIndex(m_storyboardModel->rowCount(), 2); + QVariant value = QVariant(100); + m_stroyboardModel->setData(index, value, Qt::EditRole); + + QCOMPARE(m_stroyboardModel->data(index), 100); + + //invalid value shouldn't change anything + QVariant value = QVariant(-1); + m_stroyboardModel->setData(index, value, Qt::EditRole); + + QVERIFY(m_stroyboardModel->data(index), 100); } void StoryboardModelTest::testCommentChanged() { - QModelIndex index = m_commentModel->createIndex(m_storyboardModel->rowCount(),m_storyboardModel->columnCount()); - QVariant value = QVariant(100); - m_stroyboardModel->setData(index, value, StoryboardModel::CommentRole); auto tester = new QAbstractItemModelTester(m_storyboardModel, 0); - //should we store different comments in different columns?? + QModelIndex index = m_commentModel->createIndex(m_storyboardModel->rowCount(),4); + QVariant value = QVariant(QString("newComment")); + m_stroyboardModel->setData(index, value, Qt::EditRole); + + QCOMPARE(m_stroyboardModel->data(index,Qt::EditRole), QString("newComment")); } QTEST_MAIN(StoryboardModelTest)