File indexing completed on 2025-10-26 03:35:32
0001 /* 0002 File : ImportDialog.cc 0003 Project : LabPlot 0004 Description : import file data dialog 0005 -------------------------------------------------------------------- 0006 SPDX-FileCopyrightText: 2008-2019 Alexander Semke <alexander.semke@web.de> 0007 SPDX-FileCopyrightText: 2008-2015 Stefan Gerlach <stefan.gerlach@uni.kn> 0008 SPDX-License-Identifier: GPL-2.0-or-later 0009 */ 0010 0011 #include "ImportFileDialog.h" 0012 #include "ImportErrorDialog.h" 0013 #include "ImportFileWidget.h" 0014 #include "backend/core/AspectTreeModel.h" 0015 #include "backend/core/Settings.h" 0016 #include "backend/core/Workbook.h" 0017 #include "backend/datasources/filters/AbstractFileFilter.h" 0018 #include "backend/datasources/filters/filters.h" 0019 #include "backend/matrix/Matrix.h" 0020 #include "backend/spreadsheet/Spreadsheet.h" 0021 #include "commonfrontend/widgets/TreeViewComboBox.h" 0022 #include "kdefrontend/MainWin.h" 0023 0024 #ifdef HAVE_MQTT 0025 #include "backend/datasources/MQTTClient.h" 0026 #endif 0027 0028 #include <KLocalizedString> 0029 #include <KWindowConfig> 0030 0031 #include <QDialogButtonBox> 0032 #include <QDir> 0033 #include <QElapsedTimer> 0034 #include <QInputDialog> 0035 #include <QLocalSocket> 0036 #include <QMenu> 0037 #include <QProgressBar> 0038 #include <QStatusBar> 0039 #include <QTcpSocket> 0040 #include <QUdpSocket> 0041 #include <QWindow> 0042 0043 /*! 0044 \class ImportFileDialog 0045 \brief Dialog for importing data from a file. Embeds \c ImportFileWidget and provides the standard buttons. 0046 0047 \ingroup kdefrontend 0048 */ 0049 0050 ImportFileDialog::ImportFileDialog(MainWin* parent, bool liveDataSource, const QString& fileName) 0051 : ImportDialog(parent) 0052 , m_importFileWidget(new ImportFileWidget(this, liveDataSource, fileName)) { 0053 vLayout->addWidget(m_importFileWidget); 0054 0055 // dialog buttons 0056 auto* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Reset | QDialogButtonBox::Cancel); 0057 okButton = buttonBox->button(QDialogButtonBox::Ok); 0058 m_optionsButton = buttonBox->button(QDialogButtonBox::Reset); // we highjack the default "Reset" button and use if for showing/hiding the options 0059 okButton->setEnabled(false); // ok is only available if a valid container was selected 0060 vLayout->addWidget(buttonBox); 0061 0062 // hide the data-source related widgets 0063 if (!liveDataSource) 0064 setModel(); 0065 0066 // Signals/Slots 0067 connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept); 0068 connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); 0069 0070 if (!liveDataSource) 0071 setWindowTitle(i18nc("@title:window", "Import Data to Spreadsheet or Matrix")); 0072 else 0073 setWindowTitle(i18nc("@title:window", "Add New Live Data Source")); 0074 0075 setWindowIcon(QIcon::fromTheme(QStringLiteral("document-import-database"))); 0076 0077 // restore saved settings if available 0078 create(); // ensure there's a window created 0079 0080 QApplication::processEvents(QEventLoop::AllEvents, 0); 0081 m_importFileWidget->loadSettings(); 0082 0083 KConfigGroup conf = Settings::group(QStringLiteral("ImportFileDialog")); 0084 if (conf.exists()) { 0085 m_showOptions = conf.readEntry("ShowOptions", false); 0086 0087 KWindowConfig::restoreWindowSize(windowHandle(), conf); 0088 resize(windowHandle()->size()); // workaround for QTBUG-40584 0089 } else 0090 resize(QSize(0, 0).expandedTo(minimumSize())); 0091 0092 m_importFileWidget->showOptions(m_showOptions); 0093 // do the signal-slot connections after all settings were loaded in import file widget and check the OK button after this 0094 connect(m_importFileWidget, &ImportFileWidget::enableImportToMatrix, this, &ImportFileDialog::enableImportToMatrix); 0095 connect(m_importFileWidget, QOverload<>::of(&ImportFileWidget::fileNameChanged), this, &ImportFileDialog::checkOkButton); 0096 connect(m_importFileWidget, QOverload<>::of(&ImportFileWidget::sourceTypeChanged), this, &ImportFileDialog::checkOkButton); 0097 connect(m_importFileWidget, &ImportFileWidget::hostChanged, this, &ImportFileDialog::checkOkButton); 0098 connect(m_importFileWidget, &ImportFileWidget::portChanged, this, &ImportFileDialog::checkOkButton); 0099 connect(m_importFileWidget, &ImportFileWidget::error, this, &ImportFileDialog::showErrorMessage); 0100 connect(this, &ImportDialog::dataContainerChanged, m_importFileWidget, &ImportFileWidget::dataContainerChanged); 0101 #ifdef HAVE_MQTT 0102 connect(m_importFileWidget, &ImportFileWidget::subscriptionsChanged, this, &ImportFileDialog::checkOkButton); 0103 connect(m_importFileWidget, &ImportFileWidget::checkFileType, this, &ImportFileDialog::checkOkButton); 0104 #endif 0105 0106 m_showOptions ? m_optionsButton->setText(i18n("Hide Options")) : m_optionsButton->setText(i18n("Show Options")); 0107 connect(m_optionsButton, &QPushButton::clicked, this, &ImportFileDialog::toggleOptions); 0108 0109 ImportFileDialog::checkOkButton(); 0110 } 0111 0112 ImportFileDialog::~ImportFileDialog() { 0113 // save current settings 0114 KConfigGroup conf = Settings::group(QStringLiteral("ImportFileDialog")); 0115 conf.writeEntry("ShowOptions", m_showOptions); 0116 if (cbPosition) 0117 conf.writeEntry("Position", cbPosition->currentIndex()); 0118 0119 KWindowConfig::saveWindowSize(windowHandle(), conf); 0120 } 0121 0122 LiveDataSource::SourceType ImportFileDialog::sourceType() const { 0123 return m_importFileWidget->currentSourceType(); 0124 } 0125 0126 /*! 0127 triggers data import to the live data source \c source 0128 */ 0129 void ImportFileDialog::importToLiveDataSource(LiveDataSource* source, QStatusBar* statusBar) const { 0130 DEBUG(Q_FUNC_INFO); 0131 m_importFileWidget->saveSettings(source); 0132 0133 // show a progress bar in the status bar 0134 auto* progressBar = new QProgressBar(); 0135 progressBar->setRange(0, 100); 0136 connect(source->filter(), &AbstractFileFilter::completed, progressBar, &QProgressBar::setValue); 0137 0138 statusBar->clearMessage(); 0139 statusBar->addWidget(progressBar, 1); 0140 WAIT_CURSOR; 0141 0142 QElapsedTimer timer; 0143 timer.start(); 0144 DEBUG(" Initial read()"); 0145 source->read(); 0146 statusBar->showMessage(i18n("Live data source created in %1 seconds.", (float)timer.elapsed() / 1000)); 0147 0148 RESET_CURSOR; 0149 statusBar->removeWidget(progressBar); 0150 } 0151 0152 #ifdef HAVE_MQTT 0153 /*! 0154 triggers data import to the MQTTClient \c client 0155 */ 0156 void ImportFileDialog::importToMQTT(MQTTClient* client) const { 0157 m_importFileWidget->saveMQTTSettings(client); 0158 client->read(); 0159 client->ready(); 0160 } 0161 #endif 0162 0163 /*! 0164 triggers data import to the currently selected data container 0165 */ 0166 void ImportFileDialog::importTo(QStatusBar* statusBar) const { 0167 DEBUG(Q_FUNC_INFO); 0168 QDEBUG(" cbAddTo->currentModelIndex() =" << cbAddTo->currentModelIndex()); 0169 AbstractAspect* aspect = static_cast<AbstractAspect*>(cbAddTo->currentModelIndex().internalPointer()); 0170 if (!aspect) { 0171 DEBUG(Q_FUNC_INFO << ", ERROR: No aspect available"); 0172 DEBUG(" cbAddTo->currentModelIndex().isValid() = " << cbAddTo->currentModelIndex().isValid()); 0173 DEBUG(" cbAddTo->currentModelIndex() row/column = " << cbAddTo->currentModelIndex().row() << ' ' << cbAddTo->currentModelIndex().column()); 0174 return; 0175 } 0176 0177 auto filter = m_importFileWidget->currentFileFilter(); 0178 if (m_importFileWidget->importValid()) { 0179 DEBUG(Q_FUNC_INFO << ", Import VALID!") 0180 auto errors = filter->lastErrors(); 0181 if (errors.isEmpty()) { 0182 // Default message, because not all filters implement lastErrors yet 0183 errors.append(i18n("No data to import.")); 0184 } 0185 ImportErrorDialog* d = new ImportErrorDialog(errors); 0186 d->setAttribute(Qt::WA_DeleteOnClose); 0187 d->show(); 0188 return; 0189 } 0190 0191 QString fileName = m_importFileWidget->fileName(); 0192 auto mode = AbstractFileFilter::ImportMode(cbPosition->currentIndex()); 0193 0194 // show a progress bar in the status bar 0195 auto* progressBar = new QProgressBar(); 0196 progressBar->setRange(0, 100); 0197 connect(filter, &AbstractFileFilter::completed, progressBar, &QProgressBar::setValue); 0198 0199 statusBar->clearMessage(); 0200 statusBar->addWidget(progressBar, 1); 0201 0202 WAIT_CURSOR; 0203 QApplication::processEvents(QEventLoop::AllEvents, 100); 0204 0205 QElapsedTimer timer; 0206 timer.start(); 0207 0208 if (aspect->inherits(AspectType::Matrix)) { 0209 DEBUG(Q_FUNC_INFO << ", to Matrix"); 0210 auto* matrix = qobject_cast<Matrix*>(aspect); 0211 filter->readDataFromFile(fileName, matrix, mode); 0212 } else if (aspect->inherits(AspectType::Spreadsheet)) { 0213 DEBUG(Q_FUNC_INFO << ", to Spreadsheet"); 0214 auto* spreadsheet = qobject_cast<Spreadsheet*>(aspect); 0215 filter->readDataFromFile(fileName, spreadsheet, mode); 0216 } else if (aspect->inherits(AspectType::Workbook)) { 0217 DEBUG(Q_FUNC_INFO << ", to Workbook"); 0218 auto* workbook = static_cast<Workbook*>(aspect); 0219 workbook->setUndoAware(false); 0220 auto sheets = workbook->children<AbstractAspect>(); 0221 0222 AbstractFileFilter::FileType fileType = m_importFileWidget->currentFileType(); 0223 // types supporting multiple data sets/variables 0224 if (fileType == AbstractFileFilter::FileType::HDF5 || fileType == AbstractFileFilter::FileType::NETCDF || fileType == AbstractFileFilter::FileType::ROOT 0225 || fileType == AbstractFileFilter::FileType::MATIO || fileType == AbstractFileFilter::FileType::XLSX 0226 || fileType == AbstractFileFilter::FileType::Ods || fileType == AbstractFileFilter::FileType::VECTOR_BLF) { 0227 QStringList names; 0228 if (fileType == AbstractFileFilter::FileType::HDF5) 0229 names = m_importFileWidget->selectedHDF5Names(); 0230 else if (fileType == AbstractFileFilter::FileType::VECTOR_BLF) 0231 names = QStringList({QStringLiteral("TODO")}); // m_importFileWidget->selectedVectorBLFNames(); 0232 else if (fileType == AbstractFileFilter::FileType::NETCDF) 0233 names = m_importFileWidget->selectedNetCDFNames(); 0234 else if (fileType == AbstractFileFilter::FileType::ROOT) 0235 names = m_importFileWidget->selectedROOTNames(); 0236 else if (fileType == AbstractFileFilter::FileType::MATIO) 0237 names = m_importFileWidget->selectedMatioNames(); 0238 else if (fileType == AbstractFileFilter::FileType::XLSX) 0239 names = m_importFileWidget->selectedXLSXRegionNames(); 0240 else if (fileType == AbstractFileFilter::FileType::Ods) 0241 names = m_importFileWidget->selectedOdsSheetNames(); 0242 0243 int nrNames = names.size(), offset = sheets.size(); 0244 QDEBUG(Q_FUNC_INFO << ", selected names: " << names) 0245 0246 // TODO: think about importing multiple sets into one sheet 0247 0248 int start = 0; // add nrNames sheets (0 to nrNames) 0249 0250 // in replace mode add only missing sheets (from offset to nrNames) 0251 // and rename the already available sheets 0252 if (mode == AbstractFileFilter::ImportMode::Replace) { 0253 start = offset; 0254 0255 // if there are more available spreadsheets, than needed, 0256 // delete the unneeded spreadsheets 0257 if (offset > nrNames) { 0258 for (int i = nrNames; i < offset; i++) 0259 sheets.at(i)->remove(); 0260 offset = nrNames; 0261 } 0262 0263 // rename the available sheets 0264 for (int i = 0; i < offset; ++i) { 0265 // HDF5 and Ods names contain the whole path, remove it and keep the name only 0266 QString sheetName = names.at(i); 0267 if (fileType == AbstractFileFilter::FileType::HDF5 || fileType == AbstractFileFilter::FileType::Ods) 0268 sheetName = sheetName.split(QLatin1Char('/')).last(); 0269 0270 auto* sheet = sheets.at(i); 0271 sheet->setUndoAware(false); 0272 sheet->setName(sheetName); 0273 sheet->setUndoAware(true); 0274 } 0275 } 0276 0277 // add additional spreadsheets 0278 for (int i = start; i < nrNames; ++i) { 0279 // HDF5 and Ods names contain the whole path, remove it and keep the name only 0280 QString sheetName = names.at(i); 0281 if (fileType == AbstractFileFilter::FileType::HDF5 || fileType == AbstractFileFilter::FileType::Ods) 0282 sheetName = sheetName.split(QLatin1Char('/')).last(); 0283 0284 auto* spreadsheet = new Spreadsheet(sheetName); 0285 if (mode == AbstractFileFilter::ImportMode::Prepend && !sheets.isEmpty()) 0286 workbook->insertChildBefore(spreadsheet, sheets.at(0)); 0287 else 0288 workbook->addChildFast(spreadsheet); 0289 } 0290 0291 // start at offset for append, else at 0 0292 if (mode != AbstractFileFilter::ImportMode::Append) 0293 offset = 0; 0294 0295 // import every set to a different sheet 0296 sheets = workbook->children<AbstractAspect>(); 0297 for (int i = 0; i < nrNames; ++i) { 0298 if (fileType == AbstractFileFilter::FileType::HDF5) 0299 static_cast<HDF5Filter*>(filter)->setCurrentDataSetName(names.at(i)); 0300 else if (fileType == AbstractFileFilter::FileType::NETCDF) 0301 static_cast<NetCDFFilter*>(filter)->setCurrentVarName(names.at(i)); 0302 else if (fileType == AbstractFileFilter::FileType::MATIO) 0303 static_cast<MatioFilter*>(filter)->setCurrentVarName(names.at(i)); 0304 else if (fileType == AbstractFileFilter::FileType::Ods) // all selected sheets are imported 0305 static_cast<OdsFilter*>(filter)->setSelectedSheetNames(QStringList() << names.at(i)); 0306 else if (fileType == AbstractFileFilter::FileType::XLSX) { 0307 const auto& nameSplit = names.at(i).split(QLatin1Char('!')); 0308 const auto& sheet = nameSplit.at(0); 0309 const auto& range = nameSplit.at(1); 0310 static_cast<XLSXFilter*>(filter)->setCurrentSheet(sheet); 0311 static_cast<XLSXFilter*>(filter)->setCurrentRange(range); 0312 } else 0313 static_cast<ROOTFilter*>(filter)->setCurrentObject(names.at(i)); 0314 0315 int index = i + offset; 0316 filter->readDataFromFile(fileName, qobject_cast<Spreadsheet*>(sheets.at(index))); 0317 } 0318 0319 workbook->setUndoAware(true); 0320 } else { // single import file types 0321 // use active spreadsheet/matrix if present, else new spreadsheet 0322 auto* sheet = workbook->currentSpreadsheet(); 0323 if (sheet) 0324 filter->readDataFromFile(fileName, sheet, mode); 0325 else { 0326 workbook->setUndoAware(true); 0327 auto* spreadsheet = new Spreadsheet(fileName); 0328 workbook->addChild(spreadsheet); 0329 workbook->setUndoAware(false); 0330 filter->readDataFromFile(fileName, spreadsheet, mode); 0331 } 0332 } 0333 } 0334 statusBar->showMessage(i18n("File %1 imported in %2 seconds.", fileName, (float)timer.elapsed() / 1000)); 0335 0336 const auto errors = filter->lastErrors(); 0337 if (!errors.isEmpty()) { 0338 ImportErrorDialog* d = new ImportErrorDialog(errors); 0339 d->setAttribute(Qt::WA_DeleteOnClose); 0340 d->show(); 0341 } 0342 0343 RESET_CURSOR; 0344 statusBar->removeWidget(progressBar); 0345 DEBUG(Q_FUNC_INFO << ", DONE") 0346 } 0347 0348 void ImportFileDialog::toggleOptions() { 0349 m_importFileWidget->showOptions(!m_showOptions); 0350 m_showOptions = !m_showOptions; 0351 m_showOptions ? m_optionsButton->setText(i18n("Hide Options")) : m_optionsButton->setText(i18n("Show Options")); 0352 0353 // resize the dialog 0354 layout()->activate(); 0355 resize(QSize(this->width(), 0).expandedTo(minimumSize())); 0356 } 0357 0358 void ImportFileDialog::enableImportToMatrix(const bool enable) { 0359 if (cbAddTo) { 0360 QDEBUG("cbAddTo->currentModelIndex() = " << cbAddTo->currentModelIndex()); 0361 AbstractAspect* aspect = static_cast<AbstractAspect*>(cbAddTo->currentModelIndex().internalPointer()); 0362 if (!aspect) { 0363 DEBUG("ERROR: no aspect available."); 0364 return; 0365 } 0366 0367 if (aspect->inherits(AspectType::Matrix)) { 0368 okButton->setEnabled(enable); 0369 if (enable) 0370 okButton->setToolTip(i18n("Close the dialog and import the data.")); 0371 else 0372 okButton->setToolTip(i18n("Cannot import into a matrix since the data contains non-numerical data.")); 0373 } 0374 } 0375 } 0376 0377 void ImportFileDialog::checkOkButton() { 0378 DEBUG(Q_FUNC_INFO); 0379 if (cbAddTo) { // only check for the target container when no file data source is being added 0380 QDEBUG(" cbAddTo->currentModelIndex() = " << cbAddTo->currentModelIndex()); 0381 AbstractAspect* aspect = static_cast<AbstractAspect*>(cbAddTo->currentModelIndex().internalPointer()); 0382 if (!aspect) { 0383 okButton->setEnabled(false); 0384 okButton->setToolTip(i18n("Select a data container where the data has to be imported into.")); 0385 lPosition->setEnabled(false); 0386 cbPosition->setEnabled(false); 0387 cbAddTo->setFocus(); // set the focus to make the user aware about the fact that a data container needs to be provided 0388 return; 0389 } else { 0390 lPosition->setEnabled(true); 0391 cbPosition->setEnabled(true); 0392 } 0393 } 0394 0395 QString fileName = ImportFileWidget::absolutePath(m_importFileWidget->fileName()); 0396 if (fileName.isEmpty()) 0397 return; 0398 0399 DEBUG(Q_FUNC_INFO << ", Data Source Type: " << ENUM_TO_STRING(LiveDataSource, SourceType, m_importFileWidget->currentSourceType())); 0400 switch (m_importFileWidget->currentSourceType()) { 0401 case LiveDataSource::SourceType::FileOrPipe: { 0402 DEBUG(Q_FUNC_INFO << ", fileName = " << qPrintable(fileName)); 0403 const bool enable = QFile::exists(fileName); 0404 okButton->setEnabled(enable); 0405 if (enable) { 0406 okButton->setToolTip(i18n("Close the dialog and import the data.")); 0407 showErrorMessage(QString()); 0408 } else { 0409 QString msg = i18n("The provided file doesn't exist."); 0410 okButton->setToolTip(msg); 0411 0412 // suppress the error widget when the dialog is opened the first time. 0413 // show only the error widget if the file was really a non-existing file. 0414 showErrorMessage(msg); 0415 } 0416 0417 break; 0418 } 0419 case LiveDataSource::SourceType::LocalSocket: { 0420 const bool enable = QFile::exists(fileName); 0421 if (enable) { 0422 QLocalSocket lsocket{this}; 0423 DEBUG("CONNECT"); 0424 lsocket.connectToServer(fileName, QLocalSocket::ReadOnly); 0425 if (lsocket.waitForConnected()) { 0426 // this is required for server that send data as soon as connected 0427 lsocket.waitForReadyRead(); 0428 0429 DEBUG("DISCONNECT"); 0430 lsocket.disconnectFromServer(); 0431 // read-only socket is disconnected immediately (no waitForDisconnected()) 0432 okButton->setEnabled(true); 0433 okButton->setToolTip(i18n("Close the dialog and import the data.")); 0434 showErrorMessage(QString()); 0435 } else { 0436 okButton->setEnabled(false); 0437 QString msg = i18n("Could not connect to the provided local socket. Error: %1.", lsocket.errorString()); 0438 okButton->setToolTip(msg); 0439 showErrorMessage(msg); 0440 } 0441 } else { 0442 okButton->setEnabled(false); 0443 QString msg = i18n("Could not connect to the provided local socket. The socket does not exist."); 0444 okButton->setToolTip(msg); 0445 showErrorMessage(msg); 0446 } 0447 0448 break; 0449 } 0450 case LiveDataSource::SourceType::NetworkTCPSocket: { 0451 const bool enable = !m_importFileWidget->host().isEmpty() && !m_importFileWidget->port().isEmpty(); 0452 if (enable) { 0453 QTcpSocket socket(this); 0454 socket.connectToHost(m_importFileWidget->host(), m_importFileWidget->port().toUShort(), QTcpSocket::ReadOnly); 0455 if (socket.waitForConnected()) { 0456 okButton->setEnabled(true); 0457 okButton->setToolTip(i18n("Close the dialog and import the data.")); 0458 showErrorMessage(QString()); 0459 socket.disconnectFromHost(); 0460 } else { 0461 okButton->setEnabled(false); 0462 QString msg = i18n("Could not connect to the provided TCP socket. Error: %1.", socket.errorString()); 0463 okButton->setToolTip(msg); 0464 showErrorMessage(msg); 0465 } 0466 } else { 0467 okButton->setEnabled(false); 0468 QString msg = i18n("Either the host name or the port number is missing."); 0469 okButton->setToolTip(msg); 0470 showErrorMessage(msg); 0471 } 0472 break; 0473 } 0474 case LiveDataSource::SourceType::NetworkUDPSocket: { 0475 const bool enable = !m_importFileWidget->host().isEmpty() && !m_importFileWidget->port().isEmpty(); 0476 if (enable) { 0477 QUdpSocket socket(this); 0478 socket.bind(QHostAddress(m_importFileWidget->host()), m_importFileWidget->port().toUShort()); 0479 socket.connectToHost(m_importFileWidget->host(), 0, QUdpSocket::ReadOnly); 0480 if (socket.waitForConnected()) { 0481 okButton->setEnabled(true); 0482 okButton->setToolTip(i18n("Close the dialog and import the data.")); 0483 showErrorMessage(QString()); 0484 socket.disconnectFromHost(); 0485 // read-only socket is disconnected immediately (no waitForDisconnected()) 0486 } else { 0487 okButton->setEnabled(false); 0488 QString msg = i18n("Could not connect to the provided UDP socket. Error: %1.", socket.errorString()); 0489 okButton->setToolTip(msg); 0490 showErrorMessage(msg); 0491 } 0492 } else { 0493 okButton->setEnabled(false); 0494 okButton->setToolTip(i18n("Either the host name or the port number is missing.")); 0495 } 0496 0497 break; 0498 } 0499 case LiveDataSource::SourceType::SerialPort: { 0500 #ifdef HAVE_QTSERIALPORT 0501 const QString sPort = m_importFileWidget->serialPort(); 0502 0503 if (!sPort.isEmpty()) { 0504 QSerialPort serialPort{this}; 0505 const int baudRate = m_importFileWidget->baudRate(); 0506 0507 DEBUG(" Port: " << STDSTRING(sPort) << ", Settings: " << baudRate << ',' << serialPort.dataBits() << ',' << serialPort.parity() << ',' 0508 << serialPort.stopBits()); 0509 serialPort.setPortName(sPort); 0510 serialPort.setBaudRate(baudRate); 0511 0512 const bool serialPortOpened = serialPort.open(QIODevice::ReadOnly); 0513 okButton->setEnabled(serialPortOpened); 0514 if (serialPortOpened) { 0515 okButton->setToolTip(i18n("Close the dialog and import the data.")); 0516 showErrorMessage(QString()); 0517 serialPort.close(); 0518 } else { 0519 QString msg = i18n("Could not connect to the provided serial port."); 0520 okButton->setToolTip(msg); 0521 showErrorMessage(msg); 0522 } 0523 } else { 0524 okButton->setEnabled(false); 0525 QString msg = i18n("Serial port number is missing."); 0526 okButton->setToolTip(msg); 0527 showErrorMessage(msg); 0528 } 0529 #endif 0530 break; 0531 } 0532 case LiveDataSource::SourceType::MQTT: { 0533 #ifdef HAVE_MQTT 0534 const bool enable = m_importFileWidget->isMqttValid(); 0535 showErrorMessage(QString()); 0536 if (enable) { 0537 okButton->setEnabled(true); 0538 okButton->setToolTip(i18n("Close the dialog and import the data.")); 0539 } else { 0540 okButton->setEnabled(false); 0541 okButton->setToolTip(i18n("Either there is no connection, or no subscriptions were made, or the file filter is not ASCII.")); 0542 } 0543 #endif 0544 break; 0545 } 0546 } 0547 } 0548 0549 QString ImportFileDialog::selectedObject() const { 0550 return m_importFileWidget->selectedObject(); 0551 }