Browse Source

get MDI working properly, fix some longstanding bugs

master
Ivan Holmes 3 years ago
parent
commit
d31a926f92
  1. 21
      chordsheet/document.py
  2. 7
      chordsheet/parsers.py
  3. 11
      chordsheet/render.py
  4. 43
      cli.py
  5. 0
      csgui/comboBox.py
  6. 28
      csgui/dialogs.py
  7. 8
      csgui/messageBox.py
  8. 12
      csgui/panels.py
  9. 26
      csgui/pdfViewer.py
  10. 27
      csgui/tableView.py
  11. 940
      gui.py
  12. BIN
      preview.pdf
  13. 17
      ui/aboutdialog.ui
  14. 4
      ui/blocks.ui
  15. 2
      ui/chords.ui
  16. 4
      ui/document.ui
  17. 1071
      ui/mainwindow.ui
  18. 233
      ui/new.ui
  19. 32
      ui/pdfarea.ui
  20. 42
      ui/preview.ui
  21. 2
      ui/sections.ui

21
chordsheet/document.py

@ -7,7 +7,6 @@ from reportlab.lib.pagesizes import A4
defaultTimeSignature = 4
class Style:
def __init__(self, **kwargs):
# set up the style using sane defaults
@ -144,16 +143,7 @@ class Document:
self.tempo = (root.find('tempo').text if root.find(
'tempo') is not None else None)
@classmethod
def newFromXML(cls, filepath):
"""
Create a new Document object directly from an XML file.
"""
doc = cls()
doc.loadXML(filepath)
return doc
def saveXML(self, filepath):
def toXML(self):
"""
Write the contents of the Document object to an XML file.
"""
@ -200,7 +190,16 @@ class Document:
ET.SubElement(blockElement, "notes").text = b.notes
tree = ET.ElementTree(root)
return tree
def saveXML(self, filepath):
tree = self.toXML()
tree.write(filepath)
return hash(ET.tostring(tree.getroot()))
def getHash(self):
tree = self.toXML()
return hash(ET.tostring(tree.getroot()))
def loadCSMacro(self, filepath):
"""

7
chordsheet/parsers.py

@ -7,14 +7,13 @@ def parseFingering(fingering, instrument):
"""
if instrument == 'guitar':
numStrings = 6
if len(fingering) == numStrings: # if the fingering is entered in concise format e.g. xx4455
if "," not in fingering and len(fingering) == numStrings: # if the fingering is entered in concise format e.g. xx4455
output = list(fingering)
else: # if entered in long format e.g. x,x,10,10,11,11
output = [f.strip() for f in fingering.split(",")]
if len(output) == numStrings:
if len(output) != numStrings:
print("Voicing <{}> is malformed.".format(fingering))
return output
else:
raise Exception("Voicing <{}> is malformed.".format(fingering))
elif instrument == 'piano':
return [parseName(note).upper().strip() for note in fingering.split(",")]
else:

11
chordsheet/render.py

