Browse Source

commit as backup

master
Nils 5 years ago
parent
commit
02b5d8b4b7
  1. 1
      .gitignore
  2. 2
      CHANGELOG
  3. 674
      LICENSE
  4. 5
      configure
  5. 13
      desktop/desktop.desktop
  6. BIN
      desktop/icon256x256.png
  7. BIN
      desktop/icon32x32.png
  8. 430
      documentation/LICENSE
  9. 7
      documentation/README.txt
  10. 18
      documentation/build-documentation.sh
  11. 5
      documentation/english.part.adoc
  12. 5
      documentation/german.part.adoc
  13. 31
      engine/__init__.py
  14. 2314
      engine/api.py
  15. 331
      engine/block.py
  16. 56
      engine/config.py
  17. 142
      engine/cursor.py
  18. 1347
      engine/graphtracks.py
  19. 2812
      engine/items.py
  20. 142
      engine/lilypond.py
  21. 1070
      engine/main.py
  22. 52
      engine/oldmidi.py
  23. 1
      engine/resources/LICENSE
  24. 105
      engine/resources/lilypondTemplate/default.ly
  25. 17
      engine/resources/lilypondTemplate/minimal.ly
  26. BIN
      engine/resources/normal.wav
  27. BIN
      engine/resources/stressed.wav
  28. 1161
      engine/track.py
  29. 9
      laborejo2
  30. 103
      midiinput/stepmidiinput.py
  31. 0
      qtgui/__init__.py
  32. 635
      qtgui/conductor.py
  33. 177
      qtgui/constantsAndConfigs.py
  34. 242
      qtgui/cursor.py
  35. 49
      qtgui/designer/clefs.ui
  36. 956
      qtgui/designer/mainwindow.py
  37. 1675
      qtgui/designer/mainwindow.ui
  38. 99
      qtgui/designer/tickWidget.py
  39. 266
      qtgui/designer/tickWidget.ui
  40. 491
      qtgui/designer/trackWidget.py
  41. 868
      qtgui/designer/trackWidget.ui
  42. 571
      qtgui/graphs.py
  43. 920
      qtgui/items.py
  44. 200
      qtgui/mainwindow.py
  45. 570
      qtgui/menu.py
  46. 10728
      qtgui/resources.py
  47. BIN
      qtgui/resources/aboutlogo.png
  48. 4
      qtgui/resources/buildresources.sh
  49. 94
      qtgui/resources/euterpe.license.txt
  50. BIN
      qtgui/resources/euterpe.ttf
  51. BIN
      qtgui/resources/icon.png
  52. 55
      qtgui/resources/resources.qrc
  53. 58
      qtgui/resources/svg/accidentalsDoublesharp.svg
  54. 31
      qtgui/resources/svg/accidentalsFlat.svg
  55. 31
      qtgui/resources/svg/accidentalsFlatFlat.svg
  56. 31
      qtgui/resources/svg/accidentalsNatural.svg
  57. 31
      qtgui/resources/svg/accidentalsSharp.svg
  58. 62
      qtgui/resources/svg/blockEnd.svg
  59. 55
      qtgui/resources/svg/clefAlto.svg
  60. 56
      qtgui/resources/svg/clefBass.svg
  61. 61
      qtgui/resources/svg/clefBass_8.svg
  62. 55
      qtgui/resources/svg/clefPercussion.svg
  63. 56
      qtgui/resources/svg/clefTreble.svg
  64. 61
      qtgui/resources/svg/clefTreble^8.svg
  65. 61
      qtgui/resources/svg/clefTreble_8.svg
  66. 55
      qtgui/resources/svg/dot.svg
  67. 55
      qtgui/resources/svg/flag128.svg
  68. 55
      qtgui/resources/svg/flag128i.svg
  69. 55
      qtgui/resources/svg/flag16.svg
  70. 55
      qtgui/resources/svg/flag16i.svg
  71. 30
      qtgui/resources/svg/flag32.svg
  72. 55
      qtgui/resources/svg/flag32i.svg
  73. 55
      qtgui/resources/svg/flag64.svg
  74. 55
      qtgui/resources/svg/flag64i.svg
  75. 31
      qtgui/resources/svg/flag8.svg
  76. 55
      qtgui/resources/svg/flag8i.svg
  77. 56
      qtgui/resources/svg/noteheadsBlack.svg
  78. 55
      qtgui/resources/svg/noteheadsBrevis.svg
  79. 31
      qtgui/resources/svg/noteheadsHalf.svg
  80. 55
      qtgui/resources/svg/noteheadsLonga.svg
  81. 55
      qtgui/resources/svg/noteheadsMaxima.svg
  82. 56
      qtgui/resources/svg/noteheadsWhole.svg
  83. 82
      qtgui/resources/svg/numbers.svg
  84. 56
      qtgui/resources/svg/rest1.svg
  85. 31
      qtgui/resources/svg/rest128.svg
  86. 55
      qtgui/resources/svg/rest16.svg
  87. 56
      qtgui/resources/svg/rest2.svg
  88. 31
      qtgui/resources/svg/rest32.svg
  89. 56
      qtgui/resources/svg/rest4.svg
  90. 31
      qtgui/resources/svg/rest64.svg
  91. 56
      qtgui/resources/svg/rest8.svg
  92. 55
      qtgui/resources/svg/restBrevis.svg
  93. 55
      qtgui/resources/svg/restLonga.svg
  94. 55
      qtgui/resources/svg/restMaxima.svg
  95. 31
      qtgui/resources/svg/scriptsStaccato.svg
  96. 678
      qtgui/resources/svg/svg.license.txt
  97. 2
      qtgui/resources/translations/config.pro
  98. BIN
      qtgui/resources/translations/de.qm
  99. 11
      qtgui/resources/translations/de.ts
  100. 5
      qtgui/resources/translations/update.sh

1
.gitignore

@ -0,0 +1 @@
template/gitignore.template

2
CHANGELOG

@ -0,0 +1,2 @@
2019-04-15 Version 2.0
Initial Release

674
LICENSE

@ -0,0 +1,674 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.

5
configure

@ -0,0 +1,5 @@
#!/bin/bash
program=exampleClientCboxQtNsm #MUST be the same as engine/config.py shortName
cboxconfigure="--without-fluidsynth --without-libsmf"
. template/configure.template #. is the posix compatible version of source

13
desktop/desktop.desktop

@ -0,0 +1,13 @@
[Desktop Entry]
Type=Application
Name=Laborejo
GenericName=Sequencer
Comment=MIDI sequencer based on classical music notation.
Comment[de]=MIDI-Sequencer mit Musiknoten
Exec=laborejo2
Icon=laborejo
Terminal=false
StartupNotify=false
Categories=AudioVideo;Audio;X-Recorders;X-Multitrack;X-Jack;
X-NSM-capable=true
Version=2.0

BIN
desktop/icon256x256.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 680 B

BIN
desktop/icon32x32.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 680 B

430
documentation/LICENSE

@ -0,0 +1,430 @@
from: https://creativecommons.org/licenses/by-sa/4.0/legalcode.txt
Attribution-ShareAlike 4.0 International
=======================================================================
Creative Commons Corporation ("Creative Commons") is not a law firm and
does not provide legal services or legal advice. Distribution of
Creative Commons public licenses does not create a lawyer-client or
other relationship. Creative Commons makes its licenses and related
information available on an "as-is" basis. Creative Commons gives no
warranties regarding its licenses, any material licensed under their
terms and conditions, or any related information. Creative Commons
disclaims all liability for damages resulting from their use to the
fullest extent possible.
Using Creative Commons Public Licenses
Creative Commons public licenses provide a standard set of terms and
conditions that creators and other rights holders may use to share
original works of authorship and other material subject to copyright
and certain other rights specified in the public license below. The
following considerations are for informational purposes only, are not
exhaustive, and do not form part of our licenses.
Considerations for licensors: Our public licenses are
intended for use by those authorized to give the public
permission to use material in ways otherwise restricted by
copyright and certain other rights. Our licenses are
irrevocable. Licensors should read and understand the terms
and conditions of the license they choose before applying it.
Licensors should also secure all rights necessary before
applying our licenses so that the public can reuse the
material as expected. Licensors should clearly mark any
material not subject to the license. This includes other CC-
licensed material, or material used under an exception or
limitation to copyright. More considerations for licensors:
wiki.creativecommons.org/Considerations_for_licensors
Considerations for the public: By using one of our public
licenses, a licensor grants the public permission to use the
licensed material under specified terms and conditions. If
the licensor's permission is not necessary for any reason--for
example, because of any applicable exception or limitation to
copyright--then that use is not regulated by the license. Our
licenses grant only permissions under copyright and certain
other rights that a licensor has authority to grant. Use of
the licensed material may still be restricted for other
reasons, including because others have copyright or other
rights in the material. A licensor may make special requests,
such as asking that all changes be marked or described.
Although not required by our licenses, you are encouraged to
respect those requests where reasonable. More considerations
for the public:
wiki.creativecommons.org/Considerations_for_licensees
=======================================================================
Creative Commons Attribution-ShareAlike 4.0 International Public
License
By exercising the Licensed Rights (defined below), You accept and agree
to be bound by the terms and conditions of this Creative Commons
Attribution-ShareAlike 4.0 International Public License ("Public
License"). To the extent this Public License may be interpreted as a
contract, You are granted the Licensed Rights in consideration of Your
acceptance of these terms and conditions, and the Licensor grants You
such rights in consideration of benefits the Licensor receives from
making the Licensed Material available under these terms and
conditions.
Section 1 -- Definitions.
a. Adapted Material means material subject to Copyright and Similar
Rights that is derived from or based upon the Licensed Material
and in which the Licensed Material is translated, altered,
arranged, transformed, or otherwise modified in a manner requiring
permission under the Copyright and Similar Rights held by the
Licensor. For purposes of this Public License, where the Licensed
Material is a musical work, performance, or sound recording,
Adapted Material is always produced where the Licensed Material is
synched in timed relation with a moving image.
b. Adapter's License means the license You apply to Your Copyright
and Similar Rights in Your contributions to Adapted Material in
accordance with the terms and conditions of this Public License.
c. BY-SA Compatible License means a license listed at
creativecommons.org/compatiblelicenses, approved by Creative
Commons as essentially the equivalent of this Public License.
d. Copyright and Similar Rights means copyright and/or similar rights
closely related to copyright including, without limitation,
performance, broadcast, sound recording, and Sui Generis Database
Rights, without regard to how the rights are labeled or
categorized. For purposes of this Public License, the rights
specified in Section 2(b)(1)-(2) are not Copyright and Similar
Rights.
e. Effective Technological Measures means those measures that, in the
absence of proper authority, may not be circumvented under laws
fulfilling obligations under Article 11 of the WIPO Copyright
Treaty adopted on December 20, 1996, and/or similar international
agreements.
f. Exceptions and Limitations means fair use, fair dealing, and/or
any other exception or limitation to Copyright and Similar Rights
that applies to Your use of the Licensed Material.
g. License Elements means the license attributes listed in the name
of a Creative Commons Public License. The License Elements of this
Public License are Attribution and ShareAlike.
h. Licensed Material means the artistic or literary work, database,
or other material to which the Licensor applied this Public
License.
i. Licensed Rights means the rights granted to You subject to the
terms and conditions of this Public License, which are limited to
all Copyright and Similar Rights that apply to Your use of the
Licensed Material and that the Licensor has authority to license.
j. Licensor means the individual(s) or entity(ies) granting rights
under this Public License.
k. Share means to provide material to the public by any means or
process that requires permission under the Licensed Rights, such
as reproduction, public display, public performance, distribution,
dissemination, communication, or importation, and to make material
available to the public including in ways that members of the
public may access the material from a place and at a time
individually chosen by them.
l. Sui Generis Database Rights means rights other than copyright
resulting from Directive 96/9/EC of the European Parliament and of
the Council of 11 March 1996 on the legal protection of databases,
as amended and/or succeeded, as well as other essentially
equivalent rights anywhere in the world.
m. You means the individual or entity exercising the Licensed Rights
under this Public License. Your has a corresponding meaning.
Section 2 -- Scope.
a. License grant.
1. Subject to the terms and conditions of this Public License,
the Licensor hereby grants You a worldwide, royalty-free,
non-sublicensable, non-exclusive, irrevocable license to
exercise the Licensed Rights in the Licensed Material to:
a. reproduce and Share the Licensed Material, in whole or
in part; and
b. produce, reproduce, and Share Adapted Material.
2. Exceptions and Limitations. For the avoidance of doubt, where
Exceptions and Limitations apply to Your use, this Public
License does not apply, and You do not need to comply with
its terms and conditions.
3. Term. The term of this Public License is specified in Section
6(a).
4. Media and formats; technical modifications allowed. The
Licensor authorizes You to exercise the Licensed Rights in
all media and formats whether now known or hereafter created,
and to make technical modifications necessary to do so. The
Licensor waives and/or agrees not to assert any right or
authority to forbid You from making technical modifications
necessary to exercise the Licensed Rights, including
technical modifications necessary to circumvent Effective
Technological Measures. For purposes of this Public License,
simply making modifications authorized by this Section 2(a)
(4) never produces Adapted Material.
5. Downstream recipients.
a. Offer from the Licensor -- Licensed Material. Every
recipient of the Licensed Material automatically
receives an offer from the Licensor to exercise the
Licensed Rights under the terms and conditions of this
Public License.
b. Additional offer from the Licensor -- Adapted Material.
Every recipient of Adapted Material from You
automatically receives an offer from the Licensor to
exercise the Licensed Rights in the Adapted Material
under the conditions of the Adapter's License You apply.
c. No downstream restrictions. You may not offer or impose
any additional or different terms or conditions on, or
apply any Effective Technological Measures to, the
Licensed Material if doing so restricts exercise of the
Licensed Rights by any recipient of the Licensed
Material.
6. No endorsement. Nothing in this Public License constitutes or
may be construed as permission to assert or imply that You
are, or that Your use of the Licensed Material is, connected
with, or sponsored, endorsed, or granted official status by,
the Licensor or others designated to receive attribution as
provided in Section 3(a)(1)(A)(i).
b. Other rights.
1. Moral rights, such as the right of integrity, are not
licensed under this Public License, nor are publicity,
privacy, and/or other similar personality rights; however, to
the extent possible, the Licensor waives and/or agrees not to
assert any such rights held by the Licensor to the limited
extent necessary to allow You to exercise the Licensed
Rights, but not otherwise.
2. Patent and trademark rights are not licensed under this
Public License.
3. To the extent possible, the Licensor waives any right to
collect royalties from You for the exercise of the Licensed
Rights, whether directly or through a collecting society
under any voluntary or waivable statutory or compulsory
licensing scheme. In all other cases the Licensor expressly
reserves any right to collect such royalties.
Section 3 -- License Conditions.
Your exercise of the Licensed Rights is expressly made subject to the
following conditions.
a. Attribution.
1. If You Share the Licensed Material (including in modified
form), You must:
a. retain the following if it is supplied by the Licensor
with the Licensed Material:
i. identification of the creator(s) of the Licensed
Material and any others designated to receive
attribution, in any reasonable manner requested by
the Licensor (including by pseudonym if
designated);
ii. a copyright notice;
iii. a notice that refers to this Public License;
iv. a notice that refers to the disclaimer of
warranties;
v. a URI or hyperlink to the Licensed Material to the
extent reasonably practicable;
b. indicate if You modified the Licensed Material and
retain an indication of any previous modifications; and
c. indicate the Licensed Material is licensed under this
Public License, and include the text of, or the URI or
hyperlink to, this Public License.
2. You may satisfy the conditions in Section 3(a)(1) in any
reasonable manner based on the medium, means, and context in
which You Share the Licensed Material. For example, it may be
reasonable to satisfy the conditions by providing a URI or
hyperlink to a resource that includes the required
information.
3. If requested by the Licensor, You must remove any of the
information required by Section 3(a)(1)(A) to the extent
reasonably practicable.
b. ShareAlike.
In addition to the conditions in Section 3(a), if You Share
Adapted Material You produce, the following conditions also apply.
1. The Adapter's License You apply must be a Creative Commons
license with the same License Elements, this version or
later, or a BY-SA Compatible License.
2. You must include the text of, or the URI or hyperlink to, the
Adapter's License You apply. You may satisfy this condition
in any reasonable manner based on the medium, means, and
context in which You Share Adapted Material.
3. You may not offer or impose any additional or different terms
or conditions on, or apply any Effective Technological
Measures to, Adapted Material that restrict exercise of the
rights granted under the Adapter's License You apply.
Section 4 -- Sui Generis Database Rights.
Where the Licensed Rights include Sui Generis Database Rights that
apply to Your use of the Licensed Material:
a. for the avoidance of doubt, Section 2(a)(1) grants You the right
to extract, reuse, reproduce, and Share all or a substantial
portion of the contents of the database;
b. if You include all or a substantial portion of the database
contents in a database in which You have Sui Generis Database
Rights, then the database in which You have Sui Generis Database
Rights (but not its individual contents) is Adapted Material,
including for purposes of Section 3(b); and
c. You must comply with the conditions in Section 3(a) if You Share
all or a substantial portion of the contents of the database.
For the avoidance of doubt, this Section 4 supplements and does not
replace Your obligations under this Public License where the Licensed
Rights include other Copyright and Similar Rights.
Section 5 -- Disclaimer of Warranties and Limitation of Liability.
a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
c. The disclaimer of warranties and limitation of liability provided
above shall be interpreted in a manner that, to the extent
possible, most closely approximates an absolute disclaimer and
waiver of all liability.
Section 6 -- Term and Termination.
a. This Public License applies for the term of the Copyright and
Similar Rights licensed here. However, if You fail to comply with
this Public License, then Your rights under this Public License
terminate automatically.
b. Where Your right to use the Licensed Material has terminated under
Section 6(a), it reinstates:
1. automatically as of the date the violation is cured, provided
it is cured within 30 days of Your discovery of the
violation; or
2. upon express reinstatement by the Licensor.
For the avoidance of doubt, this Section 6(b) does not affect any
right the Licensor may have to seek remedies for Your violations
of this Public License.
c. For the avoidance of doubt, the Licensor may also offer the
Licensed Material under separate terms or conditions or stop
distributing the Licensed Material at any time; however, doing so
will not terminate this Public License.
d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
License.
Section 7 -- Other Terms and Conditions.
a. The Licensor shall not be bound by any additional or different
terms or conditions communicated by You unless expressly agreed.
b. Any arrangements, understandings, or agreements regarding the
Licensed Material not stated herein are separate from and
independent of the terms and conditions of this Public License.
Section 8 -- Interpretation.
a. For the avoidance of doubt, this Public License does not, and
shall not be interpreted to, reduce, limit, restrict, or impose
conditions on any use of the Licensed Material that could lawfully
be made without permission under this Public License.
b. To the extent possible, if any provision of this Public License is
deemed unenforceable, it shall be automatically reformed to the
minimum extent necessary to make it enforceable. If the provision
cannot be reformed, it shall be severed from this Public License
without affecting the enforceability of the remaining terms and
conditions.
c. No term or condition of this Public License will be waived and no
failure to comply consented to unless expressly agreed to by the
Licensor.
d. Nothing in this Public License constitutes or may be interpreted
as a limitation upon, or waiver of, any privileges and immunities
that apply to the Licensor or You, including from the legal
processes of any jurisdiction or authority.
=======================================================================
Creative Commons is not a party to its public
licenses. Notwithstanding, Creative Commons may elect to apply one of
its public licenses to material it publishes and in those instances
will be considered the “Licensor.” The text of the Creative Commons
public licenses is dedicated to the public domain under the CC0 Public
Domain Dedication. Except for the limited purpose of indicating that
material is shared under a Creative Commons public license or as
otherwise permitted by the Creative Commons policies published at
creativecommons.org/policies, Creative Commons does not authorize the
use of the trademark "Creative Commons" or any other trademark or logo
of Creative Commons without its prior written consent including,
without limitation, in connection with any unauthorized modifications
to any of its public licenses or any other arrangements,
understandings, or agreements concerning use of licensed material. For
the avoidance of doubt, this paragraph does not form part of the
public licenses.
Creative Commons may be contacted at creativecommons.org.

7
documentation/README.txt

@ -0,0 +1,7 @@
Run ./build-documentation.sh for html output in the /out directory.
.adoc is asciidoctor, not simple asciidoc.
This documentation is licensed under Creative Commons-BY-SA-4.0.
Please read the provided documentation/LICENSE file or visit
https://creativecommons.org/licenses/by-sa/4.0/legalcode

18
documentation/build-documentation.sh

@ -0,0 +1,18 @@
#!/bin/sh
#The documentation is built statically and does not belong to the normal build process with configure and make
#Its updating is part of the development process, not packaging and running.
#The correct out/ dir is already part of git.
set -e
asciidoctor index.adoc -o out/index.html
asciidoctor german.adoc -o out/german.html
cp overview-german.png out/overview-german.png
asciidoctor english.adoc -o out/english.html
cp overview-english.png out/overview-english.png
#cp *-quickstart*.mp4 out/
cp favicon.* out/

5
documentation/english.part.adoc

@ -0,0 +1,5 @@
== Usage
* Nothing
* To
* See
* Here

5
documentation/german.part.adoc

@ -0,0 +1,5 @@
== Bedienung
Hier gibt es nichts zu sehen.
* Weiter
* Gehen

31
engine/__init__.py

@ -0,0 +1,31 @@
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Copyright 2018, Nils Hilbricht, Germany ( https://www.hilbricht.net )
This file is part of the Laborejo Software Suite ( https://www.laborejo.org ),
more specifically its template base application.
The Template Base Application is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
import logging; logging.info("import {}".format(__file__))
#This file only exists as a reminder to _not_ create it again wrongly in the future.
#from .api import * #Do not star-import here!
#This leads to uncontrollable behaviour because importing _any_ file from engine will first import this init file, which would trigger the api to start its session.
#Instead use explicit import to get the api.
#No!: import engine.api as api #This loads the engine and starts a session.

2314
engine/api.py

File diff suppressed because it is too large

331
engine/block.py

@ -0,0 +1,331 @@
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Copyright 2017, Nils Hilbricht, Germany ( https://www.hilbricht.net )
This file is part of Laborejo ( https://www.laborejo.org )
Laborejo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from weakref import WeakSet
from weakref import ref as weakref_ref
from .items import * #loading from file needs all items.
class Block(object):
#allBlocks = WeakValueDictionary() #key is the blockId, value is the weak reference to the Block
allBlocks = {} #key is the blockId, value is the Block. This is a one way dict. It gets never deleted so undo can recover old blocks. Since blocks are unique this is no problem.
#NEVER!! iteratre over allBlocks if you don't know what you are doing. This contains deleted blocks as well.
firstBlockWithNewContentDuringDeserializeToObject = dict() #this is not resetted anywhere since each load is a program start.
def __init__(self, track):
self.data = list()
self.name = str(id(self))
self._minimumInTicks = [0] # if this is bigger than the actual duration-sum of the content this will be used instead. Advice: best used in the form of x*210 (multiple of real base-durations) #is content linked, thats why it is a mutable list of len==1.
self.linkedContentBlocks = WeakSet() #only new standalone blocks use this empty WeakSet. once you contentLink a block it will be overwritten.
self._secondInit(parentTrack = track)
def _secondInit(self, parentTrack):
"""see Score._secondInit"""
self._parentTrack = weakref_ref(parentTrack) #a block can only be in one track.
self.localCursorIndex = 0
self.linkedContentBlocks.add(self)
self.rememberBlock()
@property
def minimumInTicks(self):
return self._minimumInTicks[0]
@minimumInTicks.setter
def minimumInTicks(self, newValue):
"""Keep the mutable list at all cost"""
listId = id(self._minimumInTicks)
self._minimumInTicks.pop()
self._minimumInTicks.append(newValue)
assert len(self._minimumInTicks) == 1
assert listId == id(self._minimumInTicks)
@classmethod
def instanceFromSerializedData(cls, serializedObject, parentObject):
"""see Score.instanceFromSerializedData"""
assert cls.__name__ == serializedObject["class"]
self = cls.__new__(cls)
if serializedObject["data"] is None: #Found a content linked block which already has one member of its group in the score
firstBlock = Block.firstBlockWithNewContentDuringDeserializeToObject[serializedObject["contentLinkGroup"]] #block with the same contentGroup. This is the one with the real data.
self.data = firstBlock.data
self._minimumInTicks = firstBlock._minimumInTicks
self.linkedContentBlocks = firstBlock.linkedContentBlocks #add self to this is in _secondInit
else: #found a stand-alone block or the first one of a content link group
self.linkedContentBlocks = WeakSet()
self.data = [eval(item["class"]).instanceFromSerializedData(item, parentObject = self) for item in serializedObject["data"]]
Block.firstBlockWithNewContentDuringDeserializeToObject[serializedObject["contentLinkGroup"]] = self
for item in self.data:
item.parentBlocks.add(self)
self.name = serializedObject["name"]
self._minimumInTicks = [int(serializedObject["minimumInTicks"])] #saved as int, used as list
self._secondInit(parentTrack = parentObject)
return self
def serialize(self):
"""Return a serialized data from this instance.
Used for save and load.
Can be called in a chain by subclasses with super().serialize
The main difference between serialize and exportObject is that
serialize does not compute anything. I just saves the state
without calulating note on and off or stem directions,
for example.
"""
#result = super()._serialize() #call this in child classes
result = {}
result["class"] = self.__class__.__name__
result["name"] = self.name
result["minimumInTicks"] = self.minimumInTicks
#We only save the data if this is the first content-linked block in a sequence.
contentLinkGroupId = id(self.data)
result["contentLinkGroup"] = contentLinkGroupId
for block in self.parentTrack.parentData.allBlocks():
blockId = id(block)
dataId = id(block.data)
if dataId == contentLinkGroupId:
if blockId == id(self): #first block with this dataId found.
result["data"] = [item.serialize() for item in self.data]
else: #content linked, but not the first. Block already serialized.
result["data"] = None #we don't need to do anything more. The rest is handled by load and instanceFromSerializedData
break
#else:
#loop ran through. This never happens.
return result
def rememberBlock(self):
oid = id(self)
Block.allBlocks[oid] = self #This is on the score level, or a global level. That means we don't need to change this, even if the track gets moved to a new track by the api.
#weakref_finalize(self, print, "deleted block "+str(oid))
return oid
@property
def parentTrack(self):
if self._parentTrack:
return self._parentTrack() #return the real parentTrack
else:
assert self._parentTrack is None
return self._parentTrack
@parentTrack.setter
def parentTrack(self, newTrack):
if not self._parentTrack: #because it was None/not in a track
self._parentTrack = WeakSet()
if newTrack:
self._parentTrack = weakref_ref(newTrack)
else:
self._parentTrack = None
def copy(self, newParentTrack):
"""Return an independet copy of this block.
It will not be inserted into a track here but in the parentTrack
It is by design only possible that a block will be inserted
in the same track, next to the original block.
It can be moved later by the api module which will reset
the parentTrack. But at first the parentTrack stays the same."""
new = Block(newParentTrack)
assert newParentTrack
#Do not change new.linkedContentBlocks! Copy creates a stand alone copy.
assert len(new.linkedContentBlocks) == 1
for item in self.data:
copyItem = item.copy()
new.data.append(copyItem)
copyItem.parentBlocks.add(new) #parentBlock was empty until now
if self in copyItem.parentBlocks: #TODO: investigate
copyItem.parentBlocks.remove(self)
if self.name.endswith("-copy"):
new.name = self.name
else:
new.name = self.name + "-copy"
new._minimumInTicks = self._minimumInTicks[:] #mutable
return new
def getUnlinkedData(self):
"""Set and handled for undo/redo by the api"""
newData = []
newParentBlocks = WeakSet()
newParentBlocks.add(self)
for item in self.data:
copyItem = item.copy()
newData.append(copyItem)
copyItem.parentBlocks = newParentBlocks
assert len(newData) == len(self.data)
return newData
def getDataAsDict(self):
return { "name" : self.name,
"minimumInTicks" : self.minimumInTicks,
}
def putDataFromDict(self, dataDict):
"""modify inplace. Useful for a gui function. Compatible with
the data from getDataAsDict"""
self.name = dataDict["name"]
self.minimumInTicks = dataDict["minimumInTicks"]
def contentLink(self):
"""Return a copy where only certain parameters
like Content are linked. Others can be changed.
It will not be inserted into a track here but in the parentTrack
It is by design only possible that a block will be inserted
in the same track, next to the original block.
It can be moved later by the api module which will reset
the parentTrack. But at first the parentTrack stays the same.
"""
assert self.parentTrack
new = Block(self.parentTrack)
new.linkedContentBlocks = self.linkedContentBlocks
new.linkedContentBlocks.add(new)
new.data = self.data #mutable. Will change in all blocks together.
new.name = self.name #immutable. Will change independently but we start with the same name.
new._minimumInTicks = self._minimumInTicks #mutable
#Add the new block to the parentBlocks set but don't delete self from it, as in copy(). The items are now in more than one block simultaniously
for item in new.data:
item.parentBlocks.add(new)
return new
def linkedContentBlocksInScore(self):
"""filters linkedContentBlocks to only include
those currently in the score. Not those in the undo repository
"""
return (block for block in self.linkedContentBlocks if block.parentTrack)
def duration(self):
"""The first block might have an upbeat. We check that here and not in the track."""
actualBlockDuration = 0
for item in self.data:
actualBlockDuration += item.logicalDuration()
if actualBlockDuration >= self.minimumInTicks:
return actualBlockDuration
else:
return self.minimumInTicks
def staticExportEndMarkerDuration(self):
actualBlockDuration = 0
for item in self.data:
actualBlockDuration += item.logicalDuration()
if actualBlockDuration >= self.minimumInTicks: #this also guarantees that the substraction below is > 0.
return 0
else:
return self.minimumInTicks - actualBlockDuration #this is the difference to self.duration()
def position(self):
"""the position of the subcursor in this block"""
return self.localCursorIndex
def left(self):
if self.localCursorIndex > 0:
self.localCursorIndex -= 1
return True
else:
return False #Already at the start.
def right(self):
if not self.isAppending():
self.localCursorIndex += 1
return True
else:
return False #Already at the end.
def head(self):
self.localCursorIndex = 0
def tail(self):
self.localCursorIndex = len(self.data) #eventhough len counts from 1 and the cursorIndex from 0 we want exactly to be after the last item in data.
def goToItem(self, itemInstance):
if itemInstance:
self.head()
while self.right():
item = self.currentItem()
if item is itemInstance:
return True
else:
raise ValueError("Item not in this block. ", self, itemInstance)
elif itemInstance is None:
self.tail()
else:
raise ValueError("You must go to an item or None, not to: ", itemInstance)
def currentItem(self):
"""Can be used with goToItem"""
if not self.isAppending():
return self.data[self.localCursorIndex]
else:
return None
def previousItem(self):
"""Can be used with goToItem"""
if self.localCursorIndex > 0:
return self.data[self.localCursorIndex-1]
else:
return None
def nextItem(self):
"""Can be used with goToItem"""
if self.localCursorIndex+1 >= len(self.data): #one before appending or appending itself
return None
else:
return self.data[self.localCursorIndex+1]
def insert(self, item):
self.data.insert(self.localCursorIndex, item) #we do not need to check if appending or not. list.insert appends if the index is higher then len()
#self.localCursorIndex += 1 #we don't need to go right here because track.insert() is calling its own right() directly after insert, which triggers block.right()
item.parentBlocks.add(self)
def delete(self):
"""The commented out is the immediate garbage collector which
made sure that deleted item are not in the allNotes weakref
dict any more. However, this does not happen any more since
we introduced undo which keeps a saved version.
For consitency reasons we chose not to save a copy in the undo
register (return ...copy()) but the real item.
If this ever leads to problems with the weakref dict we must
reintroduce the copy"""
if not self.isAppending():
result = self.data[self.localCursorIndex]
del self.data[self.localCursorIndex]
#we don't need to delete self from item.parentBlocks. It is automatically deleted in all contentLinked blocks, of course including its parentBlocks WeakSet()
return result
def isAppending(self):
if self.localCursorIndex == len(self.data): #len counts from 1 and the cursorIndex from 0. So if they are the same we are one cursor position right of last item
return True
else:
return False
def lilypond(self):
"""Called by track.lilypond(), returns a string"""
return " ".join(item.lilypond() for item in self.data)

56
engine/config.py

@ -0,0 +1,56 @@
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
#Do not change these during runtime!
METADATA={
#The pretty name of this program. Used for NSM display and Jack client name
#Can contain everything a linux file/path supports. Never change this or it will break the
#session, making your file unable to load and destroying saved Jack connections.
"name" : "Laborejo",
#Set this to the name the user types into a terminal.
#MUST be the same as the binary name as well as the name in configure.
#Program reports that as proc title so you can killall it by name.
#Should not contain spaces or special characters. We use this as save file extension as well
#to distinguish between compatible program versions. In basic programs this will just be e.g.
#patroneo. But in complex programs with a bright future it will be "laborejo1" "laborejo2" etc.
"shortName" : "laborejo2",
"version" : "2.0",
"year" : "2019",
"author" : "Laborejo Software Suite",
"url" : "https://www.laborejo.org/laborejo",
"supportedLanguages" : {"German":"de.qm"},
#Show the About Dialog the first time the program starts up. This is the initial state for a
#new instance in NSM, not the saved state! Decide on how annoying it would be for every new
#instance to show about. Fluajho does not show it because you add it many times into a session.
#Patroneo does because its only added once.
"showAboutDialogFirstStart" : True,
#If your program handles very small duration with n-tuplets you should increase D4.
#This will not be visible to the outside jack world
"quarterNoteInTicks" : 53760,
#How many audio outputs do you want? must be pairs. These are just unconnected jack outputs
#that need to be connected internally to instrument outputs like fluidsynth
"cboxOutputs" : 2 * 0,
#Various strings for the README
#Extra whitespace will be stripped so we don't need to worry about docstring indentation
"description" : """
Laborejo (Esperanto: Workshop) is a MIDI sequencer based on classical music notation.
Its main purpose is to compose and produce "traditional" music, such as instrumental pieces,
soundtracks and other music normally played back by samplers.
""" + "\n" + """
Unlike other notation editors Laborejo is not meant primarily to print out sheets of notation but
to create music within your computer: You get all the tools you know from other midi sequencers for
maximum fine control to get exactly the music you want!
""" + "\n" + """
Working in Laborejo is very fast and efficient by using a combination of midi input and typing.""",
"dependencies" : "\n".join("* "+dep for dep in ("A Brain", "Linux" )),
}

142
engine/cursor.py

@ -0,0 +1,142 @@
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Copyright 2019, Nils Hilbricht, Germany ( https://www.hilbricht.net )
This file is part of the Laborejo Software Suite ( https://www.laborejo.org ),
more specifically its template base application.
The Template Base Application is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
import logging; logging.info("import {}".format(__file__))
#Standard Library Modules
#Third Party Modules
#Template Modules
import template.engine.pitch as pitch
import template.engine.duration as duration
#Our modules
class Cursor:
"""There is only one cursor in the program.
Each track has its own state with its own gap, tickindex etc.
but the cursor is unique.
Used for pitch and states which apply to all tracks, like
"insert next note with dot?"
The cursor moves 'on stafflines' not through the keysig. Adaption to the keysig is done
by the api like in insertCursorCode or insertKeysignature
"""
def __init__(self, score):
self.score = score
self.pitchindex = pitch.ly2pitch["c'"]
self.prevailingBaseDuration = duration.D4
self.persistentPrevailingDot = False #For the sake of simplicity this is only a bool. No "two prevailing dots"
self.oneTimePrevailingDotInverter = False #effects persistentPrevailingDot
def up(self):
"""Move the cursor/pitchindex up, +50.
The cursor always goes up and down the c major scale.
Call with Cursor.up(). Class method """
self.pitchindex += pitch.STEP
self.correctPitchindex()
def down(self):
"""Move the cursor/pitchindex down, -50.
The cursor always goes up and down the c major scale.
Call with Cursor.down(). Class method"""
self.pitchindex -= pitch.STEP
self.correctPitchindex()
def upOctave(self):
"""Move the cursor/pitchindex up, +350.
Call with Cursor.upOctave(). Class method"""
self.pitchindex += pitch.OCTAVE
self.correctPitchindex()
def downOctave(self):
"""Move the cursor/pitchindex down, -350.
Call with Cursor.downOctave(). Class method"""
self.pitchindex -= pitch.OCTAVE
self.correctPitchindex()
def correctPitchindex(self):
if self.pitchindex >= pitch.MAX:
self.pitchindex = pitch.MAX
elif self.pitchindex <= pitch.MIN:
self.pitchindex = pitch.MIN
else:
self.pitchindex = pitch.toWhite[self.pitchindex]
def getPrevailingDot(self):
"""0 or 1.
Also toggles oneTimePrevailingDotInverter"""
if self.persistentPrevailingDot:
if self.oneTimePrevailingDotInverter:
self.oneTimePrevailingDotInverter = not self.oneTimePrevailingDotInverter
return 0
else:
return 1
else:
if self.oneTimePrevailingDotInverter:
self.oneTimePrevailingDotInverter = not self.oneTimePrevailingDotInverter
return 1
else:
return 0
def distanceInDiatonicStepsFromTrebleB(self):
return pitch.distanceInDiatonicSteps(pitch.ly2pitch["b'"], self.pitchindex) #offset from the middle line in treble clef h', which is 0. c'' is -1, a' is +1
def asDotOnLine(self, clef):
return self.distanceInDiatonicStepsFromTrebleB() + clef.asDotOnLineOffset
def exportObject(self, trackState):
"""Every time the cursor moves this will be called.
return a dict which is a good layout
export basis. For example for GUI frontends. They don't have to
parse and calculate their own values in slow pure Python then.
This is for GUIs etc. not for saving to JSOn. The cursor is not
saved.
"""
tempoItem = trackState.track.parentData.tempoTrack.tempoAtTickPosition(trackState.tickindex) #TODO: maybe get that from a cached version.
item = trackState.track.currentItem()
block = trackState.track.currentBlock()
return {
"type": "Cursor",
"trackIndex": trackState.index(),
"track" : trackState.track,
"cboxMidiOutUuid" : trackState.track.sequencerInterface.cboxMidiOutUuid, #used for midi throught. Step midi shall produce sound through the current track.
"trackId" : id(trackState.track),
"position" : trackState.position(),
"tickindex" : trackState.tickindex,
"dotOnLine": self.asDotOnLine(trackState.clef()),
"pitch" : self.pitchindex,
"lilypondPitch" : pitch.pitch2ly[self.pitchindex],
"position" : trackState.position(),
"appending" : trackState.isAppending(),
"blockindex" : trackState.blockindex,
"block" : block,
"localCursorIndex" : block.localCursorIndex,
"itemId" : id(item),
"item" : item,
"tempoUnitsPerMinute" : tempoItem.unitsPerMinute,
"tempoReferenceTicks" : tempoItem.referenceTicks,
"tempoGraphType" : tempoItem.graphType,
}

1347
engine/graphtracks.py

File diff suppressed because it is too large

2812
engine/items.py

File diff suppressed because it is too large

142
engine/lilypond.py

@ -0,0 +1,142 @@
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Copyright 2017, Nils Hilbricht, Germany ( https://www.hilbricht.net )
This file is part of Laborejo ( https://www.laborejo.org )
Laborejo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
"""Use generated music data and build a complete lilypond file from it"""
import os.path
from datetime import date
import subprocess
from tempfile import gettempdir
da = date.fromordinal(730920) # 730920th day after 1. 1. 0001
def saveAsLilypond(score, absoluteFilePath = None):
#absoluteFilePath = self.absoluteFilePath + ".ly" if (not absoluteFilePath) else absoluteFilePath
assert absoluteFilePath.endswith(".ly")
result = score.lilypond()
if result:
with open(absoluteFilePath, "w", encoding="utf-8") as f:
f.write(result)
return absoluteFilePath
def saveAsLilypondPDF(score, openPDF = False):
tempfile = os.path.join(gettempdir(), str(id(score)) + ".ly")
exportedLilypond = saveAsLilypond(score, tempfile)
ret = subprocess.call("lilypond --output={} {}".format(exportedLilypond, exportedLilypond), shell=True) #suffix to output added by lilypond
if ret == 0 and openPDF:
subprocess.Popen("xdg-open {}.pdf".format(exportedLilypond), shell=True)
def stringToCharsOnlyString(string):
def num2word(n):
"""Take a number, return a str.
Lilypond does not allow numbers in variable names"""
return ''.join(chr(ord(c)+17) for c in str(n))
def num2wordForIterations(stringOrNum):
if stringOrNum in [1,2,3,4,5,6,7,8,9,0] or stringOrNum in "1234567890":
return num2word(int(stringOrNum))
elif stringOrNum in ("-", "_"):
return ""
else:
return stringOrNum
string = string.replace(" ", "_")
return "".join([num2wordForIterations(c) for c in string])
def lilyfy(string):
return string
def fromTemplate(session, templateFile, data, meta, tempoStaff):
"""Returns a string built from already ly-exported track data and a lilypond template.
Called by score.lilypond(), which is called by session.lilypond().
A template is either one of the built-ins "foo.ly" or
if the templateFile is None/"" the current filename+ly is used: "bar.lbj.ly"
Laborejo Markers in the template have the syntax %$$DATE$$ . That is pretty unique and additionaly a lilypond
comment.
"""
#Load the template
templatePath = findTemplate(session, templateFile)
with open(templatePath, 'r') as f:
templateString = f.read()
templateString = templateString.replace("%$$DATE$$", da.today().strftime("%A %d. %B %Y")) #The current date
templateString = templateString.replace("%$$FILENAME$$", session.absoluteFilePath)
templateString = templateString.replace("%$$HEADER$$", processMeta(meta))
templateString = templateString.replace("%$$SUBTEXT$$", lilyfy(meta["subtext"]))
voicesString, structureString = processData(data)
templateString = templateString.replace("%$$VOICES$$", voicesString)
templateString = templateString.replace("%$$STRUCTURE$$", structureString)
templateString = templateString.replace("%$$TEMPOSTAFF$$", tempoStaff)
return templateString
def findTemplate(session, templateFile):
"""returns a path. checks for existence.
see fromTemplate"""
if not templateFile:
path = session.absoluteFilePath, ".template.ly"
assert path.endswith(".lbj.ly")
else:
path = os.path.join(session.applicationDirectory, "laborejomodule", "templates", templateFile)
assert path.endswith(".ly")
if os.path.exists(path):
return path
else:
raise FileNotFoundError(templateFile)
def processData(data):
"""returns two strings. the first actual music data, VOICES, the second the structure and order,
STRUCTURE"""
def voice(track, lilypondTrack):
""" tgliHJuGCFAIICICBEHBJABHIJE= { \key c \major <c'>4 <e'>4 <g'>4 <c''>4 \bar "|."} """
return "{} = {}".format(stringToCharsOnlyString(track.name), "{ " + lilypondTrack + " }")
def structure(track, lilypondTrack):
""" \new Staff = "tgliHJuGCFAIICICBEHBJABHIJE_Staff" << \\new Voice = "tgliHJuGCFAIICICBEHBJABHIJE" \tgliHJuGCFAIICICBEHBJABHIJE >> %EndTrack """
name = stringToCharsOnlyString(track.name)
instruments = '\\with {{ \n instrumentName = #"{}" \n shortInstrumentName = #"{}" }}'.format(lilyfy(track.initialInstrumentName), lilyfy(track.initialShortInstrumentName))
mergeTempo = "\\new Voice = \"Tempo\" \\tempoStaff"
return """\\new Staff = "{}_Staff" {} << {} \\new Voice = "{}" \{} >> %EndTrack""".format(name, instruments, mergeTempo, name, name)
voices = "\n ".join(voice(track, lilypondTrack) for track, lilypondTrack in data.items() if lilypondTrack)
structure = "\n ".join(structure(track, lilypondTrack) for track, lilypondTrack in data.items() if lilypondTrack)
return voices, structure
def processMeta(meta):
"""returns a string with lilypond header data like title and composer"""
def valueMarkup(value):
value = value.strip()
if value:
if value.startswith("\\markup"):
return value
else:
return "\"{}\"".format(value) #results in "value"
else:
return "##f"
metaString = "\n ".join(key + " = " + valueMarkup(value) for key, value in meta.items())
return metaString

1070
engine/main.py

File diff suppressed because it is too large

52
engine/oldmidi.py

@ -0,0 +1,52 @@
class MidiState(object):
"""Various data to keep track what midi in looks like currently"""
def __init__(self):
self.midiInIsActive = False
self.ccState = {}
for cc in range(0,127):
self.ccState[cc] = None #start with undefined.
self.firstActiveNote = None #for chord entry.
self.cboxMidiPortUid = None #the INPUT midi in port. set in startMidiModule
self.currentOutputMidiPortUid = None #set in self.setMidiThrough. This changes with the active track
self.scene = cbox.Document.get_engine().new_scene()
self.scene.clear()
def toggleMidiIn(self):
self.midiInIsActive = not self.midiInIsActive
if self.midiInIsActive:
#CachedTrackDuration is a dict and never cleared completely. So our midiIn will never get touched
#We hope that nobody uses the PortUid as a track name by chance :)
api.session.data.cachedTrackDurations[self.cboxMidiPortUid] = api.DINF
else:
api.session.data.cachedTrackDurations[self.cboxMidiPortUid] = 0
finalizeRecordingBuffer()
api.callbacksDatabase._prevailingBaseDurationChanged(api.session.data.cursor.prevailingBaseDuration)
def updateCCState(self, ccNumber, ccValue):
assert 0 <= ccValue <= 127
self.ccState[ccNumber] = ccValue
def setMidiThrough(self, cursorExport):
"""
Instruct the RT part to echo midi in directly to the connect output ports so we hear the current track with the tracks instrument.
Added to the cursorChanged api callback"""
if not self.currentOutputMidiPortUid == cursorExport["cboxMidiOutUuid"]: #most of the time this stays the same e.g. cursor left/right. we only care about up and down
self.currentOutputMidiPortUid = cursorExport["cboxMidiOutUuid"]
cbox.JackIO.route_midi_input(midiState.cboxMidiPortUid, cursorExport["cboxMidiOutUuid"])
def startMidiModule(pApi):
global api
api = pApi
#global midiState
#midiState = MidiState()
midiState.cboxMidiPortUid = cbox.JackIO.create_midi_input("in")
cbox.JackIO.set_appsink_for_midi_input(midiState.cboxMidiPortUid, True) #This sounds like a program wide sink, but it is needed for every port.
cbox.JackIO.route_midi_input(midiState.cboxMidiPortUid, midiState.scene.uuid)
#midiState.currentOutputMidiPortUid = api.session.data.cursorExport()["cboxMidiOutUuid"] #TODO. Im cursor habn ich das deaktiviert.
#api.callbacks.setCursor.append(midiState.setMidiThrough) #TODO. Das brauchen wir damit wir das verknüpfte instrument vom track hören.
return processMidiIn

1
engine/resources/LICENSE

@ -0,0 +1 @@
Licenses for 3rd party resources can be found in text files with the same name as the resource.

105
engine/resources/lilypondTemplate/default.ly

@ -0,0 +1,105 @@
%% LilyPond-File generated by Laborejo - http://www.laborejo.org
%% Generation Date: %$$DATE$$
%% Filename: %$$FILENAME$$
\version "2.18"
#(set-default-paper-size "a4")
#(set-global-staff-size 18 )
#(ly:set-option 'point-and-click #f)
\paper {
print-all-headers = ##f
%scoreTitleMarkup = ##f
%Print small title on every page.
oddHeaderMarkup = \markup
\fill-line {
\on-the-fly #not-first-page \fromproperty #'header:title
\on-the-fly #not-first-page \fromproperty #'header:instrument
%"" % This will make sure that the header is never completely empty, to
% avoid some layout problems. Also, moving it in between the title and
% the page number, makes these be typeset left and right aligned, respectively.
\on-the-fly #not-first-page \on-the-fly #print-page-number-check-first \fromproperty #'page:page-number-string
}
evenHeaderMarkup = \markup
\fill-line {
\on-the-fly #print-page-number-check-first \fromproperty #'page:page-number-string
\fromproperty #'header:instrument
\fromproperty #'header:title
}
}
\header{
%$$HEADER$$
}
correctFraction = #(lambda (grob)
(let ((ev (event-cause grob)))
(if (and (= (ly:event-property ev 'numerator) 2) (= (ly:event-property ev 'denominator) 3))
(format #f "~a" 3)
(format #f "~a/~a"
(ly:event-property ev 'numerator)
(ly:event-property ev 'denominator))
)))
\layout{
%ragged-right = ##t
\context { \Score
\override TupletNumber #'text = \correctFraction %traditional but wrong: #tuplet-number::calc-fraction-text
\override Fingering #'add-stem-support = ##t
\override StringNumber #'add-stem-support = ##t
\override StrokeFinger #'add-stem-support = ##t
%Dynamics
\override Hairpin #'to-barline = ##f
\override DynamicLineSpanner #'staff-padding = #2.0
\override DynamicLineSpanner #'Y-extent = #'(-1.5 . 1.5)
\override TextScript #'Y-extent = #'(-1.5 . 1.5)
\override PaperColumn #'keep-inside-line = ##t
%Remove engraver here and add them in context staff to make multiple timesigs possible. This deactivates barnumbers!
%\remove "Timing_translator"
%\remove "Default_bar_line_engraver"
%\override Tie #'details #'ratio = #2
}
\context { \Voice
%Exchange note_heads_engraver with the completition variant which auto-ties notes on bar-breaks
\remove "Note_heads_engraver"
\consists "Completion_heads_engraver"
tieWaitForNote = ##t
}
\context { \Staff
\RemoveEmptyStaves
%\override VerticalAxisGroup #'remove-first = ##t
\override TimeSignature #'style = #'numbered
%Commenting the following two lines in again, together with the revmoval in \score enables mutli-timesig mode. But disables barnumbers.
%\consists "Timing_translator"
%\consists "Default_bar_line_engraver"
\override NoteHead #'style = #'baroque %breve and longa are squared.
}
}
%Music definitions. Containers, Staff, Parts.
tempoStaff = { %$$TEMPOSTAFF$$ }
%$$VOICES$$
\score{
<<
%How the definitions are arranged. Only staffgroups (staff prefix) and staffs, merged as voices.
\accidentalStyle Score.neo-modern-voice
%$$STRUCTURE$$
>>}
\markup{
%\column {
%$$SUBTEXT$$
%}
}

17
engine/resources/lilypondTemplate/minimal.ly

@ -0,0 +1,17 @@
%% LilyPond-File generated by Laborejo - http://www.laborejo.org
%% Generation Date: %$$DATE$$
%% Filename: %$$FILENAME$$
\version "2.18"
#(ly:set-option 'point-and-click #f)
%Music definitions. Containers, Staff, Parts.
%$$VOICES$$
\score {<<
%How the definitions are arranged. Only staffgroups (staff prefix) and staffs, merged as voices.
%$$STRUCTURE$$
>>}
%no subtext

BIN
engine/resources/normal.wav

Binary file not shown.

BIN
engine/resources/stressed.wav

Binary file not shown.

1161
engine/track.py

File diff suppressed because it is too large

9
laborejo2

@ -0,0 +1,9 @@
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
from template import start #Executes various start up checks and sets up our environment likes search paths
from qtgui import mainwindow #which in turn imports the engine and starts the engine
with start.profiler():
mainwindow.MainWindow().qtApp.exec_()
#Program is over. Code here does not get executed. Quit is done via NSM in mainWindow._nsmQuit

103
midiinput/stepmidiinput.py

@ -0,0 +1,103 @@
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Copyright 2019, Nils Hilbricht, Germany ( https://www.hilbricht.net )
This file is part of the Laborejo Software Suite ( https://www.laborejo.org ),
more specifically its template base application.
The Template Base Application is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
import logging; logging.info("import {}".format(__file__))
#Python Standard Library
#Third Party Modules
#Template Modules
from template.engine.input_midi import MidiInput
#Our Modules
import engine.api as api
class StepMidiInput(MidiInput):
"""We initialize with everything switched off. This makes it easier for a complex system
of engine, GUI and midiinput to start up and get the order of operations right
For chord entry we use the first note only as indicator. The indicator was a set() at one time,
which means that as long as one of the chord notes would still be down the chord was still "on".
That is not as robust and convenient as using the starting note, which is counter intuitive,
therefore documented here.
"""
def __init__(self):
self.firstActiveNote = None #for chord entry.
self._currentlyActiveNotes = set()
def start(self):
"""Call this manually after the engine and an event loop have started.
For example from the GUI. It is currently started by mainwindow.py start()
But it could be started from a simple command line interface as well."""
assert api.laborejoEngineStarted
super().__init__(session=api.session, portName="in")
self.midiProcessor.active = False #specific to Laborejo
#Connect the template midi input with Laborejo api calls.
#self.midiProcessor.notePrinter(True)
self.midiProcessor.register_NoteOn(self._insertMusicItemFromMidi)
self.midiProcessor.register_NoteOff(self._pop)
api.callbacks.setCursor.append(self._setMidiThru) #When the track changes re-route cbox RT midi thru
@property
def midiInIsActive(self):
try:
return self.midiProcessor.active
except AttributeError: #during startupt
return False
def _insertMusicItemFromMidi(self, channel, midipitch, velocity):
if self._currentlyActiveNotes: #Chord
api.left()
keysig = api.session.data.currentTrack().state.keySignature()
pitchToInsert = api.pitchmath.fromMidi(midipitch, keysig)
api.addNoteToChord(pitchToInsert)
api.right()
else: #Single note
baseDuration = api.session.data.cursor.prevailingBaseDuration
keysig = api.session.data.currentTrack().state.keySignature()
pitchToInsert = api.pitchmath.fromMidi(midipitch, keysig)
api.insertChord(baseDuration, pitchToInsert)
self._currentlyActiveNotes.add(midipitch)
def _pop(self, channel, midipitch, velocity):
self._currentlyActiveNotes.remove(midipitch)
def setMidiInputActive(self, state:bool):
self.midiProcessor.active = state
api.callbacks._prevailingBaseDurationChanged(api.session.data.cursor.prevailingBaseDuration)
def toggleMidiIn(self):
self.setMidiInputActive(not self.midiInIsActive)
def _setMidiThru(self, cursorExport):
"""We don't need to react to deleted tracks because that does reset the cursor.
The template midi in does _not_ check if the routed output ports still exist.
however, that is a low risk state that needs changes in the program"""
self.setMidiThru(cursorExport["cboxMidiOutUuid"])
stepMidiInput = StepMidiInput() #global to use in other parts of Laborejo

0
qtgui/__init__.py

635
qtgui/conductor.py

@ -0,0 +1,635 @@
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Copyright 2017, Nils Hilbricht, Germany ( https://www.hilbricht.net )
This file is part of Laborejo ( https://www.laborejo.org )
Laborejo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
import logging; logging.info("import {}".format(__file__))
from PyQt5 import QtCore, QtGui, QtSvg, QtWidgets
from .constantsAndConfigs import constantsAndConfigs
from template.qtgui.helper import stringToColor, removeInstancesFromScene, callContextMenu, stretchLine, stretchRect
from template.helper import pairwise
from .submenus import SecondaryTempoChangeMenu, TempoBlockPropertiesEdit
import engine.api as api
oneRectToReturnThemAll = QtCore.QRectF(0,0,0,0) #prevent the annoying "NotImplementError" from Qt for boundingRect. For items that don't need any collision detection.
_zValuesRelativeToConductor = { #Only use for objects added directly to the Conductor, not their children.
"line":0,
"block":3,
"item":4,
"handle":5,
}
class Conductor(QtWidgets.QGraphicsItem):
"""The track for tempo items. Some methods have the same name and functionality
as note-track to be compatible. For example drag and drop of blocks."""
def __init__(self, parentView):
super().__init__()
self.parentView = parentView
self.totalHeight = 71
self.staticPoints = None #Cached backend staticRepresentationList: TempoPoints and interpolated points list
self.staticBlocks = None #Cached Block Data list
self.staticMeta = None #Cached track meta data dict.
self.staffLine = QtWidgets.QGraphicsLineItem(0,0,10,0) #x1, y1, x2, y2
self.staffLine.setParentItem(self)
self.staffLine.setPos(0,0)
self.timeLine = TimeLine(self) #registers its own callbacks
self.timeLine.setParentItem(self)
api.callbacks.updateTempoTrackBlocks.append(self.updateBlocks)
api.callbacks.updateTempoTrack.append(self.createGraphicItemsFromData)
api.callbacks.updateTempoTrackMeta.append(self.updateMetaData)
def paint(self, *args):
pass
def boundingRect(self, *args):
return oneRectToReturnThemAll
def blockAt(self, xScenePosition):
for block in ConductorTransparentBlock.instances:
start = block.staticExportItem["position"] / constantsAndConfigs.ticksToPixelRatio
end = start + block.staticExportItem["duration"] / constantsAndConfigs.ticksToPixelRatio
if start <= xScenePosition < end:
return block
return None #After the last block.
@property
def transparentBlockHandles(self):
return ConductorTransparentBlock.instances
def updateMetaData(self, trackMetaDictionary):
"""Keep the meta data up to date.
Meta Data is (absolute) min and max tempo values:
{'minimumAbsoluteTempoValue': 120, 'maximumAbsoluteTempoValue': 120}
"""
self.staticMeta = trackMetaDictionary
def updateBlocks(self, staticRepresentationList):
"""This is called when the blocks itself change, of course.
But also """
self.staticBlocks = staticRepresentationList
removeInstancesFromScene(ConductorTransparentBlock)
for dictExportItem in staticRepresentationList:
guiBlock = ConductorTransparentBlock(parent = self, staticExportItem = dictExportItem, x = 0, y = -10, w = dictExportItem["duration"] / constantsAndConfigs.ticksToPixelRatio, h = 20)
guiBlock.setParentItem(self)
guiBlock.setPos(dictExportItem["position"] / constantsAndConfigs.ticksToPixelRatio,0)
guiBlock.setZValue(_zValuesRelativeToConductor["block"]) #including the handle
rightBorder = (dictExportItem["duration"] + dictExportItem["position"]) / constantsAndConfigs.ticksToPixelRatio
self.updateStaffLine(rightBorder)
def blockById(self, backendId):
for guiblock in ConductorTransparentBlock.instances:
if guiblock.staticExportItem["id"] == backendId:
return guiblock
#else:
# raise ValueError(f"{backendId} not found")
def updateStaffLine(self, x):
assert not self.staffLine.line().isNull()
line = self.staffLine.line()
line.setLength(x)
self.staffLine.setLine(line)
self.staffLine.setZValue(_zValuesRelativeToConductor["line"])
def createGraphicItemsFromData(self, staticRepresentationList):
self.staticPoints = staticRepresentationList
removeInstancesFromScene(TempoPoint)
y = -35 #The Y Value adjusts for the offset the text-item creates
for point in staticRepresentationList:
if not point["type"] == "interpolated": #a real user point or lastInBlock or lastInTrack
x = point["position"] / constantsAndConfigs.ticksToPixelRatio
p = TempoPoint(self, point, self.blockById(point["blockId"]))
p.setParentItem(self)
p.setPos(x, y)
def stretchXCoordinates(self, factor):
"""Reposition the items on the X axis.
Call goes through all parents/children, starting from ScoreView._stretchXCoordinates.
Docstring there."""
positionalItems = (TempoPoint.instances + ConductorTransparentBlock.instances)
for tempoPoint in positionalItems:
tempoPoint.setX(tempoPoint.pos().x() * factor)
for block in ConductorTransparentBlock.instances:
block.stretchXCoordinates(factor)
stretchLine(self.staffLine, factor)
self.timeLine.stretchXCoordinates(factor)
def mousePressEvent(self, event):
"""It is possible that this has coordinates outside of the Conductor instance. When the
mousePressEvent is inside and the mouse moves outside for the release event it still counts
as event of this instance"""
if event.button() == 1 and 0 <= event.scenePos().x() < self.staffLine.line().x2(): #within the conductor line: # QtCore.Qt.MouseButton.LeftButton
event.accept()
self.add(event.scenePos()) #create a new tempo point by telling the api a position and then reacting to "delete all, recreate" from the callback.
else:
super().mousePressEvent(event) #call default implementation from QGraphicsRectItem
def add(self, scenePos):
"""Use a scenePos (from self.mousePressEvent) to instruct the backend
to create a new tempo point."""
unitsPerMinute = 120
referenceTicks = api.D4
sp = scenePos.x() * constantsAndConfigs.ticksToPixelRatio
if constantsAndConfigs.snapToGrid:
sp = round(sp / constantsAndConfigs.gridRhythm) * constantsAndConfigs.gridRhythm
api.insertTempoItemAtAbsolutePosition(sp, unitsPerMinute, referenceTicks, graphType = "standalone")
class ConductorTransparentBlock(QtWidgets.QGraphicsRectItem):
"""A simplified version of a Block. Since we don't use blocks in the GUI, only in the backend
we still need them sometimes as macro strutures, where we don't care about the content.
The block handle is at the END of a block. """
class ConductorBlockName(QtWidgets.QGraphicsSimpleTextItem):
instances = []
def __init__(self, parent, positionInSeconds):
self.__class__.instances.append(self)
m, s = divmod(positionInSeconds, 60)
text = "{}:{} min".format(str(int(m)).zfill(2), str(int(s)).zfill(2))
super().__init__(text)
marker = QtWidgets.QGraphicsLineItem(0, 0, 0, -10) #vertical marker to connect to the conductor line
marker.setParentItem(self)
instances = []
def __init__(self, parent, staticExportItem, x, y, w, h):
self.__class__.instances.append(self)
super().__init__(x, y, w, h)
self.setFlags(QtWidgets.QGraphicsItem.ItemDoesntPropagateOpacityToChildren|QtWidgets.QGraphicsItem.ItemIsMovable) #no mouseReleaseEvent without selection or movable.
self.parent = parent #Conductor instance
self.color = stringToColor(staticExportItem["name"])
self.trans = QtGui.QColor("transparent")
self.setPen(self.trans)
self.setBrush(self.color)
self.setOpacity(0.2) #mimic background behaviour
self.staticExportItem = staticExportItem
self.posBeforeMove = None
self.cursorPosOnMoveStart = None
#Display Block ID
#self.idText = QtWidgets.QGraphicsSimpleTextItem(str(self.staticExportItem["id"]))
#self.idText.setParentItem(self)
#self.idText.setPos(0, -30)
if self.staticExportItem["duration"] >= 8*api.D1: #cosmetics
self.startLabel = QtWidgets.QGraphicsSimpleTextItem(self.staticExportItem["name"] + " start")
self.startLabel.setParentItem(self)
self.startLabel.setPos(15, -2*constantsAndConfigs.stafflineGap)
self.startLabel.setFlags(QtWidgets.QGraphicsItem.ItemIgnoresParentOpacity)
self.endLabel = QtWidgets.QGraphicsSimpleTextItem(self.staticExportItem["name"] + " end ")
self.endLabel.setParentItem(self)
self.endLabel.setPos(self.rect().width() - self.endLabel.boundingRect().width(), -2*constantsAndConfigs.stafflineGap)
self.endLabel.setFlags(QtWidgets.QGraphicsItem.ItemIgnoresParentOpacity)
else:
self.startLabel = QtWidgets.QGraphicsSimpleTextItem("")
self.endLabel = QtWidgets.QGraphicsSimpleTextItem("")
#Add End Line
self.marker = ConductorBlockHandle(parent = self)
self.marker.setParentItem(self)
self.marker.setPos(staticExportItem["duration"] / constantsAndConfigs.ticksToPixelRatio, -1/2* self.rect().height()+2)
#def paint(self, *args):
# """Prevent the selection rectangle when clicking the item"""
#!! This also prevents the rectangle to show up. Very bad decision.
# pass
def stretchXCoordinates(self, factor):
"""Reposition the items on the X axis.
Call goes through all parents/children, starting from ScoreView._stretchXCoordinates.
Docstring there."""
stretchRect(self, factor)
self.marker.setX(self.marker.pos().x() * factor)
def mouseMoveEvent(self, event):
"""Don't use the qt system. we move ourselves"""
event.accept()
def mousePressEvent(self, event):
self.parent.mousePressEvent(event)
def mouseMoveEventCustom(self, event):
"""
Move the whole block, change the tempoTrack form.
Custom gets called by the scene mouse press event directly only when the right keys
are hold down"""
# All the positions below don't work. They work fine when dragging Tracks around but not this Item. I can't be bothered to figure out why.
#scenePos() results ins an item position that is translated down and right. The higher the x/y value the more the offset
#Instead we calculate our delta ourselves.
#self.setPos(self.mapToItem(self, event.scenePos()))
#self.setPos(self.mapFromScene(event.scenePos()))
#posGlobal = QtGui.QCursor.pos()
#posView = self.parent.parentScore.parentView.mapFromGlobal(posGlobal) #a widget
#posScene = self.parent.parentScore.parentView.mapToScene(posView)
#print (posGlobal, posView, posScene, event.scenePos())
if self.cursorPosOnMoveStart:
self.setPos(event.scenePos().x(), self.posBeforeMove.y())
"""
#does not work with zooming
if self.cursorPosOnMoveStart:
delta = QtGui.QCursor.pos() - self.cursorPosOnMoveStart
new = self.posBeforeMove + delta
if new.x() < 0:
self.setPos(0, self.posBeforeMove.y())
else:
self.setPos(new.x(), self.posBeforeMove.y())
#event.ignore() #this blocks the qt movable object since we already move the object on our own.
"""
super().mouseMoveEvent(event)
def mousePressEventCustom(self, event):
"""Custom gets called by the scene mouse press event directly only when the right keys
are hold down"""
self.posBeforeMove = self.pos()
self.cursorPosOnMoveStart = QtGui.QCursor.pos()
#self.setBrush(self.color)
super().mousePressEvent(event)
def mouseReleaseEventCustom(self, event):
"""Custom gets called by the scene mouse press event directly only when the right keys
are hold down"""
#self.setBrush(self.trans)
self.setPos(self.posBeforeMove) #In case the block was moved to a position where no track is (below the tracks) we just reset the graphics. If the moving was correct then the new position will be set by redrawing the whole Conductor.
self.posBeforeMove = None
self.cursorPosOnMoveStart = None
super().mouseReleaseEvent(event)
def splitHere(self, event):
posRelativeToBlockStart = event.scenePos().x() * constantsAndConfigs.ticksToPixelRatio - self.x() * constantsAndConfigs.ticksToPixelRatio
if constantsAndConfigs.snapToGrid:
posRelativeToBlockStart = round(posRelativeToBlockStart / constantsAndConfigs.gridRhythm) * constantsAndConfigs.gridRhythm
if posRelativeToBlockStart > 0:
api.splitTempoBlock(self.staticExportItem["id"], int(posRelativeToBlockStart))
def contextMenuEvent(self, event):
listOfLabelsAndFunctions = [
("edit properties", lambda: TempoBlockPropertiesEdit(self.scene().parentView.mainWindow, staticExportItem = self.staticExportItem)),
("separator", None),
("split here", lambda: self.splitHere(event)),
("duplicate", lambda: api.duplicateTempoBlock(self.staticExportItem["id"])),
("create content link", lambda: api.duplicateContentLinkTempoBlock(self.staticExportItem["id"])),
("unlink", lambda: api.unlinkTempoBlock(self.staticExportItem["id"])),
("separator", None),
("join with next block", lambda: api.mergeWithNextTempoBlock(self.staticExportItem["id"])),
("delete block", lambda: api.deleteTempoBlock(self.staticExportItem["id"])),
("separator", None),
("append block at the end", api.appendTempoBlock),
]
callContextMenu(listOfLabelsAndFunctions)
class ConductorBlockHandle(QtWidgets.QGraphicsLineItem):
"""Provides user interaction so the temp block can be resized by moving this handle with the
mouse left and right.
When user interaction happens this handle acts upon its parent transparent block to resize it
and finally sends a message to the backend, to ask for a data change."""
def __init__(self, parent):
self.parentTransparentBlock = parent
super().__init__(0,-1, 0, parent.rect().height()-4) #x1, y1, x2, y2
self.setFlags(QtWidgets.QGraphicsItem.ItemIsMovable|QtWidgets.QGraphicsItem.ItemSendsGeometryChanges|QtWidgets.QGraphicsItem.ItemIsFocusable|QtWidgets.QGraphicsItem.ItemClipsToShape)
self.setAcceptHoverEvents(True)
self.setCursor(QtCore.Qt.SizeHorCursor)
pen = QtGui.QPen() # creates a default pen
if not self.parentTransparentBlock.staticExportItem["exportsAllItems"]:
pen.setStyle(QtCore.Qt.DotLine)
pen.setWidth(2)
self.setPen(pen)
self.inactivePen = pen
self.inactivePen.setColor(QtGui.QColor("black"))
self.activePen = QtGui.QPen(pen)
self.activePen.setColor(QtGui.QColor("cyan"))
self.minimalSize = api.D1 / constantsAndConfigs.ticksToPixelRatio
self.setZValue(_zValuesRelativeToConductor["handle"])
def shape(self):
"""Return a more accurate shape for this item so that
mouse hovering is more accurate"""
path = QtGui.QPainterPath()
path.addRect(QtCore.QRectF(-2, -2, 5, self.parentTransparentBlock.rect().height()+2 )) #this is directly related to inits parameter x, y, w, h
return path
def hoverEnterEvent(self, event):
self.setPen(self.activePen)
#self.parentTransparentBlock.setBrush(self.parentTransparentBlock.color)
def hoverLeaveEvent(self, event):
self.setPen(self.inactivePen)
#self.parentTransparentBlock.setBrush(self.parentTransparentBlock.trans)
def mousePressEvent(self, event):
self.posBeforeMove = self.pos()
self.cursorPosOnMoveStart = QtGui.QCursor.pos()
super().mousePressEvent(event)
def mouseMoveEvent(self, event):
if not self.cursorPosOnMoveStart:
super().mouseMoveEvent(event)
return None
delta = QtGui.QCursor.pos() - self.cursorPosOnMoveStart
new = self.posBeforeMove + delta
if not new.x() < self.minimalSize:
self.setPos(new.x(), self.posBeforeMove.y())
pRect = self.parentTransparentBlock.rect()
pRect.setRight(new.x())
self.parentTransparentBlock.setRect(pRect)
event.accept() #this blocks the qt movable object since we already move the object on our own.
#Don't call the super mouseMoveEvent!
def mouseReleaseEvent(self, event):
if self.cursorPosOnMoveStart:
endingRelativeToBlockStart = self.x() * constantsAndConfigs.ticksToPixelRatio - self.parentTransparentBlock.x()
if constantsAndConfigs.snapToGrid:
endingRelativeToBlockStart = round(endingRelativeToBlockStart / constantsAndConfigs.gridRhythm) * constantsAndConfigs.gridRhythm
assert endingRelativeToBlockStart > 0
self.setPos(self.posBeforeMove) #In case the handle was moved to a position where it wasn't allowed no backend action will happen. Just in case we reset the graphics for a smoother user experience.
self.posBeforeMove = None
self.cursorPosOnMoveStart = None
api.changeTempoBlockDuration(self.parentTransparentBlock.staticExportItem["id"], endingRelativeToBlockStart)
super().mouseReleaseEvent(event)
class TempoPoint(QtWidgets.QGraphicsItem):
"""A point where the values can be edited by the user.
The first TempoPoint cannot be hovered. It is instead attached to a block handle.
"""
instances = []
def __init__(self, parentTempoTrack, staticExportItem, parentBlock):
self.__class__.instances.append(self)
super().__init__()
self.staticExportItem = staticExportItem
self.parentTempoTrack = parentTempoTrack
self.parentBlock = parentBlock
self.setZValue(_zValuesRelativeToConductor["item"])
self.setAcceptHoverEvents(True)
if not self.staticExportItem["positionInBlock"] == 0:
self.setFlags(QtWidgets.QGraphicsItem.ItemIsMovable|QtWidgets.QGraphicsItem.ItemIsFocusable)
#Too irritating. And confuses with handle movement. self.setCursor(QtCore.Qt.SizeHorCursor) #this sets the cursor while the mouse is over the item. It is independent of AcceptHoverEvents
else:
self.ungrabMouse = api.nothing #to surpress a warning from the context menu
self.note = QtWidgets.QGraphicsTextItem("")
self.note.setParentItem(self)
self.note.setFont(constantsAndConfigs.musicFont)
self.note.setHtml("<font size='6'>{}</font>".format(constantsAndConfigs.realNoteDisplay[staticExportItem["referenceTicks"]]))
self.note.setPos(-6,0) #adjust items font x offsset.
self.number = QtWidgets.QGraphicsTextItem("")
self.number.setParentItem(self)
#self.number.setHtml("<font color='black' size='2'>{}</font>".format(str(int(staticExportItem["unitsPerMinute"]))))
self.number.setHtml("<font size='2'>{}</font>".format(str(int(staticExportItem["unitsPerMinute"]))))
self.number.setPos(-6,0) #adjust items font x offsset.
if not self.staticExportItem["graphType"] == "standalone":
self.arrow = QtWidgets.QGraphicsTextItem("") #unicode long arrow right #http://xahlee.info/comp/unicode_arrows.html
self.arrow.setParentItem(self)
self.arrow.setPos(7,30)
else:
self.arrow = None
for n in (self.note, self.number, self.arrow):
if n: n.setDefaultTextColor(QtGui.QColor("black"))
self.wheelEventChangedValue = 0 #resetted in hoverEnterEvent. But we still need it for new items that appear directly under the mouse cursor
def paint(self, painter, options, widget=None):
#painter.drawRect(self.boundingRect()) #uncomment to show the bounding rect
pass
def boundingRect(self):
return QtCore.QRectF(0,0,25,50) #x, y, w, h
def mouseMoveEvent(self, event):
if self.staticExportItem["positionInBlock"] == 0:
#First in block can't be moved
event.accept()
return
#toTheRight = True if event.scenePos().x() - event.lastScenePos().x()) > 0 else False
delta = event.scenePos().x() - event.lastScenePos().x()
newPos = self.x() + delta
if 0 <= newPos < self.parentTempoTrack.staffLine.line().x2(): #within the conductor line
self.setX(newPos)
event.accept()
def mousePressEvent(self, event):
"""Override the mousePressEvent to deactivate it.
Otherwise the event will be sent to the parent block and create a new TempoItem
at this point even if there is already one. Effectively replacing a custom item with
default value"""
#if self.staticExportItem["positionInBlock"] == 0:
# print ("no")
# #super().mousePressEvent(event)
event.accept() #
def mouseReleaseEvent(self, event):
if self.staticExportItem["positionInBlock"] == 0:
#First in block can't be moved
event.accept()
return
tickPositionAbsolute = self.scenePos().x() * constantsAndConfigs.ticksToPixelRatio
if constantsAndConfigs.snapToGrid:
tickPositionAbsolute = round(tickPositionAbsolute / constantsAndConfigs.gridRhythm) * constantsAndConfigs.gridRhythm
api.moveTempoItem(self.staticExportItem["id"], tickPositionAbsolute)
event.accept()
def hoverEnterEvent(self, event):
self.parentTempoTrack.parentView.mainWindow.ui.actionDelete.setEnabled(False) #Delete key collides with our hover-delete.
self.grabKeyboard()
self.wheelEventChangedValue = 0
for n in (self.note, self.number, self.arrow):
if n: n.setDefaultTextColor(QtGui.QColor("cyan"))
def hoverLeaveEvent(self, event):
self.parentTempoTrack.parentView.mainWindow.ui.actionDelete.setEnabled(True) #Delete key collides with our hover-delete.
self.ungrabKeyboard()
for n in (self.note, self.number, self.arrow):
if n: n.setDefaultTextColor(QtGui.QColor("black"))
if self.wheelEventChangedValue:
api.insertTempoItemAtAbsolutePosition(self.staticExportItem["position"], self.staticExportItem["unitsPerMinute"] + self.wheelEventChangedValue, self.staticExportItem["referenceTicks"], self.staticExportItem["graphType"])
def wheelEvent(self, event):
"""This buffers until hoverLeaveEvent and then the new value is sent in self.hoverLeaveEvent"""
if event.delta() > 0:
self.wheelEventChangedValue += 1
else:
self.wheelEventChangedValue -= 1
self.number.setHtml("<font size='2'>{}</font>".format(str(int(self.staticExportItem["unitsPerMinute"] + self.wheelEventChangedValue))))
event.accept()
def keyPressEvent(self, event):
"""Handle the delete item key.
Needs grabKeyboard, but NOT setFocus
The event will not be sent if it is blocked by a global shortcut.
"""
key = event.key()
if key == 16777223:
#after delete the item and tempo tracks gets recreated so we need to reactivate the shortcut now. It will work without these two lines, but that is only implicit behaviour.
self.parentTempoTrack.parentView.mainWindow.ui.actionDelete.setEnabled(True) #Delete key collides with our hover-delete.
self.ungrabKeyboard()
api.removeTempoItem(self.staticExportItem["id"])
else:
return super().keyPressEvent(event)
def contextMenuEvent(self, event):
listOfLabelsAndFunctions = [
("edit properties", lambda: SecondaryTempoChangeMenu(self.scene().parentView.mainWindow, staticExportTempoItem = self.staticExportItem)),
]
if not self.staticExportItem["positionInBlock"] == 0:
listOfLabelsAndFunctions.append(("delete", lambda: api.removeTempoItem(self.staticExportItem["id"])))
callContextMenu(listOfLabelsAndFunctions)
class TimeLine(QtWidgets.QGraphicsItem):
"""Displays the real time."""
class TimePoint(QtWidgets.QGraphicsSimpleTextItem):
instances = []
def __init__(self, parent, positionInSeconds):
self.__class__.instances.append(self)
m, s = divmod(positionInSeconds, 60)
text = "{}:{} min".format(str(int(m)).zfill(2), str(int(s)).zfill(2))
super().__init__(text)
marker = QtWidgets.QGraphicsLineItem(0, 0, 0, -10) #vertical marker to connect to the conductor line
marker.setParentItem(self)
def __init__(self, parent):
super().__init__()
self.parent = parent
self.gridInSeconds = 10
api.callbacks.updateTempoTrackBlocks.append(self.redraw)
#no redraw on init. self.parent.staticPoints is not set yet.
def paint(self, *args):
pass
def boundingRect(self, *args):
return oneRectToReturnThemAll
def redraw(self, staticRepresentationList):
if not self.parent.staticPoints:
return None
removeInstancesFromScene(self.TimePoint)
sliceStartInSeconds = 0 #counted, not calculated
gridCounter = 0 # int("how often was a gridMarker generated")
result = []
for nowPoint, nextPoint in pairwise(self.parent.staticPoints):
"""Values we can't calculate:
sliceEndInTicks / ticksPerSecond . sliceEndInTicks is an absolute position.
but ticksPerSecond changes with every slice. Therefore you would discard all
ticksPerSecond value except the last and calculate a wrong value.
Instead we need to calculate the seconds always in the slice and then count
the overall length.
"""
tempoForThisSlice = abs(nowPoint["value"])
sliceDurationInTicks = nextPoint["position"] - nowPoint["position"]
ticksPerSecondForThisSlice = tempoForThisSlice * api.D4 / 60 # ["value"] is normalized beatsPerMinute(!) for quarter notes. calculated from "units" and "referenceTicks"
sliceDurationInSeconds = sliceDurationInTicks / ticksPerSecondForThisSlice
sliceEndInSeconds = sliceStartInSeconds + sliceDurationInSeconds
while sliceStartInSeconds < (gridCounter+1) * self.gridInSeconds <= sliceEndInSeconds: #is the next grid marker(+1) in the current slice?
gridCounter += 1
secondsSinceLastTempoChange = gridCounter * self.gridInSeconds - sliceStartInSeconds
posInTicks = nowPoint["position"] + secondsSinceLastTempoChange * ticksPerSecondForThisSlice
assert nowPoint["position"] <= posInTicks <= nextPoint["position"]
result.append((posInTicks, gridCounter * self.gridInSeconds))
sliceStartInSeconds = sliceEndInSeconds
#After the loop both sliceStartInSeconds and sliceEndInSeconds are equal to the overall length of the track in seconds
#Add an end marker to the results and create the qGraphicItems to display the time markers.
if nextPoint["position"] > 0:
result.append((nextPoint["position"], sliceEndInSeconds))
for tickPos, secPos in result:
timePoint = self.TimePoint(self, secPos)
timePoint.setParentItem(self)
timePoint.setPos(tickPos / constantsAndConfigs.ticksToPixelRatio, 10)
def stretchXCoordinates(self, factor):
"""Does NOT just reposition the existing items but displays a different
time grid"""
for timePoint in self.TimePoint.instances:
timePoint.setX(timePoint.pos().x() * factor)

177
qtgui/constantsAndConfigs.py

@ -0,0 +1,177 @@
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Copyright 2017, Nils Hilbricht, Germany ( https://www.hilbricht.net )
This file is part of Laborejo ( https://www.laborejo.org )
Laborejo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
import logging; logging.info("import {}".format(__file__))
import engine.api as api
from PyQt5 import QtGui
class ConstantsAndConfigs(object):
def __init__(self):
self.ticksToPixelRatio = 128*3*5 #bigger value means less space between notes #api.D128 and 128*3*5 is also good. This gets changed during runtime as "Stretch Factor". Also: the QSettings save and reload this on a per-file basis.
#a quarter note has 53760 ticks. that is 53760 / 1920 = 28 pixels.
self.stafflineGap = 7 #it is 7 because it is an odd number, which has a middle. 123 4 567 which translates 1:1 to pixels.
self.beamHeight = 2
self.magicPixel = 4
self.negativeMagicPixel = -2
self.trackHeight = self.stafflineGap * 10
self.trackHeight = self.stafflineGap * 12
self.gridRhythm = api.D4 #Default value is quarter. The QSettings save and reload this on a per-file basis.
self.gridOpacity = 0.1 #this is only the default value. Once changed a QSetting will be used instead.
self.noteHeadMode = True #False means rectangle noteheads
self.followPlayhead = True #camera follows the playhead during playback.
self.duringPlayback = False #set by a callback.
self.velocityToPixelRatio = 2 #2.0 is the default. 128 pixels maximum.
self.availableEditModes = ("notation", "cc", "block")
self.ccViewValue = 0 #0-127. Only has effect if ccView is True
self.ccViewCallbacks = [] #list of functions. For example the main Window CC spin box and the block Editor CC spin box.
self._snapToGrid = True # For CC point and Tempo point placements
self.snapToGridCallbacks = [] # see ccViewCallbacks
self.zoomFactor = 1 # #Initial Zoom Level. Also hardcoded into scoreView.zoomNull
self.maximumZoomOut = 0.25
#fonts which are used in the QGraphicsScenes. They are special because they don't scale with the DPI.
self.fontDB = QtGui.QFontDatabase()
#fid = self.fontDB.addApplicationFont("gui/resources/freesans.ttf")
#if fid == -1:
# raise ValueError("Freesans.ttf not loaded ")
fid = self.fontDB.addApplicationFont(":euterpe.ttf")
if fid == -1:
raise ValueError("euterpe.ttf not loaded. Make sure resources were generated")
#For easier programWide access move these to constantsAndConfigs
#constantsAndConfigs.theFont = self.fontDB.font("FreeSans", "", 13)
#constantsAndConfigs.theFont.setPixelSize(13) #It is very important to set the pixel size before setting the font to the text
self.musicFont = self.fontDB.font("Euterpe", "", 13)
self.musicFont.setPixelSize(13) #It is very important to set the pixel size before setting the font to the text
self.dynamics = ["f", "ff", "p", "pp", "mf", "mp", "tacet"]
self.prettyRhythms = [ #list because we need item order
(api.DL, "0.25 Longa"),
(api.DB, "0.5 Brevis"),
(api.D1, "1 Whole"),
(api.D2, "2 Half"),
(api.D4, "4 Quarter"),
(api.D8, "8 Eigth"),
(api.D16, "16 Sixteenth"),
(api.D32, "32 Thirthy-Second"),
(api.D64, "64 Sixty-Fourth"),
(api.D128, "128 Hundred Twenty-Eighth "),
(api.D256, "256 Two-hundred Fifty-Sixth"),
]
self.prettyRhythmsStrings = [v for k,v in self.prettyRhythms]
self.prettyRhythmsValues = [k for k,v in self.prettyRhythms]
self.prettyExtendedRhythms = [ #list because we need item order
(api.DL, "0.25 Longa"),
(api.DB, "0.5 Brevis"),
(api.D1, "1 Whole"),
(api.D2, "2 Half "),
(api.D4, "4 Quarter"),
(api.D8, "8 Eigth"),
(api.D16, "16 Sixteenth"),
(api.D32, "32 Thirthy-Second"),
(api.D64, "64 Sixty-Fourth"),
(api.D128, "128 Hundred Twenty-Eighth"),
(1.5*api.DL, "Dotted 0.25 Longa"),
(1.5*api.DB, "Dotted 0.5 Brevis"),
(1.5*api.D1, "Dotted 1 Whole"),
(1.5*api.D2, "Dotted 2 Half"),
(1.5*api.D4, "Dotted 4 Quarter"),
(1.5*api.D8, "Dotted 8 Eigth "),
(1.5*api.D16, "Dotted 16 Sixteenth"),
(1.5*api.D32, "Dotted 32 Thirthy-Second"),
(1.5*api.D64, "Dotted 64 Sixty-Fourth "),
(1.5*api.D128, "Dotted 128 Hundred Twenty-Eighth "),
]
self.prettyExtendedRhythmsStrings = [v for k,v in self.prettyExtendedRhythms]
self.prettyExtendedRhythmsValues = [k for k,v in self.prettyExtendedRhythms]
#use with constantsAndConfigs.musicFont
self.realNoteDisplay = {
api.DB : "𝅜",
api.D1 : "𝅝",
api.D2 : "𝅗𝅥",
api.D4 : "𝅘𝅥",
api.D8 : "𝅘𝅥𝅮",
api.D16 : "𝅘𝅥𝅯",
api.D32 : "𝅘𝅥𝅰",
api.D64 : "𝅘𝅥𝅱",
api.D128 : "𝅘𝅥𝅲",
1.5 * api.DB : "𝅜𝅭", #dotted DB
1.5 * api.D1 : "𝅝𝅭", #dotted D1
1.5 * api.D2 : "𝅗𝅥𝅭", #dotted D2
1.5 * api.D4 : "𝅘𝅥𝅭", #dotted D4
1.5 * api.D8 : "𝅘𝅥𝅮𝅭", #dotted D8
1.5 * api.D16 : "𝅘𝅥𝅯𝅭", #dotted D16
1.5 * api.D32 : "𝅘𝅥𝅰𝅭", #dotted D32
1.5 * api.D64 : "𝅘𝅥𝅱𝅭", #dotted D64
1.5 * api.D128 : "𝅘𝅥𝅲𝅭", #dotted D128
2.25 * api.DB : "𝅜𝅭", #double dotted DB
2.25 * api.D1 : "𝅝𝅭", #double dotted D1
2.25 * api.D2 : "𝅗𝅥𝅭", #double dotted D2
2.25 * api.D4 : "𝅘𝅥𝅭", #double dotted D4
2.25 * api.D8 : "𝅘𝅥𝅮𝅭", #double dotted D8
2.25 * api.D16 : "𝅘𝅥𝅯𝅭", #double dotted D16
2.25 * api.D32 : "𝅘𝅥𝅰𝅭", #double dotted D32
2.25 * api.D64 : "𝅘𝅥𝅱𝅭", #double dotted D64
2.25 * api.D128 : "𝅘𝅥𝅲𝅭", #double dotted D128
}
self.commonNotes = [ #list because we need item order
(api.D1, "𝅝"), #D1
(api.D2 , "𝅗𝅥"), #D2
(api.D4 , "𝅘𝅥"), #D4
(api.D8 , "𝅘𝅥𝅮"), #D8
(1.5 * api.D1 , "𝅝𝅭"), #dotted D1
(1.5 * api.D2 , "𝅗𝅥𝅭"), #dotted D2
(1.5 * api.D4 , "𝅘𝅥𝅭"), #dotted D4
(1.5 * api.D8 , "𝅘𝅥𝅮𝅭"), #dotted D8
]
self.realNotesStrings = [v for k,v in self.commonNotes]
self.realNotesValues = [k for k,v in self.commonNotes]
@property
def snapToGrid(self):
return self._snapToGrid
@snapToGrid.setter
def snapToGrid(self, value):
self._snapToGrid = value
for func in self.snapToGridCallbacks:
func()
constantsAndConfigs = ConstantsAndConfigs() #singleton

242
qtgui/cursor.py

@ -0,0 +1,242 @@
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Copyright 2017, Nils Hilbricht, Germany ( https://www.hilbricht.net )
This file is part of Laborejo ( https://www.laborejo.org )
Laborejo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from PyQt5 import QtCore, QtGui, QtWidgets, QtWidgets
from .constantsAndConfigs import constantsAndConfigs
import engine.api as api
pen = QtGui.QPen()
pen.setCapStyle(QtCore.Qt.RoundCap)
pen.setJoinStyle(QtCore.Qt.RoundJoin)
pen.setWidth(2)
#pen.setColor(QtGui.QColor("red"))
class PitchCursor(QtWidgets.QGraphicsRectItem):
def __init__(self):
"""Does not need the actual dotOnLine.
this is done by the parent cursor.
This is just a fancy rect."""
#super().__init__(constantsAndConfigs.magicPixel, 2, constantsAndConfigs.magicPixel*3, constantsAndConfigs.stafflineGap/3)
super().__init__(0, 1, constantsAndConfigs.magicPixel*3, 5)
self.setBrush(QtGui.QColor("cyan"))
self.setPen(pen)
self.setEnabled(False)
class PositionCursor(QtWidgets.QGraphicsRectItem):
def __init__(self):
"""Does not need the actual position.
this is done by the parent cursor
This is just a fancy rect."""
super().__init__(-1.5*constantsAndConfigs.magicPixel, -3.5*constantsAndConfigs.stafflineGap, constantsAndConfigs.magicPixel*1.5, 7*constantsAndConfigs.stafflineGap)
self.setBrush(QtGui.QColor("cyan"))
self.setPen(pen)
self.setScale(0.8)
self.setEnabled(False)
class Cursor(QtWidgets.QGraphicsItemGroup):
"""A cursor that shows the vertical
as well as the horizontal position
"""
def __init__(self):
super().__init__()
self.cursorExportObject = None #the last cached cursor object aka the current cursor position
self.pitch = PitchCursor()
self.addToGroup(self.pitch)
self.position = PositionCursor()
self.addToGroup(self.position)
api.callbacks.setCursor.append(self.setCursor)
self.setEnabled(False)
def clearItemHighlight(self):
"""Gets called before a track changes. Most of the time when a new item is inserted/deleted.
This means the gui track will be recreated and a current highlight on an item might get
deleted while still on the item. This results in a qt crash
"""
Cursor.hightlightEffect = QtWidgets.QGraphicsColorizeEffect() #default strength of the effect is 1.0
Cursor.hightlightEffect.setColor(QtGui.QColor("cyan"))
Cursor.hightlightEffect.setStrength(0.7) #opacity of the effect
#Cursor.stafflineEffect = QtWidgets.QGraphicsColorizeEffect() #default strength of the effect is 1.0
#Cursor.stafflineEffect.setColor(QtGui.QColor("cyan"))
#Cursor.stafflineEffect.setStrength(1) #opacity of the effect
Cursor.stafflineEffect = QtWidgets.QGraphicsDropShadowEffect()
Cursor.stafflineEffect.setColor(QtGui.QColor("black"))
Cursor.stafflineEffect.setOffset(0,0)
Cursor.stafflineEffect.setBlurRadius(5)
def setCursor(self, cursorExportObject):
self.cursorExportObject = cursorExportObject
self.scene().parentView.setFocus()
self.pitch.setY(constantsAndConfigs.stafflineGap * cursorExportObject["dotOnLine"] / 2 - 3) #the same as a notehead
x = cursorExportObject["tickindex"] / constantsAndConfigs.ticksToPixelRatio
#Finally shift the Position to the correct track. Trackindex from 0, naturally.
#self.setPos(x, constantsAndConfigs.timeLineOffsetNoteEditor + cursorExportObject["trackIndex"] * constantsAndConfigs.trackHeight)
currentGuiTrack = self.scene().tracks[cursorExportObject["trackId"]]
self.setPos(x, currentGuiTrack.y() )
try:
guiItemAtCursor = currentGuiTrack.itemById(cursorExportObject["itemId"])
if not guiItemAtCursor.staticItem["completeDuration"] > 0:
#guiItemAtCursor has no duration. is type guiItemAtCursor.staticItem["type"]
Cursor.hightlightEffect.setEnabled(True)
guiItemAtCursor.setGraphicsEffect(Cursor.hightlightEffect)
else:
Cursor.hightlightEffect.setEnabled(False)
except StopIteration:
Cursor.hightlightEffect.setEnabled(False) #happens only on startup or appending (which is the same)
#Highlight the current staffline
if currentGuiTrack.staticExportItem["double"] and cursorExportObject["dotOnLine"] in (8, 10, 12, 14, 16):
lineNumber = int(cursorExportObject["dotOnLine"] / 2) + 1 #gui-stafflines are counted from 0 to n, top to bottom (listindex) while backend stafflines begin on -4
currentGuiTrack.staffLines[lineNumber].setGraphicsEffect(Cursor.stafflineEffect)
Cursor.stafflineEffect.setEnabled(True)
elif cursorExportObject["dotOnLine"] in (-4, -2, 0, 2, 4):
lineNumber = int(cursorExportObject["dotOnLine"] / 2) + 2 #gui-stafflines are counted from 0 to n, top to bottom (listindex) while backend stafflines begin on -4
currentGuiTrack.staffLines[lineNumber].setGraphicsEffect(Cursor.stafflineEffect)
Cursor.stafflineEffect.setEnabled(True)
else:
Cursor.stafflineEffect.setEnabled(False)
class Playhead(QtWidgets.QGraphicsLineItem):
def __init__(self, parentScoreScene):
super().__init__(0, 0, 0, 0) # (x1, y1, x2, y2)
self.parentScoreScene = parentScoreScene
p = QtGui.QPen()
p.setColor(QtGui.QColor("red"))
p.setCosmetic(True)
self.setPen(p)
self.setAcceptHoverEvents(True)
api.callbacks.setPlaybackTicks.append(self.setCursorPosition)
api.callbacks.tracksChanged.append(self.setLineToWindowHeigth) #for new tracks
api.callbacks.updateTempoTrack.append(self.setLineToWindowHeigth)
self.setFlags(QtWidgets.QGraphicsItem.ItemIsMovable)
self.setAcceptedMouseButtons(QtCore.Qt.LeftButton)
self.setZValue(90)
#self.parentScoreScene.parentView.verticalScrollBar().valueChanged.connect(self.setLineToWindowHeigth)
#self.hide()
#self.maxHeight = QtWidgets.QDesktopWidget().geometry().height() #we really hope the screen resolution does not change during the session.
def setCursorPosition(self, tickindex:int, playbackStatus:bool):
"""Set the playhead to the right position, but keep the viewport stable.
Shift the entire "page" if the cursor becomes invisible because its steps outside the viewport"""
self.setLineToWindowHeigth()
x = tickindex / constantsAndConfigs.ticksToPixelRatio
self.setX(x)
if constantsAndConfigs.followPlayhead and playbackStatus:
scenePos = self.parentScoreScene.parentView.mapFromScene(self.pos())
cursorViewPosX = scenePos.x() #the cursor position in View coordinates
width = self.parentScoreScene.parentView.geometry().width()
if cursorViewPosX <= 0 or cursorViewPosX >= width: #"pageflip"
self.parentScoreScene.parentView.horizontalScrollBar().setValue(x * constantsAndConfigs.zoomFactor)
def _Deprecated__ScrollingVariant___setCursorPosition(self, tickindex):
"""the tickindex to pixel index on the x axis is a fixed 1:n
relation. What you see is where you are. No jumps, the playhead
stays on course."""
self.setLineToWindowHeigth()
x = tickindex / constantsAndConfigs.ticksToPixelRatio
self.setX(x)
if constantsAndConfigs.followPlayhead and api.playbackStatus():
#self.parentScoreScene.parentView.centerOn(self) Do not use center on. It centers for Y as well which creates a recursion and the score gets taller and taller.
#self.scene().parentView.horizontalScrollBar().setValue(x - 150)
#xV = self.parentScoreScene.parentView.mapFromScene(x,0).x()
self.parentScoreScene.parentView.horizontalScrollBar().setValue(x - 150) #x does not with zoom levels. the bar drifts away.
def setLineToWindowHeigth(self, *args):
h = self.parentScoreScene.cachedSceneHeight
self.setLine(0, 0, 0, h) #(x1, y1, x2, y2)
def mouseMoveEvent(self, event):
"""Only allow movement in Y direction.
Only triggered when dragging."""
#super().mouseMoveEvent(event) allows free movement through Qt. Don't call that.
p = event.scenePos().x()
if p < 0:
p = 0
#self.setPos(p, self.scene().parentView.mapToScene(0, 0).y())
self.setX(p)
api.seek(p * constantsAndConfigs.ticksToPixelRatio)
event.accept()
def mouseReleaseEvent(self, event):
if constantsAndConfigs.snapToGrid:
x = event.scenePos().x() * constantsAndConfigs.ticksToPixelRatio
p = round(x / constantsAndConfigs.gridRhythm) * constantsAndConfigs.gridRhythm
if p < 0:
p = 0
api.seek(p)
def hoverEnterEvent(self, event):
self.setCursor(QtCore.Qt.SizeHorCursor)
self.update() #the default implementation calls this. event.accept/ignore has no effect.
def hoverLeaveEvent(self, event):
self.unsetCursor()
self.update() #the default implementation calls this. event.accept/ignore has no effect.
class Selection(QtWidgets.QGraphicsRectItem):
"""A semi-transparent rectangle that shows the current selection"""
def __init__(self):
super().__init__(0, 0, 0, 0)
self.validBrush = QtGui.QBrush(QtGui.QColor("grey"))
self.invalidBrush = QtGui.QBrush(QtGui.QColor("grey"))
self.invalidBrush.setStyle(QtCore.Qt.DiagCrossPattern)
self.setPen(pen)
self.setOpacity(0.2)
self.setEnabled(False)
api.callbacks.setSelection.append(self.setSelection)
def setSelection(self, tupleOfCursorExportObjects):
if tupleOfCursorExportObjects:
validSelection, topleftCursorObject, bottomRightCursorObject = tupleOfCursorExportObjects
if validSelection:
self.setBrush(self.validBrush)
else:
self.setBrush(self.invalidBrush)
topGuiTrack = self.scene().tracks[topleftCursorObject["trackId"]]
bottomGuiTrack = self.scene().tracks[bottomRightCursorObject["trackId"]]
#y = constantsAndConfigs.timeLineOffsetNoteEditor + topleftCursorObject["trackIndex"] * constantsAndConfigs.trackHeight - constantsAndConfigs.trackHeight/2
#h = (bottomRightCursorObject["trackIndex"] - topleftCursorObject["trackIndex"]) * constantsAndConfigs.trackHeight + constantsAndConfigs.trackHeight
x = topleftCursorObject["tickindex"] / constantsAndConfigs.ticksToPixelRatio
w = (bottomRightCursorObject["tickindex"] - topleftCursorObject["tickindex"]) / constantsAndConfigs.ticksToPixelRatio
y = topGuiTrack.y() - constantsAndConfigs.trackHeight/2
if bottomGuiTrack.staticExportItem["double"]:
h = bottomGuiTrack.y() - y + constantsAndConfigs.trackHeight
else:
h = bottomGuiTrack.y() - y + constantsAndConfigs.trackHeight/2
self.setRect(0, 0, w-3, h) #substract a few pixels to make it look less ambigious if the last item on the right edge is included or not (it is not)
self.setPos(x,y)
self.setVisible(True)
else: #no selection
self.setVisible(False)

49
qtgui/designer/clefs.ui

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Form</class>
<widget class="QWidget" name="Form">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>585</width>
<height>130</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="1">
<widget class="QPushButton" name="bass">
<property name="text">
<string>[2] Bass</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QPushButton" name="pushButton">
<property name="text">
<string>[3] Treble +Oct</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="pushButton_2">
<property name="text">
<string>[4] Bass -Oct</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QPushButton" name="treble">
<property name="text">
<string>[1] Treble</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

956
qtgui/designer/mainwindow.py

@ -0,0 +1,956 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'mainwindow.ui'
#
# Created by: PyQt5 UI code generator 5.11.3
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(1036, 625)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.centralwidget)
self.verticalLayout_2.setObjectName("verticalLayout_2")
self.mainStackWidget = QtWidgets.QStackedWidget(self.centralwidget)
self.mainStackWidget.setObjectName("mainStackWidget")
self.verticalLayout_2.addWidget(self.mainStackWidget)
MainWindow.setCentralWidget(self.centralwidget)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.toolBar = QtWidgets.QToolBar(MainWindow)
self.toolBar.setMovable(False)
self.toolBar.setFloatable(False)
self.toolBar.setObjectName("toolBar")
MainWindow.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBar)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 1036, 20))
self.menubar.setObjectName("menubar")
self.menuHelp = QtWidgets.QMenu(self.menubar)
self.menuHelp.setObjectName("menuHelp")
self.menuObjects = QtWidgets.QMenu(self.menubar)
self.menuObjects.setObjectName("menuObjects")
self.menuGeneric = QtWidgets.QMenu(self.menubar)
self.menuGeneric.setEnabled(True)
self.menuGeneric.setObjectName("menuGeneric")
self.menuType_Here = QtWidgets.QMenu(self.menuGeneric)
self.menuType_Here.setObjectName("menuType_Here")
self.menuTracks = QtWidgets.QMenu(self.menubar)
self.menuTracks.setObjectName("menuTracks")
self.menuEdit = QtWidgets.QMenu(self.menubar)
self.menuEdit.setObjectName("menuEdit")
self.menuView = QtWidgets.QMenu(self.menubar)
self.menuView.setObjectName("menuView")
self.menuMode = QtWidgets.QMenu(self.menuView)
self.menuMode.setObjectName("menuMode")
self.menu = QtWidgets.QMenu(self.menubar)
self.menu.setEnabled(False)
self.menu.setObjectName("menu")
self.menu_2 = QtWidgets.QMenu(self.menubar)
self.menu_2.setEnabled(False)
self.menu_2.setObjectName("menu_2")
self.menuEdit_MusicItem = QtWidgets.QMenu(self.menubar)
self.menuEdit_MusicItem.setObjectName("menuEdit_MusicItem")
self.menuEdit_2 = QtWidgets.QMenu(self.menubar)
self.menuEdit_2.setObjectName("menuEdit_2")
self.menuToolbox = QtWidgets.QMenu(self.menubar)
self.menuToolbox.setObjectName("menuToolbox")
self.menuOrder = QtWidgets.QMenu(self.menuToolbox)
self.menuOrder.setObjectName("menuOrder")
self.menuInsert = QtWidgets.QMenu(self.menuToolbox)
self.menuInsert.setObjectName("menuInsert")
self.menuMIDI = QtWidgets.QMenu(self.menuToolbox)
self.menuMIDI.setObjectName("menuMIDI")
self.menuLilypond = QtWidgets.QMenu(self.menubar)
self.menuLilypond.setObjectName("menuLilypond")
MainWindow.setMenuBar(self.menubar)
self.leftToolBar = QtWidgets.QToolBar(MainWindow)
self.leftToolBar.setEnabled(True)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.leftToolBar.sizePolicy().hasHeightForWidth())
self.leftToolBar.setSizePolicy(sizePolicy)
self.leftToolBar.setMinimumSize(QtCore.QSize(26, 0))
self.leftToolBar.setMaximumSize(QtCore.QSize(26, 16777215))
self.leftToolBar.setMovable(False)
self.leftToolBar.setAllowedAreas(QtCore.Qt.LeftToolBarArea)
self.leftToolBar.setFloatable(False)
self.leftToolBar.setObjectName("leftToolBar")
MainWindow.addToolBar(QtCore.Qt.LeftToolBarArea, self.leftToolBar)
self.actionUp = QtWidgets.QAction(MainWindow)
self.actionUp.setObjectName("actionUp")
self.actionDown = QtWidgets.QAction(MainWindow)
self.actionDown.setObjectName("actionDown")
self.actionLeft = QtWidgets.QAction(MainWindow)
self.actionLeft.setObjectName("actionLeft")
self.actionRight = QtWidgets.QAction(MainWindow)
self.actionRight.setObjectName("actionRight")
self.actionModal1 = QtWidgets.QAction(MainWindow)
self.actionModal1.setObjectName("actionModal1")
self.actionModal2 = QtWidgets.QAction(MainWindow)
self.actionModal2.setObjectName("actionModal2")
self.actionModal3 = QtWidgets.QAction(MainWindow)
self.actionModal3.setObjectName("actionModal3")
self.actionModal4 = QtWidgets.QAction(MainWindow)
self.actionModal4.setObjectName("actionModal4")
self.actionModal5 = QtWidgets.QAction(MainWindow)
self.actionModal5.setObjectName("actionModal5")
self.actionModal6 = QtWidgets.QAction(MainWindow)
self.actionModal6.setObjectName("actionModal6")
self.actionModal7 = QtWidgets.QAction(MainWindow)
self.actionModal7.setObjectName("actionModal7")
self.actionModal8 = QtWidgets.QAction(MainWindow)
self.actionModal8.setObjectName("actionModal8")
self.actionModal9 = QtWidgets.QAction(MainWindow)
self.actionModal9.setObjectName("actionModal9")
self.actionModal0 = QtWidgets.QAction(MainWindow)
self.actionModal0.setObjectName("actionModal0")
self.actionDelete = QtWidgets.QAction(MainWindow)
self.actionDelete.setObjectName("actionDelete")
self.actionBackspace = QtWidgets.QAction(MainWindow)
self.actionBackspace.setObjectName("actionBackspace")
self.actionShift_modal1 = QtWidgets.QAction(MainWindow)
self.actionShift_modal1.setObjectName("actionShift_modal1")
self.actionShift_modal2 = QtWidgets.QAction(MainWindow)
self.actionShift_modal2.setObjectName("actionShift_modal2")
self.actionShift_modal3 = QtWidgets.QAction(MainWindow)
self.actionShift_modal3.setObjectName("actionShift_modal3")
self.actionShift_modal4 = QtWidgets.QAction(MainWindow)
self.actionShift_modal4.setObjectName("actionShift_modal4")
self.actionShift_modal5 = QtWidgets.QAction(MainWindow)
self.actionShift_modal5.setObjectName("actionShift_modal5")
self.actionShift_modal6 = QtWidgets.QAction(MainWindow)
self.actionShift_modal6.setObjectName("actionShift_modal6")
self.actionShift_modal7 = QtWidgets.QAction(MainWindow)
self.actionShift_modal7.setObjectName("actionShift_modal7")
self.actionShift_modal8 = QtWidgets.QAction(MainWindow)
self.actionShift_modal8.setObjectName("actionShift_modal8")
self.actionShift_modal9 = QtWidgets.QAction(MainWindow)
self.actionShift_modal9.setObjectName("actionShift_modal9")
self.actionShift_modal0 = QtWidgets.QAction(MainWindow)
self.actionShift_modal0.setObjectName("actionShift_modal0")
self.actionAddCursorNoteToChord = QtWidgets.QAction(MainWindow)
self.actionAddCursorNoteToChord.setShortcutContext(QtCore.Qt.WindowShortcut)
self.actionAddCursorNoteToChord.setObjectName("actionAddCursorNoteToChord")
self.actionDeleteCursorNoteFromChord = QtWidgets.QAction(MainWindow)
self.actionDeleteCursorNoteFromChord.setObjectName("actionDeleteCursorNoteFromChord")
self.actionAdd_Track = QtWidgets.QAction(MainWindow)
self.actionAdd_Track.setObjectName("actionAdd_Track")
self.actionTrackUp = QtWidgets.QAction(MainWindow)
self.actionTrackUp.setObjectName("actionTrackUp")
self.actionTrackDown = QtWidgets.QAction(MainWindow)
self.actionTrackDown.setObjectName("actionTrackDown")
self.actionHead = QtWidgets.QAction(MainWindow)
self.actionHead.setObjectName("actionHead")
self.actionTail = QtWidgets.QAction(MainWindow)
self.actionTail.setObjectName("actionTail")
self.actionTrackFirst = QtWidgets.QAction(MainWindow)
self.actionTrackFirst.setObjectName("actionTrackFirst")
self.actionTrackLast = QtWidgets.QAction(MainWindow)
self.actionTrackLast.setObjectName("actionTrackLast")
self.actionSharpen_Note = QtWidgets.QAction(MainWindow)
self.actionSharpen_Note.setObjectName("actionSharpen_Note")
self.actionFlatten_Note = QtWidgets.QAction(MainWindow)
self.actionFlatten_Note.setObjectName("actionFlatten_Note")
self.actionMeasureLeft = QtWidgets.QAction(MainWindow)
self.actionMeasureLeft.setObjectName("actionMeasureLeft")
self.actionMeasureRight = QtWidgets.QAction(MainWindow)
self.actionMeasureRight.setObjectName("actionMeasureRight")
self.actionStep_Up = QtWidgets.QAction(MainWindow)
self.actionStep_Up.setObjectName("actionStep_Up")
self.actionStep_Down = QtWidgets.QAction(MainWindow)
self.actionStep_Down.setObjectName("actionStep_Down")
self.actionOctave_Up = QtWidgets.QAction(MainWindow)
self.actionOctave_Up.setObjectName("actionOctave_Up")
self.actionOctave_Down = QtWidgets.QAction(MainWindow)
self.actionOctave_Down.setObjectName("actionOctave_Down")
self.actionAugment = QtWidgets.QAction(MainWindow)
self.actionAugment.setObjectName("actionAugment")
self.actionDiminish = QtWidgets.QAction(MainWindow)
self.actionDiminish.setObjectName("actionDiminish")
self.actionAppend_Block = QtWidgets.QAction(MainWindow)
self.actionAppend_Block.setObjectName("actionAppend_Block")
self.actionSplit_Current_Block = QtWidgets.QAction(MainWindow)
self.actionSplit_Current_Block.setObjectName("actionSplit_Current_Block")
self.actionDuplicate = QtWidgets.QAction(MainWindow)
self.actionDuplicate.setObjectName("actionDuplicate")
self.actionCreate_Linked_Copy = QtWidgets.QAction(MainWindow)
self.actionCreate_Linked_Copy.setObjectName("actionCreate_Linked_Copy")
self.actionDelete_Current_Block = QtWidgets.QAction(MainWindow)
self.actionDelete_Current_Block.setObjectName("actionDelete_Current_Block")
self.actionToggle_Notehead_Rectangles = QtWidgets.QAction(MainWindow)
self.actionToggle_Notehead_Rectangles.setCheckable(True)
self.actionToggle_Notehead_Rectangles.setObjectName("actionToggle_Notehead_Rectangles")
self.actionPlayPause = QtWidgets.QAction(MainWindow)
self.actionPlayPause.setObjectName("actionPlayPause")
self.actionPlayFromBeginning = QtWidgets.QAction(MainWindow)
self.actionPlayFromBeginning.setObjectName("actionPlayFromBeginning")
self.actionFollow_Playhead = QtWidgets.QAction(MainWindow)
self.actionFollow_Playhead.setCheckable(True)
self.actionFollow_Playhead.setChecked(True)
self.actionFollow_Playhead.setObjectName("actionFollow_Playhead")
self.actionPlayFromEditCursor = QtWidgets.QAction(MainWindow)
self.actionPlayFromEditCursor.setObjectName("actionPlayFromEditCursor")
self.actionStaccato = QtWidgets.QAction(MainWindow)
self.actionStaccato.setObjectName("actionStaccato")
self.actionCopy = QtWidgets.QAction(MainWindow)
self.actionCopy.setObjectName("actionCopy")
self.actionCut = QtWidgets.QAction(MainWindow)
self.actionCut.setObjectName("actionCut")
self.actionPaste = QtWidgets.QAction(MainWindow)
self.actionPaste.setObjectName("actionPaste")
self.actionUpOctave = QtWidgets.QAction(MainWindow)
self.actionUpOctave.setObjectName("actionUpOctave")
self.actionDownOctave = QtWidgets.QAction(MainWindow)
self.actionDownOctave.setObjectName("actionDownOctave")
self.actionDots = QtWidgets.QAction(MainWindow)
self.actionDots.setObjectName("actionDots")
self.actionCC_Mode = QtWidgets.QAction(MainWindow)
self.actionCC_Mode.setCheckable(True)
self.actionCC_Mode.setObjectName("actionCC_Mode")
self.CCactionSplit_Current_Block = QtWidgets.QAction(MainWindow)
self.CCactionSplit_Current_Block.setObjectName("CCactionSplit_Current_Block")
self.actionChange_Grid_Rhythm = QtWidgets.QAction(MainWindow)
self.actionChange_Grid_Rhythm.setCheckable(False)
self.actionChange_Grid_Rhythm.setChecked(False)
self.actionChange_Grid_Rhythm.setObjectName("actionChange_Grid_Rhythm")
self.actionSnap_To_Grid = QtWidgets.QAction(MainWindow)
self.actionSnap_To_Grid.setCheckable(True)
self.actionSnap_To_Grid.setChecked(True)
self.actionSnap_To_Grid.setObjectName("actionSnap_To_Grid")
self.actionAlt_modal1 = QtWidgets.QAction(MainWindow)
self.actionAlt_modal1.setObjectName("actionAlt_modal1")
self.actionAlt_modal2 = QtWidgets.QAction(MainWindow)
self.actionAlt_modal2.setObjectName("actionAlt_modal2")
self.actionAlt_modal3 = QtWidgets.QAction(MainWindow)
self.actionAlt_modal3.setObjectName("actionAlt_modal3")
self.actionAlt_modal4 = QtWidgets.QAction(MainWindow)
self.actionAlt_modal4.setObjectName("actionAlt_modal4")
self.actionAlt_modal5 = QtWidgets.QAction(MainWindow)
self.actionAlt_modal5.setObjectName("actionAlt_modal5")
self.actionAlt_modal6 = QtWidgets.QAction(MainWindow)
self.actionAlt_modal6.setObjectName("actionAlt_modal6")
self.actionAlt_modal7 = QtWidgets.QAction(MainWindow)
self.actionAlt_modal7.setObjectName("actionAlt_modal7")
self.actionAlt_modal8 = QtWidgets.QAction(MainWindow)
self.actionAlt_modal8.setObjectName("actionAlt_modal8")
self.actionAlt_modal9 = QtWidgets.QAction(MainWindow)
self.actionAlt_modal9.setObjectName("actionAlt_modal9")
self.actionAlt_modal0 = QtWidgets.QAction(MainWindow)
self.actionAlt_modal0.setObjectName("actionAlt_modal0")
self.actionMidi_In_is_Active = QtWidgets.QAction(MainWindow)
self.actionMidi_In_is_Active.setCheckable(True)
self.actionMidi_In_is_Active.setObjectName("actionMidi_In_is_Active")
self.actionTie = QtWidgets.QAction(MainWindow)
self.actionTie.setObjectName("actionTie")
self.actionLegatoSlur = QtWidgets.QAction(MainWindow)
self.actionLegatoSlur.setObjectName("actionLegatoSlur")
self.actionTenuto = QtWidgets.QAction(MainWindow)
self.actionTenuto.setObjectName("actionTenuto")
self.actionTriplet = QtWidgets.QAction(MainWindow)
self.actionTriplet.setObjectName("actionTriplet")
self.actionCustom_Tuplets = QtWidgets.QAction(MainWindow)
self.actionCustom_Tuplets.setEnabled(False)
self.actionCustom_Tuplets.setObjectName("actionCustom_Tuplets")
self.actionPrevailingRest = QtWidgets.QAction(MainWindow)
self.actionPrevailingRest.setEnabled(False)
self.actionPrevailingRest.setObjectName("actionPrevailingRest")
self.actionSplit_in_2 = QtWidgets.QAction(MainWindow)
self.actionSplit_in_2.setObjectName("actionSplit_in_2")
self.actionSplit_in_3 = QtWidgets.QAction(MainWindow)
self.actionSplit_in_3.setObjectName("actionSplit_in_3")
self.actionCustom_Split = QtWidgets.QAction(MainWindow)
self.actionCustom_Split.setEnabled(True)
self.actionCustom_Split.setObjectName("actionCustom_Split")
self.actionUndo = QtWidgets.QAction(MainWindow)
self.actionUndo.setObjectName("actionUndo")
self.actionRedo = QtWidgets.QAction(MainWindow)
self.actionRedo.setObjectName("actionRedo")
self.actionJoin_with_next_Block = QtWidgets.QAction(MainWindow)
self.actionJoin_with_next_Block.setObjectName("actionJoin_with_next_Block")
self.actionSet_UpBeat = QtWidgets.QAction(MainWindow)
self.actionSet_UpBeat.setObjectName("actionSet_UpBeat")
self.actionSelectLeft = QtWidgets.QAction(MainWindow)
self.actionSelectLeft.setObjectName("actionSelectLeft")
self.actionSelectRight = QtWidgets.QAction(MainWindow)
self.actionSelectRight.setObjectName("actionSelectRight")
self.actionSelectMeasureLeft = QtWidgets.QAction(MainWindow)
self.actionSelectMeasureLeft.setObjectName("actionSelectMeasureLeft")
self.actionSelectMeasureRight = QtWidgets.QAction(MainWindow)
self.actionSelectMeasureRight.setObjectName("actionSelectMeasureRight")
self.actionSelectHead = QtWidgets.QAction(MainWindow)
self.actionSelectHead.setObjectName("actionSelectHead")
self.actionSelectTail = QtWidgets.QAction(MainWindow)
self.actionSelectTail.setObjectName("actionSelectTail")
self.actionSelectTrackUp = QtWidgets.QAction(MainWindow)
self.actionSelectTrackUp.setObjectName("actionSelectTrackUp")
self.actionSelectTrackDown = QtWidgets.QAction(MainWindow)
self.actionSelectTrackDown.setObjectName("actionSelectTrackDown")
self.actionSelectTrackFirst = QtWidgets.QAction(MainWindow)
self.actionSelectTrackFirst.setObjectName("actionSelectTrackFirst")
self.actionSelectTrackLast = QtWidgets.QAction(MainWindow)
self.actionSelectTrackLast.setObjectName("actionSelectTrackLast")
self.actionSelectUp = QtWidgets.QAction(MainWindow)
self.actionSelectUp.setObjectName("actionSelectUp")
self.actionSelectDown = QtWidgets.QAction(MainWindow)
self.actionSelectDown.setObjectName("actionSelectDown")
self.actionSelectUpOctave = QtWidgets.QAction(MainWindow)
self.actionSelectUpOctave.setObjectName("actionSelectUpOctave")
self.actionSelectDownOctave = QtWidgets.QAction(MainWindow)
self.actionSelectDownOctave.setObjectName("actionSelectDownOctave")
self.actionSelectTrack = QtWidgets.QAction(MainWindow)
self.actionSelectTrack.setObjectName("actionSelectTrack")
self.actionSelectMeasureColumn = QtWidgets.QAction(MainWindow)
self.actionSelectMeasureColumn.setObjectName("actionSelectMeasureColumn")
self.actionSelectAllTracks = QtWidgets.QAction(MainWindow)
self.actionSelectAllTracks.setObjectName("actionSelectAllTracks")
self.actionVelocityMore = QtWidgets.QAction(MainWindow)
self.actionVelocityMore.setObjectName("actionVelocityMore")
self.actionVelocityLess = QtWidgets.QAction(MainWindow)
self.actionVelocityLess.setObjectName("actionVelocityLess")
self.actionDurationModMore = QtWidgets.QAction(MainWindow)
self.actionDurationModMore.setObjectName("actionDurationModMore")
self.actionDurationModLess = QtWidgets.QAction(MainWindow)
self.actionDurationModLess.setObjectName("actionDurationModLess")
self.actionReset_Velocity_Duration_Mod = QtWidgets.QAction(MainWindow)
self.actionReset_Velocity_Duration_Mod.setObjectName("actionReset_Velocity_Duration_Mod")
self.actionWiden_Score_View = QtWidgets.QAction(MainWindow)
self.actionWiden_Score_View.setObjectName("actionWiden_Score_View")
self.actionShrink_Score_View = QtWidgets.QAction(MainWindow)
self.actionShrink_Score_View.setObjectName("actionShrink_Score_View")
self.actionData_Editor = QtWidgets.QAction(MainWindow)
self.actionData_Editor.setCheckable(True)
self.actionData_Editor.setObjectName("actionData_Editor")
self.actionClef = QtWidgets.QAction(MainWindow)
self.actionClef.setObjectName("actionClef")
self.actionMetrical_Instruction = QtWidgets.QAction(MainWindow)
self.actionMetrical_Instruction.setObjectName("actionMetrical_Instruction")
self.actionKey_Signature = QtWidgets.QAction(MainWindow)
self.actionKey_Signature.setObjectName("actionKey_Signature")
self.actionDynamics = QtWidgets.QAction(MainWindow)
self.actionDynamics.setObjectName("actionDynamics")
self.actionMulti_Measure_Rest = QtWidgets.QAction(MainWindow)
self.actionMulti_Measure_Rest.setObjectName("actionMulti_Measure_Rest")
self.actionTemporary_Tempo_Change = QtWidgets.QAction(MainWindow)
self.actionTemporary_Tempo_Change.setObjectName("actionTemporary_Tempo_Change")
self.actionBeam = QtWidgets.QAction(MainWindow)
self.actionBeam.setObjectName("actionBeam")
self.actionRemoveBeams = QtWidgets.QAction(MainWindow)
self.actionRemoveBeams.setObjectName("actionRemoveBeams")
self.actionTempo_Change = QtWidgets.QAction(MainWindow)
self.actionTempo_Change.setObjectName("actionTempo_Change")
self.actionDelete_Tempo_Change = QtWidgets.QAction(MainWindow)
self.actionDelete_Tempo_Change.setObjectName("actionDelete_Tempo_Change")
self.actionBlock_Mode = QtWidgets.QAction(MainWindow)
self.actionBlock_Mode.setCheckable(True)
self.actionBlock_Mode.setObjectName("actionBlock_Mode")
self.actionNotation_Mode = QtWidgets.QAction(MainWindow)
self.actionNotation_Mode.setCheckable(True)
self.actionNotation_Mode.setChecked(True)
self.actionNotation_Mode.setObjectName("actionNotation_Mode")
self.actionTransposeChord = QtWidgets.QAction(MainWindow)
self.actionTransposeChord.setObjectName("actionTransposeChord")
self.actionTranspose_Score = QtWidgets.QAction(MainWindow)
self.actionTranspose_Score.setObjectName("actionTranspose_Score")
self.actionSave = QtWidgets.QAction(MainWindow)
self.actionSave.setObjectName("actionSave")
self.actionExport_File = QtWidgets.QAction(MainWindow)
self.actionExport_File.setObjectName("actionExport_File")
self.actionImport_File_replaces_current = QtWidgets.QAction(MainWindow)
self.actionImport_File_replaces_current.setObjectName("actionImport_File_replaces_current")
self.actionUnlink_Current_Block = QtWidgets.QAction(MainWindow)
self.actionUnlink_Current_Block.setObjectName("actionUnlink_Current_Block")
self.actionDelete_All_Empty_Blocks = QtWidgets.QAction(MainWindow)
self.actionDelete_All_Empty_Blocks.setObjectName("actionDelete_All_Empty_Blocks")
self.actionBlockRight = QtWidgets.QAction(MainWindow)
self.actionBlockRight.setObjectName("actionBlockRight")
self.actionBlockLeft = QtWidgets.QAction(MainWindow)
self.actionBlockLeft.setObjectName("actionBlockLeft")
self.actionSelectBlockRight = QtWidgets.QAction(MainWindow)
self.actionSelectBlockRight.setObjectName("actionSelectBlockRight")
self.actionSelectBlockLeft = QtWidgets.QAction(MainWindow)
self.actionSelectBlockLeft.setObjectName("actionSelectBlockLeft")
self.actionPedalNotes = QtWidgets.QAction(MainWindow)
self.actionPedalNotes.setObjectName("actionPedalNotes")
self.actionReverse = QtWidgets.QAction(MainWindow)
self.actionReverse.setObjectName("actionReverse")
self.actionDuplicateItem = QtWidgets.QAction(MainWindow)
self.actionDuplicateItem.setObjectName("actionDuplicateItem")
self.actionRandom = QtWidgets.QAction(MainWindow)
self.actionRandom.setObjectName("actionRandom")
self.actionAscending = QtWidgets.QAction(MainWindow)
self.actionAscending.setObjectName("actionAscending")
self.actionDescending = QtWidgets.QAction(MainWindow)
self.actionDescending.setObjectName("actionDescending")
self.actionMirror_around_Cursor = QtWidgets.QAction(MainWindow)
self.actionMirror_around_Cursor.setObjectName("actionMirror_around_Cursor")
self.actionInsert_Random = QtWidgets.QAction(MainWindow)
self.actionInsert_Random.setObjectName("actionInsert_Random")
self.actionRandom_chromatic_in_clef_range = QtWidgets.QAction(MainWindow)
self.actionRandom_chromatic_in_clef_range.setObjectName("actionRandom_chromatic_in_clef_range")
self.actionRandom_in_scale_in_clef_range = QtWidgets.QAction(MainWindow)
self.actionRandom_in_scale_in_clef_range.setObjectName("actionRandom_in_scale_in_clef_range")
self.actionRandom_pitch_from_clipboard = QtWidgets.QAction(MainWindow)
self.actionRandom_pitch_from_clipboard.setObjectName("actionRandom_pitch_from_clipboard")
self.actionProperties = QtWidgets.QAction(MainWindow)
self.actionProperties.setObjectName("actionProperties")
self.actionExport_to_Ly = QtWidgets.QAction(MainWindow)
self.actionExport_to_Ly.setObjectName("actionExport_to_Ly")
self.actionShow_PDF = QtWidgets.QAction(MainWindow)
self.actionShow_PDF.setObjectName("actionShow_PDF")
self.actionExport_to_pdf_file = QtWidgets.QAction(MainWindow)
self.actionExport_to_pdf_file.setObjectName("actionExport_to_pdf_file")
self.actionInstrument_Change = QtWidgets.QAction(MainWindow)
self.actionInstrument_Change.setObjectName("actionInstrument_Change")
self.actionProgram_Change_Relative = QtWidgets.QAction(MainWindow)
self.actionProgram_Change_Relative.setObjectName("actionProgram_Change_Relative")
self.actionBank_Change_Absolute = QtWidgets.QAction(MainWindow)
self.actionBank_Change_Absolute.setObjectName("actionBank_Change_Absolute")
self.actionBank_Change_Relative = QtWidgets.QAction(MainWindow)
self.actionBank_Change_Relative.setObjectName("actionBank_Change_Relative")
self.actionChannel_Change = QtWidgets.QAction(MainWindow)
self.actionChannel_Change.setObjectName("actionChannel_Change")
self.actionChannel_Change_Relative = QtWidgets.QAction(MainWindow)
self.actionChannel_Change_Relative.setObjectName("actionChannel_Change_Relative")
self.actionMIDI_Channel_Plus = QtWidgets.QAction(MainWindow)
self.actionMIDI_Channel_Plus.setObjectName("actionMIDI_Channel_Plus")
self.actionMIDI_Channel_Minus = QtWidgets.QAction(MainWindow)
self.actionMIDI_Channel_Minus.setObjectName("actionMIDI_Channel_Minus")
self.actionMIDI_Channel_Reset = QtWidgets.QAction(MainWindow)
self.actionMIDI_Channel_Reset.setObjectName("actionMIDI_Channel_Reset")
self.actionDelete_Current_Track = QtWidgets.QAction(MainWindow)
self.actionDelete_Current_Track.setObjectName("actionDelete_Current_Track")
self.actionUse_Current_Track_as_Metronome = QtWidgets.QAction(MainWindow)
self.actionUse_Current_Track_as_Metronome.setObjectName("actionUse_Current_Track_as_Metronome")
self.actionMetronome_Enabled = QtWidgets.QAction(MainWindow)
self.actionMetronome_Enabled.setCheckable(True)
self.actionMetronome_Enabled.setObjectName("actionMetronome_Enabled")
self.actionRandom_in_scale_in_cursor_plus_octave = QtWidgets.QAction(MainWindow)
self.actionRandom_in_scale_in_cursor_plus_octave.setObjectName("actionRandom_in_scale_in_cursor_plus_octave")
self.actionRandom_in_scale_in_octave_around_cursor = QtWidgets.QAction(MainWindow)
self.actionRandom_in_scale_in_octave_around_cursor.setObjectName("actionRandom_in_scale_in_octave_around_cursor")
self.actionCreate_pool_from_selection = QtWidgets.QAction(MainWindow)
self.actionCreate_pool_from_selection.setObjectName("actionCreate_pool_from_selection")
self.menuObjects.addAction(self.actionMetrical_Instruction)
self.menuObjects.addAction(self.actionClef)
self.menuObjects.addAction(self.actionKey_Signature)
self.menuObjects.addSeparator()
self.menuObjects.addAction(self.actionDynamics)
self.menuObjects.addAction(self.actionMulti_Measure_Rest)
self.menuObjects.addAction(self.actionLegatoSlur)
self.menuObjects.addSeparator()
self.menuObjects.addAction(self.actionTempo_Change)
self.menuObjects.addAction(self.actionDelete_Tempo_Change)
self.menuObjects.addAction(self.actionTemporary_Tempo_Change)
self.menuObjects.addSeparator()
self.menuObjects.addAction(self.actionInstrument_Change)
self.menuGeneric.addAction(self.actionBlockLeft)
self.menuGeneric.addAction(self.actionBlockRight)
self.menuGeneric.addAction(self.actionSelectBlockRight)
self.menuGeneric.addAction(self.actionSelectBlockLeft)
self.menuGeneric.addAction(self.actionDownOctave)
self.menuGeneric.addAction(self.actionAlt_modal1)
self.menuGeneric.addAction(self.actionAlt_modal2)
self.menuGeneric.addAction(self.actionUpOctave)
self.menuGeneric.addAction(self.actionUp)
self.menuGeneric.addAction(self.actionDown)
self.menuGeneric.addAction(self.actionLeft)
self.menuGeneric.addAction(self.actionRight)
self.menuGeneric.addAction(self.actionAlt_modal3)
self.menuGeneric.addAction(self.actionAlt_modal4)
self.menuGeneric.addAction(self.actionAlt_modal5)
self.menuGeneric.addAction(self.actionAlt_modal6)
self.menuGeneric.addAction(self.actionAlt_modal7)
self.menuGeneric.addAction(self.actionAlt_modal8)
self.menuGeneric.addAction(self.actionAlt_modal9)
self.menuGeneric.addAction(self.actionAlt_modal0)
self.menuGeneric.addAction(self.actionModal1)
self.menuGeneric.addAction(self.actionModal2)
self.menuGeneric.addAction(self.actionModal3)
self.menuGeneric.addAction(self.actionModal4)
self.menuGeneric.addAction(self.actionModal5)
self.menuGeneric.addAction(self.actionModal6)
self.menuGeneric.addAction(self.actionModal7)
self.menuGeneric.addAction(self.actionModal8)
self.menuGeneric.addAction(self.actionModal9)
self.menuGeneric.addAction(self.actionModal0)
self.menuGeneric.addAction(self.actionShift_modal1)
self.menuGeneric.addAction(self.actionShift_modal2)
self.menuGeneric.addAction(self.actionShift_modal3)
self.menuGeneric.addAction(self.actionShift_modal4)
self.menuGeneric.addAction(self.actionShift_modal5)
self.menuGeneric.addAction(self.actionShift_modal6)
self.menuGeneric.addAction(self.actionShift_modal7)
self.menuGeneric.addAction(self.actionShift_modal8)
self.menuGeneric.addAction(self.actionShift_modal9)
self.menuGeneric.addAction(self.actionShift_modal0)
self.menuGeneric.addAction(self.actionTrackUp)
self.menuGeneric.addAction(self.actionTrackDown)
self.menuGeneric.addAction(self.actionHead)
self.menuGeneric.addAction(self.actionTail)
self.menuGeneric.addAction(self.actionTrackFirst)
self.menuGeneric.addAction(self.actionMeasureRight)
self.menuGeneric.addAction(self.actionTrackLast)
self.menuGeneric.addAction(self.actionMeasureLeft)
self.menuGeneric.addAction(self.actionSelectLeft)
self.menuGeneric.addAction(self.actionSelectRight)
self.menuGeneric.addAction(self.actionSelectMeasureLeft)
self.menuGeneric.addAction(self.actionSelectMeasureRight)
self.menuGeneric.addAction(self.actionSelectHead)
self.menuGeneric.addAction(self.actionSelectTail)
self.menuGeneric.addAction(self.actionSelectTrackUp)
self.menuGeneric.addAction(self.actionSelectTrackDown)
self.menuGeneric.addAction(self.actionSelectTrackFirst)
self.menuGeneric.addAction(self.actionSelectTrackLast)
self.menuGeneric.addAction(self.actionSelectUp)
self.menuGeneric.addAction(self.actionSelectDown)
self.menuGeneric.addAction(self.actionSelectUpOctave)
self.menuGeneric.addAction(self.actionSelectDownOctave)
self.menuGeneric.addAction(self.actionSelectTrack)
self.menuGeneric.addAction(self.actionSelectAllTracks)
self.menuGeneric.addAction(self.actionSelectMeasureColumn)
self.menuGeneric.addAction(self.menuType_Here.menuAction())
self.menuTracks.addAction(self.actionAdd_Track)
self.menuTracks.addAction(self.actionDelete_Current_Track)
self.menuTracks.addAction(self.actionUse_Current_Track_as_Metronome)
self.menuTracks.addSeparator()
self.menuTracks.addAction(self.actionSplit_Current_Block)
self.menuTracks.addAction(self.actionAppend_Block)
self.menuTracks.addAction(self.actionDuplicate)
self.menuTracks.addAction(self.actionUnlink_Current_Block)
self.menuTracks.addAction(self.actionCreate_Linked_Copy)
self.menuTracks.addAction(self.actionDelete_Current_Block)
self.menuTracks.addAction(self.actionJoin_with_next_Block)
self.menuTracks.addSeparator()
self.menuTracks.addAction(self.actionTranspose_Score)
self.menuTracks.addAction(self.actionDelete_All_Empty_Blocks)
self.menuEdit.addAction(self.actionSharpen_Note)
self.menuEdit.addAction(self.actionFlatten_Note)
self.menuEdit.addAction(self.actionStep_Up)
self.menuEdit.addAction(self.actionStep_Down)
self.menuEdit.addAction(self.actionOctave_Up)
self.menuEdit.addAction(self.actionOctave_Down)
self.menuEdit.addAction(self.actionTransposeChord)
self.menuEdit.addSeparator()
self.menuEdit.addAction(self.actionAugment)
self.menuEdit.addAction(self.actionDiminish)
self.menuEdit.addAction(self.actionDots)
self.menuEdit.addAction(self.actionTriplet)
self.menuEdit.addAction(self.actionCustom_Tuplets)
self.menuEdit.addSeparator()
self.menuEdit.addAction(self.actionStaccato)
self.menuEdit.addAction(self.actionTenuto)
self.menuEdit.addAction(self.actionTie)
self.menuEdit.addSeparator()
self.menuEdit.addAction(self.actionVelocityMore)
self.menuEdit.addAction(self.actionVelocityLess)
self.menuEdit.addAction(self.actionDurationModMore)
self.menuEdit.addAction(self.actionDurationModLess)
self.menuEdit.addAction(self.actionReset_Velocity_Duration_Mod)
self.menuMode.addAction(self.actionNotation_Mode)
self.menuMode.addAction(self.actionBlock_Mode)
self.menuMode.addAction(self.actionCC_Mode)
self.menuView.addAction(self.actionSave)
self.menuView.addSeparator()
self.menuView.addAction(self.actionToggle_Notehead_Rectangles)
self.menuView.addAction(self.actionChange_Grid_Rhythm)
self.menuView.addAction(self.actionFollow_Playhead)
self.menuView.addAction(self.actionMidi_In_is_Active)
self.menuView.addAction(self.menuMode.menuAction())
self.menuView.addSeparator()
self.menuView.addAction(self.actionData_Editor)
self.menuView.addAction(self.actionProperties)
self.menuView.addAction(self.actionWiden_Score_View)
self.menuView.addAction(self.actionShrink_Score_View)
self.menuView.addSeparator()
self.menuView.addAction(self.actionPlayPause)
self.menuView.addAction(self.actionPlayFromEditCursor)
self.menuView.addAction(self.actionPlayFromBeginning)
self.menuView.addAction(self.actionMetronome_Enabled)
self.menuView.addSeparator()
self.menuEdit_MusicItem.addAction(self.actionAddCursorNoteToChord)
self.menuEdit_MusicItem.addAction(self.actionDeleteCursorNoteFromChord)
self.menuEdit_MusicItem.addAction(self.actionSplit_in_2)
self.menuEdit_MusicItem.addAction(self.actionSplit_in_3)
self.menuEdit_MusicItem.addAction(self.actionCustom_Split)
self.menuEdit_MusicItem.addSeparator()
self.menuEdit_MusicItem.addAction(self.actionBeam)
self.menuEdit_MusicItem.addAction(self.actionRemoveBeams)
self.menuEdit_MusicItem.addSeparator()
self.menuEdit_MusicItem.addAction(self.actionMIDI_Channel_Plus)
self.menuEdit_MusicItem.addAction(self.actionMIDI_Channel_Minus)
self.menuEdit_MusicItem.addAction(self.actionMIDI_Channel_Reset)
self.menuEdit_2.addAction(self.actionDelete)
self.menuEdit_2.addAction(self.actionBackspace)
self.menuEdit_2.addAction(self.actionUndo)
self.menuEdit_2.addAction(self.actionRedo)
self.menuEdit_2.addAction(self.actionCopy)
self.menuEdit_2.addAction(self.actionPaste)
self.menuEdit_2.addAction(self.actionCut)
self.menuEdit_2.addAction(self.actionDuplicateItem)
self.menuOrder.addAction(self.actionRandom)
self.menuOrder.addAction(self.actionReverse)
self.menuOrder.addAction(self.actionAscending)
self.menuOrder.addAction(self.actionDescending)
self.menuInsert.addAction(self.actionRandom_chromatic_in_clef_range)
self.menuInsert.addAction(self.actionRandom_in_scale_in_clef_range)
self.menuInsert.addAction(self.actionRandom_in_scale_in_cursor_plus_octave)
self.menuInsert.addAction(self.actionRandom_in_scale_in_octave_around_cursor)
self.menuInsert.addAction(self.actionRandom_pitch_from_clipboard)
self.menuInsert.addSeparator()
self.menuInsert.addAction(self.actionPedalNotes)
self.menuInsert.addAction(self.actionMirror_around_Cursor)
self.menuMIDI.addAction(self.actionChannel_Change)
self.menuToolbox.addAction(self.menuInsert.menuAction())
self.menuToolbox.addAction(self.menuOrder.menuAction())
self.menuToolbox.addAction(self.menuMIDI.menuAction())
self.menuLilypond.addAction(self.actionShow_PDF)
self.menuLilypond.addAction(self.actionExport_to_Ly)
self.menubar.addAction(self.menuView.menuAction())
self.menubar.addAction(self.menuEdit_2.menuAction())
self.menubar.addAction(self.menu.menuAction())
self.menubar.addAction(self.menuTracks.menuAction())
self.menubar.addAction(self.menuObjects.menuAction())
self.menubar.addAction(self.menuEdit_MusicItem.menuAction())
self.menubar.addAction(self.menuEdit.menuAction())
self.menubar.addAction(self.menuToolbox.menuAction())
self.menubar.addAction(self.menu_2.menuAction())
self.menubar.addAction(self.menuLilypond.menuAction())
self.menubar.addAction(self.menuHelp.menuAction())
self.menubar.addAction(self.menuGeneric.menuAction())
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "Laborejo"))
self.toolBar.setWindowTitle(_translate("MainWindow", "toolBar"))
self.menuHelp.setTitle(_translate("MainWindow", "Help"))
self.menuObjects.setTitle(_translate("MainWindow", "&Insert Objects"))
self.menuGeneric.setTitle(_translate("MainWindow", "&Generic"))
self.menuType_Here.setTitle(_translate("MainWindow", "T&ype Here"))
self.menuTracks.setTitle(_translate("MainWindow", "&Structures"))
self.menuEdit.setTitle(_translate("MainWindow", "E&dit Note"))
self.menuView.setTitle(_translate("MainWindow", "&Control"))
self.menuMode.setTitle(_translate("MainWindow", "&View and Edit Mode"))
self.menu.setTitle(_translate("MainWindow", "|"))
self.menu_2.setTitle(_translate("MainWindow", "|"))
self.menuEdit_MusicItem.setTitle(_translate("MainWindow", "Edit &MusicItem"))
self.menuEdit_2.setTitle(_translate("MainWindow", "E&dit"))
self.menuToolbox.setTitle(_translate("MainWindow", "&Toolbox"))
self.menuOrder.setTitle(_translate("MainWindow", "Note &Sorting"))
self.menuInsert.setTitle(_translate("MainWindow", "&Note Generation"))
self.menuMIDI.setTitle(_translate("MainWindow", "&MIDI"))
self.menuLilypond.setTitle(_translate("MainWindow", "&Lilypond"))
self.leftToolBar.setWindowTitle(_translate("MainWindow", "leftToolBar"))
self.actionUp.setText(_translate("MainWindow", "u&p"))
self.actionUp.setShortcut(_translate("MainWindow", "Up"))
self.actionDown.setText(_translate("MainWindow", "d&own"))
self.actionDown.setShortcut(_translate("MainWindow", "Down"))
self.actionLeft.setText(_translate("MainWindow", "&left"))
self.actionLeft.setShortcut(_translate("MainWindow", "Left"))
self.actionRight.setText(_translate("MainWindow", "&right"))
self.actionRight.setShortcut(_translate("MainWindow", "Right"))
self.actionModal1.setText(_translate("MainWindow", "&modal1"))
self.actionModal1.setShortcut(_translate("MainWindow", "1"))
self.actionModal2.setText(_translate("MainWindow", "modal&2"))
self.actionModal2.setShortcut(_translate("MainWindow", "2"))
self.actionModal3.setText(_translate("MainWindow", "modal&3"))
self.actionModal3.setShortcut(_translate("MainWindow", "3"))
self.actionModal4.setText(_translate("MainWindow", "modal&4"))
self.actionModal4.setShortcut(_translate("MainWindow", "4"))
self.actionModal5.setText(_translate("MainWindow", "modal&5"))
self.actionModal5.setShortcut(_translate("MainWindow", "5"))
self.actionModal6.setText(_translate("MainWindow", "modal&6"))
self.actionModal6.setShortcut(_translate("MainWindow", "6"))
self.actionModal7.setText(_translate("MainWindow", "modal&7"))
self.actionModal7.setShortcut(_translate("MainWindow", "7"))
self.actionModal8.setText(_translate("MainWindow", "modal&8"))
self.actionModal8.setShortcut(_translate("MainWindow", "8"))
self.actionModal9.setText(_translate("MainWindow", "modal&9"))
self.actionModal9.setShortcut(_translate("MainWindow", "9"))
self.actionModal0.setText(_translate("MainWindow", "modal&0"))
self.actionModal0.setShortcut(_translate("MainWindow", "0"))
self.actionDelete.setText(_translate("MainWindow", "&Delete Item"))
self.actionDelete.setShortcut(_translate("MainWindow", "Del"))
self.actionBackspace.setText(_translate("MainWindow", "Delete previous &Item"))
self.actionBackspace.setShortcut(_translate("MainWindow", "Backspace"))
self.actionShift_modal1.setText(_translate("MainWindow", "sh&ift+modal1"))
self.actionShift_modal1.setShortcut(_translate("MainWindow", "Shift+1"))
self.actionShift_modal2.setText(_translate("MainWindow", "shi&ft+modal2"))
self.actionShift_modal2.setShortcut(_translate("MainWindow", "Shift+2"))
self.actionShift_modal3.setText(_translate("MainWindow", "shift+modal3"))
self.actionShift_modal3.setShortcut(_translate("MainWindow", "Shift+3"))
self.actionShift_modal4.setText(_translate("MainWindow", "shift+modal4"))
self.actionShift_modal4.setShortcut(_translate("MainWindow", "Shift+4"))
self.actionShift_modal5.setText(_translate("MainWindow", "shift+modal5"))
self.actionShift_modal5.setShortcut(_translate("MainWindow", "Shift+5"))
self.actionShift_modal6.setText(_translate("MainWindow", "shift+modal6"))
self.actionShift_modal6.setShortcut(_translate("MainWindow", "Shift+6"))
self.actionShift_modal7.setText(_translate("MainWindow", "shift+modal7"))
self.actionShift_modal7.setShortcut(_translate("MainWindow", "Shift+7"))
self.actionShift_modal8.setText(_translate("MainWindow", "shift+modal8"))
self.actionShift_modal8.setShortcut(_translate("MainWindow", "Shift+8"))
self.actionShift_modal9.setText(_translate("MainWindow", "shift+modal9"))
self.actionShift_modal9.setShortcut(_translate("MainWindow", "Shift+9"))
self.actionShift_modal0.setText(_translate("MainWindow", "shift+modal0"))
self.actionShift_modal0.setShortcut(_translate("MainWindow", "Shift+0"))
self.actionAddCursorNoteToChord.setText(_translate("MainWindow", "&Add Note to Chord"))
self.actionAddCursorNoteToChord.setShortcut(_translate("MainWindow", "Return"))
self.actionDeleteCursorNoteFromChord.setText(_translate("MainWindow", "&Delete Note from Chord"))
self.actionDeleteCursorNoteFromChord.setShortcut(_translate("MainWindow", "Shift+Del"))
self.actionAdd_Track.setText(_translate("MainWindow", "&Add Track"))
self.actionTrackUp.setText(_translate("MainWindow", "&trackUp"))
self.actionTrackUp.setShortcut(_translate("MainWindow", "PgUp"))
self.actionTrackDown.setText(_translate("MainWindow", "trac&kDown"))
self.actionTrackDown.setShortcut(_translate("MainWindow", "PgDown"))
self.actionHead.setText(_translate("MainWindow", "&head"))
self.actionHead.setShortcut(_translate("MainWindow", "Home"))
self.actionTail.setText(_translate("MainWindow", "tail"))
self.actionTail.setShortcut(_translate("MainWindow", "End"))
self.actionTrackFirst.setText(_translate("MainWindow", "trackFirst"))
self.actionTrackFirst.setShortcut(_translate("MainWindow", "Ctrl+PgUp"))
self.actionTrackLast.setText(_translate("MainWindow", "trackLast"))
self.actionTrackLast.setShortcut(_translate("MainWindow", "Ctrl+PgDown"))
self.actionSharpen_Note.setText(_translate("MainWindow", "&Sharpen Note"))
self.actionSharpen_Note.setShortcut(_translate("MainWindow", "+"))
self.actionFlatten_Note.setText(_translate("MainWindow", "&Flatten Note"))
self.actionFlatten_Note.setShortcut(_translate("MainWindow", "-"))
self.actionMeasureLeft.setText(_translate("MainWindow", "measureLeft"))
self.actionMeasureLeft.setShortcut(_translate("MainWindow", "Ctrl+Left"))
self.actionMeasureRight.setText(_translate("MainWindow", "measureRight"))
self.actionMeasureRight.setShortcut(_translate("MainWindow", "Ctrl+Right"))
self.actionStep_Up.setText(_translate("MainWindow", "Step &Up"))
self.actionStep_Up.setShortcut(_translate("MainWindow", "Alt+Up"))
self.actionStep_Down.setText(_translate("MainWindow", "Ste&p Down"))
self.actionStep_Down.setShortcut(_translate("MainWindow", "Alt+Down"))
self.actionOctave_Up.setText(_translate("MainWindow", "&Octave Up"))
self.actionOctave_Up.setShortcut(_translate("MainWindow", "Ctrl+Alt+Up"))
self.actionOctave_Down.setText(_translate("MainWindow", "Octa&ve Down"))
self.actionOctave_Down.setShortcut(_translate("MainWindow", "Ctrl+Alt+Down"))
self.actionAugment.setText(_translate("MainWindow", "&Augment"))
self.actionAugment.setShortcut(_translate("MainWindow", "Alt+Right"))
self.actionDiminish.setText(_translate("MainWindow", "&Diminish"))
self.actionDiminish.setShortcut(_translate("MainWindow", "Alt+Left"))
self.actionAppend_Block.setText(_translate("MainWindow", "Append &Block"))
self.actionSplit_Current_Block.setText(_translate("MainWindow", "&Split Current Block"))
self.actionSplit_Current_Block.setShortcut(_translate("MainWindow", "Ins"))
self.actionDuplicate.setText(_translate("MainWindow", "&Duplicate Current Block"))
self.actionDuplicate.setShortcut(_translate("MainWindow", "Alt+Ins"))
self.actionCreate_Linked_Copy.setText(_translate("MainWindow", "&Create Linked Copy"))
self.actionCreate_Linked_Copy.setShortcut(_translate("MainWindow", "Alt+Shift+Ins"))
self.actionDelete_Current_Block.setText(_translate("MainWindow", "De&lete Current Block"))
self.actionToggle_Notehead_Rectangles.setText(_translate("MainWindow", "&Rectangle Noteheads"))
self.actionToggle_Notehead_Rectangles.setShortcut(_translate("MainWindow", "F1"))
self.actionPlayPause.setText(_translate("MainWindow", "P&lay / Pause"))
self.actionPlayPause.setShortcut(_translate("MainWindow", "Space"))
self.actionPlayFromBeginning.setText(_translate("MainWindow", "Play fr&om Start"))
self.actionPlayFromBeginning.setShortcut(_translate("MainWindow", "Shift+Space"))
self.actionFollow_Playhead.setText(_translate("MainWindow", "&Follow Playhead"))
self.actionFollow_Playhead.setShortcut(_translate("MainWindow", "F3"))
self.actionPlayFromEditCursor.setText(_translate("MainWindow", "Pla&y from Cursor"))
self.actionPlayFromEditCursor.setShortcut(_translate("MainWindow", "Ctrl+Space"))
self.actionStaccato.setText(_translate("MainWindow", "Staccato"))
self.actionStaccato.setShortcut(_translate("MainWindow", ","))
self.actionCopy.setText(_translate("MainWindow", "&Copy"))
self.actionCopy.setShortcut(_translate("MainWindow", "Ctrl+C"))
self.actionCut.setText(_translate("MainWindow", "Cut"))
self.actionCut.setShortcut(_translate("MainWindow", "Ctrl+X"))
self.actionPaste.setText(_translate("MainWindow", "&Paste"))
self.actionPaste.setShortcut(_translate("MainWindow", "Ctrl+V"))
self.actionUpOctave.setText(_translate("MainWindow", "&upOctave"))
self.actionUpOctave.setShortcut(_translate("MainWindow", "Ctrl+Up"))
self.actionDownOctave.setText(_translate("MainWindow", "&downOctave"))
self.actionDownOctave.setShortcut(_translate("MainWindow", "Ctrl+Down"))
self.actionDots.setText(_translate("MainWindow", "Dots"))
self.actionDots.setShortcut(_translate("MainWindow", "Q"))
self.actionCC_Mode.setText(_translate("MainWindow", "&Control Changes"))
self.actionCC_Mode.setShortcut(_translate("MainWindow", "F7"))
self.CCactionSplit_Current_Block.setText(_translate("MainWindow", "CCactionSplit_Current_Block"))
self.CCactionSplit_Current_Block.setShortcut(_translate("MainWindow", "Ins"))
self.actionChange_Grid_Rhythm.setText(_translate("MainWindow", "&Change Grid Rhythm"))
self.actionChange_Grid_Rhythm.setShortcut(_translate("MainWindow", "F2"))
self.actionSnap_To_Grid.setText(_translate("MainWindow", "Snap To Grid"))
self.actionAlt_modal1.setText(_translate("MainWindow", "&Alt_modal1"))
self.actionAlt_modal1.setShortcut(_translate("MainWindow", "Alt+1"))
self.actionAlt_modal2.setText(_translate("MainWindow", "Alt_modal2"))
self.actionAlt_modal2.setShortcut(_translate("MainWindow", "Alt+2"))
self.actionAlt_modal3.setText(_translate("MainWindow", "Alt_modal3"))
self.actionAlt_modal3.setShortcut(_translate("MainWindow", "Alt+3"))
self.actionAlt_modal4.setText(_translate("MainWindow", "Alt_modal4"))
self.actionAlt_modal4.setShortcut(_translate("MainWindow", "Alt+4"))
self.actionAlt_modal5.setText(_translate("MainWindow", "Alt_modal5"))
self.actionAlt_modal5.setShortcut(_translate("MainWindow", "Alt+5"))
self.actionAlt_modal6.setText(_translate("MainWindow", "Alt_modal6"))
self.actionAlt_modal6.setShortcut(_translate("MainWindow", "Alt+6"))
self.actionAlt_modal7.setText(_translate("MainWindow", "Alt_modal7"))
self.actionAlt_modal7.setShortcut(_translate("MainWindow", "Alt+7"))
self.actionAlt_modal8.setText(_translate("MainWindow", "Alt_modal8"))
self.actionAlt_modal8.setShortcut(_translate("MainWindow", "Alt+8"))
self.actionAlt_modal9.setText(_translate("MainWindow", "Alt_modal9"))
self.actionAlt_modal9.setShortcut(_translate("MainWindow", "Alt+9"))
self.actionAlt_modal0.setText(_translate("MainWindow", "Alt_modal0"))
self.actionAlt_modal0.setShortcut(_translate("MainWindow", "Alt+0"))
self.actionMidi_In_is_Active.setText(_translate("MainWindow", "&Midi In is Active"))
self.actionMidi_In_is_Active.setToolTip(_translate("MainWindow", "Toggle midi in on and off"))
self.actionMidi_In_is_Active.setShortcut(_translate("MainWindow", "F4"))
self.actionTie.setText(_translate("MainWindow", "T&ie"))
self.actionTie.setShortcut(_translate("MainWindow", "I"))
self.actionLegatoSlur.setText(_translate("MainWindow", "&Legato Slur"))
self.actionLegatoSlur.setToolTip(_translate("MainWindow", "Toggle Legato Slur"))
self.actionLegatoSlur.setShortcut(_translate("MainWindow", "S"))
self.actionTenuto.setText(_translate("MainWindow", "T&enuto"))
self.actionTenuto.setShortcut(_translate("MainWindow", "E"))
self.actionTriplet.setText(_translate("MainWindow", "Triplet"))
self.actionTriplet.setShortcut(_translate("MainWindow", "T"))
self.actionCustom_Tuplets.setText(_translate("MainWindow", "&Custom Tuplets"))
self.actionCustom_Tuplets.setShortcut(_translate("MainWindow", "Alt+T"))
self.actionPrevailingRest.setText(_translate("MainWindow", "Prevailing Rest"))
self.actionSplit_in_2.setText(_translate("MainWindow", "&Split in 2"))
self.actionSplit_in_2.setShortcut(_translate("MainWindow", "X"))
self.actionSplit_in_3.setText(_translate("MainWindow", "Split &in 3"))
self.actionSplit_in_3.setShortcut(_translate("MainWindow", "Shift+X"))
self.actionCustom_Split.setText(_translate("MainWindow", "Split in &X"))
self.actionCustom_Split.setShortcut(_translate("MainWindow", "Alt+X"))
self.actionUndo.setText(_translate("MainWindow", "&Undo"))
self.actionUndo.setShortcut(_translate("MainWindow", "Ctrl+Z"))
self.actionRedo.setText(_translate("MainWindow", "&Redo"))
self.actionRedo.setShortcut(_translate("MainWindow", "Ctrl+Shift+Z"))
self.actionJoin_with_next_Block.setText(_translate("MainWindow", "&Join with next Block"))
self.actionJoin_with_next_Block.setShortcut(_translate("MainWindow", "Shift+Ins"))
self.actionSet_UpBeat.setText(_translate("MainWindow", "Set Upbeat"))
self.actionSelectLeft.setText(_translate("MainWindow", "selectLeft"))
self.actionSelectLeft.setShortcut(_translate("MainWindow", "Shift+Left"))
self.actionSelectRight.setText(_translate("MainWindow", "selectRi&ght"))
self.actionSelectRight.setShortcut(_translate("MainWindow", "Shift+Right"))
self.actionSelectMeasureLeft.setText(_translate("MainWindow", "selectMeasureLeft"))
self.actionSelectMeasureLeft.setShortcut(_translate("MainWindow", "Ctrl+Shift+Left"))
self.actionSelectMeasureRight.setText(_translate("MainWindow", "selectMeasureRight"))
self.actionSelectMeasureRight.setShortcut(_translate("MainWindow", "Ctrl+Shift+Right"))
self.actionSelectHead.setText(_translate("MainWindow", "selectHead"))
self.actionSelectHead.setShortcut(_translate("MainWindow", "Shift+Home"))
self.actionSelectTail.setText(_translate("MainWindow", "selectTail"))
self.actionSelectTail.setShortcut(_translate("MainWindow", "Shift+End"))
self.actionSelectTrackUp.setText(_translate("MainWindow", "selectTrackUp"))
self.actionSelectTrackUp.setShortcut(_translate("MainWindow", "Shift+PgUp"))
self.actionSelectTrackDown.setText(_translate("MainWindow", "selectTrackDown"))
self.actionSelectTrackDown.setShortcut(_translate("MainWindow", "Shift+PgDown"))
self.actionSelectTrackFirst.setText(_translate("MainWindow", "selectTrackFirst"))
self.actionSelectTrackFirst.setShortcut(_translate("MainWindow", "Ctrl+Shift+PgUp"))
self.actionSelectTrackLast.setText(_translate("MainWindow", "selectTrackLast"))
self.actionSelectTrackLast.setShortcut(_translate("MainWindow", "Ctrl+Shift+PgDown"))
self.actionSelectUp.setText(_translate("MainWindow", "selectUp"))
self.actionSelectUp.setShortcut(_translate("MainWindow", "Shift+Up"))
self.actionSelectDown.setText(_translate("MainWindow", "selectDo&wn"))
self.actionSelectDown.setShortcut(_translate("MainWindow", "Shift+Down"))
self.actionSelectUpOctave.setText(_translate("MainWindow", "selectUpOcta&ve"))
self.actionSelectUpOctave.setShortcut(_translate("MainWindow", "Ctrl+Shift+Up"))
self.actionSelectDownOctave.setText(_translate("MainWindow", "selectDow&nOctave"))
self.actionSelectDownOctave.setShortcut(_translate("MainWindow", "Ctrl+Shift+Down"))
self.actionSelectTrack.setText(_translate("MainWindow", "selectTrack"))
self.actionSelectTrack.setShortcut(_translate("MainWindow", "Shift+A"))
self.actionSelectMeasureColumn.setText(_translate("MainWindow", "selectMeasureColumn"))
self.actionSelectMeasureColumn.setShortcut(_translate("MainWindow", "Ctrl+A"))
self.actionSelectAllTracks.setText(_translate("MainWindow", "selectAllTracks"))
self.actionSelectAllTracks.setShortcut(_translate("MainWindow", "Ctrl+Shift+A"))
self.actionVelocityMore.setText(_translate("MainWindow", "&More Velocity"))
self.actionVelocityMore.setToolTip(_translate("MainWindow", "More Velocity"))
self.actionVelocityMore.setShortcut(_translate("MainWindow", ">"))
self.actionVelocityLess.setText(_translate("MainWindow", "&Less Velocity"))
self.actionVelocityLess.setToolTip(_translate("MainWindow", "Less Velocity"))
self.actionVelocityLess.setShortcut(_translate("MainWindow", "<"))
self.actionDurationModMore.setText(_translate("MainWindow", "Lo&nger Duration Mod."))
self.actionDurationModMore.setToolTip(_translate("MainWindow", "Longer Duration Mod."))
self.actionDurationModMore.setShortcut(_translate("MainWindow", "Alt+Shift+Right"))
self.actionDurationModLess.setText(_translate("MainWindow", "Shorter Duration Mod."))
self.actionDurationModLess.setToolTip(_translate("MainWindow", "Shorter Duration Mod."))
self.actionDurationModLess.setShortcut(_translate("MainWindow", "Alt+Shift+Left"))
self.actionReset_Velocity_Duration_Mod.setText(_translate("MainWindow", "&Reset Velocity / Duration Mod."))
self.actionWiden_Score_View.setText(_translate("MainWindow", "&Widen Score View"))
self.actionWiden_Score_View.setShortcut(_translate("MainWindow", "Ctrl++"))
self.actionShrink_Score_View.setText(_translate("MainWindow", "Shr&ink Score View"))
self.actionShrink_Score_View.setShortcut(_translate("MainWindow", "Ctrl+-"))
self.actionData_Editor.setText(_translate("MainWindow", "&Track Editor"))
self.actionData_Editor.setShortcut(_translate("MainWindow", "Ctrl+T"))
self.actionClef.setText(_translate("MainWindow", "&Clef"))
self.actionClef.setShortcut(_translate("MainWindow", "C"))
self.actionMetrical_Instruction.setText(_translate("MainWindow", "&Metrical Instruction"))
self.actionMetrical_Instruction.setShortcut(_translate("MainWindow", "M"))
self.actionKey_Signature.setText(_translate("MainWindow", "&Key Signature"))
self.actionKey_Signature.setShortcut(_translate("MainWindow", "K"))
self.actionDynamics.setText(_translate("MainWindow", "&Dynamics"))
self.actionDynamics.setShortcut(_translate("MainWindow", "D"))
self.actionMulti_Measure_Rest.setText(_translate("MainWindow", "Multi Measure &Rest"))
self.actionMulti_Measure_Rest.setShortcut(_translate("MainWindow", "R"))
self.actionTemporary_Tempo_Change.setText(_translate("MainWindow", "Tem&porary Tempo Change"))
self.actionTemporary_Tempo_Change.setShortcut(_translate("MainWindow", "F"))
self.actionBeam.setText(_translate("MainWindow", "&Beam"))
self.actionBeam.setShortcut(_translate("MainWindow", "B"))
self.actionRemoveBeams.setText(_translate("MainWindow", "&Remove Beams"))
self.actionRemoveBeams.setShortcut(_translate("MainWindow", "Alt+B"))
self.actionTempo_Change.setText(_translate("MainWindow", "&Tempo Change"))
self.actionTempo_Change.setShortcut(_translate("MainWindow", "G"))
self.actionDelete_Tempo_Change.setText(_translate("MainWindow", "D&elete Tempo Change"))
self.actionDelete_Tempo_Change.setShortcut(_translate("MainWindow", "Alt+G"))
self.actionBlock_Mode.setText(_translate("MainWindow", "&Blocks Only"))
self.actionBlock_Mode.setShortcut(_translate("MainWindow", "F6"))
self.actionNotation_Mode.setText(_translate("MainWindow", "&Notation"))
self.actionNotation_Mode.setShortcut(_translate("MainWindow", "F5"))
self.actionTransposeChord.setText(_translate("MainWindow", "&Transpose Chord"))
self.actionTranspose_Score.setText(_translate("MainWindow", "&Transpose Score"))
self.actionSave.setText(_translate("MainWindow", "&Save"))
self.actionSave.setShortcut(_translate("MainWindow", "Ctrl+S"))
self.actionExport_File.setText(_translate("MainWindow", "Export File"))
self.actionImport_File_replaces_current.setText(_translate("MainWindow", "Import File (replaces current)"))
self.actionUnlink_Current_Block.setText(_translate("MainWindow", "&Unlink Current Block"))
self.actionDelete_All_Empty_Blocks.setText(_translate("MainWindow", "Delete All &Empty Blocks"))
self.actionBlockRight.setText(_translate("MainWindow", "blo&ckRight"))
self.actionBlockRight.setShortcut(_translate("MainWindow", "Ctrl+Alt+Right"))
self.actionBlockLeft.setText(_translate("MainWindow", "&blockLeft"))
self.actionBlockLeft.setShortcut(_translate("MainWindow", "Ctrl+Alt+Left"))
self.actionSelectBlockRight.setText(_translate("MainWindow", "&selectBlockRight"))
self.actionSelectBlockRight.setShortcut(_translate("MainWindow", "Ctrl+Alt+Shift+Right"))
self.actionSelectBlockLeft.setText(_translate("MainWindow", "s&electBlockLeft"))
self.actionSelectBlockLeft.setShortcut(_translate("MainWindow", "Ctrl+Alt+Shift+Left"))
self.actionPedalNotes.setText(_translate("MainWindow", "&Pedal Notes"))
self.actionReverse.setText(_translate("MainWindow", "&Reverse"))
self.actionDuplicateItem.setText(_translate("MainWindow", "Dup&licate"))
self.actionDuplicateItem.setShortcut(_translate("MainWindow", "Ctrl+D"))
self.actionRandom.setText(_translate("MainWindow", "&Shuffle"))
self.actionAscending.setText(_translate("MainWindow", "&Ascending"))
self.actionDescending.setText(_translate("MainWindow", "&Descending"))
self.actionMirror_around_Cursor.setText(_translate("MainWindow", "&Mirror around Cursor"))
self.actionInsert_Random.setText(_translate("MainWindow", "Insert Random"))
self.actionRandom_chromatic_in_clef_range.setText(_translate("MainWindow", "&Random chromatic in clef range"))
self.actionRandom_in_scale_in_clef_range.setText(_translate("MainWindow", "Random &in-scale in clef range"))
self.actionRandom_pitch_from_clipboard.setText(_translate("MainWindow", "Random pitch &from clipboard"))
self.actionProperties.setText(_translate("MainWindow", "Meta&data"))
self.actionExport_to_Ly.setText(_translate("MainWindow", "&Export to .ly file"))
self.actionShow_PDF.setText(_translate("MainWindow", "&Show PDF"))
self.actionShow_PDF.setShortcut(_translate("MainWindow", "Ctrl+P"))
self.actionExport_to_pdf_file.setText(_translate("MainWindow", "Export to .pdf file"))
self.actionInstrument_Change.setText(_translate("MainWindow", "&Instrument Change"))
self.actionProgram_Change_Relative.setText(_translate("MainWindow", "Program Change Relative"))
self.actionBank_Change_Absolute.setText(_translate("MainWindow", "Insert Bank Change"))
self.actionBank_Change_Relative.setText(_translate("MainWindow", "Bank Change Relative"))
self.actionChannel_Change.setText(_translate("MainWindow", "&Insert Channel Change "))
self.actionChannel_Change_Relative.setText(_translate("MainWindow", "Channel Change Relative"))
self.actionMIDI_Channel_Plus.setText(_translate("MainWindow", "&MIDI Channel +"))
self.actionMIDI_Channel_Minus.setText(_translate("MainWindow", "MIDI &Channel -"))
self.actionMIDI_Channel_Reset.setText(_translate("MainWindow", "MIDI C&hannel Reset"))
self.actionDelete_Current_Track.setText(_translate("MainWindow", "Delete Current Track"))
self.actionUse_Current_Track_as_Metronome.setText(_translate("MainWindow", "Use Current Track as &Metronome"))
self.actionUse_Current_Track_as_Metronome.setShortcut(_translate("MainWindow", "U"))
self.actionMetronome_Enabled.setText(_translate("MainWindow", "Metronome &Enabled"))
self.actionMetronome_Enabled.setShortcut(_translate("MainWindow", "Alt+U"))
self.actionRandom_in_scale_in_cursor_plus_octave.setText(_translate("MainWindow", "Random in-scale in cursor plus octave (authentic mode)"))
self.actionRandom_in_scale_in_octave_around_cursor.setText(_translate("MainWindow", "Random in-scale in octave around cursor (hypo mode)"))
self.actionCreate_pool_from_selection.setText(_translate("MainWindow", "Create pool from selection"))

1675
qtgui/designer/mainwindow.ui

File diff suppressed because it is too large

99
qtgui/designer/tickWidget.py

@ -0,0 +1,99 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'tickWidget.ui'
#
# Created by: PyQt5 UI code generator 5.7
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_tickWidget(object):
def setupUi(self, tickWidget):
tickWidget.setObjectName("tickWidget")
tickWidget.resize(453, 229)
self.D1 = QtWidgets.QPushButton(tickWidget)
self.D1.setGeometry(QtCore.QRect(10, 40, 80, 22))
self.D1.setObjectName("D1")
self.D2 = QtWidgets.QPushButton(tickWidget)
self.D2.setGeometry(QtCore.QRect(100, 40, 80, 22))
self.D2.setObjectName("D2")
self.D4 = QtWidgets.QPushButton(tickWidget)
self.D4.setGeometry(QtCore.QRect(190, 40, 80, 22))
self.D4.setObjectName("D4")
self.D8 = QtWidgets.QPushButton(tickWidget)
self.D8.setGeometry(QtCore.QRect(280, 40, 80, 22))
self.D8.setObjectName("D8")
self.D16 = QtWidgets.QPushButton(tickWidget)
self.D16.setGeometry(QtCore.QRect(370, 40, 80, 22))
self.D16.setObjectName("D16")
self.DB = QtWidgets.QPushButton(tickWidget)
self.DB.setGeometry(QtCore.QRect(10, 80, 80, 22))
self.DB.setObjectName("DB")
self.DL = QtWidgets.QPushButton(tickWidget)
self.DL.setGeometry(QtCore.QRect(100, 80, 80, 22))
self.DL.setObjectName("DL")
self.D32 = QtWidgets.QPushButton(tickWidget)
self.D32.setGeometry(QtCore.QRect(190, 80, 80, 22))
self.D32.setObjectName("D32")
self.D64 = QtWidgets.QPushButton(tickWidget)
self.D64.setGeometry(QtCore.QRect(280, 80, 80, 22))
self.D64.setObjectName("D64")
self.D128 = QtWidgets.QPushButton(tickWidget)
self.D128.setGeometry(QtCore.QRect(370, 80, 80, 22))
self.D128.setObjectName("D128")
self.ticks = QtWidgets.QSpinBox(tickWidget)
self.ticks.setGeometry(QtCore.QRect(160, 190, 161, 23))
self.ticks.setReadOnly(True)
self.ticks.setButtonSymbols(QtWidgets.QAbstractSpinBox.NoButtons)
self.ticks.setPrefix("")
self.ticks.setMinimum(0)
self.ticks.setMaximum(999999999)
self.ticks.setObjectName("ticks")
self.ok = QtWidgets.QPushButton(tickWidget)
self.ok.setGeometry(QtCore.QRect(60, 190, 80, 22))
self.ok.setObjectName("ok")
self.cancel = QtWidgets.QPushButton(tickWidget)
self.cancel.setGeometry(QtCore.QRect(340, 190, 80, 22))
self.cancel.setObjectName("cancel")
self.durationLabel = QtWidgets.QLabel(tickWidget)
self.durationLabel.setGeometry(QtCore.QRect(30, 150, 401, 31))
self.durationLabel.setAlignment(QtCore.Qt.AlignCenter)
self.durationLabel.setObjectName("durationLabel")
self.reset = QtWidgets.QPushButton(tickWidget)
self.reset.setGeometry(QtCore.QRect(190, 120, 80, 22))
self.reset.setObjectName("reset")
self.label = QtWidgets.QLabel(tickWidget)
self.label.setGeometry(QtCore.QRect(120, 10, 241, 20))
self.label.setObjectName("label")
self.retranslateUi(tickWidget)
QtCore.QMetaObject.connectSlotsByName(tickWidget)
def retranslateUi(self, tickWidget):
_translate = QtCore.QCoreApplication.translate
tickWidget.setWindowTitle(_translate("tickWidget", "Tick Calculator"))
self.D1.setText(_translate("tickWidget", "[1] D1"))
self.D1.setShortcut(_translate("tickWidget", "1"))
self.D2.setText(_translate("tickWidget", "[2] D2"))
self.D2.setShortcut(_translate("tickWidget", "2"))
self.D4.setText(_translate("tickWidget", "[3] D4"))
self.D4.setShortcut(_translate("tickWidget", "3"))
self.D8.setText(_translate("tickWidget", "[4] D8"))
self.D8.setShortcut(_translate("tickWidget", "4"))
self.D16.setText(_translate("tickWidget", "[5] D16"))
self.D16.setShortcut(_translate("tickWidget", "5"))
self.DB.setText(_translate("tickWidget", "DBrevis"))
self.DL.setText(_translate("tickWidget", "DLonga"))
self.D32.setText(_translate("tickWidget", "D32"))
self.D64.setText(_translate("tickWidget", "D64"))
self.D128.setText(_translate("tickWidget", "D128"))
self.ticks.setSuffix(_translate("tickWidget", " Ticks"))
self.ok.setText(_translate("tickWidget", "OK"))
self.ok.setShortcut(_translate("tickWidget", "Return"))
self.cancel.setText(_translate("tickWidget", "Cancel"))
self.cancel.setShortcut(_translate("tickWidget", "Esc"))
self.durationLabel.setText(_translate("tickWidget", "Simplest Duration"))
self.reset.setText(_translate("tickWidget", "Reset"))
self.label.setText(_translate("tickWidget", "Use buttons to add to total tick duration"))

266
qtgui/designer/tickWidget.ui

@ -0,0 +1,266 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>tickWidget</class>
<widget class="QWidget" name="tickWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>453</width>
<height>229</height>
</rect>
</property>
<property name="windowTitle">
<string>Tick Calculator</string>
</property>
<widget class="QPushButton" name="D1">
<property name="geometry">
<rect>
<x>10</x>
<y>40</y>
<width>80</width>
<height>22</height>
</rect>
</property>
<property name="text">
<string>[1] D1</string>
</property>
<property name="shortcut">
<string>1</string>
</property>
</widget>
<widget class="QPushButton" name="D2">
<property name="geometry">
<rect>
<x>100</x>
<y>40</y>
<width>80</width>
<height>22</height>
</rect>
</property>
<property name="text">
<string>[2] D2</string>
</property>
<property name="shortcut">
<string>2</string>
</property>
</widget>
<widget class="QPushButton" name="D4">
<property name="geometry">
<rect>
<x>190</x>
<y>40</y>
<width>80</width>
<height>22</height>
</rect>
</property>
<property name="text">
<string>[3] D4</string>
</property>
<property name="shortcut">
<string>3</string>
</property>
</widget>
<widget class="QPushButton" name="D8">
<property name="geometry">
<rect>
<x>280</x>
<y>40</y>
<width>80</width>
<height>22</height>
</rect>
</property>
<property name="text">
<string>[4] D8</string>
</property>
<property name="shortcut">
<string>4</string>
</property>
</widget>
<widget class="QPushButton" name="D16">
<property name="geometry">
<rect>
<x>370</x>
<y>40</y>
<width>80</width>
<height>22</height>
</rect>
</property>
<property name="text">
<string>[5] D16</string>
</property>
<property name="shortcut">
<string>5</string>
</property>
</widget>
<widget class="QPushButton" name="DB">
<property name="geometry">
<rect>
<x>10</x>
<y>80</y>
<width>80</width>
<height>22</height>
</rect>
</property>
<property name="text">
<string>DBrevis</string>
</property>
</widget>
<widget class="QPushButton" name="DL">
<property name="geometry">
<rect>
<x>100</x>
<y>80</y>
<width>80</width>
<height>22</height>
</rect>
</property>
<property name="text">
<string>DLonga</string>
</property>
</widget>
<widget class="QPushButton" name="D32">
<property name="geometry">
<rect>
<x>190</x>
<y>80</y>
<width>80</width>
<height>22</height>
</rect>
</property>
<property name="text">
<string>D32</string>
</property>
</widget>
<widget class="QPushButton" name="D64">
<property name="geometry">
<rect>
<x>280</x>
<y>80</y>
<width>80</width>
<height>22</height>
</rect>
</property>
<property name="text">
<string>D64</string>
</property>
</widget>
<widget class="QPushButton" name="D128">
<property name="geometry">
<rect>
<x>370</x>
<y>80</y>
<width>80</width>
<height>22</height>
</rect>
</property>
<property name="text">
<string>D128</string>
</property>
</widget>
<widget class="QSpinBox" name="ticks">
<property name="geometry">
<rect>
<x>160</x>
<y>190</y>
<width>161</width>
<height>23</height>
</rect>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
<property name="buttonSymbols">
<enum>QAbstractSpinBox::NoButtons</enum>
</property>
<property name="suffix">
<string> Ticks</string>
</property>
<property name="prefix">
<string/>
</property>
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>999999999</number>
</property>
</widget>
<widget class="QPushButton" name="ok">
<property name="geometry">
<rect>
<x>60</x>
<y>190</y>
<width>80</width>
<height>22</height>
</rect>
</property>
<property name="text">
<string>OK</string>
</property>
<property name="shortcut">
<string>Return</string>
</property>
</widget>
<widget class="QPushButton" name="cancel">
<property name="geometry">
<rect>
<x>340</x>
<y>190</y>
<width>80</width>
<height>22</height>
</rect>
</property>
<property name="text">
<string>Cancel</string>
</property>
<property name="shortcut">
<string>Esc</string>
</property>
</widget>
<widget class="QLabel" name="durationLabel">
<property name="geometry">
<rect>
<x>30</x>
<y>150</y>
<width>401</width>
<height>31</height>
</rect>
</property>
<property name="text">
<string>Simplest Duration</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
<widget class="QPushButton" name="reset">
<property name="geometry">
<rect>
<x>190</x>
<y>120</y>
<width>80</width>
<height>22</height>
</rect>
</property>
<property name="text">
<string>Reset</string>
</property>
</widget>
<widget class="QLabel" name="label">
<property name="geometry">
<rect>
<x>120</x>
<y>10</y>
<width>241</width>
<height>20</height>
</rect>
</property>
<property name="text">
<string>Use buttons to add to total tick duration</string>
</property>
</widget>
</widget>
<resources/>
<connections/>
</ui>

491
qtgui/designer/trackWidget.py

@ -0,0 +1,491 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'trackWidget.ui'
#
# Created by: PyQt5 UI code generator 5.9.2
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_trackGroupWidget(object):
def setupUi(self, trackGroupWidget):
trackGroupWidget.setObjectName("trackGroupWidget")
trackGroupWidget.resize(1374, 530)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(trackGroupWidget.sizePolicy().hasHeightForWidth())
trackGroupWidget.setSizePolicy(sizePolicy)
trackGroupWidget.setMaximumSize(QtCore.QSize(16777215, 900))
self.verticalLayout = QtWidgets.QVBoxLayout(trackGroupWidget)
self.verticalLayout.setContentsMargins(3, 3, 3, 3)
self.verticalLayout.setSpacing(3)
self.verticalLayout.setObjectName("verticalLayout")
self.track = QtWidgets.QWidget(trackGroupWidget)
self.track.setMaximumSize(QtCore.QSize(16777215, 45))
self.track.setObjectName("track")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.track)
self.horizontalLayout.setContentsMargins(3, 3, 3, 3)
self.horizontalLayout.setSpacing(3)
self.horizontalLayout.setObjectName("horizontalLayout")
self.nameLineEdit = QtWidgets.QLineEdit(self.track)
self.nameLineEdit.setEnabled(True)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.nameLineEdit.sizePolicy().hasHeightForWidth())
self.nameLineEdit.setSizePolicy(sizePolicy)
self.nameLineEdit.setMinimumSize(QtCore.QSize(200, 0))
self.nameLineEdit.setObjectName("nameLineEdit")
self.horizontalLayout.addWidget(self.nameLineEdit)
self.frame = QtWidgets.QFrame(self.track)
self.frame.setFrameShape(QtWidgets.QFrame.Box)
self.frame.setFrameShadow(QtWidgets.QFrame.Sunken)
self.frame.setObjectName("frame")
self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.frame)
self.horizontalLayout_3.setContentsMargins(3, 0, 3, 0)
self.horizontalLayout_3.setSpacing(0)
self.horizontalLayout_3.setObjectName("horizontalLayout_3")
self.upbeatSpinBox = QtWidgets.QSpinBox(self.frame)
self.upbeatSpinBox.setPrefix("")
self.upbeatSpinBox.setMaximum(999999999)
self.upbeatSpinBox.setObjectName("upbeatSpinBox")
self.horizontalLayout_3.addWidget(self.upbeatSpinBox)
self.callTickWidget = QtWidgets.QPushButton(self.frame)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.callTickWidget.sizePolicy().hasHeightForWidth())
self.callTickWidget.setSizePolicy(sizePolicy)
self.callTickWidget.setMaximumSize(QtCore.QSize(25, 16777215))
self.callTickWidget.setFlat(False)
self.callTickWidget.setObjectName("callTickWidget")
self.horizontalLayout_3.addWidget(self.callTickWidget)
self.horizontalLayout.addWidget(self.frame)
self.doubleTrackCheckbox = QtWidgets.QCheckBox(self.track)
self.doubleTrackCheckbox.setObjectName("doubleTrackCheckbox")
self.horizontalLayout.addWidget(self.doubleTrackCheckbox)
self.visibleCheckbox = QtWidgets.QCheckBox(self.track)
self.visibleCheckbox.setChecked(True)
self.visibleCheckbox.setObjectName("visibleCheckbox")
self.horizontalLayout.addWidget(self.visibleCheckbox)
self.frame_2 = QtWidgets.QFrame(self.track)
self.frame_2.setFrameShape(QtWidgets.QFrame.Box)
self.frame_2.setFrameShadow(QtWidgets.QFrame.Sunken)
self.frame_2.setObjectName("frame_2")
self.horizontalLayout_4 = QtWidgets.QHBoxLayout(self.frame_2)
self.horizontalLayout_4.setContentsMargins(3, 0, 3, 0)
self.horizontalLayout_4.setSpacing(3)
self.horizontalLayout_4.setObjectName("horizontalLayout_4")
self.midiChannelSpinBox = QtWidgets.QSpinBox(self.frame_2)
self.midiChannelSpinBox.setMaximum(15)
self.midiChannelSpinBox.setObjectName("midiChannelSpinBox")
self.horizontalLayout_4.addWidget(self.midiChannelSpinBox)
self.ccChannelsPushButton = QtWidgets.QPushButton(self.frame_2)
self.ccChannelsPushButton.setObjectName("ccChannelsPushButton")
self.horizontalLayout_4.addWidget(self.ccChannelsPushButton)
self.midiProgramSpinBox = QtWidgets.QSpinBox(self.frame_2)
self.midiProgramSpinBox.setMinimum(-1)
self.midiProgramSpinBox.setMaximum(127)
self.midiProgramSpinBox.setProperty("value", -1)
self.midiProgramSpinBox.setObjectName("midiProgramSpinBox")
self.horizontalLayout_4.addWidget(self.midiProgramSpinBox)
self.midiBankMsbSpinBox = QtWidgets.QSpinBox(self.frame_2)
self.midiBankMsbSpinBox.setEnabled(False)
self.midiBankMsbSpinBox.setMinimum(0)
self.midiBankMsbSpinBox.setMaximum(127)
self.midiBankMsbSpinBox.setProperty("value", 0)
self.midiBankMsbSpinBox.setObjectName("midiBankMsbSpinBox")
self.horizontalLayout_4.addWidget(self.midiBankMsbSpinBox)
self.midiTransposeSpinBox = QtWidgets.QSpinBox(self.frame_2)
self.midiTransposeSpinBox.setMinimum(-127)
self.midiTransposeSpinBox.setMaximum(128)
self.midiTransposeSpinBox.setObjectName("midiTransposeSpinBox")
self.horizontalLayout_4.addWidget(self.midiTransposeSpinBox)
self.midiBankLsbSpinBox = QtWidgets.QSpinBox(self.frame_2)
self.midiBankLsbSpinBox.setEnabled(False)
self.midiBankLsbSpinBox.setMinimum(0)
self.midiBankLsbSpinBox.setMaximum(127)
self.midiBankLsbSpinBox.setProperty("value", 0)
self.midiBankLsbSpinBox.setObjectName("midiBankLsbSpinBox")
self.horizontalLayout_4.addWidget(self.midiBankLsbSpinBox)
self.horizontalLayout.addWidget(self.frame_2)
self.deleteButton = QtWidgets.QPushButton(self.track)
self.deleteButton.setObjectName("deleteButton")
self.horizontalLayout.addWidget(self.deleteButton)
spacerItem = QtWidgets.QSpacerItem(640, 477, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.horizontalLayout.addItem(spacerItem)
self.verticalLayout.addWidget(self.track)
self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.label = QtWidgets.QLabel(trackGroupWidget)
self.label.setObjectName("label")
self.horizontalLayout_2.addWidget(self.label)
self.instrumentName = QtWidgets.QLineEdit(trackGroupWidget)
self.instrumentName.setMaxLength(32767)
self.instrumentName.setObjectName("instrumentName")
self.horizontalLayout_2.addWidget(self.instrumentName)
self.label_2 = QtWidgets.QLabel(trackGroupWidget)
self.label_2.setObjectName("label_2")
self.horizontalLayout_2.addWidget(self.label_2)
self.shortInstrumentName = QtWidgets.QLineEdit(trackGroupWidget)
self.shortInstrumentName.setMaxLength(5)
self.shortInstrumentName.setObjectName("shortInstrumentName")
self.horizontalLayout_2.addWidget(self.shortInstrumentName)
spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.horizontalLayout_2.addItem(spacerItem1)
self.verticalLayout.addLayout(self.horizontalLayout_2)
self.advanced = QtWidgets.QGroupBox(trackGroupWidget)
self.advanced.setCheckable(True)
self.advanced.setObjectName("advanced")
self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.advanced)
self.verticalLayout_2.setObjectName("verticalLayout_2")
self.advancedContent = QtWidgets.QTabWidget(self.advanced)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Maximum)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.advancedContent.sizePolicy().hasHeightForWidth())
self.advancedContent.setSizePolicy(sizePolicy)
self.advancedContent.setObjectName("advancedContent")
self.tab = QtWidgets.QWidget()
self.tab.setObjectName("tab")
self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.tab)
self.verticalLayout_4.setObjectName("verticalLayout_4")
self.widget_3 = QtWidgets.QWidget(self.tab)
self.widget_3.setObjectName("widget_3")
self.horizontalLayout_5 = QtWidgets.QHBoxLayout(self.widget_3)
self.horizontalLayout_5.setObjectName("horizontalLayout_5")
self.widget_2 = QtWidgets.QWidget(self.widget_3)
self.widget_2.setObjectName("widget_2")
self.formLayout_4 = QtWidgets.QFormLayout(self.widget_2)
self.formLayout_4.setObjectName("formLayout_4")
self.label_3 = QtWidgets.QLabel(self.widget_2)
self.label_3.setObjectName("label_3")
self.formLayout_4.setWidget(7, QtWidgets.QFormLayout.LabelRole, self.label_3)
self.defaultOn = QtWidgets.QLineEdit(self.widget_2)
self.defaultOn.setObjectName("defaultOn")
self.formLayout_4.setWidget(7, QtWidgets.QFormLayout.FieldRole, self.defaultOn)
self.label_4 = QtWidgets.QLabel(self.widget_2)
self.label_4.setObjectName("label_4")
self.formLayout_4.setWidget(8, QtWidgets.QFormLayout.LabelRole, self.label_4)
self.defaultOff = QtWidgets.QLineEdit(self.widget_2)
self.defaultOff.setObjectName("defaultOff")
self.formLayout_4.setWidget(8, QtWidgets.QFormLayout.FieldRole, self.defaultOff)
self.label_6 = QtWidgets.QLabel(self.widget_2)
self.label_6.setObjectName("label_6")
self.formLayout_4.setWidget(9, QtWidgets.QFormLayout.LabelRole, self.label_6)
self.staccatoOn = QtWidgets.QLineEdit(self.widget_2)
self.staccatoOn.setObjectName("staccatoOn")
self.formLayout_4.setWidget(9, QtWidgets.QFormLayout.FieldRole, self.staccatoOn)
self.label_5 = QtWidgets.QLabel(self.widget_2)
self.label_5.setObjectName("label_5")
self.formLayout_4.setWidget(10, QtWidgets.QFormLayout.LabelRole, self.label_5)
self.staccatoOff = QtWidgets.QLineEdit(self.widget_2)
self.staccatoOff.setObjectName("staccatoOff")
self.formLayout_4.setWidget(10, QtWidgets.QFormLayout.FieldRole, self.staccatoOff)
self.label_8 = QtWidgets.QLabel(self.widget_2)
self.label_8.setObjectName("label_8")
self.formLayout_4.setWidget(11, QtWidgets.QFormLayout.LabelRole, self.label_8)
self.tenutoOn = QtWidgets.QLineEdit(self.widget_2)
self.tenutoOn.setObjectName("tenutoOn")
self.formLayout_4.setWidget(11, QtWidgets.QFormLayout.FieldRole, self.tenutoOn)
self.label_9 = QtWidgets.QLabel(self.widget_2)
self.label_9.setObjectName("label_9")
self.formLayout_4.setWidget(12, QtWidgets.QFormLayout.LabelRole, self.label_9)
self.tenutoOff = QtWidgets.QLineEdit(self.widget_2)
self.tenutoOff.setObjectName("tenutoOff")
self.formLayout_4.setWidget(12, QtWidgets.QFormLayout.FieldRole, self.tenutoOff)
self.label_10 = QtWidgets.QLabel(self.widget_2)
self.label_10.setObjectName("label_10")
self.formLayout_4.setWidget(13, QtWidgets.QFormLayout.LabelRole, self.label_10)
self.legatoOn = QtWidgets.QLineEdit(self.widget_2)
self.legatoOn.setObjectName("legatoOn")
self.formLayout_4.setWidget(13, QtWidgets.QFormLayout.FieldRole, self.legatoOn)
self.label_7 = QtWidgets.QLabel(self.widget_2)
self.label_7.setObjectName("label_7")
self.formLayout_4.setWidget(14, QtWidgets.QFormLayout.LabelRole, self.label_7)
self.legatoOff = QtWidgets.QLineEdit(self.widget_2)
self.legatoOff.setObjectName("legatoOff")
self.formLayout_4.setWidget(14, QtWidgets.QFormLayout.FieldRole, self.legatoOff)
self.horizontalLayout_5.addWidget(self.widget_2)
spacerItem2 = QtWidgets.QSpacerItem(643, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.horizontalLayout_5.addItem(spacerItem2)
self.verticalLayout_4.addWidget(self.widget_3)
self.buttonResetDurations = QtWidgets.QPushButton(self.tab)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.buttonResetDurations.sizePolicy().hasHeightForWidth())
self.buttonResetDurations.setSizePolicy(sizePolicy)
self.buttonResetDurations.setObjectName("buttonResetDurations")
self.verticalLayout_4.addWidget(self.buttonResetDurations)
self.advancedContent.addTab(self.tab, "")
self.tab_2 = QtWidgets.QWidget()
self.tab_2.setObjectName("tab_2")
self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.tab_2)
self.verticalLayout_3.setObjectName("verticalLayout_3")
self.widget = QtWidgets.QWidget(self.tab_2)
self.widget.setObjectName("widget")
self.horizontalLayout_6 = QtWidgets.QHBoxLayout(self.widget)
self.horizontalLayout_6.setObjectName("horizontalLayout_6")
self.widget_4 = QtWidgets.QWidget(self.widget)
self.widget_4.setObjectName("widget_4")
self.formLayout = QtWidgets.QFormLayout(self.widget_4)
self.formLayout.setObjectName("formLayout")
self.label_11 = QtWidgets.QLabel(self.widget_4)
self.label_11.setObjectName("label_11")
self.formLayout.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.label_11)
self.dynamics_ppppp = QtWidgets.QSpinBox(self.widget_4)
self.dynamics_ppppp.setMaximum(127)
self.dynamics_ppppp.setObjectName("dynamics_ppppp")
self.formLayout.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.dynamics_ppppp)
self.label_13 = QtWidgets.QLabel(self.widget_4)
self.label_13.setObjectName("label_13")
self.formLayout.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.label_13)
self.dynamics_pppp = QtWidgets.QSpinBox(self.widget_4)
self.dynamics_pppp.setMaximum(127)
self.dynamics_pppp.setObjectName("dynamics_pppp")
self.formLayout.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.dynamics_pppp)
self.label_29 = QtWidgets.QLabel(self.widget_4)
self.label_29.setObjectName("label_29")
self.formLayout.setWidget(2, QtWidgets.QFormLayout.LabelRole, self.label_29)
self.dynamics_ppp = QtWidgets.QSpinBox(self.widget_4)
self.dynamics_ppp.setObjectName("dynamics_ppp")
self.formLayout.setWidget(2, QtWidgets.QFormLayout.FieldRole, self.dynamics_ppp)
self.label_14 = QtWidgets.QLabel(self.widget_4)
self.label_14.setObjectName("label_14")
self.formLayout.setWidget(3, QtWidgets.QFormLayout.LabelRole, self.label_14)
self.dynamics_pp = QtWidgets.QSpinBox(self.widget_4)
self.dynamics_pp.setMaximum(127)
self.dynamics_pp.setObjectName("dynamics_pp")
self.formLayout.setWidget(3, QtWidgets.QFormLayout.FieldRole, self.dynamics_pp)
self.label_15 = QtWidgets.QLabel(self.widget_4)
self.label_15.setObjectName("label_15")
self.formLayout.setWidget(4, QtWidgets.QFormLayout.LabelRole, self.label_15)
self.dynamics_p = QtWidgets.QSpinBox(self.widget_4)
self.dynamics_p.setMaximum(127)
self.dynamics_p.setObjectName("dynamics_p")
self.formLayout.setWidget(4, QtWidgets.QFormLayout.FieldRole, self.dynamics_p)
self.label_16 = QtWidgets.QLabel(self.widget_4)
self.label_16.setObjectName("label_16")
self.formLayout.setWidget(5, QtWidgets.QFormLayout.LabelRole, self.label_16)
self.dynamics_mp = QtWidgets.QSpinBox(self.widget_4)
self.dynamics_mp.setMaximum(127)
self.dynamics_mp.setObjectName("dynamics_mp")
self.formLayout.setWidget(5, QtWidgets.QFormLayout.FieldRole, self.dynamics_mp)
self.horizontalLayout_6.addWidget(self.widget_4)
self.widgetLeft = QtWidgets.QWidget(self.widget)
self.widgetLeft.setObjectName("widgetLeft")
self.formLayout_2 = QtWidgets.QFormLayout(self.widgetLeft)
self.formLayout_2.setObjectName("formLayout_2")
self.label_17 = QtWidgets.QLabel(self.widgetLeft)
self.label_17.setObjectName("label_17")
self.formLayout_2.setWidget(2, QtWidgets.QFormLayout.LabelRole, self.label_17)
self.dynamics_mf = QtWidgets.QSpinBox(self.widgetLeft)
self.dynamics_mf.setMaximum(127)
self.dynamics_mf.setObjectName("dynamics_mf")
self.formLayout_2.setWidget(2, QtWidgets.QFormLayout.FieldRole, self.dynamics_mf)
self.label_18 = QtWidgets.QLabel(self.widgetLeft)
self.label_18.setObjectName("label_18")
self.formLayout_2.setWidget(5, QtWidgets.QFormLayout.LabelRole, self.label_18)
self.dynamics_f = QtWidgets.QSpinBox(self.widgetLeft)
self.dynamics_f.setMaximum(127)
self.dynamics_f.setObjectName("dynamics_f")
self.formLayout_2.setWidget(5, QtWidgets.QFormLayout.FieldRole, self.dynamics_f)
self.label_19 = QtWidgets.QLabel(self.widgetLeft)
self.label_19.setObjectName("label_19")
self.formLayout_2.setWidget(8, QtWidgets.QFormLayout.LabelRole, self.label_19)
self.dynamics_ff = QtWidgets.QSpinBox(self.widgetLeft)
self.dynamics_ff.setMaximum(127)
self.dynamics_ff.setObjectName("dynamics_ff")
self.formLayout_2.setWidget(8, QtWidgets.QFormLayout.FieldRole, self.dynamics_ff)
self.label_20 = QtWidgets.QLabel(self.widgetLeft)
self.label_20.setObjectName("label_20")
self.formLayout_2.setWidget(9, QtWidgets.QFormLayout.LabelRole, self.label_20)
self.dynamics_fff = QtWidgets.QSpinBox(self.widgetLeft)
self.dynamics_fff.setMaximum(127)
self.dynamics_fff.setObjectName("dynamics_fff")
self.formLayout_2.setWidget(9, QtWidgets.QFormLayout.FieldRole, self.dynamics_fff)
self.label_21 = QtWidgets.QLabel(self.widgetLeft)
self.label_21.setObjectName("label_21")
self.formLayout_2.setWidget(10, QtWidgets.QFormLayout.LabelRole, self.label_21)
self.dynamics_ffff = QtWidgets.QSpinBox(self.widgetLeft)
self.dynamics_ffff.setMaximum(127)
self.dynamics_ffff.setObjectName("dynamics_ffff")
self.formLayout_2.setWidget(10, QtWidgets.QFormLayout.FieldRole, self.dynamics_ffff)
self.horizontalLayout_6.addWidget(self.widgetLeft)
self.widgetRight = QtWidgets.QWidget(self.widget)
self.widgetRight.setObjectName("widgetRight")
self.formLayout_3 = QtWidgets.QFormLayout(self.widgetRight)
self.formLayout_3.setObjectName("formLayout_3")
self.label_12 = QtWidgets.QLabel(self.widgetRight)
self.label_12.setObjectName("label_12")
self.formLayout_3.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.label_12)
self.dynamics_tacet = QtWidgets.QSpinBox(self.widgetRight)
self.dynamics_tacet.setMaximum(127)
self.dynamics_tacet.setObjectName("dynamics_tacet")
self.formLayout_3.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.dynamics_tacet)
self.label_22 = QtWidgets.QLabel(self.widgetRight)
self.label_22.setObjectName("label_22")
self.formLayout_3.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.label_22)
self.dynamics_custom = QtWidgets.QSpinBox(self.widgetRight)
self.dynamics_custom.setMaximum(127)
self.dynamics_custom.setObjectName("dynamics_custom")
self.formLayout_3.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.dynamics_custom)
self.label_23 = QtWidgets.QLabel(self.widgetRight)
self.label_23.setObjectName("label_23")
self.formLayout_3.setWidget(2, QtWidgets.QFormLayout.LabelRole, self.label_23)
self.dynamics_sfz = QtWidgets.QSpinBox(self.widgetRight)
self.dynamics_sfz.setMaximum(127)
self.dynamics_sfz.setObjectName("dynamics_sfz")
self.formLayout_3.setWidget(2, QtWidgets.QFormLayout.FieldRole, self.dynamics_sfz)
self.label_24 = QtWidgets.QLabel(self.widgetRight)
self.label_24.setObjectName("label_24")
self.formLayout_3.setWidget(3, QtWidgets.QFormLayout.LabelRole, self.label_24)
self.dynamics_sf = QtWidgets.QSpinBox(self.widgetRight)
self.dynamics_sf.setMaximum(127)
self.dynamics_sf.setObjectName("dynamics_sf")
self.formLayout_3.setWidget(3, QtWidgets.QFormLayout.FieldRole, self.dynamics_sf)
self.label_25 = QtWidgets.QLabel(self.widgetRight)
self.label_25.setObjectName("label_25")
self.formLayout_3.setWidget(4, QtWidgets.QFormLayout.LabelRole, self.label_25)
self.dynamics_sff = QtWidgets.QSpinBox(self.widgetRight)
self.dynamics_sff.setMaximum(127)
self.dynamics_sff.setObjectName("dynamics_sff")
self.formLayout_3.setWidget(4, QtWidgets.QFormLayout.FieldRole, self.dynamics_sff)
self.label_26 = QtWidgets.QLabel(self.widgetRight)
self.label_26.setObjectName("label_26")
self.formLayout_3.setWidget(6, QtWidgets.QFormLayout.LabelRole, self.label_26)
self.dynamics_fp = QtWidgets.QSpinBox(self.widgetRight)
self.dynamics_fp.setMaximum(127)
self.dynamics_fp.setObjectName("dynamics_fp")
self.formLayout_3.setWidget(6, QtWidgets.QFormLayout.FieldRole, self.dynamics_fp)
self.label_27 = QtWidgets.QLabel(self.widgetRight)
self.label_27.setObjectName("label_27")
self.formLayout_3.setWidget(7, QtWidgets.QFormLayout.LabelRole, self.label_27)
self.dynamics_sp = QtWidgets.QSpinBox(self.widgetRight)
self.dynamics_sp.setMaximum(127)
self.dynamics_sp.setObjectName("dynamics_sp")
self.formLayout_3.setWidget(7, QtWidgets.QFormLayout.FieldRole, self.dynamics_sp)
self.label_28 = QtWidgets.QLabel(self.widgetRight)
self.label_28.setObjectName("label_28")
self.formLayout_3.setWidget(8, QtWidgets.QFormLayout.LabelRole, self.label_28)
self.dynamics_spp = QtWidgets.QSpinBox(self.widgetRight)
self.dynamics_spp.setMaximum(127)
self.dynamics_spp.setObjectName("dynamics_spp")
self.formLayout_3.setWidget(8, QtWidgets.QFormLayout.FieldRole, self.dynamics_spp)
self.horizontalLayout_6.addWidget(self.widgetRight)
spacerItem3 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.horizontalLayout_6.addItem(spacerItem3)
self.verticalLayout_3.addWidget(self.widget)
self.buttonResetDynamics = QtWidgets.QPushButton(self.tab_2)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.buttonResetDynamics.sizePolicy().hasHeightForWidth())
self.buttonResetDynamics.setSizePolicy(sizePolicy)
self.buttonResetDynamics.setObjectName("buttonResetDynamics")
self.verticalLayout_3.addWidget(self.buttonResetDynamics)
self.advancedContent.addTab(self.tab_2, "")
self.verticalLayout_2.addWidget(self.advancedContent)
self.verticalLayout.addWidget(self.advanced)
self.retranslateUi(trackGroupWidget)
self.advancedContent.setCurrentIndex(0)
QtCore.QMetaObject.connectSlotsByName(trackGroupWidget)
trackGroupWidget.setTabOrder(self.nameLineEdit, self.upbeatSpinBox)
trackGroupWidget.setTabOrder(self.upbeatSpinBox, self.callTickWidget)
trackGroupWidget.setTabOrder(self.callTickWidget, self.doubleTrackCheckbox)
trackGroupWidget.setTabOrder(self.doubleTrackCheckbox, self.visibleCheckbox)
trackGroupWidget.setTabOrder(self.visibleCheckbox, self.midiChannelSpinBox)
trackGroupWidget.setTabOrder(self.midiChannelSpinBox, self.ccChannelsPushButton)
trackGroupWidget.setTabOrder(self.ccChannelsPushButton, self.midiProgramSpinBox)
trackGroupWidget.setTabOrder(self.midiProgramSpinBox, self.midiBankMsbSpinBox)
trackGroupWidget.setTabOrder(self.midiBankMsbSpinBox, self.midiTransposeSpinBox)
trackGroupWidget.setTabOrder(self.midiTransposeSpinBox, self.midiBankLsbSpinBox)
trackGroupWidget.setTabOrder(self.midiBankLsbSpinBox, self.deleteButton)
trackGroupWidget.setTabOrder(self.deleteButton, self.instrumentName)
trackGroupWidget.setTabOrder(self.instrumentName, self.shortInstrumentName)
trackGroupWidget.setTabOrder(self.shortInstrumentName, self.advanced)
trackGroupWidget.setTabOrder(self.advanced, self.advancedContent)
trackGroupWidget.setTabOrder(self.advancedContent, self.defaultOn)
trackGroupWidget.setTabOrder(self.defaultOn, self.defaultOff)
trackGroupWidget.setTabOrder(self.defaultOff, self.staccatoOn)
trackGroupWidget.setTabOrder(self.staccatoOn, self.staccatoOff)
trackGroupWidget.setTabOrder(self.staccatoOff, self.tenutoOn)
trackGroupWidget.setTabOrder(self.tenutoOn, self.tenutoOff)
trackGroupWidget.setTabOrder(self.tenutoOff, self.legatoOn)
trackGroupWidget.setTabOrder(self.legatoOn, self.legatoOff)
trackGroupWidget.setTabOrder(self.legatoOff, self.buttonResetDurations)
trackGroupWidget.setTabOrder(self.buttonResetDurations, self.dynamics_ppppp)
trackGroupWidget.setTabOrder(self.dynamics_ppppp, self.dynamics_pppp)
trackGroupWidget.setTabOrder(self.dynamics_pppp, self.dynamics_ppp)
trackGroupWidget.setTabOrder(self.dynamics_ppp, self.dynamics_pp)
trackGroupWidget.setTabOrder(self.dynamics_pp, self.dynamics_p)
trackGroupWidget.setTabOrder(self.dynamics_p, self.dynamics_mp)
trackGroupWidget.setTabOrder(self.dynamics_mp, self.dynamics_mf)
trackGroupWidget.setTabOrder(self.dynamics_mf, self.dynamics_f)
trackGroupWidget.setTabOrder(self.dynamics_f, self.dynamics_ff)
trackGroupWidget.setTabOrder(self.dynamics_ff, self.dynamics_fff)
trackGroupWidget.setTabOrder(self.dynamics_fff, self.dynamics_ffff)
trackGroupWidget.setTabOrder(self.dynamics_ffff, self.dynamics_tacet)
trackGroupWidget.setTabOrder(self.dynamics_tacet, self.dynamics_custom)
trackGroupWidget.setTabOrder(self.dynamics_custom, self.dynamics_sfz)
trackGroupWidget.setTabOrder(self.dynamics_sfz, self.dynamics_sf)
trackGroupWidget.setTabOrder(self.dynamics_sf, self.dynamics_sff)
trackGroupWidget.setTabOrder(self.dynamics_sff, self.dynamics_fp)
trackGroupWidget.setTabOrder(self.dynamics_fp, self.dynamics_sp)
trackGroupWidget.setTabOrder(self.dynamics_sp, self.dynamics_spp)
trackGroupWidget.setTabOrder(self.dynamics_spp, self.buttonResetDynamics)
def retranslateUi(self, trackGroupWidget):
_translate = QtCore.QCoreApplication.translate
trackGroupWidget.setWindowTitle(_translate("trackGroupWidget", "GroupBox"))
trackGroupWidget.setTitle(_translate("trackGroupWidget", "GroupBox"))
self.upbeatSpinBox.setSuffix(_translate("trackGroupWidget", " Upbeat Ticks"))
self.callTickWidget.setText(_translate("trackGroupWidget", "𝅘𝅥𝅮 "))
self.doubleTrackCheckbox.setText(_translate("trackGroupWidget", "Double Track"))
self.visibleCheckbox.setText(_translate("trackGroupWidget", "Visible"))
self.midiChannelSpinBox.setPrefix(_translate("trackGroupWidget", "Channel "))
self.ccChannelsPushButton.setText(_translate("trackGroupWidget", "CC Channels"))
self.midiProgramSpinBox.setPrefix(_translate("trackGroupWidget", "Program "))
self.midiBankMsbSpinBox.setPrefix(_translate("trackGroupWidget", "Bank MSB"))
self.midiTransposeSpinBox.setPrefix(_translate("trackGroupWidget", "Transpose "))
self.midiBankLsbSpinBox.setPrefix(_translate("trackGroupWidget", "Bank LSB"))
self.deleteButton.setText(_translate("trackGroupWidget", "Delete"))
self.label.setText(_translate("trackGroupWidget", "Instrument Name"))
self.label_2.setText(_translate("trackGroupWidget", "Short Instrument Name"))
self.advanced.setTitle(_translate("trackGroupWidget", "Advanced"))
self.label_3.setText(_translate("trackGroupWidget", "Derfault On"))
self.label_4.setText(_translate("trackGroupWidget", "Default Off"))
self.label_6.setText(_translate("trackGroupWidget", "Staccato On"))
self.label_5.setText(_translate("trackGroupWidget", "Staccato Off"))
self.label_8.setText(_translate("trackGroupWidget", "Tenuto On"))
self.label_9.setText(_translate("trackGroupWidget", "Tenuto Off"))
self.label_10.setText(_translate("trackGroupWidget", "Legato On"))
self.label_7.setText(_translate("trackGroupWidget", "Legato Off"))
self.buttonResetDurations.setText(_translate("trackGroupWidget", "Reset to Default Duration Values"))
self.advancedContent.setTabText(self.advancedContent.indexOf(self.tab), _translate("trackGroupWidget", "Duration Offsets"))
self.label_11.setText(_translate("trackGroupWidget", "ppppp"))
self.label_13.setText(_translate("trackGroupWidget", "pppp"))
self.label_29.setText(_translate("trackGroupWidget", "ppp"))
self.label_14.setText(_translate("trackGroupWidget", "pp"))
self.label_15.setText(_translate("trackGroupWidget", "p"))
self.label_16.setText(_translate("trackGroupWidget", "mp"))
self.label_17.setText(_translate("trackGroupWidget", "mf"))
self.label_18.setText(_translate("trackGroupWidget", "f"))
self.label_19.setText(_translate("trackGroupWidget", "ff"))
self.label_20.setText(_translate("trackGroupWidget", "fff"))
self.label_21.setText(_translate("trackGroupWidget", "ffff"))
self.label_12.setText(_translate("trackGroupWidget", "tacet"))
self.label_22.setText(_translate("trackGroupWidget", "custom"))
self.label_23.setText(_translate("trackGroupWidget", "sfz"))
self.label_24.setText(_translate("trackGroupWidget", "sf"))
self.label_25.setText(_translate("trackGroupWidget", "sff"))
self.label_26.setText(_translate("trackGroupWidget", "fp"))
self.label_27.setText(_translate("trackGroupWidget", "sp"))
self.label_28.setText(_translate("trackGroupWidget", "spp"))
self.buttonResetDynamics.setText(_translate("trackGroupWidget", "Reset to Default Dynamic Values"))
self.advancedContent.setTabText(self.advancedContent.indexOf(self.tab_2), _translate("trackGroupWidget", "Dynamic Signature Definitions"))

868
qtgui/designer/trackWidget.ui

@ -0,0 +1,868 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>trackGroupWidget</class>
<widget class="QGroupBox" name="trackGroupWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1374</width>
<height>530</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>900</height>
</size>
</property>
<property name="windowTitle">
<string>GroupBox</string>
</property>
<property name="title">
<string>GroupBox</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>3</number>
</property>
<property name="leftMargin">
<number>3</number>
</property>
<property name="topMargin">
<number>3</number>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>3</number>
</property>
<item>
<widget class="QWidget" name="track" native="true">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>45</height>
</size>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
<number>3</number>
</property>
<property name="leftMargin">
<number>3</number>
</property>
<property name="topMargin">
<number>3</number>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>3</number>
</property>
<item>
<widget class="QLineEdit" name="nameLineEdit">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>200</width>
<height>0</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::Box</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>3</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QSpinBox" name="upbeatSpinBox">
<property name="suffix">
<string> Upbeat Ticks</string>
</property>
<property name="prefix">
<string/>
</property>
<property name="maximum">
<number>999999999</number>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="callTickWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>25</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>𝅘𝅥𝅮 </string>
</property>
<property name="flat">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QCheckBox" name="doubleTrackCheckbox">
<property name="text">
<string>Double Track</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="visibleCheckbox">
<property name="text">
<string>Visible</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QFrame" name="frame_2">
<property name="frameShape">
<enum>QFrame::Box</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<property name="spacing">
<number>3</number>
</property>
<property name="leftMargin">
<number>3</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QSpinBox" name="midiChannelSpinBox">
<property name="prefix">
<string>Channel </string>
</property>
<property name="maximum">
<number>15</number>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="ccChannelsPushButton">
<property name="text">
<string>CC Channels</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="midiProgramSpinBox">
<property name="prefix">
<string>Program </string>
</property>
<property name="minimum">
<number>-1</number>
</property>
<property name="maximum">
<number>127</number>
</property>
<property name="value">
<number>-1</number>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="midiBankMsbSpinBox">
<property name="enabled">
<bool>false</bool>
</property>
<property name="prefix">
<string>Bank MSB</string>
</property>
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>127</number>
</property>
<property name="value">
<number>0</number>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="midiTransposeSpinBox">
<property name="prefix">
<string>Transpose </string>
</property>
<property name="minimum">
<number>-127</number>
</property>
<property name="maximum">
<number>128</number>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="midiBankLsbSpinBox">
<property name="enabled">
<bool>false</bool>
</property>
<property name="prefix">
<string>Bank LSB</string>
</property>
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>127</number>
</property>
<property name="value">
<number>0</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QPushButton" name="deleteButton">
<property name="text">
<string>Delete</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>640</width>
<height>477</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Instrument Name</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="instrumentName">
<property name="maxLength">
<number>32767</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Short Instrument Name</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="shortInstrumentName">
<property name="maxLength">
<number>5</number>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QGroupBox" name="advanced">
<property name="title">
<string>Advanced</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QTabWidget" name="advancedContent">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="tab">
<attribute name="title">
<string>Duration Offsets</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QWidget" name="widget_3" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<widget class="QWidget" name="widget_2" native="true">
<layout class="QFormLayout" name="formLayout_4">
<item row="7" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Derfault On</string>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QLineEdit" name="defaultOn"/>
</item>
<item row="8" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Default Off</string>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QLineEdit" name="defaultOff"/>
</item>
<item row="9" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Staccato On</string>
</property>
</widget>
</item>
<item row="9" column="1">
<widget class="QLineEdit" name="staccatoOn"/>
</item>
<item row="10" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Staccato Off</string>
</property>
</widget>
</item>
<item row="10" column="1">
<widget class="QLineEdit" name="staccatoOff"/>
</item>
<item row="11" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Tenuto On</string>
</property>
</widget>
</item>
<item row="11" column="1">
<widget class="QLineEdit" name="tenutoOn"/>
</item>
<item row="12" column="0">
<widget class="QLabel" name="label_9">
<property name="text">
<string>Tenuto Off</string>
</property>
</widget>
</item>
<item row="12" column="1">
<widget class="QLineEdit" name="tenutoOff"/>
</item>
<item row="13" column="0">
<widget class="QLabel" name="label_10">
<property name="text">
<string>Legato On</string>
</property>
</widget>
</item>
<item row="13" column="1">
<widget class="QLineEdit" name="legatoOn"/>
</item>
<item row="14" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Legato Off</string>
</property>
</widget>
</item>
<item row="14" column="1">
<widget class="QLineEdit" name="legatoOff"/>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>643</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QPushButton" name="buttonResetDurations">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Reset to Default Duration Values</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_2">
<attribute name="title">
<string>Dynamic Signature Definitions</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QWidget" name="widget" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_6">
<item>
<widget class="QWidget" name="widget_4" native="true">
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="label_11">
<property name="text">
<string>ppppp</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSpinBox" name="dynamics_ppppp">
<property name="maximum">
<number>127</number>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_13">
<property name="text">
<string>pppp</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="dynamics_pppp">
<property name="maximum">
<number>127</number>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_29">
<property name="text">
<string>ppp</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QSpinBox" name="dynamics_ppp"/>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_14">
<property name="text">
<string>pp</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QSpinBox" name="dynamics_pp">
<property name="maximum">
<number>127</number>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_15">
<property name="text">
<string>p</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QSpinBox" name="dynamics_p">
<property name="maximum">
<number>127</number>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_16">
<property name="text">
<string>mp</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QSpinBox" name="dynamics_mp">
<property name="maximum">
<number>127</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QWidget" name="widgetLeft" native="true">
<layout class="QFormLayout" name="formLayout_2">
<item row="2" column="0">
<widget class="QLabel" name="label_17">
<property name="text">
<string>mf</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QSpinBox" name="dynamics_mf">
<property name="maximum">
<number>127</number>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_18">
<property name="text">
<string>f</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QSpinBox" name="dynamics_f">
<property name="maximum">
<number>127</number>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QLabel" name="label_19">
<property name="text">
<string>ff</string>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QSpinBox" name="dynamics_ff">
<property name="maximum">
<number>127</number>
</property>
</widget>
</item>
<item row="9" column="0">
<widget class="QLabel" name="label_20">
<property name="text">
<string>fff</string>
</property>
</widget>
</item>
<item row="9" column="1">
<widget class="QSpinBox" name="dynamics_fff">
<property name="maximum">
<number>127</number>
</property>
</widget>
</item>
<item row="10" column="0">
<widget class="QLabel" name="label_21">
<property name="text">
<string>ffff</string>
</property>
</widget>
</item>
<item row="10" column="1">
<widget class="QSpinBox" name="dynamics_ffff">
<property name="maximum">
<number>127</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QWidget" name="widgetRight" native="true">
<layout class="QFormLayout" name="formLayout_3">
<item row="0" column="0">
<widget class="QLabel" name="label_12">
<property name="text">
<string>tacet</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSpinBox" name="dynamics_tacet">
<property name="maximum">
<number>127</number>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_22">
<property name="text">
<string>custom</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="dynamics_custom">
<property name="maximum">
<number>127</number>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_23">
<property name="text">
<string>sfz</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QSpinBox" name="dynamics_sfz">
<property name="maximum">
<number>127</number>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_24">
<property name="text">
<string>sf</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QSpinBox" name="dynamics_sf">
<property name="maximum">
<number>127</number>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_25">
<property name="text">
<string>sff</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QSpinBox" name="dynamics_sff">
<property name="maximum">
<number>127</number>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_26">
<property name="text">
<string>fp</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QSpinBox" name="dynamics_fp">
<property name="maximum">
<number>127</number>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="label_27">
<property name="text">
<string>sp</string>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QSpinBox" name="dynamics_sp">
<property name="maximum">
<number>127</number>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QLabel" name="label_28">
<property name="text">
<string>spp</string>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QSpinBox" name="dynamics_spp">
<property name="maximum">
<number>127</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QPushButton" name="buttonResetDynamics">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Reset to Default Dynamic Values</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>nameLineEdit</tabstop>
<tabstop>upbeatSpinBox</tabstop>
<tabstop>callTickWidget</tabstop>
<tabstop>doubleTrackCheckbox</tabstop>
<tabstop>visibleCheckbox</tabstop>
<tabstop>midiChannelSpinBox</tabstop>
<tabstop>ccChannelsPushButton</tabstop>
<tabstop>midiProgramSpinBox</tabstop>
<tabstop>midiBankMsbSpinBox</tabstop>
<tabstop>midiTransposeSpinBox</tabstop>
<tabstop>midiBankLsbSpinBox</tabstop>
<tabstop>deleteButton</tabstop>
<tabstop>instrumentName</tabstop>
<tabstop>shortInstrumentName</tabstop>
<tabstop>advanced</tabstop>
<tabstop>advancedContent</tabstop>
<tabstop>defaultOn</tabstop>
<tabstop>defaultOff</tabstop>
<tabstop>staccatoOn</tabstop>
<tabstop>staccatoOff</tabstop>
<tabstop>tenutoOn</tabstop>
<tabstop>tenutoOff</tabstop>
<tabstop>legatoOn</tabstop>
<tabstop>legatoOff</tabstop>
<tabstop>buttonResetDurations</tabstop>
<tabstop>dynamics_ppppp</tabstop>
<tabstop>dynamics_pppp</tabstop>
<tabstop>dynamics_ppp</tabstop>
<tabstop>dynamics_pp</tabstop>
<tabstop>dynamics_p</tabstop>
<tabstop>dynamics_mp</tabstop>
<tabstop>dynamics_mf</tabstop>
<tabstop>dynamics_f</tabstop>
<tabstop>dynamics_ff</tabstop>
<tabstop>dynamics_fff</tabstop>
<tabstop>dynamics_ffff</tabstop>
<tabstop>dynamics_tacet</tabstop>
<tabstop>dynamics_custom</tabstop>
<tabstop>dynamics_sfz</tabstop>
<tabstop>dynamics_sf</tabstop>
<tabstop>dynamics_sff</tabstop>
<tabstop>dynamics_fp</tabstop>
<tabstop>dynamics_sp</tabstop>
<tabstop>dynamics_spp</tabstop>
<tabstop>buttonResetDynamics</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>

571
qtgui/graphs.py

@ -0,0 +1,571 @@
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Copyright 2017, Nils Hilbricht, Germany ( https://www.hilbricht.net )
This file is part of Laborejo ( https://www.laborejo.org )
Laborejo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from PyQt5 import QtCore, QtGui, QtSvg, QtWidgets
from .constantsAndConfigs import constantsAndConfigs
from template.qtgui.helper import stringToColor, removeInstancesFromScene, callContextMenu, stretchLine, stretchRect
import engine.api as api
class CCPath(QtWidgets.QGraphicsRectItem):
"""
A CCPath only exists when the backend track has a cc-part activated.
Since each track has 128 potential CC paths we don't create and
save a bunch of empty ones, neither in the backend nor here.
Therefore: you cannot display a message "click here to create
a CC track/block" here in the CC Path since the CCPath does not
exist at this point in time. Thus this button is created in the track. One button for all CCs.
There are two item types. Movable, or handle-points,
and non-movable: interpolation-points.
The backend only knows handle points and a function which
interpolates until the next point.
However, that results only in CC values 0-128 anyway. So
we use these directly.
We don't lie to the user. There is no smooth curve, not even
a linear one, between CC values 65 and 66. It is just a step.
So we show the steps."""
def __init__(self, parentGuiTrack, parentDataTrackId):
super().__init__(0, 0, 0, 0)
self.setAcceptHoverEvents(True)
#self.setFlags(QtWidgets.QGraphicsItem.ItemIsMovable|QtWidgets.QGraphicsItem.ItemSendsGeometryChanges|QtWidgets.QGraphicsItem.ItemIsFocusable|QtWidgets.QGraphicsItem.ItemIgnoresParentOpacity)
self.setFlags(QtWidgets.QGraphicsItem.ItemIsFocusable|QtWidgets.QGraphicsItem.ItemIgnoresParentOpacity)
#self.setBrush(QtCore.Qt.red) #debug
self.setPen(QtGui.QPen(QtCore.Qt.transparent))
self.parentDataTrackId = parentDataTrackId
self.parentGuiTrack = parentGuiTrack
self.userItems = []
self.interpolatedItems = []
self.other = []
self.blockListCache = [] #backend dictExport items. updated through self.updateGraphBlockTrack
self.blockdictCache = {} #blockId:guiBlock updated through self.updateGraphBlockTrack
self.transparentBlockHandles = [] #transparentBlockHandles in correct order. updated through self.updateGraphBlockTrack
def itemChange(self, changeEnum, value):
if changeEnum == QtWidgets.QGraphicsItem.ItemVisibleHasChanged: #12
if self.isVisible():
self.parentGuiTrack.universalCreateFirstCCBlock.hide()
else:
self.parentGuiTrack.universalCreateFirstCCBlock.show()
return super().itemChange(changeEnum, value)
def mousePressEvent(self, event):
if event.button() == 1: #QtCore.Qt.MouseButton.LeftButton
self.add(event.pos())
@property
def items(self):
return self.userItems + self.interpolatedItems + self.other
#@property
#def transparentBlockHandles(self):
#return CCGraphTransparentBlock.instances This does not work because we need the blocks per track, not all of them in all tracks.
def createGraphicItemsFromData(self, staticRepresentationList):
"""The tick position is, as always, a long tickvalue from the
backend.
The CC value, 0-127, has its default 0-line on the middle line
as all items, since this is the track root. Since CC 64 is the
middle value for CCs we shift all the points down by 64 so
the middle staff line becomes CC 64.
"""
for item in self.items:
self.scene().removeWhenIdle(item)
self.other = []
self.userItems = []
self.interpolatedItems = []
for point in staticRepresentationList:
if point["type"] == "interpolated":
p = CCInterpolatedPoint()
self.interpolatedItems.append(p)
self.userItems[-1].interpolatedItemsRight.append(p)
else: #user, lastInBlock or lastInTrack
p = CCUserPoint(self, point)
if self.userItems:
p.interpolatedItemsLeft = self.userItems[-1].interpolatedItemsRight
self.userItems.append(p)
t = QtWidgets.QGraphicsSimpleTextItem(str(abs(point["value"])))
t.setFont(constantsAndConfigs.theFont)
t.setParentItem(self)
t.setScale(0.75)
self.other.append(t)
t.setPos(point["position"] / constantsAndConfigs.ticksToPixelRatio, 29)
p.setParentItem(self)
p.setPos(point["position"] / constantsAndConfigs.ticksToPixelRatio , (point["value"]+64)*0.4375) #value goes from -0 to -127 and are compressed to fit between two lines in the staff.
def updateGraphBlockTrack(self, staticRepresentationList):
"""Handles and visualizes block boundaries"""
#{"type" : "GraphBlock", "id":id(block), "name":block.name, "duration":block.duration, "position":tickCounter}
self.blockListCache = staticRepresentationList #sorted list
self.blockdictCache = {} #reset
for tbh in self.transparentBlockHandles:
tbh.setParentItem(None)
tbh.scene().removeWhenIdle(tbh)
self.transparentBlockHandles = [] #reset
#removeInstancesFromScene(CCGraphTransparentBlock) #this removes ALL blocks in all tracks from the scene. don't.
for dictExportItem in staticRepresentationList:
guiBlock = CCGraphTransparentBlock(parent = self, staticExportItem = dictExportItem, x = 0, y = -28, w = dictExportItem["duration"] / constantsAndConfigs.ticksToPixelRatio, h = 2*28)
guiBlock.setParentItem(self)
guiBlock.setPos(dictExportItem["position"] / constantsAndConfigs.ticksToPixelRatio,0)
self.blockdictCache[dictExportItem["id"]] = guiBlock
self.transparentBlockHandles.append(guiBlock)
#Use the last item of the loop above to draw length of the boundary lines.
maximumPixels = (dictExportItem["duration"] + dictExportItem["position"]) / constantsAndConfigs.ticksToPixelRatio
upperLine = QtWidgets.QGraphicsLineItem(0,-28,maximumPixels,-28) #x1, y1, x2, y2
#upperLine.setPen(QtGui.QColor("red"))
upperLine.setParentItem(self)
self.other.append(upperLine)
lowerLine = QtWidgets.QGraphicsLineItem(0,28,maximumPixels,28) #x1, y1, x2, y2
#lowerLine.setPen(QtGui.QColor("green"))
lowerLine.setParentItem(self)
self.other.append(lowerLine)
upperLine.setOpacity(0.3)
lowerLine.setOpacity(0.3)
upperLine.setPos(0,0)
lowerLine.setPos(0,0)
#for self.stretchXCoordinates
self.upperLine = upperLine
self.lowerLine = lowerLine
self.setRect(0,-28,maximumPixels,2*28)
def stretchXCoordinates(self, factor):
"""Reposition the items on the X axis.
Call goes through all parents/children, starting from ScoreView._stretchXCoordinates.
Docstring there."""
stretchRect(self, factor)
stretchLine(self.upperLine, factor)
stretchLine(self.lowerLine, factor)
for item in self.items:
item.setX(item.pos().x() * factor)
for transparentBlockHandle in self.transparentBlockHandles:
transparentBlockHandle.setX(transparentBlockHandle.pos().x() * factor)
transparentBlockHandle.stretchXCoordinates(factor)
def blocKByPosition(self, tickPositionAbsoluteBackendValue):
for block in self.blockListCache:
start = block["position"]
end = start + block["duration"]
if start <= tickPositionAbsoluteBackendValue < end:
return block["id"], block["position"]
return None #After the last block.
def blockAt(self, qScenePosition):
"""For compatibility with track.blockAt
Can return a block or None for "after the last block" """
backendPosition = qScenePosition * constantsAndConfigs.ticksToPixelRatio
result = self.blocKByPosition(backendPosition)
if result:
blockId, blockBackendPosition = result
assert blockId in self.blockdictCache
return self.blockdictCache[blockId]
else:
return None
def getCCNumber(self):
"""The CC number is a dynamic value"""
for ccNumber, ccGraphTrack in self.parentGuiTrack.ccPaths.items():
if ccGraphTrack is self:
return ccNumber
else:
raise ValueError("This Block is not in the ccPath dict of the GuiTrack""")
def getYAsBackendValue(self, y):
newCCValue = int(y / 0.4375 - 64) #value goes from -0 to -127 and are compressed to fit between two lines in the staff.
newCCValue = abs(newCCValue)
assert 0 <= newCCValue < 128
return newCCValue
def add(self, qPos):
"""Only activated through the hover area which gives are the
most control over where clicks are allowed.
Also there was a weird bug that the CCPath itself cannot
detect mouse clicks in the right position"""
y = qPos.y()
if -28 < y < 28:
sp = qPos.x() * constantsAndConfigs.ticksToPixelRatio
blockId, blockStartOffset = self.blocKByPosition(sp) #get the block before rounding. Otherwise rounding might result in a position higher than the blocks duration
if constantsAndConfigs.snapToGrid:
sp = round(sp / constantsAndConfigs.gridRhythm) * constantsAndConfigs.gridRhythm
positionInBlockBackendTicks = sp - blockStartOffset
api.addGraphItem(blockId, positionInBlockBackendTicks, self.getYAsBackendValue(y))
class CCGraphTransparentBlock(QtWidgets.QGraphicsRectItem):
instances = []
def __init__(self, parent, staticExportItem, x, y, w, h):
self.__class__.instances.append(self)
super().__init__(x, y, w, h)
#self.setFlags(QtWidgets.QGraphicsItem.ItemDoesntPropagateOpacityToChildren|QtWidgets.QGraphicsItem.ItemIsMovable) #no mouseReleaseEvent without selection or movable.
self.setFlags(QtWidgets.QGraphicsItem.ItemDoesntPropagateOpacityToChildren) #no mouseReleaseEvent without selection or movable.
self.parent = parent # CCPath instance
self.color = stringToColor(staticExportItem["name"])
self.setBrush(self.color)
self.trans = QtGui.QColor("transparent")
self.setPen(self.trans)
self.setBrush(self.trans)
self.setOpacity(0.2) #mimic background behaviour
self.staticExportItem = staticExportItem
self.blockEndMarker = CCGraphBlockEndMarker(self, staticExportItem)
self.blockEndMarker.setParentItem(self)
self.blockEndMarker.setPos(staticExportItem["duration"] / constantsAndConfigs.ticksToPixelRatio, 0)
self.posBeforeMove = None
self.cursorPosOnMoveStart = None
def stretchXCoordinates(self, factor):
"""Reposition the items on the X axis.
Call goes through all parents/children, starting from ScoreView._stretchXCoordinates.
Docstring there."""
stretchRect(self, factor)
self.blockEndMarker.setX(self.blockEndMarker.pos().x() * factor)
def mousePressEventCustom(self, event):
"""Custom gets called by the scene mouse press event directly only when the right keys
are hold down.
e.g. shift + middle mouse button for moving this block"""
self.posBeforeMove = self.pos()
self.cursorPosOnMoveStart = QtGui.QCursor.pos()
self.setBrush(self.color)
super().mousePressEvent(event)
def mouseMoveEventCustom(self, event):
"""Custom gets called by the scene mouse press event directly only when the right keys
are hold down
e.g. shift + middle mouse button for moving this block"""
# All the positions below don't work. They work fine when dragging Tracks around but not this Item. I can't be bothered to figure out why.
#scenePos() results ins an item position that is translated down and right. The higher the x/y value the more the offset
#Instead we calculate our delta ourselves.
#self.setPos(self.mapToItem(self, event.scenePos()))
#self.setPos(self.mapFromScene(event.scenePos()))
#posGlobal = QtGui.QCursor.pos()
#posView = self.parent.parentScore.parentView.mapFromGlobal(posGlobal) #a widget
#posScene = self.parent.parentScore.parentView.mapToScene(posView)
#print (posGlobal, posView, posScene, event.scenePos())
if self.cursorPosOnMoveStart:
self.setPos(event.scenePos())
"""
#does not work with zooming
if self.cursorPosOnMoveStart:
delta = QtGui.QCursor.pos() - self.cursorPosOnMoveStart
new = self.posBeforeMove + delta
if new.x() < 0:
#self.setPos(0, self.posBeforeMove.y())
self.setPos(0, new.y())
else:
#self.setPos(new.x(), self.posBeforeMove.y()) #only move in one track
self.setPos(new.x(), new.y())
#event.ignore() #this blocks the qt movable object since we already move the object on our own.
"""
super().mouseMoveEvent(event)
def mouseReleaseEventCustom(self, event):
"""Custom gets called by the scene mouse press event directly only when the right keys
are hold down"""
self.setBrush(self.trans)
self.setPos(self.posBeforeMove) #In case the block was moved to a position where no track is (below the tracks) we just reset the graphics. If the moving was correct then the new position will be set by redrawing the whole Conductor.
self.posBeforeMove = None
self.cursorPosOnMoveStart = None
super().mouseReleaseEvent(event)
def splitHere(self, event):
posRelativeToBlockStart = event.scenePos().x() * constantsAndConfigs.ticksToPixelRatio - self.x() * constantsAndConfigs.ticksToPixelRatio
if constantsAndConfigs.snapToGrid:
posRelativeToBlockStart = round(posRelativeToBlockStart / constantsAndConfigs.gridRhythm) * constantsAndConfigs.gridRhythm
if posRelativeToBlockStart > 0:
api.splitCCBlock(self.staticExportItem["id"], int(posRelativeToBlockStart))
def contextMenuEvent(self, event):
listOfLabelsAndFunctions = [
("split here", lambda: self.splitHere(event)),
("duplicate", lambda: api.duplicateCCBlock(self.staticExportItem["id"])),
("create content link", lambda: api.duplicateContentLinkCCBlock(self.staticExportItem["id"])),
("unlink", lambda: api.unlinkCCBlock(self.staticExportItem["id"])),
("separator", None),
("join with next block", lambda: api.mergeWithNextGraphBlock(self.staticExportItem["id"])),
("delete block", lambda: api.deleteCCBlock(self.staticExportItem["id"])),
("separator", None),
("append block at the end", lambda ccNum = self.parent.getCCNumber(): api.appendGraphBlock(self.parent.parentDataTrackId, ccNum)),
]
callContextMenu(listOfLabelsAndFunctions)
class CCGraphBlockEndMarker(QtWidgets.QGraphicsLineItem):
def __init__(self, parentTransparentBlock, staticExportItem):
super(CCGraphBlockEndMarker, self).__init__(0,-28,0,28) #x, y, w, h
self.parentTransparentBlock = parentTransparentBlock
self.parentCCPath = self.parentTransparentBlock.parent
self.staticExportItem = staticExportItem
self.setFlags(QtWidgets.QGraphicsItem.ItemIsMovable|QtWidgets.QGraphicsItem.ItemSendsGeometryChanges|QtWidgets.QGraphicsItem.ItemIsFocusable)
self.setAcceptHoverEvents(True)
self.setCursor(QtCore.Qt.SizeHorCursor)
self.lastPos = self.pos()
#self.setBrush(QtGui.QColor("red"))
pen = QtGui.QPen() # creates a default pen
if not self.staticExportItem["exportsAllItems"]:
pen.setStyle(QtCore.Qt.DashDotLine)
pen.setWidth(2)
self.setPen(pen)
self.setZValue(10)
self.inactivePen = pen
self.inactivePen.setColor(QtGui.QColor("black"))
self.activePen = QtGui.QPen(pen)
self.activePen.setColor(QtGui.QColor("cyan"))
def allItemsRightOfMe(self):
for item in self.parentCCPath.items:
if item.x() > self.x():
yield item
def shape(self):
"""Qt Function
Return a more accurate shape for this item so that
mouse hovering is more accurate"""
path = QtGui.QPainterPath()
path.addRect(QtCore.QRectF(-3, -1/2 * constantsAndConfigs.trackHeight, 9, constantsAndConfigs.trackHeight)) #this is directly related to inits parameter x, y, w, h
return path
def mouseReleaseEvent(self, event):
"""After moving a point around
send an update to the backend"""
super(CCGraphBlockEndMarker, self).mouseReleaseEvent(event)
if event.button() == 1: #QtCore.Qt.MouseButton.LeftButton
x = event.scenePos().x()
#x = self.x()
x = x * constantsAndConfigs.ticksToPixelRatio
endingRelativeToBlockStart = x - self.staticExportItem["position"]
if constantsAndConfigs.snapToGrid:
endingRelativeToBlockStart = round(endingRelativeToBlockStart / constantsAndConfigs.gridRhythm) * constantsAndConfigs.gridRhythm
assert endingRelativeToBlockStart > 0
api.changeGraphBlockDuration(self.staticExportItem["id"], endingRelativeToBlockStart)
def mousePressEvent(self, event):
super(CCGraphBlockEndMarker, self).mousePressEvent(event)
if event.button() == 1: #QtCore.Qt.MouseButton.LeftButton
for i in self.allItemsRightOfMe():
i.hide()
def mouseMoveEvent(self, event):
"""Only active when the item is also selected and left
mouse button is down. Not any mouse event, no hover."""
super(CCGraphBlockEndMarker, self).mouseMoveEvent(event)
self.setY(self.lastPos.y())
def hoverEnterEvent(self, event):
#self.setZValue(20)
#self.parentTransparentBlock.setZValue(19)
self.setPen(self.activePen)
self.parentTransparentBlock.setBrush(self.parentTransparentBlock.color)
def hoverLeaveEvent(self, event):
#self.setZValue(10)
#self.parentTransparentBlock.setZValue(9)
self.setPen(self.inactivePen)
self.parentTransparentBlock.setBrush(self.parentTransparentBlock.trans)
class CCInterpolatedPoint(QtWidgets.QGraphicsEllipseItem):
"""This is practically read-only"""
def __init__(self):
super(CCInterpolatedPoint, self).__init__(0, 0,1,1) #x,y,w,h
self.setOpacity(0.6)
self.setBrush(QtCore.Qt.black) #fill
self.setEnabled(False)
self.setZValue(1)
class CCUserPoint(QtWidgets.QGraphicsEllipseItem):
"""the position is set by the parent"""
def __init__(self, parentCCPath, staticExportItem):
super(CCUserPoint, self).__init__(-3,-3,6,6) #x,y,w,h
#color = QtGui.QColor()
#color.setHsl(127-abs(value), 255, 127) #l(h, s, l) # 8bit values. Sets a HSL color value; h is the hue, s is the saturation, l is the lightness. l goes from black(0), over color(255/2) to white (255). #0 hue is green, 128 is red
#self.setBrush(color) #fill
self.setBrush(QtGui.QColor("cyan"))
self.setFlags(QtWidgets.QGraphicsItem.ItemIsMovable|QtWidgets.QGraphicsItem.ItemSendsGeometryChanges|QtWidgets.QGraphicsItem.ItemIsFocusable)
self.setAcceptHoverEvents(True)
self.setCursor(QtCore.Qt.SizeAllCursor)
self.parentCCPath = parentCCPath
self.staticExportItem = staticExportItem
self.interpolatedItemsRight = []
self.interpolatedItemsLeft = []
self.setZValue(9)
def shape(self):
"""Return a more accurate shape for this item so that
mouse hovering is more accurate"""
path = QtGui.QPainterPath()
path.addEllipse(QtCore.QRectF(-5, -5, 14, 14)) #this is directly related to inits parameter. -3, -3, 6, 6.
return path
def mousePressEvent(self, event):
super().mousePressEvent(event)
self.lastPos = self.pos()
if event.button() == 1: #QtCore.Qt.MouseButton.LeftButton
self.setCursor(QtCore.Qt.BlankCursor)
for i in self.interpolatedItemsLeft + self.interpolatedItemsRight:
i.hide()
def mouseDoubleClickEvent(self, event):
self.changeCCValue()
def hoverEnterEvent(self, event):
self.grabKeyboard()
#self.setFocus() #do NOT set the focus. GrabKeyboard is enough. The focus will stay even after hoverLeaveEvent so that Delete will delete the last hovered item. not good!
def hoverLeaveEvent(self, event):
"""reverse hoverEnterEvent"""
self.ungrabKeyboard()
def keyPressEvent(self, event):
"""Handle the delete item key.
Needs grabKeyboard, but NOT setFocus"""
key = event.key()
if key == 16777223:
self.delete()
else:
return super().keyPressEvent(event)
def mouseReleaseEvent(self, event):
"""After moving a point around
send an update to the backend"""
super(CCUserPoint, self).mouseReleaseEvent(event)
self.setCursor(QtCore.Qt.SizeAllCursor)
if event.button() == 1: #QtCore.Qt.MouseButton.LeftButton
api.changeGraphItem(self.staticExportItem["id"], self.getXDifferenceAsBackendValue(), self.getYAsBackendValue()) #send update to the backend, don't wait for callback.
def mouseMoveEvent(self, event):
"""Only active when the item is also selected and left
mouse button is down. Not any mouse event, no hover."""
modifiers = QtWidgets.QApplication.keyboardModifiers()
super(CCUserPoint, self).mouseMoveEvent(event)
if modifiers == QtCore.Qt.ShiftModifier:
self.setY(self.lastPos.y())
elif modifiers == QtCore.Qt.AltModifier:
self.setX(self.lastPos.x())
absoluteXPosition = self.x() * constantsAndConfigs.ticksToPixelRatio
withinBlock = self.staticExportItem["minPossibleAbsolutePosition"] <= absoluteXPosition <= self.staticExportItem["maxPossibleAbsolutePosition"]
if not withinBlock:
if absoluteXPosition < self.staticExportItem["minPossibleAbsolutePosition"]:
self.setX(self.staticExportItem["minPossibleAbsolutePosition"] / constantsAndConfigs.ticksToPixelRatio)
else:
self.setX(self.staticExportItem["maxPossibleAbsolutePosition"] / constantsAndConfigs.ticksToPixelRatio)
#Make mouse cursor movement not weird.
a = self.scene().parentView.mapFromScene(self.pos())
b = self.scene().parentView.viewport().mapToGlobal(a)
QtGui.QCursor.setPos(b.x(), QtGui.QCursor.pos().y())
withinYRange = -28 <= self.y() <= 28
if not withinYRange:
if self.y() < -28:
self.setY(-27.9)
else:
self.setY(28)
#Make mouse cursor movement not weird.
a = self.scene().parentView.mapFromScene(self.pos())
b = self.scene().parentView.viewport().mapToGlobal(a)
QtGui.QCursor.setPos(QtGui.QCursor.pos().x(), b.y())
def delete(self):
"""Instruct the backend to delete this item. Will trigger a
callback to redraw the graphTrack"""
api.removeGraphItem(self.staticExportItem["id"])
def contextMenuEvent(self, event):
menu = QtWidgets.QMenu()
listOfLabelsAndFunctions = [
("interpolation Type", self.changeInterpolationType),
("CC Value", self.changeCCValue),
("delete", self.delete), #deletes the last hover item which is of course the current one.
]
for text, function in listOfLabelsAndFunctions:
if text == "separator":
self.addSeparator()
else:
a = QtWidgets.QAction(text, menu)
menu.addAction(a)
a.triggered.connect(function)
pos = QtGui.QCursor.pos()
pos.setY(pos.y() + 5)
self.ungrabMouse() #if we don't ungrab and the user clicks the context menu "away" by clicking in an empty area this will still get registered as mouseclick belonging to the current item and change the value to some insane amount, breaking the point.
menu.exec_(pos)
def changeInterpolationType(self):
graphTypeString = QtWidgets.QInputDialog.getItem(self.scene().parentView, "Interpolation Type", "choose Interpolation Type", api.getListOfGraphInterpolationTypesAsStrings(), 0, False)
if graphTypeString[1]: #[1] bool if canceled
api.changeGraphItemInterpolation(self.staticExportItem["id"], graphTypeString[0])
def changeCCValue(self):
ccValue = QtWidgets.QInputDialog.getInt(self.scene().parentView, "CC Value", "specify midi Continuous Control value", value=64, minValue=0, maxValue=127)
if ccValue[1]: #[1] bool if canceled
api.changeGraphItem(self.staticExportItem["id"], self.getXDifferenceAsBackendValue(), ccValue[0]) #send update to the backend, don't wait for callback.
def getYAsBackendValue(self):
newCCValue = int(self.y() / 0.4375 - 64) #value goes from -0 to -127 and are compressed to fit between two lines in the staff.
newCCValue = abs(newCCValue)
assert 0 <= newCCValue < 128
return newCCValue
def getXDifferenceAsBackendValue(self):
"""The problem is that we need the position relativ to its
parent block, which we don't use in that way in the GUI.
So we calculate the difference to the old position"""
oldPositionAbsolute = int(self.staticExportItem["position"])
newPositionAbsolute = self.pos().x() * constantsAndConfigs.ticksToPixelRatio
if constantsAndConfigs.snapToGrid:
newPositionAbsolute = round(newPositionAbsolute / constantsAndConfigs.gridRhythm) * constantsAndConfigs.gridRhythm
diff = int(-1 * (oldPositionAbsolute - newPositionAbsolute))
return diff

920
qtgui/items.py

@ -0,0 +1,920 @@
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Copyright 2017, Nils Hilbricht, Germany ( https://www.hilbricht.net )
This file is part of Laborejo ( https://www.laborejo.org )
Laborejo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from PyQt5 import QtCore, QtGui, QtSvg, QtWidgets
from itertools import groupby
from engine.items import Chord, KeySignature
from .constantsAndConfigs import constantsAndConfigs
from template.qtgui.helper import stretchRect
import engine.api as api
"""All svg items (execept pitch-related) graphics are expected to be
already on the correct position and will be inserter ON the middle line
That means g-clef needs to be 14 pxiels below the y=0 coordinate since
these are two stafflines. Or in other words: Open the graphic and
scale and reposition it until it fits correctly when inserted with
setPos(0,0)"""
#Atomic items:
oneRectToReturnThemAll = QtCore.QRectF(0,0,0,0) #prevent the annoying "NotImplementError" from Qt for boundingRect. For items that don't need any collision detection.
class GuiTieCurveGraphicsItem(QtWidgets.QGraphicsPathItem):
pen = QtGui.QPen()
pen.setCapStyle(QtCore.Qt.RoundCap)
pen.setWidth(2)
def __init__(self, noteExportObject):
"""The origin of this item is the scene position.
We create a curve by drawing a straight line from zero
to end (the local item and the receiving tie item) and then
bend it down in the middle, leaving one of the control points
empty (0,0)."""
super().__init__()
self.setPen(GuiTieCurveGraphicsItem.pen)
if noteExportObject["dotOnLine"] < 0: #higher than the middle line
#self.translate(6, -5)
pass
else:
if noteExportObject["notehead"] <= 1: #whole notes have a bug in the gui because the backend stem info is misleading. Works fine except for ties.
pass #TODO
#self.translate(6, 0)
else:
pass #TODO
#self.translate(6, 6)
self.noteExportObject = noteExportObject
self.draw()
def draw(self):
lengthInPixel = self.noteExportObject["tieDistanceInTicks"] / constantsAndConfigs.ticksToPixelRatio
path = QtGui.QPainterPath()
path.cubicTo(0, 0, lengthInPixel/2, constantsAndConfigs.stafflineGap, lengthInPixel, 0) # ctrlPt1x, ctrlPt1y, ctrlPt2x, ctrlPt2y, endPtx, endPty
self.setPath(path) #set path edits the old one in place
def stretchXCoordinates(self, factor):
"""Called directly by the track by iterating through instances"""
self.draw()
class GuiPositionMarker(QtWidgets.QGraphicsRectItem):
def __init__(self, height, position = 1):
"""A simple position marker that connects an annotation above a staff with the staff.
Height and position are calculated in stafflines/gaps"""
super().__init__(-2, position*constantsAndConfigs.stafflineGap, 1, height * constantsAndConfigs.stafflineGap) #x,y, w, h
self.setBrush(QtCore.Qt.black)
class GuiTupletNumber(QtWidgets.QGraphicsItem):
"""The baseline is the scene Position.
We position in the up direction"""
pen = QtGui.QPen()
pen.setColor(QtGui.QColor("darkGrey"))
pen.setWidth(1)
def paint(self, *args):
pass
def boundingRect(self, *args):
return oneRectToReturnThemAll
def __init__(self, upper, lower):
super().__init__()
#self.upper = QtWidgets.QGraphicsSimpleTextItem(str(upper))
#self.divider = QtWidgets.QGraphicsLineItem(0,0,10,0)
#self.divider.rotate(-70)
#self.divider.setPen(GuiTupletNumber.pen)
self.lower = QtWidgets.QGraphicsSimpleTextItem(str(lower))
#self.upper.setParentItem(self)
#self.divider.setParentItem(self)
self.lower.setParentItem(self)
#self.upper.setPos(-1,-8)
#self.divider.setPos(5,5)
#self.lower.setPos(7,-5)
self.lower.setPos(-1,-4)
self.setScale(0.75)
class GuiItem(QtWidgets.QGraphicsItem):
"""A blank item. Subclass to implement your own"""
def __init__(self, staticItem):
super().__init__()
self.staticItem = staticItem
dur = self.staticItem["completeDuration"]
exceptions = ["BlockEndMarker"]
#Deactivated after stretchX was reimplemented properly as recursive function and not a catch all on all items. I don't think that was used anywhere else. #self.rectangles = [] #Prevents typechecking. only implemented in GuiChord
self.pixelPosition = self.staticItem["tickindex"] / constantsAndConfigs.ticksToPixelRatio
self.pixelWidth = self.staticItem["completeDuration"] / constantsAndConfigs.ticksToPixelRatio
#if dur or self.staticItem["type"] in exceptions:
# self.pixelPosition = self.staticItem["tickindex"] / constantsAndConfigs.ticksToPixelRatio
# self.pixelWidth = self.staticItem["completeDuration"] / constantsAndConfigs.ticksToPixelRatio
#else:
# self.pixelPosition = self.staticItem["tickindex"] / constantsAndConfigs.ticksToPixelRatio + constantsAndConfigs.negativeMagicPixel*6 #an offset to the left. this will still get in the way for short notes, but for now it is better than colliding 100% when placed on the note. #TODO: place above the track
# self.pixelWidth = 25 #Does not need to be the actual size because this is ONLY important when the item gets inserted at the appending position and the cursor needs to jump "over" the current item, because there is no next one. This is the direct response to the cursor method that sets the appending position as items tickposition+pixelwidth.
def updateVisibility(self):
"""Prevent against typechecking. This method is only implemented
in GuiChord"""
pass
def paint(self, *args):
pass
def boundingRect(self, *args):
return oneRectToReturnThemAll
def stretchXCoordinates(self, factor):
"""Reposition the items on the X axis.
Call goes through all parents/children, starting from ScoreView._stretchXCoordinates.
Docstring there."""
pass
class GuiRectangleNotehead(QtWidgets.QGraphicsRectItem):
"""Displays the pitch and actual duration of one note when in rectangle view mode"""
def __init__(self, parent, noteExportObject):
#Dimensions and Position
x = noteExportObject["leftModInTicks"] / constantsAndConfigs.ticksToPixelRatio
y = -1 * constantsAndConfigs.stafflineGap / 2 + 1
w = (noteExportObject["rightModInTicks"] + noteExportObject["completeDuration"] - noteExportObject["leftModInTicks"]) / constantsAndConfigs.ticksToPixelRatio
h = constantsAndConfigs.stafflineGap #- 2 #2 pixel to make room for the pen-width.
super().__init__(x, y, w, h)
self.setPos(0, constantsAndConfigs.stafflineGap * noteExportObject["dotOnLine"] / 2)
self.setParentItem(parent)
#Prepare self.shape()
#NOTE: this was from a time when mouse modification was possible. Leave for later use.
#self.path = QtGui.QPainterPath()
#self.pathRect = QtCore.QRectF(x, y-1, w, h+4) #this is directly related to inits parameter x, y, w, h
#self.path.addRect(self.pathRect)
#self.setCursor(QtCore.Qt.SizeHorCursor)
#Different color when the duration was modified by the user
inactive = "green" if noteExportObject["manualOverride"] else "black"
self.inactiveColor = QtGui.QColor(inactive)
self.setBrush(self.inactiveColor)
#Pen for the borders
pen = QtGui.QPen()
pen.setWidth(0)
pen.setColor(QtGui.QColor("darkGrey"))
self.setPen(pen)
#Since accidentals are part of the notehead we need one here. It doesn't matter if the traditional notehead already has one
if noteExportObject["accidental"]: #0 means no difference to keysig
self.accidental = GuiNote.createAccidentalGraphicsItem(self, noteExportObject["accidental"])
self.accidental.setPos(0, 0) #not analogue to the notehead acciental position because here we choose the rectangle as parent
self.accidental.setParentItem(self)
#NOTE: this was from a time when mouse modification was possible. Leave for later use.
#def shape(self):
# """Qt Function
# Return a more accurate shape for this item so that
# mouse hovering is more accurate.
#
# Must be within the bounding rect."""
# return self.path
#def boundingRect(self, *args):
# """Keep in syn with self.shape()"""
# return self.pathRect
#def paint(self, *args):
#Do NOT implement this. This actually works already. The parent item needs this.
class GuiRectangleVelocity(QtWidgets.QGraphicsRectItem):
"""Displays the velocity of one note when in rectangle view mode.
The Y-position is fixed on the staff and not bound to the rectangle notehead.
This makes it possible for the user to compare velocities visually.
"""
def __init__(self, parent, noteExportObject):
#Dimensions and Position
x = noteExportObject["leftModInTicks"] / constantsAndConfigs.ticksToPixelRatio #same as GuiRectangleNotehead
y = -1 * (noteExportObject["velocity"] / constantsAndConfigs.velocityToPixelRatio)
w = (noteExportObject["rightModInTicks"] + noteExportObject["completeDuration"] - noteExportObject["leftModInTicks"]) / constantsAndConfigs.ticksToPixelRatio #same as GuiRectangleNotehead
h = noteExportObject["velocity"] / constantsAndConfigs.velocityToPixelRatio #velocityToPixelRation has its own compress factor since values can go from 0 to 127
super().__init__(x, y, w, h)
self.setPos(0, 2*constantsAndConfigs.stafflineGap) #The position is fixed to the staff, not to the GuiRectangleNotehead.
self.setParentItem(parent)
#Prepare self.shape()
#NOTE: this was from a time when mouse modification was possible. Leave for later use.
#self.path = QtGui.QPainterPath()
#self.pathRect = QtCore.QRectF(x, y-1, w, h+4) #this is directly related to inits parameter x, y, w, h
#self.path.addRect(self.pathRect)
#self.setCursor(QtCore.Qt.SizeHorCursor)
#Colors and Apperance
inactive = "green" if noteExportObject["velocityManualOverride"] else "lightGray"
self.inactiveVelocityColor = QtGui.QColor(inactive)
self.activeVelocityColor = QtGui.QColor("darkCyan")
self.setBrush(self.inactiveVelocityColor)
self.setOpacity(0.3)
#Pen for the borders
#The pen interferes with the precise appearance we want for live notes
pen = QtGui.QPen()
pen.setCapStyle(QtCore.Qt.RoundCap)
pen.setJoinStyle(QtCore.Qt.RoundJoin)
pen.setWidth(2)
pen.setColor(QtGui.QColor("black"))
self.setPen(pen)
#Attach a label that displays the velocity as midi value 0-127
#label = QtWidgets.QGraphicsSimpleTextItem(str(noteExportObject["velocity"]))
#label.setPos(3, -3)
#label.setParentItem(parent)
#Misc Qt Flags
self.setAcceptHoverEvents(False) #Make this explicit so it will be remembered that the gui rectangle velocity is a display only.
#NOTE: this was from a time when mouse modification was possible. Leave for later use.
#def shape(self):
# """Qt Function
# Return a more accurate shape for this item so that
# mouse hovering is more accurate.
#
# Must be within the bounding rect."""
# return self.path
#def boundingRect(self, *args):
# """Keep in syn with self.shape()"""
# return self.pathRect
#def paint(self, *args):
#Do NOT implement this. This actually works already. The parent item needs this.
class GuiRectangle(QtWidgets.QGraphicsItem):
"""An alternative notehead, used to change velocity and duration
finetuning.
This is a GraphicsItem with two main components:
The notehead which displays the duration and pitch of the note
The Velocity which displays only the velocity.
Both components share their Y position in the staff so they are one item.
The notehead rectangles have full opacity and can't layer.
The velocity rectangles layer and only a grahpical highlight shows the active one.
"""
def __init__(self, noteExportObject):
super().__init__()
self.notehead = GuiRectangleNotehead(parent = self, noteExportObject = noteExportObject)
self.velocity = GuiRectangleVelocity(parent = self, noteExportObject = noteExportObject)
self.notehead.setZValue(10) #within GuiRectangle
def boundingRect(self, *args):
return oneRectToReturnThemAll
def paint(self, *args):
pass
class GuiNote(QtWidgets.QGraphicsItem):
def __init__(self, noteExportObject, directionRightAndUpwards):
super(GuiNote, self).__init__()
self.createNote(noteExportObject, directionRightAndUpwards)
def paint(self, *args):
pass
def boundingRect(self, *args):
return oneRectToReturnThemAll
def createNote(self, noteExportObject, directionRightAndUpwards):
#note head
self.noteExportObject = noteExportObject
#self.noteHead = GuiNote.noteheads[noteExportObject["notehead"]]()
self.noteHead = self.createNoteheadGraphicsItem(noteExportObject["notehead"])
self.noteHead.setPos(0, constantsAndConfigs.stafflineGap * noteExportObject["dotOnLine"] / 2)
self.noteHead.setParentItem(self)
#Ledger lines need to be done in the chord to not be redundant and work for multiple notes.
if noteExportObject["accidental"]: #0 means no difference to keysig
self.accidental = self.createAccidentalGraphicsItem(noteExportObject["accidental"])
self.accidental.setPos(0, constantsAndConfigs.stafflineGap * noteExportObject["dotOnLine"] / 2)
self.accidental.setParentItem(self)
for dot in range(noteExportObject["dots"]):
d = QtSvg.QGraphicsSvgItem(":svg/dot.svg")
d.setPos((dot+1)*4+6, constantsAndConfigs.stafflineGap * noteExportObject["dotOnLine"] / 2)
d.setParentItem(self)
for i, (upper, lower) in enumerate(noteExportObject["tuplets"]):
tuplet = GuiTupletNumber(upper, lower)
if directionRightAndUpwards:
tuplet.setPos(3, -6*(i+1))
else:
tuplet.setPos(3, 6*(i+1))
tuplet.setParentItem(self.noteHead)
if noteExportObject["durationKeyword"]:
self.durationKeywordGlyph = GuiNote.durationKeywords[noteExportObject["durationKeyword"]](noteExportObject)
if directionRightAndUpwards:
self.durationKeywordGlyph.setPos(3, 6)
else:
self.durationKeywordGlyph.setPos(3, -6)
self.durationKeywordGlyph.setParentItem(self.noteHead)
def createNoteheadGraphicsItem(self, number):
item = QtSvg.QGraphicsSvgItem()
item.setSharedRenderer(GuiNote.noteheads[number])
return item
def createAccidentalGraphicsItem(self, number):
item = QtSvg.QGraphicsSvgItem()
item.setSharedRenderer(GuiNote.accidentals[number])
return item
durationKeywords = { #0 is default and has no markers.
api.D_STACCATO : lambda noteExportObject: QtSvg.QGraphicsSvgItem(":svg/scriptsStaccato.svg"),
api.D_TENUTO : lambda noteExportObject: QtWidgets.QGraphicsSimpleTextItem("-"), #TODO: tenuto glyph
api.D_TIE : lambda noteExportObject: GuiTieCurveGraphicsItem(noteExportObject),
}
noteheads = {
4 : QtSvg.QSvgRenderer(":svg/noteheadsBlack.svg"), #and 8, 16, 32, ...
2 : QtSvg.QSvgRenderer(":svg/noteheadsHalf.svg"),
1 : QtSvg.QSvgRenderer(":svg/noteheadsWhole.svg"),
0 : QtSvg.QSvgRenderer(":svg/noteheadsBrevis.svg"),
-1 : QtSvg.QSvgRenderer(":svg/noteheadsLonga.svg"),
-2 : QtSvg.QSvgRenderer(":svg/noteheadsMaxima.svg"),
}
#Accidental .svg are shifted to the left a bit already so we can place them on the same x-coordinates as the notes.
accidentals = {
1 : QtSvg.QSvgRenderer(":svg/accidentalsNatural.svg"),
10 : QtSvg.QSvgRenderer(":svg/accidentalsSharp.svg"),
20 : QtSvg.QSvgRenderer(":svg/accidentalsDoublesharp.svg"),
-10 : QtSvg.QSvgRenderer(":svg/accidentalsFlat.svg"),
-20 : QtSvg.QSvgRenderer(":svg/accidentalsFlatFlat.svg"),
}
def stretchXCoordinates(self, factor):
"""Reposition the items on the X axis.
Call goes through all parents/children, starting from ScoreView._stretchXCoordinates.
Docstring there."""
try:
self.durationKeywordGlyph.stretchXCoordinates(factor)
except AttributeError: #does not have any attachements or the attachment does not have the stretch function (e.g. staccato)
pass
#Top level items, all based on GuiItem.
class GuiChord(GuiItem):
"""staticItem is a chord Dict which has another list of dicts:
staticItem["notelist"].
Each note with its notehead, accidental etc is in there.
This means that a chord can consist of multiple durations as well
as pitches, of course.
For spacing calculations the chord itself gives us a duration as
well."""
def __init__(self, staticItem,):
super().__init__(staticItem)
self.staticItem = staticItem
self.rectangles = []
self.notes = []
self.stem = None #stored for rectangle/head switching
self.flag = None #stored for rectangle/head switching
self.beamGroupGlyph = None #stored for rectangle/head switching
#The actual beams are in the track
self.createRectanglesFromData()
self.createNotesFromData()
self.createGenericFromData()
self.updateVisibility()
ledgerPen = QtGui.QPen(QtCore.Qt.SolidLine)
ledgerPen.setCapStyle(QtCore.Qt.RoundCap)
ledgerPen.setWidth(1)
stemPen = QtGui.QPen(QtCore.Qt.SolidLine)
stemPen.setCapStyle(QtCore.Qt.RoundCap)
stemPen.setWidth(1.5)
flags = { #QGraphicsItems can only be used once so we have to save a class constructor here instead of an instance.
1024 : lambda: QtSvg.QGraphicsSvgItem(":svg/flag1024.svg"), #TODO
512 : lambda: QtSvg.QGraphicsSvgItem(":svg/flag512.svg"), #TODO
256 : lambda: QtSvg.QGraphicsSvgItem(":svg/flag256.svg"),
128 : lambda: QtSvg.QGraphicsSvgItem(":svg/flag128.svg"),
64 : lambda: QtSvg.QGraphicsSvgItem(":svg/flag64.svg"),
32 : lambda: QtSvg.QGraphicsSvgItem(":svg/flag32.svg"),
16 : lambda: QtSvg.QGraphicsSvgItem(":svg/flag16.svg"),
8 : lambda: QtSvg.QGraphicsSvgItem(":svg/flag8.svg"),
-1024 : lambda: QtSvg.QGraphicsSvgItem(":svg/flag1024i.svg"), #TODO
-512 : lambda: QtSvg.QGraphicsSvgItem(":svg/flag512i.svg"), #TODO
-256 : lambda: QtSvg.QGraphicsSvgItem(":svg/flag256i.svg"),
-128 : lambda: QtSvg.QGraphicsSvgItem(":svg/flag128i.svg"),
-64 : lambda: QtSvg.QGraphicsSvgItem(":svg/flag64i.svg"),
-32 : lambda: QtSvg.QGraphicsSvgItem(":svg/flag32i.svg"),
-16 : lambda: QtSvg.QGraphicsSvgItem(":svg/flag16i.svg"),
-8 : lambda: QtSvg.QGraphicsSvgItem(":svg/flag8i.svg"),
}
def createGenericFromData(self):
"""Graphics for both rectangles and noteheads"""
#Ledger Lines
below, above = self.staticItem["ledgerLines"]
for i in range(below):
line = QtWidgets.QGraphicsLineItem(QtCore.QLineF(0, 0, 12, 0))
line.setPen(GuiChord.ledgerPen)
line.setParentItem(self)
line.setPos(constantsAndConfigs.negativeMagicPixel, i * constantsAndConfigs.stafflineGap + constantsAndConfigs.stafflineGap*3)
for i in range(above):
line = QtWidgets.QGraphicsLineItem(QtCore.QLineF(0, 0, 12, 0))
line.setPen(GuiChord.ledgerPen)
line.setParentItem(self)
line.setPos(constantsAndConfigs.negativeMagicPixel, -1 * i * constantsAndConfigs.stafflineGap - constantsAndConfigs.stafflineGap*3)
#Display relative channel changes
if not self.staticItem["midiChannelOffset"] == 0:
channelGlyph = QtWidgets.QGraphicsSimpleTextItem("ch{0:+}".format(self.staticItem["midiChannelOffset"]))
channelGlyph.setScale(0.75)
channelGlyph.setParentItem(self)
channelGlyph.setPos(0, -5*constantsAndConfigs.stafflineGap)
def createRectanglesFromData(self):
"""Graphics only for rectangles"""
for noteExportObject in self.staticItem["notelist"]:
if not noteExportObject["tie"] == "notFirst":
#Tied notes, except the first, do not produce rectangles because the first note gets an extra large rectangle.
rectangle = GuiRectangle(noteExportObject)
self.rectangles.append(rectangle)
rectangle.setParentItem(self)
def createNotesFromData(self):
"""Graphics only for noteheads"""
if self.staticItem["beam"]:
stemOrBeam = self.staticItem["beam"]
else:
stemOrBeam = self.staticItem["stem"]
if stemOrBeam and stemOrBeam[2] > 0:
self.directionRightAndUpwards = False
else:
self.directionRightAndUpwards = True
#Stem - Both for groups and standalone.
if stemOrBeam: #may be an empty tuple for whole notes and brevis
line = QtWidgets.QGraphicsLineItem(QtCore.QLineF(0, constantsAndConfigs.stafflineGap * stemOrBeam[1]/2, 0, 0)) #x1, y1, x2, y2
line.setPen(GuiChord.stemPen)
self.stem = line #store as persistent item. Otherwise qt will delete it.
line.setParentItem(self)
line.setPos(constantsAndConfigs.magicPixel + stemOrBeam[2]*3, constantsAndConfigs.stafflineGap * stemOrBeam[0] / 2) #stem[2] is left/-1 or right/1 shifting. #4 is the middle
#Flags
if not self.staticItem["beam"] and self.staticItem["flag"]:
assert self.stem
flag = GuiChord.flags[self.staticItem["flag"]]() #the graphic.
flag.setParentItem(self)
self.flag = flag #store as persistent item. Otherwise qt will delete it.
flag.setPos(self.stem.pos().x(), self.stem.line().p1().y() + self.stem.pos().y()) #we already know where the stem-line is.
#Check if this item is the start or end of a beam group and mark it with lilypond syntax
if self.staticItem["beamGroup"]:
if self.staticItem["beamGroup"] == "open":
beamGroupGlyph = QtWidgets.QGraphicsSimpleTextItem("[")
beamGroupGlyph.setParentItem(self)
beamGroupGlyph.setPos(0, -5*constantsAndConfigs.stafflineGap)
elif self.staticItem["beamGroup"] == "close":
beamGroupGlyph = QtWidgets.QGraphicsSimpleTextItem("]")
beamGroupGlyph.setParentItem(self)
beamGroupGlyph.setPos(constantsAndConfigs.magicPixel, -5*constantsAndConfigs.stafflineGap)
self.beamGroupGlyph = beamGroupGlyph
#Actual Noteheads
lastDotOnLine = float("inf")
for noteExportObject in self.staticItem["notelist"]:
#notes in a chord come in the order highest to lowest
#determine if we have two neighbouring noteheads. If yes we shift one of the heads to the right
assert lastDotOnLine > noteExportObject["dotOnLine"]
if lastDotOnLine - noteExportObject["dotOnLine"] == 1:
moveThisNoteheadToTheRight = True
lastDotOnLine = noteExportObject["dotOnLine"]
lastDotOnLine += 1 #we shift the current notehead. The next pair would be no problem, even if neighbours.
else:
moveThisNoteheadToTheRight = False
lastDotOnLine = noteExportObject["dotOnLine"]
note = GuiNote(noteExportObject, self.directionRightAndUpwards)
self.notes.append(note) #we need them later for switching between rectangles and noteheads
note.setParentItem(self)
if moveThisNoteheadToTheRight:
note.setX(note.pos().x() + 6) #6 pixels.
def stretchXCoordinates(self, factor):
"""Reposition the items on the X axis.
Call goes through all parents/children, starting from ScoreView._stretchXCoordinates.
Docstring there."""
for rectNote in self.rectangles:
stretchRect(rectNote.notehead, factor)
stretchRect(rectNote.velocity, factor)
for note in self.notes: #this is for ties only at the moment, the rest does not stretch
note.stretchXCoordinates(factor)
def updateVisibility(self):
"""decide during creation what part is visible at the moment. aka. are we in notehead
or rectangle mode.
Beams visibility is done in the track function createBeams"""
if constantsAndConfigs.noteHeadMode:
for r in self.rectangles:
r.hide()
for n in self.notes:
n.show()
if self.flag:
self.flag.show()
if self.stem:
self.stem.show()
if self.beamGroupGlyph:
#This is about the start and end marker [ ] .The beam itself is in the track
self.beamGroupGlyph.show()
else: #rectangle mode.
for r in self.rectangles:
r.show()
for n in self.notes:
n.hide()
if self.flag:
self.flag.hide()
if self.stem:
self.stem.hide()
if self.beamGroupGlyph:
#This is about the start and end marker [ ] .The beam itself is in the track
self.beamGroupGlyph.hide()
class GuiLiveNote(QtWidgets.QGraphicsRectItem):
"""A pure rectangle note, meant for live recording."""
#TODO: Velocity indicator?
instances = []
def __init__(self, parent, liveNoteData):
self.__class__.instances.append(self)
self.liveNoteData = liveNoteData
#Dimensions and Position
x = 0 #A live note is always literally where it sounds
y = -1 * constantsAndConfigs.stafflineGap / 2
w = liveNoteData["duration"] / constantsAndConfigs.ticksToPixelRatio
h = constantsAndConfigs.stafflineGap
super().__init__(x, y, w, h)
self.setY(constantsAndConfigs.stafflineGap * liveNoteData["dotOnLine"] / 2)
self.setParentItem(parent)
self.setBrush(QtGui.QColor("red"))
#Pen for the borders
pen = QtGui.QPen()
pen.setWidth(0)
self.setPen(pen)
if liveNoteData["accidental"]: #0 means no difference to keysig
self.accidental = GuiNote.createAccidentalGraphicsItem(self, liveNoteData["accidental"])
self.accidental.setPos(0, 0) #not analogue to the notehead acciental position because here we choose the rectangle as parent
self.accidental.setParentItem(self)
def update(self, duration):
r = self.rect()
r.setRight(duration / constantsAndConfigs.ticksToPixelRatio)
self.setRect(r)
class GuiRest(GuiItem):
def __init__(self, staticItem):
super(GuiRest, self).__init__(staticItem)
self.createGraphicItemsFromData()
rests = { #QGraphicsItems can only be used once so we have to save a class constructor here instead of an instance.
-1 : lambda: QtSvg.QGraphicsSvgItem(":svg/restLonga.svg"),
-2 : lambda: QtSvg.QGraphicsSvgItem(":svg/restMaxima.svg"),
0 : lambda: QtSvg.QGraphicsSvgItem(":svg/restBrevis.svg"),
1 : lambda: QtSvg.QGraphicsSvgItem(":svg/rest1.svg"),
2 : lambda: QtSvg.QGraphicsSvgItem(":svg/rest2.svg"),
4 : lambda: QtSvg.QGraphicsSvgItem(":svg/rest4.svg"),
8 : lambda: QtSvg.QGraphicsSvgItem(":svg/rest8.svg"),
16 : lambda: QtSvg.QGraphicsSvgItem(":svg/rest16.svg"),
32 : lambda: QtSvg.QGraphicsSvgItem(":svg/rest32.svg"),
64 : lambda: QtSvg.QGraphicsSvgItem(":svg/rest64.svg"),
128 : lambda: QtSvg.QGraphicsSvgItem(":svg/rest128.svg"),
256 : lambda: QtSvg.QGraphicsSvgItem(":svg/rest256.svg"), #TODO
512 : lambda: QtSvg.QGraphicsSvgItem(":svg/rest512.svg"), #TODO
1024 : lambda: QtSvg.QGraphicsSvgItem(":svg/rest1024.svg"), #TODO
}
def createGraphicItemsFromData(self):
self.glyph = GuiRest.rests[self.staticItem["rest"]]()
self.glyph.setParentItem(self)
for dot in range(self.staticItem["dots"]):
d = QtSvg.QGraphicsSvgItem(":svg/dot.svg")
d.setPos((dot+1)*4+6, -2)
d.setParentItem(self)
for i, (upper, lower) in enumerate(self.staticItem["tuplets"]):
tuplet = GuiTupletNumber(upper, lower)
tuplet.setParentItem(self)
tuplet.setPos(2, (i+1)*-4-constantsAndConfigs.stafflineGap*2)
class GuiKeySignature(GuiItem):
def __init__(self, staticItem):
super(GuiKeySignature, self).__init__(staticItem)
self.createGraphicItemsFromData()
def createGraphicItemsFromData(self):
"""staticItems accidentalsOnLines is ordered. We receive the
correct accidental order from left to right and only need
to place the gaps"""
for i, (accidentalOnLine, pitchMod) in enumerate(self.staticItem["accidentalsOnLines"]):
glyph = GuiKeySignature.accidentals[pitchMod]()
glyph.setParentItem(self)
glyph.setPos(constantsAndConfigs.magicPixel + i*1.5*constantsAndConfigs.magicPixel, constantsAndConfigs.stafflineGap * accidentalOnLine / 2) #These accidental graphics are shifted to the left in the .svg so they can be placed just as noteheads and match automatically. So we set them +x here.
if not self.staticItem["accidentalsOnLines"]:
#No accidentals in the keysig (C-Major, D-Dorian etc.) gets a big natural sign.
self.bigNatural = GuiKeySignature.accidentals[0]() #"big natural"... hö hö hö hö
self.bigNatural.setParentItem(self)
self.bigNatural.setPos(constantsAndConfigs.magicPixel, constantsAndConfigs.stafflineGap * -1)
self.rootGlyph = QtWidgets.QGraphicsSimpleTextItem(constantsAndConfigs.baseNotes[self.staticItem["root"]])
self.rootGlyph.setParentItem(self)
self.rootGlyph.setPos(constantsAndConfigs.negativeMagicPixel, 2*constantsAndConfigs.stafflineGap)
accidentals = { #QGraphicsItems can only be used once so we have to save a class constructor here instead of an instance.
0 : lambda: QtSvg.QGraphicsSvgItem(":svg/accidentalsNatural.svg"), #normaly we don't receive those, but it is possible to ask for explicit naturals in the backend and in lilypond.
10 : lambda: QtSvg.QGraphicsSvgItem(":svg/accidentalsSharp.svg"),
20 : lambda: QtSvg.QGraphicsSvgItem(":svg/accidentalsDoublesharp.svg"),
-10 : lambda: QtSvg.QGraphicsSvgItem(":svg/accidentalsFlat.svg"),
-20 : lambda: QtSvg.QGraphicsSvgItem(":svg/accidentalsFlatFlat.svg"),
}
class GuiClef(GuiItem):
def __init__(self, staticItem):
super(GuiClef, self).__init__(staticItem)
self.createGraphicItemsFromData()
def createGraphicItemsFromData(self):
self.glyph = GuiClef.clefs[self.staticItem["clef"]]()
self.glyph.setParentItem(self)
self.glyph.setPos(-5, -5 * constantsAndConfigs.stafflineGap)
#self.text = QtWidgets.QGraphicsSimpleTextItem(self.staticItem["clef"].title())
#self.text.setParentItem(self)
#self.text.setPos(0, -5 * constantsAndConfigs.stafflineGap)
self.marker = GuiPositionMarker(-5)
self.marker.setParentItem(self)
self.marker.setPos(0,0)
clefs = { #QGraphicsItems can only be used once so we have to save a class constructor here instead of an instance.
"treble" : lambda: QtSvg.QGraphicsSvgItem(":svg/clefTreble.svg"),
"treble_8" : lambda: QtSvg.QGraphicsSvgItem(":svg/clefTreble_8.svg"),
"treble^8" : lambda: QtSvg.QGraphicsSvgItem(":svg/clefTreble^8.svg"),
"bass" : lambda: QtSvg.QGraphicsSvgItem(":svg/clefBass.svg"),
"bass_8" : lambda: QtSvg.QGraphicsSvgItem(":svg/clefBass_8.svg"),
"alto" : lambda: QtSvg.QGraphicsSvgItem(":svg/clefAlto.svg"),
"midiDrum" : lambda: QtSvg.QGraphicsSvgItem(":svg/clefPercussion.svg"),
"percussion" : lambda: QtSvg.QGraphicsSvgItem(":svg/clefPercussion.svg"),
}
class GuiTimeSignature(GuiItem):
def __init__(self, staticItem):
raise Exception("Don't use this item. It will be deleted in future versions. Use a Metrical Instruction")
super().__init__(staticItem)
self.setPos(0, constantsAndConfigs.stafflineGap)
self.createGraphicItemsFromData()
def createGraphicItemsFromData(self):
#higher number, how many notes
for i, charInt in enumerate(str(self.staticItem["nominator"])):
n = GuiTimeSignature.digits[int(charInt)]
charInt = QtSvg.QGraphicsSvgItem()
charInt.setSharedRenderer(GuiTimeSignature.renderer)
charInt.setElementId(n)
charInt.setPos(i*2*constantsAndConfigs.magicPixel, -1*constantsAndConfigs.stafflineGap)
charInt.setParentItem(self)
#lower number, which note type
for i, charInt in enumerate(str(self.staticItem["denominator"])): #2^n
n = GuiTimeSignature.digits[int(charInt)]
charInt = QtSvg.QGraphicsSvgItem()
charInt.setSharedRenderer(GuiTimeSignature.renderer)
charInt.setElementId(n)
charInt.setPos(i*2*constantsAndConfigs.magicPixel, constantsAndConfigs.stafflineGap)
charInt.setParentItem(self)
renderer = QtSvg.QSvgRenderer(":svg/numbers.svg")
digits = "zero one two three four five six seven eight nine".split() #a list
class GuiMetricalInstruction(GuiItem):
def __init__(self, staticItem):
super().__init__(staticItem)
if staticItem["oneMeasureInTicks"] == 0:
#Basically just a manual barline
displayString = "Metrical Off"
markerPosition = -2
markerHeight = 4
else:
#Format the Tree of Instructions
realTree = eval(staticItem["treeOfInstructions"])
if not type(realTree[0]) is tuple: #first order measure. like 3/4 or 2/4 or anything with just one stressed position
realTree = (realTree, ) #created nested iterator
r = self.treeToPrettyString(realTree)
r = r.__repr__()[1:-1].replace("'", "")
onlyTopLevelElements = not any(isinstance(el, list) for el in r)
if onlyTopLevelElements:
r = r.replace(",", "")
displayString = "Metrical " + r
markerHeight = -7
markerPosition = 1
self.text = QtWidgets.QGraphicsSimpleTextItem(displayString)
self.text.setParentItem(self)
self.text.setPos(0, -7 * constantsAndConfigs.stafflineGap)
self.marker = GuiPositionMarker(markerHeight, markerPosition)
self.marker.setParentItem(self)
self.marker.setPos(0,0)
def treeToPrettyString(self, tree):
"""Convert a metrical instruction into a pretty string with note symbols
For example
((53760, 53760), (53760, 53760))
which is ((D4, D4), (D4, D4))
into
2𝅘𝅥 2𝅘𝅥
"""
result = []
for element in tree:
if type(element) is tuple:
l = self.treeToPrettyString(element)
l = ["{}{}".format(sum(1 for e in grouper), note) for note, grouper in groupby(l)]
if len(l) == 1:
l = l[0] #makes formatting clearerm
result.append(l)
else:
assert type(element) is int
noteString = constantsAndConfigs.realNoteDisplay[element]
result.append(noteString)
return result
class GuiBlockEndMarker(GuiItem):
def __init__(self, staticItem):
super(GuiBlockEndMarker, self).__init__(staticItem)
self.glyph = QtSvg.QGraphicsSvgItem(":svg/blockEnd.svg")
self.createGraphicItemsFromData()
def createGraphicItemsFromData(self):
self.glyph.setParentItem(self)
class GuiDynamicSignature(GuiItem):
def __init__(self, staticItem):
super(GuiDynamicSignature, self).__init__(staticItem)
self.glyph = QtWidgets.QGraphicsSimpleTextItem(staticItem["keyword"])
self.createGraphicItemsFromData()
def createGraphicItemsFromData(self):
self.glyph.setPos(0, 5*constantsAndConfigs.stafflineGap)
self.glyph.setParentItem(self)
class GuiMultiMeasureRest(GuiItem):
def __init__(self, staticItem):
super(GuiMultiMeasureRest, self).__init__(staticItem)
self.createGraphicItemsFromData()
def createGraphicItemsFromData(self):
w = self.staticItem["completeDuration"] / constantsAndConfigs.ticksToPixelRatio - constantsAndConfigs.magicPixel*2
if int(self.staticItem["numberOfMeasures"]) == self.staticItem["numberOfMeasures"]: #just an int?
numberOfMeasuresString = str(int(self.staticItem["numberOfMeasures"]))
else:
numberOfMeasuresString = str(self.staticItem["numberOfMeasures"]) #include the decimal dot
rect = QtWidgets.QGraphicsRectItem(constantsAndConfigs.magicPixel,0, w, constantsAndConfigs.stafflineGap) #x,y, w, h
rect.setBrush(QtCore.Qt.black)
rect.setParentItem(self)
self.rect = rect #for stretching
leftBlock = QtWidgets.QGraphicsRectItem(2, -1* constantsAndConfigs.stafflineGap, constantsAndConfigs.magicPixel, 3*constantsAndConfigs.stafflineGap)
leftBlock.setBrush(QtCore.Qt.black)
leftBlock.setParentItem(self)
rightBlock = QtWidgets.QGraphicsRectItem(0, -1* constantsAndConfigs.stafflineGap, constantsAndConfigs.magicPixel, 3*constantsAndConfigs.stafflineGap) #x, y, w, h
rightBlock.setBrush(QtCore.Qt.black)
#rightBlock.setPos(w,0)
rightBlock.setPos(rect.rect().right(),0)
rightBlock.setParentItem(self)
self.rightBlock = rightBlock #for stretching
for i, char in enumerate(numberOfMeasuresString):
if char == ".":
continue #TODO: Maybe warn about that? MMR below 1 are not valid but they are needed for editing purposes. Sometimes you need to go through such a value.
else:
n = GuiTimeSignature.digits[int(char)]
char = QtSvg.QGraphicsSvgItem()
char.setSharedRenderer(GuiTimeSignature.renderer)
char.setElementId(n)
#char.setPos(i*4*constantsAndConfigs.magicPixel + 4* constantsAndConfigs.magicPixel, -3*constantsAndConfigs.stafflineGap)
char.setPos(leftBlock.rect().width(), -3*constantsAndConfigs.stafflineGap)
char.setScale(1.5)
char.setParentItem(self)
self.setPos(0, -3 * constantsAndConfigs.stafflineGap)
def stretchXCoordinates(self, factor):
"""Reposition the items on the X axis.
Call goes through all parents/children, starting from ScoreView._stretchXCoordinates.
Docstring there."""
stretchRect(self.rect, factor)
self.rightBlock.setX(self.rightBlock.pos().x() * factor)
#self.char.setX(self.char.pos().x() * factor)
class GuiLegatoSlur(GuiItem):
def __init__(self, staticItem):
super().__init__(staticItem)
if staticItem["slur"] == "open":
self.glyph = QtWidgets.QGraphicsSimpleTextItem("(")
self.glyph.setPos(2,-5*constantsAndConfigs.stafflineGap)
else:
assert staticItem["slur"] == "close"
self.glyph = QtWidgets.QGraphicsSimpleTextItem(")")
self.glyph.setPos(-4,-5*constantsAndConfigs.stafflineGap)
self.createGraphicItemsFromData()
def createGraphicItemsFromData(self):
#self.glyph.setPos(0, -5*constantsAndConfigs.stafflineGap)
self.glyph.setParentItem(self)
class GuiGenericText(GuiItem):
def __init__(self, staticItem):
super().__init__(staticItem)
self.glyph = QtWidgets.QGraphicsSimpleTextItem(staticItem["UIstring"])
self.glyph.setPos(0, -5*constantsAndConfigs.stafflineGap)
self.glyph.setParentItem(self)
def staticItem2Item(staticItem):
typ = staticItem["type"]
if typ is "Chord":
return GuiChord(staticItem)
elif typ is "Rest":
return GuiRest(staticItem)
elif typ is "LegatoSlur":
return GuiLegatoSlur(staticItem)
elif typ is "MultiMeasureRest":
return GuiMultiMeasureRest(staticItem)
elif typ is "DynamicSignature":
return GuiDynamicSignature(staticItem)
elif typ is "Clef":
return GuiClef(staticItem)
elif typ is "KeySignature":
return GuiKeySignature(staticItem)
#elif typ is "TimeSignature":
# return GuiTimeSignature(staticItem)
elif typ is "MetricalInstruction":
return GuiMetricalInstruction(staticItem)
elif typ is "BlockEndMarker":
return GuiBlockEndMarker(staticItem)
elif typ in ("InstrumentChange", "ChannelChange",):
return GuiGenericText(staticItem)
else:
raise ValueError("Unknown Item Type:", staticItem)

200
qtgui/mainwindow.py

@ -0,0 +1,200 @@
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Copyright 2018, Nils Hilbricht, Germany ( https://www.hilbricht.net )
This file is part of the Laborejo Software Suite ( https://www.laborejo.org ),
more specifically its template base application.
The Template Base Application is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
import logging; logging.info("import {}".format(__file__))
#Standard Library Modules
import os.path
#Third Party Modules
from PyQt5 import QtWidgets, QtCore, QtGui
#Template Modules
from template.qtgui.mainwindow import MainWindow as TemplateMainWindow
from template.qtgui.menu import Menu
from template.qtgui.about import About
#Our modules
import engine.api as api
from midiinput.stepmidiinput import stepMidiInput #singleton instance
from .constantsAndConfigs import constantsAndConfigs
from .menu import MenuActionDatabase
from .scoreview import ScoreView
from .structures import GuiScore
from .trackEditor import TrackEditor
from .resources import *
class MainWindow(TemplateMainWindow):
def __init__(self):
"""The order of calls is very important.
The split ploint is calling the super.__init. Some functions need to be called before,
some after.
For example:
The about dialog is created in the template main window init. So we need to set additional
help texts before that init.
"""
#Inject more help texts in the templates About "Did You Know" field.
#About.didYouKnow is a class variable.
#Make the first three words matter!
#Do not start them all with "You can..." or "...that you can", in response to the Did you know? title.
#We use injection into the class and not a parameter because this dialog gets shown by creating an object. We can't give the parameters when this is shown via the mainWindow menu.
About.didYouKnow = [
QtCore.QCoreApplication.translate("About", "This is an example application. Extend it to your liking. Start by editing config.py")
] + About.didYouKnow
super().__init__()
#New menu entries and template-menu overrides
self.menu.addMenuEntry("menuDebug", "actionRedrawAllTracks", "Redraw all Tracks")
self.menu.connectMenuEntry("actionSave", api.save)
self.menu.hideSubmenu("menuFile")
self.menu.hideSubmenu("menuGeneric")
api.callbacks.setCursor.append(self.updateStatusBar) #returns a dict. This get's called after loading the file so the status bar is filled on self.show
self.initiGuiSharedDataToSave()
#Create the Main Widgets in the Stacked Widget
self.scoreView = ScoreView(self)
self.ui.mainStackWidget.addWidget(self.scoreView)
self.ui.mainStackWidget.setCurrentIndex(self.ui.mainStackWidget.indexOf(self.scoreView))
self.trackEditor = QtWidgets.QScrollArea()
self.trackEditor.setWidgetResizable(True)
self.actualTrackEditor = TrackEditor(self)
self.trackEditor.setWidget(self.actualTrackEditor)
self.ui.actionData_Editor.setChecked(False)
self.ui.mainStackWidget.addWidget(self.trackEditor)
#Bind shortcuts to actions (as init effect)
#TODO: Integrate better into template menu system.
self.menuActionDatabase = MenuActionDatabase(self) #The menu needs to be started before api.startEngine
#Make toolbars unclosable
##self.ui.toolBar.setContextMenuPolicy(QtCore.Qt.PreventContextMenu) #only for right mouse clicks. Keyboard context menu key still works.
##self.ui.leftToolBar.setContextMenuPolicy(QtCore.Qt.PreventContextMenu)
self.setContextMenuPolicy(QtCore.Qt.NoContextMenu) #instead prevent the main window from having context menus.
#The statusbar is used for tooltips. To make it permanent we add our own widget
self.statusLabel = QtWidgets.QLabel()
self.statusBar().insertPermanentWidget(0, self.statusLabel)
self.scoreView.setFocus() #So the user can start typing from moment 0.
self.start() #Inherited from template main window #This shows the GUI, or not, depends on the NSM gui save setting. We need to call that after the menu, otherwise the about dialog will block and then we get new menu entries, which looks strange.
stepMidiInput.start() #imported directly. Handles everything else internally, we just need to start it after the engine somehow. Which is here.
#Populate the left toolbar. The upper toolbar is created in menu.py
self.ui.leftToolBar.addWidget(LeftToolBarPrevailingDuration(self)) #needs stepmidiinput started
#Now all tracks and items from a loaded backend-file are created. We can setup the initial editMode and viewPort.
self.scoreView.updateMode() #hide CCs at program start and other stuff
self.scoreView.scoreScene.grid.redrawTickGrid() #Init the grid only after everything got loaded and drawn to prevent a gap in the display. #TODO: which might be a bug. but this here works fine.
def initiGuiSharedDataToSave(self):
"""Called by init"""
if not "last_export_dir" in api.session.guiSharedDataToSave:
api.session.guiSharedDataToSave["last_export_dir"] = os.path.expanduser("~")
if "grid_opacity" in api.session.guiSharedDataToSave:
constantsAndConfigs.gridOpacity = float(api.session.guiSharedDataToSave["grid_opacity"])
if "grid_rhythm" in api.session.guiSharedDataToSave:
#setting this is enough. When the grid gets created it fetches the constantsAndConfigs value.
#Set only in submenus.GridRhytmEdit
constantsAndConfigs.gridRhythm = int(api.session.guiSharedDataToSave["grid_rhythm"])
#Stretch
if "ticks_to_pixel_ratio" in api.session.guiSharedDataToSave:
#setting this is enough. Drawing on startup uses the constantsAndConfigs value.
#Set only in ScoreView._stretchXCoordinates
constantsAndConfigs.ticksToPixelRatio = float(api.session.guiSharedDataToSave["ticks_to_pixel_ratio"])
if "zoom_factor" in api.session.guiSharedDataToSave:
#setting this is enough. Drawing on startup uses the constantsAndConfigs value.
#Set only in ScoreView._zoom
constantsAndConfigs.zoomFactor = float(api.session.guiSharedDataToSave["zoom_factor"])
def updateStatusBar(self, exportCursorDict):
"""Every cursor movement updates the statusBar message"""
c = exportCursorDict
i = c["item"]
if i:
ly = i.lilypond()
if (not ly) or len(ly) > 10:
ly = ""
else:
ly = "Lilypond: <b>{}</b>".format(ly.replace("<", "&#60;").replace(">", "&#62;"))
itemMessage = "Item: <b>{}</b> {}".format(i.__class__.__name__, ly)
else:
itemMessage = "" #Appending
positionMessage = "Pos: <b>{}</b> Ticks: <b>{}</b> Pitch: <b>{}</b>".format(c["position"], c["tickindex"], c["lilypondPitch"])
message = "{} | {}".format(itemMessage, positionMessage)
#self.statusBar().showMessage(message) #overriden by tool tips, even empty ones
self.statusLabel.setText(message)
def toggleMainView(self):
if self.ui.actionData_Editor.isChecked():
self.ui.mainStackWidget.setCurrentIndex(self.ui.mainStackWidget.indexOf(self.trackEditor))
self.scoreView.setEnabled(False) #disables shortcut like cursor movement, but not all of them.
self.menuActionDatabase.writeProtection(True)
self.trackEditor.setEnabled(True)
else:
self.ui.mainStackWidget.setCurrentIndex(self.ui.mainStackWidget.indexOf(self.scoreView))
self.scoreView.setEnabled(True)
self.menuActionDatabase.writeProtection(False)
self.scoreView.updateMode()
self.trackEditor.setEnabled(False)
class LeftToolBarPrevailingDuration(QtWidgets.QLabel):
def __init__(self, mainWindow):
super().__init__(self.makeText(api.D4))
self.mainWindow = mainWindow
#self.setFont(constantsAndConfigs.musicFont) #TODO replace with svg
api.callbacks.prevailingBaseDurationChanged.append(self.changed)
def makeText(self, baseDuration):
if not stepMidiInput.midiInIsActive:
return ""
labelText = "<font size=6>"
for i in (api.D1, api.D2, api.D4, api.D8, api.D16): #,api.DB, api.DL):
if i == baseDuration:
labelText += "<font color='cyan'>"
labelText += constantsAndConfigs.realNoteDisplay[i]
if i == baseDuration:
labelText += "</font>"
labelText += "<br>"
labelText += "</font>"
return labelText
def changed(self, newBaseDuration):
self.setText(self.makeText(newBaseDuration))

570
qtgui/menu.py

@ -0,0 +1,570 @@
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Copyright 2017, Nils Hilbricht, Germany ( https://www.hilbricht.net )
This file is part of Laborejo ( https://www.laborejo.org )
Laborejo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from PyQt5 import QtCore, QtGui, QtWidgets
import os.path
import engine.api as api
from midiinput.stepmidiinput import stepMidiInput #singleton instance
from .constantsAndConfigs import constantsAndConfigs
from .submenus import SecondaryClefMenu, SecondaryKeySignatureMenu, SecondaryDynamicsMenu, SecondaryMetricalInstructionMenu, SecondaryTempoChangeMenu, SecondaryTemporaryTempoChangeMenu, SecondarySplitMenu, TransposeMenu, pedalNoteChooser, SecondaryProperties, SecondaryProgramChangeMenu, SecondaryChannelChangeMenu
class ModalKeys(object):
def __init__(self):
pass
def keyRest(self):
if stepMidiInput.midiInIsActive:
baseDuration = api.session.data.cursor.prevailingBaseDuration
api.insertRest(baseDuration)
#else: deactivated.
def key1(self):
if stepMidiInput.midiInIsActive: api.prevailing1()
else: api.insert1()
def key2(self):
if stepMidiInput.midiInIsActive: api.prevailing2()
else: api.insert2()
def key3(self):
if stepMidiInput.midiInIsActive: api.prevailing4()
else: api.insert4()
def key4(self):
if stepMidiInput.midiInIsActive: api.prevailing8()
else: api.insert8()
def key5(self):
if stepMidiInput.midiInIsActive: api.prevailing16()
else: api.insert16()
def key6(self):
if stepMidiInput.midiInIsActive: api.prevailing32()
else: api.insert32()
def key7(self):
if stepMidiInput.midiInIsActive: api.prevailingBrevis()
else: api.insertBrevis()
def key8(self):
if stepMidiInput.midiInIsActive: api.prevailingLonga()
else: api.insertLonga()
def key9(self):
pass
def key0(self):
pass
class MenuActionDatabase(object):
"""There are different edit and view modes in Laborejo-Qt:
Main Program
ScoreView
NoteEdit
Noteheads
Rectangles
BlockEdit
Transparent Block Handles
CCEdit
CC 0
CC 1
...
CC 127
DataEditor
Each level has shorcuts associated with them which depend on the context.
To implement those we use the qt shortcut contexts. See QAction docs.
Additionaly there is midi-in and the modal number keys, which are
connected to each other. Without midi in the modal keys insert notes,
in midi mode they choose the duration for the next midi key.
"""
def __init__(self, mainWindow):
self.mainWindow = mainWindow
self.modalKeys = ModalKeys()
modes = QtWidgets.QActionGroup(self.mainWindow)
modes.addAction(self.mainWindow.ui.actionNotation_Mode)
modes.addAction(self.mainWindow.ui.actionBlock_Mode)
modes.addAction(self.mainWindow.ui.actionCC_Mode)
self.mainWindow.ui.actionNotation_Mode.setChecked(True)
self.rememberMidi = stepMidiInput.midiInIsActive
api.callbacks.historyChanged.append(self.renameUndoRedoByHistory)
api.callbacks.metronomeChanged.append(lambda v: self.mainWindow.ui.actionMetronome_Enabled.setChecked(v["enabled"])) #accompanied by a normal menu action down below
self.actionsWithoutMenu = { #these are only available in Note Edit Mode, not in CC Edit Mode etc. but have no menu entry.
#Of course these actions have shortcuts, they are in a menu, visible and editable in qt-Designer, which gets hidden on program start.
self.mainWindow.ui.actionLeft : api.left,
self.mainWindow.ui.actionRight : api.right,
self.mainWindow.ui.actionSelectLeft : api.selectLeft,
self.mainWindow.ui.actionSelectRight : api.selectRight,
self.mainWindow.ui.actionMeasureLeft : api.measureLeft,
self.mainWindow.ui.actionMeasureRight : api.measureRight,
self.mainWindow.ui.actionSelectMeasureLeft : api.selectMeasureLeft,
self.mainWindow.ui.actionSelectMeasureRight : api.selectMeasureRight,
self.mainWindow.ui.actionBlockLeft : api.blockLeft,
self.mainWindow.ui.actionBlockRight : api.blockRight,
self.mainWindow.ui.actionSelectBlockLeft : api.selectBlockLeft,
self.mainWindow.ui.actionSelectBlockRight : api.selectBlockRight,
self.mainWindow.ui.actionHead : api.head,
self.mainWindow.ui.actionTail : api.tail,
self.mainWindow.ui.actionSelectHead : api.selectHead,
self.mainWindow.ui.actionSelectTail : api.selectTail,
self.mainWindow.ui.actionTrackUp : api.trackUp,
self.mainWindow.ui.actionTrackDown : api.trackDown,
self.mainWindow.ui.actionTrackFirst : api.trackFirst,
self.mainWindow.ui.actionTrackLast : api.trackLast,
self.mainWindow.ui.actionSelectTrackUp : api.selectTrackUp,
self.mainWindow.ui.actionSelectTrackDown : api.selectTrackDown,
self.mainWindow.ui.actionSelectTrackFirst : api.selectTrackFirst,
self.mainWindow.ui.actionSelectTrackLast : api.selectTrackLast,
self.mainWindow.ui.actionUp : api.up,
self.mainWindow.ui.actionDown : api.down,
self.mainWindow.ui.actionUpOctave : api.upOctave,
self.mainWindow.ui.actionDownOctave : api.downOctave,
self.mainWindow.ui.actionSelectUp : api.up, #these are the same as up and down. But for a good user experience they should work if shift is pressed down as well.
self.mainWindow.ui.actionSelectDown : api.down,
self.mainWindow.ui.actionSelectUpOctave : api.upOctave,
self.mainWindow.ui.actionSelectDownOctave : api.downOctave,
self.mainWindow.ui.actionSelectAllTracks : api.selectAllTracks,
self.mainWindow.ui.actionSelectTrack : api.selectTrack,
self.mainWindow.ui.actionSelectMeasureColumn : api.selectMeasureColumn,
#CC Edit Actions. Share the same shortcuts as some of the actions above. But only one of these is enabled at any time.
#Don't forget to add them to the list below: self.ccEditActions
#...
}
self.actions = { #always available in the main window. It doesn't matter if you change to CC mode or Note Edit etc.
self.mainWindow.ui.actionToggle_Notehead_Rectangles : self.mainWindow.scoreView.toggleNoteheadsRectangles,
self.mainWindow.ui.actionData_Editor : self.mainWindow.toggleMainView,
self.mainWindow.ui.actionProperties : lambda: SecondaryProperties(self.mainWindow),
self.mainWindow.ui.actionFollow_Playhead : self.mainWindow.scoreView.toggleFollowPlayhead,
#Modes Submenu
self.mainWindow.ui.actionNotation_Mode : self.mainWindow.scoreView.updateMode,
self.mainWindow.ui.actionBlock_Mode : self.mainWindow.scoreView.updateMode,
self.mainWindow.ui.actionCC_Mode : self.mainWindow.scoreView.updateMode,
self.mainWindow.ui.actionChange_Grid_Rhythm : self.mainWindow.scoreView.changeGridRhythm,
self.mainWindow.ui.actionAdd_Track : api.newEmptyTrack,
self.mainWindow.ui.actionDelete_Current_Track : api.deleteCurrentTrack,
self.mainWindow.ui.actionUse_Current_Track_as_Metronome : api.useCurrentTrackAsMetronome,
self.mainWindow.ui.actionMidi_In_is_Active : self.toggleMidiInIsActive,
#self.mainWindow.ui.actionZoom_In_Score : self.mainWindow.scoreView.zoomIn,
#self.mainWindow.ui.actionZoom_Out_Score : self.mainWindow.scoreView.zoomOut,
self.mainWindow.ui.actionWiden_Score_View : self.mainWindow.scoreView.widen,
self.mainWindow.ui.actionShrink_Score_View : self.mainWindow.scoreView.shrinken,
self.mainWindow.ui.actionSave : api.save,
self.mainWindow.ui.actionShow_PDF : api.showPDF,
self.mainWindow.ui.actionExport_to_Ly : self.exportLy,
self.mainWindow.ui.actionPlayFromBeginning : api.playFromStart,
self.mainWindow.ui.actionPlayPause : api.playPause,
self.mainWindow.ui.actionPlayFromEditCursor : api.playFromCursor,
self.mainWindow.ui.actionMetronome_Enabled : api.toggleMetronome, #toggle is enough. The callback makes sure all the checkboxes have the correct value.
}
self.noteEditActions = { #these are only available in Note Edit Mode, not in CC Edit Mode etc. #all xxxEditActions are mutually exclusive.
self.mainWindow.ui.actionBeam : api.toggleBeam,
self.mainWindow.ui.actionRemoveBeams : api.removeBeam,
self.mainWindow.ui.actionLegatoSlur : api.insertLegatoSlur,
self.mainWindow.ui.actionClef : SecondaryClefMenu(self.mainWindow), #no lambda for submenus. They get created here once and have a __call__ option that executes them. There is no internal state in these menus.
self.mainWindow.ui.actionKey_Signature : SecondaryKeySignatureMenu(self.mainWindow),
self.mainWindow.ui.actionDynamics : SecondaryDynamicsMenu(self.mainWindow),
self.mainWindow.ui.actionMulti_Measure_Rest : lambda: api.insertMultiMeasureRest(1),
self.mainWindow.ui.actionMetrical_Instruction : SecondaryMetricalInstructionMenu(self.mainWindow),
self.mainWindow.ui.actionTempo_Change : lambda: SecondaryTempoChangeMenu(self.mainWindow),
self.mainWindow.ui.actionDelete_Tempo_Change : api.removeCurrentTempoItem,
self.mainWindow.ui.actionTemporary_Tempo_Change : SecondaryTemporaryTempoChangeMenu(self.mainWindow),
self.mainWindow.ui.actionSharpen_Note : api.sharpenNote,
self.mainWindow.ui.actionFlatten_Note : api.flattenNote,
self.mainWindow.ui.actionStep_Up : api.stepUp,
self.mainWindow.ui.actionStep_Down : api.stepDown,
self.mainWindow.ui.actionOctave_Up : api.stepUpOctave,
self.mainWindow.ui.actionOctave_Down : api.stepDownOctave,
self.mainWindow.ui.actionTransposeChord : lambda: TransposeMenu(self.mainWindow, "item"),
self.mainWindow.ui.actionVelocityMore : lambda: self.mainWindow.scoreView._switchToRectanglesForFunction(api.moreVelocity),
self.mainWindow.ui.actionVelocityLess : lambda: self.mainWindow.scoreView._switchToRectanglesForFunction(api.lessVelocity),
self.mainWindow.ui.actionDurationModMore : lambda: self.mainWindow.scoreView._switchToRectanglesForFunction(api.moreDuration),
self.mainWindow.ui.actionDurationModLess : lambda: self.mainWindow.scoreView._switchToRectanglesForFunction(api.lessDuration),
self.mainWindow.ui.actionReset_Velocity_Duration_Mod : lambda: self.mainWindow.scoreView._switchToRectanglesForFunction(api.resetDurationVelocity),
self.mainWindow.ui.actionAugment : api.augment,
self.mainWindow.ui.actionDiminish : api.diminish,
self.mainWindow.ui.actionDots : api.dot,
self.mainWindow.ui.actionTriplet : api.triplet,
#self.mainWindow.ui.actionCustomTuplet : something with a GUI that allows any type and number of nested tuplets, #TODO
self.mainWindow.ui.actionStaccato : api.staccato,
self.mainWindow.ui.actionTenuto : api.tenuto,
self.mainWindow.ui.actionTie : api.tie,
self.mainWindow.ui.actionSplit_in_2 : lambda: api.split(2),
self.mainWindow.ui.actionSplit_in_3 : lambda: api.split(3),
self.mainWindow.ui.actionCustom_Split : SecondarySplitMenu(self.mainWindow), #no lambda for submenus. They get created here once and have a __call__ option that executes them. There is no internal state in these menus.
self.mainWindow.ui.actionMIDI_Channel_Plus : api.midiRelativeChannelPlus,
self.mainWindow.ui.actionMIDI_Channel_Minus : api.midiRelativeChannelMinus,
self.mainWindow.ui.actionMIDI_Channel_Reset : api.midiRelativeChannelReset,
self.mainWindow.ui.actionAppend_Block : api.appendBlock,
self.mainWindow.ui.actionSplit_Current_Block : api.splitBlock,
self.mainWindow.ui.actionJoin_with_next_Block : api.joinBlock,
self.mainWindow.ui.actionDuplicate : api.duplicateCurrentBlock,
self.mainWindow.ui.actionCreate_Linked_Copy : api.duplicateContentLinkCurrentBlock,
self.mainWindow.ui.actionUnlink_Current_Block : api.unlinkCurrentBlock,
self.mainWindow.ui.actionDelete_Current_Block : api.deleteCurrentBlock,
self.mainWindow.ui.actionTranspose_Score : lambda: TransposeMenu(self.mainWindow, "score"),
self.mainWindow.ui.actionDelete_All_Empty_Blocks : api.deleteEmptyBlocks,
self.mainWindow.ui.actionDelete : api.delete,
self.mainWindow.ui.actionBackspace : api.backspace,
self.mainWindow.ui.actionAddCursorNoteToChord : api.addCursorNoteToChord,
self.mainWindow.ui.actionDeleteCursorNoteFromChord : api.deleteCursorNoteFromChord,
self.mainWindow.ui.actionCut : api.cutObjects,
self.mainWindow.ui.actionCopy : api.copyObjects,
self.mainWindow.ui.actionPaste : api.pasteObjects,
self.mainWindow.ui.actionDuplicateItem : api.duplicate,
self.mainWindow.ui.actionUndo : api.undo,
self.mainWindow.ui.actionRedo : api.redo,
self.mainWindow.ui.actionRedrawAllTracks : api.updateCallbackAllTracks,
#Toolbox
#Note Generation
self.mainWindow.ui.actionPedalNotes : lambda: pedalNoteChooser(self.mainWindow),
self.mainWindow.ui.actionRandom_chromatic_in_clef_range: api.insertRandomChromaticInClefRange,
self.mainWindow.ui.actionRandom_in_scale_in_clef_range: api.insertRandomFromScaleInClefRange,
self.mainWindow.ui.actionRandom_pitch_from_clipboard: api.insertRandomFromClipboard,
self.mainWindow.ui.actionRandom_in_scale_in_octave_around_cursor: api.insertRandomFromScaleAuthenticModeCursor,
self.mainWindow.ui.actionRandom_in_scale_in_cursor_plus_octave: api.insertRandomFromScaleHypoModeCursor,
self.mainWindow.ui.actionMirror_around_Cursor: api.mirrorAroundCursor,
#Note Sorting
self.mainWindow.ui.actionRandom: api.nothing,
self.mainWindow.ui.actionReverse: api.nothing,
self.mainWindow.ui.actionAscending: api.nothing,
self.mainWindow.ui.actionDescending: api.nothing,
#Midi
self.mainWindow.ui.actionInstrument_Change: SecondaryProgramChangeMenu(self.mainWindow), #no lambda for submenus. They get created here once and have a __call__ option that executes them. There is no internal state in these menus.
self.mainWindow.ui.actionChannel_Change: SecondaryChannelChangeMenu(self.mainWindow), #no lambda for submenus. They get created here once and have a __call__ option that executes them. There is no internal state in these menus.
}
self.modalActions = { #these are only available in Note Edit Mode, not in CC Edit Mode etc.
self.mainWindow.ui.actionModal1 : self.modalKeys.key1,
self.mainWindow.ui.actionModal2 : self.modalKeys.key2,
self.mainWindow.ui.actionModal3 : self.modalKeys.key3,
self.mainWindow.ui.actionModal4 : self.modalKeys.key4,
self.mainWindow.ui.actionModal5 : self.modalKeys.key5,
self.mainWindow.ui.actionModal6 : self.modalKeys.key6,
self.mainWindow.ui.actionModal7 : self.modalKeys.key7, #brevis
self.mainWindow.ui.actionModal8 : self.modalKeys.key8, #longa
self.mainWindow.ui.actionPrevailingRest : self.modalKeys.keyRest,
self.mainWindow.ui.actionShift_modal1 : api.insertRest1,
self.mainWindow.ui.actionShift_modal2 : api.insertRest2,
self.mainWindow.ui.actionShift_modal3 : api.insertRest4,
self.mainWindow.ui.actionShift_modal4 : api.insertRest8,
self.mainWindow.ui.actionShift_modal5 : api.insertRest16,
self.mainWindow.ui.actionShift_modal6 : api.insertRest32,
#self.mainWindow.ui.actionShift_modal7 : api.insertRestBrevis,
#self.mainWindow.ui.actionShift_modal8 : api.insertRestLonga,
#self.mainWindow.ui.actionShift_modal7 : api.insertRest64,
#self.mainWindow.ui.actionShift_modal8 : api.insertRest128,
}
self.nonEditingMusicActions = [ #These are available in CC Edit Mode, Note Edit mode etc.
self.mainWindow.ui.actionPlayFromBeginning,
self.mainWindow.ui.actionPlayPause,
self.mainWindow.ui.actionPlayFromEditCursor,
self.mainWindow.ui.actionToggle_Notehead_Rectangles,
self.mainWindow.ui.actionData_Editor,
self.mainWindow.ui.actionFollow_Playhead,
self.mainWindow.ui.actionNotation_Mode,
self.mainWindow.ui.actionBlock_Mode,
self.mainWindow.ui.actionCC_Mode,
self.mainWindow.ui.actionChange_Grid_Rhythm,
self.mainWindow.ui.actionAdd_Track,
self.mainWindow.ui.actionUndo,
self.mainWindow.ui.actionRedo,
#self.mainWindow.ui.actionZoom_In_Score,
#self.mainWindow.ui.actionZoom_Out_Score,
self.mainWindow.ui.actionWiden_Score_View,
self.mainWindow.ui.actionShrink_Score_View,
self.mainWindow.ui.actionSave,
]
self.ccEditActions = [ #only in CC edit, when editing user points. #all xxxEditActions are mutually exclusive. These are defined in non-menu actions above.
# self.mainWindow.ui.CCactionDelete,
]
#Prepare non-designer widgets. Designer can't put normal widgets in a toolbar, but Qt can.
#Eventhough this is a dict, which has no order, the CREATION has an order. So the first item in the dict will be the first item in the toolBar
self.extraToolBarWidgets = {
"snapToGrid" : self.mainWindow.ui.toolBar.addWidget(ToolBarSnapToGrid(mainWindow=self.mainWindow)),
"metronome" : self.mainWindow.ui.toolBar.addWidget(ToolBarMetronome(mainWindow=self.mainWindow)),
"playbackSpeed" : self.mainWindow.ui.toolBar.addWidget(ToolBarPlaybackSpeed(mainWindow=self.mainWindow)),
"ccType" : self.mainWindow.ui.toolBar.addWidget(ToolBarCCType(mainWindow=self.mainWindow)), #keep this at the end of the toolbar because it toggles visibility
}
self.toolbarContexts = {
"notation" : [self.extraToolBarWidgets["snapToGrid"], self.extraToolBarWidgets["metronome"], self.extraToolBarWidgets["playbackSpeed"], ],
"cc" : [self.extraToolBarWidgets["snapToGrid"], self.extraToolBarWidgets["metronome"], self.extraToolBarWidgets["ccType"], self.extraToolBarWidgets["playbackSpeed"]],
"block": [self.extraToolBarWidgets["snapToGrid"], self.extraToolBarWidgets["metronome"], self.extraToolBarWidgets["playbackSpeed"], ],
}
#Now connect all actions to functions
for action, function in self.actions.items():
action.triggered.connect(function)
#all xxxEditActions are mutually exclusive.
for action, function in self.noteEditActions.items():
action.triggered.connect(function)
for action in self.ccEditActions: # a list.
action.setEnabled(False) #These are the same keys as noteEditActions, so we need to disable them for now.
for action, function in self.modalActions.items():
self.mainWindow.ui.centralwidget.addAction(action) #no actions without a widget
action.triggered.connect(function)
#Do not connect modalActionsPrevailing yet
for action, function in self.actionsWithoutMenu.items():
self.mainWindow.ui.centralwidget.addAction(action) #no actions without a widget
action.triggered.connect(function)
self.mainWindow.ui.menubar.removeAction(self.mainWindow.ui.menuGeneric.menuAction()) #thats why we added the actions to the centralwidget above.
self.loadToolbarContext("notation")
def toggleMidiInIsActive(self):
"""That is: "toggle midiInIsActive", not "toggleMidiIn is active?" """
stepMidiInput.toggleMidiIn()
self.mainWindow.ui.actionPrevailingRest.setEnabled(stepMidiInput.midiInIsActive)
self.mainWindow.ui.actionMidi_In_is_Active.setChecked(stepMidiInput.midiInIsActive)
def setMusicEditingEnabled(self, boolean):
"""This is the "reset to standard" functions for shortcuts.
If you want to enable other keys, such as CC editing keys,
you have to call another function after this one"""
allActions = list(self.actions.keys()) + list(self.modalActions.keys()) + list(self.actionsWithoutMenu.keys()) + list(self.noteEditActions.keys())
for x in self.nonEditingMusicActions:
allActions.remove(x)
for editAction in allActions:
editAction.setEnabled(boolean)
for action in self.ccEditActions: # Call this after enabling stuff in the for-loop above.
action.setEnabled(False) #These are the same keys as noteEditActions, so we need to disable them for now. Maybe they are enabled later again, after this function.
self.mainWindow.ui.actionPrevailingRest.setEnabled(boolean and stepMidiInput.midiInIsActive)
def noteEditMode(self):
self.setMusicEditingEnabled(True)
def ccEditMode(self):
self.setMusicEditingEnabled(False)
for action in self.ccEditActions: # a list.
action.setEnabled(True) #These are the same keys as noteEditActions, which are disabled above.
def writeProtection(self, boolean):
"""Artificial read only mode that was designed for the mouse-only track editor etc.
When zoomed out the user should be able to use the mouse but the cursor is hidden and
"""
if boolean:
#Switch off midi input
if stepMidiInput.midiInIsActive:
self.rememberMidi = stepMidiInput.midiInIsActive
stepMidiInput.toggleMidiIn()
assert not stepMidiInput.midiInIsActive
self.mainWindow.ui.actionPrevailingRest.setEnabled(stepMidiInput.midiInIsActive)
self.mainWindow.ui.actionMidi_In_is_Active.setChecked(stepMidiInput.midiInIsActive)
#Deactivate Note Editing Actions
self.setMusicEditingEnabled(False)
self.mainWindow.scoreView.scoreScene.cursor.hide() #the cursor which can be used to edit notes. Since the cursor shortcuts get disabled it cannot be changed invisbly.
else:
self.setMusicEditingEnabled(True)
self.mainWindow.scoreView.scoreScene.cursor.show()
if self.rememberMidi and not stepMidiInput.midiInIsActive:
self.toggleMidiInIsActive()
self.rememberMidi = None
def loadToolbarContext(self, nameAsString):
"""Hide all toolbar actions and only load those
which are in the current context, defined as list"""
assert nameAsString in constantsAndConfigs.availableEditModes
for action in self.mainWindow.ui.toolBar.actions():
action.setVisible(False)
for action in self.toolbarContexts[nameAsString]:
action.setVisible(True)
def renameUndoRedoByHistory(self, undoList, redoList):
if undoList:
self.mainWindow.ui.actionUndo.setText("Undo: {}".format(undoList[-1]))
self.mainWindow.ui.actionUndo.setEnabled(True)
else:
self.mainWindow.ui.actionUndo.setText("Undo")
self.mainWindow.ui.actionUndo.setEnabled(False)
if redoList:
self.mainWindow.ui.actionRedo.setText("Redo: {}".format(redoList[-1]))
self.mainWindow.ui.actionRedo.setEnabled(True)
else:
self.mainWindow.ui.actionRedo.setText("Redo")
self.mainWindow.ui.actionRedo.setEnabled(False)
def exportLy(self):
filename = QtWidgets.QFileDialog.getSaveFileName(self.mainWindow, "Export Lilypond Source File", self.mainWindow.settings.value("last_export_dir"), "Lilypond Source (*.ly)")
filename = filename[0] #(path, filter)
if filename:
if not os.path.splitext(filename)[1]: #no file extension given?
filename = filename + ".ly"
self.mainWindow.settings.setValue("last_export_dir", os.path.dirname(filename))
api.exportLilypond(filename)
class ToolBarCCType(QtWidgets.QSpinBox):
def __init__(self, mainWindow):
super().__init__()
self.mainWindow = mainWindow
self.setRange(0,127)
self.setPrefix("CC ")
self.valueChanged.connect(self.changed)
#self.addItems([str(i).zfill(3) for i in range(128) ])
def changed(self):
constantsAndConfigs.ccViewValue = self.value()
self.mainWindow.scoreView.updateMode() #gets the new value itself from constantsAndConfigs
class ToolBarSnapToGrid(QtWidgets.QCheckBox):
def __init__(self, mainWindow):
super().__init__("Snap to Grid")
self.setStatus()
self.stateChanged.connect(self.changed)
constantsAndConfigs.snapToGridCallbacks.append(self.updateFromCallback)
def setStatus(self):
if constantsAndConfigs.snapToGrid:
self.setCheckState(QtCore.Qt.Checked)
else:
self.setCheckState(QtCore.Qt.Unchecked)
def isChecked(self):
if self.checkState() == QtCore.Qt.Checked:
return True
else:
return False
def updateFromCallback(self):
self.blockSignals(True)
self.setStatus()
self.blockSignals(False)
def changed(self):
constantsAndConfigs.snapToGrid = self.isChecked() #this sends a call back to all Snap to Grid in the whole program
class ToolBarMetronome(QtWidgets.QCheckBox):
"""Contrary to SnapToGrid this reflects a backend state, not a pure GUI one.
There is also the menu actionMetronome_Enabled , itself a normal checkbox. It's callback and
state are handled in the menuDatabase classes init."""
def __init__(self, mainWindow):
super().__init__("Metronome")
self.setStatus()
self.stateChanged.connect(self.changed)
api.callbacks.metronomeChanged.append(self.updateFromCallback)
def setStatus(self):
if api.isMetronomeEnabled():
self.setCheckState(QtCore.Qt.Checked)
else:
self.setCheckState(QtCore.Qt.Unchecked)
def isChecked(self):
if self.checkState() == QtCore.Qt.Checked:
assert api.isMetronomeEnabled(), api.isMetronomeEnabled()
return True
else:
assert not api.isMetronomeEnabled(), api.isMetronomeEnabled()
return False
def updateFromCallback(self, exportDict):
self.blockSignals(True)
self.setStatus()
assert self.isChecked() == exportDict["enabled"], (self.isChecked(), exportDict["enabled"])
self.setText("Metronome: " + exportDict["trackName"])
self.blockSignals(False)
def changed(self, value):
api.enableMetronome(value) #triggers callback
class ToolBarPlaybackSpeed(QtWidgets.QDoubleSpinBox):
def __init__(self, mainWindow):
super().__init__()
self.setRange(0.1,3.0)
self.setDecimals(1)
self.setValue(1.0)
self.setSingleStep(0.1)
self.setPrefix("Tempo ×") #yes, this is the unicode multiplication sign × and not an x
api.callbacks.playbackSpeedChanged.append(self.updateFromCallback)
self.valueChanged.connect(self.changed)
def updateFromCallback(self, newValue):
self.blockSignals(True)
self.setValue(newValue)
self.blockSignals(False)
def changed(self):
api.playbackChangeSpeed(self.value())
constantsAndConfigs.ccViewValue = self.value() #this sends a call back to all CC spinboxes in the whole program

10728
qtgui/resources.py

File diff suppressed because it is too large

BIN
qtgui/resources/aboutlogo.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

4
qtgui/resources/buildresources.sh

@ -0,0 +1,4 @@
#!/bin/bash
#https://doc.qt.io/qt-5/resources.html
#Resources are kept up-to-date upstream. They are not part of the make and build process.
pyrcc5 -no-compress resources.qrc -o ../resources.py #put them into the gui directly. Engine does not need any translation or images.

94
qtgui/resources/euterpe.license.txt

@ -0,0 +1,94 @@
Euterpe Font - Ben Laenen, SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.

BIN
qtgui/resources/euterpe.ttf

Binary file not shown.

BIN
qtgui/resources/icon.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 942 B

55
qtgui/resources/resources.qrc

@ -0,0 +1,55 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource>
<file>euterpe.ttf</file>
<file>aboutlogo.png</file>
<file>icon.png</file>
<file>translations/de.qm</file>
<file>svg/accidentalsDoublesharp.svg</file>
<file>svg/accidentalsFlatFlat.svg</file>
<file>svg/accidentalsFlat.svg</file>
<file>svg/accidentalsNatural.svg</file>
<file>svg/accidentalsSharp.svg</file>
<file>svg/blockEnd.svg</file>
<file>svg/clefAlto.svg</file>
<file>svg/clefBass_8.svg</file>
<file>svg/clefBass.svg</file>
<file>svg/clefPercussion.svg</file>
<file>svg/clefTreble^8.svg</file>
<file>svg/clefTreble_8.svg</file>
<file>svg/clefTreble.svg</file>
<file>svg/dot.svg</file>
<file>svg/flag128i.svg</file>
<file>svg/flag128.svg</file>
<file>svg/flag16i.svg</file>
<file>svg/flag16.svg</file>
<file>svg/flag32i.svg</file>
<file>svg/flag32.svg</file>
<file>svg/flag64i.svg</file>
<file>svg/flag64.svg</file>
<file>svg/flag8i.svg</file>
<file>svg/flag8.svg</file>
<file>svg/noteheadsBlack.svg</file>
<file>svg/noteheadsBrevis.svg</file>
<file>svg/noteheadsHalf.svg</file>
<file>svg/noteheadsLonga.svg</file>
<file>svg/noteheadsMaxima.svg</file>
<file>svg/noteheadsWhole.svg</file>
<file>svg/numbers.svg</file>
<file>svg/rest128.svg</file>
<file>svg/rest16.svg</file>
<file>svg/rest1.svg</file>
<file>svg/rest2.svg</file>
<file>svg/rest32.svg</file>
<file>svg/rest4.svg</file>
<file>svg/rest64.svg</file>
<file>svg/rest8.svg</file>
<file>svg/restBrevis.svg</file>
<file>svg/restLonga.svg</file>
<file>svg/restMaxima.svg</file>
<file>svg/scriptsStaccato.svg</file>
</qresource>
</RCC>

58
qtgui/resources/svg/accidentalsDoublesharp.svg

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
width="1000"
height="1000"
id="svg3079"
inkscape:version="0.48.4 r9939"
sodipodi:docname="accidentalsDoublesharp.svg">
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1916"
inkscape:window-height="1041"
id="namedview3152"
showgrid="false"
showguides="true"
inkscape:guide-bbox="true"
inkscape:zoom="21.360282"
inkscape:cx="-6.5567979"
inkscape:cy="1003.856"
inkscape:window-x="1920"
inkscape:window-y="18"
inkscape:window-maximized="0"
inkscape:current-layer="svg3079" />
<metadata
id="metadata3087">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs3085" />
<path
d="m -2.8851159,0.00621828 c 0.575,0.575 1.45,0.7 2.27500001,0.7 0.1,0 0.2,0.1 0.2,0.2 l 0.225,2.22500002 c 0,0.1 -0.075,0.2 -0.175,0.2 h -0.025 l -2.22500001,-0.225 c -0.1,0 -0.2,-0.1 -0.2,-0.2 0,-0.825 -0.125,-1.7 -0.7,-2.27500002 -0.575,0.57500002 -0.7,1.45000002 -0.7,2.27500002 0,0.1 -0.1,0.2 -0.2,0.2 l -2.225,0.225 h -0.025 c -0.1,0 -0.175,-0.1 -0.175,-0.2 l 0.225,-2.22500002 c 0,-0.1 0.1,-0.2 0.2,-0.2 0.825,0 1.7,-0.125 2.275,-0.7 -0.575,-0.575 -1.45,-0.7 -2.275,-0.7 -0.1,0 -0.2,-0.1 -0.2,-0.2 l -0.225,-2.22499998 c 0,-0.1 0.075,-0.2 0.175,-0.2 h 0.025 l 2.225,0.225 c 0.1,0 0.2,0.1 0.2,0.2 0,0.825 0.125,1.7 0.7,2.27499998 0.575,-0.57499998 0.7,-1.44999998 0.7,-2.27499998 0,-0.1 0.1,-0.2 0.2,-0.2 l 2.22500001,-0.225 h 0.025 c 0.1,0 0.175,0.1 0.175,0.2 l -0.225,2.22499998 c 0,0.1 -0.1,0.2 -0.2,0.2 -0.82500001,0 -1.70000001,0.125 -2.27500001,0.7 z"
id="path3081"
inkscape:connector-curvature="0" />
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

31
qtgui/resources/svg/accidentalsFlat.svg

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
version="1.1"
width="1000"
height="1000"
id="svg3089">
<metadata
id="metadata3097">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs3095" />
<path
d="m -5.1059322,-0.78771185 -0.025,1.725 c 0,0.10000005 -0.025,0.17499995 -0.025,0.27499995 0,0.55 0.05,1.1 0.1,1.65 1.15,-0.95 2.4,-1.99999995 2.4,-3.47499995 0,-0.85000005 -0.35,-1.72500005 -1.1,-1.72500005 -0.775,0 -1.325,0.725 -1.35,1.55000005 z m -0.975,4.49999995 -0.275,-14.9750001 c 0.2,-0.1 0.4,-0.175 0.625,-0.175 0.225,0 0.425,0.075 0.625,0.175 l -0.15,8.7250001 c 0.65,-0.475 1.4,-0.75 2.2,-0.75 1.325,0 2.32499998,1.15 2.32499998,2.50000005 0,2.04999995 -2.24999998,2.94999995 -3.82499998,4.22499995 -0.35,0.275 -0.55,0.8 -1,0.8 -0.3,0 -0.525,-0.225 -0.525,-0.525 z"
id="path3091" />
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

31
qtgui/resources/svg/accidentalsFlatFlat.svg

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
version="1.1"
width="1000"
height="1000"
id="svg3099">
<metadata
id="metadata3107">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs3105" />
<path
d="m -4.9290784,-0.22494702 -0.025,1.72500002 v 0.275 c 0,0.55 0.05,1.1 0.1,1.65 1.125,-0.925 2.225,-2.025 2.225,-3.47500002 0,-0.85 -0.3,-1.72499998 -1.025,-1.72499998 -0.75,0 -1.25,0.75 -1.275,1.54999998 z m -0.95,4.50000002 -0.05,-2.65 c -0.7,0.875 -1.775,1.575 -2.625,2.375 -0.3,0.275 -0.45,0.8 -0.875,0.8 -0.3,0 -0.525,-0.225 -0.525,-0.525 l -0.2749996,-14.975 c 0.2,-0.1 0.3999996,-0.175 0.6249996,-0.175 0.225,0 0.425,0.075 0.625,0.175 l -0.15,8.725 c 0.45,-0.475 1.05,-0.75 1.7,-0.75 0.55,0 1.05,0.225 1.425,0.575 l -0.175,-8.55 c 0.2,-0.1 0.4,-0.175 0.625,-0.175 0.225,0 0.45,0.075 0.65,0.175 l -0.175,8.725 c 0.6,-0.475 1.375,-0.75 2.15,-0.75 1.35,0 2.37499997,1.125 2.37499997,2.47499998 0,2.05000002 -2.24999997,2.95000002 -3.82499997,4.25000002 -0.35,0.275 -0.525,0.8 -0.975,0.8 -0.3,0 -0.525,-0.225 -0.525,-0.525 z m -3.3,-4.50000002 -0.025,1.72500002 v 0.275 c 0,0.575 0.025,1.125 0.1,1.7 1,-0.95 1.8,-2.15 1.8,-3.52500002 0,-0.825 -0.15,-1.72499998 -0.85,-1.72499998 -0.675,0 -1,0.77499998 -1.025,1.54999998 z"
id="path3101" />
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

31
qtgui/resources/svg/accidentalsNatural.svg

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
version="1.1"
width="1000"
height="1000"
id="svg3109">
<metadata
id="metadata3117">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs3115" />
<path
d="m -5.0561131,-8.8814055 c 0.175,-0.1 0.4,-0.15 0.6,-0.15 0.2,0 0.4,0.05 0.575,0.15 l -0.05,4.375 2.725,-0.425 c 0.025,0 0.05,-0.025 0.075,-0.025 0.22499998,0 0.42499998,0.2 0.42499998,0.425 l 0.15,14.4 c -0.175,0.1 -0.375,0.1500005 -0.57499998,0.1500005 -0.2,0 -0.4,-0.05 -0.575,-0.1500005 l 0.05,-4.375 -2.75,0.425 c -0.025,0 -0.025,0.025 -0.05,0.025 -0.225,0 -0.425,-0.2 -0.425,-0.425 z m 3.425,11.85 0.05,-5.325 -2.375,0.375 -0.075,5.325 z"
id="path3111" />
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

31
qtgui/resources/svg/accidentalsSharp.svg

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
version="1.1"
width="1000"
height="1000"
id="svg3119">
<metadata
id="metadata3127">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs3125" />
<path
d="m -3.1102814,7.8941649 c 0,0.225 -0.2,0.425 -0.425,0.425 -0.225,0 -0.425,-0.2 -0.425,-0.425 v -3.775 l -2.175,0.775 v 4.05 c 0,0.225 -0.2,0.425 -0.425,0.425 -0.225,0 -0.425,-0.2 -0.425,-0.425 v -3.75 l -0.975,0.325 c -0.25,0.1 -0.525,-0.1 -0.525,-0.375 v -1.6 c 0,-0.175 0.125,-0.325 0.275,-0.375 l 1.225,-0.45 v -4.1 l -0.975,0.35 c -0.25,0.1 -0.525,-0.1 -0.525,-0.375 v -1.625 c 0,-0.175 0.125,-0.325 0.275,-0.375 l 1.225,-0.425 v -4.075 c 0,-0.225 0.2,-0.425 0.425,-0.425 0.225,0 0.425,0.2 0.425,0.425 v 3.775 l 2.175,-0.775 v -4.05 c 0,-0.225 0.2,-0.425 0.425,-0.425 0.225,0 0.425,0.2 0.425,0.425 v 3.75 l 0.975,-0.325 c 0.25,-0.1 0.525,0.1 0.525,0.375 v 1.6 c 0,0.175 -0.125,0.325 -0.275,0.375 l -1.225,0.45 v 4.1 l 0.975,-0.35 c 0.25,-0.10000003 0.525,0.1 0.525,0.375 v 1.625 c 0,0.175 -0.125,0.325 -0.275,0.375 l -1.225,0.425 v 4.075 z m -0.85,-10.325 -2.175,0.75 v 4.1 l 2.175,-0.75 v -4.1 z"
id="path3121" />
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

62
qtgui/resources/svg/blockEnd.svg

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
width="1000"
height="1000"
id="svg2983"
inkscape:version="0.48.4 r9939"
sodipodi:docname="blockEnd.svg">
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1916"
inkscape:window-height="1041"
id="namedview6"
showgrid="false"
inkscape:zoom="5.3400704"
inkscape:cx="38.564766"
inkscape:cy="991.52484"
inkscape:window-x="1920"
inkscape:window-y="18"
inkscape:window-maximized="0"
inkscape:current-layer="svg2983" />
<metadata
id="metadata2991">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs2989" />
<g
style="font-size:40px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:'8-bit Limit O BRK';-inkscape-font-specification:'8-bit Limit O BRK'"
id="text3739"
transform="translate(-21.441665,14.887444)">
<path
style="font-family:Weaver BRK;-inkscape-font-specification:Weaver BRK"
d="m 18.672839,2.0041092 c -1.322345,0.6647453 0.790324,1.2148069 0.4,1.68 -1.028292,-0.1592025 -2.57358,-1.0672435 -2.161251,-2.3568777 0.434484,-1.28467025 1.799339,-1.70810589 2.728749,-2.525623 0.679559,-1.0330742 -1.37363,-1.1629705 -1.6975,-2.0474988 -1.653642,-1.8371378 -1.335186,-4.7724653 0.236598,-6.5454613 0.668094,-1.0097804 1.786598,-1.9215544 1.670902,-3.2445334 -0.178193,-1.328826 -1.67418,-1.706435 -2.259999,-2.792499 -1.307455,-1.913446 -0.800868,-4.545484 0.677962,-6.201455 0.691388,-1.024751 1.898427,-2.037182 1.514536,-3.406034 -0.28034,-1.302195 -1.780879,-1.330998 -2.559529,-2.168906 -0.944276,-0.978102 0.08241,-2.306564 0.974974,-2.876951 0.552029,-0.423496 1.238397,-0.71126 1.662056,-1.269145 -0.04247,-0.498496 -1.736153,-1.491798 -0.380468,-1.139698 1.390055,0.323352 2.475516,1.947527 1.211093,3.102816 -0.68667,0.807696 -1.84437,1.086223 -2.445624,1.97438 0.614331,1.086295 2.27534,1.568388 2.681248,2.97547 0.855506,1.943791 0.05183,4.151103 -1.269251,5.671197 -0.675445,0.946203 -1.759067,1.937177 -1.334498,3.220829 0.363918,1.186901 1.751495,1.546678 2.289998,2.629998 1.247926,1.914606 0.597913,4.4632023 -0.821624,6.091878 -0.69617,1.014488 -1.903797,2.0291078 -1.468374,3.3981151 0.232542,0.9701739 1.190962,1.2868291 1.98578,1.6656237 1.352963,0.5470348 1.089858,2.30978451 0.04713,3.04146834 C 19.795663,1.2565791 19.233737,1.6297264 18.67284,2.0041092 z"
id="path3746"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.4 KiB

55
qtgui/resources/svg/clefAlto.svg

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
height="1000.0"
width="1000.0"
id="svg4485"
inkscape:version="0.91 r13725"
sodipodi:docname="clefViola.svg">
<metadata
id="metadata4493">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs4491" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1916"
inkscape:window-height="1046"
id="namedview4489"
showgrid="false"
inkscape:zoom="5.3400704"
inkscape:cx="107.42526"
inkscape:cy="1052.8645"
inkscape:window-x="0"
inkscape:window-y="30"
inkscape:window-maximized="0"
inkscape:current-layer="svg4485" />
<path
glyph-name="clefs.C"
d="m 7.8,0 c 0,-0.825 0.175,-1.85 1.15,-1.85 0.725,0 1.425,0.725 2.2,0.725 3.075,0 5.775,-2.175 5.775,-5.125 0,-4.25 -2.375,-6.25 -6.725,-6.25 -2.075,0 -3.85,1.55 -3.85,3.575 0,1.05 0.875,1.925 1.925,1.925 1.05,0 1.925,-0.875 1.925,-1.925 0,-1 -1.275,-0.925 -1.275,-1.925 0,-0.6 0.625,-1 1.275,-1 2.925,0 3.525,2.275 3.525,5.6 0,2.625 -0.3,4.5 -2.575,4.5 C 9.3,-1.75 8.1,-3.6 8.1,-5.575 8.1,-5.8 7.95,-5.9 7.8,-5.9 c -0.15,0 -0.325,0.1 -0.325,0.325 0,1.925 -0.775,3.75 -2.1,5.125 l 0,-11.85 c 0,-0.1 -0.1,-0.2 -0.2,-0.2 l -0.55,0 c -0.1,0 -0.2,0.1 -0.2,0.2 l 0,24.6 c 0,0.1 0.1,0.2 0.2,0.2 l 0.55,0 c 0.1,0 0.2,-0.1 0.2,-0.2 l 0,-11.85 c 1.325,1.375 2.1,3.2 2.1,5.125 C 7.475,5.8 7.65,5.9 7.8,5.9 7.95,5.9 8.1,5.8 8.1,5.575 8.1,3.6 9.3,1.75 11.15,1.75 c 2.275,0 2.575,1.875 2.575,4.5 0,3.325 -0.6,5.6 -3.525,5.6 -0.65,0 -1.275,-0.4 -1.275,-1 0,-1 1.275,-0.925 1.275,-1.925 C 10.2,7.875 9.325,7 8.275,7 7.225,7 6.35,7.875 6.35,8.925 c 0,2.025 1.775,3.575 3.85,3.575 4.35,0 6.725,-2 6.725,-6.25 0,-2.95 -2.7,-5.125 -5.775,-5.125 -0.775,0 -1.475,0.725 -2.2,0.725 C 7.975,1.85 7.8,0.825 7.8,0 Z m -4.55,-12.5 -3.05,0 c -0.1,0 -0.2,0.1 -0.2,0.2 l 0,24.6 c 0,0.1 0.1,0.2 0.2,0.2 l 3.05,0 c 0.1,0 0.2,-0.1 0.2,-0.2 l 0,-24.6 c 0,-0.1 -0.1,-0.2 -0.2,-0.2 z"
id="path4487"
inkscape:connector-curvature="0" />
</svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

56
qtgui/resources/svg/clefBass.svg

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
width="1000"
height="1000"
id="svg3169"
inkscape:version="0.48.4 r9939"
sodipodi:docname="clefBass.svg">
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="956"
inkscape:window-height="1041"
id="namedview3018"
showgrid="false"
inkscape:zoom="17.830405"
inkscape:cx="22.422317"
inkscape:cy="987.38096"
inkscape:window-x="2880"
inkscape:window-y="18"
inkscape:window-maximized="0"
inkscape:current-layer="svg3169" />
<metadata
id="metadata3177">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs3175" />
<path
d="m 14.175,-3.1509855 c 0,-0.725 0.575,-1.3000001 1.3,-1.3000001 0.725,0 1.3,0.5750001 1.3,1.3000001 0,0.725 -0.575,1.2999999 -1.3,1.2999999 -0.725,0 -1.3,-0.5749999 -1.3,-1.2999999 z m 0,-6.2500001 c 0,-0.7250004 0.575,-1.3000004 1.3,-1.3000004 0.725,0 1.3,0.575 1.3,1.3000004 0,0.725 -0.575,1.3 -1.3,1.3 -0.725,0 -1.3,-0.575 -1.3,-1.3 z M 6.1,-12.800986 c 4.275,0 7.3,2.15 7.3,6.2000004 0,6.57500003 -6.6,10.375 -12.925,13.025 -0.05,0.05 -0.125,0.075 -0.2,0.075 -0.15,0 -0.275,-0.125 -0.275,-0.275 0,-0.075 0.025,-0.15 0.075,-0.2 5.075,-2.95 10.375,-6.62499997 10.375,-12.35 0,-3.025 -1.6,-5.9250004 -4.35,-5.9250004 -1.975,0 -3.45,1.425 -4.1,3.3250004 0.35,-0.2 0.7,-0.325 1.075,-0.325 1.375,0 2.5,1.125 2.5,2.5 0,1.45 -1.1,2.6750001 -2.5,2.6750001 -1.5,0 -2.8,-1.2000001 -2.8,-2.6750001 0,-3.3000004 2.575,-6.0500004 5.825,-6.0500004 z"
id="path3171"
inkscape:connector-curvature="0" />
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

61
qtgui/resources/svg/clefBass_8.svg

@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
width="1000"
height="1000"
id="svg3169"
inkscape:version="0.91 r13725"
sodipodi:docname="clefBass_8.svg">
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1916"
inkscape:window-height="2096"
id="namedview3018"
showgrid="false"
inkscape:zoom="4.4576013"
inkscape:cx="-25.75699"
inkscape:cy="994.59974"
inkscape:window-x="0"
inkscape:window-y="30"
inkscape:window-maximized="0"
inkscape:current-layer="svg3169" />
<metadata
id="metadata3177">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs3175" />
<path
d="m 14.175,-3.1509855 c 0,-0.725 0.575,-1.3000001 1.3,-1.3000001 0.725,0 1.3,0.5750001 1.3,1.3000001 0,0.725 -0.575,1.2999999 -1.3,1.2999999 -0.725,0 -1.3,-0.5749999 -1.3,-1.2999999 z m 0,-6.2500001 c 0,-0.7250004 0.575,-1.3000004 1.3,-1.3000004 0.725,0 1.3,0.575 1.3,1.3000004 0,0.725 -0.575,1.3 -1.3,1.3 -0.725,0 -1.3,-0.575 -1.3,-1.3 z M 6.1,-12.800986 c 4.275,0 7.3,2.15 7.3,6.2000004 0,6.57500003 -6.6,10.375 -12.925,13.025 -0.05,0.05 -0.125,0.075 -0.2,0.075 -0.15,0 -0.275,-0.125 -0.275,-0.275 0,-0.075 0.025,-0.15 0.075,-0.2 5.075,-2.95 10.375,-6.62499997 10.375,-12.35 0,-3.025 -1.6,-5.9250004 -4.35,-5.9250004 -1.975,0 -3.45,1.425 -4.1,3.3250004 0.35,-0.2 0.7,-0.325 1.075,-0.325 1.375,0 2.5,1.125 2.5,2.5 0,1.45 -1.1,2.6750001 -2.5,2.6750001 -1.5,0 -2.8,-1.2000001 -2.8,-2.6750001 0,-3.3000004 2.575,-6.0500004 5.825,-6.0500004 z"
id="path3171"
inkscape:connector-curvature="0" />
<path
glyph-name="eight"
d="M 9.3946774,9.6002892 C 9.9409485,9.0351814 10.411872,8.4324001 10.411872,7.6600861 c 0,-1.0548678 -1.0925423,-1.7141603 -2.2415948,-1.7141603 -0.9230094,0 -1.4692803,0.7158032 -1.4692803,1.4127695 0,0.4144124 0.1695324,0.7911509 0.5839447,1.0360309 z M 9.9032747,9.90168 c 1.0360313,0.602782 1.6011383,1.46928 1.6011383,2.39229 0,1.356258 -1.2244,2.674843 -3.4848312,2.674843 -1.7329972,0 -3.3718098,-0.998357 -3.3718098,-2.599496 0,-0.960683 0.753477,-1.619975 1.4692802,-2.279268 C 5.2882275,9.5626153 4.911489,8.7903017 4.911489,8.0368246 c 0,-1.262074 1.1302155,-2.4864742 3.2587882,-2.4864742 1.506954,0 2.9762348,0.753477 2.9762348,2.1097357 0,0.9041725 -0.602782,1.5823015 -1.2432373,2.2415939 z m -3.2587885,0.48976 c -0.6404555,0.565108 -1.2432372,1.149053 -1.2432372,1.977877 0,1.299748 1.2432372,2.203921 2.6183328,2.203921 1.0360309,0 1.6576494,-0.809988 1.6576494,-1.601139 0,-0.470923 -0.2072061,-0.960683 -0.6969662,-1.243237 z"
id="path3728"
inkscape:connector-curvature="0" />
</svg>

After

Width:  |  Height:  |  Size: 3.4 KiB

55
qtgui/resources/svg/clefPercussion.svg

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
height="1000.0"
width="1000.0"
id="svg3336"
inkscape:version="0.91 r13725"
sodipodi:docname="clefPercussion.svg">
<metadata
id="metadata3344">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs3342" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1916"
inkscape:window-height="2096"
id="namedview3340"
showgrid="false"
inkscape:zoom="1.343"
inkscape:cx="500"
inkscape:cy="619.13626"
inkscape:window-x="0"
inkscape:window-y="30"
inkscape:window-maximized="1"
inkscape:current-layer="svg3336" />
<path
glyph-name="clefs.percussion"
d="m 8.1,-6.25 -2.425,0 c -0.1,0 -0.175,0.1 -0.175,0.2 l 0,12.1 c 0,0.1 0.075,0.2 0.175,0.2 l 2.425,0 c 0.1,0 0.2,-0.1 0.2,-0.2 l 0,-12.1 c 0,-0.1 -0.1,-0.2 -0.2,-0.2 z m -5.5,0 -2.425,0 C 0.075,-6.25 0,-6.15 0,-6.05 l 0,12.1 c 0,0.1 0.075,0.2 0.175,0.2 l 2.425,0 c 0.1,0 0.2,-0.1 0.2,-0.2 l 0,-12.1 c 0,-0.1 -0.1,-0.2 -0.2,-0.2 z"
id="path3338"
inkscape:connector-curvature="0" />
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

56
qtgui/resources/svg/clefTreble.svg

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
width="1000"
height="1000"
id="svg3179"
inkscape:version="0.48.4 r9939"
sodipodi:docname="clefTreble.svg">
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="956"
inkscape:window-height="1041"
id="namedview2989"
showgrid="false"
inkscape:zoom="13.6"
inkscape:cx="23.86716"
inkscape:cy="1009.9681"
inkscape:window-x="1920"
inkscape:window-y="18"
inkscape:window-maximized="0"
inkscape:current-layer="svg3179" />
<metadata
id="metadata3187">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs3185" />
<path
d="M 6.35,-7.5070824 C 5.5,-10.457082 5,-13.282082 5,-16.982082 c 0,-3 1.4,-5.8 3.775,-7.625 0.05,-0.05 0.125,-0.075 0.2,-0.075 0.075,0 0.15,0.025 0.2,0.075 1.9,2.25 3.575,6.6 3.575,9.625 0,3.75 -2.25,6.6749996 -4.75,9.4999996 0.55,1.8249999 1.05,3.6749999 1.525,5.5249999 h 0.15 c 3.85,0 6.35,3.175 6.35,6.4750001 0,1.8999999 -0.825,3.8250004 -2.675,5.2000004 -0.625,0.475 -1.325,0.8 -2.075,1 0,0.325 0.025,0.675 0.025,1 0,1.15 -0.025,2.3 -0.1,3.45 -0.175,3.025 -2.35,5.675 -5.35,5.675 -2.775,0 -5.05,-2.3 -5.05,-5.125 0,-1.45 1.35,-2.6 2.825,-2.6 1.35,0 2.375,1.2 2.375,2.6 0,1.3 -1.075,2.375 -2.375,2.375 -0.325,0 -0.675,-0.1 -0.975,-0.25 0.65,1.175 1.85,2 3.25,2 2.475,0 4.15,-2.3 4.3,-4.825 0.075,-1.1 0.1,-2.225 0.1,-3.325 v -0.775 c -0.65,0.1 -1.3,0.15 -1.975,0.15 -4.7,0 -8.325,-4.2750005 -8.325,-9.3000005 0,-4.525 3.35,-7.8499999 6.35,-11.2749999 z m 4.9,19.2500004 c 1.825,-0.55 3.1,-2.4250005 3.1,-4.2500005 0,-2.2499999 -1.6,-4.45 -4.2,-4.8 0.575,2.7500001 1,5.975 1.1,9.0500005 z m -2.85,0.325 c 0.625,0 1.25,-0.025 1.875,-0.125 C 10.175,8.7679175 9.7,5.4679176 9.1,2.6429175 c -2.175,0.125 -3.4,1.55 -3.4,3.1000001 0,1.125 0.65,2.2999999 2.075,3.1249999 0.1,0.1 0.175,0.225 0.175,0.35 0,0.275 -0.225,0.525 -0.5,0.525 -0.075,0 -0.15,-0.025 -0.225,-0.05 -2,-1.075 -2.9,-2.8499999 -2.9,-4.6 0,-2.25 1.525,-4.45 4.2,-4.95 -0.4,-1.6 -0.875,-3.175 -1.325,-4.7499999 -2.75,3.0999999 -5.5,6.2249999 -5.5,10.35 0,3.4499999 3.275,6.3250004 6.7,6.3250004 z m 1.775,-33.2 c -2.5,1.375 -4.05,3.975 -4.05,6.825 0,2.25 0.475,4.05 1,5.8999996 2.15,-2.5499996 3.95,-5.2249996 3.95,-8.5499996 0,-1.825 -0.2,-2.575 -0.9,-4.175 z"
id="path3181"
inkscape:connector-curvature="0" />
</svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

61
qtgui/resources/svg/clefTreble^8.svg

@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
width="1000"
height="1000"
id="svg3179"
inkscape:version="0.91 r13725"
sodipodi:docname="clefTreble^8.svg">
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1916"
inkscape:window-height="2096"
id="namedview2989"
showgrid="false"
inkscape:zoom="4.8083261"
inkscape:cx="32.64208"
inkscape:cy="965.18803"
inkscape:window-x="1920"
inkscape:window-y="30"
inkscape:window-maximized="0"
inkscape:current-layer="svg3179" />
<metadata
id="metadata3187">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs3185" />
<path
d="M 6.35,-7.5070824 C 5.5,-10.457082 5,-13.282082 5,-16.982082 c 0,-3 1.4,-5.8 3.775,-7.625 0.05,-0.05 0.125,-0.075 0.2,-0.075 0.075,0 0.15,0.025 0.2,0.075 1.9,2.25 3.575,6.6 3.575,9.625 0,3.75 -2.25,6.6749996 -4.75,9.4999996 0.55,1.8249999 1.05,3.6749999 1.525,5.5249999 h 0.15 c 3.85,0 6.35,3.175 6.35,6.4750001 0,1.8999999 -0.825,3.8250004 -2.675,5.2000004 -0.625,0.475 -1.325,0.8 -2.075,1 0,0.325 0.025,0.675 0.025,1 0,1.15 -0.025,2.3 -0.1,3.45 -0.175,3.025 -2.35,5.675 -5.35,5.675 -2.775,0 -5.05,-2.3 -5.05,-5.125 0,-1.45 1.35,-2.6 2.825,-2.6 1.35,0 2.375,1.2 2.375,2.6 0,1.3 -1.075,2.375 -2.375,2.375 -0.325,0 -0.675,-0.1 -0.975,-0.25 0.65,1.175 1.85,2 3.25,2 2.475,0 4.15,-2.3 4.3,-4.825 0.075,-1.1 0.1,-2.225 0.1,-3.325 v -0.775 c -0.65,0.1 -1.3,0.15 -1.975,0.15 -4.7,0 -8.325,-4.2750005 -8.325,-9.3000005 0,-4.525 3.35,-7.8499999 6.35,-11.2749999 z m 4.9,19.2500004 c 1.825,-0.55 3.1,-2.4250005 3.1,-4.2500005 0,-2.2499999 -1.6,-4.45 -4.2,-4.8 0.575,2.7500001 1,5.975 1.1,9.0500005 z m -2.85,0.325 c 0.625,0 1.25,-0.025 1.875,-0.125 C 10.175,8.7679175 9.7,5.4679176 9.1,2.6429175 c -2.175,0.125 -3.4,1.55 -3.4,3.1000001 0,1.125 0.65,2.2999999 2.075,3.1249999 0.1,0.1 0.175,0.225 0.175,0.35 0,0.275 -0.225,0.525 -0.5,0.525 -0.075,0 -0.15,-0.025 -0.225,-0.05 -2,-1.075 -2.9,-2.8499999 -2.9,-4.6 0,-2.25 1.525,-4.45 4.2,-4.95 -0.4,-1.6 -0.875,-3.175 -1.325,-4.7499999 -2.75,3.0999999 -5.5,6.2249999 -5.5,10.35 0,3.4499999 3.275,6.3250004 6.7,6.3250004 z m 1.775,-33.2 c -2.5,1.375 -4.05,3.975 -4.05,6.825 0,2.25 0.475,4.05 1,5.8999996 2.15,-2.5499996 3.95,-5.2249996 3.95,-8.5499996 0,-1.825 -0.2,-2.575 -0.9,-4.175 z"
id="path3181"
inkscape:connector-curvature="0" />
<path
glyph-name="eight"
d="m 9.8454611,-32.411274 c 0.5462709,-0.565108 1.0171939,-1.167889 1.0171939,-1.940203 0,-1.054868 -1.0925419,-1.714161 -2.2415941,-1.714161 -0.92301,0 -1.469281,0.715804 -1.469281,1.41277 0,0.414412 0.169533,0.791151 0.583945,1.036031 z m 0.5085969,0.301391 c 1.036031,0.602782 1.601138,1.46928 1.601138,2.39229 0,1.356258 -1.2244,2.674843 -3.4848311,2.674843 -1.732997,0 -3.37181,-0.998357 -3.37181,-2.599496 0,-0.960683 0.753477,-1.619975 1.469281,-2.279268 -0.828825,-0.527434 -1.205564,-1.299748 -1.205564,-2.053225 0,-1.262074 1.130216,-2.486474 3.258789,-2.486474 1.5069541,0 2.9762341,0.753477 2.9762341,2.109736 0,0.904172 -0.602782,1.582301 -1.243237,2.241594 z m -3.2587881,0.48976 c -0.640456,0.565108 -1.243238,1.149053 -1.243238,1.977877 0,1.299748 1.243238,2.203921 2.618333,2.203921 1.0360312,0 1.6576501,-0.809988 1.6576501,-1.601139 0,-0.470923 -0.2072059,-0.960683 -0.6969669,-1.243237 z"
id="path3728"
inkscape:connector-curvature="0" />
</svg>

After

Width:  |  Height:  |  Size: 4.1 KiB

61
qtgui/resources/svg/clefTreble_8.svg

@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
width="1000"
height="1000"
id="svg3179"
inkscape:version="0.91 r13725"
sodipodi:docname="clefTreble_8.svg">
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1916"
inkscape:window-height="2096"
id="namedview2989"
showgrid="false"
inkscape:zoom="4.8083261"
inkscape:cx="32.64208"
inkscape:cy="965.18803"
inkscape:window-x="1920"
inkscape:window-y="30"
inkscape:window-maximized="0"
inkscape:current-layer="svg3179" />
<metadata
id="metadata3187">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs3185" />
<path
d="M 6.35,-7.5070824 C 5.5,-10.457082 5,-13.282082 5,-16.982082 c 0,-3 1.4,-5.8 3.775,-7.625 0.05,-0.05 0.125,-0.075 0.2,-0.075 0.075,0 0.15,0.025 0.2,0.075 1.9,2.25 3.575,6.6 3.575,9.625 0,3.75 -2.25,6.6749996 -4.75,9.4999996 0.55,1.8249999 1.05,3.6749999 1.525,5.5249999 h 0.15 c 3.85,0 6.35,3.175 6.35,6.4750001 0,1.8999999 -0.825,3.8250004 -2.675,5.2000004 -0.625,0.475 -1.325,0.8 -2.075,1 0,0.325 0.025,0.675 0.025,1 0,1.15 -0.025,2.3 -0.1,3.45 -0.175,3.025 -2.35,5.675 -5.35,5.675 -2.775,0 -5.05,-2.3 -5.05,-5.125 0,-1.45 1.35,-2.6 2.825,-2.6 1.35,0 2.375,1.2 2.375,2.6 0,1.3 -1.075,2.375 -2.375,2.375 -0.325,0 -0.675,-0.1 -0.975,-0.25 0.65,1.175 1.85,2 3.25,2 2.475,0 4.15,-2.3 4.3,-4.825 0.075,-1.1 0.1,-2.225 0.1,-3.325 v -0.775 c -0.65,0.1 -1.3,0.15 -1.975,0.15 -4.7,0 -8.325,-4.2750005 -8.325,-9.3000005 0,-4.525 3.35,-7.8499999 6.35,-11.2749999 z m 4.9,19.2500004 c 1.825,-0.55 3.1,-2.4250005 3.1,-4.2500005 0,-2.2499999 -1.6,-4.45 -4.2,-4.8 0.575,2.7500001 1,5.975 1.1,9.0500005 z m -2.85,0.325 c 0.625,0 1.25,-0.025 1.875,-0.125 C 10.175,8.7679175 9.7,5.4679176 9.1,2.6429175 c -2.175,0.125 -3.4,1.55 -3.4,3.1000001 0,1.125 0.65,2.2999999 2.075,3.1249999 0.1,0.1 0.175,0.225 0.175,0.35 0,0.275 -0.225,0.525 -0.5,0.525 -0.075,0 -0.15,-0.025 -0.225,-0.05 -2,-1.075 -2.9,-2.8499999 -2.9,-4.6 0,-2.25 1.525,-4.45 4.2,-4.95 -0.4,-1.6 -0.875,-3.175 -1.325,-4.7499999 -2.75,3.0999999 -5.5,6.2249999 -5.5,10.35 0,3.4499999 3.275,6.3250004 6.7,6.3250004 z m 1.775,-33.2 c -2.5,1.375 -4.05,3.975 -4.05,6.825 0,2.25 0.475,4.05 1,5.8999996 2.15,-2.5499996 3.95,-5.2249996 3.95,-8.5499996 0,-1.825 -0.2,-2.575 -0.9,-4.175 z"
id="path3181"
inkscape:connector-curvature="0" />
<path
glyph-name="eight"
d="m 9.8454611,28.31672 c 0.5462709,-0.565108 1.0171939,-1.167889 1.0171939,-1.940203 0,-1.054868 -1.0925419,-1.714161 -2.2415941,-1.714161 -0.92301,0 -1.469281,0.715804 -1.469281,1.41277 0,0.414412 0.169533,0.791151 0.583945,1.036031 z m 0.5085969,0.301391 c 1.036031,0.602782 1.601138,1.46928 1.601138,2.39229 0,1.356258 -1.2244,2.674843 -3.4848311,2.674843 -1.732997,0 -3.37181,-0.998357 -3.37181,-2.599496 0,-0.960683 0.753477,-1.619975 1.469281,-2.279268 -0.828825,-0.527434 -1.205564,-1.299748 -1.205564,-2.053225 0,-1.262074 1.130216,-2.486474 3.258789,-2.486474 1.5069541,0 2.9762341,0.753477 2.9762341,2.109736 0,0.904172 -0.602782,1.582301 -1.243237,2.241594 z m -3.2587881,0.48976 c -0.640456,0.565108 -1.243238,1.149053 -1.243238,1.977877 0,1.299748 1.243238,2.203921 2.618333,2.203921 1.0360312,0 1.6576501,-0.809988 1.6576501,-1.601139 0,-0.470923 -0.2072059,-0.960683 -0.6969669,-1.243237 z"
id="path3728"
inkscape:connector-curvature="0" />
</svg>

After

Width:  |  Height:  |  Size: 4.1 KiB

55
qtgui/resources/svg/dot.svg

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
height="1000.0"
width="1000.0"
id="svg3059"
inkscape:version="0.48.4 r9939"
sodipodi:docname="dots.dot.svg">
<metadata
id="metadata3067">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs3065" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1916"
inkscape:window-height="1041"
id="namedview3063"
showgrid="false"
inkscape:zoom="13.6"
inkscape:cx="0.36672413"
inkscape:cy="1003.307"
inkscape:window-x="1920"
inkscape:window-y="18"
inkscape:window-maximized="0"
inkscape:current-layer="svg3059" />
<path
glyph-name="dots.dot"
d="m 0.79558812,0 c 0,0.8 0.62499998,1.425 1.42499998,1.425 0.8,0 1.425,-0.625 1.425,-1.425 0,-0.8 -0.625,-1.425 -1.425,-1.425 -0.8,0 -1.42499998,0.625 -1.42499998,1.425 z"
id="path3061"
inkscape:connector-curvature="0" />
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

55
qtgui/resources/svg/flag128.svg

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
height="1000.0"
width="1000.0"
id="svg4340"
inkscape:version="0.91 r13725"
sodipodi:docname="flag128.svg">
<metadata
id="metadata4348">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs4346" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1916"
inkscape:window-height="2096"
id="namedview4344"
showgrid="false"
inkscape:zoom="15.104"
inkscape:cx="16.260679"
inkscape:cy="996.73672"
inkscape:window-x="0"
inkscape:window-y="30"
inkscape:window-maximized="0"
inkscape:current-layer="svg4340" />
<path
glyph-name="flags.d7"
d="m 6.6777542,21.597775 c 0,-0.675 -0.2,-1.275 -0.5,-1.8 0.175,-0.675 0.3,-1.375 0.3,-2.075 0,-0.75 -0.2,-1.425 -0.5,-2.025 0.175,-0.85 0.3,-1.7 0.3,-2.55 0,-0.925 -0.25,-1.75 -0.65,-2.525 0.05,-0.7999999 0.075,-1.6249999 0.075,-2.4249999 0,-0.925 -0.225,-1.7749997 -0.575,-2.5749997 0.05,-0.775 0.05,-1.55 0.05,-2.325 0,-4.7750002 -5.22499996,-7.9750002 -5.22499996,-12.7500002 l 0,-0.225 -0.35,0 0,31.2499998 0.35,0 0,-3.75 c 2.49999996,0.375 5.74999996,1.5 5.74999996,3.775 0,0.425 -0.15,0.875 -0.15,1.3 0,0.3 0.275,0.5 0.55,0.5 0.65,0 0.575,-1.2 0.575,-1.8 z M -0.04724576,-4.4522247 c 1.84999996,2.0999999 4.27499996,4.97500008 4.27499996,7.7500001 0,0.225 -0.025,0.475 -0.025,0.7 -1.7,-2.55 -4.24999996,-4.82499998 -4.24999996,-7.9500001 l 0,-0.5 z m 0,5.5000001 c 2.04999996,1.825 4.77499996,4.425 4.77499996,7.1499997 l 0,1 c -1.875,-2.425 -4.77499996,-4.4499997 -4.77499996,-7.6249997 l 0,-0.525 z m 0,5.5249997 c 2.29999996,1.55 5.34999996,3.8499999 5.34999996,6.5749999 0,0.45 -0.025,0.9 -0.1,1.35 -1.9,-2.375 -5.24999996,-4.1 -5.24999996,-7.2999999 l 0,-0.625 z m 0,5.6249999 c 2.39999996,1.125 5.54999996,2.975 5.54999996,5.525 0,0.375 -0.05,0.725 -0.125,1.1 -1.95,-1.925 -5.42499996,-3.05 -5.42499996,-6 l 0,-0.625 z"
id="path4342"
inkscape:connector-curvature="0" />
</svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

55
qtgui/resources/svg/flag128i.svg

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
height="1000.0"
width="1000.0"
id="svg4350"
inkscape:version="0.91 r13725"
sodipodi:docname="flag128i.svg">
<metadata
id="metadata4358">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs4356" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1916"
inkscape:window-height="2096"
id="namedview4354"
showgrid="false"
inkscape:zoom="42.720563"
inkscape:cx="15.615802"
inkscape:cy="989.49518"
inkscape:window-x="1920"
inkscape:window-y="30"
inkscape:window-maximized="0"
inkscape:current-layer="svg4350" />
<path
glyph-name="flags.u7"
d="m 0.02297803,19.218031 0,-0.475 c 0,-2.85 2.17499997,-5 3.67499997,-7.375 0.1,0.4 0.15,0.825 0.15,1.225 0,2.425 -2.175,4.85 -3.82499997,6.625 z m 0,5.325 c 0,-4.45 4.79999997,-7.5 4.79999997,-11.95 0,-0.825 -0.15,-1.625 -0.45,-2.4 0.425,-0.9000004 0.7,-1.8250004 0.7,-2.85 0,-1.025 -0.25,-2.0499996 -0.7,-2.9749996 0.425,-0.875 0.7,-1.8000004 0.7,-2.8250004 0,-1.02500002 -0.25,-2.05000002 -0.7,-2.975 0.425,-0.875 0.7,-1.825 0.7,-2.85 0,-0.875 -0.325,-1.725 -0.85,-2.425 0.6,-1.05 1.025,-2.125 1.025,-3.375 0,-1.525 -0.4,-3.025 -1.05,-4.425 -0.1,-0.175 -0.275,-0.275 -0.45,-0.275 -0.3,0 -0.6,0.25 -0.525,0.625 0.65,1.275 1.05,2.65 1.05,4.075 0,2.375 -2.425,4.55 -4.24999997,6.075 l 0,-2.7 -0.35,0 0,31.25 0.35,0 z m 0,-11.125 0,-0.5 c 0,-2.875 2.22499997,-5.05 3.72499997,-7.4499996 0.225,0.5999996 0.35,1.2249996 0.35,1.8749996 0,2.3249996 -2.325,4.525 -4.07499997,6.075 z m 0,-5.8 0,-0.5 c 0,-2.8749996 2.22499997,-5.05 3.72499997,-7.45000002 0.225,0.6 0.35,1.225 0.35,1.87500002 0,2.3250004 -2.325,4.525 -4.07499997,6.075 z m 0,-5.825 0,-0.5 c 0,-2.775 2.09999997,-4.85 3.62499997,-7.125 0.275,0.475 0.45,1 0.45,1.55 0,2.325 -2.325,4.52499998 -4.07499997,6.075 z"
id="path4352"
inkscape:connector-curvature="0" />
</svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

55
qtgui/resources/svg/flag16.svg

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
height="1000.0"
width="1000.0"
id="svg3346"
inkscape:version="0.48.4 r9939"
sodipodi:docname="flags.d4.svg">
<metadata
id="metadata3354">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs3352" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1916"
inkscape:window-height="1041"
id="namedview3350"
showgrid="false"
inkscape:zoom="4"
inkscape:cx="-57.95172"
inkscape:cy="1005.6643"
inkscape:window-x="1920"
inkscape:window-y="18"
inkscape:window-maximized="0"
inkscape:current-layer="svg3346" />
<path
glyph-name="flags.d4"
d="m 0.35,5 c 2.325,1.325 5.4,3.375 5.4,6 0,0.625 -0.125,1.25 -0.35,1.825 C 3.4,10.55 0.35,8.75 0.35,5.625 V 5 z m 6.725,11.625 c 0,-1.1 -0.4,-2.05 -0.975,-2.9 C 6.5,12.875 6.725,11.95 6.725,11 6.725,6.45 0.35,4.55 0.35,0 H 0 v 12.5 h 0.35 v -1.875 c 2.475,1.275 5.75,3.3 5.75,6 C 6.1,17.175 5.975,17.7 5.775,18.2 5.7,18.575 6,18.825 6.3,18.825 c 0.7,0 0.775,-1.6 0.775,-2.2 z"
id="path3348"
inkscape:connector-curvature="0" />
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

55
qtgui/resources/svg/flag16i.svg

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
height="1000.0"
width="1000.0"
id="svg3346"
inkscape:version="0.91 r13725"
sodipodi:docname="flag16i.svg">
<metadata
id="metadata3354">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs3352" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1916"
inkscape:window-height="1046"
id="namedview3350"
showgrid="false"
inkscape:zoom="16"
inkscape:cx="12.060729"
inkscape:cy="1000.4471"
inkscape:window-x="0"
inkscape:window-y="30"
inkscape:window-maximized="0"
inkscape:current-layer="svg3346" />
<path
glyph-name="flags.d4"
d="m -0.10266511,5.7253201 c 2.32499981,-1.325 5.39999981,-3.375 5.39999981,-5.99999995 0,-0.62499998 -0.125,-1.24999995 -0.35,-1.82499995 -2,2.27499996 -5.04999981,4.0749999 -5.04999981,7.1999999 l 0,0.625 z m 6.72499981,-11.625 c 0,1.1 -0.4,2.05 -0.975,2.9 0.4,0.85 0.625,1.7750001 0.625,2.72500005 0,4.54999995 -6.37499981,6.44999995 -6.37499981,11.00000085 l -0.35,0 0,-12.5000008 0.35,0 0,1.87499996 C 2.3723347,-1.1746798 5.6473347,-3.1996799 5.6473347,-5.8996799 c 0,-0.55 -0.125,-1.075 -0.325,-1.575 -0.075,-0.375 0.225,-0.625 0.525,-0.625 0.7,0 0.775,1.6 0.775,2.2 z"
id="path3348"
inkscape:connector-curvature="0" />
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

30
qtgui/resources/svg/flag32.svg

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
id="svg3858"
width="1000.0"
height="1000.0"
version="1.1">
<metadata
id="metadata3866">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs3864" />
<path
id="path3860"
d="m 0.35,5.2917931 c 2.25,1.425 5.225,3.575 5.225,6.1749999 0,0.475 -0.125,0.95 -0.3,1.375 C 3.35,10.566793 0.35,8.7667931 0.35,5.6667931 l 0,-0.375 z M 7.075,22.191793 c 0,-1.1 -0.375,-2.025 -0.95,-2.875 0.475,-0.85 0.75,-1.775 0.75,-2.75 0,-1.075 -0.375,-2 -0.925,-2.85 0.375,-0.7 0.6,-1.475 0.6,-2.25 0,-4.6249999 -6.2,-6.7999999 -6.2,-11.4249999 l -0.35,0 0,18.7499999 0.35,0 0,-2.25 c 2.475,1.15 5.75,3.025 5.75,5.65 0,0.55 -0.125,1.05 -0.325,1.55 -0.075,0.375 0.225,0.625 0.525,0.625 0.7,0 0.775,-1.575 0.775,-2.175 z m -6.725,-11.275 c 2.4,1.175 5.55,3.075 5.55,5.65 0,0.675 -0.175,1.3 -0.45,1.9 -2,-2.275 -5.1,-4.05 -5.1,-7.175 l 0,-0.375 z"
glyph-name="flags.d5" />
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

55
qtgui/resources/svg/flag32i.svg

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
height="1000.0"
width="1000.0"
id="svg4021"
inkscape:version="0.91 r13725"
sodipodi:docname="flag32i.svg">
<metadata
id="metadata4029">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs4027" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1916"
inkscape:window-height="1046"
id="namedview4025"
showgrid="false"
inkscape:zoom="30.208"
inkscape:cx="-5.1876193"
inkscape:cy="993.98106"
inkscape:window-x="1920"
inkscape:window-y="1080"
inkscape:window-maximized="0"
inkscape:current-layer="svg4021" />
<path
glyph-name="flags.u5"
d="m 0.01896186,10.917929 0,-0.1 c 0,-2.8500006 2.20000004,-5.0000007 3.70000004,-7.3500007 0.075,0.3 0.125,0.6 0.125,0.925 0,2.4000001 -2.175,4.7750005 -3.82500004,6.5250007 z m 0,5.325 c 0,-4.425 4.80000004,-7.4250002 4.80000004,-11.8500007 0,-0.7 -0.15,-1.4 -0.45,-2.05 0.425,-0.875 0.7,-1.80000009 0.7,-2.82500011 0,-0.89999989 -0.2,-1.77499989 -0.575,-2.59999979 0.45,-0.875 0.75,-1.8250001 0.75,-2.8500001 0,-1.525 -0.4,-3 -1.05,-4.3749993 -0.1,-0.175 -0.275,-0.275 -0.45,-0.275 -0.3,0 -0.6,0.25 -0.525,0.6249993 0.65,1.25 1.05,2.625 1.05,4.025 0,2.3500001 -2.425,4.5 -4.25000004,5.99999989 l 0,-2.57499989 -0.35,0 0,18.7500007 0.35,0 z m 0,-10.7500007 0,-0.125 c 0,-2.875 2.27500004,-4.97500009 3.82500004,-7.35 0.15,0.475 0.25,0.99999991 0.25,1.49999989 0,2.30000011 -2.325,4.45000011 -4.07500004,5.97500011 z"
id="path4023"
inkscape:connector-curvature="0" />
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

55
qtgui/resources/svg/flag64.svg

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
height="1000.0"
width="1000.0"
id="svg3868"
inkscape:version="0.91 r13725"
sodipodi:docname="flag64.svg">
<metadata
id="metadata3876">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs3874" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1916"
inkscape:window-height="2096"
id="namedview3872"
showgrid="false"
inkscape:zoom="21.360282"
inkscape:cx="20.305445"
inkscape:cy="1013.4566"
inkscape:window-x="1920"
inkscape:window-y="30"
inkscape:window-maximized="0"
inkscape:current-layer="svg3868" />
<path
glyph-name="flags.d6"
d="m 6.1854986,20.324093 c 0,-0.675 -0.2,-1.25 -0.5,-1.775 0.175,-0.675 0.3,-1.4 0.3,-2.1 0,-0.75 -0.2,-1.425 -0.5,-2.025 0.175,-0.85 0.3,-1.7 0.3,-2.55 0,-0.925 -0.25,-1.75 -0.65,-2.5249998 0.05,-0.8 0.075,-1.625 0.075,-2.425 0,-4.7000004 -5.74999998,-7.45000037 -5.74999998,-12.1500003 l 0,-0.1 -0.35,0 0,25.0000001 0.35,0 0,-3.125 c 2.49999998,0.375 5.74999998,1.5 5.74999998,3.775 0,0.425 -0.15,0.875 -0.15,1.3 0,0.3 0.275,0.5 0.55,0.5 0.65,0 0.575,-1.2 0.575,-1.8 z M -0.53950138,-0.22590717 C 1.5104986,1.5990928 4.2354986,4.1990928 4.2354986,6.9240932 l 0,1 c -1.875,-2.4250007 -4.77499998,-4.4500004 -4.77499998,-7.62500037 l 0,-0.525 z m 0,5.52499967 c 2.29999998,1.550001 5.34999998,3.8500007 5.34999998,6.5750005 0,0.45 -0.025,0.9 -0.1,1.35 -1.9,-2.375 -5.24999998,-4.0999998 -5.24999998,-7.2999995 l 0,-0.625001 z m 0,5.6250005 c 2.39999998,1.125 5.54999998,2.975 5.54999998,5.525 0,0.375 -0.05,0.725 -0.125,1.1 -1.95,-1.925 -5.42499998,-3.05 -5.42499998,-6 l 0,-0.625 z"
id="path3870"
inkscape:connector-curvature="0" />
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

55
qtgui/resources/svg/flag64i.svg

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
height="1000.0"
width="1000.0"
id="svg4188"
inkscape:version="0.91 r13725"
sodipodi:docname="flag64i.svg">
<metadata
id="metadata4196">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs4194" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1916"
inkscape:window-height="1046"
id="namedview4192"
showgrid="false"
inkscape:zoom="30.208"
inkscape:cx="-6.5278404"
inkscape:cy="999.41198"
inkscape:window-x="0"
inkscape:window-y="1080"
inkscape:window-maximized="0"
inkscape:current-layer="svg4188" />
<path
glyph-name="flags.u6"
d="m -0.04724576,17.153445 0,-0.3 c 0,-2.875 2.19999996,-5.05 3.69999996,-7.4500001 0.1,0.325 0.125,0.6750001 0.125,1.0250001 0,2.45 -2.175,4.925 -3.82499996,6.725 z m 0,5.325 c 0,-4.475 4.79999996,-7.575 4.79999996,-12.05 0,-0.7500001 -0.15,-1.4750001 -0.45,-2.1750001 0.425,-0.9 0.7,-1.8500002 0.7,-2.8750002 0,-0.975 -0.25,-1.925 -0.7,-2.775 0.425,-0.9 0.7,-1.82500001 0.7,-2.85000001 0,-0.82499999 -0.325,-1.59999999 -0.85,-2.22499999 0.6,-1.05 1.025,-2.15 1.025,-3.4 0,-1.55 -0.4,-3.05 -1.05,-4.4499997 -0.1,-0.175 -0.275,-0.275 -0.45,-0.275 -0.3,0 -0.6,0.25 -0.525,0.6249997 0.65,1.275 1.05,2.675 1.05,4.1 0,2.375 -2.425,4.625 -4.24999996,6.17499999 l 0,-2.82499999 -0.35,0 0,25.0000003 0.35,0 z m 0,-10.95 0,-0.3 c 0,-2.9250001 2.24999996,-5.1250003 3.74999996,-7.5500003 0.225,0.525 0.325,1.125 0.325,1.7 0,2.3500002 -2.325,4.5750002 -4.07499996,6.1500003 z m 0,-5.6000003 0,-0.325 c 0,-2.8 2.14999996,-4.92500001 3.67499996,-7.225 0.275,0.4 0.4,0.87499999 0.4,1.37499999 0,2.35000001 -2.325,4.60000001 -4.07499996,6.17500001 z"
id="path4190"
inkscape:connector-curvature="0" />
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

31
qtgui/resources/svg/flag8.svg

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
version="1.1"
width="1000"
height="1000"
id="svg2">
<metadata
id="metadata10">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs8" />
<path
d="M 0.35,6.25 C 2.825,7.725 6.1,10 6.1,12.825 c 0,1.625 -0.525,3.225 -1.35,4.625 -0.075,0.375 0.225,0.625 0.525,0.625 0.175,0 0.35,-0.1 0.45,-0.275 0.825,-1.525 1.35,-3.225 1.35,-4.975 C 7.075,7.7 0.35,5.125 0.35,0 H 0 v 6.25 h 0.35 z"
id="path4" />
</svg>

After

Width:  |  Height:  |  Size: 1009 B

55
qtgui/resources/svg/flag8i.svg

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
height="1000.0"
width="1000.0"
id="svg2"
inkscape:version="0.48.4 r9939"
sodipodi:docname="flag8i.svg">
<metadata
id="metadata10">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs8" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1916"
inkscape:window-height="1041"
id="namedview6"
showgrid="false"
inkscape:zoom="21.360282"
inkscape:cx="22.411917"
inkscape:cy="995.91989"
inkscape:window-x="1920"
inkscape:window-y="18"
inkscape:window-maximized="0"
inkscape:current-layer="svg2" />
<path
glyph-name="flags.d3"
d="M -0.07134228,-0.07030621 C 2.4036578,-1.5453063 5.6786578,-3.8203063 5.6786578,-6.6453063 c 0,-1.6250005 -0.525,-3.2250004 -1.35,-4.6250007 -0.075,-0.375 0.225,-0.625 0.525,-0.625 0.175,0 0.35,0.1 0.45,0.275 0.825,1.525 1.35,3.2250002 1.35,4.9750007 0,5.125 -6.72500008,7.7000001 -6.72500008,12.825 h -0.35 v -6.24999991 h 0.35 z"
id="path4"
inkscape:connector-curvature="0" />
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

56
qtgui/resources/svg/noteheadsBlack.svg

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
width="1000"
height="1000"
id="svg2983"
inkscape:version="0.48.4 r9939"
sodipodi:docname="noteheadsBlack.svg">
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1916"
inkscape:window-height="1041"
id="namedview6"
showgrid="false"
inkscape:zoom="15.104"
inkscape:cx="3.0502115"
inkscape:cy="993.27007"
inkscape:window-x="1920"
inkscape:window-y="18"
inkscape:window-maximized="0"
inkscape:current-layer="svg2983" />
<metadata
id="metadata2991">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs2989" />
<path
d="m 5.3351694,-3.4 c 1.325,0 2.625,0.65 2.625,2.15 0,1.775 -1.425,3.05 -2.6,3.75 -0.9,0.55 -1.95,0.9 -3,0.9 -1.3249999,0 -2.62499991,-0.65 -2.62499991,-2.15 0,-1.775 1.45000001,-3.05 2.62499991,-3.75 0.9,-0.55 1.925,-0.9 2.975,-0.9 z"
id="path2985"
inkscape:connector-curvature="0" />
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

55
qtgui/resources/svg/noteheadsBrevis.svg

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
height="1000.0"
width="1000.0"
id="svg5210"
inkscape:version="0.91 r13725"
sodipodi:docname="noteheadsBrevis.svg">
<metadata
id="metadata5218">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs5216" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1916"
inkscape:window-height="1046"
id="namedview5214"
showgrid="false"
inkscape:zoom="1.888"
inkscape:cx="202.48505"
inkscape:cy="782.26312"
inkscape:window-x="0"
inkscape:window-y="30"
inkscape:window-maximized="0"
inkscape:current-layer="svg5210" />
<path
glyph-name="noteheads.sM1neomensural"
d="m 1.3,-0.8 9.9,0 c 0.3,0 0.55,0.225 0.55,0.525 l 0,0.55 c 0,0.3 -0.25,0.525 -0.55,0.525 l -9.9,0 C 1,0.8 0.75,0.575 0.75,0.275 l 0,-0.55 C 0.75,-0.575 1,-0.8 1.3,-0.8 Z m 9.9,-2.6 -9.9,0 C 0.95,-3.4 0.75,-3.8 0.75,-4.2 0.75,-4.45 0.575,-4.575 0.375,-4.575 0.175,-4.575 0,-4.45 0,-4.2 L 0,4.2 C 0,4.45 0.175,4.575 0.375,4.575 0.575,4.575 0.75,4.45 0.75,4.2 0.75,3.8 0.95,3.4 1.3,3.4 l 9.9,0 c 0.35,0 0.55,0.4 0.55,0.8 0,0.25 0.175,0.375 0.375,0.375 0.2,0 0.375,-0.125 0.375,-0.375 l 0,-8.4 c 0,-0.25 -0.175,-0.375 -0.375,-0.375 -0.2,0 -0.375,0.125 -0.375,0.375 0,0.4 -0.2,0.8 -0.55,0.8 z"
id="path5212"
inkscape:connector-curvature="0" />
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

31
qtgui/resources/svg/noteheadsHalf.svg

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
version="1.1"
width="1000"
height="1000"
id="svg2">
<metadata
id="metadata10">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs8" />
<path
d="m 7.95,-1.675 c 0,-0.625 -0.525,-1.05 -1.075,-1.05 -0.1,0 -0.225,0.025 -0.325,0.05 C 5.775,-2.45 4.575,-1.65 3.625,-1.05 2.675,-0.45 1.5,0.325 0.975,0.95 0.8,1.15 0.7,1.425 0.7,1.675 c 0,0.625 0.525,1.05 1.075,1.05 0.1,0 0.2,-0.025 0.3,-0.05 C 2.85,2.45 4.05,1.65 5,1.05 5.95,0.45 7.15,-0.325 7.675,-0.95 7.85,-1.15 7.95,-1.425 7.95,-1.675 z M 6.675,-3.4 c 1.1,0 1.975,0.5 1.975,1.7 0,0.475 -0.15,0.95 -0.3,1.425 C 8.025,0.65 7.55,1.55 6.725,2.1 5.375,3 3.85,3.4 1.975,3.4 0.875,3.4 0,2.9 0,1.7 0,1.225 0.15,0.75 0.3,0.275 0.625,-0.65 1.075,-1.55 1.9,-2.1 3.25,-3 4.8,-3.4 6.675,-3.4 z"
id="path4" />
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

55
qtgui/resources/svg/noteheadsLonga.svg

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
height="1000.0"
width="1000.0"
id="svg5230"
inkscape:version="0.91 r13725"
sodipodi:docname="noteheadsLonga.svg">
<metadata
id="metadata5238">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs5236" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1916"
inkscape:window-height="1046"
id="namedview5234"
showgrid="false"
inkscape:zoom="21.360282"
inkscape:cx="21.508575"
inkscape:cy="996.82559"
inkscape:window-x="1920"
inkscape:window-y="30"
inkscape:window-maximized="0"
inkscape:current-layer="svg5230" />
<path
glyph-name="noteheads.sM2neomensural"
d="m 1.2531841,-0.773 9.8999999,0 c 0.3,0 0.55,0.22500003 0.55,0.52500003 l 0,0.55 c 0,0.3 -0.25,0.525 -0.55,0.525 l -9.8999999,0 c -0.29999996,0 -0.54999996,-0.225 -0.54999996,-0.525 l 0,-0.55 c 0,-0.3 0.25,-0.52500003 0.54999996,-0.52500003 z m 9.8999999,-2.6 -9.8999999,0 c -0.34999996,0 -0.54999996,-0.4 -0.54999996,-0.8 0,-0.25 -0.175,-0.375 -0.375,-0.375 -0.2,0 -0.375,0.125 -0.375,0.375 l 0,8.4 c 0,0.25 0.175,0.375 0.375,0.375 0.2,0 0.375,-0.125 0.375,-0.375 0,-0.4 0.2,-0.8 0.54999996,-0.8 l 9.8999999,0 c 0.35,0 0.55,0.4 0.55,0.8 0,0.25 0.175,0.375 0.375,0.375 0.2,0 0.375,-0.125 0.375,-0.375 l 0,-8.4 c 0.175,-2.075 0.45,-4.2 0.45,-6.275 0,-0.3 -0.225,-0.425 -0.45,-0.425 -0.225,0 -0.425,0.125 -0.45,0.425 l -0.3,6.25 0,0.025 c 0,0.4 -0.2,0.8 -0.55,0.8 z"
id="path5232"
inkscape:connector-curvature="0" />
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

55
qtgui/resources/svg/noteheadsMaxima.svg

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
height="1000.0"
width="1000.0"
id="svg5250"
inkscape:version="0.91 r13725"
sodipodi:docname="noteheadsMaxima.svg">
<metadata
id="metadata5258">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs5256" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1916"
inkscape:window-height="1046"
id="namedview5254"
showgrid="false"
inkscape:zoom="22.627417"
inkscape:cx="12.473326"
inkscape:cy="990.46191"
inkscape:window-x="0"
inkscape:window-y="1080"
inkscape:window-maximized="0"
inkscape:current-layer="svg5250" />
<path
glyph-name="noteheads.sM3neomensural"
d="m 1.3,-0.81694176 13.65,0 c 0.3,0 0.55,0.22500002 0.55,0.52500002 l 0,0.55 c 0,0.3 -0.25,0.525 -0.55,0.525 l -13.65,0 c -0.3,0 -0.55,-0.225 -0.55,-0.525 l 0,-0.55 c 0,-0.3 0.25,-0.52500002 0.55,-0.52500002 z m 13.65,-2.60000004 -13.65,0 c -0.35,0 -0.55,-0.4 -0.55,-0.8 0,-0.25 -0.175,-0.375 -0.375,-0.375 -0.2,0 -0.375,0.125 -0.375,0.375 l 0,8.4 c 0,0.25 0.175,0.375 0.375,0.375 0.2,0 0.375,-0.125 0.375,-0.375 0,-0.4 0.2,-0.8 0.55,-0.8 l 13.65,0 c 0.35,0 0.55,0.4 0.55,0.8 0,0.25 0.175,0.375 0.375,0.375 0.2,0 0.375,-0.125 0.375,-0.375 l 0,-8.4 c 0.175,-2.075 0.45,-4.2 0.45,-6.2749992 0,-0.3 -0.225,-0.425 -0.45,-0.425 -0.225,0 -0.425,0.125 -0.45,0.425 l -0.3,6.2499992 0,0.025 c 0,0.4 -0.2,0.8 -0.55,0.8 z"
id="path5252"
inkscape:connector-curvature="0" />
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

56
qtgui/resources/svg/noteheadsWhole.svg

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
width="1000"
height="1000"
id="svg3460"
inkscape:version="0.48.4 r9939"
sodipodi:docname="noteheadsWhole.svg">
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1916"
inkscape:window-height="1041"
id="namedview6"
showgrid="false"
inkscape:zoom="5.3400704"
inkscape:cx="3.053232"
inkscape:cy="945.45537"
inkscape:window-x="1920"
inkscape:window-y="18"
inkscape:window-maximized="0"
inkscape:current-layer="svg3460" />
<metadata
id="metadata3468">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs3466" />
<path
d="m 3.0346811,-2.85 c -1.0444213,0 -1.4830783,1.05 -1.4830783,2.2 0,1.975 1.2533056,3.5 2.9034914,3.5 1.0444214,0 1.46219,-1.05 1.46219,-2.2 0,-1.975 -1.2324173,-3.5 -2.8826031,-3.5 z M 8.9669949,0 c 0,1.075 -0.7102069,1.875 -1.5248556,2.4 -1.1279751,0.725 -2.4230576,1 -3.6972516,1 C 2.4706936,3.4 1.1547227,3.125 0.0267476,2.4 -0.78790111,1.875 -1.4981076,1.075 -1.4981076,0 c 0,-1.075 0.71020649,-1.875 1.5248552,-2.4 1.1279751,-0.725 2.443946,-1 3.7181401,-1 1.274194,0 2.5692765,0.275 3.6972516,1 0.8146487,0.525 1.5248556,1.325 1.5248556,2.4 z"
id="path3462"
inkscape:connector-curvature="0" />
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

82
qtgui/resources/svg/numbers.svg

@ -0,0 +1,82 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
width="1000"
height="1000"
id="svg3069"
inkscape:version="0.48.4 r9939"
sodipodi:docname="numbers.svg">
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1916"
inkscape:window-height="1041"
id="namedview2998"
showgrid="false"
inkscape:zoom="9.6166522"
inkscape:cx="147.1806"
inkscape:cy="974.99663"
inkscape:window-x="1920"
inkscape:window-y="18"
inkscape:window-maximized="0"
inkscape:current-layer="svg3069" />
<metadata
id="metadata3077">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs3075" />
<path
d="m 11.745125,-0.48477158 2.725,-6.24999982 c 0.025,-0.05 0.075,-0.075 0.125,-0.075 0.075,0 0.175,0.025 0.25,0.075 0.325,0.15 0.65,0.325 1,0.325 0.35,0 0.65,-0.175 0.975,-0.325 0.025,-0.025 0.075,-0.025 0.1,-0.025 0.15,0 0.275,0.175 0.275,0.4 v 9.3999998 c 0,1.125 0.65,2.2 1.7,2.2 0.175,0 0.275,0.125 0.275,0.25 0,0.125 -0.1,0.275 -0.275,0.275 -1.025,0 -2.025,-0.325 -3.05,-0.325 -1.025,0 -2.05,0.325 -3.075,0.325 -0.175,0 -0.275,-0.15 -0.275,-0.275 0,-0.125 0.1,-0.25 0.275,-0.25 1.05,0 1.7,-1.075 1.7,-2.2 v -6.45 c 0,-0.275 -0.2,-0.425 -0.375,-0.425 -0.1,0 -0.175,0.05 -0.225,0.15 l -1.525,3.47500002 c -0.05,0.15 -0.15,0.2 -0.275,0.2 -0.175,0 -0.35,-0.125 -0.35,-0.325 0,-0.05 0,-0.1 0.025,-0.15 z"
id="one" />
<path
d="m 22.701625,5.5152284 c -0.025,0.175 -0.125,0.25 -0.25,0.25 -0.125,0 -0.275,-0.075 -0.275,-0.25 0,-4.375 5.9,-4.125 5.9,-8.625 0,-1.5249998 -0.55,-3.0999998 -1.875,-3.0999998 -0.625,0 -1.2,0.35 -1.2,0.925 0,0.675 0.875,1.025 0.875,1.6999998 0,0.95 -0.775,1.725 -1.725,1.725 -0.95,0 -1.7,-0.775 -1.7,-1.725 0,-1.8749998 1.775,-3.1499998 3.75,-3.1499998 2.375,0 4.6,1.425 4.6,3.6249998 0,3.95000002 -4.05,4.00000002 -6.425,5.725 0.3,-0.075 0.6,-0.125 0.925,-0.125 0.8,0 1.675,0.25 2.525,0.825 0.575,0.4 1.225,0.625 1.75,0.625 0.5,0 0.925,-0.2 1.05,-0.7 0.025,-0.15 0.15,-0.2 0.25,-0.2 0.125,0 0.275,0.1 0.275,0.25 0,1.575 -2.125,2.475 -3.3,2.475 -0.875,0 -1.725,-0.35 -2.35,-1.05 -0.35,-0.4 -0.8,-0.575 -1.25,-0.575 -0.75,0 -1.475,0.525 -1.55,1.375 z"
id="two" />
<path
d="m 37.483025,-6.2097714 c -0.7,0 -1.45,0.225 -1.45,0.825 0,0.55 0.9,0.625 0.9,1.175 0,0.7999998 -0.625,1.4249998 -1.425,1.4249998 -0.8,0 -1.425,-0.625 -1.425,-1.4249998 0,-1.575 1.65,-2.525 3.4,-2.525 2.25,0 4.125,0.875 4.125,2.8749998 0,1.1 -0.075,2.075 -1.025,2.525 -0.2,0.1 -0.325,0.3 -0.325,0.50000002 0,0.2 0.125,0.4 0.325,0.5 1.025,0.475 1.375,1.44999998 1.375,2.59999998 0,2.275 -1.925,3.5 -4.375,3.5 -1.925,0 -3.775,-1.025 -3.775,-2.775 0,-0.9 0.725,-1.625 1.625,-1.625 0.9,0 1.625,0.725 1.625,1.625 0,0.625 -1,0.7 -1,1.325 0,0.65 0.775,0.925 1.525,0.925 1.25,0 1.65,-1.525 1.65,-2.975 0,-1.54999998 -0.025,-2.74999998 -1.35,-2.74999998 h -2.05 c -0.225,0 -0.325,-0.175 -0.325,-0.35 0,-0.17500002 0.1,-0.32500002 0.325,-0.32500002 h 2.05 c 1.3,0 1.35,-1.175 1.35,-2.7 0,-1.3999998 -0.45,-2.3499998 -1.75,-2.3499998 z"
id="three" />
<path
d="m 49.439525,-2.2097716 c 0.525,-0.325 1.05,-0.675 1.425,-1.175 0.275,-0.375 0.45,-0.7999998 0.625,-1.2249998 0.1,-0.225 0.5,-0.175 0.5,0.175 v 6.3999998 h 1.7 c 0.225,0 0.325,0.175 0.325,0.35 0,0.175 -0.1,0.325 -0.325,0.325 h -1.7 v 0.4 c 0,1.125 0.65,2.2 1.7,2.2 0.175,0 0.25,0.125 0.25,0.25 0,0.125 -0.075,0.275 -0.25,0.275 -1.025,0 -2.05,-0.325 -3.075,-0.325 -1.025,0 -2.05,0.325 -3.075,0.325 -0.175,0 -0.25,-0.15 -0.25,-0.275 0,-0.125 0.075,-0.25 0.25,-0.25 1.05,0 1.7,-1.075 1.7,-2.2 v -0.4 h -4.325 c -0.525,0 -0.725,-0.325 -0.725,-0.525 0,-0.05 0.025,-0.125 0.05,-0.15 2.025,-2.39999998 3.65,-5.2 3.65,-8.3249998 0,-0.2 0.125,-0.375 0.3,-0.375 h 0.075 c 0.55,0.175 1.1,0.325 1.675,0.325 0.575,0 1.125,-0.15 1.675,-0.325 0.05,-0.025 0.05,-0.025 0.1,-0.025 0.25,0 0.4,0.25 0.275,0.4 l -7.075,8.3249998 h 4.325 v -3.675 c 0,-0.2 0.05,-0.4 0.2,-0.5 z"
id="four" />
<path
d="m 57.108425,-6.7347714 c 1.125,0.2 2.275,0.325 3.425,0.325 1.15,0 2.3,-0.125 3.425,-0.325 h 0.075 c 0.275,0 0.425,0.25 0.3,0.375 -1.7,1.7 -4.175,2.175 -6.575,2.175 -0.2,0 -0.375,0.1749998 -0.375,0.3749998 v 2.7 c 0.7,-0.7 1.625,-1.175 2.6,-1.175 2.875,0 4.6,1.275 4.6,4.025 0,2.3 -2.075,4.025 -4.475,4.025 -2.05,0 -4.05,-0.95 -4.05,-2.775 0,-0.9 0.725,-1.625 1.625,-1.625 0.9,0 1.625,0.725 1.625,1.625 0,0.625 -1,0.7 -1,1.325 0,0.75 0.925,0.925 1.8,0.925 1.425,0 1.75,-1.825 1.75,-3.5 0,-1.62499998 -0.45,-3.35 -1.875,-3.35 -1.025,0 -2.075,0.35 -2.65,1.20000002 -0.075,0.1 -0.175,0.125 -0.275,0.125 -0.175,0 -0.325,-0.125 -0.325,-0.325 V -6.3597714 c 0,-0.2 0.15,-0.375 0.325,-0.375 h 0.05 z"
id="five" />
<path
d="m 71.527325,-0.60977158 c -1.4,0 -1.425,1.275 -1.425,2.92499998 0,1.65 0.025,2.925 1.425,2.925 1.45,0 1.6,-1.25 1.6,-2.925 0,-1.67499998 -0.15,-2.92499998 -1.6,-2.92499998 z m -1.425,-0.2 c 0.475,-0.175 0.925,-0.35000002 1.425,-0.35000002 2.475,0 4.175,1.15000002 4.175,3.475 0,2.325 -1.7,3.45 -4.175,3.45 -2.775,0 -4.15,-3.125 -4.15,-6.24999998 0,-3.20000002 1.725,-6.24999982 4.65,-6.24999982 1.725,0 3.4,0.95 3.4,2.525 0,0.8999998 -0.725,1.6249998 -1.625,1.6249998 -0.9,0 -1.625,-0.725 -1.625,-1.6249998 0,-0.575 0.975,-0.65 0.975,-1.225 0,-0.5 -0.575,-0.775 -1.125,-0.775 -1.75,0 -1.95,1.775 -1.95,3.7749998 0,0.55 0.025,1.075 0.025,1.62500002 z"
id="six" />
<path
d="m 79.958825,-4.7347714 c -0.75,0 -0.925,0.9999998 -0.925,1.6749998 v 2.17500002 c 0,0.225 -0.175,0.325 -0.35,0.325 -0.175,0 -0.325,-0.1 -0.325,-0.325 V -6.4847714 c 0,-0.225 0.15,-0.325 0.325,-0.325 0.175,0 0.35,0.1 0.35,0.325 v 0.35 c 0,0.225 0.25,0.45 0.325,0.35 0.475,-0.675 1.175,-1.025 1.9,-1.025 0.725,0 1.475,0.325 2.1,0.925 0.325,0.3 0.7,0.45 1.1,0.45 0.75,0 1.575,-0.475 2.1,-1.225 0.075,-0.1 0.15,-0.15 0.25,-0.15 0.175,0 0.35,0.15 0.35,0.325 0,0.05 0,0.125 -0.05,0.2 -2.1,2.9999998 -4.125,6.32499982 -4.125,9.8249998 0,0.6 0.05,1.2 0.175,1.825 0.05,0.2 -0.1,0.4 -0.275,0.4 -0.025,0 -0.075,-0.025 -0.1,-0.025 -0.575,-0.175 -1.125,-0.375 -1.725,-0.375 -0.6,0 -1.15,0.2 -1.725,0.375 -0.025,0 -0.075,0.025 -0.1,0.025 -0.2,0 -0.35,-0.2 -0.275,-0.4 1.4,-3.3 3.45,-6.24999998 5.525,-9.15 -0.525,0.3 -1.05,0.475 -1.55,0.475 -0.525,0 -1.025,-0.175 -1.475,-0.6 -0.475,-0.4499998 -1.025,-0.8249998 -1.5,-0.8249998 z"
id="seven" />
<path
d="m 95.727725,-1.3597716 c 0.725,-0.75 1.35,-1.55 1.35,-2.575 0,-1.3999998 -1.45,-2.2749998 -2.975,-2.2749998 -1.225,0 -1.95,0.95 -1.95,1.875 0,0.5499998 0.225,1.0499998 0.775,1.3749998 z m 0.675,0.40000002 c 1.375,0.8 2.125,1.95 2.125,3.17499998 0,1.8 -1.625,3.55 -4.625,3.55 -2.3,0 -4.475,-1.325 -4.475,-3.45 0,-1.275 1,-2.14999998 1.95,-3.02499998 -1.1,-0.70000002 -1.6,-1.72500002 -1.6,-2.72500002 0,-1.6749998 1.5,-3.2999998 4.325,-3.2999998 2,0 3.95,1 3.95,2.7999998 0,1.2 -0.8,2.1 -1.65,2.97500002 z m -4.325,0.65 c -0.85,0.75 -1.65,1.52499998 -1.65,2.62499998 0,1.725 1.65,2.925 3.475,2.925 1.375,0 2.2,-1.075 2.2,-2.125 0,-0.625 -0.275,-1.275 -0.925,-1.65 z"
id="eight" />
<path
d="m 105.18422,-0.35977158 c 1.40001,0 1.45001,-1.27500002 1.45001,-2.92500002 0,-1.6499998 -0.05,-2.9249998 -1.45001,-2.9249998 -1.45,0 -1.59999,1.25 -1.59999,2.9249998 0,1.675 0.15,2.92500002 1.59999,2.92500002 z m 1.45001,0.2 c -0.475,0.175 -0.95001,0.35 -1.45001,0.35 -2.47499,0 -4.15,-1.15 -4.15,-3.47500002 0,-2.3249998 1.675,-3.4499998 4.15,-3.4499998 2.77501,0 4.175,3.1249998 4.175,6.24999982 0,3.19999998 -1.75,6.24999998 -4.675,6.24999998 -1.72499,0 -3.375,-0.95 -3.375,-2.525 0,-0.9 0.725,-1.625 1.625,-1.625 0.90001,0 1.625,0.725 1.625,1.625 0,0.575 -0.97499,0.65 -0.97499,1.225 0,0.5 0.55,0.775 1.09999,0.775 1.75,0 1.95001,-1.775 1.95001,-3.775 v -1.62499998 z"
id="nine" />
<path
d="m 4.4749996,-5.8977814 c -1.65,0 -1.75,2.5 -1.75,4.575 v 1.00000002 1 c 0,2.07499998 0.1,4.57499998 1.75,4.57499998 1.65,0 1.775,-2.5 1.775,-4.57499998 v -1 -1.00000002 c 0,-2.075 -0.125,-4.575 -1.775,-4.575 z m 0,-0.675 c 2.875,0 4.5,3.075 4.5,6.25000002 0,3.17499998 -1.625,6.24999998 -4.5,6.24999998 C 1.6,5.9272186 0,2.8522186 0,-0.32278138 0,-3.4977814 1.6,-6.5727814 4.4749996,-6.5727814 z"
id="zero" />
</svg>

After

Width:  |  Height:  |  Size: 8.8 KiB

56
qtgui/resources/svg/rest1.svg

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
width="1000"
height="1000"
id="svg3361"
inkscape:version="0.48.4 r9939"
sodipodi:docname="rest1.svg">
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1916"
inkscape:window-height="1041"
id="namedview3154"
showgrid="false"
inkscape:zoom="4.8083261"
inkscape:cx="111.64752"
inkscape:cy="988.38611"
inkscape:window-x="1920"
inkscape:window-y="18"
inkscape:window-maximized="0"
inkscape:current-layer="svg3361" />
<metadata
id="metadata3369">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs3367" />
<path
d="M 10.00689,0 H 1.0318903 c -0.1,0 -0.19999997,-0.1 -0.19999997,-0.2 v -3.5 c 0,-0.1 0.1,-0.2 0.19999997,-0.2 H 10.00689 c 0.1,0 0.2,0.1 0.2,0.2 v 3.5 c 0,0.1 -0.1,0.2 -0.2,0.2 z"
id="path3363"
inkscape:connector-curvature="0" />
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

31
qtgui/resources/svg/rest128.svg

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
version="1.1"
width="1000"
height="1000"
id="svg3431">
<metadata
id="metadata3439">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs3437" />
<path
d="m 3.675,22.285593 1.525,-8.25 c -0.975,0.35 -1.975,0.65 -3.025,0.65 -1.15,0 -2.175,-0.85 -2.175,-2 0,-0.975 0.775,-1.775 1.775,-1.775 0.65,0 1.225,0.4 1.425,1 0.25,0.7 0.15,1.5 0.875,1.5 0.45,0 1.5,-1.45 1.6,-1.925 L 6.35,7.8105933 c -0.95,0.325 -1.9,0.625 -2.9,0.625 -1.15,0 -2.2,-0.85 -2.2,-2 0,-0.975 0.8,-1.775 1.8,-1.775 0.65,0 1.2,0.4 1.4,1 0.25,0.7 0.175,1.5 0.9,1.5 0.425,0 1.375,-1.4 1.45,-1.875 l 0.7,-3.7 c -0.9,0.325 -1.85,0.6 -2.8,0.6 -1.15,0 -2.175,-0.85 -2.175,-2.00000002 0,-0.975 0.775,-1.77499998 1.775,-1.77499998 0.65,0 1.225,0.4 1.425,0.99999998 0.25,0.7 0.15,1.5 0.875,1.5 0.4,0 1.275,-1.35 1.35,-1.8 l 0.7,-3.74999998 c -0.875,0.3 -1.775,0.575 -2.7,0.575 -1.15,0 -2.175,-0.85 -2.175,-2 0,-0.975 0.8,-1.775 1.8,-1.775 0.65,0 1.2,0.4 1.4,1 0.25,0.7 0.175,1.5 0.9,1.5 0.4,0 1.15,-1.325 1.225,-1.75 l 0.7,-3.7750003 c -0.825,0.3 -1.7,0.55 -2.575,0.55 -1.15,0 -2.175,-0.85 -2.175,-2 0,-0.975 0.775,-1.775 1.775,-1.775 0.65,0 1.225,0.4 1.425,1 0.25,0.7 0.15,1.5 0.875,1.5 0.4,0 0.975,-1.375 1.125,-1.75 0.1,-0.275 0.5,-0.275 0.6,0 l -5.975,35.625 c -0.175,0.15 -0.4,0.225 -0.6,0.225 -0.2,0 -0.425,-0.075 -0.6,-0.225 z"
id="path3433" />
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

55
qtgui/resources/svg/rest16.svg

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
height="1000.0"
width="1000.0"
id="svg3401"
inkscape:version="0.48.4 r9939"
sodipodi:docname="rests.4.svg">
<metadata
id="metadata3409">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs3407" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1916"
inkscape:window-height="1041"
id="namedview3405"
showgrid="false"
inkscape:zoom="2.6700352"
inkscape:cx="109.38042"
inkscape:cy="1014.0746"
inkscape:window-x="1920"
inkscape:window-y="18"
inkscape:window-maximized="0"
inkscape:current-layer="svg3401" />
<path
glyph-name="rests.4"
d="M 2.4,8.7636456 4.9,0.58864559 C 4.025,0.9136455 3.1,1.1636455 2.175,1.1636455 1.025,1.1636455 0,0.31364559 0,-0.83635441 0,-1.8113544 0.775,-2.6113544 1.775,-2.6113544 c 0.65,0 1.225,0.4 1.425,1 0.25,0.69999999 0.15,1.49999999 0.875,1.49999999 0.425,0 1.425,-1.32499999 1.55,-1.74999999 l 1.175,-3.8 c -0.85,0.3 -1.75,0.575 -2.675,0.575 -1.15,0 -2.175,-0.85 -2.175,-2 0,-0.975 0.775,-1.7750001 1.775,-1.7750001 0.65,0 1.225,0.4 1.425,1.0000001 0.25,0.7 0.15,1.5 0.875,1.5 0.425,0 1.325,-1.35 1.5,-1.75 0.1,-0.2750001 0.5,-0.2750001 0.6,0 l -4.55,16.875 c -0.175,0.15 -0.375,0.225 -0.575,0.225 -0.2,0 -0.425,-0.075 -0.6,-0.225 z"
id="path3403"
inkscape:connector-curvature="0" />
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

56
qtgui/resources/svg/rest2.svg

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
width="1000"
height="1000"
id="svg3371"
inkscape:version="0.48.4 r9939"
sodipodi:docname="rest2.svg">
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1916"
inkscape:window-height="1041"
id="namedview3160"
showgrid="false"
inkscape:zoom="3.776"
inkscape:cx="200.7814"
inkscape:cy="1013.0608"
inkscape:window-x="1920"
inkscape:window-y="18"
inkscape:window-maximized="0"
inkscape:current-layer="svg3371" />
<metadata
id="metadata3379">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs3377" />
<path
d="m 10.234322,3.9325324 h -8.975 c -0.1,0 -0.2,-0.1 -0.2,-0.2 V 0.23253243 c 0,-0.1 0.1,-0.2 0.2,-0.2 h 8.975 c 0.1,0 0.2,0.1 0.2,0.2 V 3.7325324 c 0,0.1 -0.1,0.2 -0.2,0.2 z"
id="path3373"
inkscape:connector-curvature="0" />
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

31
qtgui/resources/svg/rest32.svg

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
version="1.1"
width="1000"
height="1000"
id="svg3411">
<metadata
id="metadata3419">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs3417" />
<path
d="m 2.825,15.692393 2.15,-8.1999998 c -0.9,0.325 -1.825,0.6 -2.8,0.6 -1.15,0 -2.175,-0.85 -2.175,-2 0,-0.975 0.775,-1.775 1.775,-1.775 0.65,0 1.2,0.4 1.4,1 0.25,0.7 0.175,1.5 0.9,1.5 0.425,0 1.425,-1.35 1.55,-1.8 l 0.975,-3.75 c -0.875,0.325 -1.8,0.575 -2.725,0.575 -1.15,0 -2.175,-0.85000005 -2.175,-2.00000005 0,-0.97499995 0.8,-1.77499995 1.8,-1.77499995 0.65,0 1.2,0.4 1.4,0.99999995 0.25,0.7 0.175,1.5 0.9,1.5 0.425,0 1.35,-1.325 1.45,-1.74999995 l 1,-3.8 c -0.85,0.3 -1.75,0.575 -2.65,0.575 -1.15,0 -2.175,-0.85 -2.175,-2 0,-0.975 0.775,-1.775 1.775,-1.775 0.65,0 1.225,0.4 1.425,1 0.25,0.7 0.15,1.5 0.875,1.5 0.4,0 1.225,-1.35 1.375,-1.75 0.1,-0.275 0.5,-0.275 0.6,0 L 4,15.692393 c -0.175,0.15 -0.375,0.225 -0.575,0.225 -0.2,0 -0.425,-0.075 -0.6,-0.225 z"
id="path3413" />
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

56
qtgui/resources/svg/rest4.svg

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
width="1000"
height="1000"
id="svg3381"
inkscape:version="0.48.4 r9939"
sodipodi:docname="rest4.svg">
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1916"
inkscape:window-height="1041"
id="namedview3166"
showgrid="false"
inkscape:zoom="7.552"
inkscape:cx="48.972702"
inkscape:cy="1004.0443"
inkscape:window-x="1920"
inkscape:window-y="18"
inkscape:window-maximized="0"
inkscape:current-layer="svg3381" />
<metadata
id="metadata3389">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs3387" />
<path
d="m 1.7213983,2.340538 c 0,-0.65 0.25,-1 0.9,-1 0.85,0 2.125,0.375 3.25,0.925 l -3.425,-4.1 c -0.175,-0.2 -0.25,-0.425 -0.25,-0.625 0,-0.825 1.225,-1.6 2.15,-2.4 0.65,-0.55 0.975,-1.35 0.975,-2.125 0,-0.6 -0.2,-1.175 -0.6,-1.675 l -0.975,-1.15 c -0.05,-0.075 -0.075,-0.15 -0.075,-0.225 0,-0.175 0.175,-0.35 0.35,-0.35 0.075,0 0.175,0.025 0.25,0.125 l 3.8,4.55 c 0.175,0.2 0.25,0.425 0.25,0.625 0,0.825 -1.225,1.6 -2.15,2.4 -0.65,0.55 -0.975,1.35 -0.975,2.12499995 0,0.6 0.2,1.175 0.6,1.67500005 l 2.175,2.6 c 0.05,0.075 0.075,0.125 0.075,0.2 0,0.175 -0.175,0.35 -0.35,0.35 -0.075,0 -0.175,-0.025 -0.25,-0.125 -0.475,-0.55 -1.65,-1.075 -2.55,-1.075 -1,0 -1.3,0.725 -1.3,1.75 0,0.875 0.275,1.875 0.7,2.4 0.1,0.125 0,0.275 -0.125,0.275 -0.05,0 -0.1,0 -0.125,-0.05 -1.15,-1.375 -2.325,-3.75 -2.325,-5.1 z"
id="path3383"
inkscape:connector-curvature="0" />
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

31
qtgui/resources/svg/rest64.svg

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
version="1.1"
width="1000"
height="1000"
id="svg3421">
<metadata
id="metadata3429">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs3427" />
<path
d="m 3.275,19.107627 1.825,-8.225 c -0.95,0.325 -1.925,0.625 -2.925,0.625 -1.15,0 -2.175,-0.85 -2.175,-1.9999998 0,-0.975 0.8,-1.775 1.8,-1.775 0.65,0 1.2,0.4 1.4,1 0.25,0.7 0.175,1.4999998 0.9,1.4999998 0.45,0 1.45,-1.3999998 1.55,-1.8749998 l 0.825,-3.7 c -0.9,0.325 -1.825,0.6 -2.8,0.6 -1.15,0 -2.175,-0.85 -2.175,-2 0,-0.975 0.775,-1.775 1.775,-1.775 0.65,0 1.225,0.4 1.425,1 0.25,0.7 0.15,1.5 0.875,1.5 0.425,0 1.35,-1.375 1.45,-1.825 l 0.85,-3.725 c -0.875,0.3 -1.775,0.57499996 -2.7,0.57499996 -1.15,0 -2.2,-0.84999996 -2.2,-1.99999996 0,-0.975 0.8,-1.775 1.8,-1.775 0.65,0 1.2,0.4 1.4,1 0.25,0.7 0.175,1.5 0.9,1.5 0.4,0 1.225,-1.325 1.325,-1.75 l 0.85,-3.775 c -0.85,0.3 -1.7,0.55 -2.6,0.55 -1.15,0 -2.175,-0.85 -2.175,-2 0,-0.9750002 0.775,-1.7750002 1.775,-1.7750002 0.65,0 1.225,0.4 1.425,1 0.25,0.7000002 0.15,1.5000002 0.875,1.5000002 0.4,0 1.1,-1.375 1.25,-1.7500002 0.1,-0.275 0.5,-0.275 0.6,0 l -5.95,29.375 c -0.175,0.15 -0.4,0.225 -0.6,0.225 -0.2,0 -0.4,-0.075 -0.575,-0.225 z"
id="path3423" />
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

56
qtgui/resources/svg/rest8.svg

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
width="1000"
height="1000"
id="svg3391"
inkscape:version="0.48.4 r9939"
sodipodi:docname="rest8.svg">
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1916"
inkscape:window-height="1041"
id="namedview3172"
showgrid="false"
inkscape:zoom="21.360282"
inkscape:cx="2.1888882"
inkscape:cy="1000.2744"
inkscape:window-x="1920"
inkscape:window-y="18"
inkscape:window-maximized="0"
inkscape:current-layer="svg3391" />
<metadata
id="metadata3399">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs3397" />
<path
d="m 2.5586062,5.3929035 2.9,-8.175 c -0.875,0.3 -1.75,0.575 -2.675,0.575 -1.15,0 -2.17499999,-0.85 -2.17499999,-2 0,-0.975 0.77499999,-1.775 1.77499999,-1.775 0.65,0 1.225,0.4 1.425,1 0.25,0.7 0.15,1.5 0.875,1.5 0.425,0 1.45,-1.35 1.625,-1.75 0.125,-0.275 0.5,-0.25 0.6,0 l -3.15,10.625 c -0.175,0.15 -0.4,0.225 -0.6,0.225 -0.2,0 -0.425,-0.075 -0.6,-0.225 z"
id="path3393"
inkscape:connector-curvature="0" />
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

55
qtgui/resources/svg/restBrevis.svg

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
height="1000.0"
width="1000.0"
id="svg3445"
inkscape:version="0.91 r13725"
sodipodi:docname="restBrevis.svg">
<metadata
id="metadata3453">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs3451" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1916"
inkscape:window-height="1046"
id="namedview3449"
showgrid="false"
inkscape:zoom="21.360282"
inkscape:cx="6.1128518"
inkscape:cy="995.35539"
inkscape:window-x="0"
inkscape:window-y="30"
inkscape:window-maximized="1"
inkscape:current-layer="svg3445" />
<path
glyph-name="rests.M1mensural"
d="m 5.475,6.6869704 0,-6.25000004 -5.475,-0.5 0,6.25000004 z"
id="path3447"
inkscape:connector-curvature="0" />
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

55
qtgui/resources/svg/restLonga.svg

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
height="1000.0"
width="1000.0"
id="svg3475"
inkscape:version="0.91 r13725"
sodipodi:docname="restLonga.svg">
<metadata
id="metadata3483">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs3481" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1916"
inkscape:window-height="1046"
id="namedview3479"
showgrid="false"
inkscape:zoom="30.208"
inkscape:cx="8.5318575"
inkscape:cy="998.6441"
inkscape:window-x="1920"
inkscape:window-y="30"
inkscape:window-maximized="0"
inkscape:current-layer="svg3475" />
<path
glyph-name="rests.M2mensural"
d="M 5.475,6.5 5.475,-6 0,-6.5 0,6 Z"
id="path3477"
inkscape:connector-curvature="0" />
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

55
qtgui/resources/svg/restMaxima.svg

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
height="1000.0"
width="1000.0"
id="svg3505"
inkscape:version="0.91 r13725"
sodipodi:docname="restMaxima.svg">
<metadata
id="metadata3513">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs3511" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1916"
inkscape:window-height="1046"
id="namedview3509"
showgrid="false"
inkscape:zoom="30.208"
inkscape:cx="-8.3469377"
inkscape:cy="999.28205"
inkscape:window-x="0"
inkscape:window-y="1080"
inkscape:window-maximized="0"
inkscape:current-layer="svg3505" />
<path
glyph-name="rests.M3mensural"
d="m 5.475,12.84428 0,-18.7500003 -5.475,-0.5 0,18.7500003 z"
id="path3507"
inkscape:connector-curvature="0" />
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

31
qtgui/resources/svg/scriptsStaccato.svg

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
version="1.1"
width="1000"
height="1000"
id="svg3504">
<metadata
id="metadata3512">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs3510" />
<path
d="M -1.25,0 C -1.25,0.7 -0.7,1.25 0,1.25 0.7,1.25 1.25,0.7 1.25,0 1.25,-0.7 0.7,-1.25 0,-1.25 -0.7,-1.25 -1.25,-0.7 -1.25,0 z"
id="path3506" />
</svg>

After

Width:  |  Height:  |  Size: 911 B

678
qtgui/resources/svg/svg.license.txt

@ -0,0 +1,678 @@
Laborejos Notation Glyphs are based on Lilypond - Lilypond Team, GPLv3, http://lilypond.org/
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.

2
qtgui/resources/translations/config.pro

@ -0,0 +1,2 @@
SOURCES = ../../mainwindow.py ../../designer/mainwindow.py
TRANSLATIONS = de.ts

BIN
qtgui/resources/translations/de.qm

Binary file not shown.

11
qtgui/resources/translations/de.ts

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS><TS version="2.0" language="de" sourcelanguage="">
<context>
<name>About</name>
<message>
<location filename="../../mainwindow.py" line="57"/>
<source>This is an example application. Extend it to your liking. Start by editing config.py</source>
<translation>Willkommen im Beispielprogramm. Erstellen Sie neue Programme auf dieser Grundlage wie es Ihnen gefällt. Ein guter Einstieg wäre config.py</translation>
</message>
</context>
</TS>

5
qtgui/resources/translations/update.sh

@ -0,0 +1,5 @@
#!/bin/sh
set -e
pylupdate5 config.pro
echo "linguist-qt5 de.ts"

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save