/** * Helper class for simple function topic request handling * $Id$ * $HeadURL$ * $Author$ */ #pragma once #ifdef REQUEST_HELPER_WITH_GUI #include #define LTSUTILSGUIDDS_INTERNAL_EXPORT LTSUTILSGUIDDS_EXPORT #else #include #define LTSUTILSGUIDDS_INTERNAL_EXPORT LTSUTILSDDS_EXPORT #endif #include #include // Core::FunctionReply (base reply) #include #include #include #include namespace LtsUtils { template dds::core::optional toOptional(T inVal) { return inVal != T() ? dds::core::optional(inVal) : dds::core::optional(); } template dds::core::optional optional() { return dds::core::optional(); } class LTSUTILSGUIDDS_INTERNAL_EXPORT RequestHelper : public QObject // TODO: DOC !!! { Q_OBJECT public: static bool s_debug; explicit RequestHelper(QObject *parent = nullptr, bool quiet = false, // for non-blocking const std::function &success = [](){}, const std::function &failure = [](){}); ~RequestHelper() = default; bool quiet() const { return m_quiet; } void setQuiet(bool quiet) { m_quiet = quiet; } void addRequest(const std::function &requestFunction, const std::function &baseReplyHandler = nullptr); bool startRequests(); // blocks! // do not throw a message if this method fails, as this method does this already // blocks! bool startSingleRequest(const std::function &requestFunction, const std::function &baseReplyHandler = nullptr // for replies that return a custom FunctionReply, which has to be handled >>after successful execution<< ); // non-blocking ! /** * @brief startSingleBackgroundRequest << you cannot reuse this request helper after using background requests! Only use if your REALLY need it. * @param requestFunction * @param baseReplyHandler */ void startSingleBackgroundRequest(const std::function &requestFunction, const std::function &baseReplyHandler = nullptr); /** * @brief startBackgroundRequests << you cannot reuse this request helper after using background requests! Only use if your REALLY need it. */ void startBackgroundRequests(); // non-blocking ! bool requestReply(const Core::FunctionReply &baseReply); // if you have a custom FunctionReply, pass the base ptr bool requestReply(const Core::FunctionReplyObject &replyObject); /** * @brief hasRequests are requests is added? * @return True if a request is added, otherwise false */ bool hasRequests() const { return !m_requestFunctions.isEmpty(); } /** * @brief getRepliedId returns the Return-ID of the ReplyObject you gave to the method 'requestReply' - which is mostly the ID for the new Table Entry (Unique ID) * @return the Return-ID or -1 on error (not set) */ int getRepliedId() const { return m_repliedId; } /** * @brief getErrorString returns the error string set by an ftc reply * @return */ QString getErrorString() const { return m_errorString; } /** * @brief setCustomWaitMessage changes the default 'Waiting for server reply ...' message with a custom one (NOTE: " ..." is automagically added to the custom text) * After a request was started, the custom wait message is immediately reset, so that the next call to start a request, shows the default message again * @param customWaitMessage the wait message to replace the default message with (note that " ..." is added to the text) */ void setCustomWaitMessage(const QString &customWaitMessage); bool failed() const { return m_failed; } void failure(); private: using RequestFunctionContainer = QPair, std::function>; QVector m_requestFunctions; bool m_failed; int m_repliedId; std::function m_singleRequestCustomFunctionReply; bool m_quiet; bool m_blockingCall; std::function m_successFn; std::function m_failureFn; QString m_errorString; QString m_customWaitMessage; void done(); bool _requestReply(const Core::FunctionReplyObject &fro, const Core::FunctionReply *baseReply); signals: void signalNextRequest(); void signalQuitLoop(); void signalSuccess(); void signalFailed(); private slots: void slotNextRequest(); }; } // namespace LtsUtils