Advertisement
Guest User

Untitled

a guest
Feb 9th, 2019
568
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
  2. index 33e3a9208..11d7d561e 100644
  3. --- a/src/CMakeLists.txt
  4. +++ b/src/CMakeLists.txt
  5. @@ -40,6 +40,7 @@ set(GUI_SOURCES
  6.     ${KDEFRONTEND_DIR}/datasources/FITSOptionsWidget.cpp
  7.     ${KDEFRONTEND_DIR}/datasources/MQTTErrorWidget.cpp
  8.     ${KDEFRONTEND_DIR}/datasources/MQTTHelpers.cpp
  9. +    ${KDEFRONTEND_DIR}/datasources/MQTTSubscriptionWidget
  10.     ${KDEFRONTEND_DIR}/datasources/JsonOptionsWidget.cpp
  11.     ${KDEFRONTEND_DIR}/datasources/MQTTConnectionManagerWidget.cpp
  12.     ${KDEFRONTEND_DIR}/datasources/MQTTConnectionManagerDialog.cpp
  13. @@ -122,6 +123,7 @@ set(UI_SOURCES
  14.     ${KDEFRONTEND_DIR}/ui/datasources/rootoptionswidget.ui
  15.     ${KDEFRONTEND_DIR}/ui/datasources/fitsoptionswidget.ui
  16.     ${KDEFRONTEND_DIR}/ui/datasources/mqtterrorwidget.ui
  17. +    ${KDEFRONTEND_DIR}/ui/datasources/mqttsubscriptionwidget.ui
  18.     ${KDEFRONTEND_DIR}/ui/datasources/jsonoptionswidget.ui
  19.     ${KDEFRONTEND_DIR}/ui/datasources/mqttconnectionmanagerwidget.ui
  20.     ${KDEFRONTEND_DIR}/ui/dockwidgets/axisdock.ui
  21. diff --git a/src/kdefrontend/datasources/ImportFileWidget.cpp b/src/kdefrontend/datasources/ImportFileWidget.cpp
  22. index 7471f7cda..9673f3089 100644
  23. --- a/src/kdefrontend/datasources/ImportFileWidget.cpp
  24. +++ b/src/kdefrontend/datasources/ImportFileWidget.cpp
  25. @@ -6,7 +6,7 @@ Description          : import file data widget
  26.  Copyright            : (C) 2009-2018 Stefan Gerlach (stefan.gerlach@uni.kn)
  27.  Copyright            : (C) 2009-2019 Alexander Semke (alexander.semke@web.de)
  28.  Copyright            : (C) 2017-2018 Fabian Kristof (fkristofszabolcs@gmail.com)
  29. -Copyright            : (C) 2018 Kovacs Ferencz (kferike98@gmail.com)
  30. +Copyright            : (C) 2018-2019 Kovacs Ferencz (kferike98@gmail.com)
  31.  
  32.  ***************************************************************************/
  33.  
  34. @@ -67,6 +67,7 @@ Copyright            : (C) 2018 Kovacs Ferencz (kferike98@gmail.com)
  35.  #include "kdefrontend/widgets/MQTTWillSettingsWidget.h"
  36.  #include "MQTTConnectionManagerDialog.h"
  37.  #include "MQTTHelpers.h"
  38. +#include "MQTTSubscriptionWidget.h"
  39.  #include <QMqttClient>
  40.  #include <QMqttSubscription>
  41.  #include <QMqttTopicFilter>
  42. @@ -86,9 +87,9 @@ ImportFileWidget::ImportFileWidget(QWidget* parent, bool liveDataSource, const Q
  43.     m_fileName(fileName),
  44.     m_liveDataSource(liveDataSource)
  45.  #ifdef HAVE_MQTT
  46. -   ,
  47. -   m_searchTimer(new QTimer(this)),
  48. -   m_connectTimeoutTimer(new QTimer(this))
  49. +    ,
  50. +    m_connectTimeoutTimer(new QTimer(this)),
  51. +    m_subscriptionWidget(new MQTTSubscriptionWidget(this))
  52.  #endif
  53.  {
  54.     ui.setupUi(this);
  55. @@ -135,7 +136,6 @@ ImportFileWidget::ImportFileWidget(QWidget* parent, bool liveDataSource, const Q
  56.         ui.tabWidget->removeTab(2);
  57.  
  58.  #ifdef HAVE_MQTT
  59. -       m_searchTimer->setInterval(10000);
  60.         m_connectTimeoutTimer->setInterval(6000);
  61.  #endif
  62.     }
  63. @@ -173,35 +173,16 @@ ImportFileWidget::ImportFileWidget(QWidget* parent, bool liveDataSource, const Q
  64.     ui.cbSourceType->addItem(QLatin1String("MQTT"));
  65.     m_configPath = QStandardPaths::standardLocations(QStandardPaths::AppDataLocation).constFirst() + QLatin1String("MQTT_connections");
  66.  
  67. -   const int size = ui.leTopics->height();
  68. -   ui.lTopicSearch->setPixmap( QIcon::fromTheme(QLatin1String("go-next")).pixmap(size, size) );
  69. -   ui.lSubscriptionSearch->setPixmap( QIcon::fromTheme(QLatin1String("go-next")).pixmap(size, size) );
  70. -   ui.bSubscribe->setIcon(ui.bSubscribe->style()->standardIcon(QStyle::SP_ArrowRight));
  71. -   ui.bSubscribe->setToolTip(i18n("Subscribe selected topics"));
  72. -   ui.bUnsubscribe->setIcon(ui.bUnsubscribe->style()->standardIcon(QStyle::SP_ArrowLeft));
  73. -   ui.bUnsubscribe->setToolTip(i18n("Unsubscribe selected topics"));
  74. +    ui.swSubscriptions->addWidget(m_subscriptionWidget);
  75. +    ui.swSubscriptions->setCurrentWidget(m_subscriptionWidget);
  76.     ui.bManageConnections->setIcon(QIcon::fromTheme(QLatin1String("network-server")));
  77. -   ui.bManageConnections->setToolTip(i18n("Manage MQTT connections"));
  78. +    ui.bManageConnections->setToolTip(i18n("Manage MQTT connections"));
  79.  
  80. -   QString info = i18n("Enter the name of the topic to navigate to it.");
  81. -   ui.lTopicSearch->setToolTip(info);
  82. -   ui.leTopics->setToolTip(info);
  83. -   ui.lSubscriptionSearch->setToolTip(info);
  84. -   ui.leSubscriptions->setToolTip(info);
  85. -
  86. -   info = i18n("Specify the 'Last Will and Testament' message (LWT). At least one topic has to be subscribed.");
  87. +    QString info = i18n("Specify the 'Last Will and Testament' message (LWT). At least one topic has to be subscribed.");
  88.     ui.lLWT->setToolTip(info);
  89.     ui.bLWT->setToolTip(info);
  90.     ui.bLWT->setEnabled(false);
  91. -   ui.bLWT->setIcon(ui.bLWT->style()->standardIcon(QStyle::SP_FileDialogDetailedView));
  92. -
  93. -   info = i18n("Set the Quality of Service (QoS) for the subscription to define the guarantee of the message delivery:"
  94. -   "<ul>"
  95. -   "<li>0 - deliver at most once</li>"
  96. -   "<li>1 - deliver at least once</li>"
  97. -   "<li>2 - deliver exactly once</li>"
  98. -   "</ul>");
  99. -   ui.cbQos->setToolTip(info);
  100. +    ui.bLWT->setIcon(ui.bLWT->style()->standardIcon(QStyle::SP_FileDialogDetailedView));
  101.  #endif
  102.  
  103.     //TODO: implement save/load of user-defined settings later and activate these buttons again
  104. @@ -316,6 +297,10 @@ ImportFileWidget::~ImportFileWidget() {
  105.     conf.writeEntry("UpdateInterval", ui.sbUpdateInterval->value());
  106.  
  107.  #ifdef HAVE_MQTT
  108. +
  109. +    delete m_connectTimeoutTimer;
  110. +    delete m_subscriptionWidget;
  111. +
  112.     //MQTT related settings
  113.     conf.writeEntry("Connection", ui.cbConnection->currentText());
  114.     conf.writeEntry("mqttWillMessageType", static_cast<int>(m_willSettings.willMessageType));
  115. @@ -367,19 +352,14 @@ void ImportFileWidget::initSlots() {
  116.     connect(ui.bRefreshPreview, &QPushButton::clicked, this, &ImportFileWidget::refreshPreview);
  117.  
  118.  #ifdef HAVE_MQTT
  119. -   connect(ui.cbConnection, static_cast<void (QComboBox::*) (int)>(&QComboBox::currentIndexChanged), this, &ImportFileWidget::mqttConnectionChanged);
  120. -   connect(ui.bSubscribe,  &QPushButton::clicked, this, &ImportFileWidget::mqttSubscribe);
  121. -   connect(ui.bUnsubscribe, &QPushButton::clicked, this,&ImportFileWidget::mqttUnsubscribe);
  122. -   connect(this, &ImportFileWidget::newTopic, this, &ImportFileWidget::setTopicCompleter);
  123. -   connect(m_searchTimer, &QTimer::timeout, this, &ImportFileWidget::topicTimeout);
  124. +    connect(ui.cbConnection, static_cast<void (QComboBox::*) (int)>(&QComboBox::currentIndexChanged), this, &ImportFileWidget::mqttConnectionChanged);
  125.     connect(m_connectTimeoutTimer, &QTimer::timeout, this, &ImportFileWidget::mqttConnectTimeout);
  126. -   connect(ui.cbFileType, static_cast<void (QComboBox::*) (int)>(&QComboBox::currentIndexChanged), [this]() {emit checkFileType();});
  127. -   connect(ui.leTopics, &QLineEdit::textChanged, this, &ImportFileWidget::scrollToTopicTreeItem);
  128. -   connect(ui.leSubscriptions, &QLineEdit::textChanged, this, &ImportFileWidget::scrollToSubsriptionTreeItem);
  129. +    connect(ui.cbFileType, static_cast<void (QComboBox::*) (int)>(&QComboBox::currentIndexChanged), [this]() {emit checkFileType();});
  130.     connect(ui.bManageConnections, &QPushButton::clicked, this, &ImportFileWidget::showMQTTConnectionManager);
  131. -   connect(ui.bLWT, &QPushButton::clicked, this, &ImportFileWidget::showWillSettings);
  132. -   connect(ui.twTopics, &QTreeWidget::itemDoubleClicked, this, &ImportFileWidget::mqttAvailableTopicDoubleClicked);
  133. -   connect(ui.twSubscriptions, &QTreeWidget::itemDoubleClicked, this, &ImportFileWidget::mqttSubscribedTopicDoubleClicked);
  134. +    connect(ui.bLWT, &QPushButton::clicked, this, &ImportFileWidget::showWillSettings);
  135. +    connect(m_subscriptionWidget, &MQTTSubscriptionWidget::makeSubscription, this, &ImportFileWidget::mqttSubscribe);
  136. +    connect(m_subscriptionWidget, &MQTTSubscriptionWidget::MQTTUnsubscribeFromTopic, this, &ImportFileWidget::unsubscribeFromTopic);
  137. +    connect(m_subscriptionWidget, &MQTTSubscriptionWidget::enableWill, this, &ImportFileWidget::enableWill);
  138.  #endif
  139.  }
  140.  
  141. @@ -774,16 +754,19 @@ void ImportFileWidget::selectFile() {
  142.  void ImportFileWidget::setMQTTVisible(bool visible) {
  143.     ui.lConnections->setVisible(visible);
  144.     ui.cbConnection->setVisible(visible);
  145. -   ui.bManageConnections->setVisible(visible);
  146. -   ui.cbQos->setVisible(visible);
  147. +    ui.bManageConnections->setVisible(visible);
  148.  
  149.     //topics
  150.     if (ui.cbConnection->currentIndex() != -1 && visible) {
  151.         ui.lTopics->setVisible(true);
  152. -       ui.gbManageSubscriptions->setVisible(true);
  153. +        ui.swSubscriptions->setVisible(true);
  154. +        m_subscriptionWidget->setVisible(true);
  155. +        m_subscriptionWidget->makeVisible(true);
  156.     } else {
  157.         ui.lTopics->setVisible(false);
  158. -       ui.gbManageSubscriptions->setVisible(false);
  159. +        ui.swSubscriptions->setVisible(false);
  160. +        m_subscriptionWidget->setVisible(false);
  161. +        m_subscriptionWidget->makeVisible(false);
  162.     }
  163.  
  164.     //will message
  165. @@ -801,7 +784,7 @@ bool ImportFileWidget::isMqttValid() {
  166.         return false;
  167.  
  168.     bool connected = (m_client->state() == QMqttClient::ClientState::Connected);
  169. -   bool subscribed = (ui.twSubscriptions->topLevelItemCount() > 0);
  170. +    bool subscribed = (m_subscriptionWidget->subscriptionCount() > 0);
  171.     bool fileTypeOk = false;
  172.     if (this->currentFileType() == AbstractFileFilter::FileType::Ascii)
  173.         fileTypeOk = true;
  174. @@ -814,7 +797,7 @@ bool ImportFileWidget::isMqttValid() {
  175.   *
  176.   * \param topicName the name of a topic we want to unsubscribe from
  177.   */
  178. -void ImportFileWidget::unsubscribeFromTopic(const QString& topicName) {
  179. +void ImportFileWidget::unsubscribeFromTopic(const QString& topicName, QVector<QTreeWidgetItem*> children) {
  180.     if (topicName.isEmpty())
  181.         return;
  182.  
  183. @@ -841,14 +824,7 @@ void ImportFileWidget::unsubscribeFromTopic(const QString& topicName) {
  184.         j.next();
  185.         if (MQTTHelpers::checkTopicContains(topicName, j.key().name()))
  186.             m_lastMessage.remove(j.key());
  187. -   }
  188. -
  189. -   for (int row = 0; row < ui.twSubscriptions->topLevelItemCount(); row++)  {
  190. -       if (ui.twSubscriptions->topLevelItem(row)->text(0) == topicName) {
  191. -           ui.twSubscriptions->topLevelItem(row)->takeChildren();
  192. -           ui.twSubscriptions->takeTopLevelItem(row);
  193. -       }
  194. -   }
  195. +    }
  196.  
  197.     for (int i = 0; i < m_subscribedTopicNames.size(); ++i) {
  198.         if (MQTTHelpers::checkTopicContains(topicName, m_subscribedTopicNames[i])) {
  199. @@ -857,10 +833,8 @@ void ImportFileWidget::unsubscribeFromTopic(const QString& topicName) {
  200.         }
  201.     }
  202.  
  203. -   if (m_willSettings.willTopic == topicName) {
  204. -       QVector<QTreeWidgetItem*> children;
  205. -       if (ui.twSubscriptions->topLevelItemCount() > 0) {
  206. -           MQTTHelpers::findSubscriptionLeafChildren(children, ui.twSubscriptions->topLevelItem(0));
  207. +    if (m_willSettings.willTopic == topicName) {
  208. +        if (m_subscriptionWidget->subscriptionCount() > 0) {
  209.             m_willSettings.willTopic = children[0]->text(0);
  210.         } else
  211.             m_willSettings.willTopic = "";
  212. @@ -870,185 +844,6 @@ void ImportFileWidget::unsubscribeFromTopic(const QString& topicName) {
  213.     emit subscriptionsChanged();
  214.     refreshPreview();
  215.  }
  216. -
  217. -/*!
  218. - *\brief We search in twSubscriptions for topics that can be represented using + wildcards, then merge them.
  219. - *      We do this until there are no topics to merge
  220. - */
  221. -void ImportFileWidget::manageCommonLevelSubscriptions() {
  222. -   bool foundEqual = false;
  223. -
  224. -   do {
  225. -       foundEqual = false;
  226. -       QMap<QString, QVector<QString>> equalTopicsMap;
  227. -       QVector<QString> equalTopics;
  228. -
  229. -       //compare the subscriptions present in the TreeWidget
  230. -       for (int i = 0; i < ui.twSubscriptions->topLevelItemCount() - 1; ++i) {
  231. -           for (int j = i + 1; j < ui.twSubscriptions->topLevelItemCount(); ++j) {
  232. -               QString commonTopic = MQTTHelpers::checkCommonLevel(ui.twSubscriptions->topLevelItem(i)->text(0), ui.twSubscriptions->topLevelItem(j)->text(0));
  233. -
  234. -               //if there is a common topic for the 2 compared topics, we add them to the map (using the common topic as key)
  235. -               if (!commonTopic.isEmpty()) {
  236. -                   if (!equalTopicsMap[commonTopic].contains(ui.twSubscriptions->topLevelItem(i)->text(0)))
  237. -                       equalTopicsMap[commonTopic].push_back(ui.twSubscriptions->topLevelItem(i)->text(0));
  238. -
  239. -                   if (!equalTopicsMap[commonTopic].contains(ui.twSubscriptions->topLevelItem(j)->text(0)))
  240. -                       equalTopicsMap[commonTopic].push_back(ui.twSubscriptions->topLevelItem(j)->text(0));
  241. -               }
  242. -           }
  243. -       }
  244. -
  245. -       if (!equalTopicsMap.isEmpty()) {
  246. -           DEBUG("Manage common topics");
  247. -
  248. -           QVector<QString> commonTopics;
  249. -           QMapIterator<QString, QVector<QString>> topics(equalTopicsMap);
  250. -
  251. -           //check for every map entry, if the found topics can be merged or not
  252. -           while (topics.hasNext()) {
  253. -               topics.next();
  254. -
  255. -               int level = MQTTHelpers::commonLevelIndex(topics.value().last(), topics.value().first());
  256. -               QStringList commonList = topics.value().first().split('/', QString::SkipEmptyParts);
  257. -               QTreeWidgetItem* currentItem = nullptr;
  258. -               //search the corresponding item to the common topics first level(root)
  259. -               for (int i = 0; i < ui.twTopics->topLevelItemCount(); ++i) {
  260. -                   if (ui.twTopics->topLevelItem(i)->text(0) == commonList.first()) {
  261. -                       currentItem = ui.twTopics->topLevelItem(i);
  262. -                       break;
  263. -                   }
  264. -               }
  265. -
  266. -               if (!currentItem)
  267. -                   break;
  268. -
  269. -               //calculate the number of topics the new + wildcard could replace
  270. -               int childCount = MQTTHelpers::checkCommonChildCount(1, level, commonList, currentItem);
  271. -               if (childCount > 0) {
  272. -                   //if the number of topics found and the calculated number of topics is equal, the topics can be merged
  273. -                   if (topics.value().size() == childCount) {
  274. -                       QDEBUG("Found common topic to manage: " << topics.key());
  275. -                       foundEqual = true;
  276. -                       commonTopics.push_back(topics.key());
  277. -                   }
  278. -               }
  279. -           }
  280. -
  281. -           if (foundEqual) {
  282. -               //if there are more common topics, the topics of which can be merged, we choose the one which has the lowest level new '+' wildcard
  283. -               int lowestLevel = INT_MAX;
  284. -               int topicIdx = -1;
  285. -               for (int i = 0; i < commonTopics.size(); ++i) {
  286. -                   int level = MQTTHelpers::commonLevelIndex(equalTopicsMap[commonTopics[i]].first(), commonTopics[i]);
  287. -                   if (level < lowestLevel) {
  288. -                       topicIdx = i;
  289. -                       lowestLevel = level;
  290. -                   }
  291. -               }
  292. -               QDEBUG("Manage: " << commonTopics[topicIdx]);
  293. -               equalTopics.append(equalTopicsMap[commonTopics[topicIdx]]);
  294. -
  295. -               //Add the common topic ("merging")
  296. -               QString commonTopic;
  297. -               commonTopic = MQTTHelpers::checkCommonLevel(equalTopics.first(), equalTopics.last());
  298. -               QStringList nameList;
  299. -               nameList.append(commonTopic);
  300. -               QTreeWidgetItem* newTopic = new QTreeWidgetItem(nameList);
  301. -               ui.twSubscriptions->addTopLevelItem(newTopic);
  302. -               QMqttTopicFilter filter {commonTopic};
  303. -               QMqttSubscription *temp_subscription = m_client->subscribe(filter, static_cast<quint8> (ui.cbQos->currentText().toUInt()) );
  304. -
  305. -               if (temp_subscription) {
  306. -                   m_mqttSubscriptions.push_back(temp_subscription);
  307. -                   connect(temp_subscription, &QMqttSubscription::messageReceived, this, &ImportFileWidget::mqttSubscriptionMessageReceived);
  308. -                   emit subscriptionsChanged();
  309. -               }
  310. -
  311. -               //remove the "merged" topics
  312. -               for (int i = 0; i < equalTopics.size(); ++i) {
  313. -                   for (int j = 0; j < ui.twSubscriptions->topLevelItemCount(); ++j) {
  314. -                       if (ui.twSubscriptions->topLevelItem(j)->text(0) == equalTopics[i]) {
  315. -                           newTopic->addChild(ui.twSubscriptions->takeTopLevelItem(j));
  316. -                           unsubscribeFromTopic(equalTopics[i]);
  317. -                           break;
  318. -                       }
  319. -                   }
  320. -               }
  321. -
  322. -               //remove any subscription that the new subscription contains
  323. -               for (int i = 0; i < ui.twSubscriptions->topLevelItemCount(); ++i) {
  324. -                   if (MQTTHelpers::checkTopicContains(commonTopic, ui.twSubscriptions->topLevelItem(i)->text(0)) &&
  325. -                           commonTopic != ui.twSubscriptions->topLevelItem(i)->text(0) ) {
  326. -                       unsubscribeFromTopic(ui.twSubscriptions->topLevelItem(i)->text(0));
  327. -                       i--;
  328. -                   }
  329. -               }
  330. -           }
  331. -       }
  332. -   } while (foundEqual);
  333. -}
  334. -
  335. -/*!
  336. - *\brief Fills twSubscriptions with the subscriptions made by the client
  337. - */
  338. -void ImportFileWidget::updateSubscriptionTree() {
  339. -   DEBUG("ImportFileWidget::updateSubscriptionTree()");
  340. -   ui.twSubscriptions->clear();
  341. -
  342. -   for (int i = 0; i < m_mqttSubscriptions.size(); ++i) {
  343. -       QStringList name;
  344. -       name.append(m_mqttSubscriptions[i]->topic().filter());
  345. -
  346. -       bool found = false;
  347. -       for (int j = 0; j < ui.twSubscriptions->topLevelItemCount(); ++j) {
  348. -           if (ui.twSubscriptions->topLevelItem(j)->text(0) == m_mqttSubscriptions[i]->topic().filter()) {
  349. -               found = true;
  350. -               break;
  351. -           }
  352. -       }
  353. -
  354. -       if (!found) {
  355. -           //Add the subscription to the tree widget
  356. -           QTreeWidgetItem* newItem = new QTreeWidgetItem(name);
  357. -           ui.twSubscriptions->addTopLevelItem(newItem);
  358. -           name.clear();
  359. -           name = m_mqttSubscriptions[i]->topic().filter().split('/', QString::SkipEmptyParts);
  360. -
  361. -           //find the corresponding "root" item in twTopics
  362. -           QTreeWidgetItem* topic = nullptr;
  363. -           for (int j = 0; j < ui.twTopics->topLevelItemCount(); ++j) {
  364. -               if (ui.twTopics->topLevelItem(j)->text(0) == name[0]) {
  365. -                   topic = ui.twTopics->topLevelItem(j);
  366. -                   break;
  367. -               }
  368. -           }
  369. -
  370. -           //restore the children of the subscription
  371. -           if (topic != nullptr && topic->childCount() > 0) {
  372. -               MQTTHelpers::restoreSubscriptionChildren(topic, newItem, name, 1);
  373. -           }
  374. -       }
  375. -   }
  376. -   m_searching = false;
  377. -}
  378. -
  379. -/*!
  380. - *\brief Updates the completer for leSubscriptions
  381. - */
  382. -void ImportFileWidget::updateSubscriptionCompleter() {
  383. -   QStringList subscriptionList;
  384. -   for (int i = 0; i < ui.twSubscriptions->topLevelItemCount(); ++i)
  385. -       subscriptionList.append(ui.twSubscriptions->topLevelItem(i)->text(0));
  386. -
  387. -   if (!subscriptionList.isEmpty()) {
  388. -       m_subscriptionCompleter = new QCompleter(subscriptionList, this);
  389. -       m_subscriptionCompleter->setCompletionMode(QCompleter::PopupCompletion);
  390. -       m_subscriptionCompleter->setCaseSensitivity(Qt::CaseSensitive);
  391. -       ui.leSubscriptions->setCompleter(m_subscriptionCompleter);
  392. -   } else
  393. -       ui.leSubscriptions->setCompleter(nullptr);
  394. -}
  395.  #endif
  396.  
  397.  /************** SLOTS **************************************************************/
  398. @@ -1963,9 +1758,7 @@ void ImportFileWidget::mqttConnectionChanged() {
  399.  
  400.     //disconnected from the broker that was selected before, if this is the case
  401.     if (m_client && m_client->state() == QMqttClient::ClientState::Connected) {
  402. -       ui.twTopics->clear();
  403. -       ui.twSubscriptions->clear();
  404. -       ui.twTopics->headerItem()->setText(0, i18n("Available"));
  405. +        emit MQTTClearTopics();
  406.         disconnect(m_client, &QMqttClient::disconnected, this, &ImportFileWidget::onMqttDisconnect);
  407.         QDEBUG("Disconnecting from " << m_client->hostname());
  408.         m_client->disconnectFromHost();
  409. @@ -2008,7 +1801,9 @@ void ImportFileWidget::mqttConnectionChanged() {
  410.  void ImportFileWidget::onMqttConnect() {
  411.     if (m_client->error() == QMqttClient::NoError) {
  412.         m_connectTimeoutTimer->stop();
  413. -       ui.gbManageSubscriptions->setVisible(true);
  414. +        ui.swSubscriptions->setVisible(true);
  415. +        m_subscriptionWidget->setVisible(true);
  416. +        m_subscriptionWidget->makeVisible(true);
  417.  
  418.         if (!m_client->subscribe(QMqttTopicFilter(QLatin1String("#")), 1))
  419.             QMessageBox::critical(this, i18n("Couldn't subscribe"), i18n("Couldn't subscribe to all available topics. Something went wrong"));
  420. @@ -2022,20 +1817,16 @@ void ImportFileWidget::onMqttConnect() {
  421.   * removes every information about the former connection
  422.   */
  423.  void ImportFileWidget::onMqttDisconnect() {
  424. -   DEBUG("Disconected from " << m_client->hostname().toStdString());
  425. -   m_searchTimer->stop();
  426. +    DEBUG("Disconected from " << m_client->hostname().toStdString());
  427.     m_connectTimeoutTimer->stop();
  428.  
  429.     ui.lTopics->hide();
  430. -   ui.gbManageSubscriptions->hide();
  431. +    ui.swSubscriptions->hide();
  432.     ui.lLWT->hide();
  433.     ui.bLWT->hide();
  434.  
  435.     ui.cbConnection->setItemText(ui.cbConnection->currentIndex(), ui.cbConnection->currentText() + " " + i18n("(Disconnected)"));
  436. -   m_mqttReadyForPreview = false;
  437. -   m_searching = false;
  438. -   delete m_topicCompleter;
  439. -   delete m_subscriptionCompleter;
  440. +   m_mqttReadyForPreview = false; 
  441.  
  442.     emit subscriptionsChanged();
  443.     RESET_CURSOR;
  444. @@ -2043,175 +1834,21 @@ void ImportFileWidget::onMqttDisconnect() {
  445.         i18n("Disconnected from the broker '%1' before the connection was successful.", m_client->hostname()));
  446.  }
  447.  
  448. -/*!
  449. - *\brief When a leaf topic is double clicked in the topics tree widget we subscribe on that
  450. - */
  451. -void ImportFileWidget::mqttAvailableTopicDoubleClicked(QTreeWidgetItem* item, int column) {
  452. -   Q_UNUSED(column)
  453. -   // Only for leaf topics
  454. -   if (item->childCount() == 0)
  455. -       mqttSubscribe();
  456. -}
  457. -
  458. -/*!
  459. - *\brief When a leaf subscription is double clicked in the topics tree widget we unsubscribe
  460. - */
  461. -void ImportFileWidget::mqttSubscribedTopicDoubleClicked(QTreeWidgetItem* item, int column) {
  462. -   Q_UNUSED(column)
  463. -   // Only for leaf subscriptions
  464. -   if (item->childCount() == 0)
  465. -       mqttUnsubscribe();
  466. -}
  467. -
  468.  /*!
  469.   *\brief called when the subscribe button is pressed
  470.   * subscribes to the topic represented by the current item of twTopics
  471.   */
  472. -void ImportFileWidget::mqttSubscribe() {
  473. -   QTreeWidgetItem* item = ui.twTopics->currentItem();
  474. -   if (!item) {
  475. -       QMessageBox::warning(this, i18n("Warning"), i18n("You didn't select any item from the Tree Widget"));
  476. -       return;
  477. -   }
  478. -
  479. -   //determine the topic name that the current item represents
  480. -   QTreeWidgetItem* tempItem = item;
  481. -   QString name = item->text(0);
  482. -   if (item->childCount() != 0)
  483. -       name.append("/#");
  484. -
  485. -   while (tempItem->parent()) {
  486. -       tempItem = tempItem->parent();
  487. -       name.prepend(tempItem->text(0) + '/');
  488. -   }
  489. -
  490. -   //check if the subscription already exists
  491. -   const QList<QTreeWidgetItem*>& topLevelList = ui.twSubscriptions->findItems(name, Qt::MatchExactly);
  492. -   if (topLevelList.isEmpty() || topLevelList.first()->parent() != nullptr) {
  493. -       QDEBUG("Subscribe to: " << name);
  494. -       bool foundSuperior = false;
  495. -
  496. -       for (int i = 0; i < ui.twSubscriptions->topLevelItemCount(); ++i) {
  497. -           //if the new subscirptions contains an already existing one, we remove the inferior one
  498. -           if (MQTTHelpers::checkTopicContains(name, ui.twSubscriptions->topLevelItem(i)->text(0))
  499. -                   && name != ui.twSubscriptions->topLevelItem(i)->text(0)) {
  500. -               unsubscribeFromTopic(ui.twSubscriptions->topLevelItem(i)->text(0));
  501. -               --i;
  502. -               continue;
  503. -           }
  504. -
  505. -           //if there is a subscription containing the new one we set foundSuperior true
  506. -           if (MQTTHelpers::checkTopicContains(ui.twSubscriptions->topLevelItem(i)->text(0), name)
  507. -                   && name != ui.twSubscriptions->topLevelItem(i)->text(0)) {
  508. -               foundSuperior = true;
  509. -               QDEBUG("Can't continue subscribing. Found superior for " << name << " : " << ui.twSubscriptions->topLevelItem(i)->text(0));
  510. -               break;
  511. -           }
  512. -       }
  513. -
  514. -       //if there wasn't a superior subscription we can subscribe to the new topic
  515. -       if (!foundSuperior) {
  516. -           QStringList toplevelName;
  517. -           toplevelName.push_back(name);
  518. -           QTreeWidgetItem* newTopLevelItem = new QTreeWidgetItem(toplevelName);
  519. -           ui.twSubscriptions->addTopLevelItem(newTopLevelItem);
  520. -
  521. -           const QMqttTopicFilter filter {name};
  522. -           QMqttSubscription *tempSubscription = m_client->subscribe(filter, static_cast<quint8>(ui.cbQos->currentText().toUInt()) );
  523. -
  524. -           if (tempSubscription) {
  525. -               m_mqttSubscriptions.push_back(tempSubscription);
  526. -               connect(tempSubscription, &QMqttSubscription::messageReceived, this, &ImportFileWidget::mqttSubscriptionMessageReceived);
  527. -               emit subscriptionsChanged();
  528. -           }
  529. -
  530. -           if (name.endsWith('#')) {
  531. -               //adding every topic that the subscription contains to twSubscriptions
  532. -               MQTTHelpers::addSubscriptionChildren(item, newTopLevelItem);
  533. -
  534. -               //if an already existing subscription contains a topic that the new subscription also contains
  535. -               //we decompose the already existing subscription
  536. -               //by unsubscribing from its topics, that are present in the new subscription as well
  537. -               const QStringList nameList = name.split('/', QString::SkipEmptyParts);
  538. -               const QString& root = nameList.first();
  539. -               QVector<QTreeWidgetItem*> children;
  540. -               for (int i = 0; i < ui.twSubscriptions->topLevelItemCount(); ++i) {
  541. -                   if (ui.twSubscriptions->topLevelItem(i)->text(0).startsWith(root)
  542. -                           && name != ui.twSubscriptions->topLevelItem(i)->text(0)) {
  543. -                       children.clear();
  544. -                       //get the "leaf" children of the inspected subscription
  545. -                       MQTTHelpers::findSubscriptionLeafChildren(children, ui.twSubscriptions->topLevelItem(i));
  546. -                       for (int j = 0; j < children.size(); ++j) {
  547. -                           if (MQTTHelpers::checkTopicContains(name, children[j]->text(0))) {
  548. -                               //if the new subscription contains a topic, we unsubscribe from it
  549. -                               ui.twSubscriptions->setCurrentItem(children[j]);
  550. -                               mqttUnsubscribe();
  551. -                               --i;
  552. -                           }
  553. -                       }
  554. -                   }
  555. -               }
  556. -           }
  557. -
  558. -           manageCommonLevelSubscriptions();
  559. -           updateSubscriptionCompleter();
  560. -
  561. -           if (!ui.bLWT->isEnabled())
  562. -               ui.bLWT->setEnabled(true);
  563. -       } else
  564. -           QMessageBox::warning(this, i18n("Warning"), i18n("You already subscribed to a topic containing this one"));
  565. -   } else
  566. -       QMessageBox::warning(this, i18n("Warning"), i18n("You already subscribed to this topic"));
  567. +void ImportFileWidget::mqttSubscribe(const QString& name, uint QoS) {
  568. +    const QMqttTopicFilter filter {name};
  569. +    QMqttSubscription *tempSubscription = m_client->subscribe(filter, static_cast<quint8>(QoS) );
  570. +
  571. +    if (tempSubscription) {
  572. +        m_mqttSubscriptions.push_back(tempSubscription);
  573. +        connect(tempSubscription, &QMqttSubscription::messageReceived, this, &ImportFileWidget::mqttSubscriptionMessageReceived);
  574. +        emit subscriptionsChanged();
  575. +    }
  576.  }
  577.  
  578. -/*!
  579. - *\brief called when the unsubscribe button is pressed
  580. - * unsubscribes from the topic represented by the current item of twSubscription
  581. - */
  582. -void ImportFileWidget::mqttUnsubscribe() {
  583. -   QTreeWidgetItem* unsubscribeItem = ui.twSubscriptions->currentItem();
  584. -   if (!unsubscribeItem) {
  585. -       QMessageBox::warning(this, i18n("Warning"), i18n("You didn't select any item from the Tree Widget"));
  586. -       return;
  587. -   }
  588. -
  589. -   QDEBUG("Unsubscribe from: " << unsubscribeItem->text(0));
  590. -   //if it is a top level item, meaning a topic that we really subscribed to(not one that belongs to a subscription)
  591. -   //we can simply unsubscribe from it
  592. -   if (unsubscribeItem->parent() == nullptr)
  593. -       unsubscribeFromTopic(unsubscribeItem->text(0));
  594. -
  595. -   //otherwise we remove the selected item, but subscribe to every other topic, that was contained by
  596. -   //the selected item's parent subscription(top level item of twSubscriptions)
  597. -   else {
  598. -       while (unsubscribeItem->parent() != nullptr) {
  599. -           for (int i = 0; i < unsubscribeItem->parent()->childCount(); ++i) {
  600. -               if (unsubscribeItem->text(0) != unsubscribeItem->parent()->child(i)->text(0)) {
  601. -                   const QMqttTopicFilter filter {unsubscribeItem->parent()->child(i)->text(0)};
  602. -                   QMqttSubscription *tempSubscription = m_client->subscribe(filter, static_cast<quint8>(ui.cbQos->currentText().toUInt()) );
  603. -
  604. -                   ui.twSubscriptions->addTopLevelItem(unsubscribeItem->parent()->takeChild(i));
  605. -
  606. -                   if (tempSubscription) {
  607. -                       m_mqttSubscriptions.push_back(tempSubscription);
  608. -                       connect(tempSubscription, &QMqttSubscription::messageReceived, this, &ImportFileWidget::mqttSubscriptionMessageReceived);
  609. -                       emit subscriptionsChanged();
  610. -                   }
  611. -                   --i;
  612. -               }
  613. -           }
  614. -           unsubscribeItem = unsubscribeItem->parent();
  615. -       }
  616. -       unsubscribeFromTopic(unsubscribeItem->text(0));
  617. -
  618. -       //check if any common topics were subscribed, if possible merge them
  619. -       manageCommonLevelSubscriptions();
  620. -   }
  621. -   updateSubscriptionCompleter();
  622. -
  623. -   if (ui.twSubscriptions->topLevelItemCount() <= 0)
  624. -       ui.bLWT->setEnabled(false);
  625. -}
  626.  
  627.  /*!
  628.   *\brief called when the client receives a message
  629. @@ -2224,7 +1861,7 @@ void ImportFileWidget::mqttMessageReceived(const QByteArray& message, const QMqt
  630.         return;
  631.  
  632.     m_addedTopics.push_back(topic.name());
  633. -   ui.twTopics->headerItem()->setText(0, i18n("Available (%1)", m_addedTopics.size()));
  634. +    m_subscriptionWidget->setTopicTreeText(i18n("Available (%1)", m_addedTopics.size()));
  635.     QStringList name;
  636.     QString rootName;
  637.     const QChar sep = '/';
  638. @@ -2237,8 +1874,8 @@ void ImportFileWidget::mqttMessageReceived(const QByteArray& message, const QMqt
  639.             name.append(list.at(0));
  640.             int topItemIdx = -1;
  641.             //check whether the first level of the topic can be found in twTopics
  642. -           for (int i = 0; i < ui.twTopics->topLevelItemCount(); ++i) {
  643. -               if (ui.twTopics->topLevelItem(i)->text(0) == list.at(0)) {
  644. +            for (int i = 0; i < m_subscriptionWidget->topicCount(); ++i) {
  645. +                if (m_subscriptionWidget->topLevelTopic(i)->text(0) == list.at(0)) {
  646.                     topItemIdx = i;
  647.                     break;
  648.                 }
  649. @@ -2247,7 +1884,7 @@ void ImportFileWidget::mqttMessageReceived(const QByteArray& message, const QMqt
  650.             //if not we simply add every level of the topic to the tree
  651.             if (topItemIdx < 0) {
  652.                 QTreeWidgetItem* currentItem = new QTreeWidgetItem(name);
  653. -               ui.twTopics->addTopLevelItem(currentItem);
  654. +                m_subscriptionWidget->addTopic(currentItem);
  655.                 for (int i = 1; i < list.size(); ++i) {
  656.                     name.clear();
  657.                     name.append(list.at(i));
  658. @@ -2258,7 +1895,7 @@ void ImportFileWidget::mqttMessageReceived(const QByteArray& message, const QMqt
  659.             //otherwise we search for the first level that isn't part of the tree,
  660.             //then add every level of the topic to the tree from that certain level
  661.             else {
  662. -               QTreeWidgetItem* currentItem = ui.twTopics->topLevelItem(topItemIdx);
  663. +                QTreeWidgetItem* currentItem = m_subscriptionWidget->topLevelTopic(topItemIdx);
  664.                 int listIdx = 1;
  665.                 for (; listIdx < list.size(); ++listIdx) {
  666.                     QTreeWidgetItem* childItem = nullptr;
  667. @@ -2289,15 +1926,18 @@ void ImportFileWidget::mqttMessageReceived(const QByteArray& message, const QMqt
  668.     } else {
  669.         rootName = topic.name();
  670.         name.append(topic.name());
  671. -       ui.twTopics->addTopLevelItem(new QTreeWidgetItem(name));
  672. +        m_subscriptionWidget->addTopic(new QTreeWidgetItem(name));
  673.     }
  674.  
  675.     //if a subscribed topic contains the new topic, we have to update twSubscriptions
  676. -   for (int i = 0; i < ui.twSubscriptions->topLevelItemCount(); ++i) {
  677. -       const QStringList subscriptionName = ui.twSubscriptions->topLevelItem(i)->text(0).split('/', QString::SkipEmptyParts);
  678. +    for (int i = 0; i < m_subscriptionWidget->subscriptionCount(); ++i) {
  679. +        const QStringList subscriptionName = m_subscriptionWidget->topLevelSubscription(i)->text(0).split('/', QString::SkipEmptyParts);
  680.         if (!subscriptionName.isEmpty()) {
  681.             if (rootName == subscriptionName.first()) {
  682. -               updateSubscriptionTree();
  683. +                QVector<QString> subscriptions;
  684. +                for(int i = 0; i < m_mqttSubscriptions.size(); ++i)
  685. +                    subscriptions.push_back(m_mqttSubscriptions[i]->topic().filter());
  686. +                emit updateSubscriptionTree(subscriptions);
  687.                 break;
  688.             }
  689.         }
  690. @@ -2307,32 +1947,6 @@ void ImportFileWidget::mqttMessageReceived(const QByteArray& message, const QMqt
  691.     emit newTopic(rootName);
  692.  }
  693.  
  694. -/*!
  695. - *\brief called when a new topic is added to the tree(twTopics)
  696. - * appends the topic's root to the topicList if it isn't in the list already
  697. - * then sets the completer for leTopics
  698. - */
  699. -void ImportFileWidget::setTopicCompleter(const QString& topic) {
  700. -   if (!m_topicList.contains(topic)) {
  701. -       m_topicList.append(topic);
  702. -       if (!m_searching) {
  703. -           m_topicCompleter = new QCompleter(m_topicList, this);
  704. -           m_topicCompleter->setCompletionMode(QCompleter::PopupCompletion);
  705. -           m_topicCompleter->setCaseSensitivity(Qt::CaseSensitive);
  706. -           ui.leTopics->setCompleter(m_topicCompleter);
  707. -       }
  708. -   }
  709. -}
  710. -
  711. -/*!
  712. - *\brief called when 10 seconds passed since the last time the user searched for a certain root in twTopics
  713. - * enables updating the completer for le
  714. - */
  715. -void ImportFileWidget::topicTimeout() {
  716. -   m_searching = false;
  717. -   m_searchTimer->stop();
  718. -}
  719. -
  720.  /*!
  721.   *\brief called when the client receives a message from a subscribed topic (that isn't the "#" wildcard)
  722.   */
  723. @@ -2399,48 +2013,6 @@ void ImportFileWidget::mqttErrorChanged(QMqttClient::ClientError clientError) {
  724.     }
  725.  }
  726.  
  727. -/*!
  728. - *\brief called when leTopics' text is changed
  729. - *      if the rootName can be found in twTopics, then we scroll it to the top of the tree widget
  730. - *
  731. - * \param rootName the current text of leTopics
  732. - */
  733. -void ImportFileWidget::scrollToTopicTreeItem(const QString& rootName) {
  734. -   m_searching = true;
  735. -   m_searchTimer->start();
  736. -
  737. -   int topItemIdx = -1;
  738. -   for (int i = 0; i < ui.twTopics->topLevelItemCount(); ++i)
  739. -       if (ui.twTopics->topLevelItem(i)->text(0) == rootName) {
  740. -           topItemIdx = i;
  741. -           break;
  742. -       }
  743. -
  744. -   if (topItemIdx >= 0)
  745. -       ui.twTopics->scrollToItem(ui.twTopics->topLevelItem(topItemIdx), QAbstractItemView::ScrollHint::PositionAtTop);
  746. -}
  747. -
  748. -/*!
  749. - *\brief called when leSubscriptions' text is changed
  750. - *      if the rootName can be found in twSubscriptions, then we scroll it to the top of the tree widget
  751. - *
  752. - * \param rootName the current text of leSubscriptions
  753. - */
  754. -void ImportFileWidget::scrollToSubsriptionTreeItem(const QString& rootName) {
  755. -   m_searching = true;
  756. -   m_searchTimer->start();
  757. -
  758. -   int topItemIdx = -1;
  759. -   for (int i = 0; i < ui.twSubscriptions->topLevelItemCount(); ++i)
  760. -       if (ui.twSubscriptions->topLevelItem(i)->text(0) == rootName) {
  761. -           topItemIdx = i;
  762. -           break;
  763. -       }
  764. -
  765. -   if (topItemIdx >= 0)
  766. -       ui.twSubscriptions->scrollToItem(ui.twSubscriptions->topLevelItem(topItemIdx), QAbstractItemView::ScrollHint::PositionAtTop);
  767. -}
  768. -
  769.  /*!
  770.   *\brief called when m_connectTimeoutTimer ticks,
  771.   *      meaning that the client couldn't connect to the broker in 5 seconds
  772. @@ -2510,8 +2082,8 @@ void ImportFileWidget::showWillSettings() {
  773.     QMenu menu;
  774.  
  775.     QVector<QTreeWidgetItem*> children;
  776. -   for (int i = 0; i < ui.twSubscriptions->topLevelItemCount(); ++i)
  777. -       MQTTHelpers::findSubscriptionLeafChildren(children, ui.twSubscriptions->topLevelItem(i));
  778. +    for (int i = 0; i < m_subscriptionWidget->subscriptionCount(); ++i)
  779. +        MQTTHelpers::findSubscriptionLeafChildren(children, m_subscriptionWidget->topLevelSubscription(i));
  780.  
  781.     QVector<QString> topics;
  782.     for (int i = 0; i < children.size(); ++i)
  783. @@ -2531,4 +2103,13 @@ void ImportFileWidget::showWillSettings() {
  784.     menu.exec(ui.bLWT->mapToGlobal(pos));
  785.  }
  786.  
  787. +void ImportFileWidget::enableWill(bool enable) {
  788. +    if(enable) {
  789. +        if(!ui.bLWT->isEnabled())
  790. +            ui.bLWT->setEnabled(enable);
  791. +    } else {
  792. +        ui.bLWT->setEnabled(enable);
  793. +    }
  794. +}
  795. +
  796.  #endif
  797. diff --git a/src/kdefrontend/datasources/ImportFileWidget.h b/src/kdefrontend/datasources/ImportFileWidget.h
  798. index 4f4b7043f..77f948236 100644
  799. --- a/src/kdefrontend/datasources/ImportFileWidget.h
  800. +++ b/src/kdefrontend/datasources/ImportFileWidget.h
  801. @@ -6,6 +6,7 @@
  802.      Copyright            : (C) 2009-2017 by Stefan Gerlach (stefan.gerlach@uni-konstanz.de)
  803.      Copyright            : (C) 2009-2019 Alexander Semke (alexander.semke@web.de)
  804.      Copyright            : (C) 2017-2018 Fabian Kristof (fkristofszabolcs@gmail.com)
  805. +    Copyright            : (C) 2018-2019 Kovacs Ferencz (kferike98@gmail.com)
  806.  
  807.   ***************************************************************************/
  808.  
  809. @@ -36,6 +37,7 @@
  810.  
  811.  #ifdef HAVE_MQTT
  812.  #include "backend/datasources/MQTTClient.h"
  813. +class MQTTSubscriptionWidget;
  814.  #endif
  815.  
  816.  #include <QVector>
  817. @@ -138,18 +140,10 @@ signals:
  818.  
  819.  #ifdef HAVE_MQTT
  820.  private:
  821. -   void updateSubscriptionCompleter();
  822. -   void unsubscribeFromTopic(const QString&);
  823. -   void manageCommonLevelSubscriptions();
  824. -   void updateSubscriptionTree();
  825. +    void unsubscribeFromTopic(const QString&, QVector<QTreeWidgetItem*> children);
  826.  
  827.     QMqttClient* m_client{nullptr};
  828. -   QVector<QMqttSubscription*> m_mqttSubscriptions;
  829. -   QCompleter* m_topicCompleter{nullptr};
  830. -   QCompleter* m_subscriptionCompleter{nullptr};
  831. -   QStringList m_topicList;
  832. -   bool m_searching{false};
  833. -   QTimer* m_searchTimer;
  834. +    QVector<QMqttSubscription*> m_mqttSubscriptions;
  835.     QTimer* m_connectTimeoutTimer;
  836.     QMap<QMqttTopicName, bool> m_messageArrived;
  837.     QMap<QMqttTopicName, QMqttMessage> m_lastMessage;
  838. @@ -158,36 +152,34 @@ private:
  839.     QVector<QString> m_addedTopics;
  840.     QString m_configPath;
  841.     bool m_initialisingMQTT{false};
  842. -   bool m_connectionTimedOut{false};
  843. +   bool m_connectionTimedOut{false};    
  844.     MQTTClient::MQTTWill m_willSettings;
  845. +    MQTTSubscriptionWidget* m_subscriptionWidget;
  846. +
  847.  public:
  848.     void saveMQTTSettings(MQTTClient*) const;
  849. -   bool isMqttValid();
  850. +   bool isMqttValid();    
  851.  
  852.  signals:
  853. -   void newTopic(QString);
  854. +    void newTopic(const QString&);
  855.     void subscriptionsChanged();
  856.     void checkFileType();
  857. +    void updateSubscriptionTree(const QVector<QString>&);
  858. +    void MQTTClearTopics();
  859.  
  860.  private slots:
  861.     void mqttConnectionChanged();
  862. -   void onMqttConnect();
  863. -   void mqttAvailableTopicDoubleClicked(QTreeWidgetItem*, int);
  864. -   void mqttSubscribedTopicDoubleClicked(QTreeWidgetItem*, int);
  865. -   void mqttSubscribe();
  866. -   void mqttUnsubscribe();
  867. -   void mqttMessageReceived(const QByteArray&, const QMqttTopicName&);
  868. -   void setTopicCompleter(const QString&);
  869. -   void topicTimeout();
  870. +    void onMqttConnect();
  871. +    void mqttSubscribe(const QString&, uint);
  872. +    void mqttMessageReceived(const QByteArray&, const QMqttTopicName&);
  873.     void mqttSubscriptionMessageReceived(const QMqttMessage& );
  874.     void onMqttDisconnect();
  875. -   void mqttErrorChanged(QMqttClient::ClientError);
  876. -   void scrollToTopicTreeItem(const QString&);
  877. -   void scrollToSubsriptionTreeItem(const QString&);
  878. +    void mqttErrorChanged(QMqttClient::ClientError);
  879.     void mqttConnectTimeout();
  880.     void showMQTTConnectionManager();
  881.     void readMQTTConnections();
  882.     void showWillSettings();
  883. +    void enableWill(bool);
  884.  #endif
  885.  };
  886.  
  887. diff --git a/src/kdefrontend/dockwidgets/LiveDataDock.cpp b/src/kdefrontend/dockwidgets/LiveDataDock.cpp
  888. index 482757467..4787cdc56 100644
  889. --- a/src/kdefrontend/dockwidgets/LiveDataDock.cpp
  890. +++ b/src/kdefrontend/dockwidgets/LiveDataDock.cpp
  891. @@ -4,7 +4,7 @@ Project              : LabPlot
  892.  Description          : Dock widget for live data properties
  893.  --------------------------------------------------------------------
  894.  Copyright            : (C) 2017 by Fabian Kristof (fkristofszabolcs@gmail.com)
  895. -Copyright            : (C) 2018 by Kovacs Ferencz (kferike98@gmail.com)
  896. +Copyright            : (C) 2018-2019 Kovacs Ferencz (kferike98@gmail.com)
  897.  Copyright            : (C) 2018 by Stefan Gerlach (stefan.gerlach@uni.kn)
  898.  ***************************************************************************/
  899.  
  900. @@ -37,6 +37,7 @@ Copyright            : (C) 2018 by Stefan Gerlach (stefan.gerlach@uni.kn)
  901.  #ifdef HAVE_MQTT
  902.  #include "kdefrontend/widgets/MQTTWillSettingsWidget.h"
  903.  #include "kdefrontend/datasources/MQTTHelpers.h"
  904. +#include "kdefrontend/datasources/MQTTSubscriptionWidget.h"
  905.  #include <QMessageBox>
  906.  #include <QWidgetAction>
  907.  #include <QMenu>
  908. @@ -44,8 +45,8 @@ Copyright            : (C) 2018 by Stefan Gerlach (stefan.gerlach@uni.kn)
  909.  
  910.  LiveDataDock::LiveDataDock(QWidget* parent) : QWidget(parent)
  911.  #ifdef HAVE_MQTT
  912. -   ,
  913. -   m_searchTimer(new QTimer(this))
  914. +    ,
  915. +    m_subscriptionWidget(new MQTTSubscriptionWidget(this))
  916.  #endif
  917.  {
  918.     ui.setupUi(this);
  919. @@ -63,55 +64,30 @@ LiveDataDock::LiveDataDock(QWidget* parent) : QWidget(parent)
  920.     connect(ui.cbReadingType, static_cast<void (QComboBox::*) (int)>(&QComboBox::currentIndexChanged), this, &LiveDataDock::readingTypeChanged);
  921.  
  922.  #ifdef HAVE_MQTT
  923. -   m_searchTimer->setInterval(10000);
  924. -
  925. -   const int size = ui.leTopics->height();
  926. -   ui.lTopicSearch->setPixmap( QIcon::fromTheme(QLatin1String("go-next")).pixmap(size, size) );
  927. -   ui.lSubscriptionSearch->setPixmap( QIcon::fromTheme(QLatin1String("go-next")).pixmap(size, size) );
  928. -
  929. -   connect(this, &LiveDataDock::newTopic, this, &LiveDataDock::setTopicCompleter);
  930. -   connect(m_searchTimer, &QTimer::timeout, this, &LiveDataDock::topicTimeout);
  931. -   connect(ui.bSubscribe, &QPushButton::clicked, this, &LiveDataDock::addSubscription);
  932. -   connect(ui.bUnsubscribe, &QPushButton::clicked, this, &LiveDataDock::removeSubscription);
  933. -   connect(ui.bWillUpdateNow, &QPushButton::clicked, this, &LiveDataDock::willUpdateNow);
  934. -   connect(ui.leTopics, &QLineEdit::textChanged, this, &LiveDataDock::scrollToTopicTreeItem);
  935. -   connect(ui.leSubscriptions, &QLineEdit::textChanged, this, &LiveDataDock::scrollToSubsriptionTreeItem);
  936. -   connect(ui.bLWT, &QPushButton::clicked, this, &LiveDataDock::showWillSettings);
  937. -
  938. -   ui.bSubscribe->setIcon(ui.bSubscribe->style()->standardIcon(QStyle::SP_ArrowRight));
  939. -   ui.bSubscribe->setToolTip(i18n("Subscribe selected topics"));
  940. -   ui.bUnsubscribe->setIcon(ui.bUnsubscribe->style()->standardIcon(QStyle::SP_ArrowLeft));
  941. -   ui.bUnsubscribe->setToolTip(i18n("Unsubscribe selected topics"));
  942. +    connect(ui.bWillUpdateNow, &QPushButton::clicked, this, &LiveDataDock::willUpdateNow);
  943. +    connect(ui.bLWT, &QPushButton::clicked, this, &LiveDataDock::showWillSettings);
  944. +    connect(m_subscriptionWidget, &MQTTSubscriptionWidget::enableWill, this, &LiveDataDock::enableWill);
  945. +
  946. +    ui.swSubscriptions->addWidget(m_subscriptionWidget);
  947. +    ui.swSubscriptions->setCurrentWidget(m_subscriptionWidget);
  948. +
  949.     ui.bLWT->setToolTip(i18n("Manage MQTT connection's will settings"));
  950.     ui.bLWT->setIcon(ui.bLWT->style()->standardIcon(QStyle::SP_FileDialogDetailedView));
  951.  
  952. -   QString info = i18n("Enter the name of the topic to navigate to it.");
  953. -   ui.lTopicSearch->setToolTip(info);
  954. -   ui.leTopics->setToolTip(info);
  955. -   ui.lSubscriptionSearch->setToolTip(info);
  956. -   ui.leSubscriptions->setToolTip(info);
  957. -
  958. -   info = i18n("Specify the 'Last Will and Testament' message (LWT). At least one topic has to be subscribed.");
  959. +    QString info = i18n("Specify the 'Last Will and Testament' message (LWT). At least one topic has to be subscribed.");
  960.     ui.lLWT->setToolTip(info);
  961.     ui.bLWT->setToolTip(info);
  962.     ui.bLWT->setEnabled(false);
  963. -   ui.bLWT->setIcon(ui.bLWT->style()->standardIcon(QStyle::SP_FileDialogDetailedView));
  964. -
  965. -   info = i18n("Set the Quality of Service (QoS) for the subscription to define the guarantee of the message delivery:"
  966. -   "<ul>"
  967. -   "<li>0 - deliver at most once</li>"
  968. -   "<li>1 - deliver at least once</li>"
  969. -   "<li>2 - deliver exactly once</li>"
  970. -   "</ul>");
  971. -   ui.cbQoS->setToolTip(info);
  972. +    ui.bLWT->setIcon(ui.bLWT->style()->standardIcon(QStyle::SP_FileDialogDetailedView));
  973.  #endif
  974.  }
  975.  
  976.  #ifdef HAVE_MQTT
  977.  LiveDataDock::~LiveDataDock() {
  978. -   delete m_searchTimer;
  979.     for (auto & host : m_hosts)
  980.         delete host.client;
  981. +
  982. +    delete m_subscriptionWidget;
  983.  }
  984.  #else
  985.  LiveDataDock::~LiveDataDock() = default;
  986. @@ -169,15 +145,10 @@ void LiveDataDock::setMQTTClient(MQTTClient* const client) {
  987.     m_mqttClient = client; // updates may be applied from now on
  988.  
  989.     //show MQTT connected options
  990. -   ui.lTopics->show();
  991. -   ui.gbManageSubscriptions->show();
  992. -   ui.bSubscribe->show();
  993. -   ui.bUnsubscribe->show();
  994. -   ui.twTopics->show();
  995. -   ui.leTopics->show();
  996. -   ui.lTopicSearch->show();
  997. -   ui.twSubscriptions->show();
  998. -   ui.cbQoS->show();
  999. +    ui.lTopics->show();
  1000. +    ui.swSubscriptions->setVisible(true);
  1001. +    m_subscriptionWidget->setVisible(true);
  1002. +    m_subscriptionWidget->makeVisible(true);
  1003.     ui.lLWT->show();
  1004.     ui.bLWT->show();
  1005.  
  1006. @@ -194,6 +165,12 @@ void LiveDataDock::setMQTTClient(MQTTClient* const client) {
  1007.         connect(m_currentHost->client, &QMqttClient::connected, this, &LiveDataDock::onMQTTConnect);
  1008.         connect(m_currentHost->client, &QMqttClient::messageReceived, this, &LiveDataDock::mqttMessageReceived);
  1009.  
  1010. +        connect(m_subscriptionWidget, &MQTTSubscriptionWidget::reparentTopic, client, &MQTTClient::reparentTopic);
  1011. +        connect(m_subscriptionWidget, &MQTTSubscriptionWidget::addBeforeRemoveSubscription, client, &MQTTClient::addBeforeRemoveSubscription);
  1012. +        connect(m_subscriptionWidget, &MQTTSubscriptionWidget::removeMQTTSubscription, client, &MQTTClient::removeMQTTSubscription);
  1013. +        connect(m_subscriptionWidget, &MQTTSubscriptionWidget::makeSubscription, client, &MQTTClient::addMQTTSubscription);
  1014. +
  1015. +
  1016.         m_currentHost->client->setHostname(id.first);
  1017.         m_currentHost->client->setPort(id.second);
  1018.  
  1019. @@ -211,38 +188,50 @@ void LiveDataDock::setMQTTClient(MQTTClient* const client) {
  1020.         ++m_currentHost->count;
  1021.     }
  1022.  
  1023. -   if (m_previousMQTTClient == nullptr) {
  1024. -       connect(client, &MQTTClient::MQTTSubscribed, this, &LiveDataDock::fillSubscriptions);
  1025. +    if (m_previousMQTTClient == nullptr) {
  1026. +       m_updateSubscriptionConn = connect(client, &MQTTClient::MQTTSubscribed, [this]() {emit updateSubscriptionTree(m_mqttClient->MQTTSubscriptions());});
  1027.  
  1028.         //Fill the subscription tree(useful if the MQTTClient was loaded)
  1029.         QVector<QString> topics = client->topicNames();
  1030.         for (const auto& topic : topics) {
  1031.             addTopicToTree(topic);
  1032.         }
  1033. -       fillSubscriptions();
  1034. +        emit updateSubscriptionTree(m_mqttClient->MQTTSubscriptions());
  1035.     }
  1036.  
  1037.     //if the previous MQTTClient's host name was different from the current one we have to disconnect some slots
  1038.     //and clear the tree widgets
  1039. -   else if (m_previousMQTTClient->clientHostName() != client->clientHostName()) {
  1040. -       disconnect(m_previousMQTTClient, &MQTTClient::MQTTSubscribed, this, &LiveDataDock::fillSubscriptions);
  1041. +   else if (m_previousMQTTClient->clientHostName() != client->clientHostName()) {        
  1042. +        disconnect(m_updateSubscriptionConn);
  1043.         disconnect(m_previousHost->client, &QMqttClient::messageReceived, this, &LiveDataDock::mqttMessageReceived);
  1044.         connect(m_previousHost->client, &QMqttClient::messageReceived, this, &LiveDataDock::mqttMessageReceivedInBackground);
  1045.  
  1046.         disconnect(m_currentHost->client, &QMqttClient::messageReceived, this, &LiveDataDock::mqttMessageReceivedInBackground);
  1047.  
  1048. -       ui.twTopics->clear();
  1049. +        disconnect(m_subscriptionWidget, &MQTTSubscriptionWidget::reparentTopic, m_previousMQTTClient, &MQTTClient::reparentTopic);
  1050. +        disconnect(m_subscriptionWidget, &MQTTSubscriptionWidget::addBeforeRemoveSubscription, m_previousMQTTClient, &MQTTClient::addBeforeRemoveSubscription);
  1051. +        disconnect(m_subscriptionWidget, &MQTTSubscriptionWidget::removeMQTTSubscription, m_previousMQTTClient, &MQTTClient::removeMQTTSubscription);
  1052. +        disconnect(m_subscriptionWidget, &MQTTSubscriptionWidget::makeSubscription,  m_previousMQTTClient, &MQTTClient::addMQTTSubscription);
  1053. +
  1054. +        m_previousHost->topicList = m_subscriptionWidget->getTopicList();
  1055. +        m_subscriptionWidget->setTopicList(m_currentHost->topicList);
  1056. +
  1057. +        emit MQTTClearTopics();
  1058.         //repopulating the tree widget with the already known topics of the client
  1059.         for (int i = 0; i < m_currentHost->addedTopics.size(); ++i) {
  1060.             addTopicToTree(m_currentHost->addedTopics.at(i));
  1061.         }
  1062.  
  1063. -       //fill subscriptions tree widget
  1064. -       ui.twSubscriptions->clear();
  1065. -       fillSubscriptions();
  1066. +        //fill subscriptions tree widget
  1067. +        emit updateSubscriptionTree(m_mqttClient->MQTTSubscriptions());
  1068.  
  1069. -       connect(client, &MQTTClient::MQTTSubscribed, this, &LiveDataDock::fillSubscriptions);
  1070. +        m_updateSubscriptionConn = connect(client, &MQTTClient::MQTTSubscribed, [this]() {emit updateSubscriptionTree(m_mqttClient->MQTTSubscriptions());});
  1071.         connect(m_currentHost->client, &QMqttClient::messageReceived, this, &LiveDataDock::mqttMessageReceived);
  1072. +
  1073. +        connect(m_subscriptionWidget, &MQTTSubscriptionWidget::reparentTopic, client, &MQTTClient::reparentTopic);
  1074. +        connect(m_subscriptionWidget, &MQTTSubscriptionWidget::addBeforeRemoveSubscription, client, &MQTTClient::addBeforeRemoveSubscription);
  1075. +        connect(m_subscriptionWidget, &MQTTSubscriptionWidget::removeMQTTSubscription, client, &MQTTClient::removeMQTTSubscription);
  1076. +        connect(m_subscriptionWidget, &MQTTSubscriptionWidget::makeSubscription, client, &MQTTClient::addMQTTSubscription);
  1077.     }
  1078.  
  1079.     if (client->willUpdateType() == MQTTClient::OnClick && client->MQTTWillUse())
  1080. @@ -275,7 +264,7 @@ void LiveDataDock::setLiveDataSource(LiveDataSource* const source) {
  1081.  
  1082.     switch (sourceType) {
  1083.     case LiveDataSource::FileOrPipe:
  1084. -       ui.leSourceInfo->setText(source->fileName());
  1085. +        ui.leSourceInfo->setText(source->fileName());
  1086.         break;
  1087.     case LiveDataSource::NetworkTcpSocket:
  1088.     case LiveDataSource::NetworkUdpSocket:
  1089. @@ -345,14 +334,9 @@ void LiveDataDock::setLiveDataSource(LiveDataSource* const source) {
  1090.     ui.bLWT->hide();
  1091.     ui.lLWT->hide();
  1092.     ui.bWillUpdateNow->hide();
  1093. -   ui.bSubscribe->hide();
  1094. -   ui.bUnsubscribe->hide();
  1095. -   ui.twTopics->hide();
  1096. -   ui.leTopics->hide();
  1097. -   ui.lTopicSearch->hide();
  1098. -   ui.twSubscriptions->hide();
  1099. -   ui.gbManageSubscriptions->hide();
  1100. -
  1101. +    ui.swSubscriptions->setVisible(false);
  1102. +    m_subscriptionWidget->setVisible(false);
  1103. +    m_subscriptionWidget->makeVisible(false);
  1104.     m_liveDataSource = source; // updates may be applied from now on
  1105.  }
  1106.  
  1107. @@ -705,425 +689,6 @@ void LiveDataDock::mqttMessageReceived(const QByteArray& message, const QMqttTop
  1108.     }
  1109.  }
  1110.  
  1111. -/*!
  1112. - *\brief called when the subscribe button is pressed
  1113. - * subscribes to the topic represented by the current item of twTopics in every client from m_mqttClients
  1114. - */
  1115. -void LiveDataDock::addSubscription() {
  1116. -   QString name;
  1117. -   QTreeWidgetItem* item = ui.twTopics->currentItem();
  1118. -   if (item != nullptr) {
  1119. -       QTreeWidgetItem* tempItem = item;
  1120. -
  1121. -       //determine the topic name that the current item represents
  1122. -       name.prepend(item->text(0));
  1123. -       if (item->childCount() != 0)
  1124. -           name.append("/#");
  1125. -       while (tempItem->parent() != nullptr) {
  1126. -           tempItem = tempItem->parent();
  1127. -           name.prepend(tempItem->text(0) + '/');
  1128. -       }
  1129. -
  1130. -       //check if the subscription already exists
  1131. -       const QList<QTreeWidgetItem *> topLevelList = ui.twSubscriptions->findItems(name, Qt::MatchExactly);
  1132. -       if (topLevelList.isEmpty() || topLevelList.first()->parent() != nullptr) {
  1133. -           qDebug() << "LiveDataDock: start to add new subscription: " << name;
  1134. -           bool foundSuperior = false;
  1135. -
  1136. -           for (int i = 0; i < ui.twSubscriptions->topLevelItemCount(); ++i) {
  1137. -               //if the new subscriptions contains an already existing one, we remove the inferior one
  1138. -               if (MQTTHelpers::checkTopicContains(name, ui.twSubscriptions->topLevelItem(i)->text(0))
  1139. -                       && name != ui.twSubscriptions->topLevelItem(i)->text(0)) {
  1140. -                   ui.twSubscriptions->topLevelItem(i)->takeChildren();
  1141. -                   ui.twSubscriptions->takeTopLevelItem(i);
  1142. -                   --i;
  1143. -                   continue;
  1144. -               }
  1145. -
  1146. -               //if there is a subscription containing the new one we set foundSuperior true
  1147. -               if (MQTTHelpers::checkTopicContains(ui.twSubscriptions->topLevelItem(i)->text(0), name)
  1148. -                       && name != ui.twSubscriptions->topLevelItem(i)->text(0)) {
  1149. -                   foundSuperior = true;
  1150. -                   qDebug()<<"Can't add "<<name<<" because found superior: "<< ui.twSubscriptions->topLevelItem(i)->text(0);
  1151. -                   break;
  1152. -               }
  1153. -           }
  1154. -
  1155. -           //if there wasn't a superior subscription we can subscribe to the new topic
  1156. -           if (!foundSuperior) {
  1157. -               QStringList toplevelName;
  1158. -               toplevelName.push_back(name);
  1159. -               QTreeWidgetItem* newTopLevelItem = new QTreeWidgetItem(toplevelName);
  1160. -               ui.twSubscriptions->addTopLevelItem(newTopLevelItem);
  1161. -
  1162. -               if (name.endsWith('#')) {
  1163. -                   //adding every topic that the subscription contains to twSubscriptions
  1164. -                   MQTTHelpers::addSubscriptionChildren(item, newTopLevelItem);
  1165. -               }
  1166. -
  1167. -               m_mqttClient->addMQTTSubscription(name, ui.cbQoS->currentIndex());
  1168. -
  1169. -               if (name.endsWith('#')) {
  1170. -                   //if an already existing subscription contains a topic that the new subscription also contains
  1171. -                   //we decompose the already existing subscription
  1172. -                   //by unsubscribing from its topics, that are present in the new subscription as well
  1173. -                   const QStringList& nameList = name.split('/', QString::SkipEmptyParts);
  1174. -                   const QString root = nameList.first();
  1175. -                   QVector<QTreeWidgetItem*> children;
  1176. -                   for (int i = 0; i < ui.twSubscriptions->topLevelItemCount(); ++i) {
  1177. -                       if (ui.twSubscriptions->topLevelItem(i)->text(0).startsWith(root)
  1178. -                               && name != ui.twSubscriptions->topLevelItem(i)->text(0)) {
  1179. -                           children.clear();
  1180. -
  1181. -                           //get the "leaf" children of the inspected subscription
  1182. -                           MQTTHelpers::findSubscriptionLeafChildren(children, ui.twSubscriptions->topLevelItem(i));
  1183. -                           for (int j = 0; j < children.size(); ++j) {
  1184. -                               if (MQTTHelpers::checkTopicContains(name, children[j]->text(0))) {
  1185. -                                   //if the new subscription contains a topic, we unsubscribe from it
  1186. -                                   QTreeWidgetItem* unsubscribeItem = children[j];
  1187. -                                   while (unsubscribeItem->parent() != nullptr) {
  1188. -                                       for (int i = 0; i < unsubscribeItem->parent()->childCount(); ++i) {
  1189. -
  1190. -                                           if (unsubscribeItem->text(0) != unsubscribeItem->parent()->child(i)->text(0)) {
  1191. -                                               //add topic as subscription
  1192. -                                               m_mqttClient->addBeforeRemoveSubscription(unsubscribeItem->parent()->child(i)->text(0), ui.cbQoS->currentIndex());
  1193. -                                               //also add it to twSubscriptions
  1194. -                                               ui.twSubscriptions->addTopLevelItem(unsubscribeItem->parent()->takeChild(i));
  1195. -                                               --i;
  1196. -                                           } else {
  1197. -                                               //before we remove the topic, we reparent it to the new subscription
  1198. -                                               //so no data is lost
  1199. -                                               m_mqttClient->reparentTopic(unsubscribeItem->text(0), name);
  1200. -                                           }
  1201. -                                       }
  1202. -                                       unsubscribeItem = unsubscribeItem->parent();
  1203. -                                   }
  1204. -
  1205. -                                   qDebug()<<"Remove: "<<unsubscribeItem->text(0);
  1206. -                                   m_mqttClient->removeMQTTSubscription(unsubscribeItem->text(0));
  1207. -
  1208. -                                   ui.twSubscriptions->takeTopLevelItem(ui.twSubscriptions->indexOfTopLevelItem(unsubscribeItem));
  1209. -                               }
  1210. -                           }
  1211. -                       }
  1212. -                   }
  1213. -               }
  1214. -
  1215. -               manageCommonLevelSubscriptions();
  1216. -               updateSubscriptionCompleter();
  1217. -
  1218. -               if (!ui.bLWT->isEnabled())
  1219. -                   ui.bLWT->setEnabled(true);
  1220. -           } else {
  1221. -               QMessageBox::warning(this, "Warning", "You already subscribed to a topic containing this one");
  1222. -           }
  1223. -       }
  1224. -       else
  1225. -           QMessageBox::warning(this, "Warning", "You already subscribed to this topic");
  1226. -   }
  1227. -   else
  1228. -       QMessageBox::warning(this, "Warning", "You didn't select any item from the Tree Widget");
  1229. -}
  1230. -
  1231. -/*!
  1232. - *\brief called when the unsubscribe button is pressed
  1233. - * unsubscribes from the topic represented by the current item of twSubscription in m_mqttClient
  1234. - */
  1235. -void LiveDataDock::removeSubscription() {
  1236. -   QTreeWidgetItem* unsubscribeItem = ui.twSubscriptions->currentItem();
  1237. -
  1238. -   if (unsubscribeItem != nullptr) {
  1239. -       qDebug() << "LiveDataDock: unsubscribe from " << unsubscribeItem->text(0);
  1240. -
  1241. -       //if it is a top level item, meaning a topic that we really subscribed to(not one that belongs to a subscription)
  1242. -       //we can simply unsubscribe from it
  1243. -       if (unsubscribeItem->parent() == nullptr) {
  1244. -           m_mqttClient->removeMQTTSubscription(unsubscribeItem->text(0));
  1245. -           ui.twSubscriptions->takeTopLevelItem(ui.twSubscriptions->indexOfTopLevelItem(unsubscribeItem));
  1246. -       }
  1247. -       //otherwise we remove the selected item, but subscribe to every other topic, that was contained by
  1248. -       //the selected item's parent subscription(top level item of twSubscriptions)
  1249. -       else {
  1250. -           while (unsubscribeItem->parent() != nullptr) {
  1251. -               for (int i = 0; i < unsubscribeItem->parent()->childCount(); ++i) {
  1252. -                   if (unsubscribeItem->text(0) != unsubscribeItem->parent()->child(i)->text(0)) {
  1253. -                       //add topic as subscription
  1254. -                       m_mqttClient->addBeforeRemoveSubscription(unsubscribeItem->parent()->child(i)->text(0), ui.cbQoS->currentIndex());
  1255. -                       ui.twSubscriptions->addTopLevelItem(unsubscribeItem->parent()->takeChild(i));
  1256. -                       --i;
  1257. -                   }
  1258. -               }
  1259. -               unsubscribeItem = unsubscribeItem->parent();
  1260. -           }
  1261. -
  1262. -           //remove topic/subscription
  1263. -           m_mqttClient->removeMQTTSubscription(unsubscribeItem->text(0));
  1264. -           ui.twSubscriptions->takeTopLevelItem(ui.twSubscriptions->indexOfTopLevelItem(unsubscribeItem));
  1265. -
  1266. -           //check if any common topics were subscribed, if possible merge them
  1267. -           manageCommonLevelSubscriptions();
  1268. -       }
  1269. -
  1270. -       if (ui.twSubscriptions->topLevelItemCount() <= 0)
  1271. -           ui.bLWT->setEnabled(false);
  1272. -
  1273. -       updateSubscriptionCompleter();
  1274. -   } else
  1275. -       QMessageBox::warning(this, "Warning", "You didn't select any item from the Tree Widget");
  1276. -}
  1277. -
  1278. -/*!
  1279. - *\brief called when a new topic is added to the tree(twTopics)
  1280. - * appends the topic's root to the topicList if it isn't in the list already
  1281. - * then sets the completer for leTopics
  1282. - */
  1283. -void LiveDataDock::setTopicCompleter(const QString& topicName) {
  1284. -   if (!m_searching) {
  1285. -       const QStringList& list = topicName.split('/', QString::SkipEmptyParts);
  1286. -       QString topic;
  1287. -       if (!list.isEmpty()) {
  1288. -           topic = list.at(0);
  1289. -       } else
  1290. -           topic = topicName;
  1291. -
  1292. -       if (!m_currentHost->topicList.contains(topic)) {
  1293. -           m_currentHost->topicList.append(topic);
  1294. -           m_topicCompleter = new QCompleter(m_currentHost->topicList, this);
  1295. -           m_topicCompleter->setCompletionMode(QCompleter::PopupCompletion);
  1296. -           m_topicCompleter->setCaseSensitivity(Qt::CaseSensitive);
  1297. -           ui.leTopics->setCompleter(m_topicCompleter);
  1298. -       }
  1299. -   }
  1300. -}
  1301. -
  1302. -/*!
  1303. - *\brief Updates the completer for leSubscriptions
  1304. - */
  1305. -void LiveDataDock::updateSubscriptionCompleter() {
  1306. -   QStringList subscriptionList;
  1307. -   const QVector<QString>& subscriptions = m_mqttClient->MQTTSubscriptions();
  1308. -
  1309. -   if (!subscriptions.isEmpty()) {
  1310. -       for (const auto& subscription : subscriptions)
  1311. -           subscriptionList << subscription;
  1312. -
  1313. -       m_subscriptionCompleter = new QCompleter(subscriptionList, this);
  1314. -       m_subscriptionCompleter->setCompletionMode(QCompleter::PopupCompletion);
  1315. -       m_subscriptionCompleter->setCaseSensitivity(Qt::CaseSensitive);
  1316. -       ui.leSubscriptions->setCompleter(m_subscriptionCompleter);
  1317. -   } else {
  1318. -       ui.leSubscriptions->setCompleter(nullptr);
  1319. -   }
  1320. -}
  1321. -
  1322. -/*!
  1323. - *\brief called when 10 seconds passed since the last time the user searched for a certain root in twTopics
  1324. - * enables updating the completer for le
  1325. - */
  1326. -void LiveDataDock::topicTimeout() {
  1327. -   m_searching = false;
  1328. -   m_searchTimer->stop();
  1329. -}
  1330. -
  1331. -/*!
  1332. - *\brief called when a new the host name of m_mqttClient changes
  1333. - * or when the MQTTClients initialize their subscriptions
  1334. - * Fills twSubscriptions with the subscriptions of the MQTTClient
  1335. - */
  1336. -void LiveDataDock::fillSubscriptions() {
  1337. -   ui.twSubscriptions->clear();
  1338. -
  1339. -   QVector<QString> subscriptions = m_mqttClient->MQTTSubscriptions();
  1340. -   for (int i = 0; i < subscriptions.count(); ++i) {
  1341. -       QStringList name;
  1342. -       name.append(subscriptions[i]);
  1343. -
  1344. -       bool found = false;
  1345. -       for (int j = 0; j < ui.twSubscriptions->topLevelItemCount(); ++j) {
  1346. -           if (ui.twSubscriptions->topLevelItem(j)->text(0) == subscriptions[i]) {
  1347. -               found = true;
  1348. -               break;
  1349. -           }
  1350. -       }
  1351. -
  1352. -       if (!found) {
  1353. -           //Add the subscription to the tree widget
  1354. -           QTreeWidgetItem* newItem = new QTreeWidgetItem(name);
  1355. -           ui.twSubscriptions->addTopLevelItem(newItem);
  1356. -           name.clear();
  1357. -           name = subscriptions[i].split('/', QString::SkipEmptyParts);
  1358. -
  1359. -           //find the corresponding "root" item in twTopics
  1360. -           QTreeWidgetItem* topic = nullptr;
  1361. -           for (int j = 0; j < ui.twTopics->topLevelItemCount(); ++j) {
  1362. -               if (ui.twTopics->topLevelItem(j)->text(0) == name[0]) {
  1363. -                   topic = ui.twTopics->topLevelItem(j);
  1364. -                   break;
  1365. -               }
  1366. -           }
  1367. -
  1368. -           //restore the children of the subscription
  1369. -           if (topic != nullptr && topic->childCount() > 0)
  1370. -               MQTTHelpers::restoreSubscriptionChildren(topic, newItem, name, 1);
  1371. -       }
  1372. -   }
  1373. -   m_searching = false;
  1374. -}
  1375. -
  1376. -/*!
  1377. - *\brief called when leTopics' text is changed
  1378. - *      if the rootName can be found in twTopics, then we scroll it to the top of the tree widget
  1379. - *
  1380. - * \param rootName the current text of leTopics
  1381. - */
  1382. -void LiveDataDock::scrollToTopicTreeItem(const QString& rootName) {
  1383. -   m_searching = true;
  1384. -   m_searchTimer->start();
  1385. -
  1386. -   int topItemIdx = -1;
  1387. -   for (int i = 0; i < ui.twTopics->topLevelItemCount(); ++i)
  1388. -       if (ui.twTopics->topLevelItem(i)->text(0) == rootName) {
  1389. -           topItemIdx = i;
  1390. -           break;
  1391. -       }
  1392. -
  1393. -   if (topItemIdx >= 0)
  1394. -       ui.twTopics->scrollToItem(ui.twTopics->topLevelItem(topItemIdx), QAbstractItemView::ScrollHint::PositionAtTop);
  1395. -}
  1396. -
  1397. -/*!
  1398. - *\brief called when leSubscriptions' text is changed
  1399. - *      if the rootName can be found in twSubscriptions, then we scroll it to the top of the tree widget
  1400. - *
  1401. - * \param rootName the current text of leSubscriptions
  1402. - */
  1403. -void LiveDataDock::scrollToSubsriptionTreeItem(const QString& rootName) {
  1404. -   int topItemIdx = -1;
  1405. -   for (int i = 0; i < ui.twSubscriptions->topLevelItemCount(); ++i)
  1406. -       if (ui.twSubscriptions->topLevelItem(i)->text(0) == rootName) {
  1407. -           topItemIdx = i;
  1408. -           break;
  1409. -       }
  1410. -
  1411. -   if (topItemIdx >= 0)
  1412. -       ui.twSubscriptions->scrollToItem(ui.twSubscriptions->topLevelItem(topItemIdx), QAbstractItemView::ScrollHint::PositionAtTop);
  1413. -}
  1414. -
  1415. -/*!
  1416. - *\brief We search in twSubscriptions for topics that can be represented using + wildcards, then merge them.
  1417. - *      We do this until there are no topics to merge
  1418. - */
  1419. -void LiveDataDock::manageCommonLevelSubscriptions() {
  1420. -   bool foundEqual = false;
  1421. -   do {
  1422. -       foundEqual = false;
  1423. -       QMap<QString, QVector<QString>> equalTopicsMap;
  1424. -       QVector<QString> equalTopics;
  1425. -
  1426. -       //compare the subscriptions present in the TreeWidget
  1427. -       for (int i = 0; i < ui.twSubscriptions->topLevelItemCount() - 1; ++i) {
  1428. -           for (int j = i + 1; j < ui.twSubscriptions->topLevelItemCount(); ++j) {
  1429. -               QString commonTopic = MQTTHelpers::checkCommonLevel(ui.twSubscriptions->topLevelItem(i)->text(0), ui.twSubscriptions->topLevelItem(j)->text(0));
  1430. -
  1431. -               //if there is a common topic for the 2 compared topics, we add them to the map (using the common topic as key)
  1432. -               if (!commonTopic.isEmpty()) {
  1433. -                   if (!equalTopicsMap[commonTopic].contains(ui.twSubscriptions->topLevelItem(i)->text(0))) {
  1434. -                       equalTopicsMap[commonTopic].push_back(ui.twSubscriptions->topLevelItem(i)->text(0));
  1435. -                   }
  1436. -
  1437. -                   if (!equalTopicsMap[commonTopic].contains(ui.twSubscriptions->topLevelItem(j)->text(0))) {
  1438. -                       equalTopicsMap[commonTopic].push_back(ui.twSubscriptions->topLevelItem(j)->text(0));
  1439. -                   }
  1440. -               }
  1441. -           }
  1442. -       }
  1443. -
  1444. -       if (!equalTopicsMap.isEmpty()) {
  1445. -           qDebug()<<"Manage equal topics";
  1446. -
  1447. -           QVector<QString> commonTopics;
  1448. -           QMapIterator<QString, QVector<QString>> topics(equalTopicsMap);
  1449. -
  1450. -           //check for every map entry, if the found topics can be merged or not
  1451. -           while (topics.hasNext()) {
  1452. -               topics.next();
  1453. -
  1454. -               int level = MQTTHelpers::commonLevelIndex(topics.value().last(), topics.value().first());
  1455. -               QStringList commonList = topics.value().first().split('/', QString::SkipEmptyParts);
  1456. -               QTreeWidgetItem* currentItem = nullptr;
  1457. -
  1458. -               //search the corresponding item to the common topics first level(root)
  1459. -               for (int i = 0; i < ui.twTopics->topLevelItemCount(); ++i) {
  1460. -                   if (ui.twTopics->topLevelItem(i)->text(0) == commonList.first()) {
  1461. -                       currentItem = ui.twTopics->topLevelItem(i);
  1462. -                       break;
  1463. -                   }
  1464. -               }
  1465. -
  1466. -               if (!currentItem)
  1467. -                   break;
  1468. -
  1469. -               //calculate the number of topics the new + wildcard could replace
  1470. -               int childCount = MQTTHelpers::checkCommonChildCount(1, level, commonList, currentItem);
  1471. -               if (childCount > 0) {
  1472. -                   //if the number of topics found and the calculated number of topics is equal, the topics can be merged
  1473. -                   if (topics.value().size() == childCount) {
  1474. -                       qDebug() << "Found common topic to manage: " << topics.key();
  1475. -                       foundEqual = true;
  1476. -                       commonTopics.push_back(topics.key());
  1477. -                   }
  1478. -               }
  1479. -           }
  1480. -
  1481. -           if (foundEqual) {
  1482. -               //if there are more common topics, the topics of which can be merged, we choose the one which has the lowest level new "+" wildcard
  1483. -               int highestLevel = INT_MAX;
  1484. -               int topicIdx = -1;
  1485. -               for (int i = 0; i < commonTopics.size(); ++i) {
  1486. -                   int level = MQTTHelpers::commonLevelIndex(equalTopicsMap[commonTopics[i]].first(), commonTopics[i]);
  1487. -                   if (level < highestLevel) {
  1488. -                       topicIdx = i;
  1489. -                       highestLevel = level;
  1490. -                   }
  1491. -               }
  1492. -               qDebug() << "Start to manage: " << commonTopics[topicIdx];
  1493. -               equalTopics.append(equalTopicsMap[commonTopics[topicIdx]]);
  1494. -
  1495. -               //Add the common topic ("merging")
  1496. -               QString commonTopic;
  1497. -               commonTopic = MQTTHelpers::checkCommonLevel(equalTopics.first(), equalTopics.last());
  1498. -               QStringList nameList;
  1499. -               nameList.append(commonTopic);
  1500. -               QTreeWidgetItem* newTopic = new QTreeWidgetItem(nameList);
  1501. -               ui.twSubscriptions->addTopLevelItem(newTopic);
  1502. -
  1503. -               //remove the "merged" topics
  1504. -               for (int i = 0; i < equalTopics.size(); ++i) {
  1505. -                   for (int j = 0; j < ui.twSubscriptions->topLevelItemCount(); ++j) {
  1506. -                       if (ui.twSubscriptions->topLevelItem(j)->text(0) == equalTopics[i]) {
  1507. -                           newTopic->addChild(ui.twSubscriptions->takeTopLevelItem(j));
  1508. -                           break;
  1509. -                       }
  1510. -                   }
  1511. -               }
  1512. -
  1513. -               //remove any subscription that the new subscription contains
  1514. -               for (int i = 0; i < ui.twSubscriptions->topLevelItemCount(); ++i) {
  1515. -                   if (MQTTHelpers::checkTopicContains(commonTopic, ui.twSubscriptions->topLevelItem(i)->text(0)) &&
  1516. -                           commonTopic != ui.twSubscriptions->topLevelItem(i)->text(0) ) {
  1517. -                       ui.twSubscriptions->topLevelItem(i)->takeChildren();
  1518. -                       ui.twSubscriptions->takeTopLevelItem(i);
  1519. -                       i--;
  1520. -                   }
  1521. -               }
  1522. -
  1523. -               //make the subscription on commonTopic in m_mqttClient
  1524. -               m_mqttClient->addMQTTSubscription(commonTopic, ui.cbQoS->currentIndex());
  1525. -           }
  1526. -       }
  1527. -   } while (foundEqual);
  1528. -}
  1529. -
  1530.  /*!
  1531.   *\brief Adds topicName to twTopics
  1532.   *
  1533. @@ -1142,8 +707,8 @@ void LiveDataDock::addTopicToTree(const QString &topicName) {
  1534.             QTreeWidgetItem* currentItem;
  1535.             //check whether the first level of the topic can be found in twTopics
  1536.             int topItemIdx = -1;
  1537. -           for (int i = 0; i < ui.twTopics->topLevelItemCount(); ++i) {
  1538. -               if (ui.twTopics->topLevelItem(i)->text(0) == list.at(0)) {
  1539. +            for (int i = 0; i < m_subscriptionWidget->topicCount(); ++i) {
  1540. +                if (m_subscriptionWidget->topLevelTopic(i)->text(0) == list.at(0)) {
  1541.                     topItemIdx = i;
  1542.                     break;
  1543.                 }
  1544. @@ -1151,7 +716,7 @@ void LiveDataDock::addTopicToTree(const QString &topicName) {
  1545.             //if not we simply add every level of the topic to the tree
  1546.             if ( topItemIdx < 0) {
  1547.                 currentItem = new QTreeWidgetItem(name);
  1548. -               ui.twTopics->addTopLevelItem(currentItem);
  1549. +                m_subscriptionWidget->addTopic(currentItem);
  1550.                 for (int i = 1; i < list.size(); ++i) {
  1551.                     name.clear();
  1552.                     name.append(list.at(i));
  1553. @@ -1162,7 +727,7 @@ void LiveDataDock::addTopicToTree(const QString &topicName) {
  1554.             //otherwise we search for the first level that isn't part of the tree,
  1555.             //then add every level of the topic to the tree from that certain level
  1556.             else {
  1557. -               currentItem = ui.twTopics->topLevelItem(topItemIdx);
  1558. +                currentItem = m_subscriptionWidget->topLevelTopic(topItemIdx);
  1559.                 int listIdx = 1;
  1560.                 for (; listIdx < list.size(); ++listIdx) {
  1561.                     QTreeWidgetItem* childItem = nullptr;
  1562. @@ -1194,14 +759,14 @@ void LiveDataDock::addTopicToTree(const QString &topicName) {
  1563.     else {
  1564.         rootName = topicName;
  1565.         name.append(topicName);
  1566. -       ui.twTopics->addTopLevelItem(new QTreeWidgetItem(name));
  1567. +        m_subscriptionWidget->addTopic(new QTreeWidgetItem(name));
  1568.     }
  1569.  
  1570.     //if a subscribed topic contains the new topic, we have to update twSubscriptions
  1571. -   for (int i = 0; i < ui.twSubscriptions->topLevelItemCount(); ++i) {
  1572. -       QStringList subscriptionName = ui.twSubscriptions->topLevelItem(i)->text(0).split('/', QString::SkipEmptyParts);
  1573. +    for (int i = 0; i < m_subscriptionWidget->subscriptionCount(); ++i) {
  1574. +        QStringList subscriptionName = m_subscriptionWidget->topLevelSubscription(i)->text(0).split('/', QString::SkipEmptyParts);
  1575.         if (rootName == subscriptionName[0]) {
  1576. -           fillSubscriptions();
  1577. +            emit updateSubscriptionTree(m_mqttClient->MQTTSubscriptions());
  1578.             break;
  1579.         }
  1580.     }
  1581. @@ -1248,8 +813,7 @@ void LiveDataDock::removeClient(const QString& hostname, quint16 port) {
  1582.     }
  1583.  
  1584.     if (m_mqttClient->clientHostName() == hostname) {
  1585. -       ui.twSubscriptions->clear();
  1586. -       ui.twTopics->clear();
  1587. +        emit MQTTClearTopics();
  1588.         m_mqttClient = nullptr;
  1589.     }
  1590.  
  1591. @@ -1264,9 +828,9 @@ void LiveDataDock::removeClient(const QString& hostname, quint16 port) {
  1592.  bool LiveDataDock::testSubscribe(const QString& topic) {
  1593.     QStringList topicList = topic.split('/', QString::SkipEmptyParts);
  1594.     QTreeWidgetItem* currentItem = nullptr;
  1595. -   for (int i = 0; i < ui.twTopics->topLevelItemCount(); ++i) {
  1596. -       if (ui.twTopics->topLevelItem(i)->text(0) == topicList[0]) {
  1597. -           currentItem = ui.twTopics->topLevelItem(i);
  1598. +    for (int i = 0; i < m_subscriptionWidget->topicCount(); ++i) {
  1599. +        if (m_subscriptionWidget->topLevelTopic(i)->text(0) == topicList[0]) {
  1600. +            currentItem = m_subscriptionWidget->topLevelTopic(i);
  1601.             break;
  1602.         }
  1603.     }
  1604. @@ -1288,8 +852,7 @@ bool LiveDataDock::testSubscribe(const QString& topic) {
  1605.     } else
  1606.         return false;
  1607.  
  1608. -   ui.twTopics->setCurrentItem(currentItem);
  1609. -   addSubscription();
  1610. +    m_subscriptionWidget->testSubscribe(currentItem);
  1611.     return true;
  1612.  }
  1613.  
  1614. @@ -1299,9 +862,9 @@ bool LiveDataDock::testSubscribe(const QString& topic) {
  1615.   */
  1616.  bool LiveDataDock::testUnsubscribe(const QString& topic) {
  1617.     QTreeWidgetItem* currentItem = nullptr;
  1618. -   for (int i = 0; i < ui.twSubscriptions->topLevelItemCount(); ++i) {
  1619. -       if (MQTTHelpers::checkTopicContains(ui.twSubscriptions->topLevelItem(i)->text(0), topic)) {
  1620. -           currentItem = ui.twSubscriptions->topLevelItem(i);
  1621. +    for (int i = 0; i < m_subscriptionWidget->subscriptionCount(); ++i) {
  1622. +        if (MQTTHelpers::checkTopicContains(m_subscriptionWidget->topLevelSubscription(i)->text(0), topic)) {
  1623. +            currentItem = m_subscriptionWidget->topLevelSubscription(i);
  1624.             break;
  1625.         }
  1626.     }
  1627. @@ -1309,8 +872,7 @@ bool LiveDataDock::testUnsubscribe(const QString& topic) {
  1628.     if (currentItem) {
  1629.         do {
  1630.             if (topic == currentItem->text(0)) {
  1631. -               ui.twSubscriptions->setCurrentItem(currentItem);
  1632. -               removeSubscription();
  1633. +                 m_subscriptionWidget->testUnsubscribe(currentItem);
  1634.                 return true;
  1635.             } else {
  1636.                 for (int i = 0; i < currentItem->childCount(); ++i) {
  1637. @@ -1354,4 +916,13 @@ void LiveDataDock::showWillSettings() {
  1638.     QPoint pos(ui.bLWT->sizeHint().width(), ui.bLWT->sizeHint().height());
  1639.     menu.exec(ui.bLWT->mapToGlobal(pos));
  1640.  }
  1641. +
  1642. +void LiveDataDock::enableWill(bool enable) {
  1643. +    if(enable) {
  1644. +        if(!ui.bLWT->isEnabled())
  1645. +            ui.bLWT->setEnabled(enable);
  1646. +    } else {
  1647. +        ui.bLWT->setEnabled(enable);
  1648. +    }
  1649. +}
  1650.  #endif
  1651. diff --git a/src/kdefrontend/dockwidgets/LiveDataDock.h b/src/kdefrontend/dockwidgets/LiveDataDock.h
  1652. index c26843f69..7d580e9d2 100644
  1653. --- a/src/kdefrontend/dockwidgets/LiveDataDock.h
  1654. +++ b/src/kdefrontend/dockwidgets/LiveDataDock.h
  1655. @@ -4,6 +4,7 @@ Project              : LabPlot
  1656.  Description          : Dock widget for live data properties
  1657.  --------------------------------------------------------------------
  1658.  Copyright            : (C) 2017 by Fabian Kristof (fkristofszabolcs@gmail.com)
  1659. +Copyright            : (C) 2018-2019 Kovacs Ferencz (kferike98@gmail.com)
  1660.  ***************************************************************************/
  1661.  
  1662.  /***************************************************************************
  1663. @@ -33,6 +34,8 @@ Copyright            : (C) 2017 by Fabian Kristof (fkristofszabolcs@gmail.com)
  1664.  #include <QMap>
  1665.  #include "backend/datasources/filters/AsciiFilter.h"
  1666.  #include "backend/datasources/MQTTClient.h"
  1667. +
  1668. +class MQTTSubscriptionWidget;
  1669.  #endif
  1670.  
  1671.  #include <QWidget>
  1672. @@ -90,27 +93,21 @@ private slots:
  1673.     void willUpdateTypeChanged(int);
  1674.     void willUpdateNow();
  1675.     void willUpdateIntervalChanged(int);
  1676. -   void statisticsChanged(MQTTClient::WillStatisticsType);
  1677. -   void addSubscription();
  1678. -   void removeSubscription();
  1679. +    void statisticsChanged(MQTTClient::WillStatisticsType);
  1680.     void onMQTTConnect();
  1681.     void mqttMessageReceived(const QByteArray&, const QMqttTopicName&);
  1682. -   void mqttMessageReceivedInBackground(const QByteArray&, const QMqttTopicName&);
  1683. -   void setTopicCompleter(const QString&);
  1684. -   void topicTimeout();
  1685. -   void fillSubscriptions();
  1686. -   void scrollToTopicTreeItem(const QString&);
  1687. -   void scrollToSubsriptionTreeItem(const QString&);
  1688. +    void mqttMessageReceivedInBackground(const QByteArray&, const QMqttTopicName&);
  1689.     void removeClient(const QString&, quint16);
  1690.     void showWillSettings();
  1691. +    void enableWill(bool enable);
  1692.  
  1693.  signals:
  1694.     void newTopic(const QString&);
  1695. +    void MQTTClearTopics();
  1696. +    void updateSubscriptionTree(const QVector<QString>&);
  1697.  
  1698.  private:
  1699. -   void updateSubscriptionCompleter();
  1700. -   void addTopicToTree(const QString&);
  1701. -   void manageCommonLevelSubscriptions();
  1702. +    void addTopicToTree(const QString&);
  1703.  
  1704.     struct MQTTHost {
  1705.         int count;
  1706. @@ -123,13 +120,10 @@ private:
  1707.     const MQTTClient* m_previousMQTTClient{nullptr};
  1708.     QMap<QPair<QString, int>, MQTTHost> m_hosts;
  1709.     MQTTHost* m_currentHost{nullptr};
  1710. -   MQTTHost* m_previousHost{nullptr};
  1711. -   QCompleter* m_topicCompleter{nullptr};
  1712. -   QCompleter* m_subscriptionCompleter{nullptr};
  1713. -   bool m_searching{true};
  1714. -   QTimer* m_searchTimer;
  1715. -   bool m_interpretMessage{true};
  1716. -   QString m_mqttUnsubscribeName;
  1717. +    MQTTHost* m_previousHost{nullptr};
  1718. +    bool m_interpretMessage{true};
  1719. +    MQTTSubscriptionWidget* m_subscriptionWidget;
  1720. +    QMetaObject::Connection m_updateSubscriptionConn;
  1721.  #endif
  1722.  };
  1723.  
  1724. diff --git a/src/kdefrontend/ui/datasources/importfilewidget.ui b/src/kdefrontend/ui/datasources/importfilewidget.ui
  1725. index b41dbfdb9..0676de028 100644
  1726. --- a/src/kdefrontend/ui/datasources/importfilewidget.ui
  1727. +++ b/src/kdefrontend/ui/datasources/importfilewidget.ui
  1728. @@ -29,227 +29,88 @@
  1729.        <string>Data Source</string>
  1730.       </property>
  1731.       <layout class="QGridLayout" name="gridLayout">
  1732. -      <item row="9" column="3">
  1733. -       <widget class="QPushButton" name="bLWT">
  1734. +      <item row="5" column="2" colspan="3">
  1735. +       <widget class="QComboBox" name="cbSerialPort"/>
  1736. +      </item>
  1737. +      <item row="3" column="0">
  1738. +       <widget class="QLabel" name="lConnections">
  1739.          <property name="text">
  1740. -         <string/>
  1741. +         <string>Connection:</string>
  1742.          </property>
  1743.         </widget>
  1744.        </item>
  1745. -      <item row="10" column="4">
  1746. -       <spacer name="spacerWillMessage">
  1747. +      <item row="6" column="2" colspan="3">
  1748. +       <widget class="QComboBox" name="cbBaudRate"/>
  1749. +      </item>
  1750. +      <item row="13" column="0">
  1751. +       <widget class="QLabel" name="lField">
  1752. +        <property name="text">
  1753. +         <string>Field:</string>
  1754. +        </property>
  1755. +        <property name="alignment">
  1756. +         <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
  1757. +        </property>
  1758. +       </widget>
  1759. +      </item>
  1760. +      <item row="5" column="0">
  1761. +       <widget class="QLabel" name="lSerialPort">
  1762. +        <property name="text">
  1763. +         <string>Port:</string>
  1764. +        </property>
  1765. +       </widget>
  1766. +      </item>
  1767. +      <item row="0" column="1">
  1768. +       <spacer name="hsName">
  1769.          <property name="orientation">
  1770.           <enum>Qt::Horizontal</enum>
  1771.          </property>
  1772. +        <property name="sizeType">
  1773. +         <enum>QSizePolicy::Fixed</enum>
  1774. +        </property>
  1775.          <property name="sizeHint" stdset="0">
  1776.           <size>
  1777. -          <width>40</width>
  1778. -          <height>0</height>
  1779. +          <width>10</width>
  1780. +          <height>23</height>
  1781.           </size>
  1782.          </property>
  1783.         </spacer>
  1784.        </item>
  1785. -      <item row="8" column="2" colspan="3">
  1786. -       <widget class="QGroupBox" name="gbManageSubscriptions">
  1787. -        <property name="sizePolicy">
  1788. -         <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
  1789. -          <horstretch>0</horstretch>
  1790. -          <verstretch>0</verstretch>
  1791. -         </sizepolicy>
  1792. +      <item row="13" column="2" colspan="3">
  1793. +       <widget class="QTreeView" name="tvJson">
  1794. +        <property name="editTriggers">
  1795. +         <set>QAbstractItemView::NoEditTriggers</set>
  1796.          </property>
  1797. -        <property name="title">
  1798. -         <string/>
  1799. +        <property name="showDropIndicator" stdset="0">
  1800. +         <bool>false</bool>
  1801.          </property>
  1802. -        <property name="flat">
  1803. -         <bool>true</bool>
  1804. +        <property name="iconSize">
  1805. +         <size>
  1806. +          <width>16</width>
  1807. +          <height>16</height>
  1808. +         </size>
  1809.          </property>
  1810. -        <layout class="QGridLayout" name="gridLayout_6" columnstretch="1,1,0,1,1">
  1811. -         <property name="leftMargin">
  1812. -          <number>0</number>
  1813. -         </property>
  1814. -         <property name="topMargin">
  1815. -          <number>0</number>
  1816. -         </property>
  1817. -         <property name="rightMargin">
  1818. -          <number>0</number>
  1819. -         </property>
  1820. -         <property name="bottomMargin">
  1821. -          <number>0</number>
  1822. -         </property>
  1823. -         <property name="spacing">
  1824. -          <number>0</number>
  1825. -         </property>
  1826. -         <item row="0" column="0" colspan="2">
  1827. -          <widget class="QTreeWidget" name="twTopics">
  1828. -           <property name="sizePolicy">
  1829. -            <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
  1830. -             <horstretch>0</horstretch>
  1831. -             <verstretch>0</verstretch>
  1832. -            </sizepolicy>
  1833. -           </property>
  1834. -           <column>
  1835. -            <property name="text">
  1836. -             <string>Available</string>
  1837. -            </property>
  1838. -           </column>
  1839. -          </widget>
  1840. -         </item>
  1841. -         <item row="1" column="3">
  1842. -          <widget class="QLabel" name="lSubscriptionSearch">
  1843. -           <property name="sizePolicy">
  1844. -            <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
  1845. -             <horstretch>0</horstretch>
  1846. -             <verstretch>0</verstretch>
  1847. -            </sizepolicy>
  1848. -           </property>
  1849. -           <property name="text">
  1850. -            <string/>
  1851. -           </property>
  1852. -          </widget>
  1853. -         </item>
  1854. -         <item row="0" column="2">
  1855. -          <layout class="QVBoxLayout" name="verticalLayout_5" stretch="0,1,1,0,0">
  1856. -           <property name="spacing">
  1857. -            <number>12</number>
  1858. -           </property>
  1859. -           <property name="leftMargin">
  1860. -            <number>6</number>
  1861. -           </property>
  1862. -           <property name="topMargin">
  1863. -            <number>6</number>
  1864. -           </property>
  1865. -           <property name="rightMargin">
  1866. -            <number>6</number>
  1867. -           </property>
  1868. -           <item>
  1869. -            <spacer name="verticalSpacer_5">
  1870. -             <property name="orientation">
  1871. -              <enum>Qt::Vertical</enum>
  1872. -             </property>
  1873. -             <property name="sizeHint" stdset="0">
  1874. -              <size>
  1875. -               <width>20</width>
  1876. -               <height>40</height>
  1877. -              </size>
  1878. -             </property>
  1879. -            </spacer>
  1880. -           </item>
  1881. -           <item>
  1882. -            <widget class="QPushButton" name="bSubscribe">
  1883. -             <property name="text">
  1884. -              <string/>
  1885. -             </property>
  1886. -            </widget>
  1887. -           </item>
  1888. -           <item>
  1889. -            <widget class="QPushButton" name="bUnsubscribe">
  1890. -             <property name="text">
  1891. -              <string/>
  1892. -             </property>
  1893. -            </widget>
  1894. -           </item>
  1895. -           <item>
  1896. -            <spacer name="verticalSpacer_3">
  1897. -             <property name="orientation">
  1898. -              <enum>Qt::Vertical</enum>
  1899. -             </property>
  1900. -             <property name="sizeHint" stdset="0">
  1901. -              <size>
  1902. -               <width>20</width>
  1903. -               <height>40</height>
  1904. -              </size>
  1905. -             </property>
  1906. -            </spacer>
  1907. -           </item>
  1908. -           <item>
  1909. -            <widget class="QComboBox" name="cbQos">
  1910. -             <item>
  1911. -              <property name="text">
  1912. -               <string>QoS 0</string>
  1913. -              </property>
  1914. -             </item>
  1915. -             <item>
  1916. -              <property name="text">
  1917. -               <string>QoS 1</string>
  1918. -              </property>
  1919. -             </item>
  1920. -             <item>
  1921. -              <property name="text">
  1922. -               <string>QoS 2</string>
  1923. -              </property>
  1924. -             </item>
  1925. -            </widget>
  1926. -           </item>
  1927. -          </layout>
  1928. -         </item>
  1929. -         <item row="1" column="4">
  1930. -          <widget class="QLineEdit" name="leSubscriptions">
  1931. -           <property name="clearButtonEnabled">
  1932. -            <bool>true</bool>
  1933. -           </property>
  1934. -          </widget>
  1935. -         </item>
  1936. -         <item row="0" column="3" colspan="2">
  1937. -          <widget class="QTreeWidget" name="twSubscriptions">
  1938. -           <property name="sizePolicy">
  1939. -            <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
  1940. -             <horstretch>0</horstretch>
  1941. -             <verstretch>0</verstretch>
  1942. -            </sizepolicy>
  1943. -           </property>
  1944. -           <column>
  1945. -            <property name="text">
  1946. -             <string>Subscribed</string>
  1947. -            </property>
  1948. -           </column>
  1949. -          </widget>
  1950. -         </item>
  1951. -         <item row="1" column="0">
  1952. -          <widget class="QLabel" name="lTopicSearch">
  1953. -           <property name="sizePolicy">
  1954. -            <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
  1955. -             <horstretch>0</horstretch>
  1956. -             <verstretch>0</verstretch>
  1957. -            </sizepolicy>
  1958. -           </property>
  1959. -           <property name="text">
  1960. -            <string/>
  1961. -           </property>
  1962. -           <property name="alignment">
  1963. -            <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
  1964. -           </property>
  1965. -          </widget>
  1966. -         </item>
  1967. -         <item row="1" column="1">
  1968. -          <widget class="QLineEdit" name="leTopics">
  1969. -           <property name="clearButtonEnabled">
  1970. -            <bool>true</bool>
  1971. -           </property>
  1972. -          </widget>
  1973. -         </item>
  1974. -        </layout>
  1975.         </widget>
  1976.        </item>
  1977. -      <item row="3" column="2" colspan="3">
  1978. -       <widget class="QComboBox" name="cbConnection"/>
  1979. -      </item>
  1980. -      <item row="6" column="2" colspan="3">
  1981. -       <widget class="QComboBox" name="cbBaudRate"/>
  1982. -      </item>
  1983. -      <item row="12" column="0">
  1984. -       <widget class="QLabel" name="lFilter">
  1985. +      <item row="9" column="0">
  1986. +       <widget class="QLabel" name="lLWT">
  1987.          <property name="text">
  1988. -         <string>Filter:</string>
  1989. +         <string>LWT:</string>
  1990.          </property>
  1991.         </widget>
  1992.        </item>
  1993. -      <item row="4" column="2" colspan="3">
  1994. -       <widget class="QLineEdit" name="lePort"/>
  1995. +      <item row="2" column="2" colspan="3">
  1996. +       <widget class="QLineEdit" name="leHost"/>
  1997.        </item>
  1998. -      <item row="3" column="0">
  1999. -       <widget class="QLabel" name="lConnections">
  2000. +      <item row="3" column="7">
  2001. +       <widget class="QPushButton" name="bManageConnections">
  2002. +        <property name="sizePolicy">
  2003. +         <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
  2004. +          <horstretch>0</horstretch>
  2005. +          <verstretch>0</verstretch>
  2006. +         </sizepolicy>
  2007. +        </property>
  2008.          <property name="text">
  2009. -         <string>Connection:</string>
  2010. +         <string/>
  2011.          </property>
  2012.         </widget>
  2013.        </item>
  2014. @@ -260,48 +121,43 @@
  2015.          </property>
  2016.         </widget>
  2017.        </item>
  2018. -      <item row="5" column="2" colspan="3">
  2019. -       <widget class="QComboBox" name="cbSerialPort"/>
  2020. -      </item>
  2021. -      <item row="3" column="7">
  2022. -       <widget class="QPushButton" name="bManageConnections">
  2023. +      <item row="12" column="2" colspan="3">
  2024. +       <widget class="KComboBox" name="cbFilter">
  2025. +        <property name="enabled">
  2026. +         <bool>false</bool>
  2027. +        </property>
  2028.          <property name="sizePolicy">
  2029. -         <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
  2030. +         <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
  2031.            <horstretch>0</horstretch>
  2032.            <verstretch>0</verstretch>
  2033.           </sizepolicy>
  2034.          </property>
  2035. -        <property name="text">
  2036. -         <string/>
  2037. -        </property>
  2038.         </widget>
  2039.        </item>
  2040. -      <item row="4" column="0">
  2041. -       <widget class="QLabel" name="lPort">
  2042. -        <property name="text">
  2043. -         <string>Port:</string>
  2044. +      <item row="1" column="7">
  2045. +       <widget class="QPushButton" name="bFileInfo">
  2046. +        <property name="enabled">
  2047. +         <bool>false</bool>
  2048.          </property>
  2049. -       </widget>
  2050. -      </item>
  2051. -      <item row="2" column="0">
  2052. -       <widget class="QLabel" name="lHost">
  2053. -        <property name="text">
  2054. -         <string>Host:</string>
  2055. +        <property name="sizePolicy">
  2056. +         <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
  2057. +          <horstretch>0</horstretch>
  2058. +          <verstretch>0</verstretch>
  2059. +         </sizepolicy>
  2060.          </property>
  2061. -       </widget>
  2062. -      </item>
  2063. -      <item row="8" column="0">
  2064. -       <widget class="QLabel" name="lTopics">
  2065. -        <property name="text">
  2066. -         <string>Topics:</string>
  2067. +        <property name="toolTip">
  2068. +         <string>Show file info</string>
  2069.          </property>
  2070. -        <property name="alignment">
  2071. -         <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
  2072. +        <property name="text">
  2073. +         <string/>
  2074.          </property>
  2075.         </widget>
  2076.        </item>
  2077. -      <item row="1" column="5" colspan="2">
  2078. -       <widget class="QPushButton" name="bOpen">
  2079. +      <item row="12" column="6" colspan="2">
  2080. +       <widget class="QPushButton" name="bManageFilters">
  2081. +        <property name="enabled">
  2082. +         <bool>false</bool>
  2083. +        </property>
  2084.          <property name="sizePolicy">
  2085.           <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
  2086.            <horstretch>0</horstretch>
  2087. @@ -309,35 +165,36 @@
  2088.           </sizepolicy>
  2089.          </property>
  2090.          <property name="toolTip">
  2091. -         <string> Select the file to import</string>
  2092. +         <string>Manage filters</string>
  2093.          </property>
  2094.          <property name="text">
  2095.           <string/>
  2096.          </property>
  2097.         </widget>
  2098.        </item>
  2099. -      <item row="6" column="0">
  2100. -       <widget class="QLabel" name="lBaudRate">
  2101. +      <item row="9" column="3">
  2102. +       <widget class="QPushButton" name="bLWT">
  2103.          <property name="text">
  2104. -         <string>Baud rate:</string>
  2105. +         <string/>
  2106.          </property>
  2107.         </widget>
  2108.        </item>
  2109. -      <item row="0" column="1">
  2110. -       <spacer name="hsName">
  2111. -        <property name="orientation">
  2112. -         <enum>Qt::Horizontal</enum>
  2113. -        </property>
  2114. -        <property name="sizeType">
  2115. -         <enum>QSizePolicy::Fixed</enum>
  2116. +      <item row="4" column="2" colspan="3">
  2117. +       <widget class="QLineEdit" name="lePort"/>
  2118. +      </item>
  2119. +      <item row="0" column="0">
  2120. +       <widget class="QLabel" name="lSourceType">
  2121. +        <property name="text">
  2122. +         <string>Source:</string>
  2123.          </property>
  2124. -        <property name="sizeHint" stdset="0">
  2125. -         <size>
  2126. -          <width>10</width>
  2127. -          <height>23</height>
  2128. -         </size>
  2129. +       </widget>
  2130. +      </item>
  2131. +      <item row="4" column="0">
  2132. +       <widget class="QLabel" name="lPort">
  2133. +        <property name="text">
  2134. +         <string>Port:</string>
  2135.          </property>
  2136. -       </spacer>
  2137. +       </widget>
  2138.        </item>
  2139.        <item row="0" column="2" colspan="3">
  2140.         <widget class="QComboBox" name="cbSourceType">
  2141. @@ -368,22 +225,31 @@
  2142.          </item>
  2143.         </widget>
  2144.        </item>
  2145. -      <item row="0" column="0">
  2146. -       <widget class="QLabel" name="lSourceType">
  2147. +      <item row="2" column="0">
  2148. +       <widget class="QLabel" name="lHost">
  2149.          <property name="text">
  2150. -         <string>Source:</string>
  2151. +         <string>Host:</string>
  2152.          </property>
  2153.         </widget>
  2154.        </item>
  2155. -      <item row="11" column="0">
  2156. -       <widget class="QLabel" name="lFileType">
  2157. +      <item row="1" column="5" colspan="2">
  2158. +       <widget class="QPushButton" name="bOpen">
  2159. +        <property name="sizePolicy">
  2160. +         <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
  2161. +          <horstretch>0</horstretch>
  2162. +          <verstretch>0</verstretch>
  2163. +         </sizepolicy>
  2164. +        </property>
  2165. +        <property name="toolTip">
  2166. +         <string> Select the file to import</string>
  2167. +        </property>
  2168.          <property name="text">
  2169. -         <string>Type:</string>
  2170. +         <string/>
  2171.          </property>
  2172.         </widget>
  2173.        </item>
  2174. -      <item row="2" column="2" colspan="3">
  2175. -       <widget class="QLineEdit" name="leHost"/>
  2176. +      <item row="3" column="2" colspan="3">
  2177. +       <widget class="QComboBox" name="cbConnection"/>
  2178.        </item>
  2179.        <item row="1" column="2" colspan="3">
  2180.         <widget class="QLineEdit" name="leFileName">
  2181. @@ -395,112 +261,77 @@
  2182.          </property>
  2183.         </widget>
  2184.        </item>
  2185. -      <item row="1" column="7">
  2186. -       <widget class="QPushButton" name="bFileInfo">
  2187. -        <property name="enabled">
  2188. -         <bool>false</bool>
  2189. -        </property>
  2190. -        <property name="sizePolicy">
  2191. -         <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
  2192. -          <horstretch>0</horstretch>
  2193. -          <verstretch>0</verstretch>
  2194. -         </sizepolicy>
  2195. -        </property>
  2196. -        <property name="toolTip">
  2197. -         <string>Show file info</string>
  2198. -        </property>
  2199. +      <item row="6" column="0">
  2200. +       <widget class="QLabel" name="lBaudRate">
  2201.          <property name="text">
  2202. -         <string/>
  2203. +         <string>Baud rate:</string>
  2204.          </property>
  2205.         </widget>
  2206.        </item>
  2207. -      <item row="1" column="0">
  2208. -       <widget class="QLabel" name="lFileName">
  2209. +      <item row="11" column="0">
  2210. +       <widget class="QLabel" name="lFileType">
  2211.          <property name="text">
  2212. -         <string>Name:</string>
  2213. +         <string>Type:</string>
  2214.          </property>
  2215.         </widget>
  2216.        </item>
  2217. -      <item row="5" column="0">
  2218. -       <widget class="QLabel" name="lSerialPort">
  2219. +      <item row="1" column="0">
  2220. +       <widget class="QLabel" name="lFileName">
  2221.          <property name="text">
  2222. -         <string>Port:</string>
  2223. -        </property>
  2224. -       </widget>
  2225. -      </item>
  2226. -      <item row="13" column="2" colspan="3">
  2227. -       <widget class="QTreeView" name="tvJson">
  2228. -        <property name="editTriggers">
  2229. -         <set>QAbstractItemView::NoEditTriggers</set>
  2230. -        </property>
  2231. -        <property name="showDropIndicator" stdset="0">
  2232. -         <bool>false</bool>
  2233. -        </property>
  2234. -        <property name="iconSize">
  2235. -         <size>
  2236. -          <width>16</width>
  2237. -          <height>16</height>
  2238. -         </size>
  2239. +         <string>Name:</string>
  2240.          </property>
  2241.         </widget>
  2242.        </item>
  2243. -      <item row="12" column="6" colspan="2">
  2244. -       <widget class="QPushButton" name="bManageFilters">
  2245. +      <item row="12" column="5">
  2246. +       <widget class="QPushButton" name="bSaveFilter">
  2247.          <property name="enabled">
  2248.           <bool>false</bool>
  2249.          </property>
  2250. -        <property name="sizePolicy">
  2251. -         <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
  2252. -          <horstretch>0</horstretch>
  2253. -          <verstretch>0</verstretch>
  2254. -         </sizepolicy>
  2255. -        </property>
  2256.          <property name="toolTip">
  2257. -         <string>Manage filters</string>
  2258. +         <string>Save the current filter settings</string>
  2259.          </property>
  2260. +       </widget>
  2261. +      </item>
  2262. +      <item row="12" column="0">
  2263. +       <widget class="QLabel" name="lFilter">
  2264.          <property name="text">
  2265. -         <string/>
  2266. +         <string>Filter:</string>
  2267.          </property>
  2268.         </widget>
  2269.        </item>
  2270. -      <item row="13" column="0">
  2271. -       <widget class="QLabel" name="lField">
  2272. -        <property name="text">
  2273. -         <string>Field:</string>
  2274. +      <item row="10" column="4">
  2275. +       <spacer name="spacerWillMessage">
  2276. +        <property name="orientation">
  2277. +         <enum>Qt::Horizontal</enum>
  2278.          </property>
  2279. -        <property name="alignment">
  2280. -         <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
  2281. +        <property name="sizeHint" stdset="0">
  2282. +         <size>
  2283. +          <width>40</width>
  2284. +          <height>0</height>
  2285. +         </size>
  2286.          </property>
  2287. -       </widget>
  2288. +       </spacer>
  2289.        </item>
  2290. -      <item row="12" column="5">
  2291. -       <widget class="QPushButton" name="bSaveFilter">
  2292. -        <property name="enabled">
  2293. -         <bool>false</bool>
  2294. +      <item row="8" column="0">
  2295. +       <widget class="QLabel" name="lTopics">
  2296. +        <property name="text">
  2297. +         <string>Topics:</string>
  2298.          </property>
  2299. -        <property name="toolTip">
  2300. -         <string>Save the current filter settings</string>
  2301. +        <property name="alignment">
  2302. +         <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
  2303.          </property>
  2304.         </widget>
  2305.        </item>
  2306. -      <item row="12" column="2" colspan="3">
  2307. -       <widget class="KComboBox" name="cbFilter">
  2308. -        <property name="enabled">
  2309. -         <bool>false</bool>
  2310. -        </property>
  2311. +      <item row="8" column="3" colspan="2">
  2312. +       <widget class="QStackedWidget" name="swSubscriptions">
  2313.          <property name="sizePolicy">
  2314. -         <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
  2315. +         <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
  2316.            <horstretch>0</horstretch>
  2317.            <verstretch>0</verstretch>
  2318.           </sizepolicy>
  2319.          </property>
  2320. -       </widget>
  2321. -      </item>
  2322. -      <item row="9" column="0">
  2323. -       <widget class="QLabel" name="lLWT">
  2324. -        <property name="text">
  2325. -         <string>LWT:</string>
  2326. -        </property>
  2327. +        <widget class="QWidget" name="page_3"/>
  2328. +        <widget class="QWidget" name="page_4"/>
  2329.         </widget>
  2330.        </item>
  2331.       </layout>
  2332. diff --git a/src/kdefrontend/ui/dockwidgets/livedatadock.ui b/src/kdefrontend/ui/dockwidgets/livedatadock.ui
  2333. index c09dcf5a5..20798c7e0 100644
  2334. --- a/src/kdefrontend/ui/dockwidgets/livedatadock.ui
  2335. +++ b/src/kdefrontend/ui/dockwidgets/livedatadock.ui
  2336. @@ -11,154 +11,6 @@
  2337.     </rect>
  2338.    </property>
  2339.    <layout class="QGridLayout" name="gridLayout">
  2340. -   <item row="10" column="2" colspan="2">
  2341. -    <widget class="QGroupBox" name="gbManageSubscriptions">
  2342. -     <property name="sizePolicy">
  2343. -      <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
  2344. -       <horstretch>0</horstretch>
  2345. -       <verstretch>0</verstretch>
  2346. -      </sizepolicy>
  2347. -     </property>
  2348. -     <property name="title">
  2349. -      <string/>
  2350. -     </property>
  2351. -     <property name="flat">
  2352. -      <bool>true</bool>
  2353. -     </property>
  2354. -     <layout class="QGridLayout" name="gridLayout_2">
  2355. -      <property name="leftMargin">
  2356. -       <number>0</number>
  2357. -      </property>
  2358. -      <property name="topMargin">
  2359. -       <number>0</number>
  2360. -      </property>
  2361. -      <property name="rightMargin">
  2362. -       <number>0</number>
  2363. -      </property>
  2364. -      <property name="bottomMargin">
  2365. -       <number>0</number>
  2366. -      </property>
  2367. -      <property name="spacing">
  2368. -       <number>0</number>
  2369. -      </property>
  2370. -      <item row="2" column="1">
  2371. -       <widget class="QLabel" name="lTopicSearch">
  2372. -        <property name="text">
  2373. -         <string/>
  2374. -        </property>
  2375. -        <property name="alignment">
  2376. -         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
  2377. -        </property>
  2378. -       </widget>
  2379. -      </item>
  2380. -      <item row="1" column="1" colspan="2">
  2381. -       <widget class="QTreeWidget" name="twTopics">
  2382. -        <column>
  2383. -         <property name="text">
  2384. -          <string>Available</string>
  2385. -         </property>
  2386. -        </column>
  2387. -       </widget>
  2388. -      </item>
  2389. -      <item row="2" column="2">
  2390. -       <widget class="QLineEdit" name="leTopics">
  2391. -        <property name="clearButtonEnabled">
  2392. -         <bool>true</bool>
  2393. -        </property>
  2394. -       </widget>
  2395. -      </item>
  2396. -      <item row="1" column="4" colspan="2">
  2397. -       <widget class="QTreeWidget" name="twSubscriptions">
  2398. -        <column>
  2399. -         <property name="text">
  2400. -          <string>Subscribed</string>
  2401. -         </property>
  2402. -        </column>
  2403. -       </widget>
  2404. -      </item>
  2405. -      <item row="2" column="5">
  2406. -       <widget class="QLineEdit" name="leSubscriptions">
  2407. -        <property name="clearButtonEnabled">
  2408. -         <bool>true</bool>
  2409. -        </property>
  2410. -       </widget>
  2411. -      </item>
  2412. -      <item row="2" column="4">
  2413. -       <widget class="QLabel" name="lSubscriptionSearch">
  2414. -        <property name="text">
  2415. -         <string/>
  2416. -        </property>
  2417. -       </widget>
  2418. -      </item>
  2419. -      <item row="1" column="3">
  2420. -       <layout class="QVBoxLayout" name="verticalLayout_5" stretch="0,1,1,0,0">
  2421. -        <property name="spacing">
  2422. -         <number>12</number>
  2423. -        </property>
  2424. -        <item>
  2425. -         <spacer name="verticalSpacer_5">
  2426. -          <property name="orientation">
  2427. -           <enum>Qt::Vertical</enum>
  2428. -          </property>
  2429. -          <property name="sizeHint" stdset="0">
  2430. -           <size>
  2431. -            <width>20</width>
  2432. -            <height>40</height>
  2433. -           </size>
  2434. -          </property>
  2435. -         </spacer>
  2436. -        </item>
  2437. -        <item>
  2438. -         <widget class="QPushButton" name="bSubscribe">
  2439. -          <property name="text">
  2440. -           <string/>
  2441. -          </property>
  2442. -         </widget>
  2443. -        </item>
  2444. -        <item>
  2445. -         <widget class="QPushButton" name="bUnsubscribe">
  2446. -          <property name="text">
  2447. -           <string/>
  2448. -          </property>
  2449. -         </widget>
  2450. -        </item>
  2451. -        <item>
  2452. -         <spacer name="verticalSpacer_3">
  2453. -          <property name="orientation">
  2454. -           <enum>Qt::Vertical</enum>
  2455. -          </property>
  2456. -          <property name="sizeHint" stdset="0">
  2457. -           <size>
  2458. -            <width>20</width>
  2459. -            <height>40</height>
  2460. -           </size>
  2461. -          </property>
  2462. -         </spacer>
  2463. -        </item>
  2464. -        <item>
  2465. -         <widget class="QComboBox" name="cbQoS">
  2466. -          <item>
  2467. -           <property name="text">
  2468. -            <string>QoS 0</string>
  2469. -           </property>
  2470. -          </item>
  2471. -          <item>
  2472. -           <property name="text">
  2473. -            <string>QoS 1</string>
  2474. -           </property>
  2475. -          </item>
  2476. -          <item>
  2477. -           <property name="text">
  2478. -            <string>QoS 2</string>
  2479. -           </property>
  2480. -          </item>
  2481. -         </widget>
  2482. -        </item>
  2483. -       </layout>
  2484. -      </item>
  2485. -     </layout>
  2486. -    </widget>
  2487. -   </item>
  2488.     <item row="2" column="2" colspan="2">
  2489.      <widget class="QLineEdit" name="leSourceInfo">
  2490.       <property name="readOnly">
  2491. @@ -456,6 +308,18 @@
  2492.     <item row="1" column="2" colspan="2">
  2493.      <widget class="QLineEdit" name="leName"/>
  2494.     </item>
  2495. +   <item row="10" column="2" colspan="2">
  2496. +    <widget class="QStackedWidget" name="swSubscriptions">
  2497. +     <property name="sizePolicy">
  2498. +      <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
  2499. +       <horstretch>0</horstretch>
  2500. +       <verstretch>0</verstretch>
  2501. +      </sizepolicy>
  2502. +     </property>
  2503. +     <widget class="QWidget" name="page"/>
  2504. +     <widget class="QWidget" name="page_2"/>
  2505. +    </widget>
  2506. +   </item>
  2507.    </layout>
  2508.   </widget>
  2509.   <resources/>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement