Compare commits

...

1 Commits

Author SHA1 Message Date
ee252296a8
Add a configuration dialog
- Add configure dialog
- Dynamically create rendering options
- Load and save settings
- Pass on options to the renderer
2021-08-03 23:15:22 -07:00
3 changed files with 256 additions and 2 deletions

View File

@ -0,0 +1,72 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ConfigureDialog</class>
<widget class="QDialog" name="ConfigureDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QVBoxLayout" name="configureLayout">
<item>
<widget class="QGroupBox" name="renderOptionsGroupBox">
<property name="title">
<string>Render Options</string>
</property>
<layout class="QFormLayout" name="renderOptionsLayout"/>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>ConfigureDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>ConfigureDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -0,0 +1,165 @@
# -*- coding: utf-8 -*-
from functools import partial
from PyQt5 import QtCore, QtGui, QtWidgets
from chordpro.renderers.html import get_options, get_option_groups
def _coerce_bool(value):
"""Coerce a value to be a boolean"""
if isinstance(value, str):
return value[0].lower() in ['t', 'y', '1']
else:
return bool(value)
class ConfigureDialog(QtWidgets.QDialog):
def __init__(self, parent=None):
super().__init__(parent)
self.settings = QtCore.QSettings()
self.settings.beginGroup('render')
self.setup_ui()
self.setup_options()
def setup_ui(self):
self.setObjectName('ConfigureDialog')
self.resize(600, 400)
self.configure_layout = QtWidgets.QVBoxLayout(self)
self.configure_layout.setObjectName("configure_layout")
self.category_layout = QtWidgets.QHBoxLayout()
self.category_layout.setObjectName('category_layout')
self.configure_layout.addLayout(self.category_layout)
self.category_list_widget = QtWidgets.QListWidget(self)
self.category_list_widget.setFixedWidth(100)
self.category_list_widget.addItems(['', '', ''])
self.category_list_widget.setObjectName('category_list_widget')
self.category_layout.addWidget(self.category_list_widget)
self.category_stack = QtWidgets.QStackedWidget(self)
self.category_stack.setObjectName('category_stack')
self.category_layout.addWidget(self.category_stack)
# General settings
self.general_page = QtWidgets.QWidget()
self.general_page.setObjectName('general_page')
self.category_stack.addWidget(self.general_page)
# Editor settings
self.editor_page = QtWidgets.QWidget()
self.editor_page.setObjectName('editor_page')
self.category_stack.addWidget(self.editor_page)
self.editor_layout = QtWidgets.QFormLayout(self.editor_page)
self.editor_font_combobox = QtWidgets.QFontComboBox(self.editor_page)
self.editor_layout.addRow('Font', self.editor_font_combobox)
# Renderer settings
self.renderer_page = QtWidgets.QWidget()
self.renderer_page.setObjectName('renderer_page')
self.category_stack.addWidget(self.renderer_page)
self.render_layout = QtWidgets.QVBoxLayout(self.renderer_page)
self.render_options_combobox = QtWidgets.QComboBox(self.renderer_page)
self.render_options_combobox.setObjectName("render_options_combobox")
self.render_layout.addWidget(self.render_options_combobox)
self.render_options_stack = QtWidgets.QStackedWidget(self)
self.render_options_stack.setObjectName("render_options_stack")
self.render_layout.addWidget(self.render_options_stack)
# Buttons
self.button_box = QtWidgets.QDialogButtonBox(self)
self.button_box.setOrientation(QtCore.Qt.Horizontal)
self.button_box.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel |
QtWidgets.QDialogButtonBox.Ok)
self.button_box.setObjectName("button_box")
self.configure_layout.addWidget(self.button_box)
self.retranslate_ui()
self.button_box.accepted.connect(self.accept)
self.button_box.rejected.connect(self.reject)
self.category_list_widget.currentRowChanged.connect(self.category_stack.setCurrentIndex)
self.render_options_combobox.activated.connect(self.render_options_stack.setCurrentIndex)
def retranslate_ui(self):
_translate = QtCore.QCoreApplication.translate
self.setWindowTitle(_translate("ConfigureDialog", "Configure"))
self.category_list_widget.item(0).setText(_translate('ConfigureDialog', 'General'))
self.category_list_widget.item(1).setText(_translate('ConfigureDialog', 'Editor'))
self.category_list_widget.item(2).setText(_translate('ConfigureDialog', 'Render'))
def _set_value(self, name, value):
"""Set an option value"""
self.option_values[name] = value
def setup_options(self):
self.option_widgets = {}
self.option_values = {}
for group in get_option_groups():
pretty_group = group.replace('_', ' ').title()
self.render_options_combobox.addItem(pretty_group)
page_widget = QtWidgets.QWidget()
page_layout = QtWidgets.QFormLayout(page_widget)
for name, details in get_options(group).items():
pretty_name = name.replace(group, '').replace('_', ' ').title()
self.option_values[name] = details['default']
widget = None
set_value = partial(self._set_value, name)
if details["type"] is int:
widget = QtWidgets.QSpinBox(page_widget)
if details['default']:
widget.setValue(details['default'])
widget.valueChanged.connect(set_value)
elif details["type"] is bool:
widget = QtWidgets.QCheckBox(page_widget)
widget.setChecked(_coerce_bool(details['default']))
widget.toggled.connect(set_value)
elif 'font' in name:
widget = QtWidgets.QFontComboBox(page_widget)
if details['default']:
widget.setFont(QtGui.QFont(details['default']))
widget.currentFontChanged.connect(set_value)
else:
widget = QtWidgets.QLineEdit(page_widget)
if details['default']:
widget.setText(details['default'])
widget.textChanged.connect(set_value)
if widget:
widget.setObjectName(name)
self.option_widgets[name] = widget
page_layout.addRow(pretty_name, widget)
if details['description']:
label = QtWidgets.QLabel(page_widget)
label.setText(details['description'])
page_layout.addRow('', label)
self.render_options_stack.addWidget(page_widget)
def load_settings(self):
"""Load the settings"""
for name, details in get_options().items():
if self.settings.contains(name):
value = self.settings.value(name)
if value is None:
continue
if details["type"] is int:
value = int(value)
self.option_widgets[name].setValue(value)
elif details['type'] is bool:
value = _coerce_bool(value)
self.option_widgets[name].setChecked(value)
elif 'font' in name:
value = QtGui.QFont(value)
self.option_widgets[name].setCurrentFont(value)
else:
self.option_widgets[name].setText(value)
self.option_values[name] = value
def save_settings(self):
"""Save the settings"""
for name, value in self.option_values.items():
if isinstance(value, QtGui.QFont):
value = value.family()
self.settings.setValue(name, value)
def exec(self):
"""Execute the dialog"""
self.load_settings()
return super().exec()
def accept(self):
"""The user clicked the "OK" button"""
self.save_settings()
return super().accept()

