[Qt] Parsing of generic toolbars and auto-creation of those bars.
authorJean-Baptiste Kempf <jb@videolan.org>
Sun, 2 Nov 2008 19:14:16 +0000 (20:14 +0100)
committerJean-Baptiste Kempf <jb@videolan.org>
Sun, 2 Nov 2008 19:17:37 +0000 (20:17 +0100)
This introduce a parseAndCreate function that creates all the needed buttons from a QString input.
This also introduce a next-frame button and the code needed behind it.

modules/gui/qt4/components/controller.cpp
modules/gui/qt4/components/controller.hpp
modules/gui/qt4/main_interface.cpp

index bab841e..94c0de4 100644 (file)
@@ -42,7 +42,6 @@
 #include <QSpacerItem>
 #include <QCursor>
 #include <QToolButton>
-#include <QToolButton>
 #include <QHBoxLayout>
 #include <QMenu>
 #include <QPalette>
@@ -77,6 +76,7 @@ AbstractController::AbstractController( intf_thread_t * _p_i ) : QFrame( NULL )
     CONNECT( THEMIM->getIM(), statusChanged( int ), this, setStatus( int ) );
 }
 
+/* Reemit some signals on status Change to activate some buttons */
 void AbstractController::setStatus( int status )
 {
     bool b_hasInput = THEMIM->getIM()->hasInput();
@@ -89,6 +89,7 @@ void AbstractController::setStatus( int status )
                             var_GetBool( THEMIM->getInput(), "can-record" ) );
 }
 
+/* Generic button setup */
 void AbstractController::setupButton( QAbstractButton *aButton )
 {
     static QSizePolicy sizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
@@ -101,6 +102,69 @@ void AbstractController::setupButton( QAbstractButton *aButton )
     aButton->setFocusPolicy( Qt::NoFocus );
 }
 
+/* Open the generic config line for the toolbar, parse it
+ * and create the widgets accordingly */
+void AbstractController::parseAndCreateLine( QString config, int i_line )
+{
+    int i_column = 0;
+    QStringList list = config.split( ";" ) ;
+    for( int i = 0; i < list.size(); i++ )
+    {
+         QStringList list2 = list.at( i ).split( "-" );
+         if( list2.size() < 1 )
+         {
+             msg_Warn( p_intf, "Parsing error. Report this" );
+             continue;
+         }
+
+         bool ok;
+         int i_option = WIDGET_NORMAL;
+         buttonType_e i_type = (buttonType_e)list2.at( 0 ).toInt( &ok );
+         if( !ok )
+         {
+             msg_Warn( p_intf, "Parsing error 0. Please report this" );
+             continue;
+         }
+         /* Special case for SPACERS, who aren't QWidgets */
+         if( i_type == WIDGET_SPACER || i_type == WIDGET_SPACER_EXTEND )
+         {
+             controlLayout->setColumnMinimumWidth( i, 10 );
+             i_column++;
+             controlLayout->setColumnStretch( i,
+                     ( i_type == WIDGET_SPACER ) ? 0 : 10 );
+             continue;
+         }
+
+         if( list2.size() > 1 )
+         {
+             i_option = list2.at( 1 ).toInt( &ok );
+             if( !ok )
+             {
+                 msg_Warn( p_intf, "Parsing error 1. Please report this" );
+                 continue;
+             }
+         }
+
+         int i_size;
+         QWidget *widg = createWidget( i_type, &i_size, i_option );
+         if( !widg ) continue;
+
+         if( list2.size() > 2 )
+         {
+             i_size = list.at( 2 ).toInt( &ok );
+
+             if( !ok )
+             {
+                 msg_Warn( p_intf, "Parsing error 2. Please report this" );
+                 continue;
+             }
+         }
+
+         controlLayout->addWidget( widg, i_line, i_column, 1, i_size );
+         i_column += i_size;
+    }
+}
+
 #define CONNECT_MAP( a ) CONNECT( a, clicked(),  toolbarActionsMapper, map() )
 #define SET_MAPPING( a, b ) toolbarActionsMapper->setMapping( a , b )
 #define CONNECT_MAP_SET( a, b ) \
