]> git.sesse.net Git - vlc/blob - modules/gui/qt4/dialogs/open.cpp
Qt4 - Open Dialog: Attempt to solve a Windows only bug. qt4 bug? VLC bug? I don't...
[vlc] / modules / gui / qt4 / dialogs / open.cpp
1 /*****************************************************************************
2  * open.cpp : Advanced open dialog
3  *****************************************************************************
4  * Copyright (C) 2006 the VideoLAN team
5  * $Id: streaminfo.cpp 16816 2006-09-23 20:56:52Z jb $
6  *
7  * Authors: Jean-Baptiste Kempf <jb@videolan.org>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 #include <QTabWidget>
25 #include <QGridLayout>
26 #include <QFileDialog>
27 #include <QRegExp>
28 #include <QMenu>
29 #include "dialogs/open.hpp"
30 #include "components/open.hpp"
31
32 #include "qt4.hpp"
33 #include "util/qvlcframe.hpp"
34
35 #include "input_manager.hpp"
36 #include "dialogs_provider.hpp"
37
38 OpenDialog *OpenDialog::instance = NULL;
39
40 OpenDialog::OpenDialog( QWidget *parent, intf_thread_t *_p_intf, bool modal,
41                         bool _stream_after ) :  QVLCDialog( parent, _p_intf )
42 {
43     setModal( modal );
44     b_stream_after = _stream_after;
45
46     ui.setupUi( this );
47     setWindowTitle( qtr("Open" ) );
48     resize( 500, 300);
49
50     /* Tab definition and creation */
51     fileOpenPanel = new FileOpenPanel( ui.Tab, p_intf );
52     discOpenPanel = new DiscOpenPanel( ui.Tab, p_intf );
53     netOpenPanel = new NetOpenPanel( ui.Tab, p_intf );
54     captureOpenPanel = new CaptureOpenPanel( ui.Tab, p_intf );
55
56     ui.Tab->insertTab( OPEN_FILE_TAB, fileOpenPanel, qtr( "&File" ) );
57     ui.Tab->insertTab( OPEN_DISC_TAB, discOpenPanel, qtr( "&Disc" ) );
58     ui.Tab->insertTab( OPEN_NETWORK_TAB, netOpenPanel, qtr( "&Network" ) );
59     ui.Tab->insertTab( OPEN_CAPTURE_TAB, captureOpenPanel,
60                                 qtr( "Capture &Device" ) );
61
62     /* Hide the advancedPanel */
63     ui.advancedFrame->hide();
64
65     /* Buttons Creation */
66     QSizePolicy buttonSizePolicy( static_cast<QSizePolicy::Policy>(7),
67                                   static_cast<QSizePolicy::Policy>(1) );
68     buttonSizePolicy.setHorizontalStretch(0);
69     buttonSizePolicy.setVerticalStretch(0);
70
71     playButton = new QToolButton();
72     playButton->setText( qtr( "&Play" ) );
73     playButton->setSizePolicy( buttonSizePolicy );
74     playButton->setMinimumSize( QSize(90, 0) );
75     playButton->setPopupMode( QToolButton::MenuButtonPopup );
76     playButton->setToolButtonStyle( Qt::ToolButtonTextOnly );
77     playButton->setAutoRaise( false );
78
79     cancelButton = new QToolButton();
80     cancelButton->setText( qtr( "&Cancel" ) );
81     cancelButton->setSizePolicy( buttonSizePolicy );
82
83     QMenu * openButtonMenu = new QMenu( "Open" );
84     openButtonMenu->addAction( qtr("&Enqueue"), this, SLOT( enqueue() ),
85                                     QKeySequence( "Alt+E") );
86     openButtonMenu->addAction( qtr("&Play"), this, SLOT( play() ),
87                                     QKeySequence( "Alt+P" ) );
88     openButtonMenu->addAction( qtr("&Stream"), this, SLOT( stream() ) ,
89                                     QKeySequence( "Alt+S" ) );
90
91     playButton->setMenu( openButtonMenu );
92
93     ui.buttonsBox->addButton( playButton, QDialogButtonBox::AcceptRole );
94     ui.buttonsBox->addButton( cancelButton, QDialogButtonBox::RejectRole );
95
96
97     /* Force MRL update on tab change */
98     CONNECT( ui.Tab, currentChanged(int), this, signalCurrent());
99
100     CONNECT( fileOpenPanel, mrlUpdated( QString ), this, updateMRL(QString) );
101     CONNECT( netOpenPanel, mrlUpdated( QString ), this, updateMRL(QString) );
102     CONNECT( discOpenPanel, mrlUpdated( QString ), this, updateMRL(QString) );
103     CONNECT( captureOpenPanel, mrlUpdated( QString ), this,
104             updateMRL(QString) );
105
106     CONNECT( fileOpenPanel, methodChanged( QString ),
107              this, newMethod(QString) );
108     CONNECT( netOpenPanel, methodChanged( QString ),
109              this, newMethod(QString) );
110     CONNECT( discOpenPanel, methodChanged( QString ),
111              this, newMethod(QString) );
112
113     CONNECT( ui.slaveText, textChanged(QString), this, updateMRL());
114     CONNECT( ui.cacheSpinBox, valueChanged(int), this, updateMRL());
115     CONNECT( ui.startTimeSpinBox, valueChanged(int), this, updateMRL());
116
117     /* Buttons action */
118     BUTTONACT( playButton, play());
119     BUTTONACT( cancelButton, cancel());
120
121     if ( b_stream_after ) setAfter();
122
123     BUTTONACT( ui.advancedCheckBox , toggleAdvancedPanel() );
124
125     /* Initialize caching */
126     storedMethod = "";
127     newMethod("file-caching");
128
129     mainHeight = advHeight = 0;
130 }
131
132 OpenDialog::~OpenDialog()
133 {
134 }
135
136 void OpenDialog::setAfter()
137 {
138     if (!b_stream_after )
139     {
140         playButton->setText( qtr("&Play") );
141         BUTTONACT( playButton, play() );
142     }
143     else
144     {
145         playButton->setText( qtr("&Stream") );
146         BUTTONACT( playButton, stream() );
147     }
148 }
149
150 void OpenDialog::showTab(int i_tab=0)
151 {
152     this->show();
153     ui.Tab->setCurrentIndex(i_tab);
154 }
155
156 void OpenDialog::signalCurrent() {
157     if (ui.Tab->currentWidget() != NULL) {
158         (dynamic_cast<OpenPanel*>(ui.Tab->currentWidget()))->updateMRL();
159     }
160 }
161
162 /*********** 
163  * Actions *
164  ***********/
165
166 /* If Cancel is pressed or escaped */
167 void OpenDialog::cancel()
168 {
169     fileOpenPanel->clear();
170     this->toggleVisible();
171     if( isModal() )
172         reject();
173 }
174
175 /* If EnterKey is pressed */
176 void OpenDialog::close()
177 {
178     if ( !b_stream_after )
179     {
180         play();
181     }
182     else
183     {
184         stream();
185     }
186 }
187
188 /* Play button */
189 void OpenDialog::play()
190 {
191     playOrEnqueue( false );
192 }
193
194 void OpenDialog::enqueue()
195 {
196     playOrEnqueue( true );
197 }
198
199 void OpenDialog::stream()
200 {
201     /* not finished FIXME */
202     THEDP->streamingDialog( mrl );
203 }
204
205
206 void OpenDialog::playOrEnqueue( bool b_enqueue = false )
207 {
208     this->toggleVisible();
209     mrl = ui.advancedLineInput->text();
210
211     if( !isModal() )
212     {
213         QStringList tempMRL = SeparateEntries( mrl );
214         for( size_t i = 0; i < tempMRL.size(); i++ )
215         {
216             bool b_start = !i && !b_enqueue;
217             input_item_t *p_input;
218             const char *psz_utf8 = qtu( tempMRL[i] );
219
220             p_input = input_ItemNew( p_intf, psz_utf8, NULL );
221
222             /* Insert options */
223             while( i + 1 < tempMRL.size() && tempMRL[i + 1].startsWith( ":" ) )
224             {
225                 i++;
226                 psz_utf8 = qtu( tempMRL[i] );
227                 input_ItemAddOption( p_input, psz_utf8 );
228             }
229
230             if( b_start )
231             {
232                 playlist_AddInput( THEPL, p_input,
233                                    PLAYLIST_APPEND | PLAYLIST_GO,
234                                    PLAYLIST_END, VLC_TRUE, VLC_FALSE );
235             }
236             else
237             {
238                 playlist_AddInput( THEPL, p_input,
239                                    PLAYLIST_APPEND|PLAYLIST_PREPARSE,
240                                    PLAYLIST_END, VLC_TRUE, VLC_FALSE );
241             }
242         }
243     }
244     else
245         accept();
246 }
247
248 void OpenDialog::toggleAdvancedPanel()
249 {
250     //FIXME does not work under Windows
251     if (ui.advancedFrame->isVisible()) {
252         ui.advancedFrame->hide();
253         setMinimumHeight(1);
254         resize( width(), mainHeight );
255
256     } else {
257         if( mainHeight == 0 )
258             mainHeight = height();
259
260         ui.advancedFrame->show();
261         if( advHeight == 0 ) {
262             advHeight = height() - mainHeight;
263         }
264         resize( width(), mainHeight + advHeight );
265     }
266 }
267
268 void OpenDialog::updateMRL() {
269     mrl = mainMRL;
270     if( ui.slaveCheckbox->isChecked() ) {
271         mrl += " :input-slave=" + ui.slaveText->text();
272     }
273     int i_cache = config_GetInt( p_intf, qta(storedMethod) );
274     if( i_cache != ui.cacheSpinBox->value() ) {
275         mrl += QString(" :%1=%2").arg(storedMethod).
276                                   arg(ui.cacheSpinBox->value());
277     }
278     if( ui.startTimeSpinBox->value()) {
279         mrl += " :start-time=" + QString("%1").
280             arg(ui.startTimeSpinBox->value());
281     }
282     ui.advancedLineInput->setText(mrl);
283 }
284
285 void OpenDialog::updateMRL(QString tempMRL)
286 {
287     mainMRL = tempMRL;
288     updateMRL();
289 }
290
291 void OpenDialog::newMethod(QString method)
292 {
293     if( method != storedMethod ) {
294         storedMethod = method;
295         int i_value = config_GetInt( p_intf, qta(storedMethod) );
296         ui.cacheSpinBox->setValue(i_value);
297     }
298 }
299
300 QStringList OpenDialog::SeparateEntries( QString entries )
301 {
302     bool b_quotes_mode = false;
303
304     QStringList entries_array;
305     QString entry;
306
307     int index = 0;
308     while( index < entries.size() )
309     {
310         int delim_pos = entries.indexOf( QRegExp( "\\s+|\"" ), index );
311         if( delim_pos < 0 ) delim_pos = entries.size() - 1;
312         entry += entries.mid( index, delim_pos - index + 1 );
313         index = delim_pos + 1;
314
315         if( entry.isEmpty() ) continue;
316
317         if( !b_quotes_mode && entry.endsWith( "\"" ) )
318         {
319             /* Enters quotes mode */
320             entry.truncate( entry.size() - 1 );
321             b_quotes_mode = true;
322         }
323         else if( b_quotes_mode && entry.endsWith( "\"" ) )
324         {
325             /* Finished the quotes mode */
326             entry.truncate( entry.size() - 1 );
327             b_quotes_mode = false;
328         }
329         else if( !b_quotes_mode && !entry.endsWith( "\"" ) )
330         {
331             /* we found a non-quoted standalone string */
332             if( index < entries.size() ||
333                 entry.endsWith( " " ) || entry.endsWith( "\t" ) ||
334                 entry.endsWith( "\r" ) || entry.endsWith( "\n" ) )
335                 entry.truncate( entry.size() - 1 );
336             if( !entry.isEmpty() ) entries_array.append( entry );
337             entry.clear();
338         }
339         else
340         {;}
341     }
342
343     if( !entry.isEmpty() ) entries_array.append( entry );
344
345     return entries_array;
346 }