Skip to content

Improve fade/animation behavior #1291

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

Open
wants to merge 35 commits into
base: master
Choose a base branch
from

Conversation

scrubbbbs
Copy link
Collaborator

@scrubbbbs scrubbbbs commented Mar 23, 2025

In this PR I am aiming to improve the fade/animation part of nomacs UI with a couple of objectives.

  • refactor DkFadeWidget and friends which share a lot of common code
  • Add option to disable all animations #922
  • be able to disable animations in some situations like when when switching modes or window is first created.

TODO: Decide if we should be fading things we did not before. The following are now fading because behavior was masked before. I think I am ok with all of this but the animation could be a bit quicker

  • settings/batch pages on show/hide (removed fade)
  • settings/batch tabs on show/hide (removed fade)
  • thumbs panel (Shift+T) (removed fade)
  • recent files (removed fade)
  • crop widget (C) (RETAINED)

Full list of widgets now fading:
image

@scrubbbbs scrubbbbs force-pushed the ui-animation branch 6 times, most recently from 8428eb3 to 4f55700 Compare March 26, 2025 20:49
@scrubbbbs scrubbbbs mentioned this pull request Mar 26, 2025
@scrubbbbs scrubbbbs requested review from novomesk and leejuyuu March 27, 2025 15:37
@scrubbbbs scrubbbbs marked this pull request as ready for review March 27, 2025 15:42
@scrubbbbs
Copy link
Collaborator Author

This seems to be ready now. The most noticeable change is the fades I listed above, which could be taken out if you guys don't like it. I'm on the fence at the moment.

@novomesk
Copy link
Collaborator

When trying the appveyor build, I am getting Unhandled exception at 0x00007FFDB106286E (ucrtbase.dll) in nomacs.exe: Fatal program exit requested. when closing nomacs.

image

@novomesk
Copy link
Collaborator

The crash is not related to this PR, I can reproduce it with 3.21.0 version too.

Open batch processing window, select few files and close nomacs.

Thread 1 "nomacs" received signal SIGSEGV, Segmentation fault.