@@ -118,9 +182,16 @@ void AbstractController::setupButton( QAbstractButton *aButton )
     CONNECT( this, inputExists( bool ), a, setEnabled( bool ) ); \
     a->setEnabled( THEMIM->getIM()->hasInput() ); /* TODO: is this necessary? when input is started before the interface? */
 
-QWidget *AbstractController::createWidget( buttonType_e button, bool b_flat,
-        bool b_big, bool b_shiny )
+QWidget *AbstractController::createWidget( buttonType_e button, int* i_size,
+        int options )
 {
+    assert( i_size );
+
+    bool b_flat = options & WIDGET_FLAT;
+    bool b_big = options & WIDGET_BIG;
+    bool b_shiny = options & WIDGET_SHINY;
+    *i_size = 1; 
+
     QWidget *widget = NULL;
     switch( button )
     {
@@ -179,16 +250,15 @@ QWidget *AbstractController::createWidget( buttonType_e button, bool b_flat,
         widget = fasterButton;
         }
         break;
-#if 0
     case FRAME_BUTTON: {
-        QToolButton *frameButton = new QToolButton( "Fr" );
+        QToolButton *frameButton = new QToolButton;
         setupButton( frameButton );
+        CONNECT_MAP_SET( frameButton, FRAME_ACTION );
         BUTTON_SET_BAR( frameButton, "", qtr( "Frame by frame" ) );
         ENABLE_ON_INPUT( frameButton );
         widget = frameButton;
         }
         break;
-#endif
     case FULLSCREEN_BUTTON:{
         QToolButton *fullscreenButton = new QToolButton;
         setupButton( fullscreenButton );
@@ -199,6 +269,16 @@ QWidget *AbstractController::createWidget( buttonType_e button, bool b_flat,
         widget = fullscreenButton;
         }
         break;
+    case DEFULLSCREEN_BUTTON:{
+        QToolButton *fullscreenButton = new QToolButton;
+        setupButton( fullscreenButton );
+        CONNECT_MAP_SET( fullscreenButton, FULLSCREEN_ACTION );
+        BUTTON_SET_BAR( fullscreenButton, defullscreen,
+                qtr( "Toggle the video in fullscreen" ) );
+        ENABLE_ON_VIDEO( fullscreenButton );
+        widget = fullscreenButton;
+        }
+        break;
     case EXTENDED_BUTTON:{
         QToolButton *extSettingsButton = new QToolButton;
         setupButton( extSettingsButton );
@@ -255,23 +335,49 @@ QWidget *AbstractController::createWidget( buttonType_e button, bool b_flat,
         /* And update the IM, when the position has changed */
         CONNECT( slider, sliderDragged( float ),
                 THEMIM->getIM(), sliderUpdate( float ) );
+        /* *i_size = -1; */
         widget = slider;
         }
         break;
     case MENU_BUTTONS:
         widget = discFrame();
         widget->hide();
+        *i_size = 3;
         break;
     case TELETEXT_BUTTONS:
         widget = telexFrame();
         widget->hide();
+        *i_size = 4;
         break;
     case VOLUME:
         {
             SoundWidget *snd = new SoundWidget( p_intf, b_shiny );
             widget = snd;
+            *i_size = 4;
+        }
+        break;
+    case TIME_LABEL:
+        {
+            TimeLabel *timeLabel = new TimeLabel( p_intf );
+            widget = timeLabel;
+        }
+        break;
+    case SPLITTER:
+        {
+            QFrame *line = new QFrame;
+            line->setFrameShape( QFrame::VLine );
+            line->setFrameShadow( QFrame::Raised );
+            line->setLineWidth( 0 );
+            line->setMidLineWidth( 1 );
+            widget = line;
         }
         break;
+    case ADVANCED_CONTROLLER:
+        {
+            advControls = new AdvControlsWidget( p_intf );
+            widget = advControls;
+            *i_size = advControls->getWidth();
+        }
     default:
         msg_Warn( p_intf, "This should not happen" );
         break;
@@ -289,6 +395,7 @@ QWidget *AbstractController::createWidget( buttonType_e button, bool b_flat,
             {
                 tmpButton->setFixedSize( QSize( 32, 32 ) );
                 tmpButton->setIconSize( QSize( 26, 26 ) );
+                *i_size = 2;
             }
         }
     }
@@ -401,7 +508,10 @@ QWidget *AbstractController::telexFrame()
 }
 #undef CONNECT_MAP
 #undef SET_MAPPING
+#undef CONNECT_MAP_SET
 #undef BUTTON_SET_BAR
+#undef ENABLE_ON_VIDEO
+#undef ENABLE_ON_INPUT
 
 SoundWidget::SoundWidget( intf_thread_t * _p_intf, bool b_shiny )
                          : b_my_volume( false )
@@ -553,6 +663,8 @@ void AbstractController::doAction( int id_action )
             record(); break;
         case ATOB_ACTION:
             THEMIM->getIM()->setAtoB(); break;
+        case FRAME_ACTION:
+            frame(); break;
         default:
             msg_Dbg( p_intf, "Action: %i", id_action );
             break;
@@ -613,7 +725,6 @@ void AbstractController::snapshot()
     }
 }
 
