Compare commits

..

No commits in common. "master" and "new-file" have entirely different histories.

5 changed files with 38 additions and 106 deletions

View File

@ -1,51 +1,3 @@
[metadata]
name = ukatali
author = Raoul Snyman
author_email = raoul@snyman.info
description = A ChordPro GUI, written in Python and Qt5
long_description = file:README.rst
long_description_content_type = text/x-rst
url = https://git.snyman.info/raoul/ukatali
license = MIT
classifiers =
Development Status :: 3 - Alpha
Intended Audience :: End Users/Desktop
License :: OSI Approved :: MIT License
Operating System :: POSIX
Programming Language :: Python :: 3
Programming Language :: Python :: 3.7
Programming Language :: Python :: 3.8
Programming Language :: Python :: 3.9
Programming Language :: Python :: 3.10
Topic :: Utilities
keywords =
music
chords
guitar
[options]
package_dir =
= src
packages = find:
python_requires = >=3.7
setup_requires =
setuptools_scm
install_requires =
igitar
PyQt5
PyQtWebEngine
QScintilla
[options.packages.find]
where = src
[options.entry_points]
console_scripts =
ukatali = ukatali.app:run_ukutali
[bdist_wheel]
universal = 1
[pep8] [pep8]
exclude=resources.py,vlc.py exclude=resources.py,vlc.py
max-line-length = 120 max-line-length = 120

View File

@ -1,2 +0,0 @@
from setuptools import setup
setup(use_scm_version=True, setup_requires=['setuptools_scm'])

View File

@ -2,7 +2,7 @@
from functools import partial from functools import partial
from PyQt5 import QtCore, QtGui, QtWidgets from PyQt5 import QtCore, QtGui, QtWidgets
from igitar.renderers.html import get_options, get_option_groups from chordpro.renderers.html import get_options, get_option_groups
from ukatali.util import coerce_bool, convert_units from ukatali.util import coerce_bool, convert_units

View File

