Introduces a new class FileRevealer to manage file selection across different platforms (Windows, macOS, Linux, and other *nix operating systems with xdg). Includes methods to open and select files or directories using the default file manager on the respective platform.
---------
Co-authored-by: Tres Finocchiaro <tres.finocchiaro@gmail.com>
Co-authored-by: Hyunjin Song <tteu.ingog@gmail.com>
Co-authored-by: Sotonye Atemie <sakertooth@gmail.com>
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
* Use dbFS scale for the faders
Make the faders use a linear dbFS scale. They now also change position on first click and can then be dragged.
The `Fader` class now has a new property called `m_faderMinDb`. It's the minimum value before the amplification drops down fully to 0. It is needed because we cannot represent a scale from -inf to maxDB.
Rename `knobPosY` to `calculateKnobPosYFromModel` and move the implementation into the cpp file. The method now first converts the model's current amplification value to dbFS and then computes a ratio based on that values and the minimum and maximum dbFS values.
Add the method `setVolumeByLocalPixelValue` which takes a local y coordinate of the widget and sets the amplification of the model based on a dbFS scale.
Adjust `mousePressEvent` and `mouseMoveEvent` so that they mostly take the local y coordinate of the event and use that to adjust the model via `setVolumeByLocalPixelValue`.
Remove `m_moveStartPoint` and `m_startValue` and they are not needed anymore.
* Apply curve to faders
Apply a curve, i.e. the cube function and its inverse, to the fader
positions to that we have more space to work with in the "interesting"
areas around 0 dB and less space in the area where we tend to "-inf dB".
Set the minimum dB value of the fader to -120 dB to increase the potential
headroom.
* Support for dB models
Add support for models that are in dB.
There's a new member `m_modelIsLinear` which can be set via the
constructor. The default value in the constructor is `true`.
Add the method `modelIsLinear` which can be used to query the parameter.
It is used in `calculateKnobPosYFromModel` and
`setVolumeByLocalPixelValue`. Both methods got extended to deal with
models in dB. They were also refactored to extract code that is common
for both cases.
Ensure that the constructor of `Fader` is called with `false` for
`CrossoverEQControlDialog` and `EqFader` because these use models that
are in dB.
* Show current dB value of fader in tool tip
Show the current value of the fader in its tool tip. Please note that
this value is always shown in dB because the goal should be to get rid
of the linear values for the faders.
Some of the code is extracted into the new method
`Fader::getModelValueAsDbString` which is shared by
`Fader::modelValueChanged` (also new) and `Fader::updateTextFloat`.
Please note that `getModelValueAsDbString` will use "dB" instead of
"dBFS" as the unit and that it will format "-inf dB" instead of "-∞ dB".
These changes will also be visible in the text float that is used to
show the new values as the fader is being dragged.
* Let users enter values in dB
Let users enter values in dB in the dialog that opens with a double
click.
The minimum value that can be entered is the minimum value that the
fader allows to set, i.e. -120 dB. The maximum value is the maximum
value of the model converted to dB. As of now this is ~6 dB. The
current value is converted to dB. If it corresponds to "-inf dB", i.e.
if the amplification is 0 then the minimum value is used.
* Remove option "Display volume as dBFS"
Remove the option "Display volume as dBFS" from the settings dialog and
the check box option "Volume as dBFS" from the "View" menu. Volumes are
now always treated as dB, i.e. all evaluations of the property
"displaydbfs" have been removed which results in assuming that this
option is always true.
The upgrade code in `ConfigManager::upgrade_1_1_91` was left as is.
However, a note was added which informs the reader that the value of
"displaydbfs" is not evaluated anymore.
* Extend Fader::wheelEvent
Extend `Fader::wheelEvent` for the case where the model is not a dB
model (`modelIsLinear() == true`), e.g. for the mixer faders. In that
case it works as follows. Each step increments or decrements by 1 dB if
no modifier is pressed. With "Shift" pressed the increment value is 3 dB.
With "STRG" ("CTRL") pressed the increment value is reduced to 0.1 dB. If
the value goes below the minimum positive dB value that is allowed by the
fader then the fader is set to "-inf dB", i.e. zero amplification. If the
fader is set to "-inf dB" and the users want to increase the value then
it is first set to the minimum positive value that is allowed by the
fader.
If the model is a dB model then the same behavior as before is used.
Although it should be considered to adjust this case as well. These
models are used by the faders of the Crossover Equalizer, Equalizer,
Compressor and Delay and they are not very usable with the mouse wheel.
* Adjust the wheel behavior for faders with dB models
Make the faders of the Crossover Equalizer, Equalizer, Compressor and
Delay behave like the mixer faders, i.e. step in sizes of 3 dB, 1dB and
0.1 dB depending on whether a modifier key is pressed or not.
Extract some common code to do so and add some `const` keywords.
* Less "jumpy" knobs
Implement a more stable knob behavior.
Remove the jumping behavior if the users directly click on a volume
knob. By storing the offset from the knob center and taking it into
account during the changes it now also feels like the users are
dragging the knob.
Changes to the amplification are now only applied when the mouse is
moved. This makes the double click behavior much more stable, i.e. if
users click on the knob when it is at 0 dB the dialog will also show
0 dB and not something like 0.3 dB because the first click is already
registered as a change of volume.
If the users click next to the knob the amplification will still be
changed immediately to that value.
## Technical details
To make the knobs more stable a variable called `m_knobCenterOffset` was
introduced. It stores the offset of the click from the knob center so
that this value can be taken into account for in the method
`setVolumeByLocalPixelValue`.
* Make MSVC happy
Add an indication that a float value is assigned to a float variable.
* Introduce constexpr for scaling exponent
Introduce the `constexpr c_dBScalingExponent` which describes the
scaling exponent that's used to scale the dB scale in both directions.
This will simplify potential adjustments by keeping the values
consistent everywhere.
* Draw fader ticks
Draw fader ticks in case the model is a linear one. This means that for
now they should only be painted for the mixer faders but not for the
faders of the Compressor, Delay, etc.
Extract the computation of the scaled ratio between the maximum model dB
value and the minimum supported fader dB value into the new private
method `computeScaledRatio`. This is necessary because it is needed to
paint the fader knob at the correct position (using the knob bottom as
the reference) and to paint the fader ticks at the correct position
(using the knob center).
Introduce the private method `paintFaderTicks` which paints the fader
ticks.
Note: to paint some non-evenly spaced fader ticks replace the `for`
expression in `paintFaderTicks` with something like the following:
```
for (auto & i : {6.f, 0.f, -6.f, -12.f, -24.f, -36.f, -48.f, -60.f, -72.f, -84.f, -96.f, -108.f, -120.f})
```
* Fader adjustments via keyboard
Allow the adjustment of the faders via the keyboard. Using the up or
plus key will increment the fader value whereas the down or minus key
will decrement it. The same key modifiers as for the wheel event apply:
* No modifier: adjust by 1 dB
* Shift: adjust by 3 dB
* Control: adjust by 0.1 dB
Due to the very similar behavior of the mouse wheel and key press
handling some common functionality was factored out:
* Determinination of the (absolute) adjustment delta value by
insprecting the modifier keys of an event. Factored into
`determineAdjustmentDelta`.
* Adjustment of the model by a given dB delta value. Factored into
`adjustModelByDBDelta`.
* Move the fader of the selected channel
Move the fader of the selected channel instead of the fader that has
focus when the up/plus or down/minus keys are pressed. Doing so also
feels more natural because users can already change the selected
channel via the left and right keys and now they can immediately adjust
the volume of the currently selected channel while doing so.
Key events are now handled in `MixerView::keyPressEvent` instead of
`Fader::keyPressEvent` and the latter is removed. `MixerChannelView`
now has a method called `fader` which provides the associated fader.
This is needed so that the event handler of `MixerView` can act upon
the currently selected fader.
## Changes in Fader
The `Fader` class provides two new public methods.
The `adjust` method takes the modifier key(s) and the adjustment
direction and then decides internally how the modifier keys are mapped
to increment values. This is done to keep the mapping between modifier
keys and increment values consistent across different clients, e.g. the
key event of the `MixerView` and the wheel event of the `Fader` itself.
The direction is provided by the client because the means to determine
the direction can differ between clients and cases, e.g. a wheel event
determines the direction differently than a key event does.
The method `adjustByDecibelDelta` simply adjusts the fader by the given
delta amount. It currently is not really used in a public way but it
still makes sense to provide this functionality in case a parent class
or client wants to manipulate the faders by its very own logic.
Because the `Fader` class does not react itself to key press events
anymore the call to `setFocusPolicy` is removed again.
* Enter fader value when space key pressed
Let the users enter the fader value via dialog when the space key is
pressed.
Extract the dialog logic into the new method `adjustByDialog` and call
it from `MixerView::keyPressEvent`.
Make `Fader::mouseDoubleClickEvent` delegate to `adjustByDialog` and
also fix the behavior by accepting the event.
* More prominent fader ticks around 0 dB
Make the fader ticks around 0 dB more prominent but drawing them
slightly wider and with a more opaque color.
* Work around a Qt bug
Work around a Qt bug in conjunction with the scroll wheel and the Alt
key. Simply return 0 for the fader delta as soon as Alt is pressed.
* Fix wheel events without any modifier
Fix the handling of wheel events without any modifier key being pressed.
Commit ff435d551b accidentally tested against Alt using a logical OR
instead of an AND.
* Code review changes
First set of code review changes:
* Use Doxygen style documentation comments
* Remove comment about `displaydbfs` from upgrade routine
* White-space changes for touched lines.
* Make minimum dB value a constexpr
Make the minimum dB value a constexpr in the implementation file because
currently it's an implementation detail that should not be of any
interest to any other client.
So `m_faderMinDb` becomes `c_faderMinDb`.
* More flexible painting of fader ticks
Paint the fader ticks in a more systematic and flexible way. This also
removes some "magic numbers", e.g. by using `c_faderMinDb` instead of
`-120.f` as the lower limit.
The upper limit, i.e. the "starting point" is now also computed using
the maximum value of the model so that the fader will still paint
correctly if it ever changes.
* Make the zero indicator bolder
Make the zero indicator tick of the fader bolder.
* Make rendering of fader ticks a preference
Make rendering of fader ticks a preference which is off by default.
Introduce the new option "Show fader ticks" to the setup dialog and save
it to the UI attribute `showfaderticks`.
The configuration value is currently evaluated in `Fader::paintEvent`.
If this leads to performance problems it might be better to introduce a
boolean member to the `Fader` class which caches that value.
* Move constexprs to anonymous namespace
* unmute related FX channels
When soled one FX channel, unmute send and receive channels, to allow complex FX channel routing (BUS, SENDs, etc.)
* Comment change
* SEND channels
Activate also SEND channels recursively
* Remove unnecessary whitespace
* Encapsulate mixer channel index
Make the mixer channel index `m_channelIndex` private and add getters and
setters. Also add a method to determine if the channel is the master
channel.
Move `m_channelIndex` to the end of the initialization list of the
`MixerChannel` constructor because it is now the last member in the
header.
Adjust all clients to make use of the new methods.
* Replace const int& getIndex() with int index() const
* Format changes
---------
Co-authored-by: Michael Gregorius <michael.gregorius.git@arcor.de>
Co-authored-by: Sotonye Atemie <sakertooth@gmail.com>
* use c++20 concepts and numbers for lmms_constants.h
* replace lmms::numbers::sqrt2 with std::numbers::sqrt2
* replace lmms::numbers::e with std::numbers::e
Also replace the only use of lmms::numbers::inv_e with a local constexpr instead
* remove lmms::numbers::pi_half and lmms::numbers::pi_sqr
They were only used in one or two places each
* replace lmms::numbers::pi with std::numbers::pi
* add #include <numbers> to every file touched so far
This is probably not needed for some of these files. I'll remove those later
* Remove lmms::numbers
Rest in peace lmms::numbers::tau, my beloved
* Add missing #include <numbers>
* replace stray use of F_EPSILON with approximatelyEqual()
* make many constants inline constexpr
A lot of the remaining constants in lmms_constants.h are specific to
SaProcessor. If they are only used there, shouldn't they be in SaProcessor.h?
* ok then, it's allowed to be signed
* remove #include "lmms_constants.h" for files that don't need it
- And also move F_EPSILON into lmms_math.h
- And also add an overload for fast_rand() to specify a higher and lower bound
- And a bunch of other nonsense
* ok then, it's allowed to be inferred
* ok then, it can accept an integral
* fix typo
* appease msvc
* appease msvc again
* Replace linearInterpolate with std::lerp()
As well as time travel to undo several foolish decisions and squash tiny
commits together
* Fix msvc constexpr warnings
* Fix msvc float to double truncation warning
* Apply two suggestions from code review
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
* Apply suggestions from code review
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
* fix silly mistake
* Remove SlicerT's dependence on lmms_math.h
* Allow more type inference on fastRand() and fastPow10f()
* Apply suggestions from code review
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
* Clean up fastRand() a little bit more
---------
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
* Try to fix MSVC linker error related to lilv
* Remove temporary workaround
* Temporary debugging messages
* oops
* Temporary debugging
* Try to find FluidSynth using Config mode first
* Try again to fix lilv
* Fix FluidSynth installed with vcpkg on Windows
* Fix lilv from vcpkg
* Remove debug flag
* Fix for when lilv is not found (*-NOTFOUND evaluates to false)
* Use lowercase package name for lv2
* Try using only pkg_check_modules for lv2
* Use Lilv::lilv
* Add pkg-config guard back in
* Fix package name
Co-authored-by: Tres Finocchiaro <tres.finocchiaro@gmail.com>
* Fix Lilv_INCLUDE_DIRS
* Rename vcpkg cache key
---------
Co-authored-by: Tres Finocchiaro <tres.finocchiaro@gmail.com>
macOS: Replace Command + Drag shortcut key with Option + Drag
Add new header `KeyboardShortcuts.h` for platform-specific keyboard mappings
---------
Co-authored-by: Michael Gregorius <michael.gregorius.git@arcor.de>
* use c++ std::* math functions
This updates usages of sin, cos, tan, pow, exp, log, log10, sqrt, fmod, fabs, and fabsf,
excluding any usages that look like they might be part of a submodule or 3rd-party code.
There's probably some std math functions not listed here that haven't been updated yet.
* fix std::sqrt typo
lmao one always sneaks by
* Apply code review suggestions
- std::pow(2, x) -> std::exp2(x)
- std::pow(10, x) -> lmms::fastPow10f(x)
- std::pow(x, 2) -> x * x, std::pow(x, 3) -> x * x * x, etc.
- Resolve TODOs, fix typos, and so forth
Co-authored-by: Rossmaxx <74815851+Rossmaxx@users.noreply.github.com>
* Fix double -> float truncation, DrumSynth fix
I mistakenly introduced a bug in my recent PR regarding template
constants, in which a -1 that was supposed to appear outside of an abs()
instead was moved inside it, screwing up the generated waveform. I fixed
that and also simplified the function by factoring out the phase domain
wrapping using the new `ediv()` function from this PR. It should behave
how it's supposed to now... assuming all my parentheses are in the right
place lol
* Annotate magic numbers with TODOs for C++20
* On second thought, why wait?
What else is lmms::numbers for?
* begone inline
Co-authored-by: Rossmaxx <74815851+Rossmaxx@users.noreply.github.com>
* begone other inline
Co-authored-by: Rossmaxx <74815851+Rossmaxx@users.noreply.github.com>
* Re-inline function in lmms_math.h
For functions, constexpr implies inline so this just re-adds inline to
the one that isn't constexpr yet
* Formatting fixes, readability improvements
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
* Fix previously missed pow() calls, cleanup
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
* Just delete ediv() entirely lmao
No ediv(), no std::fmod(), no std::remainder(), just std::floor().
It should all work for negative phase inputs as well. If I end up
needing ediv() in the future, I can add it then.
* Simplify DrumSynth triangle waveform
This reuses more work and is also a lot more easy to visualize.
It's probably a meaningless micro-optimization, but it might be worth changing it back to a switch-case and just calculating ph_tau and saw01 at the beginning of the function in all code paths, even if it goes unused for the first two cases. Guess I'll see if anybody has strong opinions about it.
* Move multiplication inside abs()
* Clean up a few more pow(x, 2) -> x * x
* Remove numbers::inv_pi, numbers::inv_tau
* delete spooky leading 0
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
---------
Co-authored-by: Rossmaxx <74815851+Rossmaxx@users.noreply.github.com>
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
This PR attempts a number of improvements to the sample rendering (in the song editor, automation editor, AudioFileProcessor, SlicerT, etc) in LMMS:
Thumbnails: Samples are aggregated into a set of thumbnails of multiple resolutions. The smallest larger thumbnail is then chosen for rendering during sample drawing. Each set of thumbnails is stored with its sample file metadata in an unordered_map, so that duplicate samples will use the same set of thumbnails.
Partial rendering: additionally, this PR only renders the portions of the sample clips visible to the viewer to save rendering time.
* Experimental sample thumbnail
* Rename some classes and type aliases. Make some type declarations explicit
* Use a combination of audioFile name and shared_ptrs to track samples; refactor some loops
* That weird line at the end of the sample is now gone
* Small changes to the code; Add comments
* Add missing word to comment; Fix typo
* Track `SharedSampleThumbnailList`s instead
* Major refactor; implement thumbnailing for SlicerT, AFP and Automation editor
* Code clean up, renames and documenting
* Add the namespace lmms comments
* More code updates and documentation
* Fix error in comment
* Comment out `qDebug`s
* Fix formatting
* Use alternative initialization of `SampleThumbnailVisualizeParameters`
* Remove commented code
* Fix style and simplify code
* Use auto
* Draw lines using floating point
* Merge the classes into one nested class
+ Replace while loop with std::find_if
* Fix comparison of different signedness
* Include memory header
* Fix a logic error when selecting samples; Rename a const
* Fix more issues with signedness
* Fix sample drawing error in `visualizeOriginal`
* Only render regions in view of the sample
* Allow partial repaints of sample clips
* Remove unused variable
* Limit most of the painting to the visible region
* Revert back to using rect() in some places
* Partial rendering for AutomationEditor
* Don't redraw painted regions; allowHighResolution; remove `visualizeOriginal`; Remove s_sampleThumbnailCacheMap
* Add s_sampleThumbnailCacheMap back for testing convenience
* Minor change to the way `thumbnailSizeDivisor` is calculated
* Extend update region by an amount
* forgot about this
* Adapt to master; Redesign VisualizeParameters; Don't rely entirely on needsUpdate()
* Don't try to preserve painted regions
* Allow for a bit more thumbnails; Fix incorrect rendering when vertically scrolling
* Fix missing include statement
* Remove the unused variable
* Code optimization; Remove RMS member from Bit; Rename viewRect to drawRect
* More code optimizations
* Fix formatting
* Use begin instead of cbegin
* Improve generation of thumbnails
* Improve expressiveness of the draw code
* Add support for reversing
* Fix drawing code
* Fix draw code (part 2)
* Apply more fixes and simplifications
* Undo some out of scope changes
* Remove SampleWaveform
* Improve documentation
* Use size_t for some counters
* Change width parameter to be size_t
* Remove temporary aggregated peak variable
* Bump up AggregationPerZoomStep to 10
* Zoom out only requested range of thumbnail instead of clipping it separately
* Rename targetSampleWidth to targetThumbnailWidth
* Handle reversing for AFP; Iterate in reverse instead of reversing the entire thumbnail
* Change names to be more accurate
* Improve implementation of sample thumbnail cache map
* Move AggregationPerZoomStep back down to 2, do not cap smallest thumbnail width to display width
To improve performance with especially long
samples (~20 minutes)
* Simplify sample thumbnail cache handling in constructor
* Call drawLines instead of drawLine in a loop
QPainter::drawLine calls drawLines with a line count of 1. Therefore, calling drawLine in a loop means we are simply calling drawLines a lot more times than necessary.
* Bump up AggregationPerZoomStep to 10 again
Thought using 2 would help performance (when rendering). Maybe it does, but it's still quite slow when rendering a bunch of thumbnails at once.
* Fix off-by-one error when constructing Thumbnail from buffer
* Fix crash when viewport is not in bounds
* Apply performance improvements
Performance in the zoomOut function was bad because of the dynamic memory allocation. Huge chunks of memory were being allocated quite often, casuing a ton of cache misses and all around slower performance. To fix this, all the necessary downsampling is now done within the for loop and handled one pixel after another, instead of all at once.
To further avoid allocations in the draw call, the change to use drawLines has been reverted.
We now pass VisualizeParameters by value (it is only 64 bytes, which will fit quite nicely in a cache line, which is more benefical than reaching for that data by reference to some other part of the code).
After applying these changes, we are now practically only bounded by the painting done by Qt (according to profiling done by Valgrind). Proper use of OpenGL could resolve this issue, which should finally make the performance quite optimal in variety of situations.
* Apply minor changes
Update copyright and unused functions. Move in newly created thumbnail into the cache instead of copying it.
* Use C++20's designated initializers
* Create param right before visualizing
* Fix regressions with reversing
* Fix incorrect rendering in AFP and SlicerT
* Move MaxSampleThumbnailCacheSize and AggregationPerZoomStep into implementation file
* Remove static keyword
* Remove getter and setter for peak data
---------
Co-authored-by: Sotonye Atemie <sakertooth@gmail.com>
* add templates for common geometric constants
* oops missed one
* LD_2PI -> LD_PI
i re-added the wrong constant ffs
* CamelCase names and also verify compilation without -DLMMS_MINIMAL
* C++20 stuff
Updated to account for `<numbers>` and C++20:
- Marked all `lmms_constants.h` constants with an exact equivalent in `<numbers>` as deprecated
- Removed all `lmms_constants.h` constants where no variant is currently in use
- Using `inline constexpr`
- Using `std::floating_point` concept instead of `typename`
* add lmms::numbers namespace
* Remove panning_constants.h
Moves the four constants in panning_constants.h into panning.h, then
removes panning.h.
* Use std::exp(n) instead of powf(numbers::e, n)
* Use C++ std math functions
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
* Use overloaded std math functions
An attempt to fix compiler warnings on some platforms
* Remove uses of __USE_XOPEN
And also update two functions I missed from the previous commit
* Missed a few
* Fix ANOTHER std math function use
Of course there's another one
---------
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
* Fix rendering for Vectorscope
The rendering of the Vectorscope is broken on Wayland if the size of the
Vectorscope is increased. This is caused by using a `QImage` to render
the scope traces which is then scaled up.
Introduce a new way to paint the vector scope (goniometer) which simply
paints lines or points that progressively get dimmer and which does not
make use of a QImage anymore.
It supports the following features:
* Log mode
* Zooming
* Rendering the drawing performance
* Selecting a different color for the traces
It does not support:
* HQ Mode: The new implementation provides a performance that's
equivalent to Non-HQ mode and look similar or better than the HQ mode.
* Blurring of old data
* Persistence: Might be implemented by using a factor for the dimming
Rendering of the samples/trances uses the composition mode "Plus" so
that overlapping elements will appear like adding brightness. Painting
the grid and lines is done using the normal composition mode "Source
Over" so that it simply replaces existing pixels.
Painting of the lines/points and the grids and lines is done in a
"signal space", i.e. a transform where elements in the interval of
[-1, 1] feel "natural". The text is painted in "widget space".
* Remove old implementation
Remove HQ mode and persistence. Also remove the legacy option again.
This removes the models, loading, saving and the GUI controls.
Remove all unnecessary members from `VectorView`, adjust the
constructor. Move the implementation of `paintLinesMode` into
`paintEvent`. Remove methods `paintLegacyMode` and `paintLinesMode`.
* Move colors into VectorView
Move the colors out of `VecControls` into `VectorView` as they are
related to presentation.
* Remove friend relationship to VectorView
Remove a friend relationship to `VectorView` from `VecControls` by
introducing const getters for the models.
* Remove VectorView::m_visible
Remove the unnecessary member `m_visible` from `VectorView`. It was not
initialized and only written to but never read.
* Make Vectorscope themeable
Make the Vectorscope themeable by introducing Qt properties for the
relevant colors.
The default theme gets the values from the code whereas the classic
theme gets a trace with amber color.
* Rename m_colorFG
Rename `m_colorFG` to `m_colorTrace`. Adjust the Qt property
accordingly.
Remove local variable `traceColor` from paint method and use member
`m_colorTrace` directly.
* Remove m_colorOutline
Remove unused member `m_colorOutline`.
* Fix horizontal lines on silence
Fix the horizontal lines that are rendered on silence. They seem to be
produced when rendering lines that start and end at the same point.
Therefore we only draw a point if the current and last point are the
same.
* Add some margin to the VectorView
Add some margin to the rendering of the `VectorView` so that the circle
does not touch the bounary of the widget.
* Clean up the layout of the Vectorscope
Clean up the layout of the Vectorscope. The checkboxes are not put on
top of the vector view anymore but are organized in a horizontal layout
beneath it. This gives a much tidier look.
* Maximize button for resizable instruments
Show the maximize button for resizable instruments.
Most other changes have the character of refactorings and code
reorganizations.
Remove the negation in the if condition for resizable instruments to
make the code better readable.
Only manipulate the system menu if the instrument is not resizable.
Add a TODO to the special code that sets a size.
* Fix rendering of maximized sub windows
In `SubWindow::paintEvent` don't paint anything if the sub window is
maximized . Otherwise some gradients are visible behind the maximized
child content.
In `SubWindow::adjustTitleBar` hide the title label and the buttons if the
sub window is maximized. Always show the title and close button if not
maximized. This is needed to reset the state correctly after
maximization.
* Add SubWindow::addTitleButton
Add the helper method `SubWindow::addTitleButton` to reduce code
repetition in the constructor.
* Only disable the minimize button
Disable the minimize button by taking the current flags and removing
the minimize button hint from them instead of giving a list which might
become incomplete in the future. So only do what we want to do.
* Remove dependency on MdiArea
Remove a dependency on the `MdiArea` when checking if the sub window is
the active one. Query its own window state to find out if it is active.
* Clear Qt::MSWindowsFixedSizeDialogHint
Clear the `Qt::MSWindowsFixedSizeDialogHint` flag for resizable
instruments (symmetric to the `else` case).
* Update the sub window title bar of exchanged instruments
Update the title bar of an instrument's sub window if the model changes, e.g. if an instrument is exchanged via drag & drop.
The main fix is to call the new method `updateSubWindowState` in `InstrumentTrackWindow::modelChanged`. It contains mostly the code that was previously executed in the constructor of `InstrumentTrackWindow`. The constructor now simply calls this method after it has put the constructed instance into a sub window.
With the current implementation the sub window needs to be explicitly triggered to update its title bar once the flags have been adjusted in `updateSubWindowState`. This is done with the new public method `SubWindow::updateTitleBar`. Please note that such an explicit update is not needed if the instrument windows are managed by a `QMdiSubWindow` instead of a `SubWindow`. This means that the implementation of `SubWindow` is still missing something that `QMdiSubWindow` does. However, debugging also showed that setting the window flags of the sub window does not seem to lead to an event that could be caught in `SubWindow::changeEvent`. This was found out by simply dumping the event types of all events that arrive in that method and exchanging an instrument.
The method `updateSubWindowState` uses the added method `findSubWindowInParents` to find the sub window it is contained in. The latter method should be considered to be moved into a templated helper class because it might be useful in other contexts as well.
## Technical details
If you want to experiment with using QMdiSubWindows then simply add the following method to `MainWindow` (right next to `addWindowedWidget`):
```
QMdiSubWindow* MainWindow::addQMdiSubWindow(QWidget *w, Qt::WindowFlags windowFlags)
{
// wrap the widget in our own *custom* window that patches some errors in QMdiSubWindow
auto win = new QMdiSubWindow(m_workspace->viewport(), windowFlags);
win->setAttribute(Qt::WA_DeleteOnClose);
win->setWidget(w);
m_workspace->addSubWindow(win);
return win;
}
```
Then call that method instead of `addWindowedWidget` in the constructor of `InstrumentTrackWindow`:
```
QMdiSubWindow* subWin = getGUI()->mainWindow()->addQMdiSubWindow( this );
```
You can then comment out the cast and the call of `updateTitleBar` in `updateSubWindowState` and everything will still work.
* Update the system menu
Show or hide the "Size" and "Maximize" entries in the system menu
depending on whether the instrument view is resizable or not.
* Show non-resizable instruments as normal
Show the sub windows of non-resizable instruments as normal if the sub
window is maximized because it was previously used with a resizable
instrument.
* Fix typo
* Rename updateSubWindowState
Rename `updateSubWindowState` to `updateSubWindow`.