* debian/changelog: Changelog for the forthcoming 0.6.0+cvs-20030704-1 Debian
[vlc.git] / modules / gui / kde / preferences.cpp
1 /*****************************************************************************
2  * preferences.cpp: preferences window for the kde gui
3  *****************************************************************************
4  * Copyright (C) 2001 VideoLAN
5  * $Id: preferences.cpp,v 1.17 2003/07/04 16:35:20 sam Exp $
6  *
7  * Authors: Sigmund Augdal <sigmunau@idi.ntnu.no> Mon Aug 12 2002
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., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23 #include <kdialogbase.h>
24 #include <qmap.h>
25 #include <qcheckbox.h>
26 #include <qframe.h>
27 #include <qgroupbox.h>
28 #include <qlayout.h>
29 #include <qlabel.h>
30 #include <qlistview.h>
31 #include <qnamespace.h>
32 #include <qobjectlist.h>
33 #include <qslider.h>
34 #include <qspinbox.h>
35 #include <qtooltip.h>
36 #include <qvbox.h>
37
38 #include <kbuttonbox.h>
39 #include <klineedit.h>
40 #include <klocale.h>
41 #include <knuminput.h>
42 #include <kurlrequester.h>
43 #include <kfiledialog.h>
44 #include <kcombobox.h>
45
46 #include "QConfigItem.h"
47 #include "pluginsbox.h"
48 #include "preferences.h"
49
50 /*
51   construct a new configuration window for the given module
52 */
53 KPreferences::KPreferences(intf_thread_t *p_intf, const char *psz_module_name,
54                            QWidget *parent, const QString &caption) :
55     KDialogBase ( TreeList, caption, Ok| Apply|Cancel|User1, Ok, parent,
56                   "vlc preferences", true, false, i18n("&Save") )
57 {
58     module_t *p_parser = NULL;
59     vlc_list_t *p_list;
60     module_config_t *p_item;
61     int i_index;
62     QVBox *category_table = NULL;
63     QString *category_label;
64
65     this->p_intf = p_intf;
66
67     /* List all modules */
68     p_list = vlc_list_find( p_intf, VLC_OBJECT_MODULE, FIND_ANYWHERE );
69
70     for( i_index = 0; i_index < p_list->i_count; i_index++ )
71     {
72         p_parser = (module_t *)p_list->p_values[i_index].p_object ;
73         p_item = p_parser->p_config;
74         while( p_item && p_item->i_type != CONFIG_HINT_END )
75         {
76             switch( p_item->i_type )
77             {
78             case CONFIG_HINT_CATEGORY:
79                 /* force the content to the top of the page */
80                 if ( category_table )
81                 {
82                     QWidget *space = new QWidget( category_table );
83                     category_table->setStretchFactor( space, 10 );
84                     category_table = NULL;
85                 }
86                 
87                 /*
88                  * Now we can start taking care of the new category
89                  */
90                 if( p_item->i_type == CONFIG_HINT_CATEGORY )
91                 {
92                     category_label = new QString( p_item->psz_text );
93                     QStringList path;
94                     if ( strcmp( p_parser->psz_object_name, "main" ) )
95                     {
96                         path += _( "Plugins" );
97                         path += p_parser->psz_capability;
98                         path += p_parser->psz_object_name;
99                     }
100                     path += *category_label;
101                     QFrame *page = addPage( path );
102                     QVBoxLayout *toplayout = new QVBoxLayout( page);
103                     QScrollView *sv = new QScrollView(page);
104                     sv->setResizePolicy(QScrollView::AutoOneFit);
105                     sv->setFrameStyle(QScrollView::NoFrame);
106                     toplayout->addWidget(sv);
107                     category_table = new QVBox(sv->viewport());
108                     sv->addChild(category_table);
109                     category_table->setSpacing(spacingHint());
110                 }
111
112                 break;
113
114             case CONFIG_ITEM_MODULE:
115
116             {
117                 vlc_mutex_lock( p_item->p_lock );
118                 KPluginsBox *item_frame =
119                     new KPluginsBox( p_intf, p_item->psz_text,
120                                      p_item->psz_value ? p_item->psz_value :"",
121                                      category_table,
122                                      spacingHint(),
123                                      this );
124                 QConfigItem *ci = new QConfigItem(this,
125                                                   p_item->psz_name,
126                                                   p_item->i_type,
127                                                   p_item->psz_value);
128                 connect(item_frame, SIGNAL(selectionChanged(const QString &)),
129                         ci, SLOT(setValue(const QString &)));
130
131
132                 /* build a list of available plugins */
133                 for( int i_index = 0; i_index < p_list->i_count; i_index++ )
134                 {
135                     module_t *p_parser = (module_t *)p_list->p_values[i_index].p_object ;
136
137                     if( !strcmp( p_parser->psz_capability,
138                                  p_item->psz_type ) )
139                     {
140                         new QListViewItem(item_frame->getListView(),
141                                           p_parser->psz_object_name,
142                                           p_parser->psz_longname);
143                     }
144                 }
145
146                 vlc_mutex_unlock( p_item->p_lock );
147             }
148             break;
149
150             case CONFIG_ITEM_STRING:
151             {
152                 QHBox *hb = new QHBox(category_table);
153                 hb->setSpacing(spacingHint());
154                 new QLabel(p_item->psz_text, hb);
155                 /* add input box with default value */
156                 vlc_mutex_lock( p_item->p_lock );
157                 QConfigItem *ci = new QConfigItem(this, p_item->psz_name,
158                                                   p_item->i_type,
159                                                   p_item->psz_value ?
160                                                   p_item->psz_value : "");
161                 if ( p_item->ppsz_list )
162                 {
163                     char **ppsz_list = p_item->ppsz_list;
164                     KComboBox *p_combobox = new KComboBox( true, hb );
165                     QToolTip::add(p_combobox, p_item->psz_longtext);
166                     connect(p_combobox, SIGNAL(activated ( const QString & )),
167                             ci, SLOT(setValue( const QString &)));
168                     while ( *ppsz_list )
169                     {
170                         p_combobox->insertItem( *ppsz_list );
171                         if ( !strcmp( *ppsz_list, p_item->psz_value ?
172                                                   p_item->psz_value : "" ) )
173                         {
174 #if KDE_VERSION_MAJOR >= 3
175                             p_combobox->setCurrentText( *ppsz_list );
176 #else
177                             p_combobox->setCurrentItem( p_combobox->count() );
178 #endif
179                         }
180                         ppsz_list++;
181                     }
182                 }
183                 else
184                 {
185                     KLineEdit *kl = new KLineEdit( p_item->psz_value ?
186                                                    p_item->psz_value : "", hb);
187                     connect(kl, SIGNAL(textChanged ( const QString & )),
188                             ci, SLOT(setValue( const QString &)));
189                     QToolTip::add(kl, p_item->psz_longtext);
190                     kl->setMaxLength(40);
191                 }
192
193                 vlc_mutex_unlock( p_item->p_lock );
194             }
195             break;
196
197             case CONFIG_ITEM_FILE:
198             case CONFIG_ITEM_DIRECTORY:
199             {
200                 QHBox *hb = new QHBox(category_table);
201                 hb->setSpacing(spacingHint());
202                 new QLabel(p_item->psz_text, hb);
203                 /* add input box with default value */
204                 vlc_mutex_lock( p_item->p_lock );
205
206 //            KLineEdit *kl = new KLineEdit( p_item->psz_value ?
207 //                                           p_item->psz_value : "", hb);
208                 QConfigItem *ci = new QConfigItem(this, p_item->psz_name,
209                                                   p_item->i_type,
210                                                   p_item->psz_value ?
211                                                   p_item->psz_value : "");
212 //            QPushButton *bbrowse = new QPushButton( _("Browse"), hb );
213                 KURLRequester *kfile = new KURLRequester( p_item->psz_value ?
214                                                           p_item->psz_value : "",
215                                                           hb );
216                 if ( p_item->i_type == CONFIG_ITEM_DIRECTORY )
217                 {
218                     kfile->fileDialog()->setMode(KFile::Directory|KFile::ExistingOnly|KFile::LocalOnly);
219                 }
220                 connect(kfile, SIGNAL(textChanged ( const QString & )),
221                         ci, SLOT(setValue( const QString &)));
222                 QToolTip::add(kfile, p_item->psz_longtext);
223                 vlc_mutex_unlock( p_item->p_lock );
224             }
225             break;
226
227             case CONFIG_ITEM_INTEGER:
228                 /* add input box with default value */
229             {
230                 QHBox *hb = new QHBox(category_table);
231                 hb->setSpacing(spacingHint());
232                 new QLabel(p_item->psz_text, hb);
233                 QConfigItem *ci = new QConfigItem(this, p_item->psz_name,
234                                                   p_item->i_type,
235                                                   p_item->i_value);
236                 if ( p_item->i_min == 0 && p_item->i_max == 0 )
237                 {
238                     QSpinBox *item_adj = new QSpinBox(-1, 99999, 1, hb);
239                     item_adj->setValue( p_item->i_value );
240                     connect(item_adj, SIGNAL(valueChanged( int)),
241                             ci, SLOT(setValue(int)));
242                     QToolTip::add(item_adj, p_item->psz_longtext);
243                 }
244                 else
245                 {
246                     KIntNumInput *p_ii = new KIntNumInput( p_item->i_value, hb );
247                     p_ii->setRange( p_item->i_min, p_item->i_max, 1, true ); 
248                     connect( p_ii, SIGNAL( valueChanged( int ) ),
249                              ci, SLOT( setValue( int ) ) );
250                     QToolTip::add( p_ii, p_item->psz_longtext );
251                 }
252             }
253             break;
254
255             case CONFIG_ITEM_FLOAT:
256             {
257                 QHBox *hb = new QHBox(category_table);
258                 hb->setSpacing(spacingHint());
259                 new QLabel(p_item->psz_text, hb);
260                 KDoubleNumInput *kdi= new KDoubleNumInput(p_item->f_value, hb);
261                 if ( p_item->f_min == 0 && p_item->f_max == 0 )
262                 {
263                     kdi->setRange(-1, 99999, 0.01, false);
264                 }
265                 else
266                 {
267                     kdi->setRange( p_item->f_min, p_item->f_max, 0.01, true );
268                 }
269                 QConfigItem *ci = new QConfigItem(this, p_item->psz_name,
270                                                   p_item->i_type,
271                                                   p_item->f_value);
272                 connect(kdi, SIGNAL(valueChanged(double)),
273                         ci, SLOT(setValue(double)));
274                 QToolTip::add(kdi, p_item->psz_longtext);
275             }
276             break;
277
278             case CONFIG_ITEM_BOOL:
279
280                 /* add check button */
281             {
282                 QCheckBox *bool_checkbutton =
283                     new QCheckBox(QString(p_item->psz_text), category_table);
284                 QConfigItem *ci = new QConfigItem(this, p_item->psz_name,
285                                                   p_item->i_type,
286                                                   p_item->i_value);
287                 bool_checkbutton->setChecked(p_item->i_value);
288                 connect(bool_checkbutton, SIGNAL(stateChanged( int)),
289                         ci, SLOT(setValue(int)));
290                 QToolTip::add(bool_checkbutton, p_item->psz_longtext);
291
292             }
293             break;
294
295             }
296             
297             p_item++;
298         }
299     }
300     /* force the content to the top of the page, even on the last page */
301     if ( category_table )
302     {
303         QWidget *space = new QWidget( category_table );
304         category_table->setStretchFactor( space, 10 );
305         category_table = NULL;
306     }
307                 
308
309     vlc_list_release( p_list );
310
311     exec();
312 }
313
314 /*
315   empty destructor, qt takes care of this (I think)
316 */
317 KPreferences::~KPreferences()
318 {
319 }
320
321 /*
322   return true if the give module is configureable
323 */
324 bool KPreferences::isConfigureable(QString module)
325 {
326     module_t *p_parser;
327     vlc_list_t *p_list;
328     int i_index;
329
330     p_list = vlc_list_find( this->p_intf, VLC_OBJECT_MODULE, FIND_ANYWHERE );
331
332     for( i_index = 0; i_index < p_list->i_count; i_index++ )
333     {
334         p_parser = (module_t *)p_list->p_values[i_index].p_object ;
335
336         if( !module.compare( p_parser->psz_object_name ) )
337         {
338             bool ret = p_parser->i_config_items != 0;
339             vlc_list_release( p_list );
340             return ret;
341         }
342     }
343
344     vlc_list_release( p_list );
345     return false;
346 }
347
348 /*
349   run when the Apply button is pressed, and by the methods for the ok
350   and save buttons
351 */
352 void KPreferences::slotApply()
353 {
354     QObjectList * l = queryList( "QConfigItem" );
355     QObjectListIt it( *l );             // iterate over the config items
356     QObject * obj;
357     while ( (obj=it.current()) != 0 ) {
358         ++it;
359         QConfigItem *p_config = (QConfigItem *)obj;
360         if ( p_config->changed() )
361         {
362             msg_Dbg( p_intf, const_cast<char *>(p_config->name()));
363             msg_Dbg( p_intf, "%d", p_config->getType());
364
365             switch( p_config->getType() ) {
366
367             case CONFIG_ITEM_DIRECTORY:
368             case CONFIG_ITEM_STRING:
369             case CONFIG_ITEM_FILE:
370             case CONFIG_ITEM_MODULE:
371                 if (p_config->sValue()) {
372                     config_PutPsz( p_intf, p_config->name(),
373                                    strdup(p_config->sValue().latin1()));
374                 }
375                 else {
376                     config_PutPsz( p_intf, p_config->name(), NULL );
377                 }
378                 break;
379             case CONFIG_ITEM_INTEGER:
380             case CONFIG_ITEM_BOOL:
381                 config_PutInt( p_intf, p_config->name(), p_config->iValue() );
382                 break;
383             case CONFIG_ITEM_FLOAT:
384                 config_PutFloat( p_intf, p_config->name(), p_config->fValue() );
385                 break;
386             }
387             p_config->resetChanged();
388         }
389     }
390     delete l;
391 }
392
393 /*
394   run when the Ok button is pressed
395 */
396 void KPreferences::slotOk()
397 {
398     slotApply();
399     accept();
400 }
401
402 /*
403   run when the save button is pressed
404 */
405 void KPreferences::slotUser1()
406 {
407     slotApply();
408     config_SaveConfigFile( p_intf, NULL );
409 }