Mercurial > public > ostc_companion
view MainWindow.cpp @ 12:ac837fe1d590 default tip
Switch implementation for reqex class and added RFCOMM as label for Bluetooth based connection by Linux
| author | Ideenmodellierer |
|---|---|
| date | Mon, 12 Jan 2026 13:58:41 +0000 |
| parents | 21ce6187d32e |
| children |
line wrap: on
line source
////////////////////////////////////////////////////////////////////////////// /// \file MainWindow.cpp /// \brief GUI for OSTC Companion. /// \author JD Gascuel. /// /// \copyright (c) 2011-2014 JD Gascuel. All rights reserved. /// $Id$ ////////////////////////////////////////////////////////////////////////////// // // BSD 2-Clause License: // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // 1. Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. // ////////////////////////////////////////////////////////////////////////////// #include "MainWindow.h" #include "Utils/LogAppender.h" #include "Utils/ProgressEvent.h" #include "SettingsDialog.h" #include "editlogdialog.h" #include "ui_MainWindow.h" #include <QDateTime> #include <QFileDialog> #include <QInputDialog> #include <QMenu> #include <QMenuBar> #include <QMessageBox> #include <QPlainTextEdit> #include <QProgressBar> #include <QSettings> #include <QString> #include <QTextCursor> #include "OSTC2Operations.h" #include "OSTC2cOperations.h" #include "OSTC3Operations.h" #include "OSTC3pOperations.h" #include "OSTC4Operations.h" #include "OSTCFrogOperations.h" #include "OSTCSportOperations.h" #include "OSTC_CR_Operations.h" extern QSettings *settings; ////////////////////////////////////////////////////////////////////////////// class EXPORT LogWindow : public LogAppender { MainWindow *_window; //---- The <<printing>> function ----------------------------------------- void operator()(const Log &log) override { QString message = log.message; message.replace("< ", "< ").replace(" >", " >"); if (!message.isEmpty()) _window->statusMessage(message); } //---- Reimplementing mandatory methds ----------------------------------- const char *type() const override { return "File"; } Log::Level defaultMinLevel() const override { return Log::LEVEL_INFO; } const char *defaultFormat() const override { return "%m"; } public: LogWindow(MainWindow *window) : LogAppender(0, NULL) , _window(window) {} }; ////////////////////////////////////////////////////////////////////////////// MainWindow::MainWindow() : QMainWindow(NULL) , _ui(new Ui::MainWindow) , _op(0) { // Connect the Log system to this window: new LogWindow(this); // Connect the progress system to this window: ProgressManager::getInstance()->setMainWindow(this); _ui->setupUi(this); _ui->progressBar->show(); _ui->editLog->setVisible(false); // Auto-select last model: QString model = settings->value("Interface/computerType").toString(); _ui->computerType->setCurrentIndex(0); if (model == "ostc2c") _ui->computerType->setCurrentIndex(0); else if (model == "hwOS (Bluetooth)") _ui->computerType->setCurrentIndex(1); else if (model == "hwOS (USB)") _ui->computerType->setCurrentIndex(2); else if (model == "ostc4") _ui->computerType->setCurrentIndex(3); changeTypeSlot(); #ifdef Q_OS_MAC { QMenuBar *menuBar = new QMenuBar(this); QMenu *help = menuBar->addMenu(tr("&Help")); help->addAction(tr("Preferences..."), this, SLOT(settingsSlot())); } #endif setWindowTitle(QString("OSTC Companion v%1.%2 %3") .arg(MAJOR_VERSION) .arg(MINOR_VERSION) // kein sprintf nötig, arg konvertiert automatisch .arg(BETA_VERSION ? QString(" beta %1").arg(PATCH_VERSION) : QString::number(PATCH_VERSION))); } ////////////////////////////////////////////////////////////////////////////// MainWindow::~MainWindow() { delete _ui; delete _op; } ////////////////////////////////////////////////////////////////////////////// bool MainWindow::event(QEvent *e) { if (ProgressEvent *p = dynamic_cast<ProgressEvent *>(e)) { QProgressBar *w = _ui->progressBar; if (p->current > p->maximum && p->maximum > 0) { w->setMaximum(p->maximum); // Remove throttling mode, if any. w->reset(); } else { if (!w->isEnabled()) w->setEnabled(true); if (w->maximum() != p->maximum) w->setMaximum(p->maximum); // Start throttling if max==0 w->setValue(p->current); } return true; } return QMainWindow::event(e); } ////////////////////////////////////////////////////////////////////////////// void MainWindow::changeTypeSlot() { QString name; //---- Setup a new driver ------------------------------------------------ delete _op; _op = 0; switch (_ui->computerType->currentIndex()) { case 0: name = "ostc2c"; _op = new OSTC2cOperations; break; case 1: name = "hwOS (USB)"; _op = new OSTC3Operations; break; case 2: name = "hwOS (Bluetooth)"; _op = new OSTC3pOperations; break; case 3: name = "ostc4"; _op = new OSTC4Operations; break; default: qWarning("Internal error: unknown computer type"); return; } LOG_INFO(tr("%1 selected.").arg(_op->model())); settings->setValue("Interface/computerType", name); settings->sync(); // backword compatibility >= translate name if necessary if (name == "hwOS (Bluetooth)") name = "ostc3p"; if (name == "hwOS (USB)") name = "ostc3"; if (name == "ostc 4/5") name = "ostc4"; _ui->computerImage->setPixmap(QPixmap(":/Images/" + name + "_160x120.png")); updateStatus(); } ////////////////////////////////////////////////////////////////////////////// void MainWindow::settingsSlot() { Settings *s = new Settings(this, _op); s->exec(); delete s; } ////////////////////////////////////////////////////////////////////////////// void MainWindow::connectSlot() { Q_ASSERT(_op); try { LOG_INFO("Connecting..."); //---- Already connected ? ---------------------------------------------- if (!_op->description().isEmpty()) _op->disconnect(); //---- (Re)connect ------------------------------------------------------ if (_op->connect()) { if (Settings::autoSetDateTime) dateSlot(); LOG_INFO("Connected: " + _op->description()); } updateStatus(); } catch (const std::exception &e) { LOG_INFO( QString("<bg><font color='red'>%1</font></color>: %2").arg(tr("Error")).arg(e.what())); } } ////////////////////////////////////////////////////////////////////////////// void MainWindow::closeSlot() { Q_ASSERT(_op); try { LOG_INFO("Disconnecting..."); if (_op->disconnect()) LOG_INFO("Disconnected."); updateStatus(); } catch (const std::exception &e) { LOG_INFO( QString("<bg><font color='red'>%1</font></color>: %2").arg(tr("Error")).arg(e.what())); } } ////////////////////////////////////////////////////////////////////////////// void MainWindow::updateStatus() { bool ok = _op; _ui->connectButton->setEnabled(ok); // ON when supported but NOT connected, OFF once connected. _ui->upgradeButton->setEnabled( ok && (_op->supported() & HardwareOperations::CompanionFeatures(HardwareOperations::FIRMWARE)) && !_op->serial().isOpen()); // Only allow buttons when connected: ok &= _op->serial().isOpen(); _ui->dateButton->setEnabled(ok && _op->supported().testFlag(HardwareOperations::DATE)); _ui->nameButton->setEnabled(ok && _op->supported().testFlag(HardwareOperations::NAME)); _ui->iconButton->setEnabled(ok); // && _op->supported().testFlag(HardwareOperations::ICON)); _ui->signalButton->setEnabled(ok && _op->supported().testFlag(HardwareOperations::SIGNAL_CHECK)); _ui->closeButton->setEnabled(ok); } ////////////////////////////////////////////////////////////////////////////// void MainWindow::dateSlot() { Q_ASSERT(_op); try { QDateTime date = QDateTime::currentDateTime(); LOG_INFO(tr("Settings date & time...")); _op->setDate(date); LOG_INFO(QString("Date set to %1").arg(date.toString("yyyy/MM/dd hh:mm:ss"))); } catch (const std::exception &e) { LOG_INFO( QString("<bg><font color='red'>%1</font></color>: %2").arg(tr("Error")).arg(e.what())); } } ////////////////////////////////////////////////////////////////////////////// void MainWindow::nameSlot() { Q_ASSERT(_op); try { LOG_INFO(tr("Settings name...")); //---- Get old name, and reformat to multi-lines --------------------- QString oldName = _op->description().section(", ", 2); QString oldText; QSize size = _op->nameSize(); for (int l = 0; l < size.height(); ++l) { QString line = oldName.left(size.width()).leftJustified(size.width()); if (line.contains("\n")) { line = line.section("\n", 0, 0); oldName = oldName.mid(line.length()); } else { oldName = oldName.mid(line.length()); if (oldName[0] == '\n') oldName = oldName.mid(1); } oldText += line + "|\n"; } //---- Ask user ------------------------------------------------------ QInputDialog *d = new QInputDialog(this); d->setWindowTitle("Set Computer Name..."); d->setInputMode(QInputDialog::TextInput); d->setOptions(QInputDialog::UsePlainTextEditForTextInput); d->setTextValue(oldText); QPlainTextEdit *edit = d->findChild<QPlainTextEdit *>(); assert(edit); edit->setStyleSheet("background-color: black;" "color: green;" "font: 14pt 'Courier New';"); if (d->exec() != QDialog::Accepted) return; QString newText = d->textValue(); delete d; //---- Reformat to single padded string ------------------------------ QStringList lines = newText.split("\n"); QString name; for (int l = 0; l < size.height(); ++l) { if (l < lines.count()) name += lines[l].leftJustified(size.width(), ' ', true); else name += QString(size.width(), ' '); } //---- Send result --------------------------------------------------- _op->setName(name); _op->getIdentity(); LOG_INFO( QString("Name set to '%1'").arg(_op->description().section(',', 2)).replace("\n", "|")); } catch (const std::exception &e) { LOG_INFO( QString("<bg><font color='red'>%1</font></color>: %2").arg(tr("Error")).arg(e.what())); } } ////////////////////////////////////////////////////////////////////////////// void MainWindow::iconSlot() { Q_ASSERT(_op); try { LOG_INFO(tr("Settings icons...")); QString fileName = QFileDialog::getOpenFileName(this, "Icon File...", QString(), "Images (*.bmp);;" "BMP Image (*.bmp);;" "Anything (*.*)"); if (!fileName.isEmpty()) _op->setIcons(fileName); } catch (const std::exception &e) { LOG_INFO( QString("<bg><font color='red'>%1</font></color>: %2").arg(tr("Error")).arg(e.what())); } } ////////////////////////////////////////////////////////////////////////////// void MainWindow::upgradeSlot() { Q_ASSERT(_op); try { LOG_INFO(tr("Upgrading firmware...")); QString hexFile = QFileDialog::getOpenFileName(0, "Hex File...", Settings::currentPath, _op->firmwareTemplate()); if (hexFile.isEmpty()) return; Settings::currentPath = QFileInfo(hexFile).absoluteDir().path(); Settings::save(); if (_op) _op->upgradeFW(hexFile); } catch (const std::exception &e) { LOG_INFO( QString("<bg><font color='red'>%1</font></color>: %2").arg(tr("Error")).arg(e.what())); } } ////////////////////////////////////////////////////////////////////////////// void MainWindow::statusMessage(const QString &msg) { { // Move cursor to end of document. QTextCursor c = _ui->console->textCursor(); c.movePosition(QTextCursor::End, QTextCursor::MoveAnchor); _ui->console->setTextCursor(c); } _ui->console->appendHtml(msg); _ui->console->ensureCursorVisible(); qApp->processEvents(QEventLoop::AllEvents, 50); } void MainWindow::retranslate() { _ui->retranslateUi(this); } ////////////////////////////////////////////////////////////////////////////// void MainWindow::on_signalButton_clicked() { Q_ASSERT(_op); try { LOG_INFO(tr("Request Bluetooth signal strength...")); _op->getSignal(); } catch (const std::exception &e) { LOG_INFO( QString("<bg><font color='red'>%1</font></color>: %2").arg(tr("Error")).arg(e.what())); } } void MainWindow::on_editLog_clicked() { EditLogDialog *eL = new EditLogDialog(this, _op); eL->exec(); delete eL; }
