diff --git a/core/account.cpp b/core/account.cpp index 96ca4e1..a71bf4a 100644 --- a/core/account.cpp +++ b/core/account.cpp @@ -141,14 +141,13 @@ Core::Account::Account( loadingOmemo = true; future.then(this, [this] (bool result) { loadingOmemo = false; - if (state == Shared::ConnectionState::scheduled) { + if (state == Shared::ConnectionState::scheduled) client.connectToServer(config, presence); - } - if (result) { + + if (result) qDebug() << "successfully loaded OMEMO data for account" << getName(); - } else { + else qDebug() << "couldn't load OMEMO data for account" << getName(); - } }); } #endif diff --git a/core/components/archive.cpp b/core/components/archive.cpp index 003cce6..67f6693 100644 --- a/core/components/archive.cpp +++ b/core/components/archive.cpp @@ -30,7 +30,7 @@ Core::Archive::Archive(const QString& account, const QString& p_jid, QObject* pa opened(false), db(account + "/" + jid), messages(db.addStorage("messages")), - order(db.addStorage("order")), + order(db.addStorage("order", true)), stats(db.addStorage("stats")), avatars(db.addStorage("avatars")), stanzaIdToId(db.addStorage("stanzaIdToId")), diff --git a/core/handlers/messagehandler.cpp b/core/handlers/messagehandler.cpp index 2a546e9..0d0c446 100644 --- a/core/handlers/messagehandler.cpp +++ b/core/handlers/messagehandler.cpp @@ -51,8 +51,7 @@ void Core::MessageHandler::onMessageReceived(const QXmppMessage& msg) { qDebug() << "Account" << acc->getName() << "received an Omemo1 encrypted message, not supported yet"; break; //let it go the way it is, there is nothing I can do yet case QXmpp::Omemo2: - qDebug() << "Account" << acc->getName() << "received an Omemo2 encrypted message, not supported yet"; - break; //let it go the way it is, there is nothing I can do yet + break; } #endif #endif @@ -359,6 +358,8 @@ std::pair Core::MessageHandler::scheduleSending const QXmppE2eeExtension::MessageEncryptResult& res = task.result(); if (std::holds_alternative>(res)) { const std::unique_ptr& encrypted = std::get>(res); + encrypted->setBody("This message is encrypted with OMEMO 2 but could not be decrypted"); + encrypted->setOutOfBandUrl(""); bool success = acc->client.sendPacket(*encrypted.get()); if (success) return {Shared::Message::State::sent, ""}; @@ -375,6 +376,7 @@ std::pair Core::MessageHandler::scheduleSending if (std::holds_alternative>(result)) { const std::unique_ptr& encrypted = std::get>(result); encrypted->setBody("This message is encrypted with OMEMO 2 but could not be decrypted"); + encrypted->setOutOfBandUrl(""); bool success = acc->client.sendPacket(*encrypted.get()); if (success) { std::tuple ids = getOriginalPendingMessageId(id, false); diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index b5bc725..e92710f 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -11,7 +11,4 @@ set(HEADER_FILES root.h ) -target_sources(squawk PRIVATE - ${SOURCE_FILES} - ${HEADER_FILES} -) +target_sources(squawk PRIVATE ${SOURCE_FILES}) diff --git a/shared/CMakeLists.txt b/shared/CMakeLists.txt index 4ba24ea..2ef3970 100644 --- a/shared/CMakeLists.txt +++ b/shared/CMakeLists.txt @@ -18,7 +18,6 @@ set(SOURCE_FILES ) set(HEADER_FILES - order.h shared.h enums.h global.h diff --git a/shared/order.h b/shared/order.h deleted file mode 100644 index fa9379b..0000000 --- a/shared/order.h +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Squawk messenger. - * Copyright (C) 2019 Yury Gubich - * - * 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 . - */ - -#ifndef ORDER_H -#define ORDER_H - -#include -#include - -#include "exception.h" - -namespace W -{ - template > - class Order - { - public: - class Duplicates: - public Utils::Exception - { - public: - Duplicates():Exception(){} - - std::string getMessage() const{return "Inserting element duplicates existing";} - }; - - class NotFound: - public Utils::Exception - { - public: - NotFound():Exception(){} - - std::string getMessage() const{return "Erasing element haven't been found";} - }; - - protected: - typedef std::list List; - - public: - typedef typename List::size_type size_type; - typedef typename List::const_iterator const_iterator; - typedef typename List::iterator iterator; - - protected: - typedef std::map Map; - typedef typename Map::const_iterator m_const_itr; - typedef typename Map::iterator m_itr; - - public: - Order(): - order(), - r_map() - {} - ~Order() {}; - - size_type size() const { - return order.size(); - } - - void push_back(data_type element) { - m_const_itr m_itr = r_map.find(element); - if (m_itr != r_map.end()) { - throw Duplicates(); - } - - const_iterator itr = order.insert(order.end(), element); - r_map.insert(std::make_pair(element, itr)); - } - - void erase(data_type element) { - m_const_itr itr = r_map.find(element); - if (itr == r_map.end()) { - throw NotFound(); - } - order.erase(itr->second); - r_map.erase(itr); - - } - - void clear() { - order.clear(); - r_map.clear(); - } - - void insert(const_iterator pos, data_type element) { - m_const_itr m_itr = r_map.find(element); - if (m_itr != r_map.end()) { - throw Duplicates(); - } - - const_iterator itr = order.insert(pos, element); - r_map.insert(std::make_pair(element, itr)); - } - - void insert(iterator pos, data_type element) { - m_const_itr m_itr = r_map.find(element); - if (m_itr != r_map.end()) { - throw Duplicates(); - } - - const_iterator itr = order.insert(pos, element); - r_map.insert(std::make_pair(element, itr)); - } - - const_iterator find(data_type element) const { - m_const_itr itr = r_map.find(element); - - if (itr == r_map.end()) { - return end(); - } else { - return itr->second; - } - } - - const_iterator begin() const { - return order.begin(); - } - - const_iterator end() const { - return order.end(); - } - - iterator begin() { - return order.begin(); - } - - iterator end() { - return order.end(); - } - - private: - List order; - Map r_map; - }; -} - - - -#endif // ORDER_H diff --git a/ui/utils/badge.cpp b/ui/utils/badge.cpp index b3b321a..d65b957 100644 --- a/ui/utils/badge.cpp +++ b/ui/utils/badge.cpp @@ -18,6 +18,8 @@ #include "badge.h" +#include "shared/utils.h" + Badge::Badge(const QString& p_id, const QString& p_text, const QIcon& icon, QWidget* parent): QFrame(parent), id(p_id), @@ -48,8 +50,7 @@ Badge::Badge(QWidget* parent): layout->addWidget(closeButton); } -void Badge::setIcon(const QIcon& icon) -{ +void Badge::setIcon(const QIcon& icon) { if (image == nullptr) { image = new QLabel(); image->setPixmap(icon.pixmap(25, 25)); @@ -59,8 +60,7 @@ void Badge::setIcon(const QIcon& icon) } } -void Badge::setText(const QString& p_text) -{ +void Badge::setText(const QString& p_text) { if (text == nullptr) { text = new QLabel(p_text); int index = 0; @@ -73,42 +73,30 @@ void Badge::setText(const QString& p_text) } } -Badge::~Badge() -{ - if (image != nullptr) { +Badge::~Badge() { + if (image != nullptr) delete image; - } - if (text != nullptr) { + + if (text != nullptr) delete text; - } + delete closeButton; } -bool Badge::Comparator::operator()(const Badge* a, const Badge* b) const -{ - return a->id < b->id; -} - -bool Badge::Comparator::operator()(const Badge& a, const Badge& b) const -{ - return a.id < b.id; -} - -void Badge::createMandatoryComponents() -{ +void Badge::createMandatoryComponents() { setBackgroundRole(QPalette::Base); //setAutoFillBackground(true); setFrameStyle(QFrame::StyledPanel); setFrameShadow(QFrame::Raised); QIcon tabCloseIcon = QIcon::fromTheme("tab-close"); - if (tabCloseIcon.isNull()) { + if (tabCloseIcon.isNull()) tabCloseIcon.addFile(QString::fromUtf8(":/images/fallback/dark/big/edit-none.svg"), QSize(), QIcon::Normal, QIcon::Off); - } + closeButton->setIcon(tabCloseIcon); closeButton->setMaximumHeight(25); closeButton->setMaximumWidth(25); layout->setContentsMargins(2, 2, 2, 2); - connect(closeButton, &QPushButton::clicked, this, &Badge::close); + connect(closeButton, &QPushButton::clicked, this, &Badge::closeClicked); } diff --git a/ui/utils/badge.h b/ui/utils/badge.h index 52f4747..074eda0 100644 --- a/ui/utils/badge.h +++ b/ui/utils/badge.h @@ -16,8 +16,7 @@ * along with this program. If not, see . */ -#ifndef BADGE_H -#define BADGE_H +#pragma once #include #include @@ -25,13 +24,7 @@ #include #include -#include "shared/utils.h" - -/** - * @todo write docs - */ -class Badge : public QFrame -{ +class Badge : public QFrame { Q_OBJECT public: Badge(const QString& id, const QString& text, const QIcon& icon, QWidget* parent = nullptr); @@ -45,7 +38,7 @@ public: void setIcon(const QIcon& icon); signals: - void close(); + void closeClicked(); private: QLabel* image; @@ -55,12 +48,5 @@ private: private: void createMandatoryComponents(); - -public: - struct Comparator { - bool operator()(const Badge& a, const Badge& b) const; - bool operator()(const Badge* a, const Badge* b) const; - }; -}; -#endif // BADGE_H +}; diff --git a/ui/utils/flowlayout.h b/ui/utils/flowlayout.h index 0e52c87..24830e7 100644 --- a/ui/utils/flowlayout.h +++ b/ui/utils/flowlayout.h @@ -16,8 +16,7 @@ * along with this program. If not, see . */ -#ifndef FLOWLAYOUT_H -#define FLOWLAYOUT_H +#pragma once #include #include @@ -26,8 +25,7 @@ /** * @todo write docs */ -class FlowLayout : public QLayout -{ +class FlowLayout : public QLayout { Q_OBJECT public: explicit FlowLayout(QWidget *parent, int margin = -1, int hSpacing = -1, int vSpacing = -1); @@ -55,5 +53,3 @@ private: int m_hSpace; int m_vSpace; }; - -#endif // FLOWLAYOUT_H diff --git a/ui/widgets/conversation.cpp b/ui/widgets/conversation.cpp index 32c38a8..7214a40 100644 --- a/ui/widgets/conversation.cpp +++ b/ui/widgets/conversation.cpp @@ -33,6 +33,12 @@ #include #include +#include + +#include "shared/icons.h" +#include "shared/utils.h" +#include "shared/pathcheck.h" +#include "shared/defines.h" constexpr QSize avatarSize(50, 50); @@ -61,58 +67,9 @@ Conversation::Conversation(bool muc, Models::Account* acc, Models::Element* el, currentAction(CurrentAction::none), currentMessageId() { - m_ui->setupUi(this); - - shadow.setFrames(true, false, true, false); - - feed->setItemDelegate(delegate); - feed->setFrameShape(QFrame::NoFrame); - feed->setContextMenuPolicy(Qt::CustomContextMenu); - feed->setModel(el->feed); - el->feed->incrementObservers(); - m_ui->widget->layout()->addWidget(feed); - - connect(el->feed, &Models::MessageFeed::newMessage, this, &Conversation::onFeedMessage); - connect(feed, &FeedView::resized, this, &Conversation::positionShadow); - connect(feed, &FeedView::customContextMenuRequested, this, &Conversation::onFeedContext); - - connect(acc, &Models::Account::childChanged, this, &Conversation::onAccountChanged); - - filesLayout = new FlowLayout(m_ui->filesPanel, 0); - m_ui->filesPanel->setLayout(filesLayout); - - statusIcon = m_ui->statusIcon; - statusLabel = m_ui->statusLabel; - - connect(&ker, &KeyEnterReceiver::enterPressed, this, qOverload<>(&Conversation::initiateMessageSending)); - connect(&ker, &KeyEnterReceiver::imagePasted, this, &Conversation::onImagePasted); - connect(m_ui->sendButton, &QPushButton::clicked, this, qOverload<>(&Conversation::initiateMessageSending)); - connect(m_ui->attachButton, &QPushButton::clicked, this, &Conversation::onAttach); - connect(m_ui->clearButton, &QPushButton::clicked, this, &Conversation::clear); - connect(m_ui->messageEditor->document()->documentLayout(), &QAbstractTextDocumentLayout::documentSizeChanged, - this, &Conversation::onTextEditDocSizeChanged); - connect(m_ui->encryptionButton, &QPushButton::clicked, this, &Conversation::onEncryptionButtonClicked); - - m_ui->messageEditor->installEventFilter(&ker); - - connect(m_ui->messageEditor, &QTextEdit::customContextMenuRequested, this, &Conversation::onMessageEditorContext); - connect(pasteImageAction, &QAction::triggered, this, &Conversation::onImagePasted); - - connect(m_ui->currentActionBadge, &Badge::close, this, &Conversation::clear); - m_ui->currentActionBadge->setVisible(false); - - m_ui->encryptionButton->setVisible(false); - - //line->setAutoFillBackground(false); - //if (testAttribute(Qt::WA_TranslucentBackground)) { - //m_ui->scrollArea->setAutoFillBackground(false); - //} else { - //m_ui->scrollArea->setBackgroundRole(QPalette::Base); - //} - - //line->setMyAvatarPath(acc->getAvatarPath()); - //line->setMyName(acc->getName()); - + createUI(); + createFeed(); + subscribeEvents(); initializeOverlay(); } @@ -123,6 +80,52 @@ Conversation::~Conversation() { delete m_ui; } +void Conversation::createFeed() { + feed->setItemDelegate(delegate); + feed->setFrameShape(QFrame::NoFrame); + feed->setContextMenuPolicy(Qt::CustomContextMenu); + feed->setModel(element->feed); + element->feed->incrementObservers(); + m_ui->widget->layout()->addWidget(feed); + + connect(element->feed, &Models::MessageFeed::newMessage, this, &Conversation::onFeedMessage); + connect(feed, &FeedView::resized, this, &Conversation::positionShadow); + connect(feed, &FeedView::customContextMenuRequested, this, &Conversation::onFeedContext); +} + +void Conversation::createUI() { + m_ui->setupUi(this); + statusIcon = m_ui->statusIcon; + statusLabel = m_ui->statusLabel; + + filesLayout = new FlowLayout(m_ui->filesPanel, 0); + m_ui->filesPanel->setLayout(filesLayout); + + m_ui->currentActionBadge->setVisible(false); + m_ui->encryptionButton->setVisible(false); + + shadow.setFrames(true, false, true, false); +} + +void Conversation::subscribeEvents() { + connect(account, &Models::Account::childChanged, this, &Conversation::onAccountChanged); + connect(&ker, &KeyEnterReceiver::enterPressed, this, qOverload<>(&Conversation::initiateMessageSending)); + connect(&ker, &KeyEnterReceiver::imagePasted, this, &Conversation::onImagePasted); + connect(m_ui->sendButton, &QPushButton::clicked, this, qOverload<>(&Conversation::initiateMessageSending)); + connect(m_ui->attachButton, &QPushButton::clicked, this, &Conversation::onAttach); + connect(m_ui->clearButton, &QPushButton::clicked, this, &Conversation::clear); + connect(m_ui->messageEditor->document()->documentLayout(), &QAbstractTextDocumentLayout::documentSizeChanged, + this, &Conversation::onTextEditDocSizeChanged); + connect(m_ui->encryptionButton, &QPushButton::clicked, this, &Conversation::onEncryptionButtonClicked); + + m_ui->messageEditor->installEventFilter(&ker); + + connect(m_ui->messageEditor, &QTextEdit::customContextMenuRequested, this, &Conversation::onMessageEditorContext); + connect(pasteImageAction, &QAction::triggered, this, &Conversation::onImagePasted); + + connect(m_ui->currentActionBadge, &Badge::closeClicked, this, &Conversation::clear); +} + void Conversation::onAccountChanged(Models::Item* item, int row, int col) { SHARED_UNUSED(row); if (item == account) { @@ -228,7 +231,7 @@ void Conversation::initiateMessageSending() { initiateMessageSending(msg); } if (filesToAttach.size() > 0) { - for (Badge* badge : filesToAttach) { + for (const Badge* badge : filesToAttach) { Shared::Message msg = createMessage(); msg.setAttachPath(badge->id); element->feed->registerUpload(msg.getId()); @@ -291,6 +294,14 @@ Models::Roster::ElId Conversation::getId() const { } void Conversation::addAttachedFile(const QString& path) { + std::vector::const_iterator itr = std::find_if( + filesToAttach.begin(), + filesToAttach.end(), + [&path] (const Badge* badge) {return badge->id == path;} + ); + if (itr != filesToAttach.end()) + return; + QMimeDatabase db; QMimeType type = db.mimeTypeForFile(path); QFileInfo info(path); @@ -300,25 +311,23 @@ void Conversation::addAttachedFile(const QString& path) { fileIcon.addFile(QString::fromUtf8(":/images/fallback/dark/big/mail-attachment.svg"), QSize(), QIcon::Normal, QIcon::Off); Badge* badge = new Badge(path, info.fileName(), fileIcon); + filesToAttach.push_back(badge); - connect(badge, &Badge::close, this, &Conversation::onBadgeClose); - try { - filesToAttach.push_back(badge); - filesLayout->addWidget(badge); - if (filesLayout->count() == 1) { - filesLayout->setContentsMargins(3, 3, 3, 3); - } - } catch (const W::Order::Duplicates& e) { - delete badge; - } catch (...) { - throw; - } + connect(badge, &Badge::closeClicked, this, &Conversation::onBadgeClose); + filesLayout->addWidget(badge); + if (filesLayout->count() == 1) + filesLayout->setContentsMargins(3, 3, 3, 3); } -void Conversation::removeAttachedFile(Badge* badge) { - W::Order::const_iterator itr = filesToAttach.find(badge); +void Conversation::removeAttachedFile(const QString& id) { + std::vector::const_iterator itr = std::find_if( + filesToAttach.begin(), + filesToAttach.end(), + [&id] (const Badge* badge) {return badge->id == id;} + ); if (itr != filesToAttach.end()) { - filesToAttach.erase(badge); + Badge* badge = *itr; + filesToAttach.erase(itr); if (filesLayout->count() == 1) filesLayout->setContentsMargins(0, 0, 0, 0); @@ -328,7 +337,7 @@ void Conversation::removeAttachedFile(Badge* badge) { void Conversation::onBadgeClose() { Badge* badge = static_cast(sender()); - removeAttachedFile(badge); + removeAttachedFile(badge->id); } void Conversation::clearAttachedFiles() { @@ -351,12 +360,10 @@ void Conversation::onEncryptionButtonClicked() {} void Conversation::setAvatar(const QString& path) { QPixmap pixmap; - if (path.size() == 0) { + if (path.size() == 0) pixmap = Shared::icon("user", true).pixmap(avatarSize); - } else { + else pixmap = QPixmap(path).scaled(avatarSize, Qt::KeepAspectRatio, Qt::SmoothTransformation); - } - QPixmap result(avatarSize); result.fill(Qt::transparent); @@ -379,8 +386,7 @@ void Conversation::setFeedFrames(bool top, bool right, bool bottom, bool left) { shadow.setFrames(top, right, bottom, left); } -void Conversation::dragEnterEvent(QDragEnterEvent* event) -{ +void Conversation::dragEnterEvent(QDragEnterEvent* event) { bool accept = false; if (event->mimeData()->hasUrls()) { QList list = event->mimeData()->urls(); @@ -542,9 +548,8 @@ void Conversation::onMessageEditRequested(const QString& id) { currentAction = CurrentAction::edit; m_ui->messageEditor->setText(msg.getBody()); QString path = msg.getAttachPath(); - if (path.size() > 0) { + if (path.size() > 0) addAttachedFile(path); - } } catch (const Models::MessageFeed::NotFound& e) { qDebug() << "The message requested to be edited was not found" << e.getMessage().c_str(); diff --git a/ui/widgets/conversation.h b/ui/widgets/conversation.h index 73e6536..bece7a8 100644 --- a/ui/widgets/conversation.h +++ b/ui/widgets/conversation.h @@ -16,8 +16,7 @@ * along with this program. If not, see . */ -#ifndef CONVERSATION_H -#define CONVERSATION_H +#pragma once #include #include @@ -30,12 +29,9 @@ #include #include +#include + #include "shared/message.h" -#include "shared/order.h" -#include "shared/icons.h" -#include "shared/utils.h" -#include "shared/pathcheck.h" -#include "shared/defines.h" #include "ui/models/account.h" #include "ui/models/roster.h" @@ -96,7 +92,7 @@ protected: virtual Shared::Message createMessage() const; void setStatus(const QString& status); void addAttachedFile(const QString& path); - void removeAttachedFile(Badge* badge); + void removeAttachedFile(const QString& id); void clearAttachedFiles(); void dragEnterEvent(QDragEnterEvent* event) override; void dragLeaveEvent(QDragLeaveEvent* event) override; @@ -104,6 +100,10 @@ protected: void initializeOverlay(); virtual void onMessage(const Shared::Message& msg); virtual void showEvent(QShowEvent * event) override; + + void createFeed(); + void createUI(); + void subscribeEvents(); protected slots: void initiateMessageSending(); @@ -142,7 +142,7 @@ protected: QLabel* statusLabel; FlowLayout* filesLayout; QWidget* overlay; - W::Order filesToAttach; + std::vector filesToAttach; FeedView* feed; MessageDelegate* delegate; bool manualSliderChange; @@ -161,5 +161,3 @@ private: static QPixmap* avatarPixmap; static QPainter* avatarPainter; }; - -#endif // CONVERSATION_H diff --git a/ui/widgets/room.cpp b/ui/widgets/room.cpp index 3409a86..56ce5a0 100644 --- a/ui/widgets/room.cpp +++ b/ui/widgets/room.cpp @@ -18,6 +18,8 @@ #include "room.h" +#include "shared/defines.h" + Room::Room(Models::Account* acc, Models::Room* p_room, QWidget* parent): Conversation(true, acc, p_room, p_room->getJid(), "", parent), room(p_room)