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 }