mirror of
https://github.com/qTox/qTox.git
synced 2024-03-22 14:00:36 +08:00
Previously HiDPI support is conditionally enabled based on compilation parameters as well as environmental variables which makes binary distribution difficult. This commit automatically enables runtime DPI scaling if Qt supports it (version 5.6 and beyond).
308 lines
9.2 KiB
C++
308 lines
9.2 KiB
C++
/*
|
|
Copyright © 2014-2015 by The qTox Project
|
|
|
|
This file is part of qTox, a Qt-based graphical interface for Tox.
|
|
|
|
qTox is libre 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.
|
|
|
|
qTox 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 qTox. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "widget/widget.h"
|
|
#include "persistence/settings.h"
|
|
#include "src/nexus.h"
|
|
#include "src/ipc.h"
|
|
#include "src/net/toxuri.h"
|
|
#include "src/net/autoupdate.h"
|
|
#include "src/persistence/toxsave.h"
|
|
#include "src/persistence/profile.h"
|
|
#include "src/widget/loginscreen.h"
|
|
#include "src/widget/translator.h"
|
|
#include "src/video/camerasource.h"
|
|
#include <QApplication>
|
|
#include <QCommandLineParser>
|
|
#include <QDateTime>
|
|
#include <QDebug>
|
|
#include <QDir>
|
|
#include <QFile>
|
|
#include <QMutex>
|
|
#include <QFontDatabase>
|
|
#include <QMutexLocker>
|
|
|
|
#include <sodium.h>
|
|
#include <stdio.h>
|
|
|
|
#if defined(Q_OS_OSX)
|
|
#include "platform/install_osx.h"
|
|
#endif
|
|
|
|
#ifdef LOG_TO_FILE
|
|
static QAtomicPointer<FILE> logFileFile = nullptr;
|
|
static QList<QByteArray>* logBuffer = new QList<QByteArray>(); //Store log messages until log file opened
|
|
QMutex* logBufferMutex = new QMutex();
|
|
#endif
|
|
|
|
void logMessageHandler(QtMsgType type, const QMessageLogContext& ctxt, const QString& msg)
|
|
{
|
|
// Silence qWarning spam due to bug in QTextBrowser (trying to open a file for base64 images)
|
|
if (ctxt.function == QString("virtual bool QFSFileEngine::open(QIODevice::OpenMode)")
|
|
&& msg == QString("QFSFileEngine::open: No file name specified"))
|
|
return;
|
|
|
|
QString LogMsg = QString("[%1] %2:%3 : ")
|
|
.arg(QTime::currentTime().toString("HH:mm:ss.zzz")).arg(ctxt.file).arg(ctxt.line);
|
|
switch (type)
|
|
{
|
|
case QtDebugMsg:
|
|
LogMsg += "Debug";
|
|
break;
|
|
case QtWarningMsg:
|
|
LogMsg += "Warning";
|
|
break;
|
|
case QtCriticalMsg:
|
|
LogMsg += "Critical";
|
|
break;
|
|
case QtFatalMsg:
|
|
LogMsg += "Fatal";
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
LogMsg += ": " + msg + "\n";
|
|
QByteArray LogMsgBytes = LogMsg.toUtf8();
|
|
fwrite(LogMsgBytes.constData(), 1, LogMsgBytes.size(), stderr);
|
|
|
|
#ifdef LOG_TO_FILE
|
|
FILE * logFilePtr = logFileFile.load(); // atomically load the file pointer
|
|
if (!logFilePtr)
|
|
{
|
|
logBufferMutex->lock();
|
|
if(logBuffer)
|
|
{
|
|
logBuffer->append(LogMsgBytes);
|
|
}
|
|
logBufferMutex->unlock();
|
|
}
|
|
else
|
|
{
|
|
logBufferMutex->lock();
|
|
if(logBuffer)
|
|
{
|
|
// empty logBuffer to file
|
|
foreach(QByteArray msg, *logBuffer)
|
|
{
|
|
fwrite(msg.constData(), 1, msg.size(), logFilePtr);
|
|
}
|
|
|
|
delete logBuffer; // no longer needed
|
|
logBuffer = nullptr;
|
|
}
|
|
logBufferMutex->unlock();
|
|
|
|
fwrite(LogMsgBytes.constData(), 1, LogMsgBytes.size(), logFilePtr);
|
|
fflush(logFilePtr);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
|
|
#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
|
|
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
|
QGuiApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
|
|
#endif
|
|
|
|
qInstallMessageHandler(logMessageHandler);
|
|
|
|
QApplication a(argc, argv);
|
|
a.setApplicationName("qTox");
|
|
a.setOrganizationName("Tox");
|
|
a.setApplicationVersion("\nGit commit: " + QString(GIT_VERSION));
|
|
|
|
#if defined(Q_OS_OSX)
|
|
//osx::moveToAppFolder(); TODO: Add setting to enable this feature.
|
|
osx::migrateProfiles();
|
|
#endif
|
|
|
|
qsrand(time(0));
|
|
Settings::getInstance();
|
|
Translator::translate();
|
|
|
|
// Process arguments
|
|
QCommandLineParser parser;
|
|
parser.setApplicationDescription("qTox, version: " + QString(GIT_VERSION) + "\nBuilt: " + __TIME__ + " " + __DATE__);
|
|
parser.addHelpOption();
|
|
parser.addVersionOption();
|
|
parser.addPositionalArgument("uri", QObject::tr("Tox URI to parse"));
|
|
parser.addOption(QCommandLineOption("p", QObject::tr("Starts new instance and loads specified profile."), QObject::tr("profile")));
|
|
parser.process(a);
|
|
|
|
#ifndef Q_OS_ANDROID
|
|
IPC& ipc = IPC::getInstance();
|
|
#endif
|
|
|
|
if (sodium_init() < 0) // For the auto-updater
|
|
{
|
|
qCritical() << "Can't init libsodium";
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
#ifdef LOG_TO_FILE
|
|
QString logFileDir = Settings::getInstance().getAppCacheDirPath();
|
|
QDir(logFileDir).mkpath(".");
|
|
|
|
QString logfile = logFileDir + "qtox.log";
|
|
FILE * mainLogFilePtr = fopen(logfile.toLocal8Bit().constData(), "a");
|
|
|
|
// Trim log file if over 1MB
|
|
if (QFileInfo(logfile).size() > 1000000)
|
|
{
|
|
qDebug() << "Log file over 1MB, rotating...";
|
|
|
|
QDir dir (logFileDir);
|
|
|
|
// Check if log.1 already exists, and if so, delete it
|
|
if (dir.remove(logFileDir + "qtox.log.1"))
|
|
qDebug() << "Removed old log successfully";
|
|
else
|
|
qWarning() << "Unable to remove old log file";
|
|
|
|
if(!dir.rename(logFileDir + "qtox.log", logFileDir + "qtox.log.1"))
|
|
qCritical() << "Unable to move logs";
|
|
|
|
// close old logfile
|
|
if(mainLogFilePtr)
|
|
fclose(mainLogFilePtr);
|
|
|
|
// open a new logfile
|
|
mainLogFilePtr = fopen(logfile.toLocal8Bit().constData(), "a");
|
|
}
|
|
|
|
if(!mainLogFilePtr)
|
|
qCritical() << "Couldn't open logfile" << logfile;
|
|
|
|
logFileFile.store(mainLogFilePtr); // atomically set the logFile
|
|
#endif
|
|
|
|
// Windows platform plugins DLL hell fix
|
|
QCoreApplication::addLibraryPath(QCoreApplication::applicationDirPath());
|
|
a.addLibraryPath("platforms");
|
|
|
|
qDebug() << "built on: " << __TIME__ << __DATE__ << "(" << TIMESTAMP << ")";
|
|
qDebug() << "commit: " << GIT_VERSION << "\n";
|
|
|
|
// Install Unicode 6.1 supporting font
|
|
QFontDatabase::addApplicationFont("://DejaVuSans.ttf");
|
|
|
|
// Check whether we have an update waiting to be installed
|
|
#if AUTOUPDATE_ENABLED
|
|
if (AutoUpdater::isLocalUpdateReady())
|
|
AutoUpdater::installLocalUpdate(); ///< NORETURN
|
|
#endif
|
|
|
|
|
|
QString profileName;
|
|
bool autoLogin = Settings::getInstance().getAutoLogin();
|
|
#ifndef Q_OS_ANDROID
|
|
// Inter-process communication
|
|
ipc.registerEventHandler("uri", &toxURIEventHandler);
|
|
ipc.registerEventHandler("save", &toxSaveEventHandler);
|
|
ipc.registerEventHandler("activate", &toxActivateEventHandler);
|
|
|
|
uint32_t ipcDest = 0;
|
|
QString eventType, firstParam;
|
|
if (parser.isSet("p"))
|
|
{
|
|
profileName = parser.value("p");
|
|
if (!Profile::exists(profileName))
|
|
{
|
|
qCritical() << "-p profile" << profileName + ".tox" << "doesn't exist";
|
|
return EXIT_FAILURE;
|
|
}
|
|
ipcDest = Settings::makeProfileId(profileName);
|
|
autoLogin = true;
|
|
}
|
|
else
|
|
profileName = Settings::getInstance().getCurrentProfile();
|
|
|
|
if (parser.positionalArguments().size() == 0)
|
|
eventType = "activate";
|
|
else
|
|
{
|
|
firstParam = parser.positionalArguments()[0];
|
|
// Tox URIs. If there's already another qTox instance running, we ask it to handle the URI and we exit
|
|
// Otherwise we start a new qTox instance and process it ourselves
|
|
if (firstParam.startsWith("tox:"))
|
|
eventType = "uri";
|
|
else if (firstParam.endsWith(".tox"))
|
|
eventType = "save";
|
|
else
|
|
{
|
|
qCritical() << "Invalid argument";
|
|
return EXIT_FAILURE;
|
|
}
|
|
}
|
|
|
|
if (!ipc.isCurrentOwner())
|
|
{
|
|
time_t event = ipc.postEvent(eventType, firstParam.toUtf8(), ipcDest);
|
|
// If someone else processed it, we're done here, no need to actually start qTox
|
|
if (ipc.waitUntilAccepted(event, 2))
|
|
{
|
|
qDebug() << "Event" << eventType << "was handled by other client.";
|
|
return EXIT_SUCCESS;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
// Autologin
|
|
if (autoLogin)
|
|
{
|
|
if (Profile::exists(profileName))
|
|
{
|
|
if (!Profile::isEncrypted(profileName))
|
|
{
|
|
Profile* profile = Profile::loadProfile(profileName);
|
|
if (profile)
|
|
Nexus::getInstance().setProfile(profile);
|
|
}
|
|
Settings::getInstance().setCurrentProfile(profileName);
|
|
}
|
|
}
|
|
|
|
Nexus::getInstance().start();
|
|
|
|
#ifndef Q_OS_ANDROID
|
|
// Event was not handled by already running instance therefore we handle it ourselves
|
|
if (eventType == "uri")
|
|
handleToxURI(firstParam.toUtf8());
|
|
else if (eventType == "save")
|
|
handleToxSave(firstParam.toUtf8());
|
|
#endif
|
|
|
|
// Run
|
|
int errorcode = a.exec();
|
|
|
|
Nexus::destroyInstance();
|
|
CameraSource::destroyInstance();
|
|
Settings::destroyInstance();
|
|
qDebug() << "Clean exit with status" << errorcode;
|
|
|
|
#ifdef LOG_TO_FILE
|
|
logFileFile.store(nullptr); // atomically disable logging to file
|
|
fclose(mainLogFilePtr);
|
|
#endif
|
|
return errorcode;
|
|
}
|