started refactoring of the VCard UI

This commit is contained in:
Blue 2023-02-01 18:56:00 +03:00
parent bb304ce774
commit 4af16b75bf
Signed by: blue
GPG key ID: 9B203B252A63EE38
32 changed files with 1250 additions and 166 deletions

View file

@ -1,13 +1,5 @@
target_sources(squawk PRIVATE
emailsmodel.cpp
emailsmodel.h
phonesmodel.cpp
phonesmodel.h
vcard.cpp
vcard.h
vcard.ui
)
if (WITH_OMEMO)
add_subdirectory(omemo)
endif()

View file

@ -1,208 +0,0 @@
/*
* 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 "emailsmodel.h"
#include "shared/icons.h"
#include <QCoreApplication>
UI::VCard::EMailsModel::EMailsModel(bool p_edit, QObject* parent):
QAbstractTableModel(parent),
edit(p_edit),
deque()
{
}
int UI::VCard::EMailsModel::columnCount(const QModelIndex& parent) const
{
return 3;
}
int UI::VCard::EMailsModel::rowCount(const QModelIndex& parent) const
{
return deque.size();
}
QVariant UI::VCard::EMailsModel::data(const QModelIndex& index, int role) const
{
if (index.isValid()) {
int col = index.column();
switch (col) {
case 0:
switch (role) {
case Qt::DisplayRole:
case Qt::EditRole:
return deque[index.row()].address;
default:
return QVariant();
}
break;
case 1:
switch (role) {
case Qt::DisplayRole:
return QCoreApplication::translate("Global", Shared::VCard::Email::roleNames[deque[index.row()].role].toStdString().c_str());
case Qt::EditRole:
return deque[index.row()].role;
default:
return QVariant();
}
break;
case 2:
switch (role) {
case Qt::DisplayRole:
return QVariant();
case Qt::DecorationRole:
if (deque[index.row()].prefered) {
return Shared::icon("favorite", false);
}
return QVariant();
default:
return QVariant();
}
break;
default:
return QVariant();
}
}
return QVariant();
}
Qt::ItemFlags UI::VCard::EMailsModel::flags(const QModelIndex& index) const
{
Qt::ItemFlags f = QAbstractTableModel::flags(index);
if (edit && index.column() != 2) {
f = Qt::ItemIsEditable | f;
}
return f;
}
bool UI::VCard::EMailsModel::setData(const QModelIndex& index, const QVariant& value, int role)
{
if (role == Qt::EditRole && checkIndex(index)) {
Shared::VCard::Email& item = deque[index.row()];
switch (index.column()) {
case 0:
item.address = value.toString();
return true;
case 1: {
quint8 newRole = value.toUInt();
if (newRole > Shared::VCard::Email::work) {
return false;
}
item.role = static_cast<Shared::VCard::Email::Role>(newRole);
return true;
}
case 2: {
bool newDef = value.toBool();
if (newDef != item.prefered) {
if (newDef) {
//dropPrefered();
}
item.prefered = newDef;
return true;
}
}
}
return true;
}
return false;
}
bool UI::VCard::EMailsModel::dropPrefered()
{
bool dropped = false;
int i = 0;
for (Shared::VCard::Email& email : deque) {
if (email.prefered) {
email.prefered = false;
QModelIndex ci = createIndex(i, 2, &email);
emit dataChanged(ci, ci);
dropped = true;
}
++i;
}
return dropped;
}
QModelIndex UI::VCard::EMailsModel::addNewEmptyLine()
{
beginInsertRows(QModelIndex(), deque.size(), deque.size());
deque.emplace_back("");
endInsertRows();
return createIndex(deque.size() - 1, 0, &(deque.back()));
}
bool UI::VCard::EMailsModel::isPreferred(quint32 row) const
{
if (row < deque.size()) {
return deque[row].prefered;
} else {
return false;
}
}
void UI::VCard::EMailsModel::removeLines(quint32 index, quint32 count)
{
if (index < deque.size()) {
quint32 maxCount = deque.size() - index;
if (count > maxCount) {
count = maxCount;
}
if (count > 0) {
beginRemoveRows(QModelIndex(), index, index + count - 1);
std::deque<Shared::VCard::Email>::const_iterator itr = deque.begin() + index;
std::deque<Shared::VCard::Email>::const_iterator end = itr + count;
deque.erase(itr, end);
endRemoveRows();
}
}
}
void UI::VCard::EMailsModel::getEmails(std::deque<Shared::VCard::Email>& emails) const
{
for (const Shared::VCard::Email& my : deque) {
emails.emplace_back(my);
}
}
void UI::VCard::EMailsModel::setEmails(const std::deque<Shared::VCard::Email>& emails)
{
if (deque.size() > 0) {
removeLines(0, deque.size());
}
if (emails.size() > 0) {
beginInsertRows(QModelIndex(), 0, emails.size() - 1);
for (const Shared::VCard::Email& comming : emails) {
deque.emplace_back(comming);
}
endInsertRows();
}
}
void UI::VCard::EMailsModel::revertPreferred(quint32 row)
{
setData(createIndex(row, 2), !isPreferred(row));
}
QString UI::VCard::EMailsModel::getEmail(quint32 row) const
{
return deque[row].address;
}

View file

@ -1,64 +0,0 @@
/*
* 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_VCARD_EMAILSMODEL_H
#define UI_VCARD_EMAILSMODEL_H
#include <QAbstractTableModel>
#include <QIcon>
#include <deque>
#include "shared/vcard.h"
namespace UI {
namespace VCard {
class EMailsModel : public QAbstractTableModel
{
Q_OBJECT
public:
EMailsModel(bool edit = false, QObject *parent = nullptr);
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
int columnCount(const QModelIndex& parent = QModelIndex()) const override;
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
Qt::ItemFlags flags(const QModelIndex &index) const override;
bool isPreferred(quint32 row) const;
void removeLines(quint32 index, quint32 count);
void setEmails(const std::deque<Shared::VCard::Email>& emails);
void getEmails(std::deque<Shared::VCard::Email>& emails) const;
QString getEmail(quint32 row) const;
public slots:
QModelIndex addNewEmptyLine();
void revertPreferred(quint32 row);
private:
bool edit;
std::deque<Shared::VCard::Email> deque;
private:
bool dropPrefered();
};
}}
#endif // UI_VCARD_EMAILSMODEL_H

View file

@ -1,9 +0,0 @@
target_sources(squawk PRIVATE
omemo.cpp
omemo.h
omemo.ui
keysmodel.cpp
keysmodel.h
keydelegate.cpp
keydelegate.h
)

View file

@ -1,226 +0,0 @@
// 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 "keydelegate.h"
#include <QPainter>
#include <QDebug>
#include "keysmodel.h"
#include <shared/global.h>
constexpr uint8_t margin = 10;
constexpr uint8_t partSize = 8;
constexpr uint8_t maxSingleLineParts = 3;
UI::KeyDelegate::KeyDelegate(QObject* parent):
QStyledItemDelegate(parent),
defaultFont(Shared::Global::getInstance()->defaultFont),
fingerPrintFont(Shared::Global::getInstance()->monospaceFont),
labelFont(Shared::Global::getInstance()->smallFont),
defaultMetrics(Shared::Global::getInstance()->defaultFontMetrics),
fingerPrintMetrics(Shared::Global::getInstance()->monospaceMetrics),
labelMetrics(Shared::Global::getInstance()->smallFontMetrics),
spaceWidth(fingerPrintMetrics.horizontalAdvance(" "))
{}
UI::KeyDelegate::~KeyDelegate() {}
void UI::KeyDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const {
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();
painter->fillRect(option.rect, option.palette.brush(QPalette::Inactive, QPalette::Highlight));
painter->restore();
}
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();
}
rect.adjust(margin, margin, -margin, -margin);
QVariant labelV = index.data(UI::KeysModel::Label);
if (labelV.isValid()) {
QString label = labelV.toString();
if (label.size() > 0) {
painter->save();
painter->setFont(labelFont);
painter->setPen(q);
painter->drawText(rect, Qt::AlignLeft | Qt::AlignTop, label, &r);
rect.adjust(0, labelMetrics.lineSpacing(), 0, 0);
maxRight = std::max(r.width(), maxRight);
painter->restore();
}
}
QVariant fingerPrintV = index.data(UI::KeysModel::FingerPrint);
if (fingerPrintV.isValid()) {
painter->save();
painter->setFont(fingerPrintFont);
QByteArray fingerPrint = fingerPrintV.toByteArray();
std::vector<QString> parts = getParts(fingerPrint);
uint8_t partsLength = parts.size();
uint8_t firstLine;
if (partsLength > maxSingleLineParts)
firstLine = partsLength / 2 + partsLength % 2;
else
firstLine = partsLength;
for (uint8_t i = 0; i < partsLength; ++i) {
if (i == firstLine) {
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(leftOrigin);
painter->restore();
}
QVariant lastV = index.data(UI::KeysModel::LastInteraction);
if (lastV.isValid()) {
QDateTime last = lastV.toDateTime();
if (last.isValid()) {
painter->save();
painter->setFont(labelFont);
painter->setPen(q);
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();
}
}
QVariant levelV = index.data(UI::KeysModel::TrustLevel);
if (levelV.isValid()) {
Shared::TrustLevel level = static_cast<Shared::TrustLevel>(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();
}
QSize UI::KeyDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const {
QSize size = QStyledItemDelegate::sizeHint(option, index);
int mh = margin * 2;
int mw = margin * 2;
int width = 0;
QVariant labelV = index.data(UI::KeysModel::Label);
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);
if (fingerPrintV.isValid()) {
QString hex = fingerPrintV.toByteArray().toHex();
uint8_t parts = hex.size() / partSize;
mh += fingerPrintMetrics.height();
if (parts > maxSingleLineParts)
mh += fingerPrintMetrics.height() + fingerPrintMetrics.leading();
uint8_t firstLine;
if (parts > maxSingleLineParts)
firstLine = parts / 2 + parts % 2;
else
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()) {
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<Shared::TrustLevel>(levelV.toUInt());
QString levelName = Shared::Global::getName(level);
if (width > 0)
width += margin;
width += defaultMetrics.horizontalAdvance(levelName);
width += 1; //there is a mistake somewhere, this the cheapest way to compensate it
}
mw += width;
if (size.width() < mw)
size.setWidth(mw);
if (size.height() < mh)
size.setHeight(mh);
return size;
}
std::vector<QString> UI::KeyDelegate::getParts(const QByteArray& data) {
QString hex = data.toHex();
uint8_t parts = hex.size() / partSize;
std::vector<QString> result(parts);
for (uint8_t i = 0; i < parts; ++i) {
uint16_t index = i * partSize;
uint8_t length = partSize;
if (index + length > hex.size())
length = hex.size() - index;
QStringRef part(&hex, index, length);
result[i] = part.toString();
}
return result;
}

View file

@ -1,50 +0,0 @@
// 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_KEYDELEGATE_H
#define UI_KEYDELEGATE_H
#include <QStyledItemDelegate>
#include <QString>
#include <vector>
namespace UI {
class KeyDelegate : public QStyledItemDelegate
{
public:
KeyDelegate(QObject *parent = nullptr);
~KeyDelegate();
QSize sizeHint(const QStyleOptionViewItem & option, const QModelIndex & index) const override;
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& labelMetrics;
int spaceWidth;
private:
static std::vector<QString> getParts(const QByteArray& data);
};
}
#endif // UI_KEYDELEGATE_H

View file

@ -1,141 +0,0 @@
// 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(),
modified()
{
}
UI::KeysModel::~KeysModel() {
for (Shared::KeyInfo* key : keys) {
delete key;
}
for (std::pair<const int, Shared::KeyInfo*>& pair: modified) {
delete pair.second;
}
}
std::deque<Shared::KeyInfo> UI::KeysModel::modifiedKeys() const {
std::deque<Shared::KeyInfo> response(modified.size());
int i = 0;
for (const std::pair<const int, Shared::KeyInfo*>& pair: modified) {
response[i] = *(pair.second);
++i;
}
return response;
}
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();
const Shared::KeyInfo* info;
bool dirty;
std::map<int, Shared::KeyInfo*>::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 = info->label;
break;
case FingerPrint:
answer = info->fingerPrint;
break;
case TrustLevel:
answer = static_cast<uint8_t>(info->trustLevel);
break;
case LastInteraction:
answer = info->lastInteraction;
break;
case Dirty:
answer = dirty;
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]);
}
void UI::KeysModel::revertKey(int row) {
std::map<int, Shared::KeyInfo*>::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<int, Shared::KeyInfo*>::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});
}

View file

@ -1,67 +0,0 @@
// 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;
std::deque<Shared::KeyInfo> modifiedKeys() const;
enum Roles {
Label = Qt::UserRole + 1,
FingerPrint,
TrustLevel,
LastInteraction,
Dirty
};
public slots:
void revertKey(int index);
void setTrustLevel(int index, Shared::TrustLevel level);
private:
std::deque<Shared::KeyInfo*> keys;
std::map<int, Shared::KeyInfo*> modified;
private:
static const QHash<int, QByteArray> roles;
};
}
#endif // UI_KEYSMODEL_H

View file

@ -1,111 +0,0 @@
// 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 "omemo.h"
#include "ui_omemo.h"
#include <random>
constexpr uint8_t fingerprintLength = 32;
Omemo::Omemo(QWidget* parent):
QWidget(parent),
m_ui(new Ui::Omemo()),
keysDelegate(),
unusedKeysDelegate(),
keysModel(),
unusedKeysModel(),
contextMenu(new QMenu())
{
m_ui->setupUi(this);
generateMockData();
m_ui->keysView->setItemDelegate(&keysDelegate);
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() {
std::random_device rd;
std::uniform_int_distribution<char> dist(CHAR_MIN, CHAR_MAX);
for (int i = 0; i < 5; ++i) {
QByteArray fp(fingerprintLength, 0);
for (int i = 0; i < fingerprintLength; ++i) {
fp[i] = dist(rd);
}
Shared::KeyInfo info;
info.id = i;
if (i % 3 == 0)
info.label = QString("test_") + std::to_string(i).c_str();
info.fingerPrint = fp;
if (i % 2 == 0)
info.lastInteraction = QDateTime::currentDateTime();
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<Shared::TrustLevel>(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));
}

View file

@ -1,54 +0,0 @@
// 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 VCARD_OMEMO_H
#define VCARD_OMEMO_H
#include <QWidget>
#include <QScopedPointer>
#include <QMenu>
#include "keysmodel.h"
#include "keydelegate.h"
#include "shared/icons.h"
namespace Ui
{
class Omemo;
}
class Omemo : public QWidget {
Q_OBJECT
public:
Omemo(QWidget* parent = nullptr);
~Omemo();
private slots:
void onActiveKeysContextMenu(const QPoint& pos);
private:
void generateMockData();
private:
QScopedPointer<Ui::Omemo> m_ui;
UI::KeyDelegate keysDelegate;
UI::KeyDelegate unusedKeysDelegate;
UI::KeysModel keysModel;
UI::KeysModel unusedKeysModel;
QMenu* contextMenu;
};
#endif // VCARD_OMEMO_H

View file

@ -1,194 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Omemo</class>
<widget class="QWidget" name="Omemo">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>473</width>
<height>657</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="OMEMOHeading">
<property name="font">
<font>
<pointsize>24</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>OMEMO</string>
</property>
</widget>
</item>
<item>
<widget class="QScrollArea" name="scrollArea">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>473</width>
<height>592</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout" columnstretch="1,3,1">
<item row="1" column="1">
<widget class="ExpandingList" name="keysView">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="sizeAdjustPolicy">
<enum>QAbstractScrollArea::AdjustToContents</enum>
</property>
<property name="showDropIndicator" stdset="0">
<bool>false</bool>
</property>
<property name="verticalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
<property name="horizontalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
<property name="uniformItemSizes">
<bool>false</bool>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="keysHeading">
<property name="font">
<font>
<pointsize>16</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Active keys</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLabel" name="unusedKeysHeading">
<property name="font">
<font>
<pointsize>16</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Unused keys</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="ExpandingList" name="unusedKeysView">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="sizeAdjustPolicy">
<enum>QAbstractScrollArea::AdjustToContents</enum>
</property>
<property name="showDropIndicator" stdset="0">
<bool>false</bool>
</property>
<property name="verticalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
<property name="horizontalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
<property name="uniformItemSizes">
<bool>false</bool>
</property>
</widget>
</item>
<item row="0" column="0" rowspan="6">
<spacer name="spacerLeft">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="2" rowspan="6">
<spacer name="spacerRight">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>ExpandingList</class>
<extends>QListView</extends>
<header location="global">ui/utils/expandinglist.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View file

@ -1,225 +0,0 @@
/*
* 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 "phonesmodel.h"
#include "shared/icons.h"
#include <QCoreApplication>
UI::VCard::PhonesModel::PhonesModel(bool p_edit, QObject* parent):
QAbstractTableModel(parent),
edit(p_edit),
deque()
{
}
int UI::VCard::PhonesModel::columnCount(const QModelIndex& parent) const
{
return 4;
}
int UI::VCard::PhonesModel::rowCount(const QModelIndex& parent) const
{
return deque.size();
}
QVariant UI::VCard::PhonesModel::data(const QModelIndex& index, int role) const
{
if (index.isValid()) {
int col = index.column();
switch (col) {
case 0:
switch (role) {
case Qt::DisplayRole:
case Qt::EditRole:
return deque[index.row()].number;
default:
return QVariant();
}
break;
case 1:
switch (role) {
case Qt::DisplayRole:
return QCoreApplication::translate("Global", Shared::VCard::Phone::roleNames[deque[index.row()].role].toStdString().c_str());
case Qt::EditRole:
return deque[index.row()].role;
default:
return QVariant();
}
break;
case 2:
switch (role) {
case Qt::DisplayRole:
return QCoreApplication::translate("Global", Shared::VCard::Phone::typeNames[deque[index.row()].type].toStdString().c_str());
case Qt::EditRole:
return deque[index.row()].type;
default:
return QVariant();
}
break;
case 3:
switch (role) {
case Qt::DisplayRole:
return QVariant();
case Qt::DecorationRole:
if (deque[index.row()].prefered) {
return Shared::icon("favorite", false);
}
return QVariant();
default:
return QVariant();
}
break;
default:
return QVariant();
}
}
return QVariant();
}
QModelIndex UI::VCard::PhonesModel::addNewEmptyLine()
{
beginInsertRows(QModelIndex(), deque.size(), deque.size());
deque.emplace_back("", Shared::VCard::Phone::other);
endInsertRows();
return createIndex(deque.size() - 1, 0, &(deque.back()));
}
Qt::ItemFlags UI::VCard::PhonesModel::flags(const QModelIndex& index) const
{
Qt::ItemFlags f = QAbstractTableModel::flags(index);
if (edit && index.column() != 3) {
f = Qt::ItemIsEditable | f;
}
return f;
}
bool UI::VCard::PhonesModel::dropPrefered()
{
bool dropped = false;
int i = 0;
for (Shared::VCard::Phone& phone : deque) {
if (phone.prefered) {
phone.prefered = false;
QModelIndex ci = createIndex(i, 2, &phone);
emit dataChanged(ci, ci);
dropped = true;
}
++i;
}
return dropped;
}
void UI::VCard::PhonesModel::getPhones(std::deque<Shared::VCard::Phone>& phones) const
{
for (const Shared::VCard::Phone& my : deque) {
phones.emplace_back(my);
}
}
bool UI::VCard::PhonesModel::isPreferred(quint32 row) const
{
if (row < deque.size()) {
return deque[row].prefered;
} else {
return false;
}
}
void UI::VCard::PhonesModel::removeLines(quint32 index, quint32 count)
{
if (index < deque.size()) {
quint32 maxCount = deque.size() - index;
if (count > maxCount) {
count = maxCount;
}
if (count > 0) {
beginRemoveRows(QModelIndex(), index, index + count - 1);
std::deque<Shared::VCard::Phone>::const_iterator itr = deque.begin() + index;
std::deque<Shared::VCard::Phone>::const_iterator end = itr + count;
deque.erase(itr, end);
endRemoveRows();
}
}
}
void UI::VCard::PhonesModel::revertPreferred(quint32 row)
{
setData(createIndex(row, 3), !isPreferred(row));
}
bool UI::VCard::PhonesModel::setData(const QModelIndex& index, const QVariant& value, int role)
{
if (role == Qt::EditRole && checkIndex(index)) {
Shared::VCard::Phone& item = deque[index.row()];
switch (index.column()) {
case 0:
item.number = value.toString();
return true;
case 1: {
quint8 newRole = value.toUInt();
if (newRole > Shared::VCard::Phone::work) {
return false;
}
item.role = static_cast<Shared::VCard::Phone::Role>(newRole);
return true;
}
case 2: {
quint8 newType = value.toUInt();
if (newType > Shared::VCard::Phone::other) {
return false;
}
item.type = static_cast<Shared::VCard::Phone::Type>(newType);
return true;
}
case 3: {
bool newDef = value.toBool();
if (newDef != item.prefered) {
if (newDef) {
//dropPrefered();
}
item.prefered = newDef;
return true;
}
}
}
return true;
}
return false;
}
void UI::VCard::PhonesModel::setPhones(const std::deque<Shared::VCard::Phone>& phones)
{
if (deque.size() > 0) {
removeLines(0, deque.size());
}
if (phones.size() > 0) {
beginInsertRows(QModelIndex(), 0, phones.size() - 1);
for (const Shared::VCard::Phone& comming : phones) {
deque.emplace_back(comming);
}
endInsertRows();
}
}
QString UI::VCard::PhonesModel::getPhone(quint32 row) const
{
return deque[row].number;
}

View file

@ -1,65 +0,0 @@
/*
* 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_VCARD_PHONESMODEL_H
#define UI_VCARD_PHONESMODEL_H
#include <QAbstractTableModel>
#include <QIcon>
#include "shared/vcard.h"
namespace UI {
namespace VCard {
/**
* @todo write docs
*/
class PhonesModel : public QAbstractTableModel
{
Q_OBJECT
public:
PhonesModel(bool edit = false, QObject *parent = nullptr);
QVariant data(const QModelIndex& index, int role) const override;
int columnCount(const QModelIndex& parent) const override;
int rowCount(const QModelIndex& parent) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
Qt::ItemFlags flags(const QModelIndex &index) const override;
bool isPreferred(quint32 row) const;
void removeLines(quint32 index, quint32 count);
void setPhones(const std::deque<Shared::VCard::Phone>& phones);
void getPhones(std::deque<Shared::VCard::Phone>& phones) const;
QString getPhone(quint32 row) const;
public slots:
QModelIndex addNewEmptyLine();
void revertPreferred(quint32 row);
private:
bool edit;
std::deque<Shared::VCard::Phone> deque;
private:
bool dropPrefered();
};
}}
#endif // UI_VCARD_PHONESMODEL_H

