Skip to content

Commit

Permalink
[OMEMO] Improve plugin options dialog:
Browse files Browse the repository at this point in the history
  - add "Device ID" column to Known Keys tab
  - add ability to copy fingerprints from all tables
  - add support of selecting of multiple rows in all tables

+ Do not show trust confirmation dialog for devices with unknown keys
+ Update list of interlocutor's devices after receiving of encrypted message
  from unknown device. [Thanks to taurus]
  • Loading branch information
tehnick committed May 25, 2020
1 parent 94fafd7 commit 36b992f
Show file tree
Hide file tree
Showing 9 changed files with 179 additions and 73 deletions.
10 changes: 10 additions & 0 deletions generic/omemoplugin/changelog.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
2020-05-25
v2.3 tehnick
* Improve plugin options dialog:
- add "Device ID" column to Known Keys tab
- add ability to copy fingerprints from all tables
- add support of selecting of multiple rows in all tables
* Do not show trust confirmation dialog for devices with unknown keys
* Update list of interlocutor's devices after receiving of encrypted message
from unknown device. [Thanks to taurus]

2020-05-21
v2.2 tehnick
* Improve plugin description in "About plugin" dialog
Expand Down
173 changes: 126 additions & 47 deletions generic/omemoplugin/src/configwidget.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/*
/*
* OMEMO Plugin for Psi
* Copyright (C) 2018 Vyacheslav Karpukhin
* Copyright (C) 2020 Boris Pek
Expand All @@ -19,10 +19,13 @@
*/

#include "configwidget.h"
#include <QApplication>
#include <QClipboard>
#include <QGroupBox>
#include <QHBoxLayout>
#include <QHeaderView>
#include <QLabel>
#include <QMenu>
#include <QMessageBox>
#include <QVBoxLayout>