-
 void AbstractController::extSettings()
 {
     THEDP->extendedDialog();
@@ -658,11 +769,12 @@ void AbstractController::record()
     }
 }
 
-#if 0
-//TODO Frame by frame function
-void AbstractController::frame(){}
-#endif
-
+void AbstractController::frame()
+{
+    input_thread_t *p_input = THEMIM->getInput();
+    if( p_input )
+        var_SetVoid( p_input, "frame-next" );
+}
 
 /*****************************
  * DA Control Widget !
@@ -675,48 +787,28 @@ ControlsWidget::ControlsWidget( intf_thread_t *_p_i,
 
     /* advanced Controls handling */
     b_advancedVisible = b_advControls;
-
-    advControls = new AdvControlsWidget( p_intf );
-    if( !b_advancedVisible ) advControls->hide();
+    advControls = NULL;
 
     controlLayout->setSpacing( 0 );
-    controlLayout->setLayoutMargins( 7, 5, 7, 3, 6 );
-
-    controlLayout->addWidget( createWidget( INPUT_SLIDER ), 0, 1, 1, 18 );
-    controlLayout->addWidget( createWidget( SLOWER_BUTTON, true ), 0, 0 );
-    controlLayout->addWidget( createWidget( FASTER_BUTTON, true ), 0, 19 );
-
-    controlLayout->addWidget( createWidget( MENU_BUTTONS ), 1, 8, 2, 3 );
-    controlLayout->addWidget( createWidget( TELETEXT_BUTTONS ), 1, 8, 2, 5, Qt::AlignBottom );
+    controlLayout->setLayoutMargins( 6, 4, 6, 2, 5 );
 
-    controlLayout->addWidget( createWidget( PLAY_BUTTON, false, true ), 2, 0, 2, 2, Qt::AlignBottom );
-    controlLayout->setColumnMinimumWidth( 2, 10 );
-    controlLayout->setColumnStretch( 2, 0 );
+    QString line1 = getSettings()->value( "MainWindow/Controls2",
+            "18;19;25" ).toString();
+    parseAndCreateLine( line1, 0 );
 
-    controlLayout->addWidget( createWidget( PREVIOUS_BUTTON ), 3, 3, Qt::AlignBottom );
-    controlLayout->addWidget( createWidget( STOP_BUTTON ), 3, 4, Qt::AlignBottom  );
-    controlLayout->addWidget( createWidget( NEXT_BUTTON ), 3, 5, Qt::AlignBottom  );
+/*    QString line2 = QString( "%1-2;%2;%3;%4;%5;%6;%6;%7;%8;%9;%6;%10;%11-4")
+        .arg( PLAY_BUTTON )         .arg( WIDGET_SPACER )
+        .arg( PREVIOUS_BUTTON )         .arg( STOP_BUTTON )
+        .arg( NEXT_BUTTON )        .arg( WIDGET_SPACER )
+        .arg( FULLSCREEN_BUTTON )        .arg( PLAYLIST_BUTTON )
+        .arg( EXTENDED_BUTTON )        .arg( WIDGET_SPACER_EXTEND )
+        .arg( VOLUME ); */
 
