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 SearchFieldRangeDate::SearchFieldRangeDate(QObject* const parent, Type type)
0022     : SearchField     (parent),
0023       m_firstTimeEdit (nullptr),
0024       m_firstDateEdit (nullptr),
0025       m_secondTimeEdit(nullptr),
0026       m_secondDateEdit(nullptr),
0027       m_type          (type)
0028 {
0029     m_betweenLabel = new QLabel;
0030 }
0031 
0032 void SearchFieldRangeDate::setupValueWidgets(QGridLayout* layout, int row, int column)
0033 {
0034 /*
0035     QHBoxLayout *hbox = new QHBoxLayout;
0036     layout->addLayout(hbox, row, column, 1, 3);
0037 */
0038     m_firstDateEdit  = new DDateEdit;
0039     m_secondDateEdit = new DDateEdit;
0040 
0041     if (m_type == DateOnly)
0042     {
0043         layout->addWidget(m_firstDateEdit,  row, column);
0044         layout->addWidget(m_betweenLabel,   row, column + 1, Qt::AlignHCenter);
0045         layout->addWidget(m_secondDateEdit, row, column + 2);
0046     }
0047     else
0048     {
0049         QHBoxLayout* const hbox1 = new QHBoxLayout;
0050         QHBoxLayout* const hbox2 = new QHBoxLayout;
0051 
0052         m_firstTimeEdit  = new QTimeEdit;
0053         m_secondTimeEdit = new QTimeEdit;
0054 
0055         hbox1->addWidget(m_firstDateEdit);
0056         hbox1->addWidget(m_firstTimeEdit);
0057         hbox2->addWidget(m_secondDateEdit);
0058         hbox2->addWidget(m_secondTimeEdit);
0059 
0060         layout->addLayout(hbox1,          row, column);
0061         layout->addWidget(m_betweenLabel, row, column + 1, Qt::AlignHCenter);
0062         layout->addLayout(hbox2,          row, column + 2);
0063     }
0064 
0065     connect(m_firstDateEdit, SIGNAL(dateChanged(QDate)),
0066             this, SLOT(valueChanged()));
0067 
0068     connect(m_secondDateEdit, SIGNAL(dateChanged(QDate)),
0069             this, SLOT(valueChanged()));
0070 }
0071 
0072 void SearchFieldRangeDate::setBetweenText(const QString& between)
0073 {
0074     m_betweenLabel->setText(between);
0075 }
0076 
0077 void SearchFieldRangeDate::read(SearchXmlCachingReader& reader)
0078 {
0079     SearchXml::Relation relation = reader.fieldRelation();
0080 
0081     if ((relation == SearchXml::Interval) || (relation == SearchXml::IntervalOpen))
0082     {
0083         QList<QDateTime> dates = reader.valueToDateTimeList();
0084 
0085         if (dates.size() != 2)
0086         {
0087             return;
0088         }
0089 
0090         if (m_type == DateTime)
0091         {
0092             m_firstDateEdit->setDate(dates.first().date());
0093             m_firstTimeEdit->setTime(dates.first().time());
0094             m_secondDateEdit->setDate(dates.last().date());
0095             m_secondTimeEdit->setTime(dates.last().time());
0096         }
0097         else
0098         {
0099             if (relation == SearchXml::Interval)
0100             {
0101                 dates.last() = dates.last().addDays(-1);
0102             }
0103 
0104             m_firstDateEdit->setDate(dates.first().date());
0105             m_secondDateEdit->setDate(dates.last().date());
0106         }
0107     }
0108     else
0109     {
0110         QDateTime dt = reader.valueToDateTime();
0111 
0112         if (m_type == DateTime)
0113         {
0114             if      (relation == SearchXml::Equal)
0115             {
0116                 m_firstDateEdit->setDate(dt.date());
0117                 m_firstTimeEdit->setTime(dt.time());
0118                 m_secondDateEdit->setDate(dt.date());
0119                 m_secondTimeEdit->setTime(dt.time());
0120             }
0121             else if (relation == SearchXml::GreaterThanOrEqual || relation == SearchXml::GreaterThan)
0122             {
0123                 m_firstDateEdit->setDate(dt.date());
0124                 m_firstTimeEdit->setTime(dt.time());
0125             }
0126 
0127             {
0128                 m_secondDateEdit->setDate(dt.date());
0129                 m_secondTimeEdit->setTime(dt.time());
0130             }
0131         }
0132         else
0133         {
0134             // In DateOnly mode, we always assume dealing with the beginning of the day, QTime(0,0,0).
0135             // In the UI, we show the date only (including the whole day).
0136             // The difference between ...Than and ...ThanOrEqual is only one second, ignored.
0137 
0138             if      (relation == SearchXml::Equal)
0139             {
0140                 m_firstDateEdit->setDate(dt.date());
0141                 m_secondDateEdit->setDate(dt.date());
0142             }
0143             else if (relation == SearchXml::GreaterThanOrEqual || relation == SearchXml::GreaterThan)
0144             {
0145                 m_firstDateEdit->setDate(dt.date());
0146             }
0147             else if (relation == SearchXml::LessThanOrEqual || relation == SearchXml::LessThan)
0148             {
0149                 dt = dt.addDays(-1);
0150                 m_secondDateEdit->setDate(dt.date());
0151             }
0152         }
0153     }
0154 
0155     valueChanged();
0156 }
0157 
0158 void SearchFieldRangeDate::write(SearchXmlWriter& writer)
0159 {
0160     if (m_firstDateEdit->date().isValid() && m_secondDateEdit->date().isValid())
0161     {
0162         QDateTime firstDate = startOfDay(m_firstDateEdit->date());
0163 
0164         if (m_type == DateTime)
0165         {
0166             firstDate.setTime(m_firstTimeEdit->time());
0167         }
0168 
0169         QDateTime secondDate = startOfDay(m_secondDateEdit->date());
0170 
0171         if (m_type == DateTime)
0172         {
0173             secondDate.setTime(m_secondTimeEdit->time());
0174         }
0175 
0176         if (firstDate == secondDate)
0177         {
0178             writer.writeField(m_name, SearchXml::Equal);
0179             writer.writeValue(firstDate);
0180             writer.finishField();
0181         }
0182         else
0183         {
0184             if (m_type == DateOnly)
0185             {
0186                 secondDate = secondDate.addDays(1);
0187             }
0188 
0189             writer.writeField(m_name, SearchXml::Interval);
0190             writer.writeValue(QList<QDateTime>() << firstDate << secondDate);
0191             writer.finishField();
0192         }
0193     }
0194     else
0195     {
0196         QDate date = m_firstDateEdit->date();
0197 
0198         if (date.isValid())
0199         {
0200             writer.writeField(m_name, SearchXml::GreaterThanOrEqual);
0201             QDateTime dt = startOfDay(date);
0202 
0203             if (m_type == DateTime)
0204             {
0205                 dt.setTime(m_firstTimeEdit->time());
0206             }
0207 
0208             writer.writeValue(dt);
0209             writer.finishField();
0210         }
0211 
0212         date = m_secondDateEdit->date();
0213 
0214         if (date.isValid())
0215         {
0216             writer.writeField(m_name, SearchXml::LessThan);
0217             QDateTime dt = startOfDay(date);
0218 
0219             if (m_type == DateTime)
0220             {
0221                 dt.setTime(m_secondTimeEdit->time());
0222             }
0223             else
0224             {
0225                 dt = dt.addDays(1);    // include whole day
0226             }
0227 
0228             writer.writeValue(dt);
0229             writer.finishField();
0230         }
0231     }
0232 }
0233 
0234 void SearchFieldRangeDate::reset()
0235 {
0236     m_firstDateEdit->setDate(QDate());
0237 
0238     if (m_type == DateTime)
0239     {
0240         m_firstTimeEdit->setTime(QTime(0, 0, 0, 0));
0241     }
0242 
0243     m_secondDateEdit->setDate(QDate());
0244 
0245     if (m_type == DateTime)
0246     {
0247         m_secondTimeEdit->setTime(QTime(0, 0, 0, 0));
0248     }
0249 
0250     valueChanged();
0251 }
0252 
0253 void SearchFieldRangeDate::setBoundary(const QDateTime& min, const QDateTime& max)
0254 {
0255     // something here?
0256 
0257     Q_UNUSED(min);
0258     Q_UNUSED(max);
0259 }
0260 
0261 void SearchFieldRangeDate::setValueWidgetsVisible(bool visible)
0262 {
0263     m_firstDateEdit->setVisible(visible);
0264 
0265     if (m_firstTimeEdit)
0266     {
0267         m_firstTimeEdit->setVisible(visible);
0268     }
0269 
0270     m_secondDateEdit->setVisible(visible);
0271 
0272     if (m_secondTimeEdit)
0273     {
0274         m_secondTimeEdit->setVisible(visible);
0275     }
0276 
0277     m_betweenLabel->setVisible(visible);
0278 }
0279 
0280 QList<QRect> SearchFieldRangeDate::valueWidgetRects() const
0281 {
0282     QList<QRect> rects;
0283     rects << m_firstDateEdit->geometry();
0284 
0285     if (m_firstTimeEdit)
0286     {
0287         rects << m_firstTimeEdit->geometry();
0288     }
0289 
0290     rects << m_secondDateEdit->geometry();
0291 
0292     if (m_secondTimeEdit)
0293     {
0294         rects << m_secondTimeEdit->geometry();
0295     }
0296 
0297     return rects;
0298 }
0299 
0300 void SearchFieldRangeDate::valueChanged()
0301 {
0302     setValidValueState(m_firstDateEdit->date().isValid() || m_secondDateEdit->date().isValid());
0303 }
0304 
0305 //-----------------------------------------------------------------------------
0306 
0307 SearchFieldRangeTime::SearchFieldRangeTime(QObject* const parent)
0308     : SearchField     (parent),
0309       m_firstTimeEdit (nullptr),
0310       m_secondTimeEdit(nullptr)
0311 {
0312     m_betweenLabel = new QLabel;
0313 }
0314 
0315 void SearchFieldRangeTime::setupValueWidgets(QGridLayout* layout, int row, int column)
0316 {
0317     m_firstTimeEdit  = new QTimeEdit;
0318     m_secondTimeEdit = new QTimeEdit;
0319 
0320     layout->addWidget(m_firstTimeEdit,  row, column);
0321     layout->addWidget(m_betweenLabel,   row, column + 1, Qt::AlignHCenter);
0322     layout->addWidget(m_secondTimeEdit, row, column + 2);
0323 
0324     connect(m_firstTimeEdit, SIGNAL(timeChanged(QTime)),
0325             this, SLOT(valueChanged()));
0326 
0327     connect(m_secondTimeEdit, SIGNAL(timeChanged(QTime)),
0328             this, SLOT(valueChanged()));
0329 }
0330 
0331 void SearchFieldRangeTime::setBetweenText(const QString& between)
0332 {
0333     m_betweenLabel->setText(between);
0334 }
0335 
0336 void SearchFieldRangeTime::read(SearchXmlCachingReader& reader)
0337 {
0338     SearchXml::Relation relation = reader.fieldRelation();
0339 
0340     if      (relation == SearchXml::Interval)
0341     {
0342         QList<QDateTime> dates = reader.valueToDateTimeList();
0343 
0344         if (dates.size() != 2)
0345         {
0346             return;
0347         }
0348 
0349         m_firstTimeEdit->setTime(dates.first().time());
0350         m_secondTimeEdit->setTime(dates.last().time());
0351     }
0352 
0353     valueChanged();
0354 }
0355 
0356 void SearchFieldRangeTime::write(SearchXmlWriter& writer)
0357 {
0358     if (m_firstTimeEdit->time().isValid() && m_secondTimeEdit->time().isValid())
0359     {
0360         int time = m_firstTimeEdit->time().hour()   +
0361                    m_firstTimeEdit->time().minute() +
0362                    m_secondTimeEdit->time().hour()  +
0363                    m_secondTimeEdit->time().minute();
0364 
0365         if (time > 0)
0366         {
0367             QDateTime firstDate = QDateTime::currentDateTime();
0368             firstDate.setTime(m_firstTimeEdit->time());
0369 
0370             QDateTime secondDate = QDateTime::currentDateTime();
0371             secondDate.setTime(m_secondTimeEdit->time());
0372 
0373             writer.writeField(m_name, SearchXml::Interval);
0374             writer.writeValue(QList<QDateTime>() << firstDate << secondDate);
0375             writer.finishField();
0376         }
0377     }
0378 }
0379 
0380 void SearchFieldRangeTime::reset()
0381 {
0382     m_firstTimeEdit->setTime(QTime(0, 0, 0, 0));
0383     m_secondTimeEdit->setTime(QTime(0, 0, 0, 0));
0384 
0385     valueChanged();
0386 }
0387 
0388 void SearchFieldRangeTime::setBoundary(const QTime& min, const QTime& max)
0389 {
0390     // something here?
0391 
0392     Q_UNUSED(min);
0393     Q_UNUSED(max);
0394 }
0395 
0396 void SearchFieldRangeTime::setValueWidgetsVisible(bool visible)
0397 {
0398     m_firstTimeEdit->setVisible(visible);
0399     m_secondTimeEdit->setVisible(visible);
0400     m_betweenLabel->setVisible(visible);
0401 }
0402 
0403 QList<QRect> SearchFieldRangeTime::valueWidgetRects() const
0404 {
0405     QList<QRect> rects;
0406     rects << m_firstTimeEdit->geometry();
0407     rects << m_secondTimeEdit->geometry();
0408 
0409     return rects;
0410 }
0411 
0412 void SearchFieldRangeTime::valueChanged()
0413 {
0414     int time       = 0;
0415     bool validTime = (m_firstTimeEdit->time().isValid() &&
0416                       m_secondTimeEdit->time().isValid());
0417 
0418     if (validTime)
0419     {
0420         QTime secondTime = m_secondTimeEdit->time();
0421 
0422         if (m_firstTimeEdit->time() >= secondTime)
0423         {
0424             secondTime = m_firstTimeEdit->time();
0425         }
0426 
0427         m_secondTimeEdit->setTime(QTime(secondTime.hour(),
0428                                         secondTime.minute(), 59));
0429 
0430         time = m_firstTimeEdit->time().hour()   +
0431                m_firstTimeEdit->time().minute() +
0432                m_secondTimeEdit->time().hour()  +
0433                m_secondTimeEdit->time().minute();
0434     }
0435 
0436     setValidValueState(validTime && (time > 0));
0437 }
0438 
0439 } // namespace Digikam