@ -12,6 +12,7 @@ from reportlab.platypus import BaseDocTemplate, Spacer, Paragraph, Flowable, Fra
from chordsheet.document import Block
from chordsheet.rlStylesheet import getStyleSheet
defaultSpacing = 1.15
def writeText(canvas, style, string, size, vpos, width, **kwargs):
"""
@ -122,7 +123,7 @@ class GuitarChart(Flowable):
for i in range(self.nStrings+1): # i is the string line currently being drawn
writeText(canvas, self.style, ['e', 'B', 'G', 'D', 'A', 'E', 'Name'][i], fontsize, v_origin-(
i*self.stringHeight), self.width, hpos=chartmargin, align='right')
i*self.stringHeight), self.width, hpos=chartmargin, align='right', spacing=defaultSpacing)
# j is which chord (0 is first chord, 1 is 2nd etc)
for j in range(len(stringList[-1])):
@ -152,7 +153,7 @@ class GuitarChart(Flowable):
canvas.line(x, y, x+l, y)
writeText(canvas, self.style, stringList[i][j], fontsize, v_origin-(
i*self.stringHeight), self.width, hpos=chartmargin+self.stringHzSp*(j+0.5))
i*self.stringHeight), self.width, hpos=chartmargin+self.stringHzSp*(j+0.5), spacing=defaultSpacing)
lastWidth = currentWidth
@ -458,7 +459,7 @@ class ChordProgression(Flowable):
if u == maxWidth: # Avoid writing beat number after the final line
break
writeText(canvas, self.style, str((u % self.timeSignature)+1), self.style.beatsFontSize,
v_origin+self.beatsHeight, self.width, hpos=x+unitWidth/2)
v_origin+self.beatsHeight, self.width, hpos=x+unitWidth/2, spacing=defaultSpacing)
parsedBlockList = self.wrapBlocks(self.blockList, maxWidth)
@ -470,12 +471,12 @@ class ChordProgression(Flowable):
b.length*unitWidth, self.unitHeight)
if b.notes is not None:
writeText(canvas, self.style, b.notes, self.style.notesFontSize, v_origin-((v_loc+1)*self.unitHeight)+(
1.3*self.style.notesFontSize), self.width, hpos=h_offset+((h_loc+b.length/2)*unitWidth))
1.3*self.style.notesFontSize), self.width, hpos=h_offset+((h_loc+b.length/2)*unitWidth), spacing=defaultSpacing)
v_offset = ((v_loc*self.unitHeight) +
self.unitHeight/2)-self.style.chordNameFontSize/2
if b.chord is not None:
writeText(canvas, self.style, b.chord.name, self.style.chordNameFontSize,
v_origin-v_offset, self.width, hpos=h_offset+((h_loc+b.length/2)*unitWidth))
v_origin-v_offset, self.width, hpos=h_offset+((h_loc+b.length/2)*unitWidth), spacing=defaultSpacing)
h_loc += b.length

43
cli.py

@ -0,0 +1,43 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
import os
import time
from reportlab.lib.units import mm, cm, inch, pica
from reportlab.lib.pagesizes import A4, A5, LETTER, LEGAL
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
from chordsheet.common import scriptDir
from chordsheet.document import Document, Style, Chord, Block, Section
from chordsheet.render import Renderer
from chordsheet.parsers import parseFingering, parseName
import _version
pdfmetrics.registerFont(
TTFont('FreeSans', os.path.join(scriptDir, 'fonts', 'FreeSans.ttf')))
if sys.platform == "darwin":
pdfmetrics.registerFont(
TTFont('HelveticaNeue', 'HelveticaNeue.ttc', subfontIndex=0))
if len(sys.argv) == 2:
inputFilePath = sys.argv[1]
else:
print("Please provide a .cml, .xml, or .cma file to process.")
sys.exit()
doc = Document()
if inputFilePath[-4:] == ".cma":
doc.loadCSMacro(inputFilePath)
else:
doc.loadXML(inputFilePath)
style = Style()
renderer = Renderer(doc, style)
outputFilePath = ".".join(inputFilePath.split(".")[:-1]) + ".pdf"
renderer.savePDF(outputFilePath)

0
chordsheet/comboBox.py → csgui/comboBox.py

28
chordsheet/dialogs.py → csgui/dialogs.py

@ -25,17 +25,31 @@ class GuitarDialog(QDialog):
self.dialog = uic.loadUi(ui_file)
ui_file.close()
def getVoicing(self):
def getVoicing(self, existingVoicing):
"""
Show the dialogue and return the voicing that has been entered.
"""
lineEditsList = [
self.dialog.ELineEdit,
self.dialog.ALineEdit,
self.dialog.DLineEdit,
self.dialog.GLineEdit,
self.dialog.BLineEdit,
self.dialog.eLineEdit
]
# Read the present voicing
if type(existingVoicing) == list:
for count in range(len(existingVoicing)):
lineEditsList[count].setText(existingVoicing[count])
if self.dialog.exec_() == QDialog.Accepted:
result = [self.dialog.ELineEdit.text(),
self.dialog.ALineEdit.text(),
self.dialog.DLineEdit.text(),
self.dialog.GLineEdit.text(),
self.dialog.BLineEdit.text(),
self.dialog.eLineEdit.text()]
result = [self.dialog.ELineEdit.text() or 'x',
self.dialog.ALineEdit.text() or 'x',
self.dialog.DLineEdit.text() or 'x',
self.dialog.GLineEdit.text() or 'x',
self.dialog.BLineEdit.text() or 'x',
self.dialog.eLineEdit.text() or 'x']
resultJoined = ",".join(result)
return resultJoined
else:

8
chordsheet/messageBox.py → csgui/messageBox.py

@ -5,12 +5,12 @@ class UnsavedMessageBox(QMessageBox):
Message box to alert the user of unsaved changes and allow them to choose how to act.
"""
def __init__(self):
def __init__(self, fileName):
super().__init__()
self.setIcon(QMessageBox.Question)
self.setWindowTitle("Unsaved changes")
self.setText("The document has been modified.")
self.setText(f"The document \"{fileName}\" has been modified.")
self.setInformativeText("Do you want to save your changes?")
self.setStandardButtons(
QMessageBox.Save | QMessageBox.Discard | QMessageBox.Cancel)
@ -22,11 +22,11 @@ class UnreadableMessageBox(QMessageBox):
Message box to warn the user that the chosen file cannot be opened.
"""
def __init__(self):
def __init__(self, fileName):
super().__init__()
self.setIcon(QMessageBox.Warning)
self.setWindowTitle("File cannot be opened")
self.setWindowTitle(f"File \"{fileName}\" cannot be opened")
self.setText("The file you have selected cannot be opened.")
self.setInformativeText("Please make sure it is in the right format.")
self.setStandardButtons(QMessageBox.Ok)

12
chordsheet/panels.py → csgui/panels.py

@ -1,10 +1,11 @@
import os
from PyQt5.QtWidgets import QApplication, QAction, QLabel, QDialogButtonBox, QDialog, QFileDialog, QMessageBox, QPushButton, QLineEdit, QCheckBox, QSpinBox, QDoubleSpinBox, QTableWidgetItem, QTabWidget, QComboBox, QWidget, QScrollArea, QMainWindow, QShortcut, QDockWidget
from PyQt5.QtWidgets import QApplication, QAction, QLabel, QDialogButtonBox, QDialog, QFileDialog, QMessageBox, QPushButton, QLineEdit, QCheckBox, QSpinBox, QDoubleSpinBox, QTableWidgetItem, QTabWidget, QComboBox, QWidget, QScrollArea, QMainWindow, QShortcut, QDockWidget, QLineEdit, QTableView
from PyQt5.QtCore import QFile, QObject, Qt
from PyQt5.QtGui import QImage, QPixmap
from PyQt5 import uic
from chordsheet.common import scriptDir
from csgui.tableView import MTableView
class UIFileDockWidget(QDockWidget):
def __init__(self):
@ -17,6 +18,15 @@ class UIFileDockWidget(QDockWidget):
self.setWidget(uic.loadUi(ui_file))
ui_file.close()
def clear(self):
# Clear all the fields
for lineEdit in self.findChildren(QLineEdit):
lineEdit.clear()
for comboBox in self.findChildren(QComboBox):
comboBox.clear()
for tableView in self.findChildren(MTableView):
tableView.clear()
class DocInfoDockWidget(UIFileDockWidget):
def __init__(self):
super().__init__()

26
chordsheet/pdfViewer.py → csgui/pdfViewer.py

@ -14,8 +14,20 @@ class PDFLabel(QLabel):
self.adjustSize()
if self.pixmap() is not None:
painter = QPainter(self)
painter.setRenderHint(QPainter.Antialiasing)
idealWidth = self.parent.width()-45
# painter.setRenderHint(QPainter.Antialiasing)
parentLayoutMargins = self.parent.scrollAreaLayout.getContentsMargins()
parentMargins = self.parent.getContentsMargins()
if self.parent.verticalScrollBar().isVisible():
scrollBarWidth = self.parent.verticalScrollBar().sizeHint().width()
else:
scrollBarWidth = 0
totalMargin = parentLayoutMargins[0] + parentLayoutMargins[2] + \
parentMargins[0]*2 + scrollBarWidth
idealWidth = self.parent.width() - totalMargin
pixSize = self.pixmap().size()
pixSize.scale(idealWidth, 1000000, Qt.KeepAspectRatio)
@ -32,6 +44,7 @@ class PDFViewer(QScrollArea):
self.setWidget(self.scrollAreaContents)
self.setWidgetResizable(True)
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.scrollAreaContents.setLayout(self.scrollAreaLayout)
self.pixmapList = []
@ -48,9 +61,8 @@ class PDFViewer(QScrollArea):
self.pixmapList = []
pdfView = fitz.Document(stream=pdf, filetype='pdf')
# render at 8x resolution and scale
for page in pdfView:
self.pixmapList.append(page.getPixmap(matrix=fitz.Matrix(8, 8), alpha=False))
self.pixmapList.append(page.get_pixmap(alpha=False))
def clear(self):
while self.scrollAreaLayout.count():
@ -64,11 +76,7 @@ class PDFViewer(QScrollArea):
label = PDFLabel(parent=self)
label.setAlignment(Qt.AlignHCenter)
qtimg = QImage(p.samples, p.width, p.height, p.stride, QImage.Format_RGB888)
# -45 because of various margins... value obtained by trial and error.
label.setPixmap(QPixmap.fromImage(qtimg))
self.scrollAreaLayout.addWidget(label)
self.scrollAreaLayout.addStretch(1)
# necessary on Mojave with PyInstaller (or previous contents will be shown)
self.repaint()
# self.scrollAreaLayout.addStretch(1)

27
chordsheet/tableView.py → csgui/tableView.py

@ -1,16 +1,35 @@
from PyQt5 import QtWidgets, QtGui
from PyQt5.QtCore import pyqtSignal, Qt, QModelIndex
class MItemModel(QtGui.QStandardItemModel):
"""
Special item model to ensure whole row is moved.
"""
itemsDropped = pyqtSignal()
def __init__(self):
super().__init__()
self.pendingRemoveRows = False
def dropMimeData(self, data, action, row, col, parent):
"""
Always move the entire row, and don't allow column "shifting"
"""
return super().dropMimeData(data, action, row, 0, parent)
ret = super().dropMimeData(data, Qt.MoveAction, row, 0, parent)
if ret:
self.pendingRemoveRows = True
return ret
def removeRows(self, row, count, index=QModelIndex()):
"""
Emit a signal after rows have been moved
"""
ret = super().removeRows(row, count, index)
if self.pendingRemoveRows:
self.itemsDropped.emit()
self.pendingRemoveRows = False
return ret
class MProxyStyle(QtWidgets.QProxyStyle):
@ -50,11 +69,13 @@ class MTableView(QtWidgets.QTableView):
self.setShowGrid(False)
# self.setDragDropMode(self.InternalMove)
# self.setDragDropOverwriteMode(False)
self.setDragDropOverwriteMode(False)
# Set our custom style - this draws the drop indicator across the whole row
self.setStyle(MProxyStyle())
def clear(self):
self.model.removeRows(0, self.model.rowCount())
class ChordTableView(MTableView):
"""

