diff --git a/lib/crop/croptool.cpp b/lib/crop/croptool.cpp --- a/lib/crop/croptool.cpp +++ b/lib/crop/croptool.cpp @@ -201,6 +201,9 @@ q, SLOT(slotCropRequested())); QObject::connect(mCropWidget, SIGNAL(done()), q, SIGNAL(done())); + + // This is needed when crop ratio set to Current Image, and the image is rotated + QObject::connect(view, &RasterImageView::imageRectUpdated, mCropWidget, &CropWidget::updateCropRatio); } QRect computeVisibleImageRect() const diff --git a/lib/crop/cropwidget.h b/lib/crop/cropwidget.h --- a/lib/crop/cropwidget.h +++ b/lib/crop/cropwidget.h @@ -52,13 +52,16 @@ void cropRequested(); void done(); +public Q_SLOTS: + void updateCropRatio(); + private Q_SLOTS: void slotPositionChanged(); void slotWidthChanged(); void slotHeightChanged(); void setCropRect(const QRect& rect); - void slotRatioComboBoxEditTextChanged(); + void slotAdvancedCheckBoxToggled(bool checked); void applyRatioConstraint(); private: diff --git a/lib/crop/cropwidget.cpp b/lib/crop/cropwidget.cpp --- a/lib/crop/cropwidget.cpp +++ b/lib/crop/cropwidget.cpp @@ -50,13 +50,10 @@ return b == 0 ? a : gcd(b, a % b); } -static QSize screenRatio() +static QSize ratio(const QSize &size) { - const QRect rect = QApplication::desktop()->screenGeometry(); - const int width = rect.width(); - const int height = rect.height(); - const int divisor = gcd(width, height); - return QSize(width / divisor, height / divisor); + const int divisor = gcd(size.width(), size.height()); + return size / divisor; } struct CropWidgetPrivate : public Ui_CropWidget @@ -66,40 +63,50 @@ Document::Ptr mDocument; CropTool* mCropTool; bool mUpdatingFromCropTool; + int mCurrentImageComboBoxIndex; bool ratioIsConstrained() const { return cropRatio() > 0; } double cropRatio() const { - int index = ratioComboBox->currentIndex(); - if (index != -1 && ratioComboBox->currentText() == ratioComboBox->itemText(index)) { - // Get ratio from predefined value - // Note: We check currentText is itemText(currentIndex) because - // currentIndex is not reset to -1 when text is edited by hand. - QSizeF size = ratioComboBox->itemData(index).toSizeF(); - return size.height() / size.width(); - } - - // Not a predefined value, extract ratio from the combobox text - const QStringList lst = ratioComboBox->currentText().split(':'); - if (lst.size() != 2) { - return 0; + if (q->advancedSettingsEnabled()) { + int index = ratioComboBox->currentIndex(); + if (index != -1 && ratioComboBox->currentText() == ratioComboBox->itemText(index)) { + // Get ratio from predefined value + // Note: We check currentText is itemText(currentIndex) because + // currentIndex is not reset to -1 when text is edited by hand. + QSizeF size = ratioComboBox->itemData(index).toSizeF(); + return size.height() / size.width(); + } + + // Not a predefined value, extract ratio from the combobox text + const QStringList lst = ratioComboBox->currentText().split(':'); + if (lst.size() != 2) { + return 0; + } + + bool ok; + const double width = lst[0].toDouble(&ok); + if (!ok) { + return 0; + } + const double height = lst[1].toDouble(&ok); + if (!ok) { + return 0; + } + + return height / width; } - bool ok; - const double width = lst[0].toDouble(&ok); - if (!ok) { - return 0; - } - const double height = lst[1].toDouble(&ok); - if (!ok) { - return 0; + if (restrictToImageRatioCheckBox->isChecked()) { + QSizeF size = ratio(mDocument->size()); + return size.height() / size.width(); } - return height / width; + return 0; } void addRatioToComboBox(const QSizeF& size, const QString& label = QString()) @@ -137,8 +144,11 @@ << QSizeF(4, 3) << QSizeF(5, 4); + addRatioToComboBox(ratio(mDocument->size()), i18n("Current Image")); + mCurrentImageComboBoxIndex = ratioComboBox->count() - 1; // We need to refer to this ratio later + addRatioToComboBox(QSizeF(1, 1), i18n("Square")); - addRatioToComboBox(screenRatio(), i18n("This Screen")); + addRatioToComboBox(ratio(QApplication::desktop()->screenGeometry().size()), i18n("This Screen")); addSectionHeaderToComboBox(i18n("Landscape")); Q_FOREACH(const QSizeF& size, ratioList) { @@ -162,6 +172,15 @@ // Do not use i18n("%1:%2") because ':' should not be translated, it is // used to parse the ratio string. edit->setPlaceholderText(QString("%1:%2").arg(i18n("Width")).arg(i18n("Height"))); + + // Enable clear button + edit->setClearButtonEnabled(true); + // Must manually adjust minimum width because the auto size adjustment doesn't take the + // clear button into account + const int width = ratioComboBox->minimumSizeHint().width(); + ratioComboBox->setMinimumWidth(width + 24); + + ratioComboBox->setCurrentIndex(-1); } QRect cropRect() const @@ -208,11 +227,12 @@ setFont(QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont)); layout()->setSizeConstraint(QLayout::SetFixedSize); - connect(d->advancedCheckBox, SIGNAL(toggled(bool)), - d->advancedWidget, SLOT(setVisible(bool))); + connect(d->advancedCheckBox, &QCheckBox::toggled, this, &CropWidget::slotAdvancedCheckBoxToggled); d->advancedWidget->setVisible(false); d->advancedWidget->layout()->setMargin(0); + connect(d->restrictToImageRatioCheckBox, &QCheckBox::toggled, this, &CropWidget::applyRatioConstraint); + d->initRatioComboBox(); connect(d->mCropTool, &CropTool::rectUpdated, this, &CropWidget::setCropRect); @@ -224,7 +244,7 @@ d->initDialogButtonBox(); - connect(d->ratioComboBox, &QComboBox::editTextChanged, this, &CropWidget::slotRatioComboBoxEditTextChanged); + connect(d->ratioComboBox, &QComboBox::editTextChanged, this, &CropWidget::applyRatioConstraint); // Don't do this before signals are connected, otherwise the tool won't get // initialized @@ -311,9 +331,24 @@ d->mCropTool->setRect(rect); } -void CropWidget::slotRatioComboBoxEditTextChanged() +void CropWidget::slotAdvancedCheckBoxToggled(bool checked) { + d->advancedWidget->setVisible(checked); + d->restrictToImageRatioCheckBox->setVisible(!checked); + applyRatioConstraint(); +} + +void CropWidget::updateCropRatio() +{ + // First we need to re-calculate the "Current Image" ratio in case the user rotated the image + d->ratioComboBox->setItemData(d->mCurrentImageComboBoxIndex, QVariant(ratio(d->mDocument->size()))); + + // Always re-apply the constraint, even though we only need to when the user has "Current Image" + // selected or the "Restrict to current image" checked, since there's no harm applyRatioConstraint(); + // If the ratio is unrestricted, calling applyRatioConstraint doesn't update the rect, so we call + // this manually to make sure the rect is adjusted to fit within the image + d->mCropTool->setRect(d->mCropTool->rect()); } } // namespace diff --git a/lib/crop/cropwidget.ui b/lib/crop/cropwidget.ui --- a/lib/crop/cropwidget.ui +++ b/lib/crop/cropwidget.ui @@ -6,7 +6,7 @@ 0 0 - 824 + 1006 66 @@ -160,6 +160,13 @@ + + + + Restrict to image ratio + + + diff --git a/lib/documentview/rasterimageview.h b/lib/documentview/rasterimageview.h --- a/lib/documentview/rasterimageview.h +++ b/lib/documentview/rasterimageview.h @@ -60,6 +60,7 @@ Q_SIGNALS: void currentToolChanged(AbstractRasterImageViewTool*); + void imageRectUpdated(); protected: void loadFromDocument() Q_DECL_OVERRIDE; diff --git a/lib/documentview/rasterimageview.cpp b/lib/documentview/rasterimageview.cpp --- a/lib/documentview/rasterimageview.cpp +++ b/lib/documentview/rasterimageview.cpp @@ -320,6 +320,7 @@ d->setScalerRegionToVisibleRect(); update(); + emit imageRectUpdated(); } void RasterImageView::slotDocumentIsAnimatedUpdated()