Expand Down Expand Up @@ -65,9 +68,9 @@ ConfigWidgetTabWithTable::ConfigWidgetTabWithTable(int account, OMEMO *omemo, QW
{
m_table = new QTableView(this);
m_table->setShowGrid(true);
m_table->setEditTriggers(QAbstractItemView::NoEditTriggers);
m_table->setEditTriggers(nullptr);
m_table->setSelectionBehavior(QAbstractItemView::SelectRows);
m_table->setSelectionMode(QAbstractItemView::SingleSelection);
m_table->setContextMenuPolicy(Qt::CustomContextMenu);
m_table->setSortingEnabled(true);
m_table->horizontalHeader()->setSortIndicator(0, Qt::AscendingOrder);

Expand All @@ -93,6 +96,21 @@ void ConfigWidgetTabWithTable::updateData()
m_table->resizeColumnsToContents();
}

void ConfigWidgetTabWithTable::copyFingerprintFromTable(QStandardItemModel *tableModel,
const QModelIndexList &indexesList,
const int column)
{
QString text;
for (auto selectIndex : indexesList) {
if (!text.isEmpty()) {
text += "\n";
}
text += tableModel->item(selectIndex.row(), column)->text();
}
QClipboard *clipboard = QApplication::clipboard();
clipboard->setText(text);
}

void ConfigWidget::currentAccountChanged(int index)
{
int account = dynamic_cast<QComboBox *>(sender())->itemData(index).toInt();
Expand All @@ -112,9 +130,9 @@ KnownFingerprints::KnownFingerprints(int account, OMEMO *omemo, QWidget *parent)
auto revokeButton = new QPushButton(tr("Do not trust"), this);
auto removeButton = new QPushButton(tr("Delete"), this);

connect(trustButton, &QPushButton::clicked, this, &KnownFingerprints::trustFingerprint);
connect(revokeButton, &QPushButton::clicked, this, &KnownFingerprints::revokeFingerprint);
connect(removeButton, &QPushButton::clicked, this, &KnownFingerprints::removeFingerprint);
connect(trustButton, &QPushButton::clicked, this, &KnownFingerprints::trustKnownKey);
connect(revokeButton, &QPushButton::clicked, this, &KnownFingerprints::revokeKnownKey);
connect(removeButton, &QPushButton::clicked, this, &KnownFingerprints::removeKnownKey);

buttonsLayout->addWidget(trustButton);
buttonsLayout->addWidget(revokeButton);
Expand All @@ -124,12 +142,15 @@ KnownFingerprints::KnownFingerprints(int account, OMEMO *omemo, QWidget *parent)

setLayout(mainLayout);
updateData();

connect(m_table, &QTableView::customContextMenuRequested,
this, &KnownFingerprints::contextMenuKnownKeys);
}

void KnownFingerprints::doUpdateData()
{
m_tableModel->setColumnCount(3);
m_tableModel->setHorizontalHeaderLabels({ tr("User"), tr("Trust"), tr("Fingerprint") });
m_tableModel->setColumnCount(4);
m_tableModel->setHorizontalHeaderLabels({ tr("User"), tr("Device ID"), tr("Trust"), tr("Fingerprint") });
for (auto fingerprint : m_omemo->getKnownFingerprints(m_account)) {
if (!m_jid.isEmpty()) {
if (fingerprint.contact != m_jid) {
Expand All @@ -141,6 +162,7 @@ void KnownFingerprints::doUpdateData()
auto contact = new QStandardItem(fingerprint.contact);
contact->setData(QVariant(fingerprint.deviceId));
row.append(contact);
row.append(new QStandardItem(QString::number(fingerprint.deviceId)));
TRUST_STATE state = fingerprint.trust;
row.append(new QStandardItem(state == TRUSTED ? tr("trusted")
: state == UNTRUSTED ? tr("untrusted") : tr("not decided")));
Expand All @@ -153,47 +175,82 @@ void KnownFingerprints::doUpdateData()
}
}

void KnownFingerprints::removeFingerprint()
void KnownFingerprints::removeKnownKey()
{
if (!m_table->selectionModel()->hasSelection())
return;

QStandardItem *item = m_tableModel->item(m_table->selectionModel()->selectedRows(0).at(0).row(), 0);
m_omemo->removeDevice(m_account, item->text(), item->data().toUInt());
bool keyRemoved = false;
for (auto selectIndex : m_table->selectionModel()->selectedRows(0)) {
QStandardItem *item = m_tableModel->item(selectIndex.row(), 0);
if (m_omemo->removeDevice(m_account, item->text(), item->data().toUInt())) {
keyRemoved = true;
}
}

updateData();
if (keyRemoved)
updateData();
}

void KnownFingerprints::trustFingerprint()
void KnownFingerprints::trustKnownKey()
{
if (!m_table->selectionModel()->hasSelection())
return;

QStandardItem *item = m_tableModel->item(m_table->selectionModel()->selectedRows(0).at(0).row(), 0);
m_omemo->confirmDeviceTrust(m_account, item->text(), item->data().toUInt());
const auto &&selection = m_table->selectionModel()->selectedRows(0);
for (auto selectIndex : selection) {
QStandardItem *item = m_tableModel->item(selectIndex.row(), 0);
m_omemo->confirmDeviceTrust(m_account, item->text(), item->data().toUInt());
}

const int index = item->row();
const int rowCount = m_tableModel->rowCount();
updateData();

if (rowCount == m_tableModel->rowCount())
m_table->selectRow(index);
if (rowCount == m_tableModel->rowCount() && selection.size() == 1) {
m_table->selectRow(selection.first().row());
}
}

void KnownFingerprints::revokeFingerprint()
void KnownFingerprints::revokeKnownKey()
{
if (!m_table->selectionModel()->hasSelection())
return;

QStandardItem *item = m_tableModel->item(m_table->selectionModel()->selectedRows(0).at(0).row(), 0);
m_omemo->revokeDeviceTrust(m_account, item->text(), item->data().toUInt());
const auto &&selection = m_table->selectionModel()->selectedRows(0);
for (auto selectIndex : selection) {
QStandardItem *item = m_tableModel->item(selectIndex.row(), 0);
m_omemo->revokeDeviceTrust(m_account, item->text(), item->data().toUInt());
}

const int index = item->row();
const int rowCount = m_tableModel->rowCount();
updateData();

if (rowCount == m_tableModel->rowCount())
m_table->selectRow(index);
if (rowCount == m_tableModel->rowCount() && selection.size() == 1) {
m_table->selectRow(selection.first().row());
}
}

void KnownFingerprints::contextMenuKnownKeys(const QPoint &pos)
{
QModelIndex index = m_table->indexAt(pos);
if (!index.isValid())
return;

QMenu *menu = new QMenu(this);

// TODO: update after stopping support of Ubuntu Xenial:
menu->addAction(QIcon::fromTheme("edit-copy"), tr("Copy fingerprint"),
this, SLOT(copyKnownFingerprint()));

menu->exec(QCursor::pos());
}

void KnownFingerprints::copyKnownFingerprint()
{
if (!m_table->selectionModel()->hasSelection())
return;

copyFingerprintFromTable(m_tableModel, m_table->selectionModel()->selectedRows(0), 3);
}

ManageDevices::ManageDevices(int account, OMEMO *omemo, QWidget *parent) :
Expand All @@ -213,13 +270,14 @@ ManageDevices::ManageDevices(int account, OMEMO *omemo, QWidget *parent) :
deviceInfoLayout->addWidget(infoLabel);
deviceInfoLayout->addWidget(m_fingerprintLabel);

m_deviceIdLabel = new QLabel(currentDevice);
auto deleteCurrentDeviceButton = new QPushButton(tr("Delete all OMEMO data for current device"), currentDevice);
connect(deleteCurrentDeviceButton, &QPushButton::clicked, this, &ManageDevices::deleteCurrentDevice);

auto deleteCurrentDeviceLayout = new QHBoxLayout();
deleteCurrentDeviceLayout->addWidget(deleteCurrentDeviceButton);
deleteCurrentDeviceLayout->addWidget(new QLabel(currentDevice));
deleteCurrentDeviceLayout->addWidget(m_deviceIdLabel);
deleteCurrentDeviceLayout->addWidget(new QLabel(currentDevice));
deleteCurrentDeviceLayout->addWidget(deleteCurrentDeviceButton);

auto currentDeviceLayout = new QVBoxLayout(currentDevice);
currentDeviceLayout->addLayout(deviceInfoLayout);
Expand All @@ -230,7 +288,6 @@ ManageDevices::ManageDevices(int account, OMEMO *omemo, QWidget *parent) :
auto otherDevices = new QGroupBox(tr("Other devices"), this);
auto buttonsLayout = new QHBoxLayout();
m_deleteButton = new QPushButton(tr("Delete"), this);
m_deleteButton->setEnabled(false);
connect(m_deleteButton, &QPushButton::clicked, this, &ManageDevices::deleteDevice);
buttonsLayout->addWidget(m_deleteButton);
buttonsLayout->addWidget(new QLabel(this));
Expand All @@ -246,33 +303,22 @@ ManageDevices::ManageDevices(int account, OMEMO *omemo, QWidget *parent) :
mainLayout->addWidget(otherDevices);
setLayout(mainLayout);

connect(m_table->selectionModel(), &QItemSelectionModel::selectionChanged, this, &ManageDevices::selectionChanged);
connect(m_omemo, &OMEMO::deviceListUpdated, this, &ManageDevices::deviceListUpdated);
connect(m_table, &QTableView::customContextMenuRequested,
this, &ManageDevices::contextMenuOwnDevices);

ManageDevices::updateData();
}

void ManageDevices::updateData()
{
m_currentDeviceId = m_omemo->getDeviceId(m_account);
m_deviceIdLabel->setText(tr("Device ID") + QString(": %1").arg(QString::number(m_currentDeviceId)));
m_fingerprintLabel->setText(QString("<code>%1</code>").arg(m_omemo->getOwnFingerprint(m_account)));

ConfigWidgetTabWithTable::updateData();
}

void ManageDevices::selectionChanged(const QItemSelection &selected, const QItemSelection &)
{
QModelIndexList selection = selected.indexes();
if (!selection.isEmpty()) {
m_deleteButton->setEnabled(selectedDeviceId(selection) != m_currentDeviceId);
}
}

uint32_t ManageDevices::selectedDeviceId(const QModelIndexList &selection) const
{
return m_tableModel->itemFromIndex(selection.first())->data().toUInt();
}

void ManageDevices::doUpdateData()
{
m_tableModel->setColumnCount(1);
Expand Down Expand Up @@ -324,22 +370,32 @@ void ManageDevices::deleteCurrentDevice()

void ManageDevices::deleteDevice()
{
QModelIndexList selection = m_table->selectionModel()->selectedIndexes();
if (!selection.isEmpty()) {
const QString &message = tr("After deleting of device from list of available devices "
const QModelIndexList &&selection = m_table->selectionModel()->selectedRows(0);
if (selection.isEmpty())
return;

for (auto selectIndex : selection) {
const QString &&deviceId = m_tableModel->item(selectIndex.row(), 0)->data().toString();
const QString &&fingerprint = m_tableModel->item(selectIndex.row(), 1)->text();
const QString &&message = tr("After deleting of device from list of available devices "
"it stops receiving offline messages from your contacts "
"until it will become online and your contacts mark it "
"as trusted.")
+ "\n\n" + tr("Delete selected device?");
+ "\n\n"
+ tr("Device ID") + QString(": %1").arg(deviceId)
+ "\n"
+ tr("Fingerprint") + QString(": %1").arg(fingerprint)
+ "\n\n"
+ tr("Delete selected device?");

QMessageBox messageBox(QMessageBox::Question, QObject::tr("Confirm action"), message);
messageBox.addButton(QObject::tr("Delete"), QMessageBox::AcceptRole);
messageBox.addButton(QObject::tr("Cancel"), QMessageBox::RejectRole);

if (messageBox.exec() != 0)
return;
continue;

m_omemo->unpublishDevice(m_account, selectedDeviceId(selection));
m_omemo->unpublishDevice(m_account, deviceId.toUInt());
}
}

Expand All @@ -350,6 +406,29 @@ void ManageDevices::deviceListUpdated(int account)
}
}

void ManageDevices::contextMenuOwnDevices(const QPoint &pos)
{
QModelIndex index = m_table->indexAt(pos);
if (!index.isValid())
return;

QMenu *menu = new QMenu(this);

// TODO: update after stopping support of Ubuntu Xenial:
menu->addAction(QIcon::fromTheme("edit-copy"), tr("Copy fingerprint"),
this, SLOT(copyOwnFingerprint()));

menu->exec(QCursor::pos());
}

void ManageDevices::copyOwnFingerprint()
{
if (!m_table->selectionModel()->hasSelection())
return;

copyFingerprintFromTable(m_tableModel, m_table->selectionModel()->selectedRows(0), 1);
}

OmemoConfiguration::OmemoConfiguration(int account, OMEMO *omemo, QWidget *parent) :
ConfigWidgetTab(account, omemo, parent)
{
Expand Down
16 changes: 11 additions & 5 deletions generic/omemoplugin/src/configwidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ class ConfigWidgetTabWithTable : public ConfigWidgetTab {
ConfigWidgetTabWithTable(int account, OMEMO *omemo, QWidget *parent);
void filterContacts(const QString &jid);
void updateData() override;
void copyFingerprintFromTable(QStandardItemModel *tableModel,
const QModelIndexList &indexesList,
const int column);

protected:
virtual void doUpdateData() = 0;
Expand All @@ -76,9 +79,11 @@ class KnownFingerprints : public ConfigWidgetTabWithTable {
void doUpdateData() override;

private slots:
void removeFingerprint();
void trustFingerprint();
void revokeFingerprint();
void removeKnownKey();
void trustKnownKey();
void revokeKnownKey();
void contextMenuKnownKeys(const QPoint &pos);
void copyKnownFingerprint();
};

class ManageDevices : public ConfigWidgetTabWithTable {
Expand All @@ -95,18 +100,19 @@ class ManageDevices : public ConfigWidgetTabWithTable {

private:
QLabel * m_fingerprintLabel;
QLabel * m_deviceIdLabel;
uint32_t m_currentDeviceId;
QPushButton *m_deleteButton;
uint32_t selectedDeviceId(const QModelIndexList &selection) const;

protected:
void doUpdateData() override;

private slots:
void selectionChanged(const QItemSelection &, const QItemSelection &);
void deleteCurrentDevice();
void deleteDevice();
void deviceListUpdated(int account);
void contextMenuOwnDevices(const QPoint &pos);
void copyOwnFingerprint();
};

class OmemoConfiguration : public ConfigWidgetTab {
Expand Down

0 comments on commit 36b992f

Please sign in to comment.