]> git.sesse.net Git - vlc/blob - modules/gui/qt4/dialogs/extensions.cpp
Qt: EPG in BuildSystem
[vlc] / modules / gui / qt4 / dialogs / extensions.cpp
1 /*****************************************************************************
2  * extensions.cpp: Extensions manager for Qt: dialogs manager
3  ****************************************************************************
4  * Copyright (C) 2009-2010 VideoLAN and authors
5  * $Id$
6  *
7  * Authors: Jean-Philippe AndrĂ© < jpeg # 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 "extensions.hpp"
25 #include "../extensions_manager.hpp" // for isUnloading()
26
27 #include <vlc_dialog.h>
28
29 #include <QGridLayout>
30 #include <QPushButton>
31 #include <QSignalMapper>
32 #include <QLabel>
33 #include <QPixmap>
34 #include <QLineEdit>
35 #include <QTextEdit>
36 #include <QCheckBox>
37 #include <QListWidget>
38 #include <QComboBox>
39 #include <QCloseEvent>
40
41 ExtensionsDialogProvider *ExtensionsDialogProvider::instance = NULL;
42
43 static int DialogCallback( vlc_object_t *p_this, const char *psz_variable,
44                            vlc_value_t old_val, vlc_value_t new_val,
45                            void *param );
46
47
48 ExtensionsDialogProvider::ExtensionsDialogProvider( intf_thread_t *_p_intf,
49                                                     extensions_manager_t *p_mgr )
50         : QObject( NULL ), p_intf( _p_intf ), p_extensions_manager( p_mgr )
51 {
52     // At this point, we consider that the Qt interface already called
53     // dialog_Register() in order to be the extension dialog provider
54     var_Create( p_intf, "dialog-extension", VLC_VAR_ADDRESS );
55     var_AddCallback( p_intf, "dialog-extension", DialogCallback, NULL );
56
57     CONNECT( this, SignalDialog( extension_dialog_t* ),
58              this, UpdateExtDialog( extension_dialog_t* ) );
59 }
60
61 ExtensionsDialogProvider::~ExtensionsDialogProvider()
62 {
63     var_DelCallback( p_intf, "dialog-extension", DialogCallback, NULL );
64 }
65
66 /** Create a dialog
67  * Note: Lock on p_dialog->lock must be held. */
68 ExtensionDialog* ExtensionsDialogProvider::CreateExtDialog(
69         extension_dialog_t *p_dialog )
70 {
71     ExtensionDialog *dialog = new ExtensionDialog( p_intf,
72                                                    p_extensions_manager,
73                                                    p_dialog );
74     p_dialog->p_sys_intf = (void*) dialog;
75     CONNECT( dialog, destroyDialog( extension_dialog_t* ),
76              this, DestroyExtDialog( extension_dialog_t* ) );
77     return dialog;
78 }
79
80 /** Destroy a dialog
81  * Note: Lock on p_dialog->lock must be held. */
82 int ExtensionsDialogProvider::DestroyExtDialog( extension_dialog_t *p_dialog )
83 {
84     assert( p_dialog );
85     ExtensionDialog *dialog = ( ExtensionDialog* ) p_dialog->p_sys_intf;
86     if( !dialog )
87         return VLC_EGENERIC;
88     delete dialog;
89     p_dialog->p_sys_intf = NULL;
90     return VLC_SUCCESS;
91 }
92
93 /**
94  * Update/Create/Destroy a dialog
95  **/
96 ExtensionDialog* ExtensionsDialogProvider::UpdateExtDialog(
97         extension_dialog_t *p_dialog )
98 {
99     assert( p_dialog );
100
101     ExtensionDialog *dialog = ( ExtensionDialog* ) p_dialog->p_sys_intf;
102     if( p_dialog->b_kill && !dialog )
103     {
104         /* This extension could not be activated properly but tried
105            to create a dialog. We must ignore it. */
106         return NULL;
107     }
108
109     vlc_mutex_lock( &p_dialog->lock );
110     if( !p_dialog->b_kill && !dialog )
111     {
112         dialog = CreateExtDialog( p_dialog );
113         dialog->setVisible( !p_dialog->b_hide );
114     }
115     else if( !p_dialog->b_kill && dialog )
116     {
117         dialog->has_lock = true;
118         dialog->UpdateWidgets();
119         dialog->has_lock = false;
120         dialog->setVisible( !p_dialog->b_hide );
121     }
122     else if( p_dialog->b_kill )
123     {
124         DestroyExtDialog( p_dialog );
125     }
126     vlc_cond_signal( &p_dialog->cond );
127     vlc_mutex_unlock( &p_dialog->lock );
128     return dialog;
129 }
130
131 /**
132  * Ask the dialog manager to create/update/kill the dialog. Thread-safe.
133  **/
134 void ExtensionsDialogProvider::ManageDialog( extension_dialog_t *p_dialog )
135 {
136     assert( p_dialog );
137     ExtensionsManager *extMgr = ExtensionsManager::getInstance( p_intf );
138     assert( extMgr != NULL );
139     if( !extMgr->isUnloading() )
140         emit SignalDialog( p_dialog ); // Safe because we signal Qt thread
141     else
142         UpdateExtDialog( p_dialog ); // This is safe, we're already in Qt thread
143 }
144
145 /**
146  * Ask the dialogs provider to create a new dialog
147  **/
148 static int DialogCallback( vlc_object_t *p_this, const char *psz_variable,
149                            vlc_value_t old_val, vlc_value_t new_val,
150                            void *param )
151 {
152     (void) p_this;
153     (void) psz_variable;
154     (void) old_val;
155     (void) param;
156
157     ExtensionsDialogProvider *p_edp = ExtensionsDialogProvider::getInstance();
158     if( !p_edp )
159         return VLC_EGENERIC;
160     if( !new_val.p_address )
161         return VLC_EGENERIC;
162
163     extension_dialog_t *p_dialog = ( extension_dialog_t* ) new_val.p_address;
164     p_edp->ManageDialog( p_dialog );
165     return VLC_SUCCESS;
166 }
167
168
169 ExtensionDialog::ExtensionDialog( intf_thread_t *_p_intf,
170                                   extensions_manager_t *p_mgr,
171                                   extension_dialog_t *_p_dialog )
172          : QDialog( NULL ), p_intf( _p_intf ), p_extensions_manager( p_mgr )
173          , p_dialog( _p_dialog ), has_lock(false)
174 {
175     assert( p_dialog );
176
177     msg_Dbg( p_intf, "Creating a new dialog: '%s'", p_dialog->psz_title );
178 #if HAS_QT45
179     this->setWindowFlags( Qt::WindowMinMaxButtonsHint
180                         | Qt::WindowCloseButtonHint );
181 #else
182     this->setWindowFlags( Qt::WindowMinMaxButtonsHint );
183 #endif
184
185     this->setWindowTitle( qfu( p_dialog->psz_title ) );
186
187     layout = new QGridLayout( this );
188     clickMapper = new QSignalMapper( this );
189     CONNECT( clickMapper, mapped( QObject* ), this, TriggerClick( QObject* ) );
190     inputMapper = new QSignalMapper( this );
191     CONNECT( inputMapper, mapped( QObject* ), this, SyncInput( QObject* ) );
192     selectMapper = new QSignalMapper( this );
193     CONNECT( selectMapper, mapped( QObject* ), this, SyncSelection(QObject*) );
194
195     UpdateWidgets();
196 }
197
198 ExtensionDialog::~ExtensionDialog()
199 {
200     msg_Dbg( p_intf, "Deleting extension dialog '%s'", qtu(windowTitle()) );
201     p_dialog->p_sys_intf = NULL;
202 }
203
204 QWidget* ExtensionDialog::CreateWidget( extension_widget_t *p_widget )
205 {
206     QLabel *label = NULL;
207     QPushButton *button = NULL;
208     QTextEdit *textArea = NULL;
209     QLineEdit *textInput = NULL;
210     QCheckBox *checkBox = NULL;
211     QComboBox *comboBox = NULL;
212     QListWidget *list = NULL;
213     struct extension_widget_t::extension_widget_value_t *p_value = NULL;
214
215     assert( p_widget->p_sys_intf == NULL );
216
217     switch( p_widget->type )
218     {
219         case EXTENSION_WIDGET_LABEL:
220             label = new QLabel( qfu( p_widget->psz_text ), this );
221             p_widget->p_sys_intf = label;
222             label->setTextFormat( Qt::RichText );
223             //label->setFixedHeight( label->sizeHint().height );
224             return label;
225
226         case EXTENSION_WIDGET_BUTTON:
227             button = new QPushButton( qfu( p_widget->psz_text ), this );
228             clickMapper->setMapping( button, new WidgetMapper( p_widget ) );
229             CONNECT( button, clicked(), clickMapper, map() );
230             p_widget->p_sys_intf = button;
231             return button;
232
233         case EXTENSION_WIDGET_IMAGE:
234             label = new QLabel( this );
235             label->setPixmap( QPixmap( qfu( p_widget->psz_text ) ) );
236             if( p_widget->i_width > 0 )
237                 label->setMaximumWidth( p_widget->i_width );
238             if( p_widget->i_height > 0 )
239                 label->setMaximumHeight( p_widget->i_height );
240             label->setScaledContents( true );
241             p_widget->p_sys_intf = label;
242             return label;
243
244         case EXTENSION_WIDGET_HTML:
245             textArea = new QTextEdit( this );
246             textArea->setAcceptRichText( true );
247             textArea->setReadOnly( true );
248             textArea->setHtml( qfu( p_widget->psz_text ) );
249             p_widget->p_sys_intf = textArea;
250             return textArea;
251
252         case EXTENSION_WIDGET_TEXT_FIELD:
253             textInput = new QLineEdit( this );
254             textInput->setText( qfu( p_widget->psz_text ) );
255             textInput->setReadOnly( false );
256             textInput->setEchoMode( QLineEdit::Normal );
257             inputMapper->setMapping( textInput, new WidgetMapper( p_widget ) );
258             /// @note: maybe it would be wiser to use textEdited here?
259             CONNECT( textInput, textChanged(const QString &),
260                      inputMapper, map() );
261             p_widget->p_sys_intf = textInput;
262             return textInput;
263
264         case EXTENSION_WIDGET_PASSWORD:
265             textInput = new QLineEdit( this );
266             textInput->setText( qfu( p_widget->psz_text ) );
267             textInput->setReadOnly( false );
268             textInput->setEchoMode( QLineEdit::Password );
269             inputMapper->setMapping( textInput, new WidgetMapper( p_widget ) );
270             /// @note: maybe it would be wiser to use textEdited here?
271             CONNECT( textInput, textChanged(const QString &),
272                      inputMapper, map() );
273             p_widget->p_sys_intf = textInput;
274             return textInput;
275
276         case EXTENSION_WIDGET_CHECK_BOX:
277             checkBox = new QCheckBox( this );
278             checkBox->setText( qfu( p_widget->psz_text ) );
279             checkBox->setChecked( p_widget->b_checked );
280             clickMapper->setMapping( checkBox, new WidgetMapper( p_widget ) );
281             CONNECT( checkBox, stateChanged( int ), clickMapper, map() );
282             p_widget->p_sys_intf = checkBox;
283             return checkBox;
284
285         case EXTENSION_WIDGET_DROPDOWN:
286             comboBox = new QComboBox( this );
287             comboBox->setEditable( false );
288             for( p_value = p_widget->p_values;
289                  p_value != NULL;
290                  p_value = p_value->p_next )
291             {
292                 comboBox->addItem( qfu( p_value->psz_text ), p_value->i_id );
293             }
294             /* Set current item */
295             if( p_widget->psz_text )
296             {
297                 int idx = comboBox->findText( qfu( p_widget->psz_text ) );
298                 if( idx >= 0 )
299                     comboBox->setCurrentIndex( idx );
300             }
301             selectMapper->setMapping( comboBox, new WidgetMapper( p_widget ) );
302             CONNECT( comboBox, currentIndexChanged( const QString& ),
303                      selectMapper, map() );
304             return comboBox;
305
306         case EXTENSION_WIDGET_LIST:
307             list = new QListWidget( this );
308             list->setSelectionMode( QAbstractItemView::MultiSelection );
309             for( p_value = p_widget->p_values;
310                  p_value != NULL;
311                  p_value = p_value->p_next )
312             {
313                 QListWidgetItem *item =
314                     new QListWidgetItem( qfu( p_value->psz_text ) );
315                 item->setData( Qt::UserRole, p_value->i_id );
316                 list->addItem( item );
317             }
318             selectMapper->setMapping( list, new WidgetMapper( p_widget ) );
319             CONNECT( list, itemSelectionChanged(),
320                      selectMapper, map() );
321             return list;
322
323         default:
324             msg_Err( p_intf, "Widget type %d unknown", p_widget->type );
325             return NULL;
326     }
327 }
328
329 /**
330  * Forward click event to the extension
331  * @param object A WidgetMapper, whose data() is the p_widget
332  **/
333 int ExtensionDialog::TriggerClick( QObject *object )
334 {
335     assert( object != NULL );
336     WidgetMapper *mapping = static_cast< WidgetMapper* >( object );
337     extension_widget_t *p_widget = mapping->getWidget();
338
339     QCheckBox *checkBox = NULL;
340     int i_ret = VLC_EGENERIC;
341
342     bool lockedHere = false;
343     if( !has_lock )
344     {
345         vlc_mutex_lock( &p_dialog->lock );
346         has_lock = true;
347         lockedHere = true;
348     }
349
350     switch( p_widget->type )
351     {
352         case EXTENSION_WIDGET_BUTTON:
353             i_ret = extension_WidgetClicked( p_dialog, p_widget );
354             break;
355
356         case EXTENSION_WIDGET_CHECK_BOX:
357             checkBox = static_cast< QCheckBox* >( p_widget->p_sys_intf );
358             p_widget->b_checked = checkBox->isChecked();
359             i_ret = VLC_SUCCESS;
360             break;
361
362         default:
363             msg_Dbg( p_intf, "A click event was triggered by a wrong widget" );
364             break;
365     }
366
367     if( lockedHere )
368     {
369         vlc_mutex_unlock( &p_dialog->lock );
370         has_lock = false;
371     }
372
373     return i_ret;
374 }
375
376 /**
377  * Synchronize psz_text with the widget's text() value on update
378  * @param object A WidgetMapper
379  **/
380 void ExtensionDialog::SyncInput( QObject *object )
381 {
382     assert( object != NULL );
383
384     bool lockedHere = false;
385     if( !has_lock )
386     {
387         vlc_mutex_lock( &p_dialog->lock );
388         has_lock = true;
389         lockedHere = true;
390     }
391
392     WidgetMapper *mapping = static_cast< WidgetMapper* >( object );
393     extension_widget_t *p_widget = mapping->getWidget();
394     assert( p_widget->type == EXTENSION_WIDGET_TEXT_FIELD
395             || p_widget->type == EXTENSION_WIDGET_PASSWORD );
396     /* Synchronize psz_text with the new value */
397     QLineEdit *widget = static_cast< QLineEdit* >( p_widget->p_sys_intf );
398     char *psz_text = widget->text().isNull() ? NULL : strdup( qtu( widget->text() ) );
399     free( p_widget->psz_text );
400     p_widget->psz_text =  psz_text;
401
402     if( lockedHere )
403     {
404         vlc_mutex_unlock( &p_dialog->lock );
405         has_lock = false;
406     }
407 }
408
409 /**
410  * Synchronize parameter b_selected in the values list
411  * @param object A WidgetMapper
412  **/
413 void ExtensionDialog::SyncSelection( QObject *object )
414 {
415     assert( object != NULL );
416     struct extension_widget_t::extension_widget_value_t *p_value;
417
418     bool lockedHere = false;
419     if( !has_lock )
420     {
421         vlc_mutex_lock( &p_dialog->lock );
422         has_lock = true;
423         lockedHere = true;
424     }
425
426     WidgetMapper *mapping = static_cast< WidgetMapper* >( object );
427     extension_widget_t *p_widget = mapping->getWidget();
428     assert( p_widget->type == EXTENSION_WIDGET_DROPDOWN
429             || p_widget->type == EXTENSION_WIDGET_LIST );
430
431     if( p_widget->type == EXTENSION_WIDGET_DROPDOWN )
432     {
433         QComboBox *combo = static_cast< QComboBox* >( p_widget->p_sys_intf );
434         for( p_value = p_widget->p_values;
435              p_value != NULL;
436              p_value = p_value->p_next )
437         {
438 //             if( !qstrcmp( p_value->psz_text, qtu( combo->currentText() ) ) )
439             if( combo->itemData( combo->currentIndex(), Qt::UserRole ).toInt()
440                 == p_value->i_id )
441             {
442                 p_value->b_selected = true;
443             }
444             else
445             {
446                 p_value->b_selected = false;
447             }
448         }
449         free( p_widget->psz_text );
450         p_widget->psz_text = strdup( qtu( combo->currentText() ) );
451     }
452     else if( p_widget->type == EXTENSION_WIDGET_LIST )
453     {
454         QListWidget *list = static_cast<QListWidget*>( p_widget->p_sys_intf );
455         QList<QListWidgetItem *> selection = list->selectedItems();
456         for( p_value = p_widget->p_values;
457              p_value != NULL;
458              p_value = p_value->p_next )
459         {
460             bool b_selected = false;
461             foreach( const QListWidgetItem *item, selection )
462             {
463 //                 if( !qstrcmp( qtu( item->text() ), p_value->psz_text ) )
464                 if( item->data( Qt::UserRole ).toInt() == p_value->i_id )
465                 {
466                     b_selected = true;
467                     break;
468                 }
469             }
470             p_value->b_selected = b_selected;
471         }
472     }
473
474     if( lockedHere )
475     {
476         vlc_mutex_unlock( &p_dialog->lock );
477         has_lock = false;
478     }
479 }
480
481 void ExtensionDialog::UpdateWidgets()
482 {
483     assert( p_dialog );
484     extension_widget_t *p_widget;
485     FOREACH_ARRAY( p_widget, p_dialog->widgets )
486     {
487         if( !p_widget ) continue; /* Some widgets may be NULL at this point */
488         QWidget *widget;
489         int row = p_widget->i_row - 1;
490         int col = p_widget->i_column - 1;
491         if( row < 0 )
492         {
493             row = layout->rowCount();
494             col = 0;
495         }
496         else if( col < 0 )
497             col = layout->columnCount();
498         int hsp = __MAX( 1, p_widget->i_horiz_span );
499         int vsp = __MAX( 1, p_widget->i_vert_span );
500         if( !p_widget->p_sys_intf && !p_widget->b_kill )
501         {
502             widget = CreateWidget( p_widget );
503             if( !widget )
504             {
505                 msg_Warn( p_intf, "Could not create a widget for dialog %s",
506                           p_dialog->psz_title );
507                 continue;
508             }
509             widget->setVisible( !p_widget->b_hide );
510             layout->addWidget( widget, row, col, vsp, hsp );
511             if( ( p_widget->i_width > 0 ) && ( p_widget->i_height > 0 ) )
512                 widget->resize( p_widget->i_width, p_widget->i_height );
513             p_widget->p_sys_intf = widget;
514             this->resize( sizeHint() );
515         }
516         else if( p_widget->p_sys_intf && !p_widget->b_kill
517                  && p_widget->b_update )
518         {
519             widget = UpdateWidget( p_widget );
520             if( !widget )
521             {
522                 msg_Warn( p_intf, "Could not update a widget for dialog %s",
523                           p_dialog->psz_title );
524                 return;
525             }
526             widget->setVisible( !p_widget->b_hide );
527             layout->addWidget( widget, row, col, vsp, hsp );
528             if( ( p_widget->i_width > 0 ) && ( p_widget->i_height > 0 ) )
529                 widget->resize( p_widget->i_width, p_widget->i_height );
530             p_widget->p_sys_intf = widget;
531             this->resize( sizeHint() );
532
533             /* Do not update again */
534             p_widget->b_update = false;
535         }
536         else if( p_widget->p_sys_intf && p_widget->b_kill )
537         {
538             DestroyWidget( p_widget );
539             p_widget->p_sys_intf = NULL;
540             this->resize( sizeHint() );
541         }
542     }
543     FOREACH_END()
544 }
545
546 QWidget* ExtensionDialog::UpdateWidget( extension_widget_t *p_widget )
547 {
548     QLabel *label = NULL;
549     QPushButton *button = NULL;
550     QTextEdit *textArea = NULL;
551     QLineEdit *textInput = NULL;
552     QCheckBox *checkBox = NULL;
553     QComboBox *comboBox = NULL;
554     QListWidget *list = NULL;
555     struct extension_widget_t::extension_widget_value_t *p_value = NULL;
556
557     assert( p_widget->p_sys_intf != NULL );
558
559     switch( p_widget->type )
560     {
561         case EXTENSION_WIDGET_LABEL:
562             label = static_cast< QLabel* >( p_widget->p_sys_intf );
563             label->setText( qfu( p_widget->psz_text ) );
564             return label;
565
566         case EXTENSION_WIDGET_BUTTON:
567             // FIXME: looks like removeMappings does not work
568             button = static_cast< QPushButton* >( p_widget->p_sys_intf );
569             button->setText( qfu( p_widget->psz_text ) );
570             clickMapper->removeMappings( button );
571             clickMapper->setMapping( button, new WidgetMapper( p_widget ) );
572             CONNECT( button, clicked(), clickMapper, map() );
573             return button;
574
575         case EXTENSION_WIDGET_IMAGE:
576             label = static_cast< QLabel* >( p_widget->p_sys_intf );
577             label->setPixmap( QPixmap( qfu( p_widget->psz_text ) ) );
578             return label;
579
580         case EXTENSION_WIDGET_HTML:
581             textArea = static_cast< QTextEdit* >( p_widget->p_sys_intf );
582             textArea->setHtml( qfu( p_widget->psz_text ) );
583             return textArea;
584
585         case EXTENSION_WIDGET_TEXT_FIELD:
586             textInput = static_cast< QLineEdit* >( p_widget->p_sys_intf );
587             textInput->setText( qfu( p_widget->psz_text ) );
588             return textInput;
589
590         case EXTENSION_WIDGET_PASSWORD:
591             textInput = static_cast< QLineEdit* >( p_widget->p_sys_intf );
592             textInput->setText( qfu( p_widget->psz_text ) );
593             return textInput;
594
595         case EXTENSION_WIDGET_CHECK_BOX:
596             checkBox = static_cast< QCheckBox* >( p_widget->p_sys_intf );
597             checkBox->setText( qfu( p_widget->psz_text ) );
598             checkBox->setChecked( p_widget->b_checked );
599             return checkBox;
600
601         case EXTENSION_WIDGET_DROPDOWN:
602             comboBox = static_cast< QComboBox* >( p_widget->p_sys_intf );
603             comboBox->clear();
604             for( p_value = p_widget->p_values;
605                  p_value != NULL;
606                  p_value = p_value->p_next )
607             {
608                 comboBox->addItem( qfu( p_value->psz_text ), p_value->i_id );
609             }
610             /* Set current item */
611             if( p_widget->psz_text )
612             {
613                 int idx = comboBox->findText( qfu( p_widget->psz_text ) );
614                 if( idx >= 0 )
615                     comboBox->setCurrentIndex( idx );
616             }
617             return comboBox;
618
619         case EXTENSION_WIDGET_LIST:
620             list = static_cast< QListWidget* >( p_widget->p_sys_intf );
621             list->clear();
622             for( p_value = p_widget->p_values;
623                  p_value != NULL;
624                  p_value = p_value->p_next )
625             {
626                 QListWidgetItem *item =
627                         new QListWidgetItem( qfu( p_value->psz_text ) );
628                 item->setData( Qt::UserRole, p_value->i_id );
629                 list->addItem( item );
630             }
631             return list;
632
633         default:
634             msg_Err( p_intf, "Widget type %d unknown", p_widget->type );
635             return NULL;
636     }
637 }
638
639 void ExtensionDialog::DestroyWidget( extension_widget_t *p_widget )
640 {
641     assert( p_widget && p_widget->b_kill );
642     QWidget *widget = static_cast< QWidget* >( p_widget->p_sys_intf );
643     delete widget;
644     p_widget->p_sys_intf = NULL;
645 }
646
647 /** Implement closeEvent() in order to intercept the event */
648 void ExtensionDialog::closeEvent( QCloseEvent *event )
649 {
650     assert( p_dialog != NULL );
651     extension_DialogClosed( p_dialog );
652     event->accept();
653     emit destroyDialog( p_dialog );
654 }
655