@ -1,7 +1,7 @@
import re import re
from PyQt5 import QtCore, QtGui, QtWidgets, Qsci from PyQt5 import QtCore, QtGui, QtWidgets, Qsci
from igitar.constants import KNOWN_DIRECTIVES, KNOWN_VERSE_TYPES from chordpro.constants import KNOWN_DIRECTIVES, KNOWN_VERSE_TYPES
PALETTE_ROLES = { PALETTE_ROLES = {
'window': QtGui.QPalette.WindowText, 'window': QtGui.QPalette.WindowText,

View File

@ -1,9 +1,10 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import os
from pathlib import Path from pathlib import Path
from PyQt5 import QtCore, QtGui, QtWidgets, QtWebEngineWidgets, Qsci, QtPrintSupport from PyQt5 import QtCore, QtGui, QtWidgets, QtWebEngineWidgets, Qsci, QtPrintSupport
from igitar import Song from chordpro import Song
from igitar.renderers.html import render, get_options from chordpro.renderers.html import render, get_options
from ukatali.configuredialog import ConfigureDialog from ukatali.configuredialog import ConfigureDialog
from ukatali.lexer import ChordProLexer from ukatali.lexer import ChordProLexer
@ -18,7 +19,6 @@ class MainWindow(QtWidgets.QMainWindow):
self.setup_ui() self.setup_ui()
self.settings = QtCore.QSettings() self.settings = QtCore.QSettings()
self.filename = None self.filename = None
self.is_lyrics_mode = False
self.configure_dialog = ConfigureDialog(self) self.configure_dialog = ConfigureDialog(self)
def setup_ui(self): def setup_ui(self):
@ -67,10 +67,6 @@ class MainWindow(QtWidgets.QMainWindow):
self.preview_layout.setContentsMargins(0, 0, 0, 0) self.preview_layout.setContentsMargins(0, 0, 0, 0)
self.preview_layout.setSpacing(0) self.preview_layout.setSpacing(0)
self.preview_layout.setObjectName('preview_layout') self.preview_layout.setObjectName('preview_layout')
self.preview_toolbar = QtWidgets.QToolBar(self.preview_dock_contents)
self.preview_toolbar.setMovable(False)
self.preview_toolbar.setObjectName('preview_toolbar')
self.preview_layout.addWidget(self.preview_toolbar)
self.preview_view = QtWebEngineWidgets.QWebEngineView(self.preview_dock_contents) self.preview_view = QtWebEngineWidgets.QWebEngineView(self.preview_dock_contents)
self.preview_view.setUrl(QtCore.QUrl('about:blank')) self.preview_view.setUrl(QtCore.QUrl('about:blank'))
self.preview_view.setObjectName('preview_view') self.preview_view.setObjectName('preview_view')
@ -78,7 +74,6 @@ class MainWindow(QtWidgets.QMainWindow):
self.preview_dock.setWidget(self.preview_dock_contents) self.preview_dock.setWidget(self.preview_dock_contents)
self.addDockWidget(QtCore.Qt.DockWidgetArea(2), self.preview_dock) self.addDockWidget(QtCore.Qt.DockWidgetArea(2), self.preview_dock)
self.toolbar = QtWidgets.QToolBar(self) self.toolbar = QtWidgets.QToolBar(self)
self.toolbar.setMovable(False)
self.toolbar.setObjectName('toolbar') self.toolbar.setObjectName('toolbar')
self.addToolBar(QtCore.Qt.TopToolBarArea, self.toolbar) self.addToolBar(QtCore.Qt.TopToolBarArea, self.toolbar)
self.new_action = QtWidgets.QAction(self) self.new_action = QtWidgets.QAction(self)
@ -122,25 +117,25 @@ class MainWindow(QtWidgets.QMainWindow):
self.cut_action.setIcon(icon) self.cut_action.setIcon(icon)
self.cut_action.setObjectName('cut_action') self.cut_action.setObjectName('cut_action')
self.copy_action = QtWidgets.QAction(self) self.copy_action = QtWidgets.QAction(self)
self.copy_action.setIcon(QtGui.QIcon.fromTheme('edit-copy')) icon = QtGui.QIcon.fromTheme('edit-copy')
self.copy_action.setIcon(icon)
self.copy_action.setObjectName('copy_action') self.copy_action.setObjectName('copy_action')
self.paste_action = QtWidgets.QAction(self) self.paste_action = QtWidgets.QAction(self)
self.paste_action.setIcon(QtGui.QIcon.fromTheme('edit-paste')) icon = QtGui.QIcon.fromTheme('edit-paste')
self.paste_action.setIcon(icon)
self.paste_action.setObjectName('paste_action') self.paste_action.setObjectName('paste_action')
self.configure_action = QtWidgets.QAction(self) self.configure_action = QtWidgets.QAction(self)
self.configure_action.setIcon(QtGui.QIcon.fromTheme('configure')) icon = QtGui.QIcon.fromTheme('configure')
self.configure_action.setIcon(icon)
self.configure_action.setObjectName('configure_action') self.configure_action.setObjectName('configure_action')
self.about_action = QtWidgets.QAction(self) self.about_action = QtWidgets.QAction(self)
self.about_action.setIcon(QtGui.QIcon.fromTheme('help-about')) icon = QtGui.QIcon.fromTheme('help-about')
self.about_action.setIcon(icon)
self.about_action.setObjectName('about_action') self.about_action.setObjectName('about_action')
self.exit_action = QtWidgets.QAction(self) self.exit_action = QtWidgets.QAction(self)
self.exit_action.setIcon(QtGui.QIcon.fromTheme('application-exit')) icon = QtGui.QIcon.fromTheme('application-exit')
self.exit_action.setIcon(icon)
self.exit_action.setObjectName('exit_action') self.exit_action.setObjectName('exit_action')
self.hide_chords_action = QtWidgets.QAction(self)
self.hide_chords_action.setCheckable(True)
self.hide_chords_action.setChecked(False)
self.hide_chords_action.setIcon(QtGui.QIcon.fromTheme('view-hidden'))
self.hide_chords_action.setObjectName('hide_chords_action')
self.file_menu.addAction(self.new_action) self.file_menu.addAction(self.new_action)
self.file_menu.addAction(self.open_action) self.file_menu.addAction(self.open_action)
self.file_menu.addAction(self.save_action) self.file_menu.addAction(self.save_action)
@ -180,7 +175,6 @@ class MainWindow(QtWidgets.QMainWindow):
self.toolbar.addAction(self.paste_action) self.toolbar.addAction(self.paste_action)
self.toolbar.addSeparator() self.toolbar.addSeparator()
self.toolbar.addAction(self.configure_action) self.toolbar.addAction(self.configure_action)
self.preview_toolbar.addAction(self.hide_chords_action)
self.retranslate_ui() self.retranslate_ui()
self.exit_action.triggered.connect(self.close) self.exit_action.triggered.connect(self.close)
@ -199,7 +193,6 @@ class MainWindow(QtWidgets.QMainWindow):
self.configure_action.triggered.connect(self.on_configure_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)
self.preview_view.page().pdfPrintingFinished.connect(self.on_pdf_finished) self.preview_view.page().pdfPrintingFinished.connect(self.on_pdf_finished)
self.hide_chords_action.triggered.connect(self.on_hide_chords_clicked)
def retranslate_ui(self): def retranslate_ui(self):
_translate = QtCore.QCoreApplication.translate _translate = QtCore.QCoreApplication.translate
@ -253,7 +246,6 @@ class MainWindow(QtWidgets.QMainWindow):
self.exit_action.setText(_translate('MainWindow', 'E&xit')) self.exit_action.setText(_translate('MainWindow', 'E&xit'))
self.exit_action.setToolTip(_translate('MainWindow', 'Quit Ukatali')) self.exit_action.setToolTip(_translate('MainWindow', 'Quit Ukatali'))
self.exit_action.setShortcut(_translate('MainWindow', 'Alt+F4')) self.exit_action.setShortcut(_translate('MainWindow', 'Alt+F4'))
self.hide_chords_action.setText(_translate('MainWindow', 'Hide Chords'))
def on_new_clicked(self): def on_new_clicked(self):
"""Start a new file""" """Start a new file"""
@ -319,7 +311,7 @@ class MainWindow(QtWidgets.QMainWindow):
if self.configure_dialog.exec() == QtWidgets.QDialog.Accepted and self.file_editor.text(): if self.configure_dialog.exec() == QtWidgets.QDialog.Accepted and self.file_editor.text():
self.on_text_changed() self.on_text_changed()
def _get_render_options(self, is_lyrics_mode=False): def _get_render_options(self):
"""Get all the render options from the settings""" """Get all the render options from the settings"""
options = {} options = {}
self.settings.beginGroup('render') self.settings.beginGroup('render')
@ -333,29 +325,26 @@ class MainWindow(QtWidgets.QMainWindow):
elif details['type'] is bool: elif details['type'] is bool:
value = coerce_bool(value) value = coerce_bool(value)
options[name] = value options[name] = value
if is_lyrics_mode and 'indent' in name:
options[name] = 0
elif is_lyrics_mode and 'is_hidden' in name:
options[name] = True
self.settings.endGroup() self.settings.endGroup()
return options return options
def _render_song(self, extra_styles=None): def _render_song(self, extra_styles=None):
"""Render the current song and return the HTML""" """Render the current song and return the HTML"""
options = self._get_render_options(self.is_lyrics_mode) options = self._get_render_options()
text = self.file_editor.text() text = self.file_editor.text()
song = Song() song = Song()
try: song.parse(text)
song.parse(text) if song.metadata.get('copyright'):
return render(song, options, extra_styles) extra_styles = extra_styles or ''
except Exception: extra_styles += os.linesep
return None extra_styles += '@page {{ @bottom-left {{ content: "{}"; }} }}'.format(song.metadata.get('copyright'))
return render(song, options, extra_styles)
def on_text_changed(self): def on_text_changed(self):
"""Update the preview when the text changes""" """Update the preview when the text changes"""
# self.setWindowModified(True)
html = self._render_song() html = self._render_song()
if html: self.preview_view.setHtml(html)
self.preview_view.setHtml(html)
def on_export_pdf_clicked(self): def on_export_pdf_clicked(self):
"""Export the current song to PDF""" """Export the current song to PDF"""
@ -383,7 +372,7 @@ class MainWindow(QtWidgets.QMainWindow):
margin_top = float(self.settings.value('margin_top', 20)) margin_top = float(self.settings.value('margin_top', 20))
margin_bottom = float(self.settings.value('margin_bottom', 20)) margin_bottom = float(self.settings.value('margin_bottom', 20))
self.settings.endGroup() self.settings.endGroup()
margins = QtCore.QMarginsF(margin_left, margin_top, margin_right, margin_bottom) margins = QtCore.QMarginsF(QtCore.QMargins(margin_left, margin_top, margin_right, margin_bottom))
page_layout = QtGui.QPageLayout(page_size, orientation, margins, unit) page_layout = QtGui.QPageLayout(page_size, orientation, margins, unit)
# Export to PDF # Export to PDF
self.preview_view.page().printToPdf(str(filename), page_layout) self.preview_view.page().printToPdf(str(filename), page_layout)
@ -407,14 +396,9 @@ class MainWindow(QtWidgets.QMainWindow):
# Export to HTML # Export to HTML
try: try:
with filename.open('w') as html_file: with filename.open('w') as html_file:
html = self._render_song() html_file.write(self._render_song())
if html: QtWidgets.QMessageBox.information(self, 'Export to HTML Successful',
html_file.write(html) 'Successfully exported to "{}"'.format(filename.name))
QtWidgets.QMessageBox.information(self, 'Export to HTML Successful',
'Successfully exported to "{}"'.format(filename.name))
else:
QtWidgets.QMessageBox.critical(self, 'Error Exporting to HTML',
'There was an error while exporting to HTML')
except Exception as e: except Exception as e:
QtWidgets.QMessageBox.critical(self, 'Error Exporting to HTML', QtWidgets.QMessageBox.critical(self, 'Error Exporting to HTML',
'There was an error while exporting to HTML:\n{e}'.format(e=e)) 'There was an error while exporting to HTML:\n{e}'.format(e=e))
@ -427,18 +411,16 @@ class MainWindow(QtWidgets.QMainWindow):
else: else:
QtWidgets.QMessageBox.critical(self, 'Error Exporting to PDF', 'There was an error while exporting to PDF') QtWidgets.QMessageBox.critical(self, 'Error Exporting to PDF', 'There was an error while exporting to PDF')
def on_print_finished(self, is_success):
print(is_success)
def on_print_clicked(self): def on_print_clicked(self):
"""Print the current song""" """Print the current song"""
printer = QtPrintSupport.QPrinter(QtPrintSupport.QPrinter.HighResolution)
def _on_print_finished(is_success):
print(is_success)
# print(QtPrintSupport.QPrinterInfo.defaultPrinterName())
# default_printer = QtPrintSupport.QPrinterInfo.defaultPrinter()
# print(default_printer)
printer = QtPrintSupport.QPrinter()
print_dialog = QtPrintSupport.QPrintDialog(printer, self.preview_view.page().view()) print_dialog = QtPrintSupport.QPrintDialog(printer, self.preview_view.page().view())
if print_dialog.exec() == QtWidgets.QDialog.Accepted: if print_dialog.exec() == QtWidgets.QDialog.Accepted:
self.preview_view.page().print(printer, self.on_print_finished) self.preview_view.page().print(printer, _on_print_finished)
def on_hide_chords_clicked(self, is_checked):
"""Hide the chords in the preview window"""
self.is_lyrics_mode = is_checked
if self.file_editor.text():
self.on_text_changed()