-    /* Column 6 is unused */
-    controlLayout->setColumnStretch( 6, 0 );
-    controlLayout->setColumnStretch( 7, 0 );
-    controlLayout->setColumnMinimumWidth( 7, 10 );
+    QString line2 = getSettings()->value( "MainWindow/Controls2",
+            "0-2;21;21;4;2;5;21;21;8;11;10;21;22;20-4" ).toString();
+    parseAndCreateLine( line2, 1 );
 
-    controlLayout->addWidget( createWidget( FULLSCREEN_BUTTON ), 3, 8, Qt::AlignBottom );
-    controlLayout->addWidget( createWidget( PLAYLIST_BUTTON ), 3, 9, Qt::AlignBottom );
-    controlLayout->addWidget( createWidget( EXTENDED_BUTTON ), 3, 10, Qt::AlignBottom );
-    controlLayout->setColumnStretch( 11, 0 ); /* telex alignment */
-
-    controlLayout->setColumnStretch( 12, 0 );
-    controlLayout->setColumnMinimumWidth( 12, 10 );
-
-    controlLayout->addWidget( advControls, 3, 13, 1, 3, Qt::AlignBottom );
-
-    controlLayout->setColumnStretch( 16, 10 );
-    controlLayout->setColumnMinimumWidth( 16, 10 );
-
-    controlLayout->addWidget( createWidget( VOLUME, false, false, true ),
-            3, 17, 1, 3, Qt::AlignBottom );
+    if( !b_advancedVisible && advControls ) advControls->hide();
 }
 
 ControlsWidget::~ControlsWidget()
@@ -724,7 +816,9 @@ ControlsWidget::~ControlsWidget()
 
 void ControlsWidget::toggleAdvanced()
 {
-    if( advControls && !b_advancedVisible )
+    if( !advControls ) return;
+
+    if( !b_advancedVisible )
     {
         advControls->show();
         b_advancedVisible = true;
@@ -743,15 +837,30 @@ AdvControlsWidget::AdvControlsWidget( intf_thread_t *_p_i ) :
     controlLayout->setMargin( 0 );
     controlLayout->setSpacing( 0 );
 
-    controlLayout->addWidget( createWidget( RECORD_BUTTON ), 0, 0 );
-    controlLayout->addWidget( createWidget( SNAPSHOT_BUTTON ), 0, 1 );
-    controlLayout->addWidget( createWidget( ATOB_BUTTON ), 0, 2 );
-}
+    /* QString line = QString( "%1;%2;%3").arg( RECORD_BUTTON )
+        .arg( SNAPSHOT_BUTTON )
+        .arg( ATOB_BUTTON )
+        .arg( FRAME_BUTTON ); */
 
-AdvControlsWidget::~AdvControlsWidget()
-{}
+    QString line = getSettings()->value( "MainWindow/AdvControl",
+            "12;13;14;15" ).toString();
+    parseAndCreateLine( line, 0 );
+}
 
+InputControlsWidget::InputControlsWidget( intf_thread_t *_p_i ) :
+                                     AbstractController( _p_i )
+{
+    controlLayout->setMargin( 0 );
+    controlLayout->setSpacing( 0 );
 
+    /*    QString line = QString( "%1-%2;%3;%4-%2")
+        .arg( SLOWER_BUTTON ).arg( WIDGET_FLAT )
+        .arg( INPUT_SLIDER )
+        .arg( FASTER_BUTTON ); */
+    QString line = getSettings()->value( "MainWindow/InputControl",
+                   "6-1;16;7-1" ).toString();
+    parseAndCreateLine( line, 0 );
+}
 /**********************************************************************
  * Fullscrenn control widget
  **********************************************************************/
@@ -782,30 +891,26 @@ FullscreenControllerWidget::FullscreenControllerWidget( intf_thread_t *_p_i )
     controlLayout->setLayoutMargins( 5, 2, 5, 2, 5 );
 
     /* First line */
