File indexing completed on 2024-05-26 05:28:10

0001 /* Copyright (C) 2006 - 2015 Jan Kundrát <jkt@kde.org>
0002 
0003    This file is part of the Trojita Qt IMAP e-mail client,
0004    http://trojita.flaska.net/
0005 
0006    This program is free software; you can redistribute it and/or
0007    modify it under the terms of the GNU General Public License as
0008    published by the Free Software Foundation; either version 2 of
0009    the License or (at your option) version 3 or any later version
0010    accepted by the membership of KDE e.V. (or its successor approved
0011    by the membership of KDE e.V.), which shall act as a proxy
0012    defined in Section 14 of version 3 of the license.
0013 
0014    This program is distributed in the hope that it will be useful,
0015    but WITHOUT ANY WARRANTY; without even the implied warranty of
0016    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0017    GNU General Public License for more details.
0018 
0019    You should have received a copy of the GNU General Public License
0020    along with this program.  If not, see <http://www.gnu.org/licenses/>.
0021 */
0022 #include "Gui/AddressRowWidget.h"
0023 #include "Gui/FlowLayout.h"
0024 #include "Gui/OneEnvelopeAddress.h"
0025 
0026 #include <QLabel>
0027 #include <QMouseEvent>
0028 #include <QPainter>
0029 #include <QTextDocument>
0030 
0031 namespace Gui {
0032 
0033 static const int nonExpandingLength = 3*33;
0034 
0035 static int plainChars(const QLabel *l)
0036 {
0037     static QTextDocument converter;
0038     converter.setHtml(l->text());
0039     return converter.toPlainText().length();
0040 }
0041 
0042 AddressRowWidget::AddressRowWidget(QWidget *parent, const QString &description,
0043                                    const QList<Imap::Message::MailAddress> &addresses, MessageView *messageView):
0044     QWidget(parent), m_expander(0), m_expandedLength(0)
0045 {
0046     FlowLayout *lay = new FlowLayout(this, 0, 0, 0);
0047     setLayout(lay);
0048 
0049     setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
0050 
0051     addAddresses(description, addresses, messageView);
0052 }
0053 
0054 void AddressRowWidget::addAddresses(const QString &description, const QList<Imap::Message::MailAddress> &addresses, MessageView *messageView)
0055 {
0056     if (m_expander)
0057         layout()->removeWidget(m_expander);
0058     if (!description.isEmpty()) {
0059         QLabel *title = new QLabel(description, this);
0060         title->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
0061         title->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::LinksAccessibleByMouse);
0062         layout()->addWidget(title);
0063         if (m_expander)
0064             title->hide();
0065     }
0066     int collapse = m_expander ? m_expander->expanding() : 0;
0067     for (int i = 0; i < addresses.size(); ++i) {
0068         auto *w = new OneEnvelopeAddress(this, addresses[i], messageView,
0069                                          i == addresses.size() - 1 ?
0070                                          OneEnvelopeAddress::Position::Last :
0071                                          OneEnvelopeAddress::Position::Middle);
0072         m_expandedLength += plainChars(w);
0073         layout()->addWidget(w);
0074         if (collapse || (i > 1 && m_expandedLength > nonExpandingLength)) {
0075             w->hide();
0076             ++collapse;
0077         }
0078     }
0079     if (collapse && !m_expander) {
0080         m_expander = new Expander(this, collapse);
0081         connect(m_expander, &Expander::clicked, this, &AddressRowWidget::toggle);
0082     }
0083     if (m_expander)
0084         layout()->addWidget(m_expander);
0085 }
0086 
0087 void AddressRowWidget::toggle()
0088 {
0089     Q_ASSERT(m_expander);
0090     if (m_expander->expanding()) {
0091         m_expander->setExpanding(false);
0092         for (int i = 0; i < layout()->count(); ++i) {
0093             if (QWidget *w = layout()->itemAt(i)->widget())
0094                 w->show();
0095         }
0096     } else {
0097         int chars = 0, addresses = 0;
0098         int collapse = 0;
0099         for (int i = 0; i < layout()->count(); ++i) {
0100             QWidget *w = layout()->itemAt(i)->widget();
0101             if (collapse && w != m_expander) {
0102                 ++collapse;
0103                 w->hide();
0104                 continue;
0105             }
0106             if (OneEnvelopeAddress *oea = qobject_cast<OneEnvelopeAddress*>(w)) {
0107                 ++addresses;
0108                 chars += plainChars(oea);
0109                 if ((collapse = (addresses > 1 && chars > nonExpandingLength)))
0110                     w->hide();
0111             }
0112         }
0113         m_expander->setExpanding(collapse);
0114     }
0115 }
0116 
0117 Expander::Expander(QWidget *parent, int count) : QLabel(parent)
0118 {
0119     setCursor(Qt::PointingHandCursor);
0120     setExpanding(count);
0121 }
0122 
0123 int Expander::expanding() const {
0124     return m_expanding;
0125 }
0126 
0127 void Expander::setExpanding(const int expanding)
0128 {
0129     m_expanding = expanding;
0130     setToolTip(expanding ? tr("Click to see %1 more items").arg(expanding) : tr("Click to collapse"));
0131 }
0132 
0133 QSize Expander::sizeHint() const
0134 {
0135     QSize s = QLabel::sizeHint();
0136     s.setWidth(m_expanding ? 2*s.height() : s.height());
0137     return s;
0138 }
0139 
0140 void Expander::mouseReleaseEvent(QMouseEvent *me)
0141 {
0142     if (me->button() == Qt::LeftButton)
0143         emit clicked();
0144 }
0145 
0146 void Expander::paintEvent(QPaintEvent *pe)
0147 {
0148     QPainter p(this);
0149     p.setRenderHint(QPainter::Antialiasing);
0150     QRectF r(rect());
0151     r.setWidth(height());
0152     if (m_expanding) {
0153         // ellipsis
0154         p.setPen(palette().color(foregroundRole()));
0155         p.setBrush(Qt::NoBrush);
0156         p.drawText(r, Qt::AlignCenter, QStringLiteral("\u2026"));
0157         r.moveRight(rect().right());
0158     }
0159     p.setBrush(palette().color(foregroundRole()));
0160     p.setPen(Qt::NoPen);
0161     p.drawEllipse(r);
0162     p.setBrush(palette().color(backgroundRole()));
0163     float d = r.height()/4.0f;
0164     r.adjust(d,d,-d,-d);
0165     // the unicode triangles are not necessarily centered - looks crap
0166     if (m_expanding) {
0167         r.translate(r.width()/8.0f,0); // fix gravity
0168         const QPointF points[3] = { r.topLeft(), r.bottomLeft(), QPointF(r.right(), r.y() + r.height()/2.0) };
0169         p.drawConvexPolygon(points, 3);
0170     } else {
0171         r.translate(-r.width()/8.0f,0); // fix gravity
0172         const QPointF points[3] = { r.topRight(), r.bottomRight(), QPointF(r.left(), r.y() + r.height()/2.0) };
0173         p.drawConvexPolygon(points, 3);
0174     }
0175     p.end();
0176 }
0177 
0178 }