File indexing completed on 2024-05-12 15:26:57

0001 /***************************************************************************
0002 File        : MQTTSubscription.cpp
0003 Project     : LabPlot
0004 Description : Represents a subscription made in MQTTClient
0005 --------------------------------------------------------------------
0006 Copyright   : (C) 2018 Kovacs Ferencz (kferike98@gmail.com)
0007 
0008 ***************************************************************************/
0009 
0010 /***************************************************************************
0011 *                                                                         *
0012 *  This program is free software; you can redistribute it and/or modify   *
0013 *  it under the terms of the GNU General Public License as published by   *
0014 *  the Free Software Foundation; either version 2 of the License, or      *
0015 *  (at your option) any later version.                                    *
0016 *                                                                         *
0017 *  This program is distributed in the hope that it will be useful,        *
0018 *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
0019 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
0020 *  GNU General Public License for more details.                           *
0021 *                                                                         *
0022 *   You should have received a copy of the GNU General Public License     *
0023 *   along with this program; if not, write to the Free Software           *
0024 *   Foundation, Inc., 51 Franklin Street, Fifth Floor,                    *
0025 *   Boston, MA  02110-1301  USA                                           *
0026 *                                                                         *
0027 ***************************************************************************/
0028 #include "backend/datasources/MQTTSubscription.h"
0029 #include "backend/datasources/MQTTTopic.h"
0030 #include "backend/datasources/MQTTClient.h"
0031 
0032 #include <KLocalizedString>
0033 #include <QIcon>
0034 
0035 /*!
0036   \class MQTTSubscription
0037   \brief Represents a subscription made in a MQTTClient object. It plays a role in managing MQTTTopic objects
0038   and makes possible representing the subscriptions and topics in a tree like structure
0039 
0040   \ingroup datasources
0041 */
0042 MQTTSubscription::MQTTSubscription(const QString& name) : Folder(name, AspectType::MQTTSubscription),
0043     m_subscriptionName(name) {
0044     qDebug() << "New MQTTSubscription: " << name;
0045 }
0046 
0047 MQTTSubscription::~MQTTSubscription() {
0048     qDebug() << "Delete MQTTSubscription: " << m_subscriptionName;
0049 }
0050 
0051 /*!
0052  *\brief Returns the object's MQTTTopic children
0053  *
0054  * \return a vector of pointers to the children of the MQTTSubscription
0055  */
0056 const QVector<MQTTTopic*> MQTTSubscription::topics() const {
0057     return children<MQTTTopic>();
0058 }
0059 
0060 /*!
0061  *\brief Returns the object's parent
0062  *
0063  * \return a pointer to the parent MQTTTopic of the object
0064  */
0065 MQTTClient* MQTTSubscription::mqttClient() const {
0066     return m_MQTTClient;
0067 }
0068 
0069 /*!
0070  *\brief Called when a message arrived to a topic contained by the MQTTSubscription
0071  * If the topic can't be found among the children, a new MQTTTopic is instantiated
0072  * Passes the messages to the appropriate MQTTTopic
0073  *
0074  * \param message the message to pass
0075  * \param topicName the name of the topic the message was sent to
0076  */
0077 void MQTTSubscription::messageArrived(const QString& message, const QString& topicName) {
0078     bool found = false;
0079     QVector<MQTTTopic*> topics = children<MQTTTopic>();
0080     //search for the topic among the MQTTTopic children
0081     for (auto* topic: topics) {
0082         if (topicName == topic->topicName()) {
0083             //pass the message to the topic
0084             topic->newMessage(message);
0085 
0086             //read the message if needed
0087             if ((m_MQTTClient->updateType() == MQTTClient::UpdateType::NewData) &&
0088                     !m_MQTTClient->isPaused())
0089                 topic->read();
0090 
0091             found = true;
0092             break;
0093         }
0094     }
0095 
0096     //if the topic can't be found, we add it as a new MQTTTopic, and read from it if needed
0097     if (!found) {
0098         auto* newTopic = new MQTTTopic(topicName, this, false);
0099         addChildFast(newTopic); //no need for undo/redo here
0100         newTopic->newMessage(message);
0101         if ((m_MQTTClient->updateType() == MQTTClient::UpdateType::NewData) && !m_MQTTClient->isPaused())
0102             newTopic->read();
0103     }
0104 }
0105 
0106 /*!
0107  *\brief Returns the subscription's name
0108  *
0109  * \return m_subscriptionName
0110  */
0111 QString MQTTSubscription::subscriptionName() const {
0112     return m_subscriptionName;
0113 }
0114 
0115 /*!
0116  *\brief Sets the MQTTClient the subscription belongs to
0117  *
0118  * \param client
0119  */
0120 void MQTTSubscription::setMQTTClient(MQTTClient* client) {
0121     m_MQTTClient = client;
0122 }
0123 
0124 /*!
0125  *\brief Returns the icon of MQTTSubscription
0126  */
0127 QIcon MQTTSubscription::icon() const {
0128     return QIcon::fromTheme("mail-signed-full");
0129 }
0130 
0131 //##############################################################################
0132 //##################  Serialization/Deserialization  ###########################
0133 //##############################################################################
0134 /*!
0135   Saves as XML.
0136  */
0137 void MQTTSubscription::save(QXmlStreamWriter* writer) const {
0138     writer->writeStartElement("MQTTSubscription");
0139     writeBasicAttributes(writer);
0140     writeCommentElement(writer);
0141 
0142     //general
0143     writer->writeStartElement("general");
0144     writer->writeAttribute("subscriptionName", m_subscriptionName);
0145     writer->writeEndElement();
0146 
0147     //MQTTTopics
0148     for (auto* topic : children<MQTTTopic>(AbstractAspect::ChildIndexFlag::IncludeHidden))
0149         topic->save(writer);
0150 
0151     writer->writeEndElement(); // "MQTTSubscription"
0152 }
0153 
0154 /*!
0155   Loads from XML.
0156 */
0157 bool MQTTSubscription::load(XmlStreamReader* reader, bool preview) {
0158     if (!readBasicAttributes(reader))
0159         return false;
0160 
0161     QXmlStreamAttributes attribs;
0162 
0163     while (!reader->atEnd()) {
0164         reader->readNext();
0165         if (reader->isEndElement() && reader->name() == "MQTTSubscription")
0166             break;
0167 
0168         if (!reader->isStartElement())
0169             continue;
0170 
0171         if (reader->name() == "comment") {
0172             if (!readCommentElement(reader))
0173                 return false;
0174         } else if (reader->name() == "general") {
0175             attribs = reader->attributes();
0176             m_subscriptionName = attribs.value("subscriptionName").toString();
0177         } else if(reader->name() == QLatin1String("MQTTTopic")) {
0178             auto* topic = new MQTTTopic(QString(), this, false);
0179             if (!topic->load(reader, preview)) {
0180                 delete topic;
0181                 return false;
0182             }
0183             addChildFast(topic);
0184         } else {// unknown element
0185             reader->raiseWarning(i18n("unknown element '%1'", reader->name().toString()));
0186             if (!reader->skipToEndElement()) return false;
0187         }
0188     }
0189 
0190     emit loaded(this->subscriptionName());
0191     return !reader->hasError();
0192 }
0193