1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
/* ============================================================
 *
 * This file is a part of digiKam project
 * https://www.digikam.org
 *
 * Date        : 1997-04-21
 * Description : A date selection widget.
 *
 * SPDX-FileCopyrightText: 2011-2026 by Gilles Caulier <caulier dot gilles at gmail dot com>
 * SPDX-FileCopyrightText: 1997      by Tim D. Gilman <tdgilman at best dot org>
 * SPDX-FileCopyrightText: 1998-2001 by Mirko Boehm <mirko at kde dot org>
 * SPDX-FileCopyrightText: 2007      by John Layt <john at layt dot net>
 *
 * SPDX-License-Identifier: GPL-2.0-or-later
 *
 * ============================================================ */

#include "ddatepicker_p.h"

// Qt includes

#include <QFontDatabase>

// KDE includes

#include <klocalizedstring.h>

namespace Digikam
{

DatePickerValidator::DatePickerValidator(DDatePicker* const parent)
    : QValidator(parent),
      m_picker  (parent)
{
}

QValidator::State DatePickerValidator::validate(QString& text, int&) const
{
    QLocale::FormatType formats[] =
    {
        QLocale::LongFormat,
        QLocale::ShortFormat,
        QLocale::NarrowFormat
    };

    QLocale locale = m_picker->locale();

    for (int i = 0 ; i < 3 ; ++i)
    {
        QDate tmp = locale.toDate(text, formats[i]);

        if (tmp.isValid())
        {
            return Acceptable;
        }
    }

    return QValidator::Intermediate;
}

// ------------------------------------------------------------------------------

/**
 * NOTE: Week numbers are defined by ISO 8601
 * See https://en.wikipedia.org/wiki/Week#Week_numbering for details
 */
DatePickerYearSelector::DatePickerYearSelector(const QDate& currentDate, QWidget* const parent)
    : QLineEdit(parent),
      val      (new QIntValidator(this)),
      oldDate  (currentDate)
{
    setFont(QFontDatabase::systemFont(QFontDatabase::GeneralFont));

    setFrame(false);

/*
    TODO: Find a way to get that from QLocale

    val->setRange(calendar->year(calendar->earliestValidDate()),
                  calendar->year(calendar->latestValidDate()));
*/
    setValidator(val);

    connect(this, &QLineEdit::returnPressed,
            this, &DatePickerYearSelector::yearEnteredSlot);
}

void DatePickerYearSelector::yearEnteredSlot()
{
    bool ok;
    int newYear;

    // check if entered value is a number

    newYear = text().toInt(&ok);

    if (!ok)
    {
        QApplication::beep();
        return;
    }

    // check if new year will lead to a valid date

    if (QDate(newYear, oldDate.month(), oldDate.day()).isValid())
    {
        result = newYear;

        Q_EMIT closeMe(1);
    }
    else
    {
        QApplication::beep();
    }
}

int DatePickerYearSelector::year() const
{
    return result;
}

void DatePickerYearSelector::setYear(int year)<--- Shadow argument
{
    setText(QString::number(year));
}

// ------------------------------------------------------------------------------

DDatePicker::Private::Private(DDatePicker* const qq)
    : q(qq)
{
}

void DDatePicker::Private::fillWeeksCombo()
{
    /**
     * @note Every year can have a different number of weeks
     * it could be that we had 53,1..52 and now 1..53 which is the same number but different
     * so always fill with new values
     * We show all week numbers for all weeks between first day of year to last day of year
     * This of course can be a list like 53,1,2..52
     */
    const QDate thisDate      = q->date();
    const int thisYear        = thisDate.year();
    QDate day(thisDate.year(), 1, 1);
    const QDate lastDayOfYear = QDate(thisDate.year() + 1, 1, 1).addDays(-1);

    selectWeek->clear();

    // Starting from the first day in the year, loop through the year a week at a time
    // adding an entry to the week combo for each week in the year

    for ( ; day.isValid() && (day <= lastDayOfYear) ; (day = day.addDays(7)))
    {
        // Get the ISO week number for the current day and what year that week is in
        // e.g. 1st day of this year may fall in week 53 of previous year

        int weekYear       = thisYear;
        const int week     = day.weekNumber(&weekYear);
        QString weekString = i18n("Week %1", week);

        // show that this is a week from a different year

        if (weekYear != thisYear)
        {
            weekString += QLatin1Char('*');
        }

        // when the week is selected, go to the same weekday as the one
        // that is currently selected in the date table

        QDate targetDate = day.addDays(thisDate.dayOfWeek() - day.dayOfWeek());
        selectWeek->addItem(weekString, targetDate);

        // make sure that the week of the lastDayOfYear is always inserted: in Chinese calendar
        // system, this is not always the case

        if (
            (day < lastDayOfYear)           &&
            (day.daysTo(lastDayOfYear) < 7) &&
            (lastDayOfYear.weekNumber() != day.weekNumber())
           )
        {
            day = lastDayOfYear.addDays(-7);
        }
    }
}

QDate DDatePicker::Private::validDateInYearMonth(int year, int month)
{
    QDate newDate;

    // Try to create a valid date in this year and month
    // First try the first of the month, then try last of month

    if      (QDate(year, month, 1).isValid())
    {
        newDate = QDate(year, month, 1);
    }
    else if (QDate(year, month + 1, 1).isValid())
    {
        newDate = QDate(year, month + 1, 1).addDays(-1);
    }
    else
    {
        newDate = QDate::fromJulianDay(0);
    }

    return newDate;
}

} // namespace Digikam

#include "moc_ddatepicker_p.cpp"