-    controlLayout->addWidget( createWidget( SLOWER_BUTTON, true ), 0, 0 );
-    controlLayout->addWidget( createWidget( INPUT_SLIDER ), 0, 1, 1, 13 );
-    controlLayout->addWidget( createWidget( FASTER_BUTTON, true ), 0, 14 );
+    InputControlsWidget *inputC = new InputControlsWidget( p_intf );
+    controlLayout->addWidget( inputC, 0, 0, 1, -1 );
 
     /* Second line */
-    controlLayout->addWidget( createWidget( PLAY_BUTTON, false, true ), 1, 0, 1, 2 );
-    controlLayout->addWidget( createWidget( PREVIOUS_BUTTON ), 1, 2 );
-    controlLayout->addWidget( createWidget( STOP_BUTTON ), 1, 3 );
-    controlLayout->addWidget( createWidget( NEXT_BUTTON ), 1, 4 );
-
-    controlLayout->addWidget( createWidget( MENU_BUTTONS ), 1, 5 );
-    controlLayout->addWidget( createWidget( TELETEXT_BUTTONS ), 1, 6 );
-    QToolButton *fullscreenButton =
-         qobject_cast<QToolButton *>(createWidget( FULLSCREEN_BUTTON ) );
-    fullscreenButton->setIcon( QIcon( ":/defullscreen" ) );
-    controlLayout->addWidget( fullscreenButton, 1, 7 );
-
-    controlLayout->setColumnStretch( 9, 10 );
-
-    TimeLabel *timeLabel = new TimeLabel( p_intf );
-
-    controlLayout->addWidget( timeLabel, 1, 10 );
-    controlLayout->addWidget( createWidget( VOLUME, false, false, true ),
-            1, 11, 1, 3 );
+    /* QString line2 = QString( "%1-2;%2;%3;%4;%5;%2;%6;%2;%7;%2;%8;%9;%10-4")
+        .arg( PLAY_BUTTON )
+        .arg( WIDGET_SPACER )
+        .arg( PREVIOUS_BUTTON )
+        .arg( STOP_BUTTON )
+        .arg( NEXT_BUTTON )
+        .arg( MENU_BUTTONS )
+        .arg( TELETEXT_BUTTONS )
+        .arg( DEFULLSCREEN_BUTTON )
+        .arg( WIDGET_SPACER_EXTEND )
+        .arg( TIME_LABEL )
+        .arg( VOLUME ); */
+
+    QString line = getSettings()->value( "MainWindow/FSCline",
+            "0-2;21;4;2;5;21;18;21;19;21;9;22;23-4" ).toString();
+    parseAndCreateLine( line, 1 );
 
     /* hiding timer */
     p_hideTimer = new QTimer( this );
@@ -832,9 +937,7 @@ FullscreenControllerWidget::FullscreenControllerWidget( intf_thread_t *_p_i )
 
 FullscreenControllerWidget::~FullscreenControllerWidget()
 {
-    getSettings()->beginGroup( "FullScreen" );
-    getSettings()->setValue( "pos", pos() );
-    getSettings()->endGroup();
+    getSettings()->setValue( "FullScreen/pos", pos() );
     detachVout();
     vlc_mutex_destroy( &lock );
 }
index e5cec3c..68be2e5 100644 (file)
@@ -66,19 +66,23 @@ typedef enum buttonType_e
     SLOWER_BUTTON,
     FASTER_BUTTON,
     FULLSCREEN_BUTTON,
+    DEFULLSCREEN_BUTTON,
     EXTENDED_BUTTON,
     PLAYLIST_BUTTON,
     SNAPSHOT_BUTTON,
     RECORD_BUTTON,
     ATOB_BUTTON,
-#if 0
     FRAME_BUTTON,
-#endif
     INPUT_SLIDER,
     VOLUME_SLIDER,
     MENU_BUTTONS,
     TELETEXT_BUTTONS,
     VOLUME,
