From 73d83f55af829135db3f2879cf849e5c6b9ed144 Mon Sep 17 00:00:00 2001 From: blue Date: Sun, 15 Jan 2023 21:17:38 +0300 Subject: [PATCH] context menu to trust or distrust keys --- ui/widgets/vcard/omemo/keydelegate.cpp | 22 +++++--- ui/widgets/vcard/omemo/keysmodel.cpp | 71 +++++++++++++++++++++++--- ui/widgets/vcard/omemo/keysmodel.h | 7 +++ ui/widgets/vcard/omemo/omemo.cpp | 54 ++++++++++++++++++-- ui/widgets/vcard/omemo/omemo.h | 8 ++- 5 files changed, 144 insertions(+), 18 deletions(-) diff --git a/ui/widgets/vcard/omemo/keydelegate.cpp b/ui/widgets/vcard/omemo/keydelegate.cpp index 189d8df..d0023e5 100644 --- a/ui/widgets/vcard/omemo/keydelegate.cpp +++ b/ui/widgets/vcard/omemo/keydelegate.cpp @@ -43,6 +43,12 @@ void UI::KeyDelegate::paint(QPainter* painter, const QStyleOptionViewItem& optio painter->save(); painter->setRenderHint(QPainter::Antialiasing, true); + QRect r; + int maxRight = 0; + int leftOrigin = option.rect.left() + margin; + QColor q = painter->pen().color(); + q.setAlpha(180); + QRect rect = option.rect; bool hover = option.state & QStyle::State_MouseOver; if (hover) { painter->save(); @@ -50,13 +56,15 @@ 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); + QVariant dirtyV = index.data(UI::KeysModel::Dirty); + if (dirtyV.isValid() && dirtyV.toBool()) { + painter->save(); + rect.setWidth(margin / 2); + painter->fillRect(rect, option.palette.brush(QPalette::Active, QPalette::Highlight)); + rect.setWidth(option.rect.width()); + painter->restore(); + } - QRect rect = option.rect; rect.adjust(margin, margin, -margin, -margin); QVariant labelV = index.data(UI::KeysModel::Label); if (labelV.isValid()) { @@ -167,6 +175,7 @@ QSize UI::KeyDelegate::sizeHint(const QStyleOptionViewItem& option, const QModel firstLine = parts; width = std::max(width, firstLine * fingerPrintMetrics.horizontalAdvance(hex, partSize) + (firstLine - 1) * spaceWidth); + width += 1; //there is a mistake somewhere, this the cheapest way to compensate it } QVariant lastV = index.data(UI::KeysModel::LastInteraction); if (lastV.isValid()) { @@ -186,6 +195,7 @@ QSize UI::KeyDelegate::sizeHint(const QStyleOptionViewItem& option, const QModel width += margin; width += defaultMetrics.horizontalAdvance(levelName); + width += 1; //there is a mistake somewhere, this the cheapest way to compensate it } mw += width; diff --git a/ui/widgets/vcard/omemo/keysmodel.cpp b/ui/widgets/vcard/omemo/keysmodel.cpp index 750e42a..1488370 100644 --- a/ui/widgets/vcard/omemo/keysmodel.cpp +++ b/ui/widgets/vcard/omemo/keysmodel.cpp @@ -24,12 +24,32 @@ const QHash UI::KeysModel::roles = { UI::KeysModel::KeysModel(QObject* parent): QAbstractListModel(parent), - keys() + keys(), + modified() { + } UI::KeysModel::~KeysModel() { + for (Shared::KeyInfo* key : keys) { + delete key; + } + for (std::pair& pair: modified) { + delete pair.second; + } +} + +std::deque UI::KeysModel::modifiedKeys() const { + std::deque response(modified.size()); + + int i = 0; + for (const std::pair& pair: modified) { + response[i] = *(pair.second); + ++i; + } + + return response; } void UI::KeysModel::addKey(const Shared::KeyInfo& info) { @@ -40,24 +60,34 @@ void UI::KeysModel::addKey(const Shared::KeyInfo& info) { QVariant UI::KeysModel::data(const QModelIndex& index, int role) const { int i = index.row(); + const Shared::KeyInfo* info; + bool dirty; + std::map::const_iterator itr = modified.find(i); + if (itr != modified.end()) { + info = itr->second; + dirty = true; + } else { + dirty = false; + info = keys[i]; + } QVariant answer; switch (role) { case Qt::DisplayRole: case Label: - answer = keys[i]->label; + answer = info->label; break; case FingerPrint: - answer = keys[i]->fingerPrint; + answer = info->fingerPrint; break; case TrustLevel: - answer = static_cast(keys[i]->trustLevel); + answer = static_cast(info->trustLevel); break; case LastInteraction: - answer = keys[i]->lastInteraction; + answer = info->lastInteraction; break; case Dirty: - answer = false; + answer = dirty; break; } @@ -78,7 +108,34 @@ QModelIndex UI::KeysModel::index(int row, int column, const QModelIndex& parent) return createIndex(row, column, keys[row]); } - +void UI::KeysModel::revertKey(int row) { + std::map::const_iterator itr = modified.find(row); + if (itr != modified.end()) { + modified.erase(itr); + QModelIndex index = createIndex(row, 0, keys[row]); + dataChanged(index, index); + } +} + +void UI::KeysModel::setTrustLevel(int row, Shared::TrustLevel level) { + std::map::const_iterator itr = modified.find(row); + Shared::KeyInfo* info; + if (itr == modified.end()) { + if (row < rowCount()) { + info = new Shared::KeyInfo(*(keys[row])); + modified.insert(std::make_pair(row, info)); + } else { + return; + } + } else { + info = itr->second; + } + + info->trustLevel = level; + + QModelIndex index = createIndex(row, 0, info); + dataChanged(index, index, {KeysModel::Dirty}); +} diff --git a/ui/widgets/vcard/omemo/keysmodel.h b/ui/widgets/vcard/omemo/keysmodel.h index 68f222c..e1a7606 100644 --- a/ui/widgets/vcard/omemo/keysmodel.h +++ b/ui/widgets/vcard/omemo/keysmodel.h @@ -40,6 +40,8 @@ public: QHash roleNames() const override; QModelIndex index(int row, int column, const QModelIndex & parent) const override; + std::deque modifiedKeys() const; + enum Roles { Label = Qt::UserRole + 1, FingerPrint, @@ -48,8 +50,13 @@ public: Dirty }; +public slots: + void revertKey(int index); + void setTrustLevel(int index, Shared::TrustLevel level); + private: std::deque keys; + std::map modified; private: static const QHash roles; diff --git a/ui/widgets/vcard/omemo/omemo.cpp b/ui/widgets/vcard/omemo/omemo.cpp index c260ab8..3a5ab73 100644 --- a/ui/widgets/vcard/omemo/omemo.cpp +++ b/ui/widgets/vcard/omemo/omemo.cpp @@ -26,7 +26,8 @@ Omemo::Omemo(QWidget* parent): keysDelegate(), unusedKeysDelegate(), keysModel(), - unusedKeysModel() + unusedKeysModel(), + contextMenu(new QMenu()) { m_ui->setupUi(this); @@ -36,15 +37,17 @@ Omemo::Omemo(QWidget* parent): m_ui->keysView->setModel(&keysModel); m_ui->unusedKeysView->setItemDelegate(&unusedKeysDelegate); m_ui->unusedKeysView->setModel(&unusedKeysModel); + + m_ui->keysView->setContextMenuPolicy(Qt::CustomContextMenu); + connect(m_ui->keysView, &QWidget::customContextMenuRequested, this, &Omemo::onActiveKeysContextMenu); } Omemo::~Omemo() { - + contextMenu->deleteLater(); } -void Omemo::generateMockData() -{ +void Omemo::generateMockData() { std::random_device rd; std::uniform_int_distribution dist(CHAR_MIN, CHAR_MAX); for (int i = 0; i < 5; ++i) { @@ -63,3 +66,46 @@ void Omemo::generateMockData() keysModel.addKey(info); } } + +void Omemo::onActiveKeysContextMenu(const QPoint& pos) { + contextMenu->clear(); + QModelIndex index = m_ui->keysView->indexAt(pos); + if (index.isValid()) { + QVariant dirtyV = index.data(UI::KeysModel::Dirty); + if (dirtyV.isValid() && dirtyV.toBool()) { + QAction* rev = contextMenu->addAction(Shared::icon("clean"), tr("Revert changes")); + connect(rev, &QAction::triggered, std::bind(&UI::KeysModel::revertKey, &keysModel, index.row())); + } + + QVariant levelV = index.data(UI::KeysModel::TrustLevel); + if (levelV.isValid()) { + Shared::TrustLevel level = static_cast(levelV.toUInt()); + if (level == Shared::TrustLevel::undecided || + level == Shared::TrustLevel::automaticallyDistrusted || + level == Shared::TrustLevel::manuallyDistrusted + ) { + QAction* rev = contextMenu->addAction(Shared::icon("favorite"), tr("Trust")); + connect(rev, &QAction::triggered, + std::bind(&UI::KeysModel::setTrustLevel, &keysModel, + index.row(), Shared::TrustLevel::manuallyTrusted + ) + ); + } + + if (level == Shared::TrustLevel::undecided || + level == Shared::TrustLevel::automaticallyTrusted || + level == Shared::TrustLevel::manuallyTrusted || + level == Shared::TrustLevel::authenticated + ) { + QAction* rev = contextMenu->addAction(Shared::icon("unfavorite"), tr("Distrust")); + connect(rev, &QAction::triggered, + std::bind(&UI::KeysModel::setTrustLevel, &keysModel, + index.row(), Shared::TrustLevel::manuallyDistrusted + ) + ); + } + } + } + + contextMenu->popup(m_ui->keysView->viewport()->mapToGlobal(pos)); +} diff --git a/ui/widgets/vcard/omemo/omemo.h b/ui/widgets/vcard/omemo/omemo.h index 2bc0433..59e3dac 100644 --- a/ui/widgets/vcard/omemo/omemo.h +++ b/ui/widgets/vcard/omemo/omemo.h @@ -17,11 +17,13 @@ #ifndef VCARD_OMEMO_H #define VCARD_OMEMO_H -#include +#include #include +#include #include "keysmodel.h" #include "keydelegate.h" +#include "shared/icons.h" namespace Ui { @@ -34,6 +36,9 @@ public: Omemo(QWidget* parent = nullptr); ~Omemo(); +private slots: + void onActiveKeysContextMenu(const QPoint& pos); + private: void generateMockData(); @@ -43,6 +48,7 @@ private: UI::KeyDelegate unusedKeysDelegate; UI::KeysModel keysModel; UI::KeysModel unusedKeysModel; + QMenu* contextMenu; }; #endif // VCARD_OMEMO_H