From: Michal MalĂ˝ Date: Wed, 8 Jul 2015 15:18:35 +0000 (+0200) Subject: Use proper MVC in ComboBoxes. X-Git-Tag: 0.4a~4 X-Git-Url: https://gitweb.devoid-pointer.net/?a=commitdiff_plain;h=dc3adea0e51c730bf580e288fe9e72a5d1376f55;p=FFBChecker.git Use proper MVC in ComboBoxes. --- diff --git a/conditioneffectsettings.cpp b/conditioneffectsettings.cpp index 8ec9540..448cabb 100644 --- a/conditioneffectsettings.cpp +++ b/conditioneffectsettings.cpp @@ -7,6 +7,9 @@ ConditionEffectSettings::ConditionEffectSettings(QWidget* parent) : ui(new Ui::ConditionEffectSettings) { ui->setupUi(this); + + ui->cbox_axis->setItemData(0, static_cast::type>(FFBConditionEffectParameters::Axis::X)); + ui->cbox_axis->setItemData(1, static_cast::type>(FFBConditionEffectParameters::Axis::Y)); connect(ui->cbox_axis, SIGNAL(currentIndexChanged(int)), this, SLOT(axisChanged(const int))); axisChanged(ui->cbox_axis->currentIndex()); } @@ -22,10 +25,27 @@ void ConditionEffectSettings::axisChanged(const int idx) qDebug() << "Axis changed" << idx; } -void ConditionEffectSettings::fillAvailableSubtypesList(const QStringList& list) +QString ConditionEffectSettings::conditionSubtypeToConditionName(const ConditionSubtypes subtype) const +{ + switch (subtype) { + case ConditionSubtypes::DAMPER: + return "Damper"; + case ConditionSubtypes::FRICTION: + return "Friction"; + case ConditionSubtypes::INERTIA: + return "Inertia"; + case ConditionSubtypes::SPRING: + return "Spring"; + default: + return "Unknown subtype"; + } +} + +void ConditionEffectSettings::fillAvailableSubtypesList(const std::vector& list) { ui->cbox_subtype->clear(); - ui->cbox_subtype->addItems(list); + for (const ConditionSubtypes subtype : list) + ui->cbox_subtype->addItem(conditionSubtypeToConditionName(subtype), static_cast::type>(subtype)); } bool ConditionEffectSettings::fillFromParameters(const std::shared_ptr params) @@ -59,14 +79,8 @@ bool ConditionEffectSettings::fillFromParameters(const std::shared_ptrcbox_axis->currentIndex()) { - case 0: - return FFBConditionEffectParameters::Axis::X; - case 1: - return FFBConditionEffectParameters::Axis::Y; - default: - return FFBConditionEffectParameters::Axis::NONE; - } + FFBConditionEffectParameters::Axis a = *static_cast(ui->cbox_axis->currentData(Qt::UserRole).data()); + return a; } QString ConditionEffectSettings::centerX() const @@ -129,9 +143,10 @@ QString ConditionEffectSettings::rightSatY() const return ui->qle_rightSatY->text(); } -int ConditionEffectSettings::subtypeIdx() const +ConditionSubtypes ConditionEffectSettings::subtype() const { - return ui->cbox_subtype->currentIndex(); + ConditionSubtypes subtype = *static_cast(ui->cbox_subtype->currentData(Qt::UserRole).data()); + return subtype; } ConditionEffectSettings::~ConditionEffectSettings() diff --git a/conditioneffectsettings.h b/conditioneffectsettings.h index 5dd680d..d8751bc 100644 --- a/conditioneffectsettings.h +++ b/conditioneffectsettings.h @@ -14,7 +14,8 @@ class ConditionEffectSettings : public EffectSettings public: explicit ConditionEffectSettings(QWidget* parent = nullptr); ~ConditionEffectSettings(); - void fillAvailableSubtypesList(const QStringList& list); + QString conditionSubtypeToConditionName(const ConditionSubtypes subtype) const; + void fillAvailableSubtypesList(const std::vector& list); bool fillFromParameters(const std::shared_ptr params); bool fillFromParameters(const std::shared_ptr cdParams); FFBConditionEffectParameters::Axis axis() const; @@ -30,7 +31,7 @@ public: QString leftSatY() const; QString rightSatX() const; QString rightSatY() const; - int subtypeIdx() const; + ConditionSubtypes subtype() const; private: Ui::ConditionEffectSettings* ui; diff --git a/ffbdevice.cpp b/ffbdevice.cpp index 82c59cb..3b0efa8 100644 --- a/ffbdevice.cpp +++ b/ffbdevice.cpp @@ -17,68 +17,19 @@ FFBDevice::FFBDevice(const int fd, const QString& path, const int maxEffectCount m_effects.push_back(FFBEffectFactory::createEffect(FFBEffectTypes::NONE)); } -QStringList FFBDevice::availableConditionSubtypesList() const +const std::vector& FFBDevice::availableConditionSubtypesList() const { - QStringList list; - - for (const ConditionSubtypes s : m_availableConditionSubtypes) - list << conditionSubtypeName(s); - - return list; + return m_availableConditionSubtypes; } -QStringList FFBDevice::availableEffectsList() const +const std::vector& FFBDevice::availableEffectsList() const { - QStringList list; - - for (const FFBEffectTypes e : m_availableEffects) - list << effectName(e); - - return list; + return m_availableEffects; } -QStringList FFBDevice::availableWaveformsList() const +const std::vector& FFBDevice::availableWaveformsList() const { - QStringList list; - - for (const PeriodicWaveforms w : m_availablePeriodicWaveforms) - list << waveformName(w); - - return list; -} - -QString FFBDevice::conditionSubtypeName(const ConditionSubtypes subtype) const -{ - switch (subtype) { - case ConditionSubtypes::DAMPER: - return "Damper"; - case ConditionSubtypes::FRICTION: - return "Friction"; - case ConditionSubtypes::INERTIA: - return "Inertia"; - case ConditionSubtypes::SPRING: - return "Spring"; - default: - return "Unknown subtype"; - } -} - -QString FFBDevice::effectName(const FFBEffectTypes effect) const -{ - switch (effect) { - case FFBEffectTypes::CONSTANT: - return "Constant force"; - case FFBEffectTypes::PERIODIC: - return "Periodic force"; - case FFBEffectTypes::RAMP: - return "Ramp"; - case FFBEffectTypes::CONDITION: - return "Condition"; - case FFBEffectTypes::RUMBLE: - return "Rumble"; - default: - return "Unknown effect"; - } + return m_availablePeriodicWaveforms; } const std::shared_ptr FFBDevice::effectParameters(const int idx) @@ -102,34 +53,6 @@ FFBEffectTypes FFBDevice::effectTypeByEffectIdx(const int idx) const return m_effects[idx]->type(); } -unsigned int FFBDevice::effectTypeToIdx(FFBEffectTypes type) -{ - for (unsigned int i = 0; i < m_availableEffects.size(); i++) { - if (m_availableEffects[i] == type) - return i; - } - qWarning() << "Effect type no found in the list!"; - return 0; -} - -QString FFBDevice::waveformName(const PeriodicWaveforms waveform) const -{ - switch (waveform) { - case PeriodicWaveforms::SQUARE: - return "Square"; - case PeriodicWaveforms::TRIANGLE: - return "Triangle"; - case PeriodicWaveforms::SINE: - return "Sine"; - case PeriodicWaveforms::SAW_UP: - return "Saw up"; - case PeriodicWaveforms::SAW_DOWN: - return "Saw down"; - default: - return "Unknown waveform"; - } -} - bool FFBDevice::hasEffect(FFBEffectTypes id) const { for (const FFBEffectTypes e : m_availableEffects) @@ -228,24 +151,21 @@ bool FFBDevice::removeEffect(const int idx) bool FFBDevice::startEffect(const int idx, const FFBEffectTypes type, std::shared_ptr parameters) { int ret; - std::shared_ptr effect; CHECK_EFFECT_IDX(idx); - effect = m_effects[idx]; - - if (effect->status() == FFBEffect::FFBEffectStatus::NOT_LOADED) { + if (m_effects[idx]->status() == FFBEffect::FFBEffectStatus::NOT_LOADED) { if (!uploadEffect(idx, type, parameters)) return false; } - if (effect->status() == FFBEffect::FFBEffectStatus::PLAYING) + if (m_effects[idx]->status() == FFBEffect::FFBEffectStatus::PLAYING) return true; /* Start playback */ struct input_event evt; evt.type = EV_FF; - evt.code = effect->internalIdx(); - evt.value = effect->parameters()->repeat; + evt.code = m_effects[idx]->internalIdx(); + evt.value = m_effects[idx]->parameters()->repeat; ret = write(c_fd, &evt, sizeof(struct input_event)); if (ret != sizeof(struct input_event)) { @@ -254,7 +174,7 @@ bool FFBDevice::startEffect(const int idx, const FFBEffectTypes type, std::share return false; } - effect->setStatus(FFBEffect::FFBEffectStatus::PLAYING); + m_effects[idx]->setStatus(FFBEffect::FFBEffectStatus::PLAYING); return true; } diff --git a/ffbdevice.h b/ffbdevice.h index c467e5a..547bff4 100644 --- a/ffbdevice.h +++ b/ffbdevice.h @@ -17,16 +17,11 @@ class FFBDevice : public QObject public: explicit FFBDevice(const int fd, const QString& path, const int maxEffectCount, QObject* parent = 0); - QStringList availableConditionSubtypesList() const; - QStringList availableEffectsList() const; - QStringList availableWaveformsList() const; - inline ConditionSubtypes conditionSubtypeByIdx(const int idx) { return m_availableConditionSubtypes[idx]; } - QString conditionSubtypeName(const ConditionSubtypes subtype) const; - QString effectName(const FFBEffectTypes effect) const; + const std::vector& availableConditionSubtypesList() const; + const std::vector& availableEffectsList() const; + const std::vector& availableWaveformsList() const; const std::shared_ptr effectParameters(const int idx); FFBEffect::FFBEffectStatus effectStatusByIdx(const int idx) const; - inline FFBEffectTypes effectTypeFromSelectionIdx(const int idx) const { return m_availableEffects[idx]; } - unsigned int effectTypeToIdx(FFBEffectTypes type); FFBEffectTypes effectTypeByEffectIdx(const int idx) const; bool hasEffect(FFBEffectTypes id) const; bool hasPeriodicWaveform(PeriodicWaveforms id) const; @@ -37,7 +32,6 @@ public: bool startEffect(const int idx, const FFBEffectTypes type, std::shared_ptr parameters); bool stopEffect(const int idx); bool uploadEffect(const int idx, const FFBEffectTypes type, std::shared_ptr parameters); - QString waveformName(const PeriodicWaveforms waveform) const; inline PeriodicWaveforms waveformByIdx(const int idx) const { return m_availablePeriodicWaveforms[idx]; } private: diff --git a/mainwindow.cpp b/mainwindow.cpp index 2220057..c62d60c 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -61,6 +61,24 @@ EffectSettings* MainWindow::effectSettingsByType(FFBEffectTypes type) } } +QString MainWindow::effectTypeToEffectName(const FFBEffectTypes etype) const +{ + switch (etype) { + case FFBEffectTypes::CONSTANT: + return "Constant force"; + case FFBEffectTypes::PERIODIC: + return "Periodic force"; + case FFBEffectTypes::RAMP: + return "Ramp"; + case FFBEffectTypes::CONDITION: + return "Condition"; + case FFBEffectTypes::RUMBLE: + return "Rumble"; + default: + return "Unknown effect"; + } +} + void MainWindow::fillDeviceList() { ui->cbox_devices->clear(); @@ -69,22 +87,25 @@ void MainWindow::fillDeviceList() ui->cbox_devices->addItem(dinfo.tag, dinfo.path); } -void MainWindow::fillEffectSlotsList(const int idx) +void MainWindow::fillEffectSlotsList(const int effectCount) { ui->cbox_effectSlots->clear(); - for (int i = 1; i <= idx; i++) - ui->cbox_effectSlots->addItem(QString::number(i)); + for (int i = 1; i <= effectCount; i++) + ui->cbox_effectSlots->addItem(QString::number(i), i-1); } -void MainWindow::fillEffectTypesList(const QStringList& list) +void MainWindow::fillEffectTypesList(const std::vector& list) { ui->cbox_effectTypes->clear(); - ui->cbox_effectTypes->addItems(list); + for (const FFBEffectTypes etype : list) + ui->cbox_effectTypes->addItem(effectTypeToEffectName(etype), static_cast::type>(etype)); } -void MainWindow::onDeviceSelected(const int idx) +void MainWindow::onDeviceSelected(const int cboxIdx) { - QString path = ui->cbox_devices->itemData(idx, Qt::UserRole).toString(); + Q_UNUSED(cboxIdx); + + QString path = ui->cbox_devices->currentData(Qt::UserRole).toString(); ui->cbox_effectSlots->clear(); m_activeDevice = m_prober->openDevice(path); @@ -95,48 +116,58 @@ void MainWindow::onDeviceSelected(const int idx) fillEffectTypesList(m_activeDevice->availableEffectsList()); m_conditionEffSet->fillAvailableSubtypesList(m_activeDevice->availableConditionSubtypesList()); m_periodicEffSet->fillAvailableWaveformsList(m_activeDevice->availableWaveformsList()); + ui->cbox_effectSlots->setCurrentIndex(0); onEffectSlotSelected(0); } -void MainWindow::onEffectSlotSelected(const int idx) +void MainWindow::onEffectSlotSelected(const int cboxIdx) { - if (idx < 0) - return; + int effectIdx; + bool ok; + + Q_UNUSED(cboxIdx); + if (m_activeDevice == nullptr) return; - FFBEffectTypes type = m_activeDevice->effectTypeByEffectIdx(idx); - qDebug() << static_cast(type); - if (type == FFBEffectTypes::NONE) { + effectIdx = ui->cbox_effectSlots->currentData(Qt::UserRole).toInt(&ok); + if (!ok) { + QMessageBox::critical(this, "Runtime error", "Nonsensical data passed as effect slot index."); + return; + } + FFBEffectTypes etype = m_activeDevice->effectTypeByEffectIdx(effectIdx); + qDebug() << static_cast(etype); + if (etype == FFBEffectTypes::NONE) { qDebug() << "Empty effect"; - ui->cbox_effectTypes->setCurrentIndex(0); - ui->qstw_effectSpecifics->setCurrentWidget(effectSettingsByType(m_activeDevice->effectTypeFromSelectionIdx(0))); + setEffectTypeIndexByType(etype); + ui->qstw_effectSpecifics->setCurrentWidget(effectSettingsByType(FFBEffectTypes::CONSTANT)); setEffectStatusText(FFBEffect::FFBEffectStatus::NOT_LOADED); return; } - const std::shared_ptr params = m_activeDevice->effectParameters(idx); + const std::shared_ptr params = m_activeDevice->effectParameters(effectIdx); /* Set global parameters */ ui->qle_direction->setText(QString::number(params->direction)); ui->qle_replayDelay->setText(QString::number(params->replayDelay)); ui->qle_replayLength->setText(QString::number(params->replayLength)); - EffectSettings* efs = effectSettingsByType(type); + EffectSettings* efs = effectSettingsByType(etype); if (!efs->fillFromParameters(params)) QMessageBox::warning(this, "UI error", "Unable to read effect parameters."); - ui->cbox_effectTypes->setCurrentIndex(m_activeDevice->effectTypeToIdx(type)); + setEffectTypeIndexByType(etype); ui->qstw_effectSpecifics->setCurrentWidget(efs); - setEffectStatusText(m_activeDevice->effectStatusByIdx(idx)); + setEffectStatusText(m_activeDevice->effectStatusByIdx(effectIdx)); } -void MainWindow::onEffectTypeSelected(const int idx) +void MainWindow::onEffectTypeSelected(const int cboxIdx) { - if (idx < 0) - return; + Q_UNUSED(cboxIdx); + if (m_activeDevice == nullptr) return; - ui->qstw_effectSpecifics->setCurrentWidget(effectSettingsByType(m_activeDevice->effectTypeFromSelectionIdx(idx))); + FFBEffectTypes etype = *static_cast(ui->cbox_effectTypes->currentData(Qt::UserRole).data()); + ui->qstw_effectSpecifics->setCurrentWidget(effectSettingsByType(etype)); } void MainWindow::onRefreshDevicesClicked() @@ -156,17 +187,25 @@ void MainWindow::onRemoveEffectClicked() void MainWindow::onStartEffectClicked() { + bool ok; + int effectSlot; + if (m_activeDevice == nullptr) return; - FFBEffectTypes type = m_activeDevice->effectTypeFromSelectionIdx(ui->cbox_effectTypes->currentIndex()); + FFBEffectTypes etype = *static_cast(ui->cbox_effectTypes->currentData(Qt::UserRole).data()); std::shared_ptr params; - int effectSlot = ui->cbox_effectSlots->currentIndex(); - if (!readEffectParameters(params, type)) { + effectSlot = ui->cbox_effectSlots->currentData().toInt(&ok); + if (!ok) { + QMessageBox::critical(this, "Runtime error", "Nonsensical data passed as effect slot index."); + return; + } + + if (!readEffectParameters(params, etype)) { qDebug() << "Cannot read effect params."; return; } - bool ret = m_activeDevice->startEffect(effectSlot, type, params); + bool ret = m_activeDevice->startEffect(effectSlot, etype, params); if (ret) setEffectStatusText(m_activeDevice->effectStatusByIdx(effectSlot)); else @@ -175,28 +214,42 @@ void MainWindow::onStartEffectClicked() void MainWindow::onStopEffectClicked() { + int effectSlot; + bool ok; + if (m_activeDevice == nullptr) return; - int effectSlot = ui->cbox_effectSlots->currentIndex(); + effectSlot = ui->cbox_effectSlots->currentData().toInt(&ok); + if (!ok) { + QMessageBox::critical(this, "Runtime error", "Nonsensical data passed as effect slot index."); + return; + } m_activeDevice->stopEffect(effectSlot); setEffectStatusText(m_activeDevice->effectStatusByIdx(effectSlot)); } void MainWindow::onUploadEffectClicked() { + bool ok; + int effectSlot; + if (m_activeDevice == nullptr) return; - FFBEffectTypes type = m_activeDevice->effectTypeFromSelectionIdx(ui->cbox_effectTypes->currentIndex()); + FFBEffectTypes etype = *static_cast(ui->cbox_effectTypes->currentData(Qt::UserRole).data()); std::shared_ptr params; - int effectSlot = ui->cbox_effectSlots->currentIndex(); + effectSlot = ui->cbox_effectSlots->currentData().toInt(&ok); + if (!ok) { + QMessageBox::critical(this, "Runtime error", "Nonsensical data passed as effect slot index."); + return; + } - if (!readEffectParameters(params, type)) { + if (!readEffectParameters(params, etype)) { qDebug() << "Cannot read effect params."; return; } - bool ret = m_activeDevice->uploadEffect(effectSlot, type, params); + bool ret = m_activeDevice->uploadEffect(effectSlot, etype, params); if (ret) setEffectStatusText(m_activeDevice->effectStatusByIdx(effectSlot)); else @@ -332,8 +385,8 @@ bool MainWindow::readEffectParameters(std::shared_ptr& para return false; } - ConditionSubtypes subtype = m_activeDevice->conditionSubtypeByIdx(m_conditionEffSet->subtypeIdx()); - iParams->subtypeFromIdx(subtype); + ConditionSubtypes subtype = m_conditionEffSet->subtype(); + iParams->subtype = subtype; params = iParams; break; @@ -419,6 +472,17 @@ void MainWindow::setEffectStatusText(const FFBEffect::FFBEffectStatus status) } } +void MainWindow::setEffectTypeIndexByType(const FFBEffectTypes etype) +{ + for (int idx = 0; idx < ui->cbox_effectTypes->count(); idx++) { + FFBEffectTypes ietype = *static_cast(ui->cbox_effectTypes->itemData(idx, Qt::UserRole).data()); + if (ietype == etype) { + ui->cbox_effectTypes->setCurrentIndex(idx); + return; + } + } +} + MainWindow::~MainWindow() { delete ui; diff --git a/mainwindow.h b/mainwindow.h index bbe2216..cdd1ca9 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -29,13 +29,15 @@ public: private: EffectSettings* effectSettingsByType(FFBEffectTypes type); + QString effectTypeToEffectName(const FFBEffectTypes type) const; void fillDeviceList(); - void fillEffectSlotsList(const int idx); - void fillEffectTypesList(const QStringList& list); + void fillEffectSlotsList(const int effectCount); + void fillEffectTypesList(const std::vector& list); bool readEnvelopeParameters(std::shared_ptr params, const EnvelopeSettings* es); - bool readEffectParameters(std::shared_ptr& params, FFBEffectTypes type); + bool readEffectParameters(std::shared_ptr& params, FFBEffectTypes etype); bool readGeneralEffectParameters(std::shared_ptr params); void setEffectStatusText(const FFBEffect::FFBEffectStatus status); + void setEffectTypeIndexByType(const FFBEffectTypes etype); std::shared_ptr m_activeDevice; ConditionEffectSettings* m_conditionEffSet; @@ -53,9 +55,9 @@ private: static const QString res_inputFormatErrCap; private slots: - void onDeviceSelected(const int idx); - void onEffectSlotSelected(const int idx); - void onEffectTypeSelected(const int idx); + void onDeviceSelected(const int cboxIdx); + void onEffectSlotSelected(const int cboxIdx); + void onEffectTypeSelected(const int cboxIdx); void onRefreshDevicesClicked(); void onRemoveEffectClicked(); void onStartEffectClicked(); diff --git a/periodiceffectsettings.cpp b/periodiceffectsettings.cpp index d5d474c..68d7b6b 100644 --- a/periodiceffectsettings.cpp +++ b/periodiceffectsettings.cpp @@ -13,10 +13,11 @@ const EnvelopeSettings* PeriodicEffectSettings::envelopeSettings() const return ui->qwid_envelope; } -void PeriodicEffectSettings::fillAvailableWaveformsList(const QStringList& list) +void PeriodicEffectSettings::fillAvailableWaveformsList(const std::vector& list) { ui->cbox_waveform->clear(); - ui->cbox_waveform->addItems(list); + for (const PeriodicWaveforms waveform : list) + ui->cbox_waveform->addItem(waveformTypeToWaveformName(waveform), static_cast::type>(waveform)); } bool PeriodicEffectSettings::fillFromParameters(const std::shared_ptr params) @@ -56,6 +57,24 @@ QString PeriodicEffectSettings::phase() const return ui->qle_phase->text(); } +QString PeriodicEffectSettings::waveformTypeToWaveformName(const PeriodicWaveforms waveform) const +{ + switch (waveform) { + case PeriodicWaveforms::SQUARE: + return "Square"; + case PeriodicWaveforms::TRIANGLE: + return "Triangle"; + case PeriodicWaveforms::SINE: + return "Sine"; + case PeriodicWaveforms::SAW_UP: + return "Saw up"; + case PeriodicWaveforms::SAW_DOWN: + return "Saw down"; + default: + return "Unknown waveform"; + } +} + int PeriodicEffectSettings::waveformIdx() const { return ui->cbox_waveform->currentIndex(); diff --git a/periodiceffectsettings.h b/periodiceffectsettings.h index 47a4ee3..ea71b09 100644 --- a/periodiceffectsettings.h +++ b/periodiceffectsettings.h @@ -17,12 +17,13 @@ public: explicit PeriodicEffectSettings(QWidget* parent = 0); ~PeriodicEffectSettings(); const EnvelopeSettings* envelopeSettings() const; - void fillAvailableWaveformsList(const QStringList& list); + void fillAvailableWaveformsList(const std::vector& list); bool fillFromParameters(const std::shared_ptr params); QString magnitude() const; QString offset() const; QString period() const; QString phase() const; + QString waveformTypeToWaveformName(const PeriodicWaveforms waveform) const; int waveformIdx() const; private: