Destroy preferences dialog on close and on reset.
[vlc.git] / modules / gui / qt4 / dialogs / preferences.cpp
1 /*****************************************************************************
2  * preferences.cpp : Preferences
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 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #include "dialogs/preferences.hpp"
30 #include "dialogs_provider.hpp"
31 #include "util/qvlcframe.hpp"
32
33 #include "components/complete_preferences.hpp"
34 #include "components/simple_preferences.hpp"
35
36 #include <QHBoxLayout>
37 #include <QGroupBox>
38 #include <QRadioButton>
39 #include <QVBoxLayout>
40 #include <QPushButton>
41 #include <QCheckBox>
42 #include <QMessageBox>
43 #include <QDialogButtonBox>
44
45 PrefsDialog *PrefsDialog::instance = NULL;
46
47 PrefsDialog::PrefsDialog( QWidget *parent, intf_thread_t *_p_intf )
48             : QVLCDialog( parent, _p_intf )
49 {
50     QGridLayout *main_layout = new QGridLayout( this );
51     setWindowTitle( qtr( "Preferences" ) );
52
53     /* Whether we want it or not, we need to destroy on close to get
54        consistency when reset */
55     setAttribute( Qt::WA_DeleteOnClose );
56
57     /* Create Panels */
58     tree_panel = new QWidget;
59     tree_panel_l = new QHBoxLayout;
60     tree_panel->setLayout( tree_panel_l );
61     main_panel = new QWidget;
62     main_panel_l = new QHBoxLayout;
63     main_panel->setLayout( main_panel_l );
64
65     /* Choice for types */
66     types = new QGroupBox( "Show settings" );
67     types->setAlignment( Qt::AlignHCenter );
68     QHBoxLayout *types_l = new QHBoxLayout;
69     types_l->setSpacing( 3 ); types_l->setMargin( 3 );
70     small = new QRadioButton( qtr( "Simple" ), types );
71     types_l->addWidget( small );
72     all = new QRadioButton( qtr("All"), types ); types_l->addWidget( all );
73     types->setLayout( types_l );
74     small->setChecked( true );
75
76     /* Tree and panel initialisations */
77     advanced_tree = NULL;
78     simple_tree = NULL;
79     current_simple_panel  = NULL;
80     advanced_panel = NULL;
81
82     /* Buttons */
83     QDialogButtonBox *buttonsBox = new QDialogButtonBox();
84     QPushButton *save = new QPushButton( qtr( "&Save" ) );
85     QPushButton *cancel = new QPushButton( qtr( "&Cancel" ) );
86     QPushButton *reset = new QPushButton( qtr( "&Reset Preferences" ) );
87
88     buttonsBox->addButton( save, QDialogButtonBox::AcceptRole );
89     buttonsBox->addButton( cancel, QDialogButtonBox::RejectRole );
90     buttonsBox->addButton( reset, QDialogButtonBox::ResetRole );
91
92     /* Layout  */
93     main_layout->addWidget( tree_panel, 0, 0, 3, 1 );
94     main_layout->addWidget( types, 3, 0, 2, 1 );
95     main_layout->addWidget( main_panel, 0, 1, 4, 2 );
96     main_layout->addWidget( buttonsBox, 4, 2, 1 ,1 );
97
98     main_layout->setColumnMinimumWidth( 0, 150 );
99     main_layout->setColumnMinimumWidth( 1, 10 );
100     main_layout->setColumnStretch( 0, 1 );
101     main_layout->setColumnStretch( 1, 0 );
102     main_layout->setColumnStretch( 2, 3 );
103
104     main_layout->setRowStretch( 2, 4 );
105
106     main_layout->setMargin( 9 );
107     setLayout( main_layout );
108
109     /* Margins */
110     tree_panel_l->setMargin( 1 );
111     main_panel_l->setLayoutMargins( 6, 0, 0, 3, 3 );
112
113     for( int i = 0; i < SPrefsMax ; i++ ) simple_panels[i] = NULL;
114
115     if( config_GetInt( p_intf, "qt-advanced-pref" ) == 1 )
116         setAdvanced();
117     else
118         setSmall();
119
120     BUTTONACT( save, save() );
121     BUTTONACT( cancel, cancel() );
122     BUTTONACT( reset, reset() );
123
124     BUTTONACT( small, setSmall() );
125     BUTTONACT( all, setAdvanced() );
126
127     resize( 750, sizeHint().height() );
128 }
129
130 void PrefsDialog::setAdvanced()
131 {
132     /* We already have a simple TREE, and we just want to hide it */
133     if( simple_tree )
134         if( simple_tree->isVisible() ) simple_tree->hide();
135
136     /* If don't have already and advanced TREE, then create it */
137     if( !advanced_tree )
138     {
139         /* Creation */
140          advanced_tree = new PrefsTree( p_intf, tree_panel );
141         /* and connections */
142          CONNECT( advanced_tree,
143                   currentItemChanged( QTreeWidgetItem *, QTreeWidgetItem * ),
144                   this, changeAdvPanel( QTreeWidgetItem * ) );
145         tree_panel_l->addWidget( advanced_tree );
146     }
147
148     /* Show it */
149     advanced_tree->show();
150
151     /* Remove the simple current panel from the main panels*/
152     if( current_simple_panel )
153         if( current_simple_panel->isVisible() ) current_simple_panel->hide();
154
155     /* If no advanced Panel exist, create one, attach it and show it*/
156     if( !advanced_panel )
157     {
158         advanced_panel = new AdvPrefsPanel( main_panel );
159         main_panel_l->addWidget( advanced_panel );
160     }
161     advanced_panel->show();
162
163     /* Select the first Item of the preferences. Maybe you want to select a specified
164        category... */
165     advanced_tree->setCurrentIndex(
166             advanced_tree->model()->index( 0, 0, QModelIndex() ) );
167
168     all->setChecked( true );
169 }
170
171 void PrefsDialog::setSmall()
172 {
173     /* If an advanced TREE exists, remove and hide it */
174     if( advanced_tree )
175         if( advanced_tree->isVisible() ) advanced_tree->hide();
176
177     /* If no simple_tree, create one, connect it */
178     if( !simple_tree )
179     {
180          simple_tree = new SPrefsCatList( p_intf, tree_panel );
181          CONNECT( simple_tree,
182                   currentItemChanged( int ),
183                   this,  changeSimplePanel( int ) );
184         tree_panel_l->addWidget( simple_tree );
185     }
186
187     /*show it */
188     simple_tree->show();
189
190     /* If an Advanced PANEL exists, remove it */
191     if( advanced_panel )
192         if( advanced_panel->isVisible() ) advanced_panel->hide();
193
194     if( !current_simple_panel )
195     {
196         current_simple_panel =
197             new SPrefsPanel( p_intf, main_panel, SPrefsDefaultCat );
198         simple_panels[SPrefsDefaultCat] =  current_simple_panel;
199         main_panel_l->addWidget( current_simple_panel );
200     }
201
202     current_simple_panel->show();
203     small->setChecked( true );
204 }
205
206 /* Switching from on simple panel to another */
207 void PrefsDialog::changeSimplePanel( int number )
208 {
209     if( current_simple_panel )
210         if( current_simple_panel->isVisible() ) current_simple_panel->hide();
211
212     current_simple_panel = simple_panels[number];
213     if( !current_simple_panel )
214     {
215         current_simple_panel  = new SPrefsPanel( p_intf, main_panel, number );
216         simple_panels[number] = current_simple_panel;
217         main_panel_l->addWidget( current_simple_panel );
218     }
219
220     current_simple_panel->show();
221 }
222
223 /* Changing from one Advanced Panel to another */
224 void PrefsDialog::changeAdvPanel( QTreeWidgetItem *item )
225 {
226     PrefsItemData *data = item->data( 0, Qt::UserRole ).value<PrefsItemData*>();
227
228     if( advanced_panel )
229         if( advanced_panel->isVisible() ) advanced_panel->hide();
230
231     if( !data->panel )
232     {
233         data->panel = new AdvPrefsPanel( p_intf, main_panel , data );
234         main_panel_l->addWidget( data->panel );
235     }
236
237     advanced_panel = data->panel;
238     advanced_panel->show();
239 }
240
241 #if 0
242 /*Called from extended settings, is not used anymore, but could be useful one day*/
243 void PrefsDialog::showModulePrefs( char *psz_module )
244 {
245     setAdvanced();
246     all->setChecked( true );
247     for( int i_cat_index = 0 ; i_cat_index < advanced_tree->topLevelItemCount();
248          i_cat_index++ )
249     {
250         QTreeWidgetItem *cat_item = advanced_tree->topLevelItem( i_cat_index );
251         PrefsItemData *data = cat_item->data( 0, Qt::UserRole ).
252                                                    value<PrefsItemData *>();
253         for( int i_sc_index = 0; i_sc_index < cat_item->childCount();
254                                   i_sc_index++ )
255         {
256             QTreeWidgetItem *subcat_item = cat_item->child( i_sc_index );
257             PrefsItemData *sc_data = subcat_item->data(0, Qt::UserRole).
258                                                     value<PrefsItemData *>();
259             for( int i_module = 0; i_module < subcat_item->childCount();
260                                    i_module++ )
261             {
262                 QTreeWidgetItem *module_item = subcat_item->child( i_module );
263                 PrefsItemData *mod_data = module_item->data( 0, Qt::UserRole ).
264                                                     value<PrefsItemData *>();
265                 if( !strcmp( mod_data->psz_name, psz_module ) ) {
266                     advanced_tree->setCurrentItem( module_item );
267                 }
268             }
269         }
270     }
271     show();
272 }
273 #endif
274
275 /* Actual apply and save for the preferences */
276 void PrefsDialog::save()
277 {
278     if( small->isChecked() && simple_tree->isVisible() )
279     {
280         msg_Dbg( p_intf, "Saving the simple preferences" );
281         for( int i = 0 ; i< SPrefsMax; i++ ){
282             if( simple_panels[i] )simple_panels[i]->apply();
283         }
284     }
285     else if( all->isChecked() && advanced_tree->isVisible() )
286     {
287         msg_Dbg( p_intf, "Saving the advanced preferences" );
288         advanced_tree->applyAll();
289     }
290
291     /* Save to file */
292     config_SaveConfigFile( p_intf, NULL );
293
294     destroyPanels();
295
296     hide();
297 }
298
299 void PrefsDialog::destroyPanels()
300 {
301     msg_Dbg( p_intf, "Destroying the Panels" );
302     /* Delete the other panel in order to force its reload after clicking
303        on apply. In fact, if we don't do that, the preferences from the other
304        panels won't be accurate, so we would have to recreate the whole dialog,
305        and we don't want that.*/
306     if( small->isChecked() && advanced_panel )
307     {
308         /* Deleting only the active panel from the advanced config doesn't work
309            because the data records of PrefsItemData  contains still a
310            reference to it only cleanAll() is sure to remove all Panels! */
311         advanced_tree->cleanAll();
312         advanced_panel = NULL;
313     }
314     if( all->isChecked() && current_simple_panel )
315     {
316         for( int i = 0 ; i< SPrefsMax; i++ )
317         {
318             if( simple_panels[i] )
319             {
320                delete simple_panels[i];
321                simple_panels[i] = NULL;
322             }
323         }
324         current_simple_panel  = NULL;
325     }
326 }
327
328
329 /* Clean the preferences, dunno if it does something really */
330 void PrefsDialog::cancel()
331 {
332     if( small->isChecked() && simple_tree )
333     {
334         for( int i = 0 ; i< SPrefsMax; i++ )
335             if( simple_panels[i] ) simple_panels[i]->clean();
336     }
337     else if( all->isChecked() && advanced_tree )
338     {
339         advanced_tree->cleanAll();
340         advanced_panel = NULL;
341     }
342     hide();
343 }
344
345 /* Reset all the preferences, when you click the button */
346 void PrefsDialog::reset()
347 {
348     int ret = QMessageBox::question(
349                  this,
350                  qtr( "Reset Preferences" ),
351                  qtr( "This will reset your VLC media player preferences.\n"
352                       "Are you sure you want to continue?" ),
353                  QMessageBox::Ok | QMessageBox::Cancel,
354                  QMessageBox::Ok);
355
356     if( ret == QMessageBox::Ok )
357     {
358         config_ResetAll( p_intf );
359         config_SaveConfigFile( p_intf, NULL );
360
361         instance = NULL;
362         close();
363     }
364 }