File indexing completed on 2025-01-05 04:47:40
0001 /* 0002 SPDX-FileCopyrightText: 2010 Casey Link <unnamedrambler@gmail.com> 0003 SPDX-FileCopyrightText: 2009-2010 Klaralvdalens Datakonsult AB, a KDAB Group company <info@kdab.net> 0004 0005 SPDX-License-Identifier: LGPL-2.0-or-later 0006 */ 0007 0008 #include "freeperiodmodel.h" 0009 0010 #include <KFormat> 0011 #include <KLocalizedString> 0012 0013 #include <QDateTime> 0014 #include <QLocale> 0015 #include <QTimeZone> 0016 0017 using namespace CalendarSupport; 0018 0019 FreePeriodModel::FreePeriodModel(QObject *parent) 0020 : QAbstractTableModel(parent) 0021 { 0022 } 0023 0024 FreePeriodModel::~FreePeriodModel() = default; 0025 0026 QVariant FreePeriodModel::data(const QModelIndex &index, int role) const 0027 { 0028 if (!index.isValid() || !hasIndex(index.row(), index.column())) { 0029 return {}; 0030 } 0031 0032 if (index.column() == 0) { // day 0033 switch (role) { 0034 case Qt::DisplayRole: 0035 return day(index.row()); 0036 case Qt::ToolTipRole: 0037 return tooltipify(index.row()); 0038 case FreePeriodModel::PeriodRole: 0039 return QVariant::fromValue(mPeriodList.at(index.row())); 0040 case Qt::TextAlignmentRole: 0041 return static_cast<int>(Qt::AlignRight | Qt::AlignVCenter); 0042 default: 0043 return {}; 0044 } 0045 } else { // everything else 0046 switch (role) { 0047 case Qt::DisplayRole: 0048 return date(index.row()); 0049 case Qt::ToolTipRole: 0050 return tooltipify(index.row()); 0051 case FreePeriodModel::PeriodRole: 0052 return QVariant::fromValue(mPeriodList.at(index.row())); 0053 case Qt::TextAlignmentRole: 0054 return static_cast<int>(Qt::AlignLeft | Qt::AlignVCenter); 0055 default: 0056 return {}; 0057 } 0058 } 0059 } 0060 0061 int FreePeriodModel::rowCount(const QModelIndex &parent) const 0062 { 0063 if (!parent.isValid()) { 0064 return mPeriodList.size(); 0065 } 0066 return 0; 0067 } 0068 0069 int FreePeriodModel::columnCount(const QModelIndex &parent) const 0070 { 0071 Q_UNUSED(parent) 0072 return 2; 0073 } 0074 0075 QVariant FreePeriodModel::headerData(int section, Qt::Orientation orientation, int role) const 0076 { 0077 return QAbstractItemModel::headerData(section, orientation, role); 0078 } 0079 0080 void FreePeriodModel::slotNewFreePeriods(const KCalendarCore::Period::List &freePeriods) 0081 { 0082 beginResetModel(); 0083 mPeriodList.clear(); 0084 mPeriodList = splitPeriodsByDay(freePeriods); 0085 std::sort(mPeriodList.begin(), mPeriodList.end()); 0086 endResetModel(); 0087 } 0088 0089 KCalendarCore::Period::List FreePeriodModel::splitPeriodsByDay(const KCalendarCore::Period::List &freePeriods) 0090 { 0091 KCalendarCore::Period::List splitList; 0092 for (const KCalendarCore::Period &period : freePeriods) { 0093 if (period.start().date() == period.end().date()) { 0094 splitList << period; // period occurs on the same day 0095 continue; 0096 } 0097 0098 const int validPeriodSecs = 300; // 5 minutes 0099 KCalendarCore::Period tmpPeriod = period; 0100 while (tmpPeriod.start().date() != tmpPeriod.end().date()) { 0101 const QDateTime midnight(tmpPeriod.start().date(), QTime(23, 59, 59, 999), tmpPeriod.start().timeZone()); 0102 KCalendarCore::Period firstPeriod(tmpPeriod.start(), midnight); 0103 KCalendarCore::Period secondPeriod(midnight.addMSecs(1), tmpPeriod.end()); 0104 if (firstPeriod.duration().asSeconds() >= validPeriodSecs) { 0105 splitList << firstPeriod; 0106 } 0107 tmpPeriod = secondPeriod; 0108 } 0109 if (tmpPeriod.duration().asSeconds() >= validPeriodSecs) { 0110 splitList << tmpPeriod; 0111 } 0112 } 0113 0114 // Perform some jiggery pokery to remove duplicates 0115 std::sort(splitList.begin(), splitList.end()); 0116 splitList.erase(std::unique(splitList.begin(), splitList.end()), splitList.end()); 0117 return splitList; 0118 } 0119 0120 QString FreePeriodModel::day(int index) const 0121 { 0122 KCalendarCore::Period period = mPeriodList.at(index); 0123 const QDate startDate = period.start().date(); 0124 return ki18nc("@label Day of the week name, example: Monday,", "%1,") 0125 .subs(QLocale::system().dayName(startDate.dayOfWeek(), QLocale::LongFormat)) 0126 .toString(); 0127 } 0128 0129 QString FreePeriodModel::date(int index) const 0130 { 0131 KCalendarCore::Period period = mPeriodList.at(index); 0132 0133 const QDate startDate = period.start().date(); 0134 const QString startTime = QLocale::system().toString(period.start().time(), QLocale::ShortFormat); 0135 const QString endTime = QLocale::system().toString(period.end().time(), QLocale::ShortFormat); 0136 const QString longMonthName = QLocale::system().monthName(startDate.month()); 0137 return ki18nc( 0138 "@label A time period duration. It is preceded/followed (based on the " 0139 "orientation) by the name of the week, see the message above. " 0140 "example: 12 June, 8:00am to 9:30am", 0141 "%1 %2, %3 to %4") 0142 .subs(startDate.day()) 0143 .subs(longMonthName) 0144 .subs(startTime) 0145 .subs(endTime) 0146 .toString(); 0147 } 0148 0149 QString FreePeriodModel::stringify(int index) const 0150 { 0151 KCalendarCore::Period period = mPeriodList.at(index); 0152 0153 const QDate startDate = period.start().date(); 0154 const QString startTime = QLocale().toString(period.start().time(), QLocale::ShortFormat); 0155 const QString endTime = QLocale().toString(period.end().time(), QLocale::ShortFormat); 0156 const QString longMonthName = QLocale::system().monthName(startDate.month(), QLocale::LongFormat); 0157 const QString dayofWeek = QLocale::system().dayName(startDate.dayOfWeek(), QLocale::LongFormat); 0158 0159 return ki18nc( 0160 "@label A time period duration. KLocale is used to format the components. " 0161 "example: Monday, 12 June, 8:00am to 9:30am", 0162 "%1, %2 %3, %4 to %5") 0163 .subs(dayofWeek) 0164 .subs(startDate.day()) 0165 .subs(longMonthName) 0166 .subs(startTime) 0167 .subs(endTime) 0168 .toString(); 0169 } 0170 0171 QString FreePeriodModel::tooltipify(int index) const 0172 { 0173 KCalendarCore::Period period = mPeriodList.at(index); 0174 unsigned long duration = period.duration().asSeconds() * 1000; // we want milliseconds 0175 QString toolTip = QStringLiteral("<qt>"); 0176 toolTip += QLatin1StringView("<b>") + i18nc("@info:tooltip", "Free Period") + QLatin1StringView("</b>"); 0177 toolTip += QLatin1StringView("<hr>"); 0178 toolTip += QLatin1StringView("<i>") + i18nc("@info:tooltip period start time", "Start:") + QLatin1StringView("</i> "); 0179 toolTip += QLocale().toString(period.start().toLocalTime(), QLocale::ShortFormat); 0180 toolTip += QLatin1StringView("<br>"); 0181 toolTip += QLatin1StringView("<i>") + i18nc("@info:tooltip period end time", "End:") + QLatin1StringView("</i> "); 0182 toolTip += QLocale().toString(period.end().toLocalTime(), QLocale::ShortFormat); 0183 toolTip += QLatin1StringView("<br>"); 0184 toolTip += QLatin1StringView("<i>") + i18nc("@info:tooltip period duration", "Duration:") + QLatin1StringView("</i> "); 0185 toolTip += KFormat().formatSpelloutDuration(duration); 0186 toolTip += QLatin1StringView("</qt>"); 0187 return toolTip; 0188 } 0189 0190 #include "moc_freeperiodmodel.cpp"