First crack at a session model
[gc-dialer] / src / session.py
1 import os
2 import logging
3
4 from PyQt4 import QtCore
5
6
7 _moduleLogger = logging.getLogger(__name__)
8
9
10 class Draft(QtCore.QObject):
11
12         sendingMessage = QtCore.pyqtSignal()
13         sentMessage = QtCore.pyqtSignal()
14         calling = QtCore.pyqtSignal()
15         called = QtCore.pyqtSignal()
16         cancelling = QtCore.pyqtSignal()
17         cancelled = QtCore.pyqtSignal()
18         error = QtCore.pyqtSignal(str)
19
20         recipientsChanged = QtCore.pyqtSignal()
21
22         def __init__(self):
23                 self._contacts = []
24
25         def send(self, text):
26                 assert 0 < len(self._contacts)
27                 self.sendingMessage.emit()
28                 self.error.emit("Not Implemented")
29                 # self.clear()
30
31         def call(self):
32                 assert 0 < len(self._contacts)
33                 self.calling.emit()
34                 self.error.emit("Not Implemented")
35                 # self.clear()
36
37         def cancel(self):
38                 self.cancelling.emit()
39                 self.error.emit("Not Implemented")
40
41         def add_contact(self, contact):
42                 assert contact not in self._contacts
43                 self._contacts.append(contact)
44                 self.recipientsChanged.emit()
45
46         def remove_contact(self, contact):
47                 assert contact not in self._contacts
48                 self._contacts.remove(contact)
49                 self.recipientsChanged.emit()
50
51         def get_contacts(self, contact):
52                 return self._contacts
53
54         def clear(self):
55                 self._contacts = []
56                 self.recipientsChanged.emit()
57
58
59 class Session(QtCore.QObject):
60
61         stateChange = QtCore.pyqtSignal(str)
62         loggedOut = QtCore.pyqtSignal()
63         loggedIn = QtCore.pyqtSignal()
64         callbackNumberChanged = QtCore.pyqtSignal(str)
65
66         contactsUpdated = QtCore.pyqtSignal()
67         messagesUpdated = QtCore.pyqtSignal()
68         historyUpdated = QtCore.pyqtSignal()
69         dndStateChange = QtCore.pyqtSignal(bool)
70
71         error = QtCore.pyqtSignal(str)
72
73         LOGGEDOUT_STATE = "logged out"
74         LOGGINGIN_STATE = "logging in"
75         LOGGEDIN_STATE = "logged in"
76
77         _LOGGEDOUT_TIME = -1
78         _LOGGINGING_TIME = 0
79
80         def __init__(self, cachePath = None):
81                 QtCore.QObject.__init__(self)
82                 self._loggedInTime = self._LOGGEDOUT_TIME
83                 self._loginOps = []
84                 self._cachePath = cachePath
85                 self._username = None
86                 self._draft = Draft()
87
88                 self._contacts = []
89                 self._messages = []
90                 self._history = []
91                 self._dnd = False
92
93         @property
94         def state(self):
95                 return {
96                         self._LOGGEDOUT_TIME: self.LOGGEDOUT_STATE,
97                         self._LOGGINGIN_TIME: self.LOGGINGIN_STATE,
98                 }.get(self._loggedInTime, default=self.LOGGEDIN_STATE)
99
100         @property
101         def draft(self):
102                 return self._draft
103
104         def login(self, username, password):
105                 assert self.state == self.LOGGEDOUT_STATE
106                 if self._cachePath is not None:
107                         cookiePath = os.path.join(self._cachePath, "%s.cookies" % username)
108                 else:
109                         cookiePath = None
110
111                 self.error.emit("Not Implemented")
112
113                 # if the username is the same, do nothing
114                 # else clear the in-memory caches and attempt to load from file-caches
115                 # If caches went from empty to something, fire signals
116
117         def logout(self):
118                 assert self.state != self.LOGGEDOUT_STATE
119                 self.error.emit("Not Implemented")
120
121         def clear(self):
122                 assert self.state == self.LOGGEDOUT_STATE
123                 self._draft.clear()
124                 self._contacts = []
125                 self.contactsUpdated.emit()
126                 self._messages = []
127                 self.messagesUpdated.emit()
128                 self._history = []
129                 self.historyUpdated.emit()
130                 self._dnd = False
131                 self.dndStateChange.emit(self._dnd)
132
133         def update_contacts(self):
134                 self._perform_op_while_loggedin(self._update_contacts)
135
136         def get_contacts(self):
137                 return self._contacts
138
139         def update_messages(self):
140                 self._perform_op_while_loggedin(self._update_messages)
141
142         def get_messages(self):
143                 return self._messages
144
145         def update_history(self):
146                 self._perform_op_while_loggedin(self._update_history)
147
148         def get_history(self):
149                 return self._history
150
151         def update_dnd(self):
152                 self._perform_op_while_loggedin(self._update_dnd)
153
154         def set_dnd(self, dnd):
155                 assert self.state == self.LOGGEDIN_STATE
156                 self.error.emit("Not Implemented")
157
158         def get_dnd(self):
159                 return self._dnd
160
161         def get_callback_numbers(self):
162                 return []
163
164         def get_callback_number(self):
165                 return ""
166
167         def set_callback_number(self):
168                 assert self.state == self.LOGGEDIN_STATE
169                 self.error.emit("Not Implemented")
170
171         def _update_contacts(self):
172                 self.error.emit("Not Implemented")
173
174         def _update_messages(self):
175                 self.error.emit("Not Implemented")
176
177         def _update_history(self):
178                 self.error.emit("Not Implemented")
179
180         def _update_dnd(self):
181                 self.error.emit("Not Implemented")
182
183         def _perform_op_while_loggedin(self, op):
184                 if self.state == self.LOGGEDIN_STATE:
185                         op()
186                 else:
187                         self._push_login_op(op)
188
189         def _push_login_op(self, op):
190                 assert self.state != self.LOGGEDIN_STATE
191                 if op in self._loginOps:
192                         _moduleLogger.info("Skipping queueing duplicate op: %r" % op)
193                         return
194                 self._loginOps.append(op)