diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index f8bc03c..c65eb23 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,43 +1,43 @@
# set Kaidans sources (used in main cmake file)
set(KAIDAN_SOURCES
src/main.cpp
src/Kaidan.cpp
src/ClientWorker.cpp
src/AvatarFileStorage.cpp
src/Database.cpp
src/RosterModel.cpp
src/RosterManager.cpp
src/RegistrationManager.cpp
src/MessageHandler.cpp
src/MessageModel.cpp
src/Notifications.cpp
src/PresenceCache.cpp
src/DiscoveryManager.cpp
src/VCardManager.cpp
src/LogHandler.cpp
src/StatusBar.cpp
src/UploadManager.cpp
src/EmojiModel.cpp
src/TransferCache.cpp
src/DownloadManager.cpp
- src/Utils.cpp
+ src/QmlUtils.cpp
# needed to trigger moc generation
src/Enums.h
# kaidan QXmpp extensions (need to be merged into QXmpp upstream)
src/qxmpp-exts/QXmppHttpUploadIq.cpp
src/qxmpp-exts/QXmppUploadRequestManager.cpp
src/qxmpp-exts/QXmppUploadManager.cpp
src/qxmpp-exts/QXmppColorGenerator.cpp
# hsluv-c required for color generation
src/hsluv-c/hsluv.c
)
if(NOT ANDROID AND NOT IOS)
set(KAIDAN_SOURCES ${KAIDAN_SOURCES}
src/singleapp/singleapplication.cpp
src/singleapp/singleapplication_p.cpp
)
endif()
diff --git a/src/Kaidan.cpp b/src/Kaidan.cpp
index cca3c81..5c56abf 100644
--- a/src/Kaidan.cpp
+++ b/src/Kaidan.cpp
@@ -1,221 +1,221 @@
/*
* Kaidan - A user-friendly XMPP client for every device!
*
* Copyright (C) 2016-2019 Kaidan developers and contributors
* (see the LICENSE file for a full list of copyright authors)
*
* Kaidan 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.
*
* In addition, as a special exception, the author of Kaidan gives
* permission to link the code of its release with the OpenSSL
* project's "OpenSSL" library (or with modified versions of it that
* use the same license as the "OpenSSL" library), and distribute the
* linked executables. You must obey the GNU General Public License in
* all respects for all of the code used other than "OpenSSL". If you
* modify this file, you may extend this exception to your version of
* the file, but you are not obligated to do so. If you do not wish to
* do so, delete this exception statement from your version.
*
* Kaidan 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 Kaidan. If not, see .
*/
#include "Kaidan.h"
// Qt
#include
#include
#include
// QXmpp
#include
#include "qxmpp-exts/QXmppColorGenerator.h"
// Kaidan
#include "AvatarFileStorage.h"
#include "Database.h"
#include "RosterModel.h"
#include "MessageModel.h"
#include "PresenceCache.h"
-#include "Utils.h"
+#include "QmlUtils.h"
Kaidan *Kaidan::s_instance = nullptr;
Kaidan::Kaidan(QGuiApplication *app, bool enableLogging, QObject *parent)
- : QObject(parent), utils(new Utils(this)), database(new Database())
+ : QObject(parent), m_utils(new QmlUtils(this)), database(new Database())
{
Q_ASSERT(!Kaidan::s_instance);
Kaidan::s_instance = this;
// Database setup
database->openDatabase();
if (database->needToConvert())
database->convertDatabase();
// Caching components
caches = new ClientWorker::Caches(database, this);
// Connect the avatar changed signal of the avatarStorage with the NOTIFY signal
// of the Q_PROPERTY for the avatar storage (so all avatars are updated in QML)
connect(caches->avatarStorage, &AvatarFileStorage::avatarIdsChanged,
this, &Kaidan::avatarStorageChanged);
//
// Load settings
//
creds.jid = caches->settings->value(KAIDAN_SETTINGS_AUTH_JID).toString();
creds.jidResource = caches->settings->value(KAIDAN_SETTINGS_AUTH_RESOURCE)
.toString();
creds.password = QString(QByteArray::fromBase64(caches->settings->value(
KAIDAN_SETTINGS_AUTH_PASSWD).toString().toUtf8()));
// use Kaidan as resource, if no set
if (creds.jidResource.isEmpty())
setJidResource(APPLICATION_DISPLAY_NAME);
creds.isFirstTry = false;
//
// Start ClientWorker on new thread
//
cltThrd = new ClientThread();
client = new ClientWorker(caches, this, enableLogging, app);
client->setCredentials(creds);
connect(client, &ClientWorker::disconnReasonChanged, this, &Kaidan::setDisconnReason);
client->moveToThread(cltThrd);
connect(cltThrd, &QThread::started, client, &ClientWorker::main);
cltThrd->start();
}
Kaidan::~Kaidan()
{
delete caches;
delete database;
Kaidan::s_instance = nullptr;
}
void Kaidan::start()
{
if (creds.jid.isEmpty() || creds.password.isEmpty())
emit newCredentialsNeeded();
else
mainConnect();
}
void Kaidan::mainConnect()
{
if (connectionState != ConnectionState::StateDisconnected) {
qWarning() << "[main] Tried to connect, even if still connected!"
<< "Requesting disconnect.";
emit client->disconnectRequested();
}
emit client->credentialsUpdated(creds);
emit client->connectRequested();
// update own JID to display correct messages
caches->msgModel->setOwnJid(creds.jid);
}
void Kaidan::mainDisconnect(bool openLogInPage)
{
// disconnect the client if connected or connecting
if (connectionState != ConnectionState::StateDisconnected)
emit client->disconnectRequested();
if (openLogInPage) {
// clear password
caches->settings->remove(KAIDAN_SETTINGS_AUTH_PASSWD);
setPassword(QString());
// trigger log in page
emit newCredentialsNeeded();
}
}
void Kaidan::setConnectionState(QXmppClient::State state)
{
this->connectionState = (ConnectionState) state;
emit connectionStateChanged();
// Open the possibly cached URI when connected.
// This is needed because the XMPP URIs can't be opened when Kaidan is not connected.
if (connectionState == ConnectionState::StateConnected && !openUriCache.isEmpty()) {
// delay is needed because sometimes the RosterPage needs to be loaded first
QTimer::singleShot(300, [=] () {
emit xmppUriReceived(openUriCache);
openUriCache = "";
});
}
}
void Kaidan::setDisconnReason(DisconnectionReason reason)
{
disconnReason = reason;
emit disconnReasonChanged();
}
void Kaidan::setJid(const QString &jid)
{
creds.jid = jid;
// credentials were modified -> first try
creds.isFirstTry = true;
}
void Kaidan::setJidResource(const QString &jidResource)
{
// JID resource won't influence the authentication, so we don't need
// to set the first try flag and can save it.
creds.jidResource = jidResource;
caches->settings->setValue(KAIDAN_SETTINGS_AUTH_RESOURCE, jidResource);
}
void Kaidan::setPassword(const QString &password)
{
creds.password = password;
// credentials were modified -> first try
creds.isFirstTry = true;
}
void Kaidan::setChatPartner(const QString &chatPartner)
{
// check if different
if (this->chatPartner == chatPartner)
return;
this->chatPartner = chatPartner;
emit chatPartnerChanged(chatPartner);
caches->msgModel->applyRecipientFilter(chatPartner);
}
quint8 Kaidan::getDisconnReason() const
{
return static_cast(disconnReason);
}
void Kaidan::addOpenUri(const QByteArray &uri)
{
qDebug() << "[main]" << uri;
if (!uri.startsWith("xmpp:") || !uri.contains("@"))
return;
if (connectionState == ConnectionState::StateConnected) {
emit xmppUriReceived(QString::fromUtf8(uri));
} else {
//: The link is an XMPP-URI (i.e. 'xmpp:kaidan@muc.kaidan.im?join' for joining a chat)
emit passiveNotificationRequested(tr("The link will be opened after you have connected."));
openUriCache = QString::fromUtf8(uri);
}
}
Kaidan *Kaidan::instance()
{
return s_instance;
}
diff --git a/src/Kaidan.h b/src/Kaidan.h
index 5f23345..f7bf5b5 100644
--- a/src/Kaidan.h
+++ b/src/Kaidan.h
@@ -1,425 +1,425 @@
/*
* Kaidan - A user-friendly XMPP client for every device!
*
* Copyright (C) 2016-2019 Kaidan developers and contributors
* (see the LICENSE file for a full list of copyright authors)
*
* Kaidan 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.
*
* In addition, as a special exception, the author of Kaidan gives
* permission to link the code of its release with the OpenSSL
* project's "OpenSSL" library (or with modified versions of it that
* use the same license as the "OpenSSL" library), and distribute the
* linked executables. You must obey the GNU General Public License in
* all respects for all of the code used other than "OpenSSL". If you
* modify this file, you may extend this exception to your version of
* the file, but you are not obligated to do so. If you do not wish to
* do so, delete this exception statement from your version.
*
* Kaidan 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 Kaidan. If not, see .
*/
#ifndef KAIDAN_H
#define KAIDAN_H
// Qt
#include
#include
#include
// Kaidan
#include "ClientWorker.h"
#include "Globals.h"
#include "Enums.h"
class QGuiApplication;
class Database;
class QXmppClient;
-class Utils;
+class QmlUtils;
using namespace Enums;
/**
* @class Kaidan Kaidan's Back-End Class
*
* @brief This class will initiate the complete back-end, including the @see Database
* connection, viewing models (@see MessageModel, @see RosterModel), etc.
*
* This class will run in the main thread, only the XMPP connection runs in another
* thread (@see ClientThread).
*/
class Kaidan : public QObject
{
Q_OBJECT
- Q_PROPERTY(Utils* utils READ getUtils CONSTANT)
+ Q_PROPERTY(QmlUtils* utils READ getUtils CONSTANT)
Q_PROPERTY(RosterModel* rosterModel READ getRosterModel CONSTANT)
Q_PROPERTY(MessageModel* messageModel READ getMessageModel CONSTANT)
Q_PROPERTY(AvatarFileStorage* avatarStorage READ getAvatarStorage NOTIFY avatarStorageChanged)
Q_PROPERTY(PresenceCache* presenceCache READ getPresenceCache CONSTANT)
Q_PROPERTY(TransferCache* transferCache READ getTransferCache CONSTANT)
Q_PROPERTY(QSettings* settings READ getSettings CONSTANT)
Q_PROPERTY(quint8 connectionState READ getConnectionState NOTIFY connectionStateChanged)
Q_PROPERTY(quint8 disconnReason READ getDisconnReason NOTIFY disconnReasonChanged)
Q_PROPERTY(QString jid READ getJid WRITE setJid NOTIFY jidChanged)
Q_PROPERTY(QString jidResource READ getJidResource WRITE setJidResource NOTIFY jidResourceChanged)
Q_PROPERTY(QString password READ getPassword WRITE setPassword NOTIFY passwordChanged)
Q_PROPERTY(QString chatPartner READ getChatPartner WRITE setChatPartner NOTIFY chatPartnerChanged)
Q_PROPERTY(bool uploadServiceFound READ getUploadServiceFound NOTIFY uploadServiceFoundChanged)
public:
Kaidan(QGuiApplication *app, bool enableLogging = true, QObject *parent = nullptr);
~Kaidan();
/**
* Start connection (called from QML when ready)
*/
Q_INVOKABLE void start();
/**
* Connect to the XMPP server
*
* If you haven't set a username and password, they are used from the
* last successful login (the settings file).
*/
Q_INVOKABLE void mainConnect();
/**
* Disconnect from XMPP server
*
* This will disconnect the client from the server. When disconnected,
* the connectionStateChanged signal will be emitted.
*
* @param openLogInPage If true, the newCredentialsNeeded signal will be
* emitted.
*/
Q_INVOKABLE void mainDisconnect(bool openLogInPage = false);
/**
* Returns the current ConnectionState
*/
Q_INVOKABLE quint8 getConnectionState() const
{
return (quint8) connectionState;
}
/**
* Returns the last disconnection reason
*/
Q_INVOKABLE quint8 getDisconnReason() const;
/**
* Set own JID used for connection
*
* To really change the JID of the current connection, you'll need to
* reconnect.
*/
void setJid(const QString &jid);
/**
* Get the current JID
*/
QString getJid() const
{
return creds.jid;
}
/**
* Set a optional custom JID resource (device name)
*/
void setJidResource(const QString &jidResource);
/**
* Get the JID resoruce
*/
QString getJidResource() const
{
return creds.jidResource;
}
/**
* Set the password for next connection
*/
void setPassword(const QString &password);
/**
* Get the currently used password
*/
QString getPassword() const
{
return creds.password;
}
/**
* Set the currently opened chat
*
* This will set a filter on the database to only view the related messages.
*/
void setChatPartner(const QString &jid);
/**
* Get the currrently opened chat
*/
QString getChatPartner() const
{
return chatPartner;
}
RosterModel* getRosterModel() const
{
return caches->rosterModel;
}
MessageModel* getMessageModel() const
{
return caches->msgModel;
}
AvatarFileStorage* getAvatarStorage() const
{
return caches->avatarStorage;
}
PresenceCache* getPresenceCache() const
{
return caches->presCache;
}
TransferCache* getTransferCache() const
{
return caches->transferCache;
}
QSettings* getSettings() const
{
return caches->settings;
}
- Utils* getUtils() const
+ QmlUtils* getUtils() const
{
- return utils;
+ return m_utils;
}
/**
* Adds XMPP URI to open as soon as possible
*/
void addOpenUri(const QByteArray &uri);
/**
* Returns whether an HTTP File Upload service has been found
*/
bool getUploadServiceFound() const
{
return uploadServiceFound;
}
static Kaidan *instance();
signals:
void avatarStorageChanged();
/**
* Emitted, when the client's connection state has changed (e.g. when
* successfully connected or when disconnected)
*/
void connectionStateChanged();
/**
* Emitted, when the client failed to connect and gives the reason in
* a DisconnectionReason enumatrion.
*/
void disconnReasonChanged();
/**
* Emitted when the JID was changed
*/
void jidChanged();
/**
* Emitted when the JID resouce (device name) has changed
*/
void jidResourceChanged();
/**
* Emitted when the used password for logging in has changed
*/
void passwordChanged();
/**
* Emitted when the currently opnened chat has changed
*/
void chatPartnerChanged(QString chatPartner);
/**
* Emitted when there are no (correct) credentials and new are needed
*
* The client will be in disconnected state, when this is emitted.
*/
void newCredentialsNeeded();
/**
* Emitted when log in worked with new credentials
*
* The client will be in connected state, when this is emitted.
*/
void logInWorked();
/**
* Show passive notification
*/
void passiveNotificationRequested(QString text);
/**
* Emitted, whan a subscription request was received
*/
void subscriptionRequestReceived(QString from, QString msg);
/**
* Incoming subscription request was accepted or declined by the user
*/
void subscriptionRequestAnswered(QString jid, bool accepted);
/**
* Request vCard of any JID
*
* Is required when the avatar (or other information) of a JID are
* requested and the JID is not in the roster.
*/
void vCardRequested(QString jid);
/**
* XMPP URI received
*
* Is called when Kaidan was used to open an XMPP URI (i.e. 'xmpp:kaidan@muc.kaidan.im?join')
*/
void xmppUriReceived(QString uri);
/**
* The upload progress of a file upload has changed
*/
void uploadProgressMade(QString msgId, unsigned long sent, unsigned long total);
/**
* An HTTP File Upload service was discovered
*/
void uploadServiceFoundChanged();
/**
* Send a text message to any JID
*
* Currently only contacts are displayed on the RosterPage (there is no
* way to view a list of all chats -> for contacts and non-contacts), so
* you should only send messages to JIDs from your roster, otherwise you
* won't be able to see the message history.
*/
void sendMessage(QString jid, QString message, bool isSpoiler, QString spoilerHint);
/**
* Correct the last message
*
* To get/check the last message id, use `kaidan.messageModel.lastMessageId(jid)`
*/
void correctMessage(QString toJid, QString msgId, QString message);
/**
* Upload and send file
*/
void sendFile(QString jid, QString filePath, QString message);
/**
* Add a contact to your roster
*
* @param nick A simple nick name for the new contact, which should be
* used to display in the roster.
*/
void addContact(QString jid, QString nick, QString msg);
/**
* Remove a contact from your roster
*
* Only the JID is needed.
*/
void removeContact(QString jid);
/**
* Downloads an attached media file of a message
*
* @param msgId The message
* @param url the media url from the message
*/
void downloadMedia(QString msgId, QString url);
/**
* Changes the user's password on the server
*
* @param newPassword The new password
*/
void changePassword(const QString &newPassword);
/**
* Emitted, when changing the password has succeeded.
*/
void passwordChangeSucceeded();
/**
* Emitted, when changing the password has failed.
*/
void passwordChangeFailed();
public slots:
/**
* Set current connection state
*/
void setConnectionState(QXmppClient::State state);
/**
* Sets the disconnection error/reason
*/
void setDisconnReason(DisconnectionReason reason);
/**
* Receives messages from another instance of the application
*/
void receiveMessage(quint32, QByteArray msg)
{
// currently we only send XMPP URIs
addOpenUri(msg);
}
/**
* Enables HTTP File Upload to be used (will be called from UploadManager)
*/
void setUploadServiceFound(bool enabled)
{
uploadServiceFound = enabled;
emit uploadServiceFoundChanged();
}
private:
void connectDatabases();
- Utils *utils;
+ QmlUtils *m_utils;
Database *database;
ClientWorker::Caches *caches;
ClientThread *cltThrd;
ClientWorker *client;
ClientWorker::Credentials creds;
QString chatPartner;
QString openUriCache;
bool uploadServiceFound = false;
ConnectionState connectionState = ConnectionState::StateDisconnected;
DisconnReason disconnReason = DisconnReason::ConnNoError;
static Kaidan *s_instance;
};
#endif
diff --git a/src/Utils.cpp b/src/QmlUtils.cpp
similarity index 88%
rename from src/Utils.cpp
rename to src/QmlUtils.cpp
index 2aff763..fb9fe79 100644
--- a/src/Utils.cpp
+++ b/src/QmlUtils.cpp
@@ -1,140 +1,140 @@
/*
* Kaidan - A user-friendly XMPP client for every device!
*
* Copyright (C) 2016-2019 Kaidan developers and contributors
* (see the LICENSE file for a full list of copyright authors)
*
* Kaidan 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.
*
* In addition, as a special exception, the author of Kaidan gives
* permission to link the code of its release with the OpenSSL
* project's "OpenSSL" library (or with modified versions of it that
* use the same license as the "OpenSSL" library), and distribute the
* linked executables. You must obey the GNU General Public License in
* all respects for all of the code used other than "OpenSSL". If you
* modify this file, you may extend this exception to your version of
* the file, but you are not obligated to do so. If you do not wish to
* do so, delete this exception statement from your version.
*
* Kaidan 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 Kaidan. If not, see .
*/
-#include "Utils.h"
+#include "QmlUtils.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "qxmpp-exts/QXmppColorGenerator.h"
-Utils::Utils(QObject *parent)
+QmlUtils::QmlUtils(QObject *parent)
: QObject(parent)
{
}
-QString Utils::getResourcePath(const QString &name) const
+QString QmlUtils::getResourcePath(const QString &name) const
{
// We generally prefer to first search for files in application resources
if (QFile::exists(":/" + name))
return QString("qrc:/" + name);
// list of file paths where to search for the resource file
QStringList pathList;
// add relative path from binary (only works if installed)
pathList << QCoreApplication::applicationDirPath() + QString("/../share/") + QString(APPLICATION_NAME);
// get the standard app data locations for current platform
pathList << QStandardPaths::standardLocations(QStandardPaths::AppDataLocation);
#ifdef UBUNTU_TOUCH
pathList << QString("./share/") + QString(APPLICATION_NAME);
#endif
#ifndef NDEBUG
#ifdef DEBUG_SOURCE_PATH
// add source directory (only for debug builds)
pathList << QString(DEBUG_SOURCE_PATH) + QString("/data");
#endif
#endif
// search for file in directories
for (int i = 0; i < pathList.size(); i++) {
// open directory
QDir directory(pathList.at(i));
// look up the file
if (directory.exists(name)) {
// found the file, return the path
return QUrl::fromLocalFile(directory.absoluteFilePath(name)).toString();
}
}
// no file found
qWarning() << "[main] Could NOT find media file:" << name;
return "";
}
-bool Utils::isImageFile(const QUrl &fileUrl) const
+bool QmlUtils::isImageFile(const QUrl &fileUrl) const
{
QMimeType type = QMimeDatabase().mimeTypeForUrl(fileUrl);
return type.inherits("image/jpeg") || type.inherits("image/png");
}
-void Utils::copyToClipboard(const QString &text) const
+void QmlUtils::copyToClipboard(const QString &text) const
{
QGuiApplication::clipboard()->setText(text);
}
-QString Utils::fileNameFromUrl(const QUrl &url) const
+QString QmlUtils::fileNameFromUrl(const QUrl &url) const
{
return QUrl(url).fileName();
}
-QString Utils::fileSizeFromUrl(const QUrl &url) const
+QString QmlUtils::fileSizeFromUrl(const QUrl &url) const
{
#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0) // Qt 5.10 or later
return QLocale::system().formattedDataSize(QFileInfo(QUrl(url).toLocalFile())
.size());
#else
// before Qt 5.10 there was no formattedDataSize() method:
// sizes will always be in MiB
double size = QFileInfo(QUrl(url).toLocalFile()).size();
return QString::number(qRound(size / 1024.0 / 10.24) / 100.0).append(" MiB");
#endif
}
-QString Utils::formatMessage(const QString &message) const
+QString QmlUtils::formatMessage(const QString &message) const
{
// escape all special XML chars (like '<' and '>')
// and spilt into words for processing
return processMsgFormatting(message.toHtmlEscaped().split(" "));
}
-QColor Utils::getUserColor(const QString &nickName) const
+QColor QmlUtils::getUserColor(const QString &nickName) const
{
QXmppColorGenerator::RGBColor color = QXmppColorGenerator::generateColor(nickName);
return QColor(color.red, color.green, color.blue);
}
-QString Utils::processMsgFormatting(const QStringList &list, bool isFirst) const
+QString QmlUtils::processMsgFormatting(const QStringList &list, bool isFirst) const
{
if (list.isEmpty())
return "";
// link highlighting
if (list.first().startsWith("https://") || list.first().startsWith("http://"))
return (isFirst ? "" : " ") + QString("%1").arg(list.first())
+ processMsgFormatting(list.mid(1), false);
return (isFirst ? "" : " ") + list.first() + processMsgFormatting(list.mid(1), false);
}
diff --git a/src/Utils.h b/src/QmlUtils.h
similarity index 97%
rename from src/Utils.h
rename to src/QmlUtils.h
index 132633b..cbc78a0 100644
--- a/src/Utils.h
+++ b/src/QmlUtils.h
@@ -1,118 +1,118 @@
/*
* Kaidan - A user-friendly XMPP client for every device!
*
* Copyright (C) 2016-2019 Kaidan developers and contributors
* (see the LICENSE file for a full list of copyright authors)
*
* Kaidan 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.
*
* In addition, as a special exception, the author of Kaidan gives
* permission to link the code of its release with the OpenSSL
* project's "OpenSSL" library (or with modified versions of it that
* use the same license as the "OpenSSL" library), and distribute the
* linked executables. You must obey the GNU General Public License in
* all respects for all of the code used other than "OpenSSL". If you
* modify this file, you may extend this exception to your version of
* the file, but you are not obligated to do so. If you do not wish to
* do so, delete this exception statement from your version.
*
* Kaidan 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 Kaidan. If not, see .
*/
#ifndef UTILS_H
#define UTILS_H
#include
#include "Globals.h"
/**
* @brief C++ utitlities to be used in QML
*
* The methods are not static, because they need to be used from QML and registered in
* Qt.
*/
-class Utils : public QObject
+class QmlUtils : public QObject
{
Q_OBJECT
public:
- Utils(QObject *parent = nullptr);
+ QmlUtils(QObject *parent = nullptr);
public slots:
/**
* Returns a URL to a given resource file name
*
* This will check various paths which could contain the searched file.
* If the file was found, it'll return a `file://` or a `qrc:/` url to
* the file.
*/
QString getResourcePath(const QString &resourceName) const;
/**
* Returns a string of this build's Kaidan version
*/
QString getVersionString() const
{
return VERSION_STRING;
}
/**
* Returns a string without new lines, unneeded spaces, etc.
*
* See QString::simplified for more information.
*/
QString removeNewLinesFromString(const QString &input) const
{
return input.simplified();
}
/**
* Checks whether a file is an image and could be displayed as such.
* @param fileUrl URL to the possible image file
*/
bool isImageFile(const QUrl &fileUrl) const;
/**
* Copy text to the clipboard
*/
void copyToClipboard(const QString &text) const;
/**
* Returns the file name from a URL
*/
QString fileNameFromUrl(const QUrl &url) const;
/**
* Returns the file size from a URL
*/
QString fileSizeFromUrl(const QUrl &url) const;
/**
* Styles/formats a message for displaying
*
* This currently only adds some link highlighting
*/
QString formatMessage(const QString &message) const;
/**
* Returns a consistent user color generated from the nickname.
*/
QColor getUserColor(const QString &nickName) const;
private:
/**
* Highlights links in a list of words
*/
QString processMsgFormatting(const QStringList &words, bool isFirst = true) const;
};
#endif // UTILS_H
diff --git a/src/main.cpp b/src/main.cpp
index 8222652..709128f 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1,283 +1,283 @@
/*
* Kaidan - A user-friendly XMPP client for every device!
*
* Copyright (C) 2016-2019 Kaidan developers and contributors
* (see the LICENSE file for a full list of copyright authors)
*
* Kaidan 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.
*
* In addition, as a special exception, the author of Kaidan gives
* permission to link the code of its release with the OpenSSL
* project's "OpenSSL" library (or with modified versions of it that
* use the same license as the "OpenSSL" library), and distribute the
* linked executables. You must obey the GNU General Public License in
* all respects for all of the code used other than "OpenSSL". If you
* modify this file, you may extend this exception to your version of
* the file, but you are not obligated to do so. If you do not wish to
* do so, delete this exception statement from your version.
*
* Kaidan 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 Kaidan. If not, see .
*/
// Qt
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
// QXmpp
#include
#include "qxmpp-exts/QXmppUploadManager.h"
// Kaidan
#include "Kaidan.h"
#include "RosterModel.h"
#include "MessageModel.h"
#include "AvatarFileStorage.h"
#include "PresenceCache.h"
#include "UploadManager.h"
#include "Globals.h"
#include "Enums.h"
#include "StatusBar.h"
#include "EmojiModel.h"
-#include "Utils.h"
+#include "QmlUtils.h"
#ifdef STATIC_BUILD
#include "static_plugins.h"
#endif
#ifndef QAPPLICATION_CLASS
#define QAPPLICATION_CLASS QApplication
#endif
#include QT_STRINGIFY(QAPPLICATION_CLASS)
#if !defined(Q_OS_IOS) && !defined(Q_OS_ANDROID)
// SingleApplication (Qt5 replacement for QtSingleApplication)
#include "singleapp/singleapplication.h"
#endif
#ifdef STATIC_BUILD
#define KIRIGAMI_BUILD_TYPE_STATIC
#include "./3rdparty/kirigami/src/kirigamiplugin.h"
#endif
#ifdef Q_OS_ANDROID
#include
#endif
#ifdef Q_OS_WIN
#include
#endif
enum CommandLineParseResult {
CommandLineOk,
CommandLineError,
CommandLineVersionRequested,
CommandLineHelpRequested
};
CommandLineParseResult parseCommandLine(QCommandLineParser &parser, QString *errorMessage)
{
// application description
parser.setApplicationDescription(QString(APPLICATION_DISPLAY_NAME) +
" - " + QString(APPLICATION_DESCRIPTION));
// add all possible arguments
QCommandLineOption helpOption = parser.addHelpOption();
QCommandLineOption versionOption = parser.addVersionOption();
parser.addOption({"disable-xml-log", "Disable output of full XMPP XML stream."});
parser.addOption({{"m", "multiple"}, "Allow multiple instances to be started."});
parser.addPositionalArgument("xmpp-uri", "An XMPP-URI to open (i.e. join a chat).",
"[xmpp-uri]");
// parse arguments
if (!parser.parse(QGuiApplication::arguments())) {
*errorMessage = parser.errorText();
return CommandLineError;
}
// check for special cases
if (parser.isSet(versionOption))
return CommandLineVersionRequested;
if (parser.isSet(helpOption))
return CommandLineHelpRequested;
// if nothing special happened, return OK
return CommandLineOk;
}
Q_DECL_EXPORT int main(int argc, char *argv[])
{
#ifdef Q_OS_WIN
if (AttachConsole(ATTACH_PARENT_PROCESS)) {
freopen("CONOUT$", "w", stdout);
freopen("CONOUT$", "w", stderr);
}
#endif
// initialize random generator
qsrand(time(nullptr));
//
// App
//
#ifdef UBUNTU_TOUCH
qputenv("QT_AUTO_SCREEN_SCALE_FACTOR", "true");
qputenv("QT_QUICK_CONTROLS_MOBILE", "true");
#endif
// name, display name, description
QGuiApplication::setApplicationName(APPLICATION_NAME);
QGuiApplication::setApplicationDisplayName(APPLICATION_DISPLAY_NAME);
QGuiApplication::setApplicationVersion(VERSION_STRING);
// attributes
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
// create a qt app
#if defined(Q_OS_IOS) || defined(Q_OS_ANDROID)
QGuiApplication app(argc, argv);
#else
SingleApplication app(argc, argv, true);
#endif
// register qMetaTypes
qRegisterMetaType("RosterModel*");
qRegisterMetaType("MessageModel*");
qRegisterMetaType("Message");
qRegisterMetaType("AvatarFileStorage*");
qRegisterMetaType("ContactMap");
qRegisterMetaType("PresenceCache*");
qRegisterMetaType("QXmppPresence");
qRegisterMetaType("Credentials");
qRegisterMetaType("Qt::ApplicationState");
qRegisterMetaType("QXmppClient::State");
qRegisterMetaType("MessageType");
qRegisterMetaType("DisconnectionReason");
qRegisterMetaType("TransferJob*");
- qRegisterMetaType("Utils*");
+ qRegisterMetaType("QmlUtils*");
// Qt-Translator
QTranslator qtTranslator;
qtTranslator.load("qt_" + QLocale::system().name(),
QLibraryInfo::location(QLibraryInfo::TranslationsPath));
app.installTranslator(&qtTranslator);
// Kaidan-Translator
QTranslator kaidanTranslator;
// load the systems locale or none from resources
kaidanTranslator.load(QLocale::system().name(), ":/i18n");
app.installTranslator(&kaidanTranslator);
//
// Command line arguments
//
// create parser and add a description
QCommandLineParser parser;
// parse the arguments
QString commandLineErrorMessage;
switch (parseCommandLine(parser, &commandLineErrorMessage)) {
case CommandLineError:
qWarning() << commandLineErrorMessage;
return 1;
case CommandLineVersionRequested:
parser.showVersion();
return 0;
case CommandLineHelpRequested:
parser.showHelp();
return 0;
case CommandLineOk:
break;
}
#if !defined(Q_OS_IOS) && !defined(Q_OS_ANDROID)
// check if another instance already runs
if (app.isSecondary() && !parser.isSet("multiple")) {
qDebug().noquote() << QString("Another instance of %1 is already running.")
.arg(APPLICATION_DISPLAY_NAME)
<< "You can enable multiple instances by specifying '--multiple'.";
// send a possible link to the primary instance
if (!parser.positionalArguments().isEmpty())
app.sendMessage(parser.positionalArguments()[0].toUtf8());
return 0;
}
#endif
//
// Kaidan back-end
//
Kaidan kaidan(&app, !parser.isSet("disable-xml-log"));
#if !defined(Q_OS_IOS) && !defined(Q_OS_ANDROID)
// receive messages from other instances of Kaidan
kaidan.connect(&app, &SingleApplication::receivedMessage,
&kaidan, &Kaidan::receiveMessage);
#endif
// open the XMPP-URI/link (if given)
if (!parser.positionalArguments().isEmpty())
kaidan.addOpenUri(parser.positionalArguments()[0].toUtf8());
//
// QML-GUI
//
if (QIcon::themeName().isEmpty()) {
QIcon::setThemeName("breeze");
}
QQmlApplicationEngine engine;
// QtQuickControls2 Style
if (qgetenv("QT_QUICK_CONTROLS_STYLE").isEmpty()) {
#ifdef Q_OS_WIN
QString defaultStyle = "Universal";
#else
QString defaultStyle = "Material";
#endif
qDebug() << "QT_QUICK_CONTROLS_STYLE not set, setting to" << defaultStyle;
qputenv("QT_QUICK_CONTROLS_STYLE", defaultStyle.toLatin1());
}
// QML type bindings
#ifdef STATIC_BUILD
KirigamiPlugin::getInstance().registerTypes();
#endif
qmlRegisterType("StatusBar", 0, 1, "StatusBar");
qmlRegisterType("EmojiModel", 0, 1, "EmojiModel");
qmlRegisterType("EmojiModel", 0, 1, "EmojiProxyModel");
qmlRegisterUncreatableType("EmojiModel", 0, 1, "QAbstractItemModel", "Used by proxy models");
qmlRegisterUncreatableType("EmojiModel", 0, 1, "Emoji", "Used by emoji models");
qmlRegisterUncreatableMetaObject(Enums::staticMetaObject, APPLICATION_ID,
1, 0, "Enums", "Can't create object; only enums defined!");
engine.rootContext()->setContextProperty("kaidan", &kaidan);
engine.load(QUrl("qrc:/qml/main.qml"));
if(engine.rootObjects().isEmpty())
return -1;
#ifdef Q_OS_ANDROID
QtAndroid::hideSplashScreen();
#endif
// enter qt main loop
return app.exec();
}