some initial classes for keys form

This commit is contained in:
Blue 2023-01-03 18:27:03 +03:00
parent b45a73b723
commit 5aa0f4bca9
Signed by untrusted user: blue
GPG Key ID: 9B203B252A63EE38
11 changed files with 361 additions and 159 deletions

View File

@ -39,8 +39,29 @@ Shared::KeyInfo::KeyInfo():
id(0),
fingerPrint(),
label(),
trustLevel(TrustLevel::Undecided),
trustLevel(TrustLevel::undecided),
protocol(EncryptionProtocol::omemo),
currentDevice(false)
{
}
Shared::KeyInfo::KeyInfo(const Shared::KeyInfo& other):
id(other.id),
fingerPrint(other.fingerPrint),
label(other.label),
trustLevel(other.trustLevel),
protocol(other.protocol),
currentDevice(other.currentDevice)
{
}
Shared::KeyInfo & Shared::KeyInfo::operator=(const Shared::KeyInfo& other) {
id = other.id;
fingerPrint = other.fingerPrint;
label = other.label;
trustLevel = other.trustLevel;
protocol = other.protocol;
currentDevice = other.currentDevice;
return *this;
}

View File

@ -39,8 +39,11 @@ public:
bool currentDevice = false
);
KeyInfo();
KeyInfo(const KeyInfo& other);
private:
KeyInfo& operator=(const KeyInfo& other);
public:
uint32_t id;
QByteArray fingerPrint;
QString label;

View File

