File indexing completed on 2024-04-21 04:40:44

0001 /*
0002     SPDX-FileCopyrightText: 2020 Volker Krause <vkrause@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "rule_p.h"
0008 #include "logging.h"
0009 #include "openinghours_p.h"
0010 
0011 
0012 using namespace KOpeningHours;
0013 
0014 Interval::State Rule::state() const
0015 {
0016     if (m_state == Interval::Invalid) { // implicitly defined state
0017         return m_comment.isEmpty() ? Interval::Open : Interval::Unknown;
0018     }
0019     return m_state;
0020 }
0021 
0022 bool Rule::hasImplicitState() const
0023 {
0024     return m_state == Interval::Invalid;
0025 }
0026 
0027 void Rule::setState(State state)
0028 {
0029     if (state == State::Off) {
0030         m_state = Interval::Closed;
0031         m_stateFlags = Off;
0032     } else {
0033         m_state = static_cast<Interval::State>(state);
0034     }
0035 }
0036 
0037 void Rule::copyStateFrom(const Rule &otherRule)
0038 {
0039     m_state = otherRule.m_state;
0040     m_stateFlags = otherRule.m_stateFlags;
0041 }
0042 
0043 bool Rule::hasComment() const
0044 {
0045     return !m_comment.isEmpty();
0046 }
0047 
0048 void Rule::setComment(const char *str, int len)
0049 {
0050     m_comment = QString::fromUtf8(str, len);
0051 }
0052 
0053 int Rule::requiredCapabilities() const
0054 {
0055     int c = Capability::None;
0056     c |= m_timeSelector ? m_timeSelector->requiredCapabilities() : Capability::None;
0057     c |= m_weekdaySelector ? m_weekdaySelector->requiredCapabilities() : Capability::None;
0058     c |= m_weekSelector ? m_weekSelector->requiredCapabilities() : Capability::None;
0059     c |= m_monthdaySelector ? m_monthdaySelector->requiredCapabilities() : Capability::None;
0060     c |= m_yearSelector ? m_yearSelector->requiredCapabilities() : Capability::None;
0061     c |= m_wideRangeSelectorComment.isEmpty() ? Capability::None : Capability::NotImplemented;
0062 
0063     return c;
0064 }
0065 
0066 bool Rule::isEmpty() const
0067 {
0068     return !hasComment()
0069         && hasImplicitState()
0070         && (selectorCount() == 0)
0071         && !m_seen_24_7
0072         && m_wideRangeSelectorComment.isEmpty();
0073 }
0074 
0075 bool Rule::hasSmallRangeSelector() const
0076 {
0077     return m_weekdaySelector || m_timeSelector;
0078 }
0079 
0080 bool Rule::hasWideRangeSelector() const
0081 {
0082     return m_yearSelector || m_weekSelector || m_monthdaySelector || !m_wideRangeSelectorComment.isEmpty();
0083 }
0084 
0085 QByteArray Rule::toExpression() const
0086 {
0087     QByteArray expr;
0088     if (!m_timeSelector && !m_weekdaySelector && !m_monthdaySelector && !m_weekSelector && !m_yearSelector) {
0089         if (m_seen_24_7) {
0090             expr = "24/7";
0091         }
0092     }
0093     auto maybeSpace = [&]() {
0094         if (!expr.isEmpty()) {
0095             expr += ' ';
0096         }
0097     };
0098     if (m_yearSelector) {
0099         expr = m_yearSelector->toExpression();
0100     }
0101     if (m_monthdaySelector) {
0102         maybeSpace();
0103         expr += m_monthdaySelector->toExpression({});
0104     }
0105     if (m_weekSelector) {
0106         maybeSpace();
0107         expr += "week " + m_weekSelector->toExpression();
0108     }
0109     if (!m_wideRangeSelectorComment.isEmpty()) {
0110         expr += '"' + m_wideRangeSelectorComment.toUtf8() + '"';
0111     }
0112     if (m_colonAfterWideRangeSelector) {
0113         expr += ':';
0114     }
0115     if (m_weekdaySelector) {
0116         maybeSpace();
0117         expr += m_weekdaySelector->toExpression();
0118     }
0119     if (m_timeSelector) {
0120         maybeSpace();
0121         expr += m_timeSelector->toExpression();
0122     }
0123     switch (m_state) {
0124     case Interval::Open:
0125         maybeSpace();
0126         expr += "open";
0127         break;
0128     case Interval::Closed:
0129         maybeSpace();
0130         expr += m_stateFlags & Off ? "off" : "closed";
0131         break;
0132     case Interval::Unknown:
0133         maybeSpace();
0134         expr += "unknown";
0135         break;
0136     case Interval::Invalid:
0137         break;
0138     }
0139     if (!m_comment.isEmpty()) {
0140         if (!expr.isEmpty()) {
0141             expr += ' ';
0142         }
0143         expr += '"' + m_comment.toUtf8() + '"';
0144     }
0145     return expr;
0146 }
0147 
0148 int Rule::selectorCount() const
0149 {
0150     const auto selectors = { (bool)m_yearSelector, (bool)m_monthdaySelector, (bool)m_weekSelector, (bool)m_weekdaySelector, (bool)m_timeSelector };
0151     return std::count(std::begin(selectors), std::end(selectors), true);
0152 }