[vlc-commits] [Git][videolan/vlc][master] 3 commits: qml: Instantiate error notification at MainDisplay and Player

Steve Lhomme (@robUx4) gitlab at videolan.org
Sat Oct 22 09:10:19 UTC 2022



Steve Lhomme pushed to branch master at VideoLAN / VLC


Commits:
911df68d by Leon Vitanos at 2022-10-22T07:25:35+00:00
qml: Instantiate error notification at MainDisplay and Player

- - - - -
e6944753 by Leon Vitanos at 2022-10-22T07:25:35+00:00
qt/qml: error notification UI redesign

- - - - -
13d2ab55 by Leon Vitanos at 2022-10-22T07:25:35+00:00
qt/qml: display error messages on the messages dialog

- - - - -


14 changed files:

- modules/gui/qt/dialogs/dialogs/dialogmodel.cpp
- modules/gui/qt/dialogs/dialogs/dialogmodel.hpp
- modules/gui/qt/dialogs/dialogs/qml/Dialogs.qml
- modules/gui/qt/dialogs/dialogs_provider.cpp
- modules/gui/qt/dialogs/dialogs_provider.hpp
- modules/gui/qt/dialogs/messages/messages.cpp
- modules/gui/qt/dialogs/messages/messages.hpp
- modules/gui/qt/dialogs/messages/messages_panel.ui
- modules/gui/qt/maininterface/mainui.cpp
- modules/gui/qt/maininterface/qml/MainDisplay.qml
- modules/gui/qt/maininterface/qml/MainInterface.qml
- modules/gui/qt/player/qml/Player.qml
- modules/gui/qt/qt.cpp
- modules/gui/qt/style/VLCColors.qml


Changes:

=====================================
modules/gui/qt/dialogs/dialogs/dialogmodel.cpp
=====================================
@@ -109,6 +109,13 @@ void DialogErrorModel::pushError(const DialogError & error)
 
     endInsertRows();
 
+    if (lastNotificationText == error.title)
+        repeatedNotificationCount += 1;
+    else{
+        lastNotificationText = error.title;
+        repeatedNotificationCount = 1;
+    }
+
     emit countChanged();
 }
 
@@ -121,6 +128,21 @@ int DialogErrorModel::count() const
     return m_data.count();
 }
 
+QString DialogErrorModel::notificationText() const
+{
+    return lastNotificationText;
+}
+
+int DialogErrorModel::repeatedMessageCount() const
+{
+    return repeatedNotificationCount;
+}
+
+void DialogErrorModel::resetRepeatedMessageCount()
+{
+   repeatedNotificationCount = 0;
+}
+
 //=================================================================================================
 // DialogModel
 //=================================================================================================


=====================================
modules/gui/qt/dialogs/dialogs/dialogmodel.hpp
=====================================
@@ -33,6 +33,7 @@
 #include <QAbstractListModel>
 
 #include "qt.hpp"
+#include "util/singleton.hpp"
 
 class DialogId
 {
@@ -54,13 +55,15 @@ public: // Variables
 Q_DECLARE_METATYPE(DialogId)
 
 
-class DialogErrorModel : public QAbstractListModel
+class DialogErrorModel : public QAbstractListModel, public Singleton<DialogErrorModel>
 {
     Q_OBJECT
 
     Q_ENUMS(DialogRoles)
 
     Q_PROPERTY(int count READ count NOTIFY countChanged FINAL)
+    Q_PROPERTY(QString notificationText READ notificationText NOTIFY countChanged FINAL)
+    Q_PROPERTY(int repeatedMessageCount READ repeatedMessageCount NOTIFY countChanged FINAL)
 
 public: // Enums
     enum DialogRoles
@@ -75,10 +78,12 @@ private:
         QString title;
         QString text;
     };
+    QString lastNotificationText;
+    int repeatedNotificationCount = 0;
 
 public:
     explicit DialogErrorModel(qt_intf_t* intf, QObject * parent = nullptr);
-    ~DialogErrorModel();
+    virtual ~DialogErrorModel();
 
 public: // QAbstractItemModel implementation
     QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const override;
@@ -100,10 +105,15 @@ signals:
 
 public: // Properties
     int count() const;
+    QString notificationText() const;
+    int repeatedMessageCount() const;
+    Q_INVOKABLE void resetRepeatedMessageCount();
 
 private: // Variables
     QList<DialogError> m_data;
     qt_intf_t* m_intf = nullptr;
+
+    friend class Singleton<DialogErrorModel>;
 };
 
 class DialogModel : public QObject


