-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Add LcdFloatSpinBox
(extracted from microtonal PR)
#5865
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
🤖 Hey, I'm @LmmsBot from github.com/lmms/bot and I made downloads for this pull request, click me to make them magically appear! 🎩
Windows
Linux
macOS🤖{"platform_name_to_artifacts": {"Windows": [{"artifact": {"title": {"title": "32-bit", "platform_name": "Windows"}, "link": {"link": "https://12785-15778896-gh.circle-artifacts.com/0/lmms-1.3.0-alpha.1.80%2Bg15944565b-mingw-win32.exe"}}, "build_link": "https://circleci.com/gh/LMMS/lmms/12785?utm_campaign=vcs-integration-link&utm_medium=referral&utm_source=github-build-link"}, {"artifact": {"title": {"title": "64-bit", "platform_name": "Windows"}, "link": {"link": "https://12783-15778896-gh.circle-artifacts.com/0/lmms-1.3.0-alpha.1.80%2Bg15944565b-mingw-win64.exe"}}, "build_link": "https://circleci.com/gh/LMMS/lmms/12783?utm_campaign=vcs-integration-link&utm_medium=referral&utm_source=github-build-link"}, {"artifact": {"title": {"title": "32-bit", "platform_name": "Windows"}, "link": {"link": "https://ci.appveyor.com/api/buildjobs/w60psoj21ggacmav/artifacts/build/lmms-1.3.0-alpha-msvc2017-win32.exe"}}, "build_link": "https://ci.appveyor.com/project/Lukas-W/lmms/builds/38069679"}, {"artifact": {"title": {"title": "64-bit", "platform_name": "Windows"}, "link": {"link": "https://ci.appveyor.com/api/buildjobs/vg6bg2t46csu4k50/artifacts/build/lmms-1.3.0-alpha-msvc2017-win64.exe"}}, "build_link": "https://ci.appveyor.com/project/Lukas-W/lmms/builds/38069679"}], "Linux": [{"artifact": {"title": {"title": "(AppImage)", "platform_name": "Linux"}, "link": {"link": "https://12782-15778896-gh.circle-artifacts.com/0/lmms-1.3.0-alpha.1.80%2Bg1594456-linux-x86_64.AppImage"}}, "build_link": "https://circleci.com/gh/LMMS/lmms/12782?utm_campaign=vcs-integration-link&utm_medium=referral&utm_source=github-build-link"}], "macOS": [{"artifact": {"title": {"title": "", "platform_name": "macOS"}, "link": {"link": "https://12784-15778896-gh.circle-artifacts.com/0/lmms-1.3.0-alpha.1.80%2Bg15944565b-mac10.14.dmg"}}, "build_link": "https://circleci.com/gh/LMMS/lmms/12784?utm_campaign=vcs-integration-link&utm_medium=referral&utm_source=github-build-link"}]}, "commit_sha": "932b01d043eaa27a98621e3ef776765f70ad9591"} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Except for some code style to be fixed (mostly code block spacing, parenthesis spacing and a if
without explicit blocks) and one line that could reuse a variable it looks good to me. I've to look at the paint events with more care, since I don't yet understand them completely. No obvious problems were noticed on a first review of them though.
I left the changes as suggestions so they can be batch applied if you want!
Co-authored-by: IanCaio <iancaio_dev@hotmail.com>
Thanks for the cleaning pass. A lot of the code was copied from the original As for the remaining suggestions, I posted a question on Discord and I will apply or ignore them depending on what happens with the weird one-liner spacing rule. EDIT: Conventions clarified, suggestions applied. |
(adding oneliner spaces) Co-authored-by: IanCaio <iancaio_dev@hotmail.com>
Co-authored-by: Hyunjin Song <tteu.ingog@gmail.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From what I can tell, LcdFloatSpinBox
is mostly copied from LcdSpinBox
, so a lot of these comments apply to that class too. Those comment could be considered out of scope, since the issues referred to aren't introduced by this PR, and could be fixed at the same time as the original class.
void setLabel(const QString &label) { m_label = label; } | ||
|
||
public slots: | ||
virtual void update(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this have a name other than update
? The base class function isn't virtual, so this function shadows it, not overrides it. I don't know how this interacts with the signal-slot mechanism, but it may not behave as the implementation/callers intended. Also, it needn't be marked virtual, as it doesn't look like it's intended to be overridden.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did not even think of any of this, I just copied it from LcdSpinBox
and assumed it will work the same. I would guess it still needs to be called update()
since that is what Qt calls when it plans to redraw a widget?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since QWidget::update()
is non-virtual, the name of this function doesn't matter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know it doesn't matter, but I think the name is misleading, shadowing QWidget::update
with something different. Also, slot lookups are done using strings, not vtables, so it's still not clear how this interacts with the signal-slot mechanism. I'll investigate it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To clarify, I was answering to @he29-net's question.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just tried to rename it and the display GUI stopped updating. So Qt (or LMMS, not sure who calls the global update()
on all widgets) definitely expects the slot to be named update()
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tested this, see the code at https://gist.github.com/DomClark/fc976514c6e1b083d9bce0ab777eefad. It appears slots have virtual behaviour when connected using SIGNAL
/SLOT
macros, and non-virtual behaviour when using member function pointer connections. This inconsistency, along with the fact that it doesn't work with the modern connection style, suggests to me that it's not a good idea to override slots by name. I'm fine with leaving it as is for now, since the existing LcdSpinBox
code does the same thing, but I think we should clean this up in the future.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That inconsistency certainly looks like an invitation for some confusing bugs, interesting..
I wonder what is the intended workflow then? I would expect that a derived widget implements its own update()
, so that it can react to any changes specific to the modified version. And as a part of its update()
it would call update()
of the base class to finish the rest. So the non-virtual behavior should be almost always unwanted, right?
But if update()
s are called by Qt on some occasions, wouldn't choosing a different "update" slot name on a derived class mean that it simply won't be called when needed? Or do we only call / signal update()
s explicitly from our code?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
update()
isn't supposed actually update anything itself. Its purpose is to schedule a repaint of the widget in the near future, once control returns to the event loop. If virtual behaviour were intended, it would be a virtual function.
It looks like the code there is to set the LCD display to the current value of the model, in which case it should run in response to changes in the model. The appropriate places for this are in LcdFloatSpinBox::modelChanged
(called when a new model is viewed by the spin box) and in response to the Model::dataChanged
signal (emitted when the model's value changes).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In addition to @DomClark's comment, ModelView::doConnections
connects Model::dataChanged
and Model::propertiesChanged
to SLOT(update())
of ModelView::m_widget
. This means at least one of them should be satisfied:
paintEvent()
of the model reads the value of the model,- The view monitors changes in its model
- The view implements its own
update()
LcdFloatSpinBox
(and LcdSpinBox
, too) is using the third approach. If this approach is not recommended, we should move to other approaches.
However, this looks out of scope of this PR.
Co-authored-by: Dominic Clark <mrdomclark@gmail.com>
…nd hiding from Lcd*SpinBoxes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Most of the code looks good, but there are some things that I think are worth changing, besides the update
method name that @DomClark was concerned about.
I also left two comments about things I had doubt about (use of explicit
and right margin drawing).
void setLabel(const QString &label) { m_label = label; } | ||
|
||
public slots: | ||
virtual void update(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could call it updateDisplay
as it's basically what the method is doing.
if (!m_seamlessLeft && !m_seamlessRight) | ||
{ | ||
QStyleOptionFrame opt; | ||
opt.initFrom(this); | ||
opt.state = QStyle::State_Sunken; | ||
opt.rect = QRect(0, 0, m_cellWidth * m_numDigits + (margin + m_marginWidth) * 2 - 1, | ||
m_cellHeight + (margin * 2)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we should add a TODO
comment for futurely moving the border drawing to the LcdSpinBox
class later. It's inconsistent that on regular spin boxes the border is drawn on the LcdWidget
class and on the float spin boxes it's drawn on the LcdFloatSpinBox
paint event.
If it's possible to move this to the LcdSpinBox
class with no major issues in this PR, I'd even think better to just deal with it now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if I read it correctly, but wouldn't that mean that all "vanilla" LcdWidget
s would have no borders?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, I just meant that on the regular LCD Widget, the borders are being drawn on the LcdWidget
class (LcdWidget::paintEvent
, where this comment was made) but on the Float LCD Widget they are being drawn on the LcdFloatSpinBox
class (LcdFloatSpinBox::paintEvent
). As far as I understood, LcdWidget is the LCD number while the LcdSpinBox is the widget itself, that contains the LCD number. LcdFloatSpinBox for example has 2 LcdWidgets.
I was just pointing out it feels inconsistent to draw borders on the LcdWidgets on the regular spin box and on the LcdFloatSpinBox for the float spin box. We probably should do the border drawing on the spin box classes (both LcdSpinBox
and LcdFloatSpinBox
).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We probably should do the border drawing on the spin box classes (both LcdSpinBox and LcdFloatSpinBox).
But that would mean LcdWidget
is left with no border-drawing code, hence my worry that LcdWidgets
will not have borders if we do that. They are currently used in the FX mixer (where a nuber is needed, but you cannot change it), so there would be no borders around the green numbers on the FX mixer. Either that, or I'm getting really confused. :D
LcdFloatSpinBox
does border drawing simply because it needs to visually join two widgets that were not originally designed to be joined. That's also why there are the new "seamless" parameters in LcdWidget
. It all feels a bit like a hack, all the three LCD widgets could be probably rewritten in some way to make it cleaner, but I felt that is already way out of scope of the original Microtuner (I generally try to avoid touching existing code when not necessary, not to mention big rewrites like this).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I didn't realize that LcdWidget
was used by other widgets besides the Spin Box. Well, in that case it's probably a big rewrite to move the border to the outer widgets: Even though it makes sense it's out of the scope of this PR. I'm not sure it's worth it adding a TODO
comment for the future, but you can ignore this comment then!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could a comment be added at the beginning about the border drawing, just for future reference? Something like:
// When either the right or left is seamless we are in a LcdFloatSpinBox
// and the border drawing will be done by the float spin box class instead
// TODO: Possibly move the frame drawing to the outer widget classes
// (i.e.: Spin boxes) for consistency
I know this sounds unimportant, but if in the future someone decides to change the frame drawing and isn't aware of that, the frames of regular spin boxes and float spin boxes won't match. The TODO
also serves as a reference for possibly coming up with an alternative in the future.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added a comment explaining why is the border drawing skipped. I left out the "TODO", because I still do not understand where do you propose to "move" the code. If it is moved, it is no longer there, which breaks LcdWidget
borders in the mixer. So we can only copy it to LcdSpinBox
, which does not make sense, it only adds more duplicate code that needs to be maintained.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know, maybe someone else can step in to give an opinion too, I could be wrong after all. For me it feels like bad design that a widget contains another one (SpinBox contains LcdWidgets) but in some cases the inner widget (LcdWidget) draws the frame and in other cases the outer widget (Float Spinbox) draws the frame. In a ideal scenario either the inner OR the outer widget should be responsible by the frame. That's all I was suggesting, that in the future we move the drawing of the frame to the outer widgets (LcdFloatSpinBox, LcdSpinBox, FxLineLcdSpinBox, etc) or that we come up with a design where we don't have it being drawn in different places.
I understand this is out of the scope of this PR (and obviously not its fault by any means), I just thought about adding a TODO
comment so we could remember about maybe fixing it in the future. Just to let you know, this is by no means holding my approval (as I mentioned in Discord, I'm mostly waiting on @DomClark regarding the update
method name, the aside the PR LGTM).
Co-authored-by: IanCaio <iancaio_dev@hotmail.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm happy with this if @IanCaio is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM too!
* Add changes extracted from microtonal PR * Apply suggestions from code review Co-authored-by: IanCaio <iancaio_dev@hotmail.com> * Apply suggestions from code review (adding oneliner spaces) Co-authored-by: IanCaio <iancaio_dev@hotmail.com> * Update src/gui/widgets/LcdFloatSpinBox.cpp Co-authored-by: Hyunjin Song <tteu.ingog@gmail.com> * Apply suggestions from code review Co-authored-by: Dominic Clark <mrdomclark@gmail.com> * Implement suggestions from review * Reorder constructor parameters, remove old code for cursor movement and hiding from Lcd*SpinBoxes * Apply suggestions from code review Co-authored-by: IanCaio <iancaio_dev@hotmail.com> * Fix right margin width in seamless mode * Add explanation to border drawing code Co-authored-by: IanCaio <iancaio_dev@hotmail.com> Co-authored-by: Hyunjin Song <tteu.ingog@gmail.com> Co-authored-by: Dominic Clark <mrdomclark@gmail.com>
* Add changes extracted from microtonal PR * Apply suggestions from code review Co-authored-by: IanCaio <iancaio_dev@hotmail.com> * Apply suggestions from code review (adding oneliner spaces) Co-authored-by: IanCaio <iancaio_dev@hotmail.com> * Update src/gui/widgets/LcdFloatSpinBox.cpp Co-authored-by: Hyunjin Song <tteu.ingog@gmail.com> * Apply suggestions from code review Co-authored-by: Dominic Clark <mrdomclark@gmail.com> * Implement suggestions from review * Reorder constructor parameters, remove old code for cursor movement and hiding from Lcd*SpinBoxes * Apply suggestions from code review Co-authored-by: IanCaio <iancaio_dev@hotmail.com> * Fix right margin width in seamless mode * Add explanation to border drawing code Co-authored-by: IanCaio <iancaio_dev@hotmail.com> Co-authored-by: Hyunjin Song <tteu.ingog@gmail.com> Co-authored-by: Dominic Clark <mrdomclark@gmail.com>
* Add changes extracted from microtonal PR * Apply suggestions from code review Co-authored-by: IanCaio <iancaio_dev@hotmail.com> * Apply suggestions from code review (adding oneliner spaces) Co-authored-by: IanCaio <iancaio_dev@hotmail.com> * Update src/gui/widgets/LcdFloatSpinBox.cpp Co-authored-by: Hyunjin Song <tteu.ingog@gmail.com> * Apply suggestions from code review Co-authored-by: Dominic Clark <mrdomclark@gmail.com> * Implement suggestions from review * Reorder constructor parameters, remove old code for cursor movement and hiding from Lcd*SpinBoxes * Apply suggestions from code review Co-authored-by: IanCaio <iancaio_dev@hotmail.com> * Fix right margin width in seamless mode * Add explanation to border drawing code Co-authored-by: IanCaio <iancaio_dev@hotmail.com> Co-authored-by: Hyunjin Song <tteu.ingog@gmail.com> Co-authored-by: Dominic Clark <mrdomclark@gmail.com>
This PR contains code for a new
LcdFloatSpinBox
widget, originally included in #5522.As the name says, it is an LCD Spin Box that can be used for decimal numbers. It is a wrapper class, which instantiates two
LcdSpinBox
es, positions them next to each other and adds a decimal point in between. The whole and fractional part can be individually adjusted by a mouse, allowing easy coarse and fine adjustments.The goal was to have only a "thin" wrapper and instantiate
LcdSpinBox
es to avoid redundancy and large changes to existing code, but in the end some parts had to be re-used in some form from theLcdSpinBox
class. So there is a good chance it could be designed better, with even less redundancy, but it would likely require a substantial rewrite of theLcdSpinBox
class.