]>
Commit | Line | Data |
---|---|---|
77df9d06 SH |
1 | # -*- coding: utf-8 -*- |
2 | # | |
3 | # qweechat.py - WeeChat remote GUI using Qt toolkit | |
4 | # | |
82e0d920 | 5 | # Copyright (C) 2011-2022 Sébastien Helleu <flashcode@flashtux.org> |
77df9d06 SH |
6 | # |
7 | # This file is part of QWeeChat, a Qt remote GUI for WeeChat. | |
8 | # | |
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. | |
13 | # | |
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. | |
18 | # | |
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/>. | |
21 | # | |
22 | ||
23 | """ | |
24 | QWeeChat is a WeeChat remote GUI using Qt toolkit. | |
25 | ||
26 | It requires requires WeeChat 0.3.7 or newer, running on local or remote host. | |
27 | """ | |
28 | ||
29 | # | |
30 | # History: | |
31 | # | |
32 | # 2011-05-27, Sébastien Helleu <flashcode@flashtux.org>: | |
33 | # start dev | |
34 | # | |
35 | ||
36 | import sys | |
37 | import traceback | |
38 | from pkg_resources import resource_filename | |
8e15c19f | 39 | |
f3da694d | 40 | from PySide6 import QtCore, QtGui, QtWidgets |
8e15c19f | 41 | |
0ee7d2e9 | 42 | from qweechat import config |
0ee7d2e9 | 43 | from qweechat.about import AboutDialog |
3b0947c9 SH |
44 | from qweechat.buffer import BufferListWidget, Buffer |
45 | from qweechat.connection import ConnectionDialog | |
0dffebcf | 46 | from qweechat.network import Network, STATUS_DISCONNECTED |
3b0947c9 SH |
47 | from qweechat.preferences import PreferencesDialog |
48 | from qweechat.weechat import protocol | |
77df9d06 | 49 | |
1f27a20e | 50 | |
beddac26 | 51 | APP_NAME = 'QWeeChat' |
77df9d06 | 52 | AUTHOR = 'Sébastien Helleu' |
9036a59a | 53 | WEECHAT_SITE = 'https://weechat.org/' |
77df9d06 | 54 | |
77df9d06 | 55 | |
1f27a20e | 56 | class MainWindow(QtWidgets.QMainWindow): |
77df9d06 SH |
57 | """Main window.""" |
58 | ||
59 | def __init__(self, *args): | |
1fe88536 | 60 | super().__init__(*args) |
77df9d06 SH |
61 | |
62 | self.config = config.read() | |
63 | ||
64 | self.resize(1000, 600) | |
beddac26 | 65 | self.setWindowTitle(APP_NAME) |
77df9d06 | 66 | |
77df9d06 SH |
67 | self.about_dialog = None |
68 | self.connection_dialog = None | |
0bd929dc | 69 | self.preferences_dialog = None |
77df9d06 SH |
70 | |
71 | # network | |
72 | self.network = Network() | |
73 | self.network.statusChanged.connect(self._network_status_changed) | |
74 | self.network.messageFromWeechat.connect(self._network_weechat_msg) | |
75 | ||
76 | # list of buffers | |
77 | self.list_buffers = BufferListWidget() | |
78 | self.list_buffers.currentRowChanged.connect(self._buffer_switch) | |
79 | ||
80 | # default buffer | |
81 | self.buffers = [Buffer()] | |
1f27a20e | 82 | self.stacked_buffers = QtWidgets.QStackedWidget() |
77df9d06 SH |
83 | self.stacked_buffers.addWidget(self.buffers[0].widget) |
84 | ||
85 | # splitter with buffers + chat/input | |
1f27a20e | 86 | splitter = QtWidgets.QSplitter() |
77df9d06 SH |
87 | splitter.addWidget(self.list_buffers) |
88 | splitter.addWidget(self.stacked_buffers) | |
89 | ||
90 | self.setCentralWidget(splitter) | |
91 | ||
92 | if self.config.getboolean('look', 'statusbar'): | |
93 | self.statusBar().visible = True | |
94 | ||
95 | # actions for menu and toolbar | |
96 | actions_def = { | |
97 | 'connect': [ | |
3b0947c9 SH |
98 | 'network-connect.png', |
99 | 'Connect to WeeChat', | |
100 | 'Ctrl+O', | |
101 | self.open_connection_dialog, | |
102 | ], | |
77df9d06 | 103 | 'disconnect': [ |
3b0947c9 SH |
104 | 'network-disconnect.png', |
105 | 'Disconnect from WeeChat', | |
106 | 'Ctrl+D', | |
107 | self.network.disconnect_weechat, | |
108 | ], | |
77df9d06 | 109 | 'debug': [ |
3b0947c9 SH |
110 | 'edit-find.png', |
111 | 'Open debug console window', | |
112 | 'Ctrl+B', | |
113 | self.network.open_debug_dialog, | |
114 | ], | |
77df9d06 | 115 | 'preferences': [ |
3b0947c9 SH |
116 | 'preferences-other.png', |
117 | 'Change preferences', | |
118 | 'Ctrl+P', | |
119 | self.open_preferences_dialog, | |
120 | ], | |
77df9d06 | 121 | 'about': [ |
3b0947c9 SH |
122 | 'help-about.png', |
123 | 'About QWeeChat', | |
124 | 'Ctrl+H', | |
125 | self.open_about_dialog, | |
126 | ], | |
77df9d06 | 127 | 'save connection': [ |
3b0947c9 SH |
128 | 'document-save.png', |
129 | 'Save connection configuration', | |
130 | 'Ctrl+S', | |
131 | self.save_connection, | |
132 | ], | |
77df9d06 | 133 | 'quit': [ |
3b0947c9 SH |
134 | 'application-exit.png', |
135 | 'Quit application', | |
136 | 'Ctrl+Q', | |
137 | self.close, | |
138 | ], | |
77df9d06 SH |
139 | } |
140 | self.actions = {} | |
141 | for name, action in list(actions_def.items()): | |
356719e0 SH |
142 | self.actions[name] = QtGui.QAction( |
143 | QtGui.QIcon( | |
77df9d06 SH |
144 | resource_filename(__name__, 'data/icons/%s' % action[0])), |
145 | name.capitalize(), self) | |
3b0947c9 | 146 | self.actions[name].setToolTip(f'{action[1]} ({action[2]})') |
77df9d06 SH |
147 | self.actions[name].setShortcut(action[2]) |
148 | self.actions[name].triggered.connect(action[3]) | |
149 | ||
150 | # menu | |
151 | self.menu = self.menuBar() | |
152 | menu_file = self.menu.addMenu('&File') | |
153 | menu_file.addActions([self.actions['connect'], | |
154 | self.actions['disconnect'], | |
155 | self.actions['preferences'], | |
156 | self.actions['save connection'], | |
157 | self.actions['quit']]) | |
158 | menu_window = self.menu.addMenu('&Window') | |
159 | menu_window.addAction(self.actions['debug']) | |
160 | menu_help = self.menu.addMenu('&Help') | |
161 | menu_help.addAction(self.actions['about']) | |
1f27a20e | 162 | self.network_status = QtWidgets.QLabel() |
77df9d06 SH |
163 | self.network_status.setFixedHeight(20) |
164 | self.network_status.setFixedWidth(200) | |
165 | self.network_status.setContentsMargins(0, 0, 10, 0) | |
356719e0 | 166 | self.network_status.setAlignment(QtCore.Qt.AlignRight) |
77df9d06 SH |
167 | if hasattr(self.menu, 'setCornerWidget'): |
168 | self.menu.setCornerWidget(self.network_status, | |
356719e0 | 169 | QtCore.Qt.TopRightCorner) |
6958c235 | 170 | self.network_status_set(STATUS_DISCONNECTED) |
77df9d06 SH |
171 | |
172 | # toolbar | |
173 | toolbar = self.addToolBar('toolBar') | |
356719e0 | 174 | toolbar.setToolButtonStyle(QtCore.Qt.ToolButtonTextUnderIcon) |
77df9d06 SH |
175 | toolbar.addActions([self.actions['connect'], |
176 | self.actions['disconnect'], | |
177 | self.actions['debug'], | |
178 | self.actions['preferences'], | |
179 | self.actions['about'], | |
180 | self.actions['quit']]) | |
181 | ||
182 | self.buffers[0].widget.input.setFocus() | |
183 | ||
184 | # open debug dialog | |
185 | if self.config.getboolean('look', 'debug'): | |
3b0947c9 | 186 | self.network.open_debug_dialog() |
77df9d06 SH |
187 | |
188 | # auto-connect to relay | |
189 | if self.config.getboolean('relay', 'autoconnect'): | |
3b0947c9 | 190 | self.network.connect_weechat( |
ae648fd7 SH |
191 | hostname=self.config.get('relay', 'hostname', fallback=''), |
192 | port=self.config.get('relay', 'port', fallback=''), | |
193 | ssl=self.config.getboolean('relay', 'ssl', fallback=''), | |
194 | password=self.config.get('relay', 'password', fallback=''), | |
3b0947c9 | 195 | totp=None, |
ae648fd7 | 196 | lines=self.config.get('relay', 'lines', fallback=''), |
3b0947c9 | 197 | ) |
77df9d06 SH |
198 | |
199 | self.show() | |
200 | ||
201 | def _buffer_switch(self, index): | |
202 | """Switch to a buffer.""" | |
203 | if index >= 0: | |
204 | self.stacked_buffers.setCurrentIndex(index) | |
205 | self.stacked_buffers.widget(index).input.setFocus() | |
206 | ||
207 | def buffer_input(self, full_name, text): | |
208 | """Send buffer input to WeeChat.""" | |
209 | if self.network.is_connected(): | |
210 | message = 'input %s %s\n' % (full_name, text) | |
211 | self.network.send_to_weechat(message) | |
3b0947c9 | 212 | self.network.debug_print(0, '<==', message, forcecolor='#AA0000') |
77df9d06 SH |
213 | |
214 | def open_preferences_dialog(self): | |
215 | """Open a dialog with preferences.""" | |
0bd929dc | 216 | # TODO: implement the preferences dialog box |
3b0947c9 | 217 | self.preferences_dialog = PreferencesDialog(self) |
77df9d06 SH |
218 | |
219 | def save_connection(self): | |
220 | """Save connection configuration.""" | |
221 | if self.network: | |
222 | options = self.network.get_options() | |
1fe88536 | 223 | for option in options: |
77df9d06 SH |
224 | self.config.set('relay', option, options[option]) |
225 | ||
77df9d06 SH |
226 | def open_about_dialog(self): |
227 | """Open a dialog with info about QWeeChat.""" | |
beddac26 | 228 | self.about_dialog = AboutDialog(APP_NAME, AUTHOR, WEECHAT_SITE, self) |
77df9d06 SH |
229 | |
230 | def open_connection_dialog(self): | |
231 | """Open a dialog with connection settings.""" | |
232 | values = {} | |
ae648fd7 SH |
233 | for option in ('hostname', 'port', 'ssl', 'password', 'lines'): |
234 | values[option] = self.config.get('relay', option, fallback='') | |
77df9d06 SH |
235 | self.connection_dialog = ConnectionDialog(values, self) |
236 | self.connection_dialog.dialog_buttons.accepted.connect( | |
237 | self.connect_weechat) | |
238 | ||
239 | def connect_weechat(self): | |
240 | """Connect to WeeChat.""" | |
241 | self.network.connect_weechat( | |
ae648fd7 | 242 | hostname=self.connection_dialog.fields['hostname'].text(), |
3b0947c9 SH |
243 | port=self.connection_dialog.fields['port'].text(), |
244 | ssl=self.connection_dialog.fields['ssl'].isChecked(), | |
245 | password=self.connection_dialog.fields['password'].text(), | |
246 | totp=self.connection_dialog.fields['totp'].text(), | |
247 | lines=int(self.connection_dialog.fields['lines'].text()), | |
248 | ) | |
77df9d06 SH |
249 | self.connection_dialog.close() |
250 | ||
251 | def _network_status_changed(self, status, extra): | |
252 | """Called when the network status has changed.""" | |
253 | if self.config.getboolean('look', 'statusbar'): | |
254 | self.statusBar().showMessage(status) | |
3b0947c9 | 255 | self.network.debug_print(0, '', status, forcecolor='#0000AA') |
77df9d06 SH |
256 | self.network_status_set(status) |
257 | ||
258 | def network_status_set(self, status): | |
259 | """Set the network status.""" | |
260 | pal = self.network_status.palette() | |
6958c235 SH |
261 | pal.setColor(self.network_status.foregroundRole(), |
262 | self.network.status_color(status)) | |
263 | ssl = ' (SSL)' if status != STATUS_DISCONNECTED \ | |
77df9d06 SH |
264 | and self.network.is_ssl() else '' |
265 | self.network_status.setPalette(pal) | |
266 | icon = self.network.status_icon(status) | |
267 | if icon: | |
268 | self.network_status.setText( | |
269 | '<img src="%s"> %s' % | |
270 | (resource_filename(__name__, 'data/icons/%s' % icon), | |
6958c235 | 271 | self.network.status_label(status) + ssl)) |
77df9d06 SH |
272 | else: |
273 | self.network_status.setText(status.capitalize()) | |
6958c235 | 274 | if status == STATUS_DISCONNECTED: |
77df9d06 SH |
275 | self.actions['connect'].setEnabled(True) |
276 | self.actions['disconnect'].setEnabled(False) | |
277 | else: | |
278 | self.actions['connect'].setEnabled(False) | |
279 | self.actions['disconnect'].setEnabled(True) | |
280 | ||
281 | def _network_weechat_msg(self, message): | |
282 | """Called when a message is received from WeeChat.""" | |
3b0947c9 SH |
283 | self.network.debug_print( |
284 | 0, '==>', | |
285 | 'message (%d bytes):\n%s' | |
286 | % (len(message), | |
287 | protocol.hex_and_ascii(message.data(), 20)), | |
288 | forcecolor='#008800', | |
289 | ) | |
77df9d06 SH |
290 | try: |
291 | proto = protocol.Protocol() | |
1f27a20e | 292 | message = proto.decode(message.data()) |
77df9d06 | 293 | if message.uncompressed: |
3b0947c9 | 294 | self.network.debug_print( |
77df9d06 SH |
295 | 0, '==>', |
296 | 'message uncompressed (%d bytes):\n%s' | |
297 | % (message.size_uncompressed, | |
298 | protocol.hex_and_ascii(message.uncompressed, 20)), | |
7a3a48a5 | 299 | forcecolor='#008800') |
3b0947c9 | 300 | self.network.debug_print(0, '', 'Message: %s' % message) |
77df9d06 | 301 | self.parse_message(message) |
1f27a20e | 302 | except Exception: # noqa: E722 |
77df9d06 SH |
303 | print('Error while decoding message from WeeChat:\n%s' |
304 | % traceback.format_exc()) | |
305 | self.network.disconnect_weechat() | |
306 | ||
3b0947c9 SH |
307 | def _parse_handshake(self, message): |
308 | """Parse a WeeChat message with handshake response.""" | |
309 | for obj in message.objects: | |
310 | if obj.objtype != 'htb': | |
311 | continue | |
312 | self.network.init_with_handshake(obj.value) | |
313 | break | |
314 | ||
77df9d06 | 315 | def _parse_listbuffers(self, message): |
3b0947c9 | 316 | """Parse a WeeChat message with list of buffers.""" |
77df9d06 SH |
317 | for obj in message.objects: |
318 | if obj.objtype != 'hda' or obj.value['path'][-1] != 'buffer': | |
319 | continue | |
320 | self.list_buffers.clear() | |
321 | while self.stacked_buffers.count() > 0: | |
322 | buf = self.stacked_buffers.widget(0) | |
323 | self.stacked_buffers.removeWidget(buf) | |
324 | self.buffers = [] | |
325 | for item in obj.value['items']: | |
326 | buf = self.create_buffer(item) | |
327 | self.insert_buffer(len(self.buffers), buf) | |
328 | self.list_buffers.setCurrentRow(0) | |
329 | self.buffers[0].widget.input.setFocus() | |
330 | ||
331 | def _parse_line(self, message): | |
332 | """Parse a WeeChat message with a buffer line.""" | |
333 | for obj in message.objects: | |
334 | lines = [] | |
335 | if obj.objtype != 'hda' or obj.value['path'][-1] != 'line_data': | |
336 | continue | |
337 | for item in obj.value['items']: | |
338 | if message.msgid == 'listlines': | |
339 | ptrbuf = item['__path'][0] | |
340 | else: | |
341 | ptrbuf = item['buffer'] | |
342 | index = [i for i, b in enumerate(self.buffers) | |
343 | if b.pointer() == ptrbuf] | |
344 | if index: | |
e38ef663 SH |
345 | lines.append( |
346 | (index[0], | |
347 | (item['date'], item['prefix'], | |
348 | item['message'])) | |
349 | ) | |
77df9d06 SH |
350 | if message.msgid == 'listlines': |
351 | lines.reverse() | |
352 | for line in lines: | |
e38ef663 | 353 | self.buffers[line[0]].widget.chat.display(*line[1]) |
77df9d06 SH |
354 | |
355 | def _parse_nicklist(self, message): | |
356 | """Parse a WeeChat message with a buffer nicklist.""" | |
357 | buffer_refresh = {} | |
358 | for obj in message.objects: | |
359 | if obj.objtype != 'hda' or \ | |
360 | obj.value['path'][-1] != 'nicklist_item': | |
361 | continue | |
362 | group = '__root' | |
363 | for item in obj.value['items']: | |
364 | index = [i for i, b in enumerate(self.buffers) | |
365 | if b.pointer() == item['__path'][0]] | |
366 | if index: | |
367 | if not index[0] in buffer_refresh: | |
368 | self.buffers[index[0]].nicklist = {} | |
369 | buffer_refresh[index[0]] = True | |
370 | if item['group']: | |
371 | group = item['name'] | |
372 | self.buffers[index[0]].nicklist_add_item( | |
373 | group, item['group'], item['prefix'], item['name'], | |
374 | item['visible']) | |
375 | for index in buffer_refresh: | |
376 | self.buffers[index].nicklist_refresh() | |
377 | ||
378 | def _parse_nicklist_diff(self, message): | |
379 | """Parse a WeeChat message with a buffer nicklist diff.""" | |
380 | buffer_refresh = {} | |
381 | for obj in message.objects: | |
382 | if obj.objtype != 'hda' or \ | |
383 | obj.value['path'][-1] != 'nicklist_item': | |
384 | continue | |
385 | group = '__root' | |
386 | for item in obj.value['items']: | |
387 | index = [i for i, b in enumerate(self.buffers) | |
388 | if b.pointer() == item['__path'][0]] | |
389 | if not index: | |
390 | continue | |
391 | buffer_refresh[index[0]] = True | |
392 | if item['_diff'] == ord('^'): | |
393 | group = item['name'] | |
394 | elif item['_diff'] == ord('+'): | |
395 | self.buffers[index[0]].nicklist_add_item( | |
396 | group, item['group'], item['prefix'], item['name'], | |
397 | item['visible']) | |
398 | elif item['_diff'] == ord('-'): | |
399 | self.buffers[index[0]].nicklist_remove_item( | |
400 | group, item['group'], item['name']) | |
401 | elif item['_diff'] == ord('*'): | |
402 | self.buffers[index[0]].nicklist_update_item( | |
403 | group, item['group'], item['prefix'], item['name'], | |
404 | item['visible']) | |
405 | for index in buffer_refresh: | |
406 | self.buffers[index].nicklist_refresh() | |
407 | ||
408 | def _parse_buffer_opened(self, message): | |
409 | """Parse a WeeChat message with a new buffer (opened).""" | |
410 | for obj in message.objects: | |
411 | if obj.objtype != 'hda' or obj.value['path'][-1] != 'buffer': | |
412 | continue | |
413 | for item in obj.value['items']: | |
414 | buf = self.create_buffer(item) | |
415 | index = self.find_buffer_index_for_insert(item['next_buffer']) | |
416 | self.insert_buffer(index, buf) | |
417 | ||
418 | def _parse_buffer(self, message): | |
419 | """Parse a WeeChat message with a buffer event | |
420 | (anything except a new buffer). | |
421 | """ | |
422 | for obj in message.objects: | |
423 | if obj.objtype != 'hda' or obj.value['path'][-1] != 'buffer': | |
424 | continue | |
425 | for item in obj.value['items']: | |
426 | index = [i for i, b in enumerate(self.buffers) | |
427 | if b.pointer() == item['__path'][0]] | |
428 | if not index: | |
429 | continue | |
430 | index = index[0] | |
431 | if message.msgid == '_buffer_type_changed': | |
432 | self.buffers[index].data['type'] = item['type'] | |
433 | elif message.msgid in ('_buffer_moved', '_buffer_merged', | |
434 | '_buffer_unmerged'): | |
435 | buf = self.buffers[index] | |
436 | buf.data['number'] = item['number'] | |
437 | self.remove_buffer(index) | |
438 | index2 = self.find_buffer_index_for_insert( | |
439 | item['next_buffer']) | |
440 | self.insert_buffer(index2, buf) | |
441 | elif message.msgid == '_buffer_renamed': | |
442 | self.buffers[index].data['full_name'] = item['full_name'] | |
443 | self.buffers[index].data['short_name'] = item['short_name'] | |
444 | elif message.msgid == '_buffer_title_changed': | |
445 | self.buffers[index].data['title'] = item['title'] | |
446 | self.buffers[index].update_title() | |
8217c4e2 SH |
447 | elif message.msgid == '_buffer_cleared': |
448 | self.buffers[index].widget.chat.clear() | |
77df9d06 SH |
449 | elif message.msgid.startswith('_buffer_localvar_'): |
450 | self.buffers[index].data['local_variables'] = \ | |
451 | item['local_variables'] | |
452 | self.buffers[index].update_prompt() | |
453 | elif message.msgid == '_buffer_closing': | |
454 | self.remove_buffer(index) | |
455 | ||
456 | def parse_message(self, message): | |
457 | """Parse a WeeChat message.""" | |
458 | if message.msgid.startswith('debug'): | |
3b0947c9 SH |
459 | self.network.debug_print(0, '', '(debug message, ignored)') |
460 | elif message.msgid == 'handshake': | |
461 | self._parse_handshake(message) | |
77df9d06 SH |
462 | elif message.msgid == 'listbuffers': |
463 | self._parse_listbuffers(message) | |
464 | elif message.msgid in ('listlines', '_buffer_line_added'): | |
465 | self._parse_line(message) | |
466 | elif message.msgid in ('_nicklist', 'nicklist'): | |
467 | self._parse_nicklist(message) | |
468 | elif message.msgid == '_nicklist_diff': | |
469 | self._parse_nicklist_diff(message) | |
470 | elif message.msgid == '_buffer_opened': | |
471 | self._parse_buffer_opened(message) | |
472 | elif message.msgid.startswith('_buffer_'): | |
473 | self._parse_buffer(message) | |
474 | elif message.msgid == '_upgrade': | |
475 | self.network.desync_weechat() | |
476 | elif message.msgid == '_upgrade_ended': | |
477 | self.network.sync_weechat() | |
1f27a20e AR |
478 | else: |
479 | print(f"Unknown message with id {message.msgid}") | |
77df9d06 SH |
480 | |
481 | def create_buffer(self, item): | |
482 | """Create a new buffer.""" | |
483 | buf = Buffer(item) | |
484 | buf.bufferInput.connect(self.buffer_input) | |
485 | buf.widget.input.bufferSwitchPrev.connect( | |
486 | self.list_buffers.switch_prev_buffer) | |
487 | buf.widget.input.bufferSwitchNext.connect( | |
488 | self.list_buffers.switch_next_buffer) | |
489 | return buf | |
490 | ||
491 | def insert_buffer(self, index, buf): | |
492 | """Insert a buffer in list.""" | |
493 | self.buffers.insert(index, buf) | |
7a3a48a5 AR |
494 | self.list_buffers.insertItem(index, '%s' |
495 | % (buf.data['local_variables']['name'])) | |
77df9d06 SH |
496 | self.stacked_buffers.insertWidget(index, buf.widget) |
497 | ||
498 | def remove_buffer(self, index): | |
499 | """Remove a buffer.""" | |
500 | if self.list_buffers.currentRow == index and index > 0: | |
501 | self.list_buffers.setCurrentRow(index - 1) | |
502 | self.list_buffers.takeItem(index) | |
503 | self.stacked_buffers.removeWidget(self.stacked_buffers.widget(index)) | |
504 | self.buffers.pop(index) | |
505 | ||
506 | def find_buffer_index_for_insert(self, next_buffer): | |
507 | """Find position to insert a buffer in list.""" | |
508 | index = -1 | |
509 | if next_buffer == '0x0': | |
510 | index = len(self.buffers) | |
511 | else: | |
512 | index = [i for i, b in enumerate(self.buffers) | |
513 | if b.pointer() == next_buffer] | |
514 | if index: | |
515 | index = index[0] | |
516 | if index < 0: | |
517 | print('Warning: unable to find position for buffer, using end of ' | |
518 | 'list by default') | |
519 | index = len(self.buffers) | |
520 | return index | |
521 | ||
522 | def closeEvent(self, event): | |
523 | """Called when QWeeChat window is closed.""" | |
524 | self.network.disconnect_weechat() | |
3b0947c9 SH |
525 | if self.network.debug_dialog: |
526 | self.network.debug_dialog.close() | |
77df9d06 | 527 | config.write(self.config) |
1f27a20e | 528 | QtWidgets.QMainWindow.closeEvent(self, event) |
77df9d06 | 529 | |
7a3a48a5 | 530 | |
b8a96ada | 531 | def main(): |
80f4f34c | 532 | app = QtWidgets.QApplication(sys.argv) |
b8a96ada AR |
533 | app.setStyle(QtWidgets.QStyleFactory.create('Cleanlooks')) |
534 | app.setWindowIcon(QtGui.QIcon( | |
535 | resource_filename(__name__, 'data/icons/weechat.png'))) | |
1fe88536 SH |
536 | main_win = MainWindow() |
537 | main_win.show() | |
b8a96ada | 538 | sys.exit(app.exec_()) |
77df9d06 | 539 | |
b8a96ada AR |
540 | |
541 | if __name__ == '__main__': | |
542 | main() |