qt6 fixed
This commit is contained in:
parent
d1c8d445bc
commit
dd8ed70958
13 changed files with 1212 additions and 82 deletions
|
@ -1,8 +1,9 @@
|
||||||
# the versions are the current ones tested - may work with earlier versions
|
# the versions are the current ones tested - may work with earlier versions
|
||||||
# choose one of PyQt5 PyQt6 PySide2 PySide6
|
# choose one of PyQt5 PyQt6 PySide2 PySide6
|
||||||
# for now only PyQt5 is working:
|
# for now PyQt5 and PyQt6 is working, and most of the testing is PyQt5
|
||||||
# AttributeError: module 'qtpy.QtCore' has no attribute 'pyqtSignal'
|
# usually this is installed by your OS package manager and pip may not
|
||||||
PyQt5 >= 5.15.10
|
# detect the right version, so we leave these commented
|
||||||
|
# PyQt5 >= 5.15.10
|
||||||
QtPy >= 2.4.1
|
QtPy >= 2.4.1
|
||||||
PyAudio >= 0.2.13
|
PyAudio >= 0.2.13
|
||||||
numpy >= 1.26.1
|
numpy >= 1.26.1
|
||||||
|
|
|
@ -5,4 +5,5 @@ path = os.path.dirname(os.path.realpath(__file__)) # curr dir
|
||||||
|
|
||||||
sys.path.insert(0, os.path.join(path, 'styles'))
|
sys.path.insert(0, os.path.join(path, 'styles'))
|
||||||
sys.path.insert(0, os.path.join(path, 'plugins'))
|
sys.path.insert(0, os.path.join(path, 'plugins'))
|
||||||
|
sys.path.insert(0, os.path.join(path, 'third_party'))
|
||||||
sys.path.insert(0, path)
|
sys.path.insert(0, path)
|
||||||
|
|
2
toxygen/third_party/qweechat/about.py
vendored
2
toxygen/third_party/qweechat/about.py
vendored
|
@ -24,7 +24,7 @@
|
||||||
|
|
||||||
from qtpy import QtCore, QtWidgets as QtGui
|
from qtpy import QtCore, QtWidgets as QtGui
|
||||||
|
|
||||||
from third_party.qweechat.version import qweechat_version
|
from qweechat.version import qweechat_version
|
||||||
|
|
||||||
|
|
||||||
class AboutDialog(QtGui.QDialog):
|
class AboutDialog(QtGui.QDialog):
|
||||||
|
|
7
toxygen/third_party/qweechat/buffer.py
vendored
7
toxygen/third_party/qweechat/buffer.py
vendored
|
@ -25,12 +25,11 @@
|
||||||
from pkg_resources import resource_filename
|
from pkg_resources import resource_filename
|
||||||
|
|
||||||
from qtpy import QtCore, QtGui, QtWidgets
|
from qtpy import QtCore, QtGui, QtWidgets
|
||||||
# from PyQt5.QtCore import pyqtSignal as Signal
|
|
||||||
from qtpy.QtCore import Signal
|
from qtpy.QtCore import Signal
|
||||||
|
|
||||||
from third_party.qweechat.chat import ChatTextEdit
|
from qweechat.chat import ChatTextEdit
|
||||||
from third_party.qweechat.input import InputLineEdit
|
from qweechat.input import InputLineEdit
|
||||||
from third_party.qweechat.weechat import color
|
from qweechat.weechat import color
|
||||||
|
|
||||||
|
|
||||||
class GenericListWidget(QtWidgets.QListWidget):
|
class GenericListWidget(QtWidgets.QListWidget):
|
||||||
|
|
4
toxygen/third_party/qweechat/chat.py
vendored
4
toxygen/third_party/qweechat/chat.py
vendored
|
@ -26,8 +26,8 @@ import datetime
|
||||||
|
|
||||||
from qtpy import QtCore, QtWidgets, QtGui
|
from qtpy import QtCore, QtWidgets, QtGui
|
||||||
|
|
||||||
from third_party.qweechat import config
|
from qweechat import config
|
||||||
from third_party.qweechat.weechat import color
|
from qweechat.weechat import color
|
||||||
|
|
||||||
|
|
||||||
class ChatTextEdit(QtWidgets.QTextEdit):
|
class ChatTextEdit(QtWidgets.QTextEdit):
|
||||||
|
|
10
toxygen/third_party/qweechat/connection.py
vendored
10
toxygen/third_party/qweechat/connection.py
vendored
|
@ -45,7 +45,10 @@ class ConnectionDialog(QtWidgets.QDialog):
|
||||||
line_edit = QtWidgets.QLineEdit()
|
line_edit = QtWidgets.QLineEdit()
|
||||||
line_edit.setFixedWidth(200)
|
line_edit.setFixedWidth(200)
|
||||||
value = self.values.get('hostname', '')
|
value = self.values.get('hostname', '')
|
||||||
if value in ['None', None]: value = ''
|
if value in ['None', None]:
|
||||||
|
value = '0'
|
||||||
|
elif type(value) == int:
|
||||||
|
value = str(value)
|
||||||
line_edit.insert(value)
|
line_edit.insert(value)
|
||||||
grid.addWidget(line_edit, 0, 1)
|
grid.addWidget(line_edit, 0, 1)
|
||||||
self.fields['hostname'] = line_edit
|
self.fields['hostname'] = line_edit
|
||||||
|
@ -78,7 +81,10 @@ class ConnectionDialog(QtWidgets.QDialog):
|
||||||
line_edit.setFixedWidth(200)
|
line_edit.setFixedWidth(200)
|
||||||
line_edit.setEchoMode(QtWidgets.QLineEdit.Password)
|
line_edit.setEchoMode(QtWidgets.QLineEdit.Password)
|
||||||
value = self.values.get('password', '')
|
value = self.values.get('password', '')
|
||||||
if value in ['None', None]: value = ''
|
if value in ['None', None]:
|
||||||
|
value = '0'
|
||||||
|
elif type(value) == int:
|
||||||
|
value = str(value)
|
||||||
line_edit.insert(value)
|
line_edit.insert(value)
|
||||||
grid.addWidget(line_edit, 2, 1)
|
grid.addWidget(line_edit, 2, 1)
|
||||||
self.fields['password'] = line_edit
|
self.fields['password'] = line_edit
|
||||||
|
|
4
toxygen/third_party/qweechat/debug.py
vendored
4
toxygen/third_party/qweechat/debug.py
vendored
|
@ -24,8 +24,8 @@
|
||||||
|
|
||||||
from qtpy import QtWidgets
|
from qtpy import QtWidgets
|
||||||
|
|
||||||
from third_party.qweechat.chat import ChatTextEdit
|
from qweechat.chat import ChatTextEdit
|
||||||
from third_party.qweechat.input import InputLineEdit
|
from qweechat.input import InputLineEdit
|
||||||
|
|
||||||
|
|
||||||
class DebugDialog(QtWidgets.QDialog):
|
class DebugDialog(QtWidgets.QDialog):
|
||||||
|
|
1
toxygen/third_party/qweechat/input.py
vendored
1
toxygen/third_party/qweechat/input.py
vendored
|
@ -23,7 +23,6 @@
|
||||||
"""Input line for chat and debug window."""
|
"""Input line for chat and debug window."""
|
||||||
|
|
||||||
from qtpy import QtCore, QtWidgets
|
from qtpy import QtCore, QtWidgets
|
||||||
# from PyQt5.QtCore import pyqtSignal as Signal
|
|
||||||
from qtpy.QtCore import Signal
|
from qtpy.QtCore import Signal
|
||||||
|
|
||||||
class InputLineEdit(QtWidgets.QLineEdit):
|
class InputLineEdit(QtWidgets.QLineEdit):
|
||||||
|
|
27
toxygen/third_party/qweechat/network.py
vendored
27
toxygen/third_party/qweechat/network.py
vendored
|
@ -30,8 +30,8 @@ from qtpy import QtCore, QtNetwork
|
||||||
# from PyQt5.QtCore import pyqtSignal as Signal
|
# from PyQt5.QtCore import pyqtSignal as Signal
|
||||||
from qtpy.QtCore import Signal
|
from qtpy.QtCore import Signal
|
||||||
|
|
||||||
from third_party.qweechat import config
|
from qweechat import config
|
||||||
from third_party.qweechat.debug import DebugDialog
|
from qweechat.debug import DebugDialog
|
||||||
|
|
||||||
|
|
||||||
# list of supported hash algorithms on our side
|
# list of supported hash algorithms on our side
|
||||||
|
@ -232,7 +232,19 @@ class Network(QtCore.QObject):
|
||||||
|
|
||||||
def is_connected(self):
|
def is_connected(self):
|
||||||
"""Return True if the socket is connected, False otherwise."""
|
"""Return True if the socket is connected, False otherwise."""
|
||||||
return self._socket.state() == QtNetwork.QAbstractSocket.ConnectedState
|
return is_state(self, at='ConnectedState')
|
||||||
|
|
||||||
|
def is_state(self, at='ConnectedState'):
|
||||||
|
"""Return True if the socket is connected, False otherwise."""
|
||||||
|
if hasattr(QtNetwork.QAbstractSocket, 'ConnectedState'):
|
||||||
|
if self._socket.state() == getattr(QtNetwork.QAbstractSocket, at):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
if hasattr(QtNetwork.QAbstractSocket, 'SocketState'):
|
||||||
|
if self._socket.state() == getattr(QtNetwork.QAbstractSocket.SocketState, at):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
return False
|
||||||
|
|
||||||
def is_ssl(self):
|
def is_ssl(self):
|
||||||
"""Return True if SSL is used, False otherwise."""
|
"""Return True if SSL is used, False otherwise."""
|
||||||
|
@ -252,9 +264,10 @@ class Network(QtCore.QObject):
|
||||||
self._lines = int(lines)
|
self._lines = int(lines)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self._lines = config.CONFIG_DEFAULT_RELAY_LINES
|
self._lines = config.CONFIG_DEFAULT_RELAY_LINES
|
||||||
if self._socket.state() == QtNetwork.QAbstractSocket.ConnectedState:
|
# AttributeError: type object 'QAbstractSocket' has no attribute 'ConnectedState'
|
||||||
|
if self.is_connected():
|
||||||
return
|
return
|
||||||
if self._socket.state() != QtNetwork.QAbstractSocket.UnconnectedState:
|
if not self.is_state('UnconnectedState'):
|
||||||
self._socket.abort()
|
self._socket.abort()
|
||||||
if self._ssl:
|
if self._ssl:
|
||||||
self._socket.ignoreSslErrors()
|
self._socket.ignoreSslErrors()
|
||||||
|
@ -265,10 +278,10 @@ class Network(QtCore.QObject):
|
||||||
|
|
||||||
def disconnect_weechat(self):
|
def disconnect_weechat(self):
|
||||||
"""Disconnect from WeeChat."""
|
"""Disconnect from WeeChat."""
|
||||||
if self._socket.state() == QtNetwork.QAbstractSocket.UnconnectedState:
|
if self.is_state('UnconnectedState'):
|
||||||
self.set_status(STATUS_DISCONNECTED)
|
self.set_status(STATUS_DISCONNECTED)
|
||||||
return
|
return
|
||||||
if self._socket.state() == QtNetwork.QAbstractSocket.ConnectedState:
|
if self.is_state('ConnectedState'):
|
||||||
self.send_to_weechat('quit\n')
|
self.send_to_weechat('quit\n')
|
||||||
self._socket.waitForBytesWritten(1000)
|
self._socket.waitForBytesWritten(1000)
|
||||||
else:
|
else:
|
||||||
|
|
536
toxygen/third_party/qweechat/preferences.py
vendored
536
toxygen/third_party/qweechat/preferences.py
vendored
|
@ -2,7 +2,7 @@
|
||||||
#
|
#
|
||||||
# preferences.py - preferences dialog box
|
# preferences.py - preferences dialog box
|
||||||
#
|
#
|
||||||
# Copyright (C) 2011-2022 Sébastien Helleu <flashcode@flashtux.org>
|
# Copyright (C) 2016 Ricky Brent <ricky@rickybrent.com>
|
||||||
#
|
#
|
||||||
# This file is part of QWeeChat, a Qt remote GUI for WeeChat.
|
# This file is part of QWeeChat, a Qt remote GUI for WeeChat.
|
||||||
#
|
#
|
||||||
|
@ -20,38 +20,538 @@
|
||||||
# along with QWeeChat. If not, see <http://www.gnu.org/licenses/>.
|
# along with QWeeChat. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
|
|
||||||
"""Preferences dialog box."""
|
import config
|
||||||
|
import utils
|
||||||
from qtpy import QtCore, QtWidgets as QtGui
|
from inputlinespell import InputLineSpell
|
||||||
|
|
||||||
|
from qtpy import QtCore, QtGui
|
||||||
|
|
||||||
class PreferencesDialog(QtGui.QDialog):
|
class PreferencesDialog(QtGui.QDialog):
|
||||||
"""Preferences dialog."""
|
"""Preferences dialog."""
|
||||||
|
|
||||||
def __init__(self, *args):
|
custom_sections = {
|
||||||
|
"look": "Look",
|
||||||
|
"input": "Input Box",
|
||||||
|
"nicks": "Nick List",
|
||||||
|
"buffers": "Buffer List",
|
||||||
|
"buffer_flags": False,
|
||||||
|
"notifications": "Notifications",
|
||||||
|
"color": "Colors",
|
||||||
|
"relay": "Relay/Connection"
|
||||||
|
}
|
||||||
|
|
||||||
|
def __init__(self, name, parent, *args):
|
||||||
QtGui.QDialog.__init__(*(self,) + args)
|
QtGui.QDialog.__init__(*(self,) + args)
|
||||||
self.setModal(True)
|
self.setModal(True)
|
||||||
self.setWindowTitle('Preferences')
|
self.setWindowTitle(name)
|
||||||
|
self.parent = parent
|
||||||
|
self.config = parent.config
|
||||||
|
self.stacked_panes = QtGui.QStackedWidget()
|
||||||
|
self.list_panes = PreferencesTreeWidget("Settings")
|
||||||
|
|
||||||
close_button = QtGui.QPushButton('Close')
|
splitter = QtGui.QSplitter()
|
||||||
close_button.pressed.connect(self.close)
|
splitter.addWidget(self.list_panes)
|
||||||
|
splitter.addWidget(self.stacked_panes)
|
||||||
|
|
||||||
|
# Follow same order as defaults:
|
||||||
|
section_panes = {}
|
||||||
|
for section in config.CONFIG_DEFAULT_SECTIONS:
|
||||||
|
item = QtGui.QTreeWidgetItem(section)
|
||||||
|
name = section
|
||||||
|
item.setText(0, section.title())
|
||||||
|
if section in self.custom_sections:
|
||||||
|
if not self.custom_sections[section]:
|
||||||
|
continue
|
||||||
|
item.setText(0, self.custom_sections[section])
|
||||||
|
section_panes[section] = PreferencesPaneWidget(section, name)
|
||||||
|
self.list_panes.addTopLevelItem(item)
|
||||||
|
self.stacked_panes.addWidget(section_panes[section])
|
||||||
|
|
||||||
|
for setting, default in config.CONFIG_DEFAULT_OPTIONS:
|
||||||
|
section_key = setting.split(".")
|
||||||
|
section = section_key[0]
|
||||||
|
key = ".".join(section_key[1:])
|
||||||
|
section_panes[section].addItem(
|
||||||
|
key, self.config.get(section, key), default)
|
||||||
|
for key, value in self.config.items("color"):
|
||||||
|
section_panes["color"].addItem(key, value, False)
|
||||||
|
notification_field_count = len(section_panes["notifications"].fields)
|
||||||
|
notification = PreferencesNotificationBlock(
|
||||||
|
section_panes["notifications"])
|
||||||
|
section_panes["notifications"].grid.addLayout(
|
||||||
|
notification, notification_field_count, 0, 1, -1)
|
||||||
|
|
||||||
|
self.list_panes.currentItemChanged.connect(self._pane_switch)
|
||||||
|
self.list_panes.setCurrentItem(self.list_panes.topLevelItem(0))
|
||||||
|
|
||||||
hbox = QtGui.QHBoxLayout()
|
hbox = QtGui.QHBoxLayout()
|
||||||
|
self.dialog_buttons = QtGui.QDialogButtonBox()
|
||||||
|
self.dialog_buttons.setStandardButtons(
|
||||||
|
QtGui.QDialogButtonBox.Save | QtGui.QDialogButtonBox.Cancel)
|
||||||
|
self.dialog_buttons.rejected.connect(self.close)
|
||||||
|
self.dialog_buttons.accepted.connect(self._save_and_close)
|
||||||
|
|
||||||
hbox.addStretch(1)
|
hbox.addStretch(1)
|
||||||
hbox.addWidget(close_button)
|
hbox.addWidget(self.dialog_buttons)
|
||||||
hbox.addStretch(1)
|
hbox.addStretch(1)
|
||||||
|
|
||||||
vbox = QtGui.QVBoxLayout()
|
vbox = QtGui.QVBoxLayout()
|
||||||
|
vbox.addWidget(splitter)
|
||||||
label = QtGui.QLabel('Not yet implemented!')
|
|
||||||
label.setAlignment(QtCore.Qt.AlignHCenter)
|
|
||||||
vbox.addWidget(label)
|
|
||||||
|
|
||||||
label = QtGui.QLabel('')
|
|
||||||
label.setAlignment(QtCore.Qt.AlignHCenter)
|
|
||||||
vbox.addWidget(label)
|
|
||||||
|
|
||||||
vbox.addLayout(hbox)
|
vbox.addLayout(hbox)
|
||||||
|
|
||||||
self.setLayout(vbox)
|
self.setLayout(vbox)
|
||||||
self.show()
|
self.show()
|
||||||
|
|
||||||
|
def _pane_switch(self, item):
|
||||||
|
"""Switch the visible preference pane."""
|
||||||
|
index = self.list_panes.indexOfTopLevelItem(item)
|
||||||
|
if index >= 0:
|
||||||
|
self.stacked_panes.setCurrentIndex(index)
|
||||||
|
|
||||||
|
def _save_and_close(self):
|
||||||
|
for widget in (self.stacked_panes.widget(i)
|
||||||
|
for i in range(self.stacked_panes.count())):
|
||||||
|
for key, field in widget.fields.items():
|
||||||
|
if isinstance(field, QtGui.QComboBox):
|
||||||
|
text = field.itemText(field.currentIndex())
|
||||||
|
data = field.itemData(field.currentIndex())
|
||||||
|
text = data if data else text
|
||||||
|
elif isinstance(field, QtGui.QCheckBox):
|
||||||
|
text = "on" if field.isChecked() else "off"
|
||||||
|
else:
|
||||||
|
text = field.text()
|
||||||
|
self.config.set(widget.section_name, key, str(text))
|
||||||
|
config.write(self.config)
|
||||||
|
self.parent.apply_preferences()
|
||||||
|
self.close()
|
||||||
|
|
||||||
|
|
||||||
|
class PreferencesNotificationBlock(QtGui.QVBoxLayout):
|
||||||
|
"""Display notification settings with drill down to configure."""
|
||||||
|
def __init__(self, pane, *args):
|
||||||
|
QtGui.QVBoxLayout.__init__(*(self,) + args)
|
||||||
|
self.section = "notifications"
|
||||||
|
self.config = QtGui.QApplication.instance().config
|
||||||
|
self.pane = pane
|
||||||
|
self.stack = QtGui.QStackedWidget()
|
||||||
|
|
||||||
|
self.table = QtGui.QTableWidget()
|
||||||
|
fg_color = self.table.palette().text().color().name()
|
||||||
|
self.action_labels = {
|
||||||
|
"sound": "Play a sound",
|
||||||
|
"message": "Show a message in a popup",
|
||||||
|
"file": "Log to a file",
|
||||||
|
"taskbar": "Mark taskbar entry",
|
||||||
|
"tray": "Mark systray/indicator",
|
||||||
|
"command": "Run a command"}
|
||||||
|
self.action_icons = {
|
||||||
|
"sound": utils.qicon_from_theme("media-playback-start"),
|
||||||
|
"message": utils.qicon_from_theme("dialog-information"),
|
||||||
|
"file": utils.qicon_from_theme("document-export"),
|
||||||
|
"taskbar": utils.qicon_from_theme("weechat"),
|
||||||
|
"tray": utils.qicon_tint("ic_hot", fg_color),
|
||||||
|
"command": utils.qicon_from_theme("system-run")}
|
||||||
|
self.icon_widget_qss = "padding:0;min-height:10px;min-width:16px;"
|
||||||
|
self.table.resizeColumnsToContents()
|
||||||
|
self.table.setColumnCount(2)
|
||||||
|
self.table.resizeRowsToContents()
|
||||||
|
self.table.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
|
||||||
|
self.table.setSelectionMode(QtGui.QAbstractItemView.SingleSelection)
|
||||||
|
self.table.setHorizontalHeaderLabels(["State", "Type"])
|
||||||
|
self.table.horizontalHeader().setStretchLastSection(True)
|
||||||
|
self.table.horizontalHeader().setHighlightSections(False)
|
||||||
|
self.table.verticalHeader().setVisible(False)
|
||||||
|
self.table.setShowGrid(False)
|
||||||
|
self.table.itemSelectionChanged.connect(self._table_row_changed)
|
||||||
|
|
||||||
|
self.buftypes = {}
|
||||||
|
for key, value in config.CONFIG_DEFAULT_NOTIFICATION_OPTIONS:
|
||||||
|
buftype, optkey = key.split(".")
|
||||||
|
if buftype not in self.buftypes:
|
||||||
|
self.buftypes[buftype] = {}
|
||||||
|
self.buftypes[buftype][optkey] = self.config.get(self.section, key)
|
||||||
|
for buftype, optkey in self.buftypes.items():
|
||||||
|
self._insert_type(buftype)
|
||||||
|
self.update_icons()
|
||||||
|
self.resize_table()
|
||||||
|
self.addWidget(self.table)
|
||||||
|
self.addWidget(self.stack)
|
||||||
|
self.table.selectRow(0)
|
||||||
|
|
||||||
|
def _insert_type(self, buftype):
|
||||||
|
row = self.table.rowCount()
|
||||||
|
self.table.insertRow(row)
|
||||||
|
buftype_item = QtGui.QTableWidgetItem(buftype)
|
||||||
|
buftype_item.setTextAlignment(QtCore.Qt.AlignCenter)
|
||||||
|
self.table.setItem(row, 0, QtGui.QTableWidgetItem())
|
||||||
|
self.table.setItem(row, 1, buftype_item)
|
||||||
|
subgrid = QtGui.QGridLayout()
|
||||||
|
subgrid.setColumnStretch(2, 1)
|
||||||
|
subgrid.setSpacing(10)
|
||||||
|
|
||||||
|
for key, qicon in self.action_icons.items():
|
||||||
|
value = self.buftypes[buftype][key]
|
||||||
|
line = subgrid.rowCount()
|
||||||
|
label = IconTextLabel(self.action_labels[key], qicon, 16)
|
||||||
|
|
||||||
|
checkbox = QtGui.QCheckBox()
|
||||||
|
span = 1
|
||||||
|
edit = None
|
||||||
|
if key in ("message", "taskbar", "tray"):
|
||||||
|
checkbox.setChecked(value == "on")
|
||||||
|
span = 2
|
||||||
|
elif key == "sound":
|
||||||
|
edit = PreferencesFileEdit(
|
||||||
|
checkbox=checkbox, caption='Select a sound file',
|
||||||
|
filter='Audio Files (*.wav *.mp3 *.ogg)')
|
||||||
|
elif key == "file":
|
||||||
|
edit = PreferencesFileEdit(checkbox=checkbox, mode="save")
|
||||||
|
else:
|
||||||
|
edit = PreferencesFileEdit(checkbox=checkbox)
|
||||||
|
if edit:
|
||||||
|
edit.insert(value)
|
||||||
|
subgrid.addWidget(edit, line, 2)
|
||||||
|
else:
|
||||||
|
edit = checkbox
|
||||||
|
subgrid.addWidget(label, line, 1, 1, span)
|
||||||
|
subgrid.addWidget(checkbox, line, 0)
|
||||||
|
self.pane.fields[buftype + "." + key] = edit
|
||||||
|
subpane = QtGui.QWidget()
|
||||||
|
subpane.setLayout(subgrid)
|
||||||
|
subpane.setMaximumHeight(subgrid.totalMinimumSize().height())
|
||||||
|
self.stack.addWidget(subpane)
|
||||||
|
|
||||||
|
def resize_table(self):
|
||||||
|
"""Fit the table height to contents."""
|
||||||
|
height = self.table.horizontalHeader().height()
|
||||||
|
height = height * (self.table.rowCount() + 1)
|
||||||
|
height += self.table.contentsMargins().top()
|
||||||
|
height += self.table.contentsMargins().bottom()
|
||||||
|
self.table.setMaximumHeight(height)
|
||||||
|
self.table.setMinimumHeight(height)
|
||||||
|
self.table.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
|
||||||
|
|
||||||
|
def update_icons(self):
|
||||||
|
"""Draw the correct icons in the left col."""
|
||||||
|
for i in range(self.table.rowCount()):
|
||||||
|
hbox = QtGui.QHBoxLayout()
|
||||||
|
iconset = QtGui.QWidget()
|
||||||
|
buftype = self.table.item(i, 1).text()
|
||||||
|
for key, qicon in self.action_icons.items():
|
||||||
|
field = self.pane.fields[buftype + "." + key]
|
||||||
|
if isinstance(field, QtGui.QCheckBox):
|
||||||
|
val = "on" if field.isChecked() else "off"
|
||||||
|
else:
|
||||||
|
val = field.text()
|
||||||
|
iconbtn = QtGui.QPushButton()
|
||||||
|
iconbtn.setContentsMargins(0, 0, 0, 0)
|
||||||
|
iconbtn.setFlat(True)
|
||||||
|
iconbtn.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
if val and val != "off":
|
||||||
|
iconbtn.setIcon(qicon)
|
||||||
|
iconbtn.setStyleSheet(self.icon_widget_qss)
|
||||||
|
iconbtn.setToolTip(key)
|
||||||
|
iconbtn.clicked.connect(lambda i=i: self.table.selectRow(i))
|
||||||
|
hbox.addWidget(iconbtn)
|
||||||
|
iconset.setLayout(hbox)
|
||||||
|
self.table.setCellWidget(i, 0, iconset)
|
||||||
|
|
||||||
|
def _table_row_changed(self):
|
||||||
|
row = self.table.selectionModel().selectedRows()[0].row()
|
||||||
|
self.stack.setCurrentIndex(row)
|
||||||
|
|
||||||
|
|
||||||
|
class PreferencesTreeWidget(QtGui.QTreeWidget):
|
||||||
|
"""Widget with tree list of preferences."""
|
||||||
|
def __init__(self, header_label, *args):
|
||||||
|
QtGui.QTreeWidget.__init__(*(self,) + args)
|
||||||
|
self.setHeaderLabel(header_label)
|
||||||
|
self.setRootIsDecorated(False)
|
||||||
|
self.setMaximumWidth(180)
|
||||||
|
self.setTextElideMode(QtCore.Qt.ElideNone)
|
||||||
|
self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
|
||||||
|
self.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||||
|
|
||||||
|
|
||||||
|
class PreferencesSliderEdit(QtGui.QSlider):
|
||||||
|
"""Percentage slider."""
|
||||||
|
def __init__(self, *args):
|
||||||
|
QtGui.QSlider.__init__(*(self,) + args)
|
||||||
|
self.setMinimum(0)
|
||||||
|
self.setMaximum(100)
|
||||||
|
self.setTickPosition(QtGui.QSlider.TicksBelow)
|
||||||
|
self.setTickInterval(5)
|
||||||
|
|
||||||
|
def insert(self, percent):
|
||||||
|
self.setValue(int(percent[:-1]))
|
||||||
|
|
||||||
|
def text(self):
|
||||||
|
return str(self.value()) + "%"
|
||||||
|
|
||||||
|
|
||||||
|
class PreferencesColorEdit(QtGui.QPushButton):
|
||||||
|
"""Simple color square that changes based on the color selected."""
|
||||||
|
def __init__(self, *args):
|
||||||
|
QtGui.QPushButton.__init__(*(self,) + args)
|
||||||
|
self.color = "#000000"
|
||||||
|
self.clicked.connect(self._color_picker)
|
||||||
|
# Some of the configured colors use a astrisk prefix.
|
||||||
|
# Toggle this on right click.
|
||||||
|
self.star = False
|
||||||
|
self.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
|
||||||
|
self.customContextMenuRequested.connect(self._color_star)
|
||||||
|
|
||||||
|
def insert(self, color):
|
||||||
|
"""Insert the desired color for the widget."""
|
||||||
|
if color[:1] == "*":
|
||||||
|
self.star = True
|
||||||
|
color = color[1:]
|
||||||
|
self.setText("*" if self.star else "")
|
||||||
|
self.color = color
|
||||||
|
self.setStyleSheet("background-color: " + color)
|
||||||
|
|
||||||
|
def text(self):
|
||||||
|
"""Returns the hex value of the color."""
|
||||||
|
return ("*" if self.star else "") + self.color
|
||||||
|
|
||||||
|
def _color_picker(self):
|
||||||
|
color = QtGui.QColorDialog.getColor(self.color)
|
||||||
|
self.insert(color.name())
|
||||||
|
|
||||||
|
def _color_star(self):
|
||||||
|
self.star = not self.star
|
||||||
|
self.insert(self.text())
|
||||||
|
|
||||||
|
|
||||||
|
class PreferencesFontEdit(QtGui.QWidget):
|
||||||
|
"""Font entry and selection."""
|
||||||
|
def __init__(self, *args):
|
||||||
|
QtGui.QWidget.__init__(*(self,) + args)
|
||||||
|
layout = QtGui.QHBoxLayout()
|
||||||
|
self.checkbox = QtGui.QCheckBox()
|
||||||
|
self.edit = QtGui.QLineEdit()
|
||||||
|
self.font = ""
|
||||||
|
self.qfont = None
|
||||||
|
self.button = QtGui.QPushButton("C&hoose")
|
||||||
|
self.button.clicked.connect(self._font_picker)
|
||||||
|
self.checkbox.toggled.connect(
|
||||||
|
lambda: self._checkbox_toggled(self.checkbox))
|
||||||
|
layout.addWidget(self.checkbox)
|
||||||
|
layout.addWidget(self.edit)
|
||||||
|
layout.addWidget(self.button)
|
||||||
|
layout.setContentsMargins(0, 0, 0, 0)
|
||||||
|
self.setLayout(layout)
|
||||||
|
|
||||||
|
def insert(self, font_str):
|
||||||
|
"""Insert the font described by the string."""
|
||||||
|
self.font = font_str
|
||||||
|
self.edit.insert(font_str)
|
||||||
|
if font_str:
|
||||||
|
self.qfont = utils.Font.str_to_qfont(font_str)
|
||||||
|
self.edit.setFont(self.qfont)
|
||||||
|
self.checkbox.setChecked(True)
|
||||||
|
self._checkbox_toggled(self.checkbox)
|
||||||
|
else:
|
||||||
|
self.checkbox.setChecked(False)
|
||||||
|
self.qfont = None
|
||||||
|
self._checkbox_toggled(self.checkbox)
|
||||||
|
|
||||||
|
def text(self):
|
||||||
|
"""Returns the human readable font string."""
|
||||||
|
return self.font
|
||||||
|
|
||||||
|
def _font_picker(self):
|
||||||
|
font, ok = QtGui.QFontDialog.getFont(self.qfont)
|
||||||
|
if ok:
|
||||||
|
self.insert(utils.Font.qfont_to_str(font))
|
||||||
|
|
||||||
|
def _checkbox_toggled(self, button):
|
||||||
|
if button.isChecked() is False and not self.font == "":
|
||||||
|
self.insert("")
|
||||||
|
self.edit.setEnabled(button.isChecked())
|
||||||
|
self.button.setEnabled(button.isChecked())
|
||||||
|
|
||||||
|
|
||||||
|
class PreferencesFileEdit(QtGui.QWidget):
|
||||||
|
"""File entry and selection."""
|
||||||
|
def __init__(self, checkbox=None, caption="Select a file", filter=None,
|
||||||
|
mode="open", *args):
|
||||||
|
QtGui.QWidget.__init__(*(self,) + args)
|
||||||
|
layout = QtGui.QHBoxLayout()
|
||||||
|
self.caption = caption
|
||||||
|
self.filter = filter
|
||||||
|
self.edit = QtGui.QLineEdit()
|
||||||
|
self.file_str = ""
|
||||||
|
self.mode = mode
|
||||||
|
self.button = QtGui.QPushButton("B&rowse")
|
||||||
|
self.button.clicked.connect(self._file_picker)
|
||||||
|
if checkbox:
|
||||||
|
self.checkbox = checkbox
|
||||||
|
else:
|
||||||
|
self.checkbox = QtGui.QCheckBox()
|
||||||
|
layout.addWidget(self.checkbox)
|
||||||
|
self.checkbox.toggled.connect(
|
||||||
|
lambda: self._checkbox_toggled(self.checkbox))
|
||||||
|
layout.addWidget(self.edit)
|
||||||
|
layout.addWidget(self.button)
|
||||||
|
layout.setContentsMargins(0, 0, 0, 0)
|
||||||
|
self.setLayout(layout)
|
||||||
|
|
||||||
|
def insert(self, file_str):
|
||||||
|
"""Insert the file."""
|
||||||
|
self.file_str = file_str
|
||||||
|
self.edit.insert(file_str)
|
||||||
|
if file_str:
|
||||||
|
self.checkbox.setChecked(True)
|
||||||
|
self._checkbox_toggled(self.checkbox)
|
||||||
|
else:
|
||||||
|
self.checkbox.setChecked(False)
|
||||||
|
self._checkbox_toggled(self.checkbox)
|
||||||
|
|
||||||
|
def text(self):
|
||||||
|
"""Returns the human readable font string."""
|
||||||
|
return self.file_str
|
||||||
|
|
||||||
|
def _file_picker(self):
|
||||||
|
path = ""
|
||||||
|
if self.mode == "save":
|
||||||
|
fn = QtGui.QFileDialog.getSaveFileName
|
||||||
|
else:
|
||||||
|
fn = QtGui.QFileDialog.getOpenFileName
|
||||||
|
filename, fil = fn(self, self.caption, path, self.filter, self.filter)
|
||||||
|
if filename:
|
||||||
|
self.insert(filename)
|
||||||
|
|
||||||
|
def _checkbox_toggled(self, button):
|
||||||
|
if button.isChecked() is False and not self.file_str == "":
|
||||||
|
self.insert("")
|
||||||
|
self.edit.setEnabled(button.isChecked())
|
||||||
|
self.button.setEnabled(button.isChecked())
|
||||||
|
|
||||||
|
|
||||||
|
class PreferencesPaneWidget(QtGui.QWidget):
|
||||||
|
"""
|
||||||
|
Widget with (from top to bottom):
|
||||||
|
title, chat + nicklist (optional) + prompt/input.
|
||||||
|
"""
|
||||||
|
|
||||||
|
disabled_fields = ["show_hostnames", "hide_nick_changes",
|
||||||
|
"hide_join_and_part"]
|
||||||
|
|
||||||
|
def __init__(self, section, section_name):
|
||||||
|
QtGui.QWidget.__init__(self)
|
||||||
|
self.grid = QtGui.QGridLayout()
|
||||||
|
self.grid.setAlignment(QtCore.Qt.AlignTop)
|
||||||
|
self.section = section
|
||||||
|
self.section_name = section_name
|
||||||
|
self.fields = {}
|
||||||
|
self.setLayout(self.grid)
|
||||||
|
self.grid.setColumnStretch(2, 1)
|
||||||
|
self.grid.setSpacing(10)
|
||||||
|
self.int_validator = QtGui.QIntValidator(0, 2147483647, self)
|
||||||
|
toolbar_icons = [
|
||||||
|
('ToolButtonFollowStyle', 'Default'),
|
||||||
|
('ToolButtonIconOnly', 'Icon Only'),
|
||||||
|
('ToolButtonTextOnly', 'Text Only'),
|
||||||
|
('ToolButtonTextBesideIcon', 'Text Alongside Icons'),
|
||||||
|
('ToolButtonTextUnderIcon', 'Text Under Icons')]
|
||||||
|
tray_options = [
|
||||||
|
('always', 'Always'),
|
||||||
|
('unread', 'On Unread Messages'),
|
||||||
|
('never', 'Never'),
|
||||||
|
]
|
||||||
|
list_positions = [
|
||||||
|
('left', 'Left'),
|
||||||
|
('right', 'Right'),
|
||||||
|
]
|
||||||
|
sort_options = ['A-Z Ranked', 'A-Z', 'Z-A Ranked', 'Z-A']
|
||||||
|
spellcheck_langs = [(x, x) for x in
|
||||||
|
InputLineSpell.list_languages()]
|
||||||
|
spellcheck_langs.insert(0, ('', ''))
|
||||||
|
focus_opts = ["requested", "always", "never"]
|
||||||
|
self.comboboxes = {"style": QtGui.QStyleFactory.keys(),
|
||||||
|
"position": list_positions,
|
||||||
|
"toolbar_icons": toolbar_icons,
|
||||||
|
"focus_new_tabs": focus_opts,
|
||||||
|
"tray_icon": tray_options,
|
||||||
|
"sort": sort_options,
|
||||||
|
"spellcheck_dictionary": spellcheck_langs}
|
||||||
|
|
||||||
|
def addItem(self, key, value, default):
|
||||||
|
"""Add a key-value pair."""
|
||||||
|
line = len(self.fields)
|
||||||
|
name = key.split(".")[-1:][0].capitalize().replace("_", " ")
|
||||||
|
label = QtGui.QLabel(name)
|
||||||
|
start = 0
|
||||||
|
|
||||||
|
if self.section == "color":
|
||||||
|
start = 2 * (line % 2)
|
||||||
|
line = line // 2
|
||||||
|
edit = PreferencesColorEdit()
|
||||||
|
edit.setFixedWidth(edit.sizeHint().height())
|
||||||
|
edit.insert(value)
|
||||||
|
label.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
||||||
|
elif key == "custom_stylesheet":
|
||||||
|
edit = PreferencesFileEdit(caption='Select QStyleSheet File',
|
||||||
|
filter='*.qss')
|
||||||
|
edit.insert(value)
|
||||||
|
elif name.lower()[-5:] == "sound":
|
||||||
|
edit = PreferencesFileEdit(
|
||||||
|
caption='Select a sound file',
|
||||||
|
filter='Audio Files (*.wav *.mp3 *.ogg)')
|
||||||
|
edit.insert(value)
|
||||||
|
elif name.lower()[-4:] == "font":
|
||||||
|
edit = PreferencesFontEdit()
|
||||||
|
edit.setFixedWidth(200)
|
||||||
|
edit.insert(value)
|
||||||
|
elif key in self.comboboxes.keys():
|
||||||
|
edit = QtGui.QComboBox()
|
||||||
|
if len(self.comboboxes[key][0]) == 2:
|
||||||
|
for keyvalue in self.comboboxes[key]:
|
||||||
|
edit.addItem(keyvalue[1], keyvalue[0])
|
||||||
|
# if self.section == "nicks" and key == "position":
|
||||||
|
# edit.addItem("below", "Below Buffer List")
|
||||||
|
# edit.addItem("above", "Above Buffer List")
|
||||||
|
edit.setCurrentIndex(edit.findData(value))
|
||||||
|
else:
|
||||||
|
edit.addItems(self.comboboxes[key])
|
||||||
|
edit.setCurrentIndex(edit.findText(value))
|
||||||
|
edit.setFixedWidth(200)
|
||||||
|
elif default in ["on", "off"]:
|
||||||
|
edit = QtGui.QCheckBox()
|
||||||
|
edit.setChecked(value == "on")
|
||||||
|
elif default[-1:] == "%":
|
||||||
|
edit = PreferencesSliderEdit(QtCore.Qt.Horizontal)
|
||||||
|
edit.setFixedWidth(200)
|
||||||
|
edit.insert(value)
|
||||||
|
else:
|
||||||
|
edit = QtGui.QLineEdit()
|
||||||
|
edit.setFixedWidth(200)
|
||||||
|
edit.insert(value)
|
||||||
|
if default.isdigit() or key == "port":
|
||||||
|
edit.setValidator(self.int_validator)
|
||||||
|
if key == 'password':
|
||||||
|
edit.setEchoMode(QtGui.QLineEdit.Password)
|
||||||
|
if key in self.disabled_fields:
|
||||||
|
edit.setDisabled(True)
|
||||||
|
self.grid.addWidget(label, line, start + 0)
|
||||||
|
self.grid.addWidget(edit, line, start + 1)
|
||||||
|
|
||||||
|
self.fields[key] = edit
|
||||||
|
|
||||||
|
|
||||||
|
class IconTextLabel(QtGui.QWidget):
|
||||||
|
"""An icon next to text."""
|
||||||
|
def __init__(self, text=None, icon=None, extent=None):
|
||||||
|
QtGui.QWidget.__init__(self)
|
||||||
|
text_label = QtGui.QLabel(text)
|
||||||
|
if not extent:
|
||||||
|
extent = text_label.height()
|
||||||
|
icon_label = QtGui.QLabel()
|
||||||
|
pixmap = icon.pixmap(extent, QtGui.QIcon.Normal, QtGui.QIcon.On)
|
||||||
|
icon_label.setPixmap(pixmap)
|
||||||
|
label_layout = QtGui.QHBoxLayout()
|
||||||
|
label_layout.addWidget(icon_label)
|
||||||
|
label_layout.addWidget(text_label)
|
||||||
|
label_layout.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
|
||||||
|
self.setLayout(label_layout)
|
||||||
|
|
57
toxygen/third_party/qweechat/preferences.py.bak
vendored
Normal file
57
toxygen/third_party/qweechat/preferences.py.bak
vendored
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# preferences.py - preferences dialog box
|
||||||
|
#
|
||||||
|
# Copyright (C) 2011-2022 Sébastien Helleu <flashcode@flashtux.org>
|
||||||
|
#
|
||||||
|
# This file is part of QWeeChat, a Qt remote GUI for WeeChat.
|
||||||
|
#
|
||||||
|
# QWeeChat is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# QWeeChat is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with QWeeChat. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
"""Preferences dialog box."""
|
||||||
|
|
||||||
|
from qtpy import QtCore, QtGui
|
||||||
|
|
||||||
|
|
||||||
|
class PreferencesDialog(QtGui.QDialog):
|
||||||
|
"""Preferences dialog."""
|
||||||
|
|
||||||
|
def __init__(self, *args):
|
||||||
|
QtGui.QDialog.__init__(*(self,) + args)
|
||||||
|
self.setModal(True)
|
||||||
|
self.setWindowTitle('Preferences')
|
||||||
|
|
||||||
|
close_button = QtGui.QPushButton('Close')
|
||||||
|
close_button.pressed.connect(self.close)
|
||||||
|
|
||||||
|
hbox = QtGui.QHBoxLayout()
|
||||||
|
hbox.addStretch(1)
|
||||||
|
hbox.addWidget(close_button)
|
||||||
|
hbox.addStretch(1)
|
||||||
|
|
||||||
|
vbox = QtGui.QVBoxLayout()
|
||||||
|
|
||||||
|
label = QtGui.QLabel('Not yet implemented!')
|
||||||
|
label.setAlignment(QtCore.Qt.AlignHCenter)
|
||||||
|
vbox.addWidget(label)
|
||||||
|
|
||||||
|
label = QtGui.QLabel('')
|
||||||
|
label.setAlignment(QtCore.Qt.AlignHCenter)
|
||||||
|
vbox.addWidget(label)
|
||||||
|
|
||||||
|
vbox.addLayout(hbox)
|
||||||
|
|
||||||
|
self.setLayout(vbox)
|
||||||
|
self.show()
|
69
toxygen/third_party/qweechat/qweechat.py
vendored
69
toxygen/third_party/qweechat/qweechat.py
vendored
|
@ -39,13 +39,13 @@ from pkg_resources import resource_filename
|
||||||
|
|
||||||
from qtpy import QtCore, QtGui, QtWidgets
|
from qtpy import QtCore, QtGui, QtWidgets
|
||||||
|
|
||||||
from third_party.qweechat import config
|
from qweechat import config
|
||||||
from third_party.qweechat.about import AboutDialog
|
from qweechat.about import AboutDialog
|
||||||
from third_party.qweechat.buffer import BufferListWidget, Buffer
|
from qweechat.buffer import BufferListWidget, Buffer
|
||||||
from third_party.qweechat.connection import ConnectionDialog
|
from qweechat.connection import ConnectionDialog
|
||||||
from third_party.qweechat.network import Network, STATUS_DISCONNECTED
|
from qweechat.network import Network, STATUS_DISCONNECTED
|
||||||
from third_party.qweechat.preferences import PreferencesDialog
|
from qweechat.preferences import PreferencesDialog
|
||||||
from third_party.qweechat.weechat import protocol
|
from qweechat.weechat import protocol
|
||||||
|
|
||||||
|
|
||||||
APP_NAME = 'QWeeChat'
|
APP_NAME = 'QWeeChat'
|
||||||
|
@ -163,13 +163,6 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||||
self.actions['quit']])
|
self.actions['quit']])
|
||||||
menu_window = self.menu.addMenu('&Window')
|
menu_window = self.menu.addMenu('&Window')
|
||||||
menu_window.addAction(self.actions['debug'])
|
menu_window.addAction(self.actions['debug'])
|
||||||
name = 'toggle'
|
|
||||||
menu_window.addAction(
|
|
||||||
QtWidgets.QAction(QtGui.QIcon(
|
|
||||||
resource_filename(__name__, 'data/icons/%s' % 'weechat.png')),
|
|
||||||
name.capitalize(), self))
|
|
||||||
#? .triggered.connect(self.onMyToolBarButtonClick)
|
|
||||||
|
|
||||||
menu_help = self.menu.addMenu('&Help')
|
menu_help = self.menu.addMenu('&Help')
|
||||||
menu_help.addAction(self.actions['about'])
|
menu_help.addAction(self.actions['about'])
|
||||||
self.network_status = QtWidgets.QLabel()
|
self.network_status = QtWidgets.QLabel()
|
||||||
|
@ -177,21 +170,23 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||||
self.network_status.setFixedWidth(200)
|
self.network_status.setFixedWidth(200)
|
||||||
self.network_status.setContentsMargins(0, 0, 10, 0)
|
self.network_status.setContentsMargins(0, 0, 10, 0)
|
||||||
self.network_status.setAlignment(QtCore.Qt.AlignRight)
|
self.network_status.setAlignment(QtCore.Qt.AlignRight)
|
||||||
if hasattr(self.menu, 'setCornerWidget'):
|
if hasattr(self, 'menuBar'):
|
||||||
self.menu.setCornerWidget(self.network_status,
|
if hasattr(self.menu, 'setCornerWidget'):
|
||||||
QtCore.Qt.TopRightCorner)
|
self.menu.setCornerWidget(self.network_status,
|
||||||
|
QtCore.Qt.TopRightCorner)
|
||||||
self.network_status_set(STATUS_DISCONNECTED)
|
self.network_status_set(STATUS_DISCONNECTED)
|
||||||
|
|
||||||
# toolbar
|
# toolbar
|
||||||
toolbar = self.addToolBar('toolBar')
|
if hasattr(self, 'addToolBar'):
|
||||||
toolbar.setToolButtonStyle(QtCore.Qt.ToolButtonTextUnderIcon)
|
toolbar = self.addToolBar('toolBar')
|
||||||
toolbar.addActions([self.actions['connect'],
|
toolbar.setToolButtonStyle(QtCore.Qt.ToolButtonTextUnderIcon)
|
||||||
self.actions['disconnect'],
|
toolbar.addActions([self.actions['connect'],
|
||||||
self.actions['debug'],
|
self.actions['disconnect'],
|
||||||
self.actions['preferences'],
|
self.actions['debug'],
|
||||||
self.actions['about'],
|
self.actions['preferences'],
|
||||||
self.actions['quit']])
|
self.actions['about'],
|
||||||
self.toolbar = toolbar
|
self.actions['quit']])
|
||||||
|
|
||||||
self.buffers[0].widget.input.setFocus()
|
self.buffers[0].widget.input.setFocus()
|
||||||
|
|
||||||
# open debug dialog
|
# open debug dialog
|
||||||
|
@ -203,9 +198,9 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||||
self.network.connect_weechat(
|
self.network.connect_weechat(
|
||||||
hostname=self.config.get('relay', 'hostname', fallback='127.0.0.1'),
|
hostname=self.config.get('relay', 'hostname', fallback='127.0.0.1'),
|
||||||
port=self.config.get('relay', 'port', fallback='9000'),
|
port=self.config.get('relay', 'port', fallback='9000'),
|
||||||
ssl=self.config.getboolean('relay', 'ssl', fallback=False),
|
ssl=self.config.getboolean('relay', 'ssl', fallback=''),
|
||||||
password=self.config.get('relay', 'password', fallback=''),
|
password=self.config.get('relay', 'password', fallback=''),
|
||||||
totp=self.config.get('relay', 'password', fallback=''),
|
totp=None,
|
||||||
lines=self.config.get('relay', 'lines', fallback=''),
|
lines=self.config.get('relay', 'lines', fallback=''),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -244,10 +239,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||||
"""Open a dialog with connection settings."""
|
"""Open a dialog with connection settings."""
|
||||||
values = {}
|
values = {}
|
||||||
for option in ('hostname', 'port', 'ssl', 'password', 'lines'):
|
for option in ('hostname', 'port', 'ssl', 'password', 'lines'):
|
||||||
val = self.config.get('relay', option, fallback='')
|
values[option] = self.config.get('relay', option, fallback='')
|
||||||
if val in [None, 'None']: val = ''
|
|
||||||
if option == 'port' and val in [None, 'None']: val = 0
|
|
||||||
values[option] = val
|
|
||||||
self.connection_dialog = ConnectionDialog(values, self)
|
self.connection_dialog = ConnectionDialog(values, self)
|
||||||
self.connection_dialog.dialog_buttons.accepted.connect(
|
self.connection_dialog.dialog_buttons.accepted.connect(
|
||||||
self.connect_weechat)
|
self.connect_weechat)
|
||||||
|
@ -262,13 +254,6 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||||
totp=self.connection_dialog.fields['totp'].text(),
|
totp=self.connection_dialog.fields['totp'].text(),
|
||||||
lines=int(self.connection_dialog.fields['lines'].text()),
|
lines=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()
|
|
||||||
self.config.set('relay', 'port', port)
|
|
||||||
self.config.set('relay', 'hostname', hostname)
|
|
||||||
self.config.set('relay', 'password', password)
|
|
||||||
self.connection_dialog.close()
|
self.connection_dialog.close()
|
||||||
|
|
||||||
def _network_status_changed(self, status, extra):
|
def _network_status_changed(self, status, extra):
|
||||||
|
@ -536,10 +521,10 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||||
if next_buffer == '0x0':
|
if next_buffer == '0x0':
|
||||||
index = len(self.buffers)
|
index = len(self.buffers)
|
||||||
else:
|
else:
|
||||||
elts = [i for i, b in enumerate(self.buffers)
|
index = [i for i, b in enumerate(self.buffers)
|
||||||
if b.pointer() == next_buffer]
|
if b.pointer() == next_buffer]
|
||||||
if len(elts):
|
if index:
|
||||||
index = elts[0]
|
index = index[0]
|
||||||
if index < 0:
|
if index < 0:
|
||||||
print('Warning: unable to find position for buffer, using end of '
|
print('Warning: unable to find position for buffer, using end of '
|
||||||
'list by default')
|
'list by default')
|
||||||
|
|
569
toxygen/third_party/qweechat/qweechat.py.bak
vendored
Normal file
569
toxygen/third_party/qweechat/qweechat.py.bak
vendored
Normal file
|
@ -0,0 +1,569 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# qweechat.py - WeeChat remote GUI using Qt toolkit
|
||||||
|
#
|
||||||
|
# Copyright (C) 2011-2022 Sébastien Helleu <flashcode@flashtux.org>
|
||||||
|
#
|
||||||
|
# This file is part of QWeeChat, a Qt remote GUI for WeeChat.
|
||||||
|
#
|
||||||
|
# QWeeChat is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# QWeeChat is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with QWeeChat. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
"""
|
||||||
|
QWeeChat is a WeeChat remote GUI using Qt toolkit.
|
||||||
|
|
||||||
|
It requires requires WeeChat 0.3.7 or newer, running on local or remote host.
|
||||||
|
"""
|
||||||
|
|
||||||
|
#
|
||||||
|
# History:
|
||||||
|
#
|
||||||
|
# 2011-05-27, Sébastien Helleu <flashcode@flashtux.org>:
|
||||||
|
# start dev
|
||||||
|
#
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import traceback
|
||||||
|
from pkg_resources import resource_filename
|
||||||
|
|
||||||
|
from qtpy import QtCore, QtGui, QtWidgets
|
||||||
|
|
||||||
|
from qweechat import config
|
||||||
|
from qweechat.about import AboutDialog
|
||||||
|
from qweechat.buffer import BufferListWidget, Buffer
|
||||||
|
from qweechat.connection import ConnectionDialog
|
||||||
|
from qweechat.network import Network, STATUS_DISCONNECTED
|
||||||
|
from qweechat.preferences import PreferencesDialog
|
||||||
|
from qweechat.weechat import protocol
|
||||||
|
|
||||||
|
|
||||||
|
APP_NAME = 'QWeeChat'
|
||||||
|
AUTHOR = 'Sébastien Helleu'
|
||||||
|
WEECHAT_SITE = 'https://weechat.org/'
|
||||||
|
|
||||||
|
# not QFrame
|
||||||
|
class MainWindow(QtWidgets.QMainWindow):
|
||||||
|
"""Main window."""
|
||||||
|
|
||||||
|
def __init__(self, *args):
|
||||||
|
super().__init__(*args)
|
||||||
|
|
||||||
|
self.config = config.read()
|
||||||
|
|
||||||
|
self.resize(1000, 600)
|
||||||
|
self.setWindowTitle(APP_NAME)
|
||||||
|
|
||||||
|
self.about_dialog = None
|
||||||
|
self.connection_dialog = None
|
||||||
|
self.preferences_dialog = None
|
||||||
|
|
||||||
|
# network
|
||||||
|
self.network = Network()
|
||||||
|
self.network.statusChanged.connect(self._network_status_changed)
|
||||||
|
self.network.messageFromWeechat.connect(self._network_weechat_msg)
|
||||||
|
|
||||||
|
# list of buffers
|
||||||
|
self.list_buffers = BufferListWidget()
|
||||||
|
self.list_buffers.currentRowChanged.connect(self._buffer_switch)
|
||||||
|
|
||||||
|
# default buffer
|
||||||
|
self.buffers = [Buffer()]
|
||||||
|
self.stacked_buffers = QtWidgets.QStackedWidget()
|
||||||
|
self.stacked_buffers.addWidget(self.buffers[0].widget)
|
||||||
|
|
||||||
|
# splitter with buffers + chat/input
|
||||||
|
splitter = QtWidgets.QSplitter()
|
||||||
|
splitter.addWidget(self.list_buffers)
|
||||||
|
splitter.addWidget(self.stacked_buffers)
|
||||||
|
|
||||||
|
self.list_buffers.setSizePolicy(QtWidgets.QSizePolicy.Preferred,
|
||||||
|
QtWidgets.QSizePolicy.Preferred)
|
||||||
|
self.stacked_buffers.setSizePolicy(QtWidgets.QSizePolicy.Expanding,
|
||||||
|
QtWidgets.QSizePolicy.Expanding)
|
||||||
|
# MainWindow
|
||||||
|
self.setCentralWidget(splitter)
|
||||||
|
|
||||||
|
if self.config.getboolean('look', 'statusbar'):
|
||||||
|
self.statusBar().visible = True
|
||||||
|
self.statusBar().visible = True
|
||||||
|
|
||||||
|
# actions for menu and toolbar
|
||||||
|
actions_def = {
|
||||||
|
'connect': [
|
||||||
|
'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,
|
||||||
|
],
|
||||||
|
'debug': [
|
||||||
|
'edit-find.png',
|
||||||
|
'Open debug console window',
|
||||||
|
'Ctrl+B',
|
||||||
|
self.network.open_debug_dialog,
|
||||||
|
],
|
||||||
|
'preferences': [
|
||||||
|
'preferences-other.png',
|
||||||
|
'Change preferences',
|
||||||
|
'Ctrl+P',
|
||||||
|
self.open_preferences_dialog,
|
||||||
|
],
|
||||||
|
'about': [
|
||||||
|
'help-about.png',
|
||||||
|
'About QWeeChat',
|
||||||
|
'Ctrl+H',
|
||||||
|
self.open_about_dialog,
|
||||||
|
],
|
||||||
|
'save connection': [
|
||||||
|
'document-save.png',
|
||||||
|
'Save connection configuration',
|
||||||
|
'Ctrl+S',
|
||||||
|
self.save_connection,
|
||||||
|
],
|
||||||
|
'quit': [
|
||||||
|
'application-exit.png',
|
||||||
|
'Quit application',
|
||||||
|
'Ctrl+Q',
|
||||||
|
self.close,
|
||||||
|
],
|
||||||
|
}
|
||||||
|
self.actions = {}
|
||||||
|
for name, action in list(actions_def.items()):
|
||||||
|
self.actions[name] = QtWidgets.QAction(
|
||||||
|
QtGui.QIcon(
|
||||||
|
resource_filename(__name__, 'data/icons/%s' % action[0])),
|
||||||
|
name.capitalize(), self)
|
||||||
|
self.actions[name].setToolTip(f'{action[1]} ({action[2]})')
|
||||||
|
self.actions[name].setShortcut(action[2])
|
||||||
|
self.actions[name].triggered.connect(action[3])
|
||||||
|
|
||||||
|
# menu
|
||||||
|
self.menu = self.menuBar()
|
||||||
|
menu_file = self.menu.addMenu('&File')
|
||||||
|
menu_file.addActions([self.actions['connect'],
|
||||||
|
self.actions['disconnect'],
|
||||||
|
self.actions['preferences'],
|
||||||
|
self.actions['save connection'],
|
||||||
|
self.actions['quit']])
|
||||||
|
menu_window = self.menu.addMenu('&Window')
|
||||||
|
menu_window.addAction(self.actions['debug'])
|
||||||
|
name = 'toggle'
|
||||||
|
menu_window.addAction(
|
||||||
|
QtWidgets.QAction(QtGui.QIcon(
|
||||||
|
resource_filename(__name__, 'data/icons/%s' % 'weechat.png')),
|
||||||
|
name.capitalize(), self))
|
||||||
|
#? .triggered.connect(self.onMyToolBarButtonClick)
|
||||||
|
|
||||||
|
menu_help = self.menu.addMenu('&Help')
|
||||||
|
menu_help.addAction(self.actions['about'])
|
||||||
|
self.network_status = QtWidgets.QLabel()
|
||||||
|
self.network_status.setFixedHeight(20)
|
||||||
|
self.network_status.setFixedWidth(200)
|
||||||
|
self.network_status.setContentsMargins(0, 0, 10, 0)
|
||||||
|
self.network_status.setAlignment(QtCore.Qt.AlignRight)
|
||||||
|
if hasattr(self.menu, 'setCornerWidget'):
|
||||||
|
self.menu.setCornerWidget(self.network_status,
|
||||||
|
QtCore.Qt.TopRightCorner)
|
||||||
|
self.network_status_set(STATUS_DISCONNECTED)
|
||||||
|
|
||||||
|
# toolbar
|
||||||
|
toolbar = self.addToolBar('toolBar')
|
||||||
|
toolbar.setToolButtonStyle(QtCore.Qt.ToolButtonTextUnderIcon)
|
||||||
|
toolbar.addActions([self.actions['connect'],
|
||||||
|
self.actions['disconnect'],
|
||||||
|
self.actions['debug'],
|
||||||
|
self.actions['preferences'],
|
||||||
|
self.actions['about'],
|
||||||
|
self.actions['quit']])
|
||||||
|
self.toolbar = toolbar
|
||||||
|
self.buffers[0].widget.input.setFocus()
|
||||||
|
|
||||||
|
# open debug dialog
|
||||||
|
if self.config.getboolean('look', 'debug'):
|
||||||
|
self.network.open_debug_dialog()
|
||||||
|
|
||||||
|
# auto-connect to relay
|
||||||
|
if self.config.getboolean('relay', 'autoconnect'):
|
||||||
|
self.network.connect_weechat(
|
||||||
|
hostname=self.config.get('relay', 'hostname', fallback='127.0.0.1'),
|
||||||
|
port=self.config.get('relay', 'port', fallback='9000'),
|
||||||
|
ssl=self.config.getboolean('relay', 'ssl', fallback=False),
|
||||||
|
password=self.config.get('relay', 'password', fallback=''),
|
||||||
|
totp=self.config.get('relay', 'password', fallback=''),
|
||||||
|
lines=self.config.get('relay', 'lines', fallback=''),
|
||||||
|
)
|
||||||
|
|
||||||
|
self.show()
|
||||||
|
|
||||||
|
def _buffer_switch(self, index):
|
||||||
|
"""Switch to a buffer."""
|
||||||
|
if index >= 0:
|
||||||
|
self.stacked_buffers.setCurrentIndex(index)
|
||||||
|
self.stacked_buffers.widget(index).input.setFocus()
|
||||||
|
|
||||||
|
def buffer_input(self, full_name, text):
|
||||||
|
"""Send buffer input to WeeChat."""
|
||||||
|
if self.network.is_connected():
|
||||||
|
message = 'input %s %s\n' % (full_name, text)
|
||||||
|
self.network.send_to_weechat(message)
|
||||||
|
self.network.debug_print(0, '<==', message, forcecolor='#AA0000')
|
||||||
|
|
||||||
|
def open_preferences_dialog(self):
|
||||||
|
"""Open a dialog with preferences."""
|
||||||
|
# TODO: implement the preferences dialog box
|
||||||
|
self.preferences_dialog = PreferencesDialog(self)
|
||||||
|
|
||||||
|
def save_connection(self):
|
||||||
|
"""Save connection configuration."""
|
||||||
|
if self.network:
|
||||||
|
options = self.network.get_options()
|
||||||
|
for option in options:
|
||||||
|
self.config.set('relay', option, options[option])
|
||||||
|
|
||||||
|
def open_about_dialog(self):
|
||||||
|
"""Open a dialog with info about QWeeChat."""
|
||||||
|
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 ('hostname', 'port', 'ssl', 'password', 'lines'):
|
||||||
|
val = self.config.get('relay', option, fallback='')
|
||||||
|
if val in [None, 'None']: val = ''
|
||||||
|
if option == 'port' and val in [None, 'None']: val = 0
|
||||||
|
values[option] = val
|
||||||
|
self.connection_dialog = ConnectionDialog(values, self)
|
||||||
|
self.connection_dialog.dialog_buttons.accepted.connect(
|
||||||
|
self.connect_weechat)
|
||||||
|
|
||||||
|
def connect_weechat(self):
|
||||||
|
"""Connect to WeeChat."""
|
||||||
|
self.network.connect_weechat(
|
||||||
|
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()),
|
||||||
|
)
|
||||||
|
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()
|
||||||
|
self.config.set('relay', 'port', port)
|
||||||
|
self.config.set('relay', 'hostname', hostname)
|
||||||
|
self.config.set('relay', 'password', password)
|
||||||
|
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.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()
|
||||||
|
try:
|
||||||
|
pal.setColor(self.network_status.foregroundRole(),
|
||||||
|
self.network.status_color(status))
|
||||||
|
except:
|
||||||
|
# dunno
|
||||||
|
pass
|
||||||
|
ssl = ' (SSL)' if status != STATUS_DISCONNECTED \
|
||||||
|
and self.network.is_ssl() else ''
|
||||||
|
self.network_status.setPalette(pal)
|
||||||
|
icon = self.network.status_icon(status)
|
||||||
|
if icon:
|
||||||
|
self.network_status.setText(
|
||||||
|
'<img src="%s"> %s' %
|
||||||
|
(resource_filename(__name__, 'data/icons/%s' % icon),
|
||||||
|
self.network.status_label(status) + ssl))
|
||||||
|
else:
|
||||||
|
self.network_status.setText(status.capitalize())
|
||||||
|
if status == STATUS_DISCONNECTED:
|
||||||
|
self.actions['connect'].setEnabled(True)
|
||||||
|
self.actions['disconnect'].setEnabled(False)
|
||||||
|
else:
|
||||||
|
self.actions['connect'].setEnabled(False)
|
||||||
|
self.actions['disconnect'].setEnabled(True)
|
||||||
|
|
||||||
|
def _network_weechat_msg(self, message):
|
||||||
|
"""Called when a message is received from WeeChat."""
|
||||||
|
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.network.debug_print(
|
||||||
|
0, '==>',
|
||||||
|
'message uncompressed (%d bytes):\n%s'
|
||||||
|
% (message.size_uncompressed,
|
||||||
|
protocol.hex_and_ascii(message.uncompressed, 20)),
|
||||||
|
forcecolor='#008800')
|
||||||
|
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 message with list of buffers."""
|
||||||
|
for obj in message.objects:
|
||||||
|
if obj.objtype != 'hda' or obj.value['path'][-1] != 'buffer':
|
||||||
|
continue
|
||||||
|
self.list_buffers.clear()
|
||||||
|
while self.stacked_buffers.count() > 0:
|
||||||
|
buf = self.stacked_buffers.widget(0)
|
||||||
|
self.stacked_buffers.removeWidget(buf)
|
||||||
|
self.buffers = []
|
||||||
|
for item in obj.value['items']:
|
||||||
|
buf = self.create_buffer(item)
|
||||||
|
self.insert_buffer(len(self.buffers), buf)
|
||||||
|
self.list_buffers.setCurrentRow(0)
|
||||||
|
self.buffers[0].widget.input.setFocus()
|
||||||
|
|
||||||
|
def _parse_line(self, message):
|
||||||
|
"""Parse a WeeChat message with a buffer line."""
|
||||||
|
for obj in message.objects:
|
||||||
|
lines = []
|
||||||
|
if obj.objtype != 'hda' or obj.value['path'][-1] != 'line_data':
|
||||||
|
continue
|
||||||
|
for item in obj.value['items']:
|
||||||
|
if message.msgid == 'listlines':
|
||||||
|
ptrbuf = item['__path'][0]
|
||||||
|
else:
|
||||||
|
ptrbuf = item['buffer']
|
||||||
|
index = [i for i, b in enumerate(self.buffers)
|
||||||
|
if b.pointer() == ptrbuf]
|
||||||
|
if index:
|
||||||
|
lines.append(
|
||||||
|
(index[0],
|
||||||
|
(item['date'], item['prefix'],
|
||||||
|
item['message']))
|
||||||
|
)
|
||||||
|
if message.msgid == 'listlines':
|
||||||
|
lines.reverse()
|
||||||
|
for line in lines:
|
||||||
|
self.buffers[line[0]].widget.chat.display(*line[1])
|
||||||
|
|
||||||
|
def _parse_nicklist(self, message):
|
||||||
|
"""Parse a WeeChat message with a buffer nicklist."""
|
||||||
|
buffer_refresh = {}
|
||||||
|
for obj in message.objects:
|
||||||
|
if obj.objtype != 'hda' or \
|
||||||
|
obj.value['path'][-1] != 'nicklist_item':
|
||||||
|
continue
|
||||||
|
group = '__root'
|
||||||
|
for item in obj.value['items']:
|
||||||
|
index = [i for i, b in enumerate(self.buffers)
|
||||||
|
if b.pointer() == item['__path'][0]]
|
||||||
|
if index:
|
||||||
|
if not index[0] in buffer_refresh:
|
||||||
|
self.buffers[index[0]].nicklist = {}
|
||||||
|
buffer_refresh[index[0]] = True
|
||||||
|
if item['group']:
|
||||||
|
group = item['name']
|
||||||
|
self.buffers[index[0]].nicklist_add_item(
|
||||||
|
group, item['group'], item['prefix'], item['name'],
|
||||||
|
item['visible'])
|
||||||
|
for index in buffer_refresh:
|
||||||
|
self.buffers[index].nicklist_refresh()
|
||||||
|
|
||||||
|
def _parse_nicklist_diff(self, message):
|
||||||
|
"""Parse a WeeChat message with a buffer nicklist diff."""
|
||||||
|
buffer_refresh = {}
|
||||||
|
for obj in message.objects:
|
||||||
|
if obj.objtype != 'hda' or \
|
||||||
|
obj.value['path'][-1] != 'nicklist_item':
|
||||||
|
continue
|
||||||
|
group = '__root'
|
||||||
|
for item in obj.value['items']:
|
||||||
|
index = [i for i, b in enumerate(self.buffers)
|
||||||
|
if b.pointer() == item['__path'][0]]
|
||||||
|
if not index:
|
||||||
|
continue
|
||||||
|
buffer_refresh[index[0]] = True
|
||||||
|
if item['_diff'] == ord('^'):
|
||||||
|
group = item['name']
|
||||||
|
elif item['_diff'] == ord('+'):
|
||||||
|
self.buffers[index[0]].nicklist_add_item(
|
||||||
|
group, item['group'], item['prefix'], item['name'],
|
||||||
|
item['visible'])
|
||||||
|
elif item['_diff'] == ord('-'):
|
||||||
|
self.buffers[index[0]].nicklist_remove_item(
|
||||||
|
group, item['group'], item['name'])
|
||||||
|
elif item['_diff'] == ord('*'):
|
||||||
|
self.buffers[index[0]].nicklist_update_item(
|
||||||
|
group, item['group'], item['prefix'], item['name'],
|
||||||
|
item['visible'])
|
||||||
|
for index in buffer_refresh:
|
||||||
|
self.buffers[index].nicklist_refresh()
|
||||||
|
|
||||||
|
def _parse_buffer_opened(self, message):
|
||||||
|
"""Parse a WeeChat message with a new buffer (opened)."""
|
||||||
|
for obj in message.objects:
|
||||||
|
if obj.objtype != 'hda' or obj.value['path'][-1] != 'buffer':
|
||||||
|
continue
|
||||||
|
for item in obj.value['items']:
|
||||||
|
buf = self.create_buffer(item)
|
||||||
|
index = self.find_buffer_index_for_insert(item['next_buffer'])
|
||||||
|
self.insert_buffer(index, buf)
|
||||||
|
|
||||||
|
def _parse_buffer(self, message):
|
||||||
|
"""Parse a WeeChat message with a buffer event
|
||||||
|
(anything except a new buffer).
|
||||||
|
"""
|
||||||
|
for obj in message.objects:
|
||||||
|
if obj.objtype != 'hda' or obj.value['path'][-1] != 'buffer':
|
||||||
|
continue
|
||||||
|
for item in obj.value['items']:
|
||||||
|
index = [i for i, b in enumerate(self.buffers)
|
||||||
|
if b.pointer() == item['__path'][0]]
|
||||||
|
if not index:
|
||||||
|
continue
|
||||||
|
index = index[0]
|
||||||
|
if message.msgid == '_buffer_type_changed':
|
||||||
|
self.buffers[index].data['type'] = item['type']
|
||||||
|
elif message.msgid in ('_buffer_moved', '_buffer_merged',
|
||||||
|
'_buffer_unmerged'):
|
||||||
|
buf = self.buffers[index]
|
||||||
|
buf.data['number'] = item['number']
|
||||||
|
self.remove_buffer(index)
|
||||||
|
index2 = self.find_buffer_index_for_insert(
|
||||||
|
item['next_buffer'])
|
||||||
|
self.insert_buffer(index2, buf)
|
||||||
|
elif message.msgid == '_buffer_renamed':
|
||||||
|
self.buffers[index].data['full_name'] = item['full_name']
|
||||||
|
self.buffers[index].data['short_name'] = item['short_name']
|
||||||
|
elif message.msgid == '_buffer_title_changed':
|
||||||
|
self.buffers[index].data['title'] = item['title']
|
||||||
|
self.buffers[index].update_title()
|
||||||
|
elif message.msgid == '_buffer_cleared':
|
||||||
|
self.buffers[index].widget.chat.clear()
|
||||||
|
elif message.msgid.startswith('_buffer_localvar_'):
|
||||||
|
self.buffers[index].data['local_variables'] = \
|
||||||
|
item['local_variables']
|
||||||
|
self.buffers[index].update_prompt()
|
||||||
|
elif message.msgid == '_buffer_closing':
|
||||||
|
self.remove_buffer(index)
|
||||||
|
|
||||||
|
def parse_message(self, message):
|
||||||
|
"""Parse a WeeChat message."""
|
||||||
|
if message.msgid.startswith('debug'):
|
||||||
|
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'):
|
||||||
|
self._parse_line(message)
|
||||||
|
elif message.msgid in ('_nicklist', 'nicklist'):
|
||||||
|
self._parse_nicklist(message)
|
||||||
|
elif message.msgid == '_nicklist_diff':
|
||||||
|
self._parse_nicklist_diff(message)
|
||||||
|
elif message.msgid == '_buffer_opened':
|
||||||
|
self._parse_buffer_opened(message)
|
||||||
|
elif message.msgid.startswith('_buffer_'):
|
||||||
|
self._parse_buffer(message)
|
||||||
|
elif message.msgid == '_upgrade':
|
||||||
|
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."""
|
||||||
|
buf = Buffer(item)
|
||||||
|
buf.bufferInput.connect(self.buffer_input)
|
||||||
|
buf.widget.input.bufferSwitchPrev.connect(
|
||||||
|
self.list_buffers.switch_prev_buffer)
|
||||||
|
buf.widget.input.bufferSwitchNext.connect(
|
||||||
|
self.list_buffers.switch_next_buffer)
|
||||||
|
return buf
|
||||||
|
|
||||||
|
def insert_buffer(self, index, buf):
|
||||||
|
"""Insert a buffer in list."""
|
||||||
|
self.buffers.insert(index, buf)
|
||||||
|
self.list_buffers.insertItem(index, '%s'
|
||||||
|
% (buf.data['local_variables']['name']))
|
||||||
|
self.stacked_buffers.insertWidget(index, buf.widget)
|
||||||
|
|
||||||
|
def remove_buffer(self, index):
|
||||||
|
"""Remove a buffer."""
|
||||||
|
if self.list_buffers.currentRow == index and index > 0:
|
||||||
|
self.list_buffers.setCurrentRow(index - 1)
|
||||||
|
self.list_buffers.takeItem(index)
|
||||||
|
self.stacked_buffers.removeWidget(self.stacked_buffers.widget(index))
|
||||||
|
self.buffers.pop(index)
|
||||||
|
|
||||||
|
def find_buffer_index_for_insert(self, next_buffer):
|
||||||
|
"""Find position to insert a buffer in list."""
|
||||||
|
index = -1
|
||||||
|
if next_buffer == '0x0':
|
||||||
|
index = len(self.buffers)
|
||||||
|
else:
|
||||||
|
elts = [i for i, b in enumerate(self.buffers)
|
||||||
|
if b.pointer() == next_buffer]
|
||||||
|
if len(elts):
|
||||||
|
index = elts[0]
|
||||||
|
if index < 0:
|
||||||
|
print('Warning: unable to find position for buffer, using end of '
|
||||||
|
'list by default')
|
||||||
|
index = len(self.buffers)
|
||||||
|
return index
|
||||||
|
|
||||||
|
def closeEvent(self, event):
|
||||||
|
"""Called when QWeeChat window is closed."""
|
||||||
|
self.network.disconnect_weechat()
|
||||||
|
if self.network.debug_dialog:
|
||||||
|
self.network.debug_dialog.close()
|
||||||
|
config.write(self.config)
|
||||||
|
QtWidgets.QFrame.closeEvent(self, event)
|
||||||
|
|
||||||
|
|
||||||
|
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_win = MainWindow()
|
||||||
|
main_win.show()
|
||||||
|
sys.exit(app.exec_())
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
Loading…
Reference in a new issue