]> jfr.im git - irc/weechat/qweechat.git/blame - src/qweechat/network.py
Add option relay.lines to limit the number of lines received on connection (default...
[irc/weechat/qweechat.git] / src / qweechat / network.py
CommitLineData
fbb0156d 1#!/usr/bin/env python
7dcf23b1
SH
2# -*- coding: utf-8 -*-
3#
e836cfb0
SH
4# network.py - I/O with WeeChat/relay
5#
da74afdb 6# Copyright (C) 2011-2014 Sébastien Helleu <flashcode@flashtux.org>
7dcf23b1
SH
7#
8# This file is part of QWeeChat, a Qt remote GUI for WeeChat.
9#
10# QWeeChat is free software; you can redistribute it and/or modify
11# it under the terms of the GNU General Public License as published by
12# the Free Software Foundation; either version 3 of the License, or
13# (at your option) any later version.
14#
15# QWeeChat is distributed in the hope that it will be useful,
16# but WITHOUT ANY WARRANTY; without even the implied warranty of
17# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18# GNU General Public License for more details.
19#
20# You should have received a copy of the GNU General Public License
21# along with QWeeChat. If not, see <http://www.gnu.org/licenses/>.
22#
23
7dcf23b1
SH
24import struct
25import qt_compat
26QtCore = qt_compat.import_module('QtCore')
27QtNetwork = qt_compat.import_module('QtNetwork')
46e5dee0 28import config
7dcf23b1 29
9c265019 30_PROTO_INIT_CMD = ['init password=%(password)s']
beaa8775 31_PROTO_SYNC_CMDS = ['(listbuffers) hdata buffer:gui_buffers(*) number,full_name,short_name,type,nicklist,title,local_variables',
46e5dee0 32 '(listlines) hdata buffer:gui_buffers(*)/own_lines/last_line(-%(lines)d)/data date,displayed,prefix,message',
7dcf23b1 33 '(nicklist) nicklist',
ca67c3a7 34 'sync',
7dcf23b1
SH
35 '']
36
37
38class Network(QtCore.QObject):
39 """I/O with WeeChat/relay."""
40
41 statusChanged = qt_compat.Signal(str, str)
42 messageFromWeechat = qt_compat.Signal(QtCore.QByteArray)
43
44 def __init__(self, *args):
67ae3204 45 QtCore.QObject.__init__(*(self,) + args)
7dcf23b1
SH
46 self.status_disconnected = 'disconnected'
47 self.status_connecting = 'connecting...'
48 self.status_connected = 'connected'
49 self._server = None
50 self._port = None
77b25057 51 self._ssl = None
7dcf23b1 52 self._password = None
46e5dee0 53 self._lines = config.CONFIG_DEFAULT_RELAY_LINES
7dcf23b1 54 self._buffer = QtCore.QByteArray()
77b25057 55 self._socket = QtNetwork.QSslSocket()
7dcf23b1
SH
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)
60
61 def _socket_connected(self):
62 """Slot: socket connected."""
63 self.statusChanged.emit(self.status_connected, None)
64 if self._password:
46e5dee0
SH
65 self.send_to_weechat('\n'.join(_PROTO_INIT_CMD + _PROTO_SYNC_CMDS)
66 % {'password': str(self._password),
67 'lines': self._lines})
7dcf23b1
SH
68
69 def _socket_error(self, error):
70 """Slot: socket error."""
71 self.statusChanged.emit(self.status_disconnected, 'Failed, error: %s' % self._socket.errorString())
72
73 def _socket_read(self):
74 """Slot: data available on socket."""
77b25057 75 bytes = self._socket.readAll()
7dcf23b1
SH
76 self._buffer.append(bytes)
77 while len(self._buffer) >= 4:
78 remainder = None
79 length = struct.unpack('>i', self._buffer[0:4])[0]
80 if len(self._buffer) < length:
81 # partial message, just wait for end of message
82 break
83 # more than one message?
84 if length < len(self._buffer):
85 # save beginning of another message
86 remainder = self._buffer[length:]
87 self._buffer = self._buffer[0:length]
88 self.messageFromWeechat.emit(self._buffer)
77b25057
SH
89 if not self.is_connected():
90 return
7dcf23b1
SH
91 self._buffer.clear()
92 if remainder:
93 self._buffer.append(remainder)
94
95 def _socket_disconnected(self):
96 """Slot: socket disconnected."""
97 self._server = None
98 self._port = None
77b25057 99 self._ssl = None
7dcf23b1
SH
100 self._password = None
101 self.statusChanged.emit(self.status_disconnected, None)
102
103 def is_connected(self):
104 return self._socket.state() == QtNetwork.QAbstractSocket.ConnectedState
105
77b25057
SH
106 def is_ssl(self):
107 return self._ssl
108
46e5dee0 109 def connect_weechat(self, server, port, ssl, password, lines):
7dcf23b1
SH
110 self._server = server
111 try:
112 self._port = int(port)
113 except:
114 self._port = 0
77b25057 115 self._ssl = ssl
7dcf23b1 116 self._password = password
46e5dee0
SH
117 try:
118 self._lines = int(lines)
119 except:
120 self._lines = config.CONFIG_DEFAULT_RELAY_LINES
7dcf23b1
SH
121 if self._socket.state() == QtNetwork.QAbstractSocket.ConnectedState:
122 return
123 if self._socket.state() != QtNetwork.QAbstractSocket.UnconnectedState:
124 self._socket.abort()
125 self._socket.connectToHost(self._server, self._port)
77b25057
SH
126 if self._ssl:
127 self._socket.ignoreSslErrors()
128 self._socket.startClientEncryption()
7dcf23b1
SH
129 self.statusChanged.emit(self.status_connecting, None)
130
131 def disconnect_weechat(self):
132 if self._socket.state() != QtNetwork.QAbstractSocket.UnconnectedState:
eafb7aeb 133 if self._socket.state() == QtNetwork.QAbstractSocket.ConnectedState:
77b25057 134 self.send_to_weechat('quit\n')
eafb7aeb
SH
135 self._socket.waitForBytesWritten(1000)
136 else:
7dcf23b1
SH
137 self.statusChanged.emit(self.status_disconnected, None)
138 self._socket.abort()
139
140 def send_to_weechat(self, message):
e09c80ab 141 self._socket.write(message.encode('utf-8'))
7dcf23b1 142
beaa8775 143 def desync_weechat(self):
77b25057 144 self.send_to_weechat('desync\n')
beaa8775
SH
145
146 def sync_weechat(self):
77b25057 147 self.send_to_weechat('\n'.join(_PROTO_SYNC_CMDS))
beaa8775 148
7dcf23b1
SH
149 def status_icon(self, status):
150 icon = {self.status_disconnected: 'dialog-close.png',
151 self.status_connecting: 'dialog-close.png',
152 self.status_connected: 'dialog-ok-apply.png'}
153 return icon.get(status, '')
b548a19e 154
155 def get_options(self):
156 return {'server': self._server,
157 'port': self._port,
158 'ssl': 'on' if self._ssl else 'off',
46e5dee0
SH
159 'password': self._password,
160 'lines': str(self._lines)}