Extensions/Qt: information panel for Extensions
[vlc.git] / modules / gui / qt4 / dialogs / plugins.cpp
index 40bb9bc..017be5e 100644 (file)
@@ -1,10 +1,11 @@
 /*****************************************************************************
  * plugins.hpp : Plug-ins and extensions listing
  ****************************************************************************
- * Copyright (C) 2008 the VideoLAN team
+ * Copyright (C) 2008-2010 the VideoLAN team
  * $Id$
  *
  * Authors: Jean-Baptiste Kempf <jb (at) videolan.org>
+ *          Jean-Philippe AndrĂ© <jpeg (at) videolan.org>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
 #include "plugins.hpp"
 
 #include "util/customwidgets.hpp"
+#include "extensions_manager.hpp"
 
 //#include <vlc_modules.h>
 
 #include <QTreeWidget>
 #include <QStringList>
+#include <QTabWidget>
 #include <QHeaderView>
 #include <QDialogButtonBox>
 #include <QLineEdit>
 #include <QLabel>
+#include <QVBoxLayout>
+#include <QComboBox>
+#include <QTextBrowser>
+#include <QHBoxLayout>
+#include <QSpacerItem>
 
 PluginDialog::PluginDialog( intf_thread_t *_p_intf ) : QVLCFrame( _p_intf )
 {
     setWindowTitle( qtr( "Plugins and extensions" ) );
     setWindowRole( "vlc-plugins" );
+
+    QVBoxLayout *layout = new QVBoxLayout( this );
+    tabs = new QTabWidget( this );
+    tabs->addTab( extensionTab = new ExtensionTab( p_intf ),
+                  qtr( "Extensions" ) );
+    tabs->addTab( pluginTab = new PluginTab( p_intf ),
+                  qtr( "Plugins" ) );
+    layout->addWidget( tabs );
+
+    QDialogButtonBox *box = new QDialogButtonBox;
+    QPushButton *okButton = new QPushButton( qtr( "&Close" ), this );
+    box->addButton( okButton, QDialogButtonBox::AcceptRole );
+    layout->addWidget( box );
+    BUTTONACT( okButton, close() );
+}
+
+PluginDialog::~PluginDialog()
+{
+}
+
+/* Plugins tab */
+
+PluginTab::PluginTab( intf_thread_t *p_intf )
+        : QVLCFrame( p_intf )
+{
     QGridLayout *layout = new QGridLayout( this );
 
     /* Main Tree for modules */
@@ -74,22 +107,15 @@ PluginDialog::PluginDialog( intf_thread_t *_p_intf ) : QVLCFrame( _p_intf )
     label->setBuddy( edit );
 
     layout->addWidget( label, 1, 0 );
-    layout->addWidget( edit, 1, 1, 1, -1 );
+    layout->addWidget( edit, 1, 1, 1, 1 );
     CONNECT( edit, textChanged( const QString& ),
             this, search( const QString& ) );
 
-    QDialogButtonBox *box = new QDialogButtonBox;
-    QPushButton *okButton = new QPushButton( qtr( "&Close" ), this );
-    box->addButton( okButton, QDialogButtonBox::AcceptRole );
-    layout->addWidget( box, 2, 2 );
-
-    BUTTONACT( okButton, close() );
-
     setMinimumSize( 500, 300 );
     readSettings( "Plugins", QSize( 540, 400 ) );
 }
 
-inline void PluginDialog::FillTree()
+inline void PluginTab::FillTree()
 {
     module_t **p_list = module_list_get( NULL );
     module_t *p_module;
@@ -109,7 +135,7 @@ inline void PluginDialog::FillTree()
     }
 }
 
-void PluginDialog::search( const QString& qs )
+void PluginTab::search( const QString& qs )
 {
     QList<QTreeWidgetItem *> items = treePlugins->findItems( qs, Qt::MatchContains );
     items += treePlugins->findItems( qs, Qt::MatchContains, 1 );
@@ -122,7 +148,7 @@ void PluginDialog::search( const QString& qs )
     }
 }
 