#0  0x00007ffff6f58b29 in QGraphicsItem::group() const () at /usr/lib64/libQt6Widgets.so.6
#1  0x00007ffff6f590ab in QGraphicsItem::isSelected() const () at /usr/lib64/libQt6Widgets.so.6
#2  0x00007ffff7d299ca in nmc::DkThumbScene::getSelectedFiles () at /var/tmp/portage/media-gfx/nomacs-3.21.0/work/nomacs-3.21.0/ImageLounge/src/DkGui/DkThumbsWidgets.cpp:1573
#3  0x00007ffff7d2a43f in nmc::DkThumbScrollWidget::enableSelectionActions () at /var/tmp/portage/media-gfx/nomacs-3.21.0/work/nomacs-3.21.0/ImageLounge/src/DkGui/DkThumbsWidgets.cpp:2035
#4  0x00007ffff7d3366c in QtPrivate::FunctorCall<QtPrivate::IndexesList<>, QtPrivate::List<>, void, void (nmc::DkThumbScrollWidget::*)()>::call(void (nmc::DkThumbScrollWidget::*)(), nmc::DkThumbScrollWidget*, void**)::{lambda()#1}::operator()() const () at /usr/include/qt6/QtCore/qobjectdefs_impl.h:152
#5  0x00007ffff7d336bf in QtPrivate::FunctorCallBase::call_internal<void, QtPrivate::FunctorCall<QtPrivate::IndexesList<>, QtPrivate::List<>, void, void (nmc::DkThumbScrollWidget::*)()>::call(void (nmc::DkThumbScrollWidget::*)(), nmc::DkThumbScrollWidget*, void**)::{lambda()#1}>(void**, QtPrivate::FunctorCall<QtPrivate::IndexesList<>, QtPrivate::List<>, void, void (nmc::DkThumbScrollWidget::*)()>::call(void (nmc::DkThumbScrollWidget::*)(), nmc::DkThumbScrollWidget*, void**)::{lambda()#1}&&) () at /usr/include/qt6/QtCore/qobjectdefs_impl.h:65
#6  QtPrivate::FunctorCall<QtPrivate::IndexesList<>, QtPrivate::List<>, void, void (nmc::DkThumbScrollWidget::*)()>::call(void (nmc::DkThumbScrollWidget::*)(), nmc::DkThumbScrollWidget*, void**) () at /usr/include/qt6/QtCore/qobjectdefs_impl.h:151
#7  QtPrivate::FunctionPointer<void (nmc::DkThumbScrollWidget::*)()>::call<QtPrivate::List<>, void>(void (nmc::DkThumbScrollWidget::*)(), nmc::DkThumbScrollWidget*, void**) () at /usr/include/qt6/QtCore/qobjectdefs_impl.h:199
#8  0x00007ffff7d33715 in QtPrivate::QCallableObject<void (nmc::DkThumbScrollWidget::*)(), QtPrivate::List<>, void>::impl(int, QtPrivate::QSlotObjectBase*, QObject*, void**, bool*) () at /usr/include/qt6/QtCore/qobjectdefs_impl.h:570
#9  0x00007ffff62eba26 in void doActivate<false>(QObject*, int, void**) () at /usr/lib64/libQt6Core.so.6
#10 0x00007ffff6ffdd68 in QGraphicsScenePrivate::removeItemHelper(QGraphicsItem*) () at /usr/lib64/libQt6Widgets.so.6
#11 0x00007ffff6ffeae5 in QGraphicsItem::~QGraphicsItem() () at /usr/lib64/libQt6Widgets.so.6
#12 0x00007ffff6ffee67 in QGraphicsObject::~QGraphicsObject() () at /usr/lib64/libQt6Widgets.so.6
#13 0x00007ffff7d2e632 in nmc::DkThumbLabel::~DkThumbLabel () at /var/tmp/portage/media-gfx/nomacs-3.21.0/work/nomacs-3.21.0/ImageLounge/src/DkGui/DkThumbsWidgets.cpp:850
#14 0x00007ffff7d2e64b in nmc::DkThumbLabel::~DkThumbLabel () at /var/tmp/portage/media-gfx/nomacs-3.21.0/work/nomacs-3.21.0/ImageLounge/src/DkGui/DkThumbsWidgets.cpp:850
#15 0x00007ffff6f81a4e in QGraphicsScene::clear() () at /usr/lib64/libQt6Widgets.so.6
#16 0x00007ffff7000eff in QGraphicsScene::~QGraphicsScene() () at /usr/lib64/libQt6Widgets.so.6
#17 0x00007ffff7c5cb6d in nmc::DkThumbScene::~DkThumbScene () at /var/tmp/portage/media-gfx/nomacs-3.21.0/work/nomacs-3.21.0/ImageLounge_build/nomacsCore_autogen/XJ2BUHI2UY/../../../ImageLounge/src/DkGui/DkThumbsWidgets.h:236
#18 0x00007ffff7c5cb7d in nmc::DkThumbScene::~DkThumbScene () at /var/tmp/portage/media-gfx/nomacs-3.21.0/work/nomacs-3.21.0/ImageLounge_build/nomacsCore_autogen/XJ2BUHI2UY/../../../ImageLounge/src/DkGui/DkThumbsWidgets.h:236
#19 0x00007ffff62a7ebd in QObjectPrivate::deleteChildren() () at /usr/lib64/libQt6Core.so.6
#20 0x00007ffff7327708 in QWidget::~QWidget() () at /usr/lib64/libQt6Widgets.so.6
#21 0x00007ffff7c543f6 in nmc::DkWidget::~DkWidget () at /var/tmp/portage/media-gfx/nomacs-3.21.0/work/nomacs-3.21.0/ImageLounge/src/DkGui/DkBaseWidgets.h:56
#22 nmc::DkFadeWidget::~DkFadeWidget () at /var/tmp/portage/media-gfx/nomacs-3.21.0/work/nomacs-3.21.0/ImageLounge/src/DkGui/DkBaseWidgets.h:64
#23 nmc::DkThumbScrollWidget::~DkThumbScrollWidget () at /var/tmp/portage/media-gfx/nomacs-3.21.0/work/nomacs-3.21.0/ImageLounge_build/nomacsCore_autogen/XJ2BUHI2UY/../../../ImageLounge/src/DkGui/DkThumbsWidgets.h:320
#24 nmc::DkThumbScrollWidget::~DkThumbScrollWidget () at /var/tmp/portage/media-gfx/nomacs-3.21.0/work/nomacs-3.21.0/ImageLounge_build/nomacsCore_autogen/XJ2BUHI2UY/../../../ImageLounge/src/DkGui/DkThumbsWidgets.h:320
#25 0x00007ffff62a7ebd in QObjectPrivate::deleteChildren() () at /usr/lib64/libQt6Core.so.6
#26 0x00007ffff7327708 in QWidget::~QWidget() () at /usr/lib64/libQt6Widgets.so.6
#27 0x00007ffff712ccbd in QStackedWidget::~QStackedWidget() () at /usr/lib64/libQt6Widgets.so.6
#28 0x00007ffff62a7ebd in QObjectPrivate::deleteChildren() () at /usr/lib64/libQt6Core.so.6
#29 0x00007ffff7327708 in QWidget::~QWidget() () at /usr/lib64/libQt6Widgets.so.6
#30 0x00007ffff705321d in QTabWidget::~QTabWidget() () at /usr/lib64/libQt6Widgets.so.6
#31 0x00007ffff62a7ebd in QObjectPrivate::deleteChildren() () at /usr/lib64/libQt6Core.so.6
#32 0x00007ffff7327708 in QWidget::~QWidget() () at /usr/lib64/libQt6Widgets.so.6
#33 0x00007ffff7c5cb02 in nmc::DkWidget::~DkWidget () at /var/tmp/portage/media-gfx/nomacs-3.21.0/work/nomacs-3.21.0/ImageLounge/src/DkGui/DkBaseWidgets.h:56
#34 nmc::DkBatchContent::~DkBatchContent () at /var/tmp/portage/media-gfx/nomacs-3.21.0/work/nomacs-3.21.0/ImageLounge_build/nomacsCore_autogen/XJ2BUHI2UY/../../../ImageLounge/src/DkGui/DkBatch.h:104

