diff --git a/libs/ui/utils/kis_document_aware_spin_box_unit_manager.cpp b/libs/ui/utils/kis_document_aware_spin_box_unit_manager.cpp index 425becbdeb..fd30aba99b 100644 --- a/libs/ui/utils/kis_document_aware_spin_box_unit_manager.cpp +++ b/libs/ui/utils/kis_document_aware_spin_box_unit_manager.cpp @@ -1,153 +1,163 @@ /* * Copyright (c) 2016 Laurent Valentin Jospin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_document_aware_spin_box_unit_manager.h" #include "KisPart.h" #include "KisMainWindow.h" #include "KisView.h" #include "KisDocument.h" #include "kis_types.h" #include "kis_image.h" #include "kis_image_animation_interface.h" #include "kis_time_range.h" KisSpinBoxUnitManager* KisDocumentAwareSpinBoxUnitManagerBuilder::buildUnitManager(QObject* parent) { return new KisDocumentAwareSpinBoxUnitManager(parent); } void KisDocumentAwareSpinBoxUnitManager::setDocumentAwarnessToExistingUnitSpinBox(KisDoubleParseUnitSpinBox* spinBox, bool setUnitFromOutsideToggle) { KisDocumentAwareSpinBoxUnitManager* manager = new KisDocumentAwareSpinBoxUnitManager(spinBox); spinBox->setUnitManager(manager); spinBox->setUnitChangeFromOutsideBehavior(setUnitFromOutsideToggle); } KisDoubleParseUnitSpinBox* KisDocumentAwareSpinBoxUnitManager::createUnitSpinBoxWithDocumentAwarness(QWidget* parent) { KisDoubleParseUnitSpinBox* spinBox = new KisDoubleParseUnitSpinBox(parent); setDocumentAwarnessToExistingUnitSpinBox(spinBox); return spinBox; } KisDocumentAwareSpinBoxUnitManager::KisDocumentAwareSpinBoxUnitManager(QObject *parent, int pPixDir): KisSpinBoxUnitManager(parent) { if (pPixDir == PIX_DIR_Y) { pixDir = PIX_DIR_Y; } else { pixDir = PIX_DIR_X; } grantDocumentRelativeUnits(); //the purpose of this class is to manage document relative units. } -qreal KisDocumentAwareSpinBoxUnitManager::getConversionFactor(UnitDimension dim, QString symbol) const +qreal KisDocumentAwareSpinBoxUnitManager::getConversionFactor(int dim, QString symbol) const { qreal factor = KisSpinBoxUnitManager::getConversionFactor(dim, symbol); if (factor > 0) { //no errors occured at a lower level, so the conversion factor has been get. return factor; } factor = 1; //fall back to something natural in case document is unreachable (1 px = 1 pt = 1vw = 1vh). So a virtual document of 100x100 with a resolution of 1. KisView* view = KisPart::instance()->currentMainwindow()->activeView(); if (view == nullptr) { return factor; } KisDocument* doc = view->document(); if (doc == nullptr) { return factor; } KisImage* img = doc->image().data(); if (img == nullptr) { return factor; } qreal resX = img->xRes(); qreal resY = img->yRes(); qreal sizeX = img->width(); qreal sizeY = img->height(); switch (dim) { case LENGTH: if (symbol == "px") { if (pixDir == PIX_DIR_X) { factor = resX; } else { factor = resY; } } else if (symbol == "vw") { qreal docWidth = sizeX/resX; factor = 100.0/docWidth; //1 vw is 1% of document width, 1 vw in point is docWidth/100 so 1 point in vw is the inverse. } else if (symbol == "vh") { qreal docHeight = sizeY/resY; factor = 100.0/docHeight; } break; + case IMLENGTH: + + if (symbol == "vw") { + factor = 100.0/sizeX; //1 vw is 1% of document width, 1 vw in pixel is sizeX/100 so 1 pixel in vw is the inverse. + + } else if (symbol == "vh") { + factor = 100.0/sizeY; + } + break; + case TIME: { if (symbol == "s") { qreal fps = img->animationInterface()->framerate(); factor = 1/fps; } else if (symbol == "%") { const KisTimeRange & time_range = img->animationInterface()->fullClipRange(); qreal n_frame = time_range.end() - time_range.start(); factor = 100/n_frame; } } break; default: break; } return factor; } -qreal KisDocumentAwareSpinBoxUnitManager::getConversionConstant(UnitDimension dim, QString symbol) const +qreal KisDocumentAwareSpinBoxUnitManager::getConversionConstant(int dim, QString symbol) const { if (dim == TIME && symbol == "%") { KisImage* img = KisPart::instance()->currentMainwindow()->activeView()->document()->image().data(); const KisTimeRange & time_range = img->animationInterface()->fullClipRange(); qreal n_frame = time_range.end() - time_range.start(); return -time_range.start()*100.0/n_frame; } return KisSpinBoxUnitManager::getConversionConstant(dim, symbol); } diff --git a/libs/ui/utils/kis_document_aware_spin_box_unit_manager.h b/libs/ui/utils/kis_document_aware_spin_box_unit_manager.h index 377c3bdfab..a07b20d8b6 100644 --- a/libs/ui/utils/kis_document_aware_spin_box_unit_manager.h +++ b/libs/ui/utils/kis_document_aware_spin_box_unit_manager.h @@ -1,61 +1,61 @@ /* * Copyright (c) 2016 Laurent Valentin Jospin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KISDOCUMENTAWARESPINBOXUNITMANAGER_H #define KISDOCUMENTAWARESPINBOXUNITMANAGER_H #include "kis_spin_box_unit_manager.h" #include "kis_double_parse_unit_spin_box.h" #include "kritaui_export.h" class KisDocumentAwareSpinBoxUnitManagerBuilder : public KisSpinBoxUnitManagerBuilder { public: KisSpinBoxUnitManager* buildUnitManager(QObject* parent); }; class KRITAUI_EXPORT KisDocumentAwareSpinBoxUnitManager : public KisSpinBoxUnitManager { Q_OBJECT public: enum PixDir { PIX_DIR_X, PIX_DIR_Y }; //in case the image has not the same x and y resolution, indicate on which direction get the resolution. //! \brief configure a KisDocumentAwareSpinBoxUnitManager for the given spinbox (make the manager a child of the spinbox and attach it to the spinbox). static void setDocumentAwarnessToExistingUnitSpinBox(KisDoubleParseUnitSpinBox* spinBox, bool setUnitFromOutsideToggle = false); //! \brief create a unitSpinBox that is already document aware. static KisDoubleParseUnitSpinBox* createUnitSpinBoxWithDocumentAwarness(QWidget* parent = 0); KisDocumentAwareSpinBoxUnitManager(QObject *parent = 0, int pPixDir = PIX_DIR_X); - virtual qreal getConversionFactor(UnitDimension dim, QString symbol) const; - virtual qreal getConversionConstant(UnitDimension dim, QString symbol) const; + virtual qreal getConversionFactor(int dim, QString symbol) const; + virtual qreal getConversionConstant(int dim, QString symbol) const; private: PixDir pixDir; }; #endif // KISDOCUMENTAWARESPINBOXUNITMANAGER_H diff --git a/libs/widgets/kis_double_parse_unit_spin_box.cpp b/libs/widgets/kis_double_parse_unit_spin_box.cpp index 19e8990daa..b48ffcf698 100644 --- a/libs/widgets/kis_double_parse_unit_spin_box.cpp +++ b/libs/widgets/kis_double_parse_unit_spin_box.cpp @@ -1,383 +1,422 @@ /* * Copyright (c) 2016 Laurent Valentin Jospin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_double_parse_unit_spin_box.h" #include "kis_spin_box_unit_manager.h" #include class Q_DECL_HIDDEN KisDoubleParseUnitSpinBox::Private { public: - Private(double low, double up, double step, KisSpinBoxUnitManager* unitManager) - : lowerInPoints(low), - upperInPoints(up), - stepInPoints(step), - unit(KoUnit(KoUnit::Point)), - unitManager(unitManager), - defaultUnitManager(unitManager), - isDeleting(false), - unitHasBeenChangedFromOutSideOnce(false), - letUnitBeChangedFromOutsideMoreThanOnce(true), - displayUnit(true) - { - } - - double lowerInPoints; ///< lowest value in points - double upperInPoints; ///< highest value in points - double stepInPoints; ///< step in points - KoUnit unit; + Private(double low, double up, double step, KisSpinBoxUnitManager* unitManager) + : lowerInPoints(low), + upperInPoints(up), + stepInPoints(step), + unit(KoUnit(KoUnit::Point)), + outPutSymbol(""), + unitManager(unitManager), + defaultUnitManager(unitManager), + isDeleting(false), + unitHasBeenChangedFromOutSideOnce(false), + letUnitBeChangedFromOutsideMoreThanOnce(true), + displayUnit(true) + { + } + + double lowerInPoints; ///< lowest value in points + double upperInPoints; ///< highest value in points + double stepInPoints; ///< step in points + KoUnit unit; double previousValueInPoint; ///< allow to store the previous value in point, usefull in some cases, even if, usually, we prefere to refer to the actual value (in selected unit) and convert it, since this is not alway updated. QString previousSymbol; + QString outPutSymbol; - KisSpinBoxUnitManager* unitManager; //manage more units than permitted by KoUnit. - KisSpinBoxUnitManager* defaultUnitManager; //the default unit manager is the one the spinbox rely on and go back to if a connected unit manager is destroyed before the spinbox. + KisSpinBoxUnitManager* unitManager; //manage more units than permitted by KoUnit. + KisSpinBoxUnitManager* defaultUnitManager; //the default unit manager is the one the spinbox rely on and go back to if a connected unit manager is destroyed before the spinbox. - bool isDeleting; + bool isDeleting; - bool unitHasBeenChangedFromOutSideOnce; //in some part of the code the unit is reset. We want to prevent this overriding the unit defined by the user. We use this switch to do so. - bool letUnitBeChangedFromOutsideMoreThanOnce; + bool unitHasBeenChangedFromOutSideOnce; //in some part of the code the unit is reset. We want to prevent this overriding the unit defined by the user. We use this switch to do so. + bool letUnitBeChangedFromOutsideMoreThanOnce; bool displayUnit; }; KisDoubleParseUnitSpinBox::KisDoubleParseUnitSpinBox(QWidget *parent) : - KisDoubleParseSpinBox(parent), - d(new Private(-9999, 9999, 1, KisSpinBoxUnitManagerFactory::buildDefaultUnitManager(this))) + KisDoubleParseSpinBox(parent), + d(new Private(-9999, 9999, 1, KisSpinBoxUnitManagerFactory::buildDefaultUnitManager(this))) { - setUnit( KoUnit(KoUnit::Point) ); - setAlignment( Qt::AlignRight ); + setUnit( KoUnit(KoUnit::Point) ); + setAlignment( Qt::AlignRight ); connect(this, SIGNAL(valueChanged( double )), this, SLOT(privateValueChanged())); - connect(lineEdit(), SIGNAL(textChanged(QString)), - this, SLOT(detectUnitChanges()) ); + connect(lineEdit(), SIGNAL(textChanged(QString)), + this, SLOT(detectUnitChanges()) ); connect(d->unitManager, (void (KisSpinBoxUnitManager::*)()) &KisSpinBoxUnitManager::unitAboutToChange, this, (void (KisDoubleParseUnitSpinBox::*)()) &KisDoubleParseUnitSpinBox::prepareUnitChange); connect(d->unitManager, (void (KisSpinBoxUnitManager::*)( QString )) &KisSpinBoxUnitManager::unitChanged, this, (void (KisDoubleParseUnitSpinBox::*)( QString const& )) &KisDoubleParseUnitSpinBox::internalUnitChange); } KisDoubleParseUnitSpinBox::~KisDoubleParseUnitSpinBox() { - d->isDeleting = true; - delete d->defaultUnitManager; - delete d; + d->isDeleting = true; + delete d->defaultUnitManager; + delete d; } void KisDoubleParseUnitSpinBox::setUnitManager(KisSpinBoxUnitManager* unitManager) { - qreal oldVal = d->unitManager->getReferenceValue(KisDoubleParseSpinBox::value()); - QString oldSymbol = d->unitManager->getApparentUnitSymbol(); - - if (oldSymbol == unitManager->getApparentUnitSymbol() && - d->unitManager->getUnitDimensionType() == unitManager->getUnitDimensionType()) - { - d->unitManager = unitManager; //set the new unitmanager anyway, since it may be a subclass, so change the behavior anyway. - return; - } - - qreal newVal; - - if (d->unitManager->getUnitDimensionType() != unitManager->getUnitDimensionType()) { - //dimension is the same, calculate the new value - newVal = unitManager->getApparentValue(oldVal); - } else { - newVal = unitManager->getApparentValue(d->lowerInPoints); - } - - double newMin = unitManager->getApparentValue(d->lowerInPoints); - double newMax = unitManager->getApparentValue(d->upperInPoints); - double newStep = unitManager->getApparentValue(d->stepInPoints); - - if (unitManager->getApparentUnitSymbol() == KoUnit(KoUnit::Pixel).symbol()) { - // limit the pixel step by 1.0 - newStep = qMax(qreal(1.0), newStep); - } - - KisDoubleParseSpinBox::setMinimum(newMin); - KisDoubleParseSpinBox::setMaximum(newMax); - KisDoubleParseSpinBox::setSingleStep(newStep); - - if (d->unitManager != d->defaultUnitManager) { - disconnect(d->unitManager, &QObject::destroyed, + qreal oldVal = d->unitManager->getReferenceValue(KisDoubleParseSpinBox::value()); + QString oldSymbol = d->unitManager->getApparentUnitSymbol(); + + qreal newVal; + + double newMin; + double newMax; + double newStep; + + if (oldSymbol == unitManager->getApparentUnitSymbol() && + d->unitManager->getUnitDimensionType() == unitManager->getUnitDimensionType()) + { + d->unitManager = unitManager; //set the new unitmanager anyway, since it may be a subclass, so change the behavior anyway. + goto connect_signals; + } + + if (d->unitManager->getUnitDimensionType() == unitManager->getUnitDimensionType()) { + //dimension is the same, calculate the new value + newVal = unitManager->getApparentValue(oldVal); + } else { + newVal = unitManager->getApparentValue(d->lowerInPoints); + } + + newMin = unitManager->getApparentValue(d->lowerInPoints); + newMax = unitManager->getApparentValue(d->upperInPoints); + newStep = unitManager->getApparentValue(d->stepInPoints); + + if (unitManager->getApparentUnitSymbol() == KoUnit(KoUnit::Pixel).symbol()) { + // limit the pixel step by 1.0 + newStep = qMax(qreal(1.0), newStep); + } + + KisDoubleParseSpinBox::setMinimum(newMin); + KisDoubleParseSpinBox::setMaximum(newMax); + KisDoubleParseSpinBox::setSingleStep(newStep); + +connect_signals: + + if (d->unitManager != d->defaultUnitManager) { + disconnect(d->unitManager, &QObject::destroyed, this, &KisDoubleParseUnitSpinBox::disconnectExternalUnitManager); //there's no dependance anymore. } disconnect(d->unitManager, (void (KisSpinBoxUnitManager::*)()) &KisSpinBoxUnitManager::unitAboutToChange, this, (void (KisDoubleParseUnitSpinBox::*)()) &KisDoubleParseUnitSpinBox::prepareUnitChange); disconnect(d->unitManager, (void (KisSpinBoxUnitManager::*)( QString )) &KisSpinBoxUnitManager::unitChanged, this, (void (KisDoubleParseUnitSpinBox::*)( QString const& )) &KisDoubleParseUnitSpinBox::internalUnitChange); - d->unitManager = unitManager; + d->unitManager = unitManager; - connect(d->unitManager, &QObject::destroyed, - this, &KisDoubleParseUnitSpinBox::disconnectExternalUnitManager); + connect(d->unitManager, &QObject::destroyed, + this, &KisDoubleParseUnitSpinBox::disconnectExternalUnitManager); connect(d->unitManager, (void (KisSpinBoxUnitManager::*)()) &KisSpinBoxUnitManager::unitAboutToChange, this, (void (KisDoubleParseUnitSpinBox::*)()) &KisDoubleParseUnitSpinBox::prepareUnitChange); connect(d->unitManager, (void (KisSpinBoxUnitManager::*)( QString )) &KisSpinBoxUnitManager::unitChanged, this, (void (KisDoubleParseUnitSpinBox::*)( QString const& )) &KisDoubleParseUnitSpinBox::internalUnitChange); - KisDoubleParseSpinBox::setValue(newVal); + KisDoubleParseSpinBox::setValue(newVal); } void KisDoubleParseUnitSpinBox::changeValue( double newValue ) { - if (d->unitManager->getApparentValue(newValue) == KisDoubleParseSpinBox::value()) { - return; - } + double apparentValue; + double fact; + double cons; + + if (d->outPutSymbol.isEmpty()) { + apparentValue = d->unitManager->getApparentValue(newValue); + } else { + + fact = d->unitManager->getConversionFactor(d->unitManager->getUnitDimensionType(), d->outPutSymbol); + cons = d->unitManager->getConversionConstant(d->unitManager->getUnitDimensionType(), d->outPutSymbol); + + apparentValue = fact*newValue + cons; + } + + if (apparentValue == KisDoubleParseSpinBox::value()) { + return; + } + + if (d->outPutSymbol.isEmpty()) { + KisDoubleParseSpinBox::setValue( d->unitManager->getApparentValue(newValue) ); + } else { - KisDoubleParseSpinBox::setValue( d->unitManager->getApparentValue(newValue) ); + KisDoubleParseSpinBox::setValue( d->unitManager->getApparentValue((newValue - cons)/fact) ); + } } void KisDoubleParseUnitSpinBox::setUnit( const KoUnit & unit) { - if (d->unitHasBeenChangedFromOutSideOnce && !d->letUnitBeChangedFromOutsideMoreThanOnce) { - return; - } + if (d->unitHasBeenChangedFromOutSideOnce && !d->letUnitBeChangedFromOutsideMoreThanOnce) { + return; + } - if (d->unitManager->getUnitDimensionType() != KisSpinBoxUnitManager::LENGTH) { - d->unitManager->setUnitDim(KisSpinBoxUnitManager::LENGTH); //setting the unit using a KoUnit mean you want to use a length. - } + if (d->unitManager->getUnitDimensionType() != KisSpinBoxUnitManager::LENGTH) { + d->unitManager->setUnitDim(KisSpinBoxUnitManager::LENGTH); //setting the unit using a KoUnit mean you want to use a length. + } - setUnit(unit.symbol()); - d->unit = unit; + setUnit(unit.symbol()); + d->unit = unit; } void KisDoubleParseUnitSpinBox::setUnit(const QString &symbol) { d->unitManager->setApparentUnitFromSymbol(symbol); //via signals and slots, the correct functions should be called. } +void KisDoubleParseUnitSpinBox::setReturnUnit(const QString & symbol) +{ + d->outPutSymbol = symbol; +} void KisDoubleParseUnitSpinBox::prepareUnitChange() { d->previousValueInPoint = d->unitManager->getReferenceValue(KisDoubleParseSpinBox::value()); d->previousSymbol = d->unitManager->getApparentUnitSymbol(); } void KisDoubleParseUnitSpinBox::internalUnitChange(const QString &symbol) { //d->unitManager->setApparentUnitFromSymbol(symbol); if (d->unitManager->getApparentUnitSymbol() == d->previousSymbol) { //the setApparentUnitFromSymbol is a bit clever, for example in regard of Casesensitivity. So better check like this. return; } KisDoubleParseSpinBox::setMinimum( d->unitManager->getApparentValue( d->lowerInPoints ) ); KisDoubleParseSpinBox::setMaximum( d->unitManager->getApparentValue( d->upperInPoints ) ); qreal step = d->unitManager->getApparentValue( d->stepInPoints ); if (symbol == KoUnit(KoUnit::Pixel).symbol()) { // limit the pixel step by 1.0 step = qMax(qreal(1.0), step); } KisDoubleParseSpinBox::setSingleStep( step ); KisDoubleParseSpinBox::setValue( d->unitManager->getApparentValue( d->previousValueInPoint ) ); d->unitHasBeenChangedFromOutSideOnce = true; } void KisDoubleParseUnitSpinBox::setDimensionType(int dim) { - if (!KisSpinBoxUnitManager::isUnitId(dim)) { - return; - } + if (!KisSpinBoxUnitManager::isUnitId(dim)) { + return; + } - d->unitManager->setUnitDim((KisSpinBoxUnitManager::UnitDimension) dim); + d->unitManager->setUnitDim((KisSpinBoxUnitManager::UnitDimension) dim); } double KisDoubleParseUnitSpinBox::value( ) const { - return d->unitManager->getReferenceValue( KisDoubleParseSpinBox::value() ); + if (d->outPutSymbol.isEmpty()) { + return d->unitManager->getReferenceValue( KisDoubleParseSpinBox::value() ); + } + + double ref = d->unitManager->getReferenceValue( KisDoubleParseSpinBox::value() ); + double fact = d->unitManager->getConversionFactor(d->unitManager->getUnitDimensionType(), d->outPutSymbol); + double cons = d->unitManager->getConversionConstant(d->unitManager->getUnitDimensionType(), d->outPutSymbol); + + return fact*ref + cons; } void KisDoubleParseUnitSpinBox::setMinimum(double min) { - d->lowerInPoints = min; - KisDoubleParseSpinBox::setMinimum( d->unitManager->getApparentValue( min ) ); + d->lowerInPoints = min; + KisDoubleParseSpinBox::setMinimum( d->unitManager->getApparentValue( min ) ); } void KisDoubleParseUnitSpinBox::setMaximum(double max) { - d->upperInPoints = max; - KisDoubleParseSpinBox::setMaximum( d->unitManager->getApparentValue( max ) ); + d->upperInPoints = max; + KisDoubleParseSpinBox::setMaximum( d->unitManager->getApparentValue( max ) ); } void KisDoubleParseUnitSpinBox::setLineStep(double step) { - d->stepInPoints = d->unitManager->getReferenceValue(step); - KisDoubleParseSpinBox::setSingleStep( step ); + d->stepInPoints = d->unitManager->getReferenceValue(step); + KisDoubleParseSpinBox::setSingleStep( step ); } void KisDoubleParseUnitSpinBox::setLineStepPt(double step) { - d->stepInPoints = step; - KisDoubleParseSpinBox::setSingleStep( d->unitManager->getApparentValue( step ) ); + d->stepInPoints = step; + KisDoubleParseSpinBox::setSingleStep( d->unitManager->getApparentValue( step ) ); } void KisDoubleParseUnitSpinBox::setMinMaxStep( double min, double max, double step ) { - setMinimum( min ); - setMaximum( max ); - setLineStepPt( step ); + setMinimum( min ); + setMaximum( max ); + setLineStepPt( step ); } QValidator::State KisDoubleParseUnitSpinBox::validate(QString &input, int &pos) const { Q_UNUSED(pos); - QRegExp regexp ("([ a-zA-Z]+)$"); // Letters or spaces at end - const int res = input.indexOf( regexp ); + QRegExp regexp ("([ a-zA-Z]+)$"); // Letters or spaces at end + const int res = input.indexOf( regexp ); /*if ( res == -1 ) { - // Nothing like an unit? The user is probably editing the unit - return QValidator::Intermediate; + // Nothing like an unit? The user is probably editing the unit + return QValidator::Intermediate; }*/ QString expr ( (res > 0) ? input.left( res ) : input ); const QString unitName ( (res > 0) ? regexp.cap( 1 ).trimmed().toLower() : "" ); - bool ok = true; - bool interm = false; + bool ok = true; + bool interm = false; - QValidator::State exprState = KisDoubleParseSpinBox::validate(expr, pos); + QValidator::State exprState = KisDoubleParseSpinBox::validate(expr, pos); if (res < 0) { return exprState; } - if (exprState == QValidator::Invalid) { - return exprState; - } else if (exprState == QValidator::Intermediate) { - interm = true; - } + if (exprState == QValidator::Invalid) { + return exprState; + } else if (exprState == QValidator::Intermediate) { + interm = true; + } - //check if we can parse the unit. - QStringList listOfSymbol = d->unitManager->getsUnitSymbolList(); - ok = listOfSymbol.contains(unitName); + //check if we can parse the unit. + QStringList listOfSymbol = d->unitManager->getsUnitSymbolList(); + ok = listOfSymbol.contains(unitName); - if (!ok || interm) { - return QValidator::Intermediate; - } + if (!ok || interm) { + return QValidator::Intermediate; + } - return QValidator::Acceptable; + return QValidator::Acceptable; } QString KisDoubleParseUnitSpinBox::textFromValue( double value ) const { - QString txt = KisDoubleParseSpinBox::textFromValue(value); + QString txt = KisDoubleParseSpinBox::textFromValue(value); if (d->displayUnit) { if (!txt.endsWith(d->unitManager->getApparentUnitSymbol())) { txt += " " + d->unitManager->getApparentUnitSymbol(); } } - return txt; + return txt; } QString KisDoubleParseUnitSpinBox::veryCleanText() const { - return makeTextClean(cleanText()); + return makeTextClean(cleanText()); } double KisDoubleParseUnitSpinBox::valueFromText( const QString& str ) const { - QString txt = makeTextClean(str); + QString txt = makeTextClean(str); - return KisDoubleParseSpinBox::valueFromText(txt); //this function will take care of prefix (and don't mind if suffix has been removed. + return KisDoubleParseSpinBox::valueFromText(txt); //this function will take care of prefix (and don't mind if suffix has been removed. } void KisDoubleParseUnitSpinBox::setUnitChangeFromOutsideBehavior(bool toggle) { - d->letUnitBeChangedFromOutsideMoreThanOnce = toggle; + d->letUnitBeChangedFromOutsideMoreThanOnce = toggle; } void KisDoubleParseUnitSpinBox::setDisplayUnit(bool toggle) { d->displayUnit = toggle; } void KisDoubleParseUnitSpinBox::privateValueChanged() { - emit valueChangedPt( value() ); + emit valueChangedPt( value() ); } QString KisDoubleParseUnitSpinBox::detectUnit() { - QString str = veryCleanText().trimmed(); //text with the new unit but not the old one. + QString str = veryCleanText().trimmed(); //text with the new unit but not the old one. - QRegExp regexp ("([ ]*[a-zA-Z]+[ ]*)$"); // Letters or spaces at end - int res = str.indexOf( regexp ); + QRegExp regexp ("([ ]*[a-zA-Z]+[ ]*)$"); // Letters or spaces at end + int res = str.indexOf( regexp ); - if (res > -1) { - QString expr ( str.right( str.size() - res ) ); - expr = expr.trimmed(); - return expr; - } + if (res > -1) { + QString expr ( str.right( str.size() - res ) ); + expr = expr.trimmed(); + return expr; + } - return ""; + return ""; } void KisDoubleParseUnitSpinBox::detectUnitChanges() { - QString unitSymb = detectUnit(); + QString unitSymb = detectUnit(); - if (unitSymb.isEmpty()) { - return; - } + if (unitSymb.isEmpty()) { + return; + } - QString oldUnitSymb = d->unitManager->getApparentUnitSymbol(); + QString oldUnitSymb = d->unitManager->getApparentUnitSymbol(); setUnit(unitSymb); - setValue(valueFromText(cleanText())); //change value keep the old value, but converted to new unit... which is different from the value the user entered in the new unit. So we need to set the new value. + setValue(valueFromText(cleanText())); //change value keep the old value, but converted to new unit... which is different from the value the user entered in the new unit. So we need to set the new value. - if (oldUnitSymb != d->unitManager->getApparentUnitSymbol()) { - // the user has changed the unit, so we block changes from outside. - setUnitChangeFromOutsideBehavior(false); - } + if (oldUnitSymb != d->unitManager->getApparentUnitSymbol()) { + // the user has changed the unit, so we block changes from outside. + setUnitChangeFromOutsideBehavior(false); + } } QString KisDoubleParseUnitSpinBox::makeTextClean(QString const& txt) const { - QString expr = txt; - QString symbol = d->unitManager->getApparentUnitSymbol(); + QString expr = txt; + QString symbol = d->unitManager->getApparentUnitSymbol(); - if ( expr.endsWith(suffix()) ) { - expr.remove(expr.size()-suffix().size(), suffix().size()); - } + if ( expr.endsWith(suffix()) ) { + expr.remove(expr.size()-suffix().size(), suffix().size()); + } - expr = expr.trimmed(); + expr = expr.trimmed(); - if ( expr.endsWith(symbol) ) { - expr.remove(expr.size()-symbol.size(), symbol.size()); - } + if ( expr.endsWith(symbol) ) { + expr.remove(expr.size()-symbol.size(), symbol.size()); + } return expr.trimmed(); } void KisDoubleParseUnitSpinBox::disconnectExternalUnitManager() { - if (!d->isDeleting) - { - setUnitManager(d->defaultUnitManager); //go back to default unit manager. - } + if (!d->isDeleting) + { + setUnitManager(d->defaultUnitManager); //go back to default unit manager. + } } diff --git a/libs/widgets/kis_double_parse_unit_spin_box.h b/libs/widgets/kis_double_parse_unit_spin_box.h index 54dd3351cc..9535c92827 100644 --- a/libs/widgets/kis_double_parse_unit_spin_box.h +++ b/libs/widgets/kis_double_parse_unit_spin_box.h @@ -1,132 +1,137 @@ /* * Copyright (c) 2016 Laurent Valentin Jospin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_DOUBLEPARSEUNITSPINBOX_H #define KIS_DOUBLEPARSEUNITSPINBOX_H #include #include "kis_double_parse_spin_box.h" #include "kritawidgets_export.h" class KisSpinBoxUnitManager; /*! * \brief The KisDoubleParseUnitSpinBox class is an evolution of the \see KoUnitDoubleSpinBox, but inherit from \see KisDoubleParseSpinBox to be able to parse math expressions. * * This class store the */ class KRITAWIDGETS_EXPORT KisDoubleParseUnitSpinBox : public KisDoubleParseSpinBox { Q_OBJECT public: KisDoubleParseUnitSpinBox(QWidget* parent = 0); virtual ~KisDoubleParseUnitSpinBox(); void setUnitManager(KisSpinBoxUnitManager* unitManager); /** - * Set the new value in points which will then be converted to the current unit for display + * Set the new value in points (or other reference unit) which will then be converted to the current unit for display * @param newValue the new value * @see value() */ virtual void changeValue( double newValue ); /** * This spinbox shows the internal value after a conversion to the unit set here. */ virtual void setUnit(const KoUnit &unit); virtual void setUnit(const QString & symbol); + /*! + * \brief setReturnUnit set a unit, such that the spinbox now return values in this unit instead of the reference unit for the current dimension. + * \param symbol the symbol of the new unit. + */ + void setReturnUnit(const QString & symbol); /** * @brief setDimensionType set the dimension (for example length or angle) of the units the spinbox manage * @param dim the dimension id. (if not an id in KisSpinBoxUnitManager::UnitDimension, then the function does nothing). */ virtual void setDimensionType(int dim); /// @return the current value, converted in points double value( ) const; /// Set minimum value in points. void setMinimum(double min); /// Set maximum value in points. void setMaximum(double max); /// Set step size in the current unit. void setLineStep(double step); /// Set step size in points. void setLineStepPt(double step); /// Set minimum, maximum value and the step size (all in points) void setMinMaxStep( double min, double max, double step ); /// reimplemented from superclass, will forward to KoUnitDoubleValidator virtual QValidator::State validate(QString &input, int &pos) const; /** * Transform the double in a nice text, using locale symbols * @param value the number as double * @return the resulting string */ virtual QString textFromValue( double value ) const; //! \brief get the text in the spinbox without prefix or suffix, and remove unit symbol if present. virtual QString veryCleanText() const; /** * Transfrom a string into a double, while taking care of locale specific symbols. * @param str the string to transform into a number * @return the value as double */ virtual double valueFromText( const QString& str ) const; void setUnitChangeFromOutsideBehavior(bool toggle); //if set to false, setting the unit using KoUnit won't have any effect. //! \brief display the unit symbol in the spinbox or not. For example if the unit is displayed in a combobox connected to the unit manager. void setDisplayUnit(bool toggle); Q_SIGNALS: - /// emitted like valueChanged in the parent, but this one emits the point value + /// emitted like valueChanged in the parent, but this one emits the point value, or converted to another reference unit. void valueChangedPt( qreal ); private: class Private; Private * const d; QString detectUnit(); QString makeTextClean(QString const& txt) const; //thoses functions are usefull to sync the spinbox with it's unitmanager. //! \brief change the unit, reset the spin box everytime. From the outside it's alway set unit that should be called. void internalUnitChange(QString const& symbol); void prepareUnitChange(); private Q_SLOTS: // exists to do emits for valueChangedPt void privateValueChanged(); void detectUnitChanges(); void disconnectExternalUnitManager(); }; #endif // KIS_DOUBLEPARSEUNITSPINBOX_H diff --git a/libs/widgetutils/kis_spin_box_unit_manager.cpp b/libs/widgetutils/kis_spin_box_unit_manager.cpp index 849bd85be9..777a7cea65 100644 --- a/libs/widgetutils/kis_spin_box_unit_manager.cpp +++ b/libs/widgetutils/kis_spin_box_unit_manager.cpp @@ -1,494 +1,524 @@ /* * Copyright (c) 2016 Laurent Valentin Jospin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_spin_box_unit_manager.h" #include "KoUnit.h" #include #include KisSpinBoxUnitManagerBuilder* KisSpinBoxUnitManagerFactory::builder = nullptr; KisSpinBoxUnitManager* KisSpinBoxUnitManagerFactory::buildDefaultUnitManager(QObject* parent) { if (builder == nullptr) { return new KisSpinBoxUnitManager(parent); } return builder->buildUnitManager(parent); } void KisSpinBoxUnitManagerFactory::setDefaultUnitManagerBuilder(KisSpinBoxUnitManagerBuilder* pBuilder) { if (builder != nullptr) { delete builder; //The factory took over the lifecycle of the builder, so it delete it when replaced. } builder = pBuilder; } void KisSpinBoxUnitManagerFactory::clearUnitManagerBuilder() { if (builder != nullptr) { delete builder; //The factory took over the lifecycle of the builder, so it delete it when replaced. } builder = nullptr; } -const QStringList KisSpinBoxUnitManager::referenceUnitSymbols = {"pt", "°", "frame"}; +const QStringList KisSpinBoxUnitManager::referenceUnitSymbols = {"pt", "px", "°", "frame"}; const QStringList KisSpinBoxUnitManager::documentRelativeLengthUnitSymbols = {"px", "vw", "vh"}; //px are relative to the resolution, vw and vh to the width and height. const QStringList KisSpinBoxUnitManager::documentRelativeTimeUnitSymbols = {"s", "%"}; //secondes are relative to the framerate, % to the sequence length. class Q_DECL_HIDDEN KisSpinBoxUnitManager::Private { public: Private(KisSpinBoxUnitManager::UnitDimension pDim = KisSpinBoxUnitManager::LENGTH, QString pUnitSymbol = "pt", double pConv = 1.0): dim(pDim), unitSymbol(pUnitSymbol), conversionFactor(pConv), conversionFactorIsFixed(true), conversionConstant(0), conversionConstantIsFixed(true), constrains(0), unitListCached(false), hasHundredPercent(false), canAccessDocument(false) { } KisSpinBoxUnitManager::UnitDimension dim; QString unitSymbol; mutable double conversionFactor; bool conversionFactorIsFixed; //tell if it's possible to trust the conversion factor stored or if it's needed to recompute it. mutable double conversionConstant; bool conversionConstantIsFixed; //tell if it's possible to trust the conversion constant stored or if it's needed to recompute it. KisSpinBoxUnitManager::Constrains constrains; mutable QStringList unitList; mutable bool unitListCached; mutable QStringList unitListWithName; mutable bool unitListWithNameCached; //it's possible to store a reference for the % unit, for lenght. bool hasHundredPercent; qreal hundredPercent; bool canAccessDocument; }; KisSpinBoxUnitManager::KisSpinBoxUnitManager(QObject *parent) : QAbstractListModel(parent) { d = new Private(); connect(this, (void (KisSpinBoxUnitManager::*)( QString )) &KisSpinBoxUnitManager::unitChanged, this, &KisSpinBoxUnitManager::newUnitSymbolToUnitIndex); } KisSpinBoxUnitManager::~KisSpinBoxUnitManager() { delete d; } int KisSpinBoxUnitManager::getUnitDimensionType() const { return d->dim; } QString KisSpinBoxUnitManager::getReferenceUnitSymbol() const { return referenceUnitSymbols[d->dim]; } QString KisSpinBoxUnitManager::getApparentUnitSymbol() const { return d->unitSymbol; } int KisSpinBoxUnitManager::getApparentUnitId() const { QStringList list = getsUnitSymbolList(); return list.indexOf(d->unitSymbol); } QStringList KisSpinBoxUnitManager::getsUnitSymbolList(bool withName) const{ QStringList list; //TODO: cache if (withName) { if (d->unitListWithNameCached) { return d->unitListWithName; } } else { if (d->unitListCached) { return d->unitList; } } switch (d->dim) { case LENGTH: for (int i = 0; i < KoUnit::TypeCount; i++) { if (KoUnit::Type(i) == KoUnit::Pixel) { continue; //skip pixel, which is a document relative unit, in the base classe. } if (withName) { list << KoUnit::unitDescription(KoUnit::Type(i)); } else { list << KoUnit(KoUnit::Type(i)).symbol(); } } if (d->canAccessDocument) { // ad document relative units if (withName) { list << KoUnit::unitDescription(KoUnit::Pixel) << i18n("view width (vw)") << i18n("view height (vh)"); } else { list << documentRelativeLengthUnitSymbols; } } - break; + break; + + case IMLENGTH: + + if (withName) { + list << KoUnit::unitDescription(KoUnit::Pixel); + } else { + list << "px"; + } + + if (d->canAccessDocument) { + // ad document relative units + if (withName) { + list << i18n("view width (vw)") << i18n("view height (vh)"); + } else { + list << "vw" << "vh"; + } + } + break; case ANGLE: if (withName) { list << i18n("degrees (°)") << i18n("radians (rad)") << i18n("gons (gon)") << i18n("percent of circle (%)"); } else { list << "°" << "rad" << "gon" << "%"; } break; case TIME: if (withName) { list << i18n("frames (f)"); } else { list << "f"; } if (d->canAccessDocument) { if (withName) { list << i18n("seconds (s)") << i18n("percent of animation (%)"); } else { list << documentRelativeTimeUnitSymbols; } } break; } if (withName) { d->unitListWithName = list; d->unitListWithNameCached = true; } else { d->unitList = list; d->unitListCached = true; } return list; } -qreal KisSpinBoxUnitManager::getConversionConstant(UnitDimension dim, QString symbol) const +qreal KisSpinBoxUnitManager::getConversionConstant(int dim, QString symbol) const { Q_UNUSED(dim); Q_UNUSED(symbol); return 0; // all units managed here are transform via a linear function, so this wll alway be 0 in this class. } qreal KisSpinBoxUnitManager::getReferenceValue(double apparentValue) const { if (!d->conversionFactorIsFixed) { recomputeConversionFactor(); } if(!d->conversionConstantIsFixed) { recomputeConvesrionConstant(); } qreal v = (apparentValue - d->conversionConstant)/d->conversionFactor; if (d->constrains &= REFISINT) { v = qFloor(v); } return v; } int KisSpinBoxUnitManager::rowCount(const QModelIndex &parent) const { if (parent == QModelIndex()) { return getsUnitSymbolList().size(); } return 0; } QVariant KisSpinBoxUnitManager::data(const QModelIndex &index, int role) const { if (role == Qt::DisplayRole) { return getsUnitSymbolList(false).at(index.row()); } return QVariant(); } qreal KisSpinBoxUnitManager::getApparentValue(double refValue) const { if (!d->conversionFactorIsFixed) { recomputeConversionFactor(); } if(!d->conversionConstantIsFixed) { recomputeConvesrionConstant(); } qreal v = refValue*d->conversionFactor + d->conversionConstant; if (d->constrains &= VALISINT) { v = qFloor(v); } return v; } -qreal KisSpinBoxUnitManager::getConversionFactor(UnitDimension dim, QString symbol) const +qreal KisSpinBoxUnitManager::getConversionFactor(int dim, QString symbol) const { qreal factor = -1; switch (dim) { case LENGTH: do { if (symbol == "px") { break; } bool ok; KoUnit unit = KoUnit::fromSymbol(symbol, &ok); if (! ok) { break; } factor = unit.toUserValue(1.0); } while (0) ; break; + case IMLENGTH: + if (symbol == "px") { + factor = 1; + } + break; + case ANGLE: if (symbol == "°") { factor = 1.0; break; } if (symbol == "rad") { factor = acos(-1)/90.0; break; } if (symbol == "gon") { factor = 10.0/9.0; break; } if (symbol == "%") { factor = 2.5/9.0; //(25% of circle is 90°) break; } break; case TIME: if (symbol != "f") { //we have only frames for the moment. break; } factor = 1.0; break; + default: + break; } return factor; } void KisSpinBoxUnitManager::setUnitDim(UnitDimension dim) { if (dim == d->dim) { return; } d->dim = dim; d->unitSymbol = referenceUnitSymbols[d->dim]; //Active dim is reference dim when just changed. d->conversionFactor = 1.0; emit unitDimensionChanged(d->dim); } void KisSpinBoxUnitManager::setApparentUnitFromSymbol(QString pSymbol) { QString symbol = pSymbol.trimmed(); if (symbol == d->unitSymbol) { return; } emit unitAboutToChange(); QString newSymb = ""; switch (d->dim) { case ANGLE: if (symbol.toLower() == "deg") { newSymb = "°"; break; } goto default_indentifier; //alway do default after handling possible special cases. default_indentifier: default: QStringList list = getsUnitSymbolList(); if (list.contains(symbol, Qt::CaseInsensitive)) { for (QString str : list) { if (str.toLower() == symbol.toLower()) { newSymb = str; //official symbol may contain capitals letters, so better take the official version. break; } } break; } } if(newSymb.isEmpty()) { return; //abort if it was impossible to locate the correct symbol. } if (d->canAccessDocument) { //manage document relative units. QStringList speUnits; switch (d->dim) { case LENGTH: speUnits = documentRelativeLengthUnitSymbols; goto default_identifier_conv_fact; + case IMLENGTH: + speUnits << "vw" << "vh"; + goto default_identifier_conv_fact; + case TIME: speUnits = documentRelativeTimeUnitSymbols; goto default_identifier_conv_fact; default_identifier_conv_fact: default: if (speUnits.isEmpty()) { d->conversionFactorIsFixed = true; break; } if (speUnits.contains(newSymb)) { d->conversionFactorIsFixed = false; break; } d->conversionFactorIsFixed = true; break; } if (d->dim == TIME) { if (newSymb == "%") { d->conversionConstantIsFixed = false; } } else { d->conversionConstantIsFixed = true; } } qreal conversFact = getConversionFactor(d->dim, newSymb); qreal oldConversFact = d->conversionFactor; d->conversionFactor = conversFact; emit conversionFactorChanged(d->conversionFactor, oldConversFact); d->unitSymbol = newSymb; emit unitChanged(newSymb); } void KisSpinBoxUnitManager::selectApparentUnitFromIndex(int index) { if (index >= 0 && index < rowCount()) { setApparentUnitFromSymbol(getsUnitSymbolList().at(index)); } } void KisSpinBoxUnitManager::newUnitSymbolToUnitIndex(QString symbol) { int id = getsUnitSymbolList().indexOf(symbol); if (id >= 0) { emit unitChanged(id); } } void KisSpinBoxUnitManager::recomputeConversionFactor() const { if (d->conversionFactorIsFixed) { return; } qreal oldConversionFactor = d->conversionFactor; d->conversionFactor = getConversionFactor(d->dim, d->unitSymbol); if (oldConversionFactor != d->conversionFactor) { emit conversionFactorChanged(d->conversionFactor, oldConversionFactor); } } void KisSpinBoxUnitManager::recomputeConvesrionConstant() const { if (d->conversionConstantIsFixed) { return; } qreal oldConversionConstant = d->conversionConstant; d->conversionConstant = getConversionConstant(d->dim, d->unitSymbol); if (oldConversionConstant != d->conversionConstant) { emit conversionConstantChanged(d->conversionConstant, oldConversionConstant); } } void KisSpinBoxUnitManager::grantDocumentRelativeUnits() { d->canAccessDocument = true; } diff --git a/libs/widgetutils/kis_spin_box_unit_manager.h b/libs/widgetutils/kis_spin_box_unit_manager.h index b75e0642e8..bf626a4ae0 100644 --- a/libs/widgetutils/kis_spin_box_unit_manager.h +++ b/libs/widgetutils/kis_spin_box_unit_manager.h @@ -1,155 +1,156 @@ /* * Copyright (c) 2016 Laurent Valentin Jospin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KISSPINBOXUNITMANAGER_H #define KISSPINBOXUNITMANAGER_H #include #include #include #include "kritawidgetutils_export.h" class KisSpinBoxUnitManager; class KisSpinBoxUnitManagerBuilder; class KisSpinBoxUnitManagerFactory; class KRITAWIDGETUTILS_EXPORT KisSpinBoxUnitManagerFactory { public: static KisSpinBoxUnitManager* buildDefaultUnitManager(QObject* parent); //! \brief set a builder the factory can use. The factory should take on the lifecycle of the builder, so to delete it call clearUnitManagerBuilder(); static void setDefaultUnitManagerBuilder(KisSpinBoxUnitManagerBuilder* pBuilder); static void clearUnitManagerBuilder(); private: static KisSpinBoxUnitManagerBuilder* builder; }; class KRITAWIDGETUTILS_EXPORT KisSpinBoxUnitManagerBuilder { public: virtual ~KisSpinBoxUnitManagerBuilder() {} virtual KisSpinBoxUnitManager* buildUnitManager(QObject* parent) = 0; //this pure virtual function is used to build a unitmanager, it will be used by the unitManagerFactory. }; /** * @brief The KisSpinBoxUnitManager class is an abstract interface for the unitspinboxes classes to manage different type of units. * * The class make a difference between unit dimension (distance, angle, time). * * The class allow to convert values between reference unit and apparent unit, but also to get other information like possible units symbols. * * This class don't allow to use relative units (units which conversion factor is dependant of the context), even if it's private data are prepared to manage it. * The reason for this is that from the library of this class it's very hard to acess easily the informations needed. So all will be managed by subclasses in other libs. * * The class is a subclass of QAbstractListModel, so that available list of units is easily acessed by other Qt standard components, like QComboBoxes. * */ class KRITAWIDGETUTILS_EXPORT KisSpinBoxUnitManager : public QAbstractListModel { Q_OBJECT public: enum UnitDimension{ - LENGTH = 0, - ANGLE = 1, - TIME = 2 + LENGTH = 0, //length, print size, reference is point + IMLENGTH = 1, //length, image size, reference is pixel. This dimension is used when the printing units must be avoided + ANGLE = 2, + TIME = 3 }; static inline bool isUnitId(int code) { return (code == LENGTH || code == ANGLE || code == TIME); } //! \brief this list hold the symbols of the referenc unit per dimension. The index is equal to the value in UnitDimension so that the dimension name can be used to index the list. static const QStringList referenceUnitSymbols; enum Constrain{ NOCONSTR = 0, REFISINT = 1, VALISINT = 2 }; Q_DECLARE_FLAGS(Constrains, Constrain) explicit KisSpinBoxUnitManager(QObject *parent = 0); virtual ~KisSpinBoxUnitManager(); int getUnitDimensionType() const; QString getReferenceUnitSymbol() const; QString getApparentUnitSymbol() const; //! \brief get the position of the apparent unit in the list of units. It is usefull if we want to build a model for combo-box based unit management. int getApparentUnitId() const; virtual QStringList getsUnitSymbolList(bool withName = false) const; qreal getReferenceValue(double apparentValue) const; qreal getApparentValue(double refValue) const; //! \brief gets the conversion factor of a managed unit, or -1 in case of error. This method is the one that need to be overridden to extend the ability of the KisSpinBoxUnitManager. - virtual qreal getConversionFactor(UnitDimension dim, QString symbol) const; + virtual qreal getConversionFactor(int dim, QString symbol) const; //! \brief some units conversions are done via an affine transform, not just a linear transform. This function gives the constant of this affine transform (usually 0). - virtual qreal getConversionConstant(UnitDimension dim, QString symbol) const; + virtual qreal getConversionConstant(int dim, QString symbol) const; virtual int rowCount(const QModelIndex &parent = QModelIndex()) const; virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; Q_SIGNALS: void unitDimensionChanged(int dimCode); void unitAboutToChange(); void unitChanged(QString symbol); void unitChanged(int index); void conversionFactorChanged(qreal newConversionFactor, qreal oldConversionFactor) const; void conversionConstantChanged(qreal newConversionFactor, qreal oldConversionFactor) const; void unitListChanged(); public Q_SLOTS: void setUnitDim(UnitDimension dim); void setApparentUnitFromSymbol(QString pSymbol); void selectApparentUnitFromIndex(int index); protected: class Private; Private * d; //! \brief convert a unitChanged signal with a QString to one with an index. void newUnitSymbolToUnitIndex(QString symbol); //unit's that may be used only if acess to the document informations exists. static const QStringList documentRelativeLengthUnitSymbols; static const QStringList documentRelativeTimeUnitSymbols; void recomputeConversionFactor() const; void recomputeConvesrionConstant() const; //! \brief calling this method give acess to document relative units. Only subclasses that manage thoses units should call it. void grantDocumentRelativeUnits(); }; #endif // KISSPINBOXUNITMANAGER_H diff --git a/plugins/extensions/imagesize/dlg_imagesize.cc b/plugins/extensions/imagesize/dlg_imagesize.cc index 1d38c57bdc..41a7e8430d 100644 --- a/plugins/extensions/imagesize/dlg_imagesize.cc +++ b/plugins/extensions/imagesize/dlg_imagesize.cc @@ -1,493 +1,422 @@ /* * dlg_imagesize.cc - part of KimageShop^WKrayon^WKrita * * Copyright (c) 2004 Boudewijn Rempt * Copyright (c) 2009 C. Boemann * Copyright (c) 2013 Juan Palacios * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "dlg_imagesize.h" #include #include #include #include #include +#include "kis_double_parse_unit_spin_box.h" +#include "kis_document_aware_spin_box_unit_manager.h" + 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) + : 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); - setDefaultButton(Ok); - - m_page = new WdgImageSize(this); - - Q_CHECK_PTR(m_page); - m_page->layout()->setMargin(0); - m_page->setObjectName("image_size"); - - m_page->pixelWidth->setValue(width); - m_page->pixelWidth->setFocus(); - m_page->pixelHeight->setValue(height); - - m_page->pixelWidthDouble->setVisible(false); - m_page->pixelHeightDouble->setVisible(false); - - m_page->pixelFilterCmb->setIDList(KisFilterStrategyRegistry::instance()->listKeys()); - m_page->pixelFilterCmb->setToolTip(KisFilterStrategyRegistry::instance()->formatedDescriptions()); - m_page->pixelFilterCmb->setCurrent("Bicubic"); - - m_page->pixelWidthUnit->addItem(pixelStr); - m_page->pixelWidthUnit->addItem(percentStr); - m_page->pixelWidthUnit->setCurrentIndex(0); - - m_page->pixelHeightUnit->addItem(pixelStr); - m_page->pixelHeightUnit->addItem(percentStr); - m_page->pixelHeightUnit->setCurrentIndex(0); - - m_page->printWidthUnit->addItems(KoUnit::listOfUnitNameForUi(KoUnit::HidePixel)); - m_page->printWidthUnit->addItem(percentStr); - m_page->printHeightUnit->addItems(KoUnit::listOfUnitNameForUi(KoUnit::HidePixel)); - m_page->printHeightUnit->addItem(percentStr); - - m_page->printResolutionUnit->addItem(pixelsInchStr); - m_page->printResolutionUnit->addItem(pixelsCentimeterStr); - - // pick selected print units from user locale - if (QLocale().measurementSystem() == QLocale::MetricSystem) { - const int unitIndex = KoUnit(KoUnit::Centimeter).indexInListForUi(KoUnit::HidePixel); - m_page->printWidthUnit->setCurrentIndex(unitIndex); - m_page->printHeightUnit->setCurrentIndex(unitIndex); - m_page->printResolutionUnit->setCurrentIndex(0); // Pixels/Centimeter - } else { // Imperial - const int unitIndex = KoUnit(KoUnit::Inch).indexInListForUi(KoUnit::HidePixel); - m_page->printWidthUnit->setCurrentIndex(unitIndex); - m_page->printHeightUnit->setCurrentIndex(unitIndex); - m_page->printResolutionUnit->setCurrentIndex(1); // Pixels/Inch - } - updatePrintWidthUIValue(m_printWidth); - updatePrintHeightUIValue(m_printHeight); - updatePrintResolutionUIValue(m_resolution); - - m_page->pixelAspectRatioBtn->setKeepAspectRatio(true); - m_page->printAspectRatioBtn->setKeepAspectRatio(true); - m_page->constrainProportionsCkb->setChecked(true); - - KisSizeGroup *labelsGroup = new KisSizeGroup(this); - labelsGroup->addWidget(m_page->lblPixelWidth); - labelsGroup->addWidget(m_page->lblPixelHeight); - labelsGroup->addWidget(m_page->lblPixelFilter); - labelsGroup->addWidget(m_page->lblPrintWidth); - labelsGroup->addWidget(m_page->lblPrintHeight); - labelsGroup->addWidget(m_page->lblResolution); - - KisSizeGroup *spinboxesGroup = new KisSizeGroup(this); - spinboxesGroup->addWidget(m_page->pixelWidth); - spinboxesGroup->addWidget(m_page->pixelWidthDouble); - spinboxesGroup->addWidget(m_page->pixelHeight); - spinboxesGroup->addWidget(m_page->pixelHeightDouble); - spinboxesGroup->addWidget(m_page->printWidth); - spinboxesGroup->addWidget(m_page->printHeight); - spinboxesGroup->addWidget(m_page->printResolution); - - KisSizeGroup *comboboxesGroup = new KisSizeGroup(this); - comboboxesGroup->addWidget(m_page->pixelWidthUnit); - comboboxesGroup->addWidget(m_page->pixelHeightUnit); - 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->pixelWidth, SIGNAL(valueChanged(int)), this, SLOT(slotPixelWidthChanged(int))); - connect(m_page->pixelHeight, SIGNAL(valueChanged(int)), this, SLOT(slotPixelHeightChanged(int))); - connect(m_page->pixelWidthDouble, SIGNAL(valueChanged(double)), this, SLOT(slotPixelWidthChanged(double))); - connect(m_page->pixelHeightDouble, SIGNAL(valueChanged(double)), this, SLOT(slotPixelHeightChanged(double))); - connect(m_page->pixelWidthUnit, SIGNAL(currentIndexChanged(int)), this, SLOT(slotPixelWidthUnitChanged())); - connect(m_page->pixelHeightUnit, SIGNAL(currentIndexChanged(int)), this, SLOT(slotPixelHeightUnitChanged())); - - connect(m_page->printWidth, SIGNAL(valueChanged(double)), this, SLOT(slotPrintWidthChanged(double))); - connect(m_page->printHeight, SIGNAL(valueChanged(double)), this, SLOT(slotPrintHeightChanged(double))); - connect(m_page->printWidthUnit, SIGNAL(currentIndexChanged(int)), this, SLOT(slotPrintWidthUnitChanged())); - connect(m_page->printHeightUnit, SIGNAL(currentIndexChanged(int)), this, SLOT(slotPrintHeightUnitChanged())); - - 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())); - - setMainWidget(m_page); + setCaption(i18n("Scale To New Size")); + setButtons(Ok | Cancel); + setDefaultButton(Ok); + + m_page = new WdgImageSize(this); + + Q_CHECK_PTR(m_page); + m_page->layout()->setMargin(0); + m_page->setObjectName("image_size"); + + _widthUnitManager = new KisDocumentAwareSpinBoxUnitManager(this); + _heightUnitManager = new KisDocumentAwareSpinBoxUnitManager(this, KisDocumentAwareSpinBoxUnitManager::PIX_DIR_Y); + + //configure the unit to image length, default unit is pixel and printing units are forbiden. + _widthUnitManager->setUnitDim(KisSpinBoxUnitManager::IMLENGTH); + _heightUnitManager->setUnitDim(KisSpinBoxUnitManager::IMLENGTH); + + m_page->pixelWidthDouble->setUnitManager(_widthUnitManager); + m_page->pixelHeightDouble->setUnitManager(_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"); + + m_page->pixelFilterCmb->setIDList(KisFilterStrategyRegistry::instance()->listKeys()); + m_page->pixelFilterCmb->setToolTip(KisFilterStrategyRegistry::instance()->formatedDescriptions()); + m_page->pixelFilterCmb->setCurrent("Bicubic"); + + _printWidthUnitManager = new KisSpinBoxUnitManager(this); + _printHeightUnitManager = new KisSpinBoxUnitManager(this); + + m_page->printWidth->setUnitManager(_printWidthUnitManager); + m_page->printHeight->setUnitManager(_printHeightUnitManager); + 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); + + //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); + + KisSizeGroup *labelsGroup = new KisSizeGroup(this); + labelsGroup->addWidget(m_page->lblPixelWidth); + labelsGroup->addWidget(m_page->lblPixelHeight); + labelsGroup->addWidget(m_page->lblPixelFilter); + labelsGroup->addWidget(m_page->lblPrintWidth); + labelsGroup->addWidget(m_page->lblPrintHeight); + labelsGroup->addWidget(m_page->lblResolution); + + KisSizeGroup *spinboxesGroup = new KisSizeGroup(this); + spinboxesGroup->addWidget(m_page->pixelWidthDouble); + spinboxesGroup->addWidget(m_page->pixelHeightDouble); + spinboxesGroup->addWidget(m_page->printWidth); + spinboxesGroup->addWidget(m_page->printHeight); + spinboxesGroup->addWidget(m_page->printResolution); + + KisSizeGroup *comboboxesGroup = new KisSizeGroup(this); + comboboxesGroup->addWidget(m_page->pixelWidthUnit); + comboboxesGroup->addWidget(m_page->pixelHeightUnit); + 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). + 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. + } + + setMainWidget(m_page); } DlgImageSize::~DlgImageSize() { - delete m_page; + delete m_page; } qint32 DlgImageSize::width() { - return (qint32)m_width; + return (qint32)m_width; } qint32 DlgImageSize::height() { - return (qint32)m_height; + return (qint32)m_height; } double DlgImageSize::resolution() { - return m_resolution; + return m_resolution; } KisFilterStrategy *DlgImageSize::filterType() { - KoID filterID = m_page->pixelFilterCmb->currentItem(); - KisFilterStrategy *filter = KisFilterStrategyRegistry::instance()->value(filterID.id()); - return filter; + KoID filterID = m_page->pixelFilterCmb->currentItem(); + KisFilterStrategy *filter = KisFilterStrategyRegistry::instance()->value(filterID.id()); + return filter; } // SLOTS -void DlgImageSize::slotPixelWidthChanged(int w) +void DlgImageSize::slotPixelWidthChanged(double w) { - slotPixelWidthChanged((double) w); -} + m_width = w; -void DlgImageSize::slotPixelHeightChanged(int h) -{ - slotPixelHeightChanged((double) h); -} + m_printWidth = m_width / m_resolution; + updatePrintWidthUIValue(m_printWidth); -void DlgImageSize::slotPixelWidthChanged(double w) -{ - if (m_page->pixelWidthUnit->currentText() == percentStr) { - m_width = qRound((w * m_originalWidth) / 100.0); - } else { - 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); - } -} + if (m_keepAspect) { + m_height = qRound(m_width / m_aspectRatio); + updatePixelHeightUIValue(m_height); -void DlgImageSize::slotPixelHeightChanged(double h) -{ - if (m_page->pixelHeightUnit->currentText() == percentStr) { - m_height = qRound((h * m_originalHeight) / 100.0); - } else { - 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); - } + m_printHeight = m_height / m_resolution; + updatePrintHeightUIValue(m_printHeight); + } } -void DlgImageSize::slotPixelWidthUnitChanged() +void DlgImageSize::slotPixelHeightChanged(double h) { - updatePixelWidthUIValue(m_width); + m_height = h; - m_page->pixelWidth->setVisible(m_page->pixelWidthUnit->currentText() == pixelStr); - m_page->pixelWidthDouble->setVisible(m_page->pixelWidthUnit->currentText() == percentStr); -} + m_printHeight = m_height / m_resolution; + updatePrintHeightUIValue(m_printHeight); -void DlgImageSize::slotPixelHeightUnitChanged() -{ - updatePixelHeightUIValue(m_height); + if (m_keepAspect) { + m_width = qRound(m_height * m_aspectRatio); + updatePixelWidthUIValue(m_width); - m_page->pixelHeight->setVisible(m_page->pixelHeightUnit->currentText() == pixelStr); - m_page->pixelHeightDouble->setVisible(m_page->pixelHeightUnit->currentText() == percentStr); + m_printWidth = m_width / m_resolution; + updatePrintWidthUIValue(m_printWidth); + } } void DlgImageSize::slotPrintWidthChanged(double w) { - if (m_page->printWidthUnit->currentText() == percentStr) { - const double originalWidthPoint = m_originalWidth / m_originalResolution; - m_printWidth = (w * originalWidthPoint) / 100.0; - } else { - KoUnit selectedUnit = KoUnit::fromListForUi(m_page->printWidthUnit->currentIndex(), KoUnit::HidePixel); - m_printWidth = selectedUnit.fromUserValue(w); - } - - if (m_keepAspect) { - m_printHeight = m_printWidth / m_aspectRatio; - updatePrintHeightUIValue(m_printHeight); - } - - 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); - } - } 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); - } - } + m_printWidth = w; + + if (m_keepAspect) { + m_printHeight = m_printWidth / m_aspectRatio; + updatePrintHeightUIValue(m_printHeight); + } + + 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); + } + } 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); + } + } } void DlgImageSize::slotPrintHeightChanged(double h) { - if (m_page->printHeightUnit->currentText() == percentStr) { - const double originalHeightPoint = m_originalHeight / m_originalResolution; - m_printHeight = (h * originalHeightPoint) / 100.0; - } else { - KoUnit selectedUnit = KoUnit::fromListForUi(m_page->printHeightUnit->currentIndex(), KoUnit::HidePixel); - m_printHeight = selectedUnit.fromUserValue(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); - - 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); - } - } else { - const double printHeightInch = KoUnit::convertFromUnitToUnit(m_printHeight, KoUnit(KoUnit::Point), KoUnit(KoUnit::Inch)); - m_height = qRound(printHeightInch * 72 * m_resolution); - updatePixelHeightUIValue(m_height); - - if (m_keepAspect) { - m_width = qRound(m_height * m_aspectRatio); - updatePixelWidthUIValue(m_width); - } - } -} - -void DlgImageSize::slotPrintWidthUnitChanged() -{ - updatePrintWidthUIValue(m_printWidth); -} - -void DlgImageSize::slotPrintHeightUnitChanged() -{ - updatePrintHeightUIValue(m_printHeight); + 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); + + 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); + } + } else { + const double printHeightInch = KoUnit::convertFromUnitToUnit(m_printHeight, KoUnit(KoUnit::Point), KoUnit(KoUnit::Inch)); + m_height = qRound(printHeightInch * 72 * m_resolution); + updatePixelHeightUIValue(m_height); + + if (m_keepAspect) { + m_width = qRound(m_height * m_aspectRatio); + updatePixelWidthUIValue(m_width); + } + } } void DlgImageSize::slotAspectChanged(bool keep) { - 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); - } + 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); + } } void DlgImageSize::slotPrintResolutionChanged(double r) { - 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); - } + 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); + } } void DlgImageSize::slotPrintResolutionEditFinished() { - 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)); + 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)); - // Commit width and height values - m_width = qRound(printWidthInch * 72 * m_resolution); - m_height = qRound(printHeightInch * 72 * m_resolution); + // Commit width and height values + m_width = qRound(printWidthInch * 72 * m_resolution); + m_height = qRound(printHeightInch * 72 * m_resolution); - // Note that spinbox values should be up to date - // (updated through slotResolutionChanged()) - } + // Note that spinbox values should be up to date + // (updated through slotResolutionChanged()) + } } void DlgImageSize::slotPrintResolutionUnitChanged() { - updatePrintResolutionUIValue(m_resolution); + updatePrintResolutionUIValue(m_resolution); } void DlgImageSize::updatePixelWidthUIValue(double value) { - if (m_page->pixelWidthUnit->currentText() == percentStr) { - m_page->pixelWidthDouble->blockSignals(true); - m_page->pixelWidthDouble->setValue((value * 100.0) / m_originalWidth); - m_page->pixelWidthDouble->blockSignals(false); - } else { - m_page->pixelWidth->blockSignals(true); - m_page->pixelWidth->setValue(value); - m_page->pixelWidth->blockSignals(false); - } + m_page->pixelWidthDouble->blockSignals(true); + m_page->pixelWidthDouble->changeValue(value); + m_page->pixelWidthDouble->blockSignals(false); } void DlgImageSize::updatePixelHeightUIValue(double value) { - if (m_page->pixelHeightUnit->currentText() == percentStr) { - m_page->pixelHeightDouble->blockSignals(true); - m_page->pixelHeightDouble->setValue((value * 100.0) / m_originalHeight); - m_page->pixelHeightDouble->blockSignals(false); - } else { - m_page->pixelHeight->blockSignals(true); - m_page->pixelHeight->setValue(value); - m_page->pixelHeight->blockSignals(false); - } + m_page->pixelHeightDouble->blockSignals(true); + m_page->pixelHeightDouble->changeValue(value); + m_page->pixelHeightDouble->blockSignals(false); } void DlgImageSize::updatePrintWidthUIValue(double value) { - double uiValue = 0.0; - if (m_page->printWidthUnit->currentText() == percentStr) { - // We need to compute percent in point unit because: - // - originalWith is a value expressed in px (original resolution) - // - value is expressed in point unit (current resolution) - // - the percentage value should be based on the original print size - const double originalWidthPoint = m_originalWidth / m_originalResolution; - uiValue = (value * 100.0) / originalWidthPoint; - } else { - const KoUnit selectedUnit = KoUnit::fromListForUi(m_page->printWidthUnit->currentIndex()); - uiValue = selectedUnit.toUserValue(value); - } - m_page->printWidth->blockSignals(true); - m_page->printWidth->setValue(uiValue); - m_page->printWidth->blockSignals(false); + m_page->printWidth->blockSignals(true); + m_page->printWidth->changeValue(value); + m_page->printWidth->blockSignals(false); } void DlgImageSize::updatePrintHeightUIValue(double value) { - double uiValue = 0.0; - if (m_page->printHeightUnit->currentText() == percentStr) { - // We need to compute percent in point unit because: - // - originalHeight is a value expressed in px (original resolution) - // - value is expressed in point unit (current resolution) - // - the percentage value should be based on the original print size - const double originalHeightPoint = m_originalHeight / m_originalResolution; - uiValue = (value * 100.0) / originalHeightPoint; - } else { - const KoUnit selectedUnit = KoUnit::fromListForUi(m_page->printHeightUnit->currentIndex()); - uiValue = selectedUnit.toUserValue(value); - } - m_page->printHeight->blockSignals(true); - m_page->printHeight->setValue(uiValue); - m_page->printHeight->blockSignals(false); + m_page->printHeight->blockSignals(true); + m_page->printHeight->changeValue(value); + m_page->printHeight->blockSignals(false); } void DlgImageSize::updatePrintResolutionUIValue(double value) { - double uiValue = 0.0; - if (m_page->printResolutionUnit->currentText() == pixelsInchStr) { - // show the value in pixel/inch unit - uiValue = KoUnit::convertFromUnitToUnit(value, KoUnit(KoUnit::Inch), KoUnit(KoUnit::Pixel)); - } else { - // show the value in pixel/centimeter unit - uiValue = KoUnit::convertFromUnitToUnit(value, KoUnit(KoUnit::Centimeter), KoUnit(KoUnit::Pixel)); - } - - m_page->printResolution->blockSignals(true); - m_page->printResolution->setValue(uiValue); - m_page->printResolution->blockSignals(false); + double uiValue = 0.0; + if (m_page->printResolutionUnit->currentText() == pixelsInchStr) { + // show the value in pixel/inch unit + uiValue = KoUnit::convertFromUnitToUnit(value, KoUnit(KoUnit::Inch), KoUnit(KoUnit::Pixel)); + } else { + // show the value in pixel/centimeter unit + uiValue = KoUnit::convertFromUnitToUnit(value, KoUnit(KoUnit::Centimeter), KoUnit(KoUnit::Pixel)); + } + + m_page->printResolution->blockSignals(true); + m_page->printResolution->setValue(uiValue); + m_page->printResolution->blockSignals(false); } diff --git a/plugins/extensions/imagesize/dlg_imagesize.h b/plugins/extensions/imagesize/dlg_imagesize.h index ba2d8c7667..f6f1e3b271 100644 --- a/plugins/extensions/imagesize/dlg_imagesize.h +++ b/plugins/extensions/imagesize/dlg_imagesize.h @@ -1,89 +1,91 @@ /* * dlg_imagesize.h -- part of KimageShop^WKrayon^WKrita * * Copyright (c) 2004 Boudewijn Rempt * Copyright (c) 2013 Juan Palacios * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef DLG_IMAGESIZE #define DLG_IMAGESIZE #include class KisFilterStrategy; class WdgImageSize; +class KisDocumentAwareSpinBoxUnitManager; +class KisSpinBoxUnitManager; #include "ui_wdg_imagesize.h" class WdgImageSize : public QWidget, public Ui::WdgImageSize { Q_OBJECT public: WdgImageSize(QWidget *parent) : QWidget(parent) { setupUi(this); } }; class DlgImageSize: public KoDialog { Q_OBJECT public: DlgImageSize(QWidget * parent, int width, int height, double resolution); ~DlgImageSize(); qint32 width(); qint32 height(); double resolution(); KisFilterStrategy *filterType(); private Q_SLOTS: - void slotPixelWidthChanged(int w); - void slotPixelHeightChanged(int h); void slotPixelWidthChanged(double w); - void slotPixelHeightChanged(double h); - void slotPixelWidthUnitChanged(); - void slotPixelHeightUnitChanged(); + void slotPixelHeightChanged(double h); void slotPrintWidthChanged(double w); - void slotPrintHeightChanged(double h); - void slotPrintWidthUnitChanged(); - void slotPrintHeightUnitChanged(); + void slotPrintHeightChanged(double h); void slotAspectChanged(bool keep); void slotPrintResolutionChanged(double r); void slotPrintResolutionEditFinished(); - void slotPrintResolutionUnitChanged(); + void slotPrintResolutionUnitChanged(); private: void updatePixelWidthUIValue(double value); void updatePixelHeightUIValue(double value); void updatePrintWidthUIValue(double value); void updatePrintHeightUIValue(double value); void updatePrintResolutionUIValue(double value); 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; }; #endif // DLG_IMAGESIZE diff --git a/plugins/extensions/imagesize/wdg_imagesize.ui b/plugins/extensions/imagesize/wdg_imagesize.ui index 8a45fdf251..af5641e00b 100644 --- a/plugins/extensions/imagesize/wdg_imagesize.ui +++ b/plugins/extensions/imagesize/wdg_imagesize.ui @@ -1,447 +1,413 @@ WdgImageSize 0 0 391 386 Scale To New Size Pixel Dimensions true - + 80 0 4 0.000100000000000 10000.000000000000000 0.100000000000000 - - - - - 80 - 0 - - - - 1 - - - 100000 - - - Qt::Horizontal QSizePolicy::Fixed 25 20 W&idth: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - pixelWidth - &Filter: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter printWidth &Height: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - pixelHeight - - + 80 0 4 0.000100000000000 10000.000000000000000 0.100000000000000 - - - - 1 - - - 100000 - - - Qt::Horizontal QSizePolicy::MinimumExpanding 40 20 Print Size true Hei&ght: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter printHeight - + 80 0 4 0.000100000000000 10000.000000000000000 0.100000000000000 Wid&th: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter printWidth - + 80 0 4 0.000100000000000 10000.000000000000000 0.100000000000000 Resolution: 0 0 70 0 4 0.000100000000000 10000.000000000000000 0.100000000000000 Qt::Horizontal QSizePolicy::Fixed 25 20 Qt::Horizontal QSizePolicy::MinimumExpanding 40 20 Qt::Vertical QSizePolicy::Fixed 20 16 Constrain aspect ratio Constrain proportions true Adjust print size separately Qt::Vertical QSizePolicy::MinimumExpanding 20 30 KisCmbIDList
widgets/kis_cmb_idlist.h
KoAspectButton QWidget
KoAspectButton.h
1
- - KisIntParseSpinBox - QSpinBox -
kis_int_parse_spin_box.h
-
KisDoubleParseSpinBox QDoubleSpinBox
kis_double_parse_spin_box.h
+ + KisDoubleParseUnitSpinBox + QDoubleSpinBox +
kis_double_parse_unit_spin_box.h
+
- pixelWidth pixelWidthDouble pixelWidthUnit - pixelHeight pixelHeightDouble pixelHeightUnit pixelFilterCmb printWidth printWidthUnit printHeight printHeightUnit printResolution printResolutionUnit constrainProportionsCkb adjustPrintSizeSeparatelyCkb
diff --git a/plugins/extensions/offsetimage/dlg_offsetimage.cpp b/plugins/extensions/offsetimage/dlg_offsetimage.cpp index 5c4094921c..68d79ec85d 100644 --- a/plugins/extensions/offsetimage/dlg_offsetimage.cpp +++ b/plugins/extensions/offsetimage/dlg_offsetimage.cpp @@ -1,79 +1,109 @@ /* * Copyright (c) 2013 Lukáš Tvrdý * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "dlg_offsetimage.h" #include #include +#include "kis_document_aware_spin_box_unit_manager.h" + DlgOffsetImage::DlgOffsetImage(QWidget * parent, const char * name, QSize imageSize) : KoDialog(parent), m_offsetSize(imageSize) { setCaption("BUG: No sane caption is set"); setButtons(Ok | Cancel); setDefaultButton(Ok); setObjectName(name); m_lock = false; m_page = new WdgOffsetImage(this); Q_CHECK_PTR(m_page); m_page->setObjectName("offset_image"); setMainWidget(m_page); resize(m_page->sizeHint()); + _widthUnitManager = new KisDocumentAwareSpinBoxUnitManager(this); + _heightUnitManager = new KisDocumentAwareSpinBoxUnitManager(this, KisDocumentAwareSpinBoxUnitManager::PIX_DIR_Y); + + _widthUnitManager->setApparentUnitFromSymbol("px"); + _heightUnitManager->setApparentUnitFromSymbol("px"); + + m_page->offsetXdoubleSpinBox->setUnitManager(_widthUnitManager); + m_page->offsetYdoubleSpinBox->setUnitManager(_heightUnitManager); + m_page->offsetXdoubleSpinBox->setDecimals(2); + m_page->offsetYdoubleSpinBox->setDecimals(2); + m_page->offsetXdoubleSpinBox->setDisplayUnit(false); + m_page->offsetYdoubleSpinBox->setDisplayUnit(false); + + m_page->offsetXdoubleSpinBox->setReturnUnit("px"); + m_page->offsetYdoubleSpinBox->setReturnUnit("px"); + + m_page->unitXComboBox->setModel(_widthUnitManager); + m_page->unitYComboBox->setModel(_heightUnitManager); + + const int pixelUnitIndex = _widthUnitManager->getsUnitSymbolList().indexOf("px"); //TODO: have a better way to identify units. + m_page->unitXComboBox->setCurrentIndex(pixelUnitIndex); + m_page->unitYComboBox->setCurrentIndex(pixelUnitIndex); + connect(this, SIGNAL(okClicked()),this, SLOT(okClicked())); connect(m_page->middleOffsetBtn, SIGNAL(clicked()), this, SLOT(slotMiddleOffset())); - connect(m_page->offsetXspinBox, SIGNAL(valueChanged(int)), this, SLOT(slotOffsetXChanged(int))); - connect(m_page->offsetYspinBox, SIGNAL(valueChanged(int)), this, SLOT(slotOffsetYChanged(int))); + connect(m_page->offsetXdoubleSpinBox, SIGNAL(valueChangedPt(double)), this, SLOT(slotOffsetXChanged(double))); + connect(m_page->offsetYdoubleSpinBox, SIGNAL(valueChangedPt(double)), this, SLOT(slotOffsetYChanged(double))); + + connect(m_page->unitXComboBox, SIGNAL(currentIndexChanged(int)), _widthUnitManager, SLOT(selectApparentUnitFromIndex(int))); + connect(m_page->unitYComboBox, SIGNAL(currentIndexChanged(int)), _heightUnitManager, SLOT(selectApparentUnitFromIndex(int))); + connect(_widthUnitManager, SIGNAL(unitChanged(int)), m_page->unitXComboBox, SLOT(setCurrentIndex(int))); + connect(_heightUnitManager, SIGNAL(unitChanged(int)), m_page->unitYComboBox, SLOT(setCurrentIndex(int))); slotMiddleOffset(); } DlgOffsetImage::~DlgOffsetImage() { delete m_page; } -void DlgOffsetImage::slotOffsetXChanged(int newOffsetX) +void DlgOffsetImage::slotOffsetXChanged(double newOffsetX) { m_offsetX = newOffsetX; } -void DlgOffsetImage::slotOffsetYChanged(int newOffsetY) +void DlgOffsetImage::slotOffsetYChanged(double newOffsetY) { m_offsetY = newOffsetY; } void DlgOffsetImage::slotMiddleOffset() { int offsetX = m_offsetSize.width() / 2; int offsetY = m_offsetSize.height() / 2; - m_page->offsetXspinBox->setValue(offsetX); - m_page->offsetYspinBox->setValue(offsetY); + m_page->offsetXdoubleSpinBox->setValue(offsetX); + m_page->offsetYdoubleSpinBox->setValue(offsetY); } void DlgOffsetImage::okClicked() { accept(); } diff --git a/plugins/extensions/offsetimage/dlg_offsetimage.h b/plugins/extensions/offsetimage/dlg_offsetimage.h index 785d8bd2a3..a6c43612d6 100644 --- a/plugins/extensions/offsetimage/dlg_offsetimage.h +++ b/plugins/extensions/offsetimage/dlg_offsetimage.h @@ -1,66 +1,70 @@ /* * Copyright (c) 2013 Lukáš Tvrdý * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef DLG_OFFSETIMAGE #define DLG_OFFSETIMAGE #include #include #include "ui_wdg_offsetimage.h" +class KisDocumentAwareSpinBoxUnitManager; class WdgOffsetImage : public QWidget, public Ui::WdgOffsetImage { Q_OBJECT public: WdgOffsetImage(QWidget *parent) : QWidget(parent) { setupUi(this); } }; class DlgOffsetImage: public KoDialog { Q_OBJECT public: DlgOffsetImage(QWidget * parent = 0, const char* name = 0, QSize imageSize = QSize()); ~DlgOffsetImage(); int offsetX() const { return m_offsetX;} int offsetY() const { return m_offsetY;} private Q_SLOTS: void okClicked(); - void slotOffsetXChanged(int); - void slotOffsetYChanged(int); + void slotOffsetXChanged(double); + void slotOffsetYChanged(double); void slotMiddleOffset(); private: WdgOffsetImage * m_page; int m_offsetX; int m_offsetY; bool m_lock; QSize m_offsetSize; + KisDocumentAwareSpinBoxUnitManager* _widthUnitManager; + KisDocumentAwareSpinBoxUnitManager* _heightUnitManager; + }; #endif // DLG_OFFSETIMAGE diff --git a/plugins/extensions/offsetimage/wdg_offsetimage.ui b/plugins/extensions/offsetimage/wdg_offsetimage.ui index dbcf84b6bd..8a1eedac33 100644 --- a/plugins/extensions/offsetimage/wdg_offsetimage.ui +++ b/plugins/extensions/offsetimage/wdg_offsetimage.ui @@ -1,126 +1,132 @@ WdgOffsetImage 0 0 - 203 + 214 157 Rotate Image Offset - + 0 0 0 0 X: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - px - - - 999999999 + + + + 0 + 0 + + + + - + Y: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - px - - - 999999999 + + + + 0 + 0 + + + + 0 0 Offset by x/2, y/2 Qt::Vertical QSizePolicy::Minimum 0 0 - KisIntParseSpinBox - QSpinBox -
kis_int_parse_spin_box.h
+ KisDoubleParseUnitSpinBox + QDoubleSpinBox +
kis_double_parse_unit_spin_box.h