diff --git a/plugins/dockers/storyboarddocker/storyboardDelegate.cpp b/plugins/dockers/storyboarddocker/storyboardDelegate.cpp index 5b102588d5..ab13ef6c42 100644 --- a/plugins/dockers/storyboarddocker/storyboardDelegate.cpp +++ b/plugins/dockers/storyboarddocker/storyboardDelegate.cpp @@ -1,519 +1,534 @@ /* * 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 "storyboardDelegate.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "storyboardModel.h" StoryboardDelegate::StoryboardDelegate(QObject *parent) : QStyledItemDelegate(parent) { } StoryboardDelegate::~StoryboardDelegate() { } void StoryboardDelegate::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); if (!index.isValid()){ p->restore(); return; } if (!index.parent().isValid()){ QRect parentRect = option.rect; p->drawRect(parentRect); parentRect.setTopLeft(parentRect.topLeft() + QPoint(4, 4)); parentRect.setBottomRight(parentRect.bottomRight() - QPoint(4, 4)); //TODO: change highlight color and the area that is highlighted if (option.state & QStyle::State_Selected){ p->fillRect(option.rect, option.palette.foreground()); } else { p->fillRect(option.rect, option.palette.background()); } p->eraseRect(parentRect); } else{ //paint Child index (the indices that hold data) QModelIndex parent = index.parent(); //draw the child items int rowNum = index.model()->rowCount(parent); int childNum = index.row(); QString data = index.model()->data(index, Qt::DisplayRole).toString(); switch (childNum) { case 0: { QRect frameNumRect = option.rect; frameNumRect.setHeight(m_view->fontMetrics().height()+3); frameNumRect.setWidth(3 * m_view->fontMetrics().width("0")+2); frameNumRect.moveBottom(option.rect.top()-1); p->setPen(QPen(option.palette.dark(), 2)); p->drawRect(frameNumRect); p->setPen(QPen(option.palette.text(), 1)); p->drawText(frameNumRect, Qt::AlignHCenter | Qt::AlignVCenter, data); QIcon icon = KisIconUtils::loadIcon("krita-base"); + + QRect thumbnailRect = option.rect; + //TO DO make thumbnail keep aspect ratio icon.paint(p, option.rect); p->setPen(QPen(option.palette.dark(), 2)); p->drawRect(option.rect); if (option.state & QStyle::State_MouseOver){ QRect buttonsRect = option.rect; buttonsRect.setTop(option.rect.bottom() - 22); p->fillRect(buttonsRect, option.palette.background()); buttonsRect.setWidth(22); buttonsRect.moveBottomLeft(option.rect.bottomLeft()); QIcon addIcon = KisIconUtils::loadIcon("list-add"); addIcon.paint(p, buttonsRect); buttonsRect.moveBottomRight(option.rect.bottomRight()); QIcon deleteIcon = KisIconUtils::loadIcon("trash-empty"); deleteIcon.paint(p, buttonsRect); } break; } case 1: { QRect itemNameRect = option.rect; itemNameRect.setLeft(option.rect.left() + 5); p->setPen(QPen(option.palette.text(), 1)); p->drawText(itemNameRect, Qt::AlignLeft | Qt::AlignVCenter, data); p->setPen(QPen(option.palette.dark(), 2)); p->drawRect(option.rect); break; } case 2: //time duration case 3: //frame duration { drawSpinBox(p, option, data); break; } default: { const StoryboardModel* model = dynamic_cast(index.model()); if (model->getComment(index.row() - 4).visibility){ p->setPen(QPen(option.palette.dark(), 2)); drawComment(p, option, index); } break; } } } } p->restore(); } void StoryboardDelegate::drawSpinBox(QPainter *p, const QStyleOptionViewItem &option, QString data) const { QStyle *style = option.widget ? option.widget->style() : QApplication::style(); QStyleOptionSpinBox spinBoxOption; spinBoxOption.stepEnabled = QAbstractSpinBox::StepDownEnabled | QAbstractSpinBox::StepUpEnabled; spinBoxOption.subControls = QStyle::SC_SpinBoxUp | QStyle::SC_SpinBoxDown; spinBoxOption.rect = option.rect; p->setPen(QPen(option.palette.dark(), 2)); p->drawRect(option.rect); style->drawComplexControl(QStyle::CC_SpinBox, &spinBoxOption, p, option.widget); QRect rect = style->subControlRect(QStyle::CC_SpinBox, &spinBoxOption, QStyle::QStyle::SC_SpinBoxEditField); rect.moveTopLeft(option.rect.topLeft()); p->setPen(QPen(option.palette.text(), 1)); p->drawText(rect, Qt::AlignHCenter | Qt::AlignVCenter, data); } QStyleOptionSlider StoryboardDelegate::drawComment(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const { QStyle *style = option.widget ? option.widget->style() : QApplication::style(); const StoryboardModel* model = dynamic_cast(index.model()); QString data = index.model()->data(index, Qt::DisplayRole).toString(); QRect titleRect = option.rect; titleRect.setHeight(option.fontMetrics.height() + 3); if (p){ p->setPen(QPen(option.palette.text(), 1)); p->drawText(titleRect, Qt::AlignLeft | Qt::AlignVCenter, model->getComment(index.row() - 4).name); + p->setPen(QPen(option.palette.dark(), 2)); + p->drawRect(titleRect); } QRect contentRect = option.rect; contentRect.setTop(option.rect.top() + option.fontMetrics.height() + 3); if (p){ p->setPen(QPen(option.palette.dark(), 2)); p->drawRect(contentRect); p->save(); } contentRect.setTopLeft(contentRect.topLeft() + QPoint(5, 5)); contentRect.setBottomRight(contentRect.bottomRight() - QPoint(5, 5)); int scrollValue = index.model()->data(index, Qt::UserRole).toInt(); //draw comment QRect commentRect = contentRect; commentRect.setRight(contentRect.right() - 15); QTextDocument doc; doc.setTextWidth(commentRect.width()); doc.setDocumentMargin(0); doc.setDefaultFont(option.font); doc.setPlainText(data.simplified()); QRectF clipRect = commentRect; clipRect.moveTopLeft(QPoint(0, 0 + scrollValue)); if (p){ p->translate(QPoint(commentRect.topLeft().x(), commentRect.topLeft().y() - scrollValue)); p->setPen(QPen(option.palette.text(), 1)); doc.drawContents(p, clipRect); p->restore(); } //draw scroll bar QStyleOptionSlider scrollbarOption; scrollbarOption.sliderPosition = scrollValue; scrollbarOption.minimum = 0; scrollbarOption.maximum = qMax(0.0, doc.size().height() - contentRect.height()); scrollbarOption.sliderPosition = qMin(scrollValue, scrollbarOption.maximum); scrollbarOption.pageStep = contentRect.height() - 2; scrollbarOption.orientation = Qt::Vertical; QRect scrollRect = option.rect; scrollRect.setTop(option.rect.top() + option.fontMetrics.height() + 3); scrollRect.setLeft(option.rect.right()-15); scrollbarOption.rect = scrollRect; if (p){ p->save(); p->setPen(QPen(option.palette.dark(), 2)); p->translate(scrollRect.topLeft()); - p->drawRect(scrollRect); style->drawComplexControl(QStyle::CC_ScrollBar, &scrollbarOption, p, option.widget); p->restore(); } return scrollbarOption; } QSize StoryboardDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const { if (!index.parent().isValid()){ - int width = option.widget->width() - 17; - const StoryboardModel* model = dynamic_cast(index.model()); - int numComments = model->visibleCommentCount(); - int numItem = width/250; - if(numItem <=0){ - return QSize(0, 0); + if (m_view->itemOrientation() == Qt::Vertical){ + int width = m_view->viewport()->width(); + const StoryboardModel* model = dynamic_cast(index.model()); + int numComments = model->visibleCommentCount(); + int numItem = width/250; + if(numItem <=0){ + return QSize(0, 0); + } + return QSize(width / numItem, 120 + option.fontMetrics.height() + 3 + numComments*100 + 10); + } + else{ + const StoryboardModel* model = dynamic_cast(index.model()); + int numComments = model->visibleCommentCount(); + int commentWidth = 200; + if (numComments){ + commentWidth = qMax(200, (m_view->viewport()->width() - 250) / numComments); + } + int width = 250 + numComments * commentWidth; + return QSize(width + 10, 120 + option.fontMetrics.height() + 3 + 10); } - return QSize(width / numItem, 120 + option.fontMetrics.height() + 3 + numComments*100 + 10); } else { return option.rect.size(); } return QSize(0,0); } - QWidget *StoryboardDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option , const QModelIndex &index) const { //only create editor for children if (index.parent().isValid()){ int row = index.row(); switch (row) { case 0: //frame thumbnail is uneditable return nullptr; case 1: { QLineEdit *editor = new QLineEdit(parent); return editor; } case 2: //second and frame spin box case 3: { QSpinBox *spinbox = new QSpinBox(parent); spinbox->setRange(0, 999); return spinbox; } default: // for itemName and comments { QTextEdit *editor = new QTextEdit(parent); return editor; } } } return nullptr; } bool StoryboardDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) { if ((event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonDblClick) && (index.flags() & Qt::ItemIsEnabled)) { QMouseEvent *mouseEvent = static_cast(event); const bool leftButton = mouseEvent->buttons() & Qt::LeftButton; //handle the duration edit event if (index.parent().isValid() && (index.row() == 2 || index.row() == 3)){ QRect upButton = spinBoxUpButton(option); QRect downButton = spinBoxDownButton(option); bool upButtonClicked = upButton.isValid() && upButton.contains(mouseEvent->pos()); bool downButtonClicked = downButton.isValid() && downButton.contains(mouseEvent->pos()); if (leftButton && upButtonClicked){ model->setData(index, index.data().toInt() + 1); return true; } else if (leftButton && downButtonClicked){ model->setData(index, std::max(0,index.data().toInt() - 1)); return true; } } else if (index.parent().isValid() && index.row() > 3){ QStyleOptionSlider scrollBarOption = drawComment(nullptr, option, index); QRect upButton = scrollUpButton(option, scrollBarOption); QRect downButton = scrollDownButton(option, scrollBarOption); bool upButtonClicked = upButton.isValid() && upButton.contains(mouseEvent->pos()); bool downButtonClicked = downButton.isValid() && downButton.contains(mouseEvent->pos()); if (leftButton && upButtonClicked){ int lastValue = model->data(index, Qt::UserRole).toInt(); int value = lastValue - option.fontMetrics.height(); StoryboardModel* modelSB = dynamic_cast(model); modelSB->setCommentScrollData(index, qMax(0, value)); return true; } else if (leftButton && downButtonClicked){ int lastValue = model->data(index, Qt::UserRole).toInt(); int value = lastValue + option.fontMetrics.height(); StoryboardModel* modelSB = dynamic_cast(model); modelSB->setCommentScrollData(index, qMin(scrollBarOption.maximum, value)); return true; } } } if ((event->type() == QEvent::MouseMove) && (index.flags() & Qt::ItemIsEnabled)) { QMouseEvent *mouseEvent = static_cast(event); const bool leftButton = mouseEvent->buttons() & Qt::LeftButton; QStyleOptionSlider scrollBarOption = drawComment(nullptr, option, index); QRect scrollBarRect = scrollBar(option, scrollBarOption); bool lastClickPosInScroll = scrollBarRect.isValid() && scrollBarRect.contains(m_lastDragPos); bool currClickPosInScroll = scrollBarRect.isValid() && scrollBarRect.contains(mouseEvent->pos()); if (leftButton && index.parent().isValid() && index.row() > 3){ if (lastClickPosInScroll && currClickPosInScroll){ int lastValue = model->data(index, Qt::UserRole).toInt(); int value = lastValue + mouseEvent->pos().y() - m_lastDragPos.y(); StoryboardModel* modelSB = dynamic_cast(model); if (value >= 0 && value <= scrollBarOption.maximum){ modelSB->setCommentScrollData(index, value); return true; } return false; } m_lastDragPos = mouseEvent->pos(); } } return false; } //set the existing data in the editor void StoryboardDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const { QVariant value = index.data(); if (index.parent().isValid()){ int row = index.row(); switch (row) { case 0: //frame thumbnail is uneditable return; case 1: //for itemName { QLineEdit *lineEdit = static_cast(editor); lineEdit->setText(value.toString()); return; } case 2: //second and frame spin box case 3: { QSpinBox *spinbox = static_cast(editor); spinbox->setValue(value.toInt()); return; } default: // for comments { QTextEdit *textEdit = static_cast(editor); textEdit->setText(value.toString()); + textEdit->moveCursor(QTextCursor::End, QTextCursor::MoveAnchor); textEdit->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); textEdit->verticalScrollBar()->setProperty("index", index); connect(textEdit->verticalScrollBar(), SIGNAL(sliderMoved(int)), this, SLOT(slotCommentScrolledTo(int))); return; } } } } void StoryboardDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const { QVariant value = index.data(); if (index.parent().isValid()){ int row = index.row(); switch (row) { case 0: //frame thumbnail is uneditable return; case 1: // for itemName { QLineEdit *lineEdit = static_cast(editor); QString value = lineEdit->text(); model->setData(index, value, Qt::EditRole); return; } case 2: //second and frame spin box case 3: { QSpinBox *spinbox = static_cast(editor); int value = spinbox->value(); model->setData(index, value, Qt::EditRole); return; } default: // for comments { QTextEdit *textEdit = static_cast(editor); QString value = textEdit->toPlainText(); model->setData(index, value, Qt::EditRole); return; } } } } void StoryboardDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const { if (index.row() < 4){ editor->setGeometry(option.rect); } else { //for comment textedits QRect commentRect = option.rect; commentRect.setTop(option.rect.top() + option.fontMetrics.height() + 3); editor->setGeometry(commentRect); } } -void StoryboardDelegate::setView(QListView *view) +void StoryboardDelegate::setView(StoryboardView *view) { m_view = view; } QRect StoryboardDelegate::spinBoxUpButton(const QStyleOptionViewItem &option) { QStyle *style = option.widget ? option.widget->style() : QApplication::style(); QStyleOptionSpinBox spinOption; spinOption.rect = option.rect; QRect rect = style->subControlRect(QStyle::CC_SpinBox, &spinOption, QStyle::QStyle::SC_SpinBoxUp); rect.moveTopRight(option.rect.topRight()); return rect; } QRect StoryboardDelegate::spinBoxDownButton(const QStyleOptionViewItem &option) { QStyle *style = option.widget ? option.widget->style() : QApplication::style(); QStyleOptionSpinBox spinOption; spinOption.rect = option.rect; QRect rect = style->subControlRect(QStyle::CC_SpinBox, &spinOption, QStyle::QStyle::SC_SpinBoxDown); rect.moveBottomRight(option.rect.bottomRight()); return rect; } QRect StoryboardDelegate::spinBoxEditField(const QStyleOptionViewItem &option) { QStyle *style = option.widget ? option.widget->style() : QApplication::style(); QStyleOptionSpinBox spinOption; spinOption.rect = option.rect; QRect rect = style->subControlRect(QStyle::CC_SpinBox, &spinOption, QStyle::QStyle::SC_SpinBoxEditField); rect.moveTopLeft(option.rect.topLeft()); return rect; } void StoryboardDelegate::slotCommentScrolledTo(int value) const { const QModelIndex index = sender()->property("index").toModelIndex(); StoryboardModel* model = dynamic_cast(m_view->model()); model->setCommentScrollData(index, value); } QRect StoryboardDelegate::scrollBar(const QStyleOptionViewItem &option, QStyleOptionSlider &scrollBarOption) const { QStyle *style = option.widget ? option.widget->style() : QApplication::style(); QRect rect = style->subControlRect(QStyle::CC_ScrollBar, &scrollBarOption, QStyle::QStyle::SC_ScrollBarSlider); rect.moveTopLeft(rect.topLeft() + scrollBarOption.rect.topLeft()); return rect; } QRect StoryboardDelegate::scrollDownButton(const QStyleOptionViewItem &option, QStyleOptionSlider &scrollBarOption) { QStyle *style = option.widget ? option.widget->style() : QApplication::style(); QRect rect = style->subControlRect(QStyle::CC_ScrollBar, &scrollBarOption, QStyle::QStyle::SC_ScrollBarAddLine); rect.moveTopLeft(rect.topLeft() + scrollBarOption.rect.topLeft()); return rect; } QRect StoryboardDelegate::scrollUpButton(const QStyleOptionViewItem &option, QStyleOptionSlider &scrollBarOption) { - QStyle *style = option.widget ? option.widget->style() : QApplication::style(); QRect rect = style->subControlRect(QStyle::CC_ScrollBar, &scrollBarOption, QStyle::QStyle::SC_ScrollBarSubLine); rect.moveTopLeft(rect.topLeft() + scrollBarOption.rect.topLeft()); return rect; } diff --git a/plugins/dockers/storyboarddocker/storyboardDelegate.h b/plugins/dockers/storyboarddocker/storyboardDelegate.h index 3cafba58b6..6371abb8c6 100644 --- a/plugins/dockers/storyboarddocker/storyboardDelegate.h +++ b/plugins/dockers/storyboarddocker/storyboardDelegate.h @@ -1,68 +1,69 @@ /* * 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_DELEGATE_H #define __STORYBOARD_DELEGATE_H #include +#include "storyboardView.h" class QListView; class StoryboardModel; class StoryboardDelegate : public QStyledItemDelegate { Q_OBJECT public: StoryboardDelegate(QObject *parent); ~StoryboardDelegate() override; void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override; QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override; bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index); QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const; void setEditorData(QWidget *editor, const QModelIndex &index) const; void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const; void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const; - void setView(QListView *view); + void setView(StoryboardView *view); void drawSpinBox(QPainter *p, const QStyleOptionViewItem &option, QString data) const; QStyleOptionSlider drawComment(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const; QRect spinBoxUpButton(const QStyleOptionViewItem &option); QRect spinBoxDownButton(const QStyleOptionViewItem &option); QRect spinBoxEditField(const QStyleOptionViewItem &option); QRect scrollBar(const QStyleOptionViewItem &option, QStyleOptionSlider &scrollBarOption) const; QRect scrollDownButton(const QStyleOptionViewItem &option, QStyleOptionSlider &scrollBarOption); QRect scrollUpButton(const QStyleOptionViewItem &option, QStyleOptionSlider &scrollBarOption); private Q_SLOTS: void slotCommentScrolledTo(int value) const; private: - QListView *m_view; + StoryboardView *m_view; QPoint m_lastDragPos = QPoint(0, 0); }; #endif diff --git a/plugins/dockers/storyboarddocker/storyboardView.cpp b/plugins/dockers/storyboarddocker/storyboardView.cpp index dd1973ba77..d846c97aba 100644 --- a/plugins/dockers/storyboarddocker/storyboardView.cpp +++ b/plugins/dockers/storyboarddocker/storyboardView.cpp @@ -1,170 +1,199 @@ /* Copyright (c) 2020 Saurabh Kumar This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include #include "storyboardView.h" #include "storyboardModel.h" /** * This view draws the children of every index in the first column of * the model inside the parent * * */ StoryboardView::StoryboardView(QWidget *parent) :QListView(parent) { - setWrapping(true); setFlow(QListView::LeftToRight); setResizeMode(QListView::Adjust); setUniformItemSizes(true); setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); QWidget::setMouseTracking(true); //make drag and drop work as expected /* setDragEnabled(true); setAcceptDrops(true); setDropIndicatorShown(true); setDragDropMode(QAbstractItemView::InternalMove); - */ +*/ } StoryboardView::~StoryboardView() {} void StoryboardView::paintEvent(QPaintEvent *event) { event->accept(); QListView::paintEvent(event); //ask delegate to draw the child nodes too QPainter painter(viewport()); int itemNum = model()->rowCount(); for (int row = 0; row < itemNum; row++){ QModelIndex index = model()->index(row, 0); int childNum = model()->rowCount(index); for (int childRow = 0; childRow < childNum; childRow++){ QModelIndex childIndex = model()->index(childRow, 0, index); QStyleOptionViewItem option; - //TO DO: check if the childIndex is in focus - //TO DO: set proper options for spinbox type indices if (selectionModel()->isSelected(childIndex)) { option.state |= QStyle::State_Selected; } if (childIndex == selectionModel()->currentIndex()) { option.state |= QStyle::State_HasFocus; } if (childIndex == m_hoverIndex){ option.state |= QStyle::State_MouseOver; } option.font = font(); option.fontMetrics = fontMetrics(); option.rect = visualRect(childIndex); itemDelegate()->paint(&painter, option, childIndex); } } } QRect StoryboardView::visualRect(const QModelIndex &index) const { if (!index.isValid() || !index.parent().isValid()) { return QListView::visualRect(index); } else { QRect parentRect = visualRect(index.parent()); parentRect.setTopLeft(parentRect.topLeft() + QPoint(5, 5)); parentRect.setBottomRight(parentRect.bottomRight() - QPoint(5, 5)); int fontHeight = fontMetrics().height() + 3; int numericFontWidth = fontMetrics().width("0"); int height = parentRect.height(); - int width = parentRect.width(); + int parentWidth = parentRect.width(); int childRow = index.row(); + + int thumbnailWidth = parentWidth; + if (m_itemOrientation == Qt::Horizontal){ + thumbnailWidth = 250; + } switch (childRow) { case 0: { //the frame thumbnail rect - parentRect.setSize(QSize(width, 120)); + parentRect.setSize(QSize(thumbnailWidth, 120)); parentRect.translate(0, fontHeight); return parentRect; } case 1: { QRect itemNameRect = parentRect; - itemNameRect.setSize(QSize(width - (10 * numericFontWidth + 22), fontHeight)); + itemNameRect.setSize(QSize(thumbnailWidth - (10 * numericFontWidth + 22), fontHeight)); itemNameRect.moveLeft(parentRect.left() + 3*numericFontWidth + 2); return itemNameRect; } case 2: { QRect secondRect = parentRect; secondRect.setSize(QSize(4 * numericFontWidth + 10, fontHeight)); - secondRect.moveRight(parentRect.right() - 3*numericFontWidth -10); + //secondRect.moveRight(parentRect.right() - 3*numericFontWidth -10); + secondRect.moveLeft(parentRect.left() - 7*numericFontWidth + thumbnailWidth -20); return secondRect; } case 3: { QRect frameRect = parentRect; frameRect.setSize(QSize(3 * numericFontWidth + 10, fontHeight)); frameRect.moveRight(parentRect.right()); + frameRect.moveLeft(parentRect.left() - 3*numericFontWidth + thumbnailWidth - 10); return frameRect; } default: { //comment rect - const StoryboardModel* Model = dynamic_cast(model()); - parentRect.setTop(parentRect.top() + 120 + fontHeight + Model->visibleCommentsUpto(index) * 100); - parentRect.setHeight(100); - return parentRect; + if (m_itemOrientation == Qt::Vertical){ + const StoryboardModel* Model = dynamic_cast(model()); + parentRect.setTop(parentRect.top() + 120 + fontHeight + Model->visibleCommentsUpto(index) * 100); + parentRect.setHeight(100); + return parentRect; + } + else { + const StoryboardModel* Model = dynamic_cast(model()); + //TODO: dynamically set commentrect's size + int numVisibleComments = Model->visibleCommentCount(); + int commentWidth = 200; + if (numVisibleComments){ + commentWidth = qMax(200, (viewport()->width() - 250) / numVisibleComments); + } + parentRect.setSize(QSize(commentWidth, 120 + fontHeight)); + parentRect.moveLeft(parentRect.left() + thumbnailWidth + Model->visibleCommentsUpto(index) * commentWidth); + return parentRect; + } } } } return QRect(); } QModelIndex StoryboardView::indexAt(const QPoint &point) const { QModelIndex index = QListView::indexAt(point); if (index.isValid()) { //look for the index in children of the current index int numChild = model()->rowCount(index); for (int row = 0; row < numChild; row++) { QRect childRect = visualRect(model()->index(row, 0, index)); if (childRect.contains(point)) { return model()->index(row, 0, index); } } } return index; } void StoryboardView::mouseMoveEvent(QMouseEvent *event) { event->accept(); QListView::mouseMoveEvent(event); m_hoverIndex = indexAt(event->pos()); } + +void StoryboardView::setItemOrientation(Qt::Orientation orientation) +{ + m_itemOrientation = orientation; +} + +Qt::Orientation StoryboardView::itemOrientation() +{ + return m_itemOrientation; +} + diff --git a/plugins/dockers/storyboarddocker/storyboardView.h b/plugins/dockers/storyboarddocker/storyboardView.h index 0c293db6f5..d5bf7db9ce 100644 --- a/plugins/dockers/storyboarddocker/storyboardView.h +++ b/plugins/dockers/storyboarddocker/storyboardView.h @@ -1,51 +1,54 @@ /* Copyright (c) 2020 Saurabh Kumar This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef STORYBOARD_VIEW_H #define STORYBOARD_VIEW_H #include #include class QStyleOptionViewItem; class StoryboardModel; /** * This view draws the children of every index in the first column of * the model inside the parent index * * */ class StoryboardView: public QListView { Q_OBJECT public: explicit StoryboardView(QWidget *parent = 0); ~StoryboardView() override; void paintEvent(QPaintEvent *event) override; QRect visualRect(const QModelIndex &index) const override; QModelIndex indexAt(const QPoint &point) const override; void mouseMoveEvent(QMouseEvent *event) override; + void setItemOrientation(Qt::Orientation orientation); + Qt::Orientation itemOrientation(); private: QModelIndex m_hoverIndex; + Qt::Orientation m_itemOrientation; }; #endif diff --git a/plugins/dockers/storyboarddocker/storyboarddocker_dock.cpp b/plugins/dockers/storyboarddocker/storyboarddocker_dock.cpp index 969a5a4a31..7488755f63 100644 --- a/plugins/dockers/storyboarddocker/storyboarddocker_dock.cpp +++ b/plugins/dockers/storyboarddocker/storyboarddocker_dock.cpp @@ -1,253 +1,260 @@ /* * 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 "storyboardModel.h" #include "storyboardDelegate.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, CommentModel *m_model) : QMenu(parent) , m_menuUI(new Ui_WdgCommentMenu()) , model(m_model) , 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 = 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); + modeGroup->addButton(m_menuUI->btnColumnMode, 0); + modeGroup->addButton(m_menuUI->btnRowMode, 1); + modeGroup->addButton(m_menuUI->btnGridMode, 2); - viewGroup->addButton(m_menuUI->btnAllView, Qt::FlatCap); - viewGroup->addButton(m_menuUI->btnThumbnailsView, Qt::FlatCap); - viewGroup->addButton(m_menuUI->btnCommentsView, Qt::FlatCap); + viewGroup->addButton(m_menuUI->btnAllView, 0); + viewGroup->addButton(m_menuUI->btnThumbnailsView, 1); + viewGroup->addButton(m_menuUI->btnCommentsView, 2); 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_commentModel = new CommentModel(this); m_commentMenu = new CommentMenu(this, m_commentModel); 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*))); + m_modeGroup->button(0)->click(); + m_viewGroup->button(0)->click(); + m_storyboardModel = new StoryboardModel(this); StoryboardDelegate *delegate = new StoryboardDelegate(this); delegate->setView(m_ui->listView); m_ui->listView->setModel(m_storyboardModel); m_ui->listView->setItemDelegate(delegate); delegate->setView(m_ui->listView); m_storyboardModel->insertRows(0, 10); m_storyboardModel->setCommentModel(m_commentModel); } 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(); QString mode = button->text(); - if (mode == "Row"){ + if (mode == "Column"){ m_ui->listView->setFlow(QListView::LeftToRight); m_ui->listView->setWrapping(false); + m_ui->listView->setItemOrientation(Qt::Vertical); } - else if (mode == "Column"){ + else if (mode == "Row"){ m_ui->listView->setFlow(QListView::TopToBottom); m_ui->listView->setWrapping(false); + //TO DO: change item orientation. + m_ui->listView->setItemOrientation(Qt::Horizontal); } else if (mode == "Grid"){ m_ui->listView->setFlow(QListView::LeftToRight); m_ui->listView->setWrapping(true); + m_ui->listView->setItemOrientation(Qt::Vertical); } } void StoryboardDockerDock::slotViewChanged(QAbstractButton* button) { qDebug()<<"View changed to "<text(); } #include "storyboarddocker_dock.moc" \ No newline at end of file