]> jfr.im git - irc/weechat/qweechat.git/blobdiff - qweechat/qweechat.py
Rename option/field "server" to "hostname"
[irc/weechat/qweechat.git] / qweechat / qweechat.py
index cc181c35920e7ff1e46c3e785eccd247b0b05208..090b76ef8b244a3354cb9b55d78beddc6d31fb6f 100644 (file)
@@ -37,40 +37,32 @@ import sys
 import traceback
 from pkg_resources import resource_filename
 
-from PySide6 import QtGui, QtWidgets, QtCore
+from PySide6 import QtCore, QtGui, QtWidgets
 
 from qweechat import config
-from qweechat.weechat import protocol
-from qweechat.network import Network
-from qweechat.connection import ConnectionDialog
-from qweechat.buffer import BufferListWidget, Buffer
-from qweechat.debug import DebugDialog
 from qweechat.about import AboutDialog
-from qweechat.version import qweechat_version
+from qweechat.buffer import BufferListWidget, Buffer
+from qweechat.connection import ConnectionDialog
+from qweechat.network import Network, STATUS_DISCONNECTED, NETWORK_STATUS
+from qweechat.preferences import PreferencesDialog
+from qweechat.weechat import protocol
 
 
-NAME = 'QWeeChat'
+APP_NAME = 'QWeeChat'
 AUTHOR = 'Sébastien Helleu'
-AUTHOR_MAIL = 'flashcode@flashtux.org'
 WEECHAT_SITE = 'https://weechat.org/'
 
-# number of lines in buffer for debug window
-DEBUG_NUM_LINES = 50
-
 
 class MainWindow(QtWidgets.QMainWindow):
     """Main window."""
 
     def __init__(self, *args):
-        super().__init__()
+        super().__init__(*args)
 
         self.config = config.read()
 
         self.resize(1000, 600)
-        self.setWindowTitle(NAME)
-
-        self.debug_dialog = None
-        self.debug_lines = []
+        self.setWindowTitle(APP_NAME)
 
         self.about_dialog = None
         self.connection_dialog = None
@@ -103,26 +95,47 @@ class MainWindow(QtWidgets.QMainWindow):
         # actions for menu and toolbar
         actions_def = {
             'connect': [
-                'network-connect.png', 'Connect to WeeChat',
-                'Ctrl+O', self.open_connection_dialog],
+                'network-connect.png',
+                'Connect to WeeChat',
+                'Ctrl+O',
+                self.open_connection_dialog,
+            ],
             'disconnect': [
-                'network-disconnect.png', 'Disconnect from WeeChat',
-                'Ctrl+D', self.network.disconnect_weechat],
+                'network-disconnect.png',
+                'Disconnect from WeeChat',
+                'Ctrl+D',
+                self.network.disconnect_weechat,
+            ],
             'debug': [
-                'edit-find.png', 'Debug console window',
-                'Ctrl+B', self.open_debug_dialog],
+                'edit-find.png',
+                'Open debug console window',
+                'Ctrl+B',
+                self.network.open_debug_dialog,
+            ],
             'preferences': [
-                'preferences-other.png', 'Preferences',
-                'Ctrl+P', self.open_preferences_dialog],
+                'preferences-other.png',
+                'Change preferences',
+                'Ctrl+P',
+                self.open_preferences_dialog,
+            ],
             'about': [
-                'help-about.png', 'About',
-                'Ctrl+H', self.open_about_dialog],
+                'help-about.png',
+                'About QWeeChat',
+                'Ctrl+H',
+                self.open_about_dialog,
+            ],
             'save connection': [
-                'document-save.png', 'Save connection configuration',
-                'Ctrl+S', self.save_connection],
+                'document-save.png',
+                'Save connection configuration',
+                'Ctrl+S',
+                self.save_connection,
+            ],
             'quit': [
-                'application-exit.png', 'Quit application',
-                'Ctrl+Q', self.close],
+                'application-exit.png',
+                'Quit application',
+                'Ctrl+Q',
+                self.close,
+            ],
         }
         self.actions = {}
         for name, action in list(actions_def.items()):
