File indexing completed on 2024-10-06 04:18:09

0001 /*
0002     SPDX-FileCopyrightText: 2020 Volker Krause <vkrause@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "display.h"
0008 #include "interval.h"
0009 #include "openinghours.h"
0010 
0011 #include <KLocalizedString>
0012 
0013 #include <cmath>
0014 
0015 using namespace KOpeningHours;
0016 
0017 QString Display::currentState(const OpeningHours &oh)
0018 {
0019     if (oh.error() != OpeningHours::NoError) {
0020         return {};
0021     }
0022 
0023     const auto now = QDateTime::currentDateTime();
0024     const auto i = oh.interval(now);
0025     if (i.hasOpenEnd()) {
0026         switch (i.state()) {
0027             case Interval::Open:
0028                 return i.comment().isEmpty() ? i18n("Open") : i18n("Open (%1)", i.comment());
0029             case Interval::Closed:
0030                 return i.comment().isEmpty() ? i18n("Closed") : i18n("Closed (%1)", i.comment());
0031             case Interval::Unknown:
0032             case Interval::Invalid:
0033                 return {};
0034         }
0035     }
0036 
0037     const auto next = oh.nextInterval(i);
0038     // common transitions we have texts for
0039     if ((i.state() == Interval::Closed && next.state() == Interval::Open)
0040      || (i.state() == Interval::Open && next.state() == Interval::Closed)
0041     ) {
0042 
0043         // time to change is 90 min or less
0044         const auto timeToChange = now.secsTo(i.end());
0045         if (timeToChange < 90 * 60) {
0046             const int minDiff = std::ceil(timeToChange / 60.0);
0047             switch (i.state()) {
0048                 case Interval::Open:
0049                     return i.comment().isEmpty()
0050                         ? i18np("Open for one more minute", "Open for %1 more minutes", minDiff)
0051                         : i18np("Open for one more minute (%2)", "Open for %1 more minutes (%2)", minDiff, i.comment());
0052                 case Interval::Closed:
0053                     return i.comment().isEmpty()
0054                         ? i18np("Currently closed, opens in one minute", "Currently closed, opens in %1 minutes", minDiff)
0055                         : i18np("Currently closed (%2), opens in one minute", "Currently closed (%2), opens in %1 minutes", minDiff, i.comment());
0056                 case Interval::Unknown:
0057                 case Interval::Invalid:
0058                     return {};
0059             }
0060         }
0061 
0062         // time to change is 24h or less
0063         if (timeToChange < 24 * 60 * 60) {
0064             const int hourDiff = std::round(timeToChange / (60.0 * 60.0));
0065             switch (i.state()) {
0066                 case Interval::Open:
0067                     return i.comment().isEmpty()
0068                         ? i18np("Open for one more hour", "Open for %1 more hours", hourDiff)
0069                         : i18np("Open for one more hour (%2)", "Open for %1 more hours (%2)", hourDiff, i.comment());
0070                 case Interval::Closed:
0071                     return i.comment().isEmpty()
0072                         ? i18np("Currently closed, opens in one hour", "Currently closed, opens in %1 hours", hourDiff)
0073                         : i18np("Currently closed (%2), opens in one hour", "Currently closed (%2), opens in %1 hours", hourDiff, i.comment());
0074                 case Interval::Unknown:
0075                 case Interval::Invalid:
0076                     return {};
0077             }
0078         }
0079 
0080         // time to change is 7 days or less
0081         if (timeToChange < 7 * 24 * 60 * 60) {
0082             const int dayDiff = std::round(timeToChange / (24.0 * 60.0 * 60.0));
0083             switch (i.state()) {
0084                 case Interval::Open:
0085                     return i.comment().isEmpty()
0086                         ? i18np("Open for one more day", "Open for %1 more days", dayDiff)
0087                         : i18np("Open for one more day (%2)", "Open for %1 more days (%2)", dayDiff, i.comment());
0088                 case Interval::Closed:
0089                     return i.comment().isEmpty()
0090                         ? i18np("Currently closed, opens in one day", "Currently closed, opens in %1 days", dayDiff)
0091                         : i18np("Currently closed (%2), opens in one day", "Currently closed (%2), opens in %1 days", dayDiff, i.comment());
0092                 case Interval::Unknown:
0093                 case Interval::Invalid:
0094                     return {};
0095             }
0096         }
0097     }
0098 
0099     // next change is further ahead than one week, or we are transitioning in a way we don't handle above
0100     switch (i.state()) {
0101         case Interval::Open:
0102             return i.comment().isEmpty() ? i18n("Currently open") : i18n("Currently open (%1)", i.comment());
0103         case Interval::Closed:
0104             return i.comment().isEmpty() ? i18n("Currently closed") : i18n("Currently closed (%1)", i.comment());
0105         case Interval::Unknown:
0106             return i.comment();
0107         case Interval::Invalid:
0108             return {};
0109     }
0110 
0111     return {};
0112 }
0113 
0114 #include "moc_display.cpp"