301 lines
9.5 KiB
C++
301 lines
9.5 KiB
C++
/*
|
|
* 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/>.
|
|
*/
|
|
|
|
// Qt
|
|
#include <QCommandLineOption>
|
|
#include <QCommandLineParser>
|
|
#include <QDebug>
|
|
#include <QIcon>
|
|
#include <QLibraryInfo>
|
|
#include <QLocale>
|
|
#include <QQmlApplicationEngine>
|
|
#include <QQmlContext>
|
|
#include <QTranslator>
|
|
#include <qqml.h>
|
|
|
|
// QXmpp
|
|
#include "qxmpp-exts/QXmppUploadManager.h"
|
|
#include <QXmppClient.h>
|
|
|
|
// Kaidan
|
|
#include "AvatarFileStorage.h"
|
|
#include "EmojiModel.h"
|
|
#include "Enums.h"
|
|
#include "Globals.h"
|
|
#include "Kaidan.h"
|
|
#include "Message.h"
|
|
#include "MessageModel.h"
|
|
#include "PresenceCache.h"
|
|
#include "QmlUtils.h"
|
|
#include "RosterModel.h"
|
|
#include "StatusBar.h"
|
|
#include "UploadManager.h"
|
|
#include "EmojiModel.h"
|
|
#include "Utils.h"
|
|
#include "QrCodeScannerFilter.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 <QtAndroid>
|
|
#endif
|
|
|
|
#ifdef Q_OS_WIN
|
|
#include <windows.h>
|
|
#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);
|
|
QGuiApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
|
|
|
|
// 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<RosterItem>("RosterItem");
|
|
qRegisterMetaType<RosterModel*>("RosterModel*");
|
|
qRegisterMetaType<Message>("Message");
|
|
qRegisterMetaType<MessageModel*>("MessageModel*");
|
|
qRegisterMetaType<AvatarFileStorage*>("AvatarFileStorage*");
|
|
qRegisterMetaType<PresenceCache*>("PresenceCache*");
|
|
qRegisterMetaType<QXmppPresence>("QXmppPresence");
|
|
qRegisterMetaType<ClientWorker::Credentials>("Credentials");
|
|
qRegisterMetaType<Qt::ApplicationState>("Qt::ApplicationState");
|
|
qRegisterMetaType<QXmppClient::State>("QXmppClient::State");
|
|
qRegisterMetaType<MessageType>("MessageType");
|
|
qRegisterMetaType<DisconnectionReason>("DisconnectionReason");
|
|
qRegisterMetaType<TransferJob*>("TransferJob*");
|
|
qRegisterMetaType<QmlUtils*>("QmlUtils*");
|
|
qRegisterMetaType<QVector<Message>>("QVector<Message>");
|
|
qRegisterMetaType<QVector<RosterItem>>("QVector<RosterItem>");
|
|
qRegisterMetaType<QHash<QString,RosterItem>>("QHash<QString,RosterItem>");
|
|
qRegisterMetaType<std::function<void(RosterItem&)>>("std::function<void(RosterItem&)>");
|
|
qRegisterMetaType<std::function<void(Message&)>>("std::function<void(Message&)>");
|
|
qRegisterMetaType<ClientWorker::Credentials>("ClientWorker::Credentials");
|
|
// Enums for c++ member calls using enums
|
|
qRegisterMetaType<Enums::ConnectionState>();
|
|
qRegisterMetaType<Enums::DisconnectionReason>();
|
|
qRegisterMetaType<Enums::MessageType>();
|
|
qRegisterMetaType<Enums::AvailabilityTypes>();
|
|
|
|
// Qt-Translator
|
|
QTranslator qtTranslator;
|
|
qtTranslator.load("qt_" + QLocale::system().name(),
|
|
QLibraryInfo::location(QLibraryInfo::TranslationsPath));
|
|
QCoreApplication::installTranslator(&qtTranslator);
|
|
|
|
// Kaidan-Translator
|
|
QTranslator kaidanTranslator;
|
|
// load the systems locale or none from resources
|
|
kaidanTranslator.load(QLocale::system().name(), ":/i18n");
|
|
QCoreApplication::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().first().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().first());
|
|
|
|
//
|
|
// QML-GUI
|
|
//
|
|
|
|
if (QIcon::themeName().isEmpty()) {
|
|
QIcon::setThemeName("breeze");
|
|
}
|
|
|
|
QQmlApplicationEngine engine;
|
|
// QtQuickControls2 Style
|
|
if (qEnvironmentVariableIsEmpty("QT_QUICK_CONTROLS_STYLE")) {
|
|
#ifdef Q_OS_WIN
|
|
const QString defaultStyle = QStringLiteral("Universal");
|
|
#else
|
|
const QString defaultStyle = QStringLiteral("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>("StatusBar", 0, 1, "StatusBar");
|
|
qmlRegisterType<EmojiModel>("EmojiModel", 0, 1, "EmojiModel");
|
|
qmlRegisterType<EmojiProxyModel>("EmojiModel", 0, 1, "EmojiProxyModel");
|
|
qmlRegisterType<QrCodeScannerFilter>(APPLICATION_ID, 1, 0, "QrCodeScannerFilter");
|
|
|
|
qmlRegisterUncreatableType<QAbstractItemModel>("EmojiModel", 0, 1, "QAbstractItemModel", "Used by proxy models");
|
|
qmlRegisterUncreatableType<Emoji>("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();
|
|
}
|