File indexing completed on 2024-04-14 04:15:17
0001 /* 0002 SPDX-FileCopyrightText: 2001 The Kompany 0003 SPDX-FileCopyrightText: 2002-2003 Ilya Konstantinov <kde-devel@future.shiny.co.il> 0004 SPDX-FileCopyrightText: 2002-2003 Marcus Meissner <marcus@jet.franken.de> 0005 SPDX-FileCopyrightText: 2003 Nadeem Hasan <nhasan@nadmm.com> 0006 0007 SPDX-License-Identifier: GPL-2.0-or-later 0008 */ 0009 0010 #include "kameraconfigdialog.h" 0011 0012 #include <QCheckBox> 0013 #include <QComboBox> 0014 #include <QDialogButtonBox> 0015 #include <QFrame> 0016 #include <QGroupBox> 0017 #include <QLabel> 0018 #include <QLineEdit> 0019 #include <QPushButton> 0020 #include <QRadioButton> 0021 #include <QScrollArea> 0022 #include <QSlider> 0023 #include <QVBoxLayout> 0024 0025 #include <KLocalizedString> 0026 0027 #include "kcm_kamera_log.h" 0028 0029 KameraConfigDialog::KameraConfigDialog(Camera * /*camera*/, CameraWidget *widget, QWidget *parent) 0030 : QDialog(parent) 0031 , m_widgetRoot(widget) 0032 { 0033 auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this); 0034 0035 auto mainWidget = new QWidget(this); 0036 auto mainLayout = new QVBoxLayout; 0037 setLayout(mainLayout); 0038 mainLayout->addWidget(mainWidget); 0039 mainLayout->setContentsMargins(0, 0, 0, 0); 0040 0041 QPushButton *okButton = buttonBox->button(QDialogButtonBox::Ok); 0042 okButton->setDefault(true); 0043 okButton->setShortcut(Qt::CTRL | Qt::Key_Return); 0044 0045 connect(buttonBox, &QDialogButtonBox::accepted, this, &KameraConfigDialog::accept); 0046 connect(buttonBox, &QDialogButtonBox::rejected, this, &KameraConfigDialog::reject); 0047 okButton->setDefault(true); 0048 setModal(true); 0049 0050 auto main = new QFrame(this); 0051 mainLayout->addWidget(main); 0052 0053 // Sets a layout for the frame, which is the parent of the GP_WIDGET_WINDOW 0054 auto topLayout = new QVBoxLayout(main); 0055 topLayout->setContentsMargins(0, 0, 0, 0); 0056 0057 m_tabWidget = nullptr; 0058 0059 appendWidget(main, widget); 0060 0061 connect(okButton, &QPushButton::clicked, this, &KameraConfigDialog::slotOk); 0062 mainLayout->addWidget(buttonBox); 0063 } 0064 0065 void KameraConfigDialog::appendWidget(QWidget *parent, CameraWidget *widget) 0066 { 0067 QWidget *newParent = parent; 0068 0069 CameraWidgetType widget_type; 0070 const char *widget_name; 0071 const char *widget_info; 0072 const char *widget_label; 0073 float widget_value_float; 0074 int widget_value_int; 0075 const char *widget_value_string = nullptr; 0076 gp_widget_get_type(widget, &widget_type); 0077 gp_widget_get_label(widget, &widget_label); 0078 gp_widget_get_info(widget, &widget_info); 0079 gp_widget_get_name(widget, &widget_name); 0080 0081 QString whats_this = QString::fromLocal8Bit(widget_info); // gphoto2 doesn't seem to have any standard for i18n 0082 0083 // Add this widget to parent 0084 switch (widget_type) { 0085 case GP_WIDGET_WINDOW: { 0086 setWindowTitle(QString::fromLocal8Bit(widget_label)); 0087 break; 0088 } 0089 case GP_WIDGET_SECTION: { 0090 if (!m_tabWidget) { 0091 m_tabWidget = new QTabWidget(parent); 0092 parent->layout()->addWidget(m_tabWidget); 0093 } 0094 auto tab = new QWidget; 0095 // widgets are to be aligned vertically in the tab 0096 auto tabLayout = new QVBoxLayout(tab); 0097 tabLayout->setContentsMargins(0, 0, 0, 0); 0098 m_tabWidget->addTab(tab, QString::fromLocal8Bit(widget_label)); 0099 0100 // Add scroll area 0101 auto scrollArea = new QScrollArea(tab); 0102 scrollArea->setWidgetResizable(true); 0103 scrollArea->setFrameShape(QFrame::NoFrame); 0104 tabLayout->addWidget(scrollArea); 0105 0106 // Add a container widget to hold the page 0107 auto tabContainer = new QWidget(tab); 0108 // Add a layout for later parent->layout()->... calls 0109 new QVBoxLayout(tabContainer); 0110 0111 // Set the container as the widget to be managed by the ScrollArea 0112 scrollArea->setWidget(tabContainer); 0113 scrollArea->show(); 0114 0115 newParent = tabContainer; 0116 break; 0117 } 0118 case GP_WIDGET_TEXT: 0119 case GP_WIDGET_RANGE: 0120 case GP_WIDGET_TOGGLE: { 0121 // Share the QGridLayout code 0122 auto grid = new QWidget(parent); 0123 auto gridLayout = new QGridLayout(grid); 0124 grid->setLayout(gridLayout); 0125 parent->layout()->addWidget(grid); 0126 0127 QLabel *label = nullptr; 0128 if (widget_type == GP_WIDGET_TEXT) { 0129 gp_widget_get_value(widget, &widget_value_string); 0130 0131 label = new QLabel(QString::fromLocal8Bit(widget_label) + QLatin1Char(':'), grid); 0132 auto lineEdit = new QLineEdit(widget_value_string, grid); 0133 0134 gridLayout->addWidget(lineEdit, 0, 1, Qt::AlignRight); 0135 m_wmap.insert(widget, lineEdit); 0136 } else if (widget_type == GP_WIDGET_RANGE) { 0137 float widget_low; 0138 float widget_high; 0139 float widget_increment; 0140 gp_widget_get_range(widget, &widget_low, &widget_high, &widget_increment); 0141 gp_widget_get_value(widget, &widget_value_float); 0142 0143 label = new QLabel(QString::fromLocal8Bit(widget_label) + ':', grid); 0144 auto slider = new QSlider(Qt::Horizontal, grid); 0145 0146 gridLayout->addWidget(slider, 0, 1, Qt::AlignRight); 0147 m_wmap.insert(widget, slider); 0148 } else if (widget_type == GP_WIDGET_TOGGLE) { 0149 gp_widget_get_value(widget, &widget_value_int); 0150 0151 label = new QLabel(QString::fromLocal8Bit(widget_label), grid); 0152 auto checkBox = new QCheckBox(grid); 0153 checkBox->setChecked(widget_value_int); 0154 0155 gridLayout->addWidget(checkBox, 0, 1, Qt::AlignRight); 0156 m_wmap.insert(widget, checkBox); 0157 break; 0158 } 0159 if (label) { 0160 gridLayout->addWidget(label, 0, 0, Qt::AlignLeft); 0161 } 0162 break; 0163 } 0164 case GP_WIDGET_RADIO: { 0165 gp_widget_get_value(widget, &widget_value_string); 0166 0167 int count = gp_widget_count_choices(widget); 0168 // KDE4 code used Q3V/HBoxGroup to specify alignment based on count 0169 // For fewer than 5 options, align them horizontally 0170 QBoxLayout *layout; 0171 if (count < 5) { 0172 layout = new QHBoxLayout; 0173 } else { 0174 layout = new QVBoxLayout; 0175 } 0176 auto buttonGroup = new QGroupBox(QString::fromLocal8Bit(widget_label), parent); 0177 parent->layout()->addWidget(buttonGroup); 0178 0179 for (int i = 0; i < count; ++i) { 0180 const char *widget_choice; 0181 gp_widget_get_choice(widget, i, &widget_choice); 0182 0183 auto newestButton = new QRadioButton(widget_choice); 0184 if (widget_value_string && !strcmp(widget_value_string, widget_choice)) { 0185 newestButton->setChecked(true); 0186 } 0187 layout->addWidget(newestButton); 0188 } 0189 m_wmap.insert(widget, buttonGroup); 0190 0191 buttonGroup->setLayout(layout); 0192 0193 if (!whats_this.isEmpty()) { 0194 buttonGroup->setWhatsThis(whats_this); 0195 } 0196 0197 break; 0198 } 0199 case GP_WIDGET_MENU: { 0200 gp_widget_get_value(widget, &widget_value_string); 0201 0202 auto comboBox = new QComboBox(parent); 0203 parent->layout()->addWidget(comboBox); 0204 comboBox->clear(); 0205 for (int i = 0; i < gp_widget_count_choices(widget); ++i) { 0206 const char *widget_choice; 0207 gp_widget_get_choice(widget, i, &widget_choice); 0208 0209 comboBox->addItem(widget_choice); 0210 if (widget_value_string && !strcmp(widget_value_string, widget_choice)) 0211 comboBox->setCurrentIndex(i); 0212 } 0213 m_wmap.insert(widget, comboBox); 0214 0215 if (!whats_this.isEmpty()) { 0216 comboBox->setWhatsThis(whats_this); 0217 } 0218 0219 break; 0220 } 0221 case GP_WIDGET_BUTTON: { 0222 // TODO 0223 // I can't see a way of implementing this. Since there is 0224 // no way of telling which button sent you a signal, we 0225 // can't map to the appropriate widget->callback 0226 auto label = new QLabel(i18n("Button (not supported by KControl)"), parent); 0227 parent->layout()->addWidget(label); 0228 0229 break; 0230 } 0231 case GP_WIDGET_DATE: { 0232 // TODO 0233 auto label = new QLabel(i18n("Date (not supported by KControl)"), parent); 0234 parent->layout()->addWidget(label); 0235 0236 break; 0237 } 0238 default: 0239 return; 0240 } 0241 0242 // Append all this widgets children 0243 for (int i = 0; i < gp_widget_count_children(widget); ++i) { 0244 CameraWidget *widget_child; 0245 gp_widget_get_child(widget, i, &widget_child); 0246 appendWidget(newParent, widget_child); 0247 } 0248 0249 if (widget_type == GP_WIDGET_SECTION) { 0250 // Get latest tab 0251 QWidget *tab = m_tabWidget->widget(m_tabWidget->count() - 1); 0252 auto scrollArea = dynamic_cast<QScrollArea *>(tab->children().at(1)); 0253 if (scrollArea) { 0254 auto vbox_layout = dynamic_cast<QVBoxLayout *>(scrollArea->widget()->layout()); 0255 if (vbox_layout) { 0256 vbox_layout->addStretch(); 0257 } 0258 } 0259 } 0260 } 0261 0262 void KameraConfigDialog::updateWidgetValue(CameraWidget *widget) 0263 { 0264 CameraWidgetType widget_type; 0265 gp_widget_get_type(widget, &widget_type); 0266 0267 switch (widget_type) { 0268 case GP_WIDGET_WINDOW: 0269 // nothing to do 0270 break; 0271 case GP_WIDGET_SECTION: 0272 // nothing to do 0273 break; 0274 case GP_WIDGET_TEXT: { 0275 auto lineEdit = static_cast<QLineEdit *>(m_wmap[widget]); 0276 gp_widget_set_value(widget, (void *)lineEdit->text().toLocal8Bit().data()); 0277 0278 break; 0279 } 0280 case GP_WIDGET_RANGE: { 0281 auto slider = static_cast<QSlider *>(m_wmap[widget]); 0282 float value_float = slider->value(); 0283 gp_widget_set_value(widget, (void *)&value_float); 0284 0285 break; 0286 } 0287 case GP_WIDGET_TOGGLE: { 0288 auto checkBox = static_cast<QCheckBox *>(m_wmap[widget]); 0289 int value_int = checkBox->isChecked() ? 1 : 0; 0290 gp_widget_set_value(widget, (void *)&value_int); 0291 0292 break; 0293 } 0294 case GP_WIDGET_RADIO: { 0295 auto buttonGroup = static_cast<QGroupBox *>(m_wmap[widget]); 0296 for (auto button : buttonGroup->children()) { 0297 auto radButton = static_cast<QRadioButton *>(button); 0298 if (radButton->isChecked()) { 0299 gp_widget_set_value(widget, (void *)radButton->text().toLocal8Bit().data()); 0300 break; 0301 } 0302 } 0303 break; 0304 } 0305 case GP_WIDGET_MENU: { 0306 auto comboBox = static_cast<QComboBox *>(m_wmap[widget]); 0307 gp_widget_set_value(widget, (void *)comboBox->currentText().toLocal8Bit().data()); 0308 0309 break; 0310 } 0311 case GP_WIDGET_BUTTON: 0312 // nothing to do 0313 break; 0314 case GP_WIDGET_DATE: { 0315 // not implemented 0316 break; 0317 } 0318 } 0319 0320 // Copy child widget values 0321 for (int i = 0; i < gp_widget_count_children(widget); ++i) { 0322 CameraWidget *widget_child; 0323 gp_widget_get_child(widget, i, &widget_child); 0324 updateWidgetValue(widget_child); 0325 } 0326 } 0327 0328 void KameraConfigDialog::slotOk() 0329 { 0330 // Copy Qt widget values into CameraWidget hierarchy 0331 updateWidgetValue(m_widgetRoot); 0332 0333 // 'ok' dialog 0334 accept(); 0335 } 0336 0337 #include "moc_kameraconfigdialog.cpp"