66 Commits
49 changed files with 4723 additions and 1700 deletions
-
5.gitignore
-
33README.md
-
4_version.py
-
7chordsheet/common.py
-
61chordsheet/components/chordprogression.py
-
56chordsheet/components/guitarchart.py
-
4chordsheet/components/header.py
-
293chordsheet/document.py
-
44chordsheet/parsers.py
-
39chordsheet/primitives.py
-
709chordsheet/render.py
-
51chordsheet/rlStylesheet.py
-
84chordsheet/tableView.py
-
43cli.py
-
12csgui/comboBox.py
-
81csgui/dialogs.py
-
124csgui/messageBox.py
-
64csgui/panels.py
-
96csgui/pdfViewer.py
-
153csgui/tableView.py
-
6examples/ah.xml
-
309examples/ahlong.xml
-
1examples/angela.xml
-
135examples/example.xml
-
143examples/examplelong.xml
-
24examples/kissoflife.cma
-
1examples/kissoflife.xml
-
1examples/test.xml
-
15generate_version_rc.py
-
1315gui.py
-
47linux.spec
-
19mac.spec
-
4requirements.txt
-
142ui/aboutdialog.ui
-
291ui/blocks.ui
-
237ui/chords.ui
-
162ui/docinfo.ui
-
57ui/document.ui
-
BINui/icon.afdesign
-
BINui/icon.icns
-
BINui/icon.ico
-
BINui/icon.png
-
871ui/mainwindow.ui
-
83ui/preview.ui
-
326ui/psetup.ui
-
165ui/sections.ui
-
43version.rc
-
43version.rc.template
-
20win.spec
@ -0,0 +1,4 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
|
||||
|
appName = "Chordsheet" |
||||
|
version = '0.5.0' |
@ -0,0 +1,7 @@ |
|||||
|
import sys, os |
||||
|
|
||||
|
# set the directory where our files are depending on whether we're running a pyinstaller binary or not |
||||
|
if getattr(sys, 'frozen', False): |
||||
|
scriptDir = sys._MEIPASS |
||||
|
else: |
||||
|
scriptDir = os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)), os.pardir)) |
@ -1,61 +0,0 @@ |
|||||
# -*- coding: utf-8 -*- |
|
||||
|
|
||||
from reportlab.pdfgen import canvas |
|
||||
from reportlab.lib.units import mm |
|
||||
from reportlab.lib.pagesizes import A4 |
|
||||
from reportlab.pdfbase import pdfmetrics |
|
||||
from reportlab.pdfbase.ttfonts import TTFont |
|
||||
from reportlab.graphics.shapes import * |
|
||||
|
|
||||
from graphics.primitives import * |
|
||||
|
|
||||
class ChordProgression: |
|
||||
def __init__(self, currentCanvas, blockList, **kwargs): |
|
||||
self.currentCanvas = currentCanvas |
|
||||
|
|
||||
self.beatsHeight = kwargs.get('beatsHeight', 5*mm) |
|
||||
self.timeFontSize = kwargs.get('timeFontSize', 12) |
|
||||
self.chordNameFontSize = kwargs.get('chordNameFontSize', 18) |
|
||||
self.notesFontSize = kwargs.get('notesFontSize', 12) |
|
||||
self.unitWidth = kwargs.get('unitWidth', 10*mm) |
|
||||
self.unitHeight = kwargs.get('unitHeight', 20*mm) |
|
||||
|
|
||||
self.timeSignature = kwargs.get('timeSignature', 4) |
|
||||
def draw(self): |
|
||||
global cur_pos, margin, pagesize |
|
||||
writeText(self.currentCanvas, "Chord progression", size=18, align="left") |
|
||||
|
|
||||
v_origin = cur_pos + 2*mm + self.beatsHeight |
|
||||
h_origin = margin |
|
||||
|
|
||||
h_loc = 0 |
|
||||
v_loc = 0 |
|
||||
|
|
||||
maxWidth = int((((pagesize[0]-(2*margin))/self.unitWidth)//(self.timeSignature*2))*(self.timeSignature*2)) # use integer division to round maxWidth to nearest multiple of time signature |
|
||||
|
|
||||
for u in range(maxWidth+1): |
|
||||
s = 0 |
|
||||
x = u*self.unitWidth+margin |
|
||||
if u % self.timeSignature == 0: |
|
||||
e = -self.beatsHeight |
|
||||
else: |
|
||||
e = -self.beatsHeight/2 |
|
||||
drawVertLine(self.currentCanvas, s, e, x, h_origin, v_origin) |
|
||||
if u == maxWidth: # Avoid writing beat number after the final line |
|
||||
break |
|
||||
writeText(str((u % self.timeSignature)+1),size=self.timeFontSize, hpos=x+self.unitWidth/2, vpos=v_origin-self.beatsHeight) |
|
||||
|
|
||||
blockList = parseBlockList(self.blockList, maxWidth) |
|
||||
|
|
||||
for b in blockList: |
|
||||
if h_loc == maxWidth: |
|
||||
v_loc += 1 |
|
||||
h_loc = 0 |
|
||||
currentCanvas.rect(h_origin+(h_loc*self.unitWidth), v_origin+(v_loc*self.unitHeight), b[0]*self.unitWidth, self.unitHeight) |
|
||||
if b[2]: |
|
||||
writeText(currentCanvas, b[2], size=self.notesFontSize, hpos=h_origin+((h_loc+b[0]/2)*self.unitWidth), vpos=v_origin+((v_loc+1)*self.unitHeight)-(1.3*self.notesFontSize)) |
|
||||
v_offset = (v_loc*self.unitHeight+self.unitHeight/2)-self.chordNameFontSize/2 |
|
||||
writeText(currentCanvas, parseName(b[1]), size=self.chordNameFontSize, hpos=h_origin+((h_loc+b[0]/2)*self.unitWidth), vpos=v_origin+v_offset) |
|
||||
h_loc += b[0] |
|
||||
|
|
||||
cur_pos = v_origin+(v_loc+1)*self.unitHeight+self.beatsHeight |
|
@ -1,56 +0,0 @@ |
|||||
# -*- coding: utf-8 -*- |
|
||||
|
|
||||
from reportlab.pdfgen import canvas |
|
||||
from reportlab.lib.units import mm |
|
||||
from reportlab.lib.pagesizes import A4 |
|
||||
from reportlab.pdfbase import pdfmetrics |
|
||||
from reportlab.pdfbase.ttfonts import TTFont |
|
||||
from reportlab.graphics.shapes import * |
|
||||
|
|
||||
from graphics.primitives import * |
|
||||
|
|
||||
string_hz_sp = 20*mm |
|
||||
string_hz_gap = 2*mm |
|
||||
string_height = 5*mm |
|
||||
|
|
||||
def guitarChart(currentCanvas, string_hz_sp, string_hz_gap, string_height): |
|
||||
global cur_pos, margin, pagesize |
|
||||
|
|
||||
writeText("Guitar chord voicings", size=18, align="left") |
|
||||
|
|
||||
chartmargin = 15*mm |
|
||||
v_origin = cur_pos + 2*mm |
|
||||
h_origin = margin + chartmargin |
|
||||
nstrings = 6 |
|
||||
fontsize = 12 |
|
||||
|
|
||||
guitarChordList = [[chordList[q].guitar[r] for q in range(len(chordList)) if hasattr(chordList[q], 'guitar')] for r in range(6)] |
|
||||
guitarChordList.append([chordList[q].name for q in range(len(chordList))]) |
|
||||
|
|
||||
for i in range(nstrings+1): # i is the string currently being drawn |
|
||||
writeText(['e','B','G','D','A','E','Name'][i], size=fontsize, hpos=(h_origin), vpos=v_origin+(i*string_height), align='right') |
|
||||
|
|
||||
for j in range(len(ls.chords)): # j is which chord (0 is first chord, 1 is 2nd etc) |
|
||||
if j == 0: |
|
||||
charpos = string_hz_sp/2 |
|
||||
s = string_hz_gap |
|
||||
e = charpos-((c.stringWidth(chordList[i][j])/2)+string_hz_gap) |
|
||||
y = v_origin+(string_height*i)+string_height/2 |
|
||||
drawHorizLine(currentCanvas, s, e, y, h_origin, v_origin) |
|
||||
else: |
|
||||
charpos = string_hz_sp*(j+0.5) |
|
||||
s = charpos-string_hz_sp+(lastWidth/2+string_hz_gap) |
|
||||
e = charpos-((currentCanvas.stringWidth(chordList[i][j])/2)+string_hz_gap) |
|
||||
y = v_origin+(string_height*i)+string_height/2 |
|
||||
drawHorizLine(currentCanvas, s, e, y, h_origin, v_origin) |
|
||||
if j == len(ls.chords)-1: |
|
||||
s = charpos+(currentCanvas.stringWidth(chordList[i][j])/2+string_hz_gap) |
|
||||
e = charpos+string_hz_sp/2 |
|
||||
y = v_origin+(string_height*i)+string_height/2 |
|
||||
drawHorizLine(currentCanvas, s, e, y, h_origin, v_origin) |
|
||||
|
|
||||
writeText(chordList[i][j], size=fontsize, hpos=h_origin+charpos, vpos=v_origin+(i*string_height)) |
|
||||
|
|
||||
lastWidth = currentCanvas.stringWidth(chordList[i][j]) |
|
||||
|
|
||||
cur_pos += (string_height*(nstrings+2)) |
|
@ -1,4 +0,0 @@ |
|||||
def header(): |
|
||||
writeText(ls.title.cdata, size=24) |
|
||||
writeText("Composer: {c}".format(c = ls.composer.cdata), size=12) |
|
||||
writeText("Arranger: {a}".format(a = ls.arranger.cdata), size=12) |
|
@ -1,25 +1,33 @@ |
|||||
# -*- coding: utf-8 -*- |
# -*- coding: utf-8 -*- |
||||
|
|
||||
from sys import exit |
|
||||
|
|
||||
def parseFingering(fingering, instrument): |
def parseFingering(fingering, instrument): |
||||
if instrument == 'guitar': |
|
||||
numStrings = 6 |
|
||||
if len(fingering) == numStrings: |
|
||||
output = list(fingering) |
|
||||
else: |
|
||||
output = [x for x in fingering.split(',')] |
|
||||
if len(output) == numStrings: |
|
||||
return output |
|
||||
else: |
|
||||
exit("Voicing <{v}> is malformed.".format(v=fingering)) |
|
||||
else: |
|
||||
return [fingering] |
|
||||
|
""" |
||||
|
Converts fingerings into the list format that Chord objects understand. |
||||
|
""" |
||||
|
if instrument == 'guitar': |
||||
|
numStrings = 6 |
||||
|
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: |
||||
|
print("Voicing <{}> is malformed.".format(fingering)) |
||||
|
return output |
||||
|
elif instrument == 'piano': |
||||
|
return [parseName(note).upper().strip() for note in fingering.split(",")] |
||||
|
else: |
||||
|
return [fingering] |
||||
|
|
||||
nameReplacements = { "b":"♭", "#":"♯" } |
|
||||
|
|
||||
|
# dictionary holding text to be replaced in chord names |
||||
|
nameReplacements = {"b": "♭", "#": "♯"} |
||||
|
|
||||
def parseName(chordName): |
def parseName(chordName): |
||||
parsedName = chordName |
|
||||
for i, j in nameReplacements.items(): |
|
||||
parsedName = parsedName.replace(i, j) |
|
||||
return parsedName |
|
||||
|
""" |
||||
|
Replaces symbols in chord names. |
||||
|
""" |
||||
|
parsedName = chordName |
||||
|
for i, j in nameReplacements.items(): |
||||
|
parsedName = parsedName.replace(i, j) |
||||
|
return parsedName |
@ -1,39 +0,0 @@ |
|||||
# -*- coding: utf-8 -*- |
|
||||
|
|
||||
from reportlab.pdfgen import canvas |
|
||||
from reportlab.lib.units import mm |
|
||||
from reportlab.graphics.shapes import * |
|
||||
|
|
||||
def writeText(currentCanvas, style, string, size, vpos, **kwargs): |
|
||||
margin = style.leftMargin*style.unit |
|
||||
|
|
||||
align = kwargs.get('align', 'centre') |
|
||||
if align == 'centre' or align == 'center': |
|
||||
hpos = kwargs.get('hpos', style.pageSize[0]/2) |
|
||||
elif align == 'left': |
|
||||
hpos = kwargs.get('hpos', margin) |
|
||||
elif align == 'right': |
|
||||
hpos = kwargs.get('hpos', style.pageSize[0]-margin) |
|
||||
spacing = kwargs.get('spacing', style.lineSpacing) |
|
||||
|
|
||||
currentCanvas.setFont(style.font, size) |
|
||||
|
|
||||
if align == 'centre' or align == 'center': |
|
||||
currentCanvas.drawCentredString(hpos, vpos+(0.75*size*spacing),string) |
|
||||
elif align == 'left': |
|
||||
currentCanvas.drawString(hpos, vpos+(0.75*size*spacing),string) |
|
||||
elif align == 'right': |
|
||||
currentCanvas.drawString(hpos-currentCanvas.stringWidth(string), vpos+(0.75*size*spacing),string) |
|
||||
|
|
||||
return size*style.lineSpacing |
|
||||
|
|
||||
def drawHorizLine(currentCanvas, startpoint, endpoint, v_pos, h_origin, v_origin): |
|
||||
x1 = h_origin+startpoint |
|
||||
x2 = h_origin+endpoint |
|
||||
currentCanvas.line(x1, v_pos, x2, v_pos) |
|
||||
|
|
||||
def drawVertLine(currentCanvas, startpoint, endpoint, h_pos, h_origin, v_origin): |
|
||||
y1 = v_origin+startpoint |
|
||||
y2 = v_origin+endpoint |
|
||||
currentCanvas.line(h_pos, y1, h_pos, y2) |
|
||||
|
|
@ -1,161 +1,560 @@ |
|||||
# -*- coding: utf-8 -*- |
# -*- coding: utf-8 -*- |
||||
|
|
||||
|
from math import trunc, ceil |
||||
|
from io import BytesIO |
||||
|
|
||||
from reportlab.pdfgen import canvas |
from reportlab.pdfgen import canvas |
||||
from reportlab.lib.units import mm |
from reportlab.lib.units import mm |
||||
from reportlab.graphics.shapes import * |
|
||||
from chordsheet.primitives import writeText, drawVertLine, drawHorizLine |
|
||||
|
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle |
||||
|
from reportlab.lib.colors import black, white |
||||
|
from reportlab.platypus import BaseDocTemplate, Spacer, Paragraph, Flowable, Frame, PageTemplate, PageBreak |
||||
|
|
||||
from chordsheet.document import Block |
from chordsheet.document import Block |
||||
|
from chordsheet.rlStylesheet import getStyleSheet |
||||
|
|
||||
|
defaultSpacing = 1.15 |
||||
|
|
||||
|
def writeText(canvas, style, string, size, vpos, width, **kwargs): |
||||
|
""" |
||||
|
Wrapper function to conveniently write text and return how much vertical space it took up. |
||||
|
""" |
||||
|
|
||||
|
align = kwargs.get('align', 'centre') |
||||
|
if align == 'centre' or align == 'center': |
||||
|
hpos = kwargs.get('hpos', width/2) |
||||
|
elif align == 'left': |
||||
|
hpos = kwargs.get('hpos', 0) |
||||
|
elif align == 'right': |
||||
|
hpos = kwargs.get('hpos', width) |
||||
|
spacing = kwargs.get('spacing', style.lineSpacing) |
||||
|
|
||||
|
canvas.setFont(style.font, size) |
||||
|
|
||||
|
if align == 'centre' or align == 'center': |
||||
|
canvas.drawCentredString(hpos, vpos-(0.75*size*spacing), string) |
||||
|
elif align == 'left': |
||||
|
canvas.drawString(hpos, vpos-(0.75*size*spacing), string) |
||||
|
elif align == 'right': |
||||
|
canvas.drawString(hpos-canvas.stringWidth(string), |
||||
|
vpos-(0.75*size*spacing), string) |
||||
|
|
||||
|
return size*style.lineSpacing |
||||
|
|
||||
|
|
||||
|
class Tempo(Flowable): |
||||
|
""" |
||||
|
Flowable that draws the tempo. Necessary because Paragraph does not support the crotchet character. |
||||
|
""" |
||||
|
|
||||
|
def __init__(self, tempo, paraStyle): |
||||
|
self.tempo = tempo |
||||
|
self.text = "♩ = {t} bpm".format(t=self.tempo) |
||||
|
self.fontSize = paraStyle.fontSize |
||||
|
self.fontName = paraStyle.fontName |
||||
|
self.leading = paraStyle.leading |
||||
|
|
||||
|
def wrap(self, availWidth, availHeight): |
||||
|
self.width = availWidth |
||||
|
self.height = self.leading |
||||
|
return (self.width, self.height) |
||||
|
|
||||
|
def draw(self): |
||||
|
canvas = self.canv |
||||
|
canvas.setFont(self.fontName, self.fontSize) |
||||
|
canvas.drawString(0, self.leading * 0.25, self.text) |
||||
|
|
||||
|
|
||||
|
class GuitarChart(Flowable): |
||||
|
""" |
||||
|
Flowable that draws a guitar chord voicing chart. |
||||
|
""" |
||||
|
|
||||
|
def __init__(self, style, chordList): |
||||
|
self.style = style |
||||
|
self.guitarChordList = [ |
||||
|
c for c in chordList if 'guitar' in c.voicings.keys()] |
||||
|
self.chartMargin = 13*mm |
||||
|
self.nStrings = 6 |
||||
|
|
||||
|
self.stringHzSp = 20*mm |
||||
|
self.stringHzGap = 2*mm |
||||
|
self.stringHeight = 5*mm |
||||
|
|
||||
|
self.spaceAfter = self.style.separatorSize |
||||
|
|
||||
|
def splitChordList(self, l, n): |
||||
|
"""Yield successive n-sized chunks from l.""" |
||||
|
for i in range(0, len(l), n): |
||||
|
yield l[i:i + n] |
||||
|
|
||||
|
def wrap(self, availWidth, availHeight): |
||||
|
self.nChords = trunc((availWidth - self.chartMargin - |
||||
|
self.stringHzGap) / self.stringHzSp) |
||||
|
# the height of one layer of chart |
||||
|
self.oneHeight = self.stringHeight * (self.nStrings+1) |
||||
|
# only one line needed |
||||
|
if len(self.guitarChordList) <= self.nChords: |
||||
|
self.width = self.chartMargin + self.stringHzGap + self.stringHzSp * \ |
||||
|
len(self.guitarChordList) # calculate the width |
||||
|
self.height = self.oneHeight # and its height |
||||
|
# multiple lines needed |
||||
|
else: |
||||
|
self.width = self.chartMargin + self.stringHzGap + \ |
||||
|
self.stringHzSp * self.nChords |
||||
|
self.height = self.oneHeight * ceil(len(self.guitarChordList) / self.nChords) + \ |
||||
|
(self.stringHeight * |
||||
|
trunc(len(self.guitarChordList) / self.nChords)) |
||||
|
return (self.width, self.height) |
||||
|
|
||||
|
def draw(self): |
||||
|
canvas = self.canv |
||||
|
chartmargin = self.chartMargin |
||||
|
|
||||
|
for count, gcl in enumerate(self.splitChordList(self.guitarChordList, self.nChords)): |
||||
|
v_origin = self.height - count * \ |
||||
|
(self.oneHeight + self.stringHeight) |
||||
|
|
||||
|
self.nStrings = 6 |
||||
|
fontsize = 12 |
||||
|
|
||||
|
stringList = [ |
||||
|
[c.voicings['guitar'][-(r+1)] for c in gcl] for r in range(self.nStrings)] |
||||
|
stringList.append([c.name for c in gcl]) |
||||
|
|
||||
|
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', spacing=defaultSpacing) |
||||
|
|
||||
|
# j is which chord (0 is first chord, 1 is 2nd etc) |
||||
|
for j in range(len(stringList[-1])): |
||||
|
currentWidth = canvas.stringWidth(stringList[i][j]) |
||||
|
if j == 0: |
||||
|
x = self.stringHzGap + chartmargin |
||||
|
l = self.stringHzSp/2 - self.stringHzGap - \ |
||||
|
((currentWidth/2)) - self.stringHzGap |
||||
|
y = v_origin-(self.stringHeight*i) - \ |
||||
|
self.stringHeight/2 |
||||
|
canvas.line(x, y, x+l, y) |
||||
|
else: |
||||
|
x = chartmargin + self.stringHzSp * \ |
||||
|
(j-0.5)+(lastWidth/2+self.stringHzGap) |
||||
|
l = self.stringHzSp - currentWidth / \ |
||||
|
2 - lastWidth/2 - self.stringHzGap*2 |
||||
|
y = v_origin-(self.stringHeight*i) - \ |
||||
|
self.stringHeight/2 |
||||
|
canvas.line(x, y, x+l, y) |
||||
|
|
||||
|
if j == len(stringList[-1])-1: |
||||
|
x = chartmargin + self.stringHzSp * \ |
||||
|
(j+0.5) + currentWidth/2 + self.stringHzGap |
||||
|
l = self.stringHzSp/2 - currentWidth/2 - self.stringHzGap |
||||
|
y = v_origin-(self.stringHeight*i) - \ |
||||
|
self.stringHeight/2 |
||||
|
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), spacing=defaultSpacing) |
||||
|
|
||||
|
lastWidth = currentWidth |
||||
|
|
||||
|
|
||||
|
class PianoChart(Flowable): |
||||
|
""" |
||||
|
Flowable that draws a series of piano chord charts. |
||||
|
""" |
||||
|
|
||||
|
def __init__(self, style, chordList): |
||||
|
self.style = style |
||||
|
self.pianoChordList = [ |
||||
|
c for c in chordList if 'piano' in c.voicings.keys()] |
||||
|
|
||||
|
self.whiteKeyWidth = 2.5 * mm |
||||
|
self.blackKeyWidth = 1.5 * mm |
||||
|
self.whiteKeyHeight = 10 * mm |
||||
|
self.blackKeyHeight = 5.5 * mm |
||||
|
self.dotRadius = 0.5 * mm |
||||
|
|
||||
|
self.chartMargin = 0.7 * mm |
||||
|
self.iconHzSpacing = 5 * mm |
||||
|
self.vSpacing = 2*mm |
||||
|
|
||||
|
self.indicatorFontSize = 8 |
||||
|
self.chordNameFontSize = 12 |
||||
|
self.lineSpacing = 1.15 |
||||
|
|
||||
|
self.keyDict = {'A': 'white', 'A♯': 'black', 'B': 'white', 'C': 'white', 'C♯': 'black', 'D': 'white', |
||||
|
'D♯': 'black', 'E': 'white', 'F': 'white', 'F♯': 'black', 'G': 'white', 'G♯': 'black'} |
||||
|
self.keyList = list(self.keyDict.keys()) |
||||
|
|
||||
|
self.spaceAfter = self.style.separatorSize |
||||
|
|
||||
|
def wrap(self, availWidth, availHeight): |
||||
|
self.availWidth = availWidth |
||||
|
vUnits = 1 |
||||
|
currentWidth = self.chartMargin |
||||
|
widest = 0 |
||||
|
for index, c in enumerate(self.pianoChordList): |
||||
|
cKL, vL, fKN, iconWidth = self.calculate(c) |
||||
|
if currentWidth + iconWidth >= availWidth: |
||||
|
vUnits += 1 |
||||
|
currentWidth = self.chartMargin |
||||
|
else: |
||||
|
currentWidth += self.iconHzSpacing |
||||
|
currentWidth += iconWidth |
||||
|
|
||||
|
if currentWidth > widest: |
||||
|
widest = currentWidth |
||||
|
if vUnits == 1: |
||||
|
widest -= self.iconHzSpacing # chop off the trailing space |
||||
|
self.oneHeight = self.chordNameFontSize * self.lineSpacing + \ |
||||
|
self.whiteKeyHeight + self.indicatorFontSize * self.lineSpacing |
||||
|
|
||||
|
self.width = widest |
||||
|
self.height = self.oneHeight * vUnits + self.vSpacing * (vUnits - 1) |
||||
|
return (self.width, self.height) |
||||
|
|
||||
|
def replaceFlats(self, fingering): |
||||
|
# note name replacements |
||||
|
noteReplacements = {"B♭": "A♯", "D♭": "C♯", |
||||
|
"E♭": "D♯", "G♭": "F♯", "A♭": "G♯"} |
||||
|
|
||||
|
parsedFingering = [] |
||||
|
for key in fingering: |
||||
|
parsedFingering.append(noteReplacements.get(key, key)) |
||||
|
|
||||
|
return parsedFingering |
||||
|
|
||||
|
def splitChordList(self, chordList, width): |
||||
|
bigList = [] |
||||
|
currentList = [] |
||||
|
currentWidth = self.chartMargin |
||||
|
for c in self.pianoChordList: |
||||
|
cKL, vL, fKN, iconWidth = self.calculate(c) |
||||
|
|
||||
|
if currentWidth + iconWidth >= width + self.iconHzSpacing: |
||||
|
bigList.append(currentList) |
||||
|
currentList = [c] |
||||
|
currentWidth = self.chartMargin |
||||
|
else: |
||||
|
currentList.append(c) |
||||
|
currentWidth += self.iconHzSpacing |
||||
|
currentWidth += iconWidth |
||||
|
|
||||
|
bigList.append(currentList) |
||||
|
return bigList |
||||
|
|
||||
|
def calculate(self, c): |
||||
|
voicingList = self.replaceFlats(c.voicings['piano']) |
||||
|
# save this as we convert all the flats to sharps, but the user would probably like to see the name they entered... |
||||
|
firstKeyName = c.voicings['piano'][0] |
||||
|
chartKeyList = [] |
||||
|
|
||||
|
# get the list of keys to be drawn for each chord |
||||
|
for count, note in enumerate(voicingList): |
||||
|
if count == 0: |
||||
|
curIndex = self.keyList.index(note) |
||||
|
if self.keyDict[self.keyList[curIndex-1]] == 'black': |
||||
|
chartKeyList.append( |
||||
|
self.keyList[curIndex-2]) # don't start on a black key |
||||
|
chartKeyList.append(self.keyList[curIndex-1]) # the key before |
||||
|
|
||||
|
chartKeyList.append(note) |
||||
|
else: |
||||
|
lastIndex = self.keyList.index(lastNote) |
||||
|
curIndex = self.keyList.index(note) |
||||
|
|
||||
|
if curIndex > lastIndex and curIndex != 11: |
||||
|
chartKeyList.extend( |
||||
|
self.keyList[lastIndex+1:((curIndex+1) % len(self.keyList))]) |
||||
|
elif curIndex < lastIndex or curIndex == 11: |
||||
|
chartKeyList.extend(self.keyList[lastIndex+1:]) |
||||
|
chartKeyList.extend( |
||||
|
self.keyList[0:((curIndex+1) % len(self.keyList))]) |
||||
|
else: |
||||
|
chartKeyList.append(note) |
||||
|
|
||||
|
if count == len(voicingList) - 1: |
||||
|
curIndex = self.keyList.index(note) |
||||
|
chartKeyList.append( |
||||
|
self.keyList[((curIndex+1) % len(self.keyList))]) |
||||
|
# don't finish on a black key |
||||
|
if self.keyDict[self.keyList[((curIndex+1) % len(self.keyList))]] == 'black': |
||||
|
chartKeyList.append( |
||||
|
self.keyList[((curIndex+2) % len(self.keyList))]) |
||||
|
|
||||
|
lastNote = note |
||||
|
|
||||
|
iconWidth = sum([self.whiteKeyWidth if self.keyDict[k] |
||||
|
== 'white' else 0 for k in chartKeyList]) |
||||
|
|
||||
|
return chartKeyList, voicingList, firstKeyName, iconWidth |
||||
|
|
||||
|
def draw(self): |
||||
|
canvas = self.canv |
||||
|
|
||||
|
for index, cL in enumerate(self.splitChordList(self.pianoChordList, self.width)): |
||||
|
h_offset = self.chartMargin |
||||
|
v_offset = self.height - self.oneHeight * index - self.vSpacing * \ |
||||
|
index - self.chordNameFontSize * self.lineSpacing |
||||
|
|
||||
|
for c in cL: |
||||
|
chartKeyList, voicingList, firstKeyName, iconWidth = self.calculate( |
||||
|
c) |
||||
|
# draw chord names |
||||
|
canvas.setFont(self.style.font, self.chordNameFontSize) |
||||
|
canvas.drawCentredString(h_offset + iconWidth/2, v_offset+( |
||||
|
0.3*self.chordNameFontSize*self.lineSpacing), c.name) |
||||
|
|
||||
|
# draw the keys |
||||
|
count = 0 |
||||
|
for key in chartKeyList: |
||||
|
if self.keyDict[key] == 'white': |
||||
|
canvas.rect(h_offset + (count*self.whiteKeyWidth), v_offset - |
||||
|
self.whiteKeyHeight, self.whiteKeyWidth, self.whiteKeyHeight) |
||||
|
count += 1 |
||||
|
elif self.keyDict[key] == 'black': |
||||
|
canvas.rect(h_offset + (count*self.whiteKeyWidth) - (self.blackKeyWidth/2), |
||||
|
v_offset-self.blackKeyHeight, self.blackKeyWidth, self.blackKeyHeight, fill=1) |
||||
|
|
||||
|
# draw the indicator dots |
||||
|
count = 0 |
||||
|
dotCount = 0 |
||||
|
for key in chartKeyList: |
||||
|
if self.keyDict[key] == 'white': |
||||
|
count += 1 |
||||
|
if len(voicingList) > dotCount and key == voicingList[dotCount]: |
||||
|
hpos = h_offset + \ |
||||
|
(count*self.whiteKeyWidth) - \ |
||||
|
(self.whiteKeyWidth/2) |
||||
|
if dotCount == 0: |
||||
|
canvas.setFont(self.style.font, |
||||
|
self.indicatorFontSize) |
||||
|
canvas.drawCentredString( |
||||
|
hpos, v_offset - self.whiteKeyHeight*1.3, firstKeyName) |
||||
|
dotCount += 1 |
||||
|
canvas.circle(hpos, v_offset - self.whiteKeyHeight + (self.whiteKeyWidth/2), |
||||
|
self.dotRadius, stroke=0, fill=1) |
||||
|
elif self.keyDict[key] == 'black': |
||||
|
if len(voicingList) > dotCount and key == voicingList[dotCount]: |
||||
|
hpos = h_offset + \ |
||||
|
(count*self.whiteKeyWidth) |
||||
|
if dotCount == 0: |
||||
|
canvas.setFont(self.style.font, |
||||
|
self.indicatorFontSize) |
||||
|
canvas.drawCentredString( |
||||
|
hpos, v_offset - self.whiteKeyHeight*1.3, firstKeyName) |
||||
|
dotCount += 1 |
||||
|
canvas.setFillColor(white) |
||||
|
canvas.circle(hpos, v_offset - self.blackKeyHeight + (self.blackKeyWidth/2), |
||||
|
self.dotRadius, stroke=0, fill=1) |
||||
|
canvas.setFillColor(black) |
||||
|
|
||||
|
h_offset += iconWidth + self.iconHzSpacing |
||||
|
|
||||
|
|
||||
|
class ChordProgression(Flowable): |
||||
|
""" |
||||
|
Flowable that draws a chord progression made up of blocks. |
||||
|
""" |
||||
|
|
||||
|
def __init__(self, style, heading, blockList, timeSignature): |
||||
|
self.style = style |
||||
|
self.heading = heading # the title of the section |
||||
|
self.blockList = blockList |
||||
|
self.timeSignature = timeSignature |
||||
|
self.chartMargin = 0.7*mm # kludge factor to account for line width |
||||
|
|
||||
|
self.unitHeight = 20*mm |
||||
|
self.beatsHeight = 5*mm |
||||
|
|
||||
|
self.spaceAfter = self.style.separatorSize |
||||
|
|
||||
|
def wrapBlocks(self, blockList, maxWidth): |
||||
|
""" |
||||
|
Splits any blocks that won't fit in the remaining space on the line. |
||||
|
""" |
||||
|
h_loc = 0 |
||||
|
splitBlockList = [] |
||||
|
for i in range(len(blockList)): |
||||
|
c_orig = blockList[i].chord |
||||
|
n_orig = blockList[i].notes |
||||
|
if h_loc == maxWidth: |
||||
|
h_loc = 0 |
||||
|
if h_loc+blockList[i].length > maxWidth: |
||||
|
lengthList = [maxWidth - h_loc] |
||||
|
while sum(lengthList) < blockList[i].length: |
||||
|
if blockList[i].length - sum(lengthList) >= maxWidth: |
||||
|
lengthList.append(maxWidth) |
||||
|
else: |
||||
|
lengthList.append( |
||||
|
blockList[i].length - sum(lengthList)) |
||||
|
|
||||
|
for l in lengthList: |
||||
|
# create a block with the given length |
||||
|
splitBlockList.append(Block(l, chord=c_orig, notes=n_orig)) |
||||
|
|
||||
|
h_loc = lengthList[-1] |
||||
|
else: |
||||
|
splitBlockList.append(blockList[i]) |
||||
|
h_loc += blockList[i].length |
||||
|
return splitBlockList |
||||
|
|
||||
|
def splitBlockList(self, blockList, length): |
||||
|
""" |
||||
|
Splits a blockList into two lists, one of the given length (in beats) and one for the rest. Also wraps the blocks to |
||||
|
given length in case the split would fall in the middle of one. |
||||
|
""" |
||||
|
secondPart = self.wrapBlocks(blockList, length) |
||||
|
firstPart = [] |
||||
|
currentBeat = 0 |
||||
|
while currentBeat != length: |
||||
|
block = secondPart.pop(0) |
||||
|
firstPart.append(block) |
||||
|
currentBeat += block.length |
||||
|
|
||||
|
return firstPart, secondPart |
||||
|
|
||||
|
def wrap(self, availWidth, availHeight): |
||||
|
self.widthInBeats = 2 * self.timeSignature * \ |
||||
|
trunc((availWidth/(self.style.unitWidth*self.style.unit)) / |
||||
|
(2*self.timeSignature)) # width of each line, in beats |
||||
|
self.width = self.widthInBeats * self.style.unitWidth * self.style.unit |
||||
|
self.height = self.beatsHeight + self.unitHeight * \ |
||||
|
sum([b.length for b in self.blockList]) / self.widthInBeats |
||||
|
return(self.width, self.height) |
||||
|
|
||||
|
def split(self, availWidth, availHeight): |
||||
|
if availHeight >= self.height: |
||||
|
return [self] |
||||
|
else: |
||||
|
vUnits = trunc( |
||||
|
(availHeight - self.beatsHeight) / self.unitHeight) |
||||
|
firstPart, secondPart = self.splitBlockList( |
||||
|
self.blockList, vUnits * self.widthInBeats) |
||||
|
|
||||
|
return [ChordProgression(self.style, self.heading, firstPart, self.timeSignature), |
||||
|
PageBreak(), |
||||
|
ChordProgression(self.style, self.heading, secondPart, self.timeSignature)] |
||||
|
|
||||
|
def draw(self): |
||||
|
canvas = self.canv |
||||
|
unitWidth = self.style.unitWidth*self.style.unit |
||||
|
|
||||
|
v_origin = self.height - self.beatsHeight |
||||
|
h_offset = self.chartMargin |
||||
|
|
||||
|
h_loc = 0 |
||||
|
v_loc = 0 |
||||
|
|
||||
|
maxWidth = self.widthInBeats |
||||
|
|
||||
|
for u in range(maxWidth+1): |
||||
|
y = v_origin |
||||
|
x = u*unitWidth + h_offset |
||||
|
if u % self.timeSignature == 0: |
||||
|
l = self.beatsHeight |
||||
|
else: |
||||
|
l = self.beatsHeight/2 |
||||
|
canvas.line(x, y, x, y+l) |
||||
|
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, spacing=defaultSpacing) |
||||
|
|
||||
|
parsedBlockList = self.wrapBlocks(self.blockList, maxWidth) |
||||
|
|
||||
|
for b in parsedBlockList: |
||||
|
if h_loc == maxWidth: |
||||
|
v_loc += 1 |
||||
|
h_loc = 0 |
||||
|
canvas.rect(h_offset+h_loc*unitWidth, v_origin-((v_loc+1)*self.unitHeight), |
||||
|
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), 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), spacing=defaultSpacing) |
||||
|
h_loc += b.length |
||||
|
|
||||
|
|
||||
|
def instChartCheck(cL, inst): |
||||
|
""" |
||||
|
Check if a file contains a chord chart for a certain instrument. |
||||
|
""" |
||||
|
chordsPresent = False |
||||
|
for c in cL: |
||||
|
if inst in c.voicings.keys(): |
||||
|
chordsPresent = True |
||||
|
break |
||||
|
return chordsPresent |
||||
|
|
||||
|
|
||||
|
class Renderer: |
||||
|
def __init__(self, document, style): |
||||
|
self.document = document |
||||
|
self.style = style |
||||
|
|
||||
|
def savePDF(self, pathToPDF): |
||||
|
template = PageTemplate(id='AllPages', frames=[Frame(self.style.leftMargin*mm, self.style.bottomMargin*mm, |
||||
|
self.style.pageSize[0] - self.style.leftMargin * |
||||
|
mm - self.style.rightMargin*mm, |
||||
|
self.style.pageSize[1] - self.style.topMargin * |
||||
|
mm - self.style.bottomMargin*mm, |
||||
|
leftPadding=0, bottomPadding=0, rightPadding=0, topPadding=0)]) |
||||
|
|
||||
|
rlDocList = [] |
||||
|
rlDoc = BaseDocTemplate( |
||||
|
pathToPDF, pagesize=self.style.pageSize, pageTemplates=[template]) |
||||
|
|
||||
|
styles = getStyleSheet(self.style) |
||||
|
|
||||
|
if self.document.title: |
||||
|
rlDocList.append(Paragraph(self.document.title, styles['Title'])) |
||||
|
|
||||
|
if self.document.subtitle: |
||||
|
rlDocList.append( |
||||
|
Paragraph(self.document.subtitle, styles['Subtitle'])) |
||||
|
|
||||
|
if self.document.composer or self.document.arranger: |
||||
|
rlDocList.append(Spacer(0, 2*mm)) |
||||
|
|
||||
|
if self.document.composer: |
||||
|
rlDocList.append(Paragraph("Composer: {c}".format( |
||||
|
c=self.document.composer), styles['Credits'])) |
||||
|
|
||||
|
if self.document.arranger: |
||||
|
rlDocList.append(Paragraph("Arranger: {a}".format( |
||||
|
a=self.document.arranger), styles['Credits'])) |
||||
|
|
||||
|
if self.document.tempo: |
||||
|
rlDocList.append(Tempo(self.document.tempo, styles['Tempo'])) |
||||
|
|
||||
|
if self.document.title or self.document.subtitle or self.document.composer or self.document.arranger or self.document.tempo: |
||||
|
rlDocList.append(Spacer(0, self.style.separatorSize)) |
||||
|
|
||||
|
if instChartCheck(self.document.chordList, 'guitar'): |
||||
|
rlDocList.extend([ |
||||
|
Paragraph('Guitar chord voicings', styles['Heading']), |
||||
|
GuitarChart(self.style, self.document.chordList)]) |
||||
|
|
||||
|
if instChartCheck(self.document.chordList, 'piano'): |
||||
|
rlDocList.extend([ |
||||
|
Paragraph('Piano chord voicings', styles['Heading']), |
||||
|
PianoChart(self.style, self.document.chordList)]) |
||||
|
|
||||
|
for s in self.document.sectionList: |
||||
|
rlDocList.append(Paragraph(s.name, styles['Heading'])) |
||||
|
# only draw the chord progression if there are blocks |
||||
|
if s.blockList: |
||||
|
rlDocList.append(ChordProgression( |
||||
|
self.style, s.name, s.blockList, self.document.timeSignature)) |
||||
|
|
||||
|
rlDoc.build(rlDocList) |
||||
|
|
||||
def splitBlocks(blockList, maxWidth): |
|
||||
h_loc = 0 |
|
||||
splitBlockList = [] |
|
||||
for i in range(len(blockList)): |
|
||||
c_orig = blockList[i].chord |
|
||||
n_orig = blockList[i].notes |
|
||||
if h_loc == maxWidth: |
|
||||
h_loc = 0 |
|
||||
if h_loc+blockList[i].length > maxWidth: |
|
||||
lengthList = [maxWidth - h_loc] |
|
||||
while sum(lengthList) < blockList[i].length: |
|
||||
if blockList[i].length - sum(lengthList) >= maxWidth: |
|
||||
lengthList.append(maxWidth) |
|
||||
else: |
|
||||
lengthList.append(blockList[i].length - sum(lengthList)) |
|
||||
|
|
||||
for l in lengthList: |
|
||||
splitBlockList.append(Block(l, chord=c_orig, notes=n_orig)) # create a block with the given length |
|
||||
|
|
||||
h_loc = lengthList[-1] |
|
||||
else: |
|
||||
splitBlockList.append(blockList[i]) |
|
||||
h_loc += blockList[i].length |
|
||||
return splitBlockList |
|
||||
|
|
||||
def guitarChart(currentCanvas, style, chordList, cur_pos): |
|
||||
title_height = writeText(currentCanvas, style, "Guitar chord voicings", 18, cur_pos, align="left") |
|
||||
cur_pos += title_height |
|
||||
|
|
||||
string_hz_sp = style.stringHzSp |
|
||||
string_hz_gap = style.stringHzGap |
|
||||
string_height = style.stringHeight |
|
||||
|
|
||||
margin = style.leftMargin*style.unit |
|
||||
pagesize = style.pageSize |
|
||||
|
|
||||
chartmargin = 15*mm |
|
||||
v_origin = cur_pos + 2*mm |
|
||||
h_origin = margin + chartmargin |
|
||||
nstrings = 6 |
|
||||
fontsize = 12 |
|
||||
|
|
||||
guitarChordList = [[chordList[q].voicings['guitar'][-(r+1)] for q in range(len(chordList)) if 'guitar' in chordList[q].voicings.keys()] for r in range(nstrings)] |
|
||||
guitarChordList.append([chordList[q].name for q in range(len(chordList)) if 'guitar' in chordList[q].voicings.keys()]) |
|
||||
|
|
||||
for i in range(nstrings+1): # i is the string currently being drawn |
|
||||
writeText(currentCanvas, style, ['e','B','G','D','A','E','Name'][i], fontsize, v_origin+(i*string_height), hpos=h_origin, align='right') |
|
||||
|
|
||||
for j in range(len(guitarChordList[-1])): # j is which chord (0 is first chord, 1 is 2nd etc) |
|
||||
if j == 0: |
|
||||
charpos = string_hz_sp/2 |
|
||||
s = string_hz_gap |
|
||||
e = charpos-((currentCanvas.stringWidth(guitarChordList[i][j])/2)+string_hz_gap) |
|
||||
y = v_origin+(string_height*i)+string_height/2 |
|
||||
drawHorizLine(currentCanvas, s, e, y, h_origin, v_origin) |
|
||||
else: |
|
||||
charpos = string_hz_sp*(j+0.5) |
|
||||
s = charpos-string_hz_sp+(lastWidth/2+string_hz_gap) |
|
||||
e = charpos-((currentCanvas.stringWidth(guitarChordList[i][j])/2)+string_hz_gap) |
|
||||
y = v_origin+(string_height*i)+string_height/2 |
|
||||
drawHorizLine(currentCanvas, s, e, y, h_origin, v_origin) |
|
||||
|
|
||||
if j == len(guitarChordList[-1])-1: |
|
||||
s = charpos+(currentCanvas.stringWidth(guitarChordList[i][j])/2+string_hz_gap) |
|
||||
e = charpos+string_hz_sp/2 |
|
||||
y = v_origin+(string_height*i)+string_height/2 |
|
||||
drawHorizLine(currentCanvas, s, e, y, h_origin, v_origin) |
|
||||
|
|
||||
writeText(currentCanvas, style, guitarChordList[i][j], fontsize, v_origin+(i*string_height), hpos=h_origin+charpos) |
|
||||
|
|
||||
lastWidth = currentCanvas.stringWidth(guitarChordList[i][j]) |
|
||||
|
|
||||
return (string_height*(nstrings+1)) + title_height # calculate the height of the block |
|
||||
|
|
||||
def chordProgression(currentCanvas, style, document, cur_pos): |
|
||||
margin = style.leftMargin*style.unit |
|
||||
pagesize = style.pageSize |
|
||||
|
|
||||
title_height = writeText(currentCanvas, style, "Chord progression", 18, cur_pos, align="left") |
|
||||
cur_pos += title_height |
|
||||
|
|
||||
v_origin = cur_pos + 2*mm + style.beatsHeight |
|
||||
h_origin = margin |
|
||||
|
|
||||
h_loc = 0 |
|
||||
v_loc = 0 |
|
||||
|
|
||||
maxWidth = int((((pagesize[0]-(2*margin))/style.unitWidth)//(document.timeSignature*2))*(document.timeSignature*2)) # use integer division to round maxWidth to nearest two bars |
|
||||
|
|
||||
for u in range(maxWidth+1): |
|
||||
s = 0 |
|
||||
x = u*style.unitWidth+margin |
|
||||
if u % document.timeSignature == 0: |
|
||||
e = -style.beatsHeight |
|
||||
else: |
|
||||
e = -style.beatsHeight/2 |
|
||||
drawVertLine(currentCanvas, s, e, x, h_origin, v_origin) |
|
||||
if u == maxWidth: # Avoid writing beat number after the final line |
|
||||
break |
|
||||
writeText(currentCanvas, style, str((u % document.timeSignature)+1), style.beatsFontSize, v_origin-style.beatsHeight, hpos=x+style.unitWidth/2) |
|
||||
|
|
||||
parsedBlockList = splitBlocks(document.blockList, maxWidth) |
|
||||
|
|
||||
for b in parsedBlockList: |
|
||||
if h_loc == maxWidth: |
|
||||
v_loc += 1 |
|
||||
h_loc = 0 |
|
||||
currentCanvas.rect(h_origin+(h_loc*style.unitWidth), v_origin+(v_loc*style.unitHeight), b.length*style.unitWidth, style.unitHeight) |
|
||||
if b.notes is not None: |
|
||||
writeText(currentCanvas, style, b.notes, style.notesFontSize, v_origin+((v_loc+1)*style.unitHeight)-(1.3*style.notesFontSize), hpos=h_origin+((h_loc+b.length/2)*style.unitWidth)) |
|
||||
v_offset = ((v_loc*style.unitHeight)+style.unitHeight/2)-style.chordNameFontSize/2 |
|
||||
if b.chord is not None: |
|
||||
writeText(currentCanvas, style, b.chord.name, style.chordNameFontSize, v_origin+v_offset, hpos=h_origin+((h_loc+b.length/2)*style.unitWidth)) |
|
||||
h_loc += b.length |
|
||||
|
|
||||
return v_origin + (v_loc+1)*style.unitHeight + style.beatsHeight + title_height # calculate the height of the generated chart |
|
||||
|
|
||||
def guitarChartCheck(cL): |
|
||||
chordsPresent = False |
|
||||
for c in cL: |
|
||||
if 'guitar' in c.voicings.keys(): |
|
||||
chordsPresent = True |
|
||||
break |
|
||||
return chordsPresent |
|
||||
|
|
||||
def savePDF(document, style, pathToPDF): |
|
||||
|
|
||||
c = canvas.Canvas(pathToPDF, pagesize=style.pageSize, bottomup=0) |
|
||||
|
|
||||
curPos = style.topMargin*style.unit |
|
||||
|
|
||||
if document.title is not None: |
|
||||
curPos += writeText(c, style, document.title, 24, curPos) |
|
||||
|
|
||||
if document.composer is not None: |
|
||||
curPos += writeText(c, style, "Composer: {c}".format(c = document.composer), 12, curPos) |
|
||||
|
|
||||
if document.arranger is not None: |
|
||||
curPos += writeText(c, style, "Arranger: {a}".format(a = document.arranger), 12, curPos) |
|
||||
|
|
||||
curPos += style.separatorSize*style.unit |
|
||||
|
|
||||
if guitarChartCheck(document.chordList): |
|
||||
curPos += guitarChart(c, style, document.chordList, curPos) |
|
||||
|
|
||||
curPos += style.separatorSize*style.unit |
|
||||
|
|
||||
if document.blockList: |
|
||||
curPos += chordProgression(c, style, document, curPos) |
|
||||
|
|
||||
curPos += style.separatorSize*style.unit |
|
||||
|
|
||||
c.save() |
|
||||
|
def stream(self): |
||||
|
virtualFile = BytesIO() |
||||
|
self.savePDF(virtualFile) |
||||
|
return virtualFile |
@ -0,0 +1,51 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
|
||||
|
from reportlab.lib.styles import StyleSheet1, ParagraphStyle |
||||
|
from reportlab.lib.enums import * |
||||
|
from reportlab.lib.units import mm |
||||
|
from reportlab.lib.colors import black |
||||
|
|
||||
|
def getStyleSheet(csStyle): |
||||
|
"""Returns a stylesheet object""" |
||||
|
stylesheet = StyleSheet1() |
||||
|
|
||||
|
stylesheet.add(ParagraphStyle(name='Master', |
||||
|
fontName=csStyle.font)) |
||||
|
|
||||
|
stylesheet.add(ParagraphStyle(name='Title', |
||||
|
leading=csStyle.lineSpacing*csStyle.titleFontSize, |
||||
|
fontSize=csStyle.titleFontSize, |
||||
|
alignment=TA_CENTER, |
||||
|
parent=stylesheet['Master']) |
||||
|
) |
||||
|
|
||||
|
stylesheet.add(ParagraphStyle(name='Subtitle', |
||||
|
leading=csStyle.lineSpacing*csStyle.subtitleFontSize, |
||||
|
fontSize=csStyle.subtitleFontSize, |
||||
|
alignment=TA_CENTER, |
||||
|
parent=stylesheet['Master']) |
||||
|
) |
||||
|
stylesheet.add(ParagraphStyle(name='Credits', |
||||
|
leading=csStyle.lineSpacing*csStyle.creditsFontSize, |
||||
|
fontSize=csStyle.creditsFontSize, |
||||
|
alignment=TA_CENTER, |
||||
|
parent=stylesheet['Master']) |
||||
|
) |
||||
|
|
||||
|
stylesheet.add(ParagraphStyle(name='Tempo', |
||||
|
leading=csStyle.lineSpacing*csStyle.tempoFontSize, |
||||
|
fontSize=csStyle.tempoFontSize, |
||||
|
alignment=TA_LEFT, |
||||
|
parent=stylesheet['Master']) |
||||
|
) |
||||
|
|
||||
|
stylesheet.add(ParagraphStyle(name='Heading', |
||||
|
leading=csStyle.lineSpacing*csStyle.headingFontSize, |
||||
|
fontSize=csStyle.headingFontSize, |
||||
|
alignment=TA_LEFT, |
||||
|
parent=stylesheet['Master'], |
||||
|
spaceAfter=2*mm, |
||||
|
keepWithNext=1) |
||||
|
) |
||||
|
|
||||
|
return stylesheet |
@ -1,84 +0,0 @@ |
|||||
import sys |
|
||||
from PyQt5 import QtWidgets, QtGui, QtCore |
|
||||
|
|
||||
class MItemModel(QtGui.QStandardItemModel): |
|
||||
|
|
||||
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) |
|
||||
|
|
||||
class MProxyStyle(QtWidgets.QProxyStyle): |
|
||||
|
|
||||
def drawPrimitive(self, element, option, painter, widget=None): |
|
||||
""" |
|
||||
Draw a line across the entire row rather than just the column |
|
||||
we're hovering over. This may not always work depending on global |
|
||||
style. |
|
||||
""" |
|
||||
if element == self.PE_IndicatorItemViewItemDrop and not option.rect.isNull(): |
|
||||
option_new = QtWidgets.QStyleOption(option) |
|
||||
option_new.rect.setLeft(0) |
|
||||
if widget: |
|
||||
option_new.rect.setRight(widget.width()) |
|
||||
option = option_new |
|
||||
super().drawPrimitive(element, option, painter, widget) |
|
||||
|
|
||||
class MTableView(QtWidgets.QTableView): |
|
||||
|
|
||||
def __init__(self, parent): |
|
||||
super().__init__(parent) |
|
||||
|
|
||||
self.model = MItemModel() |
|
||||
self.setModel(self.model) |
|
||||
|
|
||||
self.verticalHeader().hide() |
|
||||
self.horizontalHeader().show() |
|
||||
self.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Interactive) |
|
||||
self.horizontalHeader().setStretchLastSection(True) |
|
||||
|
|
||||
self.setShowGrid(False) |
|
||||
#self.setDragDropMode(self.InternalMove) |
|
||||
#self.setDragDropOverwriteMode(False) |
|
||||
|
|
||||
# Set our custom style - this draws the drop indicator across the whole row |
|
||||
self.setStyle(MProxyStyle()) |
|
||||
|
|
||||
class ChordTableView(MTableView): |
|
||||
|
|
||||
def __init__(self, parent): |
|
||||
super().__init__(parent) |
|
||||
|
|
||||
self.model.setHorizontalHeaderLabels(['Chord', 'Voicing']) |
|
||||
|
|
||||
def populate(self, cList): |
|
||||
self.model.removeRows(0, self.model.rowCount()) |
|
||||
for c in cList: |
|
||||
rowList = [QtGui.QStandardItem(c.name), QtGui.QStandardItem(",".join(c.voicings['guitar'] if 'guitar' in c.voicings.keys() else ""))] |
|
||||
for item in rowList: |
|
||||
item.setEditable(False) |
|
||||
item.setDropEnabled(False) |
|
||||
|
|
||||
self.model.appendRow(rowList) |
|
||||
|
|
||||
self.resizeColumnsToContents() |
|
||||
|
|
||||
class BlockTableView(MTableView): |
|
||||
|
|
||||
def __init__(self, parent): |
|
||||
super().__init__(parent) |
|
||||
|
|
||||
self.model.setHorizontalHeaderLabels(['Chord', 'Length', 'Notes']) |
|
||||
|
|
||||
def populate(self, bList): |
|
||||
self.model.removeRows(0, self.model.rowCount()) |
|
||||
for b in bList: |
|
||||
rowList = [QtGui.QStandardItem((b.chord.name if b.chord else "")), QtGui.QStandardItem(str(b.length)), QtGui.QStandardItem(b.notes)] |
|
||||
for item in rowList: |
|
||||
item.setEditable(False) |
|
||||
item.setDropEnabled(False) |
|
||||
|
|
||||
self.model.appendRow(rowList) |
|
||||
|
|
||||
self.resizeColumnsToContents() |
|
@ -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,0 +1,12 @@ |
|||||
|
from PyQt5.QtWidgets import QComboBox |
||||
|
from PyQt5.QtCore import pyqtSignal |
||||
|
|
||||
|
class MComboBox(QComboBox): |
||||
|
""" |
||||
|
Modified version of combobox that emits a signal with the current item when clicked. |
||||
|
""" |
||||
|
clicked = pyqtSignal(str) |
||||
|
|
||||
|
def showPopup(self): |
||||
|
self.clicked.emit(self.currentText()) |
||||
|
super().showPopup() |
@ -0,0 +1,81 @@ |
|||||
|
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 |
||||
|
from PyQt5.QtCore import QFile, QObject, Qt |
||||
|
from PyQt5.QtGui import QImage, QPixmap |
||||
|
from PyQt5 import uic |
||||
|
|
||||
|
from chordsheet.common import scriptDir |
||||
|
import _version |
||||
|
|
||||
|
class GuitarDialog(QDialog): |
||||
|
""" |
||||
|
Dialogue to allow the user to enter a guitar chord voicing. Not particularly advanced at present! |
||||
|
May be extended in future. |
||||
|
""" |
||||
|
|
||||
|
def __init__(self): |
||||
|
super().__init__() |
||||
|
self.UIFileLoader( |
||||
|
str(os.path.join(scriptDir, 'ui', 'guitardialog.ui'))) |
||||
|
|
||||
|
def UIFileLoader(self, ui_file): |
||||
|
ui_file = QFile(ui_file) |
||||
|
ui_file.open(QFile.ReadOnly) |
||||
|
|
||||
|
self.dialog = uic.loadUi(ui_file) |
||||
|
ui_file.close() |
||||
|
|
||||
|
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() 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: |
||||
|
return None |
||||
|
|
||||
|
|
||||
|
class AboutDialog(QDialog): |
||||
|
""" |
||||
|
Dialogue showing information about the program. |
||||
|
""" |
||||
|
|
||||
|
def __init__(self): |
||||
|
super().__init__() |
||||
|
self.UIFileLoader(str(os.path.join(scriptDir, 'ui', 'aboutdialog.ui'))) |
||||
|
|
||||
|
icon = QImage(str(os.path.join(scriptDir, 'ui', 'icon.png'))) |
||||
|
self.dialog.iconLabel.setPixmap(QPixmap.fromImage(icon).scaled(self.dialog.iconLabel.width( |
||||
|
), self.dialog.iconLabel.height(), Qt.KeepAspectRatio, transformMode=Qt.SmoothTransformation)) |
||||
|
|
||||
|
self.dialog.versionLabel.setText("Version " + _version.version) |
||||
|
|
||||
|
self.dialog.exec() |
||||
|
|
||||
|
def UIFileLoader(self, ui_file): |
||||
|
ui_file = QFile(ui_file) |
||||
|
ui_file.open(QFile.ReadOnly) |
||||
|
|
||||
|
self.dialog = uic.loadUi(ui_file) |
||||
|
ui_file.close() |
@ -0,0 +1,124 @@ |
|||||
|
from PyQt5.QtWidgets import QApplication, QAction, QLabel, QDialogButtonBox, QDialog, QFileDialog, QMessageBox, QPushButton, QLineEdit, QCheckBox, QSpinBox, QDoubleSpinBox, QTableWidgetItem, QTabWidget, QComboBox, QWidget, QScrollArea, QMainWindow, QShortcut, QDialogButtonBox |
||||
|
import sys |
||||
|
|
||||
|
class UnsavedMessageBox(QMessageBox): |
||||
|
""" |
||||
|
Message box to alert the user of unsaved changes and allow them to choose how to act. |
||||
|
""" |
||||
|
|
||||
|
def __init__(self, fileName): |
||||
|
super().__init__() |
||||
|
|
||||
|
self.setIcon(QMessageBox.Information) |
||||
|
self.setWindowTitle("Unsaved changes") |
||||
|
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) |
||||
|
self.setDefaultButton(QMessageBox.Save) |
||||
|
|
||||
|
# If we are running on Haiku, use the MacOS button style to fit in more |
||||
|
# with native applications |
||||
|
if sys.platform.startswith("haiku"): |
||||
|
buttonBox = self.findChild(QDialogButtonBox) |
||||
|
buttonBox.setStyleSheet("* { button-layout: 1}") |
||||
|
|
||||
|
class UnreadableMessageBox(QMessageBox): |
||||
|
""" |
||||
|
Message box to warn the user that the chosen file cannot be opened. |
||||
|
""" |
||||
|
|
||||
|
def __init__(self, fileName): |
||||
|
super().__init__() |
||||
|
|
||||
|
self.setIcon(QMessageBox.Information) |
||||
|
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) |
||||
|
self.setDefaultButton(QMessageBox.Ok) |
||||
|
|
||||
|
|
||||
|
class ChordNameWarningMessageBox(QMessageBox): |
||||
|
""" |
||||
|
Message box to warn the user that a chord must have a name |
||||
|
""" |
||||
|
|
||||
|
def __init__(self): |
||||
|
super().__init__() |
||||
|
|
||||
|
self.setIcon(QMessageBox.Information) |
||||
|
self.setWindowTitle("Unnamed chord") |
||||
|
self.setText("Chords must have a name.") |
||||
|
self.setInformativeText("Please give your chord a name and try again.") |
||||
|
self.setStandardButtons(QMessageBox.Ok) |
||||
|
self.setDefaultButton(QMessageBox.Ok) |
||||
|
|
||||
|
|
||||
|
class SectionNameWarningMessageBox(QMessageBox): |
||||
|
""" |
||||
|
Message box to warn the user that a section must have a name |
||||
|
""" |
||||
|
|
||||
|
def __init__(self): |
||||
|
super().__init__() |
||||
|
|
||||
|
self.setIcon(QMessageBox.Information) |
||||
|
self.setWindowTitle("Unnamed section") |
||||
|
self.setText("Sections must have a unique name.") |
||||
|
self.setInformativeText( |
||||
|
"Please give your section a unique name and try again.") |
||||
|
self.setStandardButtons(QMessageBox.Ok) |
||||
|
self.setDefaultButton(QMessageBox.Ok) |
||||
|
|
||||
|
|
||||
|
class BlockMustHaveSectionWarningMessageBox(QMessageBox): |
||||
|
""" |
||||
|
Message box to warn the user that a block must belong to a section |
||||
|
""" |
||||
|
|
||||
|
def __init__(self): |
||||
|
super().__init__() |
||||
|
|
||||
|
self.setIcon(QMessageBox.Information) |
||||
|
self.setWindowTitle("No sections found") |
||||
|
self.setText("Each block must belong to a section, but no sections have yet been created.") |
||||
|
self.setInformativeText( |
||||
|
"Please create a section before adding blocks.") |
||||
|
self.setStandardButtons(QMessageBox.Ok) |
||||
|
self.setDefaultButton(QMessageBox.Ok) |
||||
|
|
||||
|
|
||||
|
class VoicingWarningMessageBox(QMessageBox): |
||||
|
""" |
||||
|
Message box to warn the user that the voicing entered could not be parsed |
||||
|
""" |
||||
|
|
||||
|
def __init__(self): |
||||
|
super().__init__() |
||||
|
|
||||
|
self.setIcon(QMessageBox.Information) |
||||
|
self.setWindowTitle("Malformed voicing") |
||||
|
self.setText( |
||||
|
"The voicing you entered was not understood and has not been applied.") |
||||
|
self.setInformativeText( |
||||
|
"Please try re-entering it in the correct format.") |
||||
|
self.setStandardButtons(QMessageBox.Ok) |
||||
|
self.setDefaultButton(QMessageBox.Ok) |
||||
|
|
||||
|
|
||||
|
class LengthWarningMessageBox(QMessageBox): |
||||
|
""" |
||||
|
Message box to warn the user that a block must have a length |
||||
|
""" |
||||
|
|
||||
|
def __init__(self): |
||||
|
super().__init__() |
||||
|
|
||||
|
self.setIcon(QMessageBox.Information) |
||||
|
self.setWindowTitle("Block without valid length") |
||||
|
self.setText("Blocks must have a length.") |
||||
|
self.setInformativeText( |
||||
|
"Please enter a valid length for your block and try again.") |
||||
|
self.setStandardButtons(QMessageBox.Ok) |
||||
|
self.setDefaultButton(QMessageBox.Ok) |
@ -0,0 +1,64 @@ |
|||||
|
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, 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): |
||||
|
super().__init__() |
||||
|
|
||||
|
def UIFileLoader(self, ui_file): |
||||
|
ui_file = QFile(os.path.join(scriptDir, 'ui', ui_file)) |
||||
|
ui_file.open(QFile.ReadOnly) |
||||
|
|
||||
|
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__() |
||||
|
self.UIFileLoader('docinfo.ui') |
||||
|
self.setWindowTitle("Document information") |
||||
|
|
||||
|
class PageSetupDockWidget(UIFileDockWidget): |
||||
|
def __init__(self): |
||||
|
super().__init__() |
||||
|
self.UIFileLoader('psetup.ui') |
||||
|
self.setWindowTitle("Page setup") |
||||
|
|
||||
|
class ChordsDockWidget(UIFileDockWidget): |
||||
|
def __init__(self): |
||||
|
super().__init__() |
||||
|
self.UIFileLoader('chords.ui') |
||||
|
self.setWindowTitle("Chords") |
||||
|
|
||||
|
class SectionsDockWidget(UIFileDockWidget): |
||||
|
def __init__(self): |
||||
|
super().__init__() |
||||
|
self.UIFileLoader('sections.ui') |
||||
|
self.setWindowTitle("Sections") |
||||
|
|
||||
|
class BlocksDockWidget(UIFileDockWidget): |
||||
|
def __init__(self): |
||||
|
super().__init__() |
||||
|
self.UIFileLoader('blocks.ui') |
||||
|
self.setWindowTitle("Blocks") |
||||
|
|
||||
|
class PreviewDockWidget(UIFileDockWidget): |
||||
|
def __init__(self): |
||||
|
super().__init__() |
||||
|
self.UIFileLoader('preview.ui') |
||||
|
self.setWindowTitle("Preview") |
@ -0,0 +1,96 @@ |
|||||
|
from PyQt5.QtWidgets import QScrollArea, QLabel, QVBoxLayout, QWidget, QSizePolicy |
||||
|
from PyQt5.QtCore import Qt, QPoint, QSize |
||||
|
from PyQt5.QtGui import QPixmap, QImage, QResizeEvent, QPainter |
||||
|
|
||||
|
import fitz |
||||
|
|
||||
|
class PDFLabel(QLabel): |
||||
|
def __init__(self, parent): |
||||
|
super().__init__(parent) |
||||
|
self.parent = parent |
||||
|
self.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Preferred) |
||||
|
|
||||
|
def paintEvent(self, event): |
||||
|
self.adjustSize() |
||||
|
if self.pixmap() is not None: |
||||
|
painter = QPainter(self) |
||||
|
# 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 |
||||
|
# print(idealWidth) |
||||
|
pixSize = self.pixmap().size() |
||||
|
# print(pixSize) |
||||
|
# print((self.parent.scrollAreaContents.size())) |
||||
|
|
||||
|
pixSize.scale(idealWidth, 1000000, Qt.KeepAspectRatio) |
||||
|
|
||||
|
scaledPix = self.pixmap().scaled(pixSize, Qt.KeepAspectRatio, Qt.SmoothTransformation) |
||||
|
painter.drawPixmap(QPoint(), scaledPix) |
||||
|
self.setMaximumSize(pixSize) |
||||
|
|
||||
|
class PDFViewer(QScrollArea): |
||||
|
def __init__(self, parent): |
||||
|
super().__init__(parent) |
||||
|
self.scrollAreaContents = QWidget() |
||||
|
self.scrollAreaLayout = QVBoxLayout() |
||||
|
|
||||
|
self.setWidget(self.scrollAreaContents) |
||||
|
self.setWidgetResizable(True) |
||||
|
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) |
||||
|
# set a fixed background colour |
||||
|
# on some OSes (Mac, Haiku) it is grey automatically but not on KDE |
||||
|
self.setStyleSheet('PDFViewer {background-color: #D8D8D8}') |
||||
|
|
||||
|
self.scrollAreaContents.setLayout(self.scrollAreaLayout) |
||||
|
self.pixmapList = [] |
||||
|
self.lastVScrollPosition = None |
||||
|
|
||||
|
def update_pdf(self, pdf): |
||||
|
self.render(pdf) |
||||
|
self.clear() |
||||
|
self.show() |
||||
|
|
||||
|
def render(self, pdf): |
||||
|
""" |
||||
|
Update the preview shown by rendering a new PDF and drawing it to the scroll area. |
||||
|
""" |
||||
|
|
||||
|
self.pixmapList = [] |
||||
|
pdfView = fitz.Document(stream=pdf, filetype='pdf') |
||||
|
for page in pdfView: |
||||
|
# needs to be high enough for big monitors. 300 should do it... |
||||
|
self.pixmapList.append(page.get_pixmap(dpi=300, alpha=False)) |
||||
|
|
||||
|
def clear(self): |
||||
|
self.lastVScrollPosition = self.verticalScrollBar().value() |
||||
|
while self.scrollAreaLayout.count(): |
||||
|
item = self.scrollAreaLayout.takeAt(0) |
||||
|
w = item.widget() |
||||
|
if w: |
||||
|
w.deleteLater() |
||||
|
|
||||
|
def show(self): |
||||
|
for p in self.pixmapList: |
||||
|
label = PDFLabel(parent=self) |
||||
|
label.setAlignment(Qt.AlignHCenter) |
||||
|
qtimg = QImage(p.samples, p.width, p.height, p.stride, QImage.Format_RGB888) |
||||
|
label.setPixmap(QPixmap.fromImage(qtimg)) |
||||
|
self.scrollAreaLayout.addWidget(label) |
||||
|
|
||||
|
self.scrollAreaLayout.addStretch(1) |
||||
|
|
||||
|
# Somewhat of a hack. Should really replace pixmaps in place |
||||
|
# rather than removing labels elsewhere in code. |
||||
|
if self.lastVScrollPosition: |
||||
|
self.verticalScrollBar().setValue(self.lastVScrollPosition) |
@ -0,0 +1,153 @@ |
|||||
|
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" |
||||
|
""" |
||||
|
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): |
||||
|
""" |
||||
|
Proxy style to change the appearance of the TableView. |
||||
|
""" |
||||
|
|
||||
|
def drawPrimitive(self, element, option, painter, widget=None): |
||||
|
""" |
||||
|
Draw a line across the entire row rather than just the column |
||||
|
we're hovering over. |
||||
|
""" |
||||
|
if element == self.PE_IndicatorItemViewItemDrop and not option.rect.isNull(): |
||||
|
option_new = QtWidgets.QStyleOption(option) |
||||
|
option_new.rect.setLeft(0) |
||||
|
if widget: |
||||
|
option_new.rect.setRight(widget.width()) |
||||
|
option = option_new |
||||
|
super().drawPrimitive(element, option, painter, widget) |
||||
|
|
||||
|
|
||||
|
class MTableView(QtWidgets.QTableView): |
||||
|
""" |
||||
|
Subclass the built in TableView to customise it. |
||||
|
""" |
||||
|
|
||||
|
def __init__(self, parent): |
||||
|
super().__init__(parent) |
||||
|
|
||||
|
self.model = MItemModel() |
||||
|
self.setModel(self.model) |
||||
|
|
||||
|
self.verticalHeader().hide() |
||||
|
self.horizontalHeader().show() |
||||
|
self.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Interactive) |
||||
|
self.horizontalHeader().setStretchLastSection(True) |
||||
|
|
||||
|
self.setShowGrid(False) |
||||
|
# self.setDragDropMode(self.InternalMove) |
||||
|
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): |
||||
|
""" |
||||
|
Subclass MTableView to add properties just for the chord table. |
||||
|
""" |
||||
|
|
||||
|
def __init__(self, parent): |
||||
|
super().__init__(parent) |
||||
|
|
||||
|
self.model.setHorizontalHeaderLabels(['Chord', 'Guitar voicing', 'Piano voicing']) |
||||
|
|
||||
|
def populate(self, cList): |
||||
|
""" |
||||
|
Fill the table from a list of Chord objects. |
||||
|
""" |
||||
|
self.model.removeRows(0, self.model.rowCount()) |
||||
|
for c in cList: |
||||
|
rowList = [QtGui.QStandardItem(c.name), QtGui.QStandardItem( |
||||
|
",".join(c.voicings['guitar'] if 'guitar' in c.voicings.keys() else "")), |
||||
|
QtGui.QStandardItem( |
||||
|
",".join(c.voicings['piano'] if 'piano' in c.voicings.keys() else ""))] |
||||
|
for item in rowList: |
||||
|
item.setEditable(False) |
||||
|
item.setDropEnabled(False) |
||||
|
|
||||
|
self.model.appendRow(rowList) |
||||
|
|
||||
|
|
||||
|
class SectionTableView(MTableView): |
||||
|
""" |
||||
|
Subclass MTableView to add properties just for the section table. |
||||
|
""" |
||||
|
|
||||
|
def __init__(self, parent): |
||||
|
super().__init__(parent) |
||||
|
|
||||
|
self.model.setHorizontalHeaderLabels(['Name']) |
||||
|
|
||||
|
def populate(self, sList): |
||||
|
""" |
||||
|
Fill the table from a list of Section objects. |
||||
|
""" |
||||
|
self.model.removeRows(0, self.model.rowCount()) |
||||
|
for s in sList: |
||||
|
rowList = [QtGui.QStandardItem(s.name)] |
||||
|
for item in rowList: |
||||
|
item.setEditable(False) |
||||
|
item.setDropEnabled(False) |
||||
|
|
||||
|
self.model.appendRow(rowList) |
||||
|
|
||||
|
|
||||
|
class BlockTableView(MTableView): |
||||
|
""" |
||||
|
Subclass MTableView to add properties just for the block table. |
||||
|
""" |
||||
|
|
||||
|
def __init__(self, parent): |
||||
|
super().__init__(parent) |
||||
|
|
||||
|
self.model.setHorizontalHeaderLabels(['Chord', 'Length', 'Notes']) |
||||
|
|
||||
|
def populate(self, bList): |
||||
|
""" |
||||
|
Fill the table from a list of Block objects. |
||||
|
""" |
||||
|
self.model.removeRows(0, self.model.rowCount()) |
||||
|
for b in bList: |
||||
|
rowList = [QtGui.QStandardItem((b.chord.name if b.chord else "")), QtGui.QStandardItem( |
||||
|
str(b.length)), QtGui.QStandardItem(b.notes)] |
||||
|
for item in rowList: |
||||
|
item.setEditable(False) |
||||
|
item.setDropEnabled(False) |
||||
|
|
||||
|
self.model.appendRow(rowList) |
@ -0,0 +1,309 @@ |
|||||
|
<chordsheet> |
||||
|
<title>"African Heritage"</title> |
||||
|
<subtitle>A corroboration</subtitle> |
||||
|
<composer>Ivan Holmes</composer> |
||||
|
<arranger>Ivan Holmes and Joe Buckley</arranger> |
||||
|
<tempo>120</tempo> |
||||
|
<timesignature>6</timesignature> |
||||
|
<chords> |
||||
|
<chord> |
||||
|
<name>Gm9</name> |
||||
|
<voicing instrument="guitar">x,10,8,10,10,x</voicing> |
||||
|
</chord> |
||||
|
<chord> |
||||
|
<name>Abm9</name> |
||||
|
<voicing instrument="guitar">x,11,9,11,11,x</voicing> |
||||
|
</chord> |
||||
|
<chord> |
||||
|
<name>Cm9</name> |
||||
|
<voicing instrument="guitar">x,x,8,8,8,10</voicing> |
||||
|
</chord> |
||||
|
<chord> |
||||
|
<name>D7#5#9</name> |
||||
|
<voicing instrument="guitar">x58565</voicing> |
||||
|
</chord> |
||||
|
<chord> |
||||
|
<name>Eb7#5#9</name> |
||||
|
<voicing instrument="guitar">x69676</voicing> |
||||
|
</chord> |
||||
|
</chords> |
||||
|
<section name="A section"> |
||||
|
<block> |
||||
|
<length>9</length> |
||||
|
<chord>Gm9</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>3</length> |
||||
|
<chord>Abm9</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>12</length> |
||||
|
<chord>Gm9</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>9</length> |
||||
|
<chord>Cm9</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>3</length> |
||||
|
<chord>D7#5#9</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>12</length> |
||||
|
<chord>Gm9</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>6</length> |
||||
|
<chord>Eb7#5#9</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>6</length> |
||||
|
<chord>D7#5#9</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>6</length> |
||||
|
<chord>Cm9</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>3</length> |
||||
|
<chord>D7#5#9</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>3</length> |
||||
|
<chord>D7#5#9</chord> |
||||
|
<notes>over Ab</notes> |
||||
|
</block> |
||||
|
</section> |
||||
|
<section name="B section"> |
||||
|
<block> |
||||
|
<length>9</length> |
||||
|
<chord>Gm9</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>3</length> |
||||
|
<chord>Abm9</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>12</length> |
||||
|
<chord>Gm9</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>6</length> |
||||
|
<chord>Eb7#5#9</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>6</length> |
||||
|
<chord>D7#5#9</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>12</length> |
||||
|
<chord>Cm9</chord> |
||||
|
</block> |
||||
|
</section> |
||||
|
<section name="C section"> |
||||
|
<block> |
||||
|
<length>9</length> |
||||
|
<chord>Gm9</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>3</length> |
||||
|
<chord>Abm9</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>12</length> |
||||
|
<chord>Gm9</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>6</length> |
||||
|
<chord>Eb7#5#9</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>6</length> |
||||
|
<chord>D7#5#9</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>12</length> |
||||
|
<chord>Cm9</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>9</length> |
||||
|
<chord>Gm9</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>3</length> |
||||
|
<chord>Abm9</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>12</length> |
||||
|
<chord>Gm9</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>9</length> |
||||
|
<chord>Cm9</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>3</length> |
||||
|
<chord>D7#5#9</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>12</length> |
||||
|
<chord>Gm9</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>6</length> |
||||
|
<chord>Eb7#5#9</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>6</length> |
||||
|
<chord>D7#5#9</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>6</length> |
||||
|
<chord>Cm9</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>3</length> |
||||
|
<chord>D7#5#9</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>3</length> |
||||
|
<chord>D7#5#9</chord> |
||||
|
<notes>over Ab</notes> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>9</length> |
||||
|
<chord>Gm9</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>3</length> |
||||
|
<chord>Abm9</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>12</length> |
||||
|
<chord>Gm9</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>9</length> |
||||
|
<chord>Cm9</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>3</length> |
||||
|
<chord>D7#5#9</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>12</length> |
||||
|
<chord>Gm9</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>6</length> |
||||
|
<chord>Eb7#5#9</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>6</length> |
||||
|
<chord>D7#5#9</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>6</length> |
||||
|
<chord>Cm9</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>3</length> |
||||
|
<chord>D7#5#9</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>3</length> |
||||
|
<chord>D7#5#9</chord> |
||||
|
<notes>over Ab</notes> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>9</length> |
||||
|
<chord>Gm9</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>3</length> |
||||
|
<chord>Abm9</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>12</length> |
||||
|
<chord>Gm9</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>9</length> |
||||
|
<chord>Cm9</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>3</length> |
||||
|
<chord>D7#5#9</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>12</length> |
||||
|
<chord>Gm9</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>6</length> |
||||
|
<chord>Eb7#5#9</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>6</length> |
||||
|
<chord>D7#5#9</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>6</length> |
||||
|
<chord>Cm9</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>3</length> |
||||
|
<chord>D7#5#9</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>3</length> |
||||
|
<chord>D7#5#9</chord> |
||||
|
<notes>over Ab</notes> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>9</length> |
||||
|
<chord>Gm9</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>3</length> |
||||
|
<chord>Abm9</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>12</length> |
||||
|
<chord>Gm9</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>9</length> |
||||
|
<chord>Cm9</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>3</length> |
||||
|
<chord>D7#5#9</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>12</length> |
||||
|
<chord>Gm9</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>6</length> |
||||
|
<chord>Eb7#5#9</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>6</length> |
||||
|
<chord>D7#5#9</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>6</length> |
||||
|
<chord>Cm9</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>3</length> |
||||
|
<chord>D7#5#9</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>3</length> |
||||
|
<chord>D7#5#9</chord> |
||||
|
<notes>over Ab</notes> |
||||
|
</block> |
||||
|
</section> |
||||
|
</chordsheet> |
@ -0,0 +1 @@ |
|||||
|
<chordsheet><title>Angela</title><subtitle>Theme from 'Taxi'</subtitle><arranger>Max</arranger><composer>Bob James</composer><timesignature>4</timesignature><chords><chord><name>E♭maj7</name><voicing instrument="guitar">x,x,1,3,3,3</voicing></chord><chord><name>A♭ma7</name><voicing instrument="guitar">x,x,1,1,1,3</voicing></chord><chord><name>Gm7</name><voicing instrument="guitar">3,x,3,3,3,x</voicing></chord><chord><name>B♭/D</name><voicing instrument="guitar">x,x,0,3,3,1</voicing></chord><chord><name>A♭maj7/C</name><voicing instrument="guitar">x,3,1,1,1,3</voicing></chord><chord><name>B♭</name><voicing instrument="guitar">x,1,3,3,3,1</voicing></chord><chord><name>A♭</name><voicing instrument="guitar">4,6,6,5,4,4</voicing></chord><chord><name>E♭/G</name><voicing instrument="guitar">x,x,5,3,4,3</voicing></chord><chord><name>Fm</name><voicing instrument="guitar">x,x,3,1,1,1</voicing></chord><chord><name>A♭/B♭</name><voicing instrument="guitar">6,x,6,5,4,4</voicing></chord><chord><name>E♭</name><voicing instrument="guitar">x,6,5,3,4,3</voicing></chord><chord><name>E♭7</name><voicing instrument="guitar">x,x,1,3,2,3</voicing></chord><chord><name>A♭maj9</name><voicing instrument="guitar">4,x,5,3,4,3</voicing></chord><chord><name>Fm7</name><voicing instrument="guitar">1,x,1,1,1,x</voicing></chord></chords><section name="Intro"><block><length>2.0</length><chord>E♭maj7</chord></block><block><length>2.0</length><chord>A♭ma7</chord></block><block><length>2.0</length><chord>Gm7</chord></block><block><length>2.0</length><chord>B♭/D</chord></block><block><length>2.0</length><chord>A♭maj7/C</chord></block><block><length>2.0</length><chord>B♭</chord></block><block><length>1.0</length><chord>A♭</chord></block><block><length>1.0</length><chord>E♭/G</chord></block><block><length>1.0</length><chord>Fm</chord></block><block><length>1.0</length><chord>A♭/B♭</chord></block><block><length>2.0</length><chord>E♭</chord></block><block><length>2.0</length><chord>E♭7</chord></block><block><length>2.0</length><chord>A♭maj9</chord></block><block><length>2.0</length><chord>E♭/G</chord></block><block><length>2.0</length><chord>Fm7</chord></block><block><length>2.0</length><chord>B♭</chord></block><block><length>1.0</length><chord>A♭</chord></block><block><length>1.0</length><chord>E♭/G</chord></block><block><length>1.0</length><chord>Fm</chord></block><block><length>1.0</length><chord>A♭/B♭</chord></block></section></chordsheet> |
@ -1,46 +1,93 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
<chordsheet> |
<chordsheet> |
||||
<title>Composition</title> |
|
||||
<composer>A. Person</composer> |
|
||||
<timesignature>4</timesignature> |
|
||||
<chords> |
|
||||
<chord> |
|
||||
<name>B</name> |
|
||||
<voicing instrument="guitar">xx2341</voicing> |
|
||||
<voicing instrument="piano">abcdefg</voicing> |
|
||||
</chord> |
|
||||
<chord> |
|
||||
<name>E</name> |
|
||||
<voicing instrument="guitar">022100</voicing> |
|
||||
</chord> |
|
||||
<chord> |
|
||||
<name>Cm9</name> |
|
||||
<voicing instrument="guitar">x,x,8,8,8,10</voicing> |
|
||||
</chord> |
|
||||
<chord> |
|
||||
<name>D7b5#9</name> |
|
||||
</chord> |
|
||||
</chords> |
|
||||
<progression> |
|
||||
<block> |
|
||||
<length>4</length> |
|
||||
<chord>B</chord> |
|
||||
<notes>These are notes</notes> |
|
||||
</block> |
|
||||
<block> |
|
||||
<length>4</length> |
|
||||
<chord>E</chord> |
|
||||
</block> |
|
||||
<block> |
|
||||
<length>12</length> |
|
||||
<chord>Cm9</chord> |
|
||||
</block> |
|
||||
<block> |
|
||||
<length>6</length> |
|
||||
<chord>D7b5#9</chord> |
|
||||
</block> |
|
||||
<block> |
|
||||
<length>6</length> |
|
||||
<notes>For quiet contemplation.</notes> |
|
||||
</block> |
|
||||
</progression> |
|
||||
|
<title>Example Song</title> |
||||
|
<composer>Ivan Holmes</composer> |
||||
|
<timesignature>4</timesignature> |
||||
|
<chords> |
||||
|
<chord> |
||||
|
<name>C7</name> |
||||
|
<voicing instrument="guitar">x,3,2,0,1,0</voicing> |
||||
|
<voicing instrument="piano">Bb,E,C,G</voicing> |
||||
|
</chord> |
||||
|
<chord> |
||||
|
<name>F</name> |
||||
|
<voicing instrument="guitar">1,3,3,2,1,1</voicing> |
||||
|
<voicing instrument="piano">A,C,F</voicing> |
||||
|
</chord> |
||||
|
<chord> |
||||
|
<name>G</name> |
||||
|
<voicing instrument="guitar">3,2,0,0,0,3</voicing> |
||||
|
<voicing instrument="piano">B,D,G</voicing> |
||||
|
</chord> |
||||
|
<chord> |
||||
|
<name>C/G</name> |
||||
|
<voicing instrument="guitar">3,3,2,0,1,0</voicing> |
||||
|
<voicing instrument="piano">G,C,E</voicing> |
||||
|
</chord> |
||||
|
<chord> |
||||
|
<name>Dm</name> |
||||
|
<voicing instrument="guitar">x,x,0,2,3,1</voicing> |
||||
|
<voicing instrument="piano">A,D,F</voicing> |
||||
|
</chord> |
||||
|
</chords> |
||||
|
<section name="Example section"> |
||||
|
<block> |
||||
|
<length>16</length> |
||||
|
<chord>C7</chord> |
||||
|
<notes>Intro, strum lightly</notes> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>4</length> |
||||
|
<chord>C7</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>4</length> |
||||
|
<chord>F</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>8</length> |
||||
|
<chord>G</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>4</length> |
||||
|
<chord>C7</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>4</length> |
||||
|
<chord>F</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>8</length> |
||||
|
<chord>G</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>4</length> |
||||
|
<chord>C7</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>4</length> |
||||
|
<chord>Dm</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>4</length> |
||||
|
<chord>C/G</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>4</length> |
||||
|
<chord>G</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>4</length> |
||||
|
<chord>C7</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>4</length> |
||||
|
<notes>Contemplation time</notes> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>8</length> |
||||
|
<chord>C7</chord> |
||||
|
<notes>Crescendo until end</notes> |
||||
|
</block> |
||||
|
</section> |
||||
</chordsheet> |
</chordsheet> |
@ -0,0 +1,143 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<chordsheet> |
||||
|
<title>Example Song</title> |
||||
|
<composer>Ivan Holmes</composer> |
||||
|
<timesignature>4</timesignature> |
||||
|
<chords> |
||||
|
<chord> |
||||
|
<name>C7</name> |
||||
|
<voicing instrument="guitar">x,3,2,0,1,0</voicing> |
||||
|
<voicing instrument="piano">Bb,E,C,G</voicing> |
||||
|
</chord> |
||||
|
<chord> |
||||
|
<name>F</name> |
||||
|
<voicing instrument="guitar">1,3,3,2,1,1</voicing> |
||||
|
<voicing instrument="piano">A,C,F</voicing> |
||||
|
</chord> |
||||
|
<chord> |
||||
|
<name>G</name> |
||||
|
<voicing instrument="guitar">3,2,0,0,0,3</voicing> |
||||
|
<voicing instrument="piano">B,D,G</voicing> |
||||
|
</chord> |
||||
|
<chord> |
||||
|
<name>C/G</name> |
||||
|
<voicing instrument="guitar">3,3,2,0,1,0</voicing> |
||||
|
<voicing instrument="piano">G,C,E</voicing> |
||||
|
</chord> |
||||
|
<chord> |
||||
|
<name>Dm</name> |
||||
|
<voicing instrument="guitar">x,x,0,2,3,1</voicing> |
||||
|
<voicing instrument="piano">A,D,F</voicing> |
||||
|
</chord> |
||||
|
<chord> |
||||
|
<name>q7</name> |
||||
|
<voicing instrument="guitar">x,3,2,0,1,0</voicing> |
||||
|
<voicing instrument="piano">Bb,E,C,G</voicing> |
||||
|
</chord> |
||||
|
<chord> |
||||
|
<name>q3</name> |
||||
|
<voicing instrument="guitar">1,3,3,2,1,1</voicing> |
||||
|
<voicing instrument="piano">A,C,F</voicing> |
||||
|
</chord> |
||||
|
<chord> |
||||
|
<name>q5</name> |
||||
|
<voicing instrument="guitar">3,2,0,0,0,3</voicing> |
||||
|
<voicing instrument="piano">B,D,G</voicing> |
||||
|
</chord> |
||||
|
<chord> |
||||
|
<name>q/G</name> |
||||
|
<voicing instrument="guitar">3,3,2,0,1,0</voicing> |
||||
|
<voicing instrument="piano">G,C,E</voicing> |
||||
|
</chord> |
||||
|
<chord> |
||||
|
<name>q</name> |
||||
|
<voicing instrument="guitar">x,x,0,2,3,1</voicing> |
||||
|
<voicing instrument="piano">A,D,F</voicing> |
||||
|
</chord> |
||||
|
<chord> |
||||
|
<name>yeeq</name> |
||||
|
<voicing instrument="guitar">x,3,2,0,1,0</voicing> |
||||
|
<voicing instrument="piano">Bb,E,C,G</voicing> |
||||
|
</chord> |
||||
|
<chord> |
||||
|
<name>quu</name> |
||||
|
<voicing instrument="guitar">1,3,3,2,1,1</voicing> |
||||
|
<voicing instrument="piano">A,C,F</voicing> |
||||
|
</chord> |
||||
|
<chord> |
||||
|
<name>b3</name> |
||||
|
<voicing instrument="guitar">3,2,0,0,0,3</voicing> |
||||
|
<voicing instrument="piano">B,D</voicing> |
||||
|
</chord> |
||||
|
<chord> |
||||
|
<name>aa</name> |
||||
|
<voicing instrument="guitar">3,3,2,0,1,0</voicing> |
||||
|
<voicing instrument="piano">G,C,E</voicing> |
||||
|
</chord> |
||||
|
<chord> |
||||
|
<name>z</name> |
||||
|
<voicing instrument="guitar">x,x,0,2,3,1</voicing> |
||||
|
<voicing instrument="piano">A,D,F,G,E,B,C</voicing> |
||||
|
</chord> |
||||
|
</chords> |
||||
|
<section name="Example section"> |
||||
|
<block> |
||||
|
<length>16</length> |
||||
|
<chord>C7</chord> |
||||
|
<notes>Intro, strum lightly</notes> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>4</length> |
||||
|
<chord>C7</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>4</length> |
||||
|
<chord>F</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>8</length> |
||||
|
<chord>G</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>4</length> |
||||
|
<chord>C7</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>4</length> |
||||
|
<chord>F</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>8</length> |
||||
|
<chord>G</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>4</length> |
||||
|
<chord>C7</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>4</length> |
||||
|
<chord>Dm</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>4</length> |
||||
|
<chord>C/G</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>4</length> |
||||
|
<chord>G</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>4</length> |
||||
|
<chord>C7</chord> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>4</length> |
||||
|
<notes>Contemplation time</notes> |
||||
|
</block> |
||||
|
<block> |
||||
|
<length>8</length> |
||||
|
<chord>C7</chord> |
||||
|
<notes>Crescendo until end</notes> |
||||
|
</block> |
||||
|
</section> |
||||
|
</chordsheet> |
@ -0,0 +1,24 @@ |
|||||
|
\chordsheet 1 |
||||
|
\rem This is a comment to say that the first line isn't really needed (as there's only one version of Chordsheet Macro so far) |
||||
|
|
||||
|
\title Kiss of Life |
||||
|
\subtitle Sade |
||||
|
\arranger Ivan Holmes |
||||
|
\composer Sade Adu, Paul S. Denman, Andrew Hale, Stuart Matthewman |
||||
|
\timesig 4 |
||||
|
\tempo 120 |
||||
|
|
||||
|
\chord AM9 piano A,B,C#,E |
||||
|
\chord F#m11 alias F piano A,B,C#,E |
||||
|
\chord DM7 piano A,C#,F# |
||||
|
\chord C#m7 piano G#,B,E |
||||
|
\chord Bm7 piano A,D,F# |
||||
|
|
||||
|
\section Intro and verse |
||||
|
AM9,8 F#m11,8 DM7,1.5 |
||||
|
C#m7,2 Bm7,4.5 F#m11,8 |
||||
|
|
||||
|
\! This is another comment. Comments may not exist in the middle of other statements. |
||||
|
|
||||
|
\section Chorus and bridge |
||||
|
Bm7,3.5 F,4.5 Bm7,3.5 F#m11,4.5 |
@ -0,0 +1 @@ |
|||||
|
<chordsheet><title>Kiss of Life</title><subtitle>Sade</subtitle><arranger>Ivan Holmes</arranger><composer>Sade Adu, Paul S. Denman, Andrew Hale, Stuart Matthewman</composer><timesignature>4</timesignature><tempo>120</tempo><chords><chord><name>AM9</name><voicing instrument="piano">A,B,C♯,E</voicing></chord><chord><name>F♯m11</name><voicing instrument="piano">A,B,C♯,E</voicing></chord><chord><name>DM7</name><voicing instrument="piano">A,C♯,F♯</voicing></chord><chord><name>C♯m7</name><voicing instrument="piano">G♯,B,E</voicing></chord><chord><name>Bm7</name><voicing instrument="piano">A,D,F♯</voicing></chord></chords><section name="Intro and verse"><block><length>8.0</length><chord>AM9</chord></block><block><length>8.0</length><chord>F♯m11</chord></block><block><length>1.5</length><chord>DM7</chord></block><block><length>2.0</length><chord>C♯m7</chord></block><block><length>4.5</length><chord>Bm7</chord></block><block><length>8.0</length><chord>F♯m11</chord></block></section><section name="Chorus and bridge"><block><length>3.5</length><chord>Bm7</chord></block><block><length>4.5</length><chord>F♯m11</chord></block><block><length>3.5</length><chord>Bm7</chord></block><block><length>4.5</length><chord>F♯m11</chord></block></section></chordsheet> |
@ -0,0 +1 @@ |
|||||
|
<chordsheet><title>Composition</title><composer>A. Person</composer><timesignature>4</timesignature><chords><chord><name>B</name><voicing instrument="guitar">x,x,2,3,4,1</voicing></chord><chord><name>E</name><voicing instrument="guitar">0,2,2,1,0,0</voicing></chord><chord><name>Cm9</name><voicing instrument="guitar">x,x,8,8,8,10</voicing></chord><chord><name>D7♭5♯9</name></chord></chords><section name="Test section"><block><length>4</length><chord>B</chord><notes>These are notes.</notes></block><block><length>4</length><chord>E</chord></block><block><length>12</length><chord>Cm9</chord></block><block><length>6</length><chord>D7♭5♯9</chord></block><block><length>6</length><notes>For quiet contemplation.</notes></block><block><length>46</length><chord>D7♭5♯9</chord><notes>A very long block to test wrapping!</notes></block></section></chordsheet> |
@ -0,0 +1,15 @@ |
|||||
|
import _version |
||||
|
|
||||
|
with open('version.rc.template', 'r') as verstf: |
||||
|
verstemp = verstf.read() |
||||
|
|
||||
|
major, minor, patch = _version.version.split(".") |
||||
|
|
||||
|
verstemp = verstemp.replace("%APPNAME%", _version.appName) |
||||
|
verstemp = verstemp.replace("%VERSION%", _version.version) |
||||
|
verstemp = verstemp.replace("%MAJOR_VERSION%", major) |
||||
|
verstemp = verstemp.replace("%MINOR_VERSION%", minor) |
||||
|
verstemp = verstemp.replace("%PATCH_VERSION%", patch) |
||||
|
|
||||
|
with open('version.rc', 'w') as versf: |
||||
|
versf.write(verstemp) |
1315
gui.py
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,47 @@ |
|||||
|
# -*- mode: python ; coding: utf-8 -*- |
||||
|
|
||||
|
block_cipher = None |
||||
|
|
||||
|
with open('_version.py', 'r') as versinfo: |
||||
|
exec(versinfo.read()) |
||||
|
|
||||
|
a = Analysis(['gui.py'], |
||||
|
pathex=['/home/ivan/Code/chordsheet'], |
||||
|
binaries=[], |
||||
|
datas=[ |
||||
|
('fonts', 'fonts'), |
||||
|
('ui', 'ui') |
||||
|
], |
||||
|
hiddenimports=['PyQt5.sip'], |
||||
|
hookspath=[], |
||||
|
runtime_hooks=[], |
||||
|
excludes=[], |
||||
|
win_no_prefer_redirects=False, |
||||
|
win_private_assemblies=False, |
||||
|
cipher=block_cipher, |
||||
|
noarchive=False) |
||||
|
pyz = PYZ(a.pure, a.zipped_data, |
||||
|
cipher=block_cipher) |
||||
|
exe = EXE(pyz, |
||||
|
a.scripts, |
||||
|
[], |
||||
|
exclude_binaries=True, |
||||
|
name='chordsheet', |
||||
|
icon='ui/icon.png', |
||||
|
debug=False, |
||||
|
bootloader_ignore_signals=False, |
||||
|
strip=False, |
||||
|
upx=True, |
||||
|
upx_exclude=[], |
||||
|
runtime_tmpdir=None, |
||||
|
console=False, |
||||
|
version='version.rc') |
||||
|
|
||||
|
coll = COLLECT(exe, |
||||
|
a.binaries, |
||||
|
a.zipfiles, |
||||
|
a.datas, |
||||
|
strip=False, |
||||
|
upx=True, |
||||
|
upx_exclude=[], |
||||
|
name='chordsheet-'+version) |
@ -0,0 +1,4 @@ |
|||||
|
reportlab>=3.5.67 |
||||
|
PyMuPDF>=1.18.13 |
||||
|
PyQt5>=5.15.4 |
||||
|
PyQt5.Sip |
@ -0,0 +1,142 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<ui version="4.0"> |
||||
|
<class>Dialog</class> |
||||
|
<widget class="QDialog" name="Dialog"> |
||||
|
<property name="enabled"> |
||||
|
<bool>true</bool> |
||||
|
</property> |
||||
|
<property name="geometry"> |
||||
|
<rect> |
||||
|
<x>0</x> |
||||
|
<y>0</y> |
||||
|
<width>400</width> |
||||
|
<height>200</height> |
||||
|
</rect> |
||||
|
</property> |
||||
|
<property name="sizePolicy"> |
||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred"> |
||||
|
<horstretch>0</horstretch> |
||||
|
<verstretch>0</verstretch> |
||||
|
</sizepolicy> |
||||
|
</property> |
||||
|
<property name="minimumSize"> |
||||
|
<size> |
||||
|
<width>400</width> |
||||
|
<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> |
||||
|
<widget class="QLabel" name="iconLabel"> |
||||
|
<property name="sizePolicy"> |
||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Fixed"> |
||||
|
<horstretch>0</horstretch> |
||||
|
<verstretch>0</verstretch> |
||||
|
</sizepolicy> |
||||
|
</property> |
||||
|
<property name="minimumSize"> |
||||
|
<size> |
||||
|
<width>128</width> |
||||
|
<height>128</height> |
||||
|
</size> |
||||
|
</property> |
||||
|
<property name="text"> |
||||
|
<string/> |
||||
|
</property> |
||||
|
<property name="scaledContents"> |
||||
|
<bool>true</bool> |
||||
|
</property> |
||||
|
<property name="alignment"> |
||||
|
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item> |
||||
|
<spacer name="verticalSpacer"> |
||||
|
<property name="orientation"> |
||||
|
<enum>Qt::Vertical</enum> |
||||
|
</property> |
||||
|
<property name="sizeHint" stdset="0"> |
||||
|
<size> |
||||
|
<width>20</width> |
||||
|
<height>40</height> |
||||
|
</size> |
||||
|
</property> |
||||
|
</spacer> |
||||
|
</item> |
||||
|
</layout> |
||||
|
</item> |
||||
|
<item> |
||||
|
<widget class="Line" name="line"> |
||||
|
<property name="orientation"> |
||||
|
<enum>Qt::Vertical</enum> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item> |
||||
|
<layout class="QVBoxLayout" name="rightPane"> |
||||
|
<item> |
||||
|
<widget class="QLabel" name="label"> |
||||
|
<property name="sizePolicy"> |
||||
|
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding"> |
||||
|
<horstretch>0</horstretch> |
||||
|
<verstretch>0</verstretch> |
||||
|
</sizepolicy> |
||||
|
</property> |
||||
|
<property name="text"> |
||||
|
<string><html><head/><body><p><span style=" font-size:24pt; font-weight:600;">Chordsheet</span><br/>by Ivan Holmes</p><p>Chordsheet is a piece of software that generates a chord sheet with a simple GUI. </p><p><a href="https://git.radivan.net/ivan/chordsheet"><span style=" text-decoration: underline; color:#0000ff;">Git repository</span></a></p></body></html></string> |
||||
|
</property> |
||||
|
<property name="alignment"> |
||||
|
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> |
||||
|
</property> |
||||
|
<property name="wordWrap"> |
||||
|
<bool>true</bool> |
||||
|
</property> |
||||
|
<property name="openExternalLinks"> |
||||
|
<bool>true</bool> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item> |
||||
|
<widget class="QLabel" name="versionLabel"> |
||||
|
<property name="sizePolicy"> |
||||
|
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Minimum"> |
||||
|
<horstretch>0</horstretch> |
||||
|
<verstretch>0</verstretch> |
||||
|
</sizepolicy> |
||||
|
</property> |
||||
|
<property name="text"> |
||||
|
<string>Version not set</string> |
||||
|
</property> |
||||
|
<property name="alignment"> |
||||
|
<set>Qt::AlignBottom|Qt::AlignRight|Qt::AlignTrailing</set> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
</layout> |
||||
|
</item> |
||||
|
</layout> |
||||
|
</widget> |
||||
|
<resources/> |
||||
|
<connections/> |
||||
|
</ui> |
@ -0,0 +1,291 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<ui version="4.0"> |
||||
|
<class>blocksWidget</class> |
||||
|
<widget class="QWidget" name="blocksWidget"> |
||||
|
<property name="geometry"> |
||||
|
<rect> |
||||
|
<x>0</x> |
||||
|
<y>0</y> |
||||
|
<width>387</width> |
||||
|
<height>206</height> |
||||
|
</rect> |
||||
|
</property> |
||||
|
<property name="windowTitle"> |
||||
|
<string>Blocks</string> |
||||
|
</property> |
||||
|
<layout class="QVBoxLayout" name="verticalLayout"> |
||||
|
<property name="spacing"> |
||||
|
<number>0</number> |
||||
|
</property> |
||||
|
<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> |
||||
|
<layout class="QFormLayout" name="formLayout_5"> |
||||
|
<property name="fieldGrowthPolicy"> |
||||
|
<enum>QFormLayout::ExpandingFieldsGrow</enum> |
||||
|
</property> |
||||
|
<property name="leftMargin"> |
||||
|
<number>6</number> |
||||
|
</property> |
||||
|
<property name="topMargin"> |
||||
|
<number>6</number> |
||||
|
</property> |
||||
|
<property name="rightMargin"> |
||||
|
<number>6</number> |
||||
|
</property> |
||||
|
<property name="bottomMargin"> |
||||
|
<number>6</number> |
||||
|
</property> |
||||
|
<item row="0" column="0"> |
||||
|
<widget class="QLabel" name="blockSectionLabel"> |
||||
|
<property name="text"> |
||||
|
<string>Section</string> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item row="0" column="1"> |
||||
|
<widget class="MComboBox" name="blockSectionComboBox"> |
||||
|
<property name="sizePolicy"> |
||||
|
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> |
||||
|
<horstretch>0</horstretch> |
||||
|
<verstretch>0</verstretch> |
||||
|
</sizepolicy> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
</layout> |
||||
|
</item> |
||||
|
<item> |
||||
|
<widget class="BlockTableView" name="blockTableView"> |
||||
|
<property name="sizePolicy"> |
||||
|
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Expanding"> |
||||
|
<horstretch>0</horstretch> |
||||
|
<verstretch>0</verstretch> |
||||
|
</sizepolicy> |
||||
|
</property> |
||||
|
<property name="editTriggers"> |
||||
|
<set>QAbstractItemView::NoEditTriggers</set> |
||||
|
</property> |
||||
|
<property name="dragEnabled"> |
||||
|
<bool>true</bool> |
||||
|
</property> |
||||
|
<property name="dragDropOverwriteMode"> |
||||
|
<bool>false</bool> |
||||
|
</property> |
||||
|
<property name="dragDropMode"> |
||||
|
<enum>QAbstractItemView::InternalMove</enum> |
||||
|
</property> |
||||
|
<property name="defaultDropAction"> |
||||
|
<enum>Qt::TargetMoveAction</enum> |
||||
|
</property> |
||||
|
<property name="selectionMode"> |
||||
|
<enum>QAbstractItemView::SingleSelection</enum> |
||||
|
</property> |
||||
|
<property name="selectionBehavior"> |
||||
|
<enum>QAbstractItemView::SelectRows</enum> |
||||
|
</property> |
||||
|
<property name="showGrid"> |
||||
|
<bool>false</bool> |
||||
|
</property> |
||||
|
<property name="cornerButtonEnabled"> |
||||
|
<bool>false</bool> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item> |
||||
|
<layout class="QGridLayout" name="blockGridLayout"> |
||||
|
<property name="leftMargin"> |
||||
|
<number>6</number> |
||||
|
</property> |
||||
|
<property name="topMargin"> |
||||
|
<number>6</number> |
||||
|
</property> |
||||
|
<property name="rightMargin"> |
||||
|
<number>6</number> |
||||
|
</property> |
||||
|
<property name="bottomMargin"> |
||||
|
<number>6</number> |
||||
|
</property> |
||||
|
<property name="spacing"> |
||||
|
<number>6</number> |
||||
|
</property> |
||||
|
<item row="0" column="0"> |
||||
|
<widget class="QLabel" name="blockLengthLabel"> |
||||
|
<property name="text"> |
||||
|
<string>Length</string> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item row="0" column="4"> |
||||
|
<widget class="QComboBox" name="blockChordComboBox"/> |
||||
|
</item> |
||||
|
<item row="1" column="0"> |
||||
|
<widget class="QLabel" name="blockNotesLabel"> |
||||
|
<property name="minimumSize"> |
||||
|
<size> |
||||
|
<width>0</width> |
||||
|
<height>0</height> |
||||
|
</size> |
||||
|
</property> |
||||
|
<property name="text"> |
||||
|
<string>Notes</string> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item row="0" column="3"> |
||||
|
<widget class="QLabel" name="blockChordLabel"> |
||||
|
<property name="text"> |
||||
|
<string>Chord</string> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item row="0" column="1"> |
||||
|
<widget class="QLineEdit" name="blockLengthLineEdit"> |
||||
|
<property name="sizePolicy"> |
||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Fixed"> |
||||
|
<horstretch>0</horstretch> |
||||
|
<verstretch>0</verstretch> |
||||
|
</sizepolicy> |
||||
|
</property> |
||||
|
<property name="maximumSize"> |
||||
|
<size> |
||||
|
<width>40</width> |
||||
|
<height>16777215</height> |
||||
|
</size> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item row="1" column="1" colspan="4"> |
||||
|
<widget class="QLineEdit" name="blockNotesLineEdit"> |
||||
|
<property name="sizePolicy"> |
||||
|
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> |
||||
|
<horstretch>0</horstretch> |
||||
|
<verstretch>0</verstretch> |
||||
|
</sizepolicy> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item row="0" column="2"> |
||||
|
<spacer name="horizontalSpacer_4"> |
||||
|
<property name="orientation"> |
||||
|
<enum>Qt::Horizontal</enum> |
||||
|
</property> |
||||
|
<property name="sizeType"> |
||||
|
<enum>QSizePolicy::MinimumExpanding</enum> |
||||
|
</property> |
||||
|
<property name="sizeHint" stdset="0"> |
||||
|
<size> |
||||
|
<width>40</width> |
||||
|
<height>20</height> |
||||
|
</size> |
||||
|
</property> |
||||
|
</spacer> |
||||
|
</item> |
||||
|
</layout> |
||||
|
</item> |
||||
|
<item> |
||||
|
<layout class="QHBoxLayout" name="bottomBlockHorizontalLayout"> |
||||
|
<property name="spacing"> |
||||
|
<number>6</number> |
||||
|
</property> |
||||
|
<property name="leftMargin"> |
||||
|
<number>6</number> |
||||
|
</property> |
||||
|
<property name="topMargin"> |
||||
|
<number>0</number> |
||||
|
</property> |
||||
|
<property name="rightMargin"> |
||||
|
<number>6</number> |
||||
|
</property> |
||||
|
<property name="bottomMargin"> |
||||
|
<number>6</number> |
||||
|
</property> |
||||
|
<item> |
||||
|
<widget class="QPushButton" name="removeBlockButton"> |
||||
|
<property name="text"> |
||||
|
<string>Remove block</string> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item> |
||||
|
<spacer name="horizontalSpacer_6"> |
||||
|
<property name="orientation"> |
||||
|
<enum>Qt::Horizontal</enum> |
||||
|
</property> |
||||
|
<property name="sizeType"> |
||||
|
<enum>QSizePolicy::MinimumExpanding</enum> |
||||
|
</property> |
||||
|
<property name="sizeHint" stdset="0"> |
||||
|
<size> |
||||
|
<width>40</width> |
||||
|
<height>20</height> |
||||
|
</size> |
||||
|
</property> |
||||
|
</spacer> |
||||
|
</item> |
||||
|
<item> |
||||
|
<widget class="QPushButton" name="updateBlockButton"> |
||||
|
<property name="text"> |
||||
|
<string>Update block</string> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item> |
||||
|
<widget class="QPushButton" name="addBlockButton"> |
||||
|
<property name="enabled"> |
||||
|
<bool>true</bool> |
||||
|
</property> |
||||
|
<property name="text"> |
||||
|
<string>Add block</string> |
||||
|
</property> |
||||
|
<property name="checkable"> |
||||
|
<bool>false</bool> |
||||
|
</property> |
||||
|
<property name="autoDefault"> |
||||
|
<bool>false</bool> |
||||
|
</property> |
||||
|
<property name="default"> |
||||
|
<bool>false</bool> |
||||
|
</property> |
||||
|
<property name="flat"> |
||||
|
<bool>false</bool> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
</layout> |
||||
|
</item> |
||||
|
</layout> |
||||
|
</widget> |
||||
|
<customwidgets> |
||||
|
<customwidget> |
||||
|
<class>BlockTableView</class> |
||||
|
<extends>QTableView</extends> |
||||
|
<header>csgui/tableView.h</header> |
||||
|
</customwidget> |
||||
|
<customwidget> |
||||
|
<class>MComboBox</class> |
||||
|
<extends>QComboBox</extends> |
||||
|
<header>csgui/comboBox.h</header> |
||||
|
</customwidget> |
||||
|
</customwidgets> |
||||
|
<tabstops> |
||||
|
<tabstop>blockLengthLineEdit</tabstop> |
||||
|
<tabstop>blockChordComboBox</tabstop> |
||||
|
<tabstop>blockNotesLineEdit</tabstop> |
||||
|
<tabstop>removeBlockButton</tabstop> |
||||
|
<tabstop>updateBlockButton</tabstop> |
||||
|
<tabstop>addBlockButton</tabstop> |
||||
|
</tabstops> |
||||
|
<resources/> |
||||
|
<connections/> |
||||
|
</ui> |
@ -0,0 +1,237 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<ui version="4.0"> |
||||
|
<class>chordsWidget</class> |
||||
|
<widget class="QWidget" name="chordsWidget"> |
||||
|
<property name="geometry"> |
||||
|
<rect> |
||||
|
<x>0</x> |
||||
|
<y>0</y> |
||||
|
<width>393</width> |
||||
|
<height>236</height> |
||||
|
</rect> |
||||
|
</property> |
||||
|
<property name="windowTitle"> |
||||
|
<string>Chords</string> |
||||
|
</property> |
||||
|
<layout class="QVBoxLayout" name="verticalLayout"> |
||||
|
<property name="spacing"> |
||||
|
<number>0</number> |
||||
|
</property> |
||||
|
<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="ChordTableView" name="chordTableView"> |
||||
|
<property name="sizePolicy"> |
||||
|
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Expanding"> |
||||
|
<horstretch>0</horstretch> |
||||
|
<verstretch>0</verstretch> |
||||
|
</sizepolicy> |
||||
|
</property> |
||||
|
<property name="editTriggers"> |
||||
|
<set>QAbstractItemView::NoEditTriggers</set> |
||||
|
</property> |
||||
|
<property name="dragEnabled"> |
||||
|
<bool>true</bool> |
||||
|
</property> |
||||
|
<property name="dragDropOverwriteMode"> |
||||
|
<bool>false</bool> |
||||
|
</property> |
||||
|
<property name="dragDropMode"> |
||||
|
<enum>QAbstractItemView::InternalMove</enum> |
||||
|
</property> |
||||
|
<property name="defaultDropAction"> |
||||
|
<enum>Qt::IgnoreAction</enum> |
||||
|
</property> |
||||
|
<property name="selectionMode"> |
||||
|
<enum>QAbstractItemView::SingleSelection</enum> |
||||
|
</property> |
||||
|
<property name="selectionBehavior"> |
||||
|
<enum>QAbstractItemView::SelectRows</enum> |
||||
|
</property> |
||||
|
<property name="showGrid"> |
||||
|
<bool>false</bool> |
||||
|
</property> |
||||
|
<property name="sortingEnabled"> |
||||
|
<bool>false</bool> |
||||
|
</property> |
||||
|
<property name="cornerButtonEnabled"> |
||||
|
<bool>false</bool> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item> |
||||
|
<layout class="QVBoxLayout" name="verticalLayout_2"> |
||||
|
<property name="spacing"> |
||||
|
<number>6</number> |
||||
|
</property> |
||||
|
<property name="leftMargin"> |
||||
|
<number>6</number> |
||||
|
</property> |
||||
|
<property name="topMargin"> |
||||
|
<number>6</number> |
||||
|
</property> |
||||
|
<property name="rightMargin"> |
||||
|
<number>6</number> |
||||
|
</property> |
||||
|
<property name="bottomMargin"> |
||||
|
<number>6</number> |
||||
|
</property> |
||||
|
<item> |
||||
|
<layout class="QGridLayout" name="chordGridLayout"> |
||||
|
<property name="spacing"> |
||||
|
<number>6</number> |
||||
|
</property> |
||||
|
<item row="1" column="1"> |
||||
|
<widget class="QLineEdit" name="guitarVoicingLineEdit"> |
||||
|
<property name="sizePolicy"> |
||||
|
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> |
||||
|
<horstretch>0</horstretch> |
||||
|
<verstretch>0</verstretch> |
||||
|
</sizepolicy> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item row="1" column="0"> |
||||
|
<widget class="QLabel" name="guitarVoicingLabel"> |
||||
|
<property name="text"> |
||||
|
<string>Guitar voicing</string> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item row="2" column="1"> |
||||
|
<widget class="QLineEdit" name="pianoVoicingLineEdit"/> |
||||
|
</item> |
||||
|
<item row="0" column="1"> |
||||
|
<widget class="QLineEdit" name="chordNameLineEdit"> |
||||
|
<property name="sizePolicy"> |
||||
|
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> |
||||
|
<horstretch>0</horstretch> |
||||
|
<verstretch>0</verstretch> |
||||
|
</sizepolicy> |
||||
|
</property> |
||||
|
<property name="maximumSize"> |
||||
|
<size> |
||||
|
<width>100</width> |
||||
|
<height>16777215</height> |
||||
|
</size> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item row="2" column="0"> |
||||
|
<widget class="QLabel" name="pianoVoicingLabel"> |
||||
|
<property name="text"> |
||||
|
<string>Piano voicing</string> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item row="0" column="0"> |
||||
|
<widget class="QLabel" name="chordNameLabel"> |
||||
|
<property name="text"> |
||||
|
<string>Chord name</string> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item row="1" column="2"> |
||||
|
<widget class="QPushButton" name="guitarVoicingButton"> |
||||
|
<property name="maximumSize"> |
||||
|
<size> |
||||
|
<width>16777215</width> |
||||
|
<height>16777215</height> |
||||
|
</size> |
||||
|
</property> |
||||
|
<property name="text"> |
||||
|
<string>Editor...</string> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
</layout> |
||||
|
</item> |
||||
|
</layout> |
||||
|
</item> |
||||
|
<item> |
||||
|
<layout class="QHBoxLayout" name="bottomChordHorizontalLayout"> |
||||
|
<property name="spacing"> |
||||
|
<number>6</number> |
||||
|
</property> |
||||
|
<property name="leftMargin"> |
||||
|
<number>6</number> |
||||
|
</property> |
||||
|
<property name="topMargin"> |
||||
|
<number>0</number> |
||||
|
</property> |
||||
|
<property name="rightMargin"> |
||||
|
<number>6</number> |
||||
|
</property> |
||||
|
<property name="bottomMargin"> |
||||
|
<number>6</number> |
||||
|
</property> |
||||
|
<item> |
||||
|
<widget class="QPushButton" name="removeChordButton"> |
||||
|
<property name="text"> |
||||
|
<string>Remove chord</string> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item> |
||||
|
<spacer name="horizontalSpacer_3"> |
||||
|
<property name="orientation"> |
||||
|
<enum>Qt::Horizontal</enum> |
||||
|
</property> |
||||
|
<property name="sizeType"> |
||||
|
<enum>QSizePolicy::MinimumExpanding</enum> |
||||
|
</property> |
||||
|
<property name="sizeHint" stdset="0"> |
||||
|
<size> |
||||
|
<width>40</width> |
||||
|
<height>20</height> |
||||
|
</size> |
||||
|
</property> |
||||
|
</spacer> |
||||
|
</item> |
||||
|
<item> |
||||
|
<widget class="QPushButton" name="updateChordButton"> |
||||
|
<property name="text"> |
||||
|
<string>Update chord</string> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item> |
||||
|
<widget class="QPushButton" name="addChordButton"> |
||||
|
<property name="text"> |
||||
|
<string>Add chord</string> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
</layout> |
||||
|
</item> |
||||
|
</layout> |
||||
|
</widget> |
||||
|
<customwidgets> |
||||
|
<customwidget> |
||||
|
<class>ChordTableView</class> |
||||
|
<extends>QTableView</extends> |
||||
|
<header>csgui/tableView.h</header> |
||||
|
</customwidget> |
||||
|
</customwidgets> |
||||
|
<tabstops> |
||||
|
<tabstop>chordNameLineEdit</tabstop> |
||||
|
<tabstop>guitarVoicingLineEdit</tabstop> |
||||
|
<tabstop>guitarVoicingButton</tabstop> |
||||
|
<tabstop>pianoVoicingLineEdit</tabstop> |
||||
|
<tabstop>removeChordButton</tabstop> |
||||
|
<tabstop>updateChordButton</tabstop> |
||||
|
<tabstop>addChordButton</tabstop> |
||||
|
</tabstops> |
||||
|
<resources/> |
||||
|
<connections/> |
||||
|
</ui> |
@ -0,0 +1,162 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<ui version="4.0"> |
||||
|
<class>docInfoWidget</class> |
||||
|
<widget class="QWidget" name="docInfoWidget"> |
||||
|
<property name="windowModality"> |
||||
|
<enum>Qt::NonModal</enum> |
||||
|
</property> |
||||
|
<property name="geometry"> |
||||
|
<rect> |
||||
|
<x>0</x> |
||||
|
<y>0</y> |
||||
|
<width>291</width> |
||||
|
<height>170</height> |
||||
|
</rect> |
||||
|
</property> |
||||
|
<property name="sizePolicy"> |
||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed"> |
||||
|
<horstretch>0</horstretch> |
||||
|
<verstretch>0</verstretch> |
||||
|
</sizepolicy> |
||||
|
</property> |
||||
|
<property name="windowTitle"> |
||||
|
<string>Document information</string> |
||||
|
</property> |
||||
|
<layout class="QHBoxLayout" name="horizontalLayout"> |
||||
|
<property name="leftMargin"> |
||||
|
<number>6</number> |
||||
|
</property> |
||||
|
<property name="topMargin"> |
||||
|
<number>6</number> |
||||
|
</property> |
||||
|
<property name="rightMargin"> |
||||
|
<number>6</number> |
||||
|
</property> |
||||
|
<property name="bottomMargin"> |
||||
|
<number>6</number> |
||||
|
</property> |
||||
|
<item> |
||||
|
<layout class="QFormLayout" name="formLayoutOverview"> |
||||
|
<property name="fieldGrowthPolicy"> |
||||
|
<enum>QFormLayout::ExpandingFieldsGrow</enum> |
||||
|
</property> |
||||
|
<property name="horizontalSpacing"> |
||||
|
<number>6</number> |
||||
|
</property> |
||||
|
<property name="verticalSpacing"> |
||||
|
<number>6</number> |
||||
|
</property> |
||||
|
<item row="0" column="0"> |
||||
|
<widget class="QLabel" name="titleLabel"> |
||||
|
<property name="text"> |
||||
|
<string>Title</string> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item row="0" column="1"> |
||||
|
<widget class="QLineEdit" name="titleLineEdit"> |
||||
|
<property name="sizePolicy"> |
||||
|
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> |
||||
|
<horstretch>0</horstretch> |
||||
|
<verstretch>0</verstretch> |
||||
|
</sizepolicy> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item row="1" column="0"> |
||||
|
<widget class="QLabel" name="subtitleLabel"> |
||||
|
<property name="text"> |
||||
|
<string>Subtitle</string> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item row="1" column="1"> |
||||
|
<widget class="QLineEdit" name="subtitleLineEdit"/> |
||||
|
</item> |
||||
|
<item row="2" column="0"> |
||||
|
<widget class="QLabel" name="composerLabel"> |
||||
|
<property name="text"> |
||||
|
<string>Composer</string> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item row="2" column="1"> |
||||
|
<widget class="QLineEdit" name="composerLineEdit"> |
||||
|
<property name="sizePolicy"> |
||||
|
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> |
||||
|
<horstretch>0</horstretch> |
||||
|
<verstretch>0</verstretch> |
||||
|
</sizepolicy> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item row="3" column="0"> |
||||
|
<widget class="QLabel" name="arrangerLabel"> |
||||
|
<property name="text"> |
||||
|
<string>Arranger</string> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item row="3" column="1"> |
||||
|
<widget class="QLineEdit" name="arrangerLineEdit"> |
||||
|
<property name="sizePolicy"> |
||||
|
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> |
||||
|
<horstretch>0</horstretch> |
||||
|
<verstretch>0</verstretch> |
||||
|
</sizepolicy> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item row="4" column="0"> |
||||
|
<widget class="QLabel" name="tempoLabel"> |
||||
|
<property name="text"> |
||||
|
<string>Tempo</string> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item row="4" column="1"> |
||||
|
<widget class="QLineEdit" name="tempoLineEdit"> |
||||
|
<property name="sizePolicy"> |
||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Fixed"> |
||||
|
<horstretch>0</horstretch> |
||||
|
<verstretch>0</verstretch> |
||||
|
</sizepolicy> |
||||
|
</property> |
||||
|
<property name="maximumSize"> |
||||
|
<size> |
||||
|
<width>60</width> |
||||
|
<height>16777215</height> |
||||
|
</size> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item row="5" column="0"> |
||||
|
<widget class="QLabel" name="timeSignatureLabel"> |
||||
|
<property name="text"> |
||||
|
<string>Time</string> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item row="5" column="1"> |
||||
|
<widget class="QSpinBox" name="timeSignatureSpinBox"> |
||||
|
<property name="maximumSize"> |
||||
|
<size> |
||||
|
<width>40</width> |
||||
|
<height>16777215</height> |
||||
|
</size> |
||||
|
</property> |
||||
|
<property name="specialValueText"> |
||||
|
<string/> |
||||
|
</property> |
||||
|
<property name="value"> |
||||
|
<number>4</number> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
</layout> |
||||
|
</item> |
||||
|
</layout> |
||||
|
</widget> |
||||
|
<resources/> |
||||
|
<connections/> |
||||
|
</ui> |
@ -0,0 +1,57 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<ui version="4.0"> |
||||
|
<class>docWindow</class> |
||||
|
<widget class="QWidget" name="docWindow"> |
||||
|
<property name="geometry"> |
||||
|
<rect> |
||||
|
<x>0</x> |
||||
|
<y>0</y> |
||||
|
<width>424</width> |
||||
|
<height>324</height> |
||||
|
</rect> |
||||
|
</property> |
||||
|
<property name="windowTitle"> |
||||
|
<string>Unsaved</string> |
||||
|
</property> |
||||
|
<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="PDFViewer" name="pdfArea" native="true"> |
||||
|
<property name="sizePolicy"> |
||||
|
<sizepolicy hsizetype="Minimum" vsizetype="Minimum"> |
||||
|
<horstretch>0</horstretch> |
||||
|
<verstretch>0</verstretch> |
||||
|
</sizepolicy> |
||||
|
</property> |
||||
|
<property name="minimumSize"> |
||||
|
<size> |
||||
|
<width>200</width> |
||||
|
<height>300</height> |
||||
|
</size> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
</layout> |
||||
|
</widget> |
||||
|
<customwidgets> |
||||
|
<customwidget> |
||||
|
<class>PDFViewer</class> |
||||
|
<extends>QWidget</extends> |
||||
|
<header>csgui/pdfViewer.h</header> |
||||
|
<container>1</container> |
||||
|
</customwidget> |
||||
|
</customwidgets> |
||||
|
<resources/> |
||||
|
<connections/> |
||||
|
</ui> |
After Width: 1024 | Height: 1024 | Size: 236 KiB |
@ -0,0 +1,83 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<ui version="4.0"> |
||||
|
<class>previewPanel</class> |
||||
|
<widget class="QWidget" name="previewPanel"> |
||||
|
<property name="geometry"> |
||||
|
<rect> |
||||
|
<x>0</x> |
||||
|
<y>0</y> |
||||
|
<width>202</width> |
||||
|
<height>72</height> |
||||
|
</rect> |
||||
|
</property> |
||||
|
<property name="sizePolicy"> |
||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed"> |
||||
|
<horstretch>0</horstretch> |
||||
|
<verstretch>0</verstretch> |
||||
|
</sizepolicy> |
||||
|
</property> |
||||
|
<property name="minimumSize"> |
||||
|
<size> |
||||
|
<width>202</width> |
||||
|
<height>72</height> |
||||
|
</size> |
||||
|
</property> |
||||
|
<property name="windowTitle"> |
||||
|
<string>Preview</string> |
||||
|
</property> |
||||
|
<layout class="QVBoxLayout" name="verticalLayout"> |
||||
|
<property name="spacing"> |
||||
|
<number>6</number> |
||||
|
</property> |
||||
|
<property name="leftMargin"> |
||||
|
<number>6</number> |
||||
|
</property> |
||||
|
<property name="topMargin"> |
||||
|
<number>6</number> |
||||
|
</property> |
||||
|
<property name="rightMargin"> |
||||
|
<number>6</number> |
||||
|
</property> |
||||
|
<property name="bottomMargin"> |
||||
|
<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> |
||||
|
</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> |
||||
|
<verstretch>0</verstretch> |
||||
|
</sizepolicy> |
||||
|
</property> |
||||
|
<property name="text"> |
||||
|
<string>Update preview</string> |
||||
|
</property> |
||||
|
<property name="checkable"> |
||||
|
<bool>false</bool> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
</layout> |
||||
|
</widget> |
||||
|
<resources/> |
||||
|
<connections/> |
||||
|
</ui> |
@ -0,0 +1,326 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<ui version="4.0"> |
||||
|
<class>psetupWidget</class> |
||||
|
<widget class="QWidget" name="psetupWidget"> |
||||
|
<property name="geometry"> |
||||
|
<rect> |
||||
|
<x>0</x> |
||||
|
<y>0</y> |
||||
|
<width>173</width> |
||||
|
<height>306</height> |
||||
|
</rect> |
||||
|
</property> |
||||
|
<property name="sizePolicy"> |
||||
|
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> |
||||
|
<horstretch>0</horstretch> |
||||
|
<verstretch>0</verstretch> |
||||
|
</sizepolicy> |
||||
|
</property> |
||||
|
<property name="windowTitle"> |
||||
|
<string>Page setup</string> |
||||
|
</property> |
||||
|
<layout class="QVBoxLayout" name="verticalLayout"> |
||||
|
<property name="leftMargin"> |
||||
|
<number>6</number> |
||||
|
</property> |
||||
|
<property name="topMargin"> |
||||
|
<number>6</number> |
||||
|
</property> |
||||
|
<property name="rightMargin"> |
||||
|
<number>6</number> |
||||
|
</property> |
||||
|
<property name="bottomMargin"> |
||||
|
<number>6</number> |
||||
|
</property> |
||||
|
<item> |
||||
|
<layout class="QGridLayout" name="gridLayout" rowstretch="0,0,0,0,0,0,0,0,0,0" columnstretch="0,0"> |
||||
|
<property name="spacing"> |
||||
|
<number>6</number> |
||||
|
</property> |
||||
|
<item row="6" column="0" colspan="2"> |
||||
|
<widget class="QFontComboBox" name="fontComboBox"> |
||||
|
<property name="enabled"> |
||||
|
<bool>true</bool> |
||||
|
</property> |
||||
|
<property name="sizePolicy"> |
||||
|
<sizepolicy hsizetype="Maximum" vsizetype="Fixed"> |
||||
|
<horstretch>0</horstretch> |
||||
|
<verstretch>0</verstretch> |
||||
|
</sizepolicy> |
||||
|
</property> |
||||
|
<property name="minimumSize"> |
||||
|
<size> |
||||
|
<width>150</width> |
||||
|
<height>0</height> |
||||
|
</size> |
||||
|
</property> |
||||
|
<property name="maximumSize"> |
||||
|
<size> |
||||
|
<width>16777215</width> |
||||
|
<height>16777215</height> |
||||
|
</size> |
||||
|
</property> |
||||
|
<property name="editable"> |
||||
|
<bool>false</bool> |
||||
|
</property> |
||||
|
<property name="maxVisibleItems"> |
||||
|
<number>12</number> |
||||
|
</property> |
||||
|
<property name="sizeAdjustPolicy"> |
||||
|
<enum>QComboBox::AdjustToContents</enum> |
||||
|
</property> |
||||
|
<property name="frame"> |
||||
|
<bool>true</bool> |
||||
|
</property> |
||||
|
<property name="writingSystem"> |
||||
|
<enum>QFontDatabase::Any</enum> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item row="7" column="1"> |
||||
|
<widget class="QCheckBox" name="includedFontCheckBox"> |
||||
|
<property name="minimumSize"> |
||||
|
<size> |
||||
|
<width>0</width> |
||||
|
<height>0</height> |
||||
|
</size> |
||||
|
</property> |
||||
|
<property name="text"> |
||||
|
<string>FreeSans</string> |
||||
|
</property> |
||||
|
<property name="checked"> |
||||
|
<bool>true</bool> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item row="3" column="1"> |
||||
|
<widget class="QLineEdit" name="rightMarginLineEdit"> |
||||
|
<property name="maximumSize"> |
||||
|
<size> |
||||
|
<width>60</width> |
||||
|
<height>16777215</height> |
||||
|
</size> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item row="5" column="1"> |
||||
|
<widget class="QLineEdit" name="bottomMarginLineEdit"> |
||||
|
<property name="maximumSize"> |
||||
|
<size> |
||||
|
<width>60</width> |
||||
|
<height>16777215</height> |
||||
|
</size> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item row="7" column="0"> |
||||
|
<widget class="QLabel" name="fontLabel"> |
||||
|
<property name="maximumSize"> |
||||
|
<size> |
||||
|
<width>40</width> |
||||
|
<height>16777215</height> |
||||
|
</size> |
||||
|
</property> |
||||
|
<property name="text"> |
||||
|
<string>Font</string> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item row="0" column="1"> |
||||
|
<widget class="QComboBox" name="pageSizeComboBox"> |
||||
|
<property name="maximumSize"> |
||||
|
<size> |
||||
|
<width>70</width> |
||||
|
<height>26</height> |
||||
|
</size> |
||||
|
</property> |
||||
|
<property name="editable"> |
||||
|
<bool>true</bool> |
||||
|
</property> |
||||
|
<property name="frame"> |
||||
|
<bool>true</bool> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item row="9" column="0"> |
||||
|
<widget class="QLabel" name="beatWidthLabel"> |
||||
|
<property name="minimumSize"> |
||||
|
<size> |
||||
|
<width>0</width> |
||||
|
<height>0</height> |
||||
|
</size> |
||||
|
</property> |
||||
|
<property name="text"> |
||||
|
<string>Beat width</string> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item row="4" column="0"> |
||||
|
<widget class="QLabel" name="topMarginLabel"> |
||||
|
<property name="minimumSize"> |
||||
|
<size> |
||||
|
<width>0</width> |
||||
|
<height>0</height> |
||||
|
</size> |
||||
|
</property> |
||||
|
<property name="maximumSize"> |
||||
|
<size> |
||||
|
<width>16777215</width> |
||||
|
<height>16777215</height> |
||||
|
</size> |
||||
|
</property> |
||||
|
<property name="text"> |
||||
|
<string>Top margin</string> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item row="1" column="1"> |
||||
|
<widget class="QComboBox" name="documentUnitsComboBox"> |
||||
|
<property name="enabled"> |
||||
|
<bool>true</bool> |
||||
|
</property> |
||||
|
<property name="maximumSize"> |
||||
|
<size> |
||||
|
<width>70</width> |
||||
|
<height>26</height> |
||||
|
</size> |
||||
|
</property> |
||||
|
<property name="editable"> |
||||
|
<bool>true</bool> |
||||
|
</property> |
||||
|
<property name="frame"> |
||||
|
<bool>true</bool> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item row="2" column="1"> |
||||
|
<widget class="QLineEdit" name="leftMarginLineEdit"> |
||||
|
<property name="maximumSize"> |
||||
|
<size> |
||||
|
<width>60</width> |
||||
|
<height>16777215</height> |
||||
|
</size> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item row="4" column="1"> |
||||
|
<widget class="QLineEdit" name="topMarginLineEdit"> |
||||
|
<property name="maximumSize"> |
||||
|
<size> |
||||
|
<width>60</width> |
||||
|
<height>16777215</height> |
||||
|
</size> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item row="0" column="0"> |
||||
|
<widget class="QLabel" name="pageSizeLabel"> |
||||
|
<property name="text"> |
||||
|
<string>Page size</string> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item row="9" column="1"> |
||||
|
<widget class="QLineEdit" name="beatWidthLineEdit"> |
||||
|
<property name="maximumSize"> |
||||
|
<size> |
||||
|
<width>60</width> |
||||
|
<height>16777215</height> |
||||
|
</size> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item row="2" column="0"> |
||||
|
<widget class="QLabel" name="leftMarginLabel"> |
||||
|
<property name="minimumSize"> |
||||
|
<size> |
||||
|
<width>0</width> |
||||
|
<height>0</height> |
||||
|
</size> |
||||
|
</property> |
||||
|
<property name="text"> |
||||
|
<string>Left margin</string> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item row="5" column="0"> |
||||
|
<widget class="QLabel" name="bottomMarginLabel"> |
||||
|
<property name="minimumSize"> |
||||
|
<size> |
||||
|
<width>0</width> |
||||
|
<height>0</height> |
||||
|
</size> |
||||
|
</property> |
||||
|
<property name="text"> |
||||
|
<string>Bottom margin</string> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item row="8" column="0"> |
||||
|
<widget class="QLabel" name="lineSpacingLabel"> |
||||
|
<property name="minimumSize"> |
||||
|
<size> |
||||
|
<width>0</width> |
||||
|
<height>0</height> |
||||
|
</size> |
||||
|
</property> |
||||
|
<property name="text"> |
||||
|
<string>Line spacing</string> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item row="3" column="0"> |
||||
|
<widget class="QLabel" name="rightMarginLabel"> |
||||
|
<property name="minimumSize"> |
||||
|
<size> |
||||
|
<width>0</width> |
||||
|
<height>0</height> |
||||
|
</size> |
||||
|
</property> |
||||
|
<property name="text"> |
||||
|
<string>Right margin</string> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item row="1" column="0"> |
||||
|
<widget class="QLabel" name="documentUnitsLabel"> |
||||
|
<property name="text"> |
||||
|
<string>Units</string> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item row="8" column="1"> |
||||
|
<widget class="QDoubleSpinBox" name="lineSpacingDoubleSpinBox"> |
||||
|
<property name="minimumSize"> |
||||
|
<size> |
||||
|
<width>70</width> |
||||
|
<height>0</height> |
||||
|
</size> |
||||
|
</property> |
||||
|
<property name="maximumSize"> |
||||
|
<size> |
||||
|
<width>70</width> |
||||
|
<height>16777215</height> |
||||
|
</size> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
</layout> |
||||
|
</item> |
||||
|
</layout> |
||||
|
</widget> |
||||
|
<tabstops> |
||||
|
<tabstop>pageSizeComboBox</tabstop> |
||||
|
<tabstop>documentUnitsComboBox</tabstop> |
||||
|
<tabstop>leftMarginLineEdit</tabstop> |
||||
|
<tabstop>rightMarginLineEdit</tabstop> |
||||
|
<tabstop>topMarginLineEdit</tabstop> |
||||
|
<tabstop>bottomMarginLineEdit</tabstop> |
||||
|
<tabstop>fontComboBox</tabstop> |
||||
|
<tabstop>includedFontCheckBox</tabstop> |
||||
|
<tabstop>lineSpacingDoubleSpinBox</tabstop> |
||||
|
<tabstop>beatWidthLineEdit</tabstop> |
||||
|
</tabstops> |
||||
|
<resources/> |
||||
|
<connections/> |
||||
|
</ui> |
@ -0,0 +1,165 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<ui version="4.0"> |
||||
|
<class>sectionsWidget</class> |
||||
|
<widget class="QWidget" name="sectionsWidget"> |
||||
|
<property name="geometry"> |
||||
|
<rect> |
||||
|
<x>0</x> |
||||
|
<y>0</y> |
||||
|
<width>405</width> |
||||
|
<height>170</height> |
||||
|
</rect> |
||||
|
</property> |
||||
|
<property name="windowTitle"> |
||||
|
<string>Sections</string> |
||||
|
</property> |
||||
|
<layout class="QVBoxLayout" name="verticalLayout"> |
||||
|
<property name="spacing"> |
||||
|
<number>0</number> |
||||
|
</property> |
||||
|
<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="SectionTableView" name="sectionTableView"> |
||||
|
<property name="sizePolicy"> |
||||
|
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Expanding"> |
||||
|
<horstretch>0</horstretch> |
||||
|
<verstretch>0</verstretch> |
||||
|
</sizepolicy> |
||||
|
</property> |
||||
|
<property name="editTriggers"> |
||||
|
<set>QAbstractItemView::NoEditTriggers</set> |
||||
|
</property> |
||||
|
<property name="dragEnabled"> |
||||
|
<bool>true</bool> |
||||
|
</property> |
||||
|
<property name="dragDropOverwriteMode"> |
||||
|
<bool>false</bool> |
||||
|
</property> |
||||
|
<property name="dragDropMode"> |
||||
|
<enum>QAbstractItemView::InternalMove</enum> |
||||
|
</property> |
||||
|
<property name="defaultDropAction"> |
||||
|
<enum>Qt::TargetMoveAction</enum> |
||||
|
</property> |
||||
|
<property name="selectionMode"> |
||||
|
<enum>QAbstractItemView::SingleSelection</enum> |
||||
|
</property> |
||||
|
<property name="selectionBehavior"> |
||||
|
<enum>QAbstractItemView::SelectRows</enum> |
||||
|
</property> |
||||
|
<property name="showGrid"> |
||||
|
<bool>false</bool> |
||||
|
</property> |
||||
|
<property name="cornerButtonEnabled"> |
||||
|
<bool>false</bool> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item> |
||||
|
<layout class="QFormLayout" name="formLayout_3"> |
||||
|
<property name="fieldGrowthPolicy"> |
||||
|
<enum>QFormLayout::ExpandingFieldsGrow</enum> |
||||
|
</property> |
||||
|
<property name="horizontalSpacing"> |
||||
|
<number>6</number> |
||||
|
</property> |
||||
|
<property name="leftMargin"> |
||||
|
<number>6</number> |
||||
|
</property> |
||||
|
<property name="topMargin"> |
||||
|
<number>6</number> |
||||
|
</property> |
||||
|
<property name="rightMargin"> |
||||
|
<number>6</number> |
||||
|
</property> |
||||
|
<property name="bottomMargin"> |
||||
|
<number>6</number> |
||||
|
</property> |
||||
|
<item row="0" column="0"> |
||||
|
<widget class="QLabel" name="sectionNameLabel"> |
||||
|
<property name="text"> |
||||
|
<string>Name</string> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item row="0" column="1"> |
||||
|
<widget class="QLineEdit" name="sectionNameLineEdit"/> |
||||
|
</item> |
||||
|
</layout> |
||||
|
</item> |
||||
|
<item> |
||||
|
<layout class="QHBoxLayout" name="bottomSectionHorizontalLayout"> |
||||
|
<property name="spacing"> |
||||
|
<number>6</number> |
||||
|
</property> |
||||
|
<property name="leftMargin"> |
||||
|
<number>6</number> |
||||
|
</property> |
||||
|
<property name="rightMargin"> |
||||
|
<number>6</number> |
||||
|
</property> |
||||
|
<property name="bottomMargin"> |
||||
|
<number>6</number> |
||||
|
</property> |
||||
|
<item> |
||||
|
<widget class="QPushButton" name="removeSectionButton"> |
||||
|
<property name="text"> |
||||
|
<string>Remove section</string> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item> |
||||
|
<spacer name="horizontalSpacer_7"> |
||||
|
<property name="orientation"> |
||||
|
<enum>Qt::Horizontal</enum> |
||||
|
</property> |
||||
|
<property name="sizeType"> |
||||
|
<enum>QSizePolicy::MinimumExpanding</enum> |
||||
|
</property> |
||||
|
<property name="sizeHint" stdset="0"> |
||||
|
<size> |
||||
|
<width>0</width> |
||||
|
<height>20</height> |
||||
|
</size> |
||||
|
</property> |
||||
|
</spacer> |
||||
|
</item> |
||||
|
<item> |
||||
|
<widget class="QPushButton" name="updateSectionButton"> |
||||
|
<property name="text"> |
||||
|
<string>Update section</string> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
<item> |
||||
|
<widget class="QPushButton" name="addSectionButton"> |
||||
|
<property name="text"> |
||||
|
<string>Add section</string> |
||||
|
</property> |
||||
|
</widget> |
||||
|
</item> |
||||
|
</layout> |
||||
|
</item> |
||||
|
</layout> |
||||
|
</widget> |
||||
|
<customwidgets> |
||||
|
<customwidget> |
||||
|
<class>SectionTableView</class> |
||||
|
<extends>QTableView</extends> |
||||
|
<header>csgui/tableView.h</header> |
||||
|
</customwidget> |
||||
|
</customwidgets> |
||||
|
<resources/> |
||||
|
<connections/> |
||||
|
</ui> |
@ -0,0 +1,43 @@ |
|||||
|
# UTF-8 |
||||
|
# |
||||
|
# For more details about fixed file info 'ffi' see: |
||||
|
# http://msdn.microsoft.com/en-us/library/ms646997.aspx |
||||
|
VSVersionInfo( |
||||
|
ffi=FixedFileInfo( |
||||
|
# filevers and prodvers should be always a tuple with four items: (1, 2, 3, 4) |
||||
|
# Set not needed items to zero 0. |
||||
|
filevers=(0, 5, 0, 0), |
||||
|
prodvers=(0, 5, 0, 0), |
||||
|
# Contains a bitmask that specifies the valid bits 'flags'r |
||||
|
mask=0x3f, |
||||
|
# Contains a bitmask that specifies the Boolean attributes of the file. |
||||
|
flags=0x0, |
||||
|
# The operating system for which this file was designed. |
||||
|
# 0x4 - NT and there is no need to change it. |
||||
|
OS=0x4, |
||||
|
# The general type of file. |
||||
|
# 0x1 - the file is an application. |
||||
|
fileType=0x1, |
||||
|
# The function of the file. |
||||
|
# 0x0 - the function is not defined for this fileType |
||||
|
subtype=0x0, |
||||
|
# Creation date and time stamp. |
||||
|
date=(0, 0) |
||||
|
), |
||||
|
kids=[ |
||||
|
StringFileInfo( |
||||
|
[ |
||||
|
StringTable( |
||||
|
u'040904B0', |
||||
|
[StringStruct(u'CompanyName', u'Ivan Holmes'), |
||||
|
StringStruct(u'FileDescription', u'Chordsheet'), |
||||
|
StringStruct(u'FileVersion', u'0.5.0'), |
||||
|
StringStruct(u'InternalName', u'Chordsheet'), |
||||
|
StringStruct(u'LegalCopyright', u'Copyright (c) Ivan Holmes, 2020. Some rights reserved.'), |
||||
|
StringStruct(u'OriginalFilename', u'chordsheet.exe'), |
||||
|
StringStruct(u'ProductName', u'Chordsheet'), |
||||
|
StringStruct(u'ProductVersion', u'0.5.0')]) |
||||
|
]), |
||||
|
VarFileInfo([VarStruct(u'Translation', [1033, 1200])]) |
||||
|
] |
||||
|
) |
@ -0,0 +1,43 @@ |
|||||
|
# UTF-8 |
||||
|
# |
||||
|
# For more details about fixed file info 'ffi' see: |
||||
|
# http://msdn.microsoft.com/en-us/library/ms646997.aspx |
||||
|
VSVersionInfo( |
||||
|
ffi=FixedFileInfo( |
||||
|
# filevers and prodvers should be always a tuple with four items: (1, 2, 3, 4) |
||||
|
# Set not needed items to zero 0. |
||||
|
filevers=(%MAJOR_VERSION%, %MINOR_VERSION%, %PATCH_VERSION%, 0), |
||||
|
prodvers=(%MAJOR_VERSION%, %MINOR_VERSION%, %PATCH_VERSION%, 0), |
||||
|
# Contains a bitmask that specifies the valid bits 'flags'r |
||||
|
mask=0x3f, |
||||
|
# Contains a bitmask that specifies the Boolean attributes of the file. |
||||
|
flags=0x0, |
||||
|
# The operating system for which this file was designed. |
||||
|
# 0x4 - NT and there is no need to change it. |
||||
|
OS=0x4, |
||||
|
# The general type of file. |
||||
|
# 0x1 - the file is an application. |
||||
|
fileType=0x1, |
||||
|
# The function of the file. |
||||
|
# 0x0 - the function is not defined for this fileType |
||||
|
subtype=0x0, |
||||
|
# Creation date and time stamp. |
||||
|
date=(0, 0) |
||||
|
), |
||||
|
kids=[ |
||||
|
StringFileInfo( |
||||
|
[ |
||||
|
StringTable( |
||||
|
u'040904B0', |
||||
|
[StringStruct(u'CompanyName', u'Ivan Holmes'), |
||||
|
StringStruct(u'FileDescription', u'%APPNAME%'), |
||||
|
StringStruct(u'FileVersion', u'%VERSION%'), |
||||
|
StringStruct(u'InternalName', u'%APPNAME%'), |
||||
|
StringStruct(u'LegalCopyright', u'Copyright (c) Ivan Holmes, 2020. Some rights reserved.'), |
||||
|
StringStruct(u'OriginalFilename', u'chordsheet.exe'), |
||||
|
StringStruct(u'ProductName', u'%APPNAME%'), |
||||
|
StringStruct(u'ProductVersion', u'%VERSION%')]) |
||||
|
]), |
||||
|
VarFileInfo([VarStruct(u'Translation', [1033, 1200])]) |
||||
|
] |
||||
|
) |
Write
Preview
Loading…
Cancel
Save
Reference in new issue