Initial commit
This commit is contained in:
@@ -0,0 +1,238 @@
|
||||
#ifndef APPLICATION_CONNECTOR_H
|
||||
#define APPLICATION_CONNECTOR_H
|
||||
|
||||
#include <QList>
|
||||
#include <QPair>
|
||||
#include <QVariant>
|
||||
|
||||
// WARNING: Not used directly in cpp file
|
||||
// You can transfer it to the cpp file, it will not be an error, but a
|
||||
// warning will remain
|
||||
#include "base_sql_table_model.h"
|
||||
#include "data_repository_signals.h"
|
||||
#include "entity_finder_widget.h"
|
||||
|
||||
// Forward declarations
|
||||
class ModelManager;
|
||||
class RepositoryManager;
|
||||
|
||||
class ApplicationConnector {
|
||||
private:
|
||||
// WARNING: Not use directly in cpp file
|
||||
|
||||
template <typename SenderType, typename ReceiverType>
|
||||
using Link = QPair<SenderType *, ReceiverType *>;
|
||||
|
||||
template <typename SignalType, typename SlotType>
|
||||
using Connection = QPair<SignalType, SlotType>;
|
||||
|
||||
template <typename SenderType, typename ReceiverType>
|
||||
using ConnectionVariant = std::variant<
|
||||
Connection<void (SenderType::*)(), bool (ReceiverType::*)()>,
|
||||
Connection<void (SenderType::*)() const, bool (ReceiverType::*)()>,
|
||||
Connection<void (SenderType::*)(), void (ReceiverType::*)()>,
|
||||
Connection<void (SenderType::*)() const, void (ReceiverType::*)()>>;
|
||||
|
||||
template <typename SenderType, typename ReceiverType>
|
||||
using ConnectionList = QList<ConnectionVariant<SenderType, ReceiverType>>;
|
||||
|
||||
template <typename Sender, typename Receiver>
|
||||
using LinkList = QList<Link<Sender, Receiver>>;
|
||||
|
||||
// Derivatives
|
||||
|
||||
using Repository = DataRepositorySignals;
|
||||
using Model = BaseSqlTableModel;
|
||||
using Finder = EntityFinderWidget;
|
||||
|
||||
// WARNING: Use only producing types in cpp file
|
||||
|
||||
// Producing types of Repository and Model
|
||||
using RMLink = QPair<Repository *, Model *>;
|
||||
using RMConnection = ConnectionVariant<Repository, Model>;
|
||||
using RMConnectionList = QList<RMConnection>;
|
||||
using RMLinkList = QList<RMLink>;
|
||||
|
||||
// Producing types of Repository and Finder
|
||||
using RFLink = QPair<Repository *, Finder *>;
|
||||
using RFConnection = ConnectionVariant<Repository, Finder>;
|
||||
using RFConnectionList = QList<RFConnection>;
|
||||
using RFLinkList = QList<RFLink>;
|
||||
|
||||
private:
|
||||
ModelManager &modelManager_;
|
||||
QObject *rootObject_;
|
||||
RepositoryManager &repositoryManager_;
|
||||
|
||||
public:
|
||||
ApplicationConnector(QObject *rootObject);
|
||||
|
||||
bool connect();
|
||||
|
||||
private:
|
||||
template <typename SenderType, typename ReceiverType>
|
||||
bool accessible(const Link<SenderType, ReceiverType> &link);
|
||||
|
||||
template <typename SignalType, typename SlotType, typename SenderType,
|
||||
typename ReceiverType>
|
||||
bool connect(SenderType *sender, ReceiverType *receiver,
|
||||
const ConnectionList<SignalType, SlotType> &connections);
|
||||
|
||||
template <typename SignalType, typename SlotType, typename SenderType,
|
||||
typename ReceiverType>
|
||||
bool connect(const LinkList<SenderType, ReceiverType> &links,
|
||||
const ConnectionList<SignalType, SlotType> &connections);
|
||||
|
||||
template <typename SignalType, typename SlotType>
|
||||
QString templateString(SignalType signal, SlotType slot, QObject *sender,
|
||||
QObject *receiver);
|
||||
|
||||
private:
|
||||
RFConnectionList repositoryToFinderConnections();
|
||||
RMConnectionList pairTableConnections();
|
||||
RMConnectionList singleTableConnections();
|
||||
|
||||
RFLinkList flattenLinkList(const QVector<RFLinkList> &linkLists);
|
||||
RFLinkList linkRepositoryToFinder(const QString &sender,
|
||||
const QString &receiver);
|
||||
RMLink linkRepositoryToModel(const QString &sender, const QString &receiver);
|
||||
|
||||
RFLinkList initializeDeleteCandidates();
|
||||
RFLinkList initializeUpdateDeleteCandidates();
|
||||
RMLinkList initializeSelfReferenceTableLinks();
|
||||
RMLinkList initializeTablePairLinks();
|
||||
|
||||
bool connectDeleteRFLinks();
|
||||
bool connectSelfReferenceTableLinks();
|
||||
bool connectTablePairLinks();
|
||||
bool connectUpdateDeleteRFLinks();
|
||||
|
||||
private:
|
||||
QString getAddress(const QObject *object);
|
||||
|
||||
QString getMetaClassName(const QMetaObject *meta);
|
||||
|
||||
QString getMethodSignature(const QMetaObject *meta, const char *methodType,
|
||||
bool isSignal);
|
||||
};
|
||||
|
||||
template <typename SenderType, typename ReceiverType>
|
||||
bool ApplicationConnector::accessible(
|
||||
const Link<SenderType, ReceiverType> &link) {
|
||||
return bool(link.first && link.second);
|
||||
}
|
||||
|
||||
template <typename SignalType, typename SlotType, typename SenderType,
|
||||
typename ReceiverType>
|
||||
bool ApplicationConnector::connect(
|
||||
const LinkList<SenderType, ReceiverType> &links,
|
||||
const ConnectionList<SignalType, SlotType> &connections) {
|
||||
for (const Link<SenderType, ReceiverType> ¤tLink : links) {
|
||||
qInfo() << "Connecting link: Index of ConnectionList:"
|
||||
<< links.indexOf(currentLink);
|
||||
|
||||
if (!accessible(currentLink)) {
|
||||
qWarning() << "Link is not accessible: Index of ConnectionList:"
|
||||
<< links.indexOf(currentLink);
|
||||
continue;
|
||||
}
|
||||
|
||||
SenderType *sender = currentLink.first;
|
||||
ReceiverType *receiver = currentLink.second;
|
||||
|
||||
if (!connect(sender, receiver, connections)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename SignalType, typename SlotType, typename SenderType,
|
||||
typename ReceiverType>
|
||||
bool ApplicationConnector::connect(
|
||||
SenderType *sender, ReceiverType *receiver,
|
||||
const ConnectionList<SignalType, SlotType> &connections) {
|
||||
|
||||
// WARNING: "auto" keyword is necessary
|
||||
auto handler = [&](const auto ¤tLink) -> bool {
|
||||
auto &[signal, slot] = currentLink;
|
||||
|
||||
bool connected = QObject::connect(sender, signal, receiver, slot);
|
||||
if (!connected) {
|
||||
qWarning().noquote() << "Failed to connect signal to slot:"
|
||||
<< templateString(signal, slot, sender, receiver);
|
||||
} else {
|
||||
qInfo().noquote() << "Connected signal to slot:"
|
||||
<< templateString(signal, slot, sender, receiver);
|
||||
}
|
||||
|
||||
return connected;
|
||||
};
|
||||
|
||||
for (const ConnectionVariant<SenderType, ReceiverType> ¤tConnection :
|
||||
connections) {
|
||||
bool connected = std::visit(handler, currentConnection);
|
||||
if (!connected) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename SignalType, typename SlotType>
|
||||
QString ApplicationConnector::templateString(SignalType signal, SlotType slot,
|
||||
QObject *sender,
|
||||
QObject *receiver) {
|
||||
const QMetaObject *senderMeta = sender ? sender->metaObject() : nullptr;
|
||||
const QMetaObject *receiverMeta = receiver ? receiver->metaObject() : nullptr;
|
||||
|
||||
auto width = [](int index) {
|
||||
switch (index) {
|
||||
case 0:
|
||||
return 10;
|
||||
case 1:
|
||||
return -30;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
QString billetTA = QString("\n\t|%0: Type: %1 Address: 0x%2");
|
||||
QString billetTAN = billetTA + QString(" Name: \"%3\"");
|
||||
QString result;
|
||||
|
||||
QString signalT = getMethodSignature(senderMeta, typeid(signal).name(), true);
|
||||
QString signalA = senderMeta ? getAddress(sender) : "null";
|
||||
|
||||
result +=
|
||||
billetTA.arg("Signal", width(0)).arg(signalT, width(1)).arg(signalA);
|
||||
|
||||
QString slotT = getMethodSignature(receiverMeta, typeid(slot).name(), false);
|
||||
QString slotA = receiverMeta ? getAddress(receiver) : "null";
|
||||
|
||||
result += billetTA.arg("Slot", width(0)).arg(slotT, width(1)).arg(slotA);
|
||||
|
||||
QString senderT = getMetaClassName(senderMeta);
|
||||
QString senderA = getAddress(sender);
|
||||
QString senderN = sender->objectName();
|
||||
|
||||
result += billetTAN.arg("Sender", width(0))
|
||||
.arg(senderT, width(1))
|
||||
.arg(senderA)
|
||||
.arg(senderN);
|
||||
|
||||
QString receiverT = getMetaClassName(receiverMeta);
|
||||
QString receiverA = getAddress(receiver);
|
||||
QString receiverN = receiver->objectName();
|
||||
|
||||
result += billetTAN.arg("Receiver", width(0))
|
||||
.arg(receiverT, width(1))
|
||||
.arg(receiverA)
|
||||
.arg(receiverN);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // APPLICATION_CONNECTOR_H
|
||||
Reference in New Issue
Block a user