diff --git a/Makefile b/Makefile
index 600e2ca..6fb6ec7 100644
--- a/Makefile
+++ b/Makefile
@@ -16,12 +16,22 @@
# You should have received a copy of the GNU General Public License
# along with QWeeChat. If not, see .
#
+# to run the tests, run make PASS=controllerpassword test
+
+PREFIX=/usr/local
+PYTHON_EXE_MSYS=${PREFIX}/bin/python3.sh
+PIP_EXE_MSYS=${PREFIX}/bin/pip3.sh
+LOCAL_DOCTEST=${PREFIX}/bin/toxcore_run_doctest3.bash
+DOCTEST=${LOCAL_DOCTEST}
+PYTHON_MINOR=`python3 --version 2>&1 | sed -e 's@^.* @@' -e 's@\.[0-9]*$$@@'`
+MOD=qweechat
all: check
check: lint test
+ sh ${PYTHON_EXE_MSYS} -c "import ${MOD}"
-lint: flake8 pylint bandit
+lint:: flake8 pylint bandit
flake8:
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
@@ -32,3 +42,8 @@ pylint:
bandit:
bandit -r qweechat
+
+install::
+# we install --nodeps because pip is installing stuff we already have in the OS
+ ${PYTHON_EXE_MSYS} setup.py install \
+ --prefix ${PREFIX}/
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 0000000..dd1a710
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,51 @@
+[project]
+name = 'qweechat'
+requires-python = ">= 3.7"
+description = "qtpy channel for qweechat"
+keywords = ["qt", "console"]
+classifiers = [
+ # How mature is this project? Common values are
+ # 3 - Alpha
+ # 4 - Beta
+ # 5 - Production/Stable
+ "Development Status :: 4 - Beta",
+
+ # Indicate who your project is intended for
+ "Intended Audience :: Developers",
+
+ # Specify the Python versions you support here.
+ "Programming Language :: Python :: 3",
+ "License :: OSI Approved",
+ "Operating System :: POSIX :: BSD :: FreeBSD",
+ "Operating System :: POSIX :: Linux",
+ "Programming Language :: Python :: 3 :: Only",
+ "Programming Language :: Python :: 3.7",
+ "Programming Language :: Python :: 3.8",
+ "Programming Language :: Python :: 3.9",
+ "Programming Language :: Python :: 3.10",
+ "Programming Language :: Python :: 3.11",
+ "Programming Language :: Python :: Implementation :: CPython",
+]
+dynamic = ["version", "readme", "dependencies"] # cannot be dynamic ['license']
+
+[project.scripts]
+qweechat = "qweechat:iMain"
+
+[project.license]
+file = "COPYING"
+
+[project.urls]
+repository = "https://git.plastiras.org/emdee/qweechat"
+homepage = "https://git.plastiras.org/emdee/qweechat"
+
+[build-system]
+requires = ["setuptools >= 61.0"]
+build-backend = "setuptools.build_meta"
+
+[tool.setuptools.dynamic]
+version = {attr = "qweechat.version.VERSION"}
+readme = {file = ["README.md"]}
+dependencies = {file = ["requirements.txt"]}
+
+#[tool.setuptools.packages.find]
+#where = "src"
diff --git a/qweechat/buffer.py b/qweechat/buffer.py
index 008ecde..9cca40e 100644
--- a/qweechat/buffer.py
+++ b/qweechat/buffer.py
@@ -25,7 +25,7 @@
from pkg_resources import resource_filename
from qtpy import QtCore, QtGui, QtWidgets
-from qtpy.QtCore import pyqtSignal as Signal
+from qtpy.QtCore import Signal
from qweechat.chat import ChatTextEdit
from qweechat.input import InputLineEdit
diff --git a/qweechat/chat.py b/qweechat/chat.py
index 43c4568..6c06aa9 100644
--- a/qweechat/chat.py
+++ b/qweechat/chat.py
@@ -26,7 +26,7 @@ import datetime
from qtpy import QtCore, QtWidgets, QtGui
-from qweechat import config
+from qweechat.config import color_options
from qweechat.weechat import color
@@ -62,7 +62,7 @@ class ChatTextEdit(QtWidgets.QTextEdit):
'/': True
}
}
- self._color = color.Color(config.color_options(), self.debug)
+ self._color = color.Color(color_options(), self.debug)
def display(self, time, prefix, text, forcecolor=None):
if time == 0:
diff --git a/qweechat/config.py b/qweechat/config.py
index ffdf793..f28450f 100644
--- a/qweechat/config.py
+++ b/qweechat/config.py
@@ -41,6 +41,7 @@ CONFIG_DEFAULT_OPTIONS = (('relay.hostname', '127.0.0.1'),
('relay.lines', str(CONFIG_DEFAULT_RELAY_LINES)),
('look.debug', 'off'),
('look.statusbar', 'on'))
+CONFIG_DEFAULT_NOTIFICATION_OPTIONS = tuple
# Default colors for WeeChat color options (option name, #rgb value)
CONFIG_DEFAULT_COLOR_OPTIONS = (
diff --git a/qweechat/network.py b/qweechat/network.py
index 0127a98..be7246d 100644
--- a/qweechat/network.py
+++ b/qweechat/network.py
@@ -232,7 +232,7 @@ class Network(QtCore.QObject):
def is_connected(self):
"""Return True if the socket is connected, False otherwise."""
- return is_state(self, at='ConnectedState')
+ return self.is_state(at='ConnectedState')
def is_state(self, at='ConnectedState'):
"""Return True if the socket is connected, False otherwise."""
diff --git a/qweechat/preferences.py b/qweechat/preferences.py
index 97feece..fc415da 100644
--- a/qweechat/preferences.py
+++ b/qweechat/preferences.py
@@ -2,7 +2,7 @@
#
# preferences.py - preferences dialog box
#
-# Copyright (C) 2016 Ricky Brent
+# Copyright (C) 2011-2022 Sébastien Helleu
#
# This file is part of QWeeChat, a Qt remote GUI for WeeChat.
#
@@ -20,541 +20,38 @@
# along with QWeeChat. If not, see .
#
-import qt_compat
-import config
-import utils
-from inputlinespell import InputLineSpell
+"""Preferences dialog box."""
-QtCore = qt_compat.import_module('QtCore')
-QtGui = qt_compat.import_module('QtGui')
+from PyQt5 import QtCore, QtWidgets as QtGui
class PreferencesDialog(QtGui.QDialog):
"""Preferences dialog."""
- 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):
+ def __init__(self, *args):
QtGui.QDialog.__init__(*(self,) + args)
self.setModal(True)
- self.setWindowTitle(name)
- self.parent = parent
- self.config = parent.config
- self.stacked_panes = QtGui.QStackedWidget()
- self.list_panes = PreferencesTreeWidget("Settings")
+ self.setWindowTitle('Preferences')
- splitter = QtGui.QSplitter()
- 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))
+ close_button = QtGui.QPushButton('Close')
+ close_button.pressed.connect(self.close)
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.addWidget(self.dialog_buttons)
+ hbox.addWidget(close_button)
hbox.addStretch(1)
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)
self.setLayout(vbox)
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)
diff --git a/qweechat/preferences.py.new b/qweechat/preferences.py.new
new file mode 100644
index 0000000..8103b27
--- /dev/null
+++ b/qweechat/preferences.py.new
@@ -0,0 +1,555 @@
+# -*- coding: utf-8 -*-
+#
+# preferences.py - preferences dialog box
+#
+# Copyright (C) 2016 Ricky Brent
+#
+# 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 .
+#
+
+from qweechat.config import (CONFIG_DEFAULT_SECTIONS,
+ CONFIG_DEFAULT_NOTIFICATION_OPTIONS,
+ CONFIG_DEFAULT_OPTIONS, write)
+import utils
+
+from qtpy import QtCore, QtGui
+qicon_from_theme = QtGui.QIcon.fromTheme
+
+class PreferencesDialog(QtGui.QDialog):
+ """Preferences dialog."""
+
+ 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)
+ self.setModal(True)
+ self.setWindowTitle(name)
+ self.parent = parent
+ self.config = parent.config
+ self.stacked_panes = QtGui.QStackedWidget()
+ self.list_panes = PreferencesTreeWidget("Settings")
+
+ splitter = QtGui.QSplitter()
+ splitter.addWidget(self.list_panes)
+ splitter.addWidget(self.stacked_panes)
+
+ # Follow same order as defaults:
+ section_panes = {}
+ for section in 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_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()
+ 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.addWidget(self.dialog_buttons)
+ hbox.addStretch(1)
+
+ vbox = QtGui.QVBoxLayout()
+ vbox.addWidget(splitter)
+ vbox.addLayout(hbox)
+
+ self.setLayout(vbox)
+ 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))
+ 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": qicon_from_theme("media-playback-start"),
+ "message": qicon_from_theme("dialog-information"),
+ "file": qicon_from_theme("document-export"),
+ "taskbar": qicon_from_theme("weechat"),
+ "tray": utils.qicon_tint("ic_hot", fg_color),
+ "command": 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_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']
+ 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}
+
+ 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)
diff --git a/qweechat/qweechat.py b/qweechat/qweechat.py
index ed6187a..49d7a68 100644
--- a/qweechat/qweechat.py
+++ b/qweechat/qweechat.py
@@ -39,7 +39,7 @@ from pkg_resources import resource_filename
from qtpy import QtCore, QtGui, QtWidgets
-from qweechat import config
+from qweechat.config import read, write
from qweechat.about import AboutDialog
from qweechat.buffer import BufferListWidget, Buffer
from qweechat.connection import ConnectionDialog
@@ -59,7 +59,7 @@ class MainWindow(QtWidgets.QMainWindow):
def __init__(self, *args):
super().__init__(*args)
- self.config = config.read()
+ self.config = read()
self.resize(1000, 600)
self.setWindowTitle(APP_NAME)
@@ -536,7 +536,7 @@ class MainWindow(QtWidgets.QMainWindow):
self.network.disconnect_weechat()
if self.network.debug_dialog:
self.network.debug_dialog.close()
- config.write(self.config)
+ write(self.config)
QtWidgets.QFrame.closeEvent(self, event)
diff --git a/qweechat/version.py b/qweechat/version.py
index 25bbf46..f607118 100644
--- a/qweechat/version.py
+++ b/qweechat/version.py
@@ -22,7 +22,7 @@
"""Version of QWeeChat."""
-VERSION = '0.0.1-dev'
+VERSION = '0.0.1'
def qweechat_version():
diff --git a/requirements.txt b/requirements.txt
index df9b5f9..122c03a 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,3 +1,3 @@
# works with PyQt5 and maybe PySide as well
-PyQt6
-
+# PyQt5
+# dev-python/qtconsole >= 5.5.1
diff --git a/setup.py b/setup.py
index dfdbe06..9224aca 100644
--- a/setup.py
+++ b/setup.py
@@ -56,6 +56,7 @@ setup(
]
},
install_requires=[
- 'PyQt6',
+ 'PyQt5',
],
+ zip_safe = False,
)