diff --git a/shared/enums.h b/shared/enums.h index 7273b2e..9fb4aad 100644 --- a/shared/enums.h +++ b/shared/enums.h @@ -144,6 +144,8 @@ enum class TrustLevel { authenticated }; Q_ENUM_NS(TrustLevel) +static const TrustLevel TrustLevelHighest = TrustLevel::undecided; +static const TrustLevel TrustLevelLowest = TrustLevel::authenticated; enum class EncryptionProtocol { omemo diff --git a/shared/global.cpp b/shared/global.cpp index dc1cb80..7a1b494 100644 --- a/shared/global.cpp +++ b/shared/global.cpp @@ -113,6 +113,14 @@ Shared::Global::Global(): tr("Always Ask", "AccountPassword"), tr("KWallet", "AccountPassword") }), + trustLevel({ + tr("Undecided", "TrustLevel"), + tr("Automatically distrusted", "TrustLevel"), + tr("Manually distrusted", "TrustLevel"), + tr("Automatically trusted", "TrustLevel"), + tr("Manually trusted", "TrustLevel"), + tr("Authenticated", "TrustLevel") + }), accountPasswordDescription({ tr("Your password is going to be stored in config file in plain text", "AccountPasswordDescription"), tr("Your password is going to be stored in config file but jammed with constant encryption key you can find in program source code. It might look like encryption but it's not", "AccountPasswordDescription"), @@ -123,10 +131,12 @@ Shared::Global::Global(): defaultSystemPalette(QApplication::palette()), omemoSupport(OMEMO_SUPPORT), defaultFont(QFontDatabase::systemFont(QFontDatabase::GeneralFont)), + monospaceFont(QFontDatabase::systemFont(QFontDatabase::FixedFont)), smallFont(getFont(QFontDatabase::SmallestReadableFont, false, true)), headerFont(getFont(QFontDatabase::TitleFont, true, false, 1.1)), titleFont(getFont(QFontDatabase::TitleFont, true, false, 1.3)), defaultFontMetrics(defaultFont), + monospaceMetrics(monospaceFont), smallFontMetrics(smallFont), headerFontMetrics(headerFont), titleFontMetrics(titleFont), @@ -256,6 +266,11 @@ QString Shared::Global::getName(Shared::AccountPassword ap) return instance->accountPassword[static_cast(ap)]; } +QString Shared::Global::getName(Shared::TrustLevel tl) +{ + return instance->trustLevel[static_cast(tl)]; +} + void Shared::Global::setSupported(const QString& pluginName, bool support) { std::map::iterator itr = instance->pluginSupport.find(pluginName); @@ -405,3 +420,4 @@ FROM_INT_INPL(Shared::SubscriptionState) FROM_INT_INPL(Shared::AccountPassword) FROM_INT_INPL(Shared::Avatar) FROM_INT_INPL(Shared::Availability) +FROM_INT_INPL(Shared::TrustLevel) diff --git a/shared/global.h b/shared/global.h index 1fc4aca..b311f9f 100644 --- a/shared/global.h +++ b/shared/global.h @@ -74,6 +74,7 @@ namespace Shared { static QString getName(Role rl); static QString getName(Message::State rl); static QString getName(AccountPassword ap); + static QString getName(TrustLevel tl); static QString getDescription(AccountPassword ap); @@ -84,6 +85,7 @@ namespace Shared { const std::deque role; const std::deque messageState; const std::deque accountPassword; + const std::deque trustLevel; const std::deque accountPasswordDescription; @@ -103,10 +105,12 @@ namespace Shared { static void setStyle(const QString& style); const bool omemoSupport; QFont defaultFont; + QFont monospaceFont; QFont smallFont; QFont headerFont; QFont titleFont; QFontMetrics defaultFontMetrics; + QFontMetrics monospaceMetrics; QFontMetrics smallFontMetrics; QFontMetrics headerFontMetrics; QFontMetrics titleFontMetrics; diff --git a/ui/utils/CMakeLists.txt b/ui/utils/CMakeLists.txt index b46d30d..7e68f25 100644 --- a/ui/utils/CMakeLists.txt +++ b/ui/utils/CMakeLists.txt @@ -15,4 +15,6 @@ target_sources(squawk PRIVATE resizer.h shadowoverlay.cpp shadowoverlay.h + expandinglist.cpp + expandinglist.h ) diff --git a/ui/utils/expandinglist.cpp b/ui/utils/expandinglist.cpp new file mode 100644 index 0000000..6d1546d --- /dev/null +++ b/ui/utils/expandinglist.cpp @@ -0,0 +1,43 @@ +// Squawk messenger. +// Copyright (C) 2019 Yury Gubich +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#include "expandinglist.h" + +QSize ExpandingList::viewportSizeHint() const { + if (QAbstractItemView::sizeAdjustPolicy() != QAbstractScrollArea::AdjustToContents) + return QListView::viewportSizeHint(); + + if (model() == nullptr) + return QSize(0, 0); + if (model()->rowCount() == 0) + return QSize(0, 0); + +#if (QT_VERSION < QT_VERSION_CHECK(6, 2, 0)) + const int rowCount = model()->rowCount(); + int height = 0; + for (int i = 0; i < rowCount; i++) { + height += QListView::sizeHintForRow(i); + } + return QSize(QListView::viewportSizeHint().width(), height); +#else + return QListView::viewportSizeHint(); +#endif +} + +QSize ExpandingList::minimumSizeHint() const { + return viewportSizeHint(); +} + diff --git a/ui/utils/expandinglist.h b/ui/utils/expandinglist.h new file mode 100644 index 0000000..0b29e89 --- /dev/null +++ b/ui/utils/expandinglist.h @@ -0,0 +1,31 @@ +// Squawk messenger. +// Copyright (C) 2019 Yury Gubich +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#ifndef EXPANDINGLIST_H +#define EXPANDINGLIST_H + +#include + +class ExpandingList : public QListView { + Q_OBJECT +public: + using QListView::QListView; //explicit constructor inheriatnce + + QSize viewportSizeHint() const override; + QSize minimumSizeHint() const override; +}; + +#endif // EXPANDINGLIST_H diff --git a/ui/widgets/vcard/omemo/keydelegate.cpp b/ui/widgets/vcard/omemo/keydelegate.cpp index e64cb19..189d8df 100644 --- a/ui/widgets/vcard/omemo/keydelegate.cpp +++ b/ui/widgets/vcard/omemo/keydelegate.cpp @@ -16,6 +16,7 @@ #include "keydelegate.h" #include +#include #include "keysmodel.h" #include @@ -26,10 +27,12 @@ constexpr uint8_t maxSingleLineParts = 3; UI::KeyDelegate::KeyDelegate(QObject* parent): QStyledItemDelegate(parent), - fingerPrintFont(Shared::Global::getInstance()->defaultFont), + defaultFont(Shared::Global::getInstance()->defaultFont), + fingerPrintFont(Shared::Global::getInstance()->monospaceFont), labelFont(Shared::Global::getInstance()->smallFont), - fingerPrintMetrics(Shared::Global::getInstance()->defaultFontMetrics), - labelFontMetrics(Shared::Global::getInstance()->smallFontMetrics), + defaultMetrics(Shared::Global::getInstance()->defaultFontMetrics), + fingerPrintMetrics(Shared::Global::getInstance()->monospaceMetrics), + labelMetrics(Shared::Global::getInstance()->smallFontMetrics), spaceWidth(fingerPrintMetrics.horizontalAdvance(" ")) {} @@ -47,11 +50,14 @@ void UI::KeyDelegate::paint(QPainter* painter, const QStyleOptionViewItem& optio painter->restore(); } + QRect r; + int maxRight = 0; + int leftOrigin = option.rect.left() + margin; QColor q = painter->pen().color(); q.setAlpha(180); QRect rect = option.rect; - rect.adjust(margin, margin, 0, 0); + rect.adjust(margin, margin, -margin, -margin); QVariant labelV = index.data(UI::KeysModel::Label); if (labelV.isValid()) { QString label = labelV.toString(); @@ -59,8 +65,9 @@ void UI::KeyDelegate::paint(QPainter* painter, const QStyleOptionViewItem& optio painter->save(); painter->setFont(labelFont); painter->setPen(q); - painter->drawText(rect, Qt::AlignLeft | Qt::AlignTop, label); - rect.adjust(0, labelFontMetrics.lineSpacing(), 0, 0); + painter->drawText(rect, Qt::AlignLeft | Qt::AlignTop, label, &r); + rect.adjust(0, labelMetrics.lineSpacing(), 0, 0); + maxRight = std::max(r.width(), maxRight); painter->restore(); } } @@ -72,7 +79,6 @@ void UI::KeyDelegate::paint(QPainter* painter, const QStyleOptionViewItem& optio QByteArray fingerPrint = fingerPrintV.toByteArray(); std::vector parts = getParts(fingerPrint); uint8_t partsLength = parts.size(); - QRect r; uint8_t firstLine; if (partsLength > maxSingleLineParts) firstLine = partsLength / 2 + partsLength % 2; @@ -81,15 +87,17 @@ void UI::KeyDelegate::paint(QPainter* painter, const QStyleOptionViewItem& optio for (uint8_t i = 0; i < partsLength; ++i) { if (i == firstLine) { - rect.setLeft(option.rect.left() + margin); + maxRight = std::max(rect.left() - leftOrigin - margin, maxRight); + rect.setLeft(leftOrigin); rect.adjust(0, r.height() + fingerPrintMetrics.leading(), 0, 0); } painter->drawText(rect, Qt::AlignLeft | Qt::AlignTop, parts[i], &r); rect.adjust(r.width() + spaceWidth ,0, 0, 0); } + maxRight = std::max(rect.left() - leftOrigin - margin, maxRight); rect.adjust(0, r.height() + fingerPrintMetrics.leading(), 0, 0); - rect.setLeft(option.rect.left() + margin); + rect.setLeft(leftOrigin); painter->restore(); } @@ -102,12 +110,27 @@ void UI::KeyDelegate::paint(QPainter* painter, const QStyleOptionViewItem& optio painter->save(); painter->setFont(labelFont); painter->setPen(q); - painter->drawText(rect, Qt::AlignLeft | Qt::AlignTop, last.toString()); - rect.adjust(0, labelFontMetrics.lineSpacing(), 0, 0); + painter->drawText(rect, Qt::AlignLeft | Qt::AlignTop, last.toString(), &r); + rect.adjust(0, labelMetrics.lineSpacing(), 0, 0); + maxRight = std::max(r.width(), maxRight); painter->restore(); } } - //painter->drawText(option.rect, option.displayAlignment, index.data().toString()); + + QVariant levelV = index.data(UI::KeysModel::TrustLevel); + if (levelV.isValid()) { + Shared::TrustLevel level = static_cast(levelV.toUInt()); + QString levelName = Shared::Global::getName(level); + + if (maxRight > 0) + maxRight += margin; + rect.setLeft(leftOrigin + maxRight); + rect.setTop(option.rect.top() + maxRight); + rect.setBottom(option.rect.bottom() - maxRight); + painter->setFont(defaultFont); + painter->drawText(rect, Qt::AlignLeft | Qt::AlignVCenter, levelName, &r); + } + painter->restore(); } @@ -117,10 +140,15 @@ QSize UI::KeyDelegate::sizeHint(const QStyleOptionViewItem& option, const QModel int mh = margin * 2; int mw = margin * 2; + int width = 0; QVariant labelV = index.data(UI::KeysModel::Label); - if (labelV.isValid() && labelV.toString().size() > 0) { - mh += labelFontMetrics.lineSpacing(); + if (labelV.isValid()) { + QString label = labelV.toString(); + if (label.size() > 0) { + mh += labelMetrics.lineSpacing(); + width = labelMetrics.horizontalAdvance(label); + } } QVariant fingerPrintV = index.data(UI::KeysModel::FingerPrint); @@ -129,9 +157,8 @@ QSize UI::KeyDelegate::sizeHint(const QStyleOptionViewItem& option, const QModel uint8_t parts = hex.size() / partSize; mh += fingerPrintMetrics.height(); - if (parts > maxSingleLineParts) { + if (parts > maxSingleLineParts) mh += fingerPrintMetrics.height() + fingerPrintMetrics.leading(); - } uint8_t firstLine; if (parts > maxSingleLineParts) @@ -139,13 +166,29 @@ QSize UI::KeyDelegate::sizeHint(const QStyleOptionViewItem& option, const QModel else firstLine = parts; - mw += firstLine * partSize * spaceWidth + (firstLine - 1) * spaceWidth; + width = std::max(width, firstLine * fingerPrintMetrics.horizontalAdvance(hex, partSize) + (firstLine - 1) * spaceWidth); } QVariant lastV = index.data(UI::KeysModel::LastInteraction); - if (lastV.isValid() && lastV.toDateTime().isValid()) { - mh += labelFontMetrics.lineSpacing(); + if (lastV.isValid()) { + QDateTime last = lastV.toDateTime(); + if (last.isValid()) { + mh += labelMetrics.lineSpacing(); + QString dt = last.toString(); + width = std::max(labelMetrics.horizontalAdvance(dt), width); + } } + QVariant levelV = index.data(UI::KeysModel::TrustLevel); + if (levelV.isValid()) { + Shared::TrustLevel level = static_cast(levelV.toUInt()); + QString levelName = Shared::Global::getName(level); + if (width > 0) + width += margin; + + width += defaultMetrics.horizontalAdvance(levelName); + } + + mw += width; if (size.width() < mw) size.setWidth(mw); diff --git a/ui/widgets/vcard/omemo/keydelegate.h b/ui/widgets/vcard/omemo/keydelegate.h index 4c914f3..01b45c1 100644 --- a/ui/widgets/vcard/omemo/keydelegate.h +++ b/ui/widgets/vcard/omemo/keydelegate.h @@ -33,10 +33,12 @@ public: void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override; private: + const QFont& defaultFont; const QFont& fingerPrintFont; const QFont& labelFont; + const QFontMetrics& defaultMetrics; const QFontMetrics& fingerPrintMetrics; - const QFontMetrics& labelFontMetrics; + const QFontMetrics& labelMetrics; int spaceWidth; private: diff --git a/ui/widgets/vcard/omemo/omemo.cpp b/ui/widgets/vcard/omemo/omemo.cpp index 0aea97c..c260ab8 100644 --- a/ui/widgets/vcard/omemo/omemo.cpp +++ b/ui/widgets/vcard/omemo/omemo.cpp @@ -18,7 +18,7 @@ #include "ui_omemo.h" #include -constexpr uint8_t fingerprintLength = 24; +constexpr uint8_t fingerprintLength = 32; Omemo::Omemo(QWidget* parent): QWidget(parent), diff --git a/ui/widgets/vcard/omemo/omemo.ui b/ui/widgets/vcard/omemo/omemo.ui index 1dc6dc9..d9f55b1 100644 --- a/ui/widgets/vcard/omemo/omemo.ui +++ b/ui/widgets/vcard/omemo/omemo.ui @@ -65,21 +65,24 @@ - + + + + 0 + 0 + + QAbstractScrollArea::AdjustToContents false - - QAbstractItemView::SelectColumns - QAbstractItemView::ScrollPerPixel - QAbstractItemView::ScrollPerItem + QAbstractItemView::ScrollPerPixel false @@ -122,7 +125,29 @@ - + + + + 0 + 0 + + + + QAbstractScrollArea::AdjustToContents + + + false + + + QAbstractItemView::ScrollPerPixel + + + QAbstractItemView::ScrollPerPixel + + + false + + @@ -156,6 +181,14 @@ + + + ExpandingList + QListView +
ui/utils/expandinglist.h
+ 1 +
+