mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-17 20:43:58 +02:00
Currently the build without implicitly included precompiled header is not supported anyway (because Qt MOC source files do not include stdafx.h, they include plain headers). So when we decide to support building without implicitly included precompiled headers we'll have to fix all the headers anyway.
666 lines
19 KiB
C++
666 lines
19 KiB
C++
/*
|
|
This file is part of Telegram Desktop,
|
|
the official desktop version of Telegram messaging app, see https://telegram.org
|
|
|
|
Telegram Desktop 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.
|
|
|
|
It 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.
|
|
|
|
In addition, as a special exception, the copyright holders give permission
|
|
to link the code of portions of this program with the OpenSSL library.
|
|
|
|
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
|
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|
*/
|
|
#include "application.h"
|
|
|
|
#include "pspecific.h"
|
|
#include "mainwidget.h"
|
|
#include "mainwindow.h"
|
|
#include "localstorage.h"
|
|
#include "autoupdater.h"
|
|
#include "window/notifications_manager.h"
|
|
#include "core/task_queue.h"
|
|
#include "messenger.h"
|
|
|
|
namespace {
|
|
|
|
QChar _toHex(ushort v) {
|
|
v = v & 0x000F;
|
|
return QChar::fromLatin1((v >= 10) ? ('a' + (v - 10)) : ('0' + v));
|
|
}
|
|
ushort _fromHex(QChar c) {
|
|
return ((c.unicode() >= uchar('a')) ? (c.unicode() - uchar('a') + 10) : (c.unicode() - uchar('0'))) & 0x000F;
|
|
}
|
|
|
|
QString _escapeTo7bit(const QString &str) {
|
|
QString result;
|
|
result.reserve(str.size() * 2);
|
|
for (int i = 0, l = str.size(); i != l; ++i) {
|
|
QChar ch(str.at(i));
|
|
ushort uch(ch.unicode());
|
|
if (uch < 32 || uch > 127 || uch == ushort(uchar('%'))) {
|
|
result.append('%').append(_toHex(uch >> 12)).append(_toHex(uch >> 8)).append(_toHex(uch >> 4)).append(_toHex(uch));
|
|
} else {
|
|
result.append(ch);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
QString _escapeFrom7bit(const QString &str) {
|
|
QString result;
|
|
result.reserve(str.size());
|
|
for (int i = 0, l = str.size(); i != l; ++i) {
|
|
QChar ch(str.at(i));
|
|
if (ch == QChar::fromLatin1('%') && i + 4 < l) {
|
|
result.append(QChar(ushort((_fromHex(str.at(i + 1)) << 12) | (_fromHex(str.at(i + 2)) << 8) | (_fromHex(str.at(i + 3)) << 4) | _fromHex(str.at(i + 4)))));
|
|
i += 4;
|
|
} else {
|
|
result.append(ch);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
Application::Application(int &argc, char **argv) : QApplication(argc, argv) {
|
|
QByteArray d(QFile::encodeName(QDir(cWorkingDir()).absolutePath()));
|
|
char h[33] = { 0 };
|
|
hashMd5Hex(d.constData(), d.size(), h);
|
|
#ifndef OS_MAC_STORE
|
|
_localServerName = psServerPrefix() + h + '-' + cGUIDStr();
|
|
#else // OS_MAC_STORE
|
|
h[4] = 0; // use only first 4 chars
|
|
_localServerName = psServerPrefix() + h;
|
|
#endif // OS_MAC_STORE
|
|
|
|
connect(&_localSocket, SIGNAL(connected()), this, SLOT(socketConnected()));
|
|
connect(&_localSocket, SIGNAL(disconnected()), this, SLOT(socketDisconnected()));
|
|
connect(&_localSocket, SIGNAL(error(QLocalSocket::LocalSocketError)), this, SLOT(socketError(QLocalSocket::LocalSocketError)));
|
|
connect(&_localSocket, SIGNAL(bytesWritten(qint64)), this, SLOT(socketWritten(qint64)));
|
|
connect(&_localSocket, SIGNAL(readyRead()), this, SLOT(socketReading()));
|
|
connect(&_localServer, SIGNAL(newConnection()), this, SLOT(newInstanceConnected()));
|
|
|
|
QTimer::singleShot(0, this, SLOT(startApplication()));
|
|
connect(this, SIGNAL(aboutToQuit()), this, SLOT(closeApplication()));
|
|
|
|
#ifndef TDESKTOP_DISABLE_AUTOUPDATE
|
|
_updateCheckTimer.create(this);
|
|
connect(_updateCheckTimer, SIGNAL(timeout()), this, SLOT(updateCheck()));
|
|
connect(this, SIGNAL(updateFailed()), this, SLOT(onUpdateFailed()));
|
|
connect(this, SIGNAL(updateReady()), this, SLOT(onUpdateReady()));
|
|
#endif // !TDESKTOP_DISABLE_AUTOUPDATE
|
|
|
|
if (cManyInstance()) {
|
|
LOG(("Many instance allowed, starting..."));
|
|
singleInstanceChecked();
|
|
} else {
|
|
LOG(("Connecting local socket to %1...").arg(_localServerName));
|
|
_localSocket.connectToServer(_localServerName);
|
|
}
|
|
}
|
|
|
|
Application::~Application() = default;
|
|
|
|
bool Application::event(QEvent *e) {
|
|
if (e->type() == QEvent::Close) {
|
|
App::quit();
|
|
}
|
|
return QApplication::event(e);
|
|
}
|
|
|
|
void Application::socketConnected() {
|
|
LOG(("Socket connected, this is not the first application instance, sending show command..."));
|
|
_secondInstance = true;
|
|
|
|
QString commands;
|
|
const QStringList &lst(cSendPaths());
|
|
for (QStringList::const_iterator i = lst.cbegin(), e = lst.cend(); i != e; ++i) {
|
|
commands += qsl("SEND:") + _escapeTo7bit(*i) + ';';
|
|
}
|
|
if (!cStartUrl().isEmpty()) {
|
|
commands += qsl("OPEN:") + _escapeTo7bit(cStartUrl()) + ';';
|
|
}
|
|
commands += qsl("CMD:show;");
|
|
|
|
DEBUG_LOG(("Application Info: writing commands %1").arg(commands));
|
|
_localSocket.write(commands.toLatin1());
|
|
}
|
|
|
|
void Application::socketWritten(qint64/* bytes*/) {
|
|
if (_localSocket.state() != QLocalSocket::ConnectedState) {
|
|
LOG(("Socket is not connected %1").arg(_localSocket.state()));
|
|
return;
|
|
}
|
|
if (_localSocket.bytesToWrite()) {
|
|
return;
|
|
}
|
|
LOG(("Show command written, waiting response..."));
|
|
}
|
|
|
|
void Application::socketReading() {
|
|
if (_localSocket.state() != QLocalSocket::ConnectedState) {
|
|
LOG(("Socket is not connected %1").arg(_localSocket.state()));
|
|
return;
|
|
}
|
|
_localSocketReadData.append(_localSocket.readAll());
|
|
if (QRegularExpression("RES:(\\d+);").match(_localSocketReadData).hasMatch()) {
|
|
uint64 pid = _localSocketReadData.mid(4, _localSocketReadData.length() - 5).toULongLong();
|
|
psActivateProcess(pid);
|
|
LOG(("Show command response received, pid = %1, activating and quitting...").arg(pid));
|
|
return App::quit();
|
|
}
|
|
}
|
|
|
|
void Application::socketError(QLocalSocket::LocalSocketError e) {
|
|
if (App::quitting()) return;
|
|
|
|
if (_secondInstance) {
|
|
LOG(("Could not write show command, error %1, quitting...").arg(e));
|
|
return App::quit();
|
|
}
|
|
|
|
if (e == QLocalSocket::ServerNotFoundError) {
|
|
LOG(("This is the only instance of Telegram, starting server and app..."));
|
|
} else {
|
|
LOG(("Socket connect error %1, starting server and app...").arg(e));
|
|
}
|
|
_localSocket.close();
|
|
|
|
// Local server does not work in WinRT build.
|
|
#ifndef Q_OS_WINRT
|
|
psCheckLocalSocket(_localServerName);
|
|
|
|
if (!_localServer.listen(_localServerName)) {
|
|
LOG(("Failed to start listening to %1 server, error %2").arg(_localServerName).arg(int(_localServer.serverError())));
|
|
return App::quit();
|
|
}
|
|
#endif // !Q_OS_WINRT
|
|
|
|
#ifndef TDESKTOP_DISABLE_AUTOUPDATE
|
|
if (!cNoStartUpdate() && checkReadyUpdate()) {
|
|
cSetRestartingUpdate(true);
|
|
DEBUG_LOG(("Application Info: installing update instead of starting app..."));
|
|
return App::quit();
|
|
}
|
|
#endif // !TDESKTOP_DISABLE_AUTOUPDATE
|
|
|
|
singleInstanceChecked();
|
|
}
|
|
|
|
void Application::singleInstanceChecked() {
|
|
if (cManyInstance()) {
|
|
Logs::multipleInstances();
|
|
}
|
|
|
|
Sandbox::start();
|
|
|
|
if (!Logs::started() || (!cManyInstance() && !Logs::instanceChecked())) {
|
|
new NotStartedWindow();
|
|
} else {
|
|
SignalHandlers::Status status = SignalHandlers::start();
|
|
if (status == SignalHandlers::CantOpen) {
|
|
new NotStartedWindow();
|
|
} else if (status == SignalHandlers::LastCrashed) {
|
|
if (Sandbox::LastCrashDump().isEmpty()) { // don't handle bad closing for now
|
|
if (SignalHandlers::restart() == SignalHandlers::CantOpen) {
|
|
new NotStartedWindow();
|
|
} else {
|
|
Sandbox::launch();
|
|
}
|
|
} else {
|
|
new LastCrashedWindow();
|
|
}
|
|
} else {
|
|
Sandbox::launch();
|
|
}
|
|
}
|
|
}
|
|
|
|
void Application::socketDisconnected() {
|
|
if (_secondInstance) {
|
|
DEBUG_LOG(("Application Error: socket disconnected before command response received, quitting..."));
|
|
return App::quit();
|
|
}
|
|
}
|
|
|
|
void Application::newInstanceConnected() {
|
|
DEBUG_LOG(("Application Info: new local socket connected"));
|
|
for (QLocalSocket *client = _localServer.nextPendingConnection(); client; client = _localServer.nextPendingConnection()) {
|
|
_localClients.push_back(LocalClient(client, QByteArray()));
|
|
connect(client, SIGNAL(readyRead()), this, SLOT(readClients()));
|
|
connect(client, SIGNAL(disconnected()), this, SLOT(removeClients()));
|
|
}
|
|
}
|
|
|
|
void Application::readClients() {
|
|
QString startUrl;
|
|
QStringList toSend;
|
|
for (LocalClients::iterator i = _localClients.begin(), e = _localClients.end(); i != e; ++i) {
|
|
i->second.append(i->first->readAll());
|
|
if (i->second.size()) {
|
|
QString cmds(QString::fromLatin1(i->second));
|
|
int32 from = 0, l = cmds.length();
|
|
for (int32 to = cmds.indexOf(QChar(';'), from); to >= from; to = (from < l) ? cmds.indexOf(QChar(';'), from) : -1) {
|
|
QStringRef cmd(&cmds, from, to - from);
|
|
if (cmd.startsWith(qsl("CMD:"))) {
|
|
Sandbox::execExternal(cmds.mid(from + 4, to - from - 4));
|
|
QByteArray response(qsl("RES:%1;").arg(QCoreApplication::applicationPid()).toLatin1());
|
|
i->first->write(response.data(), response.size());
|
|
} else if (cmd.startsWith(qsl("SEND:"))) {
|
|
if (cSendPaths().isEmpty()) {
|
|
toSend.append(_escapeFrom7bit(cmds.mid(from + 5, to - from - 5)));
|
|
}
|
|
} else if (cmd.startsWith(qsl("OPEN:"))) {
|
|
if (cStartUrl().isEmpty()) {
|
|
startUrl = _escapeFrom7bit(cmds.mid(from + 5, to - from - 5)).mid(0, 8192);
|
|
}
|
|
} else {
|
|
LOG(("Application Error: unknown command %1 passed in local socket").arg(QString(cmd.constData(), cmd.length())));
|
|
}
|
|
from = to + 1;
|
|
}
|
|
if (from > 0) {
|
|
i->second = i->second.mid(from);
|
|
}
|
|
}
|
|
}
|
|
if (!toSend.isEmpty()) {
|
|
QStringList paths(cSendPaths());
|
|
paths.append(toSend);
|
|
cSetSendPaths(paths);
|
|
}
|
|
if (!cSendPaths().isEmpty()) {
|
|
if (App::wnd()) {
|
|
App::wnd()->sendPaths();
|
|
}
|
|
}
|
|
if (!startUrl.isEmpty()) {
|
|
cSetStartUrl(startUrl);
|
|
}
|
|
if (auto main = App::main()) {
|
|
main->checkStartUrl();
|
|
}
|
|
}
|
|
|
|
void Application::removeClients() {
|
|
DEBUG_LOG(("Application Info: remove clients slot called, clients %1").arg(_localClients.size()));
|
|
for (LocalClients::iterator i = _localClients.begin(), e = _localClients.end(); i != e;) {
|
|
if (i->first->state() != QLocalSocket::ConnectedState) {
|
|
DEBUG_LOG(("Application Info: removing client"));
|
|
i = _localClients.erase(i);
|
|
e = _localClients.end();
|
|
} else {
|
|
++i;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Application::startApplication() {
|
|
if (App::quitting()) {
|
|
quit();
|
|
}
|
|
}
|
|
|
|
void Application::createMessenger() {
|
|
t_assert(!App::quitting());
|
|
_messengerInstance = std::make_unique<Messenger>();
|
|
}
|
|
|
|
void Application::closeApplication() {
|
|
if (App::launchState() == App::QuitProcessed) return;
|
|
App::setLaunchState(App::QuitProcessed);
|
|
|
|
if (auto manager = Window::Notifications::GetManager()) {
|
|
manager->clearAllFast();
|
|
}
|
|
|
|
if (_messengerInstance) {
|
|
Messenger::Instance().prepareToDestroy();
|
|
_messengerInstance.reset();
|
|
}
|
|
|
|
Sandbox::finish();
|
|
|
|
_localServer.close();
|
|
for (LocalClients::iterator i = _localClients.begin(), e = _localClients.end(); i != e; ++i) {
|
|
disconnect(i->first, SIGNAL(disconnected()), this, SLOT(removeClients()));
|
|
i->first->close();
|
|
}
|
|
_localClients.clear();
|
|
|
|
_localSocket.close();
|
|
|
|
#ifndef TDESKTOP_DISABLE_AUTOUPDATE
|
|
delete _updateReply;
|
|
_updateReply = 0;
|
|
if (_updateChecker) _updateChecker->deleteLater();
|
|
_updateChecker = 0;
|
|
if (_updateThread) {
|
|
_updateThread->quit();
|
|
}
|
|
_updateThread = 0;
|
|
#endif // !TDESKTOP_DISABLE_AUTOUPDATE
|
|
}
|
|
|
|
void Application::onMainThreadTask() {
|
|
base::TaskQueue::ProcessMainTasks();
|
|
}
|
|
|
|
#ifndef TDESKTOP_DISABLE_AUTOUPDATE
|
|
void Application::updateCheck() {
|
|
startUpdateCheck(false);
|
|
}
|
|
|
|
void Application::updateGotCurrent() {
|
|
if (!_updateReply || _updateThread) return;
|
|
|
|
cSetLastUpdateCheck(unixtime());
|
|
QRegularExpressionMatch m = QRegularExpression(qsl("^\\s*(\\d+)\\s*:\\s*([\\x21-\\x7f]+)\\s*$")).match(QString::fromLatin1(_updateReply->readAll()));
|
|
if (m.hasMatch()) {
|
|
uint64 currentVersion = m.captured(1).toULongLong();
|
|
QString url = m.captured(2);
|
|
bool betaVersion = false;
|
|
if (url.startsWith(qstr("beta_"))) {
|
|
betaVersion = true;
|
|
url = url.mid(5) + '_' + countBetaVersionSignature(currentVersion);
|
|
}
|
|
if ((!betaVersion || cBetaVersion()) && currentVersion > (betaVersion ? cBetaVersion() : uint64(AppVersion))) {
|
|
_updateThread = new QThread();
|
|
connect(_updateThread, SIGNAL(finished()), _updateThread, SLOT(deleteLater()));
|
|
_updateChecker = new UpdateChecker(_updateThread, url);
|
|
_updateThread->start();
|
|
}
|
|
}
|
|
if (_updateReply) _updateReply->deleteLater();
|
|
_updateReply = 0;
|
|
if (!_updateThread) {
|
|
QDir updates(cWorkingDir() + "tupdates");
|
|
if (updates.exists()) {
|
|
QFileInfoList list = updates.entryInfoList(QDir::Files);
|
|
for (QFileInfoList::iterator i = list.begin(), e = list.end(); i != e; ++i) {
|
|
if (QRegularExpression("^(tupdate|tmacupd|tmac32upd|tlinuxupd|tlinux32upd)\\d+(_[a-z\\d]+)?$", QRegularExpression::CaseInsensitiveOption).match(i->fileName()).hasMatch()) {
|
|
QFile(i->absoluteFilePath()).remove();
|
|
}
|
|
}
|
|
}
|
|
emit updateLatest();
|
|
}
|
|
startUpdateCheck(true);
|
|
Local::writeSettings();
|
|
}
|
|
|
|
void Application::updateFailedCurrent(QNetworkReply::NetworkError e) {
|
|
LOG(("App Error: could not get current version (update check): %1").arg(e));
|
|
if (_updateReply) _updateReply->deleteLater();
|
|
_updateReply = 0;
|
|
|
|
emit updateFailed();
|
|
startUpdateCheck(true);
|
|
}
|
|
|
|
void Application::onUpdateReady() {
|
|
if (_updateChecker) {
|
|
_updateChecker->deleteLater();
|
|
_updateChecker = nullptr;
|
|
}
|
|
_updateCheckTimer->stop();
|
|
|
|
cSetLastUpdateCheck(unixtime());
|
|
Local::writeSettings();
|
|
}
|
|
|
|
void Application::onUpdateFailed() {
|
|
if (_updateChecker) {
|
|
_updateChecker->deleteLater();
|
|
_updateChecker = 0;
|
|
if (_updateThread) _updateThread->quit();
|
|
_updateThread = 0;
|
|
}
|
|
|
|
cSetLastUpdateCheck(unixtime());
|
|
Local::writeSettings();
|
|
}
|
|
|
|
Application::UpdatingState Application::updatingState() {
|
|
if (!_updateThread) return Application::UpdatingNone;
|
|
if (!_updateChecker) return Application::UpdatingReady;
|
|
return Application::UpdatingDownload;
|
|
}
|
|
|
|
int32 Application::updatingSize() {
|
|
if (!_updateChecker) return 0;
|
|
return _updateChecker->size();
|
|
}
|
|
|
|
int32 Application::updatingReady() {
|
|
if (!_updateChecker) return 0;
|
|
return _updateChecker->ready();
|
|
}
|
|
|
|
void Application::stopUpdate() {
|
|
if (_updateReply) {
|
|
_updateReply->abort();
|
|
_updateReply->deleteLater();
|
|
_updateReply = 0;
|
|
}
|
|
if (_updateChecker) {
|
|
_updateChecker->deleteLater();
|
|
_updateChecker = 0;
|
|
if (_updateThread) _updateThread->quit();
|
|
_updateThread = 0;
|
|
}
|
|
}
|
|
|
|
void Application::startUpdateCheck(bool forceWait) {
|
|
if (!Sandbox::started()) return;
|
|
|
|
_updateCheckTimer->stop();
|
|
if (_updateThread || _updateReply || !cAutoUpdate()) return;
|
|
|
|
int32 constDelay = cBetaVersion() ? 600 : UpdateDelayConstPart, randDelay = cBetaVersion() ? 300 : UpdateDelayRandPart;
|
|
int32 updateInSecs = cLastUpdateCheck() + constDelay + int32(rand() % randDelay) - unixtime();
|
|
bool sendRequest = (updateInSecs <= 0 || updateInSecs > (constDelay + randDelay));
|
|
if (!sendRequest && !forceWait) {
|
|
QDir updates(cWorkingDir() + "tupdates");
|
|
if (updates.exists()) {
|
|
QFileInfoList list = updates.entryInfoList(QDir::Files);
|
|
for (QFileInfoList::iterator i = list.begin(), e = list.end(); i != e; ++i) {
|
|
if (QRegularExpression("^(tupdate|tmacupd|tmac32upd|tlinuxupd|tlinux32upd)\\d+(_[a-z\\d]+)?$", QRegularExpression::CaseInsensitiveOption).match(i->fileName()).hasMatch()) {
|
|
sendRequest = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (cManyInstance() && !cDebug()) return; // only main instance is updating
|
|
|
|
if (sendRequest) {
|
|
QUrl url(cUpdateURL());
|
|
if (cBetaVersion()) {
|
|
url.setQuery(qsl("version=%1&beta=%2").arg(AppVersion).arg(cBetaVersion()));
|
|
} else if (cAlphaVersion()) {
|
|
url.setQuery(qsl("version=%1&alpha=1").arg(AppVersion));
|
|
} else {
|
|
url.setQuery(qsl("version=%1").arg(AppVersion));
|
|
}
|
|
QString u = url.toString();
|
|
QNetworkRequest checkVersion(url);
|
|
if (_updateReply) _updateReply->deleteLater();
|
|
|
|
App::setProxySettings(_updateManager);
|
|
_updateReply = _updateManager.get(checkVersion);
|
|
connect(_updateReply, SIGNAL(finished()), this, SLOT(updateGotCurrent()));
|
|
connect(_updateReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(updateFailedCurrent(QNetworkReply::NetworkError)));
|
|
emit updateChecking();
|
|
} else {
|
|
_updateCheckTimer->start((updateInSecs + 5) * 1000);
|
|
}
|
|
}
|
|
|
|
#endif // !TDESKTOP_DISABLE_AUTOUPDATE
|
|
|
|
inline Application *application() {
|
|
return qobject_cast<Application*>(QApplication::instance());
|
|
}
|
|
|
|
namespace Sandbox {
|
|
|
|
QRect availableGeometry() {
|
|
if (auto a = application()) {
|
|
return a->desktop()->availableGeometry();
|
|
}
|
|
return QDesktopWidget().availableGeometry();
|
|
}
|
|
|
|
QRect screenGeometry(const QPoint &p) {
|
|
if (auto a = application()) {
|
|
return a->desktop()->screenGeometry(p);
|
|
}
|
|
return QDesktopWidget().screenGeometry(p);
|
|
}
|
|
|
|
void setActiveWindow(QWidget *window) {
|
|
if (auto a = application()) {
|
|
a->setActiveWindow(window);
|
|
}
|
|
}
|
|
|
|
bool isSavingSession() {
|
|
if (auto a = application()) {
|
|
return a->isSavingSession();
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void execExternal(const QString &cmd) {
|
|
DEBUG_LOG(("Application Info: executing external command '%1'").arg(cmd));
|
|
if (cmd == "show") {
|
|
if (App::wnd()) {
|
|
App::wnd()->activate();
|
|
} else if (PreLaunchWindow::instance()) {
|
|
PreLaunchWindow::instance()->activate();
|
|
}
|
|
}
|
|
}
|
|
|
|
void adjustSingleTimers() {
|
|
if (auto a = application()) {
|
|
a->adjustSingleTimers();
|
|
}
|
|
}
|
|
|
|
#ifndef TDESKTOP_DISABLE_AUTOUPDATE
|
|
|
|
void startUpdateCheck() {
|
|
if (auto a = application()) {
|
|
return a->startUpdateCheck(false);
|
|
}
|
|
}
|
|
|
|
void stopUpdate() {
|
|
if (auto a = application()) {
|
|
return a->stopUpdate();
|
|
}
|
|
}
|
|
|
|
Application::UpdatingState updatingState() {
|
|
if (auto a = application()) {
|
|
return a->updatingState();
|
|
}
|
|
return Application::UpdatingNone;
|
|
}
|
|
|
|
int32 updatingSize() {
|
|
if (auto a = application()) {
|
|
return a->updatingSize();
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int32 updatingReady() {
|
|
if (auto a = application()) {
|
|
return a->updatingReady();
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void updateChecking() {
|
|
if (auto a = application()) {
|
|
emit a->updateChecking();
|
|
}
|
|
}
|
|
|
|
void updateLatest() {
|
|
if (auto a = application()) {
|
|
emit a->updateLatest();
|
|
}
|
|
}
|
|
|
|
void updateProgress(qint64 ready, qint64 total) {
|
|
if (auto a = application()) {
|
|
emit a->updateProgress(ready, total);
|
|
}
|
|
}
|
|
|
|
void updateFailed() {
|
|
if (auto a = application()) {
|
|
emit a->updateFailed();
|
|
}
|
|
}
|
|
|
|
void updateReady() {
|
|
if (auto a = application()) {
|
|
emit a->updateReady();
|
|
}
|
|
}
|
|
|
|
#endif // !TDESKTOP_DISABLE_AUTOUPDATE
|
|
|
|
void connect(const char *signal, QObject *object, const char *method) {
|
|
if (auto a = application()) {
|
|
a->connect(a, signal, object, method);
|
|
}
|
|
}
|
|
|
|
void launch() {
|
|
t_assert(application() != 0);
|
|
|
|
float64 dpi = Application::primaryScreen()->logicalDotsPerInch();
|
|
if (dpi <= 108) { // 0-96-108
|
|
cSetScreenScale(dbisOne);
|
|
} else if (dpi <= 132) { // 108-120-132
|
|
cSetScreenScale(dbisOneAndQuarter);
|
|
} else if (dpi <= 168) { // 132-144-168
|
|
cSetScreenScale(dbisOneAndHalf);
|
|
} else { // 168-192-inf
|
|
cSetScreenScale(dbisTwo);
|
|
}
|
|
|
|
auto devicePixelRatio = application()->devicePixelRatio();
|
|
if (devicePixelRatio > 1.) {
|
|
if ((cPlatform() != dbipMac && cPlatform() != dbipMacOld) || (devicePixelRatio != 2.)) {
|
|
LOG(("Found non-trivial Device Pixel Ratio: %1").arg(devicePixelRatio));
|
|
LOG(("Environmental variables: QT_DEVICE_PIXEL_RATIO='%1'").arg(QString::fromLatin1(qgetenv("QT_DEVICE_PIXEL_RATIO"))));
|
|
LOG(("Environmental variables: QT_SCALE_FACTOR='%1'").arg(QString::fromLatin1(qgetenv("QT_SCALE_FACTOR"))));
|
|
LOG(("Environmental variables: QT_AUTO_SCREEN_SCALE_FACTOR='%1'").arg(QString::fromLatin1(qgetenv("QT_AUTO_SCREEN_SCALE_FACTOR"))));
|
|
LOG(("Environmental variables: QT_SCREEN_SCALE_FACTORS='%1'").arg(QString::fromLatin1(qgetenv("QT_SCREEN_SCALE_FACTORS"))));
|
|
}
|
|
cSetRetina(true);
|
|
cSetRetinaFactor(devicePixelRatio);
|
|
cSetIntRetinaFactor(int32(cRetinaFactor()));
|
|
cSetConfigScale(dbisOne);
|
|
cSetRealScale(dbisOne);
|
|
}
|
|
|
|
application()->createMessenger();
|
|
}
|
|
|
|
} // namespace Sandbox
|