940
gui.py
File diff suppressed because it is too large
View File

BIN
preview.pdf

17
ui/aboutdialog.ui

@ -14,7 +14,7 @@
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
@ -25,10 +25,25 @@
<height>200</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>436</width>
<height>200</height>
</size>
</property>
<property name="windowTitle">
<string>About Chordsheet</string>
</property>
<property name="sizeGripEnabled">
<bool>false</bool>
</property>
<property name="modal">
<bool>true</bool>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="sizeConstraint">
<enum>QLayout::SetFixedSize</enum>
</property>
<item>
<layout class="QVBoxLayout" name="leftPane">
<item>

4
ui/blocks.ui

@ -270,12 +270,12 @@
<customwidget>
<class>BlockTableView</class>
<extends>QTableView</extends>
<header>chordsheet/tableView.h</header>
<header>csgui/tableView.h</header>
</customwidget>
<customwidget>
<class>MComboBox</class>
<extends>QComboBox</extends>
<header>chordsheet/comboBox.h</header>
<header>csgui/comboBox.h</header>
</customwidget>
</customwidgets>
<tabstops>

2
ui/chords.ui

@ -220,7 +220,7 @@
<customwidget>
<class>ChordTableView</class>
<extends>QTableView</extends>
<header>chordsheet/tableView.h</header>
<header>csgui/tableView.h</header>
</customwidget>
</customwidgets>
<tabstops>

