Merge branch 'review/roland_pallai/favtags'
[trojita.git] / src / Gui / AddressRowWidget.cpp
blob2dad7c3267b8878ff2dba4141b8c5d5067e321f9
1 /* Copyright (C) 2006 - 2015 Jan Kundrát <jkt@kde.org>
3 This file is part of the Trojita Qt IMAP e-mail client,
4 http://trojita.flaska.net/
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License as
8 published by the Free Software Foundation; either version 2 of
9 the License or (at your option) version 3 or any later version
10 accepted by the membership of KDE e.V. (or its successor approved
11 by the membership of KDE e.V.), which shall act as a proxy
12 defined in Section 14 of version 3 of the license.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "Gui/AddressRowWidget.h"
23 #include "Gui/FlowLayout.h"
24 #include "Gui/OneEnvelopeAddress.h"
26 #include <QLabel>
27 #include <QMouseEvent>
28 #include <QPainter>
29 #include <QTextDocument>
31 namespace Gui {
33 static const int nonExpandingLength = 3*33;
35 static int plainChars(const QLabel *l)
37 static QTextDocument converter;
38 converter.setHtml(l->text());
39 return converter.toPlainText().length();
42 AddressRowWidget::AddressRowWidget(QWidget *parent, const QString &description,
43 const QList<Imap::Message::MailAddress> &addresses, MessageView *messageView):
44 QWidget(parent), m_expander(0), m_expandedLength(0)
46 FlowLayout *lay = new FlowLayout(this, 0, 0, 0);
47 setLayout(lay);
49 setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
51 addAddresses(description, addresses, messageView);
54 void AddressRowWidget::addAddresses(const QString &description, const QList<Imap::Message::MailAddress> &addresses, MessageView *messageView)
56 if (m_expander)
57 layout()->removeWidget(m_expander);
58 if (!description.isEmpty()) {
59 QLabel *title = new QLabel(description, this);
60 title->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
61 title->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::LinksAccessibleByMouse);
62 layout()->addWidget(title);
63 if (m_expander)
64 title->hide();
66 int collapse = m_expander ? m_expander->expanding() : 0;
67 for (int i = 0; i < addresses.size(); ++i) {
68 auto *w = new OneEnvelopeAddress(this, addresses[i], messageView,
69 i == addresses.size() - 1 ?
70 OneEnvelopeAddress::Position::Last :
71 OneEnvelopeAddress::Position::Middle);
72 m_expandedLength += plainChars(w);
73 layout()->addWidget(w);
74 if (collapse || (i > 1 && m_expandedLength > nonExpandingLength)) {
75 w->hide();
76 ++collapse;
79 if (collapse && !m_expander) {
80 m_expander = new Expander(this, collapse);
81 connect(m_expander, &Expander::clicked, this, &AddressRowWidget::toggle);
83 if (m_expander)
84 layout()->addWidget(m_expander);
87 void AddressRowWidget::toggle()
89 Q_ASSERT(m_expander);
90 if (m_expander->expanding()) {
91 m_expander->setExpanding(false);
92 for (int i = 0; i < layout()->count(); ++i) {
93 if (QWidget *w = layout()->itemAt(i)->widget())
94 w->show();
96 } else {
97 int chars = 0, addresses = 0;
98 int collapse = 0;
99 for (int i = 0; i < layout()->count(); ++i) {
100 QWidget *w = layout()->itemAt(i)->widget();
101 if (collapse && w != m_expander) {
102 ++collapse;
103 w->hide();
104 continue;
106 if (OneEnvelopeAddress *oea = qobject_cast<OneEnvelopeAddress*>(w)) {
107 ++addresses;
108 chars += plainChars(oea);
109 if ((collapse = (addresses > 1 && chars > nonExpandingLength)))
110 w->hide();
113 m_expander->setExpanding(collapse);
117 Expander::Expander(QWidget *parent, int count) : QLabel(parent)
119 setCursor(Qt::PointingHandCursor);
120 setExpanding(count);
123 int Expander::expanding() const {
124 return m_expanding;
127 void Expander::setExpanding(const int expanding)
129 m_expanding = expanding;
130 setToolTip(expanding ? tr("Click to see %1 more items").arg(expanding) : tr("Click to collapse"));
133 QSize Expander::sizeHint() const
135 QSize s = QLabel::sizeHint();
136 s.setWidth(m_expanding ? 2*s.height() : s.height());
137 return s;
140 void Expander::mouseReleaseEvent(QMouseEvent *me)
142 if (me->button() == Qt::LeftButton)
143 emit clicked();
146 void Expander::paintEvent(QPaintEvent *pe)
148 QPainter p(this);
149 p.setRenderHint(QPainter::Antialiasing);
150 QRectF r(rect());
151 r.setWidth(height());
152 if (m_expanding) {
153 // ellipsis
154 p.setPen(palette().color(foregroundRole()));
155 p.setBrush(Qt::NoBrush);
156 p.drawText(r, Qt::AlignCenter, QStringLiteral("\u2026"));
157 r.moveRight(rect().right());
159 p.setBrush(palette().color(foregroundRole()));
160 p.setPen(Qt::NoPen);
161 p.drawEllipse(r);
162 p.setBrush(palette().color(backgroundRole()));
163 float d = r.height()/4.0f;
164 r.adjust(d,d,-d,-d);
165 // the unicode triangles are not necessarily centered - looks crap
166 if (m_expanding) {
167 r.translate(r.width()/8.0f,0); // fix gravity
168 const QPointF points[3] = { r.topLeft(), r.bottomLeft(), QPointF(r.right(), r.y() + r.height()/2.0) };
169 p.drawConvexPolygon(points, 3);
170 } else {
171 r.translate(-r.width()/8.0f,0); // fix gravity
172 const QPointF points[3] = { r.topRight(), r.bottomRight(), QPointF(r.left(), r.y() + r.height()/2.0) };
173 p.drawConvexPolygon(points, 3);
175 p.end();