@leejuyuu
Copy link
Collaborator

leejuyuu commented Apr 4, 2025

The edit panel loses color for bec4d79.

image

@leejuyuu
Copy link
Collaborator

leejuyuu commented Apr 4, 2025

The Settings tab seems to have fade enabled. I think the previous behavior (no fade) looks better.

2025-04-04.17-18-46.mp4

@leejuyuu
Copy link
Collaborator

leejuyuu commented Apr 4, 2025

Batch process has the same issue.

2025-04-04.17-28-41.mp4

@leejuyuu
Copy link
Collaborator

leejuyuu commented Apr 4, 2025

I am using system theme.

fade/visiblity logic was previously copied between three classes,
DkFadeWidget, DkFadeLabel, and DkFolderScrollBar. This was required
because these cannot have a common base due to being different QWidget
subclasses.

There is now DkFadeMixin which provides the common code. There is now a
small set of functions which must be copied so that QWidget::setVisible
is correctly overridden.

Previously, QWidget::setVisible was masked, but not overridden which
allows fade logic to be bypassed depending on the static type of the
variable. This has revealed several widgets that are now fading that
were not before. This will be addressed in a separate commit.
Makes the ordering the same as QLabel which makes more sense and reduces
constructor overloading in DkFadeMixin
- mAutoHide member was set but never used
- setVisible() override is effectively doing nothing
DkControlWidget::imageLoaded was called every time an image was loaded,
but it only changes behavior on the first image loaded or null image.
This adds a bunch of redundant calls to hide/show widgets when there are
no visibility changes needed.

Therefore it is changed to DkControlWidget::imagePresenceChanged which
is only called if the viewport changes between null/loaded states.
If the direction of the animation changes it can use the same timer, and
this should appear smoother.

Also fixes a weird problem with moving the thumbnail ribbon where it
would disappear.
This should be more correct; it is possible to call fade() with
different values of saveSetting, we do not want to ignore the value
if the fade is a no-op or in progress.
scrubbbbs added 20 commits April 7, 2025 18:39
It is dead code as it was always hidden from view. DkFileInfoLabel has
taken over this function and can in the future provide an option to
toggle what info is displayed (current file name, date, and star rating)
block() is now dead due to removal of DkRatingLabelBg which was also
dead
child of DkFileInfoLabel which is faded already, so this does nothing
definition of virtual hide() makes a conflict with DkFadeMixin because
it also declares hide() with one default argument. It is also a conflict
with QWidget::hide() as that is not virtual.

There is no reason to mask hide()/show() in Qt, as these are not virtual
it can cause bugs. The correct method is to override setVisible(bool)
which is virtual.
MSVC type resolution seems to be different than gcc/clang so try it
another way
always visible so they never fade
Support disabling animations on a per-widget basis. This is desireable
when reusing widgets in different contexts e.g. DkThumbScrollWidget.

Also disable animations if the parent is animating, which could cause a
visual glitch or at best has no effect.

Also adds tighter control of timer by using QTimerEvent instead of
QTimer.
enter/exit fullscreen uses it to make transition smoother;

the hide/show of panels can make panels change position immediately
after the animation completes, which looks bad
only possible if plugins are disabled
The other widgets in the tab don't fade so this shouldn't either
don't use the same setting for disabling animation for user and
temporarily as it could cause unexpected change of user setting
prevents glitch where layout changes shortly after switch due to widgets
becoming hidden, which does not happen until animation ends, which is
some time after the switch finishes

this also disables animation for the initial startup of nomacs; as the
window manager is probably fading in the window anyways we don't want to
pile on more animations.
There are some pitfalls when overriding DkFadeMixin::setVisible() due to
the recursion through QWidget::setVisible, see comment @
DkFadeMixin::setVisible.

Infinite recursion is not possible, but the function body may be
executed multiple times per call to setVisible()

Currently, none of this is strictly required but in the future it would
likely result in bugs.
Broken by removal of fade. Was reliant on paint hack in DkFadeWidget.

Move the paint hack into DkWidget so it will be used again.
Reverts to previous behavior before refactoring fadewidget
@scrubbbbs scrubbbbs marked this pull request as draft April 9, 2025 23:34
@scrubbbbs
Copy link
Collaborator Author

Back to draft, I found some more issues with system theme.

On the system theme, when thumbs grid view is displayed,
the background shows through on some widgets. This is most apparent when
the thumbnail ribbon is pinned to the top.

This is a regression since theme overall PR#1140
@scrubbbbs scrubbbbs marked this pull request as ready for review April 10, 2025 12:17
@scrubbbbs
Copy link
Collaborator Author

Fixed a regression from #1140. I think this is ready.

We should not be using DkSettings for flags such as this which are not
user-modifyable.
Move old functionality into DkRatingLabel so actions work again.

Also remove some clutter.
- unecessary virtual
- excessive inline (inline containing a loop)
- use lambdas instead of trival methods
- use table/loop to make stars
@leejuyuu
Copy link
Collaborator

Thanks for the fixes. I think this is ready for merge.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants