1 /*
2  * Copyright 2014-2015  Christian Dávid <christian-david@web.de>
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of
7  * the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include "nationalaccountdelegate.h"
19 
20 #include <QApplication>
21 #include <QPainter>
22 #include <QAbstractItemView>
23 
24 #include <KLocalizedString>
25 
26 #include "models/payeeidentifiercontainermodel.h"
27 #include "nationalaccountedit.h"
28 
nationalAccountDelegate(QObject * parent,const QVariantList &)29 nationalAccountDelegate::nationalAccountDelegate(QObject* parent, const QVariantList&)
30     : QStyledItemDelegate(parent)
31 {
32 
33 }
34 
35 /** @todo elide texts */
paint(QPainter * painter,const QStyleOptionViewItem & option,const QModelIndex & index) const36 void nationalAccountDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
37 {
38   QStyleOptionViewItem opt = option;
39   initStyleOption(&opt, index);
40 
41   // Background
42   QStyle *style = opt.widget ? opt.widget->style() : QApplication::style();
43   style->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, painter, opt.widget);
44 
45   const int margin = style->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1;
46   const QRect textArea = QRect(opt.rect.x() + margin, opt.rect.y() + margin, opt.rect.width() - 2 * margin, opt.rect.height() - 2 * margin);
47 
48   // Do not paint text if the edit widget is shown
49   const QAbstractItemView *view = qobject_cast<const QAbstractItemView *>(opt.widget);
50   if (view && view->indexWidget(index))
51     return;
52 
53   // Get data
54   payeeIdentifierTyped<payeeIdentifiers::nationalAccount> ident = identByIndex(index);
55 
56   // Paint bank code
57   painter->save();
58   const QFont smallFont = painter->font();
59   const QFontMetrics metrics(opt.font);
60   const QFontMetrics smallMetrics(smallFont);
61   const QRect bicRect = style->alignedRect(opt.direction, Qt::AlignTop, QSize(textArea.width(), smallMetrics.lineSpacing()),
62                         QRect(textArea.left(), metrics.lineSpacing() + textArea.top(), textArea.width(), smallMetrics.lineSpacing())
63                                           );
64   painter->setFont(smallFont);
65   style->drawItemText(painter, bicRect, Qt::AlignBottom, QApplication::palette(), true, ident->bankCode(), opt.state & QStyle::State_Selected ? QPalette::HighlightedText : QPalette::Text);
66   painter->restore();
67 
68   // Paint bank name
69   painter->save();
70   const QRect nameRect = style->alignedRect(opt.direction, Qt::AlignTop, QSize(textArea.width(), smallMetrics.lineSpacing()),
71                          QRect(textArea.left(), metrics.lineSpacing() + smallMetrics.lineSpacing() + textArea.top(), textArea.width(), smallMetrics.lineSpacing())
72                                            );
73   style->drawItemText(painter, nameRect, Qt::AlignBottom, QApplication::palette(), true, ident->bankName(), opt.state & QStyle::State_Selected ? QPalette::HighlightedText : QPalette::Text);
74   painter->restore();
75 
76   // Paint account number
77   painter->save();
78   QFont normal = painter->font();
79   normal.setBold(true);
80   painter->setFont(normal);
81   const QRect ibanRect = style->alignedRect(opt.direction, Qt::AlignTop, QSize(textArea.width(), metrics.lineSpacing()), textArea);
82   style->drawItemText(painter, ibanRect, Qt::AlignTop, QApplication::palette(), true, ident->accountNumber(), opt.state & QStyle::State_Selected ? QPalette::HighlightedText : QPalette::Text);
83   painter->restore();
84 
85   // Paint type
86   painter->save();
87   QRect typeRect = style->alignedRect(opt.direction, Qt::AlignTop | Qt::AlignRight, QSize(textArea.width() / 5, metrics.lineSpacing()), textArea);
88   style->drawItemText(painter, typeRect, Qt::AlignTop | Qt::AlignRight, QApplication::palette(), true, i18n("National Account"), opt.state & QStyle::State_Selected ? QPalette::HighlightedText : QPalette::Text);
89   painter->restore();
90 }
91 
sizeHint(const QStyleOptionViewItem & option,const QModelIndex & index) const92 QSize nationalAccountDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const
93 {
94   QStyleOptionViewItem opt = option;
95   initStyleOption(&opt, index);
96 
97   // QStyle::State_Editing is never set (seems to be a bug in Qt)! This code is here only because it was written already
98   const QAbstractItemView *view = qobject_cast<const QAbstractItemView *>(opt.widget);
99   if (view && view->indexWidget(index))
100     return view->indexWidget(index)->sizeHint();
101 
102   QFontMetrics metrics(option.font);
103   const QStyle *style = opt.widget ? opt.widget->style() : QApplication::style();
104   const int margin = style->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1;
105 
106   // An iban has maximal 32 characters, so national accounts should be shorter than 28
107   return QSize((28)*metrics.width(QLatin1Char('X')) + 2*margin, 3*metrics.lineSpacing() + metrics.leading() + 2*margin);
108 }
109 
createEditor(QWidget * parent,const QStyleOptionViewItem & option,const QModelIndex & index) const110 QWidget* nationalAccountDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const
111 {
112   Q_UNUSED(option);
113   nationalAccountEdit* edit = new nationalAccountEdit(parent);
114   connect(edit, SIGNAL(commitData(QWidget*)), this, SIGNAL(commitData(QWidget*)));
115   connect(edit, SIGNAL(closeEditor(QWidget*)), this, SIGNAL(closeEditor(QWidget*)));
116   emit sizeHintChanged(index);
117   return edit;
118 }
119 
setEditorData(QWidget * editor,const QModelIndex & index) const120 void nationalAccountDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const
121 {
122   nationalAccountEdit* nationalEditor = qobject_cast< nationalAccountEdit* >(editor);
123   Q_CHECK_PTR(nationalEditor);
124 
125   nationalEditor->setIdentifier(identByIndex(index));
126 }
127 
setModelData(QWidget * editor,QAbstractItemModel * model,const QModelIndex & index) const128 void nationalAccountDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const
129 {
130   Q_CHECK_PTR(editor);
131   Q_CHECK_PTR(model);
132   Q_ASSERT(index.isValid());
133 
134   nationalAccountEdit* nationalEditor = qobject_cast< nationalAccountEdit* >(editor);
135   Q_CHECK_PTR(nationalEditor);
136 
137   payeeIdentifierTyped<payeeIdentifiers::nationalAccount> ident = identByIndex(index);
138   ident->setAccountNumber(nationalEditor->accountNumber());
139   ident->setBankCode(nationalEditor->institutionCode());
140   model->setData(index, QVariant::fromValue<payeeIdentifier>(ident), payeeIdentifierContainerModel::payeeIdentifier);
141 }
142 
updateEditorGeometry(QWidget * editor,const QStyleOptionViewItem & option,const QModelIndex & index) const143 void nationalAccountDelegate::updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const
144 {
145   Q_UNUSED(index);
146   editor->setGeometry(option.rect);
147 }
148 
149 /**
150  * Internal helper to directly convert the QVariant into the correct pointer type.
151  */
identByIndex(const QModelIndex & index) const152 payeeIdentifierTyped<payeeIdentifiers::nationalAccount> nationalAccountDelegate::identByIndex(const QModelIndex& index) const
153 {
154   payeeIdentifierTyped<payeeIdentifiers::nationalAccount> ident = payeeIdentifierTyped<payeeIdentifiers::nationalAccount>(
155         index.model()->data(index, payeeIdentifierContainerModel::payeeIdentifier).value<payeeIdentifier>()
156       );
157 
158   Q_ASSERT(!ident.isNull());
159   return ident;
160 }
161