-
Notifications
You must be signed in to change notification settings - Fork 30
Expand file tree
/
Copy pathmain.cpp
More file actions
374 lines (331 loc) · 15.2 KB
/
Copy pathmain.cpp
File metadata and controls
374 lines (331 loc) · 15.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
/***************************************************************************
main.cpp - description
-------------------
begin : sept 2011
copyright : (C) 2011 by Jaime Robles
email : jaime@robles.es
***************************************************************************/
/*****************************************************************************
* This file is part of KLog. *
* *
* KLog 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. *
* *
* KLog 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 KLog. If not, see <https://www.gnu.org/licenses/>. *
* *
*****************************************************************************/
#include <QtWidgets>
// #include <QtSql>
#include <QTranslator>
// #include <cstdlib>
#include <iostream>
#include <QTextStream>
#include <QCoreApplication>
#include <QCommandLineParser>
#include <QApplication>
#include <QSystemSemaphore>
#include <QSharedMemory>
#include <QMessageBox>
#include <QLoggingCategory>
#include "startwizard.h"
#include "mainwindow.h"
#include "utilities.h"
#include <QElapsedTimer>
// Suppress verbose debug noise from third-party Qt platform plugins (e.g. qt6ct)
// that unconditionally call//qDebug() for every palette/hint query.
static void klogMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
// Filter out the Qt6CTPlatformTheme palette/hint spam produced by qt6ct
if (msg.contains(QLatin1String("Qt6CTPlatformTheme")))
return;
if (msg.contains(QLatin1String("QThreadStorage")))
return;
// Forward everything else to Qt's default handler
qt_message_output(type, context, msg);
}
#ifdef KLOG_USE_VERSION_H
#include "version.h"
#endif
int showNoDB()
{
QMessageBox msgBox;
Utilities util(Q_FUNC_INFO);
QString msg = QString("There is no DB in the KLog folder and could not create it. KLog can't continue like this.\n") +
QString("Please remove or rename the %1 file and restart KLog.").arg(util.getCfgFile());
msgBox.setWindowTitle("KLog");
msgBox.setIcon(QMessageBox::Critical);
msgBox.setTextFormat(Qt::RichText);
msgBox.setText(msg);
msgBox.setStandardButtons(QMessageBox::Ok);
msgBox.setDefaultButton(QMessageBox::Ok);
msgBox.exec();
return -1;
}
int showErrorUpdatingTheDB()
{
QMessageBox msgBox;
Utilities util(Q_FUNC_INFO);
QString msg = QString("KLog could not update the DB and it is a critical step for this release. KLog can't continue like this.\n") +
QString("Please use the previews version of KLog to export your log to ADIF. Then do a clean installation of the new KLog version and import the ADIF file. If that doesn't work, please contact the KLog development team.");
msgBox.setWindowTitle("KLog");
msgBox.setIcon(QMessageBox::Critical);
msgBox.setTextFormat(Qt::RichText);
msgBox.setText(msg);
msgBox.setStandardButtons(QMessageBox::Ok);
msgBox.setDefaultButton(QMessageBox::Ok);
msgBox.exec();
return -1;
}
void loadTranslations(QApplication &app, QTranslator &myappTranslator)
{
Utilities util(Q_FUNC_INFO);
// The user may have selected a fixed language in the Language menu.
// "auto" (the default) follows the operating system language.
QSettings settings(util.getCfgFile(), QSettings::IniFormat);
QString language = settings.value("Language", "auto").toString().toLower();
if ((language == "auto") || language.isEmpty())
{
// Detect UI language.
// On macOS, QLocale::system().name() returns the regional-format locale
// (e.g. "en_US") which may differ from the display language set in
// System Preferences. uiLanguages() reads AppleLanguages and is
// reliable on all platforms.
QStringList uiLangs = QLocale::system().uiLanguages();
if (!uiLangs.isEmpty())
language = uiLangs.first().left(2).toLower();
else
language = QLocale::system().name().left(2).toLower();
}
//qDebug() << Q_FUNC_INFO << "Language:" << language;
if (language == "en")
return; // English is built-in; no translation file needed.
QString fileName = "klog_" + language + ".qm";
const QStringList searchPaths = util.getTranslationSearchPaths();
for (const QString &dir : searchPaths)
{
//qDebug() << Q_FUNC_INFO << "Trying:" << QDir(dir).filePath(fileName);
if (QDir(dir).exists(fileName) && myappTranslator.load(fileName, dir))
{
//qDebug() << Q_FUNC_INFO << "Loaded from:" << dir;
app.installTranslator(&myappTranslator);
return;
}
}
QMessageBox::warning(nullptr,
"KLog",
QString("No translation files for your language were found. "
"KLog will be shown in English.\n"
"If you have the %1 file for your language, "
"copy it to the translations folder and restart KLog.")
.arg(fileName));
}
int main(int argc, char *argv[])
{
//qDebug() << Q_FUNC_INFO << " - Start! ";
//qDebug() << Q_FUNC_INFO << " - " << QSslSocket::supportsSsl() << QSslSocket::sslLibraryBuildVersionString() << QSslSocket::sslLibraryVersionString();
qInstallMessageHandler(klogMessageHandler);
QT_REQUIRE_VERSION(argc, argv, "6.0")
//qDebug() << QT_VERSION_STR;
QElapsedTimer timer;
timer.start();
QDir d1 = QDir();
//qDebug() << Q_FUNC_INFO << " - STARTED: ";
Utilities util(Q_FUNC_INFO);
//qDebug() << Q_FUNC_INFO << " 001: " << timer.elapsed() << "ms"; timer.restart();
QApplication app(argc, argv);
//qDebug() << Q_FUNC_INFO << " 002: " << timer.elapsed() << "ms"; timer.restart();
app.setStyleSheet("QLineEdit:focus { background-color: #cce5ff; color: #000000; } "
"QDoubleSpinBox:focus { background-color: #cce5ff; color: #000000; } "
"QCheckBox:focus { background-color: #cce5ff; color: #000000; } "
"QDateEdit:focus { background-color: #cce5ff; color: #000000; } "
"QTimeEdit:focus { background-color: #cce5ff; color: #000000; } "
"QPushButton:focus { background-color: #cce5ff; color: #000000; } "
"QComboBox:focus { background-color: #cce5ff; color: #000000; }");
QString iconSt;
iconSt = ":/img/klog.ico";
QIcon KLogIcon(iconSt);
QApplication::setWindowIcon(KLogIcon);
app.setApplicationName(QString("KLog"));
app.setOrganizationName("EA4K");
app.setOrganizationDomain("klog.xyz");
app.setApplicationVersion(QString(APP_VERSION));
QString version = QCoreApplication::applicationVersion();
QString pkgVersion = QString(APP_PKGVERSION);
//qDebug() << Q_FUNC_INFO << " 010: " << timer.elapsed() << "ms"; timer.restart();
//qDebug() << Q_FUNC_INFO << " - " << pkgVersion;
// Now we check if the user is executing from the command line
// Command-line arguments
QTextStream cout(stdout);
QStringList arguments = app.arguments();
if (arguments.size() > 1)
{
Utilities util(Q_FUNC_INFO);
if (arguments.contains("-v"))
{
cout << "Version: KLog-" << app.applicationVersion()
<< " - pkg: " << pkgVersion << "\n";
}
else
{
util.printCommandHelp();
}
return 0;
}
//qDebug() << Q_FUNC_INFO << " 020: " << timer.elapsed() << "ms"; timer.restart();
// Start the splash show() as early as possible so macOS begins Quartz
// compositor initialisation (the ~1 s first-window cost) while the
// singleton check below runs. processEvents() is called after the check
// so by then the compositor has had a head start.
QPixmap pixmap(":img/klog_512x512.png");
QSplashScreen splash(pixmap);
splash.show();
/* Application Singleton
*
* We want to run only one instance of KLog application
*
*/
QSystemSemaphore semaphore("klogapp", 1); // create semaphore with unique ID klogapp
semaphore.acquire(); // Raise the semaphore, barring other instances to work with shared memory
#ifndef KLOG_Q_OS_WIN
// On Linux/Unix, a crashed process leaves its shared memory segment in /dev/shm.
// Unconditionally attach then detach: if an orphaned segment exists it is released;
// if no segment exists, attach() fails silently and detach() is a no-op.
{
QSharedMemory nix_fix_shared_memory("klogshm");
nix_fix_shared_memory.attach();
nix_fix_shared_memory.detach();
}
#endif
QSharedMemory sharedMemory("klogshm"); // Create a copy of the shared memory - Unique ID klogshm
bool is_running;
//qDebug() << Q_FUNC_INFO << " 030: " << timer.elapsed() << "ms"; timer.restart();
/*
* trying to attach a copy of the shared memory to an existing segment
*
* if successful, it determines that there is already a running instance
* otherwise allocate 1 byte of memory and no instance is running
*/
if (sharedMemory.attach())
{
is_running = true;
}
else
{
sharedMemory.create(1);
is_running = false;
}
// On macOS, QCoreApplication::quit() routes through NSApplication and may
// call system exit() without unwinding the C++ stack, so ~QSharedMemory()
// would never run. Explicitly detach in aboutToQuit so the segment is always
// released before the event loop exits, regardless of exit path.
QObject::connect(&app, &QCoreApplication::aboutToQuit, [&sharedMemory]() {
sharedMemory.detach();
});
semaphore.release();
//qInfo() << "[KLOG-TIMING] main 040 -:" << timer.elapsed() << "ms"; timer.restart();
// If you already run one instance of the application, then we
// inform the user about it
// and complete the current instance of the application
if (is_running)
{
splash.close();
QMessageBox msgBox;
msgBox.setIcon(QMessageBox::Warning);
msgBox.setText(QObject::tr("KLog is already running.") + "\n" +
QObject::tr("It is allowed to run only one instance."));
msgBox.exec();
return 1;
}
// END OF Application Singleton
// Flush events now. By this point macOS has had the singleton-check time
// (~93 ms) to advance Quartz initialisation, so the block here is shorter.
QApplication::processEvents();
// Load translations
//qInfo() << "[KLOG-TIMING] main 041 -:" << timer.elapsed() << "ms"; timer.restart();
// << (QTime::currentTime()).toString("HH:mm:ss");
//qDebug() << Q_FUNC_INFO << " - Detected language: " << (QLocale::system().name()).left(2) << ".qm";
QTranslator myappTranslator;
loadTranslations(app, myappTranslator);
//qInfo() << "[KLOG-TIMING] main 050 -:" << timer.elapsed() << "ms"; timer.restart();
QString klogDir = util.getHomeDir();
//qDebug() << Q_FUNC_INFO << " - 10";
// First step when running KLog, if the KLog folder does not exist, KLog creates it
if (!QDir::setCurrent (klogDir) ){
//qDebug() << Q_FUNC_INFO << " - KLogDir does not exist.... creating ";
if (d1.mkdir(klogDir))
{
if (QDir::setCurrent (klogDir) )
{
//qDebug() << Q_FUNC_INFO << " - KLogDir has just been created and pointed ";
}
}
}
//qInfo() << "[KLOG-TIMING] main 051 -:" << timer.elapsed() << "ms"; timer.restart();
splash.showMessage("Checking database...");
QApplication::processEvents();
//int firstTime = true;
// If the KLog configuration file does not exist, we launch the wizard.
//qInfo() << "[KLOG-TIMING] main 060 -:" << timer.elapsed() << "ms"; timer.restart();
if (!((QFile::exists(util.getCfgFile ()))))
{
StartWizard *wizard = new StartWizard(klogDir, version);
wizard->setModal(true);
wizard->exec();
delete wizard;
//qInfo() << "[KLOG-TIMING] main 061 -:" << timer.elapsed() << "ms"; timer.restart();
}
else
{ // KLog configuration file exists, let's look for the DB
//firstTime = false;
DataBase *db = new DataBase(Q_FUNC_INFO, version, util.getKLogDBFile());
//qInfo() << "[KLOG-TIMING] main 065 -:" << timer.elapsed() << "ms"; timer.restart();
if (!db->createConnection(Q_FUNC_INFO))
{
//qDebug() << Q_FUNC_INFO << " - Conection not created";
//qInfo() << "[KLOG-TIMING] main 066 -:" << timer.elapsed() << "ms"; timer.restart();
return showNoDB();
//return -1; // Exits with an error; no DB has been created
}
else
{
//qDebug() << Q_FUNC_INFO << " - DB to be updated";
if (!db->updateIfNeeded()) // Check if we need to update the DB
{
//qDebug() << Q_FUNC_INFO << " - DB NOT Updated";
}
//qInfo() << "[KLOG-TIMING] main 067 -:" << timer.elapsed() << "ms"; timer.restart();
//qDebug() << Q_FUNC_INFO << " - DB Updated";
}
delete db;
}
//qInfo() << "[KLOG-TIMING] main 069 -:" << timer.elapsed() << "ms"; timer.restart();
splash.showMessage ("Creating the Data Base...");
QApplication::processEvents();
DataProxy_SQLite dataProxy (Q_FUNC_INFO, version);
//qInfo() << "[KLOG-TIMING] main 071 - DataProxy_SQLite ctor [PROPOSAL-6 candidate]:" << timer.elapsed() << "ms"; timer.restart();
QApplication::processEvents();
World world(&dataProxy, Q_FUNC_INFO);
//qInfo() << "[KLOG-TIMING] main 072 - World ctor [PROPOSAL-2 done, readWorld() deferred]:" << timer.elapsed() << "ms"; timer.restart();
dataProxy.setPKGVersion(pkgVersion);
splash.showMessage("Creating window...");
QApplication::processEvents();
MainWindow mw(&dataProxy, &world);
//qInfo() << "[KLOG-TIMING] main 081 - MainWindow ctor:" << timer.elapsed() << "ms"; timer.restart();
splash.showMessage("Initializing...");
QApplication::processEvents();
mw.init();
//qInfo() << "[KLOG-TIMING] main 088 - mw.init() complete:" << timer.elapsed() << "ms"; timer.restart();
splash.showMessage("Showing window...");
QApplication::processEvents();
mw.show();
splash.finish(&mw);
return app.exec();
}