File indexing completed on 2024-05-19 04:29:31
0001 /* 0002 * SPDX-FileCopyrightText: 2022 Dmitry Kazakov <dimula73@gmail.com> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "KisWidgetConnectionUtils.h" 0008 0009 #include <QMetaObject> 0010 #include <QMetaProperty> 0011 #include <QAbstractButton> 0012 #include <QAction> 0013 #include <QComboBox> 0014 #include <QButtonGroup> 0015 #include <QSpinBox> 0016 #include <QDoubleSpinBox> 0017 #include <QLineEdit> 0018 #include "kis_debug.h" 0019 #include "kis_spacing_selection_widget.h" 0020 #include "kis_multipliers_double_slider_spinbox.h" 0021 #include "KisAngleSelector.h" 0022 #include "kis_file_name_requester.h" 0023 0024 class ConnectButtonStateHelper : public QObject 0025 { 0026 Q_OBJECT 0027 public: 0028 0029 ConnectButtonStateHelper(QAbstractButton *parent) 0030 : QObject(parent), 0031 m_button(parent) 0032 { 0033 } 0034 public Q_SLOTS: 0035 void updateState(const CheckBoxState &state) { 0036 QSignalBlocker b(m_button); 0037 m_button->setEnabled(state.enabled); 0038 m_button->setChecked(state.value); 0039 0040 // TODO: verify if the two properties are equal or the control is disabled 0041 } 0042 0043 private: 0044 QAbstractButton *m_button; 0045 }; 0046 0047 class ConnectComboBoxStateHelper : public QObject 0048 { 0049 Q_OBJECT 0050 public: 0051 0052 ConnectComboBoxStateHelper(QComboBox *parent) 0053 : QObject(parent), 0054 m_comboBox(parent) 0055 { 0056 } 0057 public Q_SLOTS: 0058 void updateState(const ComboBoxState &state) { 0059 QSignalBlocker b(m_comboBox); 0060 0061 while (m_comboBox->count() > 0) { 0062 m_comboBox->removeItem(0); 0063 } 0064 0065 m_comboBox->addItems(state.items); 0066 m_comboBox->setCurrentIndex(state.currentIndex); 0067 m_comboBox->setEnabled(state.enabled); 0068 0069 // TODO: verify if the two properties are equal or the control is disabled 0070 } 0071 0072 private: 0073 QComboBox *m_comboBox; 0074 }; 0075 0076 0077 namespace KisWidgetConnectionUtils { 0078 0079 template<typename Button> 0080 void connectButtonLikeControl(Button *button, QObject *source, const char *property) 0081 { 0082 const QMetaObject* meta = source->metaObject(); 0083 QMetaProperty prop = meta->property(meta->indexOfProperty(property)); 0084 0085 KIS_SAFE_ASSERT_RECOVER_RETURN(prop.hasNotifySignal()); 0086 0087 QMetaMethod signal = prop.notifySignal(); 0088 0089 KIS_SAFE_ASSERT_RECOVER_RETURN(signal.parameterCount() >= 1); 0090 KIS_SAFE_ASSERT_RECOVER_RETURN(signal.parameterType(0) == QMetaType::type("bool")); 0091 0092 const QMetaObject* dstMeta = button->metaObject(); 0093 0094 QMetaMethod updateSlot = dstMeta->method( 0095 dstMeta->indexOfSlot("setChecked(bool)")); 0096 QObject::connect(source, signal, button, updateSlot); 0097 0098 button->setChecked(prop.read(source).toBool()); 0099 0100 if (prop.isWritable()) { 0101 QObject::connect(button, &Button::toggled, 0102 source, [prop, source] (bool value) { prop.write(source, value); }); 0103 } 0104 } 0105 0106 void connectControl(QAbstractButton *button, QObject *source, const char *property) 0107 { 0108 connectButtonLikeControl(button, source, property); 0109 } 0110 0111 void connectControl(QAction *button, QObject *source, const char *property) 0112 { 0113 connectButtonLikeControl(button, source, property); 0114 } 0115 0116 void connectControl(QSpinBox *spinBox, QObject *source, const char *property) 0117 { 0118 const QMetaObject* meta = source->metaObject(); 0119 QMetaProperty prop = meta->property(meta->indexOfProperty(property)); 0120 0121 KIS_SAFE_ASSERT_RECOVER_RETURN(prop.hasNotifySignal()); 0122 0123 QMetaMethod signal = prop.notifySignal(); 0124 0125 KIS_SAFE_ASSERT_RECOVER_RETURN(signal.parameterCount() >= 1); 0126 KIS_SAFE_ASSERT_RECOVER_RETURN(signal.parameterType(0) == QMetaType::type("int")); 0127 0128 const QMetaObject* dstMeta = spinBox->metaObject(); 0129 0130 QMetaMethod updateSlot = dstMeta->method( 0131 dstMeta->indexOfSlot("setValue(int)")); 0132 QObject::connect(source, signal, spinBox, updateSlot); 0133 0134 spinBox->setValue(prop.read(source).toInt()); 0135 0136 if (prop.isWritable()) { 0137 QObject::connect(spinBox, qOverload<int>(&QSpinBox::valueChanged), 0138 source, [prop, source] (int value) { prop.write(source, value); }); 0139 } 0140 } 0141 0142 void connectControl(QDoubleSpinBox *spinBox, QObject *source, const char *property) 0143 { 0144 const QMetaObject* meta = source->metaObject(); 0145 QMetaProperty prop = meta->property(meta->indexOfProperty(property)); 0146 0147 KIS_SAFE_ASSERT_RECOVER_RETURN(prop.hasNotifySignal()); 0148 0149 QMetaMethod signal = prop.notifySignal(); 0150 0151 KIS_SAFE_ASSERT_RECOVER_RETURN(signal.parameterCount() >= 1); 0152 KIS_SAFE_ASSERT_RECOVER_RETURN(signal.parameterType(0) == QMetaType::type("qreal")); 0153 0154 const QMetaObject* dstMeta = spinBox->metaObject(); 0155 0156 QMetaMethod updateSlot = dstMeta->method( 0157 dstMeta->indexOfSlot("setValue(qreal)")); 0158 QObject::connect(source, signal, spinBox, updateSlot); 0159 0160 spinBox->setValue(prop.read(source).toReal()); 0161 0162 if (prop.isWritable()) { 0163 QObject::connect(spinBox, qOverload<qreal>(&QDoubleSpinBox::valueChanged), 0164 source, [prop, source] (qreal value) { prop.write(source, value); }); 0165 } 0166 } 0167 0168 class ConnectIntSpinBoxStateHelper : public QObject 0169 { 0170 Q_OBJECT 0171 public: 0172 0173 ConnectIntSpinBoxStateHelper(QSpinBox *parent) 0174 : QObject(parent), 0175 m_spinBox(parent) 0176 { 0177 } 0178 public Q_SLOTS: 0179 void setState(IntSpinBoxState state) { 0180 QSignalBlocker b(m_spinBox); 0181 0182 m_spinBox->setEnabled(state.enabled); 0183 m_spinBox->setRange(state.min, state.max); 0184 m_spinBox->setValue(state.value); 0185 } 0186 0187 private: 0188 QSpinBox *m_spinBox; 0189 }; 0190 0191 0192 void connectControlState(QSpinBox *spinBox, QObject *source, const char *readStateProperty, const char *writeProperty) 0193 { 0194 const QMetaObject* meta = source->metaObject(); 0195 QMetaProperty readStateProp = meta->property(meta->indexOfProperty(readStateProperty)); 0196 0197 KIS_SAFE_ASSERT_RECOVER_RETURN(readStateProp.hasNotifySignal()); 0198 0199 QMetaMethod signal = readStateProp.notifySignal(); 0200 0201 KIS_SAFE_ASSERT_RECOVER_RETURN(signal.parameterCount() >= 1); 0202 KIS_SAFE_ASSERT_RECOVER_RETURN(signal.parameterType(0) == QMetaType::type("IntSpinBoxState")); 0203 0204 ConnectIntSpinBoxStateHelper *helper = new ConnectIntSpinBoxStateHelper(spinBox); 0205 0206 const QMetaObject* dstMeta = helper->metaObject(); 0207 0208 QMetaMethod updateSlot = dstMeta->method( 0209 dstMeta->indexOfSlot("setState(IntSpinBoxState)")); 0210 QObject::connect(source, signal, helper, updateSlot); 0211 0212 helper->setState(readStateProp.read(source).value<IntSpinBoxState>()); 0213 0214 QMetaProperty writeProp = meta->property(meta->indexOfProperty(writeProperty)); 0215 if (writeProp.isWritable()) { 0216 QObject::connect(spinBox, qOverload<int>(&QSpinBox::valueChanged), 0217 source, [writeProp, source] (int value) { writeProp.write(source, value); }); 0218 } 0219 } 0220 0221 class ConnectDoubleSpinBoxStateHelper : public QObject 0222 { 0223 Q_OBJECT 0224 public: 0225 0226 ConnectDoubleSpinBoxStateHelper(QDoubleSpinBox *parent) 0227 : QObject(parent), 0228 m_spinBox(parent) 0229 { 0230 } 0231 public Q_SLOTS: 0232 void setState(DoubleSpinBoxState state) { 0233 QSignalBlocker b(m_spinBox); 0234 0235 m_spinBox->setEnabled(state.enabled); 0236 m_spinBox->setRange(state.min, state.max); 0237 m_spinBox->setValue(state.value); 0238 } 0239 0240 private: 0241 QDoubleSpinBox *m_spinBox; 0242 }; 0243 0244 0245 void connectControlState(QDoubleSpinBox *spinBox, QObject *source, const char *readStateProperty, const char *writeProperty) 0246 { 0247 const QMetaObject* meta = source->metaObject(); 0248 QMetaProperty readStateProp = meta->property(meta->indexOfProperty(readStateProperty)); 0249 0250 KIS_SAFE_ASSERT_RECOVER_RETURN(readStateProp.hasNotifySignal()); 0251 0252 QMetaMethod signal = readStateProp.notifySignal(); 0253 0254 KIS_SAFE_ASSERT_RECOVER_RETURN(signal.parameterCount() >= 1); 0255 KIS_SAFE_ASSERT_RECOVER_RETURN(signal.parameterType(0) == QMetaType::type("DoubleSpinBoxState")); 0256 0257 ConnectDoubleSpinBoxStateHelper *helper = new ConnectDoubleSpinBoxStateHelper(spinBox); 0258 0259 const QMetaObject* dstMeta = helper->metaObject(); 0260 0261 QMetaMethod updateSlot = dstMeta->method( 0262 dstMeta->indexOfSlot("setState(DoubleSpinBoxState)")); 0263 QObject::connect(source, signal, helper, updateSlot); 0264 0265 helper->setState(readStateProp.read(source).value<DoubleSpinBoxState>()); 0266 0267 QMetaProperty writeProp = meta->property(meta->indexOfProperty(writeProperty)); 0268 if (writeProp.isWritable()) { 0269 QObject::connect(spinBox, qOverload<qreal>(&QDoubleSpinBox::valueChanged), 0270 source, [writeProp, source] (qreal value) { writeProp.write(source, value); }); 0271 } 0272 } 0273 0274 0275 void connectControl(KisMultipliersDoubleSliderSpinBox *spinBox, QObject *source, const char *property) 0276 { 0277 const QMetaObject* meta = source->metaObject(); 0278 QMetaProperty prop = meta->property(meta->indexOfProperty(property)); 0279 0280 KIS_SAFE_ASSERT_RECOVER_RETURN(prop.hasNotifySignal()); 0281 0282 QMetaMethod signal = prop.notifySignal(); 0283 0284 KIS_SAFE_ASSERT_RECOVER_RETURN(signal.parameterCount() >= 1); 0285 KIS_SAFE_ASSERT_RECOVER_RETURN(signal.parameterType(0) == QMetaType::type("qreal")); 0286 0287 const QMetaObject* dstMeta = spinBox->metaObject(); 0288 0289 QMetaMethod updateSlot = dstMeta->method( 0290 dstMeta->indexOfSlot("setValue(qreal)")); 0291 QObject::connect(source, signal, spinBox, updateSlot); 0292 0293 spinBox->setValue(prop.read(source).toReal()); 0294 0295 if (prop.isWritable()) { 0296 QObject::connect(spinBox, qOverload<qreal>(&KisMultipliersDoubleSliderSpinBox::valueChanged), 0297 source, [prop, source] (qreal value) { prop.write(source, value); }); 0298 } 0299 } 0300 0301 0302 class ConnectButtonGroupHelper : public QObject 0303 { 0304 Q_OBJECT 0305 public: 0306 0307 ConnectButtonGroupHelper(QButtonGroup *parent) 0308 : QObject(parent), 0309 m_buttonGroup(parent) 0310 { 0311 QObject::connect(m_buttonGroup, qOverload<QAbstractButton *>(&QButtonGroup::buttonClicked), this, &ConnectButtonGroupHelper::slotButtonClicked); 0312 } 0313 public Q_SLOTS: 0314 void updateState(int value) { 0315 QAbstractButton *btn = m_buttonGroup->button(value); 0316 KIS_SAFE_ASSERT_RECOVER_RETURN(btn); 0317 btn->setChecked(true); 0318 } 0319 0320 void updateState(ButtonGroupState state) { 0321 QAbstractButton *btn = m_buttonGroup->button(state.value); 0322 KIS_SAFE_ASSERT_RECOVER_RETURN(btn); 0323 btn->setChecked(true); 0324 0325 Q_FOREACH (QAbstractButton *btn, m_buttonGroup->buttons()) { 0326 btn->setEnabled(state.enabled); 0327 } 0328 } 0329 0330 void slotButtonClicked(QAbstractButton *btn) { 0331 int id = m_buttonGroup->id(btn); 0332 KIS_SAFE_ASSERT_RECOVER_RETURN(id >= 0); 0333 0334 Q_EMIT idClicked(id); 0335 } 0336 0337 Q_SIGNALS: 0338 // this signal was added only in Qt 5.15 0339 void idClicked(int id); 0340 0341 private: 0342 QButtonGroup *m_buttonGroup; 0343 }; 0344 0345 void connectControl(QButtonGroup *group, QObject *source, const char *property) 0346 { 0347 const QMetaObject* meta = source->metaObject(); 0348 QMetaProperty prop = meta->property(meta->indexOfProperty(property)); 0349 0350 KIS_SAFE_ASSERT_RECOVER_RETURN(prop.hasNotifySignal()); 0351 0352 QMetaMethod signal = prop.notifySignal(); 0353 0354 KIS_SAFE_ASSERT_RECOVER_RETURN(signal.parameterCount() >= 1); 0355 KIS_SAFE_ASSERT_RECOVER_RETURN(signal.parameterType(0) == QMetaType::type("int")); 0356 0357 0358 ConnectButtonGroupHelper *helper = new ConnectButtonGroupHelper(group); 0359 0360 const QMetaObject* dstMeta = helper->metaObject(); 0361 0362 QMetaMethod updateSlot = dstMeta->method( 0363 dstMeta->indexOfSlot("updateState(int)")); 0364 QObject::connect(source, signal, helper, updateSlot); 0365 0366 helper->updateState(prop.read(source).toInt()); 0367 0368 if (prop.isWritable()) { 0369 QObject::connect(helper, &ConnectButtonGroupHelper::idClicked, 0370 source, [prop, source] (int value) { prop.write(source, value); }); 0371 } 0372 } 0373 0374 void connectControlState(QButtonGroup *group, QObject *source, const char *readStateProperty, const char *writeProperty) 0375 { 0376 const QMetaObject* meta = source->metaObject(); 0377 QMetaProperty readStateProp = meta->property(meta->indexOfProperty(readStateProperty)); 0378 0379 KIS_SAFE_ASSERT_RECOVER_RETURN(readStateProp.hasNotifySignal()); 0380 0381 QMetaMethod signal = readStateProp.notifySignal(); 0382 0383 KIS_SAFE_ASSERT_RECOVER_RETURN(signal.parameterCount() >= 1); 0384 KIS_SAFE_ASSERT_RECOVER_RETURN(signal.parameterType(0) == QMetaType::type("ButtonGroupState")); 0385 0386 ConnectButtonGroupHelper *helper = new ConnectButtonGroupHelper(group); 0387 0388 const QMetaObject* dstMeta = helper->metaObject(); 0389 0390 QMetaMethod updateSlot = dstMeta->method( 0391 dstMeta->indexOfSlot("updateState(ButtonGroupState)")); 0392 QObject::connect(source, signal, helper, updateSlot); 0393 0394 helper->updateState(readStateProp.read(source).value<ButtonGroupState>()); 0395 0396 QMetaProperty writeProp = meta->property(meta->indexOfProperty(writeProperty)); 0397 if (writeProp.isWritable()) { 0398 QObject::connect(helper, &ConnectButtonGroupHelper::idClicked, 0399 source, [writeProp, source] (int value) { writeProp.write(source, value); }); 0400 } 0401 } 0402 0403 void connectControlState(QAbstractButton *button, QObject *source, const char *readStatePropertyName, const char *writePropertyName) 0404 { 0405 const QMetaObject* meta = source->metaObject(); 0406 QMetaProperty readStateProp = meta->property(meta->indexOfProperty(readStatePropertyName)); 0407 0408 KIS_SAFE_ASSERT_RECOVER_RETURN(readStateProp.hasNotifySignal()); 0409 0410 QMetaMethod signal = readStateProp.notifySignal(); 0411 0412 KIS_SAFE_ASSERT_RECOVER_RETURN(signal.parameterCount() >= 1); 0413 KIS_SAFE_ASSERT_RECOVER_RETURN(signal.parameterType(0) == QMetaType::type("CheckBoxState")); 0414 0415 ConnectButtonStateHelper *helper = new ConnectButtonStateHelper(button); 0416 0417 const QMetaObject* dstMeta = helper->metaObject(); 0418 0419 QMetaMethod updateSlot = dstMeta->method( 0420 dstMeta->indexOfSlot("updateState(CheckBoxState)")); 0421 QObject::connect(source, signal, helper, updateSlot); 0422 0423 helper->updateState(readStateProp.read(source).value<CheckBoxState>()); 0424 0425 QMetaProperty writeProp = meta->property(meta->indexOfProperty(writePropertyName)); 0426 if (writeProp.isWritable()) { 0427 button->connect(button, &QAbstractButton::toggled, 0428 source, [writeProp, source] (bool value) { writeProp.write(source, value); }); 0429 } 0430 } 0431 0432 0433 void connectControlState(QComboBox *button, QObject *source, const char *readStatePropertyName, const char *writePropertyName) 0434 { 0435 const QMetaObject* meta = source->metaObject(); 0436 QMetaProperty readStateProp = meta->property(meta->indexOfProperty(readStatePropertyName)); 0437 0438 KIS_SAFE_ASSERT_RECOVER_RETURN(readStateProp.hasNotifySignal()); 0439 0440 QMetaMethod signal = readStateProp.notifySignal(); 0441 0442 KIS_SAFE_ASSERT_RECOVER_RETURN(signal.parameterCount() >= 1); 0443 KIS_SAFE_ASSERT_RECOVER_RETURN(signal.parameterType(0) == QMetaType::type("ComboBoxState")); 0444 0445 ConnectComboBoxStateHelper *helper = new ConnectComboBoxStateHelper(button); 0446 0447 const QMetaObject* dstMeta = helper->metaObject(); 0448 0449 QMetaMethod updateSlot = dstMeta->method( 0450 dstMeta->indexOfSlot("updateState(ComboBoxState)")); 0451 QObject::connect(source, signal, helper, updateSlot); 0452 0453 helper->updateState(readStateProp.read(source).value<ComboBoxState>()); 0454 0455 QMetaProperty writeProp = meta->property(meta->indexOfProperty(writePropertyName)); 0456 if (writeProp.isWritable()) { 0457 QObject::connect(button, qOverload<int>(&QComboBox::currentIndexChanged), 0458 source, [writeProp, source] (int value) { writeProp.write(source, value); }); 0459 } 0460 } 0461 0462 void connectControl(QComboBox *button, QObject *source, const char *property) 0463 { 0464 const QMetaObject* meta = source->metaObject(); 0465 QMetaProperty stateProp = meta->property(meta->indexOfProperty(property)); 0466 0467 KIS_SAFE_ASSERT_RECOVER_RETURN(stateProp.hasNotifySignal()); 0468 0469 QMetaMethod signal = stateProp.notifySignal(); 0470 0471 KIS_SAFE_ASSERT_RECOVER_RETURN(signal.parameterCount() >= 1); 0472 KIS_SAFE_ASSERT_RECOVER_RETURN(signal.parameterType(0) == QMetaType::type("int")); 0473 0474 const QMetaObject* dstMeta = button->metaObject(); 0475 0476 QMetaMethod updateSlot = dstMeta->method( 0477 dstMeta->indexOfSlot("setCurrentIndex(int)")); 0478 QObject::connect(source, signal, button, updateSlot); 0479 0480 button->setCurrentIndex(stateProp.read(source).value<int>()); 0481 0482 if (stateProp.isWritable()) { 0483 QObject::connect(button, qOverload<int>(&QComboBox::currentIndexChanged), 0484 source, [stateProp, source] (int value) { stateProp.write(source, value); }); 0485 } 0486 } 0487 0488 class ConnectSpacingWidgetHelper : public QObject 0489 { 0490 Q_OBJECT 0491 public: 0492 0493 ConnectSpacingWidgetHelper(KisSpacingSelectionWidget *parent) 0494 : QObject(parent), 0495 m_spacingWidget(parent) 0496 { 0497 connect(parent, &KisSpacingSelectionWidget::sigSpacingChanged, 0498 this, &ConnectSpacingWidgetHelper::slotWidgetChanged); 0499 } 0500 public Q_SLOTS: 0501 void slotWidgetChanged() { 0502 Q_EMIT sigWidgetChanged({m_spacingWidget->spacing(), m_spacingWidget->autoSpacingActive(), m_spacingWidget->autoSpacingCoeff()}); 0503 } 0504 0505 void slotPropertyChanged(SpacingState state) { 0506 m_spacingWidget->setSpacing(state.useAutoSpacing, state.useAutoSpacing ? state.autoSpacingCoeff : state.spacing); 0507 } 0508 0509 Q_SIGNALS: 0510 // this signal was added only in Qt 5.15 0511 void sigWidgetChanged(SpacingState state); 0512 0513 private: 0514 KisSpacingSelectionWidget *m_spacingWidget; 0515 }; 0516 0517 void connectControl(KisSpacingSelectionWidget *widget, QObject *source, const char *property) 0518 { 0519 const QMetaObject* meta = source->metaObject(); 0520 QMetaProperty stateProp = meta->property(meta->indexOfProperty(property)); 0521 0522 KIS_SAFE_ASSERT_RECOVER_RETURN(stateProp.hasNotifySignal()); 0523 0524 QMetaMethod signal = stateProp.notifySignal(); 0525 0526 KIS_SAFE_ASSERT_RECOVER_RETURN(signal.parameterCount() >= 1); 0527 KIS_SAFE_ASSERT_RECOVER_RETURN(signal.parameterType(0) == QMetaType::type("SpacingState")); 0528 0529 ConnectSpacingWidgetHelper *helper = new ConnectSpacingWidgetHelper(widget); 0530 0531 const QMetaObject* dstMeta = helper->metaObject(); 0532 0533 QMetaMethod updateSlot = dstMeta->method( 0534 dstMeta->indexOfSlot("slotPropertyChanged(SpacingState)")); 0535 QObject::connect(source, signal, helper, updateSlot); 0536 0537 helper->slotPropertyChanged(stateProp.read(source).value<SpacingState>()); 0538 0539 if (stateProp.isWritable()) { 0540 QObject::connect(helper, &ConnectSpacingWidgetHelper::sigWidgetChanged, 0541 source, [stateProp, source] (SpacingState value) { stateProp.write(source, QVariant::fromValue(value)); }); 0542 } 0543 } 0544 0545 void connectControl(KisAngleSelector *widget, QObject *source, const char *property) 0546 { 0547 const QMetaObject* meta = source->metaObject(); 0548 QMetaProperty prop = meta->property(meta->indexOfProperty(property)); 0549 0550 KIS_SAFE_ASSERT_RECOVER_RETURN(prop.hasNotifySignal()); 0551 0552 QMetaMethod signal = prop.notifySignal(); 0553 0554 KIS_SAFE_ASSERT_RECOVER_RETURN(signal.parameterCount() >= 1); 0555 KIS_SAFE_ASSERT_RECOVER_RETURN(signal.parameterType(0) == QMetaType::type("qreal")); 0556 0557 const QMetaObject* dstMeta = widget->metaObject(); 0558 0559 QMetaMethod updateSlot = dstMeta->method( 0560 dstMeta->indexOfSlot("setAngle(qreal)")); 0561 QObject::connect(source, signal, widget, updateSlot); 0562 0563 widget->setAngle(prop.read(source).toReal()); 0564 0565 if (prop.isWritable()) { 0566 QObject::connect(widget, &KisAngleSelector::angleChanged, 0567 source, [prop, source] (qreal value) { prop.write(source, value); }); 0568 } 0569 } 0570 0571 void connectControl(QLineEdit *widget, QObject *source, const char *property) 0572 { 0573 const QMetaObject* meta = source->metaObject(); 0574 QMetaProperty prop = meta->property(meta->indexOfProperty(property)); 0575 0576 KIS_SAFE_ASSERT_RECOVER_RETURN(prop.hasNotifySignal()); 0577 0578 QMetaMethod signal = prop.notifySignal(); 0579 0580 KIS_SAFE_ASSERT_RECOVER_RETURN(signal.parameterCount() >= 1); 0581 KIS_SAFE_ASSERT_RECOVER_RETURN(signal.parameterType(0) == QMetaType::type("QString")); 0582 0583 const QMetaObject* dstMeta = widget->metaObject(); 0584 0585 QMetaMethod updateSlot = dstMeta->method( 0586 dstMeta->indexOfSlot("setText(QString)")); 0587 QObject::connect(source, signal, widget, updateSlot); 0588 0589 widget->setText(prop.read(source).toString()); 0590 0591 if (prop.isWritable()) { 0592 QObject::connect(widget, &QLineEdit::textChanged, 0593 source, [prop, source] (const QString &value) { prop.write(source, value); }); 0594 } 0595 } 0596 0597 void connectControl(KisFileNameRequester *widget, QObject *source, const char *property) 0598 { 0599 const QMetaObject* meta = source->metaObject(); 0600 QMetaProperty prop = meta->property(meta->indexOfProperty(property)); 0601 0602 KIS_SAFE_ASSERT_RECOVER_RETURN(prop.hasNotifySignal()); 0603 0604 QMetaMethod signal = prop.notifySignal(); 0605 0606 KIS_SAFE_ASSERT_RECOVER_RETURN(signal.parameterCount() >= 1); 0607 KIS_SAFE_ASSERT_RECOVER_RETURN(signal.parameterType(0) == QMetaType::type("QString")); 0608 0609 const QMetaObject* dstMeta = widget->metaObject(); 0610 0611 QMetaMethod updateSlot = dstMeta->method( 0612 dstMeta->indexOfSlot("setFileName(QString)")); 0613 QObject::connect(source, signal, widget, updateSlot); 0614 0615 widget->setFileName(prop.read(source).toString()); 0616 0617 if (prop.isWritable()) { 0618 QObject::connect(widget, &KisFileNameRequester::textChanged, 0619 source, [prop, source] (const QString &value) { 0620 prop.write(source, value); }); 0621 } 0622 } 0623 0624 void connectWidgetVisibleToProperty(QWidget* widget, QObject* source, const char* property) 0625 { 0626 const QMetaObject* meta = source->metaObject(); 0627 QMetaProperty prop = meta->property(meta->indexOfProperty(property)); 0628 QMetaMethod signal = prop.notifySignal(); 0629 0630 const QMetaObject* dstMeta = widget->metaObject(); 0631 0632 QMetaMethod updateSlot = dstMeta->method( 0633 dstMeta->indexOfSlot("setVisible(bool)")); 0634 0635 QObject::connect(source, signal, widget, updateSlot); 0636 widget->setVisible(prop.read(source).toBool()); 0637 } 0638 0639 } 0640 0641 #include <KisWidgetConnectionUtils.moc>