File indexing completed on 2025-01-05 04:00:05

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2008-01-20
0007  * Description : User interface for searches
0008  *
0009  * SPDX-FileCopyrightText: 2008-2012 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
0010  * SPDX-FileCopyrightText: 2011-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0011  *
0012  * SPDX-License-Identifier: GPL-2.0-or-later
0013  *
0014  * ============================================================ */
0015 
0016 #include "searchfields_p.h"
0017 
0018 namespace Digikam
0019 {
0020 
0021 SearchFieldRangeInt::SearchFieldRangeInt(QObject* const parent)
0022     : SearchField   (parent),
0023       m_min         (0),
0024       m_max         (100),
0025       m_reciprocal  (false),
0026       m_firstBox    (nullptr),
0027       m_secondBox   (nullptr)
0028 {
0029     m_betweenLabel = new QLabel;
0030     m_firstBox     = new CustomStepsIntSpinBox;
0031     m_secondBox    = new CustomStepsIntSpinBox;
0032 }
0033 
0034 void SearchFieldRangeInt::setupValueWidgets(QGridLayout* layout, int row, int column)
0035 {
0036 /*
0037     QHBoxLayout *hbox = new QHBoxLayout;
0038     layout->addLayout(hbox, row, column);
0039 */
0040     m_firstBox->setSpecialValueText(QLatin1String(" "));
0041     m_secondBox->setSpecialValueText(QLatin1String(" "));
0042 /*
0043     hbox->addWidget(m_firstBox);
0044     hbox->addWidget(m_betweenLabel);
0045     hbox->addWidget(m_secondBox);
0046     hbox->addStretch(1);
0047 */
0048     layout->addWidget(m_firstBox, row, column);
0049     layout->addWidget(m_betweenLabel, row, column + 1, Qt::AlignHCenter);
0050     layout->addWidget(m_secondBox, row, column + 2);
0051 
0052     connect(m_firstBox, SIGNAL(valueChanged(int)),
0053             this, SLOT(valueChanged()));
0054 
0055     connect(m_secondBox, SIGNAL(valueChanged(int)),
0056             this, SLOT(valueChanged()));
0057 }
0058 
0059 void SearchFieldRangeInt::read(SearchXmlCachingReader& reader)
0060 {
0061     SearchXml::Relation relation = reader.fieldRelation();
0062 
0063     if (m_reciprocal)
0064     {
0065         switch (relation)
0066         {
0067             case SearchXml::LessThanOrEqual:
0068             case SearchXml::LessThan:
0069                 m_firstBox->setFractionMagicValue(reader.valueToDouble());
0070                 break;
0071 
0072             case SearchXml::GreaterThanOrEqual:
0073             case SearchXml::GreaterThan:
0074                 m_secondBox->setFractionMagicValue(reader.valueToDouble());
0075                 break;
0076 
0077             case SearchXml::Equal:
0078                 m_firstBox->setFractionMagicValue(reader.valueToDouble());
0079                 m_secondBox->setFractionMagicValue(reader.valueToDouble());
0080                 break;
0081 
0082             case SearchXml::Interval:
0083             case SearchXml::IntervalOpen:
0084             {
0085                 QList<double> list = reader.valueToDoubleList();
0086 
0087                 if (list.size() != 2)
0088                 {
0089                     return;
0090                 }
0091 
0092                 m_secondBox->setFractionMagicValue(list.first());
0093                 m_firstBox->setFractionMagicValue(list.last());
0094                 break;
0095             }
0096 
0097             default:
0098                 break;
0099         }
0100     }
0101     else
0102     {
0103         switch (relation)
0104         {
0105             case SearchXml::GreaterThanOrEqual:
0106                 m_firstBox->setValue(reader.valueToInt());
0107                 break;
0108 
0109             case SearchXml::GreaterThan:
0110                 m_firstBox->setValue(reader.valueToInt() - 1);
0111                 break;
0112 
0113             case SearchXml::LessThanOrEqual:
0114                 m_secondBox->setValue(reader.valueToInt());
0115                 break;
0116 
0117             case SearchXml::LessThan:
0118                 m_secondBox->setValue(reader.valueToInt() + 1);
0119                 break;
0120 
0121             case SearchXml::Equal:
0122                 m_firstBox->setValue(reader.valueToInt());
0123                 m_secondBox->setValue(reader.valueToInt());
0124                 break;
0125 
0126             case SearchXml::Interval:
0127             case SearchXml::IntervalOpen:
0128             {
0129                 QList<int> list = reader.valueToIntList();
0130 
0131                 if (list.size() != 2)
0132                 {
0133                     return;
0134                 }
0135 
0136                 m_firstBox->setValue(list.first());
0137                 m_secondBox->setValue(list.last());
0138                 break;
0139             }
0140 
0141             default:
0142                 break;
0143         }
0144     }
0145 }
0146 
0147 void SearchFieldRangeInt::write(SearchXmlWriter& writer)
0148 {
0149     if ((m_firstBox->value()  != m_firstBox->minimum()) &&
0150         (m_secondBox->value() != m_secondBox->minimum()))
0151     {
0152         if (m_firstBox->value() != m_secondBox->value())
0153         {
0154             writer.writeField(m_name, SearchXml::Interval);
0155 
0156             if (m_reciprocal)
0157             {
0158                 writer.writeValue(QList<float>() << m_secondBox->fractionMagicValue() << m_firstBox->fractionMagicValue());
0159             }
0160             else
0161             {
0162                 writer.writeValue(QList<int>() << m_firstBox->value() << m_secondBox->value());
0163             }
0164 
0165             writer.finishField();
0166         }
0167         else
0168         {
0169             /**
0170              * @todo : This condition is never met.
0171              * Right value is either displayed empty (minimum, greater than left)
0172              * or one step larger than left
0173              */
0174 
0175             writer.writeField(m_name, SearchXml::Equal);
0176 
0177             if (m_reciprocal)
0178             {
0179                 writer.writeValue(m_firstBox->fractionMagicValue());
0180             }
0181             else
0182             {
0183                 writer.writeValue(m_firstBox->value());
0184             }
0185 
0186             writer.finishField();
0187         }
0188     }
0189     else
0190     {
0191         if (m_firstBox->value() != m_firstBox->minimum())
0192         {
0193             if (m_reciprocal)
0194             {
0195                 writer.writeField(m_name, SearchXml::LessThanOrEqual);
0196                 writer.writeValue(m_firstBox->fractionMagicValue());
0197             }
0198             else
0199             {
0200                 writer.writeField(m_name, SearchXml::GreaterThanOrEqual);
0201                 writer.writeValue(m_firstBox->value());
0202             }
0203 
0204             writer.finishField();
0205         }
0206 
0207         if (m_secondBox->value() != m_secondBox->minimum())
0208         {
0209             if (m_reciprocal)
0210             {
0211                 writer.writeField(m_name, SearchXml::GreaterThanOrEqual);
0212                 writer.writeValue(m_secondBox->fractionMagicValue());
0213             }
0214             else
0215             {
0216                 writer.writeField(m_name, SearchXml::LessThanOrEqual);
0217                 writer.writeValue(m_secondBox->value());
0218             }
0219 
0220             writer.finishField();
0221         }
0222     }
0223 }
0224 
0225 void SearchFieldRangeInt::setBetweenText(const QString& text)
0226 {
0227     m_betweenLabel->setText(text);
0228 }
0229 
0230 void SearchFieldRangeInt::setNumberPrefixAndSuffix(const QString& prefix, const QString& suffix)
0231 {
0232     m_firstBox->setPrefix(prefix);
0233     m_secondBox->setPrefix(prefix);
0234     m_firstBox->setSuffix(suffix);
0235     m_secondBox->setSuffix(suffix);
0236 }
0237 
0238 void SearchFieldRangeInt::setBoundary(int min, int max, int step)
0239 {
0240     if (m_reciprocal)
0241     {
0242         m_min = max;
0243         m_max = min;
0244     }
0245     else
0246     {
0247         m_min = min;
0248         m_max = max;
0249     }
0250 
0251     m_firstBox->setRange(m_min, m_max);
0252     m_firstBox->setSingleStep(step);
0253     m_firstBox->setValue(m_min);
0254 
0255     m_secondBox->setRange(m_min, m_max);
0256     m_secondBox->setSingleStep(step);
0257     m_secondBox->setValue(m_min);
0258 }
0259 
0260 void SearchFieldRangeInt::enableFractionMagic(const QString& prefix)
0261 {
0262     m_reciprocal = true;
0263 
0264     m_firstBox->enableFractionMagic(prefix);
0265     m_firstBox->setInvertStepping(true);
0266 
0267     m_secondBox->enableFractionMagic(prefix);
0268     m_secondBox->setInvertStepping(true);
0269 }
0270 
0271 void SearchFieldRangeInt::setSuggestedValues(const QList<int>& values)
0272 {
0273     m_firstBox->setSuggestedValues(values);
0274     m_secondBox->setSuggestedValues(values);
0275 }
0276 
0277 void SearchFieldRangeInt::setSuggestedInitialValue(int value)
0278 {
0279     m_firstBox->setSuggestedInitialValue(value);
0280     m_secondBox->setSuggestedInitialValue(value);
0281 }
0282 
0283 void SearchFieldRangeInt::setSingleSteps(int smaller, int larger)
0284 {
0285     m_firstBox->setSingleSteps(smaller, larger);
0286     m_secondBox->setSingleSteps(smaller, larger);
0287 }
0288 
0289 void SearchFieldRangeInt::setInvertStepping(bool invert)
0290 {
0291     m_firstBox->setInvertStepping(invert);
0292     m_secondBox->setInvertStepping(invert);
0293 }
0294 
0295 void SearchFieldRangeInt::valueChanged()
0296 {
0297     bool validValue = false;
0298 
0299     if (m_reciprocal)
0300     {
0301         bool firstAtMinimum  = (m_firstBox->value()  == m_firstBox->minimum());
0302         bool secondAtMinimum = (m_secondBox->value() == m_secondBox->minimum());
0303 
0304         if (!secondAtMinimum)
0305         {
0306             m_firstBox->setRange(m_secondBox->value() - 1, m_max);
0307             validValue = true;
0308         }
0309 
0310         if (!firstAtMinimum)
0311         {
0312             m_secondBox->setRange(m_min - 1, m_firstBox->value());
0313 
0314             if (secondAtMinimum)
0315             {
0316                 m_firstBox->setRange(m_min, m_max);
0317                 m_secondBox->setValue(m_secondBox->minimum());
0318             }
0319 
0320             validValue = true;
0321         }
0322 
0323         if (firstAtMinimum && secondAtMinimum)
0324         {
0325             m_firstBox->setRange(m_min, m_max);
0326             m_secondBox->setRange(m_min, m_max);
0327         }
0328     }
0329     else
0330     {
0331         bool firstAtMinimum  = (m_firstBox->value()  == m_firstBox->minimum());
0332         bool secondAtMinimum = (m_secondBox->value() == m_secondBox->minimum());
0333 
0334         if (!secondAtMinimum)
0335         {
0336             m_firstBox->setRange(m_min, m_secondBox->value());
0337             validValue = true;
0338         }
0339 
0340         if (!firstAtMinimum)
0341         {
0342             m_secondBox->setRange(m_firstBox->value() - 1, m_max);
0343 
0344             if (secondAtMinimum)
0345             {
0346                 m_firstBox->setRange(m_min, m_max);
0347                 m_secondBox->setValue(m_secondBox->minimum());
0348             }
0349 
0350             validValue = true;
0351         }
0352 
0353         if (firstAtMinimum && secondAtMinimum)
0354         {
0355             m_firstBox->setRange(m_min, m_max);
0356             m_secondBox->setRange(m_min, m_max);
0357         }
0358     }
0359 
0360     setValidValueState(validValue);
0361 }
0362 
0363 void SearchFieldRangeInt::reset()
0364 {
0365     m_firstBox->setRange(m_min, m_max);
0366     m_secondBox->setRange(m_min, m_max);
0367     m_firstBox->reset();
0368     m_secondBox->reset();
0369 }
0370 
0371 void SearchFieldRangeInt::setValueWidgetsVisible(bool visible)
0372 {
0373     m_firstBox->setVisible(visible);
0374     m_secondBox->setVisible(visible);
0375     m_betweenLabel->setVisible(visible);
0376 }
0377 
0378 QList<QRect> SearchFieldRangeInt::valueWidgetRects() const
0379 {
0380     QList<QRect> rects;
0381     rects << m_firstBox->geometry();
0382     rects << m_secondBox->geometry();
0383 
0384     return rects;
0385 }
0386 
0387 } // namespace Digikam