Browse Source

Shared namespace refactoring, enum class refactoring, going offline related crash fix

pull/39/head
Blue 11 months ago
parent
commit
ddfb3419cc
59 changed files with 1948 additions and 1695 deletions
  1. +18
    -2
      CMakeLists.txt
  2. +36
    -32
      core/account.cpp
  3. +3
    -3
      core/account.h
  4. +1
    -1
      core/archive.h
  5. +1
    -1
      core/contact.cpp
  6. +3
    -1
      core/rosteritem.h
  7. +15
    -18
      core/squawk.cpp
  8. +7
    -5
      core/squawk.h
  9. +0
    -765
      global.cpp
  10. +0
    -512
      global.h
  11. +5
    -0
      main.cpp
  12. +29
    -0
      shared.h
  13. +114
    -0
      shared/enums.h
  14. +170
    -0
      shared/global.cpp
  15. +64
    -0
      shared/global.h
  16. +96
    -0
      shared/icons.cpp
  17. +176
    -0
      shared/icons.h
  18. +399
    -0
      shared/message.cpp
  19. +125
    -0
      shared/message.h
  20. +29
    -0
      shared/utils.cpp
  21. +72
    -0
      shared/utils.h
  22. +288
    -0
      shared/vcard.cpp
  23. +152
    -0
      shared/vcard.h
  24. +27
    -239
      translations/squawk.ru.ts
  25. +3
    -9
      ui/models/abstractparticipant.cpp
  26. +5
    -1
      ui/models/abstractparticipant.h
  27. +11
    -21
      ui/models/account.cpp
  28. +4
    -1
      ui/models/account.h
  29. +1
    -1
      ui/models/accounts.cpp
  30. +10
    -20
      ui/models/contact.cpp
  31. +5
    -1
      ui/models/contact.h
  32. +1
    -1
      ui/models/group.cpp
  33. +2
    -2
      ui/models/item.cpp
  34. +1
    -1
      ui/models/item.h
  35. +1
    -0
      ui/models/presence.cpp
  36. +3
    -1
      ui/models/presence.h
  37. +6
    -4
      ui/models/room.cpp
  38. +2
    -1
      ui/models/room.h
  39. +10
    -14
      ui/models/roster.cpp
  40. +2
    -1
      ui/models/roster.h
  41. +21
    -20
      ui/squawk.cpp
  42. +3
    -3
      ui/squawk.h
  43. +2
    -2
      ui/utils/message.cpp
  44. +3
    -1
      ui/utils/message.h
  45. +1
    -0
      ui/utils/messageline.cpp
  46. +1
    -1
      ui/utils/messageline.h
  47. +2
    -0
      ui/utils/progress.cpp
  48. +0
    -2
      ui/utils/progress.h
  49. +1
    -1
      ui/widgets/accounts.cpp
  50. +1
    -1
      ui/widgets/chat.cpp
  51. +3
    -1
      ui/widgets/chat.h
  52. +2
    -0
      ui/widgets/conversation.cpp
  53. +1
    -1
      ui/widgets/conversation.h
  54. +3
    -0
      ui/widgets/vcard/emailsmodel.cpp
  55. +1
    -1
      ui/widgets/vcard/emailsmodel.h
  56. +3
    -0
      ui/widgets/vcard/phonesmodel.cpp
  57. +1
    -1
      ui/widgets/vcard/phonesmodel.h
  58. +1
    -1
      ui/widgets/vcard/vcard.cpp
  59. +1
    -1
      ui/widgets/vcard/vcard.h

+ 18
- 2
CMakeLists.txt View File

@ -25,9 +25,25 @@ message("Build type: ${CMAKE_BUILD_TYPE}")
set(squawk_SRC
main.cpp
global.cpp
exception.cpp
signalcatcher.cpp
shared/global.cpp
shared/utils.cpp
shared/message.cpp
shared/vcard.cpp
shared/icons.cpp
)
set(squawk_HEAD
exception.h
signalcatcher.h
shared.h
shared/enums.h
shared/message.h
shared/global.h
shared/utils.h
shared/vcard.h
shared/icons.h
)
configure_file(resources/images/logo.svg squawk.svg COPYONLY)
@ -46,7 +62,7 @@ add_custom_target(translations ALL DEPENDS ${QM_FILES})
qt5_add_resources(RCC resources/resources.qrc)
add_executable(squawk ${squawk_SRC} ${RCC})
add_executable(squawk ${squawk_SRC} ${squawk_HEAD} ${RCC})
target_link_libraries(squawk Qt5::Widgets)
option(SYSTEM_QXMPP "Use system qxmpp lib" ON)


+ 36
- 32
core/account.cpp View File

