"Fossies" - the Fresh Open Source Software Archive

Member "labplot-2.8.2/src/kdefrontend/datasources/ImportFileDialog.cpp" (24 Feb 2021, 21540 Bytes) of package /linux/privat/labplot-2.8.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "ImportFileDialog.cpp" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.8.1_vs_2.8.2.

    1 /***************************************************************************
    2     File                 : ImportDialog.cc
    3     Project              : LabPlot
    4     Description          : import file data dialog
    5     --------------------------------------------------------------------
    6     Copyright            : (C) 2008-2019 Alexander Semke (alexander.semke@web.de)
    7     Copyright            : (C) 2008-2015 by Stefan Gerlach (stefan.gerlach@uni.kn)
    8 
    9  ***************************************************************************/
   10 
   11 /***************************************************************************
   12  *                                                                         *
   13  *  This program is free software; you can redistribute it and/or modify   *
   14  *  it under the terms of the GNU General Public License as published by   *
   15  *  the Free Software Foundation; either version 2 of the License, or      *
   16  *  (at your option) any later version.                                    *
   17  *                                                                         *
   18  *  This program is distributed in the hope that it will be useful,        *
   19  *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
   20  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
   21  *  GNU General Public License for more details.                           *
   22  *                                                                         *
   23  *   You should have received a copy of the GNU General Public License     *
   24  *   along with this program; if not, write to the Free Software           *
   25  *   Foundation, Inc., 51 Franklin Street, Fifth Floor,                    *
   26  *   Boston, MA  02110-1301  USA                                           *
   27  *                                                                         *
   28  ***************************************************************************/
   29 
   30 #include "ImportFileDialog.h"
   31 #include "ImportFileWidget.h"
   32 #include "backend/core/AspectTreeModel.h"
   33 #include "backend/datasources/filters/AbstractFileFilter.h"
   34 #include "backend/datasources/filters/filters.h"
   35 #include "backend/spreadsheet/Spreadsheet.h"
   36 #include "backend/matrix/Matrix.h"
   37 #include "backend/core/Workbook.h"
   38 #include "commonfrontend/widgets/TreeViewComboBox.h"
   39 #include "kdefrontend/MainWin.h"
   40 
   41 #ifdef HAVE_MQTT
   42 #include "backend/datasources/MQTTClient.h"
   43 #endif
   44 
   45 #include <KLocalizedString>
   46 #include <KMessageBox>
   47 #include <KMessageWidget>
   48 #include <KSharedConfig>
   49 #include <KWindowConfig>
   50 
   51 #include <QDialogButtonBox>
   52 #include <QElapsedTimer>
   53 #include <QProgressBar>
   54 #include <QTcpSocket>
   55 #include <QLocalSocket>
   56 #include <QUdpSocket>
   57 #include <QStatusBar>
   58 #include <QDir>
   59 #include <QInputDialog>
   60 #include <QMenu>
   61 #include <QWindow>
   62 
   63 /*!
   64     \class ImportFileDialog
   65     \brief Dialog for importing data from a file. Embeds \c ImportFileWidget and provides the standard buttons.
   66 
   67     \ingroup kdefrontend
   68  */
   69 
   70 ImportFileDialog::ImportFileDialog(MainWin* parent, bool liveDataSource, const QString& fileName) : ImportDialog(parent),
   71     m_importFileWidget(new ImportFileWidget(this, liveDataSource, fileName)) {
   72 
   73     vLayout->addWidget(m_importFileWidget);
   74 
   75     //dialog buttons
   76     auto* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Reset |QDialogButtonBox::Cancel);
   77     okButton = buttonBox->button(QDialogButtonBox::Ok);
   78     m_optionsButton = buttonBox->button(QDialogButtonBox::Reset); //we highjack the default "Reset" button and use if for showing/hiding the options
   79     okButton->setEnabled(false); //ok is only available if a valid container was selected
   80     vLayout->addWidget(buttonBox);
   81 
   82     //hide the data-source related widgets
   83     if (!liveDataSource)
   84         setModel();
   85 
   86     //Signals/Slots
   87     connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
   88     connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
   89 
   90     if (!liveDataSource)
   91         setWindowTitle(i18nc("@title:window", "Import Data to Spreadsheet or Matrix"));
   92     else
   93         setWindowTitle(i18nc("@title:window", "Add New Live Data Source"));
   94 
   95     setWindowIcon(QIcon::fromTheme("document-import-database"));
   96 
   97     //restore saved settings if available
   98     create(); // ensure there's a window created
   99 
  100     QApplication::processEvents(QEventLoop::AllEvents, 0);
  101     m_importFileWidget->loadSettings();
  102 
  103     KConfigGroup conf(KSharedConfig::openConfig(), "ImportFileDialog");
  104     if (conf.exists()) {
  105         m_showOptions = conf.readEntry("ShowOptions", false);
  106 
  107         KWindowConfig::restoreWindowSize(windowHandle(), conf);
  108         resize(windowHandle()->size()); // workaround for QTBUG-40584
  109     } else
  110         resize(QSize(0, 0).expandedTo(minimumSize()));
  111 
  112     m_importFileWidget->showOptions(m_showOptions);
  113     //do the signal-slot connections after all settings were loaded in import file widget and check the OK button after this
  114     connect(m_importFileWidget, &ImportFileWidget::checkedFitsTableToMatrix, this, &ImportFileDialog::checkOnFitsTableToMatrix);
  115     connect(m_importFileWidget, static_cast<void (ImportFileWidget::*)()>(&ImportFileWidget::fileNameChanged), this, &ImportFileDialog::checkOkButton);
  116     connect(m_importFileWidget, static_cast<void (ImportFileWidget::*)()>(&ImportFileWidget::sourceTypeChanged), this, &ImportFileDialog::checkOkButton);
  117     connect(m_importFileWidget, &ImportFileWidget::hostChanged, this, &ImportFileDialog::checkOkButton);
  118     connect(m_importFileWidget, &ImportFileWidget::portChanged, this, &ImportFileDialog::checkOkButton);
  119     connect(m_importFileWidget, &ImportFileWidget::error, this, &ImportFileDialog::showErrorMessage);
  120 #ifdef HAVE_MQTT
  121     connect(m_importFileWidget, &ImportFileWidget::subscriptionsChanged, this, &ImportFileDialog::checkOkButton);
  122     connect(m_importFileWidget, &ImportFileWidget::checkFileType, this, &ImportFileDialog::checkOkButton);
  123 #endif
  124 
  125     m_showOptions ? m_optionsButton->setText(i18n("Hide Options")) : m_optionsButton->setText(i18n("Show Options"));
  126     connect(m_optionsButton, &QPushButton::clicked, this, &ImportFileDialog::toggleOptions);
  127 
  128     ImportFileDialog::checkOkButton();
  129 }
  130 
  131 ImportFileDialog::~ImportFileDialog() {
  132     //save current settings
  133     KConfigGroup conf(KSharedConfig::openConfig(), "ImportFileDialog");
  134     conf.writeEntry("ShowOptions", m_showOptions);
  135     if (cbPosition)
  136         conf.writeEntry("Position", cbPosition->currentIndex());
  137 
  138     KWindowConfig::saveWindowSize(windowHandle(), conf);
  139 }
  140 
  141 LiveDataSource::SourceType ImportFileDialog::sourceType() const {
  142     return m_importFileWidget->currentSourceType();
  143 }
  144 
  145 /*!
  146   triggers data import to the live data source \c source
  147 */
  148 void ImportFileDialog::importToLiveDataSource(LiveDataSource* source, QStatusBar* statusBar) const {
  149     DEBUG("ImportFileDialog::importToLiveDataSource()");
  150     m_importFileWidget->saveSettings(source);
  151 
  152     //show a progress bar in the status bar
  153     auto* progressBar = new QProgressBar();
  154     progressBar->setRange(0, 100);
  155     connect(source->filter(), &AbstractFileFilter::completed, progressBar, &QProgressBar::setValue);
  156 
  157     statusBar->clearMessage();
  158     statusBar->addWidget(progressBar, 1);
  159     WAIT_CURSOR;
  160 
  161     QElapsedTimer timer;
  162     timer.start();
  163     DEBUG(" Initial read()");
  164     source->read();
  165     statusBar->showMessage( i18n("Live data source created in %1 seconds.", (float)timer.elapsed()/1000) );
  166 
  167     RESET_CURSOR;
  168     statusBar->removeWidget(progressBar);
  169 }
  170 
  171 #ifdef HAVE_MQTT
  172 /*!
  173   triggers data import to the MQTTClient \c client
  174 */
  175 void ImportFileDialog::importToMQTT(MQTTClient* client) const{
  176     m_importFileWidget->saveMQTTSettings(client);
  177     client->read();
  178     client->ready();
  179 }
  180 #endif
  181 
  182 /*!
  183   triggers data import to the currently selected data container
  184 */
  185 void ImportFileDialog::importTo(QStatusBar* statusBar) const {
  186     DEBUG("ImportFileDialog::importTo()");
  187     QDEBUG("    cbAddTo->currentModelIndex() =" << cbAddTo->currentModelIndex());
  188     AbstractAspect* aspect = static_cast<AbstractAspect*>(cbAddTo->currentModelIndex().internalPointer());
  189     if (!aspect) {
  190         DEBUG("ERROR in importTo(): No aspect available");
  191         DEBUG(" cbAddTo->currentModelIndex().isValid() = " << cbAddTo->currentModelIndex().isValid());
  192         DEBUG(" cbAddTo->currentModelIndex() row/column = " << cbAddTo->currentModelIndex().row() << ' ' << cbAddTo->currentModelIndex().column());
  193         return;
  194     }
  195 
  196     if (m_importFileWidget->isFileEmpty()) {
  197         KMessageBox::information(nullptr, i18n("No data to import."), i18n("No Data"));
  198         return;
  199     }
  200 
  201     QString fileName = m_importFileWidget->fileName();
  202     auto filter = m_importFileWidget->currentFileFilter();
  203     auto mode = AbstractFileFilter::ImportMode(cbPosition->currentIndex());
  204 
  205     //show a progress bar in the status bar
  206     auto* progressBar = new QProgressBar();
  207     progressBar->setRange(0, 100);
  208     connect(filter, &AbstractFileFilter::completed, progressBar, &QProgressBar::setValue);
  209 
  210     statusBar->clearMessage();
  211     statusBar->addWidget(progressBar, 1);
  212 
  213     WAIT_CURSOR;
  214     QApplication::processEvents(QEventLoop::AllEvents, 100);
  215 
  216     QElapsedTimer timer;
  217     timer.start();
  218 
  219     if (aspect->inherits(AspectType::Matrix)) {
  220         DEBUG("ImportFileDialog::importTo(): to Matrix");
  221         auto* matrix = qobject_cast<Matrix*>(aspect);
  222         filter->readDataFromFile(fileName, matrix, mode);
  223     } else if (aspect->inherits(AspectType::Spreadsheet)) {
  224         DEBUG("ImportFileDialog::importTo(): to Spreadsheet");
  225         auto* spreadsheet = qobject_cast<Spreadsheet*>(aspect);
  226         DEBUG(" Calling filter->readDataFromFile() with spreadsheet " << spreadsheet);
  227         filter->readDataFromFile(fileName, spreadsheet, mode);
  228     } else if (aspect->inherits(AspectType::Workbook)) {
  229         DEBUG("ImportFileDialog::importTo(): to Workbook");
  230         auto* workbook = static_cast<Workbook*>(aspect);
  231         workbook->setUndoAware(false);
  232         auto sheets = workbook->children<AbstractAspect>();
  233 
  234         AbstractFileFilter::FileType fileType = m_importFileWidget->currentFileType();
  235         // multiple data sets/variables for HDF5, NetCDF and ROOT
  236         if (fileType == AbstractFileFilter::FileType::HDF5 || fileType == AbstractFileFilter::FileType::NETCDF ||
  237             fileType == AbstractFileFilter::FileType::ROOT) {
  238             QStringList names;
  239             if (fileType == AbstractFileFilter::FileType::HDF5)
  240                 names = m_importFileWidget->selectedHDF5Names();
  241             else if (fileType == AbstractFileFilter::FileType::NETCDF)
  242                 names = m_importFileWidget->selectedNetCDFNames();
  243             else
  244                 names = m_importFileWidget->selectedROOTNames();
  245 
  246             int nrNames = names.size(), offset = sheets.size();
  247 
  248             //TODO: think about importing multiple sets into one sheet
  249 
  250             int start = 0;  // add nrNames sheets (0 to nrNames)
  251 
  252             //in replace mode add only missing sheets (from offset to nrNames)
  253             //and rename the already available sheets
  254             if (mode == AbstractFileFilter::ImportMode::Replace) {
  255                 start = offset;
  256 
  257                 // if there are more available spreadsheets, than needed,
  258                 // delete the unneeded spreadsheets
  259                 if (offset > nrNames) {
  260                     for (int i = nrNames; i < offset; i++)
  261                         sheets[i]->remove();
  262                     offset = nrNames;
  263                 }
  264 
  265                 //rename the available sheets
  266                 for (int i = 0; i < offset; ++i) {
  267                     //HDF5 variable names contain the whole path, remove it and keep the name only
  268                     QString sheetName = names.at(i);
  269                     if (fileType == AbstractFileFilter::FileType::HDF5)
  270                         sheetName = names[i].mid(names[i].lastIndexOf("/") + 1);
  271 
  272                     auto* sheet = sheets.at(i);
  273                     sheet->setUndoAware(false);
  274                     sheet->setName(sheetName);
  275                     sheet->setUndoAware(true);
  276                 }
  277             }
  278 
  279             // add additional spreadsheets
  280             for (int i = start; i < nrNames; ++i) {
  281                 //HDF5 variable names contain the whole path, remove it and keep the name only
  282                 QString sheetName = names.at(i);
  283                 if (fileType == AbstractFileFilter::FileType::HDF5)
  284                     sheetName = names[i].mid(names[i].lastIndexOf("/") + 1);
  285 
  286                 auto* spreadsheet = new Spreadsheet(sheetName);
  287                 if (mode == AbstractFileFilter::ImportMode::Prepend && !sheets.isEmpty())
  288                     workbook->insertChildBefore(spreadsheet, sheets[0]);
  289                 else
  290                     workbook->addChildFast(spreadsheet);
  291             }
  292 
  293             // start at offset for append, else at 0
  294             if (mode != AbstractFileFilter::ImportMode::Append)
  295                 offset = 0;
  296 
  297             // import all sets to a different sheet
  298             sheets = workbook->children<AbstractAspect>();
  299             for (int i = 0; i < nrNames; ++i) {
  300                 if (fileType == AbstractFileFilter::FileType::HDF5)
  301                     static_cast<HDF5Filter*>(filter)->setCurrentDataSetName(names[i]);
  302                 else if (fileType == AbstractFileFilter::FileType::NETCDF)
  303                     static_cast<NetCDFFilter*>(filter)->setCurrentVarName(names[i]);
  304                 else
  305                     static_cast<ROOTFilter*>(filter)->setCurrentObject(names[i]);
  306 
  307                 int index = i + offset;
  308                 filter->readDataFromFile(fileName, qobject_cast<Spreadsheet*>(sheets[index]));
  309             }
  310 
  311             workbook->setUndoAware(true);
  312         } else { // single import file types
  313             // use active spreadsheet/matrix if present, else new spreadsheet
  314             auto* sheet = workbook->currentSpreadsheet();
  315             if (sheet)
  316                 filter->readDataFromFile(fileName, sheet, mode);
  317             else {
  318                 workbook->setUndoAware(true);
  319                 auto* spreadsheet = new Spreadsheet(fileName);
  320                 workbook->addChild(spreadsheet);
  321                 workbook->setUndoAware(false);
  322                 filter->readDataFromFile(fileName, spreadsheet, mode);
  323             }
  324         }
  325     }
  326     statusBar->showMessage(i18n("File %1 imported in %2 seconds.", fileName, (float)timer.elapsed()/1000));
  327 
  328     RESET_CURSOR;
  329     statusBar->removeWidget(progressBar);
  330 }
  331 
  332 void ImportFileDialog::toggleOptions() {
  333     m_importFileWidget->showOptions(!m_showOptions);
  334     m_showOptions = !m_showOptions;
  335     m_showOptions ? m_optionsButton->setText(i18n("Hide Options")) : m_optionsButton->setText(i18n("Show Options"));
  336 
  337     //resize the dialog
  338     layout()->activate();
  339     resize( QSize(this->width(), 0).expandedTo(minimumSize()) );
  340 }
  341 
  342 void ImportFileDialog::checkOnFitsTableToMatrix(const bool enable) {
  343     if (cbAddTo) {
  344         QDEBUG("cbAddTo->currentModelIndex() = " << cbAddTo->currentModelIndex());
  345         AbstractAspect* aspect = static_cast<AbstractAspect*>(cbAddTo->currentModelIndex().internalPointer());
  346         if (!aspect) {
  347             DEBUG("ERROR: no aspect available.");
  348             return;
  349         }
  350 
  351         if (aspect->inherits(AspectType::Matrix)) {
  352             okButton->setEnabled(enable);
  353             if (enable)
  354                 okButton->setToolTip(i18n("Close the dialog and import the data."));
  355             else
  356                 okButton->setToolTip(i18n("Cannot import into a matrix since the data contains non-numerical data."));
  357         }
  358     }
  359 }
  360 
  361 void ImportFileDialog::checkOkButton() {
  362     DEBUG("ImportFileDialog::checkOkButton()");
  363     if (cbAddTo) { //only check for the target container when no file data source is being added
  364         QDEBUG(" cbAddTo->currentModelIndex() = " << cbAddTo->currentModelIndex());
  365         AbstractAspect* aspect = static_cast<AbstractAspect*>(cbAddTo->currentModelIndex().internalPointer());
  366         if (!aspect) {
  367             okButton->setEnabled(false);
  368             okButton->setToolTip(i18n("Select a data container where the data has to be imported into."));
  369             lPosition->setEnabled(false);
  370             cbPosition->setEnabled(false);
  371             cbAddTo->setFocus(); //set the focus to make the user aware about the fact that a data container needs to be provided
  372             return;
  373         } else {
  374             lPosition->setEnabled(true);
  375             cbPosition->setEnabled(true);
  376 
  377             //when doing ASCII import to a matrix, hide the options for using the file header (first line)
  378             //to name the columns since the column names are fixed in a matrix
  379             const auto* matrix = dynamic_cast<const Matrix*>(aspect);
  380             m_importFileWidget->showAsciiHeaderOptions(matrix == nullptr);
  381         }
  382     }
  383 
  384     QString fileName = m_importFileWidget->fileName();
  385 #ifdef HAVE_WINDOWS
  386     if (!fileName.isEmpty() && fileName.at(1) != QLatin1String(":"))
  387 #else
  388     if (!fileName.isEmpty() && fileName.at(0) != QLatin1String("/"))
  389 #endif
  390         fileName = QDir::homePath() + QLatin1String("/") + fileName;
  391 
  392     DEBUG("Data Source Type: " << ENUM_TO_STRING(LiveDataSource, SourceType, m_importFileWidget->currentSourceType()));
  393     switch (m_importFileWidget->currentSourceType()) {
  394     case LiveDataSource::SourceType::FileOrPipe: {
  395         DEBUG(" fileName = " << fileName.toUtf8().constData());
  396         const bool enable = QFile::exists(fileName);
  397         okButton->setEnabled(enable);
  398         if (enable) {
  399             okButton->setToolTip(i18n("Close the dialog and import the data."));
  400             showErrorMessage(QString());
  401         } else {
  402             QString msg = i18n("The provided file doesn't exist.");
  403             okButton->setToolTip(msg);
  404 
  405             //suppress the error widget when the dialog is opened the first time.
  406             //show only the error widget if the file was really a non-existing file was provided.
  407             if (!fileName.isEmpty())
  408                 showErrorMessage(msg);
  409         }
  410 
  411         break;
  412     }
  413     case LiveDataSource::SourceType::LocalSocket: {
  414         const bool enable = QFile::exists(fileName);
  415         if (enable) {
  416             QLocalSocket lsocket{this};
  417             DEBUG("CONNECT");
  418             lsocket.connectToServer(fileName, QLocalSocket::ReadOnly);
  419             if (lsocket.waitForConnected()) {
  420 
  421                 // this is required for server that send data as soon as connected
  422                 lsocket.waitForReadyRead();
  423 
  424                 DEBUG("DISCONNECT");
  425                 lsocket.disconnectFromServer();
  426                 // read-only socket is disconnected immediately (no waitForDisconnected())
  427                 okButton->setEnabled(true);
  428                 okButton->setToolTip(i18n("Close the dialog and import the data."));
  429                 showErrorMessage(QString());
  430             } else {
  431                 okButton->setEnabled(false);
  432                 QString msg = i18n("Could not connect to the provided local socket. Error: %1.", lsocket.errorString());
  433                 okButton->setToolTip(msg);
  434                 showErrorMessage(msg);
  435             }
  436         } else {
  437             okButton->setEnabled(false);
  438             QString msg = i18n("Could not connect to the provided local socket. The socket does not exist.");
  439             okButton->setToolTip(msg);
  440             if (!fileName.isEmpty())
  441                 showErrorMessage(msg);
  442         }
  443 
  444         break;
  445     }
  446     case LiveDataSource::SourceType::NetworkTcpSocket: {
  447         const bool enable = !m_importFileWidget->host().isEmpty() && !m_importFileWidget->port().isEmpty();
  448         if (enable) {
  449             QTcpSocket socket(this);
  450             socket.connectToHost(m_importFileWidget->host(), m_importFileWidget->port().toUShort(), QTcpSocket::ReadOnly);
  451             if (socket.waitForConnected()) {
  452                 okButton->setEnabled(true);
  453                 okButton->setToolTip(i18n("Close the dialog and import the data."));
  454                 showErrorMessage(QString());
  455                 socket.disconnectFromHost();
  456             } else {
  457                 okButton->setEnabled(false);
  458                 QString msg = i18n("Could not connect to the provided TCP socket. Error: %1.", socket.errorString());
  459                 okButton->setToolTip(msg);
  460                 showErrorMessage(msg);
  461             }
  462         } else {
  463             okButton->setEnabled(false);
  464             QString msg = i18n("Either the host name or the port number is missing.");
  465             okButton->setToolTip(msg);
  466             showErrorMessage(msg);
  467         }
  468         break;
  469     }
  470     case LiveDataSource::SourceType::NetworkUdpSocket: {
  471         const bool enable = !m_importFileWidget->host().isEmpty() && !m_importFileWidget->port().isEmpty();
  472         if (enable) {
  473             QUdpSocket socket(this);
  474             socket.bind(QHostAddress(m_importFileWidget->host()), m_importFileWidget->port().toUShort());
  475             socket.connectToHost(m_importFileWidget->host(), 0, QUdpSocket::ReadOnly);
  476             if (socket.waitForConnected()) {
  477                 okButton->setEnabled(true);
  478                 okButton->setToolTip(i18n("Close the dialog and import the data."));
  479                 showErrorMessage(QString());
  480                 socket.disconnectFromHost();
  481                 // read-only socket is disconnected immediately (no waitForDisconnected())
  482             } else {
  483                 okButton->setEnabled(false);
  484                 QString msg = i18n("Could not connect to the provided UDP socket. Error: %1.", socket.errorString());
  485                 okButton->setToolTip(msg);
  486                 showErrorMessage(msg);
  487             }
  488         } else {
  489             okButton->setEnabled(false);
  490             okButton->setToolTip(i18n("Either the host name or the port number is missing."));
  491         }
  492 
  493         break;
  494     }
  495     case LiveDataSource::SourceType::SerialPort: {
  496 #ifdef HAVE_QTSERIALPORT
  497         const QString sPort = m_importFileWidget->serialPort();
  498         const int baudRate = m_importFileWidget->baudRate();
  499 
  500         if (!sPort.isEmpty()) {
  501             QSerialPort serialPort{this};
  502 
  503             DEBUG(" Port: " << STDSTRING(sPort) << ", Settings: " << baudRate << ',' << serialPort.dataBits()
  504                     << ',' << serialPort.parity() << ',' << serialPort.stopBits());
  505             serialPort.setPortName(sPort);
  506             serialPort.setBaudRate(baudRate);
  507 
  508             const bool serialPortOpened = serialPort.open(QIODevice::ReadOnly);
  509             okButton->setEnabled(serialPortOpened);
  510             if (serialPortOpened) {
  511                 okButton->setToolTip(i18n("Close the dialog and import the data."));
  512                 showErrorMessage(QString());
  513                 serialPort.close();
  514             } else {
  515                 QString msg = i18n("Could not connect to the provided serial port.");
  516                 okButton->setToolTip(msg);
  517                 showErrorMessage(msg);
  518             }
  519         } else {
  520             okButton->setEnabled(false);
  521             QString msg = i18n("Serial port number is missing.");
  522             okButton->setToolTip(msg);
  523             showErrorMessage(msg);
  524         }
  525 #endif
  526         break;
  527     }
  528     case LiveDataSource::SourceType::MQTT: {
  529 #ifdef HAVE_MQTT
  530         const bool enable = m_importFileWidget->isMqttValid();
  531         showErrorMessage(QString());
  532         if (enable) {
  533             okButton->setEnabled(true);
  534             okButton->setToolTip(i18n("Close the dialog and import the data."));
  535         }
  536         else {
  537             okButton->setEnabled(false);
  538             okButton->setToolTip(i18n("Either there is no connection, or no subscriptions were made, or the file filter is not ASCII."));
  539         }
  540 #endif
  541         break;
  542     }
  543     }
  544 }
  545 
  546 QString ImportFileDialog::selectedObject() const {
  547     return m_importFileWidget->selectedObject();
  548 }
  549 
  550 void ImportFileDialog::showErrorMessage(const QString& message) {
  551     if (message.isEmpty()) {
  552         if (m_messageWidget && m_messageWidget->isVisible())
  553             m_messageWidget->close();
  554     } else {
  555         if (!m_messageWidget) {
  556             m_messageWidget = new KMessageWidget(this);
  557             m_messageWidget->setMessageType(KMessageWidget::Error);
  558             vLayout->insertWidget(vLayout->count() - 1, m_messageWidget);
  559         }
  560         m_messageWidget->setText(message);
  561         m_messageWidget->animatedShow();
  562     }
  563 }