diff --git a/src/backend/datasources/MQTTClient.h b/src/backend/datasources/MQTTClient.h --- a/src/backend/datasources/MQTTClient.h +++ b/src/backend/datasources/MQTTClient.h @@ -253,7 +253,7 @@ void MQTTSubscribed(); void MQTTTopicsChanged(); void readFromTopics(); - void clientAboutToBeDeleted(const QString&); + void clientAboutToBeDeleted(const QString&, quint16); #endif //HAVE_MQTT }; diff --git a/src/backend/datasources/MQTTClient.cpp b/src/backend/datasources/MQTTClient.cpp --- a/src/backend/datasources/MQTTClient.cpp +++ b/src/backend/datasources/MQTTClient.cpp @@ -80,10 +80,10 @@ } MQTTClient::~MQTTClient() { - emit clientAboutToBeDeleted(m_client->hostname()); + emit clientAboutToBeDeleted(m_client->hostname(), m_client->port()); //stop reading before deleting the objects pauseReading(); - qDebug()<<"Delete MQTTClient: " << m_client->hostname(); + qDebug() << "Delete MQTTClient: " << m_client->hostname() << m_client->port(); delete m_filter; delete m_updateTimer; diff --git a/src/kdefrontend/GuiObserver.cpp b/src/kdefrontend/GuiObserver.cpp --- a/src/kdefrontend/GuiObserver.cpp +++ b/src/kdefrontend/GuiObserver.cpp @@ -117,11 +117,15 @@ and activates the corresponding dockwidgets, toolbars etc. */ void GuiObserver::selectedAspectsChanged(QList& selectedAspects) const { - if (selectedAspects.isEmpty()) { + auto clearDock = [&](){ if (m_mainWindow->stackedWidget->currentWidget()) m_mainWindow->stackedWidget->currentWidget()->hide(); m_mainWindow->m_propertiesDock->setWindowTitle(i18nc("@title:window", "Properties")); + }; + + if (selectedAspects.isEmpty()) { + clearDock(); return; } @@ -132,10 +136,7 @@ for (auto* aspect : selectedAspects) { className = aspect->metaObject()->className(); if (className != prevClassName && !prevClassName.isEmpty()) { - if (m_mainWindow->stackedWidget->currentWidget()) - m_mainWindow->stackedWidget->currentWidget()->hide(); - - m_mainWindow->m_propertiesDock->setWindowTitle(i18nc("@title:window", "Properties")); + clearDock(); return; } prevClassName = className; @@ -567,10 +568,7 @@ m_mainWindow->stackedWidget->addWidget(m_mainWindow->m_liveDataDock); } - QList list; - for (auto* aspect : selectedAspects) - list << qobject_cast(aspect); - m_mainWindow->m_liveDataDock->setMQTTClients(list); + m_mainWindow->m_liveDataDock->setMQTTClient(static_cast(selectedAspects.first())); m_mainWindow->stackedWidget->setCurrentWidget(m_mainWindow->m_liveDataDock); } else if (className == QStringLiteral("MQTTSubscription")) { @@ -582,20 +580,7 @@ m_mainWindow->stackedWidget->addWidget(m_mainWindow->m_liveDataDock); } - QList list; - for (auto* aspect : selectedAspects) { - const QString clientName = qobject_cast(aspect)->mqttClient()->name(); - bool found = false; - for (const auto* client : list) { - if (client->name() == clientName) { - found = true; - break; - } - } - if (!found) - list << qobject_cast(aspect)->mqttClient(); - } - m_mainWindow->m_liveDataDock->setMQTTClients(list); + m_mainWindow->m_liveDataDock->setMQTTClient(static_cast(selectedAspects.first())->mqttClient()); m_mainWindow->stackedWidget->setCurrentWidget(m_mainWindow->m_liveDataDock); } else if (className == QStringLiteral("MQTTTopic")) { @@ -606,20 +591,7 @@ m_mainWindow->stackedWidget->addWidget(m_mainWindow->m_liveDataDock); } - QList list; - for (auto* aspect : selectedAspects) { - QString clientName = qobject_cast(qobject_cast(aspect)->mqttClient())->name(); - bool found = false; - for (const auto* client : list) { - if (client->name() == clientName) { - found = true; - break; - } - } - if (!found) - list << qobject_cast(qobject_cast(aspect)->mqttClient()); - } - m_mainWindow->m_liveDataDock->setMQTTClients(list); + m_mainWindow->m_liveDataDock->setMQTTClient(static_cast(selectedAspects.first())->mqttClient()); m_mainWindow->stackedWidget->setCurrentWidget(m_mainWindow->m_liveDataDock); } @@ -632,16 +604,11 @@ m_mainWindow->stackedWidget->addWidget(m_mainWindow->m_liveDataDock); } - QList list; - for (auto* aspect : selectedAspects) - list << qobject_cast(aspect); - m_mainWindow->m_liveDataDock->setLiveDataSources(list); + m_mainWindow->m_liveDataDock->setLiveDataSource(static_cast(selectedAspects.first())); m_mainWindow->stackedWidget->setCurrentWidget(m_mainWindow->m_liveDataDock); } else { - m_mainWindow->m_propertiesDock->setWindowTitle(i18nc("@title:window", "Properties")); - if (m_mainWindow->stackedWidget->currentWidget()) - m_mainWindow->stackedWidget->currentWidget()->hide(); + clearDock(); } } diff --git a/src/kdefrontend/MainWin.cpp b/src/kdefrontend/MainWin.cpp --- a/src/kdefrontend/MainWin.cpp +++ b/src/kdefrontend/MainWin.cpp @@ -1920,29 +1920,29 @@ dlg->importToMQTT(mqttClient); mqttClient->setName(mqttClient->clientHostName()); + QVector existingClients = m_project->children(AbstractAspect::Recursive); //doesn't make sense to have more MQTTClients connected to the same broker bool found = false; for (const auto* client : existingClients) { - if (client->clientHostName() == mqttClient->clientHostName()) { + if (client->clientHostName() == mqttClient->clientHostName() && client->clientPort() == mqttClient->clientPort()) { found = true; break; } } if (!found) - this->addAspectToProject(mqttClient); + addAspectToProject(mqttClient); else { delete mqttClient; - QMessageBox::warning(this, "Warning", "There already is a MQTTClient with this host name!"); + QMessageBox::warning(this, "Warning", "There already is a MQTTClient with this host!"); } #endif - } - else { + } else { LiveDataSource* dataSource = new LiveDataSource(i18n("Live data source%1", 1), false); dlg->importToLiveDataSource(dataSource, statusBar()); - this->addAspectToProject(dataSource); + addAspectToProject(dataSource); } } delete dlg; diff --git a/src/kdefrontend/datasources/ImportFileWidget.cpp b/src/kdefrontend/datasources/ImportFileWidget.cpp --- a/src/kdefrontend/datasources/ImportFileWidget.cpp +++ b/src/kdefrontend/datasources/ImportFileWidget.cpp @@ -248,6 +248,7 @@ ui.cbReadingType->setCurrentIndex(conf.readEntry("ReadingType").toInt()); ui.cbSerialPort->setCurrentIndex(conf.readEntry("SerialPort").toInt()); ui.cbUpdateType->setCurrentIndex(conf.readEntry("UpdateType").toInt()); + updateTypeChanged(ui.cbUpdateType->currentIndex()); ui.leHost->setText(conf.readEntry("Host","")); ui.sbKeepNValues->setValue(conf.readEntry("KeepNValues").toInt()); ui.lePort->setText(conf.readEntry("Port","")); @@ -1236,7 +1237,7 @@ //for file types other than ASCII and binary we support re-reading the whole file only //select "read whole file" and deactivate the combobox if (m_liveDataSource && (fileType != AbstractFileFilter::Ascii && fileType != AbstractFileFilter::Binary)) { - ui.cbReadingType->setCurrentIndex(3); + ui.cbReadingType->setCurrentIndex(LiveDataSource::ReadingType::WholeFile); ui.cbReadingType->setEnabled(false); } else ui.cbReadingType->setEnabled(true); @@ -1921,11 +1922,15 @@ //deactivate file types other than ascii and binary for (int i = 2; i < ui.cbFileType->count(); ++i) typeModel->item(i)->setFlags(item->flags() & ~(Qt::ItemIsSelectable | Qt::ItemIsEnabled)); + if (ui.cbFileType->currentIndex() > 1) + ui.cbFileType->setCurrentIndex(1); //"whole file" read option is available for file or pipe only, disable it typeModel = qobject_cast(ui.cbReadingType->model()); - QStandardItem* item = typeModel->item(LiveDataSource::ReadingType::WholeFile); + QStandardItem* item = typeModel->item(LiveDataSource::WholeFile); item->setFlags(item->flags() & ~(Qt::ItemIsSelectable | Qt::ItemIsEnabled)); + if (static_cast(ui.cbReadingType->currentIndex()) == LiveDataSource::WholeFile) + ui.cbReadingType->setCurrentIndex(LiveDataSource::TillEnd); //"update options" groupbox can be deactivated for "file and pipe" if the file is invalid. //Activate the groupbox when switching from "file and pipe" to a different source type. diff --git a/src/kdefrontend/dockwidgets/LiveDataDock.h b/src/kdefrontend/dockwidgets/LiveDataDock.h --- a/src/kdefrontend/dockwidgets/LiveDataDock.h +++ b/src/kdefrontend/dockwidgets/LiveDataDock.h @@ -51,19 +51,20 @@ public: explicit LiveDataDock(QWidget *parent = nullptr); - void setLiveDataSources(const QList& sources); + void setLiveDataSource(LiveDataSource* const source); ~LiveDataDock() override; private: Ui::LiveDataDock ui; - QList m_liveDataSources; + LiveDataSource* m_liveDataSource{nullptr}; bool m_paused{false}; void pauseReading(); void continueReading(); private slots: + void nameChanged(const QString&); void updateTypeChanged(int); void readingTypeChanged(int); void sampleSizeChanged(int); @@ -75,7 +76,7 @@ #ifdef HAVE_MQTT public: - void setMQTTClients(const QList& clients); + void setMQTTClient(MQTTClient* const client); bool testSubscribe(const QString&); bool testUnsubscribe(const QString&); @@ -100,7 +101,7 @@ void fillSubscriptions(); void scrollToTopicTreeItem(const QString&); void scrollToSubsriptionTreeItem(const QString&); - void removeClient(const QString&); + void removeClient(const QString&, quint16); void showWillSettings(); signals: @@ -111,17 +112,24 @@ void addTopicToTree(const QString&); void manageCommonLevelSubscriptions(); - QList m_mqttClients; - QMap m_clients; + struct MQTTHost { + int count; + QMqttClient* client; + QStringList topicList; + QVector addedTopics; + }; + + MQTTClient* m_mqttClient{nullptr}; + const MQTTClient* m_previousMQTTClient{nullptr}; + QMap, MQTTHost> m_hosts; + MQTTHost* m_currentHost{nullptr}; + MQTTHost* m_previousHost{nullptr}; QCompleter* m_topicCompleter{nullptr}; QCompleter* m_subscriptionCompleter{nullptr}; - QMap m_topicList; bool m_searching{true}; QTimer* m_searchTimer; bool m_interpretMessage{true}; - const MQTTClient* m_previousMQTTClient{nullptr}; QString m_mqttUnsubscribeName; - QMap> m_addedTopics; #endif }; diff --git a/src/kdefrontend/dockwidgets/LiveDataDock.cpp b/src/kdefrontend/dockwidgets/LiveDataDock.cpp --- a/src/kdefrontend/dockwidgets/LiveDataDock.cpp +++ b/src/kdefrontend/dockwidgets/LiveDataDock.cpp @@ -52,6 +52,7 @@ ui.bUpdateNow->setIcon(QIcon::fromTheme(QLatin1String("view-refresh"))); + connect(ui.leName, &QLineEdit::textChanged, this, &LiveDataDock::nameChanged); connect(ui.bPausePlayReading, &QPushButton::clicked, this, &LiveDataDock::pauseContinueReading); connect(ui.bUpdateNow, &QPushButton::clicked, this, &LiveDataDock::updateNow); connect(ui.sbUpdateInterval, static_cast(&QSpinBox::valueChanged), this, &LiveDataDock::updateIntervalChanged); @@ -109,57 +110,63 @@ #ifdef HAVE_MQTT LiveDataDock::~LiveDataDock() { delete m_searchTimer; - QMapIterator clients(m_clients); - while (clients.hasNext()) { - clients.next(); - delete clients.value(); - } + for (auto & host : m_hosts) + delete host.client; } #else LiveDataDock::~LiveDataDock() = default; #endif #ifdef HAVE_MQTT /*! - * \brief Sets the MQTTClients of this dock widget + * \brief Sets the MQTTClient of this dock widget * \param clients */ -void LiveDataDock::setMQTTClients(const QList& clients) { - m_liveDataSources.clear(); - m_mqttClients.clear(); - m_mqttClients = clients; - const MQTTClient* const fmc = clients.at(0); - - ui.sbUpdateInterval->setValue(fmc->updateInterval()); - ui.cbUpdateType->setCurrentIndex(static_cast(fmc->updateType())); - ui.cbReadingType->setCurrentIndex(static_cast(fmc->readingType())); - - if (fmc->updateType() == MQTTClient::UpdateType::NewData) { +void LiveDataDock::setMQTTClient(MQTTClient* const client) { + m_liveDataSource = nullptr; // prevent updates due to changes to input widgets + if (m_mqttClient == client) + return; + auto oldclient = m_mqttClient; + m_mqttClient = nullptr; // prevent updates due to changes to input widgets + + ui.leName->setText(client->name()); + const QPair id(client->clientHostName(), client->clientPort()); + ui.leSourceInfo->setText(QStringLiteral("%1:%2").arg(id.first).arg(id.second)); + + ui.sbUpdateInterval->setValue(client->updateInterval()); + ui.cbUpdateType->setCurrentIndex(static_cast(client->updateType())); + ui.cbReadingType->setCurrentIndex(static_cast(client->readingType())); + + if (client->updateType() == MQTTClient::NewData) { ui.lUpdateInterval->hide(); ui.sbUpdateInterval->hide(); } - if (fmc->isPaused()) { + if (client->isPaused()) { ui.bPausePlayReading->setText(i18n("Continue reading")); ui.bPausePlayReading->setIcon(QIcon::fromTheme(QLatin1String("media-record"))); } else { ui.bPausePlayReading->setText(i18n("Pause reading")); ui.bPausePlayReading->setIcon(QIcon::fromTheme(QLatin1String("media-playback-pause"))); } - ui.sbKeepNValues->setValue(fmc->keepNValues()); + ui.sbKeepNValues->setValue(client->keepNValues()); ui.sbKeepNValues->setEnabled(true); - if (fmc->readingType() == MQTTClient::ReadingType::TillEnd) { + if (client->readingType() == MQTTClient::TillEnd) { ui.lSampleSize->hide(); ui.sbSampleSize->hide(); } else - ui.sbSampleSize->setValue(fmc->sampleSize()); + ui.sbSampleSize->setValue(client->sampleSize()); // disable "whole file" option const QStandardItemModel* model = qobject_cast(ui.cbReadingType->model()); - QStandardItem* item = model->item(LiveDataSource::ReadingType::WholeFile); + QStandardItem* item = model->item(LiveDataSource::WholeFile); item->setFlags(item->flags() & ~(Qt::ItemIsSelectable | Qt::ItemIsEnabled)); + if (static_cast(ui.cbReadingType->currentIndex()) == LiveDataSource::WholeFile) + ui.cbReadingType->setCurrentIndex(LiveDataSource::TillEnd); + + m_mqttClient = client; // updates may be applied from now on //show MQTT connected options ui.lTopics->show(); @@ -174,124 +181,162 @@ ui.lLWT->show(); ui.bLWT->show(); + m_previousHost = m_currentHost; //if there isn't a client with this hostname we instantiate a new one - if (m_clients[fmc->clientHostName()] == nullptr) { - m_clients[fmc->clientHostName()] = new QMqttClient(); + auto it = m_hosts.find(id); + if (it == m_hosts.end()) { + m_currentHost = &m_hosts[id]; + m_currentHost->count = 1; + m_currentHost->client = new QMqttClient; - connect(fmc, &MQTTClient::clientAboutToBeDeleted, this, &LiveDataDock::removeClient); + connect(client, &MQTTClient::clientAboutToBeDeleted, this, &LiveDataDock::removeClient); - connect(m_clients[fmc->clientHostName()], &QMqttClient::connected, this, &LiveDataDock::onMQTTConnect); - connect(m_clients[fmc->clientHostName()], &QMqttClient::messageReceived, this, &LiveDataDock::mqttMessageReceived); + connect(m_currentHost->client, &QMqttClient::connected, this, &LiveDataDock::onMQTTConnect); + connect(m_currentHost->client, &QMqttClient::messageReceived, this, &LiveDataDock::mqttMessageReceived); - m_clients[fmc->clientHostName()]->setHostname(fmc->clientHostName()); - m_clients[fmc->clientHostName()]->setPort(fmc->clientPort()); + m_currentHost->client->setHostname(id.first); + m_currentHost->client->setPort(id.second); - if (fmc->MQTTUseAuthentication()) { - m_clients[fmc->clientHostName()]->setUsername(fmc->clientUserName()); - m_clients[fmc->clientHostName()]->setPassword(fmc->clientPassword()); + if (client->MQTTUseAuthentication()) { + m_currentHost->client->setUsername(client->clientUserName()); + m_currentHost->client->setPassword(client->clientPassword()); } - if (fmc->MQTTUseID()) { - m_clients[fmc->clientHostName()]->setClientId(fmc->clientID()); - } + if (client->MQTTUseID()) + m_currentHost->client->setClientId(client->clientID()); - m_clients[fmc->clientHostName()]->connectToHost(); + m_currentHost->client->connectToHost(); + } else { + m_currentHost = &it.value(); + ++m_currentHost->count; } if (m_previousMQTTClient == nullptr) { - connect(fmc, &MQTTClient::MQTTSubscribed, this, &LiveDataDock::fillSubscriptions); + connect(client, &MQTTClient::MQTTSubscribed, this, &LiveDataDock::fillSubscriptions); //Fill the subscription tree(useful if the MQTTClient was loaded) - QVector topics = fmc->topicNames(); + QVector topics = client->topicNames(); for (const auto& topic : topics) { addTopicToTree(topic); } fillSubscriptions(); } //if the previous MQTTClient's host name was different from the current one we have to disconnect some slots //and clear the tree widgets - else if (m_previousMQTTClient->clientHostName() != fmc->clientHostName()) { + else if (m_previousMQTTClient->clientHostName() != client->clientHostName()) { disconnect(m_previousMQTTClient, &MQTTClient::MQTTSubscribed, this, &LiveDataDock::fillSubscriptions); - disconnect(m_clients[m_previousMQTTClient->clientHostName()], &QMqttClient::messageReceived, this, &LiveDataDock::mqttMessageReceived); - connect(m_clients[m_previousMQTTClient->clientHostName()], &QMqttClient::messageReceived, this, &LiveDataDock::mqttMessageReceivedInBackground); + disconnect(m_previousHost->client, &QMqttClient::messageReceived, this, &LiveDataDock::mqttMessageReceived); + connect(m_previousHost->client, &QMqttClient::messageReceived, this, &LiveDataDock::mqttMessageReceivedInBackground); - disconnect(m_clients[fmc->clientHostName()], &QMqttClient::messageReceived, this, &LiveDataDock::mqttMessageReceivedInBackground); + disconnect(m_currentHost->client, &QMqttClient::messageReceived, this, &LiveDataDock::mqttMessageReceivedInBackground); ui.twTopics->clear(); //repopulating the tree widget with the already known topics of the client - for (int i = 0; i < m_addedTopics[fmc->clientHostName()].size(); ++i) { - addTopicToTree(m_addedTopics[fmc->clientHostName()].at(i)); + for (int i = 0; i < m_currentHost->addedTopics.size(); ++i) { + addTopicToTree(m_currentHost->addedTopics.at(i)); } //fill subscriptions tree widget ui.twSubscriptions->clear(); fillSubscriptions(); - connect(fmc, &MQTTClient::MQTTSubscribed, this, &LiveDataDock::fillSubscriptions); - connect(m_clients[fmc->clientHostName()], &QMqttClient::messageReceived, this, &LiveDataDock::mqttMessageReceived); + connect(client, &MQTTClient::MQTTSubscribed, this, &LiveDataDock::fillSubscriptions); + connect(m_currentHost->client, &QMqttClient::messageReceived, this, &LiveDataDock::mqttMessageReceived); } - if (fmc->willUpdateType() == MQTTClient::WillUpdateType::OnClick && fmc->MQTTWillUse()) + if (client->willUpdateType() == MQTTClient::OnClick && client->MQTTWillUse()) ui.bWillUpdateNow->show(); - m_previousMQTTClient = fmc; + m_previousMQTTClient = oldclient; } #endif /*! - * \brief Sets the live data sources of this dock widget + * \brief Sets the live data source of this dock widget * \param sources */ -void LiveDataDock::setLiveDataSources(const QList& sources) { +void LiveDataDock::setLiveDataSource(LiveDataSource* const source) { #ifdef HAVE_MQTT - m_mqttClients.clear(); + m_mqttClient = nullptr; #endif - m_liveDataSources = sources; - const LiveDataSource* const fds = sources.at(0); - const LiveDataSource::SourceType sourceType = fds->sourceType(); - const LiveDataSource::ReadingType readingType = fds->readingType(); - const LiveDataSource::UpdateType updateType = fds->updateType(); - ui.sbUpdateInterval->setValue(fds->updateInterval()); + if (m_liveDataSource == source) + return; + m_liveDataSource = nullptr; // prevent updates due to changes to input widgets + + ui.leName->setText(source->name()); + const LiveDataSource::SourceType sourceType = source->sourceType(); + const LiveDataSource::ReadingType readingType = source->readingType(); + const LiveDataSource::UpdateType updateType = source->updateType(); + const AbstractFileFilter::FileType fileType = source->fileType(); + ui.sbUpdateInterval->setValue(source->updateInterval()); ui.cbUpdateType->setCurrentIndex(static_cast(updateType)); ui.cbReadingType->setCurrentIndex(static_cast(readingType)); + switch (sourceType) { + case LiveDataSource::FileOrPipe: + ui.leSourceInfo->setText(source->fileName()); + break; + case LiveDataSource::NetworkTcpSocket: + case LiveDataSource::NetworkUdpSocket: + ui.leSourceInfo->setText(QStringLiteral("%1:%2").arg(source->host()).arg(source->port())); + break; + case LiveDataSource::LocalSocket: + ui.leSourceInfo->setText(source->localSocketName()); + break; + case LiveDataSource::SerialPort: + ui.leSourceInfo->setText(source->serialPortName()); + break; + case LiveDataSource::MQTT: + break; + } + if (updateType == LiveDataSource::UpdateType::NewData) { ui.lUpdateInterval->hide(); ui.sbUpdateInterval->hide(); } - if (fds->isPaused()) { + if (source->isPaused()) { ui.bPausePlayReading->setText(i18n("Continue Reading")); ui.bPausePlayReading->setIcon(QIcon::fromTheme(QLatin1String("media-record"))); } else { ui.bPausePlayReading->setText(i18n("Pause Reading")); ui.bPausePlayReading->setIcon(QIcon::fromTheme(QLatin1String("media-playback-pause"))); } - ui.sbKeepNValues->setValue(fds->keepNValues()); + ui.sbKeepNValues->setValue(source->keepNValues()); // disable "whole file" when having no file (i.e. socket or port) auto* model = qobject_cast(ui.cbReadingType->model()); - QStandardItem* item = model->item(LiveDataSource::ReadingType::WholeFile); - if (sourceType == LiveDataSource::SourceType::FileOrPipe) + QStandardItem* item = model->item(LiveDataSource::WholeFile); + if (sourceType == LiveDataSource::SourceType::FileOrPipe) { item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); - else + //for file types other than ASCII and binary we support re-reading the whole file only + //select "read whole file" and deactivate the combobox + if (fileType != AbstractFileFilter::Ascii && fileType != AbstractFileFilter::Binary) { + ui.cbReadingType->setCurrentIndex(LiveDataSource::WholeFile); + ui.cbReadingType->setEnabled(false); + } else + ui.cbReadingType->setEnabled(true); + } else { + if (static_cast(ui.cbReadingType->currentIndex()) == LiveDataSource::WholeFile) + ui.cbReadingType->setCurrentIndex(LiveDataSource::TillEnd); item->setFlags(item->flags() & ~(Qt::ItemIsSelectable | Qt::ItemIsEnabled)); + } - if (sourceType == LiveDataSource::SourceType::NetworkTcpSocket || sourceType == LiveDataSource::SourceType::LocalSocket || sourceType == LiveDataSource::SourceType::SerialPort - || readingType == LiveDataSource::ReadingType::TillEnd || readingType == LiveDataSource::ReadingType::WholeFile) { + if (((sourceType == LiveDataSource::FileOrPipe || sourceType == LiveDataSource::NetworkUdpSocket) && + (readingType == LiveDataSource::ContinuousFixed || readingType == LiveDataSource::FromEnd))) + ui.sbSampleSize->setValue(source->sampleSize()); + else { ui.lSampleSize->hide(); ui.sbSampleSize->hide(); - } else { - ui.sbSampleSize->setValue(fds->sampleSize()); } // disable "on new data"-option if not available model = qobject_cast(ui.cbUpdateType->model()); - item = model->item(LiveDataSource::UpdateType::NewData); - if (sourceType == LiveDataSource::SourceType::NetworkTcpSocket || sourceType == LiveDataSource::SourceType::NetworkUdpSocket || - sourceType == LiveDataSource::SourceType::SerialPort) + item = model->item(LiveDataSource::NewData); + if (sourceType == LiveDataSource::NetworkTcpSocket || sourceType == LiveDataSource::NetworkUdpSocket || + sourceType == LiveDataSource::SerialPort) item->setFlags(item->flags() & ~(Qt::ItemIsSelectable | Qt::ItemIsEnabled)); else item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); @@ -307,95 +352,95 @@ ui.lTopicSearch->hide(); ui.twSubscriptions->hide(); ui.gbManageSubscriptions->hide(); + + m_liveDataSource = source; // updates may be applied from now on } /*! - * \brief Modifies the sample size of the live data sources or MQTTClient objects + * \brief Modifies the sample size of the live data source or MQTTClient object * \param sampleSize */ void LiveDataDock::sampleSizeChanged(int sampleSize) { - if (!m_liveDataSources.isEmpty()) { - for (auto* source : m_liveDataSources) - source->setSampleSize(sampleSize); - } + if (m_liveDataSource) + m_liveDataSource->setSampleSize(sampleSize); #ifdef HAVE_MQTT - else if (!m_mqttClients.isEmpty()) { - for (auto* client : m_mqttClients) - client->setSampleSize(sampleSize); - } + else if (m_mqttClient) + m_mqttClient->setSampleSize(sampleSize); #endif } /*! - * \brief Updates the live data sources now + * \brief Updates the live data source now */ void LiveDataDock::updateNow() { - if (!m_liveDataSources.isEmpty()) { - for (auto* source : m_liveDataSources) - source->updateNow(); - } + if (m_liveDataSource) + m_liveDataSource->updateNow(); #ifdef HAVE_MQTT - else if (!m_mqttClients.isEmpty()) { - for (auto* client : m_mqttClients) - client->updateNow(); - } + else if (m_mqttClient) + m_mqttClient->updateNow(); +#endif +} + +void LiveDataDock::nameChanged(const QString& name) { + if (m_liveDataSource) + m_liveDataSource->setName(name); +#ifdef HAVE_MQTT + else if (m_mqttClient) + m_mqttClient->setName(name); #endif } /*! * \brief LiveDataDock::updateTypeChanged * \param idx */ void LiveDataDock::updateTypeChanged(int idx) { - if (!m_liveDataSources.isEmpty()) { + if (m_liveDataSource) { DEBUG("LiveDataDock::updateTypeChanged()"); - const auto type = static_cast(idx); + const LiveDataSource::UpdateType updateType = static_cast(idx); - switch (type) { - case LiveDataSource::UpdateType::TimeInterval: + switch (updateType) { + case LiveDataSource::TimeInterval: { ui.lUpdateInterval->show(); ui.sbUpdateInterval->show(); - ui.lSampleSize->show(); - ui.sbSampleSize->show(); - - for (auto* source : m_liveDataSources) { - source->setUpdateType(type); - source->setUpdateInterval(ui.sbUpdateInterval->value()); - source->setFileWatched(false); - } + const LiveDataSource::SourceType s = m_liveDataSource->sourceType(); + const LiveDataSource::ReadingType r = m_liveDataSource->readingType(); + const bool showSampleSize = ((s == LiveDataSource::FileOrPipe || s == LiveDataSource::NetworkUdpSocket) && + (r == LiveDataSource::ContinuousFixed || r == LiveDataSource::FromEnd)); + ui.lSampleSize->setVisible(showSampleSize); + ui.sbSampleSize->setVisible(showSampleSize); + + m_liveDataSource->setUpdateType(updateType); + m_liveDataSource->setUpdateInterval(ui.sbUpdateInterval->value()); + m_liveDataSource->setFileWatched(false); break; - case LiveDataSource::UpdateType::NewData: + } + case LiveDataSource::NewData: ui.lUpdateInterval->hide(); ui.sbUpdateInterval->hide(); ui.lSampleSize->hide(); ui.sbSampleSize->hide(); - for (auto* source : m_liveDataSources) { - source->setFileWatched(true); - source->setUpdateType(type); - } + m_liveDataSource->setFileWatched(true); + m_liveDataSource->setUpdateType(updateType); } } #ifdef HAVE_MQTT - else if (!m_mqttClients.isEmpty()) { + else if (m_mqttClient) { DEBUG("LiveDataDock::updateTypeChanged()"); const MQTTClient::UpdateType type = static_cast(idx); - if (type == MQTTClient::UpdateType::TimeInterval) { + if (type == MQTTClient::TimeInterval) { ui.lUpdateInterval->show(); ui.sbUpdateInterval->show(); - for (auto* client : m_mqttClients) { - client->setUpdateType(type); - client->setUpdateInterval(ui.sbUpdateInterval->value()); - } - } else if (type == MQTTClient::UpdateType::NewData) { + m_mqttClient->setUpdateType(type); + m_mqttClient->setUpdateInterval(ui.sbUpdateInterval->value()); + } else if (type == MQTTClient::NewData) { ui.lUpdateInterval->hide(); ui.sbUpdateInterval->hide(); - for (auto* client : m_mqttClients) { - client->setUpdateType(type); - } + m_mqttClient->setUpdateType(type); } } #endif @@ -406,106 +451,87 @@ * \param idx */ void LiveDataDock::readingTypeChanged(int idx) { - if (!m_liveDataSources.isEmpty()) { + if (m_liveDataSource) { const auto type = static_cast(idx); - const LiveDataSource* const fds = m_liveDataSources.at(0); - const LiveDataSource::SourceType sourceType = fds->sourceType(); - const LiveDataSource::UpdateType updateType = fds->updateType(); + const LiveDataSource::SourceType sourceType = m_liveDataSource->sourceType(); + const LiveDataSource::UpdateType updateType = m_liveDataSource->updateType(); - if (sourceType == LiveDataSource::SourceType::NetworkTcpSocket || sourceType == LiveDataSource::SourceType::LocalSocket || sourceType == LiveDataSource::SourceType::SerialPort - || type == LiveDataSource::ReadingType::TillEnd || type == LiveDataSource::ReadingType::WholeFile - || updateType == LiveDataSource::UpdateType::NewData) { + if (sourceType == LiveDataSource::NetworkTcpSocket || sourceType == LiveDataSource::LocalSocket || sourceType == LiveDataSource::SerialPort + || type == LiveDataSource::TillEnd || type == LiveDataSource::WholeFile + || updateType == LiveDataSource::NewData) { ui.lSampleSize->hide(); ui.sbSampleSize->hide(); } else { ui.lSampleSize->show(); ui.sbSampleSize->show(); } - for (auto* source : m_liveDataSources) - source->setReadingType(type); + m_liveDataSource->setReadingType(type); } #ifdef HAVE_MQTT - else if (!m_mqttClients.isEmpty()) { + else if (m_mqttClient) { MQTTClient::ReadingType type = static_cast(idx); - if (type == MQTTClient::ReadingType::TillEnd) { + if (type == MQTTClient::TillEnd) { ui.lSampleSize->hide(); ui.sbSampleSize->hide(); } else { ui.lSampleSize->show(); ui.sbSampleSize->show(); } - for (auto* client : m_mqttClients) - client->setReadingType(type); + m_mqttClient->setReadingType(type); } #endif } /*! - * \brief Modifies the update interval of the live data sources + * \brief Modifies the update interval of the live data source * \param updateInterval */ void LiveDataDock::updateIntervalChanged(int updateInterval) { - if (!m_liveDataSources.isEmpty()) { - for (auto* source : m_liveDataSources) - source->setUpdateInterval(updateInterval); - } + if (m_liveDataSource) + m_liveDataSource->setUpdateInterval(updateInterval); #ifdef HAVE_MQTT - else if (!m_mqttClients.isEmpty()) { - for (auto* client : m_mqttClients) - client->setUpdateInterval(updateInterval); - } + else if (m_mqttClient) + m_mqttClient->setUpdateInterval(updateInterval); #endif } /*! - * \brief Modifies the number of samples to keep in each of the live data sources + * \brief Modifies the number of samples to keep in each of the live data source * \param keepNValues */ void LiveDataDock::keepNValuesChanged(const int keepNValues) { - if (!m_liveDataSources.isEmpty()) { - for (auto* source : m_liveDataSources) - source->setKeepNValues(keepNValues); - } + if (m_liveDataSource) + m_liveDataSource->setKeepNValues(keepNValues); #ifdef HAVE_MQTT - else if (!m_mqttClients.isEmpty()) { - for (auto* client : m_mqttClients) - client->setKeepNValues(keepNValues); - } + else if (m_mqttClient) + m_mqttClient->setKeepNValues(keepNValues); #endif } /*! * \brief Pauses the reading of the live data source */ void LiveDataDock::pauseReading() { - if (!m_liveDataSources.isEmpty()) { - for (auto* source: m_liveDataSources) - source->pauseReading(); - } + if (m_liveDataSource) + m_liveDataSource->pauseReading(); #ifdef HAVE_MQTT - else if (!m_mqttClients.isEmpty()) { - for (auto* client : m_mqttClients) - client->pauseReading(); - } + else if (m_mqttClient) + m_mqttClient->pauseReading(); #endif } /*! * \brief Continues the reading of the live data source */ void LiveDataDock::continueReading() { - if (!m_liveDataSources.isEmpty()) { - for (auto* source : m_liveDataSources) - source->continueReading(); - } + if (m_liveDataSource) + m_liveDataSource->continueReading(); #ifdef HAVE_MQTT - else if (!m_mqttClients.isEmpty()) { - for (auto* client : m_mqttClients) - client->continueReading(); - } + else if (m_mqttClient) + m_mqttClient->continueReading(); #endif } @@ -530,165 +556,140 @@ /*! *\brief called when use will message checkbox's state is changed in the will settings widget, - * Sets the mqttUseWill according to state for every client in m_mqttClients + * Sets the mqttUseWill according to state for the m_mqttClient * * \param state the state of the checbox */ void LiveDataDock::useWillMessage(bool use) { qDebug()<<"Use will message: " << use; if (use) { - for (auto* source : m_mqttClients) - source->setMQTTWillUse(true); - - if (m_mqttClients.first()->willUpdateType() == MQTTClient::WillUpdateType::OnClick) + m_mqttClient->setMQTTWillUse(true); + if (m_mqttClient->willUpdateType() == MQTTClient::OnClick) ui.bWillUpdateNow->show(); } else { - for (auto* source : m_mqttClients) - source->setMQTTWillUse(false); - + m_mqttClient->setMQTTWillUse(false); ui.bWillUpdateNow->hide(); } } /*! *\brief called when will message's QoS is changed in the will settings widget - * sets the will QoS level for every client in m_mqttClients + * sets the will QoS level for the m_mqttClient * * \param QoS the QoS level of the will message */ void LiveDataDock::willQoSChanged(int QoS) { - for (auto* source : m_mqttClients) - source->setWillQoS(QoS); + m_mqttClient->setWillQoS(QoS); } /*! *\brief called when will message's retain flag is changed in the will settings widget - * sets the retain flag for the will message in every client in m_mqttClients + * sets the retain flag for the will message in in m_mqttClient * * \param state the state of the will retain chechbox */ void LiveDataDock::willRetainChanged(bool useWillRetainMessages) { if (useWillRetainMessages) { - for (auto* source : m_mqttClients) - source->setWillRetain(true); + m_mqttClient->setWillRetain(true); } else { - for (auto* source : m_mqttClients) - source->setWillRetain(false); + m_mqttClient->setWillRetain(false); } } /*! *\brief called when will topic combobox's current item is changed in the will settings widget - * sets the will topic for every client in m_mqttClients + * sets the will topic for the m_mqttClient * * \param topic the current text of cbWillTopic */ void LiveDataDock::willTopicChanged(const QString& topic) { - for (auto* source : m_mqttClients) { - if (source->willTopic() != topic) - source->clearLastMessage(); + if (m_mqttClient->willTopic() != topic) + m_mqttClient->clearLastMessage(); - source->setWillTopic(topic); - } + m_mqttClient->setWillTopic(topic); } /*! *\brief called when the selected will message type is changed in the will settings widget - * sets the will message type for every client in m_mqttClients + * sets the will message type for the m_mqttClient * * \param type the selected will message type */ void LiveDataDock::willMessageTypeChanged(MQTTClient::WillMessageType willMessageType) { - for (auto* source : m_mqttClients) - source->setWillMessageType(willMessageType); + m_mqttClient->setWillMessageType(willMessageType); } /*! *\brief called when the will own message is changed in the will settings widget - * sets the will own message for every client in m_mqttClients + * sets the will own message for the m_mqttClient * * \param message the will message given by the user */ void LiveDataDock::willOwnMessageChanged(const QString& message) { - for (auto* source : m_mqttClients) - source->setWillOwnMessage(message); + m_mqttClient->setWillOwnMessage(message); } /*! *\brief called when the selected update type for the will message is changed in the will settings widget - * sets the will update type for every client in m_mqttClients + * sets the will update type for the m_mqttClient * * \param type the selected will update type */ void LiveDataDock::willUpdateTypeChanged(int updateType) { - for (auto* source : m_mqttClients) - source->setWillUpdateType(static_cast(updateType)); + m_mqttClient->setWillUpdateType(static_cast(updateType)); - if (static_cast(updateType) == MQTTClient::WillUpdateType::TimePeriod) { + if (static_cast(updateType) == MQTTClient::TimePeriod) { ui.bWillUpdateNow->hide(); - for (auto* source : m_mqttClients) - source->startWillTimer(); - } else if (static_cast(updateType) == MQTTClient::WillUpdateType::OnClick) { + m_mqttClient->startWillTimer(); + } else if (static_cast(updateType) == MQTTClient::OnClick) { ui.bWillUpdateNow->show(); //if update type is on click we stop the will timer - for (auto* source : m_mqttClients) - source->stopWillTimer(); + m_mqttClient->stopWillTimer(); } } /*! *\brief called when the will update now button is pressed - * updates the will message of every client in m_mqttClients + * updates the will message of m_mqttClient */ void LiveDataDock::willUpdateNow() { - for (auto* source : m_mqttClients) - source->updateWillMessage(); + m_mqttClient->updateWillMessage(); } /*! *\brief called when the update interval for will message is changed in the will settings widget - * sets the will update interval for every client in m_mqttClients, then starts the will timer for each one + * sets the will update interval for the m_mqttClient, then starts the will timer for each one * * \param interval the new will update interval */ void LiveDataDock::willUpdateIntervalChanged(int interval) { - for (auto* source : m_mqttClients) { - source->setWillTimeInterval(interval); - source->startWillTimer(); - } + m_mqttClient->setWillTimeInterval(interval); + m_mqttClient->startWillTimer(); } /*! *\brief called when the will statistics are changed in the will settings widget - * adds or removes the statistic represented by the index from every client in m_mqttClients + * adds or removes the statistic represented by the index from m_mqttClient */ void LiveDataDock::statisticsChanged(MQTTClient::WillStatisticsType willStatisticsType) { - const bool useStatistic = m_mqttClients.first()->willStatistics()[static_cast(willStatisticsType)]; - if (willStatisticsType >= 0) { //if it's not already added and it's checked we add it - if (!useStatistic) - { - for (auto* source : m_mqttClients) - source->addWillStatistics(willStatisticsType); - } else { - //otherwise remove it - for (auto* source : m_mqttClients) - source->removeWillStatistics(willStatisticsType); - } + if (!m_mqttClient->willStatistics()[static_cast(willStatisticsType)]) + m_mqttClient->addWillStatistics(willStatisticsType); + else //otherwise remove it + m_mqttClient->removeWillStatistics(willStatisticsType); } } /*! *\brief called when the client connects to the broker successfully, it subscribes to every topic (# wildcard) * in order to later list every available topic */ void LiveDataDock::onMQTTConnect() { - auto* client = m_clients[m_mqttClients.first()->clientHostName()]; - if (!client || !client->subscribe(QMqttTopicFilter(QLatin1String("#")), 1)) + if (!m_currentHost || !m_currentHost->client || !m_currentHost->client->subscribe(QMqttTopicFilter(QLatin1String("#")), 1)) QMessageBox::critical(this, i18n("Couldn't subscribe"), i18n("Couldn't subscribe to all available topics. Something went wrong")); } @@ -698,8 +699,8 @@ */ void LiveDataDock::mqttMessageReceived(const QByteArray& message, const QMqttTopicName& topic) { Q_UNUSED(message) - if (!m_addedTopics[m_mqttClients.first()->clientHostName()].contains(topic.name())) { - m_addedTopics[m_mqttClients.first()->clientHostName()].push_back(topic.name()); + if (!m_currentHost->addedTopics.contains(topic.name())) { + m_currentHost->addedTopics.push_back(topic.name()); addTopicToTree(topic.name()); } } @@ -760,10 +761,7 @@ MQTTHelpers::addSubscriptionChildren(item, newTopLevelItem); } - //subscribe in every MQTTClient - for (auto* source : m_mqttClients) { - source->addMQTTSubscription(name, ui.cbQoS->currentIndex()); - } + m_mqttClient->addMQTTSubscription(name, ui.cbQoS->currentIndex()); if (name.endsWith('#')) { //if an already existing subscription contains a topic that the new subscription also contains @@ -787,29 +785,22 @@ for (int i = 0; i < unsubscribeItem->parent()->childCount(); ++i) { if (unsubscribeItem->text(0) != unsubscribeItem->parent()->child(i)->text(0)) { - //add topic as subscription to every client - for (auto* source : m_mqttClients) { - source->addBeforeRemoveSubscription(unsubscribeItem->parent()->child(i)->text(0), ui.cbQoS->currentIndex()); - } + //add topic as subscription + m_mqttClient->addBeforeRemoveSubscription(unsubscribeItem->parent()->child(i)->text(0), ui.cbQoS->currentIndex()); //also add it to twSubscriptions ui.twSubscriptions->addTopLevelItem(unsubscribeItem->parent()->takeChild(i)); --i; } else { //before we remove the topic, we reparent it to the new subscription //so no data is lost - for (auto* source : m_mqttClients) { - source->reparentTopic(unsubscribeItem->text(0), name); - } + m_mqttClient->reparentTopic(unsubscribeItem->text(0), name); } } unsubscribeItem = unsubscribeItem->parent(); } qDebug()<<"Remove: "<text(0); - //Remove topic/subscription - for (auto* source : m_mqttClients) { - source->removeMQTTSubscription(unsubscribeItem->text(0)); - } + m_mqttClient->removeMQTTSubscription(unsubscribeItem->text(0)); ui.twSubscriptions->takeTopLevelItem(ui.twSubscriptions->indexOfTopLevelItem(unsubscribeItem)); } @@ -836,7 +827,7 @@ /*! *\brief called when the unsubscribe button is pressed - * unsubscribes from the topic represented by the current item of twSubscription in every client from m_mqttClients + * unsubscribes from the topic represented by the current item of twSubscription in m_mqttClient */ void LiveDataDock::removeSubscription() { QTreeWidgetItem* unsubscribeItem = ui.twSubscriptions->currentItem(); @@ -847,32 +838,26 @@ //if it is a top level item, meaning a topic that we really subscribed to(not one that belongs to a subscription) //we can simply unsubscribe from it if (unsubscribeItem->parent() == nullptr) { - for (auto* source : m_mqttClients) { - source->removeMQTTSubscription(unsubscribeItem->text(0)); - } + m_mqttClient->removeMQTTSubscription(unsubscribeItem->text(0)); ui.twSubscriptions->takeTopLevelItem(ui.twSubscriptions->indexOfTopLevelItem(unsubscribeItem)); } //otherwise we remove the selected item, but subscribe to every other topic, that was contained by //the selected item's parent subscription(top level item of twSubscriptions) else { while (unsubscribeItem->parent() != nullptr) { for (int i = 0; i < unsubscribeItem->parent()->childCount(); ++i) { if (unsubscribeItem->text(0) != unsubscribeItem->parent()->child(i)->text(0)) { - //add topic as subscription to every client - for (auto* source : m_mqttClients) { - source->addBeforeRemoveSubscription(unsubscribeItem->parent()->child(i)->text(0), ui.cbQoS->currentIndex()); - } + //add topic as subscription + m_mqttClient->addBeforeRemoveSubscription(unsubscribeItem->parent()->child(i)->text(0), ui.cbQoS->currentIndex()); ui.twSubscriptions->addTopLevelItem(unsubscribeItem->parent()->takeChild(i)); --i; } } unsubscribeItem = unsubscribeItem->parent(); } - //remove topic/subscription from every client - for (auto* source : m_mqttClients) { - source->removeMQTTSubscription(unsubscribeItem->text(0)); - } + //remove topic/subscription + m_mqttClient->removeMQTTSubscription(unsubscribeItem->text(0)); ui.twSubscriptions->takeTopLevelItem(ui.twSubscriptions->indexOfTopLevelItem(unsubscribeItem)); //check if any common topics were subscribed, if possible merge them @@ -901,9 +886,9 @@ } else topic = topicName; - if (!m_topicList[m_mqttClients.first()->clientHostName()].contains(topic)) { - m_topicList[m_mqttClients.first()->clientHostName()].append(topic); - m_topicCompleter = new QCompleter(m_topicList[m_mqttClients.first()->clientHostName()], this); + if (!m_currentHost->topicList.contains(topic)) { + m_currentHost->topicList.append(topic); + m_topicCompleter = new QCompleter(m_currentHost->topicList, this); m_topicCompleter->setCompletionMode(QCompleter::PopupCompletion); m_topicCompleter->setCaseSensitivity(Qt::CaseSensitive); ui.leTopics->setCompleter(m_topicCompleter); @@ -916,7 +901,7 @@ */ void LiveDataDock::updateSubscriptionCompleter() { QStringList subscriptionList; - const QVector& subscriptions = m_mqttClients.first()->MQTTSubscriptions(); + const QVector& subscriptions = m_mqttClient->MQTTSubscriptions(); if (!subscriptions.isEmpty()) { for (const auto& subscription : subscriptions) @@ -941,16 +926,14 @@ } /*! - *\brief called when a new the host name of the MQTTClients from m _mqttClients changes + *\brief called when a new the host name of m_mqttClient changes * or when the MQTTClients initialize their subscriptions * Fills twSubscriptions with the subscriptions of the MQTTClient */ void LiveDataDock::fillSubscriptions() { - const MQTTClient* const fmc = m_mqttClients.at(0); - ui.twSubscriptions->clear(); - QVector subscriptions = fmc->MQTTSubscriptions(); + QVector subscriptions = m_mqttClient->MQTTSubscriptions(); for (int i = 0; i < subscriptions.count(); ++i) { QStringList name; name.append(subscriptions[i]); @@ -1134,10 +1117,8 @@ } } - //make the subscription on commonTopic in every MQTTClient from m_mqttClients - for (auto* source : m_mqttClients) { - source->addMQTTSubscription(commonTopic, ui.cbQoS->currentIndex()); - } + //make the subscription on commonTopic in m_mqttClient + m_mqttClient->addMQTTSubscription(commonTopic, ui.cbQoS->currentIndex()); } } } while (foundEqual); @@ -1231,40 +1212,49 @@ } /*! - *\brief called when a client receives a message, if the clients hostname isn't identic with the host name of MQTTClients - * if the message arrived from a new topic, the topic is put in m_addedTopics + *\brief called when a client receives a message, if the clients hostname isn't identic with the host name of MQTTClient + * if the message arrived from a new topic, the topic is added to the host data */ void LiveDataDock::mqttMessageReceivedInBackground(const QByteArray& message, const QMqttTopicName& topic) { Q_UNUSED(message) - if (!m_addedTopics[m_mqttClients.first()->clientHostName()].contains(topic.name())) - m_addedTopics[m_mqttClients.first()->clientHostName()].push_back(topic.name()); + if (!m_currentHost->addedTopics.contains(topic.name())) + m_currentHost->addedTopics.push_back(topic.name()); } /*! *\brief called when an MQTTClient is about to be deleted - * removes every data connected to the MQTTClient, and disconnects the corresponding client from m_clients + * removes every data connected to the MQTTClient, and disconnects the corresponding client from the host * + * \param hostname the host name of the MQTTClient that will be deleted * \param name the host name of the MQTTClient that will be deleted */ -void LiveDataDock::removeClient(const QString& name) { - m_clients[name]->disconnectFromHost(); +void LiveDataDock::removeClient(const QString& hostname, quint16 port) { + auto it = m_hosts.find(qMakePair(hostname, port)); + if (it == m_hosts.end()) + return; + + MQTTHost & host = it.value(); + + if (host.count > 1) { + --host.count; + return; + } - m_addedTopics.remove(name); - m_topicList.remove(name); + host.client->disconnectFromHost(); - if (m_previousMQTTClient != nullptr && m_previousMQTTClient->clientHostName() == name) { - disconnect(m_clients[m_previousMQTTClient->clientHostName()], &QMqttClient::messageReceived, this, &LiveDataDock::mqttMessageReceivedInBackground); + if (m_previousMQTTClient != nullptr && m_previousMQTTClient->clientHostName() == hostname) { + disconnect(m_previousHost->client, &QMqttClient::messageReceived, this, &LiveDataDock::mqttMessageReceivedInBackground); m_previousMQTTClient = nullptr; } - if (m_mqttClients.first()->clientHostName() == name) { + if (m_mqttClient->clientHostName() == hostname) { ui.twSubscriptions->clear(); ui.twTopics->clear(); - m_mqttClients.clear(); + m_mqttClient = nullptr; } - delete m_clients[name]; - m_clients.remove(name); + delete host.client; + m_hosts.erase(it); } /*! @@ -1341,9 +1331,8 @@ void LiveDataDock::showWillSettings() { QMenu menu; - const MQTTClient* const fmc = m_mqttClients.at(0); - const QVector& topics = fmc->topicNames(); - MQTTWillSettingsWidget willSettingsWidget(&menu, fmc->willSettings(), topics); + const QVector& topics = m_mqttClient->topicNames(); + MQTTWillSettingsWidget willSettingsWidget(&menu, m_mqttClient->willSettings(), topics); connect(&willSettingsWidget, &MQTTWillSettingsWidget::applyClicked, [this, &menu, &willSettingsWidget]() { this->useWillMessage(willSettingsWidget.will().enabled); diff --git a/src/kdefrontend/ui/dockwidgets/livedatadock.ui b/src/kdefrontend/ui/dockwidgets/livedatadock.ui --- a/src/kdefrontend/ui/dockwidgets/livedatadock.ui +++ b/src/kdefrontend/ui/dockwidgets/livedatadock.ui @@ -11,170 +11,7 @@ - - - - - 75 - true - - - - Update Options - - - - - - - Read: - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 10 - 20 - - - - - - - - - 0 - 0 - - - - - Continuously Fixed - - - - - From End - - - - - Till the End - - - - - Read Whole File - - - - - - - - Sample size: - - - - - - - Keep last values: - - - - - - - Update: - - - - - - - - Periodically - - - - - On New Data - - - - - - - - Update interval: - - - - - - - ms - - - 20 - - - 3600000 - - - 1000 - - - - - - - Update Now - - - - - - - Qt::Vertical - - - QSizePolicy::Fixed - - - - 20 - 40 - - - - - - - - - 75 - true - - - - Topics - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - - + @@ -322,14 +159,47 @@ - - + + + + true + + + + + + + + 75 + true + + - LWT: + Update Options - + + + + Read: + + + + + + + Qt::Horizontal + + + + 318 + 20 + + + + + @@ -342,20 +212,77 @@ - - + + + + Keep last values: + + + + + + + + 0 + 0 + + + + Update Will Message + + + + + + + Update: + + + + + - Qt::Horizontal + Qt::Vertical + + + QSizePolicy::Fixed - 318 - 20 + 20 + 40 + + + LWT: + + + + + + + Source: + + + + + + + + 0 + 0 + + + + Pause Reading + + + + Qt::Vertical @@ -368,7 +295,14 @@ - + + + + Update interval: + + + + @@ -387,7 +321,23 @@ - + + + + + 75 + true + + + + Topics + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + false @@ -406,32 +356,106 @@ - - + + + + + Periodically + + + + + On New Data + + + + + + 0 0 + + + Continuously Fixed + + + + + From End + + + + + Till the End + + + + + Read Whole File + + + + + + - Pause Reading + Sample size: - - - - - 0 - 0 - + + + + Update Now + + + + + + + ms + + + 20 + + + 3600000 + + 1000 + + + + + - Update Will Message + Name: + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 10 + 20 + + + + + + +