forked from cutelyst/cutelyst
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathapplication.h
460 lines (409 loc) · 15 KB
/
application.h
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
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
/*
* Copyright (C) 2013-2017 Daniel Nicoletti <[email protected]>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef CUTELYST_APPLICATION_H
#define CUTELYST_APPLICATION_H
#include <QtCore/QObject>
#include <QtCore/QVariant>
#include <QtCore/QLocale>
#include <QtCore/QVector>
#include <Cutelyst/cutelyst_global.h>
class QTranslator;
namespace Cutelyst {
#define CUTELYST_APPLICATION(x) \
Q_PLUGIN_METADATA(x) \
Q_INTERFACES(Cutelyst::Application)
class Context;
class Controller;
class Component;
class View;
class Dispatcher;
class DispatchType;
class Request;
class Response;
class Engine;
class EngineRequest;
class Plugin;
class Headers;
class ApplicationPrivate;
/*! \class Application application.h Cutelyst/Application
* @brief The %Cutelyst %Application
*
* This is the main class of a Cutelyst appplication
*/
class CUTELYST_LIBRARY Application : public QObject
{
Q_OBJECT
Q_DECLARE_PRIVATE(Application)
public:
/**
* The constructor is used to setup the class configuration,
* subclasses should only use this for objects that do
* not require configuration to be ready.
*
* A Web Engine will instantiate your application through this
* class, next it will load the settings file, and in the end
* it will call init() which is where your application
* should do it's own setup.
*
* \warning DO NOT register your controllers,
* plugins or anything that might want to
* use config() in here, do that in init()
*/
explicit Application(QObject *parent = nullptr);
virtual ~Application();
/**
* Returns a list with all registered controllers.
*
* The list might only be complete after application has been setup.
*/
QVector<Controller *> controllers() const;
/**
* Returns the view specified by \p name, if no view is found nullptr is returned.
*/
View *view(const QString &name = QString()) const;
/**
* Returns application config specified by \p key, with a possible default value.
*/
QVariant config(const QString &key, const QVariant &defaultValue = QVariant()) const;
/**
* Returns the dispatcher class.
*/
Dispatcher *dispatcher() const;
/**
* Returns a list with all registered dispachers.
*
* The list might only be complete after application has been setup.
*/
QVector<DispatchType *> dispatchers() const;
/**
* Returns all registered plugins
*/
QVector<Plugin *> plugins() const;
/*!
* Returns the registered plugin that casts to the template type \p T
*/
template <typename T>
T plugin()
{
const auto pluginsConst = plugins();
for (Plugin *plugin : pluginsConst) {
auto p = qobject_cast<T>(plugin);
if (p) {
return p;
}
}
return nullptr;
}
/**
* User configuration for the application
* @return A variant hash with configuration settings
*/
QVariantMap config() const;
/**
* Merges path with config("HOME") and returns an absolute path.
*/
QString pathTo(const QString &path) const;
/**
* Merges path with config("HOME") and returns an absolute path.
*/
QString pathTo(const QStringList &path) const;
/**
* Returns true if the application has been inited.
*/
bool inited() const;
/**
* Returns current engine that is generating requests.
*/
Engine *engine() const;
/**
* Tries to load a plugin in Cutelyst default plugin directory with \p parent as it's parent.
* A nullptr is returned in case of failure.
*/
Component *createComponentPlugin(const QString &name, QObject *parent = nullptr);
/**
* Returns cutelyst version.
*/
static const char *cutelystVersion();
/**
* Adds a @a translator for the specified @a locale.
*
* You can add multiple translators for different application parts for every supported
* locale. The installed translators will then be used by Context::translate() (what itself
* will use Application::translate()) to translate strings according to the locale set by
* Context::setLocale().
*
* @par Usage example:
* @code{.cpp}
* bool MyCutelystApp::init()
* {
* // ...
*
* auto trans = new QTranslator(this);
* QLocale deDE(QLocale::German, QLocale::Germany);
* if (trans->load(deDE, QStringLiteral("mycutelystapp"), QStringLiteral("."), QStringLiteral("/usr/share/mycutelystapp/l10n")) {
* addTranslator(deDE, trans);
* }
*
* // ...
* }
* @endcode
*
* @sa loadTranslations()
*
* @since Cutelyst 1.5.0
*/
void addTranslator(const QLocale &locale, QTranslator *translator);
/**
* Adds a @a translator for the specified @a locale.
*
* The @a locale string has to be parseable by QLocale.
*
* @overload
*
* @since Cutelyst 1.5.0
*/
void addTranslator(const QString &locale, QTranslator *translator);
/**
* Adds multiple @a translators for the specified @a locale.
*
* @sa addTranslator()
*
* @since Cutelyst 1.5.0
*/
void addTranslators(const QLocale &locale, const QVector<QTranslator *> &translators);
/**
* Translates the @a sourceText into the target @a locale language.
*
* This uses the installed translators for the specified @a locale to translate the @a sourceText for the
* given @a context into the target locale. Optionally you can use a @a disambiguation and/or the @a n parameter
* to translate a pluralized version.
*
* @sa Context::translate(), QTranslator::translate()
*
* @since Cutelyst 1.5.0
*/
QString translate(const QLocale &locale, const char *context, const char *sourceText, const char *disambiguation = nullptr, int n = -1) const;
/**
* Loads translations for a specific @a filename from a single directory.
*
* This can be used to load translations for a specific component if the translation file names follow a common schema.
* Let us assume you organised your translation files as follows:
* @li @c /usr/share/myapp/translations/myapp_de.qm
* @li @c /usr/share/myapp/translations/myapp_pt_BR.qm
* @li @c ...
*
* You can then use loadTranslations() in your reimplementation of Application::init() as follows:
* @code{.cpp}
* bool MyApp::init()
* {
* loadTranslations(QStringLiteral("myapp"), QStringLiteral("/usr/share/myapp/translations"), QStringLiteral("_"));
* }
* @endcode
*
* If @a directory is empty, the default directory, set by <code>-DI18NDIR</code>, will be used. @a prefix is the part between
* the file name and the locale part. In the example above it is @c "_", if it is not set the default @c "." will be used. The
* @a suffix is the file name suffix that defaults to <code>".qm"</code>.
*
* @sa addTranslator(), loadTranslationsFromDir(), loadTranslationsFromDirs()
*
* @since Cuteylst 2.0.0
*/
void loadTranslations(const QString &filename, const QString &directory = QString(), const QString &prefix = QString(), const QString &suffix = QString());
/**
* Loads translations for a specific @a filename from a single directory and returns a list of added locales.
*
* This can be used to load translations for a specific component if the translation file names follow a common schema.
* Let us assume you organised your translation files as follows:
* @li @c /usr/share/myapp/translations/myapp_de.qm
* @li @c /usr/share/myapp/translations/myapp_pt_BR.qm
* @li @c ...
*
* You can then use loadTranslationsFromDir() in your reimplementation of Application::init() as follows:
* @code{.cpp}
* bool MyApp::init()
* {
* loadTranslationsFromDir(QStringLiteral("myapp"), QStringLiteral("/usr/share/myapp/translations"), QStringLiteral("_"));
* }
* @endcode
*
* If @a directory is empty, the default directory, set by <code>-DI18NDIR</code>, will be used. @a prefix is the part between
* the file name and the locale part. In the example above it is @c "_", if it is not set the default @c "." will be used. The
* @a suffix is the file name suffix that defaults to <code>".qm"</code>.
*
* @sa addTranslator(), loadTranslationsFromDirs()
*
* @since Cuteylst 2.1.0
*/
QVector<QLocale> loadTranslationsFromDir(const QString &filename, const QString &directory = QString(), const QString &prefix = QStringLiteral("."), const QString &suffix = QStringLiteral(".qm"));
/**
* Loads translations for a specific @a filename from a directory structure under @a directory and returns a list of added locales.
*
* This can be used to load translations for a specific component or application if the the translation files are organized in
* subdirectories named after locale codes. Let us assume you organised your translation files as follows:
* @li @c /usr/share/locale/de/LC_MESSAGES/myapp.qm
* @li @c /usr/share/locale/pt_BR/LC_MESSAGES/myapp.qm
* @li @c ...
*
* You can then use loadTranslationsFromDirs() in your reimplementation of Application::init() as follows:
* @code{.cpp}
* bool MyApp::init()
* {
* loadTranslationsFromDirs(QStringLiteral("/usr/share/locale"), QStringLiteral("LC_MESSAGES/myapp.qm"));
* }
* @endcode
*
* @sa addTranslator(), loadTranslationsFromDir()
*
* @since Cutelyst 2.1.0
*/
QVector<QLocale> loadTranslationsFromDirs(const QString &directory, const QString &filename);
protected:
/**
* Do your application initialization here, if your
* application should not proceed log some information
* that might help on debuggin and return false
*
* For example if your application only works with
* PostgeSQL and the Qt driver is not available it
* makes sense to fail here. However you should not
* initialize resouces that cannot be shared among
* process. \sa postFork
*
* @return \c true if your application was successfuly initted
*/
virtual bool init();
/**
* This method is called after the engine forks
*
* After the web engine forks itself it will call
* this function so that you can initialize resources
* that can't be shared with the parent process, namely
* sockets and file descriptors.
*
* A good example of usage of this function is when
* openning a connection to the database which can't
* be shared with other process and should probably
* make this function return false if it fails to open.
*
* Default implementation returns true.
*
* @return False if the engine should not use this process
*/
virtual bool postFork();
/**
* This is the HTTP default response headers that each request gets
*
* Do not change it after the application has started.
*/
Headers &defaultHeaders();
/**
* Registers a global plugin ie one that doesn't need
* to be created explicity for a single request and returns
* true on plugin->isApplicationPlugin();
*
* @return \c true if the plugin could be registered
*/
bool registerPlugin(Plugin *plugin);
/**
* This method registers a Controller class which
* is responsible for handlying Requests,
* since they are reused between multiple requests
* beaware of not storing data there, instead you
* might want to use a session plugin or the stash.
*
* @param controller the Controller class
* @return \c true if succeeded
*/
bool registerController(Controller *controller);
/**
* This method registers a View class which
* is responsible for rendering requests.
*
* @param view the View class
* @return \c true if succeeded
*/
bool registerView(View *view);
/**
* Registers a custom DispatchType, if none is registered
* all the built-in dispatchers types will be registered
*/
bool registerDispatcher(DispatchType *dispatcher);
Q_SIGNALS:
/**
* This signal is emitted before the Dispatcher
* is called to find an action.
* It's useful if you need to intercept requests
* before they are dispached.
* Always check skipMethod and return if it's true.
* In case you want to stop further processing set
* skipMethod to true.
*/
void beforePrepareAction(Context *c, bool *skipMethod);
/**
* This signal is emitted right after the Dispatcher
* returns the Action that will be executed.
*/
void beforeDispatch(Context *c);
/**
* This signal is emitted right after the Action
* found by the dispatcher got executed.
*/
void afterDispatch(Context *c);
/**
* This signal is emitted right after application has been setup
* and before application forks and \sa postFork() is called.
*/
void preForked(Application *app);
/**
* This signal is emitted after before \sa postFork() is called.
*/
void postForked(Application *app);
/**
* This signal is likely to be emitted when the worker process should
* stop, at this point the application has a limited time to finish it's
* operations, if a timeout is reached the application will get killed.
*/
void shuttingDown(Application *app);
protected:
/**
* Change the value of the configuration key
* You should never call this from random parts of the
* code as a way to store shareable data, it should
* only be called by a subclass
*/
void setConfig(const QString &key, const QVariant &value);
friend class Engine;
friend class Context;
/*!
* Called by the Engine to setup the internal data
*/
bool setup(Engine *engine);
/*!
* Called by the Engine to handle a new Request object
*/
void handleRequest(Cutelyst::EngineRequest *request);
/*!
* Called by the Engine once post fork happened
*/
bool enginePostFork();
ApplicationPrivate *d_ptr;
};
}
#define CutelystApplicationInterface_iid "org.cutelyst.CutelystApplicationInterface"
Q_DECLARE_INTERFACE(Cutelyst::Application, CutelystApplicationInterface_iid)
#endif // CUTELYST_APPLICATION_H