Compare commits

...

4 Commits

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 import Song
from chordpro.renderers.html import render from chordpro.renderers.html import render
from ukatali.configuredialog import ConfigureDialog
from ukatali.lexer import ChordProLexer from ukatali.lexer import ChordProLexer
@ -12,6 +13,7 @@ class MainWindow(QtWidgets.QMainWindow):
super().__init__(parent) super().__init__(parent)
self.setup_ui() self.setup_ui()
self.filename = None self.filename = None
self.configure_dialog = ConfigureDialog(self)
def setup_ui(self): def setup_ui(self):
self.setObjectName('MainWindow') self.setObjectName('MainWindow')
@ -168,10 +170,10 @@ class MainWindow(QtWidgets.QMainWindow):
self.cut_action.triggered.connect(self.file_editor.cut) self.cut_action.triggered.connect(self.file_editor.cut)
self.copy_action.triggered.connect(self.file_editor.copy) self.copy_action.triggered.connect(self.file_editor.copy)
self.paste_action.triggered.connect(self.file_editor.paste) self.paste_action.triggered.connect(self.file_editor.paste)
# QtCore.QMetaObject.connectSlotsByName(self)
self.open_action.triggered.connect(self.on_open_clicked) self.open_action.triggered.connect(self.on_open_clicked)
self.save_action.triggered.connect(self.on_save_clicked) self.save_action.triggered.connect(self.on_save_clicked)
self.save_as_action.triggered.connect(self.on_save_as_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) self.file_editor.textChanged.connect(self.on_text_changed)
def retranslate_ui(self): def retranslate_ui(self):
@ -268,10 +270,25 @@ class MainWindow(QtWidgets.QMainWindow):
QtCore.QSettings().setValue('files/last-directory', str(Path(filename).parent)) QtCore.QSettings().setValue('files/last-directory', str(Path(filename).parent))
self.on_save_clicked() 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): def on_text_changed(self):
"""Update the preview when the text changes""" """Update the preview when the text changes"""
options = self._get_render_options()
text = self.file_editor.text() text = self.file_editor.text()
song = Song() song = Song()
song.parse(text) song.parse(text)
html = render(song) html = render(song, options)
self.preview_view.setHtml(html) self.preview_view.setHtml(html)