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