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