5 #include "controller_p.h" 7 #include "application.h" 8 #include "dispatcher.h" 12 #include "context_p.h" 14 #include <QMetaClassInfo> 15 #include <QRegularExpression> 20 , d_ptr(new ControllerPrivate(this))
24 Controller::~Controller()
27 qDeleteAll(d->actionList);
40 auto it = d->actions.constFind(name);
41 if (it != d->actions.constEnd()) {
44 return d->dispatcher->getAction(name, d->pathPrefix);
50 auto it = d->actions.constFind(name);
51 if (it != d->actions.constEnd()) {
54 return d->dispatcher->getAction(name.
toString(), d->pathPrefix);
65 return !qstrcmp(
metaObject()->className(), className);
80 ControllerPrivate::ControllerPrivate(
Controller *parent) :
89 dispatcher = _dispatcher;
97 q->setObjectName(className);
99 bool namespaceFound =
false;
106 namespaceFound =
true;
111 if (!namespaceFound) {
113 bool lastWasUpper =
true;
115 for (
int i = 0; i < className.
length(); ++i) {
116 const QChar c = className.
at(i);
119 lastWasUpper =
false;
133 pathPrefix = controlerNS;
136 registerActionMethods(meta, q, app);
139 void ControllerPrivate::setupFinished()
143 const ActionList beginList = dispatcher->getActions(QStringLiteral(
"Begin"), pathPrefix);
148 beginAutoList.append(dispatcher->getActions(QStringLiteral(
"Auto"), pathPrefix));
150 const ActionList endList = dispatcher->getActions(QStringLiteral(
"End"), pathPrefix);
152 end = endList.
last();
155 const auto actions = actionList;
156 for (
Action *action : actions) {
157 action->dispatcherReady(dispatcher, q);
160 q->preFork(qobject_cast<Application *>(q->parent()));
169 int &asyncDetached = c->d_ptr->asyncDetached;
172 const auto beginAutoList = d->beginAutoList;
173 for (
Action *action : beginAutoList) {
175 c->d_ptr->pendingAsync.append(action);
176 }
else if (!action->dispatch(c)) {
185 c->d_ptr->pendingAsync.append(c->action());
194 c->d_ptr->pendingAsync.append(d->end);
195 }
else if (!d->end->dispatch(c)) {
201 c->d_ptr->engineRequest->status |= EngineRequest::Async;
207 Action *ControllerPrivate::actionClass(
const QVariantHash &args)
209 const auto attributes = args.value(QStringLiteral(
"attributes")).value<
ParamsMultiMap>();
210 const QString actionClass = attributes.value(QStringLiteral(
"ActionClass"));
212 QObject *
object = instantiateClass(actionClass,
"Cutelyst::Action");
218 qCWarning(CUTELYST_CONTROLLER) <<
"ActionClass" 220 <<
"is not an ActionClass";
229 Action *action = actionClass(args);
235 for (
int i = 0; i < roles.
size(); ++i) {
237 code->
init(app, args);
243 action->
setName(args.value(QStringLiteral(
"name")).toString());
244 action->
setReverse(args.value(QStringLiteral(
"reverse")).toString());
268 if (name == classInfo.
name()) {
272 ParamsMultiMap attrs = parseAttributes(method, attributeArray, name);
281 Action *action = createAction({
292 actionList.append(action);
300 std::vector<std::pair<QString, QString> > attributes;
307 int size = str.
size();
314 if (str.
at(pos) ==
':') {
315 int keyStart = ++pos;
318 if (str.
at(pos) ==
'(') {
320 int valueStart = ++pos;
322 if (str.
at(pos) ==
')') {
325 if (++pos < size && str.
at(pos) ==
':') {
330 }
else if (pos >= size) {
343 }
else if (str.
at(pos) ==
':') {
355 if (!value.isEmpty()) {
359 value.remove(value.size() - 1, 1);
364 attributes.emplace_back(std::make_pair(key, value));
372 for (
const auto &pair : attributes) {
375 if (key.
compare(u
"Global") == 0) {
376 key = QStringLiteral(
"Path");
378 }
else if (key.
compare(u
"Local") == 0) {
379 key = QStringLiteral(
"Path");
381 }
else if (key.
compare(u
"Path") == 0) {
382 value = parsePathAttr(value);
383 }
else if (key.
compare(u
"Args") == 0) {
388 }
else if (key.
compare(u
"CaptureArgs") == 0) {
391 }
else if (key.
compare(u
"Chained") == 0) {
392 value = parseChainedAttr(value);
399 if (!ret.
contains(QStringLiteral(
"Args")) && !ret.
contains(QStringLiteral(
"CaptureArgs")) &&
400 (ret.
contains(QStringLiteral(
"AutoArgs")) || ret.
contains(QStringLiteral(
"AutoCaptureArgs")))) {
401 if (ret.
contains(QStringLiteral(
"AutoArgs")) && ret.
contains(QStringLiteral(
"AutoCaptureArgs"))) {
402 qFatal(
"Action '%s' has both AutoArgs and AutoCaptureArgs, which is not allowed", name.
constData());
405 if (ret.
contains(QStringLiteral(
"AutoArgs"))) {
406 ret.
remove(QStringLiteral(
"AutoArgs"));
407 parameterName = QStringLiteral(
"Args");
409 ret.
remove(QStringLiteral(
"AutoCaptureArgs"));
410 parameterName = QStringLiteral(
"CaptureArgs");
415 int parameterCount = 0;
418 if (typeId == QMetaType::QString) {
429 if (!ret.
contains(QStringLiteral(
"Private")) && method.
access() == QMetaMethod::Private) {
440 auto doesIt = attributes.
constFind(QStringLiteral(
"Does"));
441 while (doesIt != attributes.constEnd() && doesIt.
key().compare(u
"Does") == 0) {
442 QObject *
object = instantiateClass(doesIt.
value(), QByteArrayLiteral(
"Cutelyst::Component"));
444 roles.
push(qobject_cast<Component *>(
object));
456 }
else if (!value.isEmpty()) {
464 QString ret = QStringLiteral(
"/");
472 if (!pathPrefix.isEmpty()) {
491 #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) 498 id = QMetaType::fromName(instanceName.
toLatin1().
data());
499 if (!
id.isValid() && !instanceName.
startsWith(u
"Cutelyst::")) {
501 id = QMetaType::fromName(instanceName.
toLatin1().
data());
508 if (!superIsClassName(metaObj->
superClass(), super)) {
509 qCWarning(CUTELYST_CONTROLLER)
512 <<
"is not a derived class of" 518 qCWarning(CUTELYST_CONTROLLER)
519 <<
"Could create a new instance of" 521 <<
"make sure it's default constructor is " 522 "marked with the Q_INVOKABLE macro";
528 Component *component = application->createComponentPlugin(name);
533 component = application->createComponentPlugin(instanceName);
540 qCCritical(CUTELYST_CONTROLLER,
541 "Could not create component '%s', you can register it with qRegisterMetaType<%s>(); or set a proper CUTELYST_PLUGINS_DIR",
542 qPrintable(instanceName), qPrintable(instanceName));
553 if (!
id && !instanceName.
startsWith(u
"Cutelyst::")) {
562 if (!superIsClassName(metaObj->
superClass(), super)) {
563 qCWarning(CUTELYST_CONTROLLER)
566 <<
"is not a derived class of" 572 qCWarning(CUTELYST_CONTROLLER)
573 <<
"Could create a new instance of" 575 <<
"make sure it's default constructor is " 576 "marked with the Q_INVOKABLE macro";
582 Component *component = application->createComponentPlugin(name);
587 component = application->createComponentPlugin(instanceName);
594 qCCritical(CUTELYST_CONTROLLER,
595 "Could not create component '%s', you can register it with qRegisterMetaType<%s>(); or set a proper CUTELYST_PLUGINS_DIR",
596 qPrintable(instanceName), qPrintable(instanceName));
609 return superIsClassName(super->
superClass(), className);
614 #include "moc_controller.cpp" void setName(const QString &name)
QString & append(QChar ch)
bool dispatch(Context *c)
typename QMap< Key, T >::const_iterator constFind(const Key &key, const T &value) const const
void append(const T &value)
typename QMap< Key, T >::iterator replace(const Key &key, const T &value)
char at(int i) const const
void setReverse(const QString &reverse)
bool isDigit() const const
virtual bool preFork(Application *app)
Action * actionFor(const QString &name) const
QString & remove(int position, int n)
The Cutelyst Component base class.
T value(int i) const const
This class represents a Cutelyst Action.
QString number(int n, int base)
Cutelyst Controller base class
int remove(const Key &key, const T &value)
bool isEmpty() const const
const char * constData() const const
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const const
bool endsWith(const QString &s, Qt::CaseSensitivity cs) const const
virtual bool init(Application *application, const QVariantHash &args)
typename QMap< Key, T >::iterator insert(const Key &key, const T &value)
bool _DISPATCH(Context *c)
The Cutelyst namespace holds all public Cutelyst API.
void applyRoles(const QStack< Component *> &roles)
QByteArray mid(int pos, int len) const const
QByteArray & append(char ch)
void setParent(QObject *parent)
QVariant fromValue(const T &value)
QChar toLower() const const
void setController(Controller *controller)
virtual bool postFork(Application *app)
const Key key(const T &value, const Key &defaultKey) const const
bool contains(const Key &key, const T &value) const const
const T & at(int i) const const
QByteArray toLatin1() const const
QString toString() const const
bool isEmpty() const const
void setupAction(const QVariantHash &args, Application *app)
const QChar at(int position) const const
QString fromLatin1(const char *str, int size)
bool operator==(const char *className)
The Cutelyst Application.
void setMethod(const QMetaMethod &method)
ActionList actions() const
int compare(const QString &other, Qt::CaseSensitivity cs) const const
bool isLower() const const
const T value(const Key &key, const T &defaultValue) const const
Controller(QObject *parent=nullptr)