@ -440,10 +440,7 @@ QModelIndex Models::MessageFeed::index(int row, int column, const QModelIndex& p
}
}
QHash<int, QByteArray> Models::MessageFeed::roleNames() const
{
return roles;
}
QHash<int, QByteArray> Models::MessageFeed::roleNames() const {return roles;}
bool Models::MessageFeed::sentByMe(const Shared::Message& msg) const
{

View File

@ -2,4 +2,6 @@ target_sources(squawk PRIVATE
omemo.cpp
omemo.h
omemo.ui
keysmodel.cpp
keysmodel.h
)

View File

@ -0,0 +1,71 @@
// Squawk messenger.
// Copyright (C) 2019 Yury Gubich <blue@macaw.me>
//
// 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 <http://www.gnu.org/licenses/>.
#include "keysmodel.h"
const QHash<int, QByteArray> UI::KeysModel::roles = {
{Label, "label"},
{FingerPrint, "fingerPrint"},
{TrustLevel, "trustLevel"}
};
UI::KeysModel::KeysModel(QObject* parent):
QAbstractListModel(parent),
keys()
{
}
UI::KeysModel::~KeysModel() {
}
void UI::KeysModel::addKey(const Shared::KeyInfo& info) {
beginInsertRows(QModelIndex(), keys.size(), keys.size());
keys.push_back(new Shared::KeyInfo(info));
endInsertRows();
}
QVariant UI::KeysModel::data(const QModelIndex& index, int role) const {
int i = index.row();
QVariant answer;
switch (role) {
case Qt::DisplayRole:
answer = keys[i]->label;
break;
}
return answer;
}
int UI::KeysModel::rowCount(const QModelIndex& parent) const {
return keys.size();
}
QHash<int, QByteArray> UI::KeysModel::roleNames() const {return roles;}
QModelIndex UI::KeysModel::index(int row, int column, const QModelIndex& parent) const {
if (!hasIndex(row, column, parent)) {
return QModelIndex();
}
return createIndex(row, column, keys[row]);
}

View File

@ -0,0 +1,58 @@
// Squawk messenger.
// Copyright (C) 2019 Yury Gubich <blue@macaw.me>
//
// 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 <http://www.gnu.org/licenses/>.
#ifndef UI_KEYSMODEL_H
#define UI_KEYSMODEL_H
#include <QAbstractListModel>
#include <shared/keyinfo.h>
namespace UI {
/**
* @todo write docs
*/
class KeysModel : public QAbstractListModel
{
public:
KeysModel(QObject *parent = nullptr);
~KeysModel();
void addKey(const Shared::KeyInfo& info);
QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const override;
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
QHash<int, QByteArray> roleNames() const override;
QModelIndex index(int row, int column, const QModelIndex & parent) const override;
enum Roles {
Label = Qt::UserRole + 1,
FingerPrint,
TrustLevel
};
private:
std::deque<Shared::KeyInfo*> keys;
private:
static const QHash<int, QByteArray> roles;
};
}
#endif // UI_KEYSMODEL_H

View File

@ -17,4 +17,31 @@
#include "omemo.h"
#include "ui_omemo.h"
using namespace Ui;
Omemo::Omemo(QWidget* parent):
QWidget(parent),
m_ui(new Ui::Omemo()),
keysModel(),
unusedKeysModel()
{
m_ui->setupUi(this);
generateMockData();
m_ui->keysView->setModel(&keysModel);
m_ui->unusedKeysView->setModel(&unusedKeysModel);
}
Omemo::~Omemo()
{
}
void Omemo::generateMockData()
{
for (int i = 0; i < 5; ++i) {
Shared::KeyInfo info;
info.id = i;
info.label = QString("test_") + std::to_string(i).c_str();
keysModel.addKey(info);
}
}

View File

@ -14,30 +14,32 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef UI_OMEMO_H
#define UI_OMEMO_H
#ifndef VCARD_OMEMO_H
#define VCARD_OMEMO_H
#include <qwidget.h>
#include <QScopedPointer>
namespace Ui {
#include "keysmodel.h"
namespace Ui
{
class Omemo;
}
/**
* @todo write docs
*/
class Omemo : public QWidget
{
class Omemo : public QWidget {
Q_OBJECT
public:
Omemo(QWidget* parent = nullptr);
~Omemo();
private:
void generateMockData();
private:
QScopedPointer<Ui::Omemo> m_ui;
UI::KeysModel keysModel;
UI::KeysModel unusedKeysModel;
};
}
#endif // UI_OMEMO_H
#endif // VCARD_OMEMO_H

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Ui::Omemo</class>
<widget class="QWidget" name="Ui::Omemo">
<class>Omemo</class>
<widget class="QWidget" name="Omemo">
<property name="geometry">
<rect>
<x>0</x>

View File

@ -41,105 +41,29 @@ VCard::VCard(const QString& jid, bool edit, QWidget* parent):
phones(edit),
roleDelegate(new ComboboxDelegate()),
phoneTypeDelegate(new ComboboxDelegate())
#ifdef WITH_OMEMO
,omemo(new Omemo())
#endif
{
m_ui->setupUi(this);
m_ui->jabberID->setText(jid);
m_ui->jabberID->setReadOnly(true);
QAction* setAvatar = m_ui->actionSetAvatar;
QAction* clearAvatar = m_ui->actionClearAvatar;
connect(setAvatar, &QAction::triggered, this, &VCard::onSetAvatar);
connect(clearAvatar, &QAction::triggered, this, &VCard::onClearAvatar);
setAvatar->setEnabled(true);
clearAvatar->setEnabled(false);
roleDelegate->addEntry(QCoreApplication::translate("Global", Shared::VCard::Email::roleNames[0].toStdString().c_str()));
roleDelegate->addEntry(QCoreApplication::translate("Global", Shared::VCard::Email::roleNames[1].toStdString().c_str()));
roleDelegate->addEntry(QCoreApplication::translate("Global", Shared::VCard::Email::roleNames[2].toStdString().c_str()));
phoneTypeDelegate->addEntry(QCoreApplication::translate("Global", Shared::VCard::Phone::typeNames[0].toStdString().c_str()));
phoneTypeDelegate->addEntry(QCoreApplication::translate("Global", Shared::VCard::Phone::typeNames[1].toStdString().c_str()));
phoneTypeDelegate->addEntry(QCoreApplication::translate("Global", Shared::VCard::Phone::typeNames[2].toStdString().c_str()));
phoneTypeDelegate->addEntry(QCoreApplication::translate("Global", Shared::VCard::Phone::typeNames[3].toStdString().c_str()));
phoneTypeDelegate->addEntry(QCoreApplication::translate("Global", Shared::VCard::Phone::typeNames[4].toStdString().c_str()));
phoneTypeDelegate->addEntry(QCoreApplication::translate("Global", Shared::VCard::Phone::typeNames[5].toStdString().c_str()));
phoneTypeDelegate->addEntry(QCoreApplication::translate("Global", Shared::VCard::Phone::typeNames[6].toStdString().c_str()));
m_ui->emailsView->setContextMenuPolicy(Qt::CustomContextMenu);
m_ui->emailsView->setModel(&emails);
m_ui->emailsView->setItemDelegateForColumn(1, roleDelegate);
m_ui->emailsView->setColumnWidth(2, 25);
m_ui->emailsView->horizontalHeader()->setStretchLastSection(false);
m_ui->emailsView->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch);
m_ui->phonesView->setContextMenuPolicy(Qt::CustomContextMenu);
m_ui->phonesView->setModel(&phones);
m_ui->phonesView->setItemDelegateForColumn(1, roleDelegate);
m_ui->phonesView->setItemDelegateForColumn(2, phoneTypeDelegate);
m_ui->phonesView->setColumnWidth(3, 25);
m_ui->phonesView->horizontalHeader()->setStretchLastSection(false);
m_ui->phonesView->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch);
connect(m_ui->phonesView, &QWidget::customContextMenuRequested, this, &VCard::onContextMenu);
connect(m_ui->emailsView, &QWidget::customContextMenuRequested, this, &VCard::onContextMenu);
if (edit) {
avatarMenu = new QMenu();
m_ui->avatarButton->setMenu(avatarMenu);
avatarMenu->addAction(setAvatar);
avatarMenu->addAction(clearAvatar);
m_ui->title->setText(tr("Account %1 card").arg(jid));
} else {
m_ui->buttonBox->hide();
m_ui->fullName->setReadOnly(true);
m_ui->firstName->setReadOnly(true);
m_ui->middleName->setReadOnly(true);
m_ui->lastName->setReadOnly(true);
m_ui->nickName->setReadOnly(true);
m_ui->birthday->setReadOnly(true);
m_ui->organizationName->setReadOnly(true);
m_ui->organizationDepartment->setReadOnly(true);
m_ui->organizationTitle->setReadOnly(true);
m_ui->organizationRole->setReadOnly(true);
m_ui->description->setReadOnly(true);
m_ui->url->setReadOnly(true);
m_ui->title->setText(tr("Contact %1 card").arg(jid));
initializeActions();
initializeDelegates();
initializeViews();
initializeInteractiveElements(jid);
initializeOverlay();
#ifdef WITH_OMEMO
initializeOmemo();
#endif
}
connect(m_ui->buttonBox, &QDialogButtonBox::accepted, this, &VCard::onButtonBoxAccepted);
connect(m_ui->buttonBox, &QDialogButtonBox::rejected, this, &VCard::close);
avatarButtonMargins = m_ui->avatarButton->size();
int height = m_ui->personalForm->minimumSize().height() - avatarButtonMargins.height();
m_ui->avatarButton->setIconSize(QSize(height, height));
QGridLayout* gr = static_cast<QGridLayout*>(layout());
gr->addWidget(overlay, 0, 0, 4, 1);
QVBoxLayout* nl = new QVBoxLayout();
QGraphicsOpacityEffect* opacity = new QGraphicsOpacityEffect();
opacity->setOpacity(0.8);
overlay->setLayout(nl);
overlay->setBackgroundRole(QPalette::Base);
overlay->setAutoFillBackground(true);
overlay->setGraphicsEffect(opacity);
progressLabel->setAlignment(Qt::AlignCenter);
QFont pf = progressLabel->font();
pf.setBold(true);
pf.setPointSize(26);
progressLabel->setFont(pf);
progressLabel->setWordWrap(true);
nl->addStretch();
nl->addWidget(progress);
nl->addWidget(progressLabel);
nl->addStretch();
overlay->hide();
}
VCard::~VCard()
{
VCard::~VCard() {
#ifdef WITH_OMEMO
delete omemo;
#endif
if (editable) {
avatarMenu->deleteLater();
}
@ -149,14 +73,12 @@ VCard::~VCard()
contextMenu->deleteLater();
}
void VCard::setVCard(const QString& jid, const Shared::VCard& card)
{
void VCard::setVCard(const QString& jid, const Shared::VCard& card) {
m_ui->jabberID->setText(jid);
setVCard(card);
}
void VCard::setVCard(const Shared::VCard& card)
{
void VCard::setVCard(const Shared::VCard& card) {
m_ui->fullName->setText(card.getFullName());
m_ui->firstName->setText(card.getFirstName());
m_ui->middleName->setText(card.getMiddleName());
@ -183,13 +105,11 @@ void VCard::setVCard(const Shared::VCard& card)
phones.setPhones(phs);
}
QString VCard::getJid() const
{
QString VCard::getJid() const {
return m_ui->jabberID->text();
}
void VCard::onButtonBoxAccepted()
{
void VCard::onButtonBoxAccepted() {
Shared::VCard card;
card.setFullName(m_ui->fullName->text());
card.setFirstName(m_ui->firstName->text());
@ -212,16 +132,14 @@ void VCard::onButtonBoxAccepted()
emit saveVCard(card);
}
void VCard::onClearAvatar()
{
void VCard::onClearAvatar() {
currentAvatarType = Shared::Avatar::empty;
currentAvatarPath = "";
updateAvatar();
}
void VCard::onSetAvatar()
{
void VCard::onSetAvatar() {
QFileDialog* d = new QFileDialog(this, tr("Chose your new avatar"));
d->setFileMode(QFileDialog::ExistingFile);
d->setNameFilter(tr("Images (*.png *.jpg *.jpeg)"));
@ -232,8 +150,7 @@ void VCard::onSetAvatar()
d->show();
}
void VCard::updateAvatar()
{
void VCard::updateAvatar() {
int height = m_ui->personalForm->minimumSize().height() - avatarButtonMargins.height();
switch (currentAvatarType) {
case Shared::Avatar::empty:
@ -254,8 +171,7 @@ void VCard::updateAvatar()
}
}
void VCard::onAvatarSelected()
{
void VCard::onAvatarSelected() {
QFileDialog* d = static_cast<QFileDialog*>(sender());
QMimeDatabase db;
QString path = d->selectedFiles().front();
@ -290,21 +206,18 @@ void VCard::onAvatarSelected()
}
}
void VCard::showProgress(const QString& line)
{
void VCard::showProgress(const QString& line) {
progressLabel->setText(line);
overlay->show();
progress->start();
}
void VCard::hideProgress()
{
void VCard::hideProgress() {
overlay->hide();
progress->stop();
}
void VCard::onContextMenu(const QPoint& point)
{
void VCard::onContextMenu(const QPoint& point) {
contextMenu->clear();
bool hasMenu = false;
QAbstractItemView* snd = static_cast<QAbstractItemView*>(sender());
@ -371,28 +284,20 @@ void VCard::onContextMenu(const QPoint& point)
}
}
void VCard::onAddEmail()
{
void VCard::onAddEmail() {
QModelIndex index = emails.addNewEmptyLine();
m_ui->emailsView->setCurrentIndex(index);
m_ui->emailsView->edit(index);
}
void VCard::onAddAddress()
{
}
void VCard::onAddPhone()
{
void VCard::onAddAddress() {}
void VCard::onAddPhone() {
QModelIndex index = phones.addNewEmptyLine();
m_ui->phonesView->setCurrentIndex(index);
m_ui->phonesView->edit(index);
}
void VCard::onRemoveAddress()
{
}
void VCard::onRemoveEmail()
{
void VCard::onRemoveAddress() {}
void VCard::onRemoveEmail() {
QItemSelection selection(m_ui->emailsView->selectionModel()->selection());
QList<int> rows;
@ -412,8 +317,7 @@ void VCard::onRemoveEmail()
}
}
void VCard::onRemovePhone()
{
void VCard::onRemovePhone() {
QItemSelection selection(m_ui->phonesView->selectionModel()->selection());
QList<int> rows;
@ -433,8 +337,7 @@ void VCard::onRemovePhone()
}
}
void VCard::onCopyEmail()
{
void VCard::onCopyEmail() {
QList<QModelIndex> selection(m_ui->emailsView->selectionModel()->selectedRows());
QList<QString> addrs;
@ -448,8 +351,7 @@ void VCard::onCopyEmail()
cb->setText(list);
}
void VCard::onCopyPhone()
{
void VCard::onCopyPhone() {
QList<QModelIndex> selection(m_ui->phonesView->selectionModel()->selectedRows());
QList<QString> phs;
@ -462,3 +364,111 @@ void VCard::onCopyPhone()
QClipboard* cb = QApplication::clipboard();
cb->setText(list);
}
void VCard::initializeDelegates() {
roleDelegate->addEntry(QCoreApplication::translate("Global", Shared::VCard::Email::roleNames[0].toStdString().c_str()));
roleDelegate->addEntry(QCoreApplication::translate("Global", Shared::VCard::Email::roleNames[1].toStdString().c_str()));
roleDelegate->addEntry(QCoreApplication::translate("Global", Shared::VCard::Email::roleNames[2].toStdString().c_str()));
phoneTypeDelegate->addEntry(QCoreApplication::translate("Global", Shared::VCard::Phone::typeNames[0].toStdString().c_str()));
phoneTypeDelegate->addEntry(QCoreApplication::translate("Global", Shared::VCard::Phone::typeNames[1].toStdString().c_str()));
phoneTypeDelegate->addEntry(QCoreApplication::translate("Global", Shared::VCard::Phone::typeNames[2].toStdString().c_str()));
phoneTypeDelegate->addEntry(QCoreApplication::translate("Global", Shared::VCard::Phone::typeNames[3].toStdString().c_str()));
phoneTypeDelegate->addEntry(QCoreApplication::translate("Global", Shared::VCard::Phone::typeNames[4].toStdString().c_str()));
phoneTypeDelegate->addEntry(QCoreApplication::translate("Global", Shared::VCard::Phone::typeNames[5].toStdString().c_str()));
phoneTypeDelegate->addEntry(QCoreApplication::translate("Global", Shared::VCard::Phone::typeNames[6].toStdString().c_str()));
}
void VCard::initializeViews() {
m_ui->emailsView->setContextMenuPolicy(Qt::CustomContextMenu);
m_ui->emailsView->setModel(&emails);
m_ui->emailsView->setItemDelegateForColumn(1, roleDelegate);
m_ui->emailsView->setColumnWidth(2, 25);
m_ui->emailsView->horizontalHeader()->setStretchLastSection(false);
m_ui->emailsView->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch);
m_ui->phonesView->setContextMenuPolicy(Qt::CustomContextMenu);
m_ui->phonesView->setModel(&phones);
m_ui->phonesView->setItemDelegateForColumn(1, roleDelegate);
m_ui->phonesView->setItemDelegateForColumn(2, phoneTypeDelegate);
m_ui->phonesView->setColumnWidth(3, 25);
m_ui->phonesView->horizontalHeader()->setStretchLastSection(false);
m_ui->phonesView->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch);
connect(m_ui->phonesView, &QWidget::customContextMenuRequested, this, &VCard::onContextMenu);
connect(m_ui->emailsView, &QWidget::customContextMenuRequested, this, &VCard::onContextMenu);
}
void VCard::initializeActions() {
QAction* setAvatar = m_ui->actionSetAvatar;
QAction* clearAvatar = m_ui->actionClearAvatar;
connect(setAvatar, &QAction::triggered, this, &VCard::onSetAvatar);
connect(clearAvatar, &QAction::triggered, this, &VCard::onClearAvatar);
setAvatar->setEnabled(true);
clearAvatar->setEnabled(false);
}
void VCard::initializeInteractiveElements(const QString& jid) {
if (editable) {
avatarMenu = new QMenu();
m_ui->avatarButton->setMenu(avatarMenu);
avatarMenu->addAction(m_ui->actionSetAvatar);
avatarMenu->addAction(m_ui->actionClearAvatar);
m_ui->title->setText(tr("Account %1 card").arg(jid));
} else {
m_ui->buttonBox->hide();
m_ui->fullName->setReadOnly(true);
m_ui->firstName->setReadOnly(true);
m_ui->middleName->setReadOnly(true);
m_ui->lastName->setReadOnly(true);
m_ui->nickName->setReadOnly(true);
m_ui->birthday->setReadOnly(true);
m_ui->organizationName->setReadOnly(true);
m_ui->organizationDepartment->setReadOnly(true);
m_ui->organizationTitle->setReadOnly(true);
m_ui->organizationRole->setReadOnly(true);
m_ui->description->setReadOnly(true);
m_ui->url->setReadOnly(true);
m_ui->title->setText(tr("Contact %1 card").arg(jid));
}
connect(m_ui->buttonBox, &QDialogButtonBox::accepted, this, &VCard::onButtonBoxAccepted);
connect(m_ui->buttonBox, &QDialogButtonBox::rejected, this, &VCard::close);
avatarButtonMargins = m_ui->avatarButton->size();
int height = m_ui->personalForm->minimumSize().height() - avatarButtonMargins.height();
m_ui->avatarButton->setIconSize(QSize(height, height));
}
void VCard::initializeOverlay() {
QGridLayout* gr = static_cast<QGridLayout*>(layout());
gr->addWidget(overlay, 0, 0, 4, 1);
QVBoxLayout* nl = new QVBoxLayout();
QGraphicsOpacityEffect* opacity = new QGraphicsOpacityEffect();
opacity->setOpacity(0.8);
overlay->setLayout(nl);
overlay->setBackgroundRole(QPalette::Base);
overlay->setAutoFillBackground(true);
overlay->setGraphicsEffect(opacity);
progressLabel->setAlignment(Qt::AlignCenter);
QFont pf = progressLabel->font();
pf.setBold(true);
pf.setPointSize(26);
progressLabel->setFont(pf);
progressLabel->setWordWrap(true);
nl->addStretch();
nl->addWidget(progress);
nl->addWidget(progressLabel);
nl->addStretch();
overlay->hide();
}
#ifdef WITH_OMEMO
void VCard::initializeOmemo() {
m_ui->tabWidget->addTab(omemo, "OMEMO");
}
#endif

View File

@ -42,16 +42,16 @@
#include "ui/utils/progress.h"
#include "ui/utils/comboboxdelegate.h"
#ifdef WITH_OMEMO
#include "omemo/omemo.h"
#endif
namespace Ui
{
class VCard;
}
/**
* @todo write docs
*/
class VCard : public QWidget
{
class VCard : public QWidget {
Q_OBJECT
public:
VCard(const QString& jid, bool edit = false, QWidget* parent = nullptr);
@ -96,11 +96,22 @@ private:
UI::VCard::PhonesModel phones;
ComboboxDelegate* roleDelegate;
ComboboxDelegate* phoneTypeDelegate;
#ifdef WITH_OMEMO
Omemo* omemo;
#endif
static const std::set<QString> supportedTypes;
private:
void updateAvatar();
void initializeDelegates();
void initializeViews();
void initializeActions();
void initializeInteractiveElements(const QString& jid);
void initializeOverlay();
#ifdef WITH_OMEMO
void initializeOmemo();
#endif
};
#endif // VCARD_H