-
Notifications
You must be signed in to change notification settings - Fork 121
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
Compact GUI design, new features, combined widgets, editable text fields, movable docks, and more... #485
base: master
Are you sure you want to change the base?
Conversation
Properly (re)name the gui's XML elements to suggest their meaning. Group the gui's bottom components together into the Navigation widget. This serves the purpose of making the interface more compact, and the mouse navigation easier. Shrinking the gui's window should not clutter or overlap elements. A minimum size should be respected to allow displaying every widget. The bottom components are put into individual sets that can be hidden independently. Enable floating Navigation and Codec widgets, and allow to dock them up/down and left/right respectively. Also allow the Toolbar to dock both up/down and left/right. Add a close button to the Navigation and Codec Options widgets, and enable context menus in the widgets main Menu, Toolbar, Navigation, and Codec Options. The View->Toolbars->Navigation menu option will toggle the Navigation visibility, hiding all of its components. Allow to select and copy into the clipboard current time, total time, selection duration, marker A time, and marker B time by highlighting the content of their own element. Redesign current time, marker A time, and marker B time elements to combine action buttons and text fields. This design fixes the displaying of the selection duration's seconds, that were cut due to insufficient space for the label element.
Follow the convention dictated by T_vumeter.{cpp,h}.
Docking features require the presence of the title bar.
Bottom dock widgets have been combined into the Navigation widget as frame elements. Remove residual code about setting title bars.
Bottom dock widgets have been combined into the Navigation widget as frame elements. Remove residual code about checking heights.
Buttons float/dock and close to the left, add a title if set. Use the title's mnemonic & to switch to float/dock state. This solves the problem of Light and Dark themes that do not read dock widgets mnemonic correctly, putting a & into the widget's title.
Slightly darkening the Light theme windows' background helps to spot the dock widgets' resize handle, otherwise not visible enough.
Add new hideable items and resort Toolbars order, bottom dock widgets have been combined into the Navigation widget as frame elements.
Initialize new hideable items visibility, the Navigation dock widget contains new frame elements. Sort top to botton following the gui.
Use the status bar as a XML widget. The status bar can be hidden via 'View->Toolbars->Status Bar'.
The gui interface has space for a taller volume meter.
Reading left-to-right, the segment A to B has the former letter before the latter. It makes sense to express this positioning in the goMarkA icons (A< vs >A, where goMarkB is >B, to represent the segment A<->B).
Visually center the letter B in its box.
I can't reproduce the problem... I tried with the mouse cursor and by hitting tab... Would you take a video too, please? 2023-03-23.22-27-36.mov |
asc.mp4 |
Thank you for the huge amount of thought put into this POC. Making the time display editable was on my wishlist for quite a while. The code doesn't build with Qt6 and renaming navButtonsLayout has broken compilation on macOS specifically, but fixing all the obsolete QRegExp stuff, gone since Qt6, was luckily straightforward, so that now I am able to play with it. I need to spend some time with the new concept to evaluate it beyond the immediate knee-jerk rejection (I don't like cramped interfaces filled with small hit targets). |
Below the build fix for reference. index d1b33286f..3f52795ec 100644
--- a/avidemux/qt4/ADM_userInterfaces/ADM_gui/Q_gui2.cpp
+++ b/avidemux/qt4/ADM_userInterfaces/ADM_gui/Q_gui2.cpp
@@ -143,7 +143,13 @@ static bool uiIsMaximized=false;
static bool needsResizing=false;
-static QRegExp timeRegExp("^([0-9]{2}):([0-5][0-9]):([0-5][0-9])\\.([0-9]{3})$");
+static
+#if QT_VERSION < QT_VERSION_CHECK(5,1,0)
+ QRegExp
+#else
+ QRegularExpression
+#endif
+ timeRegExp("^([0-9]{2}):([0-5][0-9]):([0-5][0-9])\\.([0-9]{3})$");
static QAction *findAction(std::vector<MenuEntry> *list, Action action);
static QAction *findActionInToolBar(QToolBar *tb, Action action);
@@ -714,7 +720,7 @@ MainWindow::MainWindow(const vector<IScriptEngine*>& scriptEngines) : _scriptEng
#endif
#ifdef __APPLE__
- ui.navButtonsLayout->setSpacing(2);
+ ui.controlsWidgetLayout->setSpacing(2);
// Qt upscales 2x sized icons in the toolbar, making them huge and pixelated in HiDPI conditions, WTF?
ui.toolBar->setIconSize(QSize(24,24));
#endif
@@ -780,7 +786,11 @@ MainWindow::MainWindow(const vector<IScriptEngine*>& scriptEngines) : _scriptEng
connect(ui.spinBox_TimeValue,SIGNAL(valueChanged(int)),this,SLOT(timeChanged(int)));
connect(ui.spinBox_TimeValue, SIGNAL(editingFinished()), this, SLOT(timeChangeFinished()));
#if 1 /* disable if read-only */
+#if QT_VERSION < QT_VERSION_CHECK(5,1,0)
QRegExpValidator *timeValidator = new QRegExpValidator(timeRegExp, this);
+#else
+ QRegularExpressionValidator *timeValidator = new QRegularExpressionValidator(timeRegExp, this);
+#endif
ui.currentTime->setValidator(timeValidator);
ui.currentTime->setInputMask("99:99:99.999");
ui.selectionMarkerA->setValidator(timeValidator);
@@ -3727,14 +3737,29 @@ admUITaskBarProgress *UI_getTaskBarProgress()
*/
bool UI_getCurrentTime(uint32_t *hh, uint32_t *mm, uint32_t *ss, uint32_t *ms)
{
- QRegExp rx(timeRegExp);
+#if QT_VERSION < QT_VERSION_CHECK(5,1,0)
+ QRegExp
+#else
+ QRegularExpression
+#endif
+ rx(timeRegExp);
// Previous state
uint64_t pts = admPreview::getCurrentPts();
+#if QT_VERSION < QT_VERSION_CHECK(5,1,0)
if(rx.exactMatch(WIDGET(currentTime)->text()))
+#else
+ QRegularExpressionMatch match = rx.match(WIDGET(currentTime)->text());
+ if(match.hasMatch())
+#endif
{
- QStringList results = rx.capturedTexts();
+ QStringList results =
+#if QT_VERSION < QT_VERSION_CHECK(5,1,0)
+ rx.capturedTexts();
+#else
+ match.capturedTexts();
+#endif
*hh = results.at(1).toInt(NULL, 10);
*mm = results.at(2).toInt(NULL, 10);
@@ -3763,15 +3788,30 @@ bool UI_getCurrentTime(uint32_t *hh, uint32_t *mm, uint32_t *ss, uint32_t *ms)
*/
bool UI_getMarkerA(uint32_t *hh, uint32_t *mm, uint32_t *ss, uint32_t *ms)
{
- QRegExp rx(timeRegExp);
+#if QT_VERSION < QT_VERSION_CHECK(5,1,0)
+ QRegExp
+#else
+ QRegularExpression
+#endif
+ rx(timeRegExp);
// Previous state
uint64_t ptsA = video_body->getMarkerAPts();
uint64_t ptsB = video_body->getMarkerBPts();
+#if QT_VERSION < QT_VERSION_CHECK(5,1,0)
if(rx.exactMatch(WIDGET(selectionMarkerA)->text()))
+#else
+ QRegularExpressionMatch match = rx.match(WIDGET(selectionMarkerA)->text());
+ if(match.hasMatch())
+#endif
{
- QStringList results = rx.capturedTexts();
+ QStringList results =
+#if QT_VERSION < QT_VERSION_CHECK(5,1,0)
+ rx.capturedTexts();
+#else
+ match.capturedTexts();
+#endif
*hh = results.at(1).toInt(NULL, 10);
*mm = results.at(2).toInt(NULL, 10);
@@ -3800,15 +3840,30 @@ bool UI_getMarkerA(uint32_t *hh, uint32_t *mm, uint32_t *ss, uint32_t *ms)
*/
bool UI_getMarkerB(uint32_t *hh, uint32_t *mm, uint32_t *ss, uint32_t *ms)
{
- QRegExp rx(timeRegExp);
+#if QT_VERSION < QT_VERSION_CHECK(5,1,0)
+ QRegExp
+#else
+ QRegularExpression
+#endif
+ rx(timeRegExp);
// Previous state
uint64_t ptsA = video_body->getMarkerAPts();
uint64_t ptsB = video_body->getMarkerBPts();
+#if QT_VERSION < QT_VERSION_CHECK(5,1,0)
if(rx.exactMatch(WIDGET(selectionMarkerB)->text()))
+#else
+ QRegularExpressionMatch match = rx.match(WIDGET(selectionMarkerB)->text());
+ if(match.hasMatch())
+#endif
{
- QStringList results = rx.capturedTexts();
+ QStringList results =
+#if QT_VERSION < QT_VERSION_CHECK(5,1,0)
+ rx.capturedTexts();
+#else
+ match.capturedTexts();
+#endif
*hh = results.at(1).toInt(NULL, 10);
*mm = results.at(2).toInt(NULL, 10);
@@ -3837,15 +3892,30 @@ bool UI_getMarkerB(uint32_t *hh, uint32_t *mm, uint32_t *ss, uint32_t *ms)
*/
bool UI_getSelectionTime(uint32_t *hh, uint32_t *mm, uint32_t *ss, uint32_t *ms)
{
- QRegExp rx(timeRegExp);
+#if QT_VERSION < QT_VERSION_CHECK(5,1,0)
+ QRegExp
+#else
+ QRegularExpression
+#endif
+ rx(timeRegExp);
// Previous state
uint64_t ptsA = video_body->getMarkerAPts();
uint64_t ptsB = video_body->getMarkerBPts();
+#if QT_VERSION < QT_VERSION_CHECK(5,1,0)
if(rx.exactMatch(WIDGET(selectionDuration)->text()))
+#else
+ QRegularExpressionMatch match = rx.match(WIDGET(selectionDuration)->text());
+ if(match.hasMatch())
+#endif
{
- QStringList results = rx.capturedTexts();
+ QStringList results =
+#if QT_VERSION < QT_VERSION_CHECK(5,1,0)
+ rx.capturedTexts();
+#else
+ match.capturedTexts();
+#endif
*hh = results.at(1).toInt(NULL, 10);
*mm = results.at(2).toInt(NULL, 10);
@@ -3875,14 +3945,29 @@ bool UI_getSelectionTime(uint32_t *hh, uint32_t *mm, uint32_t *ss, uint32_t *ms)
bool UI_getTotalTime(uint32_t *hh, uint32_t *mm, uint32_t *ss, uint32_t *ms)
{
bool status = true;
- QRegExp rx(timeRegExp);
+#if QT_VERSION < QT_VERSION_CHECK(5,1,0)
+ QRegExp
+#else
+ QRegularExpression
+#endif
+ rx(timeRegExp);
// Previous state
uint64_t tot = video_body->getVideoDuration();
+#if QT_VERSION < QT_VERSION_CHECK(5,1,0)
if(rx.exactMatch(WIDGET(totalTime)->text()))
+#else
+ QRegularExpressionMatch match = rx.match(WIDGET(totalTime)->text());
+ if(match.hasMatch())
+#endif
{
- QStringList results = rx.capturedTexts();
+ QStringList results =
+#if QT_VERSION < QT_VERSION_CHECK(5,1,0)
+ rx.capturedTexts();
+#else
+ match.capturedTexts();
+#endif
*hh = results.at(1).toInt(NULL, 10);
*mm = results.at(2).toInt(NULL, 10); |
I feel sorry to hear that. Currently I'm working with Qt 5.15.8 on Gentoo GNU/Linux. Tell me if I can be of any help.
I was trying to sort out a configuration giving some visual hints and control over tedious tuning and adjustments, with the objective of rearrangeable widgets and togglable features. I'm debugging a problem highlighted by @szlldm right now, I hope to get it fixed soon.
Thanks. |
By the way, icons, buttons, styles, etc. are just a mean to focus on the infrastructure, pushing to implement useful features that then can be expressed and used in any other creative/conceptual way. |
@szlldm I've an insight on the problem now, thank you so much for your help ;) |
A uint64_t type cast gives the right precision to uint32_t values when converting to a hh:mm:ss.mm,us time expressed in microseconds.
New ADM_QLineEditPTS class to add precision to time fields. GUI text elements now store time at microsecond precisions. This prevents the jittering bug when switching focus out from a time field. Jittering bug: Time fields signal editingFinished after switching the focus or pressing Enter. Fields signaled as edited are compared with the previous real time to confirm that they have been truly modified. A field time is converted from milli to the micro seconds of the real time. The equality fails when the real time microseconds part is not all zero. The jitter is when the field time, differing from the real time, is replaced with the closest frame real time (usually the frame before). Thanks to szlldm for spotting the jittering bug. Thanks to eumagga0x2a for fixing obsolete regexp code.
Editing the markers A/B fields directly, by changing the text, may result in a computed frame real position not diffrent from before. Different timings may resolve to the same frame. When an A/B text refresh is not performed anyway, the edited value may be obsolete. Editing A/B directly is more flexible than the 'Go to Time' dialog but, as said before, the difference is that the former changes the field text before the frame computation is done, the latter intead changes the text after, and only if the computed time differs from the currently one set.
Confirming the total time edit should be followed by a refresh. The total time field can be edited to prepare a cut selection from the marker A to B starting from the end of the video. This feature can be used to set a cut to reduce the video length of a specific amount. After refreshing the total time field, the video length specified will be indicated by the marker A time.
Time fields will show microsecond precision timings when hovered, i.e. 99:59:59.999,999. Tooltips will be updated when a field has been programmatically changed, or a user's edit is confirmed. This could also be used for debugging purposes.
$ cd avidemux_core/ADM_coreUtils/src $ nano prefs2.conf $ chmod +x update_prefs.sh $ ./update_prefs.sh
This is a workaround about editingFinished events. Even when time fields are set to readonly, the signal triggers just one time when the field is clicked and then the focus is changed, with Tab or by clicking another element. This could be a better solution than disabling the time fields, if there are action buttons that should be kept enabled in a field.
@eumagga0x2a Hi, there are different fixes in the latest commits. The direct editing feature of the time fields got more precision. There's a new class overloading Editing the total time prepares a selection to cut a video to a specific length, the marker A is placed at the new length, and B after the last frame. Editing the selection duration will narrow the selection from A to B, moving B toward A, to the left. |
Add preference to show only the default action button on time fields or all the buttons.
Fixes typo in 'Start making use of microseconds precision' commit.
Each time field has a preference option to enable direct keyboard editing of the field.
Thank you, I've finally found a few hours to spend with the new GUI on Linux and on Windows 10, but unfortunately didn't have time to debug the functional issues, mainly the direct time input being broken (probably regressed by the newly added changes). I wonder how the new concept works with multiple displays, with detached dock widgets placed on a different display than the main window, something I cannot test at all. Everything below reflects just my impression and is entirely IMHO:
|
@eumagga0x2a Hi, thank you very much for all your considerations. I'm currently implementing a way to allow docking to a diffrent area and undocking w/o showing a title bar when a widget is docked, if it is possible, and I'll read your points one by one thoroughly as soon as my mind is at ease. May I ask you for pictures showing interface differences from a GNU/Linux platform? I you prefer to use an email, my address is in the commits.
I see that now there are merge conflicts. I still have to look into what have been changed since my PR. I did a lot of labeling on
Allow to make use of multiple displays is one of my aims. I opened the PR as soon as I had something to start a discussion. I can modify my perspective only by sharing concepts, and for this I thank you. The interface needs a lot of polishing, I'm building a TODO list while coding. For instance, dock widgets decoration when floating and keeping them streamline when docked. Expect new commits soon to this PR. I believe that first-hand experience is by comparison the best way to conceptualize and give birth to new ideas. Some issues may be just aesthetic related, and easy addressable once the infrastructure they build on is solid. Can you still compile this PR? |
I'm sorry for the inconvenience, the work on the status bar added by szlldm prior to this PR needs to be continued until it has reached some presentable shape and official nightly builds can be offered to the public. I would like to avoid blocking the project for a prolonged period of time beyond the already unsightly state of affairs following the move to FFmpeg 5.x which has left VA-API hw accel support in a half-broken state.
Will do soon. I keep your PR locally on a separate branch, so it compiles, yes. It just doesn't pick up any ongoing work in other areas of the application. |
@eumagga0x2a Hi, the context menu and dock widgets decoration are almost done. Rotating a custom title bar properly was not so easy to tweak... |
Hello, I'll be really grateful to anyone who could give me some feedback about this design.
Thank you ;)
Summary
Can undock, dock, and move Navigation, Codec, and Tool Bar.
Custom title bar in dock windows with mnemonic shortcuts to dock, undock.
Integrates smart buttons in editable text fields. Can edit times directly.
Buttons to open a dialog to edit Current Time, Marker A and B.
Buttons to Save Script and Run Project/Script.
Also buttons to Jump/Reset Marker A/B, Append Media, Cut, Copy, Paste, Undo, Redo.
Grayed out Reset Marker A/B buttons suggest when a marker is reset, and vice versa.
Can hide sets of components and save their visible state as preferences.
Views->Toolbars is accessible as context menu on Menu Bar, Tool Bar, Navigation, and Codec widgets to hide components.
And tooltips all the way...
NEW GUI
CURRENT GUI
Notice how the Selection Duration is truncated... Which is what pushed me to modify the GUI and add new features...