gadu: add some transition for disconnections
[kadu:kadu.git] / plugins / gadu_protocol / services / gadu-contact-list-state-machine.cpp
1 /*
2  * %kadu copyright begin%
3  * Copyright 2011 RafaƂ Malinowski (rafal.przemyslaw.malinowski@gmail.com)
4  * Copyright 2011, 2013 Bartosz Brachaczek (b.brachaczek@gmail.com)
5  * %kadu copyright end%
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License as
9  * published by the Free Software Foundation; either version 2 of
10  * the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program. If not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include <QtCore/QHistoryState>
22 #include <QtCore/QStringList>
23
24 #include "protocols/protocol.h"
25 #include "debug.h"
26
27 #include "services/gadu-contact-list-service.h"
28
29 #include "gadu-contact-list-state-machine.h"
30
31 GaduContactListStateMachine::GaduContactListStateMachine(GaduContactListService *service, Protocol *protocol) :
32                 QStateMachine(service)
33 {
34         auto globalState = new QState(ParallelStates);
35
36         WorkState = new QState(globalState);
37         OfflineState = new QState(WorkState);
38         IdleState = new QState(WorkState);
39         PutState = new QState(WorkState);
40         GetState = new QState(WorkState);
41
42         OfflineState->addTransition(protocol, SIGNAL(connected(Account)), IdleState);
43         IdleState->addTransition(service, SIGNAL(stateMachinePutStarted()), PutState);
44         IdleState->addTransition(service, SIGNAL(stateMachineGetStarted()), GetState);
45         IdleState->addTransition(protocol, SIGNAL(disconnected(Account)), OfflineState);
46         PutState->addTransition(service, SIGNAL(stateMachinePutFinished()), IdleState);
47         PutState->addTransition(service, SIGNAL(stateMachinePutFailed()), IdleState);
48         PutState->addTransition(protocol, SIGNAL(disconnected(Account)), OfflineState);
49         GetState->addTransition(service, SIGNAL(stateMachineGetFinished()), IdleState);
50         GetState->addTransition(service, SIGNAL(stateMachineGetFailed()), IdleState);
51         GetState->addTransition(protocol, SIGNAL(disconnected(Account)), OfflineState);
52
53         LocalState = new QState(globalState);
54         LocalCleanState = new QState(LocalState);
55         LocalDirtyState = new QState(LocalState);
56         LocalCleaningState = new QState(LocalState);
57         LocalCleaningDirtyState = new QState(LocalState);
58         LocalFailedState = new QState(LocalState);
59
60         LocalCleanState->addTransition(service, SIGNAL(stateMachineLocalDirty()), LocalDirtyState);
61         LocalDirtyState->addTransition(service, SIGNAL(stateMachinePutStarted()), LocalCleaningState);
62         LocalCleaningState->addTransition(service, SIGNAL(stateMachineLocalDirty()), LocalCleaningDirtyState);
63         LocalCleaningState->addTransition(service, SIGNAL(stateMachinePutFinished()), LocalCleanState);
64         LocalCleaningState->addTransition(service, SIGNAL(stateMachinePutFailed()), LocalFailedState);
65         LocalCleaningState->addTransition(protocol, SIGNAL(disconnected(Account)), LocalDirtyState);
66         LocalCleaningDirtyState->addTransition(service, SIGNAL(stateMachinePutFinished()), LocalDirtyState);
67         LocalCleaningDirtyState->addTransition(service, SIGNAL(stateMachinePutFailed()), LocalDirtyState);
68         LocalCleaningDirtyState->addTransition(protocol, SIGNAL(disconnected(Account)), LocalDirtyState);
69         LocalFailedState->addTransition(service, SIGNAL(stateMachineLocalDirty()), LocalDirtyState);
70         LocalFailedState->addTransition(protocol, SIGNAL(connected(Account)), LocalDirtyState);
71         LocalFailedState->addTransition(protocol, SIGNAL(disconnected(Account)), LocalDirtyState);
72
73         RemoteState = new QState(globalState);
74         RemoteCleanState = new QState(RemoteState);
75         RemoteDirtyState = new QState(RemoteState);
76         RemoteCleaningState = new QState(RemoteState);
77         RemoteCleaningDirtyState = new QState(RemoteState);
78         RemoteFailedState = new QState(RemoteState);
79
80         RemoteCleanState->addTransition(service, SIGNAL(stateMachineRemoteDirty()), RemoteDirtyState);
81         RemoteDirtyState->addTransition(service, SIGNAL(stateMachineGetStarted()), RemoteCleaningState);
82         RemoteCleaningState->addTransition(service, SIGNAL(stateMachineRemoteDirty()), RemoteCleaningDirtyState);
83         RemoteCleaningState->addTransition(service, SIGNAL(stateMachineGetFinished()), RemoteCleanState);
84         RemoteCleaningState->addTransition(service, SIGNAL(stateMachineGetFailed()), RemoteFailedState);
85         RemoteCleaningState->addTransition(protocol, SIGNAL(disconnected(Account)), RemoteDirtyState);
86         RemoteCleaningDirtyState->addTransition(service, SIGNAL(stateMachineGetFinished()), RemoteDirtyState);
87         RemoteCleaningDirtyState->addTransition(service, SIGNAL(stateMachineGetFailed()), RemoteDirtyState);
88         RemoteCleaningDirtyState->addTransition(protocol, SIGNAL(disconnected(Account)), RemoteDirtyState);
89         RemoteFailedState->addTransition(service, SIGNAL(stateMachineRemoteDirty()), RemoteDirtyState);
90         RemoteFailedState->addTransition(protocol, SIGNAL(connected(Account)), RemoteDirtyState);
91         RemoteFailedState->addTransition(protocol, SIGNAL(disconnected(Account)), RemoteDirtyState);
92
93         LocalState->setInitialState(LocalCleanState);
94         RemoteState->setInitialState(RemoteDirtyState);
95         WorkState->setInitialState(protocol->isConnected() ? IdleState : OfflineState);
96
97         connect(IdleState, SIGNAL(entered()), this, SLOT(checkIfSynchronizationRequired()));
98         connect(LocalDirtyState, SIGNAL(entered()), this, SLOT(checkIfSynchronizationRequired()));
99         connect(RemoteDirtyState, SIGNAL(entered()), this, SLOT(checkIfSynchronizationRequired()));
100
101         connect(OfflineState, SIGNAL(entered()), this, SLOT(printConfiguration()));
102         connect(IdleState, SIGNAL(entered()), this, SLOT(printConfiguration()));
103         connect(PutState, SIGNAL(entered()), this, SLOT(printConfiguration()));
104         connect(GetState, SIGNAL(entered()), this, SLOT(printConfiguration()));
105         connect(LocalCleanState, SIGNAL(entered()), this, SLOT(printConfiguration()));
106         connect(LocalDirtyState, SIGNAL(entered()), this, SLOT(printConfiguration()));
107         connect(LocalCleaningState, SIGNAL(entered()), this, SLOT(printConfiguration()));
108         connect(LocalCleaningDirtyState, SIGNAL(entered()), this, SLOT(printConfiguration()));
109         connect(LocalFailedState, SIGNAL(entered()), this, SLOT(printConfiguration()));
110         connect(RemoteCleanState, SIGNAL(entered()), this, SLOT(printConfiguration()));
111         connect(RemoteDirtyState, SIGNAL(entered()), this, SLOT(printConfiguration()));
112         connect(RemoteCleaningState, SIGNAL(entered()), this, SLOT(printConfiguration()));
113         connect(RemoteCleaningDirtyState, SIGNAL(entered()), this, SLOT(printConfiguration()));
114         connect(RemoteFailedState, SIGNAL(entered()), this, SLOT(printConfiguration()));
115
116         addState(globalState);
117
118         setInitialState(globalState);
119 }
120
121 GaduContactListStateMachine::~GaduContactListStateMachine()
122 {
123 }
124
125 void GaduContactListStateMachine::printConfiguration()
126 {
127         QStringList states;
128
129         if (configuration().contains(OfflineState))
130                 states.append("offline");
131         if (configuration().contains(IdleState))
132                 states.append("idle");
133         if (configuration().contains(PutState))
134                 states.append("put");
135         if (configuration().contains(GetState))
136                 states.append("get");
137         if (configuration().contains(LocalCleanState))
138                 states.append("local-clean");
139         if (configuration().contains(LocalDirtyState))
140                 states.append("local-dirty");
141         if (configuration().contains(LocalCleaningState))
142                 states.append("local-cleaning");
143         if (configuration().contains(LocalCleaningDirtyState))
144                 states.append("local-cleaning-dirty");
145         if (configuration().contains(LocalFailedState))
146                 states.append("local-failed");
147         if (configuration().contains(RemoteCleanState))
148                 states.append("remote-clean");
149         if (configuration().contains(RemoteDirtyState))
150                 states.append("remote-dirty");
151         if (configuration().contains(RemoteCleaningState))
152                 states.append("remote-cleaning");
153         if (configuration().contains(RemoteCleaningDirtyState))
154                 states.append("remote-cleaning-dirty");
155         if (configuration().contains(RemoteFailedState))
156                 states.append("remote-failed");
157
158         kdebugm(KDEBUG_INFO, "Gadu contact list state machine: [%s]\n", qPrintable(states.join(", ")));
159 }
160
161 void GaduContactListStateMachine::checkIfSynchronizationRequired()
162 {
163         if (shouldPerformGet())
164                 emit performGet();
165         else if (shouldPerformPut())
166                 emit performPut();
167 }
168
169 bool GaduContactListStateMachine::shouldPerformPut() const
170 {
171         return configuration().contains(IdleState) && configuration().contains(LocalDirtyState) && !configuration().contains(RemoteDirtyState);
172 }
173
174 bool GaduContactListStateMachine::isPerformingPut() const
175 {
176         return configuration().contains(PutState);
177 }
178
179 bool GaduContactListStateMachine::shouldPerformGet() const
180 {
181         return configuration().contains(IdleState) && configuration().contains(RemoteDirtyState);
182 }
183
184 bool GaduContactListStateMachine::isPerformingGet() const
185 {
186         return configuration().contains(GetState);
187 }
188
189 #include "moc_gadu-contact-list-state-machine.cpp"