started refactoring of the VCard UI
This commit is contained in:
parent
bb304ce774
commit
4af16b75bf
32 changed files with 1250 additions and 166 deletions
|
@ -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()
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -1,9 +0,0 @@
|
|||
target_sources(squawk PRIVATE
|
||||
omemo.cpp
|
||||
omemo.h
|
||||
omemo.ui
|
||||
keysmodel.cpp
|
||||
keysmodel.h
|
||||
keydelegate.cpp
|
||||
keydelegate.h
|
||||
)
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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});
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -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
|
|
@ -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));
|
||||
}
|
|
@ -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
|
|
@ -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>
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue