Members of the KDE Community are recommended to subscribe to the kde-community mailing list at https://mail.kde.org/mailman/listinfo/kde-community to allow them to participate in important discussions and receive other important announcements

Verified Commit 3a7b0bb0 authored by Linus Jahn's avatar Linus Jahn

Clean up Kaidan.cpp and move utils to external class

parent 074fcddb
......@@ -21,6 +21,7 @@ set(KAIDAN_SOURCES
${CURDIR}/EmojiModel.cpp
${CURDIR}/TransferCache.cpp
${CURDIR}/DownloadManager.cpp
${CURDIR}/Utils.cpp
# needed to trigger moc generation
${CURDIR}/Enums.h
......
......@@ -44,6 +44,11 @@
#define APPLICATION_DESCRIPTION "A simple, user-friendly Jabber/XMPP client"
#define VERSION_STRING "0.4.0-dev"
// Kaidan settings
#define KAIDAN_SETTINGS_AUTH_JID "auth/jid"
#define KAIDAN_SETTINGS_AUTH_RESOURCE "auth/resource"
#define KAIDAN_SETTINGS_AUTH_PASSWD "auth/password"
// XML namespaces
#define NS_SPOILERS "urn:xmpp:spoiler:0"
......
......@@ -50,18 +50,18 @@
#include "RosterModel.h"
#include "MessageModel.h"
#include "PresenceCache.h"
#include "Utils.h"
Kaidan::Kaidan(QGuiApplication *app, bool enableLogging, QObject *parent) : QObject(parent)
Kaidan::Kaidan(QGuiApplication *app, bool enableLogging, QObject *parent)
: QObject(parent), utils(new Utils(this)), database(new Database())
{
// Database setup
database = new Database();
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,
......@@ -71,20 +71,20 @@ Kaidan::Kaidan(QGuiApplication *app, bool enableLogging, QObject *parent) : QObj
// Load settings
//
creds.jid = caches->settings->value("auth/jid").toString();
creds.jidResource = caches->settings->value("auth/resource").toString();
creds.password = QString(QByteArray::fromBase64(caches->settings->value("auth/password")
.toString().toUtf8()));
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(QString(APPLICATION_NAME));
setJidResource(APPLICATION_DISPLAY_NAME);
creds.isFirstTry = false;
//
// Start ClientWorker on new thread
//
// create new thread for client connection
cltThrd = new ClientThread();
client = new ClientWorker(caches, this, enableLogging, app);
client->setCredentials(creds);
......@@ -161,14 +161,14 @@ void Kaidan::setDisconnReason(DisconnectionReason reason)
emit disconnReasonChanged();
}
void Kaidan::setJid(QString jid)
void Kaidan::setJid(const QString &jid)
{
creds.jid = jid;
// credentials were modified -> first try
creds.isFirstTry = true;
}
void Kaidan::setJidResource(QString jidResource)
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.
......@@ -177,14 +177,14 @@ void Kaidan::setJidResource(QString jidResource)
caches->settings->setValue("auth/resource", jidResource);
}
void Kaidan::setPassword(QString password)
void Kaidan::setPassword(const QString &password)
{
creds.password = password;
// credentials were modified -> first try
creds.isFirstTry = true;
}
void Kaidan::setChatPartner(QString chatPartner)
void Kaidan::setChatPartner(const QString &chatPartner)
{
// check if different
if (this->chatPartner == chatPartner)
......@@ -200,45 +200,7 @@ quint8 Kaidan::getDisconnReason() const
return (quint8) disconnReason;
}
QString Kaidan::getResourcePath(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 QString("");
}
void Kaidan::addOpenUri(QByteArray uri)
void Kaidan::addOpenUri(const QByteArray &uri)
{
qDebug() << "[main]" << uri;
......@@ -253,65 +215,3 @@ void Kaidan::addOpenUri(QByteArray uri)
openUriCache = QString::fromUtf8(uri);
}
}
void Kaidan::copyToClipboard(QString text)
{
QClipboard *clipboard = QGuiApplication::clipboard();
clipboard->setText(text);
}
bool Kaidan::isImageFile(QString fileUrl) const
{
QMimeDatabase mimeDb;
QMimeType type = mimeDb.mimeTypeForUrl(QUrl(fileUrl));
if (type.inherits("image/jpeg") || type.inherits("image/png"))
return true;
return false;
}
QString Kaidan::fileNameFromUrl(QString url)
{
return QUrl(url).fileName();
}
QString Kaidan::fileSizeFromUrl(QString url)
{
#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0) // Qt 5.10 or later
qint64 size = QFileInfo(QUrl(url).toLocalFile()).size();
return QLocale::system().formattedDataSize(size);
#else
// before Qt 5.10: 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 Kaidan::formatMessage(QString message)
{
// escape all special XML chars (as '<' and '>')
message = message.toHtmlEscaped();
return processMsgFormatting(message.split(" "));
}
QColor Kaidan::getUserColor(QString nickName) const
{
QXmppColorGenerator::RGBColor color = QXmppColorGenerator::generateColor(nickName);
return QColor(color.red, color.green, color.blue);
}
QString Kaidan::processMsgFormatting(QStringList list, bool isFirst)
{
if (list.isEmpty())
return "";
// add space before word (if word is not the first)
QString prepend = isFirst ? "" : " ";
// link highlighting
if (list.first().startsWith("https://") || list.first().startsWith("http://"))
return prepend + QString("<a href='%1'>%1</a>").arg(list.first())
+ processMsgFormatting(list.mid(1), false);
return prepend + list.first() + processMsgFormatting(list.mid(1), false);
}
......@@ -43,6 +43,7 @@
class QGuiApplication;
class Database;
class QXmppClient;
class Utils;
using namespace Enums;
......@@ -59,6 +60,7 @@ class Kaidan : public QObject
{
Q_OBJECT
Q_PROPERTY(Utils* 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)
......@@ -74,7 +76,6 @@ class Kaidan : public QObject
public:
Kaidan(QGuiApplication *app, bool enableLogging = true, QObject *parent = nullptr);
~Kaidan();
/**
......@@ -101,15 +102,6 @@ public:
*/
Q_INVOKABLE void mainDisconnect(bool openLogInPage = false);
/**
* 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.
*/
Q_INVOKABLE QString getResourcePath(QString resourceName) const;
/**
* Returns the current ConnectionState
*/
......@@ -123,37 +115,13 @@ public:
*/
Q_INVOKABLE quint8 getDisconnReason() const;
/**
* Returns a string of this build's Kaidan version
*/
Q_INVOKABLE QString getVersionString() const
{
return QString(VERSION_STRING);
}
/**
* Returns a string without new lines, unneeded spaces, etc.
*
* See QString::simplified for more information.
*/
Q_INVOKABLE QString removeNewLinesFromString(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
*/
Q_INVOKABLE bool isImageFile(QString fileUrl) const;
/**
* Set own JID used for connection
*
* To really change the JID of the current connection, you'll need to
* reconnect.
*/
void setJid(QString jid);
void setJid(const QString &jid);
/**
* Get the current JID
......@@ -166,7 +134,7 @@ public:
/**
* Set a optional custom JID resource (device name)
*/
void setJidResource(QString jidResource);
void setJidResource(const QString &jidResource);
/**
* Get the JID resoruce
......@@ -179,7 +147,7 @@ public:
/**
* Set the password for next connection
*/
void setPassword(QString password);
void setPassword(const QString &password);
/**
* Get the currently used password
......@@ -194,7 +162,7 @@ public:
*
* This will set a filter on the database to only view the related messages.
*/
void setChatPartner(QString jid);
void setChatPartner(const QString &jid);
/**
* Get the currrently opened chat
......@@ -229,15 +197,15 @@ public:
return caches->transferCache;
}
/**
* Adds XMPP URI to open as soon as possible
*/
void addOpenUri(QByteArray uri);
Utils* getUtils() const
{
return utils;
}
/**
* Copy text to the clipboard
* Adds XMPP URI to open as soon as possible
*/
Q_INVOKABLE void copyToClipboard(QString text);
void addOpenUri(const QByteArray &uri);
/**
* Returns whether an HTTP File Upload service has been found
......@@ -247,28 +215,6 @@ public:
return uploadServiceFound;
}
/**
* Returns the file name from a URL
*/
Q_INVOKABLE QString fileNameFromUrl(QString url);
/**
* Returns the file size from a URL
*/
Q_INVOKABLE QString fileSizeFromUrl(QString url);
/**
* Styles/formats a message for displaying
*
* This currently only adds some link highlighting
*/
Q_INVOKABLE QString formatMessage(QString message);
/**
* Returns a consistent user color generated from the nickname.
*/
Q_INVOKABLE QColor getUserColor(QString nickName) const;
signals:
void avatarStorageChanged();
......@@ -435,20 +381,15 @@ public slots:
private:
void connectDatabases();
/**
* Highlights links in a list of words
*/
QString processMsgFormatting(QStringList words, bool isFirst = true);
ClientWorker *client;
ClientThread *cltThrd;
Utils *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;
......
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "Utils.h"
#include <QColor>
#include <QClipboard>
#include <QDebug>
#include <QDir>
#include <QFile>
#include <QFileInfo>
#include <QGuiApplication>
#include <QMimeDatabase>
#include <QUrl>
#include <QStandardPaths>
#include "qxmpp-exts/QXmppColorGenerator.h"
Utils::Utils(QObject *parent)
: QObject(parent)
{
}
QString Utils::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
{
QMimeType type = QMimeDatabase().mimeTypeForUrl(fileUrl);
return type.inherits("image/jpeg") || type.inherits("image/png");
}
void Utils::copyToClipboard(const QString &text) const
{
QGuiApplication::clipboard()->setText(text);
}
QString Utils::fileNameFromUrl(const QUrl &url) const
{
return QUrl(url).fileName();
}
QString Utils::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
{
// 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
{
QXmppColorGenerator::RGBColor color = QXmppColorGenerator::generateColor(nickName);
return QColor(color.red, color.green, color.blue);
}
QString Utils::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("<a href='%1'>%1</a>").arg(list.first())
+ processMsgFormatting(list.mid(1), false);
return (isFirst ? "" : " ") + list.first() + processMsgFormatting(list.mid(1), false);
}
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#ifndef UTILS_H
#define UTILS_H
#include <QObject>
#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
{
Q_OBJECT
public:
Utils(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
......@@ -55,6 +55,7 @@
#include "Enums.h"
#include "StatusBar.h"
#include "EmojiModel.h"
#include "Utils.h"
#ifdef STATIC_BUILD
#include "static_plugins.h"
......@@ -169,6 +170,7 @@ Q_DECL_EXPORT int main(int argc, char *argv[])
qRegisterMetaType<DisconnectionReason>("DisconnectionReason");
qRegisterMetaType<EmojiModel*>("EmojiModel");
qRegisterMetaType<TransferJob*>("TransferJob*");
qRegisterMetaType<Utils*>("Utils*");
// Qt-Translator
QTranslator qtTranslator;
......@@ -244,7 +246,6 @@ Q_DECL_EXPORT int main(int argc, char *argv[])
}
QQmlApplicationEngine engine;
#ifndef SAILFISH_OS
// QtQuickControls2 Style
if (qgetenv("QT_QUICK_CONTROLS_STYLE").isEmpty()) {
#ifdef Q_OS_WIN
......@@ -255,7 +256,6 @@ Q_DECL_EXPORT int main(int argc, char *argv[])
qDebug() << "QT_QUICK_CONTROLS_STYLE not set, setting to" << defaultStyle;
qputenv("QT_QUICK_CONTROLS_STYLE", defaultStyle.toLatin1());
}
#endif
// QML type bindings
#ifdef STATIC_BUILD
KirigamiPlugin::getInstance().registerTypes();
......@@ -271,7 +271,6 @@ Q_DECL_EXPORT int main(int argc, char *argv[])
return -1;
#ifdef Q_OS_ANDROID
//TODO: use QQmlApplicationEngine::objectCreated to ensure QML was actually loaded?
QtAndroid::hideSplashScreen();
#endif
......
......@@ -46,7 +46,7 @@ Controls.Dialog {
rowSpacing: 20
Image {
source: kaidan.getResourcePath("images/kaidan.svg")
source: kaidan.utils.getResourcePath("images/kaidan.svg")
Layout.preferredWidth: Kirigami.Units.gridUnit * 9
Layout.preferredHeight: Kirigami.Units.gridUnit * 9
Layout.fillWidth: true
......@@ -63,7 +63,7 @@ Controls.Dialog {
spacing: Kirigami.gridUnit * 0.6
Kirigami.Heading {
text: "Kaidan " + kaidan.getVersionString()
text: "Kaidan " + kaidan.utils.getVersionString()
textFormat: Text.PlainText