View File

@ -4,6 +4,7 @@ from PyQt5 import QtCore, QtGui, QtWidgets, QtWebEngineWidgets, Qsci
from chordpro import Song
from chordpro.renderers.html import render
from ukatali.configuredialog import ConfigureDialog
from ukatali.lexer import ChordProLexer
@ -12,6 +13,7 @@ class MainWindow(QtWidgets.QMainWindow):
super().__init__(parent)
self.setup_ui()
self.filename = None
self.configure_dialog = ConfigureDialog(self)
def setup_ui(self):
self.setObjectName('MainWindow')
@ -168,10 +170,10 @@ class MainWindow(QtWidgets.QMainWindow):
self.cut_action.triggered.connect(self.file_editor.cut)
self.copy_action.triggered.connect(self.file_editor.copy)
self.paste_action.triggered.connect(self.file_editor.paste)
# QtCore.QMetaObject.connectSlotsByName(self)
self.open_action.triggered.connect(self.on_open_clicked)
self.save_action.triggered.connect(self.on_save_clicked)
self.save_as_action.triggered.connect(self.on_save_as_clicked)
self.configure_action.triggered.connect(self.on_configure_clicked)
self.file_editor.textChanged.connect(self.on_text_changed)
def retranslate_ui(self):
@ -268,10 +270,25 @@ class MainWindow(QtWidgets.QMainWindow):
QtCore.QSettings().setValue('files/last-directory', str(Path(filename).parent))
self.on_save_clicked()
def on_configure_clicked(self):
"""Show the configuration dialog"""
if self.configure_dialog.exec() == QtWidgets.QDialog.Accepted:
self.on_text_changed()
def _get_render_options(self):
"""Get all the render options from the settings"""
options = {}
settings = QtCore.QSettings()
settings.beginGroup('render')
for key in settings.allKeys():
options[key] = settings.value(key)
return options
def on_text_changed(self):
"""Update the preview when the text changes"""
options = self._get_render_options()
text = self.file_editor.text()
song = Song()
song.parse(text)
html = render(song)
html = render(song, options)
self.preview_view.setHtml(html)