1 /** @file conditionaltrigger.cpp  Conditional trigger.
2  *
3  * @authors Copyright (c) 2017 Jaakko Keränen <jaakko.keranen@iki.fi>
4  *
5  * @par License
6  * LGPL: http://www.gnu.org/licenses/lgpl.html
7  *
8  * <small>This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU Lesser General Public License as published by
10  * the Free Software Foundation; either version 3 of the License, or (at your
11  * option) any later version. This program is distributed in the hope that it
12  * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
13  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
14  * General Public License for more details. You should have received a copy of
15  * the GNU Lesser General Public License along with this program; if not, see:
16  * http://www.gnu.org/licenses</small>
17  */
18 
19 #include "de/ConditionalTrigger"
20 #include "de/Value"
21 
22 #include <QSet>
23 
24 namespace de {
25 
DENG2_PIMPL(ConditionalTrigger)26 DENG2_PIMPL(ConditionalTrigger)
27 , DENG2_OBSERVES(Variable, Change)
28 {
29     SafePtr<Variable const> condition;
30     QSet<QString> activeTriggers;
31     bool anyTrigger = false;
32 
33     Impl(Public *i) : Base(i)
34     {}
35 
36     void variableValueChanged(Variable &, Value const &) override
37     {
38         update();
39     }
40 
41     void update()
42     {
43         anyTrigger = false;
44         activeTriggers.clear();
45 
46         if (!condition) return;
47 
48         // The condition can be a text string or an array of text strings.
49         StringList const trigs = condition->value().asStringList();
50 
51         for (String const &trig : trigs)
52         {
53             if (trig == "*")
54             {
55                 anyTrigger = true;
56                 activeTriggers.clear();
57                 break;
58             }
59             activeTriggers << trig;
60         }
61     }
62 
63     bool check(String const &trigger)
64     {
65         if (anyTrigger) return true;
66         return activeTriggers.contains(trigger);
67     }
68 };
69 
ConditionalTrigger()70 ConditionalTrigger::ConditionalTrigger()
71     : d(new Impl(this))
72 {}
73 
~ConditionalTrigger()74 ConditionalTrigger::~ConditionalTrigger()
75 {}
76 
isValid() const77 bool ConditionalTrigger::isValid() const
78 {
79     return d->condition;
80 }
81 
setCondition(Variable const & variable)82 void ConditionalTrigger::setCondition(Variable const &variable)
83 {
84     if (d->condition)
85     {
86         d->condition->audienceForChange() -= d;
87     }
88     d->condition.reset(&variable);
89     variable.audienceForChange() += d;
90     d->update();
91 }
92 
condition() const93 Variable const &ConditionalTrigger::condition() const
94 {
95     return *d->condition;
96 }
97 
tryTrigger(String const & trigger)98 bool ConditionalTrigger::tryTrigger(String const &trigger)
99 {
100     if (d->check(trigger))
101     {
102         handleTriggered(trigger);
103         return true;
104     }
105     return false;
106 }
107 
108 } // namespace de
109