File indexing completed on 2024-05-19 04:41:22

0001 /*
0002     SPDX-FileCopyrightText: 2019 Daniel Mensinger <daniel@mensinger-ka.de>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "mesonoptionbaseview.h"
0008 
0009 #include "mesonlisteditor.h"
0010 #include "ui_mesonoptionbaseview.h"
0011 #include <debug.h>
0012 
0013 #include <KColorScheme>
0014 
0015 #include <QCheckBox>
0016 #include <QComboBox>
0017 #include <QLineEdit>
0018 #include <QPalette>
0019 #include <QPushButton>
0020 #include <QSpinBox>
0021 #include <QtGlobal>
0022 
0023 using namespace std;
0024 
0025 // Helper class for RAII signal blocking
0026 class SignalBlocker
0027 {
0028 public:
0029     SignalBlocker(QWidget* widget)
0030         : m_widget(widget)
0031     {
0032         if (m_widget) {
0033             m_widget->blockSignals(true);
0034         }
0035     }
0036 
0037     ~SignalBlocker()
0038     {
0039         if (m_widget) {
0040             m_widget->blockSignals(false);
0041         }
0042     }
0043 
0044 private:
0045     QWidget* m_widget = nullptr;
0046 };
0047 
0048 MesonOptionBaseView::MesonOptionBaseView(MesonOptionPtr option, QWidget* parent)
0049     : QWidget(parent)
0050 {
0051     Q_ASSERT(option);
0052 
0053     m_ui = new Ui::MesonOptionBaseView;
0054     m_ui->setupUi(this);
0055 
0056     m_ui->l_name->setText(option->name() + QStringLiteral(":"));
0057     m_ui->l_name->setToolTip(option->description());
0058     setToolTip(option->description());
0059 }
0060 
0061 MesonOptionBaseView::~MesonOptionBaseView()
0062 {
0063     if (m_ui) {
0064         delete m_ui;
0065     }
0066 }
0067 
0068 // Base class functions
0069 
0070 int MesonOptionBaseView::nameWidth()
0071 {
0072     // Make the name a bit (by 25) wider than it actually is to create a margin. Maybe do
0073     // something smarter in the future (TODO)
0074     return m_ui->l_name->fontMetrics().boundingRect(m_ui->l_name->text()).width() + 25;
0075 }
0076 
0077 void MesonOptionBaseView::setMinNameWidth(int width)
0078 {
0079     m_ui->l_name->setMinimumWidth(width);
0080 }
0081 
0082 void MesonOptionBaseView::setInputWidget(QWidget* input)
0083 {
0084     QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
0085     sizePolicy.setHorizontalStretch(0);
0086     sizePolicy.setVerticalStretch(0);
0087     sizePolicy.setHeightForWidth(input->sizePolicy().hasHeightForWidth());
0088     input->setSizePolicy(sizePolicy);
0089     input->setToolTip(option()->description());
0090     m_ui->layout->insertWidget(1, input);
0091     updateInput();
0092     setChanged(false);
0093 }
0094 
0095 void MesonOptionBaseView::reset()
0096 {
0097     option()->reset();
0098     updateInput();
0099     setChanged(false);
0100 }
0101 
0102 void MesonOptionBaseView::setChanged(bool changed)
0103 {
0104     KColorScheme scheme(QPalette::Normal);
0105     KColorScheme::ForegroundRole role;
0106 
0107     if (changed) {
0108         m_ui->l_name->setStyleSheet(QStringLiteral("font-weight: bold"));
0109         m_ui->b_reset->setDisabled(false);
0110         role = KColorScheme::NeutralText;
0111     } else {
0112         m_ui->l_name->setStyleSheet(QString());
0113         m_ui->b_reset->setDisabled(true);
0114         role = KColorScheme::NormalText;
0115     }
0116 
0117     QPalette pal = m_ui->l_name->palette();
0118     pal.setColor(QPalette::WindowText, scheme.foreground(role).color());
0119     m_ui->l_name->setPalette(pal);
0120     emit configChanged();
0121 }
0122 
0123 std::shared_ptr<MesonOptionBaseView> MesonOptionBaseView::fromOption(MesonOptionPtr option, QWidget* parent)
0124 {
0125     std::shared_ptr<MesonOptionBaseView> opt = nullptr;
0126     switch (option->type()) {
0127     case MesonOptionBase::ARRAY:
0128         opt = make_shared<MesonOptionArrayView>(option, parent);
0129         break;
0130     case MesonOptionBase::BOOLEAN:
0131         opt = make_shared<MesonOptionBoolView>(option, parent);
0132         break;
0133     case MesonOptionBase::COMBO:
0134         opt = make_shared<MesonOptionComboView>(option, parent);
0135         break;
0136     case MesonOptionBase::INTEGER:
0137         opt = make_shared<MesonOptionIntegerView>(option, parent);
0138         break;
0139     case MesonOptionBase::STRING:
0140         opt = make_shared<MesonOptionStringView>(option, parent);
0141         break;
0142     }
0143 
0144     return opt;
0145 }
0146 
0147 // Derived class constructors
0148 
0149 MesonOptionArrayView::MesonOptionArrayView(MesonOptionPtr option, QWidget* parent)
0150     : MesonOptionBaseView(option, parent)
0151     , m_option(dynamic_pointer_cast<MesonOptionArray>(option))
0152 {
0153     Q_ASSERT(m_option);
0154 
0155     m_input = new QPushButton(this);
0156     connect(m_input, &QPushButton::clicked, this, [this]() {
0157         MesonListEditor editor(m_option->rawValue(), this);
0158         if (editor.exec() == QDialog::Accepted) {
0159             m_option->setValue(editor.content());
0160             m_input->setText(m_option->value());
0161             setChanged(m_option->isUpdated());
0162         }
0163     });
0164     setInputWidget(m_input);
0165 }
0166 
0167 MesonOptionBoolView::MesonOptionBoolView(MesonOptionPtr option, QWidget* parent)
0168     : MesonOptionBaseView(option, parent)
0169     , m_option(dynamic_pointer_cast<MesonOptionBool>(option))
0170 {
0171     Q_ASSERT(m_option);
0172 
0173     m_input = new QCheckBox(this);
0174     connect(m_input, &QCheckBox::stateChanged, this, &MesonOptionBoolView::updated);
0175     setInputWidget(m_input);
0176 }
0177 
0178 MesonOptionComboView::MesonOptionComboView(MesonOptionPtr option, QWidget* parent)
0179     : MesonOptionBaseView(option, parent)
0180     , m_option(dynamic_pointer_cast<MesonOptionCombo>(option))
0181 {
0182     Q_ASSERT(m_option);
0183 
0184     m_input = new QComboBox(this);
0185     m_input->clear();
0186     m_input->addItems(m_option->choices());
0187     m_input->setEditable(false);
0188     connect(m_input, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &MesonOptionComboView::updated);
0189     setInputWidget(m_input);
0190 }
0191 
0192 MesonOptionIntegerView::MesonOptionIntegerView(MesonOptionPtr option, QWidget* parent)
0193     : MesonOptionBaseView(option, parent)
0194     , m_option(dynamic_pointer_cast<MesonOptionInteger>(option))
0195 {
0196     Q_ASSERT(m_option);
0197 
0198     m_input = new QSpinBox(this);
0199     m_input->setMinimum(INT32_MIN);
0200     m_input->setMaximum(INT32_MAX);
0201     connect(m_input, QOverload<int>::of(&QSpinBox::valueChanged), this, &MesonOptionIntegerView::updated);
0202     setInputWidget(m_input);
0203 }
0204 
0205 MesonOptionStringView::MesonOptionStringView(MesonOptionPtr option, QWidget* parent)
0206     : MesonOptionBaseView(option, parent)
0207     , m_option(dynamic_pointer_cast<MesonOptionString>(option))
0208 {
0209     Q_ASSERT(m_option);
0210 
0211     m_input = new QLineEdit(this);
0212     connect(m_input, &QLineEdit::textChanged, this, &MesonOptionStringView::updated);
0213     setInputWidget(m_input);
0214 }
0215 
0216 // Option getters
0217 
0218 MesonOptionBase* MesonOptionArrayView::option()
0219 {
0220     return m_option.get();
0221 }
0222 
0223 MesonOptionBase* MesonOptionBoolView::option()
0224 {
0225     return m_option.get();
0226 }
0227 
0228 MesonOptionBase* MesonOptionComboView::option()
0229 {
0230     return m_option.get();
0231 }
0232 
0233 MesonOptionBase* MesonOptionIntegerView::option()
0234 {
0235     return m_option.get();
0236 }
0237 
0238 MesonOptionBase* MesonOptionStringView::option()
0239 {
0240     return m_option.get();
0241 }
0242 
0243 // Updaters for the input widget
0244 
0245 void MesonOptionArrayView::updateInput()
0246 {
0247     SignalBlocker block(m_input);
0248     m_input->setText(m_option->value());
0249 }
0250 
0251 void MesonOptionBoolView::updateInput()
0252 {
0253     SignalBlocker block(m_input);
0254     m_input->setCheckState(m_option->rawValue() ? Qt::Checked : Qt::Unchecked);
0255 }
0256 
0257 void MesonOptionComboView::updateInput()
0258 {
0259     SignalBlocker block(m_input);
0260     m_input->setCurrentText(m_option->rawValue());
0261 }
0262 
0263 void MesonOptionIntegerView::updateInput()
0264 {
0265     SignalBlocker block(m_input);
0266     m_input->setValue(m_option->rawValue());
0267 }
0268 
0269 void MesonOptionStringView::updateInput()
0270 {
0271     SignalBlocker block(m_input);
0272     m_input->setText(m_option->rawValue());
0273 }
0274 
0275 // Slots to update the option value
0276 
0277 void MesonOptionBoolView::updated()
0278 {
0279     m_option->setValue(m_input->isChecked());
0280     setChanged(m_option->isUpdated());
0281 }
0282 
0283 void MesonOptionComboView::updated()
0284 {
0285     m_option->setValue(m_input->currentText());
0286     setChanged(m_option->isUpdated());
0287 }
0288 
0289 void MesonOptionIntegerView::updated()
0290 {
0291     m_option->setValue(m_input->value());
0292     setChanged(m_option->isUpdated());
0293 }
0294 
0295 void MesonOptionStringView::updated()
0296 {
0297     m_option->setValue(m_input->text());
0298     setChanged(m_option->isUpdated());
0299 }
0300 
0301 #include "moc_mesonoptionbaseview.cpp"