@@ -130,7 +143,7 @@ class MainWindow(QtWidgets.QMainWindow):
                 QtGui.QIcon(
                     resource_filename(__name__, 'data/icons/%s' % action[0])),
                 name.capitalize(), self)
-            self.actions[name].setStatusTip(action[1])
+            self.actions[name].setToolTip(f'{action[1]} ({action[2]})')
             self.actions[name].setShortcut(action[2])
             self.actions[name].triggered.connect(action[3])
 
@@ -154,7 +167,7 @@ class MainWindow(QtWidgets.QMainWindow):
         if hasattr(self.menu, 'setCornerWidget'):
             self.menu.setCornerWidget(self.network_status,
                                       QtCore.Qt.TopRightCorner)
-        self.network_status_set(self.network.status_disconnected)
+        self.network_status_set(STATUS_DISCONNECTED)
 
         # toolbar
         toolbar = self.addToolBar('toolBar')
@@ -170,16 +183,18 @@ class MainWindow(QtWidgets.QMainWindow):
 
         # open debug dialog
         if self.config.getboolean('look', 'debug'):
-            self.open_debug_dialog()
+            self.network.open_debug_dialog()
 
         # auto-connect to relay
         if self.config.getboolean('relay', 'autoconnect'):
-            self.network.connect_weechat(self.config.get('relay', 'server'),
-                                         self.config.get('relay', 'port'),
-                                         self.config.getboolean('relay',
-                                                                'ssl'),
-                                         self.config.get('relay', 'password'),
-                                         self.config.get('relay', 'lines'))
+            self.network.connect_weechat(
+                hostname=self.config.get('relay', 'hostname', fallback=''),
+                port=self.config.get('relay', 'port', fallback=''),
+                ssl=self.config.getboolean('relay', 'ssl', fallback=''),
+                password=self.config.get('relay', 'password', fallback=''),
+                totp=None,
+                lines=self.config.get('relay', 'lines', fallback=''),
+            )
 
         self.show()
 
@@ -194,73 +209,29 @@ class MainWindow(QtWidgets.QMainWindow):
         if self.network.is_connected():
             message = 'input %s %s\n' % (full_name, text)
             self.network.send_to_weechat(message)
-            self.debug_display(0, '<==', message, forcecolor='#AA0000')
+            self.network.debug_print(0, '<==', message, forcecolor='#AA0000')
 
     def open_preferences_dialog(self):
         """Open a dialog with preferences."""
         # TODO: implement the preferences dialog box
-        messages = ['Not yet implemented!',
-                    '']
-        self.preferences_dialog = AboutDialog('Preferences', messages, self)
+        self.preferences_dialog = PreferencesDialog(self)
 
     def save_connection(self):
         """Save connection configuration."""
         if self.network:
             options = self.network.get_options()
-            for option in options.keys():
+            for option in options:
                 self.config.set('relay', option, options[option])
 
-    def debug_display(self, *args, **kwargs):
-        """Display a debug message."""
-        self.debug_lines.append((args, kwargs))
-        self.debug_lines = self.debug_lines[-DEBUG_NUM_LINES:]
-        if self.debug_dialog:
-            self.debug_dialog.chat.display(*args, **kwargs)
-
-    def open_debug_dialog(self):
-        """Open a dialog with debug messages."""
-        if not self.debug_dialog:
-            self.debug_dialog = DebugDialog(self)
-            self.debug_dialog.input.textSent.connect(
-                self.debug_input_text_sent)
-            self.debug_dialog.finished.connect(self._debug_dialog_closed)
-            self.debug_dialog.display_lines(self.debug_lines)
-            self.debug_dialog.chat.scroll_bottom()
-
-    def debug_input_text_sent(self, text):
-        """Send debug buffer input to WeeChat."""
-        if self.network.is_connected():
-            text = str(text)
-            pos = text.find(')')
-            if text.startswith('(') and pos >= 0:
-                text = '(debug_%s)%s' % (text[1:pos], text[pos+1:])
-            else:
-                text = '(debug) %s' % text
-            self.debug_display(0, '<==', text, forcecolor='#AA0000')
-            self.network.send_to_weechat(text + '\n')
-
-    def _debug_dialog_closed(self, result):
-        """Called when debug dialog is closed."""
-        self.debug_dialog = None
-
     def open_about_dialog(self):
         """Open a dialog with info about QWeeChat."""