+    WIDGET_SPACER,
+    WIDGET_SPACER_EXTEND,
+    TIME_LABEL,
+    SPLITTER,
+    ADVANCED_CONTROLLER,
 } buttonType_e;
 
 typedef enum actionType_e
@@ -95,15 +99,24 @@ typedef enum actionType_e
     PLAYLIST_ACTION,
     SNAPSHOT_ACTION,
     RECORD_ACTION,
+    FRAME_ACTION,
     ATOB_ACTION
 } actionType_e;
 
+enum
+{
+   WIDGET_NORMAL = 0x0,
+   WIDGET_FLAT   = 0x1,
+   WIDGET_BIG    = 0x2,
+   WIDGET_SHINY  = 0x4,
+};
+
 class AbstractController : public QFrame
 {
     Q_OBJECT
 public:
     AbstractController( intf_thread_t  *_p_i );
-    virtual ~AbstractController()  {};
+    int getWidth() { return controlLayout->columnCount(); }
 
 protected:
     intf_thread_t       *p_intf;
@@ -111,11 +124,14 @@ protected:
     QSignalMapper       *toolbarActionsMapper;
     QGridLayout         *controlLayout;
 
-    QWidget *createWidget( buttonType_e, bool b_flat = false,
-                           bool b_big = false, bool b_shiny = false );
-    void setupButton( QAbstractButton * );
+    AdvControlsWidget   *advControls;
+
+    void parseAndCreateLine( QString config, int i_line );
 
 private:
+    QWidget *createWidget( buttonType_e, int *i_size,
+                           int options = WIDGET_NORMAL );
+    void setupButton( QAbstractButton * );
     QWidget *discFrame();
     QWidget *telexFrame();
 
@@ -134,9 +150,7 @@ protected slots:
     void playlist();
     void snapshot();
     void record();
-#if 0
     void frame();
-#endif
 
     virtual void setStatus( int );
 
@@ -146,6 +160,14 @@ signals:
     void inputIsRecordable( bool ); /// same ?
 };
 
+/**
+ * SPECIAL Widgets that are a bit more than just a ToolButton
+ * and have an icon/behaviour that changes depending on the context:
+ * - playButton
+ * - A->B Button
+ * - Teletext group buttons
+ * - Sound Widget group
+ **/
 class PlayButton : public QToolButton
 {
     Q_OBJECT
@@ -199,7 +221,14 @@ class AdvControlsWidget : public AbstractController
     Q_OBJECT
 public:
     AdvControlsWidget( intf_thread_t * );
-    virtual ~AdvControlsWidget();
+};
+
+/* Slider Bar */
+class InputControlsWidget : public AbstractController
+{
+    Q_OBJECT
+public:
+    InputControlsWidget( intf_thread_t * );
 };
 
 /* Button Bar */
@@ -214,7 +243,6 @@ public:
 protected:
     friend class MainInterface;
 
-    AdvControlsWidget   *advControls;
     bool                 b_advancedVisible;
 
 protected slots:
index 4665e5d..32e660e 100644 (file)
@@ -152,8 +152,7 @@ MainInterface::MainInterface( intf_thread_t *_p_intf ) : QVLCMW( _p_intf )
      **************************/
     /* Connect the input manager to the GUI elements it manages */
 
-    /* It is also connected to the control->slider, see the ControlsWidget */
-    /* Change the SpeedRate in the Status */
+    /* Change the SpeedRate in the Status Bar */
     CONNECT( THEMIM->getIM(), rateChanged( int ), this, setRate( int ) );
 
     /**
@@ -379,9 +378,11 @@ void MainInterface::handleMainUi( QSettings *settings )
                    settings->value( "adv-controls", false ).toBool() );
     CONNECT( controls, advancedControlsToggled( bool ),
              this, doComponentsUpdate() );
+    InputControlsWidget *inputC = new InputControlsWidget( p_intf );
 
     /* Add the controls Widget to the main Widget */
     mainLayout->insertWidget( 0, controls, 0, Qt::AlignBottom );
+    mainLayout->insertWidget( 0, inputC, 0, Qt::AlignBottom );
 
     /* Create the Speed Control Widget */
     speedControl = new SpeedControlWidget( p_intf );