@ -30,7 +30,7 @@ Account::Account(const QString& p_login, const QString& p_server, const QString&
client(),
config(),
presence(),
state(Shared::disconnected),
state(Shared::ConnectionState::disconnected),
groups(),
cm(new QXmppCarbonManager()),
am(new QXmppMamManager()),
@ -182,9 +182,9 @@ Shared::ConnectionState Core::Account::getState() const
void Core::Account::connect()
{
if (state == Shared::disconnected) {
if (state == Shared::ConnectionState::disconnected) {
reconnectTimes = maxReconnectTimes;
state = Shared::connecting;
state = Shared::ConnectionState::connecting;
client.connectToServer(config, presence);
emit connectionStateChanged(state);
} else {
@ -195,19 +195,19 @@ void Core::Account::connect()
void Core::Account::disconnect()
{
reconnectTimes = 0;
if (state != Shared::disconnected) {
if (state != Shared::ConnectionState::disconnected) {
clearConferences();
client.disconnectFromServer();
state = Shared::disconnected;
state = Shared::ConnectionState::disconnected;
emit connectionStateChanged(state);
}
}
void Core::Account::onClientConnected()
{
if (state == Shared::connecting) {
if (state == Shared::ConnectionState::connecting) {
reconnectTimes = maxReconnectTimes;
state = Shared::connected;
state = Shared::ConnectionState::connected;
dm->requestItems(getServer());
dm->requestInfo(getServer());
emit connectionStateChanged(state);
@ -219,16 +219,16 @@ void Core::Account::onClientConnected()
void Core::Account::onClientDisconnected()
{
clearConferences();
if (state != Shared::disconnected) {
if (state != Shared::ConnectionState::disconnected) {
if (reconnectTimes > 0) {
qDebug() << "Account" << name << "is reconnecting for" << reconnectTimes << "more times";
--reconnectTimes;
state = Shared::connecting;
state = Shared::ConnectionState::connecting;
client.connectToServer(config, presence);
emit connectionStateChanged(state);
} else {
qDebug() << "Account" << name << "has been disconnected";
state = Shared::disconnected;
state = Shared::ConnectionState::disconnected;
emit connectionStateChanged(state);
}
} else {
@ -238,7 +238,7 @@ void Core::Account::onClientDisconnected()
void Core::Account::reconnect()
{
if (state == Shared::connected) {
if (state == Shared::ConnectionState::connected) {
++reconnectTimes;
client.disconnectFromServer();
} else {
@ -281,7 +281,7 @@ void Core::Account::onRosterReceived()
void Core::Account::setReconnectTimes(unsigned int times)
{
maxReconnectTimes = times;
if (state == Shared::connected) {
if (state == Shared::ConnectionState::connected) {
reconnectTimes = times;
}
}
@ -355,7 +355,7 @@ void Core::Account::addedAccount(const QString& jid)
if (newContact) {
QMap<QString, QVariant> cData({
{"name", re.name()},
{"state", state}
{"state", QVariant::fromValue(state)}
});
Archive::AvatarInfo info;
@ -427,7 +427,7 @@ void Core::Account::onPresenceReceived(const QXmppPresence& p_presence)
if (jid == myJid) {
if (resource == getResource()) {
emit availabilityChanged(p_presence.availableStatusType());
emit availabilityChanged(static_cast<Shared::Availability>(p_presence.availableStatusType()));
} else {
if (!ownVCardRequestInProgress) {
switch (p_presence.vCardUpdateType()) {
@ -521,21 +521,25 @@ void Core::Account::setServer(const QString& p_server)
Shared::Availability Core::Account::getAvailability() const
{
if (state == Shared::connected) {
if (state == Shared::ConnectionState::connected) {
QXmppPresence::AvailableStatusType pres = presence.availableStatusType();
return static_cast<Shared::Availability>(pres); //they are compatible;
} else {
return Shared::offline;
return Shared::Availability::offline;
}
}
void Core::Account::setAvailability(Shared::Availability avail)
{
QXmppPresence::AvailableStatusType pres = static_cast<QXmppPresence::AvailableStatusType>(avail);
presence.setAvailableStatusType(pres);
if (state != Shared::disconnected) { //TODO not sure how to do here - changing state may cause connection or disconnection
client.setClientPresence(presence);
if (avail == Shared::Availability::offline) {
disconnect(); //TODO not sure how to do here - changing state may cause connection or disconnection
} else {
QXmppPresence::AvailableStatusType pres = static_cast<QXmppPresence::AvailableStatusType>(avail);
presence.setAvailableStatusType(pres);
if (state != Shared::ConnectionState::disconnected) {
client.setClientPresence(presence);
}
}
}
@ -624,7 +628,7 @@ void Core::Account::sendMessage(Shared::Message data)
QString jid = data.getPenPalJid();
QString id = data.getId();
RosterItem* ri = getRosterItem(jid);
if (state == Shared::connected) {
if (state == Shared::ConnectionState::connected) {
QXmppMessage msg(getFullJid(), data.getTo(), data.getBody(), data.getThread());
msg.setId(id);
msg.setType(static_cast<QXmppMessage::Type>(data.getType())); //it is safe here, my type is compatible
@ -660,7 +664,7 @@ void Core::Account::sendMessage(Shared::Message data)
void Core::Account::sendMessage(const Shared::Message& data, const QString& path)
{
if (state == Shared::connected) {
if (state == Shared::ConnectionState::connected) {
QString url = network->getFileRemoteUrl(path);
if (url.size() != 0) {
sendMessageWithLocalUploadedFile(data, url);
@ -727,9 +731,9 @@ bool Core::Account::handleChatMessage(const QXmppMessage& msg, bool outgoing, bo
cnt = new Contact(jid, name);
contacts.insert(std::make_pair(jid, cnt));
outOfRosterContacts.insert(jid);
cnt->setSubscriptionState(Shared::unknown);
cnt->setSubscriptionState(Shared::SubscriptionState::unknown);
emit addContact(jid, "", QMap<QString, QVariant>({
{"state", Shared::unknown}
{"state", QVariant::fromValue(Shared::SubscriptionState::unknown)}
}));
handleNewContact(cnt);
}
@ -963,7 +967,7 @@ void Core::Account::onContactGroupAdded(const QString& group)
QMap<QString, QVariant> cData({
{"name", contact->getName()},
{"state", contact->getSubscriptionState()}
{"state", QVariant::fromValue(contact->getSubscriptionState())}
});
addToGroup(contact->jid, group);
emit addContact(contact->jid, group, cData);
@ -993,7 +997,7 @@ void Core::Account::onContactSubscriptionStateChanged(Shared::SubscriptionState
{
Contact* contact = static_cast<Contact*>(sender());
QMap<QString, QVariant> cData({
{"state", cstate},
{"state", QVariant::fromValue(cstate)},
});
emit changeContact(contact->jid, cData);
}
@ -1031,7 +1035,7 @@ Shared::SubscriptionState Core::Account::castSubscriptionState(QXmppRosterIq::It
{
Shared::SubscriptionState state;
if (qs == QXmppRosterIq::Item::NotSet) {
state = Shared::unknown;
state = Shared::SubscriptionState::unknown;
} else {
state = static_cast<Shared::SubscriptionState>(qs);
}
@ -1145,7 +1149,7 @@ void Core::Account::onClientError(QXmppClient::Error err)
void Core::Account::subscribeToContact(const QString& jid, const QString& reason)
{
if (state == Shared::connected) {
if (state == Shared::ConnectionState::connected) {
rm->subscribe(jid, reason);
} else {
qDebug() << "An attempt to subscribe account " << name << " to contact " << jid << " but the account is not in the connected state, skipping";
@ -1154,7 +1158,7 @@ void Core::Account::subscribeToContact(const QString& jid, const QString& reason
void Core::Account::unsubscribeFromContact(const QString& jid, const QString& reason)
{
if (state == Shared::connected) {
if (state == Shared::ConnectionState::connected) {
rm->unsubscribe(jid, reason);
} else {
qDebug() << "An attempt to unsubscribe account " << name << " from contact " << jid << " but the account is not in the connected state, skipping";
@ -1163,7 +1167,7 @@ void Core::Account::unsubscribeFromContact(const QString& jid, const QString& re
void Core::Account::removeContactRequest(const QString& jid)
{
if (state == Shared::connected) {
if (state == Shared::ConnectionState::connected) {
std::set<QString>::const_iterator itr = outOfRosterContacts.find(jid);
if (itr != outOfRosterContacts.end()) {
outOfRosterContacts.erase(itr);
@ -1179,7 +1183,7 @@ void Core::Account::removeContactRequest(const QString& jid)
void Core::Account::addContactRequest(const QString& jid, const QString& name, const QSet<QString>& groups)
{
if (state == Shared::connected) {
if (state == Shared::ConnectionState::connected) {
std::map<QString, QString>::const_iterator itr = queuedContacts.find(jid);
if (itr != queuedContacts.end()) {
qDebug() << "An attempt to add contact " << jid << " to account " << name << " but the account is already queued for adding, skipping";


+ 3
- 3
core/account.h View File

@ -43,7 +43,7 @@
#include <QXmppVCardManager.h>
#include <QXmppMessageReceiptManager.h>
#include "global.h"
#include "shared.h"
#include "contact.h"
#include "conference.h"
#include "networkaccess.h"
@ -101,8 +101,8 @@ public slots:
signals:
void changed(const QMap<QString, QVariant>& data);
void connectionStateChanged(int);
void availabilityChanged(int);
void connectionStateChanged(Shared::ConnectionState);
void availabilityChanged(Shared::Availability);
void addGroup(const QString& name);
void removeGroup(const QString& name);
void addRoom(const QString& jid, const QMap<QString, QVariant>& data);


+ 1
- 1
core/archive.h View File

@ -24,7 +24,7 @@
#include <QMimeDatabase>
#include <QMimeType>
#include "global.h"
#include "shared/message.h"
#include "exception.h"
#include <lmdb.h>
#include <list>


+ 1
- 1
core/contact.cpp View File

@ -22,7 +22,7 @@
Core::Contact::Contact(const QString& pJid, const QString& account, QObject* parent):
RosterItem(pJid, account, parent),
groups(),
subscriptionState(Shared::unknown)
subscriptionState(Shared::SubscriptionState::unknown)
{
}


+ 3
- 1
core/rosteritem.h View File

@ -31,7 +31,9 @@
#include <QXmppVCardIq.h>
#include <QXmppPresence.h>
#include "../global.h"
#include "shared/enums.h"
#include "shared/message.h"
#include "shared/vcard.h"
#include "archive.h"
namespace Core {


+ 15
- 18
core/squawk.cpp View File

@ -146,8 +146,8 @@ void Core::Squawk::addAccount(const QString& login, const QString& server, const
{"name", name},
{"password", password},
{"resource", resource},
{"state", Shared::disconnected},
{"offline", Shared::offline},
{"state", QVariant::fromValue(Shared::ConnectionState::disconnected)},
{"offline", QVariant::fromValue(Shared::Availability::offline)},
{"error", ""},
{"avatarPath", acc->getAvatarPath()}
};
@ -155,14 +155,11 @@ void Core::Squawk::addAccount(const QString& login, const QString& server, const
emit newAccount(map);
}
void Core::Squawk::changeState(int p_state)
void Core::Squawk::changeState(Shared::Availability p_state)
{
Shared::Availability avail;
if (p_state < Shared::availabilityLowest && p_state > Shared::availabilityHighest) {
qDebug("An attempt to set invalid availability to Squawk core, skipping");
if (state != p_state) {
state = p_state;
}
avail = static_cast<Shared::Availability>(p_state);
state = avail;
for (std::deque<Account*>::iterator itr = accounts.begin(), end = accounts.end(); itr != end; ++itr) {
(*itr)->setAvailability(state);
@ -190,20 +187,20 @@ void Core::Squawk::disconnectAccount(const QString& account)
itr->second->disconnect();
}
void Core::Squawk::onAccountConnectionStateChanged(int state)
void Core::Squawk::onAccountConnectionStateChanged(Shared::ConnectionState p_state)
{
Account* acc = static_cast<Account*>(sender());
emit changeAccount(acc->getName(), {{"state", state}});
emit changeAccount(acc->getName(), {{"state", QVariant::fromValue(p_state)}});
if (state == Shared::disconnected) {
if (p_state == Shared::ConnectionState::disconnected) {
bool equals = true;
for (Accounts::const_iterator itr = accounts.begin(), end = accounts.end(); itr != end; itr++) {
if ((*itr)->getState() != Shared::disconnected) {
if ((*itr)->getState() != Shared::ConnectionState::disconnected) {
equals = false;
}
}
if (equals) {
state = Shared::offline;
if (equals && state != Shared::Availability::offline) {
state = Shared::Availability::offline;
emit stateChanged(state);
}
}
@ -257,10 +254,10 @@ void Core::Squawk::onAccountRemovePresence(const QString& jid, const QString& na
emit removePresence(acc->getName(), jid, name);
}
void Core::Squawk::onAccountAvailabilityChanged(int state)
void Core::Squawk::onAccountAvailabilityChanged(Shared::Availability state)
{
Account* acc = static_cast<Account*>(sender());
emit changeAccount(acc->getName(), {{"availability", state}});
emit changeAccount(acc->getName(), {{"availability", QVariant::fromValue(state)}});
}
void Core::Squawk::onAccountChanged(const QMap<QString, QVariant>& data)
@ -324,7 +321,7 @@ void Core::Squawk::modifyAccountRequest(const QString& name, const QMap<QString,
Core::Account* acc = itr->second;
Shared::ConnectionState st = acc->getState();
if (st != Shared::disconnected) {
if (st != Shared::ConnectionState::disconnected) {
acc->reconnect();
}
@ -367,7 +364,7 @@ void Core::Squawk::removeAccountRequest(const QString& name)
}
Account* acc = itr->second;
if (acc->getState() != Shared::disconnected) {
if (acc->getState() != Shared::ConnectionState::disconnected) {
acc->disconnect();
}


+ 7
- 5
core/squawk.h View File

@ -28,7 +28,9 @@
#include <deque>
#include "account.h"
#include "../global.h"
#include "shared/enums.h"
#include "shared/message.h"
#include "shared/global.h"
#include "networkaccess.h"
namespace Core
@ -54,7 +56,7 @@ signals:
void changeContact(const QString& account, const QString& jid, const QMap<QString, QVariant>& data);
void addPresence(const QString& account, const QString& jid, const QString& name, const QMap<QString, QVariant>& data);
void removePresence(const QString& account, const QString& jid, const QString& name);
void stateChanged(int state);
void stateChanged(Shared::Availability state);
void accountMessage(const QString& account, const Shared::Message& data);
void responseArchive(const QString& account, const QString& jid, const std::list<Shared::Message>& list);
void addRoom(const QString& account, const QString jid, const QMap<QString, QVariant>& data);
@ -79,7 +81,7 @@ public slots:
void removeAccountRequest(const QString& name);
void connectAccount(const QString& account);
void disconnectAccount(const QString& account);
void changeState(int state);
void changeState(Shared::Availability state);
void sendMessage(const QString& account, const Shared::Message& data);
void sendMessage(const QString& account, const Shared::Message& data, const QString& path);
void requestArchive(const QString& account, const QString& jid, int count, const QString& before);
@ -112,8 +114,8 @@ private:
void addAccount(const QString& login, const QString& server, const QString& password, const QString& name, const QString& resource);
private slots:
void onAccountConnectionStateChanged(int state);
void onAccountAvailabilityChanged(int state);
void onAccountConnectionStateChanged(Shared::ConnectionState state);
void onAccountAvailabilityChanged(Shared::Availability state);
void onAccountChanged(const QMap<QString, QVariant>& data);
void onAccountAddGroup(const QString& name);
void onAccountError(const QString& text);


+ 0
- 765
global.cpp View File

@ -1,765 +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 "global.h"
#include <uuid/uuid.h>
#include <QApplication>
#include <QPalette>
#include <QIcon>
#include <QDebug>
Shared::Message::Message(Shared::Message::Type p_type):
jFrom(),
rFrom(),
jTo(),
rTo(),
id(),
body(),
time(),
thread(),
type(p_type),
outgoing(false),
forwarded(false),
state(State::delivered),
edited(false)
{
}
Shared::Message::Message():
jFrom(),
rFrom(),
jTo(),
rTo(),
id(),
body(),
time(),
thread(),
type(Message::normal),
outgoing(false),
forwarded(false),
state(State::delivered),
edited(false),
errorText(),
originalMessage(),
lastModified()
{
}
QString Shared::Message::getBody() const
{
return body;
}
QString Shared::Message::getFrom() const
{
QString from = jFrom;
if (rFrom.size() > 0) {
from += "/" + rFrom;
}
return from;
}
QString Shared::Message::getTo() const
{
QString to = jTo;
if (rTo.size() > 0) {
to += "/" + rTo;
}
return to;
}
QString Shared::Message::getId() const
{
return id;
}
QDateTime Shared::Message::getTime() const
{
return time;
}
void Shared::Message::setBody(const QString& p_body)
{
body = p_body;
}
void Shared::Message::setFrom(const QString& from)
{
QStringList list = from.split("/");
if (list.size() == 1) {
jFrom = from;
} else {
jFrom = list.front();
rFrom = list.back();
}
}
void Shared::Message::setTo(const QString& to)
{
QStringList list = to.split("/");
if (list.size() == 1) {
jTo = to;
} else {
jTo = list.front();
rTo = list.back();
}
}
void Shared::Message::setId(const QString& p_id)
{
id = p_id;
}
void Shared::Message::setTime(const QDateTime& p_time)
{
time = p_time;
}
QString Shared::Message::getFromJid() const
{
return jFrom;
}
QString Shared::Message::getFromResource() const
{
return rFrom;
}
QString Shared::Message::getToJid() const
{
return jTo;
}
QString Shared::Message::getToResource() const
{
return rTo;
}
QString Shared::Message::getErrorText() const
{
return errorText;
}
QString Shared::Message::getPenPalJid() const
{
if (outgoing) {
return jTo;
} else {
return jFrom;
}
}
QString Shared::Message::getPenPalResource() const
{
if (outgoing) {
return rTo;
} else {
return rFrom;
}
}
Shared::Message::State Shared::Message::getState() const
{
return state;
}
bool Shared::Message::getEdited() const
{
return edited;
}
void Shared::Message::setFromJid(const QString& from)
{
jFrom = from;
}
void Shared::Message::setFromResource(const QString& from)
{
rFrom = from;
}
void Shared::Message::setToJid(const QString& to)
{
jTo = to;
}
void Shared::Message::setToResource(const QString& to)
{
rTo = to;
}
void Shared::Message::setErrorText(const QString& err)
{
if (state == State::error) {
errorText = err;
}
}
bool Shared::Message::getOutgoing() const
{
return outgoing;
}
void Shared::Message::setOutgoing(bool og)
{
outgoing = og;
}
bool Shared::Message::getForwarded() const
{
return forwarded;
}
void Shared::Message::generateRandomId()
{
id = generateUUID();
}
QString Shared::Message::getThread() const
{
return thread;
}
void Shared::Message::setForwarded(bool fwd)
{
forwarded = fwd;
}
void Shared::Message::setThread(const QString& p_body)
{
thread = p_body;
}
QDateTime Shared::Message::getLastModified() const
{
return lastModified;
}
QString Shared::Message::getOriginalBody() const
{
return originalMessage;
}
Shared::Message::Type Shared::Message::getType() const
{
return type;
}
void Shared::Message::setType(Shared::Message::Type t)
{
type = t;
}
void Shared::Message::setState(Shared::Message::State p_state)
{
state = p_state;
if (state != State::error) {
errorText = "";
}
}
bool Shared::Message::serverStored() const
{
return state == State::delivered || state == State::sent;
}
void Shared::Message::setEdited(bool p_edited)
{
edited = p_edited;
}
void Shared::Message::serialize(QDataStream& data) const
{
data << jFrom;
data << rFrom;
data << jTo;
data << rTo;
data << id;
data << body;
data << time;
data << thread;
data << (quint8)type;
data << outgoing;
data << forwarded;
data << oob;
data << (quint8)state;
data << edited;
if (state == State::error) {
data << errorText;
}
if (edited) {
data << originalMessage;
data << lastModified;
}
}
void Shared::Message::deserialize(QDataStream& data)
{
data >> jFrom;
data >> rFrom;
data >> jTo;
data >> rTo;
data >> id;
data >> body;
data >> time;
data >> thread;
quint8 t;
data >> t;
type = static_cast<Type>(t);
data >> outgoing;
data >> forwarded;
data >> oob;
quint8 s;
data >> s;
state = static_cast<State>(s);
data >> edited;
if (state == State::error) {
data >> errorText;
}
if (edited) {
data >> originalMessage;
data >> lastModified;
}
}
bool Shared::Message::change(const QMap<QString, QVariant>& data)
{
QMap<QString, QVariant>::const_iterator itr = data.find("state");
if (itr != data.end()) {
setState(static_cast<State>(itr.value().toUInt()));
}
if (state == State::error) {
itr = data.find("errorText");
if (itr != data.end()) {
setErrorText(itr.value().toString());
}
}
bool idChanged = false;
itr = data.find("id");
if (itr != data.end()) {
QString newId = itr.value().toString();
if (id != newId) {
setId(newId);
idChanged = true;
}
}
itr = data.find("body");
if (itr != data.end()) {
QMap<QString, QVariant>::const_iterator dItr = data.find("stamp");
QDateTime correctionDate;
if (dItr != data.end()) {
correctionDate = dItr.value().toDateTime();
} else {
correctionDate = QDateTime::currentDateTimeUtc(); //in case there is no information about time of this correction it's applied
}
if (!edited || lastModified < correctionDate) {
originalMessage = body;
lastModified = correctionDate;
setBody(itr.value().toString());
setEdited(true);
}
}
return idChanged;
}
QString Shared::generateUUID()
{
uuid_t uuid;
uuid_generate(uuid);
char uuid_str[36];
uuid_unparse_lower(uuid, uuid_str);
return uuid_str;
}
void Shared::Message::setCurrentTime()
{
time = QDateTime::currentDateTimeUtc();
}
QString Shared::Message::getOutOfBandUrl() const
{
return oob;
}
bool Shared::Message::hasOutOfBandUrl() const
{
return oob.size() > 0;
}
void Shared::Message::setOutOfBandUrl(const QString& url)
{
oob = url;
}
bool Shared::Message::storable() const
{
return id.size() > 0 && (body.size() > 0 || oob.size()) > 0;
}
Shared::VCard::Contact::Contact(Shared::VCard::Contact::Role p_role, bool p_prefered):
role(p_role),
prefered(p_prefered)
{}
Shared::VCard::Email::Email(const QString& addr, Shared::VCard::Contact::Role p_role, bool p_prefered):
Contact(p_role, p_prefered),
address(addr)
{}
Shared::VCard::Phone::Phone(const QString& nmbr, Shared::VCard::Phone::Type p_type, Shared::VCard::Contact::Role p_role, bool p_prefered):
Contact(p_role, p_prefered),
number(nmbr),
type(p_type)
{}
Shared::VCard::Address::Address(const QString& zCode, const QString& cntry, const QString& rgn, const QString& lclty, const QString& strt, const QString& ext, Shared::VCard::Contact::Role p_role, bool p_prefered):
Contact(p_role, p_prefered),
zipCode(zCode),
country(cntry),
region(rgn),
locality(lclty),
street(strt),
external(ext)
{}
Shared::VCard::VCard():
fullName(),
firstName(),
middleName(),
lastName(),
nickName(),
description(),
url(),
organizationName(),
organizationUnit(),
organizationRole(),
jobTitle(),
birthday(),
photoType(Avatar::empty),
photoPath(),
receivingTime(QDateTime::currentDateTimeUtc()),
emails(),
phones(),
addresses()
{}
Shared::VCard::VCard(const QDateTime& creationTime):
fullName(),
firstName(),
middleName(),
lastName(),
nickName(),
description(),
url(),
organizationName(),
organizationUnit(),
organizationRole(),
jobTitle(),
birthday(),
photoType(Avatar::empty),
photoPath(),
receivingTime(creationTime),
emails(),
phones(),
addresses()
{
}
QString Shared::VCard::getAvatarPath() const
{
return photoPath;
}
Shared::Avatar Shared::VCard::getAvatarType() const
{
return photoType;
}
QDate Shared::VCard::getBirthday() const
{
return birthday;
}
QString Shared::VCard::getDescription() const
{
return description;
}
QString Shared::VCard::getFirstName() const
{
return firstName;
}
QString Shared::VCard::getLastName() const
{
return lastName;
}
QString Shared::VCard::getMiddleName() const
{
return middleName;
}
QString Shared::VCard::getNickName() const
{
return nickName;
}
void Shared::VCard::setAvatarPath(const QString& path)
{
if (path != photoPath) {
photoPath = path;
}
}
void Shared::VCard::setAvatarType(Shared::Avatar type)
{
if (photoType != type) {
photoType = type;
}
}
void Shared::VCard::setBirthday(const QDate& date)
{
if (date.isValid() && birthday != date) {
birthday = date;
}
}
void Shared::VCard::setDescription(const QString& descr)
{
if (description != descr) {
description = descr;
}
}
void Shared::VCard::setFirstName(const QString& first)
{
if (firstName != first) {
firstName = first;
}
}
void Shared::VCard::setLastName(const QString& last)
{
if (lastName != last) {
lastName = last;
}
}
void Shared::VCard::setMiddleName(const QString& middle)
{
if (middleName != middle) {
middleName = middle;
}
}
void Shared::VCard::setNickName(const QString& nick)
{
if (nickName != nick) {
nickName = nick;
}
}
QString Shared::VCard::getFullName() const
{
return fullName;
}
QString Shared::VCard::getUrl() const
{
return url;
}
void Shared::VCard::setFullName(const QString& name)
{
if (fullName != name) {
fullName = name;
}
}
void Shared::VCard::setUrl(const QString& u)
{
if (url != u) {
url = u;
}
}
QString Shared::VCard::getOrgName() const
{
return organizationName;
}
QString Shared::VCard::getOrgRole() const
{
return organizationRole;
}
QString Shared::VCard::getOrgTitle() const
{
return jobTitle;
}
QString Shared::VCard::getOrgUnit() const
{
return organizationUnit;
}
void Shared::VCard::setOrgName(const QString& name)
{
if (organizationName != name) {
organizationName = name;
}
}
void Shared::VCard::setOrgRole(const QString& role)
{
if (organizationRole != role) {
organizationRole = role;
}
}
void Shared::VCard::setOrgTitle(const QString& title)
{
if (jobTitle != title) {
jobTitle = title;
}
}
void Shared::VCard::setOrgUnit(const QString& unit)
{
if (organizationUnit != unit) {
organizationUnit = unit;
}
}
QDateTime Shared::VCard::getReceivingTime() const
{
return receivingTime;
}
std::deque<Shared::VCard::Email> & Shared::VCard::getEmails()
{
return emails;
}
std::deque<Shared::VCard::Address> & Shared::VCard::getAddresses()
{
return addresses;
}
std::deque<Shared::VCard::Phone> & Shared::VCard::getPhones()
{
return phones;
}
const std::deque<Shared::VCard::Email> & Shared::VCard::getEmails() const
{
return emails;
}
const std::deque<Shared::VCard::Address> & Shared::VCard::getAddresses() const
{
return addresses;
}
const std::deque<Shared::VCard::Phone> & Shared::VCard::getPhones() const
{
return phones;
}
const std::deque<QString>Shared::VCard::Contact::roleNames = {"Not specified", "Personal", "Business"};
const std::deque<QString>Shared::VCard::Phone::typeNames = {"Fax", "Pager", "Voice", "Cell", "Video", "Modem", "Other"};
QIcon Shared::availabilityIcon(Shared::Availability av, bool big)
{
const std::deque<QString>& fallback = QApplication::palette().window().color().lightnessF() > 0.5 ?
big ?
Shared::fallbackAvailabilityThemeIconsDarkBig:
Shared::fallbackAvailabilityThemeIconsDarkSmall:
big ?
Shared::fallbackAvailabilityThemeIconsLightBig:
Shared::fallbackAvailabilityThemeIconsLightSmall;
return QIcon::fromTheme(availabilityThemeIcons[av], QIcon(fallback[av]));
}
QIcon Shared::subscriptionStateIcon(Shared::SubscriptionState ss, bool big)
{
const std::deque<QString>& fallback = QApplication::palette().window().color().lightnessF() > 0.5 ?
big ?
Shared::fallbackSubscriptionStateThemeIconsDarkBig:
Shared::fallbackSubscriptionStateThemeIconsDarkSmall:
big ?
Shared::fallbackSubscriptionStateThemeIconsLightBig:
Shared::fallbackSubscriptionStateThemeIconsLightSmall;
return QIcon::fromTheme(subscriptionStateThemeIcons[ss], QIcon(fallback[ss]));
}
QIcon Shared::connectionStateIcon(Shared::ConnectionState cs, bool big)
{
const std::deque<QString>& fallback = QApplication::palette().window().color().lightnessF() > 0.5 ?
big ?
Shared::fallbackConnectionStateThemeIconsDarkBig:
Shared::fallbackConnectionStateThemeIconsDarkSmall:
big ?
Shared::fallbackConnectionStateThemeIconsLightBig:
Shared::fallbackConnectionStateThemeIconsLightSmall;
return QIcon::fromTheme(connectionStateThemeIcons[cs], QIcon(fallback[cs]));
}
static const QString ds = ":images/fallback/dark/small/";
static const QString db = ":images/fallback/dark/big/";
static const QString ls = ":images/fallback/light/small/";
static const QString lb = ":images/fallback/light/big/";
QIcon Shared::icon(const QString& name, bool big)
{
std::map<QString, std::pair<QString, QString>>::const_iterator itr = icons.find(name);
if (itr != icons.end()) {
const QString& prefix = QApplication::palette().window().color().lightnessF() > 0.5 ?
big ? db : ds:
big ? lb : ls;
return QIcon::fromTheme(itr->second.first, QIcon(prefix + itr->second.second + ".svg"));
} else {
qDebug() << "Icon" << name << "not found";
return QIcon::fromTheme(name);
}
}
QString Shared::iconPath(const QString& name, bool big)
{
QString result = "";
std::map<QString, std::pair<QString, QString>>::const_iterator itr = icons.find(name);
if (itr != icons.end()) {
const QString& prefix = QApplication::palette().window().color().lightnessF() > 0.5 ?
big ? db : ds:
big ? lb : ls;
result = prefix + itr->second.second + ".svg";
}
return result;
}

+ 0
- 512
global.h View File

@ -1,512 +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 GLOBAL_H
#define GLOBAL_H
#include <QString>
#include <QMap>
#include <QCoreApplication>
#include <deque>
#include <QDateTime>
#include <QDataStream>
#include <QColor>
namespace Shared {
enum ConnectionState {
disconnected,
connecting,
connected,
error
};
enum Availability {
online,
away,
extendedAway,
busy,
chatty,
invisible,
offline
};
enum SubscriptionState {
none,
from,
to,
both,
unknown
};
enum class Affiliation {
unspecified,
outcast,
nobody,
member,
admin,
owner
};
enum class Role {
unspecified,
nobody,
visitor,
participant,
moderator
};
enum class Avatar {
empty,
autocreated,
valid
};
static const Availability availabilityHighest = offline;
static const Availability availabilityLowest = online;
static const SubscriptionState subscriptionStateHighest = unknown;
static const SubscriptionState subscriptionStateLowest = none;
static const Affiliation affiliationHighest = Affiliation::owner;
static const Affiliation affiliationLowest = Affiliation::unspecified;
static const Role roleHighest = Role::moderator;
static const Role roleLowest = Role::unspecified;
static const std::deque<QString> connectionStateNames = {"Disconnected", "Connecting", "Connected", "Error"};
static const std::deque<QString> connectionStateThemeIcons = {"state-offline", "state-sync", "state-ok", "state-error"};
static const std::deque<QString> availabilityThemeIcons = {
"user-online",
"user-away",
"user-away-extended",
"user-busy",
"chatty",
"user-invisible",
"user-offline"
};
static const std::deque<QString> availabilityNames = {"Online", "Away", "Absent", "Busy", "Chatty", "Invisible", "Offline"};
static const std::deque<QString> subscriptionStateThemeIcons = {"edit-none", "arrow-down-double", "arrow-up-double", "dialog-ok", "question"};
static const std::deque<QString> subscriptionStateNames = {"None", "From", "To", "Both", "Unknown"};
static const std::deque<QString> affiliationNames = {"Unspecified", "Outcast", "Nobody", "Member", "Admin", "Owner"};
static const std::deque<QString> roleNames = {"Unspecified", "Nobody", "Visitor", "Participant", "Moderator"};
static const std::deque<QString> messageStateNames = {"Pending", "Sent", "Delivered", "Error"};
static const std::deque<QString> messageStateThemeIcons = {"state-offline", "state-sync", "state-ok", "state-error"};
QString generateUUID();
static const std::vector<QColor> colorPalette = {
QColor(244, 27, 63),
QColor(21, 104, 156),
QColor(38, 156, 98),
QColor(247, 103, 101),
QColor(121, 37, 117),
QColor(242, 202, 33),
QColor(168, 22, 63),
QColor(35, 100, 52),
QColor(52, 161, 152),
QColor(239, 53, 111),
QColor(237, 234, 36),
QColor(153, 148, 194),
QColor(211, 102, 151),
QColor(194, 63, 118),
QColor(249, 149, 51),
QColor(244, 206, 109),
QColor(121, 105, 153),
QColor(244, 199, 30),
QColor(28, 112, 28),
QColor(172, 18, 20),
QColor(25, 66, 110),
QColor(25, 149, 104),
QColor(214, 148, 0),
QColor(203, 47, 57),
QColor(4, 54, 84),
QColor(116, 161, 97),
QColor(50, 68, 52),
QColor(237, 179, 20),
QColor(69, 114, 147),
QColor(242, 212, 31),
QColor(248, 19, 20),
QColor(84, 102, 84),
QColor(25, 53, 122),
QColor(91, 91, 109),
QColor(17, 17, 80),
QColor(54, 54, 94)
};
class Message {
public:
enum Type {
error,
normal,
chat,
groupChat,
headline
};
enum class State {
pending,
sent,
delivered,
error
};
Message(Type p_type);
Message();
void setFrom(const QString& from);
void setFromResource(const QString& from);
void setFromJid(const QString& from);
void setTo(const QString& to);
void setToResource(const QString& to);
void setToJid(const QString& to);
void setTime(const QDateTime& p_time);
void setId(const QString& p_id);
void setBody(const QString& p_body);
void setThread(const QString& p_body);
void setOutgoing(bool og);
void setForwarded(bool fwd);
void setType(Type t);
void setCurrentTime();
void setOutOfBandUrl(const QString& url);
void setState(State p_state);
void setEdited(bool p_edited);
void setErrorText(const QString& err);
bool change(const QMap<QString, QVariant>& data);
QString getFrom() const;
QString getFromJid() const;
QString getFromResource() const;
QString getTo() const;
QString getToJid() const;
QString getToResource() const;
QDateTime getTime() const;
QString getId() const;
QString getBody() const;
QString getThread() const;
bool getOutgoing() const;
bool getForwarded() const;
Type getType() const;
bool hasOutOfBandUrl() const;
bool storable() const;
QString getOutOfBandUrl() const;
State getState() const;
bool getEdited() const;
QString getErrorText() const;
QString getPenPalJid() const;
QString getPenPalResource() const;
void generateRandomId();
bool serverStored() const;
QDateTime getLastModified() const;
QString getOriginalBody() const;
void serialize(QDataStream& data) const;
void deserialize(QDataStream& data);
private:
QString jFrom;