-        messages = ['<b>%s</b> %s' % (NAME, qweechat_version()),
-                    '&copy; 2011-2020 %s &lt;<a href="mailto:%s">%s</a>&gt;'
-                    % (AUTHOR, AUTHOR_MAIL, AUTHOR_MAIL),
-                    '',
-                    'Running with PySide6',
-                    '',
-                    'WeeChat site: <a href="%s">%s</a>'
-                    % (WEECHAT_SITE, WEECHAT_SITE),
-                    '']
-        self.about_dialog = AboutDialog(NAME, messages, self)
+        self.about_dialog = AboutDialog(APP_NAME, AUTHOR, WEECHAT_SITE, self)
 
     def open_connection_dialog(self):
         """Open a dialog with connection settings."""
         values = {}
-        for option in ('server', 'port', 'ssl', 'password', 'lines'):
-            values[option] = self.config.get('relay', option)
+        for option in ('hostname', 'port', 'ssl', 'password', 'lines'):
+            values[option] = self.config.get('relay', option, fallback='')
         self.connection_dialog = ConnectionDialog(values, self)
         self.connection_dialog.dialog_buttons.accepted.connect(
             self.connect_weechat)
@@ -268,30 +239,28 @@ class MainWindow(QtWidgets.QMainWindow):
     def connect_weechat(self):
         """Connect to WeeChat."""
         self.network.connect_weechat(
-            self.connection_dialog.fields['server'].text(),
-            self.connection_dialog.fields['port'].text(),
-            self.connection_dialog.fields['ssl'].isChecked(),
-            self.connection_dialog.fields['password'].text(),
-            int(self.connection_dialog.fields['lines'].text()))
+            hostname=self.connection_dialog.fields['hostname'].text(),
+            port=self.connection_dialog.fields['port'].text(),
+            ssl=self.connection_dialog.fields['ssl'].isChecked(),
+            password=self.connection_dialog.fields['password'].text(),
+            totp=self.connection_dialog.fields['totp'].text(),
+            lines=int(self.connection_dialog.fields['lines'].text()),
+        )
         self.connection_dialog.close()
 
     def _network_status_changed(self, status, extra):
         """Called when the network status has changed."""
         if self.config.getboolean('look', 'statusbar'):
             self.statusBar().showMessage(status)
-        self.debug_display(0, '', status, forcecolor='#0000AA')
+        self.network.debug_print(0, '', status, forcecolor='#0000AA')
         self.network_status_set(status)
 
     def network_status_set(self, status):
         """Set the network status."""
         pal = self.network_status.palette()
-        if status == self.network.status_connected:
-            pal.setColor(self.network_status.foregroundRole(),
-                         QtGui.QColor('green'))
-        else:
-            pal.setColor(self.network_status.foregroundRole(),
-                         QtGui.QColor('#aa0000'))
-        ssl = ' (SSL)' if status != self.network.status_disconnected \
+        pal.setColor(self.network_status.foregroundRole(),
+                     self.network.status_color(status))
+        ssl = ' (SSL)' if status != STATUS_DISCONNECTED \
               and self.network.is_ssl() else ''
         self.network_status.setPalette(pal)
         icon = self.network.status_icon(status)
