20 #include "audio/audio.h"
31 #include <QApplication>
32 #include <QCommandLineParser>
37 #include <QFontDatabase>
39 #include <QMutexLocker>
41 #include <QtWidgets/QMessageBox>
46 #if defined(Q_OS_UNIX)
51 static QAtomicPointer<FILE> logFileFile =
nullptr;
54 QMutex* logBufferMutex =
new QMutex();
71 qDebug() <<
"Cleanup success";
74 #if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
75 FILE* f = logFileFile.loadRelaxed();
77 FILE* f = logFileFile.load();
81 #if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
82 logFileFile.storeRelaxed(
nullptr);
84 logFileFile.store(
nullptr);
93 if (ctxt.function == QString(
"virtual bool QFSFileEngine::open(QIODevice::OpenMode)")
94 && msg == QString(
"QFSFileEngine::open: No file name specified"))
97 QRegExp snoreFilter{QStringLiteral(
"Snore::Notification.*was already closed")};
98 if (type == QtWarningMsg
99 && msg.contains(snoreFilter))
107 QString
file = ctxt.file;
110 QString path = QString(__FILE__);
111 path = path.left(path.lastIndexOf(
'/') + 1);
112 if (
file.startsWith(path)) {
117 QTime time = QDateTime::currentDateTime().toUTC().time();
119 QString(
"[%1 UTC] %2:%3 : ").arg(time.toString(
"HH:mm:ss.zzz")).arg(
file).arg(ctxt.line);
131 LogMsg +=
"Critical";
140 LogMsg +=
": " + msg +
"\n";
141 QByteArray LogMsgBytes = LogMsg.toUtf8();
142 fwrite(LogMsgBytes.constData(), 1, LogMsgBytes.size(), stderr);
145 #if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
146 FILE* logFilePtr = logFileFile.loadRelaxed();
148 FILE* logFilePtr = logFileFile.load();
151 logBufferMutex->lock();
153 logBuffer->append(LogMsgBytes);
155 logBufferMutex->unlock();
157 logBufferMutex->lock();
160 foreach (QByteArray msg, *logBuffer)
161 fwrite(msg.constData(), 1, msg.size(), logFilePtr);
166 logBufferMutex->unlock();
168 fwrite(LogMsgBytes.constData(), 1, LogMsgBytes.size(), logFilePtr);
174 static std::unique_ptr<ToxURIDialog> uriDialog;
176 static bool toxURIEventHandler(
const QByteArray& eventData)
178 if (!eventData.startsWith(
"tox:")) {
186 uriDialog->handleToxURI(eventData);
190 int main(
int argc,
char* argv[])
192 #if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
193 QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
194 QGuiApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
199 std::unique_ptr<QApplication> a(
new QApplication(argc, argv));
201 #if defined(Q_OS_UNIX)
205 a.get(), &QApplication::quit);
209 a->setApplicationName(
"qTox");
210 #if QT_VERSION >= QT_VERSION_CHECK(5, 7, 0)
211 a->setDesktopFileName(
"io.github.qtox.qTox");
213 a->setApplicationVersion(
"\nGit commit: " + QString(GIT_VERSION));
218 if (QFontDatabase::addApplicationFont(
"://font/DejaVuSans.ttf") == -1) {
219 qWarning() <<
"Couldn't load font";
226 Q_INIT_RESOURCE(translations);
230 QCommandLineParser parser;
231 parser.setApplicationDescription(
"qTox, version: " + QString(GIT_VERSION));
232 parser.addHelpOption();
233 parser.addVersionOption();
234 parser.addPositionalArgument(
"uri", QObject::tr(
"Tox URI to parse"));
236 QCommandLineOption(QStringList() <<
"p"
238 QObject::tr(
"Starts new instance and loads specified profile."),
239 QObject::tr(
"profile")));
241 QCommandLineOption(QStringList() <<
"l"
243 QObject::tr(
"Starts new instance and opens the login screen.")));
244 parser.addOption(QCommandLineOption(QStringList() <<
"I"
246 QObject::tr(
"Sets IPv6 <on>/<off>. Default is ON."),
247 QObject::tr(
"on/off")));
248 parser.addOption(QCommandLineOption(QStringList() <<
"U"
250 QObject::tr(
"Sets UDP <on>/<off>. Default is ON."),
251 QObject::tr(
"on/off")));
253 QCommandLineOption(QStringList() <<
"L"
256 "Sets LAN discovery <on>/<off>. UDP off overrides. Default is ON."),
257 QObject::tr(
"on/off")));
258 parser.addOption(QCommandLineOption(QStringList() <<
"P"
260 QObject::tr(
"Sets proxy settings. Default is NONE."),
261 QObject::tr(
"(SOCKS5/HTTP/NONE):(ADDRESS):(PORT)")));
269 qWarning() <<
"Can't init IPC, maybe we're in a jail? Continuing with reduced multi-client functionality.";
273 if (sodium_init() < 0) {
274 qCritical() <<
"Can't init libsodium";
280 QDir(logFileDir).mkpath(
".");
282 QString logfile = logFileDir +
"qtox.log";
283 FILE* mainLogFilePtr = fopen(logfile.toLocal8Bit().constData(),
"a");
286 if (QFileInfo(logfile).size() > 1000000) {
287 qDebug() <<
"Log file over 1MB, rotating...";
291 fclose(mainLogFilePtr);
293 QDir dir(logFileDir);
296 if (dir.remove(logFileDir +
"qtox.log.1"))
297 qDebug() <<
"Removed old log successfully";
299 qWarning() <<
"Unable to remove old log file";
301 if (!dir.rename(logFileDir +
"qtox.log", logFileDir +
"qtox.log.1"))
302 qCritical() <<
"Unable to move logs";
305 mainLogFilePtr = fopen(logfile.toLocal8Bit().constData(),
"a");
309 qCritical() <<
"Couldn't open logfile" << logfile;
311 #if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
312 logFileFile.storeRelaxed(mainLogFilePtr);
314 logFileFile.store(mainLogFilePtr);
319 QCoreApplication::addLibraryPath(QCoreApplication::applicationDirPath());
320 a->addLibraryPath(
"platforms");
322 qDebug() <<
"commit: " << GIT_VERSION;
327 uint32_t ipcDest = 0;
329 QString eventType, firstParam;
330 if (parser.isSet(
"p")) {
331 profileName = parser.value(
"p");
333 qWarning() <<
"-p profile" << profileName +
".tox"
334 <<
"doesn't exist, opening login screen";
341 }
else if (parser.isSet(
"l")) {
348 if (parser.positionalArguments().empty()) {
349 eventType =
"activate";
351 firstParam = parser.positionalArguments()[0];
355 if (firstParam.startsWith(
"tox:")) {
357 }
else if (firstParam.endsWith(
".tox")) {
360 qCritical() <<
"Invalid argument";
366 time_t
event = ipc.
postEvent(eventType, firstParam.toUtf8(), ipcDest);
369 if (eventType ==
"activate") {
371 <<
"Another qTox instance is already running. If you want to start a second "
372 "instance, please open login screen (qtox -l) or start with a profile (qtox "
373 "-p <profile name>).";
375 qDebug() <<
"Event" << eventType <<
"was handled by other client.";
399 QMessageBox::information(
nullptr, QObject::tr(
"Error"),
400 QObject::tr(
"Failed to load profile automatically."));
407 int returnval = nexus.
showLogin(profileName);
408 if (returnval == QDialog::Rejected) {
424 if (eventType ==
"uri") {
425 uriDialog->handleToxURI(firstParam.toUtf8());
426 }
else if (eventType ==
"save") {
430 QObject::connect(a.get(), &QApplication::aboutToQuit,
cleanup);
433 int errorcode = a->exec();
435 qDebug() <<
"Exit with status" << errorcode;