| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_fpicker.hxx" |
| |
| //------------------------------------------------------------------------ |
| // includes |
| //------------------------------------------------------------------------ |
| #include <com/sun/star/lang/DisposedException.hpp> |
| #include <com/sun/star/lang/XMultiServiceFactory.hpp> |
| #include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp> |
| #include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp> |
| #include <com/sun/star/ui/dialogs/CommonFilePickerElementIds.hpp> |
| #include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp> |
| #include <cppuhelper/interfacecontainer.h> |
| #include <osl/diagnose.h> |
| #include <osl/process.h> |
| #include <com/sun/star/ui/dialogs/TemplateDescription.hpp> |
| #include <com/sun/star/ui/dialogs/ControlActions.hpp> |
| #include <com/sun/star/uno/Any.hxx> |
| #include <FPServiceInfo.hxx> |
| #include <vos/mutex.hxx> |
| #include <vcl/svapp.hxx> |
| #include <SalGtkFilePicker.hxx> |
| |
| #include <tools/urlobj.hxx> |
| |
| #include <iostream> |
| #include <algorithm> |
| #include <set> |
| #include "resourceprovider.hxx" |
| #ifndef _SV_RC_H |
| #include <tools/rc.hxx> |
| #endif |
| |
| //------------------------------------------------------------------------ |
| // namespace directives |
| //------------------------------------------------------------------------ |
| |
| using namespace ::com::sun::star; |
| using namespace ::com::sun::star::ui::dialogs; |
| using namespace ::com::sun::star::ui::dialogs::TemplateDescription; |
| using namespace ::com::sun::star::ui::dialogs::ExtendedFilePickerElementIds; |
| using namespace ::com::sun::star::ui::dialogs::CommonFilePickerElementIds; |
| using namespace ::com::sun::star::lang; |
| using namespace ::com::sun::star::beans; |
| using namespace ::com::sun::star::uno; |
| |
| //------------------------------------------------------------------------ |
| // helper functions |
| //------------------------------------------------------------------------ |
| |
| namespace |
| { |
| // controling event notifications |
| const bool STARTUP_SUSPENDED = true; |
| const bool STARTUP_ALIVE = false; |
| |
| uno::Sequence<rtl::OUString> SAL_CALL FilePicker_getSupportedServiceNames() |
| { |
| uno::Sequence<rtl::OUString> aRet(3); |
| aRet[0] = rtl::OUString::createFromAscii( "com.sun.star.ui.dialogs.FilePicker" ); |
| aRet[1] = rtl::OUString::createFromAscii( "com.sun.star.ui.dialogs.SystemFilePicker" ); |
| aRet[2] = rtl::OUString::createFromAscii( "com.sun.star.ui.dialogs.GtkFilePicker" ); |
| return aRet; |
| } |
| } |
| |
| //----------------------------------------------------------------------------------------- |
| // constructor |
| //----------------------------------------------------------------------------------------- |
| |
| static void expandexpanders(GtkContainer *pWidget) |
| { |
| GdkThreadLock aLock; |
| |
| GList *pChildren = gtk_container_get_children(pWidget); |
| for( GList *p = pChildren; p; p = p->next ) |
| { |
| if GTK_IS_CONTAINER(GTK_WIDGET(p->data)) |
| expandexpanders(GTK_CONTAINER(GTK_WIDGET(p->data))); |
| if GTK_IS_EXPANDER(GTK_WIDGET(p->data)) |
| gtk_expander_set_expanded(GTK_EXPANDER(GTK_WIDGET(p->data)), sal_True); |
| } |
| g_list_free(pChildren); |
| } |
| |
| void SalGtkFilePicker::dialog_mapped_cb(GtkWidget *, SalGtkFilePicker *pobjFP) |
| { |
| pobjFP->InitialMapping(); |
| } |
| |
| void SalGtkFilePicker::InitialMapping() |
| { |
| GdkThreadLock aLock; |
| |
| if (!mbPreviewState ) |
| { |
| gtk_widget_hide( m_pPreview ); |
| gtk_file_chooser_set_preview_widget_active( GTK_FILE_CHOOSER( m_pDialog ), false); |
| } |
| gtk_widget_set_size_request (m_pPreview, -1, -1); |
| } |
| |
| SalGtkFilePicker::SalGtkFilePicker( const uno::Reference<lang::XMultiServiceFactory>& xServiceMgr ) : |
| SalGtkPicker(xServiceMgr), |
| cppu::WeakComponentImplHelper10< |
| XFilterManager, |
| XFilterGroupManager, |
| XFilePickerControlAccess, |
| XFilePickerNotifier, |
| XFilePreview, |
| XFilePicker2, |
| lang::XInitialization, |
| util::XCancellable, |
| lang::XEventListener, |
| lang::XServiceInfo>( m_rbHelperMtx ), |
| m_xServiceMgr( xServiceMgr ), |
| m_pFilterList( NULL ), |
| m_pVBox ( NULL ), |
| mnHID_FolderChange( 0 ), |
| mnHID_SelectionChange( 0 ), |
| bVersionWidthUnset( false ), |
| mbPreviewState( sal_False ), |
| mHID_Preview( 0 ), |
| m_pPreview( NULL ), |
| m_pPseudoFilter( NULL ), |
| m_PreviewImageWidth( 256 ), |
| m_PreviewImageHeight( 256 ) |
| { |
| int i; |
| |
| for( i = 0; i < TOGGLE_LAST; i++ ) |
| { |
| m_pToggles[i] = NULL; |
| mbToggleVisibility[i] = false; |
| } |
| |
| for( i = 0; i < BUTTON_LAST; i++ ) |
| { |
| m_pButtons[i] = NULL; |
| mbButtonVisibility[i] = false; |
| } |
| |
| for( i = 0; i < LIST_LAST; i++ ) |
| { |
| m_pHBoxs[i] = NULL; |
| m_pAligns[i] = NULL; |
| m_pLists[i] = NULL; |
| m_pListLabels[i] = NULL; |
| mbListVisibility[i] = false; |
| } |
| |
| CResourceProvider aResProvider; |
| OUString aFilePickerTitle = aResProvider.getResString( FILE_PICKER_TITLE_OPEN ); |
| |
| GdkThreadLock aLock; |
| |
| m_pDialog = gtk_file_chooser_dialog_new( |
| OUStringToOString( aFilePickerTitle, RTL_TEXTENCODING_UTF8 ).getStr(), |
| NULL, |
| GTK_FILE_CHOOSER_ACTION_OPEN, |
| GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, |
| GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, |
| (char *)NULL ); |
| |
| gtk_dialog_set_default_response( GTK_DIALOG (m_pDialog), GTK_RESPONSE_ACCEPT ); |
| |
| gtk_file_chooser_set_local_only( GTK_FILE_CHOOSER( m_pDialog ), sal_False ); |
| gtk_file_chooser_set_select_multiple( GTK_FILE_CHOOSER( m_pDialog ), sal_False ); |
| |
| m_pVBox = gtk_vbox_new( sal_False, 0 ); |
| |
| // We don't want clickable items to have a huge hit-area |
| GtkWidget *pHBox = gtk_hbox_new( sal_False, 0 ); |
| GtkWidget *pThinVBox = gtk_vbox_new( sal_False, 0 ); |
| |
| gtk_box_pack_end (GTK_BOX( m_pVBox ), pHBox, sal_False, sal_False, 0); |
| gtk_box_pack_start (GTK_BOX( pHBox ), pThinVBox, sal_False, sal_False, 0); |
| gtk_widget_show( pHBox ); |
| gtk_widget_show( pThinVBox ); |
| |
| OUString aLabel; |
| |
| for( i = 0; i < TOGGLE_LAST; i++ ) |
| { |
| m_pToggles[i] = gtk_check_button_new(); |
| |
| #define LABEL_TOGGLE( elem ) \ |
| case elem : \ |
| aLabel = aResProvider.getResString( CHECKBOX_##elem ); \ |
| setLabel( CHECKBOX_##elem, aLabel ); \ |
| break |
| |
| switch( i ) { |
| |
| LABEL_TOGGLE( AUTOEXTENSION ); |
| LABEL_TOGGLE( PASSWORD ); |
| LABEL_TOGGLE( FILTEROPTIONS ); |
| LABEL_TOGGLE( READONLY ); |
| LABEL_TOGGLE( LINK ); |
| LABEL_TOGGLE( PREVIEW ); |
| LABEL_TOGGLE( SELECTION ); |
| default: |
| OSL_TRACE("Handle unknown control %d\n", i); |
| break; |
| } |
| |
| gtk_box_pack_end( GTK_BOX( pThinVBox ), m_pToggles[i], sal_False, sal_False, 0 ); |
| } |
| |
| for( i = 0; i < LIST_LAST; i++ ) |
| { |
| m_pHBoxs[i] = gtk_hbox_new( sal_False, 0 ); |
| |
| m_pAligns[i] = gtk_alignment_new(0, 0, 0, 1); |
| |
| m_pLists[i] = gtk_combo_box_new_text(); |
| |
| m_pListLabels[i] = gtk_label_new( "" ); |
| |
| #define LABEL_LIST( elem ) \ |
| case elem : \ |
| aLabel = aResProvider.getResString( LISTBOX_##elem##_LABEL ); \ |
| setLabel( LISTBOX_##elem##_LABEL, aLabel ); \ |
| break |
| |
| switch( i ) |
| { |
| LABEL_LIST( VERSION ); |
| LABEL_LIST( TEMPLATE ); |
| LABEL_LIST( IMAGE_TEMPLATE ); |
| default: |
| OSL_TRACE("Handle unknown control %d\n", i); |
| break; |
| } |
| |
| gtk_container_add( GTK_CONTAINER( m_pAligns[i]), m_pLists[i] ); |
| gtk_box_pack_end( GTK_BOX( m_pHBoxs[i] ), m_pAligns[i], sal_False, sal_False, 0 ); |
| |
| gtk_box_pack_end( GTK_BOX( m_pHBoxs[i] ), m_pListLabels[i], sal_False, sal_False, 0 ); |
| |
| gtk_box_pack_end( GTK_BOX( m_pVBox ), m_pHBoxs[i], sal_False, sal_False, 0 ); |
| } |
| |
| aLabel = aResProvider.getResString( FILE_PICKER_FILE_TYPE ); |
| m_pFilterExpander = gtk_expander_new_with_mnemonic( |
| OUStringToOString( aLabel, RTL_TEXTENCODING_UTF8 ).getStr()); |
| |
| gtk_box_pack_end( GTK_BOX( m_pVBox ), m_pFilterExpander, sal_False, sal_True, 0 ); |
| |
| GtkWidget *scrolled_window = gtk_scrolled_window_new (NULL, NULL); |
| gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), |
| GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); |
| gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window), |
| GTK_SHADOW_IN); |
| gtk_container_add (GTK_CONTAINER (m_pFilterExpander), scrolled_window); |
| gtk_widget_show (scrolled_window); |
| |
| ByteString sExpand(getenv("SAL_EXPANDFPICKER")); |
| sal_Int32 nExpand = sExpand.ToInt32(); |
| switch (nExpand) |
| { |
| default: |
| case 0: |
| break; |
| case 1: |
| gtk_expander_set_expanded( GTK_EXPANDER(m_pFilterExpander), sal_True); |
| break; |
| case 2: |
| expandexpanders(GTK_CONTAINER(m_pDialog)); |
| gtk_expander_set_expanded( GTK_EXPANDER(m_pFilterExpander), sal_True); |
| break; |
| } |
| |
| m_pFilterStore = gtk_list_store_new (4, G_TYPE_STRING, G_TYPE_STRING, |
| G_TYPE_STRING, G_TYPE_STRING); |
| m_pFilterView = gtk_tree_view_new_with_model (GTK_TREE_MODEL(m_pFilterStore)); |
| gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(m_pFilterView), false); |
| gtk_tree_view_set_rules_hint (GTK_TREE_VIEW(m_pFilterView), true); |
| |
| GtkTreeViewColumn *column; |
| GtkCellRenderer *cell; |
| |
| for (i = 0; i < 2; ++i) |
| { |
| column = gtk_tree_view_column_new (); |
| cell = gtk_cell_renderer_text_new (); |
| gtk_tree_view_column_set_expand (column, sal_True); |
| gtk_tree_view_column_pack_start (column, cell, sal_False); |
| gtk_tree_view_column_set_attributes (column, cell, "text", i, (char *)NULL); |
| gtk_tree_view_append_column (GTK_TREE_VIEW(m_pFilterView), column); |
| } |
| |
| gtk_container_add (GTK_CONTAINER (scrolled_window), m_pFilterView); |
| gtk_widget_show (m_pFilterView); |
| |
| gtk_file_chooser_set_extra_widget( GTK_FILE_CHOOSER( m_pDialog ), m_pVBox ); |
| |
| m_pPreview = gtk_image_new(); |
| gtk_file_chooser_set_preview_widget( GTK_FILE_CHOOSER( m_pDialog ), m_pPreview ); |
| |
| g_signal_connect( G_OBJECT( m_pToggles[PREVIEW] ), "toggled", |
| G_CALLBACK( preview_toggled_cb ), this ); |
| g_signal_connect (gtk_tree_view_get_selection (GTK_TREE_VIEW(m_pFilterView)), "changed", |
| G_CALLBACK ( type_changed_cb ), this); |
| g_signal_connect( G_OBJECT( m_pDialog ), "notify::filter", |
| G_CALLBACK( filter_changed_cb ), this); |
| g_signal_connect( G_OBJECT( m_pFilterExpander ), "activate", |
| G_CALLBACK( expander_changed_cb ), this); |
| g_signal_connect (G_OBJECT( m_pDialog ), "map", |
| G_CALLBACK (dialog_mapped_cb), this); |
| |
| gtk_widget_show( m_pVBox ); |
| |
| PangoLayout *layout = gtk_widget_create_pango_layout (m_pFilterView, NULL); |
| guint ypad; |
| PangoRectangle row_height; |
| pango_layout_set_markup (layout, "All Files", -1); |
| pango_layout_get_pixel_extents (layout, NULL, &row_height); |
| g_object_get (cell, "ypad", &ypad, (char *)NULL); |
| guint height = (row_height.height + 2*ypad) * 5; |
| gtk_widget_set_size_request (m_pFilterView, -1, height); |
| gtk_widget_set_size_request (m_pPreview, 1, height); |
| |
| gtk_file_chooser_set_preview_widget_active( GTK_FILE_CHOOSER( m_pDialog ), true); |
| } |
| |
| //------------------------------------------------------------------------------------ |
| // XFilePickerNotifier |
| //------------------------------------------------------------------------------------ |
| |
| void SAL_CALL SalGtkFilePicker::addFilePickerListener( const uno::Reference<XFilePickerListener>& xListener ) |
| throw( uno::RuntimeException ) |
| { |
| m_xListener = xListener; |
| } |
| |
| void SAL_CALL SalGtkFilePicker::removeFilePickerListener( const uno::Reference<XFilePickerListener>& ) |
| throw( uno::RuntimeException ) |
| { |
| m_xListener.clear(); |
| } |
| |
| // ------------------------------------------------- |
| // XEventListener |
| // ------------------------------------------------- |
| |
| void SAL_CALL SalGtkFilePicker::disposing( const lang::EventObject& aEvent ) throw( uno::RuntimeException ) |
| { |
| uno::Reference<XFilePickerListener> xFilePickerListener( aEvent.Source, ::com::sun::star::uno::UNO_QUERY ); |
| |
| if( xFilePickerListener.is() ) |
| removeFilePickerListener( xFilePickerListener ); |
| } |
| |
| //----------------------------------------------------------------------------------------- |
| // FilePicker Event functions |
| //----------------------------------------------------------------------------------------- |
| |
| void SAL_CALL SalGtkFilePicker::fileSelectionChanged( FilePickerEvent aEvent ) |
| { |
| OSL_TRACE( "file selection changed"); |
| if (m_xListener.is()) m_xListener->fileSelectionChanged( aEvent ); |
| } |
| |
| void SAL_CALL SalGtkFilePicker::directoryChanged( FilePickerEvent aEvent ) |
| { |
| OSL_TRACE("directory changed"); |
| if (m_xListener.is()) m_xListener->directoryChanged( aEvent ); |
| } |
| |
| void SAL_CALL SalGtkFilePicker::controlStateChanged( FilePickerEvent aEvent ) |
| { |
| OSL_TRACE("control state changed"); |
| if (m_xListener.is()) m_xListener->controlStateChanged( aEvent ); |
| } |
| |
| //----------------------------------------------------------------------------------------- |
| // If there are more then one listener the return value of the last one wins |
| //----------------------------------------------------------------------------------------- |
| |
| rtl::OUString SAL_CALL SalGtkFilePicker::helpRequested( FilePickerEvent aEvent ) const |
| { |
| rtl::OUString aHelpText; |
| |
| ::cppu::OInterfaceContainerHelper* pICHelper = |
| rBHelper.getContainer( getCppuType( ( uno::Reference<XFilePickerListener> * )0 ) ); |
| |
| if( pICHelper ) |
| { |
| ::cppu::OInterfaceIteratorHelper iter( *pICHelper ); |
| |
| while( iter.hasMoreElements() ) |
| { |
| try |
| { |
| /* |
| if there are multiple listeners responding |
| to this notification the next response |
| overwrittes the one before if it is not empty |
| */ |
| |
| rtl::OUString aTempString; |
| |
| uno::Reference<XFilePickerListener> xFPListener( iter.next(), uno::UNO_QUERY ); |
| if( xFPListener.is() ) |
| { |
| aTempString = xFPListener->helpRequested( aEvent ); |
| if( aTempString.getLength() ) |
| aHelpText = aTempString; |
| } |
| |
| } |
| catch( uno::RuntimeException& ) |
| { |
| OSL_ENSURE( false, "RuntimeException during event dispatching" ); |
| } |
| } |
| } |
| |
| return aHelpText; |
| } |
| |
| //===================================================================== |
| |
| struct FilterEntry |
| { |
| protected: |
| ::rtl::OUString m_sTitle; |
| ::rtl::OUString m_sFilter; |
| |
| UnoFilterList m_aSubFilters; |
| |
| public: |
| FilterEntry( const ::rtl::OUString& _rTitle, const ::rtl::OUString& _rFilter ) |
| :m_sTitle( _rTitle ) |
| ,m_sFilter( _rFilter ) |
| { |
| } |
| |
| FilterEntry( const ::rtl::OUString& _rTitle, const UnoFilterList& _rSubFilters ); |
| |
| ::rtl::OUString getTitle() const { return m_sTitle; } |
| ::rtl::OUString getFilter() const { return m_sFilter; } |
| |
| /// determines if the filter has sub filter (i.e., the filter is a filter group in real) |
| sal_Bool hasSubFilters( ) const; |
| |
| /** retrieves the filters belonging to the entry |
| @return |
| the number of sub filters |
| */ |
| sal_Int32 getSubFilters( UnoFilterList& _rSubFilterList ); |
| |
| // helpers for iterating the sub filters |
| const UnoFilterEntry* beginSubFilters() const { return m_aSubFilters.getConstArray(); } |
| const UnoFilterEntry* endSubFilters() const { return m_aSubFilters.getConstArray() + m_aSubFilters.getLength(); } |
| }; |
| |
| //===================================================================== |
| |
| //--------------------------------------------------------------------- |
| FilterEntry::FilterEntry( const ::rtl::OUString& _rTitle, const UnoFilterList& _rSubFilters ) |
| :m_sTitle( _rTitle ) |
| ,m_aSubFilters( _rSubFilters ) |
| { |
| } |
| |
| //--------------------------------------------------------------------- |
| sal_Bool FilterEntry::hasSubFilters() const |
| { |
| return( 0 < m_aSubFilters.getLength() ); |
| } |
| |
| //--------------------------------------------------------------------- |
| sal_Int32 FilterEntry::getSubFilters( UnoFilterList& _rSubFilterList ) |
| { |
| _rSubFilterList = m_aSubFilters; |
| return m_aSubFilters.getLength(); |
| } |
| |
| static bool |
| isFilterString( const rtl::OUString &rFilterString, const char *pMatch ) |
| { |
| sal_Int32 nIndex = 0; |
| rtl::OUString aToken; |
| bool bIsFilter = true; |
| |
| rtl::OUString aMatch(rtl::OUString::createFromAscii(pMatch)); |
| |
| do |
| { |
| aToken = rFilterString.getToken( 0, ';', nIndex ); |
| if( !aToken.match( aMatch ) ) |
| { |
| bIsFilter = false; |
| break; |
| } |
| } |
| while( nIndex >= 0 ); |
| |
| return bIsFilter; |
| } |
| |
| static rtl::OUString |
| shrinkFilterName( const rtl::OUString &rFilterName, bool bAllowNoStar = false ) |
| { |
| int i; |
| int nBracketLen = -1; |
| int nBracketEnd = -1; |
| const sal_Unicode* pStr = rFilterName.getStr(); |
| OUString aRealName = rFilterName; |
| |
| for( i = aRealName.getLength() - 1; i > 0; i-- ) |
| { |
| if( pStr[i] == ')' ) |
| nBracketEnd = i; |
| else if( pStr[i] == '(' ) |
| { |
| nBracketLen = nBracketEnd - i; |
| if( nBracketEnd <= 0 ) |
| continue; |
| if( isFilterString( rFilterName.copy( i + 1, nBracketLen - 1 ), "*." ) ) |
| aRealName = aRealName.replaceAt( i, nBracketLen + 1, rtl::OUString() ); |
| else if (bAllowNoStar) |
| { |
| if( isFilterString( rFilterName.copy( i + 1, nBracketLen - 1 ), ".") ) |
| aRealName = aRealName.replaceAt( i, nBracketLen + 1, rtl::OUString() ); |
| } |
| } |
| } |
| |
| return aRealName; |
| } |
| |
| static void |
| dialog_remove_buttons( GtkDialog *pDialog ) |
| { |
| GdkThreadLock aLock; |
| |
| g_return_if_fail( GTK_IS_DIALOG( pDialog ) ); |
| |
| GList *pChildren = |
| gtk_container_get_children( GTK_CONTAINER( pDialog->action_area ) ); |
| |
| for( GList *p = pChildren; p; p = p->next ) |
| gtk_widget_destroy( GTK_WIDGET( p->data ) ); |
| |
| g_list_free( pChildren ); |
| } |
| |
| //------------------------------------------------------------------------------------ |
| namespace { |
| //................................................................................ |
| struct FilterTitleMatch : public ::std::unary_function< FilterEntry, bool > |
| { |
| protected: |
| const ::rtl::OUString& rTitle; |
| |
| public: |
| FilterTitleMatch( const ::rtl::OUString& _rTitle ) : rTitle( _rTitle ) { } |
| |
| //............................................................................ |
| bool operator () ( const FilterEntry& _rEntry ) |
| { |
| sal_Bool bMatch; |
| if( !_rEntry.hasSubFilters() ) |
| // a real filter |
| bMatch = ( _rEntry.getTitle() == rTitle ); |
| else |
| // a filter group -> search the sub filters |
| bMatch = |
| _rEntry.endSubFilters() != ::std::find_if( |
| _rEntry.beginSubFilters(), |
| _rEntry.endSubFilters(), |
| *this |
| ); |
| |
| return bMatch ? true : false; |
| } |
| bool operator () ( const UnoFilterEntry& _rEntry ) |
| { |
| OUString aShrunkName = shrinkFilterName( _rEntry.First ); |
| return aShrunkName == rTitle ? true : false; |
| } |
| }; |
| } |
| |
| |
| //------------------------------------------------------------------------------------ |
| sal_Bool SalGtkFilePicker::FilterNameExists( const ::rtl::OUString& rTitle ) |
| { |
| sal_Bool bRet = sal_False; |
| |
| if( m_pFilterList ) |
| bRet = |
| m_pFilterList->end() != ::std::find_if( |
| m_pFilterList->begin(), |
| m_pFilterList->end(), |
| FilterTitleMatch( rTitle ) |
| ); |
| |
| return bRet; |
| } |
| |
| //------------------------------------------------------------------------------------ |
| sal_Bool SalGtkFilePicker::FilterNameExists( const UnoFilterList& _rGroupedFilters ) |
| { |
| sal_Bool bRet = sal_False; |
| |
| if( m_pFilterList ) |
| { |
| const UnoFilterEntry* pStart = _rGroupedFilters.getConstArray(); |
| const UnoFilterEntry* pEnd = pStart + _rGroupedFilters.getLength(); |
| for( ; pStart != pEnd; ++pStart ) |
| if( m_pFilterList->end() != ::std::find_if( |
| m_pFilterList->begin(), |
| m_pFilterList->end(), |
| FilterTitleMatch( pStart->First ) ) ) |
| break; |
| |
| bRet = pStart != pEnd; |
| } |
| |
| return bRet; |
| } |
| |
| //------------------------------------------------------------------------------------ |
| void SalGtkFilePicker::ensureFilterList( const ::rtl::OUString& _rInitialCurrentFilter ) |
| { |
| if( !m_pFilterList ) |
| { |
| m_pFilterList = new FilterList; |
| |
| // set the first filter to the current filter |
| if ( !m_aCurrentFilter.getLength() ) |
| m_aCurrentFilter = _rInitialCurrentFilter; |
| } |
| } |
| |
| |
| //----------------------------------------------------------------------------------------- |
| // |
| //----------------------------------------------------------------------------------------- |
| |
| void SAL_CALL SalGtkFilePicker::appendFilter( const rtl::OUString& aTitle, const rtl::OUString& aFilter ) |
| throw( lang::IllegalArgumentException, uno::RuntimeException ) |
| { |
| OSL_ASSERT( m_pDialog != NULL ); |
| |
| if( FilterNameExists( aTitle ) ) |
| throw IllegalArgumentException(); |
| |
| // ensure that we have a filter list |
| ensureFilterList( aTitle ); |
| |
| // append the filter |
| m_pFilterList->insert( m_pFilterList->end(), FilterEntry( aTitle, aFilter ) ); |
| } |
| |
| //----------------------------------------------------------------------------------------- |
| // |
| //----------------------------------------------------------------------------------------- |
| |
| void SAL_CALL SalGtkFilePicker::setCurrentFilter( const rtl::OUString& aTitle ) |
| throw( lang::IllegalArgumentException, uno::RuntimeException ) |
| { |
| OSL_ASSERT( m_pDialog != NULL ); |
| |
| OSL_TRACE( "Setting current filter to %s\n", |
| OUStringToOString( aTitle, RTL_TEXTENCODING_UTF8 ).getStr() ); |
| |
| if( aTitle != m_aCurrentFilter ) |
| { |
| m_aCurrentFilter = aTitle; |
| SetCurFilter( m_aCurrentFilter ); |
| OSL_TRACE( "REALLY Setting current filter to %s\n", |
| OUStringToOString( aTitle, RTL_TEXTENCODING_UTF8 ).getStr() ); |
| |
| } |
| |
| // TODO m_pImpl->setCurrentFilter( aTitle ); |
| } |
| |
| //----------------------------------------------------------------------------------------- |
| // |
| //----------------------------------------------------------------------------------------- |
| |
| void SalGtkFilePicker::updateCurrentFilterFromName(const gchar* filtername) |
| { |
| OUString aFilterName(filtername, strlen(filtername), RTL_TEXTENCODING_UTF8); |
| FilterList::iterator aEnd = m_pFilterList->end(); |
| for (FilterList::iterator aIter = m_pFilterList->begin(); aIter != aEnd; ++aIter) |
| { |
| if (aFilterName == shrinkFilterName( aIter->getTitle())) |
| { |
| m_aCurrentFilter = aIter->getTitle(); |
| break; |
| } |
| } |
| } |
| |
| void SalGtkFilePicker::UpdateFilterfromUI() |
| { |
| // Update the filtername from the users selection if they have had a chance to do so. |
| // If the user explicitly sets a type then use that, if not then take the implicit type |
| // from the filter of the files glob on which he is currently searching |
| if (!mnHID_FolderChange || !mnHID_SelectionChange) |
| return; |
| |
| GdkThreadLock aLock; |
| |
| GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(m_pFilterView)); |
| GtkTreeIter iter; |
| GtkTreeModel *model; |
| if (gtk_tree_selection_get_selected (selection, &model, &iter)) |
| { |
| gchar *title; |
| gtk_tree_model_get (model, &iter, 2, &title, -1); |
| updateCurrentFilterFromName(title); |
| g_free (title); |
| } |
| else if( GtkFileFilter *filter = gtk_file_chooser_get_filter(GTK_FILE_CHOOSER(m_pDialog))) |
| { |
| if (m_pPseudoFilter != filter) |
| updateCurrentFilterFromName(gtk_file_filter_get_name( filter )); |
| else |
| updateCurrentFilterFromName(OUStringToOString( m_aInitialFilter, RTL_TEXTENCODING_UTF8 ).getStr()); |
| } |
| } |
| |
| rtl::OUString SAL_CALL SalGtkFilePicker::getCurrentFilter() throw( uno::RuntimeException ) |
| { |
| OSL_ASSERT( m_pDialog != NULL ); |
| |
| OSL_TRACE( "GetCURRENTfilter\n" ); |
| |
| UpdateFilterfromUI(); |
| |
| OSL_TRACE( "Returning current filter of %s\n", |
| OUStringToOString( m_aCurrentFilter, RTL_TEXTENCODING_UTF8 ).getStr() ); |
| |
| return m_aCurrentFilter; |
| } |
| |
| //----------------------------------------------------------------------------------------- |
| // XFilterGroupManager functions |
| //----------------------------------------------------------------------------------------- |
| |
| void SAL_CALL SalGtkFilePicker::appendFilterGroup( const rtl::OUString& /*sGroupTitle*/, const uno::Sequence<beans::StringPair>& aFilters ) |
| throw( lang::IllegalArgumentException, uno::RuntimeException ) |
| { |
| OSL_ASSERT( m_pDialog != NULL ); |
| |
| // TODO m_pImpl->appendFilterGroup( sGroupTitle, aFilters ); |
| // check the names |
| if( FilterNameExists( aFilters ) ) |
| // TODO: a more precise exception message |
| throw IllegalArgumentException(); |
| |
| // ensure that we have a filter list |
| ::rtl::OUString sInitialCurrentFilter; |
| if( aFilters.getLength() ) |
| sInitialCurrentFilter = aFilters[0].First; |
| |
| ensureFilterList( sInitialCurrentFilter ); |
| |
| // append the filter |
| const StringPair* pSubFilters = aFilters.getConstArray(); |
| const StringPair* pSubFiltersEnd = pSubFilters + aFilters.getLength(); |
| for( ; pSubFilters != pSubFiltersEnd; ++pSubFilters ) |
| m_pFilterList->insert( m_pFilterList->end(), FilterEntry( pSubFilters->First, pSubFilters->Second ) ); |
| |
| } |
| |
| //----------------------------------------------------------------------------------------- |
| // XFilePicker functions |
| //----------------------------------------------------------------------------------------- |
| |
| void SAL_CALL SalGtkFilePicker::setMultiSelectionMode( sal_Bool bMode ) throw( uno::RuntimeException ) |
| { |
| OSL_ASSERT( m_pDialog != NULL ); |
| |
| GdkThreadLock aLock; |
| |
| gtk_file_chooser_set_select_multiple( GTK_FILE_CHOOSER(m_pDialog), bMode ); |
| } |
| |
| void SAL_CALL SalGtkFilePicker::setDefaultName( const rtl::OUString& aName ) |
| throw( uno::RuntimeException ) |
| { |
| OSL_ASSERT( m_pDialog != NULL ); |
| |
| GdkThreadLock aLock; |
| |
| OString aStr = OUStringToOString( aName, RTL_TEXTENCODING_UTF8 ); |
| GtkFileChooserAction eAction = gtk_file_chooser_get_action( GTK_FILE_CHOOSER( m_pDialog ) ); |
| |
| // set_current_name launches a Gtk critical error if called for other than save |
| if( GTK_FILE_CHOOSER_ACTION_SAVE == eAction ) |
| gtk_file_chooser_set_current_name( GTK_FILE_CHOOSER( m_pDialog ), aStr.getStr() ); |
| } |
| |
| void SAL_CALL SalGtkFilePicker::setDisplayDirectory( const rtl::OUString& rDirectory ) |
| throw( lang::IllegalArgumentException, uno::RuntimeException ) |
| { |
| implsetDisplayDirectory(rDirectory); |
| } |
| |
| rtl::OUString SAL_CALL SalGtkFilePicker::getDisplayDirectory() throw( uno::RuntimeException ) |
| { |
| return implgetDisplayDirectory(); |
| } |
| |
| uno::Sequence<rtl::OUString> SAL_CALL SalGtkFilePicker::getFiles() throw( uno::RuntimeException ) |
| { |
| uno::Sequence< rtl::OUString > aFiles = getSelectedFiles(); |
| /* |
| The previous multiselection API design was completely broken |
| and unimplementable for some hetrogenous pseudo-URIs eg. search:// |
| Thus crop unconditionally to a single selection. |
| */ |
| aFiles.realloc (1); |
| return aFiles; |
| } |
| |
| uno::Sequence<rtl::OUString> SAL_CALL SalGtkFilePicker::getSelectedFiles() throw( uno::RuntimeException ) |
| { |
| OSL_ASSERT( m_pDialog != NULL ); |
| |
| GdkThreadLock aLock; |
| |
| GSList* pPathList = gtk_file_chooser_get_uris( GTK_FILE_CHOOSER(m_pDialog) ); |
| |
| int nCount = g_slist_length( pPathList ); |
| int nIndex = 0; |
| OSL_TRACE( "GETFILES called %d files\n", nCount ); |
| |
| // get the current action setting |
| GtkFileChooserAction eAction = gtk_file_chooser_get_action( |
| GTK_FILE_CHOOSER( m_pDialog )); |
| |
| uno::Sequence< rtl::OUString > aSelectedFiles(nCount); |
| |
| // Convert to OOo |
| for( GSList *pElem = pPathList; pElem; pElem = pElem->next) |
| { |
| gchar *pURI = reinterpret_cast<gchar*>(pElem->data); |
| aSelectedFiles[ nIndex ] = uritounicode(pURI); |
| |
| if( GTK_FILE_CHOOSER_ACTION_SAVE == eAction ) |
| { |
| OUString sFilterName; |
| sal_Int32 nTokenIndex = 0; |
| bool bExtensionTypedIn = false; |
| |
| GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(m_pFilterView)); |
| GtkTreeIter iter; |
| GtkTreeModel *model; |
| if (gtk_tree_selection_get_selected (selection, &model, &iter)) |
| { |
| gchar *title; |
| gtk_tree_model_get (model, &iter, 2, &title, -1); |
| sFilterName = OUString( title, strlen( title), RTL_TEXTENCODING_UTF8 ); |
| g_free (title); |
| } |
| else |
| { |
| if( aSelectedFiles[nIndex].indexOf('.') > 0 ) |
| { |
| rtl::OUString sExtension; |
| nTokenIndex = 0; |
| do |
| sExtension = aSelectedFiles[nIndex].getToken( 0, '.', nTokenIndex ); |
| while( nTokenIndex >= 0 ); |
| |
| if( sExtension.getLength() >= 3 ) // 3 = typical/minimum extension length |
| { |
| static const OUString aStarDot = OUString::createFromAscii( "*." ); |
| |
| ::rtl::OUString aNewFilter; |
| ::rtl::OUString aOldFilter = getCurrentFilter(); |
| sal_Bool bChangeFilter = sal_True; |
| for ( FilterList::iterator aListIter = m_pFilterList->begin(); |
| aListIter != m_pFilterList->end(); |
| ++aListIter |
| ) |
| { |
| if( aListIter->getFilter().indexOf( aStarDot+sExtension ) >= 0 ) |
| { |
| if( !aNewFilter.getLength() ) |
| aNewFilter = aListIter->getTitle(); |
| |
| if( aOldFilter == aListIter->getTitle() ) |
| bChangeFilter = sal_False; |
| |
| bExtensionTypedIn = true; |
| } |
| } |
| if( bChangeFilter ) |
| setCurrentFilter( aNewFilter ); |
| } |
| } |
| |
| GtkFileFilter *filter = gtk_file_chooser_get_filter(GTK_FILE_CHOOSER(m_pDialog)); |
| if (m_pPseudoFilter != filter) |
| { |
| const gchar* filtername = |
| gtk_file_filter_get_name( filter ); |
| sFilterName = OUString( filtername, strlen( filtername ), RTL_TEXTENCODING_UTF8 ); |
| } |
| else |
| sFilterName = m_aInitialFilter; |
| } |
| |
| OSL_TRACE( "2: current filter is %s\n", |
| OUStringToOString( sFilterName, RTL_TEXTENCODING_UTF8 ).getStr() ); |
| |
| FilterList::iterator aListIter = ::std::find_if( |
| m_pFilterList->begin(), m_pFilterList->end(), FilterTitleMatch(sFilterName) ); |
| |
| OUString aFilter; |
| if (aListIter != m_pFilterList->end()) |
| aFilter = aListIter->getFilter(); |
| |
| OSL_TRACE( "turned into %s\n", |
| OUStringToOString( aFilter, RTL_TEXTENCODING_UTF8 ).getStr() ); |
| |
| nTokenIndex = 0; |
| rtl::OUString sToken; |
| // rtl::OUString strExt; |
| do |
| { |
| sToken = aFilter.getToken( 0, '.', nTokenIndex ); |
| |
| if ( sToken.lastIndexOf( ';' ) != -1 ) |
| { |
| sal_Int32 nZero = 0; |
| OUString aCurrentToken = sToken.getToken( 0, ';', nZero); |
| |
| sToken = aCurrentToken; |
| break; |
| } |
| } |
| while( nTokenIndex >= 0 ); |
| |
| if( !bExtensionTypedIn && ( !sToken.equalsAscii( "*" ) ) ) |
| { |
| //if the filename does not already have the auto extension, stick it on |
| OUString sExtension = OUString::createFromAscii( "." ) + sToken; |
| OUString &rBase = aSelectedFiles[nIndex]; |
| sal_Int32 nExtensionIdx = rBase.getLength() - sExtension.getLength(); |
| OSL_TRACE( "idx are %d %d\n", rBase.lastIndexOf( sExtension ), nExtensionIdx ); |
| |
| if( rBase.lastIndexOf( sExtension ) != nExtensionIdx ) |
| rBase += sExtension; |
| } |
| |
| } |
| |
| nIndex++; |
| g_free( pURI ); |
| } |
| |
| g_slist_free( pPathList ); |
| |
| return aSelectedFiles; |
| } |
| |
| //----------------------------------------------------------------------------------------- |
| // XExecutableDialog functions |
| //----------------------------------------------------------------------------------------- |
| |
| void SAL_CALL SalGtkFilePicker::setTitle( const rtl::OUString& rTitle ) throw( uno::RuntimeException ) |
| { |
| implsetTitle(rTitle); |
| } |
| |
| sal_Int16 SAL_CALL SalGtkFilePicker::execute() throw( uno::RuntimeException ) |
| { |
| OSL_TRACE( "1: HERE WE ARE\n"); |
| OSL_ASSERT( m_pDialog != NULL ); |
| |
| GdkThreadLock aLock; |
| |
| sal_Int16 retVal = 0; |
| |
| SetFilters(); |
| |
| mnHID_FolderChange = |
| g_signal_connect( GTK_FILE_CHOOSER( m_pDialog ), "current-folder-changed", |
| G_CALLBACK( folder_changed_cb ), ( gpointer )this ); |
| |
| mnHID_SelectionChange = |
| g_signal_connect( GTK_FILE_CHOOSER( m_pDialog ), "selection-changed", |
| G_CALLBACK( selection_changed_cb ), ( gpointer )this ); |
| |
| int btn = GTK_RESPONSE_NO; |
| |
| uno::Reference< awt::XExtendedToolkit > xToolkit( |
| m_xServiceMgr->createInstance( ::rtl::OUString::createFromAscii("com.sun.star.awt.Toolkit") ), uno::UNO_QUERY); |
| |
| RunDialog* pRunDialog = new RunDialog(m_pDialog, xToolkit); |
| uno::Reference < awt::XTopWindowListener > xLifeCycle(pRunDialog); |
| while( GTK_RESPONSE_NO == btn ) |
| { |
| btn = GTK_RESPONSE_YES; // we dont want to repeat unless user clicks NO for file save. |
| |
| gint nStatus = pRunDialog->run(); |
| switch( nStatus ) |
| { |
| case GTK_RESPONSE_ACCEPT: |
| if( GTK_FILE_CHOOSER_ACTION_SAVE == gtk_file_chooser_get_action( GTK_FILE_CHOOSER( m_pDialog ) ) ) |
| { |
| Sequence < OUString > aPathSeq = getFiles(); |
| if( aPathSeq.getLength() == 1 ) |
| { |
| OString sFileName = unicodetouri( aPathSeq[0] ); |
| if( g_file_test( g_filename_from_uri( sFileName.getStr(), NULL, NULL ), G_FILE_TEST_IS_REGULAR ) ) |
| { |
| CResourceProvider aResProvider; |
| GtkWidget *dlg; |
| |
| dlg = gtk_message_dialog_new( NULL, |
| GTK_DIALOG_MODAL, |
| GTK_MESSAGE_QUESTION, |
| GTK_BUTTONS_YES_NO, |
| OUStringToOString( |
| aResProvider.getResString( FILE_PICKER_OVERWRITE ), |
| RTL_TEXTENCODING_UTF8 ).getStr() ); |
| |
| gtk_window_set_title( GTK_WINDOW( dlg ), |
| OUStringToOString(aResProvider.getResString(FILE_PICKER_TITLE_SAVE ), |
| RTL_TEXTENCODING_UTF8 ).getStr() ); |
| |
| RunDialog* pAnotherDialog = new RunDialog(dlg, xToolkit); |
| uno::Reference < awt::XTopWindowListener > xAnotherLifeCycle(pAnotherDialog); |
| btn = pAnotherDialog->run(); |
| |
| gtk_widget_destroy( dlg ); |
| } |
| |
| if( btn == GTK_RESPONSE_YES ) |
| retVal = ExecutableDialogResults::OK; |
| } |
| } |
| else |
| retVal = ExecutableDialogResults::OK; |
| break; |
| |
| case GTK_RESPONSE_CANCEL: |
| retVal = ExecutableDialogResults::CANCEL; |
| break; |
| |
| case 1: //PLAY |
| { |
| FilePickerEvent evt; |
| evt.ElementId = PUSHBUTTON_PLAY; |
| OSL_TRACE( "filter_changed, isn't it great %x\n", this); |
| controlStateChanged( evt ); |
| btn = GTK_RESPONSE_NO; |
| } |
| break; |
| |
| default: |
| retVal = 0; |
| break; |
| } |
| } |
| |
| if (mnHID_FolderChange) |
| g_signal_handler_disconnect(GTK_FILE_CHOOSER( m_pDialog ), mnHID_FolderChange); |
| if (mnHID_SelectionChange) |
| g_signal_handler_disconnect(GTK_FILE_CHOOSER( m_pDialog ), mnHID_SelectionChange); |
| |
| return retVal; |
| } |
| |
| //------------------------------------------------------------------------------------ |
| |
| // cf. offapi/com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.idl |
| GtkWidget *SalGtkFilePicker::getWidget( sal_Int16 nControlId, GType *pType ) |
| { |
| OSL_TRACE("control id is %d", nControlId); |
| GType tType = GTK_TYPE_TOGGLE_BUTTON; //prevent waring by initializing |
| GtkWidget *pWidget = 0; |
| |
| #define MAP_TOGGLE( elem ) \ |
| case ExtendedFilePickerElementIds::CHECKBOX_##elem: \ |
| pWidget = m_pToggles[elem]; tType = GTK_TYPE_TOGGLE_BUTTON; \ |
| break |
| #define MAP_BUTTON( elem ) \ |
| case ExtendedFilePickerElementIds::PUSHBUTTON_##elem: \ |
| pWidget = m_pButtons[elem]; tType = GTK_TYPE_BUTTON; \ |
| break |
| #define MAP_LIST( elem ) \ |
| case ExtendedFilePickerElementIds::LISTBOX_##elem: \ |
| pWidget = m_pLists[elem]; tType = GTK_TYPE_COMBO_BOX; \ |
| break |
| #define MAP_LIST_LABEL( elem ) \ |
| case ExtendedFilePickerElementIds::LISTBOX_##elem##_LABEL: \ |
| pWidget = m_pListLabels[elem]; tType = GTK_TYPE_LABEL; \ |
| break |
| |
| switch( nControlId ) |
| { |
| MAP_TOGGLE( AUTOEXTENSION ); |
| MAP_TOGGLE( PASSWORD ); |
| MAP_TOGGLE( FILTEROPTIONS ); |
| MAP_TOGGLE( READONLY ); |
| MAP_TOGGLE( LINK ); |
| MAP_TOGGLE( PREVIEW ); |
| MAP_TOGGLE( SELECTION ); |
| MAP_BUTTON( PLAY ); |
| MAP_LIST( VERSION ); |
| MAP_LIST( TEMPLATE ); |
| MAP_LIST( IMAGE_TEMPLATE ); |
| MAP_LIST_LABEL( VERSION ); |
| MAP_LIST_LABEL( TEMPLATE ); |
| MAP_LIST_LABEL( IMAGE_TEMPLATE ); |
| default: |
| OSL_TRACE("Handle unknown control %d\n", nControlId); |
| break; |
| } |
| #undef MAP |
| |
| if( pType ) |
| *pType = tType; |
| return pWidget; |
| } |
| |
| |
| |
| //------------------------------------------------------------------------------------ |
| // XFilePickerControlAccess functions |
| //------------------------------------------------------------------------------------ |
| namespace |
| { |
| void HackWidthToFirst(GtkComboBox *pWidget) |
| { |
| GdkThreadLock aLock; |
| |
| GtkRequisition requisition; |
| gtk_widget_size_request(GTK_WIDGET(pWidget), &requisition); |
| gtk_widget_set_size_request(GTK_WIDGET(pWidget), requisition.width, -1); |
| } |
| } |
| |
| void SalGtkFilePicker::HandleSetListValue(GtkComboBox *pWidget, sal_Int16 nControlAction, const uno::Any& rValue) |
| { |
| GdkThreadLock aLock; |
| |
| switch (nControlAction) |
| { |
| case ControlActions::ADD_ITEM: |
| { |
| OUString sItem; |
| rValue >>= sItem; |
| gtk_combo_box_append_text(pWidget, rtl::OUStringToOString(sItem, RTL_TEXTENCODING_UTF8).getStr()); |
| if (!bVersionWidthUnset) |
| { |
| HackWidthToFirst(pWidget); |
| bVersionWidthUnset = true; |
| } |
| } |
| break; |
| case ControlActions::ADD_ITEMS: |
| { |
| Sequence< OUString > aStringList; |
| rValue >>= aStringList; |
| sal_Int32 nItemCount = aStringList.getLength(); |
| for (sal_Int32 i = 0; i < nItemCount; ++i) |
| { |
| gtk_combo_box_append_text(pWidget, |
| rtl::OUStringToOString(aStringList[i], RTL_TEXTENCODING_UTF8).getStr()); |
| if (!bVersionWidthUnset) |
| { |
| HackWidthToFirst(pWidget); |
| bVersionWidthUnset = true; |
| } |
| } |
| } |
| break; |
| case ControlActions::DELETE_ITEM: |
| { |
| sal_Int32 nPos=0; |
| rValue >>= nPos; |
| gtk_combo_box_remove_text(pWidget, nPos); |
| } |
| break; |
| case ControlActions::DELETE_ITEMS: |
| { |
| gtk_combo_box_set_active(pWidget, -1); |
| gint nItems = 0; |
| do |
| { |
| nItems = |
| gtk_tree_model_iter_n_children( |
| gtk_combo_box_get_model(pWidget), NULL); |
| for (gint nI = 0; nI < nItems; ++nI) |
| gtk_combo_box_remove_text(pWidget, nI); |
| } |
| while (nItems); |
| } |
| break; |
| case ControlActions::SET_SELECT_ITEM: |
| { |
| sal_Int32 nPos=0; |
| rValue >>= nPos; |
| gtk_combo_box_set_active(pWidget, nPos); |
| } |
| break; |
| default: |
| OSL_TRACE("undocumented/unimplemented ControlAction for a list"); |
| break; |
| } |
| |
| //I think its best to make it insensitive unless there is the chance to |
| //actually select something from the list. |
| gint nItems = gtk_tree_model_iter_n_children( |
| gtk_combo_box_get_model(pWidget), NULL); |
| gtk_widget_set_sensitive(GTK_WIDGET(pWidget), nItems > 1 ? true : false); |
| } |
| |
| uno::Any SalGtkFilePicker::HandleGetListValue(GtkComboBox *pWidget, sal_Int16 nControlAction) const |
| { |
| GdkThreadLock aLock; |
| |
| uno::Any aAny; |
| switch (nControlAction) |
| { |
| case ControlActions::GET_ITEMS: |
| { |
| Sequence< OUString > aItemList; |
| |
| GtkTreeModel *pTree = gtk_combo_box_get_model(pWidget); |
| GtkTreeIter iter; |
| if (gtk_tree_model_get_iter_first(pTree, &iter)) |
| { |
| sal_Int32 nSize = gtk_tree_model_iter_n_children( |
| pTree, NULL); |
| |
| aItemList.realloc(nSize); |
| for (sal_Int32 i=0; i < nSize; ++i) |
| { |
| gchar *item; |
| gtk_tree_model_get(gtk_combo_box_get_model(pWidget), |
| &iter, 0, &item, -1); |
| aItemList[i] = OUString(item, strlen(item), RTL_TEXTENCODING_UTF8); |
| g_free(item); |
| gtk_tree_model_iter_next(pTree, &iter); |
| } |
| } |
| aAny <<= aItemList; |
| } |
| break; |
| case ControlActions::GET_SELECTED_ITEM: |
| { |
| GtkTreeIter iter; |
| if (gtk_combo_box_get_active_iter(pWidget, &iter)) |
| { |
| gchar *item; |
| gtk_tree_model_get(gtk_combo_box_get_model(pWidget), |
| &iter, 0, &item, -1); |
| OUString sItem(item, strlen(item), RTL_TEXTENCODING_UTF8); |
| aAny <<= sItem; |
| g_free(item); |
| } |
| } |
| break; |
| case ControlActions::GET_SELECTED_ITEM_INDEX: |
| { |
| gint nActive = gtk_combo_box_get_active(pWidget); |
| aAny <<= static_cast< sal_Int32 >(nActive); |
| } |
| break; |
| default: |
| OSL_TRACE("undocumented/unimplemented ControlAction for a list"); |
| break; |
| } |
| return aAny; |
| } |
| |
| void SAL_CALL SalGtkFilePicker::setValue( sal_Int16 nControlId, sal_Int16 nControlAction, const uno::Any& rValue ) |
| throw( uno::RuntimeException ) |
| { |
| OSL_ASSERT( m_pDialog != NULL ); |
| |
| OSL_TRACE( "SETTING VALUE %d\n", nControlAction ); |
| GType tType; |
| GtkWidget *pWidget; |
| |
| GdkThreadLock aLock; |
| |
| if( !( pWidget = getWidget( nControlId, &tType ) ) ) |
| OSL_TRACE("enable unknown control %d\n", nControlId); |
| else if( tType == GTK_TYPE_TOGGLE_BUTTON ) |
| { |
| sal_Bool bChecked = false; |
| rValue >>= bChecked; |
| gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( pWidget ), bChecked ); |
| } |
| else if( tType == GTK_TYPE_COMBO_BOX ) |
| HandleSetListValue(GTK_COMBO_BOX(pWidget), nControlAction, rValue); |
| else |
| { |
| OSL_TRACE("Can't set value on button / list %d %d\n", |
| nControlId, nControlAction); |
| } |
| } |
| |
| uno::Any SAL_CALL SalGtkFilePicker::getValue( sal_Int16 nControlId, sal_Int16 nControlAction ) |
| throw( uno::RuntimeException ) |
| { |
| OSL_ASSERT( m_pDialog != NULL ); |
| |
| uno::Any aRetval; |
| |
| GType tType; |
| GtkWidget *pWidget; |
| |
| GdkThreadLock aLock; |
| |
| if( !( pWidget = getWidget( nControlId, &tType ) ) ) |
| OSL_TRACE("enable unknown control %d\n", nControlId); |
| else if( tType == GTK_TYPE_TOGGLE_BUTTON ) |
| aRetval <<= (sal_Bool) gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( pWidget ) ); |
| else if( tType == GTK_TYPE_COMBO_BOX ) |
| aRetval = HandleGetListValue(GTK_COMBO_BOX(pWidget), nControlAction); |
| else |
| OSL_TRACE("Can't get value on button / list %d %d\n", |
| nControlId, nControlAction ); |
| |
| return aRetval; |
| } |
| |
| void SAL_CALL SalGtkFilePicker::enableControl( sal_Int16 nControlId, sal_Bool bEnable ) |
| throw( uno::RuntimeException ) |
| { |
| OSL_ASSERT( m_pDialog != NULL ); |
| |
| GtkWidget *pWidget; |
| |
| GdkThreadLock aLock; |
| |
| if ( nControlId == ExtendedFilePickerElementIds::LISTBOX_FILTER_SELECTOR ) |
| gtk_expander_set_expanded( GTK_EXPANDER( m_pFilterExpander ), bEnable ); |
| else if( ( pWidget = getWidget( nControlId ) ) ) |
| { |
| if( bEnable ) |
| { |
| OSL_TRACE( "enable\n" ); |
| gtk_widget_set_sensitive( pWidget, sal_True ); |
| } |
| else |
| { |
| OSL_TRACE( "disable\n" ); |
| gtk_widget_set_sensitive( pWidget, sal_False ); |
| } |
| } |
| else |
| OSL_TRACE("enable unknown control %d\n", nControlId ); |
| } |
| |
| void SAL_CALL SalGtkFilePicker::setLabel( sal_Int16 nControlId, const ::rtl::OUString& rLabel ) |
| throw( uno::RuntimeException ) |
| { |
| OSL_ASSERT( m_pDialog != NULL ); |
| |
| GType tType; |
| GtkWidget *pWidget; |
| |
| GdkThreadLock aLock; |
| |
| if( !( pWidget = getWidget( nControlId, &tType ) ) ) |
| { |
| OSL_TRACE("Set label on unknown control %d\n", nControlId); |
| return; |
| } |
| |
| OString aTxt = OUStringToOString( rLabel.replace('~', '_'), RTL_TEXTENCODING_UTF8 ); |
| if (nControlId == ExtendedFilePickerElementIds::PUSHBUTTON_PLAY) |
| { |
| #ifdef GTK_STOCK_MEDIA_PLAY |
| if (!msPlayLabel.getLength()) |
| msPlayLabel = rLabel; |
| if (msPlayLabel == rLabel) |
| gtk_button_set_label(GTK_BUTTON(pWidget), GTK_STOCK_MEDIA_PLAY); |
| else |
| gtk_button_set_label(GTK_BUTTON(pWidget), GTK_STOCK_MEDIA_STOP); |
| #else |
| gtk_button_set_label(GTK_BUTTON(pWidget), aTxt.getStr()); |
| #endif |
| } |
| else if( tType == GTK_TYPE_TOGGLE_BUTTON || tType == GTK_TYPE_BUTTON || tType == GTK_TYPE_LABEL ) |
| g_object_set( pWidget, "label", aTxt.getStr(), |
| "use_underline", sal_True, (char *)NULL ); |
| else |
| OSL_TRACE("Can't set label on list\n"); |
| } |
| |
| rtl::OUString SAL_CALL SalGtkFilePicker::getLabel( sal_Int16 nControlId ) |
| throw( uno::RuntimeException ) |
| { |
| OSL_ASSERT( m_pDialog != NULL ); |
| |
| GType tType; |
| OString aTxt; |
| GtkWidget *pWidget; |
| |
| GdkThreadLock aLock; |
| |
| if( !( pWidget = getWidget( nControlId, &tType ) ) ) |
| OSL_TRACE("Get label on unknown control %d\n", nControlId); |
| else if( tType == GTK_TYPE_TOGGLE_BUTTON || tType == GTK_TYPE_BUTTON || tType == GTK_TYPE_LABEL ) |
| aTxt = gtk_button_get_label( GTK_BUTTON( pWidget ) ); |
| else |
| OSL_TRACE("Can't get label on list\n"); |
| |
| return OStringToOUString( aTxt, RTL_TEXTENCODING_UTF8 ); |
| } |
| |
| //------------------------------------------------------------------------------------ |
| // XFilePreview functions |
| //------------------------------------------------------------------------------------ |
| |
| uno::Sequence<sal_Int16> SAL_CALL SalGtkFilePicker::getSupportedImageFormats() throw( uno::RuntimeException ) |
| { |
| OSL_ASSERT( m_pDialog != NULL ); |
| |
| // TODO return m_pImpl->getSupportedImageFormats(); |
| return uno::Sequence<sal_Int16>(); |
| } |
| |
| sal_Int32 SAL_CALL SalGtkFilePicker::getTargetColorDepth() throw( uno::RuntimeException ) |
| { |
| OSL_ASSERT( m_pDialog != NULL ); |
| |
| // TODO return m_pImpl->getTargetColorDepth(); |
| return 0; |
| } |
| |
| sal_Int32 SAL_CALL SalGtkFilePicker::getAvailableWidth() throw( uno::RuntimeException ) |
| { |
| OSL_ASSERT( m_pDialog != NULL ); |
| |
| return m_PreviewImageWidth; |
| } |
| |
| sal_Int32 SAL_CALL SalGtkFilePicker::getAvailableHeight() throw( uno::RuntimeException ) |
| { |
| OSL_ASSERT( m_pDialog != NULL ); |
| |
| return m_PreviewImageHeight; |
| } |
| |
| void SAL_CALL SalGtkFilePicker::setImage( sal_Int16 /*aImageFormat*/, const uno::Any& /*aImage*/ ) |
| throw( lang::IllegalArgumentException, uno::RuntimeException ) |
| { |
| OSL_ASSERT( m_pDialog != NULL ); |
| |
| // TODO m_pImpl->setImage( aImageFormat, aImage ); |
| } |
| |
| void SalGtkFilePicker::implChangeType( GtkTreeSelection *selection ) |
| { |
| CResourceProvider aResProvider; |
| OUString aLabel = aResProvider.getResString( FILE_PICKER_FILE_TYPE ); |
| |
| GdkThreadLock aLock; |
| |
| GtkTreeIter iter; |
| GtkTreeModel *model; |
| if (gtk_tree_selection_get_selected (selection, &model, &iter)) |
| { |
| gchar *title; |
| gtk_tree_model_get (model, &iter, 2, &title, -1); |
| aLabel += rtl::OUString::createFromAscii( ": " ); |
| aLabel += rtl::OUString( title, strlen(title), RTL_TEXTENCODING_UTF8 ); |
| g_free (title); |
| } |
| gtk_expander_set_label (GTK_EXPANDER (m_pFilterExpander), |
| OUStringToOString( aLabel, RTL_TEXTENCODING_UTF8 ).getStr()); |
| FilePickerEvent evt; |
| evt.ElementId = LISTBOX_FILTER; |
| controlStateChanged( evt ); |
| } |
| |
| void SalGtkFilePicker::type_changed_cb( GtkTreeSelection *selection, SalGtkFilePicker *pobjFP ) |
| { |
| pobjFP->implChangeType(selection); |
| } |
| |
| void SalGtkFilePicker::unselect_type() |
| { |
| GdkThreadLock aLock; |
| |
| gtk_tree_selection_unselect_all(gtk_tree_view_get_selection(GTK_TREE_VIEW(m_pFilterView))); |
| } |
| |
| void SalGtkFilePicker::expander_changed_cb( GtkExpander *expander, SalGtkFilePicker *pobjFP ) |
| { |
| if (gtk_expander_get_expanded(expander)) |
| pobjFP->unselect_type(); |
| } |
| |
| void SalGtkFilePicker::filter_changed_cb( GtkFileChooser *, GParamSpec *, |
| SalGtkFilePicker *pobjFP ) |
| { |
| FilePickerEvent evt; |
| evt.ElementId = LISTBOX_FILTER; |
| OSL_TRACE( "filter_changed, isn't it great %x\n", pobjFP ); |
| pobjFP->controlStateChanged( evt ); |
| } |
| |
| void SalGtkFilePicker::folder_changed_cb( GtkFileChooser *, SalGtkFilePicker *pobjFP ) |
| { |
| FilePickerEvent evt; |
| OSL_TRACE( "folder_changed, isn't it great %x\n", pobjFP ); |
| pobjFP->directoryChanged( evt ); |
| } |
| |
| void SalGtkFilePicker::selection_changed_cb( GtkFileChooser *, SalGtkFilePicker *pobjFP ) |
| { |
| FilePickerEvent evt; |
| OSL_TRACE( "selection_changed, isn't it great %x\n", pobjFP ); |
| pobjFP->fileSelectionChanged( evt ); |
| } |
| |
| void SalGtkFilePicker::update_preview_cb( GtkFileChooser *file_chooser, SalGtkFilePicker* pobjFP ) |
| { |
| GtkWidget *preview; |
| char *filename; |
| GdkPixbuf *pixbuf; |
| gboolean have_preview = sal_False; |
| |
| preview = pobjFP->m_pPreview; |
| filename = gtk_file_chooser_get_preview_filename( file_chooser ); |
| |
| if( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( pobjFP->m_pToggles[PREVIEW] ) ) && g_file_test( filename, G_FILE_TEST_IS_REGULAR ) ) |
| { |
| pixbuf = gdk_pixbuf_new_from_file_at_size( |
| filename, |
| pobjFP->m_PreviewImageWidth, |
| pobjFP->m_PreviewImageHeight, NULL ); |
| |
| have_preview = ( pixbuf != NULL ); |
| |
| gtk_image_set_from_pixbuf( GTK_IMAGE( preview ), pixbuf ); |
| if( pixbuf ) |
| gdk_pixbuf_unref( pixbuf ); |
| |
| } |
| |
| gtk_file_chooser_set_preview_widget_active( file_chooser, have_preview ); |
| |
| if( filename ) |
| g_free( filename ); |
| } |
| |
| sal_Bool SAL_CALL SalGtkFilePicker::setShowState( sal_Bool bShowState ) throw( uno::RuntimeException ) |
| { |
| OSL_ASSERT( m_pDialog != NULL ); |
| |
| // TODO return m_pImpl->setShowState( bShowState ); |
| if( bShowState != mbPreviewState ) |
| { |
| GdkThreadLock aLock; |
| |
| if( bShowState ) |
| { |
| // Show |
| if( !mHID_Preview ) |
| { |
| mHID_Preview = g_signal_connect( |
| GTK_FILE_CHOOSER( m_pDialog ), "update-preview", |
| G_CALLBACK( update_preview_cb ), ( gpointer )this ); |
| } |
| gtk_widget_show( m_pPreview ); |
| } |
| else |
| { |
| // Hide |
| gtk_widget_hide( m_pPreview ); |
| } |
| |
| // also emit the signal |
| g_signal_emit_by_name( GTK_OBJECT( m_pDialog ), "update-preview" ); |
| |
| mbPreviewState = bShowState; |
| } |
| return true; |
| } |
| |
| sal_Bool SAL_CALL SalGtkFilePicker::getShowState() throw( uno::RuntimeException ) |
| { |
| OSL_ASSERT( m_pDialog != NULL ); |
| |
| return mbPreviewState; |
| } |
| |
| //------------------------------------------------------------------------------------ |
| // XInitialization |
| //------------------------------------------------------------------------------------ |
| |
| void SAL_CALL SalGtkFilePicker::initialize( const uno::Sequence<uno::Any>& aArguments ) |
| throw( uno::Exception, uno::RuntimeException ) |
| { |
| // parameter checking |
| uno::Any aAny; |
| if( 0 == aArguments.getLength() ) |
| throw lang::IllegalArgumentException( |
| rtl::OUString::createFromAscii( "no arguments" ), |
| static_cast<XFilePicker2*>( this ), 1 ); |
| |
| aAny = aArguments[0]; |
| |
| if( ( aAny.getValueType() != ::getCppuType( ( sal_Int16* )0 ) ) && |
| (aAny.getValueType() != ::getCppuType( ( sal_Int8* )0 ) ) ) |
| throw lang::IllegalArgumentException( |
| rtl::OUString::createFromAscii( "invalid argument type" ), |
| static_cast<XFilePicker2*>( this ), 1 ); |
| |
| sal_Int16 templateId = -1; |
| aAny >>= templateId; |
| |
| GtkFileChooserAction eAction = GTK_FILE_CHOOSER_ACTION_OPEN; |
| const gchar *first_button_text = GTK_STOCK_OPEN; |
| |
| |
| // TODO: extract full semantic from |
| // svtools/source/filepicker/filepicker.cxx (getWinBits) |
| switch( templateId ) |
| { |
| case FILEOPEN_SIMPLE: |
| eAction = GTK_FILE_CHOOSER_ACTION_OPEN; |
| first_button_text = GTK_STOCK_OPEN; |
| OSL_TRACE( "3all true\n" ); |
| break; |
| case FILESAVE_SIMPLE: |
| eAction = GTK_FILE_CHOOSER_ACTION_SAVE; |
| first_button_text = GTK_STOCK_SAVE; |
| OSL_TRACE( "2all true\n" ); |
| break; |
| case FILESAVE_AUTOEXTENSION_PASSWORD: |
| eAction = GTK_FILE_CHOOSER_ACTION_SAVE; |
| first_button_text = GTK_STOCK_SAVE; |
| mbToggleVisibility[PASSWORD] = true; |
| OSL_TRACE( "1all true\n" ); |
| // TODO |
| break; |
| case FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS: |
| eAction = GTK_FILE_CHOOSER_ACTION_SAVE; |
| first_button_text = GTK_STOCK_SAVE; |
| mbToggleVisibility[PASSWORD] = true; |
| mbToggleVisibility[FILTEROPTIONS] = true; |
| OSL_TRACE( "4all true\n" ); |
| // TODO |
| break; |
| case FILESAVE_AUTOEXTENSION_SELECTION: |
| eAction = GTK_FILE_CHOOSER_ACTION_SAVE; // SELECT_FOLDER ? |
| first_button_text = GTK_STOCK_SAVE; |
| mbToggleVisibility[SELECTION] = true; |
| OSL_TRACE( "5all true\n" ); |
| // TODO |
| break; |
| case FILESAVE_AUTOEXTENSION_TEMPLATE: |
| eAction = GTK_FILE_CHOOSER_ACTION_SAVE; |
| first_button_text = GTK_STOCK_SAVE; |
| mbListVisibility[TEMPLATE] = true; |
| OSL_TRACE( "6all true\n" ); |
| // TODO |
| break; |
| case FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE: |
| eAction = GTK_FILE_CHOOSER_ACTION_OPEN; |
| first_button_text = GTK_STOCK_OPEN; |
| mbToggleVisibility[LINK] = true; |
| mbToggleVisibility[PREVIEW] = true; |
| mbListVisibility[IMAGE_TEMPLATE] = true; |
| // TODO |
| break; |
| case FILEOPEN_PLAY: |
| eAction = GTK_FILE_CHOOSER_ACTION_OPEN; |
| first_button_text = GTK_STOCK_OPEN; |
| mbButtonVisibility[PLAY] = true; |
| // TODO |
| break; |
| case FILEOPEN_READONLY_VERSION: |
| eAction = GTK_FILE_CHOOSER_ACTION_OPEN; |
| first_button_text = GTK_STOCK_OPEN; |
| mbToggleVisibility[READONLY] = true; |
| mbListVisibility[VERSION] = true; |
| break; |
| case FILEOPEN_LINK_PREVIEW: |
| eAction = GTK_FILE_CHOOSER_ACTION_OPEN; |
| first_button_text = GTK_STOCK_OPEN; |
| mbToggleVisibility[LINK] = true; |
| mbToggleVisibility[PREVIEW] = true; |
| // TODO |
| break; |
| case FILESAVE_AUTOEXTENSION: |
| eAction = GTK_FILE_CHOOSER_ACTION_SAVE; |
| first_button_text = GTK_STOCK_SAVE; |
| OSL_TRACE( "7all true\n" ); |
| // TODO |
| break; |
| default: |
| throw lang::IllegalArgumentException( |
| rtl::OUString::createFromAscii( "Unknown template" ), |
| static_cast< XFilePicker2* >( this ), |
| 1 ); |
| } |
| |
| GdkThreadLock aLock; |
| |
| if( GTK_FILE_CHOOSER_ACTION_SAVE == eAction ) |
| { |
| CResourceProvider aResProvider; |
| OUString aFilePickerTitle(aResProvider.getResString( FILE_PICKER_TITLE_SAVE )); |
| gtk_window_set_title ( GTK_WINDOW( m_pDialog ), |
| OUStringToOString( aFilePickerTitle, RTL_TEXTENCODING_UTF8 ).getStr() ); |
| } |
| |
| gtk_file_chooser_set_action( GTK_FILE_CHOOSER( m_pDialog ), eAction); |
| dialog_remove_buttons( GTK_DIALOG( m_pDialog ) ); |
| gtk_dialog_add_button( GTK_DIALOG( m_pDialog ), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL ); |
| for( int nTVIndex = 0; nTVIndex < BUTTON_LAST; nTVIndex++ ) |
| { |
| if( mbButtonVisibility[nTVIndex] ) |
| { |
| #ifdef GTK_STOCK_MEDIA_PLAY |
| m_pButtons[ nTVIndex ] = gtk_dialog_add_button( GTK_DIALOG( m_pDialog ), GTK_STOCK_MEDIA_PLAY, 1 ); |
| #else |
| CResourceProvider aResProvider; |
| OString aPlay = OUStringToOString( aResProvider.getResString( PUSHBUTTON_PLAY ), RTL_TEXTENCODING_UTF8 ); |
| m_pButtons[ nTVIndex ] = gtk_dialog_add_button( GTK_DIALOG( m_pDialog ), aPlay.getStr(), 1 ); |
| #endif |
| } |
| } |
| gtk_dialog_add_button( GTK_DIALOG( m_pDialog ), first_button_text, GTK_RESPONSE_ACCEPT ); |
| |
| gtk_dialog_set_default_response( GTK_DIALOG (m_pDialog), GTK_RESPONSE_ACCEPT ); |
| |
| // Setup special flags |
| for( int nTVIndex = 0; nTVIndex < TOGGLE_LAST; nTVIndex++ ) |
| { |
| if( mbToggleVisibility[nTVIndex] ) |
| gtk_widget_show( m_pToggles[ nTVIndex ] ); |
| } |
| |
| for( int nTVIndex = 0; nTVIndex < LIST_LAST; nTVIndex++ ) |
| { |
| if( mbListVisibility[nTVIndex] ) |
| { |
| gtk_widget_set_sensitive( m_pLists[ nTVIndex ], false ); |
| gtk_widget_show( m_pLists[ nTVIndex ] ); |
| gtk_widget_show( m_pListLabels[ nTVIndex ] ); |
| gtk_widget_show( m_pAligns[ nTVIndex ] ); |
| gtk_widget_show( m_pHBoxs[ nTVIndex ] ); |
| } |
| } |
| } |
| |
| void SalGtkFilePicker::preview_toggled_cb( GtkObject *cb, SalGtkFilePicker* pobjFP ) |
| { |
| if( pobjFP->mbToggleVisibility[PREVIEW] ) |
| pobjFP->setShowState( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( cb ) ) ); |
| } |
| |
| //------------------------------------------------------------------------------------ |
| // XCancellable |
| //------------------------------------------------------------------------------------ |
| |
| void SAL_CALL SalGtkFilePicker::cancel() throw( uno::RuntimeException ) |
| { |
| OSL_ASSERT( m_pDialog != NULL ); |
| |
| // TODO m_pImpl->cancel(); |
| } |
| |
| // ------------------------------------------------- |
| // XServiceInfo |
| // ------------------------------------------------- |
| |
| rtl::OUString SAL_CALL SalGtkFilePicker::getImplementationName() |
| throw( uno::RuntimeException ) |
| { |
| return rtl::OUString::createFromAscii( FILE_PICKER_IMPL_NAME ); |
| } |
| |
| // ------------------------------------------------- |
| // XServiceInfo |
| // ------------------------------------------------- |
| |
| sal_Bool SAL_CALL SalGtkFilePicker::supportsService( const rtl::OUString& ServiceName ) |
| throw( uno::RuntimeException ) |
| { |
| uno::Sequence <rtl::OUString> SupportedServicesNames = FilePicker_getSupportedServiceNames(); |
| |
| for( sal_Int32 n = SupportedServicesNames.getLength(); n--; ) |
| if( SupportedServicesNames[n].compareTo( ServiceName ) == 0) |
| return sal_True; |
| |
| return sal_False; |
| } |
| |
| // ------------------------------------------------- |
| // XServiceInfo |
| // ------------------------------------------------- |
| |
| uno::Sequence<rtl::OUString> SAL_CALL SalGtkFilePicker::getSupportedServiceNames() |
| throw( uno::RuntimeException ) |
| { |
| return FilePicker_getSupportedServiceNames(); |
| } |
| |
| |
| //-------------------------------------------------- |
| // Misc |
| //------------------------------------------------- |
| void SalGtkFilePicker::SetCurFilter( const OUString& rFilter ) |
| { |
| GdkThreadLock aLock; |
| |
| // Get all the filters already added |
| GSList *filters = gtk_file_chooser_list_filters ( GTK_FILE_CHOOSER( m_pDialog ) ); |
| bool bFound = false; |
| |
| for( GSList *iter = filters; !bFound && iter; iter = iter->next ) |
| { |
| GtkFileFilter* pFilter = reinterpret_cast<GtkFileFilter *>( iter->data ); |
| G_CONST_RETURN gchar * filtername = gtk_file_filter_get_name( pFilter ); |
| OUString sFilterName( filtername, strlen( filtername ), RTL_TEXTENCODING_UTF8 ); |
| |
| OUString aShrunkName = shrinkFilterName( rFilter ); |
| if( aShrunkName.equals( sFilterName) ) |
| { |
| OSL_TRACE( "actually setting %s\n", filtername ); |
| gtk_file_chooser_set_filter( GTK_FILE_CHOOSER( m_pDialog ), pFilter ); |
| bFound = true; |
| } |
| } |
| |
| g_slist_free( filters ); |
| } |
| |
| extern "C" |
| { |
| static gboolean |
| case_insensitive_filter (const GtkFileFilterInfo *filter_info, gpointer data) |
| { |
| gboolean bRetval = sal_False; |
| const char *pFilter = (const char *) data; |
| |
| g_return_val_if_fail( data != NULL, sal_False ); |
| g_return_val_if_fail( filter_info != NULL, sal_False ); |
| |
| if( !filter_info->uri ) |
| return sal_False; |
| |
| const char *pExtn = strrchr( filter_info->uri, '.' ); |
| if( !pExtn ) |
| return sal_False; |
| pExtn++; |
| |
| if( !g_ascii_strcasecmp( pFilter, pExtn ) ) |
| bRetval = sal_True; |
| |
| #ifdef DEBUG |
| fprintf( stderr, "'%s' match extn '%s' vs '%s' yeilds %d\n", |
| filter_info->uri, pExtn, pFilter, bRetval ); |
| #endif |
| |
| return bRetval; |
| } |
| } |
| |
| GtkFileFilter* SalGtkFilePicker::implAddFilter( const OUString& rFilter, const OUString& rType ) |
| { |
| GdkThreadLock aLock; |
| |
| GtkFileFilter *filter = gtk_file_filter_new(); |
| |
| OUString aShrunkName = shrinkFilterName( rFilter ); |
| OString aFilterName = rtl::OUStringToOString( aShrunkName, RTL_TEXTENCODING_UTF8 ); |
| gtk_file_filter_set_name( filter, aFilterName.getStr() ); |
| |
| static const OUString aStarDot = OUString::createFromAscii( "*." ); |
| OUString aTokens; |
| |
| bool bAllGlob = !rType.compareToAscii( "*.*" ) || !rType.compareToAscii( "*" ); |
| if (bAllGlob) |
| gtk_file_filter_add_pattern( filter, "*" ); |
| else |
| { |
| sal_Int32 nIndex = 0; |
| rtl::OUString aToken; |
| do |
| { |
| aToken = rType.getToken( 0, ';', nIndex ); |
| // Assume all have the "*.<extn>" syntax |
| aToken = aToken.copy( aToken.lastIndexOf( aStarDot ) + 2 ); |
| if (aToken.getLength()) |
| { |
| if (aTokens.getLength()) |
| aTokens += OUString::createFromAscii(","); |
| aTokens = aTokens += aToken; |
| gtk_file_filter_add_custom (filter, GTK_FILE_FILTER_URI, |
| case_insensitive_filter, |
| g_strdup( rtl::OUStringToOString( aToken, RTL_TEXTENCODING_UTF8).getStr() ), |
| (GDestroyNotify) g_free ); |
| |
| OSL_TRACE( "fustering with %s\n", rtl::OUStringToOString( aToken, RTL_TEXTENCODING_UTF8 ).getStr()); |
| } |
| #ifdef DEBUG |
| else |
| { |
| g_warning( "Duff filter token '%s'\n", |
| rtl::OUStringToOString( rType.getToken( 0, ';', nIndex ), RTL_TEXTENCODING_UTF8 ).getStr()); |
| } |
| #endif |
| } |
| while( nIndex >= 0 ); |
| } |
| |
| gtk_file_chooser_add_filter( GTK_FILE_CHOOSER( m_pDialog ), filter ); |
| |
| if (!bAllGlob) |
| { |
| GtkTreeIter iter; |
| gtk_list_store_append (m_pFilterStore, &iter); |
| gtk_list_store_set (m_pFilterStore, &iter, |
| 0, OUStringToOString(shrinkFilterName( rFilter, true ), RTL_TEXTENCODING_UTF8).getStr(), |
| 1, OUStringToOString(aTokens, RTL_TEXTENCODING_UTF8).getStr(), |
| 2, aFilterName.getStr(), |
| 3, OUStringToOString(rType, RTL_TEXTENCODING_UTF8).getStr(), |
| -1); |
| } |
| return filter; |
| } |
| |
| void SalGtkFilePicker::implAddFilterGroup( const OUString& /*_rFilter*/, const Sequence< StringPair >& _rFilters ) |
| { |
| // Gtk+ has no filter group concept I think so ... |
| // implAddFilter( _rFilter, String() ); |
| const StringPair* pSubFilters = _rFilters.getConstArray(); |
| const StringPair* pSubFiltersEnd = pSubFilters + _rFilters.getLength(); |
| for( ; pSubFilters != pSubFiltersEnd; ++pSubFilters ) |
| implAddFilter( pSubFilters->First, pSubFilters->Second ); |
| } |
| |
| void SalGtkFilePicker::SetFilters() |
| { |
| GdkThreadLock aLock; |
| |
| if (!m_aInitialFilter.getLength()) |
| m_aInitialFilter = m_aCurrentFilter; |
| |
| rtl::OUString sPseudoFilter; |
| if( GTK_FILE_CHOOSER_ACTION_SAVE == gtk_file_chooser_get_action( GTK_FILE_CHOOSER( m_pDialog ) ) ) |
| { |
| std::set<OUString> aAllFormats; |
| if( m_pFilterList && !m_pFilterList->empty() ) |
| { |
| for ( FilterList::iterator aListIter = m_pFilterList->begin(); |
| aListIter != m_pFilterList->end(); |
| ++aListIter |
| ) |
| { |
| if( aListIter->hasSubFilters() ) |
| { // it's a filter group |
| UnoFilterList aSubFilters; |
| aListIter->getSubFilters( aSubFilters ); |
| const StringPair* pSubFilters = aSubFilters.getConstArray(); |
| const StringPair* pSubFiltersEnd = pSubFilters + aSubFilters.getLength(); |
| for( ; pSubFilters != pSubFiltersEnd; ++pSubFilters ) |
| aAllFormats.insert(pSubFilters->Second); |
| } |
| else |
| aAllFormats.insert(aListIter->getFilter()); |
| } |
| } |
| if (aAllFormats.size() > 1) |
| { |
| rtl::OUString sAllFilter; |
| std::set<OUString>::const_iterator aEnd = aAllFormats.end(); |
| for (std::set<OUString>::const_iterator aIter = aAllFormats.begin(); aIter != aEnd; ++aIter) |
| { |
| if (sAllFilter.getLength()) |
| sAllFilter += OUString(sal_Unicode(';')); |
| sAllFilter += *aIter; |
| } |
| CResourceProvider aResProvider; |
| sPseudoFilter = aResProvider.getResString(FILE_PICKER_ALLFORMATS); |
| m_pPseudoFilter = implAddFilter( sPseudoFilter, sAllFilter ); |
| } |
| } |
| |
| if( m_pFilterList && !m_pFilterList->empty() ) |
| { |
| for ( FilterList::iterator aListIter = m_pFilterList->begin(); |
| aListIter != m_pFilterList->end(); |
| ++aListIter |
| ) |
| { |
| if( aListIter->hasSubFilters() ) |
| { // it's a filter group |
| |
| UnoFilterList aSubFilters; |
| aListIter->getSubFilters( aSubFilters ); |
| |
| implAddFilterGroup( aListIter->getTitle(), aSubFilters ); |
| } |
| else |
| { |
| // it's a single filter |
| |
| implAddFilter( aListIter->getTitle(), aListIter->getFilter() ); |
| } |
| } |
| } |
| |
| if (gtk_tree_model_iter_n_children(GTK_TREE_MODEL(m_pFilterStore), NULL)) //If m_pFilterStore is not empty |
| gtk_widget_show( m_pFilterExpander ); |
| else |
| gtk_widget_hide( m_pFilterExpander ); |
| |
| // set the default filter |
| if (sPseudoFilter.getLength()) |
| SetCurFilter( sPseudoFilter ); |
| else if(m_aCurrentFilter.getLength()) |
| SetCurFilter( m_aCurrentFilter ); |
| |
| OSL_TRACE( "end setting filters\n"); |
| } |
| |
| SalGtkFilePicker::~SalGtkFilePicker() |
| { |
| int i; |
| |
| for( i = 0; i < TOGGLE_LAST; i++ ) |
| gtk_widget_destroy( m_pToggles[i] ); |
| |
| for( i = 0; i < LIST_LAST; i++ ) |
| { |
| gtk_widget_destroy( m_pListLabels[i] ); |
| gtk_widget_destroy( m_pAligns[i] ); //m_pAligns[i] owns m_pLists[i] |
| gtk_widget_destroy( m_pHBoxs[i] ); |
| } |
| |
| delete m_pFilterList; |
| |
| gtk_widget_destroy( m_pVBox ); |
| } |
| |
| /* vi:set tabstop=4 shiftwidth=4 expandtab: */ |