File indexing completed on 2022-09-27 13:41:20

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