File indexing completed on 2024-05-12 03:47:43
0001 /* 0002 File : MQTTSubscription.cpp 0003 Project : LabPlot 0004 Description : Represents a subscription made in MQTTClient 0005 -------------------------------------------------------------------- 0006 SPDX-FileCopyrightText: 2018 Kovacs Ferencz <kferike98@gmail.com> 0007 0008 SPDX-License-Identifier: GPL-2.0-or-later 0009 */ 0010 #include "backend/datasources/MQTTSubscription.h" 0011 #include "backend/datasources/MQTTClient.h" 0012 #include "backend/datasources/MQTTTopic.h" 0013 #include "backend/lib/XmlStreamReader.h" 0014 0015 #include <KLocalizedString> 0016 #include <QIcon> 0017 0018 /*! 0019 \class MQTTSubscription 0020 \brief Represents a subscription made in a MQTTClient object. It plays a role in managing MQTTTopic objects 0021 and makes possible representing the subscriptions and topics in a tree like structure 0022 0023 \ingroup datasources 0024 */ 0025 MQTTSubscription::MQTTSubscription(const QString& name) 0026 : Folder(name, AspectType::MQTTSubscription) 0027 , m_subscriptionName(name) { 0028 qDebug() << "New MQTTSubscription: " << name; 0029 } 0030 0031 MQTTSubscription::~MQTTSubscription() { 0032 qDebug() << "Delete MQTTSubscription: " << m_subscriptionName; 0033 } 0034 0035 /*! 0036 *\brief Returns the object's MQTTTopic children 0037 * 0038 * \return a vector of pointers to the children of the MQTTSubscription 0039 */ 0040 const QVector<MQTTTopic*> MQTTSubscription::topics() const { 0041 return children<MQTTTopic>(); 0042 } 0043 0044 /*! 0045 *\brief Returns the object's parent 0046 * 0047 * \return a pointer to the parent MQTTTopic of the object 0048 */ 0049 MQTTClient* MQTTSubscription::mqttClient() const { 0050 return m_MQTTClient; 0051 } 0052 0053 /*! 0054 *\brief Called when a message arrived to a topic contained by the MQTTSubscription 0055 * If the topic can't be found among the children, a new MQTTTopic is instantiated 0056 * Passes the messages to the appropriate MQTTTopic 0057 * 0058 * \param message the message to pass 0059 * \param topicName the name of the topic the message was sent to 0060 */ 0061 void MQTTSubscription::messageArrived(const QString& message, const QString& topicName) { 0062 bool found = false; 0063 QVector<MQTTTopic*> topics = children<MQTTTopic>(); 0064 // search for the topic among the MQTTTopic children 0065 for (auto* topic : topics) { 0066 if (topicName == topic->topicName()) { 0067 // pass the message to the topic 0068 topic->newMessage(message); 0069 0070 // read the message if needed 0071 if ((m_MQTTClient->updateType() == MQTTClient::UpdateType::NewData) && !m_MQTTClient->isPaused()) 0072 topic->read(); 0073 0074 found = true; 0075 break; 0076 } 0077 } 0078 0079 // if the topic can't be found, we add it as a new MQTTTopic, and read from it if needed 0080 if (!found) { 0081 auto* newTopic = new MQTTTopic(topicName, this, false); 0082 addChildFast(newTopic); // no need for undo/redo here 0083 newTopic->newMessage(message); 0084 if ((m_MQTTClient->updateType() == MQTTClient::UpdateType::NewData) && !m_MQTTClient->isPaused()) 0085 newTopic->read(); 0086 } 0087 } 0088 0089 /*! 0090 *\brief Returns the subscription's name 0091 * 0092 * \return m_subscriptionName 0093 */ 0094 QString MQTTSubscription::subscriptionName() const { 0095 return m_subscriptionName; 0096 } 0097 0098 /*! 0099 *\brief Sets the MQTTClient the subscription belongs to 0100 * 0101 * \param client 0102 */ 0103 void MQTTSubscription::setMQTTClient(MQTTClient* client) { 0104 m_MQTTClient = client; 0105 } 0106 0107 /*! 0108 *\brief Returns the icon of MQTTSubscription 0109 */ 0110 QIcon MQTTSubscription::icon() const { 0111 return QIcon::fromTheme(QStringLiteral("mail-signed-full")); 0112 } 0113 0114 // ############################################################################## 0115 // ################## Serialization/Deserialization ########################### 0116 // ############################################################################## 0117 /*! 0118 Saves as XML. 0119 */ 0120 void MQTTSubscription::save(QXmlStreamWriter* writer) const { 0121 writer->writeStartElement(QStringLiteral("MQTTSubscription")); 0122 writeBasicAttributes(writer); 0123 writeCommentElement(writer); 0124 0125 // general 0126 writer->writeStartElement(QStringLiteral("general")); 0127 writer->writeAttribute(QStringLiteral("subscriptionName"), m_subscriptionName); 0128 writer->writeEndElement(); 0129 0130 // MQTTTopics 0131 for (auto* topic : children<MQTTTopic>(AbstractAspect::ChildIndexFlag::IncludeHidden)) 0132 topic->save(writer); 0133 0134 writer->writeEndElement(); // "MQTTSubscription" 0135 } 0136 0137 /*! 0138 Loads from XML. 0139 */ 0140 bool MQTTSubscription::load(XmlStreamReader* reader, bool preview) { 0141 if (!readBasicAttributes(reader)) 0142 return false; 0143 0144 QXmlStreamAttributes attribs; 0145 0146 while (!reader->atEnd()) { 0147 reader->readNext(); 0148 if (reader->isEndElement() && reader->name() == QLatin1String("MQTTSubscription")) 0149 break; 0150 0151 if (!reader->isStartElement()) 0152 continue; 0153 0154 if (reader->name() == QLatin1String("comment")) { 0155 if (!readCommentElement(reader)) 0156 return false; 0157 } else if (reader->name() == QLatin1String("general")) { 0158 attribs = reader->attributes(); 0159 m_subscriptionName = attribs.value(QStringLiteral("subscriptionName")).toString(); 0160 } else if (reader->name() == QLatin1String("MQTTTopic")) { 0161 auto* topic = new MQTTTopic(QString(), this, false); 0162 if (!topic->load(reader, preview)) { 0163 delete topic; 0164 return false; 0165 } 0166 addChildFast(topic); 0167 } else { // unknown element 0168 reader->raiseWarning(i18n("unknown element '%1'", reader->name().toString())); 0169 if (!reader->skipToEndElement()) 0170 return false; 0171 } 0172 } 0173 0174 Q_EMIT loaded(this->subscriptionName()); 0175 return !reader->hasError(); 0176 }