Update ooo320-m1
[ooovba.git] / fpicker / source / unx / gnome / SalGtkFilePicker.cxx
blobbccee1783f426e3f543b922b7b967406bdb0a50f
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: SalGtkFilePicker.cxx,v $
10 * $Revision: 1.28.42.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_fpicker.hxx"
34 //------------------------------------------------------------------------
35 // includes
36 //------------------------------------------------------------------------
37 #include <com/sun/star/lang/DisposedException.hpp>
38 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
39 #include <com/sun/star/container/XNameAccess.hpp>
40 #include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
41 #include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
42 #include <com/sun/star/ui/dialogs/CommonFilePickerElementIds.hpp>
43 #include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
44 #include <cppuhelper/interfacecontainer.h>
45 #include <osl/diagnose.h>
46 #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
47 #include <com/sun/star/ui/dialogs/ControlActions.hpp>
48 #include <com/sun/star/uno/Any.hxx>
49 #include <FPServiceInfo.hxx>
50 #include <vos/mutex.hxx>
51 #include <vcl/svapp.hxx>
52 #include <SalGtkFilePicker.hxx>
54 #include <tools/urlobj.hxx>
56 #include <iostream>
57 #include <algorithm>
58 #include "resourceprovider.hxx"
59 #ifndef _SV_RC_H
60 #include <tools/rc.hxx>
61 #endif
63 //------------------------------------------------------------------------
64 // namespace directives
65 //------------------------------------------------------------------------
67 using namespace ::com::sun::star;
68 using namespace ::com::sun::star::ui::dialogs;
69 using namespace ::com::sun::star::ui::dialogs::TemplateDescription;
70 using namespace ::com::sun::star::ui::dialogs::ExtendedFilePickerElementIds;
71 using namespace ::com::sun::star::ui::dialogs::CommonFilePickerElementIds;
72 using namespace ::com::sun::star::lang;
73 using namespace ::com::sun::star::beans;
74 using namespace ::com::sun::star::uno;
76 //------------------------------------------------------------------------
77 // helper functions
78 //------------------------------------------------------------------------
80 namespace
82 // controling event notifications
83 const bool STARTUP_SUSPENDED = true;
84 const bool STARTUP_ALIVE = false;
86 uno::Sequence<rtl::OUString> SAL_CALL FilePicker_getSupportedServiceNames()
88 uno::Sequence<rtl::OUString> aRet(3);
89 aRet[0] = rtl::OUString::createFromAscii( "com.sun.star.ui.dialogs.FilePicker" );
90 aRet[1] = rtl::OUString::createFromAscii( "com.sun.star.ui.dialogs.SystemFilePicker" );
91 aRet[2] = rtl::OUString::createFromAscii( "com.sun.star.ui.dialogs.GtkFilePicker" );
92 return aRet;
96 //-----------------------------------------------------------------------------------------
97 // constructor
98 //-----------------------------------------------------------------------------------------
100 static void expandexpanders(GtkContainer *pWidget)
102 GList *pChildren = gtk_container_get_children(pWidget);
103 for( GList *p = pChildren; p; p = p->next )
105 if GTK_IS_CONTAINER(GTK_WIDGET(p->data))
106 expandexpanders(GTK_CONTAINER(GTK_WIDGET(p->data)));
107 if GTK_IS_EXPANDER(GTK_WIDGET(p->data))
108 gtk_expander_set_expanded(GTK_EXPANDER(GTK_WIDGET(p->data)), TRUE);
110 g_list_free(pChildren);
113 void SalGtkFilePicker::dialog_mapped_cb(GtkWidget *, SalGtkFilePicker *pobjFP)
115 pobjFP->InitialMapping();
118 void SalGtkFilePicker::InitialMapping()
120 if (!mbPreviewState )
122 gtk_widget_hide( m_pPreview );
123 gtk_file_chooser_set_preview_widget_active( GTK_FILE_CHOOSER( m_pDialog ), false);
125 gtk_widget_set_size_request (m_pPreview, -1, -1);
128 static void lcl_setGTKLanguage(const uno::Reference<lang::XMultiServiceFactory>& xServiceMgr)
130 static bool bSet = false;
131 if (bSet)
132 return;
134 OUString sUILocale;
137 uno::Reference<lang::XMultiServiceFactory> xConfigMgr =
138 uno::Reference<lang::XMultiServiceFactory>(xServiceMgr->createInstance(
139 OUString::createFromAscii("com.sun.star.configuration.ConfigurationProvider")),
140 UNO_QUERY_THROW );
142 Sequence< Any > theArgs(1);
143 theArgs[ 0 ] <<= OUString::createFromAscii("org.openoffice.Office.Linguistic/General");
145 uno::Reference< container::XNameAccess > xNameAccess =
146 uno::Reference< container::XNameAccess >(xConfigMgr->createInstanceWithArguments(
147 OUString::createFromAscii("com.sun.star.configuration.ConfigurationAccess"), theArgs ),
148 UNO_QUERY_THROW );
150 if (xNameAccess.is())
151 xNameAccess->getByName(OUString::createFromAscii("UILocale")) >>= sUILocale;
152 } catch (...) {}
154 if (sUILocale.getLength())
156 sUILocale = rtl::OUString::createFromAscii("LANGUAGE=") + sUILocale.replace('-', '_');
157 putenv(strdup(rtl::OUStringToOString(sUILocale, osl_getThreadTextEncoding()).getStr()));
159 bSet = true;
162 SalGtkFilePicker::SalGtkFilePicker( const uno::Reference<lang::XMultiServiceFactory>& xServiceMgr ) :
163 cppu::WeakComponentImplHelper10<
164 XFilterManager,
165 XFilterGroupManager,
166 XFilePickerControlAccess,
167 XFilePickerNotifier,
168 XFilePreview,
169 XFilePicker2,
170 lang::XInitialization,
171 util::XCancellable,
172 lang::XEventListener,
173 lang::XServiceInfo>( m_rbHelperMtx ),
174 m_xServiceMgr( xServiceMgr ),
175 m_pFilterList( NULL ),
176 m_pVBox ( NULL ),
177 mnHID_FolderChange( 0 ),
178 mnHID_SelectionChange( 0 ),
179 bVersionWidthUnset( false ),
180 mbPreviewState( sal_False ),
181 mHID_Preview( 0 ),
182 m_pPreview( NULL ),
183 m_PreviewImageWidth( 256 ),
184 m_PreviewImageHeight( 256 )
186 lcl_setGTKLanguage(xServiceMgr);
188 int i;
190 for( i = 0; i < TOGGLE_LAST; i++ )
192 m_pToggles[i] = NULL;
193 mbToggleVisibility[i] = false;
196 for( i = 0; i < BUTTON_LAST; i++ )
198 m_pButtons[i] = NULL;
199 mbButtonVisibility[i] = false;
202 for( i = 0; i < LIST_LAST; i++ )
204 m_pHBoxs[i] = NULL;
205 m_pAligns[i] = NULL;
206 m_pLists[i] = NULL;
207 m_pListLabels[i] = NULL;
208 mbListVisibility[i] = false;
211 CResourceProvider aResProvider;
212 OUString aFilePickerTitle = aResProvider.getResString( FILE_PICKER_TITLE_OPEN );
214 m_pDialog = gtk_file_chooser_dialog_new(
215 OUStringToOString( aFilePickerTitle, RTL_TEXTENCODING_UTF8 ).getStr(),
216 NULL,
217 GTK_FILE_CHOOSER_ACTION_OPEN,
218 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
219 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
220 (char *)NULL );
222 gtk_dialog_set_default_response( GTK_DIALOG (m_pDialog), GTK_RESPONSE_ACCEPT );
224 gtk_file_chooser_set_local_only( GTK_FILE_CHOOSER( m_pDialog ), FALSE );
225 gtk_file_chooser_set_select_multiple( GTK_FILE_CHOOSER( m_pDialog ), FALSE );
227 m_pVBox = gtk_vbox_new( FALSE, 0 );
229 // We don't want clickable items to have a huge hit-area
230 GtkWidget *pHBox = gtk_hbox_new( FALSE, 0 );
231 GtkWidget *pThinVBox = gtk_vbox_new( FALSE, 0 );
233 gtk_box_pack_end (GTK_BOX( m_pVBox ), pHBox, FALSE, FALSE, 0);
234 gtk_box_pack_start (GTK_BOX( pHBox ), pThinVBox, FALSE, FALSE, 0);
235 gtk_widget_show( pHBox );
236 gtk_widget_show( pThinVBox );
238 OUString aLabel;
240 for( i = 0; i < TOGGLE_LAST; i++ )
242 m_pToggles[i] = gtk_check_button_new();
244 #define LABEL_TOGGLE( elem ) \
245 case elem : \
246 aLabel = aResProvider.getResString( CHECKBOX_##elem ); \
247 setLabel( CHECKBOX_##elem, aLabel ); \
248 break
250 switch( i ) {
252 LABEL_TOGGLE( AUTOEXTENSION );
253 LABEL_TOGGLE( PASSWORD );
254 LABEL_TOGGLE( FILTEROPTIONS );
255 LABEL_TOGGLE( READONLY );
256 LABEL_TOGGLE( LINK );
257 LABEL_TOGGLE( PREVIEW );
258 LABEL_TOGGLE( SELECTION );
259 default:
260 OSL_TRACE("Handle unknown control %d\n", i);
261 break;
264 gtk_box_pack_end( GTK_BOX( pThinVBox ), m_pToggles[i], FALSE, FALSE, 0 );
267 for( i = 0; i < LIST_LAST; i++ )
269 m_pHBoxs[i] = gtk_hbox_new( FALSE, 0 );
271 m_pAligns[i] = gtk_alignment_new(0, 0, 0, 1);
273 m_pLists[i] = gtk_combo_box_new_text();
275 m_pListLabels[i] = gtk_label_new( "" );
277 #define LABEL_LIST( elem ) \
278 case elem : \
279 aLabel = aResProvider.getResString( LISTBOX_##elem##_LABEL ); \
280 setLabel( LISTBOX_##elem##_LABEL, aLabel ); \
281 break
283 switch( i )
285 LABEL_LIST( VERSION );
286 LABEL_LIST( TEMPLATE );
287 LABEL_LIST( IMAGE_TEMPLATE );
288 default:
289 OSL_TRACE("Handle unknown control %d\n", i);
290 break;
293 gtk_container_add( GTK_CONTAINER( m_pAligns[i]), m_pLists[i] );
294 gtk_box_pack_end( GTK_BOX( m_pHBoxs[i] ), m_pAligns[i], FALSE, FALSE, 0 );
296 gtk_box_pack_end( GTK_BOX( m_pHBoxs[i] ), m_pListLabels[i], FALSE, FALSE, 0 );
298 gtk_box_pack_end( GTK_BOX( m_pVBox ), m_pHBoxs[i], FALSE, FALSE, 0 );
301 aLabel = aResProvider.getResString( FILE_PICKER_FILE_TYPE );
302 m_pFilterExpander = gtk_expander_new_with_mnemonic(
303 OUStringToOString( aLabel, RTL_TEXTENCODING_UTF8 ).getStr());
305 gtk_box_pack_end( GTK_BOX( m_pVBox ), m_pFilterExpander, FALSE, TRUE, 0 );
307 GtkWidget *scrolled_window = gtk_scrolled_window_new (NULL, NULL);
308 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
309 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
310 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window),
311 GTK_SHADOW_IN);
312 gtk_container_add (GTK_CONTAINER (m_pFilterExpander), scrolled_window);
313 gtk_widget_show (scrolled_window);
315 ByteString sExpand(getenv("SAL_EXPANDFPICKER"));
316 sal_Int32 nExpand = sExpand.ToInt32();
317 switch (nExpand)
319 default:
320 case 0:
321 break;
322 case 1:
323 gtk_expander_set_expanded(GTK_EXPANDER(m_pFilterExpander), TRUE);
324 break;
325 case 2:
326 expandexpanders(GTK_CONTAINER(m_pDialog));
327 gtk_expander_set_expanded(GTK_EXPANDER(m_pFilterExpander), TRUE);
328 break;
331 m_pFilterStore = gtk_list_store_new (4, G_TYPE_STRING, G_TYPE_STRING,
332 G_TYPE_STRING, G_TYPE_STRING);
333 m_pFilterView = gtk_tree_view_new_with_model (GTK_TREE_MODEL(m_pFilterStore));
334 gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(m_pFilterView), false);
335 gtk_tree_view_set_rules_hint (GTK_TREE_VIEW(m_pFilterView), true);
337 GtkTreeViewColumn *column;
338 GtkCellRenderer *cell;
340 for (i = 0; i < 2; ++i)
342 column = gtk_tree_view_column_new ();
343 cell = gtk_cell_renderer_text_new ();
344 gtk_tree_view_column_set_expand (column, TRUE);
345 gtk_tree_view_column_pack_start (column, cell, FALSE);
346 gtk_tree_view_column_set_attributes (column, cell, "text", i, (char *)NULL);
347 gtk_tree_view_append_column (GTK_TREE_VIEW(m_pFilterView), column);
350 gtk_container_add (GTK_CONTAINER (scrolled_window), m_pFilterView);
351 gtk_widget_show (m_pFilterView);
353 gtk_file_chooser_set_extra_widget( GTK_FILE_CHOOSER( m_pDialog ), m_pVBox );
355 m_pPreview = gtk_image_new();
356 gtk_file_chooser_set_preview_widget( GTK_FILE_CHOOSER( m_pDialog ), m_pPreview );
358 g_signal_connect( G_OBJECT( m_pToggles[PREVIEW] ), "toggled",
359 G_CALLBACK( preview_toggled_cb ), this );
360 g_signal_connect (gtk_tree_view_get_selection (GTK_TREE_VIEW(m_pFilterView)), "changed",
361 G_CALLBACK ( type_changed_cb ), this);
362 g_signal_connect( G_OBJECT( m_pDialog ), "notify::filter",
363 G_CALLBACK( filter_changed_cb ), this);
364 g_signal_connect( G_OBJECT( m_pFilterExpander ), "activate",
365 G_CALLBACK( expander_changed_cb ), this);
366 g_signal_connect (G_OBJECT( m_pDialog ), "map",
367 G_CALLBACK (dialog_mapped_cb), this);
369 gtk_widget_show( m_pVBox );
371 PangoLayout *layout = gtk_widget_create_pango_layout (m_pFilterView, NULL);
372 guint ypad;
373 PangoRectangle row_height;
374 pango_layout_set_markup (layout, "All Files", -1);
375 pango_layout_get_pixel_extents (layout, NULL, &row_height);
376 g_object_get (cell, "ypad", &ypad, (char *)NULL);
377 guint height = (row_height.height + 2*ypad) * 5;
378 gtk_widget_set_size_request (m_pFilterView, -1, height);
379 gtk_widget_set_size_request (m_pPreview, 1, height);
381 gtk_file_chooser_set_preview_widget_active( GTK_FILE_CHOOSER( m_pDialog ), true);
384 //------------------------------------------------------------------------------------
385 // XFilePickerNotifier
386 //------------------------------------------------------------------------------------
388 void SAL_CALL SalGtkFilePicker::addFilePickerListener( const uno::Reference<XFilePickerListener>& xListener )
389 throw( uno::RuntimeException )
391 ::vos::OGuard aGuard( Application::GetSolarMutex() );
392 m_xListener = xListener;
395 void SAL_CALL SalGtkFilePicker::removeFilePickerListener( const uno::Reference<XFilePickerListener>& )
396 throw( uno::RuntimeException )
398 ::vos::OGuard aGuard( Application::GetSolarMutex() );
399 m_xListener.clear();
402 // -------------------------------------------------
403 // XEventListener
404 // -------------------------------------------------
406 void SAL_CALL SalGtkFilePicker::disposing( const lang::EventObject& aEvent ) throw( uno::RuntimeException )
408 uno::Reference<XFilePickerListener> xFilePickerListener( aEvent.Source, ::com::sun::star::uno::UNO_QUERY );
410 if( xFilePickerListener.is() )
411 removeFilePickerListener( xFilePickerListener );
414 //-----------------------------------------------------------------------------------------
415 // FilePicker Event functions
416 //-----------------------------------------------------------------------------------------
418 void SAL_CALL SalGtkFilePicker::fileSelectionChanged( FilePickerEvent aEvent )
420 OSL_TRACE( "file selection changed");
421 if (m_xListener.is()) m_xListener->fileSelectionChanged( aEvent );
424 void SAL_CALL SalGtkFilePicker::directoryChanged( FilePickerEvent aEvent )
426 OSL_TRACE("directory changed");
427 if (m_xListener.is()) m_xListener->directoryChanged( aEvent );
430 void SAL_CALL SalGtkFilePicker::controlStateChanged( FilePickerEvent aEvent )
432 OSL_TRACE("control state changed");
433 if (m_xListener.is()) m_xListener->controlStateChanged( aEvent );
436 //-----------------------------------------------------------------------------------------
437 // If there are more then one listener the return value of the last one wins
438 //-----------------------------------------------------------------------------------------
440 rtl::OUString SAL_CALL SalGtkFilePicker::helpRequested( FilePickerEvent aEvent ) const
442 rtl::OUString aHelpText;
444 ::cppu::OInterfaceContainerHelper* pICHelper =
445 rBHelper.getContainer( getCppuType( ( uno::Reference<XFilePickerListener> * )0 ) );
447 if( pICHelper )
449 ::cppu::OInterfaceIteratorHelper iter( *pICHelper );
451 while( iter.hasMoreElements() )
456 if there are multiple listeners responding
457 to this notification the next response
458 overwrittes the one before if it is not empty
461 rtl::OUString aTempString;
463 uno::Reference<XFilePickerListener> xFPListener( iter.next(), uno::UNO_QUERY );
464 if( xFPListener.is() )
466 aTempString = xFPListener->helpRequested( aEvent );
467 if( aTempString.getLength() )
468 aHelpText = aTempString;
472 catch( uno::RuntimeException& )
474 OSL_ENSURE( false, "RuntimeException during event dispatching" );
479 return aHelpText;
482 //=====================================================================
484 struct FilterEntry
486 protected:
487 ::rtl::OUString m_sTitle;
488 ::rtl::OUString m_sFilter;
490 UnoFilterList m_aSubFilters;
492 public:
493 FilterEntry( const ::rtl::OUString& _rTitle, const ::rtl::OUString& _rFilter )
494 :m_sTitle( _rTitle )
495 ,m_sFilter( _rFilter )
499 FilterEntry( const ::rtl::OUString& _rTitle, const UnoFilterList& _rSubFilters );
501 ::rtl::OUString getTitle() const { return m_sTitle; }
502 ::rtl::OUString getFilter() const { return m_sFilter; }
504 /// determines if the filter has sub filter (i.e., the filter is a filter group in real)
505 sal_Bool hasSubFilters( ) const;
507 /** retrieves the filters belonging to the entry
508 @return
509 the number of sub filters
511 sal_Int32 getSubFilters( UnoFilterList& _rSubFilterList );
513 // helpers for iterating the sub filters
514 const UnoFilterEntry* beginSubFilters() const { return m_aSubFilters.getConstArray(); }
515 const UnoFilterEntry* endSubFilters() const { return m_aSubFilters.getConstArray() + m_aSubFilters.getLength(); }
518 //=====================================================================
520 //---------------------------------------------------------------------
521 FilterEntry::FilterEntry( const ::rtl::OUString& _rTitle, const UnoFilterList& _rSubFilters )
522 :m_sTitle( _rTitle )
523 ,m_aSubFilters( _rSubFilters )
527 //---------------------------------------------------------------------
528 sal_Bool FilterEntry::hasSubFilters() const
530 return( 0 < m_aSubFilters.getLength() );
533 //---------------------------------------------------------------------
534 sal_Int32 FilterEntry::getSubFilters( UnoFilterList& _rSubFilterList )
536 _rSubFilterList = m_aSubFilters;
537 return m_aSubFilters.getLength();
540 static bool
541 isFilterString( const rtl::OUString &rFilterString, const char *pMatch )
543 sal_Int32 nIndex = 0;
544 rtl::OUString aToken;
545 bool bIsFilter = true;
547 rtl::OUString aMatch(rtl::OUString::createFromAscii(pMatch));
551 aToken = rFilterString.getToken( 0, ';', nIndex );
552 if( !aToken.match( aMatch ) )
554 bIsFilter = false;
555 break;
558 while( nIndex >= 0 );
560 return bIsFilter;
563 static rtl::OUString
564 shrinkFilterName( const rtl::OUString &rFilterName, bool bAllowNoStar = false )
566 int i;
567 int nBracketLen = -1;
568 int nBracketEnd = -1;
569 const sal_Unicode *pStr = rFilterName;
570 OUString aRealName = rFilterName;
572 for( i = aRealName.getLength() - 1; i > 0; i-- )
574 if( pStr[i] == ')' )
575 nBracketEnd = i;
576 else if( pStr[i] == '(' )
578 nBracketLen = nBracketEnd - i;
579 if( nBracketEnd <= 0 )
580 continue;
581 if( isFilterString( rFilterName.copy( i + 1, nBracketLen - 1 ), "*." ) )
582 aRealName = aRealName.replaceAt( i, nBracketLen + 1, rtl::OUString() );
583 else if (bAllowNoStar)
585 if( isFilterString( rFilterName.copy( i + 1, nBracketLen - 1 ), ".") )
586 aRealName = aRealName.replaceAt( i, nBracketLen + 1, rtl::OUString() );
591 return aRealName;
594 static void
595 dialog_remove_buttons( GtkDialog *pDialog )
597 g_return_if_fail( GTK_IS_DIALOG( pDialog ) );
599 GList *pChildren =
600 gtk_container_get_children( GTK_CONTAINER( pDialog->action_area ) );
602 for( GList *p = pChildren; p; p = p->next )
603 gtk_widget_destroy( GTK_WIDGET( p->data ) );
605 g_list_free( pChildren );
608 //------------------------------------------------------------------------------------
609 namespace {
610 //................................................................................
611 struct FilterTitleMatch : public ::std::unary_function< FilterEntry, bool >
613 protected:
614 const ::rtl::OUString& rTitle;
616 public:
617 FilterTitleMatch( const ::rtl::OUString& _rTitle ) : rTitle( _rTitle ) { }
619 //............................................................................
620 bool operator () ( const FilterEntry& _rEntry )
622 sal_Bool bMatch;
623 if( !_rEntry.hasSubFilters() )
624 // a real filter
625 bMatch = ( _rEntry.getTitle() == rTitle );
626 else
627 // a filter group -> search the sub filters
628 bMatch =
629 _rEntry.endSubFilters() != ::std::find_if(
630 _rEntry.beginSubFilters(),
631 _rEntry.endSubFilters(),
632 *this
635 return bMatch ? true : false;
637 bool operator () ( const UnoFilterEntry& _rEntry )
639 OUString aShrunkName = shrinkFilterName( _rEntry.First );
640 return aShrunkName == rTitle ? true : false;
646 //------------------------------------------------------------------------------------
647 sal_Bool SalGtkFilePicker::FilterNameExists( const ::rtl::OUString& rTitle )
649 sal_Bool bRet = sal_False;
651 if( m_pFilterList )
652 bRet =
653 m_pFilterList->end() != ::std::find_if(
654 m_pFilterList->begin(),
655 m_pFilterList->end(),
656 FilterTitleMatch( rTitle )
659 return bRet;
662 //------------------------------------------------------------------------------------
663 sal_Bool SalGtkFilePicker::FilterNameExists( const UnoFilterList& _rGroupedFilters )
665 sal_Bool bRet = sal_False;
667 if( m_pFilterList )
669 const UnoFilterEntry* pStart = _rGroupedFilters.getConstArray();
670 const UnoFilterEntry* pEnd = pStart + _rGroupedFilters.getLength();
671 for( ; pStart != pEnd; ++pStart )
672 if( m_pFilterList->end() != ::std::find_if(
673 m_pFilterList->begin(),
674 m_pFilterList->end(),
675 FilterTitleMatch( pStart->First ) ) )
676 break;
678 bRet = pStart != pEnd;
681 return bRet;
684 //------------------------------------------------------------------------------------
685 void SalGtkFilePicker::ensureFilterList( const ::rtl::OUString& _rInitialCurrentFilter )
687 if( !m_pFilterList )
689 m_pFilterList = new FilterList;
691 // set the first filter to the current filter
692 if( ( !m_aCurrentFilter ) || ( !m_aCurrentFilter.getLength() ) )
693 m_aCurrentFilter = _rInitialCurrentFilter;
698 //-----------------------------------------------------------------------------------------
700 //-----------------------------------------------------------------------------------------
702 void SAL_CALL SalGtkFilePicker::appendFilter( const rtl::OUString& aTitle, const rtl::OUString& aFilter )
703 throw( lang::IllegalArgumentException, uno::RuntimeException )
705 OSL_ASSERT( m_pDialog != NULL );
706 ::vos::OGuard aGuard( Application::GetSolarMutex() );
708 if( FilterNameExists( aTitle ) )
709 throw IllegalArgumentException();
711 // ensure that we have a filter list
712 ensureFilterList( aTitle );
714 // append the filter
715 m_pFilterList->insert( m_pFilterList->end(), FilterEntry( aTitle, aFilter ) );
716 // implAddFilter( aTitle, aFilter );
719 //-----------------------------------------------------------------------------------------
721 //-----------------------------------------------------------------------------------------
723 void SAL_CALL SalGtkFilePicker::setCurrentFilter( const rtl::OUString& aTitle )
724 throw( lang::IllegalArgumentException, uno::RuntimeException )
726 OSL_ASSERT( m_pDialog != NULL );
727 ::vos::OGuard aGuard( Application::GetSolarMutex() );
729 OSL_TRACE( "Setting current filter to %s\n",
730 OUStringToOString( aTitle, RTL_TEXTENCODING_UTF8 ).getStr() );
732 if( aTitle != m_aCurrentFilter )
734 m_aCurrentFilter = aTitle;
735 SetCurFilter( m_aCurrentFilter );
736 OSL_TRACE( "REALLY Setting current filter to %s\n",
737 OUStringToOString( aTitle, RTL_TEXTENCODING_UTF8 ).getStr() );
741 // TODO m_pImpl->setCurrentFilter( aTitle );
744 //-----------------------------------------------------------------------------------------
746 //-----------------------------------------------------------------------------------------
748 void SalGtkFilePicker::updateCurrentFilterFromName(const gchar* filtername)
750 OUString aFilterName(filtername, strlen(filtername), RTL_TEXTENCODING_UTF8);
751 FilterList::iterator aEnd = m_pFilterList->end();
752 for (FilterList::iterator aIter = m_pFilterList->begin(); aIter != aEnd; ++aIter)
754 if (aFilterName == shrinkFilterName( aIter->getTitle()))
756 m_aCurrentFilter = aIter->getTitle();
757 break;
762 void SalGtkFilePicker::UpdateFilterfromUI()
764 // Update the filtername from the users selection if they have had a chance to do so.
765 // If the user explicitly sets a type then use that, if not then take the implicit type
766 // from the filter of the files glob on which he is currently searching
767 if (!mnHID_FolderChange || !mnHID_SelectionChange)
768 return;
769 GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(m_pFilterView));
770 GtkTreeIter iter;
771 GtkTreeModel *model;
772 if (gtk_tree_selection_get_selected (selection, &model, &iter))
774 gchar *title;
775 gtk_tree_model_get (model, &iter, 2, &title, -1);
776 updateCurrentFilterFromName(title);
777 g_free (title);
779 else if( GtkFileFilter *filter = gtk_file_chooser_get_filter(GTK_FILE_CHOOSER(m_pDialog)))
781 updateCurrentFilterFromName(gtk_file_filter_get_name( filter ));
785 rtl::OUString SAL_CALL SalGtkFilePicker::getCurrentFilter() throw( uno::RuntimeException )
787 OSL_ASSERT( m_pDialog != NULL );
788 ::vos::OGuard aGuard( Application::GetSolarMutex() );
790 OSL_TRACE( "GetCURRENTfilter\n" );
792 UpdateFilterfromUI();
794 OSL_TRACE( "Returning current filter of %s\n",
795 OUStringToOString( m_aCurrentFilter, RTL_TEXTENCODING_UTF8 ).getStr() );
797 return m_aCurrentFilter;
800 //-----------------------------------------------------------------------------------------
801 // XFilterGroupManager functions
802 //-----------------------------------------------------------------------------------------
804 void SAL_CALL SalGtkFilePicker::appendFilterGroup( const rtl::OUString& /*sGroupTitle*/, const uno::Sequence<beans::StringPair>& aFilters )
805 throw( lang::IllegalArgumentException, uno::RuntimeException )
807 OSL_ASSERT( m_pDialog != NULL );
808 ::vos::OGuard aGuard( Application::GetSolarMutex() );
810 // TODO m_pImpl->appendFilterGroup( sGroupTitle, aFilters );
811 // check the names
812 if( FilterNameExists( aFilters ) )
813 // TODO: a more precise exception message
814 throw IllegalArgumentException();
816 // ensure that we have a filter list
817 ::rtl::OUString sInitialCurrentFilter;
818 if( aFilters.getLength() )
819 sInitialCurrentFilter = aFilters[0].First;
821 ensureFilterList( sInitialCurrentFilter );
823 // append the filter
824 const StringPair* pSubFilters = aFilters.getConstArray();
825 const StringPair* pSubFiltersEnd = pSubFilters + aFilters.getLength();
826 for( ; pSubFilters != pSubFiltersEnd; ++pSubFilters )
827 m_pFilterList->insert( m_pFilterList->end(), FilterEntry( pSubFilters->First, pSubFilters->Second ) );
831 //-----------------------------------------------------------------------------------------
832 // XFilePicker functions
833 //-----------------------------------------------------------------------------------------
835 void SAL_CALL SalGtkFilePicker::setMultiSelectionMode( sal_Bool bMode ) throw( uno::RuntimeException )
837 OSL_ASSERT( m_pDialog != NULL );
838 ::vos::OGuard aGuard( Application::GetSolarMutex() );
840 gtk_file_chooser_set_select_multiple( GTK_FILE_CHOOSER(m_pDialog), bMode );
843 void SAL_CALL SalGtkFilePicker::setDefaultName( const rtl::OUString& aName )
844 throw( uno::RuntimeException )
846 OSL_ASSERT( m_pDialog != NULL );
847 ::vos::OGuard aGuard( Application::GetSolarMutex() );
849 OString aStr = OUStringToOString( aName, RTL_TEXTENCODING_UTF8 );
850 GtkFileChooserAction eAction = gtk_file_chooser_get_action( GTK_FILE_CHOOSER( m_pDialog ) );
852 // set_current_name launches a Gtk critical error if called for other than save
853 if( GTK_FILE_CHOOSER_ACTION_SAVE == eAction )
854 gtk_file_chooser_set_current_name( GTK_FILE_CHOOSER( m_pDialog ), aStr.getStr() );
857 void SAL_CALL SalGtkFilePicker::setDisplayDirectory( const rtl::OUString& rDirectory )
858 throw( lang::IllegalArgumentException, uno::RuntimeException )
860 implsetDisplayDirectory(rDirectory);
863 rtl::OUString SAL_CALL SalGtkFilePicker::getDisplayDirectory() throw( uno::RuntimeException )
865 return implgetDisplayDirectory();
868 uno::Sequence<rtl::OUString> SAL_CALL SalGtkFilePicker::getFiles() throw( uno::RuntimeException )
870 uno::Sequence< rtl::OUString > aFiles = getSelectedFiles();
872 The previous multiselection API design was completely broken
873 and unimplementable for some hetrogenous pseudo-URIs eg. search://
874 Thus crop unconditionally to a single selection.
876 aFiles.realloc (1);
877 return aFiles;
880 uno::Sequence<rtl::OUString> SAL_CALL SalGtkFilePicker::getSelectedFiles() throw( uno::RuntimeException )
882 OSL_ASSERT( m_pDialog != NULL );
883 ::vos::OGuard aGuard( Application::GetSolarMutex() );
885 GSList* pPathList = gtk_file_chooser_get_uris( GTK_FILE_CHOOSER(m_pDialog) );
887 int nCount = g_slist_length( pPathList );
888 int nIndex = 0;
889 OSL_TRACE( "GETFILES called %d files\n", nCount );
891 // get the current action setting
892 GtkFileChooserAction eAction = gtk_file_chooser_get_action(
893 GTK_FILE_CHOOSER( m_pDialog ));
895 uno::Sequence< rtl::OUString > aSelectedFiles(nCount);
897 // Convert to OOo
898 for( GSList *pElem = pPathList; pElem; pElem = pElem->next)
900 gchar *pURI = reinterpret_cast<gchar*>(pElem->data);
901 aSelectedFiles[ nIndex ] = uritounicode(pURI);
903 if( GTK_FILE_CHOOSER_ACTION_SAVE == eAction )
905 OUString sFilterName;
906 sal_Int32 nTokenIndex = 0;
907 bool bExtensionTypedIn = false;
909 GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(m_pFilterView));
910 GtkTreeIter iter;
911 GtkTreeModel *model;
912 if (gtk_tree_selection_get_selected (selection, &model, &iter))
914 gchar *title;
915 gtk_tree_model_get (model, &iter, 2, &title, -1);
916 sFilterName = OUString( title, strlen( title), RTL_TEXTENCODING_UTF8 );
917 g_free (title);
919 else
921 if( aSelectedFiles[nIndex].indexOf('.') > 0 )
923 rtl::OUString sExtension;
924 nTokenIndex = 0;
926 sExtension = aSelectedFiles[nIndex].getToken( 0, '.', nTokenIndex );
927 while( nTokenIndex >= 0 );
929 if( sExtension.getLength() >= 3 ) // 3 = typical/minimum extension length
931 static const OUString aStarDot = OUString::createFromAscii( "*." );
933 for ( FilterList::iterator aListIter = m_pFilterList->begin();
934 aListIter != m_pFilterList->end();
935 ++aListIter
938 if( aListIter->getFilter().indexOf( aStarDot+sExtension ) >= 0 )
940 setCurrentFilter( aListIter->getTitle() );
941 bExtensionTypedIn = true;
942 break;
948 const gchar* filtername =
949 gtk_file_filter_get_name( gtk_file_chooser_get_filter( GTK_FILE_CHOOSER( m_pDialog ) ) );
950 sFilterName = OUString( filtername, strlen( filtername ), RTL_TEXTENCODING_UTF8 );
953 OSL_TRACE( "2: current filter is %s\n",
954 OUStringToOString( sFilterName, RTL_TEXTENCODING_UTF8 ).getStr() );
956 FilterList::iterator aListIter = ::std::find_if(
957 m_pFilterList->begin(), m_pFilterList->end(), FilterTitleMatch(sFilterName) );
959 OUString aFilter;
960 if (aListIter != m_pFilterList->end())
961 aFilter = aListIter->getFilter();
963 OSL_TRACE( "turned into %s\n",
964 OUStringToOString( aFilter, RTL_TEXTENCODING_UTF8 ).getStr() );
966 nTokenIndex = 0;
967 rtl::OUString sToken;
968 // rtl::OUString strExt;
971 sToken = aFilter.getToken( 0, '.', nTokenIndex );
973 if ( sToken.lastIndexOf( ';' ) != -1 )
975 sal_Int32 nZero = 0;
976 OUString aCurrentToken = sToken.getToken( 0, ';', nZero);
978 sToken = aCurrentToken;
979 break;
982 while( nTokenIndex >= 0 );
984 if( !bExtensionTypedIn && ( !sToken.equalsAscii( "*" ) ) )
986 //if the filename does not already have the auto extension, stick it on
987 OUString sExtension = OUString::createFromAscii( "." ) + sToken;
988 OUString &rBase = aSelectedFiles[nIndex];
989 sal_Int32 nExtensionIdx = rBase.getLength() - sExtension.getLength();
990 OSL_TRACE( "idx are %d %d\n", rBase.lastIndexOf( sExtension ), nExtensionIdx );
992 if( rBase.lastIndexOf( sExtension ) != nExtensionIdx )
993 rBase += sExtension;
998 nIndex++;
999 g_free( pURI );
1002 g_slist_free( pPathList );
1004 return aSelectedFiles;
1007 //-----------------------------------------------------------------------------------------
1008 // XExecutableDialog functions
1009 //-----------------------------------------------------------------------------------------
1011 void SAL_CALL SalGtkFilePicker::setTitle( const rtl::OUString& rTitle ) throw( uno::RuntimeException )
1013 implsetTitle(rTitle);
1016 sal_Int16 SAL_CALL SalGtkFilePicker::execute() throw( uno::RuntimeException )
1018 OSL_TRACE( "1: HERE WE ARE\n");
1019 OSL_ASSERT( m_pDialog != NULL );
1020 ::vos::OGuard aGuard( Application::GetSolarMutex() );
1022 sal_Int16 retVal = 0;
1024 SetFilters();
1026 mnHID_FolderChange =
1027 g_signal_connect( GTK_FILE_CHOOSER( m_pDialog ), "current-folder-changed",
1028 G_CALLBACK( folder_changed_cb ), ( gpointer )this );
1030 mnHID_SelectionChange =
1031 g_signal_connect( GTK_FILE_CHOOSER( m_pDialog ), "selection-changed",
1032 G_CALLBACK( selection_changed_cb ), ( gpointer )this );
1034 int btn = GTK_RESPONSE_NO;
1036 uno::Reference< awt::XExtendedToolkit > xToolkit(
1037 m_xServiceMgr->createInstance( ::rtl::OUString::createFromAscii("com.sun.star.awt.Toolkit") ), uno::UNO_QUERY);
1039 RunDialog* pRunDialog = new RunDialog(m_pDialog, xToolkit);
1040 uno::Reference < awt::XTopWindowListener > xLifeCycle(pRunDialog);
1041 while( GTK_RESPONSE_NO == btn )
1043 btn = GTK_RESPONSE_YES; // we dont want to repeat unless user clicks NO for file save.
1045 gint nStatus = pRunDialog->run();
1046 switch( nStatus )
1048 case GTK_RESPONSE_ACCEPT:
1049 if( GTK_FILE_CHOOSER_ACTION_SAVE == gtk_file_chooser_get_action( GTK_FILE_CHOOSER( m_pDialog ) ) )
1051 Sequence < OUString > aPathSeq = getFiles();
1052 if( aPathSeq.getLength() == 1 )
1054 OString sFileName = unicodetouri( aPathSeq[0] );
1055 if( g_file_test( g_filename_from_uri( sFileName.getStr(), NULL, NULL ), G_FILE_TEST_IS_REGULAR ) )
1057 CResourceProvider aResProvider;
1058 GtkWidget *dlg;
1060 dlg = gtk_message_dialog_new( NULL,
1061 GTK_DIALOG_MODAL,
1062 GTK_MESSAGE_QUESTION,
1063 GTK_BUTTONS_YES_NO,
1064 "\"%s\"", OUStringToOString(
1065 aResProvider.getResString( FILE_PICKER_OVERWRITE ),
1066 RTL_TEXTENCODING_UTF8 ).getStr() );
1068 gtk_window_set_title( GTK_WINDOW( dlg ),
1069 OUStringToOString(aResProvider.getResString(FILE_PICKER_TITLE_SAVE ),
1070 RTL_TEXTENCODING_UTF8 ).getStr() );
1072 RunDialog* pAnotherDialog = new RunDialog(dlg, xToolkit);
1073 uno::Reference < awt::XTopWindowListener > xAnotherLifeCycle(pAnotherDialog);
1074 btn = pAnotherDialog->run();
1076 gtk_widget_destroy( dlg );
1079 if( btn == GTK_RESPONSE_YES )
1080 retVal = ExecutableDialogResults::OK;
1083 else
1084 retVal = ExecutableDialogResults::OK;
1085 break;
1087 case GTK_RESPONSE_CANCEL:
1088 retVal = ExecutableDialogResults::CANCEL;
1089 break;
1091 case 1: //PLAY
1093 FilePickerEvent evt;
1094 evt.ElementId = PUSHBUTTON_PLAY;
1095 OSL_TRACE( "filter_changed, isn't it great %x\n", this);
1096 controlStateChanged( evt );
1097 btn = GTK_RESPONSE_NO;
1099 break;
1101 default:
1102 retVal = 0;
1103 break;
1107 if (mnHID_FolderChange)
1108 g_signal_handler_disconnect(GTK_FILE_CHOOSER( m_pDialog ), mnHID_FolderChange);
1109 if (mnHID_SelectionChange)
1110 g_signal_handler_disconnect(GTK_FILE_CHOOSER( m_pDialog ), mnHID_SelectionChange);
1112 return retVal;
1115 //------------------------------------------------------------------------------------
1117 // cf. offapi/com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.idl
1118 GtkWidget *SalGtkFilePicker::getWidget( sal_Int16 nControlId, GType *pType )
1120 OSL_TRACE("control id is %d", nControlId);
1121 GType tType = GTK_TYPE_TOGGLE_BUTTON; //prevent waring by initializing
1122 GtkWidget *pWidget = 0;
1124 #define MAP_TOGGLE( elem ) \
1125 case ExtendedFilePickerElementIds::CHECKBOX_##elem: \
1126 pWidget = m_pToggles[elem]; tType = GTK_TYPE_TOGGLE_BUTTON; \
1127 break
1128 #define MAP_BUTTON( elem ) \
1129 case ExtendedFilePickerElementIds::PUSHBUTTON_##elem: \
1130 pWidget = m_pButtons[elem]; tType = GTK_TYPE_BUTTON; \
1131 break
1132 #define MAP_LIST( elem ) \
1133 case ExtendedFilePickerElementIds::LISTBOX_##elem: \
1134 pWidget = m_pLists[elem]; tType = GTK_TYPE_COMBO_BOX; \
1135 break
1136 #define MAP_LIST_LABEL( elem ) \
1137 case ExtendedFilePickerElementIds::LISTBOX_##elem##_LABEL: \
1138 pWidget = m_pListLabels[elem]; tType = GTK_TYPE_LABEL; \
1139 break
1141 switch( nControlId )
1143 MAP_TOGGLE( AUTOEXTENSION );
1144 MAP_TOGGLE( PASSWORD );
1145 MAP_TOGGLE( FILTEROPTIONS );
1146 MAP_TOGGLE( READONLY );
1147 MAP_TOGGLE( LINK );
1148 MAP_TOGGLE( PREVIEW );
1149 MAP_TOGGLE( SELECTION );
1150 MAP_BUTTON( PLAY );
1151 MAP_LIST( VERSION );
1152 MAP_LIST( TEMPLATE );
1153 MAP_LIST( IMAGE_TEMPLATE );
1154 MAP_LIST_LABEL( VERSION );
1155 MAP_LIST_LABEL( TEMPLATE );
1156 MAP_LIST_LABEL( IMAGE_TEMPLATE );
1157 default:
1158 OSL_TRACE("Handle unknown control %d\n", nControlId);
1159 break;
1161 #undef MAP
1163 if( pType )
1164 *pType = tType;
1165 return pWidget;
1170 //------------------------------------------------------------------------------------
1171 // XFilePickerControlAccess functions
1172 //------------------------------------------------------------------------------------
1173 namespace
1175 void HackWidthToFirst(GtkComboBox *pWidget)
1177 GtkRequisition requisition;
1178 gtk_widget_size_request(GTK_WIDGET(pWidget), &requisition);
1179 gtk_widget_set_size_request(GTK_WIDGET(pWidget), requisition.width, -1);
1183 void SalGtkFilePicker::HandleSetListValue(GtkComboBox *pWidget, sal_Int16 nControlAction, const uno::Any& rValue)
1185 switch (nControlAction)
1187 case ControlActions::ADD_ITEM:
1189 OUString sItem;
1190 rValue >>= sItem;
1191 gtk_combo_box_append_text(pWidget, rtl::OUStringToOString(sItem, RTL_TEXTENCODING_UTF8).getStr());
1192 if (!bVersionWidthUnset)
1194 HackWidthToFirst(pWidget);
1195 bVersionWidthUnset = true;
1198 break;
1199 case ControlActions::ADD_ITEMS:
1201 Sequence< OUString > aStringList;
1202 rValue >>= aStringList;
1203 sal_Int32 nItemCount = aStringList.getLength();
1204 for (sal_Int32 i = 0; i < nItemCount; ++i)
1206 gtk_combo_box_append_text(pWidget,
1207 rtl::OUStringToOString(aStringList[i], RTL_TEXTENCODING_UTF8).getStr());
1208 if (!bVersionWidthUnset)
1210 HackWidthToFirst(pWidget);
1211 bVersionWidthUnset = true;
1215 break;
1216 case ControlActions::DELETE_ITEM:
1218 sal_Int32 nPos=0;
1219 rValue >>= nPos;
1220 gtk_combo_box_remove_text(pWidget, nPos);
1222 break;
1223 case ControlActions::DELETE_ITEMS:
1225 gtk_combo_box_set_active(pWidget, -1);
1226 gint nItems = 0;
1229 nItems =
1230 gtk_tree_model_iter_n_children(
1231 gtk_combo_box_get_model(pWidget), NULL);
1232 for (gint nI = 0; nI < nItems; ++nI)
1233 gtk_combo_box_remove_text(pWidget, nI);
1235 while (nItems);
1237 break;
1238 case ControlActions::SET_SELECT_ITEM:
1240 sal_Int32 nPos=0;
1241 rValue >>= nPos;
1242 gtk_combo_box_set_active(pWidget, nPos);
1244 break;
1245 default:
1246 OSL_TRACE("undocumented/unimplemented ControlAction for a list");
1247 break;
1250 //I think its best to make it insensitive unless there is the chance to
1251 //actually select something from the list.
1252 gint nItems = gtk_tree_model_iter_n_children(
1253 gtk_combo_box_get_model(pWidget), NULL);
1254 gtk_widget_set_sensitive(GTK_WIDGET(pWidget), nItems > 1 ? true : false);
1257 uno::Any SalGtkFilePicker::HandleGetListValue(GtkComboBox *pWidget, sal_Int16 nControlAction) const
1259 uno::Any aAny;
1260 switch (nControlAction)
1262 case ControlActions::GET_ITEMS:
1264 Sequence< OUString > aItemList;
1266 GtkTreeModel *pTree = gtk_combo_box_get_model(pWidget);
1267 GtkTreeIter iter;
1268 if (gtk_tree_model_get_iter_first(pTree, &iter))
1270 sal_Int32 nSize = gtk_tree_model_iter_n_children(
1271 pTree, NULL);
1273 aItemList.realloc(nSize);
1274 for (sal_Int32 i=0; i < nSize; ++i)
1276 gchar *item;
1277 gtk_tree_model_get(gtk_combo_box_get_model(pWidget),
1278 &iter, 0, &item, -1);
1279 aItemList[i] = OUString(item, strlen(item), RTL_TEXTENCODING_UTF8);
1280 g_free(item);
1281 gtk_tree_model_iter_next(pTree, &iter);
1284 aAny <<= aItemList;
1286 break;
1287 case ControlActions::GET_SELECTED_ITEM:
1289 GtkTreeIter iter;
1290 if (gtk_combo_box_get_active_iter(pWidget, &iter))
1292 gchar *item;
1293 gtk_tree_model_get(gtk_combo_box_get_model(pWidget),
1294 &iter, 0, &item, -1);
1295 OUString sItem(item, strlen(item), RTL_TEXTENCODING_UTF8);
1296 aAny <<= sItem;
1297 g_free(item);
1300 break;
1301 case ControlActions::GET_SELECTED_ITEM_INDEX:
1303 gint nActive = gtk_combo_box_get_active(pWidget);
1304 aAny <<= static_cast< sal_Int32 >(nActive);
1306 break;
1307 default:
1308 OSL_TRACE("undocumented/unimplemented ControlAction for a list");
1309 break;
1311 return aAny;
1314 void SAL_CALL SalGtkFilePicker::setValue( sal_Int16 nControlId, sal_Int16 nControlAction, const uno::Any& rValue )
1315 throw( uno::RuntimeException )
1317 OSL_ASSERT( m_pDialog != NULL );
1318 ::vos::OGuard aGuard( Application::GetSolarMutex() );
1320 OSL_TRACE( "SETTING VALUE %d\n", nControlAction );
1321 GType tType;
1322 GtkWidget *pWidget;
1324 if( !( pWidget = getWidget( nControlId, &tType ) ) )
1325 OSL_TRACE("enable unknown control %d\n", nControlId);
1327 else if( tType == GTK_TYPE_TOGGLE_BUTTON )
1329 sal_Bool bChecked = false;
1330 rValue >>= bChecked;
1331 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( pWidget ), bChecked );
1333 else if( tType == GTK_TYPE_COMBO_BOX )
1334 HandleSetListValue(GTK_COMBO_BOX(pWidget), nControlAction, rValue);
1335 else
1337 OSL_TRACE("Can't set value on button / list %d %d\n",
1338 nControlId, nControlAction);
1342 uno::Any SAL_CALL SalGtkFilePicker::getValue( sal_Int16 nControlId, sal_Int16 nControlAction )
1343 throw( uno::RuntimeException )
1345 OSL_ASSERT( m_pDialog != NULL );
1346 ::vos::OGuard aGuard( Application::GetSolarMutex() );
1347 uno::Any aRetval;
1349 GType tType;
1350 GtkWidget *pWidget;
1352 if( !( pWidget = getWidget( nControlId, &tType ) ) )
1353 OSL_TRACE("enable unknown control %d\n", nControlId);
1355 else if( tType == GTK_TYPE_TOGGLE_BUTTON )
1356 aRetval <<= (sal_Bool) gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( pWidget ) );
1357 else if( tType == GTK_TYPE_COMBO_BOX )
1358 aRetval = HandleGetListValue(GTK_COMBO_BOX(pWidget), nControlAction);
1359 else
1360 OSL_TRACE("Can't get value on button / list %d %d\n",
1361 nControlId, nControlAction );
1363 return aRetval;
1366 void SAL_CALL SalGtkFilePicker::enableControl( sal_Int16 nControlId, sal_Bool bEnable )
1367 throw( uno::RuntimeException )
1369 OSL_ASSERT( m_pDialog != NULL );
1370 ::vos::OGuard aGuard( Application::GetSolarMutex() );
1372 GtkWidget *pWidget;
1374 if ( nControlId == ExtendedFilePickerElementIds::LISTBOX_FILTER_SELECTOR )
1375 gtk_expander_set_expanded( GTK_EXPANDER( m_pFilterExpander ), bEnable );
1377 else if( ( pWidget = getWidget( nControlId ) ) )
1379 if( bEnable )
1381 OSL_TRACE( "enable\n" );
1382 gtk_widget_set_sensitive( pWidget, TRUE );
1384 else
1386 OSL_TRACE( "disable\n" );
1387 gtk_widget_set_sensitive( pWidget, FALSE );
1390 else
1391 OSL_TRACE("enable unknown control %d\n", nControlId );
1394 void SAL_CALL SalGtkFilePicker::setLabel( sal_Int16 nControlId, const ::rtl::OUString& rLabel )
1395 throw( uno::RuntimeException )
1397 OSL_ASSERT( m_pDialog != NULL );
1398 ::vos::OGuard aGuard( Application::GetSolarMutex() );
1400 GType tType;
1401 GtkWidget *pWidget;
1403 if( !( pWidget = getWidget( nControlId, &tType ) ) )
1405 OSL_TRACE("Set label on unknown control %d\n", nControlId);
1406 return;
1409 OString aTxt = OUStringToOString( rLabel.replace('~', '_'), RTL_TEXTENCODING_UTF8 );
1410 if (nControlId == ExtendedFilePickerElementIds::PUSHBUTTON_PLAY)
1412 #ifdef GTK_STOCK_MEDIA_PLAY
1413 if (!msPlayLabel.getLength())
1414 msPlayLabel = rLabel;
1415 if (msPlayLabel == rLabel)
1416 gtk_button_set_label(GTK_BUTTON(pWidget), GTK_STOCK_MEDIA_PLAY);
1417 else
1418 gtk_button_set_label(GTK_BUTTON(pWidget), GTK_STOCK_MEDIA_STOP);
1419 #else
1420 gtk_button_set_label(GTK_BUTTON(pWidget), aTxt.getStr());
1421 #endif
1423 else if( tType == GTK_TYPE_TOGGLE_BUTTON || tType == GTK_TYPE_BUTTON || tType == GTK_TYPE_LABEL )
1424 g_object_set( pWidget, "label", aTxt.getStr(),
1425 "use_underline", TRUE, (char *)NULL );
1426 else
1427 OSL_TRACE("Can't set label on list\n");
1430 rtl::OUString SAL_CALL SalGtkFilePicker::getLabel( sal_Int16 nControlId )
1431 throw( uno::RuntimeException )
1433 OSL_ASSERT( m_pDialog != NULL );
1434 ::vos::OGuard aGuard( Application::GetSolarMutex() );
1436 GType tType;
1437 OString aTxt;
1438 GtkWidget *pWidget;
1440 if( !( pWidget = getWidget( nControlId, &tType ) ) )
1441 OSL_TRACE("Get label on unknown control %d\n", nControlId);
1443 else if( tType == GTK_TYPE_TOGGLE_BUTTON || tType == GTK_TYPE_BUTTON || tType == GTK_TYPE_LABEL )
1444 aTxt = gtk_button_get_label( GTK_BUTTON( pWidget ) );
1446 else
1447 OSL_TRACE("Can't get label on list\n");
1449 return OStringToOUString( aTxt, RTL_TEXTENCODING_UTF8 );
1452 //------------------------------------------------------------------------------------
1453 // XFilePreview functions
1454 //------------------------------------------------------------------------------------
1456 uno::Sequence<sal_Int16> SAL_CALL SalGtkFilePicker::getSupportedImageFormats() throw( uno::RuntimeException )
1458 OSL_ASSERT( m_pDialog != NULL );
1459 ::vos::OGuard aGuard( Application::GetSolarMutex() );
1461 // TODO return m_pImpl->getSupportedImageFormats();
1462 return 0;
1465 sal_Int32 SAL_CALL SalGtkFilePicker::getTargetColorDepth() throw( uno::RuntimeException )
1467 OSL_ASSERT( m_pDialog != NULL );
1468 ::vos::OGuard aGuard( Application::GetSolarMutex() );
1470 // TODO return m_pImpl->getTargetColorDepth();
1471 return 0;
1474 sal_Int32 SAL_CALL SalGtkFilePicker::getAvailableWidth() throw( uno::RuntimeException )
1476 OSL_ASSERT( m_pDialog != NULL );
1477 ::vos::OGuard aGuard( Application::GetSolarMutex() );
1479 // TODO return m_pImpl->getAvailableWidth();
1480 return m_PreviewImageWidth;
1483 sal_Int32 SAL_CALL SalGtkFilePicker::getAvailableHeight() throw( uno::RuntimeException )
1485 OSL_ASSERT( m_pDialog != NULL );
1486 ::vos::OGuard aGuard( Application::GetSolarMutex() );
1488 // TODO return m_pImpl->getAvailableHeight();
1489 return m_PreviewImageHeight;
1492 void SAL_CALL SalGtkFilePicker::setImage( sal_Int16 /*aImageFormat*/, const uno::Any& /*aImage*/ )
1493 throw( lang::IllegalArgumentException, uno::RuntimeException )
1495 OSL_ASSERT( m_pDialog != NULL );
1496 ::vos::OGuard aGuard( Application::GetSolarMutex() );
1498 // TODO m_pImpl->setImage( aImageFormat, aImage );
1501 void SalGtkFilePicker::implChangeType( GtkTreeSelection *selection )
1503 CResourceProvider aResProvider;
1504 OUString aLabel = aResProvider.getResString( FILE_PICKER_FILE_TYPE );
1505 GtkTreeIter iter;
1506 GtkTreeModel *model;
1507 if (gtk_tree_selection_get_selected (selection, &model, &iter))
1509 gchar *title;
1510 gtk_tree_model_get (model, &iter, 2, &title, -1);
1511 aLabel += rtl::OUString::createFromAscii( ": " );
1512 aLabel += rtl::OUString( title, strlen(title), RTL_TEXTENCODING_UTF8 );
1513 g_free (title);
1515 gtk_expander_set_label (GTK_EXPANDER (m_pFilterExpander),
1516 OUStringToOString( aLabel, RTL_TEXTENCODING_UTF8 ).getStr());
1517 FilePickerEvent evt;
1518 evt.ElementId = LISTBOX_FILTER;
1519 controlStateChanged( evt );
1522 void SalGtkFilePicker::type_changed_cb( GtkTreeSelection *selection, SalGtkFilePicker *pobjFP )
1524 pobjFP->implChangeType(selection);
1527 void SalGtkFilePicker::unselect_type()
1529 gtk_tree_selection_unselect_all(gtk_tree_view_get_selection(GTK_TREE_VIEW(m_pFilterView)));
1532 void SalGtkFilePicker::expander_changed_cb( GtkExpander *expander, SalGtkFilePicker *pobjFP )
1534 if (gtk_expander_get_expanded(expander))
1535 pobjFP->unselect_type();
1538 void SalGtkFilePicker::filter_changed_cb( GtkFileChooser *, GParamSpec *,
1539 SalGtkFilePicker *pobjFP )
1541 FilePickerEvent evt;
1542 evt.ElementId = LISTBOX_FILTER;
1543 OSL_TRACE( "filter_changed, isn't it great %x\n", pobjFP );
1544 pobjFP->controlStateChanged( evt );
1547 void SalGtkFilePicker::folder_changed_cb( GtkFileChooser *, SalGtkFilePicker *pobjFP )
1549 FilePickerEvent evt;
1550 OSL_TRACE( "folder_changed, isn't it great %x\n", pobjFP );
1551 pobjFP->directoryChanged( evt );
1554 void SalGtkFilePicker::selection_changed_cb( GtkFileChooser *, SalGtkFilePicker *pobjFP )
1556 FilePickerEvent evt;
1557 OSL_TRACE( "selection_changed, isn't it great %x\n", pobjFP );
1558 pobjFP->fileSelectionChanged( evt );
1561 void SalGtkFilePicker::update_preview_cb( GtkFileChooser *file_chooser, SalGtkFilePicker* pobjFP )
1563 GtkWidget *preview;
1564 char *filename;
1565 GdkPixbuf *pixbuf;
1566 gboolean have_preview = FALSE;
1568 preview = pobjFP->m_pPreview;
1569 filename = gtk_file_chooser_get_preview_filename( file_chooser );
1571 if( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( pobjFP->m_pToggles[PREVIEW] ) ) && g_file_test( filename, G_FILE_TEST_IS_REGULAR ) )
1573 pixbuf = gdk_pixbuf_new_from_file_at_size(
1574 filename,
1575 pobjFP->m_PreviewImageWidth,
1576 pobjFP->m_PreviewImageHeight, NULL );
1578 have_preview = ( pixbuf != NULL );
1580 gtk_image_set_from_pixbuf( GTK_IMAGE( preview ), pixbuf );
1581 if( pixbuf )
1582 gdk_pixbuf_unref( pixbuf );
1586 gtk_file_chooser_set_preview_widget_active( file_chooser, have_preview );
1588 if( filename )
1589 g_free( filename );
1592 sal_Bool SAL_CALL SalGtkFilePicker::setShowState( sal_Bool bShowState ) throw( uno::RuntimeException )
1594 OSL_ASSERT( m_pDialog != NULL );
1595 ::vos::OGuard aGuard( Application::GetSolarMutex() );
1597 // TODO return m_pImpl->setShowState( bShowState );
1598 if( bShowState != mbPreviewState )
1600 if( bShowState )
1602 // Show
1603 if( !mHID_Preview )
1605 mHID_Preview = g_signal_connect(
1606 GTK_FILE_CHOOSER( m_pDialog ), "update-preview",
1607 G_CALLBACK( update_preview_cb ), ( gpointer )this );
1609 gtk_widget_show( m_pPreview );
1611 else
1613 // Hide
1614 gtk_widget_hide( m_pPreview );
1617 // also emit the signal
1618 g_signal_emit_by_name( GTK_OBJECT( m_pDialog ), "update-preview" );
1620 mbPreviewState = bShowState;
1622 return true;
1625 sal_Bool SAL_CALL SalGtkFilePicker::getShowState() throw( uno::RuntimeException )
1627 OSL_ASSERT( m_pDialog != NULL );
1628 ::vos::OGuard aGuard( Application::GetSolarMutex() );
1630 // TODO return m_pImpl->getShowState();
1631 return mbPreviewState;
1634 //------------------------------------------------------------------------------------
1635 // XInitialization
1636 //------------------------------------------------------------------------------------
1638 void SAL_CALL SalGtkFilePicker::initialize( const uno::Sequence<uno::Any>& aArguments )
1639 throw( uno::Exception, uno::RuntimeException )
1641 // parameter checking
1642 uno::Any aAny;
1643 if( 0 == aArguments.getLength() )
1644 throw lang::IllegalArgumentException(
1645 rtl::OUString::createFromAscii( "no arguments" ),
1646 static_cast<XFilePicker2*>( this ), 1 );
1648 aAny = aArguments[0];
1650 if( ( aAny.getValueType() != ::getCppuType( ( sal_Int16* )0 ) ) &&
1651 (aAny.getValueType() != ::getCppuType( ( sal_Int8* )0 ) ) )
1652 throw lang::IllegalArgumentException(
1653 rtl::OUString::createFromAscii( "invalid argument type" ),
1654 static_cast<XFilePicker2*>( this ), 1 );
1656 sal_Int16 templateId = -1;
1657 aAny >>= templateId;
1659 GtkFileChooserAction eAction = GTK_FILE_CHOOSER_ACTION_OPEN;
1660 const gchar *first_button_text = GTK_STOCK_OPEN;
1663 // TODO: extract full semantic from
1664 // svtools/source/filepicker/filepicker.cxx (getWinBits)
1665 switch( templateId )
1667 case FILEOPEN_SIMPLE:
1668 eAction = GTK_FILE_CHOOSER_ACTION_OPEN;
1669 first_button_text = GTK_STOCK_OPEN;
1670 OSL_TRACE( "3all true\n" );
1671 break;
1672 case FILESAVE_SIMPLE:
1673 eAction = GTK_FILE_CHOOSER_ACTION_SAVE;
1674 first_button_text = GTK_STOCK_SAVE;
1675 OSL_TRACE( "2all true\n" );
1676 break;
1677 case FILESAVE_AUTOEXTENSION_PASSWORD:
1678 eAction = GTK_FILE_CHOOSER_ACTION_SAVE;
1679 first_button_text = GTK_STOCK_SAVE;
1680 mbToggleVisibility[PASSWORD] = true;
1681 OSL_TRACE( "1all true\n" );
1682 // TODO
1683 break;
1684 case FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS:
1685 eAction = GTK_FILE_CHOOSER_ACTION_SAVE;
1686 first_button_text = GTK_STOCK_SAVE;
1687 mbToggleVisibility[PASSWORD] = true;
1688 mbToggleVisibility[FILTEROPTIONS] = true;
1689 OSL_TRACE( "4all true\n" );
1690 // TODO
1691 break;
1692 case FILESAVE_AUTOEXTENSION_SELECTION:
1693 eAction = GTK_FILE_CHOOSER_ACTION_SAVE; // SELECT_FOLDER ?
1694 first_button_text = GTK_STOCK_SAVE;
1695 mbToggleVisibility[SELECTION] = true;
1696 OSL_TRACE( "5all true\n" );
1697 // TODO
1698 break;
1699 case FILESAVE_AUTOEXTENSION_TEMPLATE:
1700 eAction = GTK_FILE_CHOOSER_ACTION_SAVE;
1701 first_button_text = GTK_STOCK_SAVE;
1702 mbListVisibility[TEMPLATE] = true;
1703 OSL_TRACE( "6all true\n" );
1704 // TODO
1705 break;
1706 case FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE:
1707 eAction = GTK_FILE_CHOOSER_ACTION_OPEN;
1708 first_button_text = GTK_STOCK_OPEN;
1709 mbToggleVisibility[LINK] = true;
1710 mbToggleVisibility[PREVIEW] = true;
1711 mbListVisibility[IMAGE_TEMPLATE] = true;
1712 // TODO
1713 break;
1714 case FILEOPEN_PLAY:
1715 eAction = GTK_FILE_CHOOSER_ACTION_OPEN;
1716 first_button_text = GTK_STOCK_OPEN;
1717 mbButtonVisibility[PLAY] = true;
1718 // TODO
1719 break;
1720 case FILEOPEN_READONLY_VERSION:
1721 eAction = GTK_FILE_CHOOSER_ACTION_OPEN;
1722 first_button_text = GTK_STOCK_OPEN;
1723 mbToggleVisibility[READONLY] = true;
1724 mbListVisibility[VERSION] = true;
1725 break;
1726 case FILEOPEN_LINK_PREVIEW:
1727 eAction = GTK_FILE_CHOOSER_ACTION_OPEN;
1728 first_button_text = GTK_STOCK_OPEN;
1729 mbToggleVisibility[LINK] = true;
1730 mbToggleVisibility[PREVIEW] = true;
1731 // TODO
1732 break;
1733 case FILESAVE_AUTOEXTENSION:
1734 eAction = GTK_FILE_CHOOSER_ACTION_SAVE;
1735 first_button_text = GTK_STOCK_SAVE;
1736 OSL_TRACE( "7all true\n" );
1737 // TODO
1738 break;
1739 default:
1740 throw lang::IllegalArgumentException(
1741 rtl::OUString::createFromAscii( "Unknown template" ),
1742 static_cast< XFilePicker2* >( this ),
1743 1 );
1746 if( GTK_FILE_CHOOSER_ACTION_SAVE == eAction )
1748 CResourceProvider aResProvider;
1749 OUString aFilePickerTitle(aResProvider.getResString( FILE_PICKER_TITLE_SAVE ));
1750 gtk_window_set_title ( GTK_WINDOW( m_pDialog ),
1751 OUStringToOString( aFilePickerTitle, RTL_TEXTENCODING_UTF8 ).getStr() );
1754 gtk_file_chooser_set_action( GTK_FILE_CHOOSER( m_pDialog ), eAction);
1755 dialog_remove_buttons( GTK_DIALOG( m_pDialog ) );
1756 gtk_dialog_add_button( GTK_DIALOG( m_pDialog ), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL );
1757 for( int nTVIndex = 0; nTVIndex < BUTTON_LAST; nTVIndex++ )
1759 if( mbButtonVisibility[nTVIndex] )
1761 #ifdef GTK_STOCK_MEDIA_PLAY
1762 m_pButtons[ nTVIndex ] = gtk_dialog_add_button( GTK_DIALOG( m_pDialog ), GTK_STOCK_MEDIA_PLAY, 1 );
1763 #else
1764 CResourceProvider aResProvider;
1765 OString aPlay = OUStringToOString( aResProvider.getResString( PUSHBUTTON_PLAY ), RTL_TEXTENCODING_UTF8 );
1766 m_pButtons[ nTVIndex ] = gtk_dialog_add_button( GTK_DIALOG( m_pDialog ), aPlay.getStr(), 1 );
1767 #endif
1770 gtk_dialog_add_button( GTK_DIALOG( m_pDialog ), first_button_text, GTK_RESPONSE_ACCEPT );
1772 gtk_dialog_set_default_response( GTK_DIALOG (m_pDialog), GTK_RESPONSE_ACCEPT );
1774 // Setup special flags
1775 for( int nTVIndex = 0; nTVIndex < TOGGLE_LAST; nTVIndex++ )
1777 if( mbToggleVisibility[nTVIndex] )
1778 gtk_widget_show( m_pToggles[ nTVIndex ] );
1781 for( int nTVIndex = 0; nTVIndex < LIST_LAST; nTVIndex++ )
1783 if( mbListVisibility[nTVIndex] )
1785 gtk_widget_set_sensitive( m_pLists[ nTVIndex ], false );
1786 gtk_widget_show( m_pLists[ nTVIndex ] );
1787 gtk_widget_show( m_pListLabels[ nTVIndex ] );
1788 gtk_widget_show( m_pAligns[ nTVIndex ] );
1789 gtk_widget_show( m_pHBoxs[ nTVIndex ] );
1794 void SalGtkFilePicker::preview_toggled_cb( GtkObject *cb, SalGtkFilePicker* pobjFP )
1796 if( pobjFP->mbToggleVisibility[PREVIEW] )
1797 pobjFP->setShowState( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( cb ) ) );
1800 //------------------------------------------------------------------------------------
1801 // XCancellable
1802 //------------------------------------------------------------------------------------
1804 void SAL_CALL SalGtkFilePicker::cancel() throw( uno::RuntimeException )
1806 OSL_ASSERT( m_pDialog != NULL );
1807 ::vos::OGuard aGuard( Application::GetSolarMutex() );
1809 // TODO m_pImpl->cancel();
1812 // -------------------------------------------------
1813 // XServiceInfo
1814 // -------------------------------------------------
1816 rtl::OUString SAL_CALL SalGtkFilePicker::getImplementationName()
1817 throw( uno::RuntimeException )
1819 return rtl::OUString::createFromAscii( FILE_PICKER_IMPL_NAME );
1822 // -------------------------------------------------
1823 // XServiceInfo
1824 // -------------------------------------------------
1826 sal_Bool SAL_CALL SalGtkFilePicker::supportsService( const rtl::OUString& ServiceName )
1827 throw( uno::RuntimeException )
1829 uno::Sequence <rtl::OUString> SupportedServicesNames = FilePicker_getSupportedServiceNames();
1831 for( sal_Int32 n = SupportedServicesNames.getLength(); n--; )
1832 if( SupportedServicesNames[n].compareTo( ServiceName ) == 0)
1833 return sal_True;
1835 return sal_False;
1838 // -------------------------------------------------
1839 // XServiceInfo
1840 // -------------------------------------------------
1842 uno::Sequence<rtl::OUString> SAL_CALL SalGtkFilePicker::getSupportedServiceNames()
1843 throw( uno::RuntimeException )
1845 return FilePicker_getSupportedServiceNames();
1849 //--------------------------------------------------
1850 // Misc
1851 //-------------------------------------------------
1852 void SalGtkFilePicker::SetCurFilter( const OUString& rFilter )
1854 // Get all the filters already added
1855 GSList *filters = gtk_file_chooser_list_filters ( GTK_FILE_CHOOSER( m_pDialog ) );
1856 bool bFound = false;
1858 for( GSList *iter = filters; !bFound && iter; iter = iter->next )
1860 GtkFileFilter* pFilter = reinterpret_cast<GtkFileFilter *>( iter->data );
1861 G_CONST_RETURN gchar * filtername = gtk_file_filter_get_name( pFilter );
1862 OUString sFilterName( filtername, strlen( filtername ), RTL_TEXTENCODING_UTF8 );
1864 OUString aShrunkName = shrinkFilterName( rFilter );
1865 if( aShrunkName.equals( sFilterName) )
1867 OSL_TRACE( "actually setting %s\n", filtername );
1868 gtk_file_chooser_set_filter( GTK_FILE_CHOOSER( m_pDialog ), pFilter );
1869 bFound = true;
1873 g_slist_free( filters );
1876 extern "C"
1878 static gboolean
1879 case_insensitive_filter (const GtkFileFilterInfo *filter_info, gpointer data)
1881 gboolean bRetval = FALSE;
1882 const char *pFilter = (const char *) data;
1884 g_return_val_if_fail( data != NULL, FALSE );
1885 g_return_val_if_fail( filter_info != NULL, FALSE );
1887 if( !filter_info->uri )
1888 return FALSE;
1890 const char *pExtn = strrchr( filter_info->uri, '.' );
1891 if( !pExtn )
1892 return FALSE;
1893 pExtn++;
1895 if( !g_ascii_strcasecmp( pFilter, pExtn ) )
1896 bRetval = TRUE;
1898 #ifdef DEBUG
1899 fprintf( stderr, "'%s' match extn '%s' vs '%s' yeilds %d\n",
1900 filter_info->uri, pExtn, pFilter, bRetval );
1901 #endif
1903 return bRetval;
1907 int SalGtkFilePicker::implAddFilter( const OUString& rFilter, const OUString& rType )
1909 GtkFileFilter *filter = gtk_file_filter_new();
1911 OUString aShrunkName = shrinkFilterName( rFilter );
1912 OString aFilterName = rtl::OUStringToOString( aShrunkName, RTL_TEXTENCODING_UTF8 );
1913 gtk_file_filter_set_name( filter, aFilterName );
1915 static const OUString aStarDot = OUString::createFromAscii( "*." );
1916 OUString aTokens;
1918 bool bAllGlob = !rType.compareToAscii( "*.*" ) || !rType.compareToAscii( "*" );
1919 if (bAllGlob)
1920 gtk_file_filter_add_pattern( filter, "*" );
1921 else
1923 sal_Int32 nIndex = 0;
1924 rtl::OUString aToken;
1927 aToken = rType.getToken( 0, ';', nIndex );
1928 // Assume all have the "*.<extn>" syntax
1929 aToken = aToken.copy( aToken.lastIndexOf( aStarDot ) + 2 );
1930 if (aToken.getLength())
1932 if (aTokens.getLength())
1933 aTokens += OUString::createFromAscii(",");
1934 aTokens = aTokens += aToken;
1935 gtk_file_filter_add_custom (filter, GTK_FILE_FILTER_URI,
1936 case_insensitive_filter,
1937 g_strdup( rtl::OUStringToOString( aToken, RTL_TEXTENCODING_UTF8 ) ),
1938 (GDestroyNotify) g_free );
1940 OSL_TRACE( "fustering with %s\n", rtl::OUStringToOString( aToken, RTL_TEXTENCODING_UTF8 ).getStr());
1942 #ifdef DEBUG
1943 else
1945 g_warning( "Duff filter token '%s'\n",
1946 (const sal_Char *) rtl::OUStringToOString(
1947 rType.getToken( 0, ';', nIndex ), RTL_TEXTENCODING_UTF8 ) );
1949 #endif
1951 while( nIndex >= 0 );
1954 gtk_file_chooser_add_filter( GTK_FILE_CHOOSER( m_pDialog ), filter );
1956 int nAdded = 0;
1957 if (!bAllGlob)
1959 GtkTreeIter iter;
1960 gtk_list_store_append (m_pFilterStore, &iter);
1961 gtk_list_store_set (m_pFilterStore, &iter,
1962 0, OUStringToOString(shrinkFilterName( rFilter, true ), RTL_TEXTENCODING_UTF8).getStr(),
1963 1, OUStringToOString(aTokens, RTL_TEXTENCODING_UTF8).getStr(),
1964 2, aFilterName.getStr(),
1965 3, OUStringToOString(rType, RTL_TEXTENCODING_UTF8).getStr(),
1966 -1);
1967 nAdded = 1;
1969 return nAdded;
1972 int SalGtkFilePicker::implAddFilterGroup( const OUString& /*_rFilter*/, const Sequence< StringPair >& _rFilters )
1974 // Gtk+ has no filter group concept I think so ...
1975 // implAddFilter( _rFilter, String() );
1976 int nAdded = 0;
1977 const StringPair* pSubFilters = _rFilters.getConstArray();
1978 const StringPair* pSubFiltersEnd = pSubFilters + _rFilters.getLength();
1979 for( ; pSubFilters != pSubFiltersEnd; ++pSubFilters )
1980 nAdded += implAddFilter( pSubFilters->First, pSubFilters->Second );
1981 return nAdded;
1984 void SalGtkFilePicker::SetFilters()
1986 OSL_TRACE( "start setting filters\n");
1987 int nAdded = 0;
1988 if( m_pFilterList && !m_pFilterList->empty() )
1990 for ( FilterList::iterator aListIter = m_pFilterList->begin();
1991 aListIter != m_pFilterList->end();
1992 ++aListIter
1995 if( aListIter->hasSubFilters() )
1996 { // it's a filter group
1998 UnoFilterList aSubFilters;
1999 aListIter->getSubFilters( aSubFilters );
2001 nAdded += implAddFilterGroup( aListIter->getTitle(), aSubFilters );
2003 else
2005 // it's a single filter
2007 nAdded += implAddFilter( aListIter->getTitle(), aListIter->getFilter() );
2012 if (nAdded)
2013 gtk_widget_show( m_pFilterExpander );
2014 else
2015 gtk_widget_hide( m_pFilterExpander );
2017 // set the default filter
2018 if( m_aCurrentFilter && (m_aCurrentFilter.getLength() > 0) )
2020 OSL_TRACE( "Setting current filter to %s\n",
2021 OUStringToOString( m_aCurrentFilter, RTL_TEXTENCODING_UTF8 ).getStr() );
2023 SetCurFilter( m_aCurrentFilter );
2026 OSL_TRACE( "end setting filters\n");
2029 SalGtkFilePicker::~SalGtkFilePicker()
2031 int i;
2033 for( i = 0; i < TOGGLE_LAST; i++ )
2034 gtk_widget_destroy( m_pToggles[i] );
2036 for( i = 0; i < LIST_LAST; i++ )
2038 gtk_widget_destroy( m_pListLabels[i] );
2039 gtk_widget_destroy( m_pAligns[i] ); //m_pAligns[i] owns m_pLists[i]
2040 gtk_widget_destroy( m_pHBoxs[i] );
2043 delete m_pFilterList;
2045 gtk_widget_destroy( m_pVBox );
2048 /* vi:set tabstop=4 shiftwidth=4 expandtab: */