@@ -299,10 +268,10 @@ class MainWindow(QtWidgets.QMainWindow):
             self.network_status.setText(
                 '<img src="%s"> %s' %
                 (resource_filename(__name__, 'data/icons/%s' % icon),
-                 status.capitalize() + ssl))
+                 self.network.status_label(status) + ssl))
         else:
             self.network_status.setText(status.capitalize())
-        if status == self.network.status_disconnected:
+        if status == STATUS_DISCONNECTED:
             self.actions['connect'].setEnabled(True)
             self.actions['disconnect'].setEnabled(False)
         else:
@@ -311,30 +280,40 @@ class MainWindow(QtWidgets.QMainWindow):
 
     def _network_weechat_msg(self, message):
         """Called when a message is received from WeeChat."""
-        self.debug_display(0, '==>',
-                           'message (%d bytes):\n%s'
-                           % (len(message),
-                              protocol.hex_and_ascii(message.data(), 20)),
-                           forcecolor='#008800')
+        self.network.debug_print(
+            0, '==>',
+            'message (%d bytes):\n%s'
+            % (len(message),
+               protocol.hex_and_ascii(message.data(), 20)),
+            forcecolor='#008800',
+        )
         try:
             proto = protocol.Protocol()
             message = proto.decode(message.data())
             if message.uncompressed:
-                self.debug_display(
+                self.network.debug_print(
                     0, '==>',
                     'message uncompressed (%d bytes):\n%s'
                     % (message.size_uncompressed,
                        protocol.hex_and_ascii(message.uncompressed, 20)),
                     forcecolor='#008800')
-            self.debug_display(0, '', 'Message: %s' % message)
+            self.network.debug_print(0, '', 'Message: %s' % message)
             self.parse_message(message)
         except Exception:  # noqa: E722
             print('Error while decoding message from WeeChat:\n%s'
                   % traceback.format_exc())
             self.network.disconnect_weechat()
 
+    def _parse_handshake(self, message):
+        """Parse a WeeChat message with handshake response."""
+        for obj in message.objects:
+            if obj.objtype != 'htb':
+                continue
+            self.network.init_with_handshake(obj.value)
+            break
+
     def _parse_listbuffers(self, message):
-        """Parse a WeeChat with list of buffers."""
+        """Parse a WeeChat message with list of buffers."""
         for obj in message.objects:
             if obj.objtype != 'hda' or obj.value['path'][-1] != 'buffer':
                 continue
@@ -477,7 +456,9 @@ class MainWindow(QtWidgets.QMainWindow):
     def parse_message(self, message):
         """Parse a WeeChat message."""
         if message.msgid.startswith('debug'):
-            self.debug_display(0, '', '(debug message, ignored)')
+            self.network.debug_print(0, '', '(debug message, ignored)')
+        elif message.msgid == 'handshake':
+            self._parse_handshake(message)
         elif message.msgid == 'listbuffers':
             self._parse_listbuffers(message)
         elif message.msgid in ('listlines', '_buffer_line_added'):
@@ -541,8 +522,8 @@ class MainWindow(QtWidgets.QMainWindow):
     def closeEvent(self, event):
         """Called when QWeeChat window is closed."""
         self.network.disconnect_weechat()
-        if self.debug_dialog:
-            self.debug_dialog.close()
+        if self.network.debug_dialog:
+            self.network.debug_dialog.close()
         config.write(self.config)
         QtWidgets.QMainWindow.closeEvent(self, event)
 
@@ -552,8 +533,8 @@ def main():
     app.setStyle(QtWidgets.QStyleFactory.create('Cleanlooks'))
     app.setWindowIcon(QtGui.QIcon(
         resource_filename(__name__, 'data/icons/weechat.png')))
-    main = MainWindow()
-    main.show()
+    main_win = MainWindow()
+    main_win.show()
     sys.exit(app.exec_())