]> git.sesse.net Git - vlc/blob - modules/gui/qt4/components/open_panels.cpp
Qt: PLSelector: Make effectless root entries not selectable
[vlc] / modules / gui / qt4 / components / open_panels.cpp
1 /*****************************************************************************
2  * open_panels.cpp : Panels for the open dialogs
3  ****************************************************************************
4  * Copyright (C) 2006-2009 the VideoLAN team
5  * Copyright (C) 2007 Société des arts technologiques
6  * Copyright (C) 2007 Savoir-faire Linux
7  *
8  * $Id$
9  *
10  * Authors: Clément Stenac <zorglub@videolan.org>
11  *          Jean-Baptiste Kempf <jb@videolan.org>
12  *          Pierre-Luc Beaudoin <pierre-luc.beaudoin@savoirfairelinux.com>
13  *
14  * This program is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License as published by
16  * the Free Software Foundation; either version 2 of the License, or
17  * (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the Free Software
26  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
27  *****************************************************************************/
28
29 #ifdef HAVE_CONFIG_H
30 # include "config.h"
31 #endif
32
33 #include "qt4.hpp"
34 #include "components/open_panels.hpp"
35 #include "dialogs/open.hpp"
36 #include "dialogs_provider.hpp" /* Open Subtitle file */
37 #include "util/qt_dirs.hpp"
38 #include <vlc_intf_strings.h>
39 #include <vlc_modules.h>
40 #include <vlc_plugin.h>
41 #ifdef WIN32
42   #include <vlc_charset.h> /* FromWide for Win32 */
43 #endif
44
45 #include <QFileDialog>
46 #include <QDialogButtonBox>
47 #include <QLineEdit>
48 #include <QStackedLayout>
49 #include <QCompleter>
50 #include <QDirModel>
51 #include <QScrollArea>
52 #include <QUrl>
53 #include <QDropEvent>
54
55 #define I_DEVICE_TOOLTIP \
56     I_DIR_OR_FOLDER( N_("Select a device or a VIDEO_TS directory"), \
57                      N_("Select a device or a VIDEO_TS folder") )
58
59 #include "../../eject.c"
60
61 /* Populate a combobox with the devices matching a pattern.
62    Combobox will automatically do autocompletion on the edit zone */
63 #define POPULATE_WITH_DEVS(ppsz_devlist, targetCombo) \
64     QStringList targetCombo ## StringList = QStringList(); \
65     for ( size_t i = 0; i< sizeof(ppsz_devlist) / sizeof(*ppsz_devlist); i++ ) \
66         targetCombo ## StringList << QString( ppsz_devlist[ i ] ); \
67     targetCombo->addItems( QDir( "/dev/" )\
68         .entryList( targetCombo ## StringList, QDir::System )\
69         .replaceInStrings( QRegExp("^"), "/dev/" ) \
70     );
71
72 static const char psz_devModule[][8] = { "v4l2", "pvr", "dtv",
73                                        "dshow", "screen", "jack" };
74
75 /**************************************************************************
76  * Open Files and subtitles                                               *
77  **************************************************************************/
78 FileOpenPanel::FileOpenPanel( QWidget *_parent, intf_thread_t *_p_intf ) :
79                                 OpenPanel( _parent, _p_intf ), dialogBox( NULL )
80 {
81     /* Classic UI Setup */
82     ui.setupUi( this );
83
84     setAcceptDrops( true );
85
86     /* Set Filters for file selection */
87 /*    QString fileTypes = "";
88     ADD_FILTER_MEDIA( fileTypes );
89     ADD_FILTER_VIDEO( fileTypes );
90     ADD_FILTER_AUDIO( fileTypes );
91     ADD_FILTER_PLAYLIST( fileTypes );
92     ADD_FILTER_ALL( fileTypes );
93     fileTypes.replace( QString(";*"), QString(" *")); */
94
95
96 /*    lineFileEdit = ui.fileEdit;
97     //TODO later: fill the fileCompleteList with previous items played.
98     QCompleter *fileCompleter = new QCompleter( fileCompleteList, this );
99     fileCompleter->setModel( new QDirModel( fileCompleter ) );
100     lineFileEdit->setCompleter( fileCompleter );*/
101     if( var_InheritBool( p_intf, "qt-embedded-open" ) )
102     {
103         ui.tempWidget->hide();
104         BuildOldPanel();
105     }
106
107     /* Subtitles */
108     /* Deactivate the subtitles control by default. */
109     ui.subFrame->setEnabled( false );
110
111     /* Connects  */
112     BUTTONACT( ui.fileBrowseButton, browseFile() );
113     BUTTONACT( ui.removeFileButton, removeFile() );
114
115     BUTTONACT( ui.subBrowseButton, browseFileSub() );
116     CONNECT( ui.subCheckBox, toggled( bool ), this, toggleSubtitleFrame( bool ) );
117
118     CONNECT( ui.fileListWidg, itemChanged( QListWidgetItem * ), this, updateMRL() );
119     CONNECT( ui.subInput, textChanged( const QString& ), this, updateMRL() );
120     updateButtons();
121 }
122
123 inline void FileOpenPanel::BuildOldPanel()
124 {
125     /** BEGIN QFileDialog tweaking **/
126     /* Use a QFileDialog and customize it because we don't want to
127        rewrite it all. Be careful to your eyes cause there are a few hacks.
128        Be very careful and test correctly when you modify this. */
129
130     /* Make this QFileDialog a child of tempWidget from the ui. */
131     dialogBox = new FileOpenBox( ui.tempWidget, NULL,
132                                  p_intf->p_sys->filepath, "" );
133
134     dialogBox->setFileMode( QFileDialog::ExistingFiles );
135     dialogBox->setAcceptMode( QFileDialog::AcceptOpen );
136     dialogBox->restoreState(
137             getSettings()->value( "file-dialog-state" ).toByteArray() );
138
139     /* We don't want to see a grip in the middle of the window, do we? */
140     dialogBox->setSizeGripEnabled( false );
141
142     /* Add a tooltip */
143     dialogBox->setToolTip( qtr( "Select one or multiple files" ) );
144     dialogBox->setMinimumHeight( 250 );
145
146     // But hide the two OK/Cancel buttons. Enable them for debug.
147     QDialogButtonBox *fileDialogAcceptBox =
148                       dialogBox->findChildren<QDialogButtonBox*>()[0];
149     fileDialogAcceptBox->hide();
150
151     /* Ugly hacks to get the good Widget */
152     //This lineEdit is the normal line in the fileDialog.
153     QLineEdit *lineFileEdit = dialogBox->findChildren<QLineEdit*>()[0];
154     /* Make a list of QLabel inside the QFileDialog to access the good ones */
155     QList<QLabel *> listLabel = dialogBox->findChildren<QLabel*>();
156
157     /* Hide the FileNames one. Enable it for debug */
158     listLabel[1]->setText( qtr( "File names:" ) );
159     /* Change the text that was uncool in the usual box */
160     listLabel[2]->setText( qtr( "Filter:" ) );
161
162     dialogBox->layout()->setMargin( 0 );
163     dialogBox->layout()->setSizeConstraint( QLayout::SetNoConstraint );
164
165     /** END of QFileDialog tweaking **/
166
167     // Add the DialogBox to the layout
168     ui.gridLayout->addWidget( dialogBox, 0, 0, 1, 3 );
169
170     CONNECT( lineFileEdit, textChanged( const QString& ), this, updateMRL() );
171     dialogBox->installEventFilter( this );
172 }
173
174 FileOpenPanel::~FileOpenPanel()
175 {
176     if( dialogBox )
177         getSettings()->setValue( "file-dialog-state", dialogBox->saveState() );
178 }
179
180 void FileOpenPanel::dragEnterEvent( QDragEnterEvent *event )
181 {
182     event->acceptProposedAction();
183 }
184
185 void FileOpenPanel::dragMoveEvent( QDragMoveEvent *event )
186 {
187     event->acceptProposedAction();
188 }
189
190 void FileOpenPanel::dragLeaveEvent( QDragLeaveEvent *event )
191 {
192     event->accept();
193 }
194
195 void FileOpenPanel::dropEvent( QDropEvent *event )
196 {
197     if( event->possibleActions() & Qt::CopyAction )
198        event->setDropAction( Qt::CopyAction );
199     else
200         return;
201
202     const QMimeData *mimeData = event->mimeData();
203     foreach( const QUrl &url, mimeData->urls() )
204     {
205         if( url.isValid() )
206         {
207             QListWidgetItem *item = new QListWidgetItem(
208                                          toNativeSeparators( url.toLocalFile() ),
209                                          ui.fileListWidg );
210             item->setFlags( Qt::ItemIsEditable | Qt::ItemIsEnabled );
211             ui.fileListWidg->addItem( item );
212         }
213     }
214     updateMRL();
215     updateButtons();
216     event->accept();
217 }
218
219 void FileOpenPanel::browseFile()
220 {
221     QStringList files = QFileDialog::getOpenFileNames( this, qtr( "Select one or multiple files" ), p_intf->p_sys->filepath) ;
222     foreach( const QString &file, files )
223     {
224         QListWidgetItem *item =
225             new QListWidgetItem( toNativeSeparators( file ), ui.fileListWidg );
226         item->setFlags( Qt::ItemIsEditable | Qt::ItemIsEnabled );
227         ui.fileListWidg->addItem( item );
228         savedirpathFromFile( file );
229     }
230     updateButtons();
231     updateMRL();
232 }
233
234 void FileOpenPanel::removeFile()
235 {
236     int i = ui.fileListWidg->currentRow();
237     if( i != -1 )
238     {
239         QListWidgetItem *temp = ui.fileListWidg->takeItem( i );
240         delete temp;
241     }
242
243     updateMRL();
244     updateButtons();
245 }
246
247 /* Show a fileBrowser to select a subtitle */
248 void FileOpenPanel::browseFileSub()
249 {
250     // TODO Handle selection of more than one subtitles file
251     QStringList files = THEDP->showSimpleOpen( qtr("Open subtitles file"),
252                            EXT_FILTER_SUBTITLE, p_intf->p_sys->filepath );
253
254     if( files.isEmpty() ) return;
255     ui.subInput->setText( toNativeSeparators( files.join(" ") ) );
256     updateMRL();
257 }
258
259 void FileOpenPanel::toggleSubtitleFrame( bool b )
260 {
261     ui.subFrame->setEnabled( b );
262
263     /* Update the MRL */
264     updateMRL();
265 }
266
267
268 /* Update the current MRL */
269 void FileOpenPanel::updateMRL()
270 {
271     QStringList fileList;
272     QString mrl;
273
274     /* File Listing */
275     if( dialogBox == NULL )
276         for( int i = 0; i < ui.fileListWidg->count(); i++ )
277         {
278             if( !ui.fileListWidg->item( i )->text().isEmpty() )
279                 fileList << toURI(ui.fileListWidg->item( i )->text());
280         }
281     else
282     {
283         fileList = dialogBox->selectedFiles();
284         for( int i = 0; i < fileList.count(); i++ )
285             fileList[i] = toURI( fileList[i] );
286     }
287
288     /* Options */
289     if( ui.subCheckBox->isChecked() &&  !ui.subInput->text().isEmpty() ) {
290         mrl.append( " :sub-file=" + colon_escape( ui.subInput->text() ) );
291     }
292
293     emit methodChanged( "file-caching" );
294     emit mrlUpdated( fileList, mrl );
295 }
296
297 /* Function called by Open Dialog when clicke on Play/Enqueue */
298 void FileOpenPanel::accept()
299 {
300     if( dialogBox )
301         p_intf->p_sys->filepath = dialogBox->directory().absolutePath();
302     ui.fileListWidg->clear();
303 }
304
305 /* Function called by Open Dialog when clicked on cancel */
306 void FileOpenPanel::clear()
307 {
308     ui.fileListWidg->clear();
309     ui.subInput->clear();
310 }
311
312 /* Update buttons depending on current selection */
313 void FileOpenPanel::updateButtons()
314 {
315     bool b_has_files = ( ui.fileListWidg->count() > 0 );
316     ui.removeFileButton->setEnabled( b_has_files );
317     ui.subCheckBox->setEnabled( b_has_files );
318 }
319
320 /**************************************************************************
321  * Open Discs ( DVD, CD, VCD and similar devices )                        *
322  **************************************************************************/
323 DiscOpenPanel::DiscOpenPanel( QWidget *_parent, intf_thread_t *_p_intf ) :
324                                 OpenPanel( _parent, _p_intf )
325 {
326     ui.setupUi( this );
327
328     /* Get the default configuration path for the devices */
329     psz_dvddiscpath = var_InheritString( p_intf, "dvd" );
330     psz_vcddiscpath = var_InheritString( p_intf, "vcd" );
331     psz_cddadiscpath = var_InheritString( p_intf, "cd-audio" );
332
333     /* State to avoid overwritting the users changes with the configuration */
334     m_discType = None;
335
336     ui.browseDiscButton->setToolTip( qtr( I_DEVICE_TOOLTIP ));
337     ui.deviceCombo->setToolTip( qtr(I_DEVICE_TOOLTIP) );
338     ui.deviceCombo->setInsertPolicy( QComboBox::InsertAtTop );
339
340 #ifndef WIN32
341     char const * const ppsz_discdevices[] = {
342         "sr*",
343         "sg*",
344         "scd*",
345         "dvd*",
346         "cd*"
347     };
348     QComboBox *discCombo = ui.deviceCombo; /* avoid namespacing in macro */
349     POPULATE_WITH_DEVS( ppsz_discdevices, discCombo );
350 #endif
351
352     /* CONNECTs */
353     BUTTONACT( ui.dvdRadioButton,     updateButtons() );
354     BUTTONACT( ui.bdRadioButton,      updateButtons() );
355     BUTTONACT( ui.vcdRadioButton,     updateButtons() );
356     BUTTONACT( ui.audioCDRadioButton, updateButtons() );
357     BUTTONACT( ui.dvdsimple,          updateButtons() );
358     BUTTONACT( ui.browseDiscButton, browseDevice() );
359     BUTTON_SET_ACT_I( ui.ejectButton, "", toolbar/eject, qtr( "Eject the disc" ),
360             eject() );
361
362     CONNECT( ui.deviceCombo, editTextChanged( QString ), this, updateMRL());
363     CONNECT( ui.deviceCombo, currentIndexChanged( QString ), this, updateMRL());
364     CONNECT( ui.titleSpin, valueChanged( int ), this, updateMRL());
365     CONNECT( ui.chapterSpin, valueChanged( int ), this, updateMRL());
366     CONNECT( ui.audioSpin, valueChanged( int ), this, updateMRL());
367     CONNECT( ui.subtitlesSpin, valueChanged( int ), this, updateMRL());
368
369     /* Run once the updateButtons function in order to fill correctly the comboBoxes */
370     updateButtons();
371 }
372
373 #ifdef WIN32 /* Disc drives probing for Windows */
374 void DiscOpenPanel::onFocus()
375 {
376     ui.deviceCombo->clear();
377     wchar_t szDrives[512];
378     szDrives[0] = '\0';
379     if( GetLogicalDriveStringsW( sizeof( szDrives ) - 1, szDrives ) )
380     {
381         wchar_t *drive = szDrives;
382         UINT oldMode = SetErrorMode( SEM_FAILCRITICALERRORS );
383         while( *drive )
384         {
385             if( GetDriveTypeW(drive) == DRIVE_CDROM )
386             {
387                 wchar_t psz_name[512] = L"";
388                 GetVolumeInformationW( drive, psz_name, 511, NULL, NULL, NULL, NULL, 0 );
389
390                 QString displayName = FromWide( drive );
391                 char *psz_title = FromWide( psz_name );
392                 if( !EMPTY_STR(psz_title)) {
393                     displayName = displayName + " - "  + psz_title;
394                 }
395
396                 ui.deviceCombo->addItem( displayName, FromWide( drive ) );
397                 free( psz_title );
398             }
399
400             /* go to next drive */
401             while( *(drive++) );
402         }
403         SetErrorMode(oldMode);
404     }
405 }
406 #endif
407
408 DiscOpenPanel::~DiscOpenPanel()
409 {
410     free( psz_dvddiscpath );
411     free( psz_vcddiscpath );
412     free( psz_cddadiscpath );
413 }
414
415 void DiscOpenPanel::clear()
416 {
417     ui.titleSpin->setValue( 0 );
418     ui.chapterSpin->setValue( 0 );
419     ui.subtitlesSpin->setValue( -1 );
420     ui.audioSpin->setValue( -1 );
421     m_discType = None;
422 }
423
424 #ifdef WIN32
425     #define setDrive( psz_name ) {\
426     int index = ui.deviceCombo->findText( qfu( psz_name ) ); \
427     if( index != -1 ) ui.deviceCombo->setCurrentIndex( index );}
428 #else
429     #define setDrive( psz_name ) {\
430     ui.deviceCombo->setEditText( qfu( psz_name ) ); }
431 #endif
432
433 /* update the buttons according the type of device */
434 void DiscOpenPanel::updateButtons()
435 {
436     if ( ui.dvdRadioButton->isChecked() )
437     {
438         if( m_discType != Dvd )
439         {
440             setDrive( psz_dvddiscpath );
441             m_discType = Dvd;
442         }
443         ui.titleLabel->setText( qtr("Title") );
444         ui.chapterLabel->show();
445         ui.chapterSpin->show();
446         ui.diskOptionBox_2->show();
447         ui.dvdsimple->setEnabled( true );
448     }
449     else if ( ui.bdRadioButton->isChecked() )
450     {
451         if( m_discType != BRD )
452         {
453             setDrive( psz_dvddiscpath );
454             m_discType = BRD;
455             ui.dvdsimple->setChecked( !var_InheritBool( p_intf, "bluray-menu" ) );
456         }
457         ui.titleLabel->setText( qtr("Title") );
458         ui.chapterLabel->hide();
459         ui.chapterSpin->hide();
460         ui.diskOptionBox_2->hide();
461         ui.dvdsimple->setEnabled( true );
462     }
463     else if ( ui.vcdRadioButton->isChecked() )
464     {
465         if( m_discType != Vcd )
466         {
467             setDrive( psz_vcddiscpath );
468             m_discType = Vcd;
469         }
470         ui.titleLabel->setText( qtr("Entry") );
471         ui.chapterLabel->hide();
472         ui.chapterSpin->hide();
473         ui.diskOptionBox_2->show();
474         ui.dvdsimple->setEnabled( false );
475     }
476     else /* CDDA */
477     {
478         if( m_discType != Cdda )
479         {
480             setDrive( psz_cddadiscpath );
481             m_discType = Cdda;
482         }
483         ui.titleLabel->setText( qtr("Track") );
484         ui.chapterLabel->hide();
485         ui.chapterSpin->hide();
486         ui.diskOptionBox_2->hide();
487         ui.dvdsimple->setEnabled( false );
488     }
489
490     updateMRL();
491 }
492
493 #undef setDrive
494
495 /* Update the current MRL */
496 void DiscOpenPanel::updateMRL()
497 {
498     QString discPath;
499     QStringList fileList;
500
501     discPath = ui.deviceCombo->currentText();
502
503     int tmp = ui.deviceCombo->findText( discPath );
504     if( tmp != -1 &&  ui.deviceCombo->itemData( tmp ) != QVariant::Invalid )
505         discPath = ui.deviceCombo->itemData( tmp ).toString();
506
507     /* MRL scheme */
508     const char *scheme;
509     /* DVD */
510     if( ui.dvdRadioButton->isChecked() ) {
511         if( !ui.dvdsimple->isChecked() )
512             scheme = "dvd";
513         else
514             scheme = "dvdsimple";
515     } else if ( ui.bdRadioButton->isChecked() )
516         scheme = "bluray";
517     /* VCD */
518     else if ( ui.vcdRadioButton->isChecked() )
519         scheme = "vcd";
520     /* CDDA */
521     else
522         scheme = "cdda";
523
524     char *mrl = make_URI( qtu(discPath), scheme );
525     if( unlikely(mrl == NULL) )
526         return;
527
528     /* Title/chapter encoded in MRL */
529     QString anchor = "";
530     if( ui.titleSpin->value() > 0 ) {
531         if( ui.dvdRadioButton->isChecked() || ui.bdRadioButton->isChecked() ) {
532             anchor = QString("#%1").arg( ui.titleSpin->value() );
533             if ( ui.chapterSpin->value() > 0 )
534                 anchor += QString(":%1").arg( ui.chapterSpin->value() );
535         }
536         else if ( ui.vcdRadioButton->isChecked() )
537             anchor = QString("#%1").arg( ui.titleSpin->value() );
538     }
539
540     emit methodChanged( "disc-caching" );
541
542     fileList << (qfu(mrl) + anchor);
543     free(mrl);
544
545     QString opts = "";
546
547     /* Input item options */
548     if ( ui.dvdRadioButton->isChecked() || ui.vcdRadioButton->isChecked() )
549     {
550         if ( ui.audioSpin->value() >= 0 )
551             opts += " :audio-track=" +
552                 QString("%1").arg( ui.audioSpin->value() );
553         if ( ui.subtitlesSpin->value() >= 0 )
554             opts += " :sub-track=" +
555                 QString("%1").arg( ui.subtitlesSpin->value() );
556     }
557     else if( ui.audioCDRadioButton->isChecked() )
558     {
559         if( ui.titleSpin->value() > 0 )
560             opts += QString(" :cdda-track=%1").arg( ui.titleSpin->value() );
561     }
562     else if ( ui.bdRadioButton->isChecked() )
563     {
564         if ( ui.dvdsimple->isChecked() == false )
565             opts += " :bluray-menu";
566     }
567     emit mrlUpdated( fileList, opts );
568 }
569
570 void DiscOpenPanel::browseDevice()
571 {
572     QString dir = QFileDialog::getExistingDirectory( this,
573             qtr( I_DEVICE_TOOLTIP ), p_intf->p_sys->filepath );
574     if( !dir.isEmpty() )
575     {
576         ui.deviceCombo->addItem( toNativeSepNoSlash( dir ) );
577         ui.deviceCombo->setCurrentIndex( ui.deviceCombo->findText( toNativeSepNoSlash( dir ) ) );
578     }
579
580     updateMRL();
581 }
582
583 void DiscOpenPanel::eject()
584 {
585     intf_Eject( p_intf, qtu( ui.deviceCombo->currentText() ) );
586 }
587
588 void DiscOpenPanel::accept()
589 {}
590
591 /**************************************************************************
592  * Open Network streams and URL pages                                     *
593  **************************************************************************/
594 NetOpenPanel::NetOpenPanel( QWidget *_parent, intf_thread_t *_p_intf ) :
595                                 OpenPanel( _parent, _p_intf )
596 {
597     ui.setupUi( this );
598     CONNECT( ui.urlComboBox, editTextChanged( const QString& ), this, updateMRL());
599
600     /* */
601     if( var_InheritBool( p_intf, "qt-recentplay" ) )
602     {
603         b_recentList = true;
604         ui.urlComboBox->addItems( getSettings()->value( "OpenDialog/netMRL" ).toStringList() );
605         ui.urlComboBox->setMaxCount( 10 );
606     }
607     else
608         b_recentList = false;
609
610     /* Use a simple validator for URLs */
611     ui.urlComboBox->setValidator( new UrlValidator( this ) );
612     ui.urlComboBox->setFocus();
613 }
614
615 NetOpenPanel::~NetOpenPanel()
616 {
617     if( !b_recentList ) return;
618
619     /* Create the list with the current items */
620     QStringList mrlList;
621     for( int i = 0; i < ui.urlComboBox->count(); i++ )
622         mrlList << ui.urlComboBox->itemText( i );
623
624     if( mrlList.count() > 0 )
625     {
626         /* Clean the list... */
627         mrlList.removeDuplicates();
628         /* ...and save the 8 last entries */
629         getSettings()->setValue( "OpenDialog/netMRL", mrlList );
630     }
631 }
632
633 void NetOpenPanel::clear()
634 {
635     ui.urlComboBox->clear();
636 }
637
638 void NetOpenPanel::onAccept()
639 {
640     if( ui.urlComboBox->findText( ui.urlComboBox->currentText() ) == -1 )
641         ui.urlComboBox->insertItem( 0, ui.urlComboBox->currentText());
642 }
643
644 void NetOpenPanel::onFocus()
645 {
646     ui.urlComboBox->setFocus();
647     ui.urlComboBox->lineEdit()->selectAll();
648 }
649
650 void NetOpenPanel::updateMRL()
651 {
652     QString url = ui.urlComboBox->lineEdit()->text();
653
654     if( url.isEmpty() )
655         return;
656
657     emit methodChanged( qfu( "network-caching" ) );
658
659     QStringList qsl;
660     qsl << url;
661     emit mrlUpdated( qsl, "" );
662 }
663
664 QValidator::State UrlValidator::validate( QString& str, int& ) const
665 {
666     if( str.contains( ' ' ) )
667         return QValidator::Invalid;
668     if( !str.contains( "://" ) )
669         return QValidator::Intermediate;
670     return QValidator::Acceptable;
671 }
672
673 void UrlValidator::fixup( QString& str ) const
674 {
675     str = str.trimmed();
676 }
677
678 /**************************************************************************
679  * Open Capture device ( DVB, PVR, V4L, and similar )                     *
680  **************************************************************************/
681 CaptureOpenPanel::CaptureOpenPanel( QWidget *_parent, intf_thread_t *_p_intf ) :
682                                 OpenPanel( _parent, _p_intf )
683 {
684     isInitialized = false;
685 }
686
687 void CaptureOpenPanel::initialize()
688 {
689     if( isInitialized ) return;
690
691     isInitialized = true;
692
693     ui.setupUi( this );
694
695     BUTTONACT( ui.advancedButton, advancedDialog() );
696
697     /* Create two stacked layouts in the main comboBoxes */
698     QStackedLayout *stackedDevLayout = new QStackedLayout;
699     ui.cardBox->setLayout( stackedDevLayout );
700
701     QStackedLayout *stackedPropLayout = new QStackedLayout;
702     ui.optionsBox->setLayout( stackedPropLayout );
703
704     /* Creation and connections of the WIdgets in the stacked layout */
705 #define addModuleAndLayouts( number, name, label, layout )            \
706     QWidget * name ## DevPage = new QWidget( this );                  \
707     QWidget * name ## PropPage = new QWidget( this );                 \
708     stackedDevLayout->addWidget( name ## DevPage );        \
709     stackedPropLayout->addWidget( name ## PropPage );      \
710     layout * name ## DevLayout = new layout;                \
711     layout * name ## PropLayout = new layout;               \
712     name ## DevPage->setLayout( name ## DevLayout );                  \
713     name ## PropPage->setLayout( name ## PropLayout );                \
714     ui.deviceCombo->addItem( qtr( label ), QVariant( number ) );
715
716 #define CuMRL( widget, slot ) CONNECT( widget , slot , this, updateMRL() );
717
718 #ifdef WIN32
719     /*********************
720      * DirectShow Stuffs *
721      *********************/
722     if( module_exists( "dshow" ) ){
723     addModuleAndLayouts( DSHOW_DEVICE, dshow, "DirectShow", QGridLayout );
724
725     /* dshow Main */
726     int line = 0;
727     module_config_t *p_config =
728         config_FindConfig( VLC_OBJECT(p_intf), "dshow-vdev" );
729     vdevDshowW = new StringListConfigControl(
730         VLC_OBJECT(p_intf), p_config, this );
731     vdevDshowW->insertIntoExistingGrid( dshowDevLayout, line );
732     line++;
733
734     p_config = config_FindConfig( VLC_OBJECT(p_intf), "dshow-adev" );
735     adevDshowW = new StringListConfigControl(
736         VLC_OBJECT(p_intf), p_config, this );
737     adevDshowW->insertIntoExistingGrid( dshowDevLayout, line );
738     line++;
739
740     /* dshow Properties */
741     QLabel *dshowVSizeLabel = new QLabel( qtr( "Video size" ) );
742     dshowPropLayout->addWidget( dshowVSizeLabel, 0, 0 );
743
744     dshowVSizeLine = new QLineEdit;
745     dshowPropLayout->addWidget( dshowVSizeLine, 0, 1);
746     dshowPropLayout->addItem( new QSpacerItem( 20, 20, QSizePolicy::Expanding ),
747             1, 0, 3, 1 );
748
749     /* dshow CONNECTs */
750     CuMRL( vdevDshowW, changed() );
751     CuMRL( adevDshowW, changed() );
752     CuMRL( dshowVSizeLine, textChanged( const QString& ) );
753     configList << "dshow-vdev" << "dshow-adev" << "dshow-size";
754     }
755 #else /* WIN32 */
756     /*******
757      * V4L2*
758      *******/
759     if( module_exists( "v4l2" ) ){
760     addModuleAndLayouts( V4L2_DEVICE, v4l2, "Video for Linux 2", QGridLayout );
761
762     char const * const ppsz_v4lvdevices[] = {
763         "video*"
764     };
765
766     /* V4L2 main panel */
767     QLabel *v4l2VideoDeviceLabel = new QLabel( qtr( "Video device name" ) );
768     v4l2DevLayout->addWidget( v4l2VideoDeviceLabel, 0, 0 );
769
770     v4l2VideoDevice = new QComboBox( this );
771     v4l2VideoDevice->setEditable( true );
772     POPULATE_WITH_DEVS( ppsz_v4lvdevices, v4l2VideoDevice );
773     v4l2VideoDevice->clearEditText();
774     v4l2DevLayout->addWidget( v4l2VideoDevice, 0, 1 );
775
776     QLabel *v4l2AudioDeviceLabel = new QLabel( qtr( "Audio device name" ) );
777     v4l2DevLayout->addWidget( v4l2AudioDeviceLabel, 1, 0 );
778
779     v4l2AudioDevice = new QComboBox( this );
780     v4l2AudioDevice->setEditable( true );
781     {
782         QStringList patterns = QStringList();
783         patterns << QString( "pcmC*D*c" );
784
785         QStringList nodes = QDir( "/dev/snd" ).entryList( patterns,
786                                                           QDir::System );
787         QStringList names = nodes.replaceInStrings( QRegExp("^pcmC"), "hw:" )
788                                  .replaceInStrings( QRegExp("c$"), "" )
789                                  .replaceInStrings( QRegExp("D"), "," );
790         v4l2AudioDevice->addItems( names );
791     }
792     v4l2AudioDevice->clearEditText();
793     v4l2DevLayout->addWidget( v4l2AudioDevice, 1, 1 );
794
795     /* v4l2 Props panel */
796     QLabel *v4l2StdLabel = new QLabel( qtr( "Video standard" ) );
797     v4l2PropLayout->addWidget( v4l2StdLabel, 0 , 0 );
798
799     v4l2StdBox = new QComboBox;
800     setfillVLCConfigCombo( "v4l2-standard", p_intf, v4l2StdBox );
801     v4l2PropLayout->addWidget( v4l2StdBox, 0 , 1 );
802     v4l2PropLayout->addItem( new QSpacerItem( 20, 20, QSizePolicy::Expanding ),
803             1, 0, 3, 2 );
804
805     /* v4l2 CONNECTs */
806     CuMRL( v4l2VideoDevice->lineEdit(), textChanged( const QString& ) );
807     CuMRL( v4l2VideoDevice,  currentIndexChanged ( int ) );
808     CuMRL( v4l2AudioDevice->lineEdit(), textChanged( const QString& ) );
809     CuMRL( v4l2AudioDevice,  currentIndexChanged ( int ) );
810     CuMRL( v4l2StdBox,  currentIndexChanged ( int ) );
811     configList << "v4l2-standard" << "v4l2-dev";
812     }
813
814     /*******
815      * JACK *
816      *******/
817     if( module_exists( "jack" ) ){
818     addModuleAndLayouts( JACK_DEVICE, jack, "JACK Audio Connection Kit",
819                          QGridLayout);
820
821     /* Jack Main panel */
822     /* Channels */
823     QLabel *jackChannelsLabel = new QLabel( qtr( "Channels:" ) );
824     jackDevLayout->addWidget( jackChannelsLabel, 1, 0 );
825
826     jackChannels = new QSpinBox;
827     setSpinBoxFreq( jackChannels );
828     jackChannels->setMaximum(255);
829     jackChannels->setValue(2);
830     jackChannels->setAlignment( Qt::AlignRight );
831     jackDevLayout->addWidget( jackChannels, 1, 1 );
832
833     /* Selected ports */
834     QLabel *jackPortsLabel = new QLabel( qtr( "Selected ports:" ) );
835     jackDevLayout->addWidget( jackPortsLabel, 0 , 0 );
836
837     jackPortsSelected = new QLineEdit( qtr( ".*") );
838     jackPortsSelected->setAlignment( Qt::AlignRight );
839     jackDevLayout->addWidget( jackPortsSelected, 0, 1 );
840
841     /* Jack Props panel */
842
843     /* Pace */
844     jackPace = new QCheckBox(qtr( "Use VLC pace" ));
845     jackPropLayout->addWidget( jackPace, 1, 1 );
846
847     /* Auto Connect */
848     jackConnect = new QCheckBox( qtr( "Auto connection" ));
849     jackPropLayout->addWidget( jackConnect, 1, 2 );
850
851     /* Jack CONNECTs */
852     CuMRL( jackChannels, valueChanged( int ) );
853     CuMRL( jackPace, stateChanged( int ) );
854     CuMRL( jackConnect, stateChanged( int ) );
855     CuMRL( jackPortsSelected, textChanged( const QString& ) );
856     configList << "jack-input-use-vlc-pace" << "jack-input-auto-connect";
857     }
858
859     /************
860      * PVR      *
861      ************/
862     if( module_exists( "pvr" ) ){
863     addModuleAndLayouts( PVR_DEVICE, pvr, "PVR", QGridLayout );
864
865     /* PVR Main panel */
866     QLabel *pvrDeviceLabel = new QLabel( qtr( "Device name" ) );
867     pvrDevLayout->addWidget( pvrDeviceLabel, 0, 0 );
868
869     pvrDevice = new QLineEdit;
870     pvrDevLayout->addWidget( pvrDevice, 0, 1 );
871
872     QLabel *pvrRadioDeviceLabel = new QLabel( qtr( "Radio device name" ) );
873     pvrDevLayout->addWidget( pvrRadioDeviceLabel, 1, 0 );
874
875     pvrRadioDevice = new QLineEdit;
876     pvrDevLayout->addWidget( pvrRadioDevice, 1, 1 );
877
878     /* PVR props panel */
879     QLabel *pvrNormLabel = new QLabel( qtr( "Norm" ) );
880     pvrPropLayout->addWidget( pvrNormLabel, 0, 0 );
881
882     pvrNormBox = new QComboBox;
883     setfillVLCConfigCombo( "pvr-norm", p_intf, pvrNormBox );
884     pvrPropLayout->addWidget( pvrNormBox, 0, 1 );
885
886     QLabel *pvrFreqLabel = new QLabel( qtr( "Frequency" ) );
887     pvrPropLayout->addWidget( pvrFreqLabel, 1, 0 );
888
889     pvrFreq = new QSpinBox;
890     pvrFreq->setAlignment( Qt::AlignRight );
891     pvrFreq->setSuffix(" kHz");
892     setSpinBoxFreq( pvrFreq );
893     pvrPropLayout->addWidget( pvrFreq, 1, 1 );
894
895     QLabel *pvrBitrLabel = new QLabel( qtr( "Bitrate" ) );
896     pvrPropLayout->addWidget( pvrBitrLabel, 2, 0 );
897
898     pvrBitr = new QSpinBox;
899     pvrBitr->setAlignment( Qt::AlignRight );
900     pvrBitr->setSuffix(" kHz");
901     setSpinBoxFreq( pvrBitr );
902     pvrPropLayout->addWidget( pvrBitr, 2, 1 );
903     pvrPropLayout->addItem( new QSpacerItem( 20, 20, QSizePolicy::Expanding ),
904             3, 0, 1, 1 );
905
906     /* PVR CONNECTs */
907     CuMRL( pvrDevice, textChanged( const QString& ) );
908     CuMRL( pvrRadioDevice, textChanged( const QString& ) );
909
910     CuMRL( pvrFreq, valueChanged ( int ) );
911     CuMRL( pvrBitr, valueChanged ( int ) );
912     CuMRL( pvrNormBox, currentIndexChanged ( int ) );
913     configList << "pvr-device" << "pvr-radio-device" << "pvr-norm"
914                << "pvr-frequency" << "pvr-bitrate";
915     }
916 #endif
917     /*************
918      * DVB Stuff *
919      *************/
920     if( module_exists( "dtv" ) ){
921     addModuleAndLayouts( DTV_DEVICE, dvb, N_("TV (digital)"), QGridLayout );
922
923     /* DVB Main */
924     QLabel *dvbDeviceLabel = new QLabel( qtr( "Tuner card" ) );
925     QLabel *dvbTypeLabel = new QLabel( qtr( "Delivery system" ) );
926
927     dvbCard = new QSpinBox;
928     dvbCard->setAlignment( Qt::AlignRight );
929 #ifdef __linux__
930     dvbCard->setPrefix( "/dev/dvb/adapter" );
931 #endif
932     dvbDevLayout->addWidget( dvbDeviceLabel, 0, 0 );
933     dvbDevLayout->addWidget( dvbCard, 0, 1, 1, 2 );
934
935     dvbc = new QRadioButton( "DVB-C" );
936     dvbs = new QRadioButton( "DVB-S" );
937     dvbs2 = new QRadioButton( "DVB-S2" );
938     dvbt = new QRadioButton( "DVB-T" );
939     dvbt2 = new QRadioButton( "DVB-T2" );
940     atsc = new QRadioButton( "ATSC" );
941     cqam = new QRadioButton( "Clear QAM" );
942     dvbt->setChecked( true );
943
944     dvbDevLayout->addWidget( dvbTypeLabel, 1, 0, 2, 1 );
945     dvbDevLayout->addWidget( dvbc,  1, 1 );
946     dvbDevLayout->addWidget( dvbs,  1, 2 );
947     dvbDevLayout->addWidget( dvbs2, 2, 2 );
948     dvbDevLayout->addWidget( dvbt,  1, 3 );
949     dvbDevLayout->addWidget( dvbt2, 2, 3 );
950     dvbDevLayout->addWidget( atsc,  1, 4 );
951     dvbDevLayout->addWidget( cqam,  2, 4 );
952
953     /* DVB Props panel */
954     QLabel *dvbFreqLabel =
955                     new QLabel( qtr( "Transponder/multiplex frequency" ) );
956     dvbPropLayout->addWidget( dvbFreqLabel, 0, 0 );
957
958     dvbFreq = new QSpinBox;
959     dvbFreq->setAlignment( Qt::AlignRight );
960     dvbFreq->setSuffix(" kHz");
961     dvbFreq->setSingleStep( 1000 );
962     setSpinBoxFreq( dvbFreq  );
963     dvbPropLayout->addWidget( dvbFreq, 0, 1 );
964
965     dvbSrateLabel = new QLabel( qtr( "Transponder symbol rate" ) );
966     dvbPropLayout->addWidget( dvbSrateLabel, 1, 0 );
967
968     dvbSrate = new QSpinBox;
969     dvbSrate->setAlignment( Qt::AlignRight );
970     dvbSrate->setSuffix(" bauds");
971     setSpinBoxFreq( dvbSrate );
972     dvbPropLayout->addWidget( dvbSrate, 1, 1 );
973
974     dvbModLabel = new QLabel( qtr( "Modulation / Constellation" ) );
975     dvbPropLayout->addWidget( dvbModLabel, 2, 0 );
976
977     dvbQamBox = new QComboBox;
978     dvbQamBox->addItem( qtr( "Automatic" ), qfu("QAM") );
979     dvbQamBox->addItem( "256-QAM", qfu("256QAM") );
980     dvbQamBox->addItem( "128-QAM", qfu("128QAM") );
981     dvbQamBox->addItem( "64-QAM", qfu("64QAM") );
982     dvbQamBox->addItem( "32-QAM", qfu("32QAM") );
983     dvbQamBox->addItem( "16-QAM", qfu("16QAM") );
984     dvbPropLayout->addWidget( dvbQamBox, 2, 1 );
985
986     dvbPskBox = new QComboBox;
987     dvbPskBox->addItem( "QPSK", qfu("QPSK") );
988     dvbPskBox->addItem( "DQPSK", qfu("DQPSK") );
989     dvbPskBox->addItem( "8-PSK", qfu("8PSK") );
990     dvbPskBox->addItem( "16-APSK", qfu("16APSK") );
991     dvbPskBox->addItem( "32-APSK", qfu("32APSK") );
992     dvbPropLayout->addWidget( dvbPskBox, 2, 1 );
993
994     dvbModLabel->hide();
995     dvbQamBox->hide();
996     dvbPskBox->hide();
997
998     dvbBandLabel = new QLabel( qtr( "Bandwidth" ) );
999     dvbPropLayout->addWidget( dvbBandLabel, 2, 0 );
1000
1001     dvbBandBox = new QComboBox;
1002     setfillVLCConfigCombo( "dvb-bandwidth", p_intf, dvbBandBox );
1003     dvbPropLayout->addWidget( dvbBandBox, 2, 1 );
1004
1005     dvbBandLabel->hide();
1006     dvbBandBox->hide();
1007
1008     dvbPropLayout->addItem( new QSpacerItem( 20, 20, QSizePolicy::Expanding ),
1009             2, 0, 2, 1 );
1010
1011     /* DVB CONNECTs */
1012     CuMRL( dvbCard, valueChanged ( int ) );
1013     CuMRL( dvbFreq, valueChanged ( int ) );
1014     CuMRL( dvbSrate, valueChanged ( int ) );
1015     CuMRL( dvbQamBox, currentIndexChanged ( int ) );
1016     CuMRL( dvbPskBox, currentIndexChanged ( int ) );
1017     CuMRL( dvbBandBox, currentIndexChanged ( int ) );
1018
1019     BUTTONACT( dvbc, updateButtons() );
1020     BUTTONACT( dvbs, updateButtons() );
1021     BUTTONACT( dvbs2, updateButtons() );
1022     BUTTONACT( dvbt, updateButtons() );
1023     BUTTONACT( dvbt2, updateButtons() );
1024     BUTTONACT( atsc, updateButtons() );
1025     BUTTONACT( cqam, updateButtons() );
1026     BUTTONACT( dvbc, updateMRL() );
1027     BUTTONACT( dvbt, updateMRL() );
1028     BUTTONACT( dvbt2, updateMRL() );
1029     BUTTONACT( dvbs, updateMRL() );
1030     BUTTONACT( dvbs2, updateMRL() );
1031     BUTTONACT( atsc, updateMRL() );
1032     BUTTONACT( cqam, updateMRL() );
1033     configList << "dvb-adapter" << "dvb-frequency" << "dvb-modulation"
1034                << "dvb-bandwidth";
1035     }
1036
1037     /**********
1038      * Screen *
1039      **********/
1040     addModuleAndLayouts( SCREEN_DEVICE, screen, "Desktop", QGridLayout );
1041     QLabel *screenLabel = new QLabel( qtr( "Your display will be "
1042             "opened and played in order to stream or save it." ) );
1043     screenLabel->setWordWrap( true );
1044     screenDevLayout->addWidget( screenLabel, 0, 0 );
1045
1046     QLabel *screenFPSLabel = new QLabel(
1047             qtr( "Desired frame rate for the capture." ) );
1048     screenPropLayout->addWidget( screenFPSLabel, 0, 0 );
1049
1050     screenFPS = new QDoubleSpinBox;
1051     screenFPS->setValue( 1. );
1052     screenFPS->setRange( .01, 100. );
1053     screenFPS->setAlignment( Qt::AlignRight );
1054     /* xgettext: frames per second */
1055     screenFPS->setSuffix( qtr( " f/s" ) );
1056     screenPropLayout->addWidget( screenFPS, 0, 1 );
1057
1058     /* Screen connect */
1059     CuMRL( screenFPS, valueChanged( double ) );
1060
1061     /* General connects */
1062     CONNECT( ui.deviceCombo, activated( int ) ,
1063              stackedDevLayout, setCurrentIndex( int ) );
1064     CONNECT( ui.deviceCombo, activated( int ),
1065              stackedPropLayout, setCurrentIndex( int ) );
1066     CONNECT( ui.deviceCombo, activated( int ), this, updateMRL() );
1067     CONNECT( ui.deviceCombo, activated( int ), this, updateButtons() );
1068
1069 #undef CuMRL
1070 #undef addModuleAndLayouts
1071 }
1072
1073 CaptureOpenPanel::~CaptureOpenPanel()
1074 {
1075 }
1076
1077 void CaptureOpenPanel::clear()
1078 {
1079     advMRL.clear();
1080 }
1081
1082 void CaptureOpenPanel::updateMRL()
1083 {
1084     QString mrl = "";
1085     QStringList fileList;
1086     int i_devicetype = ui.deviceCombo->itemData(
1087             ui.deviceCombo->currentIndex() ).toInt();
1088     switch( i_devicetype )
1089     {
1090 #ifdef WIN32
1091     case DSHOW_DEVICE:
1092         fileList << "dshow://";
1093         mrl+= " :dshow-vdev=" +
1094             colon_escape( QString("%1").arg( vdevDshowW->getValue() ) );
1095         mrl+= " :dshow-adev=" +
1096             colon_escape( QString("%1").arg( adevDshowW->getValue() ) )+" ";
1097         if( dshowVSizeLine->isModified() )
1098             mrl += ":dshow-size=" + dshowVSizeLine->text();
1099         break;
1100 #else
1101     case V4L2_DEVICE:
1102         fileList << "v4l2://" + v4l2VideoDevice->currentText();
1103         mrl += ":v4l2-standard="
1104             + v4l2StdBox->itemData( v4l2StdBox->currentIndex() ).toString();
1105         mrl += " :input-slave=alsa://" + v4l2AudioDevice->currentText();
1106         break;
1107     case JACK_DEVICE:
1108         mrl = "jack://";
1109         mrl += "channels=" + QString::number( jackChannels->value() );
1110         mrl += ":ports=" + jackPortsSelected->text();
1111         fileList << mrl; mrl = "";
1112
1113         if ( jackPace->isChecked() )
1114         {
1115                 mrl += " :jack-input-use-vlc-pace";
1116         }
1117         if ( jackConnect->isChecked() )
1118         {
1119                 mrl += " :jack-input-auto-connect";
1120         }
1121         break;
1122     case PVR_DEVICE:
1123         fileList << "pvr://";
1124         mrl += " :pvr-device=" + pvrDevice->text();
1125         mrl += " :pvr-radio-device=" + pvrRadioDevice->text();
1126         mrl += " :pvr-norm=" + QString::number( pvrNormBox->currentIndex() );
1127         if( pvrFreq->value() )
1128             mrl += " :pvr-frequency=" + QString::number( pvrFreq->value() );
1129         if( pvrBitr->value() )
1130             mrl += " :pvr-bitrate=" + QString::number( pvrBitr->value() );
1131         break;
1132 #endif
1133     case DTV_DEVICE:
1134         if( dvbc->isChecked() ) mrl = "dvb-c://";
1135         else
1136         if( dvbs->isChecked() ) mrl = "dvb-s://";
1137         else
1138         if( dvbs2->isChecked() ) mrl = "dvb-s2://";
1139         else
1140         if( dvbt->isChecked() ) mrl = "dvb-t://";
1141         else
1142         if( dvbt2->isChecked() ) mrl = "dvb-t2://";
1143         else
1144         if( atsc->isChecked() ) mrl = "atsc://";
1145         else
1146         if( cqam->isChecked() ) mrl = "cqam://";
1147
1148         mrl += "frequency=" + QString::number( dvbFreq->value() ) + "000";
1149
1150         if( dvbc->isChecked() || cqam->isChecked() )
1151             mrl += ":modulation="
1152                 + dvbQamBox->itemData( dvbQamBox->currentIndex() ).toString();
1153         if( dvbs2->isChecked() )
1154             mrl += ":modulation="
1155                 + dvbPskBox->itemData( dvbPskBox->currentIndex() ).toString();
1156         if( dvbc->isChecked() || dvbs->isChecked() || dvbs2->isChecked() )
1157             mrl += ":srate=" + QString::number( dvbSrate->value() );
1158         if( dvbt->isChecked() || dvbt2->isChecked() )
1159             mrl += ":bandwidth=" +
1160                 QString::number( dvbBandBox->itemData(
1161                     dvbBandBox->currentIndex() ).toInt() );
1162
1163         fileList << mrl; mrl= "";
1164         mrl += " :dvb-adapter=" + QString::number( dvbCard->value() );
1165         break;
1166     case SCREEN_DEVICE:
1167         fileList << "screen://";
1168         mrl = " :screen-fps=" + QString::number( screenFPS->value(), 'f' );
1169         updateButtons();
1170         break;
1171     }
1172     emit methodChanged( "live-caching" );
1173
1174     if( !advMRL.isEmpty() ) mrl += " " + advMRL;
1175
1176     emit mrlUpdated( fileList, mrl );
1177 }
1178
1179 /**
1180  * Update the Buttons (show/hide) for the GUI as all device type don't
1181  * use the same ui. elements.
1182  **/
1183 void CaptureOpenPanel::updateButtons()
1184 {
1185     /*  Be sure to display the ui Elements in case they were hidden by
1186      *  some Device Type (like Screen://) */
1187     ui.optionsBox->show();
1188     ui.advancedButton->show();
1189     /* Get the current Device Number */
1190     int i_devicetype = ui.deviceCombo->itemData(
1191                                 ui.deviceCombo->currentIndex() ).toInt();
1192     switch( i_devicetype )
1193     {
1194     case DTV_DEVICE:
1195         dvbSrate->hide();
1196         dvbSrateLabel->hide();
1197         dvbQamBox->hide();
1198         dvbPskBox->hide();
1199         dvbModLabel->hide();
1200         dvbBandBox->hide();
1201         dvbBandLabel->hide();
1202
1203         if( dvbc->isChecked() )
1204         {
1205             dvbSrate->show();
1206             dvbSrateLabel->show();
1207             dvbQamBox->show();
1208             dvbModLabel->show();
1209         }
1210         else if( dvbs->isChecked() )
1211         {
1212             dvbSrate->show();
1213             dvbSrateLabel->show();
1214         }
1215         else if( dvbs2->isChecked() )
1216         {
1217             dvbSrate->show();
1218             dvbSrateLabel->show();
1219             dvbPskBox->show();
1220             dvbModLabel->show();
1221         }
1222         else if( dvbt->isChecked() || dvbt2->isChecked() )
1223         {
1224             dvbBandBox->show();
1225             dvbBandLabel->show();
1226         }
1227         break;
1228     case SCREEN_DEVICE:
1229         //ui.optionsBox->hide();
1230         ui.advancedButton->hide();
1231         break;
1232     }
1233
1234     advMRL.clear();
1235 }
1236
1237 void CaptureOpenPanel::advancedDialog()
1238 {
1239     /* Get selected device type */
1240     int i_devicetype = ui.deviceCombo->itemData(
1241                                 ui.deviceCombo->currentIndex() ).toInt();
1242
1243     /* Get the corresponding module */
1244     module_t *p_module =
1245         module_find( psz_devModule[i_devicetype] );
1246     if( NULL == p_module ) return;
1247
1248     /* Init */
1249     QList<ConfigControl *> controls;
1250
1251     /* Get the confsize  */
1252     unsigned int i_confsize;
1253     module_config_t *p_config;
1254     p_config = module_config_get( p_module, &i_confsize );
1255
1256     /* New Adv Prop dialog */
1257     adv = new QDialog( this );
1258     adv->setWindowTitle( qtr( "Advanced Options" ) );
1259     adv->setWindowRole( "vlc-advanced-options" );
1260
1261     /* A main Layout with a Frame */
1262     QVBoxLayout *mainLayout = new QVBoxLayout( adv );
1263     QScrollArea *scroll = new QScrollArea;
1264     mainLayout->addWidget( scroll );
1265
1266     QFrame *advFrame = new QFrame;
1267     /* GridLayout inside the Frame */
1268     QGridLayout *gLayout = new QGridLayout( advFrame );
1269
1270     scroll->setWidgetResizable( true );
1271     scroll->setWidget( advFrame );
1272
1273     /* Create the options inside the FrameLayout */
1274     for( int n = 0; n < (int)i_confsize; n++ )
1275     {
1276         module_config_t *p_item = p_config + n;
1277         QString name = p_item->psz_name;
1278
1279         if( name.isEmpty() || configList.contains( name ) )
1280             continue;
1281
1282         msg_Dbg( p_intf, "item %s", p_item->psz_name);
1283         ConfigControl *config = ConfigControl::createControl(
1284                         VLC_OBJECT( p_intf ), p_item, advFrame, gLayout, n );
1285         if( config )
1286             controls.append( config );
1287     }
1288
1289     /* Button stuffs */
1290     QDialogButtonBox *advButtonBox = new QDialogButtonBox( adv );
1291     QPushButton *closeButton = new QPushButton( qtr( "OK" ) );
1292     QPushButton *cancelButton = new QPushButton( qtr( "Cancel" ) );
1293
1294     CONNECT( closeButton, clicked(), adv, accept() );
1295     CONNECT( cancelButton, clicked(), adv, reject() );
1296
1297     advButtonBox->addButton( closeButton, QDialogButtonBox::AcceptRole );
1298     advButtonBox->addButton( cancelButton, QDialogButtonBox::RejectRole );
1299
1300     mainLayout->addWidget( advButtonBox );
1301
1302     /* Creation of the MRL */
1303     if( adv->exec() )
1304     {
1305         QString tempMRL = "";
1306         for( int i = 0; i < controls.count(); i++ )
1307         {
1308             ConfigControl *control = controls[i];
1309
1310             tempMRL += (i ? " :" : ":");
1311
1312             if( control->getType() == CONFIG_ITEM_BOOL )
1313                 if( !(qobject_cast<VIntConfigControl *>(control)->getValue() ) )
1314                     tempMRL += "no-";
1315
1316             tempMRL += control->getName();
1317
1318             switch( control->getType() )
1319             {
1320                 case CONFIG_ITEM_STRING:
1321                 case CONFIG_ITEM_LOADFILE:
1322                 case CONFIG_ITEM_SAVEFILE:
1323                 case CONFIG_ITEM_DIRECTORY:
1324                 case CONFIG_ITEM_MODULE:
1325                     tempMRL += colon_escape( QString("=%1").arg( qobject_cast<VStringConfigControl *>(control)->getValue() ) );
1326                     break;
1327                 case CONFIG_ITEM_INTEGER:
1328                     tempMRL += QString("=%1").arg( qobject_cast<VIntConfigControl *>(control)->getValue() );
1329                     break;
1330                 case CONFIG_ITEM_FLOAT:
1331                     tempMRL += QString("=%1").arg( qobject_cast<VFloatConfigControl *>(control)->getValue() );
1332                     break;
1333             }
1334         }
1335         advMRL = tempMRL;
1336         updateMRL();
1337     }
1338     qDeleteAll( controls );
1339     delete adv;
1340     module_config_free( p_config );
1341 }
1342