4
ui/document.ui

@ -36,7 +36,7 @@
</property>
<property name="minimumSize">
<size>
<width>400</width>
<width>200</width>
<height>300</height>
</size>
</property>
@ -48,7 +48,7 @@
<customwidget>
<class>PDFViewer</class>
<extends>QWidget</extends>
<header>chordsheet/pdfViewer.h</header>
<header>csgui/pdfViewer.h</header>
<container>1</container>
</customwidget>
</customwidgets>

1071
ui/mainwindow.ui
File diff suppressed because it is too large
View File

233
ui/new.ui

@ -1,233 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1061</width>
<height>639</height>
</rect>
</property>
<property name="windowTitle">
<string>Chordsheet</string>
</property>
<property name="documentMode">
<bool>false</bool>
</property>
<property name="tabShape">
<enum>QTabWidget::Rounded</enum>
</property>
<widget class="QWidget" name="centralWidget">
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QMdiArea" name="mdiArea">
<property name="enabled">
<bool>true</bool>
</property>
<property name="documentMode">
<bool>true</bool>
</property>
<property name="tabsClosable">
<bool>true</bool>
</property>
<property name="tabsMovable">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menuBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1061</width>
<height>22</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
<property name="title">
<string>File</string>
</property>
<addaction name="actionNew"/>
<addaction name="actionOpen"/>
<addaction name="separator"/>
<addaction name="actionSave"/>
<addaction name="actionSave_as"/>
<addaction name="actionSave_PDF"/>
<addaction name="separator"/>
<addaction name="actionPrint"/>
<addaction name="separator"/>
<addaction name="actionClose"/>
</widget>
<widget class="QMenu" name="menuEdit">
<property name="title">
<string>Edit</string>
</property>
<addaction name="actionUndo"/>
<addaction name="actionRedo"/>
<addaction name="separator"/>
<addaction name="actionCut"/>
<addaction name="actionCopy"/>
<addaction name="actionPaste"/>
<addaction name="separator"/>
<addaction name="actionAbout"/>
</widget>
<widget class="QMenu" name="menuWindow">
<property name="title">
<string>Window</string>
</property>
<addaction name="actionDocument_information"/>
<addaction name="actionPage_setup"/>
<addaction name="actionChords"/>
<addaction name="actionSections"/>
<addaction name="actionBlocks"/>
<addaction name="separator"/>
<addaction name="actionPreview"/>
</widget>
<addaction name="menuFile"/>
<addaction name="menuEdit"/>
<addaction name="menuWindow"/>
</widget>
<action name="actionNew">
<property name="text">
<string>New...</string>
</property>
</action>
<action name="actionOpen">
<property name="text">
<string>Open...</string>
</property>
</action>
<action name="actionSave">
<property name="text">
<string>Save</string>
</property>
</action>
<action name="actionSave_PDF">
<property name="text">
<string>Save PDF...</string>
</property>
</action>
<action name="actionPrint">
<property name="text">
<string>Print...</string>
</property>
</action>
<action name="actionClose">
<property name="text">
<string>Close</string>
</property>
</action>
<action name="actionSave_as">
<property name="text">
<string>Save as...</string>
</property>
</action>
<action name="actionQuit">
<property name="text">
<string>Quit</string>
</property>
</action>
<action name="actionUndo">
<property name="text">
<string>Undo</string>
</property>
</action>
<action name="actionRedo">
<property name="text">
<string>Redo</string>
</property>
</action>
<action name="actionCut">
<property name="text">
<string>Cut</string>
</property>
</action>
<action name="actionCopy">
<property name="text">
<string>Copy</string>
</property>
</action>
<action name="actionPaste">
<property name="text">
<string>Paste</string>
</property>
</action>
<action name="actionPreferences">
<property name="text">
<string>Preferences</string>
</property>
</action>
<action name="actionAbout">
<property name="text">
<string>About</string>
</property>
</action>
<action name="actionDocument_information">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Document information</string>
</property>
</action>
<action name="actionPage_setup">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Page setup</string>
</property>
</action>
<action name="actionChords">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Chords</string>
</property>
</action>
<action name="actionSections">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Sections</string>
</property>
</action>
<action name="actionBlocks">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Blocks</string>
</property>
</action>
<action name="actionPreview">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Preview</string>
</property>
</action>
</widget>
<resources/>
<connections/>
</ui>

