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
|
/* Copyright (C) 2014-2016 Dan Chapman <dpniel@ubuntu.com>
This file is part of Dekko mail client
This program 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 2 of
the License or (at your option) version 3 or any later version
accepted by the membership of KDE e.V. (or its successor approved
by the membership of KDE e.V.), which shall act as a proxy
defined in Section 14 of version 3 of the license.
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
// NOTE: uncomment to enable profiling
//#define QML_COMPILER_STATS
#include <QApplication>
#include <QtQuick>
#include <QDebug>
#include <QQmlContext>
#include <QSettings>
#include <QtGui/QGuiApplication>
#include <QtQml/QtQml>
#include <QtQuick/QQuickView>
#include <QTranslator>
#include <QLocale>
#include <QScopedPointer>
#include "AppVersion/SetCoreApplication.h"
#include "Common/Application.h"
#include "Common/MetaTypes.h"
#include "Common/SettingsNames.h"
#include "static_plugins.h"
#include "DekkoGlobal.h"
#include "app/Settings/SettingsFileBase.h"
#include "app/Settings/MailboxSettings.h"
#include "app/Settings/NotificationSettings.h"
#include "app/Settings/ViewSettings.h"
#include "app/Utils/Path.h"
#include "app/Utils/CustomQQuickViewFactory.h"
#include "app/Network/MsgPartNetAccessManagerFactory.h"
#include "configure.cmake.h"
#ifdef UNCONFINED
#include <QCommandLineParser>
#endif
static bool checkForStaleLockFile(QLockFile **lockFile, QString &filePath, QString &errorMessage);
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
Q_INIT_RESOURCE(actionicons);
Q_INIT_RESOURCE(providericons);
//Install translations
QTranslator dekkoTranslator;
QTranslator dekkoBuildTranslator;
// It would appear Qt has a real problem loading translations for anywhere but in the same directory
// as the executable. I have no idea if this is click package related or a bug in Qt but this works
// so i'm not going to complain.... (*much*)
QString trPath;
#ifdef CLICK_MODE
trPath = app.applicationDirPath();
#else
trPath = QStringLiteral(DESKTOP_TR_PATH);
#endif
qDebug() << "LOCATION: " << QLibraryInfo::location(QLibraryInfo::TranslationsPath);
if (dekkoTranslator.load(QLocale::system().name(), trPath)) {
qDebug() << "Translation loaded: " << !dekkoTranslator.isEmpty();
app.installTranslator(&dekkoTranslator);
} else if (dekkoBuildTranslator.load(QLocale::system().name(), QCoreApplication::applicationDirPath() + QStringLiteral("/locale/"))) {
qDebug() << "Installing translations in build dir";
app.installTranslator(&dekkoBuildTranslator);
} else {
qWarning() << "Failed loading translations";
}
#ifdef UNCONFINED
QCommandLineParser parser;
parser.setApplicationDescription(QStringLiteral("Dekko email client"));
parser.addVersionOption();
parser.addHelpOption();
parser.addPositionalArgument(QStringLiteral("mailto"), QStringLiteral("Start a compose session using the mailto: url scheme"));
parser.process(app);
#endif
Common::registerMetaTypes();
#ifdef CLICK_MODE
Common::Application::name = QStringLiteral(APP_ID);
// If the organization is set, QStandardPaths::DataLocation will be
// $PREFIX/$APPNAME/$ORGANIZATION e.g.:
// /usr/share/dekko.dekkoproject/dekko.dekkoproject
Common::Application::organization = QStringLiteral(APP_ID);
#else
Common::Application::name = QStringLiteral(APP_NAME);
// If the organization is set, QStandardPaths::DataLocation will be
// $PREFIX/$APPNAME/$ORGANIZATION e.g.:
// /usr/share/dekko.dekkoproject/dekko.dekkoproject
Common::Application::organization = QStringLiteral(APP_ORGANIZATION);
#endif
AppVersion::setVersion();
AppVersion::setCoreApplicationData();
QString error;
// Configure mbox settings
QScopedPointer<Dekko::Settings::SettingsFileBase> mboxSettings(new Dekko::Settings::SettingsFileBase);
Dekko::Settings::MailboxSettings::setDefaultFile(mboxSettings.data());
QLockFile *mboxLock = 0;
QString mlPath = Dekko::configLocation(QStringLiteral("mailboxConfig.json.lock"));
if (!checkForStaleLockFile(&mboxLock, mlPath , error)) {
qCritical() << error;
return 1;
}
mboxSettings.data()->setPath(Dekko::configLocation(QStringLiteral("mailboxConfig.json")));
QScopedPointer<QLockFile> mboxLockFile(mboxLock);
// Notification settings
QScopedPointer<Dekko::Settings::SettingsFileBase> notificationSettings(new Dekko::Settings::SettingsFileBase);
Dekko::Settings::NotificationSettings::setSettingsFile(notificationSettings.data());
QLockFile *notifyLock = 0;
QString nlPath = Dekko::configLocation(QStringLiteral("notifications.json.lock"));
if (!checkForStaleLockFile(¬ifyLock, nlPath, error)) {
qCritical() << error;
return 1;
}
notificationSettings.data()->setPath(Dekko::configLocation(QStringLiteral("notifications.json")));
QScopedPointer<QLockFile> notifyLockFile(notifyLock);
// View settings
QScopedPointer<Dekko::Settings::SettingsFileBase> viewSettings(new Dekko::Settings::SettingsFileBase);
Dekko::Settings::ViewSettings::setViewSettingsFile(viewSettings.data());
QLockFile *viewLock = 0;
QString vlPath = Dekko::configLocation(QStringLiteral("viewSettings.json.lock"));
if (!checkForStaleLockFile(&viewLock, vlPath, error)) {
qCritical() << error;
return 1;
}
viewSettings.data()->setPath(Dekko::configLocation(QStringLiteral("viewSettings.json")));
QScopedPointer<QLockFile> viewLockFile(viewLock);
QSharedPointer<QQuickView> qQuickViewer = Dekko::Utils::CustomQQuickViewFactory::instance();
qQuickViewer->setResizeMode(QQuickView::SizeRootObjectToView);
app.addLibraryPath(QCoreApplication::applicationDirPath());
// let's first check all standard locations
QString qmlFile = Dekko::findQmlFile(QStringLiteral("qml/main.qml"));
QUrl addressbookStoreLocation(QStringLiteral(
"file://%1/.local/share/dekko.dekkoproject/addressbook.vcard")
.arg(QDir::homePath()));
qQuickViewer->engine()->rootContext()->setContextProperty(QStringLiteral("addressbookStoreLocation"), QVariant::fromValue(addressbookStoreLocation));
Dekko::Network::MsgPartNetAccessManagerFactory msgPartNetAccessManagerFactory;
qQuickViewer->engine()->setNetworkAccessManagerFactory(&msgPartNetAccessManagerFactory);
qQuickViewer->engine()->rootContext()->setContextProperty(QStringLiteral("msgPartNetAccessManagerFactory"), &msgPartNetAccessManagerFactory);
qQuickViewer->engine()->rootContext()->setContextProperty(QStringLiteral("appUris"), QString::fromLatin1(qgetenv("APP_URIS")));
#ifdef WITH_CONVERGENCE
qQuickViewer->engine()->rootContext()->setContextProperty(QStringLiteral("convergenceEnabled"), QVariant(true));
#else
qQuickViewer->engine()->rootContext()->setContextProperty(QLatin1String("convergenceEnabled"), QVariant(false));
#endif
QStringList mailToArgs;
#ifdef UNCONFINED
mailToArgs << parser.positionalArguments();
#endif
qQuickViewer->engine()->rootContext()->setContextProperty(QStringLiteral("mailToArgs"), mailToArgs);
// Context property to figure out if we are on unity8/mir or not
qQuickViewer->engine()->rootContext()->setContextProperty(QStringLiteral("isRunningOnMir"), QVariant(qgetenv("QT_QPA_PLATFORM") == "ubuntumirclient"));
DekkoGlobal::registerDekkoTypes("DekkoCore");
DekkoGlobal::registerTrojitaCoreTypes("TrojitaCore");
qQuickViewer->setTitle(QObject::trUtf8("Dekko"));
qQuickViewer->setSource(QUrl::fromLocalFile(qmlFile));
qQuickViewer->show();
return app.exec();
}
static bool checkForStaleLockFile(QLockFile **lockFile, QString &filePath, QString &errorMessage)
{
QDir dir(Dekko::configLocation(QString()));
if (!dir.exists() && !dir.mkpath(QStringLiteral("."))) {
errorMessage = QStringLiteral("Cannot create directory: %1").arg(dir.path());
return false;
}
// Reset to config directory for consistency; avoid depending on this behavior for paths
if (QDir::setCurrent(dir.absolutePath()) && dir.isRelative()) {
dir.setPath(QStringLiteral("."));
}
QLockFile *lock = new QLockFile(filePath);
*lockFile = lock;
lock->setStaleLockTime(0);
if (!lock->tryLock()) {
if (lock->error() == QLockFile::LockFailedError) {
// This happens if a stale lock file exists and another process uses that PID.
// Try removing the stale file, which will fail if a real process is holding a
// file-level lock. A false error is more problematic than not locking properly
// on corner-case systems.
if (!lock->removeStaleLockFile() || !lock->tryLock()) {
errorMessage = QStringLiteral("Configuration file is already in use");
return false;
} else
qDebug() << "Removed stale lock file";
} else {
errorMessage = QStringLiteral("Cannot write configuration file (failed to acquire lock)");
return false;
}
}
return true;
}
|