8 """ |
8 """ |
9 |
9 |
10 import collections |
10 import collections |
11 |
11 |
12 from PyQt4.QtCore import QObject, pyqtSignal, QProcess, QRegExp |
12 from PyQt4.QtCore import QObject, pyqtSignal, QProcess, QRegExp |
13 from PyQt4.QtNetwork import QHostInfo, QHostAddress, QAbstractSocket, QNetworkInterface |
13 from PyQt4.QtNetwork import QHostInfo, QHostAddress, QAbstractSocket, \ |
|
14 QNetworkInterface |
14 |
15 |
15 from .CooperationServer import CooperationServer |
16 from .CooperationServer import CooperationServer |
16 from .Connection import Connection |
17 from .Connection import Connection |
17 |
18 |
18 import Preferences |
19 import Preferences |
21 class CooperationClient(QObject): |
22 class CooperationClient(QObject): |
22 """ |
23 """ |
23 Class implementing the client of the cooperation package. |
24 Class implementing the client of the cooperation package. |
24 |
25 |
25 @signal newMessage(user, message) emitted after a new message has |
26 @signal newMessage(user, message) emitted after a new message has |
26 arrived (string, string) |
27 arrived (string, string) |
27 @signal newParticipant(nickname) emitted after a new participant joined (string) |
28 @signal newParticipant(nickname) emitted after a new participant joined |
|
29 (string) |
28 @signal participantLeft(nickname) emitted after a participant left (string) |
30 @signal participantLeft(nickname) emitted after a participant left (string) |
29 @signal connectionError(message) emitted when a connection error occurs (string) |
31 @signal connectionError(message) emitted when a connection error occurs |
|
32 (string) |
30 @signal cannotConnect() emitted, if the initial connection fails |
33 @signal cannotConnect() emitted, if the initial connection fails |
31 @signal editorCommand(hash, filename, message) emitted when an editor command |
34 @signal editorCommand(hash, filename, message) emitted when an editor |
32 has been received (string, string, string) |
35 command has been received (string, string, string) |
33 """ |
36 """ |
34 newMessage = pyqtSignal(str, str) |
37 newMessage = pyqtSignal(str, str) |
35 newParticipant = pyqtSignal(str) |
38 newParticipant = pyqtSignal(str) |
36 participantLeft = pyqtSignal(str) |
39 participantLeft = pyqtSignal(str) |
37 connectionError = pyqtSignal(str) |
40 connectionError = pyqtSignal(str) |
152 |
155 |
153 def removeConnection(self, connection): |
156 def removeConnection(self, connection): |
154 """ |
157 """ |
155 Public method to remove a connection. |
158 Public method to remove a connection. |
156 |
159 |
157 @param connection reference to the connection to be removed (Connection) |
160 @param connection reference to the connection to be removed |
|
161 (Connection) |
158 """ |
162 """ |
159 if connection.peerAddress() in self.__peers and \ |
163 if connection.peerAddress() in self.__peers and \ |
160 connection in self.__peers[connection.peerAddress()]: |
164 connection in self.__peers[connection.peerAddress()]: |
161 self.__peers[connection.peerAddress()].remove(connection) |
165 self.__peers[connection.peerAddress()].remove(connection) |
162 nick = connection.name() |
166 nick = connection.name() |
200 |
204 |
201 def __connectionError(self, socketError): |
205 def __connectionError(self, socketError): |
202 """ |
206 """ |
203 Private slot to handle a connection error. |
207 Private slot to handle a connection error. |
204 |
208 |
205 @param socketError reference to the error object (QAbstractSocket.SocketError) |
209 @param socketError reference to the error object |
|
210 (QAbstractSocket.SocketError) |
206 """ |
211 """ |
207 connection = self.sender() |
212 connection = self.sender() |
208 if socketError != QAbstractSocket.RemoteHostClosedError: |
213 if socketError != QAbstractSocket.RemoteHostClosedError: |
209 if connection.peerPort() != 0: |
214 if connection.peerPort() != 0: |
210 msg = "* {0}:{1}\n{2}\n".format( |
215 msg = "* {0}:{1}\n{2}\n".format( |
254 @param host host to connect to (string) |
259 @param host host to connect to (string) |
255 @param port port to connect to (integer) |
260 @param port port to connect to (integer) |
256 """ |
261 """ |
257 self.__initialConnection = Connection(self) |
262 self.__initialConnection = Connection(self) |
258 self.__newConnection(self.__initialConnection) |
263 self.__newConnection(self.__initialConnection) |
259 self.__initialConnection.participants.connect(self.__processParticipants) |
264 self.__initialConnection.participants.connect( |
|
265 self.__processParticipants) |
260 self.__initialConnection.connectToHost(host, port) |
266 self.__initialConnection.connectToHost(host, port) |
261 |
267 |
262 def __getParticipants(self): |
268 def __getParticipants(self): |
263 """ |
269 """ |
264 Private slot to handle the request for a list of participants. |
270 Private slot to handle the request for a list of participants. |
267 participants = [] |
273 participants = [] |
268 for connectionList in self.__peers.values(): |
274 for connectionList in self.__peers.values(): |
269 for connection in connectionList: |
275 for connection in connectionList: |
270 if connection != reqConnection: |
276 if connection != reqConnection: |
271 participants.append("{0}@{1}".format( |
277 participants.append("{0}@{1}".format( |
272 connection.peerAddress().toString(), connection.serverPort())) |
278 connection.peerAddress().toString(), |
|
279 connection.serverPort())) |
273 reqConnection.sendParticipants(participants) |
280 reqConnection.sendParticipants(participants) |
274 |
281 |
275 def __processParticipants(self, participants): |
282 def __processParticipants(self, participants): |
276 """ |
283 """ |
277 Private slot to handle the receipt of a list of participants. |
284 Private slot to handle the receipt of a list of participants. |
278 |
285 |
279 @param participants list of participants (list of strings of "host:port") |
286 @param participants list of participants (list of strings of |
|
287 "host:port") |
280 """ |
288 """ |
281 for participant in participants: |
289 for participant in participants: |
282 host, port = participant.split("@") |
290 host, port = participant.split("@") |
283 port = int(port) |
291 port = int(port) |
284 |
292 |
285 if port == 0: |
293 if port == 0: |
286 msg = self.trUtf8("Illegal address: {0}@{1}\n").format(host, port) |
294 msg = self.trUtf8("Illegal address: {0}@{1}\n").format( |
|
295 host, port) |
287 self.connectionError.emit(msg) |
296 self.connectionError.emit(msg) |
288 else: |
297 else: |
289 if not self.hasConnection(QHostAddress(host), port): |
298 if not self.hasConnection(QHostAddress(host), port): |
290 connection = Connection(self) |
299 connection = Connection(self) |
291 self.__newConnection(connection) |
300 self.__newConnection(connection) |
307 def __findConnections(self, nick): |
316 def __findConnections(self, nick): |
308 """ |
317 """ |
309 Public method to get a list of connection given a nick name. |
318 Public method to get a list of connection given a nick name. |
310 |
319 |
311 @param nick nick name in the format of self.nickName() (string) |
320 @param nick nick name in the format of self.nickName() (string) |
312 @return list of references to the connection objects (list of Connection) |
321 @return list of references to the connection objects (list of |
|
322 Connection) |
313 """ |
323 """ |
314 if "@" not in nick: |
324 if "@" not in nick: |
315 # nick given in wrong format |
325 # nick given in wrong format |
316 return [] |
326 return [] |
317 |
327 |
397 server.close() |
407 server.close() |
398 self.__listening = False |
408 self.__listening = False |
399 |
409 |
400 def errorString(self): |
410 def errorString(self): |
401 """ |
411 """ |
402 Public method to get a human readable error message about the last server error. |
412 Public method to get a human readable error message about the last |
403 |
413 server error. |
404 @return human readable error message about the last server error (string) |
414 |
|
415 @return human readable error message about the last server error |
|
416 (string) |
405 """ |
417 """ |
406 return self.__serversErrorString |
418 return self.__serversErrorString |