32
ui/pdfarea.ui

@ -1,32 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Form</class>
<widget class="QWidget" name="Form">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>PDF Viewer</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="PDFViewer" name="pdfArea" native="true"/>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>PDFViewer</class>
<extends>QWidget</extends>
<header>chordsheet/pdfViewer.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

42
ui/preview.ui

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>248</width>
<height>40</height>
<width>202</width>
<height>72</height>
</rect>
</property>
<property name="sizePolicy">
@ -18,31 +18,50 @@
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>40</height>
<width>202</width>
<height>72</height>
</size>
</property>
<property name="windowTitle">
<string>Preview</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="leftMargin">
<number>0</number>
<number>6</number>
</property>
<property name="topMargin">
<number>0</number>
<number>6</number>
</property>
<property name="rightMargin">
<number>0</number>
<number>6</number>
</property>
<property name="bottomMargin">
<number>0</number>
<number>6</number>
</property>
<item alignment="Qt::AlignHCenter">
<widget class="QCheckBox" name="autoUpdatePreviewCheckBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Automatically update preview</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
<item>
</widget>
</item>
<item alignment="Qt::AlignHCenter">
<widget class="QPushButton" name="updatePreviewButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
@ -52,6 +71,9 @@
<property name="text">
<string>Update preview</string>
</property>
<property name="checkable">
<bool>false</bool>
</property>
</widget>
</item>
</layout>

2
ui/sections.ui

@ -157,7 +157,7 @@
<customwidget>
<class>SectionTableView</class>
<extends>QTableView</extends>
<header>chordsheet/tableView.h</header>
<header>csgui/tableView.h</header>
</customwidget>
</customwidgets>
<resources/>

Loading…
Cancel
Save