diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b1d75a..8a6fdfa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,11 +6,13 @@ - build now correctly installs all build plugin libs ### Improvements +- reduced amount of places where platform specific path separator is used ### New features - the settings are here! You con config different stuff from there - now it's possible to set up different qt styles from settings - if you have KConfig nad KConfigWidgets packages installed - you can chose from global color schemes +- it's possible now to chose a folder where squawk is going to store downloaded files ## Squawk 0.2.0 (Jan 10, 2022) ### Bug fixes diff --git a/ui/utils/badge.cpp b/ui/utils/badge.cpp index 7575afc..b3b321a 100644 --- a/ui/utils/badge.cpp +++ b/ui/utils/badge.cpp @@ -26,32 +26,62 @@ Badge::Badge(const QString& p_id, const QString& p_text, const QIcon& icon, QWid closeButton(new QPushButton()), layout(new QHBoxLayout(this)) { - setBackgroundRole(QPalette::Base); - //setAutoFillBackground(true); - setFrameStyle(QFrame::StyledPanel); - setFrameShadow(QFrame::Raised); + createMandatoryComponents(); image->setPixmap(icon.pixmap(25, 25)); - QIcon tabCloseIcon = QIcon::fromTheme("tab-close"); - 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->addWidget(image); layout->addWidget(text); layout->addWidget(closeButton); - - layout->setContentsMargins(2, 2, 2, 2); - - connect(closeButton, &QPushButton::clicked, this, &Badge::close); +} + +Badge::Badge(QWidget* parent): + QFrame(parent), + id(Shared::generateUUID()), + image(nullptr), + text(nullptr), + closeButton(new QPushButton()), + layout(new QHBoxLayout(this)) +{ + createMandatoryComponents(); + + layout->addWidget(closeButton); +} + +void Badge::setIcon(const QIcon& icon) +{ + if (image == nullptr) { + image = new QLabel(); + image->setPixmap(icon.pixmap(25, 25)); + layout->insertWidget(0, image); + } else { + image->setPixmap(icon.pixmap(25, 25)); + } +} + +void Badge::setText(const QString& p_text) +{ + if (text == nullptr) { + text = new QLabel(p_text); + int index = 0; + if (image != nullptr) { + index = 1; + } + layout->insertWidget(index, text); + } else { + text->setText(p_text); + } } Badge::~Badge() { + if (image != nullptr) { + delete image; + } + if (text != nullptr) { + delete text; + } + delete closeButton; } bool Badge::Comparator::operator()(const Badge* a, const Badge* b) const @@ -63,3 +93,22 @@ bool Badge::Comparator::operator()(const Badge& a, const Badge& b) const { return a.id < b.id; } + +void Badge::createMandatoryComponents() +{ + setBackgroundRole(QPalette::Base); + //setAutoFillBackground(true); + setFrameStyle(QFrame::StyledPanel); + setFrameShadow(QFrame::Raised); + + QIcon tabCloseIcon = QIcon::fromTheme("tab-close"); + 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); +} diff --git a/ui/utils/badge.h b/ui/utils/badge.h index 93a7f00..52f4747 100644 --- a/ui/utils/badge.h +++ b/ui/utils/badge.h @@ -25,6 +25,8 @@ #include #include +#include "shared/utils.h" + /** * @todo write docs */ @@ -33,9 +35,14 @@ class Badge : public QFrame Q_OBJECT public: Badge(const QString& id, const QString& text, const QIcon& icon, QWidget* parent = nullptr); + Badge(QWidget* parent = nullptr); ~Badge(); const QString id; + +public: + void setText(const QString& text); + void setIcon(const QIcon& icon); signals: void close(); @@ -45,6 +52,9 @@ private: QLabel* text; QPushButton* closeButton; QHBoxLayout* layout; + +private: + void createMandatoryComponents(); public: struct Comparator { diff --git a/ui/widgets/conversation.cpp b/ui/widgets/conversation.cpp index 1c82024..07c599e 100644 --- a/ui/widgets/conversation.cpp +++ b/ui/widgets/conversation.cpp @@ -57,7 +57,8 @@ Conversation::Conversation(bool muc, Models::Account* acc, Models::Element* el, tsb(QApplication::style()->styleHint(QStyle::SH_ScrollBar_Transient) == 1), pasteImageAction(new QAction(tr("Paste Image"), this)), shadow(10, 1, Qt::black, this), - contextMenu(new QMenu()) + contextMenu(new QMenu()), + currentAction(CurrentAction::none) { m_ui->setupUi(this); @@ -108,6 +109,9 @@ Conversation::Conversation(bool muc, Models::Account* acc, Models::Element* el, //line->setMyName(acc->getName()); initializeOverlay(); + + m_ui->currentActionBadge->setVisible(false);; +// m_ui->currentActionBadge->setText(tr("Editing message...")); } Conversation::~Conversation() @@ -237,7 +241,7 @@ void Conversation::onEnterPressed() element->feed->registerUpload(msg.getId()); emit sendMessage(msg); } - clearAttachedFiles(); + clearAttachedFiles(); } } diff --git a/ui/widgets/conversation.h b/ui/widgets/conversation.h index 76a8dd5..c43d7a0 100644 --- a/ui/widgets/conversation.h +++ b/ui/widgets/conversation.h @@ -121,6 +121,11 @@ public: const bool isMuc; protected: + enum class CurrentAction { + none, + edit + }; + Models::Account* account; Models::Element* element; QString palJid; @@ -142,6 +147,7 @@ protected: ShadowOverlay shadow; QMenu* contextMenu; + CurrentAction currentAction; private: static bool painterInitialized; diff --git a/ui/widgets/conversation.ui b/ui/widgets/conversation.ui index 483375a..ce9ad66 100644 --- a/ui/widgets/conversation.ui +++ b/ui/widgets/conversation.ui @@ -279,6 +279,29 @@ + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + @@ -400,8 +423,8 @@ background-color: transparent <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Liberation Sans'; font-size:10pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> +</style></head><body style=" font-family:'Noto Sans'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Liberation Sans'; font-size:10pt;"><br /></p></body></html> false @@ -419,6 +442,13 @@ p, li { white-space: pre-wrap; } + + + Badge + QFrame +
ui/utils/badge.h
+
+
diff --git a/ui/widgets/messageline/CMakeLists.txt b/ui/widgets/messageline/CMakeLists.txt index 7cace9d..7a850da 100644 --- a/ui/widgets/messageline/CMakeLists.txt +++ b/ui/widgets/messageline/CMakeLists.txt @@ -1,14 +1,10 @@ target_sources(squawk PRIVATE messagedelegate.cpp messagedelegate.h - #messageline.cpp - #messageline.h preview.cpp preview.h messagefeed.cpp messagefeed.h feedview.cpp feedview.h - #message.cpp - #message.h ) diff --git a/ui/widgets/messageline/message.cpp b/ui/widgets/messageline/message.cpp deleted file mode 100644 index 7a004bb..0000000 --- a/ui/widgets/messageline/message.cpp +++ /dev/null @@ -1,344 +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 . - */ - -#include "message.h" -#include -#include -#include -#include -#include - -Message::Message(const Shared::Message& source, bool p_outgoing, const QString& p_sender, const QString& avatarPath, QWidget* parent): - QWidget(parent), - outgoing(p_outgoing), - msg(source), - body(new QWidget()), - statusBar(new QWidget()), - bodyLayout(new QVBoxLayout(body)), - layout(new QHBoxLayout(this)), - date(new QLabel(msg.getTime().toLocalTime().toString())), - sender(new QLabel(p_sender)), - text(new QLabel()), - shadow(new QGraphicsDropShadowEffect()), - button(0), - file(0), - progress(0), - fileComment(new QLabel()), - statusIcon(0), - editedLabel(0), - avatar(new Image(avatarPath.size() == 0 ? Shared::iconPath("user", true) : avatarPath, 60)), - hasButton(false), - hasProgress(false), - hasFile(false), - commentAdded(false), - hasStatusIcon(false), - hasEditedLabel(false) -{ - setContentsMargins(0, 0, 0, 0); - layout->setContentsMargins(10, 5, 10, 5); - body->setBackgroundRole(QPalette::AlternateBase); - body->setAutoFillBackground(true); - - QString bd = Shared::processMessageBody(msg.getBody()); - text->setTextFormat(Qt::RichText); - text->setText(bd);; - text->setTextInteractionFlags(text->textInteractionFlags() | Qt::TextSelectableByMouse | Qt::LinksAccessibleByMouse); - text->setWordWrap(true); - text->setOpenExternalLinks(true); - if (bd.size() == 0) { - text->hide(); - } - - QFont dFont = date->font(); - dFont.setItalic(true); - dFont.setPointSize(dFont.pointSize() - 2); - date->setFont(dFont); - - QFont f; - f.setBold(true); - sender->setFont(f); - - bodyLayout->addWidget(sender); - bodyLayout->addWidget(text); - - shadow->setBlurRadius(10); - shadow->setXOffset(1); - shadow->setYOffset(1); - shadow->setColor(Qt::black); - body->setGraphicsEffect(shadow); - avatar->setMaximumHeight(60); - avatar->setMaximumWidth(60); - - statusBar->setContentsMargins(0, 0, 0, 0); - QHBoxLayout* statusLay = new QHBoxLayout(); - statusLay->setContentsMargins(0, 0, 0, 0); - statusBar->setLayout(statusLay); - - if (outgoing) { - sender->setAlignment(Qt::AlignRight); - date->setAlignment(Qt::AlignRight); - statusIcon = new QLabel(); - setState(); - statusLay->addWidget(statusIcon); - statusLay->addWidget(date); - layout->addStretch(); - layout->addWidget(body); - layout->addWidget(avatar); - hasStatusIcon = true; - } else { - layout->addWidget(avatar); - layout->addWidget(body); - layout->addStretch(); - statusLay->addWidget(date); - } - if (msg.getEdited()) { - setEdited(); - } - - bodyLayout->addWidget(statusBar); - layout->setAlignment(avatar, Qt::AlignTop); -} - -Message::~Message() -{ - if (!commentAdded) { - delete fileComment; - } - //delete body; //not sure if I should delete it here, it's probably already owned by the infrastructure and gonna die with the rest of the widget - //delete avatar; -} - -QString Message::getId() const -{ - return msg.getId(); -} - -QString Message::getSenderJid() const -{ - return msg.getFromJid(); -} - -QString Message::getSenderResource() const -{ - return msg.getFromResource(); -} - -QString Message::getFileUrl() const -{ - return msg.getOutOfBandUrl(); -} - -void Message::setSender(const QString& p_sender) -{ - sender->setText(p_sender); -} - -void Message::addButton(const QIcon& icon, const QString& buttonText, const QString& tooltip) -{ - hideFile(); - hideProgress(); - if (!hasButton) { - hideComment(); - if (msg.getBody() == msg.getOutOfBandUrl()) { - text->setText(""); - text->hide(); - } - button = new QPushButton(icon, buttonText); - button->setToolTip(tooltip); - connect(button, &QPushButton::clicked, this, &Message::buttonClicked); - bodyLayout->insertWidget(2, button); - hasButton = true; - } -} - -void Message::setProgress(qreal value) -{ - hideFile(); - hideButton(); - if (!hasProgress) { - hideComment(); - if (msg.getBody() == msg.getOutOfBandUrl()) { - text->setText(""); - text->hide(); - } - progress = new QProgressBar(); - progress->setRange(0, 100); - bodyLayout->insertWidget(2, progress); - hasProgress = true; - } - progress->setValue(value * 100); -} - -void Message::showFile(const QString& path) -{ - hideButton(); - hideProgress(); - if (!hasFile) { - hideComment(); - if (msg.getBody() == msg.getOutOfBandUrl()) { - text->setText(""); - text->hide(); - } - QMimeDatabase db; - QMimeType type = db.mimeTypeForFile(path); - QStringList parts = type.name().split("/"); - QString big = parts.front(); - QFileInfo info(path); - if (big == "image") { - file = new Image(path); - } else { - file = new QLabel(); - file->setPixmap(QIcon::fromTheme(type.iconName()).pixmap(50)); - file->setAlignment(Qt::AlignCenter); - showComment(info.fileName(), true); - } - file->setContextMenuPolicy(Qt::ActionsContextMenu); - QAction* openAction = new QAction(QIcon::fromTheme("document-new-from-template"), tr("Open"), file); - connect(openAction, &QAction::triggered, [path]() { //TODO need to get rid of this shame - QDesktopServices::openUrl(QUrl::fromLocalFile(path)); - }); - file->addAction(openAction); - bodyLayout->insertWidget(2, file); - hasFile = true; - } -} - -void Message::hideComment() -{ - if (commentAdded) { - bodyLayout->removeWidget(fileComment); - fileComment->hide(); - fileComment->setWordWrap(false); - commentAdded = false; - } -} - -void Message::hideButton() -{ - if (hasButton) { - button->deleteLater(); - button = 0; - hasButton = false; - } -} - -void Message::hideFile() -{ - if (hasFile) { - file->deleteLater(); - file = 0; - hasFile = false; - } -} - -void Message::hideProgress() -{ - if (hasProgress) { - progress->deleteLater(); - progress = 0; - hasProgress = false;; - } -} -void Message::showComment(const QString& comment, bool wordWrap) -{ - if (!commentAdded) { - int index = 2; - if (hasFile) { - index++; - } - if (hasButton) { - index++; - } - if (hasProgress) { - index++; - } - bodyLayout->insertWidget(index, fileComment); - fileComment->show(); - commentAdded = true; - } - fileComment->setWordWrap(wordWrap); - fileComment->setText(comment); -} - -const Shared::Message & Message::getMessage() const -{ - return msg; -} - -void Message::setAvatarPath(const QString& p_path) -{ - if (p_path.size() == 0) { - avatar->setPath(Shared::iconPath("user", true)); - } else { - avatar->setPath(p_path); - } -} - -bool Message::change(const QMap& data) -{ - bool idChanged = msg.change(data); - - QString body = msg.getBody(); - QString bd = Shared::processMessageBody(body); - if (body.size() > 0) { - text->setText(bd); - text->show(); - } else { - text->setText(body); - text->hide(); - } - if (msg.getEdited()) { - setEdited(); - } - if (hasStatusIcon) { - setState(); - } - - - return idChanged; -} - -void Message::setEdited() -{ - if (!hasEditedLabel) { - editedLabel = new QLabel(); - hasEditedLabel = true; - QIcon q(Shared::icon("edit-rename")); - editedLabel->setPixmap(q.pixmap(12, 12)); - QHBoxLayout* statusLay = static_cast(statusBar->layout()); - statusLay->insertWidget(1, editedLabel); - } - editedLabel->setToolTip("Last time edited: " + msg.getLastModified().toLocalTime().toString() - + "\nOriginal message: " + msg.getOriginalBody()); -} - -void Message::setState() -{ - Shared::Message::State state = msg.getState(); - QIcon q(Shared::icon(Shared::messageStateThemeIcons[static_cast(state)])); - QString tt = Shared::Global::getName(state); - if (state == Shared::Message::State::error) { - QString errText = msg.getErrorText(); - if (errText.size() > 0) { - tt += ": " + errText; - } - } - statusIcon->setToolTip(tt); - statusIcon->setPixmap(q.pixmap(12, 12)); -} - diff --git a/ui/widgets/messageline/message.h b/ui/widgets/messageline/message.h deleted file mode 100644 index eef93a1..0000000 --- a/ui/widgets/messageline/message.h +++ /dev/null @@ -1,103 +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 MESSAGE_H -#define MESSAGE_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "shared/message.h" -#include "shared/icons.h" -#include "shared/global.h" -#include "shared/utils.h" -#include "resizer.h" -#include "image.h" - -/** - * @todo write docs - */ -class Message : public QWidget -{ - Q_OBJECT -public: - Message(const Shared::Message& source, bool outgoing, const QString& sender, const QString& avatarPath = "", QWidget* parent = nullptr); - ~Message(); - - void setSender(const QString& sender); - QString getId() const; - QString getSenderJid() const; - QString getSenderResource() const; - QString getFileUrl() const; - const Shared::Message& getMessage() const; - - void addButton(const QIcon& icon, const QString& buttonText, const QString& tooltip = ""); - void showComment(const QString& comment, bool wordWrap = false); - void hideComment(); - void showFile(const QString& path); - void setProgress(qreal value); - void setAvatarPath(const QString& p_path); - bool change(const QMap& data); - - bool const outgoing; - -signals: - void buttonClicked(); - -private: - Shared::Message msg; - QWidget* body; - QWidget* statusBar; - QVBoxLayout* bodyLayout; - QHBoxLayout* layout; - QLabel* date; - QLabel* sender; - QLabel* text; - QGraphicsDropShadowEffect* shadow; - QPushButton* button; - QLabel* file; - QProgressBar* progress; - QLabel* fileComment; - QLabel* statusIcon; - QLabel* editedLabel; - Image* avatar; - bool hasButton; - bool hasProgress; - bool hasFile; - bool commentAdded; - bool hasStatusIcon; - bool hasEditedLabel; - -private: - void hideButton(); - void hideProgress(); - void hideFile(); - void setState(); - void setEdited(); -}; - -#endif // MESSAGE_H diff --git a/ui/widgets/messageline/messageline.cpp b/ui/widgets/messageline/messageline.cpp deleted file mode 100644 index fec0037..0000000 --- a/ui/widgets/messageline/messageline.cpp +++ /dev/null @@ -1,504 +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 . - */ - -#include "messageline.h" -#include -#include -#include - -MessageLine::MessageLine(bool p_room, QWidget* parent): - QWidget(parent), - messageIndex(), - messageOrder(), - myMessages(), - palMessages(), - uploadPaths(), - palAvatars(), - exPalAvatars(), - layout(new QVBoxLayout(this)), - myName(), - myAvatarPath(), - palNames(), - uploading(), - downloading(), - room(p_room), - busyShown(false), - progress() -{ - setContentsMargins(0, 0, 0, 0); - layout->setContentsMargins(0, 0, 0, 0); - layout->setSpacing(0); - layout->addStretch(); -} - -MessageLine::~MessageLine() -{ - for (Index::const_iterator itr = messageIndex.begin(), end = messageIndex.end(); itr != end; ++itr) { - delete itr->second; - } -} - -MessageLine::Position MessageLine::message(const Shared::Message& msg, bool forceOutgoing) -{ - QString id = msg.getId(); - Index::iterator itr = messageIndex.find(id); - if (itr != messageIndex.end()) { - qDebug() << "received more then one message with the same id, skipping yet the new one"; - return invalid; - } - - QString sender; - QString aPath; - bool outgoing; - - if (forceOutgoing) { - sender = myName; - aPath = myAvatarPath; - outgoing = true; - } else { - if (room) { - if (msg.getFromResource() == myName) { - sender = myName; - aPath = myAvatarPath; - outgoing = true; - } else { - sender = msg.getFromResource(); - std::map::iterator aItr = palAvatars.find(sender); - if (aItr != palAvatars.end()) { - aPath = aItr->second; - } else { - aItr = exPalAvatars.find(sender); - if (aItr != exPalAvatars.end()) { - aPath = aItr->second; - } - } - outgoing = false; - } - } else { - if (msg.getOutgoing()) { - sender = myName; - aPath = myAvatarPath; - outgoing = true; - } else { - QString jid = msg.getFromJid(); - std::map::iterator itr = palNames.find(jid); - if (itr != palNames.end()) { - sender = itr->second; - } else { - sender = jid; - } - - std::map::iterator aItr = palAvatars.find(jid); - if (aItr != palAvatars.end()) { - aPath = aItr->second; - } - - outgoing = false; - } - } - } - - Message* message = new Message(msg, outgoing, sender, aPath); - - std::pair result = messageOrder.insert(std::make_pair(msg.getTime(), message)); - if (!result.second) { - qDebug() << "Error appending a message into a message list - seems like the time of that message exactly matches the time of some other message, can't put them in order, skipping yet"; - delete message; - return invalid; - } - if (outgoing) { - myMessages.insert(std::make_pair(id, message)); - } else { - QString senderId; - if (room) { - senderId = sender; - } else { - senderId = msg.getFromJid(); - } - - std::map::iterator pItr = palMessages.find(senderId); - if (pItr == palMessages.end()) { - pItr = palMessages.insert(std::make_pair(senderId, Index())).first; - } - pItr->second.insert(std::make_pair(id, message)); - } - messageIndex.insert(std::make_pair(id, message)); - unsigned long index = std::distance(messageOrder.begin(), result.first); //need to make with binary indexed tree - Position res = invalid; - if (index == 0) { - res = beggining; - } else if (index == messageIndex.size() - 1) { - res = end; - } else { - res = middle; - } - - if (busyShown) { - index += 1; - } - - - if (res == end) { - layout->addWidget(message); - } else { - layout->insertWidget(index + 1, message); - } - - if (msg.hasOutOfBandUrl()) { - emit requestLocalFile(msg.getId(), msg.getOutOfBandUrl()); - connect(message, &Message::buttonClicked, this, &MessageLine::onDownload); - } - - return res; -} - -void MessageLine::changeMessage(const QString& id, const QMap& data) -{ - Index::const_iterator itr = messageIndex.find(id); - if (itr != messageIndex.end()) { - Message* msg = itr->second; - if (msg->change(data)) { //if ID changed (stanza in replace of another) - QString newId = msg->getId(); //need to updated IDs of that message in all maps - messageIndex.erase(itr); - messageIndex.insert(std::make_pair(newId, msg)); - if (msg->outgoing) { - QString senderId; - if (room) { - senderId = msg->getSenderResource(); - } else { - senderId = msg->getSenderJid(); - } - - std::map::iterator pItr = palMessages.find(senderId); - if (pItr != palMessages.end()) { - Index::const_iterator sItr = pItr->second.find(id); - if (sItr != pItr->second.end()) { - pItr->second.erase(sItr); - pItr->second.insert(std::make_pair(newId, msg)); - } else { - qDebug() << "Was trying to replace message in open conversations, couldn't find it among pal's messages, probably an error"; - } - } else { - qDebug() << "Was trying to replace message in open conversations, couldn't find pal messages, probably an error"; - } - } else { - Index::const_iterator mItr = myMessages.find(id); - if (mItr != myMessages.end()) { - myMessages.erase(mItr); - myMessages.insert(std::make_pair(newId, msg)); - } else { - qDebug() << "Was trying to replace message in open conversations, couldn't find it among my messages, probably an error"; - } - } - } - } -} - -void MessageLine::onDownload() -{ - Message* msg = static_cast(sender()); - QString messageId = msg->getId(); - Index::const_iterator itr = downloading.find(messageId); - if (itr == downloading.end()) { - downloading.insert(std::make_pair(messageId, msg)); - msg->setProgress(0); - msg->showComment(tr("Downloading...")); - emit downloadFile(messageId, msg->getFileUrl()); - } else { - qDebug() << "An attempt to initiate download for already downloading file" << msg->getFileUrl() << ", skipping"; - } -} - -void MessageLine::setMyName(const QString& name) -{ - myName = name; - for (Index::const_iterator itr = myMessages.begin(), end = myMessages.end(); itr != end; ++itr) { - itr->second->setSender(name); - } -} - -void MessageLine::setPalName(const QString& jid, const QString& name) -{ - std::map::iterator itr = palNames.find(jid); - if (itr == palNames.end()) { - palNames.insert(std::make_pair(jid, name)); - } else { - itr->second = name; - } - - std::map::iterator pItr = palMessages.find(jid); - if (pItr != palMessages.end()) { - for (Index::const_iterator itr = pItr->second.begin(), end = pItr->second.end(); itr != end; ++itr) { - itr->second->setSender(name); - } - } -} - -void MessageLine::setPalAvatar(const QString& jid, const QString& path) -{ - std::map::iterator itr = palAvatars.find(jid); - if (itr == palAvatars.end()) { - palAvatars.insert(std::make_pair(jid, path)); - - std::map::const_iterator eitr = exPalAvatars.find(jid); - if (eitr != exPalAvatars.end()) { - exPalAvatars.erase(eitr); - } - } else { - itr->second = path; - } - - std::map::iterator pItr = palMessages.find(jid); - if (pItr != palMessages.end()) { - for (Index::const_iterator itr = pItr->second.begin(), end = pItr->second.end(); itr != end; ++itr) { - itr->second->setAvatarPath(path); - } - } -} - -void MessageLine::dropPalAvatar(const QString& jid) -{ - std::map::iterator itr = palAvatars.find(jid); - if (itr != palAvatars.end()) { - palAvatars.erase(itr); - } - - std::map::const_iterator eitr = exPalAvatars.find(jid); - if (eitr != exPalAvatars.end()) { - exPalAvatars.erase(eitr); - } - - std::map::iterator pItr = palMessages.find(jid); - if (pItr != palMessages.end()) { - for (Index::const_iterator itr = pItr->second.begin(), end = pItr->second.end(); itr != end; ++itr) { - itr->second->setAvatarPath(""); - } - } -} - -void MessageLine::movePalAvatarToEx(const QString& name) -{ - std::map::iterator itr = palAvatars.find(name); - if (itr != palAvatars.end()) { - std::map::iterator eitr = exPalAvatars.find(name); - if (eitr != exPalAvatars.end()) { - eitr->second = itr->second; - } else { - exPalAvatars.insert(std::make_pair(name, itr->second)); - } - - palAvatars.erase(itr); - } -} - -void MessageLine::resizeEvent(QResizeEvent* event) -{ - QWidget::resizeEvent(event); - emit resize(event->size().height() - event->oldSize().height()); -} - - -QString MessageLine::firstMessageId() const -{ - if (messageOrder.size() == 0) { - return ""; - } else { - return messageOrder.begin()->second->getId(); - } -} - -void MessageLine::showBusyIndicator() -{ - if (!busyShown) { - layout->insertWidget(0, &progress); - progress.start(); - busyShown = true; - } -} - -void MessageLine::hideBusyIndicator() -{ - if (busyShown) { - progress.stop(); - layout->removeWidget(&progress); - busyShown = false; - } -} - -void MessageLine::fileProgress(const QString& messageId, qreal progress) -{ - Index::const_iterator itr = messageIndex.find(messageId); - if (itr == messageIndex.end()) { - //TODO may be some logging, that's not normal - } else { - itr->second->setProgress(progress); - } -} - -void MessageLine::responseLocalFile(const QString& messageId, const QString& path) -{ - Index::const_iterator itr = messageIndex.find(messageId); - if (itr == messageIndex.end()) { - - } else { - Index::const_iterator uItr = uploading.find(messageId); - if (path.size() > 0) { - Index::const_iterator dItr = downloading.find(messageId); - if (dItr != downloading.end()) { - downloading.erase(dItr); - itr->second->showFile(path); - } else { - if (uItr != uploading.end()) { - uploading.erase(uItr); - std::map::const_iterator muItr = uploadPaths.find(messageId); - if (muItr != uploadPaths.end()) { - uploadPaths.erase(muItr); - } - Shared::Message msg = itr->second->getMessage(); - removeMessage(messageId); - msg.setCurrentTime(); - message(msg); - itr = messageIndex.find(messageId); - itr->second->showFile(path); - } else { - itr->second->showFile(path); //then it is already cached file - } - } - } else { - if (uItr == uploading.end()) { - const Shared::Message& msg = itr->second->getMessage(); - itr->second->addButton(QIcon::fromTheme("download"), tr("Download"), "" + msg.getOutOfBandUrl() + ""); - itr->second->showComment(tr("Push the button to download the file")); - } else { - qDebug() << "An unhandled state for file uploading - empty path"; - } - } - } -} - -void MessageLine::removeMessage(const QString& messageId) -{ - Index::const_iterator itr = messageIndex.find(messageId); - if (itr != messageIndex.end()) { - Message* ui = itr->second; - const Shared::Message& msg = ui->getMessage(); - messageIndex.erase(itr); - Order::const_iterator oItr = messageOrder.find(msg.getTime()); - if (oItr != messageOrder.end()) { - messageOrder.erase(oItr); - } else { - qDebug() << "An attempt to remove message from messageLine, but it wasn't found in order"; - } - if (msg.getOutgoing()) { - Index::const_iterator mItr = myMessages.find(messageId); - if (mItr != myMessages.end()) { - myMessages.erase(mItr); - } else { - qDebug() << "Error removing message: it seems to be outgoing yet it wasn't found in outgoing messages"; - } - } else { - if (room) { - - } else { - QString jid = msg.getFromJid(); - std::map::iterator pItr = palMessages.find(jid); - if (pItr != palMessages.end()) { - Index& pMsgs = pItr->second; - Index::const_iterator pmitr = pMsgs.find(messageId); - if (pmitr != pMsgs.end()) { - pMsgs.erase(pmitr); - } else { - qDebug() << "Error removing message: it seems to be incoming yet it wasn't found among messages from that penpal"; - } - } - } - } - ui->deleteLater(); - qDebug() << "message" << messageId << "has been removed"; - } else { - qDebug() << "An attempt to remove non existing message from messageLine"; - } -} - -void MessageLine::fileError(const QString& messageId, const QString& error) -{ - Index::const_iterator itr = downloading.find(messageId); - if (itr == downloading.end()) { - Index::const_iterator itr = uploading.find(messageId); - if (itr == uploading.end()) { - //TODO may be some logging, that's not normal - } else { - itr->second->showComment(tr("Error uploading file: %1\nYou can try again").arg(QCoreApplication::translate("NetworkErrors", error.toLatin1())), true); - itr->second->addButton(QIcon::fromTheme("upload"), tr("Upload")); - } - } else { - const Shared::Message& msg = itr->second->getMessage(); - itr->second->addButton(QIcon::fromTheme("download"), tr("Download"), "" + msg.getOutOfBandUrl() + ""); - itr->second->showComment(tr("Error downloading file: %1\nYou can try again").arg(QCoreApplication::translate("NetworkErrors", error.toLatin1())), true); - } -} - -void MessageLine::appendMessageWithUpload(const Shared::Message& msg, const QString& path) -{ - appendMessageWithUploadNoSiganl(msg, path); - emit uploadFile(msg, path); -} - -void MessageLine::appendMessageWithUploadNoSiganl(const Shared::Message& msg, const QString& path) -{ - message(msg, true); - QString id = msg.getId(); - Message* ui = messageIndex.find(id)->second; - connect(ui, &Message::buttonClicked, this, &MessageLine::onUpload); //this is in case of retry; - ui->setProgress(0); - ui->showComment(tr("Uploading...")); - uploading.insert(std::make_pair(id, ui)); - uploadPaths.insert(std::make_pair(id, path)); -} - - -void MessageLine::onUpload() -{ - //TODO retry -} - -void MessageLine::setMyAvatarPath(const QString& p_path) -{ - if (myAvatarPath != p_path) { - myAvatarPath = p_path; - for (std::pair pair : myMessages) { - pair.second->setAvatarPath(myAvatarPath); - } - } -} - -void MessageLine::setExPalAvatars(const std::map& data) -{ - exPalAvatars = data; - - for (const std::pair& pair : palMessages) { - if (palAvatars.find(pair.first) == palAvatars.end()) { - std::map::const_iterator eitr = exPalAvatars.find(pair.first); - if (eitr != exPalAvatars.end()) { - for (const std::pair& mp : pair.second) { - mp.second->setAvatarPath(eitr->second); - } - } - } - } -} diff --git a/ui/widgets/messageline/messageline.h b/ui/widgets/messageline/messageline.h deleted file mode 100644 index a0a7b6c..0000000 --- a/ui/widgets/messageline/messageline.h +++ /dev/null @@ -1,108 +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 MESSAGELINE_H -#define MESSAGELINE_H - -#include -#include -#include -#include -#include -#include - -#include "shared/message.h" -#include "message.h" -#include "progress.h" - -class MessageLine : public QWidget -{ - Q_OBJECT -public: - enum Position { - beggining, - middle, - end, - invalid - }; - MessageLine(bool p_room, QWidget* parent = 0); - ~MessageLine(); - - Position message(const Shared::Message& msg, bool forceOutgoing = false); - void setMyName(const QString& name); - void setPalName(const QString& jid, const QString& name); - QString firstMessageId() const; - void showBusyIndicator(); - void hideBusyIndicator(); - void responseLocalFile(const QString& messageId, const QString& path); - void fileError(const QString& messageId, const QString& error); - void fileProgress(const QString& messageId, qreal progress); - void appendMessageWithUpload(const Shared::Message& msg, const QString& path); - void appendMessageWithUploadNoSiganl(const Shared::Message& msg, const QString& path); - void removeMessage(const QString& messageId); - void setMyAvatarPath(const QString& p_path); - void setPalAvatar(const QString& jid, const QString& path); - void dropPalAvatar(const QString& jid); - void changeMessage(const QString& id, const QMap& data); - void setExPalAvatars(const std::map& data); - void movePalAvatarToEx(const QString& name); - -signals: - void resize(int amount); - void downloadFile(const QString& messageId, const QString& url); - void uploadFile(const Shared::Message& msg, const QString& path); - void requestLocalFile(const QString& messageId, const QString& url); - -protected: - void resizeEvent(QResizeEvent * event) override; - -protected: - void onDownload(); - void onUpload(); - -private: - struct Comparator { - bool operator()(const Shared::Message& a, const Shared::Message& b) const { - return a.getTime() < b.getTime(); - } - bool operator()(const Shared::Message* a, const Shared::Message* b) const { - return a->getTime() < b->getTime(); - } - }; - typedef std::map Order; - typedef std::map Index; - Index messageIndex; - Order messageOrder; - Index myMessages; - std::map palMessages; - std::map uploadPaths; - std::map palAvatars; - std::map exPalAvatars; - QVBoxLayout* layout; - - QString myName; - QString myAvatarPath; - std::map palNames; - Index uploading; - Index downloading; - bool room; - bool busyShown; - Progress progress; -}; - -#endif // MESSAGELINE_H