-PluginDialog::~PluginDialog()
+PluginTab::~PluginTab()
 {
     writeSettings( "Plugins" );
     getSettings()->setValue( "Plugins/Header-State",
@@ -136,3 +162,158 @@ bool PluginTreeItem::operator< ( const QTreeWidgetItem & other ) const
         return text( col ).toInt() < other.text( col ).toInt();
     return text( col ) < other.text( col );
 }
+
+/* Extensions tab */
+ExtensionTab::ExtensionTab( intf_thread_t *p_intf )
+        : QVLCFrame( p_intf )
+{
+    // Layout
+    QGridLayout *layout = new QGridLayout( this );
+
+    // Top: combo
+    extList = new QComboBox( this );
+    layout->addWidget( extList, 0, 0, 1, -1 );
+
+    // Center: Description
+    layout->addWidget( new QLabel( "<b>" + qtr( "Version" ) + "</b>" ),
+                       1, 0, 1, 1 );
+    layout->addWidget( new QLabel( "<b>" + qtr( "Author" ) + "</b>" ),
+                       2, 0, 1, 1 );
+    layout->addWidget( new QLabel( "<b>" + qtr( "Description" ) + "</b>" ),
+                       3, 0, 1, 1 );
+    layout->addWidget( new QLabel( "<b>" + qtr( "Website" ) + "</b>" ),
+                       6, 0, 1, 1 );
+    layout->addWidget( new QLabel( "<b>" + qtr( "File" ) + "</b>" ),
+                       7, 0, 1, 1 );
+
+    version = new QLabel( this );
+    layout->addWidget( version, 1, 1, 1, 1 );
+    author = new QLabel( this );
+    layout->addWidget( author, 2, 1, 1, 1 );
+    description = new QTextBrowser( this );
+    description->setOpenExternalLinks( true );
+    layout->addWidget( description, 4, 0, 1, -1 );
+    url = new QLabel( this );
+    url->setOpenExternalLinks( true );
+    url->setTextFormat( Qt::RichText );
+    layout->addWidget( url, 6, 1, 1, 1 );
+    name = new QLineEdit( this );
+    name->setReadOnly( true );
+    layout->addWidget( name, 7, 1, 1, 1 );
+
+    // Bottom: Configuration tools
+    QHBoxLayout *hbox = new QHBoxLayout;
+    QPushButton *reload = new QPushButton( QIcon( ":/update" ),
+                                           qtr( "Reload extensions" ),
+                                           this );
+    QSpacerItem *spacer = new QSpacerItem( 1, 1, QSizePolicy::Expanding,
+                                           QSizePolicy::Expanding );
+    hbox->addItem( spacer );
+    hbox->addWidget( reload );
+    BUTTONACT( reload, reloadExtensions() );
+    layout->addItem( hbox, 8, 0, 1, -1 );
+
+    // Layout: compact display
+    layout->setHorizontalSpacing( 15 );
+
+    fillList();
+
+    CONNECT( extList, currentIndexChanged( int ),
+             this, selectionChanged( int ) );
+    extList->setCurrentIndex( 0 );
+    selectionChanged( 0 );
+
+    // Connect to ExtensionsManager::extensionsUpdated()
+    ExtensionsManager* EM = ExtensionsManager::getInstance( p_intf );
+    CONNECT( EM, extensionsUpdated(), this, fillList() );
+}
+
+ExtensionTab::~ExtensionTab()
+{
+}
+
+void ExtensionTab::fillList()
+{
+    ExtensionsManager* EM = ExtensionsManager::getInstance( p_intf );
+    if( !EM->isLoaded() )
+        EM->loadExtensions();
+    extensions_manager_t* p_mgr = EM->getManager();
+    if( !p_mgr )
+        return;
+
+    // Disconnect signal: we don't want to call selectionChanged now
+    disconnect( extList, SIGNAL( currentIndexChanged( int ) ),
+                this, SLOT( selectionChanged( int ) ) );
+
+    extList->clear();
+
+    vlc_mutex_lock( &p_mgr->lock );
+
+    extension_t *p_ext;
+    FOREACH_ARRAY( p_ext, p_mgr->extensions )
+    {
+        extList->addItem( p_ext->psz_title, QString( p_ext->psz_name ) );
+    }
+    FOREACH_END()
+
+    vlc_mutex_unlock( &p_mgr->lock );
+    vlc_object_release( p_mgr );
+
+    // Reconnect signal and update screen
+    connect( extList, SIGNAL( currentIndexChanged( int ) ),
+             this, SLOT( selectionChanged( int ) ) );
+    extList->setCurrentIndex( 0 );
+    selectionChanged( 0 );
+}
+
+void ExtensionTab::selectionChanged( int index )
+{
+    QString extName = extList->itemData( index ).toString();
+    if( extName.isEmpty() )
+        return;
+
+    ExtensionsManager* EM = ExtensionsManager::getInstance( p_intf );
+    extensions_manager_t* p_mgr = EM->getManager();
+    if( !p_mgr )
+        return;
+
+    vlc_mutex_lock( &p_mgr->lock );
+
+    const char *psz_name = qtu( extName );
+
+    extension_t *p_ext;
+    FOREACH_ARRAY( p_ext, p_mgr->extensions )
+    {
+        if( !strcmp( p_ext->psz_name, psz_name ) )
+        {
+            char *psz_url;
+            if( p_ext->psz_url != NULL
+                && asprintf( &psz_url, "<a href=\"%s\">%s</a>", p_ext->psz_url,
+                             p_ext->psz_url ) != -1 )
+            {
+                url->setText( psz_url );
+                free( psz_url );
+            }
+            else
+            {
+                url->clear();
+            }
+            version->setText( qfu( p_ext->psz_version ) );
+            description->setHtml( qfu( p_ext->psz_description ) );
+            author->setText( qfu( p_ext->psz_author ) );
+            name->setText( qfu( p_ext->psz_name ) );
+            break;
+        }
+    }
+    FOREACH_END()
+
+    vlc_mutex_unlock( &p_mgr->lock );
+    vlc_object_release( p_mgr );
+}
+
+void ExtensionTab::reloadExtensions()
+{
+    ExtensionsManager* EM = ExtensionsManager::getInstance( p_intf );
+    EM->reloadExtensions();
+    fillList();
+}