]> git.sesse.net Git - vlc/blob - modules/gui/qt4/components/open.cpp
Qt4 - Open Disc Dialog, finish the disc/track-sub/audio handling. Hide, rename, show...
[vlc] / modules / gui / qt4 / components / open.cpp
1 /*****************************************************************************
2  * open.cpp : Panels for the open dialogs
3  ****************************************************************************
4  * Copyright (C) 2006-2007 the VideoLAN team
5  * $Id$
6  *
7  * Authors: ClĂ©ment Stenac <zorglub@videolan.org>
8  *          Jean-Baptiste Kempf <jb@videolan.org>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23  *****************************************************************************/
24
25
26 #include "qt4.hpp"
27 #include "components/open.hpp"
28 #include "dialogs/open.hpp"
29 #include "dialogs_provider.hpp"
30 #include "util/customwidgets.hpp"
31
32 #include <QFileDialog>
33 #include <QDialogButtonBox>
34 #include <QLineEdit>
35
36 /**************************************************************************
37  * File open
38  **************************************************************************/
39 FileOpenPanel::FileOpenPanel( QWidget *_parent, intf_thread_t *_p_intf ) :
40                                 OpenPanel( _parent, _p_intf )
41 {
42     /* Classic UI Setup */
43     ui.setupUi( this );
44
45     /* Use a QFileDialog and customize it because we don't want to
46        rewrite it all. Be careful to your eyes cause there are a few hacks.
47        Be very careful and test correctly when you modify this. */
48
49     /* Set Filters for file selection */
50     QString fileTypes = "";
51     ADD_FILTER_MEDIA( fileTypes );
52     ADD_FILTER_VIDEO( fileTypes );
53     ADD_FILTER_AUDIO( fileTypes );
54     ADD_FILTER_PLAYLIST( fileTypes );
55     ADD_FILTER_ALL( fileTypes );
56     fileTypes.replace(QString(";*"), QString(" *"));
57
58     // Make this QFileDialog a child of tempWidget from the ui.
59     dialogBox = new FileOpenBox( ui.tempWidget, NULL,
60             qfu( p_intf->p_libvlc->psz_homedir ), fileTypes );
61 /*    dialogBox->setFileMode( QFileDialog::ExistingFiles );*/
62     dialogBox->setAcceptMode( QFileDialog::AcceptOpen );
63
64     /* retrieve last known path used in file browsing */
65     char *psz_filepath = config_GetPsz( p_intf, "qt-filedialog-path" );
66     if( psz_filepath )
67     {
68         dialogBox->setDirectory( QString::fromUtf8(psz_filepath) );
69         delete psz_filepath;
70     }
71
72     /* We don't want to see a grip in the middle of the window, do we? */
73     dialogBox->setSizeGripEnabled( false );
74     dialogBox->setToolTip( qtr( "Select one or multiple files, or a folder" ));
75
76     // Add it to the layout
77     ui.gridLayout->addWidget( dialogBox, 0, 0, 1, 3 );
78
79     // But hide the two OK/Cancel buttons. Enable them for debug.
80     QDialogButtonBox *fileDialogAcceptBox =
81                         findChildren<QDialogButtonBox*>()[0];
82     fileDialogAcceptBox->hide();
83
84     /* Ugly hacks to get the good Widget */
85     //This lineEdit is the normal line in the fileDialog.
86     lineFileEdit = findChildren<QLineEdit*>()[3];
87     lineFileEdit->hide();
88
89     /* Make a list of QLabel inside the QFileDialog to access the good ones */
90     QList<QLabel *> listLabel = findChildren<QLabel*>();
91
92     /* Hide the FileNames one. Enable it for debug */
93     listLabel[4]->hide();
94     /* Change the text that was uncool in the usual box */
95     listLabel[5]->setText( qtr( "Filter:" ) );
96
97     // Hide the subtitles control by default.
98     ui.subFrame->hide();
99
100     /* Build the subs size combo box */
101     module_config_t *p_item =
102         config_FindConfig( VLC_OBJECT(p_intf), "freetype-rel-fontsize" );
103     if( p_item )
104     {
105         for( int i_index = 0; i_index < p_item->i_list; i_index++ )
106         {
107             ui.sizeSubComboBox->addItem(
108                 qfu( p_item->ppsz_list_text[i_index] ),
109                 QVariant( p_item->pi_list[i_index] ) );
110             if( p_item->value.i == p_item->pi_list[i_index] )
111             {
112                 ui.sizeSubComboBox->setCurrentIndex( i_index );
113             }
114         }
115     }
116
117     /* Build the subs align combo box */
118     p_item = config_FindConfig( VLC_OBJECT(p_intf), "subsdec-align" );
119     if( p_item )
120     {
121         for( int i_index = 0; i_index < p_item->i_list; i_index++ )
122         {
123             ui.alignSubComboBox->addItem(
124                 qfu( p_item->ppsz_list_text[i_index] ),
125                 QVariant( p_item->pi_list[i_index] ) );
126             if( p_item->value.i == p_item->pi_list[i_index] )
127             {
128                 ui.alignSubComboBox->setCurrentIndex( i_index );
129             }
130         }
131     }
132
133     BUTTONACT( ui.subBrowseButton, browseFileSub() );
134     BUTTONACT( ui.subCheckBox, toggleSubtitleFrame());
135
136     CONNECT( ui.fileInput, editTextChanged(QString ), this, updateMRL());
137     CONNECT( ui.subInput, editTextChanged(QString ), this, updateMRL());
138     CONNECT( ui.alignSubComboBox, currentIndexChanged(int), this, updateMRL());
139     CONNECT( ui.sizeSubComboBox, currentIndexChanged(int), this, updateMRL());
140     CONNECT( lineFileEdit, textChanged( QString ), this, browseFile());
141 }
142
143 FileOpenPanel::~FileOpenPanel()
144 {}
145
146 QStringList FileOpenPanel::browse(QString help)
147 {
148     return THEDP->showSimpleOpen( help );
149 }
150
151 void FileOpenPanel::browseFile()
152 {
153     QString fileString = "";
154     foreach( QString file, dialogBox->selectedFiles() ) {
155          fileString += "\"" + file + "\" ";
156     }
157     ui.fileInput->setEditText( fileString );
158     updateMRL();
159 }
160
161 void FileOpenPanel::browseFileSub()
162 {
163     // FIXME Handle selection of more than one subtitles file
164     QStringList files = THEDP->showSimpleOpen( qtr("Open subtitles file"),
165                             EXT_FILTER_SUBTITLE,
166                             dialogBox->directory().absolutePath() );
167     if( files.isEmpty() ) return;
168     ui.subInput->setEditText( files.join(" ") );
169     updateMRL();
170 }
171
172 void FileOpenPanel::updateMRL()
173 {
174     QString mrl = ui.fileInput->currentText();
175
176     if( ui.subCheckBox->isChecked() ) {
177         mrl.append( " :sub-file=" + ui.subInput->currentText() );
178         int align = ui.alignSubComboBox->itemData( ui.alignSubComboBox->currentIndex() ).toInt();
179         mrl.append( " :subsdec-align=" + QString().setNum( align ) );
180         int size = ui.sizeSubComboBox->itemData( ui.sizeSubComboBox->currentIndex() ).toInt();
181         mrl.append( " :freetype-rel-fontsize=" + QString().setNum( size ) );
182     }
183
184     const char *psz_filepath = config_GetPsz( p_intf, "qt-filedialog-path" );
185     if( (NULL == psz_filepath)
186       || strcmp(psz_filepath,dialogBox->directory().absolutePath().toUtf8()) )
187     {
188         /* set dialog box current directory as last known path */
189         config_PutPsz( p_intf, "qt-filedialog-path",
190                        dialogBox->directory().absolutePath().toUtf8() );
191     }
192     delete psz_filepath;
193
194     emit mrlUpdated( mrl );
195     emit methodChanged( "file-caching" );
196 }
197
198
199 /* Function called by Open Dialog when clicke on Play/Enqueue */
200 void FileOpenPanel::accept()
201 {
202     ui.fileInput->addItem(ui.fileInput->currentText());
203     if ( ui.fileInput->count() > 8 ) ui.fileInput->removeItem(0);
204 }
205
206 void FileOpenBox::accept()
207 {
208     OpenDialog::getInstance( NULL, NULL )->play();
209 }
210
211 /* Function called by Open Dialog when clicked on cancel */
212 void FileOpenPanel::clear()
213 {
214     ui.fileInput->setEditText( "" );
215     ui.subInput->setEditText( "" );
216 }
217
218 void FileOpenPanel::toggleSubtitleFrame()
219 {
220     if (ui.subFrame->isVisible())
221     {
222         ui.subFrame->hide();
223         updateGeometry();
224     /* FiXME Size */
225     }
226     else
227     {
228         ui.subFrame->show();
229     }
230
231     /* Update the MRL */
232     updateMRL();
233 }
234
235 /**************************************************************************
236  * Disk open
237  **************************************************************************/
238 DiscOpenPanel::DiscOpenPanel( QWidget *_parent, intf_thread_t *_p_intf ) :
239                                 OpenPanel( _parent, _p_intf )
240 {
241     ui.setupUi( this );
242
243     BUTTONACT( ui.dvdRadioButton, updateButtons());
244     BUTTONACT( ui.vcdRadioButton, updateButtons());
245     BUTTONACT( ui.audioCDRadioButton, updateButtons());
246     BUTTONACT( ui.dvdsimple,  updateButtons());
247
248     CONNECT( ui.deviceCombo, editTextChanged(QString ), this, updateMRL());
249     CONNECT( ui.titleSpin, valueChanged(int), this, updateMRL());
250     CONNECT( ui.chapterSpin, valueChanged(int), this, updateMRL());
251     CONNECT( ui.audioSpin, valueChanged(int), this, updateMRL());
252     CONNECT( ui.subtitlesSpin, valueChanged(int), this, updateMRL());
253 }
254
255 DiscOpenPanel::~DiscOpenPanel()
256 {}
257
258 void DiscOpenPanel::clear()
259 {
260     ui.titleSpin->setValue(0);
261     ui.chapterSpin->setValue(0);
262 }
263
264 void DiscOpenPanel::updateButtons()
265 {
266     if ( ui.dvdRadioButton->isChecked() )
267     {
268         ui.titleLabel->setText( qtr("Title") );
269         ui.chapterLabel->show();
270         ui.chapterSpin->show();
271         ui.diskOptionBox_2->show();
272     }
273     else if ( ui.vcdRadioButton->isChecked() )
274     {
275         ui.titleLabel->setText( qtr("Entry") );
276         ui.chapterLabel->hide();
277         ui.chapterSpin->hide();
278         ui.diskOptionBox_2->show();
279     }
280     else
281     {
282         ui.titleLabel->setText( qtr("Track") );
283         ui.chapterLabel->hide();
284         ui.chapterSpin->hide();
285         ui.diskOptionBox_2->hide();
286     }
287
288     updateMRL();
289 }
290
291
292 void DiscOpenPanel::updateMRL()
293 {
294     QString mrl = "";
295     /* DVD */
296     if( ui.dvdRadioButton->isChecked() ) {
297         if( !ui.dvdsimple->isChecked() )
298             mrl = "dvd://";
299         else
300             mrl = "dvdsimple://";
301         mrl += ui.deviceCombo->currentText();
302         emit methodChanged( "dvdnav-caching" );
303
304         if ( ui.titleSpin->value() > 0 ) {
305             mrl += QString("@%1").arg(ui.titleSpin->value());
306             if ( ui.chapterSpin->value() > 0 ) {
307                 mrl+= QString(":%1").arg(ui.chapterSpin->value());
308             }
309         }
310
311     /* VCD */
312     } else if (ui.vcdRadioButton->isChecked() ) {
313         mrl = "vcd://" + ui.deviceCombo->currentText();
314         emit methodChanged( "vcd-caching" );
315
316         if( ui.titleSpin->value() > 0 ) {
317             mrl += QString("@%1").arg(ui.titleSpin->value());
318         }
319
320     /* CDDA */
321     } else {
322         mrl = "cdda://" + ui.deviceCombo->currentText();
323         if( ui.titleSpin->value() > 0 ) {
324             QString("@%1").arg(ui.titleSpin->value());
325         }
326     }
327
328     if ( ui.dvdRadioButton->isChecked() || ui.vcdRadioButton->isChecked() )
329     {
330         if ( ui.audioSpin->value() >= 0 ) {
331             mrl += " :audio-track=" + QString("%1").arg(ui.audioSpin->value());
332         }
333         if ( ui.subtitlesSpin->value() >= 0 ) {
334             mrl += " :sub-track=" +
335                 QString("%1").arg(ui.subtitlesSpin->value());
336         }
337     }
338
339     emit mrlUpdated(mrl);
340 }
341
342
343
344 /**************************************************************************
345  * Net open
346  **************************************************************************/
347 NetOpenPanel::NetOpenPanel( QWidget *_parent, intf_thread_t *_p_intf ) :
348                                 OpenPanel( _parent, _p_intf )
349 {
350     ui.setupUi( this );
351
352     CONNECT( ui.protocolCombo, currentIndexChanged(int),
353              this, updateProtocol(int) );
354     CONNECT( ui.portSpin, valueChanged(int), this, updateMRL());
355     CONNECT( ui.addressText, textChanged(QString), this, updateAddress());
356     CONNECT( ui.timeShift, clicked(), this, updateMRL());
357     CONNECT( ui.ipv6, clicked(), this, updateMRL());
358
359     ui.protocolCombo->addItem("HTTP", QVariant("http"));
360     ui.protocolCombo->addItem("FTP", QVariant("ftp"));
361     ui.protocolCombo->addItem("MMS", QVariant("mms"));
362     ui.protocolCombo->addItem("RTSP", QVariant("rtsp"));
363     ui.protocolCombo->addItem("UDP/RTP (unicast)", QVariant("udp"));
364     ui.protocolCombo->addItem("UDP/RTP (multicast)", QVariant("udp"));
365 }
366
367 NetOpenPanel::~NetOpenPanel()
368 {}
369
370 void NetOpenPanel::clear()
371 {}
372
373 void NetOpenPanel::updateProtocol(int idx) {
374     QString addr = ui.addressText->text();
375     QString proto = ui.protocolCombo->itemData(idx).toString();
376
377     ui.timeShift->setEnabled( idx >= 4);
378     ui.ipv6->setEnabled( idx == 4 );
379     ui.addressText->setEnabled( idx != 4 );
380     ui.portSpin->setEnabled( idx >= 4 );
381
382     /* If we already have a protocol in the address, replace it */
383     if( addr.contains( "://")) {
384         msg_Err( p_intf, "replace");
385         addr.replace(QRegExp("^.*://"), proto + "://");
386         ui.addressText->setText(addr);
387     }
388
389     updateMRL();
390 }
391
392 void NetOpenPanel::updateAddress() {
393     updateMRL();
394 }
395
396 void NetOpenPanel::updateMRL() {
397     QString mrl = "";
398     QString addr = ui.addressText->text();
399     int proto = ui.protocolCombo->currentIndex();
400
401     if( addr.contains( "://") && proto != 4 ) {
402         mrl = addr;
403     } else {
404         switch(proto) {
405         case 0:
406             mrl = "http://" + addr;
407             emit methodChanged("http-caching");
408             break;
409         case 2:
410             mrl = "mms://" + addr;
411             emit methodChanged("mms-caching");
412             break;
413         case 1:
414             mrl = "ftp://" + addr;
415             emit methodChanged("ftp-caching");
416             break;
417         case 3: /* RTSP */
418             mrl = "rtsp://" + addr;
419             emit methodChanged("rtsp-caching");
420             break;
421         case 4:
422             mrl = "udp://@";
423             if( ui.ipv6->isEnabled() && ui.ipv6->isChecked() ) {
424                 mrl += "[::]";
425             }
426             mrl += QString(":%1").arg(ui.portSpin->value());
427             emit methodChanged("udp-caching");
428             break;
429         case 5: /* UDP multicast */
430             mrl = "udp://@";
431             /* Add [] to IPv6 */
432             if ( addr.contains(':') && !addr.contains('[') ) {
433                 mrl += "[" + addr + "]";
434             } else mrl += addr;
435             mrl += QString(":%1").arg(ui.portSpin->value());
436             emit methodChanged("udp-caching");
437         }
438     }
439     if( ui.timeShift->isEnabled() && ui.timeShift->isChecked() ) {
440         mrl += " :access-filter=timeshift";
441     }
442     emit mrlUpdated(mrl);
443 }
444
445 /**************************************************************************
446  * Capture open
447  **************************************************************************/
448 CaptureOpenPanel::CaptureOpenPanel( QWidget *_parent, intf_thread_t *_p_intf ) :
449                                 OpenPanel( _parent, _p_intf )
450 {
451     ui.setupUi( this );
452 }
453
454 CaptureOpenPanel::~CaptureOpenPanel()
455 {}
456
457 void CaptureOpenPanel::clear()
458 {}
459
460 void CaptureOpenPanel::updateMRL()
461 {
462     QString mrl = "";
463     emit mrlUpdated(mrl);
464 }