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 "edgetypesdelegate.h"
8 #include "libgraphtheory/dialogs/edgetypeproperties.h"
9 #include "libgraphtheory/models/edgetypemodel.h"
10 #include <KColorButton>
11 #include <KLocalizedString>
12 #include <QAbstractItemView>
13 #include <QToolButton>
14 #include <QLabel>
15 #include <QLineEdit>
16 #include <QPainter>
17 #include <QPointer>
18 #include <QApplication>
19 #include <QDebug>
20
21 using namespace GraphTheory;
22
EdgeTypesDelegate(QAbstractItemView * parent)23 EdgeTypesDelegate::EdgeTypesDelegate(QAbstractItemView* parent)
24 : KWidgetItemDelegate(parent, parent->viewport())
25 {
26
27 }
28
~EdgeTypesDelegate()29 EdgeTypesDelegate::~EdgeTypesDelegate()
30 {
31
32 }
33
paint(QPainter * painter,const QStyleOptionViewItem & option,const QModelIndex & index) const34 void EdgeTypesDelegate::paint(QPainter* painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
35 {
36 if (!index.isValid()) {
37 return;
38 }
39 QApplication::style()->drawPrimitive(QStyle::PE_PanelItemViewItem, &option, painter, nullptr);
40 }
41
sizeHint(const QStyleOptionViewItem & option,const QModelIndex & index) const42 QSize EdgeTypesDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const
43 {
44 Q_UNUSED(index);
45 int iconHeight = option.decorationSize.height() + (m_vPadding * 2); //icon height + padding either side
46 int textHeight = option.fontMetrics.height()*2 + (m_vPadding * 2) + 10; // text height * 2 + padding + some space between the lines
47 return QSize(-1,qMax(iconHeight, textHeight)); // any width, he view should give us the whole thing
48 }
49
createItemWidgets(const QModelIndex & index) const50 QList< QWidget* > EdgeTypesDelegate::createItemWidgets(const QModelIndex &index) const
51 {
52 // items created by this method and added to the return-list will be
53 // deleted by KWidgetItemDelegate
54
55 KColorButton *colorButton = new KColorButton(index.data(EdgeTypeModel::ColorRole).value<QColor>());
56 colorButton->setFlat(true);
57 QToolButton *direction = new QToolButton();
58 direction->setCheckable(true);
59 direction->setToolTip(i18n("Direction of edges of edge type."));
60 QLineEdit *title = new QLineEdit(index.data(EdgeTypeModel::TitleRole).toString());
61 title->setMinimumWidth(100);
62 QLabel *idLabel = new QLabel(index.data(EdgeTypeModel::IdRole).toString());
63 idLabel->setToolTip(i18n("Unique ID of edge type."));
64 QToolButton *propertiesButton = new QToolButton();
65 propertiesButton->setIcon(QIcon::fromTheme("document-properties"));
66
67 connect(colorButton, &KColorButton::changed, this, &EdgeTypesDelegate::onColorChanged);
68 connect(colorButton, &KColorButton::pressed, this, &EdgeTypesDelegate::onColorDialogOpened);
69 connect(direction, &QToolButton::toggled, this, &EdgeTypesDelegate::onDirectionSwitched);
70 connect(title, &QLineEdit::textEdited, this, &EdgeTypesDelegate::onNameChanged);
71 connect(propertiesButton, &QToolButton::clicked, this, &EdgeTypesDelegate::showPropertiesDialog);
72
73 return { colorButton, direction, title, idLabel, propertiesButton };
74 }
75
updateItemWidgets(const QList<QWidget * > widgets,const QStyleOptionViewItem & option,const QPersistentModelIndex & index) const76 void EdgeTypesDelegate::updateItemWidgets(const QList< QWidget* > widgets, const QStyleOptionViewItem& option, const QPersistentModelIndex& index) const
77 {
78 // widgets:
79 // Color | Direction | Title | ID
80
81 if (!index.isValid()) {
82 return;
83 }
84
85 Q_ASSERT(widgets.size() == 5);
86
87 KColorButton *colorButton = qobject_cast<KColorButton*>(widgets.at(0));
88 QToolButton *directionSwitch = qobject_cast<QToolButton*>(widgets.at(1));
89 QLineEdit *title = qobject_cast<QLineEdit*>(widgets.at(2));
90 QLabel *id = qobject_cast<QLabel*>(widgets.at(3));
91 QToolButton *propertiesButton = qobject_cast<QToolButton*>(widgets.at(4));
92
93 Q_ASSERT(colorButton);
94 Q_ASSERT(directionSwitch);
95 Q_ASSERT(title);
96 Q_ASSERT(id);
97 Q_ASSERT(propertiesButton);
98
99 colorButton->setColor(index.data(EdgeTypeModel::ColorRole).value<QColor>());
100 if (index.data(EdgeTypeModel::DirectionRole).toInt() == EdgeType::Unidirectional) {
101 directionSwitch->setIcon(QIcon::fromTheme("rocsunidirectional"));
102 } else {
103 directionSwitch->setIcon(QIcon::fromTheme("rocsbidirectional"));
104 }
105 title->setText(index.data(EdgeTypeModel::TitleRole).toString());
106 id->setText(index.data(EdgeTypeModel::IdRole).toString());
107
108 QRect outerRect(0, 0, option.rect.width(), option.rect.height());
109 QRect contentRect = outerRect.adjusted(m_hPadding, m_vPadding, -m_hPadding, -m_vPadding);
110
111 int colorButtonLeftMargin = contentRect.left();
112 int colorButtonTopMargin = (outerRect.height() - colorButton->height()) / 2;
113 colorButton->move(colorButtonLeftMargin, colorButtonTopMargin);
114
115 int directionSwitchLeftMargin = colorButtonLeftMargin + + colorButton->width() + 10;
116 int directionSwitchTopMargin = (outerRect.height() - directionSwitch->height()) / 2;
117 directionSwitch->move(directionSwitchLeftMargin, directionSwitchTopMargin);
118
119 int titleLeftMargin = directionSwitchLeftMargin + directionSwitch->width() + 10;
120 int titleTopMargin = (outerRect.height() - title->height()) / 2;
121 title->move(titleLeftMargin, titleTopMargin);
122
123 // construct remaining from right to left
124 int propertiesLeftMargin = contentRect.right() - propertiesButton->width() - m_hPadding;
125 int propertiesTopMargin = (outerRect.height() - propertiesButton->height()) / 2;
126 propertiesButton->move(propertiesLeftMargin, propertiesTopMargin);
127
128 int idLeftMargin = propertiesLeftMargin - id->width() - 10;
129 int idTopMargin = (outerRect.height() - id->height()) / 2;
130 id->move(idLeftMargin, idTopMargin);
131
132
133 // title gets remaining space
134 title->setFixedWidth(qMax(0, idLeftMargin - titleLeftMargin - 10));
135 }
136
onColorChanged(const QColor & color)137 void EdgeTypesDelegate::onColorChanged(const QColor &color)
138 {
139 // use temporary stored index, since focusedIndex() does not return current index
140 // reason: the color dialog signal does not allow for correct index estimation
141 Q_EMIT colorChanged(m_workaroundColorButtonIndex, color);
142 }
143
onColorDialogOpened()144 void EdgeTypesDelegate::onColorDialogOpened()
145 {
146 m_workaroundColorButtonIndex = focusedIndex();
147 }
148
onNameChanged(const QString & name)149 void EdgeTypesDelegate::onNameChanged(const QString &name)
150 {
151 QModelIndex index = focusedIndex();
152 Q_EMIT nameChanged(index, name);
153 }
154
onDirectionSwitched()155 void EdgeTypesDelegate::onDirectionSwitched()
156 {
157 QModelIndex index = focusedIndex();
158 EdgeType::Direction direction = static_cast<EdgeType::Direction>(
159 index.data(EdgeTypeModel::DirectionRole).toInt());
160
161 const EdgeType::Direction newDirection = direction == EdgeType::Bidirectional
162 ? EdgeType::Unidirectional
163 : EdgeType::Bidirectional;
164
165 Q_EMIT directionChanged(index, newDirection);
166 }
167
showPropertiesDialog()168 void EdgeTypesDelegate::showPropertiesDialog()
169 {
170 QModelIndex index = focusedIndex();
171 EdgeType *type = qobject_cast<EdgeType*>(index.data(EdgeTypeModel::DataRole).value<QObject*>());
172 QPointer<EdgeTypeProperties> dialog = new EdgeTypeProperties(nullptr);
173 dialog->setType(type->self());
174 dialog->exec();
175 delete dialog;
176 }
177