diff --git a/libs/global/kis_acyclic_signal_connector.h b/libs/global/kis_acyclic_signal_connector.h --- a/libs/global/kis_acyclic_signal_connector.h +++ b/libs/global/kis_acyclic_signal_connector.h @@ -23,6 +23,10 @@ #include "kritaglobal_export.h" #include +class KisAcyclicSignalConnector; + +#include +#include /** * A special class for connecting UI elements to manager classes. @@ -42,6 +46,18 @@ * will go into an infinite loop. * * See an example in KisToolCropConfigWidget. + * + * NOTE (coordinated connectors): + * + * Please make sure that you don't convert more than one forward and one backward + * connection to the connector! If you do so, they will become connected to the + * same forwarding slot and, therefore, both output signals will be emitted on + * every incoming signal. + * + * To connect multiple connections that block recursive calls, please use + * "coordinated connectors". Each such connector will have two more connection + * slots that you can reuse. + * */ class KRITAGLOBAL_EXPORT KisAcyclicSignalConnector : public QObject @@ -53,6 +69,7 @@ public: KisAcyclicSignalConnector(QObject *parent = 0); + ~KisAcyclicSignalConnector(); void connectForwardDouble(QObject *sender, const char *signal, QObject *receiver, const char *method); @@ -90,9 +107,41 @@ void connectBackwardResourcePair(QObject *sender, const char *signal, QObject *receiver, const char *method); + /** + * Lock the connector and all its coordinated child connectors + */ void lock(); + + /** + * Unlock the connector and all its coordinated child connectors + */ void unlock(); + /** + * @brief create a coordinated connector that can be used for extending + * the number of self-locking connection. + * + * The coordinated connector can be used to extend the number of self-locking + * connections. Each coordinated connector adds two more connection slots (forward + * and backward). Lock of any connector in a coordinated group will lock the whole + * group. + * + * The created connector is owned by *this, don't delete it! + */ + KisAcyclicSignalConnector *createCoordinatedConnector(); + +private: + + /** + * Lock this connector only. + */ + void coordinatedLock(); + + /** + * Unlock this connector only. + */ + void coordinatedUnlock(); + private Q_SLOTS: void forwardSlotDouble(double value); void backwardSlotDouble(double value); @@ -133,6 +182,8 @@ private: int m_signalsBlocked; + QVector> m_coordinatedConnectors; + QPointer m_parentConnector; }; #endif /* __KIS_ACYCLIC_SIGNAL_CONNECTOR_H */ diff --git a/libs/global/kis_acyclic_signal_connector.cpp b/libs/global/kis_acyclic_signal_connector.cpp --- a/libs/global/kis_acyclic_signal_connector.cpp +++ b/libs/global/kis_acyclic_signal_connector.cpp @@ -27,6 +27,10 @@ { } +KisAcyclicSignalConnector::~KisAcyclicSignalConnector() +{ +} + void KisAcyclicSignalConnector::connectForwardDouble(QObject *sender, const char *signal, QObject *receiver, const char *method) { @@ -120,118 +124,154 @@ void KisAcyclicSignalConnector::lock() { - m_signalsBlocked++; + if (m_parentConnector) { + m_parentConnector->lock(); + } else { + coordinatedLock(); + + Q_FOREACH(QPointer conn, m_coordinatedConnectors) { + if (!conn) continue; + conn->coordinatedLock(); + } + } } void KisAcyclicSignalConnector::unlock() { + if (m_parentConnector) { + m_parentConnector->unlock(); + } else { + Q_FOREACH(QPointer conn, m_coordinatedConnectors) { + if (!conn) continue; + conn->coordinatedUnlock(); + } + + coordinatedUnlock(); + } +} + +void KisAcyclicSignalConnector::coordinatedLock() +{ + m_signalsBlocked++; +} + +void KisAcyclicSignalConnector::coordinatedUnlock() +{ m_signalsBlocked--; } +KisAcyclicSignalConnector *KisAcyclicSignalConnector::createCoordinatedConnector() +{ + KisAcyclicSignalConnector *conn = new KisAcyclicSignalConnector(this); + conn->m_parentConnector = this; + m_coordinatedConnectors.append(conn); + return conn; +} + void KisAcyclicSignalConnector::forwardSlotDouble(double value) { if (m_signalsBlocked) return; - m_signalsBlocked++; + lock(); emit forwardSignalDouble(value); - m_signalsBlocked--; + unlock(); } void KisAcyclicSignalConnector::backwardSlotDouble(double value) { if (m_signalsBlocked) return; - m_signalsBlocked++; + lock(); emit backwardSignalDouble(value); - m_signalsBlocked--; + unlock(); } void KisAcyclicSignalConnector::forwardSlotInt(int value) { if (m_signalsBlocked) return; - m_signalsBlocked++; + lock(); emit forwardSignalInt(value); - m_signalsBlocked--; + unlock(); } void KisAcyclicSignalConnector::backwardSlotInt(int value) { if (m_signalsBlocked) return; - m_signalsBlocked++; + lock(); emit backwardSignalInt(value); - m_signalsBlocked--; + unlock(); } void KisAcyclicSignalConnector::forwardSlotBool(bool value) { if (m_signalsBlocked) return; - m_signalsBlocked++; + lock(); emit forwardSignalBool(value); - m_signalsBlocked--; + unlock(); } void KisAcyclicSignalConnector::backwardSlotBool(bool value) { if (m_signalsBlocked) return; - m_signalsBlocked++; + lock(); emit backwardSignalBool(value); - m_signalsBlocked--; + unlock(); } void KisAcyclicSignalConnector::forwardSlotVoid() { if (m_signalsBlocked) return; - m_signalsBlocked++; + lock(); emit forwardSignalVoid(); - m_signalsBlocked--; + unlock(); } void KisAcyclicSignalConnector::backwardSlotVoid() { if (m_signalsBlocked) return; - m_signalsBlocked++; + lock(); emit backwardSignalVoid(); - m_signalsBlocked--; + unlock(); } void KisAcyclicSignalConnector::forwardSlotVariant(const QVariant &value) { if (m_signalsBlocked) return; - m_signalsBlocked++; + lock(); emit forwardSignalVariant(value); - m_signalsBlocked--; + unlock(); } void KisAcyclicSignalConnector::backwardSlotVariant(const QVariant &value) { if (m_signalsBlocked) return; - m_signalsBlocked++; + lock(); emit backwardSignalVariant(value); - m_signalsBlocked--; + unlock(); } void KisAcyclicSignalConnector::forwardSlotResourcePair(int key, const QVariant &resource) { if (m_signalsBlocked) return; - m_signalsBlocked++; + lock(); emit forwardSignalResourcePair(key, resource); - m_signalsBlocked--; + unlock(); } void KisAcyclicSignalConnector::backwardSlotResourcePair(int key, const QVariant &resource) { if (m_signalsBlocked) return; - m_signalsBlocked++; + lock(); emit backwardSignalResourcePair(key, resource); - m_signalsBlocked--; + unlock(); } diff --git a/libs/ui/kis_aspect_ratio_locker.h b/libs/ui/kis_aspect_ratio_locker.h --- a/libs/ui/kis_aspect_ratio_locker.h +++ b/libs/ui/kis_aspect_ratio_locker.h @@ -50,6 +50,7 @@ Q_SIGNALS: void sliderValueChanged(); void aspectButtonChanged(); + void aspectButtonToggled(bool value); private: struct Private; diff --git a/libs/ui/kis_aspect_ratio_locker.cpp b/libs/ui/kis_aspect_ratio_locker.cpp --- a/libs/ui/kis_aspect_ratio_locker.cpp +++ b/libs/ui/kis_aspect_ratio_locker.cpp @@ -41,46 +41,53 @@ void setValue(qreal value) { - if (m_slider.canConvert()) { - m_slider.value()->setValue(qRound(value)); + if (m_slider.canConvert()) { + m_slider.value()->changeValue(value); - } else if (m_slider.canConvert()) { - m_slider.value()->setValue(value); - - } else if (m_slider.canConvert()) { - m_slider.value()->setValue(qRound(value)); + } else if (m_slider.canConvert()) { + m_slider.value()->setValue(value); } else if (m_slider.canConvert()) { m_slider.value()->setValue(value); + } else if (m_slider.canConvert()) { + m_slider.value()->setValue(value); + } else if (m_slider.canConvert()) { m_slider.value()->setValue(qRound(value)); - } else if (m_slider.canConvert()) { - m_slider.value()->setValue(value); + } else if (m_slider.canConvert()) { + m_slider.value()->setValue(qRound(value)); + + } else if (m_slider.canConvert()) { + m_slider.value()->setValue(qRound(value)); } } qreal value() const { qreal result = 0.0; - if (m_slider.canConvert()) { - result = m_slider.value()->value(); + if (m_slider.canConvert()) { + result = m_slider.value()->value(); - } else if (m_slider.canConvert()) { - result = m_slider.value()->value(); - - } else if (m_slider.canConvert()) { - result = m_slider.value()->value(); + } else if (m_slider.canConvert()) { + result = m_slider.value()->value(); } else if (m_slider.canConvert()) { result = m_slider.value()->value(); + } else if (m_slider.canConvert()) { + result = m_slider.value()->value(); + } else if (m_slider.canConvert()) { result = m_slider.value()->value(); - } else if (m_slider.canConvert()) { - result = m_slider.value()->value(); + } else if (m_slider.canConvert()) { + result = m_slider.value()->value(); + + } else if (m_slider.canConvert()) { + result = m_slider.value()->value(); + } return result; @@ -193,6 +200,7 @@ if (!m_d->spinTwo->isDragging()) { emit aspectButtonChanged(); + emit aspectButtonToggled(m_d->aspectButton->keepAspectRatio()); } } diff --git a/plugins/extensions/imagesize/dlg_imagesize.h b/plugins/extensions/imagesize/dlg_imagesize.h --- a/plugins/extensions/imagesize/dlg_imagesize.h +++ b/plugins/extensions/imagesize/dlg_imagesize.h @@ -27,6 +27,7 @@ class WdgImageSize; class KisDocumentAwareSpinBoxUnitManager; class KisSpinBoxUnitManager; +class KisAspectRatioLocker; #include "ui_wdg_imagesize.h" @@ -56,36 +57,34 @@ KisFilterStrategy *filterType(); private Q_SLOTS: - void slotPixelWidthChanged(double w); - void slotPixelHeightChanged(double h); - void slotPrintWidthChanged(double w); - void slotPrintHeightChanged(double h); - void slotAspectChanged(bool keep); - void slotPrintResolutionChanged(double r); - void slotPrintResolutionEditFinished(); + void slotSyncPrintToPixelSize(); + void slotSyncPixelToPrintSize(); + void slotPrintResolutionChanged(); void slotPrintResolutionUnitChanged(); + void slotLockPixelRatioSwitched(bool value); + void slotLockPrintRatioSwitched(bool value); + void slotLockAllRatioSwitched(bool value); + void slotAdjustSeparatelySwitched(bool value); + + void slotPixelUnitBoxChanged(); + void slotPixelWidthUnitSuffixChanged(); + void slotPixelHeightUnitSuffixChanged(); + private: - void updatePixelWidthUIValue(double value); - void updatePixelHeightUIValue(double value); - void updatePrintWidthUIValue(double value); - void updatePrintHeightUIValue(double value); - void updatePrintResolutionUIValue(double value); + qreal currentResolutionPPI() const; + void setCurrentResilutionPPI(qreal value); + + void updatePrintSizeMaximum(); WdgImageSize *m_page; - const double m_aspectRatio; - const int m_originalWidth, m_originalHeight; - int m_width, m_height; - double m_printWidth, m_printHeight; // in points - const double m_originalResolution; - double m_resolution; - bool m_keepAspect; - - KisDocumentAwareSpinBoxUnitManager* _widthUnitManager; - KisDocumentAwareSpinBoxUnitManager* _heightUnitManager; - - KisSpinBoxUnitManager* _printWidthUnitManager; - KisSpinBoxUnitManager* _printHeightUnitManager; + + KisAspectRatioLocker *m_pixelSizeLocker; + KisAspectRatioLocker *m_printSizeLocker; + + KisDocumentAwareSpinBoxUnitManager* m_widthUnitManager; + KisDocumentAwareSpinBoxUnitManager* m_heightUnitManager; + KisSpinBoxUnitManager* m_printSizeUnitManager; }; #endif // DLG_IMAGESIZE diff --git a/plugins/extensions/imagesize/dlg_imagesize.cc b/plugins/extensions/imagesize/dlg_imagesize.cc --- a/plugins/extensions/imagesize/dlg_imagesize.cc +++ b/plugins/extensions/imagesize/dlg_imagesize.cc @@ -30,26 +30,22 @@ #include +#include "kis_aspect_ratio_locker.h" +#include "kis_acyclic_signal_connector.h" +#include "kis_signals_blocker.h" + #include "kis_double_parse_unit_spin_box.h" #include "kis_document_aware_spin_box_unit_manager.h" +static const int maxImagePixelSize = 10000; + static const QString pixelStr(KoUnit::unitDescription(KoUnit::Pixel)); static const QString percentStr(i18n("Percent (%)")); static const QString pixelsInchStr(i18n("Pixels/Inch")); static const QString pixelsCentimeterStr(i18n("Pixels/Centimeter")); DlgImageSize::DlgImageSize(QWidget *parent, int width, int height, double resolution) : KoDialog(parent) - , m_aspectRatio(((double) width) / height) - , m_originalWidth(width) - , m_originalHeight(height) - , m_width(width) - , m_height(height) - , m_printWidth(width / resolution) - , m_printHeight(height / resolution) - , m_originalResolution(resolution) - , m_resolution(resolution) - , m_keepAspect(true) { setCaption(i18n("Scale To New Size")); setButtons(Ok | Cancel); @@ -61,58 +57,59 @@ m_page->layout()->setMargin(0); m_page->setObjectName("image_size"); - _widthUnitManager = new KisDocumentAwareSpinBoxUnitManager(this); - _heightUnitManager = new KisDocumentAwareSpinBoxUnitManager(this, KisDocumentAwareSpinBoxUnitManager::PIX_DIR_Y); + m_page->pixelFilterCmb->setIDList(KisFilterStrategyRegistry::instance()->listKeys()); + m_page->pixelFilterCmb->setToolTip(KisFilterStrategyRegistry::instance()->formattedDescriptions()); + m_page->pixelFilterCmb->setCurrent("Bicubic"); + - //configure the unit to image length, default unit is pixel and printing units are forbiden. - _widthUnitManager->setUnitDimension(KisSpinBoxUnitManager::IMLENGTH); - _heightUnitManager->setUnitDimension(KisSpinBoxUnitManager::IMLENGTH); + /** + * Initialize Pixel Width and Height fields + */ - m_page->pixelWidthDouble->setUnitManager(_widthUnitManager); - m_page->pixelHeightDouble->setUnitManager(_heightUnitManager); + m_widthUnitManager = new KisDocumentAwareSpinBoxUnitManager(this); + m_heightUnitManager = new KisDocumentAwareSpinBoxUnitManager(this, KisDocumentAwareSpinBoxUnitManager::PIX_DIR_Y); + /// configure the unit to image length, default unit is pixel and printing units are forbiden. + m_widthUnitManager->setUnitDimension(KisSpinBoxUnitManager::IMLENGTH); + m_heightUnitManager->setUnitDimension(KisSpinBoxUnitManager::IMLENGTH); + + m_page->pixelWidthDouble->setUnitManager(m_widthUnitManager); + m_page->pixelHeightDouble->setUnitManager(m_heightUnitManager); m_page->pixelWidthDouble->changeValue(width); m_page->pixelHeightDouble->changeValue(height); - m_page->pixelWidthDouble->setDecimals(2); - m_page->pixelHeightDouble->setDecimals(2); m_page->pixelWidthDouble->setDisplayUnit(false); m_page->pixelHeightDouble->setDisplayUnit(false); - m_page->pixelWidthUnit->setModel(_widthUnitManager); - m_page->pixelHeightUnit->setModel(_widthUnitManager); - m_page->pixelWidthUnit->setCurrentText("px"); - m_page->pixelHeightUnit->setCurrentText("px"); + /// add custom units + m_page->pixelSizeUnit->addItem(pixelStr); + m_page->pixelSizeUnit->addItem(percentStr); + m_page->pixelSizeUnit->setCurrentText(pixelStr); - m_page->pixelFilterCmb->setIDList(KisFilterStrategyRegistry::instance()->listKeys()); - m_page->pixelFilterCmb->setToolTip(KisFilterStrategyRegistry::instance()->formattedDescriptions()); - m_page->pixelFilterCmb->setCurrent("Bicubic"); + /** + * Initialize Print Width, Height and Resolution fields + */ - _printWidthUnitManager = new KisSpinBoxUnitManager(this); - _printHeightUnitManager = new KisSpinBoxUnitManager(this); + m_printSizeUnitManager = new KisSpinBoxUnitManager(this); - m_page->printWidth->setUnitManager(_printWidthUnitManager); - m_page->printHeight->setUnitManager(_printHeightUnitManager); + m_page->printWidth->setUnitManager(m_printSizeUnitManager); + m_page->printHeight->setUnitManager(m_printSizeUnitManager); m_page->printWidth->setDecimals(2); m_page->printHeight->setDecimals(2); m_page->printWidth->setDisplayUnit(false); m_page->printHeight->setDisplayUnit(false); m_page->printResolution->setDecimals(2); m_page->printResolution->setAlignment(Qt::AlignRight); - m_page->printWidthUnit->setModel(_printWidthUnitManager); - m_page->printHeightUnit->setModel(_printHeightUnitManager); - - m_page->printWidth->changeValue(m_printWidth); - m_page->printHeight->changeValue(m_printHeight); + m_page->printWidthUnit->setModel(m_printSizeUnitManager); //TODO: create a resolution dimension in the unit manager. m_page->printResolutionUnit->addItem(pixelsInchStr); m_page->printResolutionUnit->addItem(pixelsCentimeterStr); - m_page->pixelAspectRatioBtn->setKeepAspectRatio(true); - m_page->printAspectRatioBtn->setKeepAspectRatio(true); - m_page->constrainProportionsCkb->setChecked(true); + /** + * Initialize labels and layout + */ KisSizeGroup *labelsGroup = new KisSizeGroup(this); labelsGroup->addWidget(m_page->lblPixelWidth); labelsGroup->addWidget(m_page->lblPixelHeight); @@ -129,48 +126,118 @@ spinboxesGroup->addWidget(m_page->printResolution); KisSizeGroup *comboboxesGroup = new KisSizeGroup(this); - comboboxesGroup->addWidget(m_page->pixelWidthUnit); - comboboxesGroup->addWidget(m_page->pixelHeightUnit); + comboboxesGroup->addWidget(m_page->pixelSizeUnit); comboboxesGroup->addWidget(m_page->printWidthUnit); - comboboxesGroup->addWidget(m_page->printHeightUnit); comboboxesGroup->addWidget(m_page->printResolutionUnit); connect(this, SIGNAL(okClicked()), this, SLOT(accept())); - connect(m_page->pixelAspectRatioBtn, SIGNAL(keepAspectRatioChanged(bool)), this, SLOT(slotAspectChanged(bool))); - connect(m_page->printAspectRatioBtn, SIGNAL(keepAspectRatioChanged(bool)), this, SLOT(slotAspectChanged(bool))); - connect(m_page->constrainProportionsCkb, SIGNAL(toggled(bool)), this, SLOT(slotAspectChanged(bool))); - - connect(m_page->pixelWidthDouble, SIGNAL(valueChangedPt(double)), this, SLOT(slotPixelWidthChanged(double))); - connect(m_page->pixelHeightDouble, SIGNAL(valueChangedPt(double)), this, SLOT(slotPixelHeightChanged(double))); - connect(m_page->pixelWidthUnit, SIGNAL(currentIndexChanged(int)), _widthUnitManager, SLOT(selectApparentUnitFromIndex(int))); - connect(m_page->pixelHeightUnit, SIGNAL(currentIndexChanged(int)), _heightUnitManager, SLOT(selectApparentUnitFromIndex(int))); - connect(_widthUnitManager, SIGNAL(unitChanged(int)), m_page->pixelWidthUnit, SLOT(setCurrentIndex(int))); - connect(_heightUnitManager, SIGNAL(unitChanged(int)), m_page->pixelHeightUnit, SLOT(setCurrentIndex(int))); - - connect(m_page->printWidth, SIGNAL(valueChangedPt(double)), this, SLOT(slotPrintWidthChanged(double))); - connect(m_page->printHeight, SIGNAL(valueChangedPt(double)), this, SLOT(slotPrintHeightChanged(double))); - connect(m_page->printWidthUnit, SIGNAL(currentIndexChanged(int)), _printWidthUnitManager, SLOT(selectApparentUnitFromIndex(int))); - connect(m_page->printHeightUnit, SIGNAL(currentIndexChanged(int)), _printHeightUnitManager, SLOT(selectApparentUnitFromIndex(int))); - connect(_printWidthUnitManager, SIGNAL(unitChanged(int)), m_page->printWidthUnit, SLOT(setCurrentIndex(int))); - connect(_printHeightUnitManager, SIGNAL(unitChanged(int)), m_page->printHeightUnit, SLOT(setCurrentIndex(int))); - - connect(m_page->printResolution, SIGNAL(valueChanged(double)), this, SLOT(slotPrintResolutionChanged(double))); - connect(m_page->printResolution, SIGNAL(editingFinished()), this, SLOT(slotPrintResolutionEditFinished())); - connect(m_page->printResolutionUnit, SIGNAL(currentIndexChanged(int)), this, SLOT(slotPrintResolutionUnitChanged())); - - // pick selected print units from user locale (after slots connection, so the spinbox will be updated too). + /** + * Initialize aspect ratio buttons and lockers + */ + + m_page->pixelAspectRatioBtn->setKeepAspectRatio(true); + m_page->printAspectRatioBtn->setKeepAspectRatio(true); + m_page->constrainProportionsCkb->setChecked(true); + + m_pixelSizeLocker = new KisAspectRatioLocker(this); + m_pixelSizeLocker->connectSpinBoxes(m_page->pixelWidthDouble, m_page->pixelHeightDouble, m_page->pixelAspectRatioBtn); + + m_printSizeLocker = new KisAspectRatioLocker(this); + m_printSizeLocker->connectSpinBoxes(m_page->printWidth, m_page->printHeight, m_page->printAspectRatioBtn); + + /** + * Connect Keep Aspect Lock buttons + */ + + KisAcyclicSignalConnector *constrainsConnector = new KisAcyclicSignalConnector(this); + constrainsConnector->connectBackwardBool( + m_page->constrainProportionsCkb, SIGNAL(toggled(bool)), + this, SLOT(slotLockAllRatioSwitched(bool))); + + constrainsConnector->connectForwardBool( + m_pixelSizeLocker, SIGNAL(aspectButtonToggled(bool)), + this, SLOT(slotLockPixelRatioSwitched(bool))); + + constrainsConnector->createCoordinatedConnector()->connectBackwardBool( + m_printSizeLocker, SIGNAL(aspectButtonToggled(bool)), + this, SLOT(slotLockPrintRatioSwitched(bool))); + + constrainsConnector->createCoordinatedConnector()->connectBackwardBool( + m_page->adjustPrintSizeSeparatelyCkb, SIGNAL(toggled(bool)), + this, SLOT(slotAdjustSeparatelySwitched(bool))); + + /** + * Connect Pixel Unit switching controls + */ + + KisAcyclicSignalConnector *pixelUnitConnector = new KisAcyclicSignalConnector(this); + pixelUnitConnector->connectForwardInt( + m_page->pixelSizeUnit, SIGNAL(currentIndexChanged(int)), + this, SLOT(slotPixelUnitBoxChanged())); + + pixelUnitConnector->connectBackwardInt( + m_widthUnitManager, SIGNAL(unitChanged(int)), + this, SLOT(slotPixelWidthUnitSuffixChanged())); + + pixelUnitConnector->createCoordinatedConnector()->connectBackwardInt( + m_heightUnitManager, SIGNAL(unitChanged(int)), + this, SLOT(slotPixelHeightUnitSuffixChanged())); + + /** + * Connect Print Unit switching controls + */ + + KisAcyclicSignalConnector *printUnitConnector = new KisAcyclicSignalConnector(this); + printUnitConnector->connectForwardInt( + m_page->printWidthUnit, SIGNAL(currentIndexChanged(int)), + m_printSizeUnitManager, SLOT(selectApparentUnitFromIndex(int))); + + printUnitConnector->connectBackwardInt( + m_printSizeUnitManager, SIGNAL(unitChanged(int)), + m_page->printWidthUnit, SLOT(setCurrentIndex(int))); + + /// connect resolution + connect(m_page->printResolutionUnit, SIGNAL(currentIndexChanged(int)), + this, SLOT(slotPrintResolutionUnitChanged())); + + + /** + * Create syncing connections between Pixel and Print values + */ + KisAcyclicSignalConnector *syncConnector = new KisAcyclicSignalConnector(this); + syncConnector->connectForwardVoid( + m_pixelSizeLocker, SIGNAL(sliderValueChanged()), + this, SLOT(slotSyncPixelToPrintSize())); + + syncConnector->connectBackwardVoid( + m_printSizeLocker, SIGNAL(sliderValueChanged()), + this, SLOT(slotSyncPrintToPixelSize())); + + syncConnector->createCoordinatedConnector()->connectBackwardVoid( + m_page->printResolution, SIGNAL(valueChanged(double)), + this, SLOT(slotPrintResolutionChanged())); + + + /** + * Initialize printing values from the predefined image values + */ if (QLocale().measurementSystem() == QLocale::MetricSystem) { m_page->printWidthUnit->setCurrentText("cm"); - m_page->printHeightUnit->setCurrentText("cm"); - m_page->printResolutionUnit->setCurrentIndex(0); // Pixels/Centimeter - slotPrintResolutionUnitChanged(); //ensure the resolution is updated, even if the index didn't changed. } else { // Imperial m_page->printWidthUnit->setCurrentText("in"); - m_page->printHeightUnit->setCurrentText("in"); - m_page->printResolutionUnit->setCurrentIndex(1); // Pixels/Inch - slotPrintResolutionUnitChanged(); //ensure the resolution is updated, even if the index didn't changed. } + setCurrentResilutionPPI(resolution); + slotSyncPixelToPrintSize(); + slotPixelUnitBoxChanged(); + + /** + * Initialize aspect ratio lockers with the current proportion. + * Print locker gets the values only after the first call to slotSyncPixelToPrintSize(). + */ + m_pixelSizeLocker->updateAspect(); + m_printSizeLocker->updateAspect(); + setMainWidget(m_page); } @@ -181,17 +248,17 @@ qint32 DlgImageSize::width() { - return (qint32)m_width; + return int(m_page->pixelWidthDouble->value()); } qint32 DlgImageSize::height() { - return (qint32)m_height; + return int(m_page->pixelHeightDouble->value()); } double DlgImageSize::resolution() { - return m_resolution; + return currentResolutionPPI(); } KisFilterStrategy *DlgImageSize::filterType() @@ -201,221 +268,164 @@ return filter; } -// SLOTS - -void DlgImageSize::slotPixelWidthChanged(double w) +void DlgImageSize::slotSyncPrintToPixelSize() { - m_width = w; - - m_printWidth = m_width / m_resolution; - updatePrintWidthUIValue(m_printWidth); - - if (m_keepAspect) { - m_height = qRound(m_width / m_aspectRatio); - updatePixelHeightUIValue(m_height); - - m_printHeight = m_height / m_resolution; - updatePrintHeightUIValue(m_printHeight); + const bool printIsSeparate = m_page->adjustPrintSizeSeparatelyCkb->isChecked(); + + if (!printIsSeparate) { + KisSignalsBlocker b(m_page->pixelWidthDouble, m_page->pixelHeightDouble); + m_page->pixelWidthDouble->changeValue(m_page->printWidth->value() * currentResolutionPPI()); + m_page->pixelHeightDouble->changeValue(m_page->printHeight->value() * currentResolutionPPI()); + } else if (m_page->pixelWidthDouble->value() != 0.0) { + setCurrentResilutionPPI(m_page->pixelWidthDouble->value() / m_page->printWidth->value()); } } -void DlgImageSize::slotPixelHeightChanged(double h) +void DlgImageSize::slotSyncPixelToPrintSize() { - m_height = h; - - m_printHeight = m_height / m_resolution; - updatePrintHeightUIValue(m_printHeight); - - if (m_keepAspect) { - m_width = qRound(m_height * m_aspectRatio); - updatePixelWidthUIValue(m_width); - - m_printWidth = m_width / m_resolution; - updatePrintWidthUIValue(m_printWidth); + const qreal resolution = currentResolutionPPI(); + if (resolution != 0.0) { + KisSignalsBlocker b(m_page->printWidth, m_page->printHeight); + m_page->printWidth->changeValue(m_page->pixelWidthDouble->value() / resolution); + m_page->printHeight->changeValue(m_page->pixelHeightDouble->value() / resolution); } } -void DlgImageSize::slotPrintWidthChanged(double w) +void DlgImageSize::slotPrintResolutionChanged() { - m_printWidth = w; - - if (m_keepAspect) { - m_printHeight = m_printWidth / m_aspectRatio; - updatePrintHeightUIValue(m_printHeight); - } + const bool printIsSeparate = m_page->adjustPrintSizeSeparatelyCkb->isChecked(); - if (m_page->adjustPrintSizeSeparatelyCkb->isChecked()) { - m_resolution = m_width / m_printWidth; - updatePrintResolutionUIValue(m_resolution); - - if (!m_keepAspect) { - // compute and update a new image height value from the print size values - const double printHeightInch = KoUnit::convertFromUnitToUnit(m_printHeight, KoUnit(KoUnit::Point), KoUnit(KoUnit::Inch)); - m_height = qRound(printHeightInch * 72 * m_resolution); - updatePixelHeightUIValue(m_height); - } + if (printIsSeparate) { + slotSyncPixelToPrintSize(); } else { - const double printWidthInch = KoUnit::convertFromUnitToUnit(m_printWidth, KoUnit(KoUnit::Point), KoUnit(KoUnit::Inch)); - m_width = qRound(printWidthInch * 72 * m_resolution); - updatePixelWidthUIValue(m_width); - - if (m_keepAspect) { - m_height = qRound(m_width / m_aspectRatio); - updatePixelHeightUIValue(m_height); - } + slotSyncPrintToPixelSize(); } + + updatePrintSizeMaximum(); } -void DlgImageSize::slotPrintHeightChanged(double h) +void DlgImageSize::slotPrintResolutionUnitChanged() { - m_printHeight = h; - - if (m_keepAspect) { - m_printWidth = m_printHeight * m_aspectRatio; - updatePrintWidthUIValue(m_printWidth); - } - - if (m_page->adjustPrintSizeSeparatelyCkb->isChecked()) { - m_resolution = m_height / m_printHeight; - updatePrintResolutionUIValue(m_resolution); + qreal resolution = m_page->printResolution->value(); - if (!m_keepAspect) { - // compute and update a new image width value from the print size values - const double printWidthInch = KoUnit::convertFromUnitToUnit(m_printWidth, KoUnit(KoUnit::Point), KoUnit(KoUnit::Inch)); - m_width = qRound(printWidthInch * 72 * m_resolution); - updatePixelWidthUIValue(m_width); - } + if (m_page->printResolutionUnit->currentText() == pixelsInchStr) { + resolution = KoUnit::convertFromUnitToUnit(resolution, KoUnit(KoUnit::Inch), KoUnit(KoUnit::Centimeter)); } else { - const double printHeightInch = KoUnit::convertFromUnitToUnit(m_printHeight, KoUnit(KoUnit::Point), KoUnit(KoUnit::Inch)); - m_height = qRound(printHeightInch * 72 * m_resolution); - updatePixelHeightUIValue(m_height); + resolution = KoUnit::convertFromUnitToUnit(resolution, KoUnit(KoUnit::Centimeter), KoUnit(KoUnit::Inch)); + } - if (m_keepAspect) { - m_width = qRound(m_height * m_aspectRatio); - updatePixelWidthUIValue(m_width); - } + { + KisSignalsBlocker b(m_page->printResolution); + m_page->printResolution->setValue(resolution); } } -void DlgImageSize::slotAspectChanged(bool keep) +void DlgImageSize::slotLockPixelRatioSwitched(bool value) { - m_page->pixelAspectRatioBtn->blockSignals(true); - m_page->printAspectRatioBtn->blockSignals(true); - m_page->constrainProportionsCkb->blockSignals(true); - - m_page->pixelAspectRatioBtn->setKeepAspectRatio(keep); - m_page->printAspectRatioBtn->setKeepAspectRatio(keep); - m_page->constrainProportionsCkb->setChecked(keep); - - m_page->pixelAspectRatioBtn->blockSignals(false); - m_page->printAspectRatioBtn->blockSignals(false); - m_page->constrainProportionsCkb->blockSignals(false); - - m_keepAspect = keep; - - if (keep) { - // values may be out of sync, so we need to reset it to defaults - m_width = m_originalWidth; - m_height = m_originalHeight; - m_printWidth = m_originalWidth / m_originalResolution; - m_printHeight = m_originalHeight / m_originalResolution; - m_resolution = m_originalResolution; - - updatePixelWidthUIValue(m_width); - updatePixelHeightUIValue(m_height); - updatePrintWidthUIValue(m_printWidth); - updatePrintHeightUIValue(m_printHeight); - updatePrintResolutionUIValue(m_resolution); + const bool printIsSeparate = m_page->adjustPrintSizeSeparatelyCkb->isChecked(); + + if (!printIsSeparate) { + m_page->printAspectRatioBtn->setKeepAspectRatio(value); } + m_page->constrainProportionsCkb->setChecked(value); } -void DlgImageSize::slotPrintResolutionChanged(double r) +void DlgImageSize::slotLockPrintRatioSwitched(bool value) { - if (m_page->printResolutionUnit->currentText() == pixelsInchStr) - m_resolution = KoUnit::convertFromUnitToUnit(r, KoUnit(KoUnit::Pixel), KoUnit(KoUnit::Inch)); - else - m_resolution = KoUnit::convertFromUnitToUnit(r, KoUnit(KoUnit::Pixel), KoUnit(KoUnit::Centimeter)); - - if (m_page->adjustPrintSizeSeparatelyCkb->isChecked()) { - m_printWidth = m_width / m_resolution; - m_printHeight = m_height / m_resolution; - - updatePrintWidthUIValue(m_printWidth); - updatePrintHeightUIValue(m_printHeight); - } else { - // Do not commit m_width and m_height values yet. This is done to avoid - // nasty results in image size values while the user is typing a resolution value - const double printWidthInch = KoUnit::convertFromUnitToUnit(m_printWidth, KoUnit(KoUnit::Point), KoUnit(KoUnit::Inch)); - const int width = qRound(printWidthInch * 72 * m_resolution); - const double printHeightInch = KoUnit::convertFromUnitToUnit(m_printHeight, KoUnit(KoUnit::Point), KoUnit(KoUnit::Inch)); - const int height = qRound(printHeightInch * 72 * m_resolution); - - updatePixelWidthUIValue(width); - updatePixelHeightUIValue(height); - } + m_page->pixelAspectRatioBtn->setKeepAspectRatio(value); + m_page->constrainProportionsCkb->setChecked(value); } -void DlgImageSize::slotPrintResolutionEditFinished() +void DlgImageSize::slotLockAllRatioSwitched(bool value) { - if (!m_page->adjustPrintSizeSeparatelyCkb->isChecked()) { - const double printWidthInch = KoUnit::convertFromUnitToUnit(m_printWidth, KoUnit(KoUnit::Point), KoUnit(KoUnit::Inch)); - const double printHeightInch = KoUnit::convertFromUnitToUnit(m_printHeight, KoUnit(KoUnit::Point), KoUnit(KoUnit::Inch)); + const bool printIsSeparate = m_page->adjustPrintSizeSeparatelyCkb->isChecked(); - // Commit width and height values - m_width = qRound(printWidthInch * 72 * m_resolution); - m_height = qRound(printHeightInch * 72 * m_resolution); + m_page->pixelAspectRatioBtn->setKeepAspectRatio(value); - // Note that spinbox values should be up to date - // (updated through slotResolutionChanged()) + if (!printIsSeparate) { + m_page->printAspectRatioBtn->setKeepAspectRatio(value); } } -void DlgImageSize::slotPrintResolutionUnitChanged() +void DlgImageSize::slotAdjustSeparatelySwitched(bool value) { - updatePrintResolutionUIValue(m_resolution); + m_page->printAspectRatioBtn->setEnabled(!value); + m_page->printAspectRatioBtn->setKeepAspectRatio(!value ? m_page->constrainProportionsCkb->isChecked() : true); } -void DlgImageSize::updatePixelWidthUIValue(double value) +void DlgImageSize::slotPixelUnitBoxChanged() { - m_page->pixelWidthDouble->blockSignals(true); - m_page->pixelWidthDouble->changeValue(value); - m_page->pixelWidthDouble->blockSignals(false); + { + KisSignalsBlocker b(m_page->pixelWidthDouble, m_page->pixelHeightDouble); + + if (m_page->pixelSizeUnit->currentText() == pixelStr) { + // TODO: adjust single step as well + + m_page->pixelWidthDouble->setDecimals(0); + m_page->pixelHeightDouble->setDecimals(0); + m_page->pixelWidthDouble->setSingleStep(1); + m_page->pixelHeightDouble->setSingleStep(1); + m_widthUnitManager->setApparentUnitFromSymbol("px"); + m_heightUnitManager->setApparentUnitFromSymbol("px"); + } else { + m_page->pixelWidthDouble->setDecimals(2); + m_page->pixelHeightDouble->setDecimals(2); + m_page->pixelWidthDouble->setSingleStep(0.01); + m_page->pixelHeightDouble->setSingleStep(0.01); + m_widthUnitManager->setApparentUnitFromSymbol("vw"); + m_heightUnitManager->setApparentUnitFromSymbol("vh"); + } + } } -void DlgImageSize::updatePixelHeightUIValue(double value) +void DlgImageSize::slotPixelWidthUnitSuffixChanged() { - m_page->pixelHeightDouble->blockSignals(true); - m_page->pixelHeightDouble->changeValue(value); - m_page->pixelHeightDouble->blockSignals(false); + m_page->pixelSizeUnit->setCurrentIndex(m_widthUnitManager->getApparentUnitSymbol() != "px"); + slotPixelUnitBoxChanged(); } -void DlgImageSize::updatePrintWidthUIValue(double value) +void DlgImageSize::slotPixelHeightUnitSuffixChanged() { - m_page->printWidth->blockSignals(true); - m_page->printWidth->changeValue(value); - m_page->printWidth->blockSignals(false); + m_page->pixelSizeUnit->setCurrentIndex(m_heightUnitManager->getApparentUnitSymbol() != "px"); + slotPixelUnitBoxChanged(); } -void DlgImageSize::updatePrintHeightUIValue(double value) +qreal DlgImageSize::currentResolutionPPI() const { - m_page->printHeight->blockSignals(true); - m_page->printHeight->changeValue(value); - m_page->printHeight->blockSignals(false); + qreal resolution = m_page->printResolution->value(); + + if (m_page->printResolutionUnit->currentText() == pixelsInchStr) { + resolution = KoUnit::convertFromUnitToUnit(resolution, KoUnit(KoUnit::Point), KoUnit(KoUnit::Inch)); + } else { + resolution = KoUnit::convertFromUnitToUnit(resolution, KoUnit(KoUnit::Point), KoUnit(KoUnit::Centimeter)); + } + + return resolution; } -void DlgImageSize::updatePrintResolutionUIValue(double value) +void DlgImageSize::setCurrentResilutionPPI(qreal value) { - double uiValue = 0.0; + qreal newValue = value; + if (m_page->printResolutionUnit->currentText() == pixelsInchStr) { - // show the value in pixel/inch unit - uiValue = KoUnit::convertFromUnitToUnit(value, KoUnit(KoUnit::Inch), KoUnit(KoUnit::Pixel)); + newValue = KoUnit::convertFromUnitToUnit(value, KoUnit(KoUnit::Inch), KoUnit(KoUnit::Point)); } else { - // show the value in pixel/centimeter unit - uiValue = KoUnit::convertFromUnitToUnit(value, KoUnit(KoUnit::Centimeter), KoUnit(KoUnit::Pixel)); + newValue = KoUnit::convertFromUnitToUnit(value, KoUnit(KoUnit::Centimeter), KoUnit(KoUnit::Point)); } - m_page->printResolution->blockSignals(true); - m_page->printResolution->setValue(uiValue); - m_page->printResolution->blockSignals(false); + { + KisSignalsBlocker b(m_page->printResolution); + m_page->printResolution->setValue(newValue); + } + + updatePrintSizeMaximum(); } +void DlgImageSize::updatePrintSizeMaximum() +{ + const qreal value = currentResolutionPPI(); + if (value == 0.0) return; + + m_page->printWidth->setMaximum(maxImagePixelSize / value); + m_page->printHeight->setMaximum(maxImagePixelSize / value); +} diff --git a/plugins/extensions/imagesize/wdg_imagesize.ui b/plugins/extensions/imagesize/wdg_imagesize.ui --- a/plugins/extensions/imagesize/wdg_imagesize.ui +++ b/plugins/extensions/imagesize/wdg_imagesize.ui @@ -45,9 +45,6 @@ - - - @@ -94,9 +91,6 @@ - - - @@ -148,6 +142,9 @@ + + + @@ -173,9 +170,6 @@ - - - @@ -240,9 +234,6 @@ - - - @@ -313,6 +304,9 @@ + + + @@ -395,14 +389,12 @@ pixelWidthDouble - pixelWidthUnit + pixelSizeUnit pixelHeightDouble - pixelHeightUnit pixelFilterCmb printWidth printWidthUnit printHeight - printHeightUnit printResolution printResolutionUnit constrainProportionsCkb