1 /*
2  *  SPDX-FileCopyrightText: 2014 Andreas Cord-Landwehr <cordlandwehr@kde.org>
3  *
4  *  SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
5  */
6 
7 #include "nodetypesdelegate.h"
8 #include "libgraphtheory/nodetype.h"
9 #include "libgraphtheory/dialogs/nodetypeproperties.h"
10 #include "libgraphtheory/models/nodetypemodel.h"
11 #include <KColorButton>
12 #include <KLocalizedString>
13 #include <QApplication>
14 #include <QAbstractItemView>
15 #include <QDebug>
16 #include <QLabel>
17 #include <QLineEdit>
18 #include <QPainter>
19 #include <QPointer>
20 #include <QPushButton>
21 #include <QToolButton>
22 
23 using namespace GraphTheory;
24 
NodeTypesDelegate(QAbstractItemView * parent)25 NodeTypesDelegate::NodeTypesDelegate(QAbstractItemView* parent)
26     : KWidgetItemDelegate(parent, parent->viewport())
27 {
28 
29 }
30 
~NodeTypesDelegate()31 NodeTypesDelegate::~NodeTypesDelegate()
32 {
33 
34 }
35 
paint(QPainter * painter,const QStyleOptionViewItem & option,const QModelIndex & index) const36 void NodeTypesDelegate::paint(QPainter* painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
37 {
38     if (!index.isValid()) {
39         return;
40     }
41     QApplication::style()->drawPrimitive(QStyle::PE_PanelItemViewItem, &option, painter, nullptr);
42 }
43 
sizeHint(const QStyleOptionViewItem & option,const QModelIndex & index) const44 QSize NodeTypesDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const
45 {
46     Q_UNUSED(index);
47     int iconHeight = option.decorationSize.height() + (m_vPadding * 2); //icon height + padding either side
48     int textHeight = option.fontMetrics.height()*2 + (m_vPadding * 2) + 10; // text height * 2 + padding + some space between the lines
49     return QSize(-1,qMax(iconHeight, textHeight)); // any width, he view should give us the whole thing
50 }
51 
createItemWidgets(const QModelIndex & index) const52 QList< QWidget* > NodeTypesDelegate::createItemWidgets(const QModelIndex &index) const
53 {
54     // items created by this method and added to the return-list will be
55     // deleted by KWidgetItemDelegate
56 
57     KColorButton *colorButton = new KColorButton(index.data(NodeTypeModel::ColorRole).value<QColor>());
58     colorButton->setFlat(true);
59     QLineEdit *title = new QLineEdit(index.data(NodeTypeModel::TitleRole).toString());
60     title->setMinimumWidth(100);
61     QLabel *idLabel = new QLabel(index.data(NodeTypeModel::IdRole).toString());
62     idLabel->setToolTip(i18n("Unique ID of the node type."));
63     QToolButton *propertiesButton = new QToolButton();
64     propertiesButton->setIcon(QIcon::fromTheme("document-properties"));
65 
66     connect(colorButton, &KColorButton::changed,
67         this, &NodeTypesDelegate::onColorChanged);
68     connect(colorButton, &KColorButton::pressed,
69         this, &NodeTypesDelegate::onColorDialogOpened);
70     connect(title, &QLineEdit::textEdited,
71         this, &NodeTypesDelegate::onNameChanged);
72     connect(propertiesButton, &QToolButton::clicked,
73         this, &NodeTypesDelegate::showPropertiesDialog);
74 
75     return { colorButton, title, idLabel, propertiesButton };
76 }
77 
updateItemWidgets(const QList<QWidget * > widgets,const QStyleOptionViewItem & option,const QPersistentModelIndex & index) const78 void NodeTypesDelegate::updateItemWidgets(const QList< QWidget* > widgets, const QStyleOptionViewItem& option, const QPersistentModelIndex& index) const
79 {
80     // widgets:
81     // ColorButton | Title | ID
82 
83     if (!index.isValid()) {
84         return;
85     }
86 
87     Q_ASSERT(widgets.size() == 4);
88 
89     KColorButton *colorButton = qobject_cast<KColorButton*>(widgets.at(0));
90     QLineEdit *title = qobject_cast<QLineEdit*>(widgets.at(1));
91     QLabel *id = qobject_cast<QLabel*>(widgets.at(2));
92     QToolButton *propertiesButton = qobject_cast<QToolButton*>(widgets.at(3));
93 
94     Q_ASSERT(title);
95     Q_ASSERT(colorButton);
96     Q_ASSERT(id);
97     Q_ASSERT(propertiesButton);
98 
99     colorButton->setColor(index.data(NodeTypeModel::ColorRole).value<QColor>());
100     title->setText(index.data(NodeTypeModel::TitleRole).toString());
101     id->setText(index.data(NodeTypeModel::IdRole).toString());
102 
103     QRect outerRect(0, 0, option.rect.width(), option.rect.height());
104     QRect contentRect = outerRect.adjusted(m_hPadding, m_vPadding, -m_hPadding, -m_vPadding);
105 
106     int colorButtonLeftMargin = contentRect.left();
107     int colorButtonTopMargin = (outerRect.height() - colorButton->height()) / 2;
108     colorButton->move(colorButtonLeftMargin, colorButtonTopMargin);
109 
110     int titleLeftMargin = colorButtonLeftMargin + colorButton->width() + 10;
111     int titleTopMargin = (outerRect.height() - title->height()) / 2;
112     title->move(titleLeftMargin, titleTopMargin);
113 
114     // construct remaining from right to left
115     int propertiesLeftMargin = contentRect.right() - propertiesButton->width() - m_hPadding;
116     int propertiesTopMargin = (outerRect.height() - propertiesButton->height()) / 2;
117     propertiesButton->move(propertiesLeftMargin, propertiesTopMargin);
118 
119     int idLeftMargin = propertiesLeftMargin - id->width() - 10;
120     int idTopMargin = (outerRect.height() - id->height()) / 2;
121     id->move(idLeftMargin, idTopMargin);
122 
123     // title gets remaining space
124     title->setFixedWidth(qMax(0, idLeftMargin - titleLeftMargin - 10));
125 }
126 
onColorChanged(const QColor & color)127 void NodeTypesDelegate::onColorChanged(const QColor &color)
128 {
129     // use temporary stored index, since focusedIndex() does not return current index
130     // reason: the color dialog signal does not allow for correct index estimation
131     Q_EMIT colorChanged(m_workaroundColorButtonIndex, color);
132 }
133 
onColorDialogOpened()134 void NodeTypesDelegate::onColorDialogOpened()
135 {
136     m_workaroundColorButtonIndex = focusedIndex();
137 }
138 
onNameChanged(const QString & name)139 void NodeTypesDelegate::onNameChanged(const QString &name)
140 {
141     QModelIndex index = focusedIndex();
142     Q_EMIT nameChanged(index, name);
143 }
144 
showPropertiesDialog()145 void NodeTypesDelegate::showPropertiesDialog()
146 {
147     QModelIndex index = focusedIndex();
148     NodeType *type = qobject_cast<NodeType*>(index.data(NodeTypeModel::DataRole).value<QObject*>());
149     QPointer<NodeTypeProperties> dialog = new NodeTypeProperties(nullptr);
150     dialog->setType(type->self());
151     dialog->exec();
152     dialog->deleteLater();
153 }
154