View file

@ -235,10 +235,10 @@ void VCard::onContextMenu(const QPoint& point) {
int row = sm->selectedRows().at(0).row();
if (emails.isPreferred(row)) {
QAction* rev = contextMenu->addAction(Shared::icon("unfavorite"), tr("Unset this email as preferred"));
connect(rev, &QAction::triggered, std::bind(&UI::VCard::EMailsModel::revertPreferred, &emails, row));
connect(rev, &QAction::triggered, std::bind(&Models::EMails::revertPreferred, &emails, row));
} else {
QAction* rev = contextMenu->addAction(Shared::icon("favorite"), tr("Set this email as preferred"));
connect(rev, &QAction::triggered, std::bind(&UI::VCard::EMailsModel::revertPreferred, &emails, row));
connect(rev, &QAction::triggered, std::bind(&Models::EMails::revertPreferred, &emails, row));
}
}
@ -263,10 +263,10 @@ void VCard::onContextMenu(const QPoint& point) {
int row = sm->selectedRows().at(0).row();
if (phones.isPreferred(row)) {
QAction* rev = contextMenu->addAction(Shared::icon("view-media-favorite"), tr("Unset this phone as preferred"));
connect(rev, &QAction::triggered, std::bind(&UI::VCard::PhonesModel::revertPreferred, &phones, row));
connect(rev, &QAction::triggered, std::bind(&Models::Phones::revertPreferred, &phones, row));
} else {
QAction* rev = contextMenu->addAction(Shared::icon("favorite"), tr("Set this phone as preferred"));
connect(rev, &QAction::triggered, std::bind(&UI::VCard::PhonesModel::revertPreferred, &phones, row));
connect(rev, &QAction::triggered, std::bind(&Models::Phones::revertPreferred, &phones, row));
}
}

View file

@ -37,13 +37,13 @@
#include <set>
#include "shared/vcard.h"
#include "emailsmodel.h"
#include "phonesmodel.h"
#include "ui/models/info/emails.h"
#include "ui/models/info/phones.h"
#include "ui/utils/progress.h"
#include "ui/utils/comboboxdelegate.h"
#ifdef WITH_OMEMO
#include "omemo/omemo.h"
#include "ui/widgets/info/omemo/omemo.h"
#endif
namespace Ui
@ -92,8 +92,8 @@ private:
QLabel* progressLabel;
QWidget* overlay;
QMenu* contextMenu;
UI::VCard::EMailsModel emails;
UI::VCard::PhonesModel phones;
Models::EMails emails;
Models::Phones phones;
ComboboxDelegate* roleDelegate;
ComboboxDelegate* phoneTypeDelegate;
#ifdef WITH_OMEMO