2 # -*- coding: utf-8 -*-
4 # Copyright (C) 2011-2012 Sebastien Helleu <flashcode@flashtux.org>
6 # This file is part of QWeeChat, a Qt remote GUI for WeeChat.
8 # QWeeChat is free software; you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation; either version 3 of the License, or
11 # (at your option) any later version.
13 # QWeeChat is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details.
18 # You should have received a copy of the GNU General Public License
19 # along with QWeeChat. If not, see <http://www.gnu.org/licenses/>.
23 # I/O with WeeChat/relay.
28 QtCore
= qt_compat
.import_module('QtCore')
29 QtNetwork
= qt_compat
.import_module('QtNetwork')
31 _PROTO_INIT_CMD
= ['init password=%(password)s,compression=gzip']
32 _PROTO_SYNC_CMDS
= ['(listbuffers) hdata buffer:gui_buffers(*) number,full_name,short_name,type,nicklist,title,local_variables',
33 '(listlines) hdata buffer:gui_buffers(*)/own_lines/first_line(*)/data date,displayed,prefix,message',
34 '(nicklist) nicklist',
39 class Network(QtCore
.QObject
):
40 """I/O with WeeChat/relay."""
42 statusChanged
= qt_compat
.Signal(str, str)
43 messageFromWeechat
= qt_compat
.Signal(QtCore
.QByteArray
)
45 def __init__(self
, *args
):
46 QtCore
.QObject
.__init
__(*(self
,) + args
)
47 self
.status_disconnected
= 'disconnected'
48 self
.status_connecting
= 'connecting...'
49 self
.status_connected
= 'connected'
54 self
._buffer
= QtCore
.QByteArray()
55 self
._socket
= QtNetwork
.QSslSocket()
56 self
._socket
.connected
.connect(self
._socket
_connected
)
57 self
._socket
.error
.connect(self
._socket
_error
)
58 self
._socket
.readyRead
.connect(self
._socket
_read
)
59 self
._socket
.disconnected
.connect(self
._socket
_disconnected
)
61 def _socket_connected(self
):
62 """Slot: socket connected."""
63 self
.statusChanged
.emit(self
.status_connected
, None)
65 self
.send_to_weechat('\n'.join(_PROTO_INIT_CMD
+ _PROTO_SYNC_CMDS
) % {'password': str(self._password)}
)
67 def _socket_error(self
, error
):
68 """Slot: socket error."""
69 self
.statusChanged
.emit(self
.status_disconnected
, 'Failed, error: %s' % self
._socket
.errorString())
71 def _socket_read(self
):
72 """Slot: data available on socket."""
73 bytes = self
._socket
.readAll()
74 self
._buffer
.append(bytes)
75 while len(self
._buffer
) >= 4:
77 length
= struct
.unpack('>i', self
._buffer
[0:4])[0]
78 if len(self
._buffer
) < length
:
79 # partial message, just wait for end of message
81 # more than one message?
82 if length
< len(self
._buffer
):
83 # save beginning of another message
84 remainder
= self
._buffer
[length
:]
85 self
._buffer
= self
._buffer
[0:length
]
86 self
.messageFromWeechat
.emit(self
._buffer
)
87 if not self
.is_connected():
91 self
._buffer
.append(remainder
)
93 def _socket_disconnected(self
):
94 """Slot: socket disconnected."""
99 self
.statusChanged
.emit(self
.status_disconnected
, None)
101 def is_connected(self
):
102 return self
._socket
.state() == QtNetwork
.QAbstractSocket
.ConnectedState
107 def connect_weechat(self
, server
, port
, ssl
, password
):
108 self
._server
= server
110 self
._port
= int(port
)
114 self
._password
= password
115 if self
._socket
.state() == QtNetwork
.QAbstractSocket
.ConnectedState
:
117 if self
._socket
.state() != QtNetwork
.QAbstractSocket
.UnconnectedState
:
119 self
._socket
.connectToHost(self
._server
, self
._port
)
121 self
._socket
.ignoreSslErrors()
122 self
._socket
.startClientEncryption()
123 self
.statusChanged
.emit(self
.status_connecting
, None)
125 def disconnect_weechat(self
):
126 if self
._socket
.state() != QtNetwork
.QAbstractSocket
.UnconnectedState
:
127 if self
._socket
.state() == QtNetwork
.QAbstractSocket
.ConnectedState
:
128 self
.send_to_weechat('quit\n')
129 self
._socket
.waitForBytesWritten(1000)
131 self
.statusChanged
.emit(self
.status_disconnected
, None)
134 def send_to_weechat(self
, message
):
135 self
._socket
.write(str(message
))
137 def desync_weechat(self
):
138 self
.send_to_weechat('desync\n')
140 def sync_weechat(self
):
141 self
.send_to_weechat('\n'.join(_PROTO_SYNC_CMDS
))
143 def status_icon(self
, status
):
144 icon
= {self
.status_disconnected
: 'dialog-close.png',
145 self
.status_connecting
: 'dialog-close.png',
146 self
.status_connected
: 'dialog-ok-apply.png'}
147 return icon
.get(status
, '')