1 # -*- coding: utf-8 -*-
3 # network.py - I/O with WeeChat/relay
5 # Copyright (C) 2011-2014 Sébastien Helleu <flashcode@flashtux.org>
7 # This file is part of QWeeChat, a Qt remote GUI for WeeChat.
9 # QWeeChat is free software; you can redistribute it and/or modify
10 # it under the terms of the GNU General Public License as published by
11 # the Free Software Foundation; either version 3 of the License, or
12 # (at your option) any later version.
14 # QWeeChat is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 # GNU General Public License for more details.
19 # You should have received a copy of the GNU General Public License
20 # along with QWeeChat. If not, see <http://www.gnu.org/licenses/>.
25 QtCore
= qt_compat
.import_module('QtCore')
26 QtNetwork
= qt_compat
.import_module('QtNetwork')
29 _PROTO_INIT_CMD
= ['init password=%(password)s']
32 '(listbuffers) hdata buffer:gui_buffers(*) number,full_name,short_name,'
33 'type,nicklist,title,local_variables',
35 '(listlines) hdata buffer:gui_buffers(*)/own_lines/last_line(-%(lines)d)/'
36 'data date,displayed,prefix,message',
38 '(nicklist) nicklist',
46 class Network(QtCore
.QObject
):
47 """I/O with WeeChat/relay."""
49 statusChanged
= qt_compat
.Signal(str, str)
50 messageFromWeechat
= qt_compat
.Signal(QtCore
.QByteArray
)
52 def __init__(self
, *args
):
53 QtCore
.QObject
.__init
__(*(self
,) + args
)
54 self
.status_disconnected
= 'disconnected'
55 self
.status_connecting
= 'connecting...'
56 self
.status_connected
= 'connected'
61 self
._lines
= config
.CONFIG_DEFAULT_RELAY_LINES
62 self
._buffer
= QtCore
.QByteArray()
63 self
._socket
= QtNetwork
.QSslSocket()
64 self
._socket
.connected
.connect(self
._socket
_connected
)
65 self
._socket
.error
.connect(self
._socket
_error
)
66 self
._socket
.readyRead
.connect(self
._socket
_read
)
67 self
._socket
.disconnected
.connect(self
._socket
_disconnected
)
69 def _socket_connected(self
):
70 """Slot: socket connected."""
71 self
.statusChanged
.emit(self
.status_connected
, None)
73 self
.send_to_weechat('\n'.join(_PROTO_INIT_CMD
+ _PROTO_SYNC_CMDS
)
74 % {'password': str(self
._password
),
75 'lines': self
._lines
})
77 def _socket_error(self
, error
):
78 """Slot: socket error."""
79 self
.statusChanged
.emit(
80 self
.status_disconnected
,
81 'Failed, error: %s' % self
._socket
.errorString())
83 def _socket_read(self
):
84 """Slot: data available on socket."""
85 data
= self
._socket
.readAll()
86 self
._buffer
.append(data
)
87 while len(self
._buffer
) >= 4:
89 length
= struct
.unpack('>i', self
._buffer
[0:4])[0]
90 if len(self
._buffer
) < length
:
91 # partial message, just wait for end of message
93 # more than one message?
94 if length
< len(self
._buffer
):
95 # save beginning of another message
96 remainder
= self
._buffer
[length
:]
97 self
._buffer
= self
._buffer
[0:length
]
98 self
.messageFromWeechat
.emit(self
._buffer
)
99 if not self
.is_connected():
103 self
._buffer
.append(remainder
)
105 def _socket_disconnected(self
):
106 """Slot: socket disconnected."""
110 self
._password
= None
111 self
.statusChanged
.emit(self
.status_disconnected
, None)
113 def is_connected(self
):
114 return self
._socket
.state() == QtNetwork
.QAbstractSocket
.ConnectedState
119 def connect_weechat(self
, server
, port
, ssl
, password
, lines
):
120 self
._server
= server
122 self
._port
= int(port
)
126 self
._password
= password
128 self
._lines
= int(lines
)
130 self
._lines
= config
.CONFIG_DEFAULT_RELAY_LINES
131 if self
._socket
.state() == QtNetwork
.QAbstractSocket
.ConnectedState
:
133 if self
._socket
.state() != QtNetwork
.QAbstractSocket
.UnconnectedState
:
135 self
._socket
.connectToHost(self
._server
, self
._port
)
137 self
._socket
.ignoreSslErrors()
138 self
._socket
.startClientEncryption()
139 self
.statusChanged
.emit(self
.status_connecting
, None)
141 def disconnect_weechat(self
):
142 if self
._socket
.state() == QtNetwork
.QAbstractSocket
.UnconnectedState
:
144 if self
._socket
.state() == QtNetwork
.QAbstractSocket
.ConnectedState
:
145 self
.send_to_weechat('quit\n')
146 self
._socket
.waitForBytesWritten(1000)
148 self
.statusChanged
.emit(self
.status_disconnected
, None)
151 def send_to_weechat(self
, message
):
152 self
._socket
.write(message
.encode('utf-8'))
154 def desync_weechat(self
):
155 self
.send_to_weechat('desync\n')
157 def sync_weechat(self
):
158 self
.send_to_weechat('\n'.join(_PROTO_SYNC_CMDS
))
160 def status_icon(self
, status
):
161 icon
= {self
.status_disconnected
: 'dialog-close.png',
162 self
.status_connecting
: 'dialog-close.png',
163 self
.status_connected
: 'dialog-ok-apply.png'}
164 return icon
.get(status
, '')
166 def get_options(self
):
167 return {'server': self
._server
,
169 'ssl': 'on' if self
._ssl
else 'off',
170 'password': self
._password
,
171 'lines': str(self
._lines
)}