=====================================
modules/gui/qt/dialogs/dialogs/qml/Dialogs.qml
=====================================
@@ -44,7 +44,10 @@ Item {
     // Events
     //---------------------------------------------------------------------------------------------
 
-    Component.onCompleted: if (DialogErrorModel.count) errorPopup.state = "visible"
+    Component.onCompleted: if (DialogErrorModel.repeatedMessageCount){
+                               hideErrorPopupTimer.restart()
+                               errorPopup.state = "visible"
+                           }
 
     Component.onDestruction: {
         if (questionDialog.dialogId !== null) {
@@ -116,7 +119,10 @@ Item {
     {
         target: DialogErrorModel
 
-        onCountChanged: errorPopup.state = "visible"
+        onCountChanged: {
+            hideErrorPopupTimer.restart()
+            errorPopup.state = "visible"
+        }
     }
 
     //---------------------------------------------------------------------------------------------
@@ -131,52 +137,103 @@ Item {
 
     Widgets.DrawerExt {
         id: errorPopup
+
+        property string messageText
+        property int repeatedMessageCount: 0
+
         anchors {
             bottom: parent.bottom
             horizontalCenter: parent.horizontalCenter
+            bottomMargin: VLCStyle.margin_small
         }
+
         edge: Widgets.DrawerExt.Edges.Bottom
-        width: parent.width * 0.8
+        width: contentItem.layoutWidth
+        height: contentItem.height
         z: 10
 
         component: Rectangle {
-            color: "gray"
-            opacity: 0.7
-            width: errorPopup.width
-            height: VLCStyle.fontHeight_normal * 5
+            color: VLCStyle.colors.alert
+
+            height: messageText.implicitHeight + VLCStyle.margin_normal
             radius: VLCStyle.fontHeight_normal / 2
 
-            Flickable {
-                anchors.fill: parent
-                anchors.margins: VLCStyle.fontHeight_normal / 2
-                ScrollBar.vertical: ScrollBar{}
-                contentY: VLCStyle.fontHeight_normal * ((DialogErrorModel.count * 2) - 4)
-                clip: true
-
-                ListView {
-                    width: parent.width
-                    height: VLCStyle.fontHeight_normal * DialogErrorModel.count * 2
-                    model: DialogErrorModel
-                    delegate: Column {
-                        Text {
-                            text: model.title
-                            font.pixelSize: VLCStyle.fontSize_normal
-                            font.bold: true
-                            color: "red"
-                        }
-                        Text {
-                            text: model.text
-                            font.pixelSize: VLCStyle.fontSize_normal
-                        }
+            property real layoutWidth: layout.width
+
+            RowLayout {
+                id: layout
+
+                spacing: VLCStyle.margin_xxsmall
+                anchors.top: parent.top
+                anchors.bottom: parent.bottom
+
+                Widgets.IconLabel {
+                    text: VLCIcons.info
+                    Layout.leftMargin: VLCStyle.margin_xxsmall
+                }
+
+                Text {
+                    id: messageText
+
+                    Layout.maximumWidth: root.width * 0.5
+                    Layout.leftMargin: VLCStyle.margin_xxsmall
+                    Layout.rightMargin: VLCStyle.margin_xxsmall
+
+                    text: (DialogErrorModel.repeatedMessageCount > 1 ? '[' + DialogErrorModel.repeatedMessageCount + '] ' : '')
+                          + DialogErrorModel.notificationText
+
+                    wrapMode: Text.WrapAnywhere
+                    font.pixelSize: VLCStyle.fontSize_normal
+                    font.bold: true
+                    color: "white"
+                }
+
+                Widgets.TextToolButton {
+                    id: detailsBtn
+
+                    text: I18n.qtr("Show Details")
+
+                    onClicked: {
+                        hideErrorPopupTimer.stop()
+                        errorPopup.state = "hidden"
+                        DialogErrorModel.resetRepeatedMessageCount()
+                        DialogsProvider.messagesDialog(1)
+                    }
+
+                    background: Widgets.AnimatedBackground {
+                        active: visualFocus
+
+                        radius: VLCStyle.dp(4, VLCStyle.scale)
+                        backgroundColor: detailsBtn.hovered ? VLCStyle.colors.setColorAlpha(VLCStyle.colors.buttonHover, 0.5)
+                                                            : VLCStyle.colors.setColorAlpha(VLCStyle.colors.buttonHover, 0.3)
+                    }
+                }
+
+                Widgets.IconToolButton {
+                    id: closeBtn
+                    size: VLCStyle.icon_normal
+                    iconText: VLCIcons.clear
+                    text: I18n.qtr("Dismiss")
+                    Layout.rightMargin: VLCStyle.margin_xxsmall
+
+                    onClicked: {
+                        hideErrorPopupTimer.stop()
+                        errorPopup.state = "hidden"
+                        DialogErrorModel.resetRepeatedMessageCount()
+                    }
+
+                    background: Widgets.AnimatedBackground {
+                        active: visualFocus
+
+                        radius: VLCStyle.dp(4, VLCStyle.scale)
+                        backgroundColor: closeBtn.hovered ? VLCStyle.colors.setColorAlpha(VLCStyle.colors.buttonHover, 0.5)
+                                                          : VLCStyle.colors.setColorAlpha(VLCStyle.colors.buttonHover, 0.0)
                     }
                 }
             }
         }
 
         state: "hidden"
-        onStateChanged: {
-            hideErrorPopupTimer.restart()
-        }
 
         Timer {
             id: hideErrorPopupTimer
@@ -184,6 +241,7 @@ Item {
             repeat: false
             onTriggered: {
                 errorPopup.state = "hidden"
+                DialogErrorModel.resetRepeatedMessageCount()
             }
         }
     }


=====================================
modules/gui/qt/dialogs/dialogs_provider.cpp
=====================================
@@ -292,9 +292,14 @@ void DialogsProvider::synchroDialog()
         extDialog->hide();
 }
 
-void DialogsProvider::messagesDialog()
+void DialogsProvider::messagesDialog(int page)
 {
-    MessagesDialog::getInstance( p_intf )->toggleVisible();
+    MessagesDialog *msgDialog = MessagesDialog::getInstance( p_intf );
+
+    if(!msgDialog->isVisible() || page)
+        msgDialog->showTab(page);
+    else
+        msgDialog->toggleVisible();
 }
 
 void DialogsProvider::gotoTimeDialog()


=====================================
modules/gui/qt/dialogs/dialogs_provider.hpp
=====================================
@@ -134,7 +134,7 @@ public slots:
     void firstRunDialog();
     void extendedDialog();
     void synchroDialog();
-    void messagesDialog();
+    void messagesDialog( int page = 0 );
     void sendKey( int key );
 #ifdef ENABLE_VLM
     void vlmDialog();


=====================================
modules/gui/qt/dialogs/messages/messages.cpp
=====================================
@@ -43,6 +43,7 @@
 
 
 #include "dialogs/messages/messages.hpp"
+#include "dialogs/dialogs/dialogmodel.hpp"
 
 enum {
     MsgEvent_Type = QEvent::User + MsgEventTypeOffset + 1,
@@ -82,6 +83,13 @@ MessagesDialog::MessagesDialog( qt_intf_t *_p_intf)
     ui.bottomButtonsBox->addButton( new QPushButton( qtr("&Close"), this ),
                                          QDialogButtonBox::RejectRole );
 
+    /* Error messages */
+    QPlainTextEdit * errorsList = ui.errors;
+    DialogErrorModel *errors = DialogErrorModel::getInstance<false>();
+    connect( errors, &DialogErrorModel::countChanged, this, &MessagesDialog::errorsCountChanged );
+    for(int i=0; i<errors->count(); i++)
+        addError(i);
+
     /* Modules tree */
     ui.modulesTree->setHeaderHidden( true );
 
@@ -162,6 +170,46 @@ void MessagesDialog::updateConfig()
     getSettings()->endGroup();
 }
 
+void MessagesDialog::addError(int row){
+    DialogErrorModel *errors = DialogErrorModel::getInstance<false>();
+
+    QPlainTextEdit * errorsList = ui.errors;
+
+    bool b_autoscroll = ( errorsList->verticalScrollBar()->value()
+                          + errorsList->verticalScrollBar()->pageStep()
+                          >= errorsList->verticalScrollBar()->maximum() );
+
+    /* Copy selected text to the clipboard */
+    if( errorsList->textCursor().hasSelection() )
+        errorsList->copy();
+
+    /* Fix selected text bug */
+    if( !errorsList->textCursor().atEnd() ||
+         errorsList->textCursor().anchor() != errorsList->textCursor().position() )
+         errorsList->moveCursor( QTextCursor::End );
+
+    /* Start a new logic block */
+    if( !errorsList->document()->isEmpty() )
+        errorsList->textCursor().insertBlock();
+
+    QTextCharFormat format;
+
+    format.setProperty( QTextFormat::FontItalic, true );
+    format.setForeground( Qt::darkRed );
+    errorsList->textCursor().insertText( errors->data(errors->index(row, 0), DialogErrorModel::DIALOG_TITLE).toString()+": ", format );
+
+    format.setProperty( QTextFormat::FontItalic, false );
+    format.setForeground( errorsList->palette().windowText() );
+    errorsList->textCursor().insertText( errors->data(errors->index(row, 0), DialogErrorModel::DIALOG_TEXT).toString(), format );
+
+    if ( b_autoscroll ) errorsList->ensureCursorVisible();
+}
+
+void MessagesDialog::errorsCountChanged(){
+    DialogErrorModel *errors = DialogErrorModel::getInstance(p_intf);
+    addError(errors->count() - 1);
+}
+
 void MessagesDialog::filterMessages()
 {
     QMutexLocker locker( &messageLocker );
@@ -342,13 +390,15 @@ void MessagesDialog::buildTree( QTreeWidgetItem *parentItem,
 
 void MessagesDialog::updateOrClear()
 {
-    if( ui.mainTab->currentIndex() == 1)
+    if( ui.mainTab->currentIndex() == 2)
     {
         ui.modulesTree->clear();
         buildTree( NULL, VLC_OBJECT( vlc_object_instance(p_intf) ) );
     }
     else if( ui.mainTab->currentIndex() == 0 )
         ui.messages->clear();
+    else if( ui.mainTab->currentIndex() == 1 )
+        ui.errors->clear();
 #ifndef NDEBUG
     else
         updatePLTree();
@@ -357,9 +407,17 @@ void MessagesDialog::updateOrClear()
 
 void MessagesDialog::tabChanged( int i )
 {
-    updateButton->setIcon( i != 0 ? QIcon(":/menu/update.svg") : QIcon(":/menu/clear.svg") );
-    updateButton->setToolTip( i != 0 ? qtr("Update the tree")
-                                     : qtr("Clear the messages") );
+    updateButton->setIcon( i > 1 ? QIcon(":/menu/update.svg") : QIcon(":/menu/clear.svg") );
+    updateButton->setToolTip( i > 1 ? qtr("Update the tree")
+                                     : i == 0 ? qtr("Clear the messages")
+                                              : qtr("Clear the errors"));
+}
+
+void MessagesDialog::showTab( int i )
+{
+    ui.mainTab->setCurrentIndex(i);
+    show();
+    raise();
 }
 
 void MessagesDialog::MsgCallback( void *self, int type, const vlc_log_t *item,


=====================================
modules/gui/qt/dialogs/messages/messages.hpp
=====================================
@@ -59,6 +59,8 @@ private slots:
     void updateOrClear();
     void tabChanged( int );
     void filterMessages();
+    void addError( int );
+    void errorsCountChanged();
 
 private:
     void buildTree( QTreeWidgetItem *, vlc_object_t * );
@@ -70,6 +72,9 @@ private:
     QTreeWidget *pldebugTree;
     void updatePLTree();
 #endif
+
+public:
+    void showTab( int i );
 };
 
 #endif


=====================================
modules/gui/qt/dialogs/messages/messages_panel.ui
=====================================
@@ -89,6 +89,23 @@
        </item>
       </layout>
      </widget>
+     <widget class="QWidget" name="tab_3">
+      <attribute name="title">
+       <string>Errors</string>
+      </attribute>
+      <layout class="QGridLayout" name="gridLayout_2">
+       <item row="0" column="0">
+        <widget class="QPlainTextEdit" name="errors">
+         <property name="horizontalScrollBarPolicy">
+          <enum>Qt::ScrollBarAlwaysOff</enum>
+         </property>
+         <property name="readOnly">
+          <bool>true</bool>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </widget>
      <widget class="QWidget" name="tab_2">
       <attribute name="title">
        <string>Modules Tree</string>


=====================================
modules/gui/qt/maininterface/mainui.cpp
=====================================
@@ -130,10 +130,12 @@ MainUI::MainUI(qt_intf_t *p_intf, MainCtx *mainCtx, QWindow* interfaceWindow,  Q
     assert(DialogsProvider::getInstance());
     SingletonRegisterHelper<DialogsProvider>::setInstance(DialogsProvider::getInstance());
 
+    assert(DialogErrorModel::getInstance<false>());
+    SingletonRegisterHelper<DialogErrorModel>::setInstance( DialogErrorModel::getInstance<false>() );
+
     SingletonRegisterHelper<NavigationHistory>::setInstance( new NavigationHistory(this) );
     SingletonRegisterHelper<I18n>::setInstance( new I18n(this) );
     SingletonRegisterHelper<SystemPalette>::setInstance( new SystemPalette(this) );
-    SingletonRegisterHelper<DialogErrorModel>::setInstance( new DialogErrorModel(m_intf, this));
     SingletonRegisterHelper<QmlKeyHelper>::setInstance( new QmlKeyHelper(this) );
     SingletonRegisterHelper<SVGColorImage>::setInstance( new SVGColorImage(this) );
 


=====================================
modules/gui/qt/maininterface/qml/MainDisplay.qml
=====================================
@@ -31,6 +31,7 @@ import "qrc:///player/" as P
 
 import "qrc:///util/" as Util
 import "qrc:///util/Helpers.js" as Helpers
+import "qrc:///dialogs/" as DG
 
 FocusScope {
     id: root
@@ -486,6 +487,16 @@ FocusScope {
                 }
             }
 
+            DG.Dialogs {
+                z: 10
+                bgContent: root
+
+                anchors {
+                    bottom: miniPlayer.visible ? miniPlayer.top : parent.bottom
+                    left: parent.left
+                    right: parent.right
+                }
+            }
 
             P.MiniPlayer {
                 id: miniPlayer


=====================================
modules/gui/qt/maininterface/qml/MainInterface.qml
=====================================
@@ -27,7 +27,6 @@ import org.videolan.compat 0.1
 import "qrc:///widgets/" as Widgets
 import "qrc:///style/"
 
-import "qrc:///dialogs/" as DG
 import "qrc:///playlist/" as PL
 
 Item {
@@ -37,7 +36,6 @@ Item {
     property bool _playlistReady: false
 
     property alias g_root: root
-    property QtObject g_dialogs: dialogsLoader.item
 
     BindingCompat {
         target: VLCStyle.self
@@ -198,25 +196,6 @@ Item {
         source: "qrc:///menus/GlobalShortcuts.qml"
     }
 
-    Loader {
-        id: dialogsLoader
-
-        anchors.fill: parent
-        asynchronous: true
-        source: "qrc:///dialogs/Dialogs.qml"
-
-        onLoaded:  {
-            item.bgContent = root
-        }
-    }
-
-    Connections {
-        target: dialogsLoader.item
-        onRestoreFocus: {
-            stackView.focus = true
-        }
-    }
-
     MouseArea {
         /// handles mouse navigation buttons
         anchors.fill: parent


=====================================
modules/gui/qt/player/qml/Player.qml
=====================================
@@ -28,6 +28,7 @@ import "qrc:///style/"
 import "qrc:///widgets/" as Widgets
 import "qrc:///playlist/" as PL
 import "qrc:///util/Helpers.js" as Helpers
+import "qrc:///dialogs/" as DG
 
 FocusScope {
     id: rootPlayer
@@ -563,6 +564,18 @@ FocusScope {
         }
     }
 
+    DG.Dialogs {
+        z: 10
+        bgContent: rootPlayer
+
+        anchors {
+            bottom: controlBarView.contentItem.visible ? controlBarView.top : rootPlayer.bottom
+            left: parent.left
+            right: parent.right
+            bottomMargin: rootPlayer.pinVideoControls || !controlBarView.contentItem.visible ? 0 : - VLCStyle.margin_large
+        }
+    }
+
     Widgets.DrawerExt {
         id: controlBarView
 


=====================================
modules/gui/qt/qt.cpp
=====================================
@@ -57,6 +57,7 @@ extern "C" char **environ;
 #include "player/player_controller.hpp"    /* THEMIM destruction */
 #include "playlist/playlist_controller.hpp" /* THEMPL creation */
 #include "dialogs/dialogs_provider.hpp" /* THEDP creation */
+#include "dialogs/dialogs/dialogmodel.hpp"
 #ifdef _WIN32
 # include "maininterface/mainctx_win32.hpp"
 #else
@@ -733,6 +734,8 @@ static void *Thread( void *obj )
 
     app.setDesktopFileName( PACKAGE );
 
+    DialogErrorModel::getInstance( p_intf );
+
     /* Initialize the Dialog Provider and the Main Input Manager */
     DialogsProvider::getInstance( p_intf );
     p_intf->p_mainPlayerController = new PlayerController(p_intf);
@@ -899,6 +902,8 @@ static void *ThreadCleanup( qt_intf_t *p_intf, CleanupReason cleanupReason )
      */
     DialogsProvider::killInstance();
 
+    DialogErrorModel::killInstance();
+
     /* Destroy the main playlist controller */
     if (p_intf->p_mainPlaylistController)
     {


=====================================
modules/gui/qt/style/VLCColors.qml
=====================================
@@ -175,7 +175,7 @@ Item {
 
     property color accentText: "#ffffff";
 
-    property color alert: "red";
+    property color alert: "#d70022";
 
     property color buffer: "#696969";
 
@@ -234,7 +234,6 @@ Item {
                 lowerBanner: "#ffffff"
 
                 accent: "#ff610a";
-                alert: "#ff0000";
                 separator: "#ededed";
 
                 playerControlBarFg: "#333333"
@@ -268,7 +267,6 @@ Item {
                 topBannerHover: "#272727"
                 lowerBanner: "#000000"
                 accent: "#ff8800"
-                alert: "#ff0000"
                 separator: "#2d2d2d"
                 playerControlBarFg: "#ffffff"
 



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/d2ed8db485b433e3795ec8cc9acc28457ad0d3de...13d2ab5573c5546510601c1a72e99e70cdcbcb75

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/d2ed8db485b433e3795ec8cc9acc28457ad0d3de...13d2ab5573c5546510601c1a72e99e70cdcbcb75
You're receiving this email because of your account on code.videolan.org.


VideoLAN code repository instance


More information about the vlc-commits mailing list