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 "kbicedit.h"
19 
20 #include <QApplication>
21 #include <QCompleter>
22 #include <QStyledItemDelegate>
23 #include <QPainter>
24 #include <QStyle>
25 #include <QAbstractItemView>
26 
27 #include "kmymoneyplugin.h"
28 #include "bicvalidator.h"
29 #include "kmymoneyvalidationfeedback.h"
30 #include "plugins/ibanbicdata/ibanbicdataenums.h"
31 
32 class bicItemDelegate : public QStyledItemDelegate
33 {
34 public:
bicItemDelegate(QObject * parent=0)35   explicit bicItemDelegate(QObject* parent = 0) : QStyledItemDelegate(parent) {}
36   void paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const final override;
37   QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const final override;
38 
39 private:
40   inline QFont getSmallFont(const QStyleOptionViewItem& option) const;
41 };
42 
KBicEdit(QWidget * parent)43 KBicEdit::KBicEdit(QWidget* parent)
44   : KLineEdit(parent)
45 {
46   QCompleter* completer = new QCompleter(this);
47   if (auto plugin = pPlugins.data.value(QString::fromLatin1("ibanbicdata"), nullptr))
48     if (auto model = plugin->requestData(QString(), eIBANBIC::DataType::bicModel).value<QAbstractItemModel *>())
49       completer->setModel(model);
50 
51   m_popupDelegate = new bicItemDelegate(this);
52   completer->popup()->setItemDelegate(m_popupDelegate);
53 
54   setCompleter(completer);
55 
56   bicValidator *const validator = new bicValidator(this);
57   setValidator(validator);
58 }
59 
~KBicEdit()60 KBicEdit::~KBicEdit()
61 {
62   delete m_popupDelegate;
63 }
64 
getSmallFont(const QStyleOptionViewItem & option) const65 QFont bicItemDelegate::getSmallFont(const QStyleOptionViewItem& option) const
66 {
67   QFont smallFont = option.font;
68   smallFont.setPointSize(0.9*smallFont.pointSize());
69   return smallFont;
70 }
71 
sizeHint(const QStyleOptionViewItem & option,const QModelIndex & index) const72 QSize bicItemDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const
73 {
74   QStyleOptionViewItem opt = option;
75   initStyleOption(&opt, index);
76 
77   QFontMetrics metrics(option.font);
78   QFontMetrics smallMetrics(getSmallFont(option));
79   const QStyle *style = opt.widget ? opt.widget->style() : QApplication::style();
80   const int margin = style->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1;
81 
82   // A bic has maximal 11 characters. So we guess, we want to display 11 characters. The name of the institution has to adapt to what is given
83   return QSize(metrics.width(QLatin1Char('X')) + 2*margin, metrics.lineSpacing() + smallMetrics.lineSpacing() + smallMetrics.leading() + 2*margin);
84 }
85 
86 /**
87  * @todo enable eliding (use QFontMetrics::elidedText() )
88  */
paint(QPainter * painter,const QStyleOptionViewItem & option,const QModelIndex & index) const89 void bicItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
90 {
91   QStyleOptionViewItem opt = option;
92   initStyleOption(&opt, index);
93 
94   // Background
95   QStyle *style = opt.widget ? opt.widget->style() : QApplication::style();
96   style->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, painter, opt.widget);
97 
98   const int margin = style->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1;
99   const QRect textArea = QRect(opt.rect.x() + margin, opt.rect.y() + margin, opt.rect.width() - 2 * margin, opt.rect.height() - 2 * margin);
100 
101   // Paint name
102   painter->save();
103   QFont smallFont = getSmallFont(opt);
104   QFontMetrics metrics(opt.font);
105   QFontMetrics smallMetrics(smallFont);
106   QRect nameRect = style->alignedRect(opt.direction, Qt::AlignBottom, QSize(textArea.width(), smallMetrics.lineSpacing()), textArea);
107   painter->setFont(smallFont);
108   style->drawItemText(painter, nameRect, Qt::AlignBottom, QApplication::palette(), true, index.model()->data(index, eIBANBIC::DisplayRole::InstitutionNameRole).toString(), option.state & QStyle::State_Selected ? QPalette::HighlightedText : QPalette::Mid);
109   painter->restore();
110 
111   // Paint BIC
112   painter->save();
113   QFont normal = painter->font();
114   normal.setBold(true);
115   painter->setFont(normal);
116   QRect bicRect = style->alignedRect(opt.direction, Qt::AlignTop, QSize(textArea.width(), metrics.lineSpacing()), textArea);
117   const QString bic = index.model()->data(index, Qt::DisplayRole).toString();
118   style->drawItemText(painter, bicRect, Qt::AlignTop, QApplication::palette(), true, bic, option.state & QStyle::State_Selected ? QPalette::HighlightedText : QPalette::Text);
119 
120   painter->restore();
121 }
122