Merge pull request #13 from maxking/py3-qt6
Port to using Python3 and Pyside6
This commit is contained in:
commit
e139bca02f
@ -1,7 +1,9 @@
|
||||
language: python
|
||||
|
||||
python:
|
||||
- "2.7"
|
||||
- "3.7"
|
||||
- "3.8"
|
||||
- "3.9"
|
||||
|
||||
install:
|
||||
- pip install flake8
|
||||
|
@ -25,13 +25,13 @@ Following packages are *required*:
|
||||
|
||||
* WeeChat (version >= 0.3.7) on local or remote machine, with relay plugin
|
||||
enabled and listening on a port with protocol "weechat"
|
||||
* Python 2.x >= 2.6
|
||||
* PySide (recommended, packages: python.pyside.*) or PyQt4 (python-qt4)
|
||||
* Python 3.7+
|
||||
* PySide6
|
||||
|
||||
=== Install via source distribution
|
||||
|
||||
----
|
||||
$ python setup.py install
|
||||
$ pip install .
|
||||
----
|
||||
|
||||
== WeeChat setup
|
||||
|
@ -20,10 +20,8 @@
|
||||
# along with QWeeChat. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
import qt_compat
|
||||
|
||||
QtCore = qt_compat.import_module('QtCore')
|
||||
QtGui = qt_compat.import_module('QtGui')
|
||||
from PySide6 import QtCore
|
||||
from PySide6 import QtWidgets as QtGui
|
||||
|
||||
|
||||
class AboutDialog(QtGui.QDialog):
|
||||
@ -44,7 +42,7 @@ class AboutDialog(QtGui.QDialog):
|
||||
|
||||
vbox = QtGui.QVBoxLayout()
|
||||
for msg in messages:
|
||||
label = QtGui.QLabel(msg.decode('utf-8'))
|
||||
label = QtGui.QLabel(msg)
|
||||
label.setAlignment(QtCore.Qt.AlignHCenter)
|
||||
vbox.addWidget(label)
|
||||
vbox.addLayout(hbox)
|
||||
|
@ -19,22 +19,20 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with QWeeChat. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
from pkg_resources import resource_filename
|
||||
import qt_compat
|
||||
from chat import ChatTextEdit
|
||||
from input import InputLineEdit
|
||||
import weechat.color as color
|
||||
|
||||
QtCore = qt_compat.import_module('QtCore')
|
||||
QtGui = qt_compat.import_module('QtGui')
|
||||
from qweechat.chat import ChatTextEdit
|
||||
from qweechat.input import InputLineEdit
|
||||
from qweechat.weechat import color
|
||||
|
||||
from PySide6 import QtCore, QtGui, QtWidgets
|
||||
|
||||
|
||||
class GenericListWidget(QtGui.QListWidget):
|
||||
class GenericListWidget(QtWidgets.QListWidget):
|
||||
"""Generic QListWidget with dynamic size."""
|
||||
|
||||
def __init__(self, *args):
|
||||
QtGui.QListWidget.__init__(*(self,) + args)
|
||||
super().__init__(*args)
|
||||
self.setMaximumWidth(100)
|
||||
self.setTextElideMode(QtCore.Qt.ElideNone)
|
||||
self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
|
||||
@ -52,17 +50,17 @@ class GenericListWidget(QtGui.QListWidget):
|
||||
|
||||
def clear(self, *args):
|
||||
"""Re-implement clear to set dynamic size after clear."""
|
||||
QtGui.QListWidget.clear(*(self,) + args)
|
||||
QtWidgets.QListWidget.clear(*(self,) + args)
|
||||
self.auto_resize()
|
||||
|
||||
def addItem(self, *args):
|
||||
"""Re-implement addItem to set dynamic size after add."""
|
||||
QtGui.QListWidget.addItem(*(self,) + args)
|
||||
QtWidgets.QListWidget.addItem(*(self,) + args)
|
||||
self.auto_resize()
|
||||
|
||||
def insertItem(self, *args):
|
||||
"""Re-implement insertItem to set dynamic size after insert."""
|
||||
QtGui.QListWidget.insertItem(*(self,) + args)
|
||||
QtWidgets.QListWidget.insertItem(*(self,) + args)
|
||||
self.auto_resize()
|
||||
|
||||
|
||||
@ -70,7 +68,7 @@ class BufferListWidget(GenericListWidget):
|
||||
"""Widget with list of buffers."""
|
||||
|
||||
def __init__(self, *args):
|
||||
GenericListWidget.__init__(*(self,) + args)
|
||||
super().__init__(*args)
|
||||
|
||||
def switch_prev_buffer(self):
|
||||
if self.currentRow() > 0:
|
||||
@ -85,23 +83,23 @@ class BufferListWidget(GenericListWidget):
|
||||
self.setCurrentRow(0)
|
||||
|
||||
|
||||
class BufferWidget(QtGui.QWidget):
|
||||
class BufferWidget(QtWidgets.QWidget):
|
||||
"""
|
||||
Widget with (from top to bottom):
|
||||
title, chat + nicklist (optional) + prompt/input.
|
||||
"""
|
||||
|
||||
def __init__(self, display_nicklist=False):
|
||||
QtGui.QWidget.__init__(self)
|
||||
super().__init__()
|
||||
|
||||
# title
|
||||
self.title = QtGui.QLineEdit()
|
||||
self.title = QtWidgets.QLineEdit()
|
||||
self.title.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
|
||||
# splitter with chat + nicklist
|
||||
self.chat_nicklist = QtGui.QSplitter()
|
||||
self.chat_nicklist.setSizePolicy(QtGui.QSizePolicy.Expanding,
|
||||
QtGui.QSizePolicy.Expanding)
|
||||
self.chat_nicklist = QtWidgets.QSplitter()
|
||||
self.chat_nicklist.setSizePolicy(QtWidgets.QSizePolicy.Expanding,
|
||||
QtWidgets.QSizePolicy.Expanding)
|
||||
self.chat = ChatTextEdit(debug=False)
|
||||
self.chat_nicklist.addWidget(self.chat)
|
||||
self.nicklist = GenericListWidget()
|
||||
@ -110,16 +108,16 @@ class BufferWidget(QtGui.QWidget):
|
||||
self.chat_nicklist.addWidget(self.nicklist)
|
||||
|
||||
# prompt + input
|
||||
self.hbox_edit = QtGui.QHBoxLayout()
|
||||
self.hbox_edit = QtWidgets.QHBoxLayout()
|
||||
self.hbox_edit.setContentsMargins(0, 0, 0, 0)
|
||||
self.hbox_edit.setSpacing(0)
|
||||
self.input = InputLineEdit(self.chat)
|
||||
self.hbox_edit.addWidget(self.input)
|
||||
prompt_input = QtGui.QWidget()
|
||||
prompt_input = QtWidgets.QWidget()
|
||||
prompt_input.setLayout(self.hbox_edit)
|
||||
|
||||
# vbox with title + chat/nicklist + prompt/input
|
||||
vbox = QtGui.QVBoxLayout()
|
||||
vbox = QtWidgets.QVBoxLayout()
|
||||
vbox.setContentsMargins(0, 0, 0, 0)
|
||||
vbox.setSpacing(0)
|
||||
vbox.addWidget(self.title)
|
||||
@ -139,7 +137,7 @@ class BufferWidget(QtGui.QWidget):
|
||||
if self.hbox_edit.count() > 1:
|
||||
self.hbox_edit.takeAt(0)
|
||||
if prompt is not None:
|
||||
label = QtGui.QLabel(prompt)
|
||||
label = QtWidgets.QLabel(prompt)
|
||||
label.setContentsMargins(0, 0, 5, 0)
|
||||
self.hbox_edit.insertWidget(0, label)
|
||||
|
||||
@ -147,7 +145,7 @@ class BufferWidget(QtGui.QWidget):
|
||||
class Buffer(QtCore.QObject):
|
||||
"""A WeeChat buffer."""
|
||||
|
||||
bufferInput = qt_compat.Signal(str, str)
|
||||
bufferInput = QtCore.Signal(str, str)
|
||||
|
||||
def __init__(self, data={}):
|
||||
QtCore.QObject.__init__(self)
|
||||
@ -167,15 +165,17 @@ class Buffer(QtCore.QObject):
|
||||
"""Update title."""
|
||||
try:
|
||||
self.widget.set_title(
|
||||
color.remove(self.data['title'].decode('utf-8')))
|
||||
except: # noqa: E722
|
||||
color.remove(self.data['title']))
|
||||
except Exception: # noqa: E722
|
||||
# TODO: Debug print the exception to be fixed.
|
||||
# traceback.print_exc()
|
||||
self.widget.set_title(None)
|
||||
|
||||
def update_prompt(self):
|
||||
"""Update prompt."""
|
||||
try:
|
||||
self.widget.set_prompt(self.data['local_variables']['nick'])
|
||||
except: # noqa: E722
|
||||
except Exception: # noqa: E722
|
||||
self.widget.set_prompt(None)
|
||||
|
||||
def input_text_sent(self, text):
|
||||
@ -243,6 +243,6 @@ class Buffer(QtCore.QObject):
|
||||
pixmap = QtGui.QPixmap(8, 8)
|
||||
pixmap.fill()
|
||||
icon = QtGui.QIcon(pixmap)
|
||||
item = QtGui.QListWidgetItem(icon, nick['name'])
|
||||
item = QtWidgets.QListWidgetItem(icon, nick['name'])
|
||||
self.widget.nicklist.addItem(item)
|
||||
self.widget.nicklist.setVisible(True)
|
||||
|
@ -21,19 +21,18 @@
|
||||
#
|
||||
|
||||
import datetime
|
||||
import qt_compat
|
||||
import config
|
||||
import weechat.color as color
|
||||
from qweechat import config
|
||||
from qweechat.weechat import color
|
||||
|
||||
QtCore = qt_compat.import_module('QtCore')
|
||||
QtGui = qt_compat.import_module('QtGui')
|
||||
from PySide6 import QtCore
|
||||
from PySide6 import QtWidgets, QtGui
|
||||
|
||||
|
||||
class ChatTextEdit(QtGui.QTextEdit):
|
||||
class ChatTextEdit(QtWidgets.QTextEdit):
|
||||
"""Chat area."""
|
||||
|
||||
def __init__(self, debug, *args):
|
||||
QtGui.QTextEdit.__init__(*(self,) + args)
|
||||
QtWidgets.QTextEdit.__init__(*(self,) + args)
|
||||
self.debug = debug
|
||||
self.readOnly = True
|
||||
self.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
@ -77,9 +76,9 @@ class ChatTextEdit(QtGui.QTextEdit):
|
||||
prefix = '\x01(F%s)%s' % (forcecolor, prefix)
|
||||
text = '\x01(F%s)%s' % (forcecolor, text)
|
||||
if prefix:
|
||||
self._display_with_colors(str(prefix).decode('utf-8') + ' ')
|
||||
self._display_with_colors(prefix + ' ')
|
||||
if text:
|
||||
self._display_with_colors(str(text).decode('utf-8'))
|
||||
self._display_with_colors(text)
|
||||
if text[-1:] != '\n':
|
||||
self.insertPlainText('\n')
|
||||
else:
|
||||
|
@ -20,7 +20,7 @@
|
||||
# along with QWeeChat. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
import ConfigParser
|
||||
import configparser
|
||||
import os
|
||||
|
||||
CONFIG_DIR = '%s/.qweechat' % os.getenv('HOME')
|
||||
@ -91,7 +91,7 @@ config_color_options = []
|
||||
def read():
|
||||
"""Read config file."""
|
||||
global config_color_options
|
||||
config = ConfigParser.RawConfigParser()
|
||||
config = configparser.RawConfigParser()
|
||||
if os.path.isfile(CONFIG_FILENAME):
|
||||
config.read(CONFIG_FILENAME)
|
||||
|
||||
@ -123,7 +123,7 @@ def write(config):
|
||||
"""Write config file."""
|
||||
if not os.path.exists(CONFIG_DIR):
|
||||
os.mkdir(CONFIG_DIR, 0o0755)
|
||||
with open(CONFIG_FILENAME, 'wb') as cfg:
|
||||
with open(CONFIG_FILENAME, 'w') as cfg:
|
||||
config.write(cfg)
|
||||
|
||||
|
||||
|
@ -20,29 +20,27 @@
|
||||
# along with QWeeChat. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
import qt_compat
|
||||
|
||||
QtGui = qt_compat.import_module('QtGui')
|
||||
from PySide6 import QtGui, QtWidgets
|
||||
|
||||
|
||||
class ConnectionDialog(QtGui.QDialog):
|
||||
class ConnectionDialog(QtWidgets.QDialog):
|
||||
"""Connection window."""
|
||||
|
||||
def __init__(self, values, *args):
|
||||
QtGui.QDialog.__init__(*(self,) + args)
|
||||
super().__init__(*args)
|
||||
self.values = values
|
||||
self.setModal(True)
|
||||
|
||||
grid = QtGui.QGridLayout()
|
||||
grid = QtWidgets.QGridLayout()
|
||||
grid.setSpacing(10)
|
||||
|
||||
self.fields = {}
|
||||
for line, field in enumerate(('server', 'port', 'password', 'lines')):
|
||||
grid.addWidget(QtGui.QLabel(field.capitalize()), line, 0)
|
||||
line_edit = QtGui.QLineEdit()
|
||||
grid.addWidget(QtWidgets.QLabel(field.capitalize()), line, 0)
|
||||
line_edit = QtWidgets.QLineEdit()
|
||||
line_edit.setFixedWidth(200)
|
||||
if field == 'password':
|
||||
line_edit.setEchoMode(QtGui.QLineEdit.Password)
|
||||
line_edit.setEchoMode(QtWidgets.QLineEdit.Password)
|
||||
if field == 'lines':
|
||||
validator = QtGui.QIntValidator(0, 2147483647, self)
|
||||
line_edit.setValidator(validator)
|
||||
@ -51,14 +49,14 @@ class ConnectionDialog(QtGui.QDialog):
|
||||
grid.addWidget(line_edit, line, 1)
|
||||
self.fields[field] = line_edit
|
||||
if field == 'port':
|
||||
ssl = QtGui.QCheckBox('SSL')
|
||||
ssl = QtWidgets.QCheckBox('SSL')
|
||||
ssl.setChecked(self.values['ssl'] == 'on')
|
||||
grid.addWidget(ssl, line, 2)
|
||||
self.fields['ssl'] = ssl
|
||||
|
||||
self.dialog_buttons = QtGui.QDialogButtonBox()
|
||||
self.dialog_buttons = QtWidgets.QDialogButtonBox()
|
||||
self.dialog_buttons.setStandardButtons(
|
||||
QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Cancel)
|
||||
QtWidgets.QDialogButtonBox.Ok | QtWidgets.QDialogButtonBox.Cancel)
|
||||
self.dialog_buttons.rejected.connect(self.close)
|
||||
|
||||
grid.addWidget(self.dialog_buttons, 4, 0, 1, 2)
|
||||
|
@ -20,25 +20,24 @@
|
||||
# along with QWeeChat. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
import qt_compat
|
||||
from chat import ChatTextEdit
|
||||
from input import InputLineEdit
|
||||
from qweechat.chat import ChatTextEdit
|
||||
from qweechat.input import InputLineEdit
|
||||
|
||||
QtGui = qt_compat.import_module('QtGui')
|
||||
from PySide6 import QtWidgets
|
||||
|
||||
|
||||
class DebugDialog(QtGui.QDialog):
|
||||
class DebugDialog(QtWidgets.QDialog):
|
||||
"""Debug dialog."""
|
||||
|
||||
def __init__(self, *args):
|
||||
QtGui.QDialog.__init__(*(self,) + args)
|
||||
QtWidgets.QDialog.__init__(*(self,) + args)
|
||||
self.resize(640, 480)
|
||||
self.setWindowTitle('Debug console')
|
||||
|
||||
self.chat = ChatTextEdit(debug=True)
|
||||
self.input = InputLineEdit(self.chat)
|
||||
|
||||
vbox = QtGui.QVBoxLayout()
|
||||
vbox = QtWidgets.QVBoxLayout()
|
||||
vbox.addWidget(self.chat)
|
||||
vbox.addWidget(self.input)
|
||||
|
||||
|
@ -20,21 +20,19 @@
|
||||
# along with QWeeChat. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
import qt_compat
|
||||
|
||||
QtCore = qt_compat.import_module('QtCore')
|
||||
QtGui = qt_compat.import_module('QtGui')
|
||||
from PySide6 import QtCore
|
||||
from PySide6 import QtWidgets
|
||||
|
||||
|
||||
class InputLineEdit(QtGui.QLineEdit):
|
||||
class InputLineEdit(QtWidgets.QLineEdit):
|
||||
"""Input line."""
|
||||
|
||||
bufferSwitchPrev = qt_compat.Signal()
|
||||
bufferSwitchNext = qt_compat.Signal()
|
||||
textSent = qt_compat.Signal(str)
|
||||
bufferSwitchPrev = QtCore.Signal()
|
||||
bufferSwitchNext = QtCore.Signal()
|
||||
textSent = QtCore.Signal(str)
|
||||
|
||||
def __init__(self, scroll_widget):
|
||||
QtGui.QLineEdit.__init__(self)
|
||||
super().__init__()
|
||||
self.scroll_widget = scroll_widget
|
||||
self._history = []
|
||||
self._history_index = -1
|
||||
@ -50,7 +48,7 @@ class InputLineEdit(QtGui.QLineEdit):
|
||||
elif key == QtCore.Qt.Key_PageDown:
|
||||
self.bufferSwitchNext.emit()
|
||||
else:
|
||||
QtGui.QLineEdit.keyPressEvent(self, event)
|
||||
QtWidgets.QLineEdit.keyPressEvent(self, event)
|
||||
elif modifiers == QtCore.Qt.AltModifier:
|
||||
if key in (QtCore.Qt.Key_Left, QtCore.Qt.Key_Up):
|
||||
self.bufferSwitchPrev.emit()
|
||||
@ -65,7 +63,7 @@ class InputLineEdit(QtGui.QLineEdit):
|
||||
elif key == QtCore.Qt.Key_End:
|
||||
bar.setValue(bar.maximum())
|
||||
else:
|
||||
QtGui.QLineEdit.keyPressEvent(self, event)
|
||||
QtWidgets.QLineEdit.keyPressEvent(self, event)
|
||||
elif key == QtCore.Qt.Key_PageUp:
|
||||
bar.setValue(bar.value() - bar.pageStep())
|
||||
elif key == QtCore.Qt.Key_PageDown:
|
||||
@ -75,10 +73,10 @@ class InputLineEdit(QtGui.QLineEdit):
|
||||
elif key == QtCore.Qt.Key_Down:
|
||||
self._history_navigate(1)
|
||||
else:
|
||||
QtGui.QLineEdit.keyPressEvent(self, event)
|
||||
QtWidgets.QLineEdit.keyPressEvent(self, event)
|
||||
|
||||
def _input_return_pressed(self):
|
||||
self._history.append(self.text().encode('utf-8'))
|
||||
self._history.append(self.text())
|
||||
self._history_index = len(self._history)
|
||||
self.textSent.emit(self.text())
|
||||
self.clear()
|
||||
|
@ -21,11 +21,11 @@
|
||||
#
|
||||
|
||||
import struct
|
||||
import qt_compat
|
||||
import config
|
||||
|
||||
QtCore = qt_compat.import_module('QtCore')
|
||||
QtNetwork = qt_compat.import_module('QtNetwork')
|
||||
from PySide6 import QtCore, QtNetwork
|
||||
|
||||
from qweechat import config
|
||||
|
||||
|
||||
_PROTO_INIT_CMD = ['init password=%(password)s']
|
||||
|
||||
@ -47,11 +47,11 @@ _PROTO_SYNC_CMDS = [
|
||||
class Network(QtCore.QObject):
|
||||
"""I/O with WeeChat/relay."""
|
||||
|
||||
statusChanged = qt_compat.Signal(str, str)
|
||||
messageFromWeechat = qt_compat.Signal(QtCore.QByteArray)
|
||||
statusChanged = QtCore.Signal(str, str)
|
||||
messageFromWeechat = QtCore.Signal(QtCore.QByteArray)
|
||||
|
||||
def __init__(self, *args):
|
||||
QtCore.QObject.__init__(*(self,) + args)
|
||||
super().__init__(*args)
|
||||
self.status_disconnected = 'disconnected'
|
||||
self.status_connecting = 'connecting...'
|
||||
self.status_connected = 'connected'
|
||||
@ -63,7 +63,7 @@ class Network(QtCore.QObject):
|
||||
self._buffer = QtCore.QByteArray()
|
||||
self._socket = QtNetwork.QSslSocket()
|
||||
self._socket.connected.connect(self._socket_connected)
|
||||
self._socket.error.connect(self._socket_error)
|
||||
# self._socket.error.connect(self._socket_error)
|
||||
self._socket.readyRead.connect(self._socket_read)
|
||||
self._socket.disconnected.connect(self._socket_disconnected)
|
||||
|
||||
@ -87,7 +87,7 @@ class Network(QtCore.QObject):
|
||||
self._buffer.append(data)
|
||||
while len(self._buffer) >= 4:
|
||||
remainder = None
|
||||
length = struct.unpack('>i', self._buffer[0:4])[0]
|
||||
length = struct.unpack('>i', self._buffer[0:4].data())[0]
|
||||
if len(self._buffer) < length:
|
||||
# partial message, just wait for end of message
|
||||
break
|
||||
@ -108,7 +108,7 @@ class Network(QtCore.QObject):
|
||||
self._server = None
|
||||
self._port = None
|
||||
self._ssl = None
|
||||
self._password = None
|
||||
self._password = ""
|
||||
self.statusChanged.emit(self.status_disconnected, None)
|
||||
|
||||
def is_connected(self):
|
||||
@ -136,11 +136,12 @@ class Network(QtCore.QObject):
|
||||
return
|
||||
if self._socket.state() != QtNetwork.QAbstractSocket.UnconnectedState:
|
||||
self._socket.abort()
|
||||
self._socket.connectToHost(self._server, self._port)
|
||||
if self._ssl:
|
||||
self._socket.ignoreSslErrors()
|
||||
self._socket.startClientEncryption()
|
||||
self.statusChanged.emit(self.status_connecting, None)
|
||||
self._socket.connectToHostEncrypted(self._server, self._port)
|
||||
else:
|
||||
self._socket.connectToHost(self._server, self._port)
|
||||
self.statusChanged.emit(self.status_connecting, "")
|
||||
|
||||
def disconnect_weechat(self):
|
||||
"""Disconnect from WeeChat."""
|
||||
|
@ -1,55 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# File downloaded from:
|
||||
# https://github.com/epage/PythonUtils/blob/master/util/qt_compat.py
|
||||
# Author: epage
|
||||
# License: LGPL 2.1
|
||||
#
|
||||
|
||||
from __future__ import with_statement
|
||||
from __future__ import division
|
||||
|
||||
_TRY_PYSIDE = True
|
||||
uses_pyside = False
|
||||
|
||||
try:
|
||||
if not _TRY_PYSIDE:
|
||||
raise ImportError()
|
||||
import PySide.QtCore as _QtCore
|
||||
QtCore = _QtCore
|
||||
uses_pyside = True
|
||||
except ImportError:
|
||||
import sip
|
||||
sip.setapi('QString', 2)
|
||||
sip.setapi('QVariant', 2)
|
||||
import PyQt4.QtCore as _QtCore
|
||||
QtCore = _QtCore
|
||||
uses_pyside = False
|
||||
|
||||
|
||||
def _pyside_import_module(moduleName):
|
||||
pyside = __import__('PySide', globals(), locals(), [moduleName], -1)
|
||||
return getattr(pyside, moduleName)
|
||||
|
||||
|
||||
def _pyqt4_import_module(moduleName):
|
||||
pyside = __import__('PyQt4', globals(), locals(), [moduleName], -1)
|
||||
return getattr(pyside, moduleName)
|
||||
|
||||
|
||||
if uses_pyside:
|
||||
import_module = _pyside_import_module
|
||||
|
||||
Signal = QtCore.Signal
|
||||
Slot = QtCore.Slot
|
||||
Property = QtCore.Property
|
||||
else:
|
||||
import_module = _pyqt4_import_module
|
||||
|
||||
Signal = QtCore.pyqtSignal
|
||||
Slot = QtCore.pyqtSlot
|
||||
Property = QtCore.pyqtProperty
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
pass
|
@ -36,18 +36,18 @@ It requires requires WeeChat 0.3.7 or newer, running on local or remote host.
|
||||
import sys
|
||||
import traceback
|
||||
from pkg_resources import resource_filename
|
||||
import qt_compat
|
||||
import config
|
||||
import weechat.protocol as protocol
|
||||
from network import Network
|
||||
from connection import ConnectionDialog
|
||||
from buffer import BufferListWidget, Buffer
|
||||
from debug import DebugDialog
|
||||
from about import AboutDialog
|
||||
from version import qweechat_version
|
||||
|
||||
QtCore = qt_compat.import_module('QtCore')
|
||||
QtGui = qt_compat.import_module('QtGui')
|
||||
from PySide6 import QtGui, QtWidgets, QtCore
|
||||
|
||||
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
|
||||
|
||||
|
||||
NAME = 'QWeeChat'
|
||||
AUTHOR = 'Sébastien Helleu'
|
||||
@ -58,11 +58,11 @@ WEECHAT_SITE = 'https://weechat.org/'
|
||||
DEBUG_NUM_LINES = 50
|
||||
|
||||
|
||||
class MainWindow(QtGui.QMainWindow):
|
||||
class MainWindow(QtWidgets.QMainWindow):
|
||||
"""Main window."""
|
||||
|
||||
def __init__(self, *args):
|
||||
QtGui.QMainWindow.__init__(*(self,) + args)
|
||||
super().__init__()
|
||||
|
||||
self.config = config.read()
|
||||
|
||||
@ -87,11 +87,11 @@ class MainWindow(QtGui.QMainWindow):
|
||||
|
||||
# default buffer
|
||||
self.buffers = [Buffer()]
|
||||
self.stacked_buffers = QtGui.QStackedWidget()
|
||||
self.stacked_buffers = QtWidgets.QStackedWidget()
|
||||
self.stacked_buffers.addWidget(self.buffers[0].widget)
|
||||
|
||||
# splitter with buffers + chat/input
|
||||
splitter = QtGui.QSplitter()
|
||||
splitter = QtWidgets.QSplitter()
|
||||
splitter.addWidget(self.list_buffers)
|
||||
splitter.addWidget(self.stacked_buffers)
|
||||
|
||||
@ -146,7 +146,7 @@ class MainWindow(QtGui.QMainWindow):
|
||||
menu_window.addAction(self.actions['debug'])
|
||||
menu_help = self.menu.addMenu('&Help')
|
||||
menu_help.addAction(self.actions['about'])
|
||||
self.network_status = QtGui.QLabel()
|
||||
self.network_status = QtWidgets.QLabel()
|
||||
self.network_status.setFixedHeight(20)
|
||||
self.network_status.setFixedWidth(200)
|
||||
self.network_status.setContentsMargins(0, 0, 10, 0)
|
||||
@ -249,8 +249,7 @@ class MainWindow(QtGui.QMainWindow):
|
||||
'© 2011-2020 %s <<a href="mailto:%s">%s</a>>'
|
||||
% (AUTHOR, AUTHOR_MAIL, AUTHOR_MAIL),
|
||||
'',
|
||||
'Running with %s' % ('PySide' if qt_compat.uses_pyside
|
||||
else 'PyQt4'),
|
||||
'Running with PySide6',
|
||||
'',
|
||||
'WeeChat site: <a href="%s">%s</a>'
|
||||
% (WEECHAT_SITE, WEECHAT_SITE),
|
||||
@ -315,11 +314,11 @@ class MainWindow(QtGui.QMainWindow):
|
||||
self.debug_display(0, '==>',
|
||||
'message (%d bytes):\n%s'
|
||||
% (len(message),
|
||||
protocol.hex_and_ascii(message, 20)),
|
||||
protocol.hex_and_ascii(message.data(), 20)),
|
||||
forcecolor='#008800')
|
||||
try:
|
||||
proto = protocol.Protocol()
|
||||
message = proto.decode(str(message))
|
||||
message = proto.decode(message.data())
|
||||
if message.uncompressed:
|
||||
self.debug_display(
|
||||
0, '==>',
|
||||
@ -329,7 +328,7 @@ class MainWindow(QtGui.QMainWindow):
|
||||
forcecolor='#008800')
|
||||
self.debug_display(0, '', 'Message: %s' % message)
|
||||
self.parse_message(message)
|
||||
except: # noqa: E722
|
||||
except Exception: # noqa: E722
|
||||
print('Error while decoding message from WeeChat:\n%s'
|
||||
% traceback.format_exc())
|
||||
self.network.disconnect_weechat()
|
||||
@ -495,6 +494,8 @@ class MainWindow(QtGui.QMainWindow):
|
||||
self.network.desync_weechat()
|
||||
elif message.msgid == '_upgrade_ended':
|
||||
self.network.sync_weechat()
|
||||
else:
|
||||
print(f"Unknown message with id {message.msgid}")
|
||||
|
||||
def create_buffer(self, item):
|
||||
"""Create a new buffer."""
|
||||
@ -509,9 +510,8 @@ class MainWindow(QtGui.QMainWindow):
|
||||
def insert_buffer(self, index, buf):
|
||||
"""Insert a buffer in list."""
|
||||
self.buffers.insert(index, buf)
|
||||
self.list_buffers.insertItem(index, '%d. %s'
|
||||
% (buf.data['number'],
|
||||
buf.data['full_name'].decode('utf-8')))
|
||||
self.list_buffers.insertItem(index, '%s'
|
||||
% (buf.data['local_variables']['name']))
|
||||
self.stacked_buffers.insertWidget(index, buf.widget)
|
||||
|
||||
def remove_buffer(self, index):
|
||||
@ -544,12 +544,18 @@ class MainWindow(QtGui.QMainWindow):
|
||||
if self.debug_dialog:
|
||||
self.debug_dialog.close()
|
||||
config.write(self.config)
|
||||
QtGui.QMainWindow.closeEvent(self, event)
|
||||
QtWidgets.QMainWindow.closeEvent(self, event)
|
||||
|
||||
|
||||
app = QtGui.QApplication(sys.argv)
|
||||
app.setStyle(QtGui.QStyleFactory.create('Cleanlooks'))
|
||||
app.setWindowIcon(QtGui.QIcon(
|
||||
resource_filename(__name__, 'data/icons/weechat.png')))
|
||||
main = MainWindow()
|
||||
sys.exit(app.exec_())
|
||||
def main():
|
||||
app = QtWidgets.QApplication(sys.argv)
|
||||
app.setStyle(QtWidgets.QStyleFactory.create('Cleanlooks'))
|
||||
app.setWindowIcon(QtGui.QIcon(
|
||||
resource_filename(__name__, 'data/icons/weechat.png')))
|
||||
main = MainWindow()
|
||||
main.show()
|
||||
sys.exit(app.exec_())
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
@ -21,6 +21,7 @@
|
||||
#
|
||||
|
||||
import re
|
||||
import logging
|
||||
|
||||
RE_COLOR_ATTRS = r'[*!/_|]*'
|
||||
RE_COLOR_STD = r'(?:%s\d{2})' % RE_COLOR_ATTRS
|
||||
@ -75,6 +76,9 @@ WEECHAT_BASIC_COLORS = (
|
||||
('white', 0))
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Color():
|
||||
def __init__(self, color_options, debug=False):
|
||||
self.color_options = color_options
|
||||
@ -92,7 +96,7 @@ class Color():
|
||||
index = int(color)
|
||||
return '\x01(Fr%s)' % self.color_options[index]
|
||||
except: # noqa: E722
|
||||
print('Error decoding WeeChat color "%s"' % color)
|
||||
log.debug('Error decoding WeeChat color "%s"' % color)
|
||||
return ''
|
||||
|
||||
def _convert_terminal_color(self, fg_bg, attrs, color):
|
||||
@ -100,7 +104,7 @@ class Color():
|
||||
index = int(color)
|
||||
return '\x01(%s%s#%s)' % (fg_bg, attrs, self._rgb_color(index))
|
||||
except: # noqa: E722
|
||||
print('Error decoding terminal color "%s"' % color)
|
||||
log.debug('Error decoding terminal color "%s"' % color)
|
||||
return ''
|
||||
|
||||
def _convert_color_attr(self, fg_bg, color):
|
||||
@ -123,7 +127,7 @@ class Color():
|
||||
return self._convert_terminal_color(fg_bg, attrs,
|
||||
WEECHAT_BASIC_COLORS[index][1])
|
||||
except: # noqa: E722
|
||||
print('Error decoding color "%s"' % color)
|
||||
log.debug('Error decoding color "%s"' % color)
|
||||
return ''
|
||||
|
||||
def _attrcode_to_char(self, code):
|
||||
|
@ -34,15 +34,11 @@ import collections
|
||||
import struct
|
||||
import zlib
|
||||
|
||||
if hasattr(collections, 'OrderedDict'):
|
||||
# python >= 2.7
|
||||
class WeechatDict(collections.OrderedDict):
|
||||
def __str__(self):
|
||||
return '{%s}' % ', '.join(
|
||||
['%s: %s' % (repr(key), repr(self[key])) for key in self])
|
||||
else:
|
||||
# python <= 2.6
|
||||
WeechatDict = dict
|
||||
|
||||
class WeechatDict(collections.OrderedDict):
|
||||
def __str__(self):
|
||||
return '{%s}' % ', '.join(
|
||||
['%s: %s' % (repr(key), repr(self[key])) for key in self])
|
||||
|
||||
|
||||
class WeechatObject:
|
||||
@ -151,7 +147,7 @@ class Protocol:
|
||||
if len(self.data) < 3:
|
||||
self.data = ''
|
||||
return ''
|
||||
objtype = str(self.data[0:3])
|
||||
objtype = self.data[0:3].decode()
|
||||
self.data = self.data[3:]
|
||||
return objtype
|
||||
|
||||
@ -196,14 +192,14 @@ class Protocol:
|
||||
value = self._obj_len_data(1)
|
||||
if value is None:
|
||||
return None
|
||||
return int(str(value))
|
||||
return int(value)
|
||||
|
||||
def _obj_str(self):
|
||||
"""Read a string in data (length on 4 bytes + content)."""
|
||||
value = self._obj_len_data(4)
|
||||
if value is None:
|
||||
return None
|
||||
return str(value)
|
||||
if value in ("", None):
|
||||
return ""
|
||||
return value.decode()
|
||||
|
||||
def _obj_buffer(self):
|
||||
"""Read a buffer in data (length on 4 bytes + data)."""
|
||||
@ -214,14 +210,14 @@ class Protocol:
|
||||
value = self._obj_len_data(1)
|
||||
if value is None:
|
||||
return None
|
||||
return '0x%s' % str(value)
|
||||
return '0x%s' % value
|
||||
|
||||
def _obj_time(self):
|
||||
"""Read a time in data (length on 1 byte + value as string)."""
|
||||
value = self._obj_len_data(1)
|
||||
if value is None:
|
||||
return None
|
||||
return int(str(value))
|
||||
return int(value)
|
||||
|
||||
def _obj_hashtable(self):
|
||||
"""
|
||||
@ -314,8 +310,8 @@ class Protocol:
|
||||
if compression:
|
||||
uncompressed = zlib.decompress(self.data[5:])
|
||||
size_uncompressed = len(uncompressed) + 5
|
||||
uncompressed = '%s%s%s' % (struct.pack('>i', size_uncompressed),
|
||||
struct.pack('b', 0), uncompressed)
|
||||
uncompressed = b'%s%s%s' % (struct.pack('>i', size_uncompressed),
|
||||
struct.pack('b', 0), uncompressed)
|
||||
self.data = uncompressed
|
||||
else:
|
||||
uncompressed = self.data[:]
|
||||
@ -344,13 +340,20 @@ def hex_and_ascii(data, bytes_per_line=10):
|
||||
for i in range(num_lines):
|
||||
str_hex = []
|
||||
str_ascii = []
|
||||
for char in data[i*bytes_per_line:(i*bytes_per_line)+bytes_per_line]:
|
||||
for j in range(bytes_per_line):
|
||||
# We can't easily iterate over individual bytes, so we are going to
|
||||
# do it this way.
|
||||
index = (i*bytes_per_line) + j
|
||||
char = data[index:index+1]
|
||||
if not char:
|
||||
char = b'x'
|
||||
byte = struct.unpack('B', char)[0]
|
||||
str_hex.append('%02X' % int(byte))
|
||||
str_hex.append(b'%02X' % int(byte))
|
||||
if byte >= 32 and byte <= 127:
|
||||
str_ascii.append(char)
|
||||
else:
|
||||
str_ascii.append('.')
|
||||
fmt = '%%-%ds %%s' % ((bytes_per_line * 3) - 1)
|
||||
lines.append(fmt % (' '.join(str_hex), ''.join(str_ascii)))
|
||||
return '\n'.join(lines)
|
||||
str_ascii.append(b'.')
|
||||
fmt = b'%%-%ds %%s' % ((bytes_per_line * 3) - 1)
|
||||
lines.append(fmt % (b' '.join(str_hex),
|
||||
b''.join(str_ascii)))
|
||||
return b'\n'.join(lines)
|
||||
|
@ -24,8 +24,6 @@
|
||||
Command-line program for testing WeeChat/relay protocol.
|
||||
"""
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import select
|
||||
@ -36,8 +34,9 @@ import sys
|
||||
import time
|
||||
import traceback
|
||||
|
||||
import protocol # WeeChat/relay protocol
|
||||
from .. version import qweechat_version
|
||||
from qweechat.weechat import protocol
|
||||
|
||||
qweechat_version = '0.1'
|
||||
|
||||
NAME = 'qweechat-testproto'
|
||||
|
||||
@ -61,12 +60,13 @@ class TestProto(object):
|
||||
try:
|
||||
self.sock = socket.socket(inet, socket.SOCK_STREAM)
|
||||
self.sock.connect((self.args.hostname, self.args.port))
|
||||
except: # noqa: E722
|
||||
except Exception:
|
||||
if self.sock:
|
||||
self.sock.close()
|
||||
print('Failed to connect to', self.address)
|
||||
return False
|
||||
print('Connected to', self.address)
|
||||
|
||||
print(f'Connected to {self.address} socket {self.sock}')
|
||||
return True
|
||||
|
||||
def send(self, messages):
|
||||
@ -75,11 +75,12 @@ class TestProto(object):
|
||||
Return True if OK, False if error.
|
||||
"""
|
||||
try:
|
||||
for msg in messages.split('\n'):
|
||||
if msg == 'quit':
|
||||
for msg in messages.split(b'\n'):
|
||||
if msg == b'quit':
|
||||
self.has_quit = True
|
||||
self.sock.sendall(msg + '\n')
|
||||
print('\x1b[33m<-- ' + msg + '\x1b[0m')
|
||||
self.sock.sendall(msg + b'\n')
|
||||
sys.stdout.write(
|
||||
(b'\x1b[33m<-- ' + msg + b'\x1b[0m\n').decode())
|
||||
except: # noqa: E722
|
||||
traceback.print_exc()
|
||||
print('Failed to send message')
|
||||
@ -94,7 +95,7 @@ class TestProto(object):
|
||||
try:
|
||||
proto = protocol.Protocol()
|
||||
msgd = proto.decode(message,
|
||||
separator='\n' if self.args.debug > 0
|
||||
separator=b'\n' if self.args.debug > 0
|
||||
else ', ')
|
||||
print('')
|
||||
if self.args.debug >= 2 and msgd.uncompressed:
|
||||
@ -122,7 +123,7 @@ class TestProto(object):
|
||||
data = os.read(sys.stdin.fileno(), 4096)
|
||||
if data:
|
||||
if not self.send(data.strip()):
|
||||
# self.sock.close()
|
||||
self.sock.close()
|
||||
return False
|
||||
# open stdin to read user commands
|
||||
sys.stdin = open('/dev/tty')
|
||||
@ -136,10 +137,10 @@ class TestProto(object):
|
||||
"""
|
||||
if self.has_quit:
|
||||
return 0
|
||||
message = ''
|
||||
recvbuf = ''
|
||||
prompt = '\x1b[36mrelay> \x1b[0m'
|
||||
sys.stdout.write(prompt)
|
||||
message = b''
|
||||
recvbuf = b''
|
||||
prompt = b'\x1b[36mrelay> \x1b[0m'
|
||||
sys.stdout.write(prompt.decode())
|
||||
sys.stdout.flush()
|
||||
try:
|
||||
while not self.has_quit:
|
||||
@ -149,13 +150,14 @@ class TestProto(object):
|
||||
buf = os.read(_file.fileno(), 4096)
|
||||
if buf:
|
||||
message += buf
|
||||
if '\n' in message:
|
||||
messages = message.split('\n')
|
||||
msgsent = '\n'.join(messages[:-1])
|
||||
if b'\n' in message:
|
||||
messages = message.split(b'\n')
|
||||
msgsent = b'\n'.join(messages[:-1])
|
||||
if msgsent and not self.send(msgsent):
|
||||
return 4
|
||||
message = messages[-1]
|
||||
sys.stdout.write(prompt + message)
|
||||
sys.stdout.write((prompt + message).decode())
|
||||
# sys.stdout.write(prompt + message)
|
||||
sys.stdout.flush()
|
||||
else:
|
||||
buf = _file.recv(4096)
|
||||
@ -178,12 +180,12 @@ class TestProto(object):
|
||||
if remainder:
|
||||
recvbuf = remainder
|
||||
else:
|
||||
recvbuf = ''
|
||||
sys.stdout.write(prompt + message)
|
||||
recvbuf = b''
|
||||
sys.stdout.write((prompt + message).decode())
|
||||
sys.stdout.flush()
|
||||
except: # noqa: E722
|
||||
traceback.print_exc()
|
||||
self.send('quit')
|
||||
self.send(b'quit')
|
||||
return 0
|
||||
|
||||
def __del__(self):
|
||||
@ -220,7 +222,7 @@ The script returns:
|
||||
help='debug mode: long objects view '
|
||||
'(-dd: display raw messages)')
|
||||
parser.add_argument('-v', '--version', action='version',
|
||||
version=qweechat_version())
|
||||
version=qweechat_version)
|
||||
parser.add_argument('hostname',
|
||||
help='hostname (or IP address) of machine running '
|
||||
'WeeChat/relay')
|
||||
|
Loading…
Reference in New Issue
Block a user