From e335eb1438ed99260a5ca050548b2693b5b22b1c Mon Sep 17 00:00:00 2001 From: Michael Meeks Date: Fri, 4 Nov 2011 10:46:56 +0000 Subject: gtk3: move gtk+ file picker into vcl - a more sensible place for it --- vcl/unx/gtk/fpicker/FPServiceInfo.hxx | 53 + vcl/unx/gtk/fpicker/FPentry.cxx | 141 ++ vcl/unx/gtk/fpicker/SalGtkFilePicker.cxx | 2082 ++++++++++++++++++++++++++++ vcl/unx/gtk/fpicker/SalGtkFilePicker.hxx | 356 +++++ vcl/unx/gtk/fpicker/SalGtkFolderPicker.cxx | 253 ++++ vcl/unx/gtk/fpicker/SalGtkFolderPicker.hxx | 127 ++ vcl/unx/gtk/fpicker/SalGtkPicker.cxx | 313 +++++ vcl/unx/gtk/fpicker/SalGtkPicker.hxx | 138 ++ vcl/unx/gtk/fpicker/eventnotification.hxx | 54 + vcl/unx/gtk/fpicker/fps_gnome.component | 37 + vcl/unx/gtk/fpicker/fps_gnome.xml | 79 ++ vcl/unx/gtk/fpicker/resourceprovider.cxx | 229 +++ vcl/unx/gtk/fpicker/resourceprovider.hxx | 69 + 13 files changed, 3931 insertions(+) create mode 100644 vcl/unx/gtk/fpicker/FPServiceInfo.hxx create mode 100644 vcl/unx/gtk/fpicker/FPentry.cxx create mode 100644 vcl/unx/gtk/fpicker/SalGtkFilePicker.cxx create mode 100644 vcl/unx/gtk/fpicker/SalGtkFilePicker.hxx create mode 100644 vcl/unx/gtk/fpicker/SalGtkFolderPicker.cxx create mode 100644 vcl/unx/gtk/fpicker/SalGtkFolderPicker.hxx create mode 100644 vcl/unx/gtk/fpicker/SalGtkPicker.cxx create mode 100644 vcl/unx/gtk/fpicker/SalGtkPicker.hxx create mode 100644 vcl/unx/gtk/fpicker/eventnotification.hxx create mode 100644 vcl/unx/gtk/fpicker/fps_gnome.component create mode 100644 vcl/unx/gtk/fpicker/fps_gnome.xml create mode 100644 vcl/unx/gtk/fpicker/resourceprovider.cxx create mode 100644 vcl/unx/gtk/fpicker/resourceprovider.hxx (limited to 'vcl/unx') diff --git a/vcl/unx/gtk/fpicker/FPServiceInfo.hxx b/vcl/unx/gtk/fpicker/FPServiceInfo.hxx new file mode 100644 index 000000000000..c0352af2b25d --- /dev/null +++ b/vcl/unx/gtk/fpicker/FPServiceInfo.hxx @@ -0,0 +1,53 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _FPSERVICEINFO_HXX_ +#define _FPSERVICEINFO_HXX_ + +//------------------------------------------------------------------------ +// defines +//------------------------------------------------------------------------ + +// the service names +#define FILE_PICKER_SERVICE_NAME "com.sun.star.ui.dialogs.GtkFilePicker" +#define FOLDER_PICKER_SERVICE_NAME "com.sun.star.ui.dialogs.GtkFolderPicker" + +// the implementation names +#define FILE_PICKER_IMPL_NAME "com.sun.star.ui.dialogs.SalGtkFilePicker" +#define FOLDER_PICKER_IMPL_NAME "com.sun.star.ui.dialogs.SalGtkFolderPicker" + +// the registry key names +// a key under which this service will be registered, +// Format: -> "/ImplName/UNO/SERVICES/ServiceName" +// +#define FILE_PICKER_REGKEY_NAME "/com.sun.star.ui.dialogs.SalGtkFilePicker/UNO/SERVICES/com.sun.star.ui.dialogs.GtkFilePicker" +#define FOLDER_PICKER_REGKEY_NAME "/com.sun.star.ui.dialogs.SalGtkFolderPicker/UNO/SERVICES/com.sun.star.ui.dialogs.GtkFolderPicker" + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/unx/gtk/fpicker/FPentry.cxx b/vcl/unx/gtk/fpicker/FPentry.cxx new file mode 100644 index 000000000000..0ea7fb4bd8c2 --- /dev/null +++ b/vcl/unx/gtk/fpicker/FPentry.cxx @@ -0,0 +1,141 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_fpicker.hxx" + +#ifdef AIX +#define _LINUX_SOURCE_COMPAT +#include +#undef _LINUX_SOURCE_COMPAT +#endif + +//---------------------------------------------- +// includes of other projects +//---------------------------------------------- +#include +#include +#include "SalGtkFilePicker.hxx" +#include "SalGtkFolderPicker.hxx" +#include "FPServiceInfo.hxx" + +#include + +extern const guint gtk_major_version; +extern const guint gtk_minor_version; + +//----------------------------------------------- +// namespace directives +//----------------------------------------------- + +using namespace ::rtl; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::registry; +using namespace ::cppu; +using ::com::sun::star::ui::dialogs::XFilePicker2; +using ::com::sun::star::ui::dialogs::XFolderPicker; + +//------------------------------------------------ +// +//------------------------------------------------ + +static Reference< XInterface > SAL_CALL createFileInstance( + const Reference< XMultiServiceFactory >& rServiceManager ) +{ + return Reference< XInterface >( + static_cast< XFilePicker2* >( + new SalGtkFilePicker( rServiceManager ) ) ); +} + +static Reference< XInterface > SAL_CALL createFolderInstance( + const Reference< XMultiServiceFactory >& rServiceManager ) +{ + return Reference< XInterface >( + static_cast< XFolderPicker* >( + new SalGtkFolderPicker( rServiceManager ) ) ); +} + +extern "C" +{ + +SAL_DLLPUBLIC_EXPORT void* SAL_CALL component_getFactory( + const sal_Char* pImplName, uno_Interface* pSrvManager, uno_Interface* /*pRegistryKey*/ ) +{ + void* pRet = 0; + + if( pSrvManager ) + { + if ( + /* crude gtkplug check */ !g_type_from_name( "GdkDisplay" ) || + /* old version */ !( gtk_major_version >= 2 && gtk_minor_version >= 4 ) + ) + { + return 0; + } + + Reference< XSingleServiceFactory > xFactory; + + if (0 == rtl_str_compare(pImplName, FILE_PICKER_IMPL_NAME)) + { + Sequence< OUString > aSNS( 1 ); + aSNS.getArray( )[0] = + OUString(RTL_CONSTASCII_USTRINGPARAM(FILE_PICKER_SERVICE_NAME)); + + xFactory = createSingleFactory( + reinterpret_cast< XMultiServiceFactory* > ( pSrvManager ), + OUString::createFromAscii( pImplName ), + createFileInstance, + aSNS ); + } + else if (0 == rtl_str_compare(pImplName, FOLDER_PICKER_IMPL_NAME)) + { + Sequence< OUString > aSNS( 1 ); + aSNS.getArray( )[0] = + OUString(RTL_CONSTASCII_USTRINGPARAM(FOLDER_PICKER_SERVICE_NAME)); + + xFactory = createSingleFactory( + reinterpret_cast< XMultiServiceFactory* > ( pSrvManager ), + OUString::createFromAscii( pImplName ), + createFolderInstance, + aSNS ); + } + + if ( xFactory.is() ) + { + xFactory->acquire(); + pRet = xFactory.get(); + } + } + + return pRet; +} + +} // extern "C" + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/unx/gtk/fpicker/SalGtkFilePicker.cxx b/vcl/unx/gtk/fpicker/SalGtkFilePicker.cxx new file mode 100644 index 000000000000..1cac9895c6ca --- /dev/null +++ b/vcl/unx/gtk/fpicker/SalGtkFilePicker.cxx @@ -0,0 +1,2082 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_fpicker.hxx" + +#ifdef AIX +#define _LINUX_SOURCE_COMPAT +#include +#undef _LINUX_SOURCE_COMPAT +#endif + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include +#include "resourceprovider.hxx" + +//------------------------------------------------------------------------ +// 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 SAL_CALL FilePicker_getSupportedServiceNames() + { + uno::Sequence aRet(3); + aRet[0] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.dialogs.FilePicker" )); + aRet[1] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.dialogs.SystemFilePicker" )); + aRet[2] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.dialogs.GtkFilePicker" )); + return aRet; + } +} + +//----------------------------------------------------------------------------------------- +// constructor +//----------------------------------------------------------------------------------------- + +static void expandexpanders(GtkContainer *pWidget) +{ + 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() +{ + 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& 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 ); + + 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", 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", 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); + + rtl::OString 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& xListener ) + throw( uno::RuntimeException ) +{ + SolarMutexGuard g; + + OSL_ENSURE(!m_xListener.is(), + "SalGtkFilePicker only talks with one listener at a time..."); + m_xListener = xListener; +} + +void SAL_CALL SalGtkFilePicker::removeFilePickerListener( const uno::Reference& ) + throw( uno::RuntimeException ) +{ + SolarMutexGuard g; + + m_xListener.clear(); +} + +// ------------------------------------------------- +// XEventListener +// ------------------------------------------------- + +void SAL_CALL SalGtkFilePicker::disposing( const lang::EventObject& aEvent ) throw( uno::RuntimeException ) +{ + // no member access => no mutex needed + + uno::Reference xFilePickerListener( aEvent.Source, ::com::sun::star::uno::UNO_QUERY ); + + if( xFilePickerListener.is() ) + removeFilePickerListener( xFilePickerListener ); +} + +//----------------------------------------------------------------------------------------- +// FilePicker Event functions +//----------------------------------------------------------------------------------------- + +void SalGtkFilePicker::impl_fileSelectionChanged( FilePickerEvent aEvent ) +{ + OSL_TRACE( "file selection changed"); + if (m_xListener.is()) m_xListener->fileSelectionChanged( aEvent ); +} + +void SalGtkFilePicker::impl_directoryChanged( FilePickerEvent aEvent ) +{ + OSL_TRACE("directory changed"); + if (m_xListener.is()) m_xListener->directoryChanged( aEvent ); +} + +void SalGtkFilePicker::impl_controlStateChanged( FilePickerEvent aEvent ) +{ + OSL_TRACE("control state changed"); + if (m_xListener.is()) m_xListener->controlStateChanged( aEvent ); +} + +//===================================================================== + +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 ) +{ + 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 ) +{ + SolarMutexGuard g; + + 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 ) +{ + SolarMutexGuard g; + + 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; + + 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 ) +{ + SolarMutexGuard g; + + OSL_ASSERT( m_pDialog != NULL ); + + OSL_TRACE( "GetCURRENTfilter" ); + + 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& aFilters ) + throw( lang::IllegalArgumentException, uno::RuntimeException ) +{ + SolarMutexGuard g; + + 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 ) +{ + SolarMutexGuard g; + + OSL_ASSERT( m_pDialog != NULL ); + + gtk_file_chooser_set_select_multiple( GTK_FILE_CHOOSER(m_pDialog), bMode ); +} + +void SAL_CALL SalGtkFilePicker::setDefaultName( const rtl::OUString& aName ) + throw( uno::RuntimeException ) +{ + SolarMutexGuard g; + + OSL_ASSERT( m_pDialog != NULL ); + + 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 ) +{ + SolarMutexGuard g; + + implsetDisplayDirectory(rDirectory); +} + +rtl::OUString SAL_CALL SalGtkFilePicker::getDisplayDirectory() throw( uno::RuntimeException ) +{ + SolarMutexGuard g; + + return implgetDisplayDirectory(); +} + +uno::Sequence SAL_CALL SalGtkFilePicker::getFiles() throw( uno::RuntimeException ) +{ + // no member access => no mutex needed + + 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 SAL_CALL SalGtkFilePicker::getSelectedFiles() throw( uno::RuntimeException ) +{ + SolarMutexGuard g; + + OSL_ASSERT( m_pDialog != NULL ); + + 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", 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(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(RTL_CONSTASCII_USTRINGPARAM( "*." )); + + ::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().equalsIgnoreAsciiCase( aStarDot+sExtension ) ) + { + if( !aNewFilter.getLength() ) + aNewFilter = aListIter->getTitle(); + + if( aOldFilter == aListIter->getTitle() ) + bChangeFilter = sal_False; + + bExtensionTypedIn = true; + } + } + if( bChangeFilter && bExtensionTypedIn ) + 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.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("*")) ) ) + { + //if the filename does not already have the auto extension, stick it on + OUString sExtension = OUString(RTL_CONSTASCII_USTRINGPARAM( "." )) + sToken; + OUString &rBase = aSelectedFiles[nIndex]; + sal_Int32 nExtensionIdx = rBase.getLength() - sExtension.getLength(); + OSL_TRACE( "idx are %d %d", 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 ) +{ + SolarMutexGuard g; + + implsetTitle(rTitle); +} + +sal_Int16 SAL_CALL SalGtkFilePicker::execute() throw( uno::RuntimeException ) +{ + SolarMutexGuard g; + + OSL_TRACE( "1: HERE WE ARE"); + OSL_ASSERT( m_pDialog != NULL ); + + 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(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.awt.Toolkit")) ), uno::UNO_QUERY); + + uno::Reference< frame::XDesktop > xDesktop( + m_xServiceMgr->createInstance( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop")) ), uno::UNO_QUERY); + + RunDialog* pRunDialog = new RunDialog(m_pDialog, xToolkit, xDesktop); + 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; + + + INetURLObject aFileObj( sFileName ); + + OString baseName( + OUStringToOString( + aFileObj.getName( + INetURLObject::LAST_SEGMENT, + true, + INetURLObject::DECODE_WITH_CHARSET + ), + RTL_TEXTENCODING_UTF8 + ) + ); + OString aMsg( + OUStringToOString( + aResProvider.getResString( FILE_PICKER_OVERWRITE ), + RTL_TEXTENCODING_UTF8 + ) + ); + OString toReplace( RTL_CONSTASCII_STRINGPARAM( "$filename$" )); + + aMsg = aMsg.replaceAt( + aMsg.indexOf( toReplace ), + toReplace.getLength(), + baseName + ); + + dlg = gtk_message_dialog_new( NULL, + GTK_DIALOG_MODAL, + GTK_MESSAGE_QUESTION, + GTK_BUTTONS_YES_NO, + "%s", + aMsg.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, xDesktop); + 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", this); + impl_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", nControlId); + break; + } +#undef MAP + + if( pType ) + *pType = tType; + return pWidget; +} + + + +//------------------------------------------------------------------------------------ +// XFilePickerControlAccess functions +//------------------------------------------------------------------------------------ +namespace +{ + void HackWidthToFirst(GtkComboBox *pWidget) + { + 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) +{ + 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 +{ + 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 ) +{ + SolarMutexGuard g; + + OSL_ASSERT( m_pDialog != NULL ); + + OSL_TRACE( "SETTING VALUE %d", nControlAction ); + GType tType; + GtkWidget *pWidget; + + if( !( pWidget = getWidget( nControlId, &tType ) ) ) + OSL_TRACE("enable unknown control %d", 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 ) +{ + SolarMutexGuard g; + + OSL_ASSERT( m_pDialog != NULL ); + + uno::Any aRetval; + + GType tType; + GtkWidget *pWidget; + + if( !( pWidget = getWidget( nControlId, &tType ) ) ) + OSL_TRACE("enable unknown control %d", 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 ) +{ + SolarMutexGuard g; + + OSL_ASSERT( m_pDialog != NULL ); + + GtkWidget *pWidget; + + 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" ); + gtk_widget_set_sensitive( pWidget, sal_True ); + } + else + { + OSL_TRACE( "disable" ); + gtk_widget_set_sensitive( pWidget, sal_False ); + } + } + else + OSL_TRACE("enable unknown control %d", nControlId ); +} + +void SAL_CALL SalGtkFilePicker::setLabel( sal_Int16 nControlId, const ::rtl::OUString& rLabel ) + throw( uno::RuntimeException ) +{ + SolarMutexGuard g; + + OSL_ASSERT( m_pDialog != NULL ); + + GType tType; + GtkWidget *pWidget; + + if( !( pWidget = getWidget( nControlId, &tType ) ) ) + { + OSL_TRACE("Set label on unknown control %d", 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"); +} + +rtl::OUString SAL_CALL SalGtkFilePicker::getLabel( sal_Int16 nControlId ) + throw( uno::RuntimeException ) +{ + SolarMutexGuard g; + + OSL_ASSERT( m_pDialog != NULL ); + + GType tType; + OString aTxt; + GtkWidget *pWidget; + + if( !( pWidget = getWidget( nControlId, &tType ) ) ) + OSL_TRACE("Get label on unknown control %d", 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"); + + return OStringToOUString( aTxt, RTL_TEXTENCODING_UTF8 ); +} + +//------------------------------------------------------------------------------------ +// XFilePreview functions +//------------------------------------------------------------------------------------ + +uno::Sequence SAL_CALL SalGtkFilePicker::getSupportedImageFormats() throw( uno::RuntimeException ) +{ + SolarMutexGuard g; + + OSL_ASSERT( m_pDialog != NULL ); + + // TODO return m_pImpl->getSupportedImageFormats(); + return uno::Sequence(); +} + +sal_Int32 SAL_CALL SalGtkFilePicker::getTargetColorDepth() throw( uno::RuntimeException ) +{ + SolarMutexGuard g; + + OSL_ASSERT( m_pDialog != NULL ); + + // TODO return m_pImpl->getTargetColorDepth(); + return 0; +} + +sal_Int32 SAL_CALL SalGtkFilePicker::getAvailableWidth() throw( uno::RuntimeException ) +{ + SolarMutexGuard g; + + OSL_ASSERT( m_pDialog != NULL ); + + return m_PreviewImageWidth; +} + +sal_Int32 SAL_CALL SalGtkFilePicker::getAvailableHeight() throw( uno::RuntimeException ) +{ + SolarMutexGuard g; + + 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 ) +{ + SolarMutexGuard g; + + 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 ); + + 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(RTL_CONSTASCII_USTRINGPARAM( ": " )); + 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; + impl_controlStateChanged( evt ); +} + +void SalGtkFilePicker::type_changed_cb( GtkTreeSelection *selection, SalGtkFilePicker *pobjFP ) +{ + pobjFP->implChangeType(selection); +} + +void SalGtkFilePicker::unselect_type() +{ + 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", pobjFP ); + pobjFP->impl_controlStateChanged( evt ); +} + +void SalGtkFilePicker::folder_changed_cb( GtkFileChooser *, SalGtkFilePicker *pobjFP ) +{ + FilePickerEvent evt; + OSL_TRACE( "folder_changed, isn't it great %x", pobjFP ); + pobjFP->impl_directoryChanged( evt ); +} + +void SalGtkFilePicker::selection_changed_cb( GtkFileChooser *, SalGtkFilePicker *pobjFP ) +{ + FilePickerEvent evt; + OSL_TRACE( "selection_changed, isn't it great %x", pobjFP ); + pobjFP->impl_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 ) +{ + SolarMutexGuard g; + + OSL_ASSERT( m_pDialog != NULL ); + + // TODO return m_pImpl->setShowState( bShowState ); + if( bShowState != mbPreviewState ) + { + 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 ) +{ + SolarMutexGuard g; + + OSL_ASSERT( m_pDialog != NULL ); + + return mbPreviewState; +} + +//------------------------------------------------------------------------------------ +// XInitialization +//------------------------------------------------------------------------------------ + +void SAL_CALL SalGtkFilePicker::initialize( const uno::Sequence& aArguments ) + throw( uno::Exception, uno::RuntimeException ) +{ + // parameter checking + uno::Any aAny; + if( 0 == aArguments.getLength() ) + throw lang::IllegalArgumentException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "no arguments" )), + static_cast( this ), 1 ); + + aAny = aArguments[0]; + + if( ( aAny.getValueType() != ::getCppuType( ( sal_Int16* )0 ) ) && + (aAny.getValueType() != ::getCppuType( ( sal_Int8* )0 ) ) ) + throw lang::IllegalArgumentException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "invalid argument type" )), + static_cast( this ), 1 ); + + sal_Int16 templateId = -1; + aAny >>= templateId; + + GtkFileChooserAction eAction = GTK_FILE_CHOOSER_ACTION_OPEN; + const gchar *first_button_text = GTK_STOCK_OPEN; + + SolarMutexGuard g; + + // 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" ); + break; + case FILESAVE_SIMPLE: + eAction = GTK_FILE_CHOOSER_ACTION_SAVE; + first_button_text = GTK_STOCK_SAVE; + OSL_TRACE( "2all true" ); + break; + case FILESAVE_AUTOEXTENSION_PASSWORD: + eAction = GTK_FILE_CHOOSER_ACTION_SAVE; + first_button_text = GTK_STOCK_SAVE; + mbToggleVisibility[PASSWORD] = true; + OSL_TRACE( "1all true" ); + // 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" ); + // 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" ); + // 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" ); + // 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" ); + // TODO + break; + default: + throw lang::IllegalArgumentException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "Unknown template" )), + static_cast< XFilePicker2* >( this ), + 1 ); + } + + 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 ) +{ + SolarMutexGuard g; + + OSL_ASSERT( m_pDialog != NULL ); + + // TODO m_pImpl->cancel(); +} + +// ------------------------------------------------- +// XServiceInfo +// ------------------------------------------------- + +rtl::OUString SAL_CALL SalGtkFilePicker::getImplementationName() + throw( uno::RuntimeException ) +{ + return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( FILE_PICKER_IMPL_NAME )); +} + +// ------------------------------------------------- +// XServiceInfo +// ------------------------------------------------- + +sal_Bool SAL_CALL SalGtkFilePicker::supportsService( const rtl::OUString& ServiceName ) + throw( uno::RuntimeException ) +{ + uno::Sequence 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 SAL_CALL SalGtkFilePicker::getSupportedServiceNames() + throw( uno::RuntimeException ) +{ + return FilePicker_getSupportedServiceNames(); +} + + +//-------------------------------------------------- +// Misc +//------------------------------------------------- +void SalGtkFilePicker::SetCurFilter( const OUString& rFilter ) +{ + // 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( 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", 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; + +#if OSL_DEBUG_LEVEL > 1 + 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 ) +{ + 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(RTL_CONSTASCII_USTRINGPARAM( "*." )); + 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 "*." syntax + aToken = aToken.copy( aToken.lastIndexOf( aStarDot ) + 2 ); + if (aToken.getLength()) + { + if (aTokens.getLength()) + aTokens += OUString(RTL_CONSTASCII_USTRINGPARAM(",")); + 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", rtl::OUStringToOString( aToken, RTL_TEXTENCODING_UTF8 ).getStr()); + } +#if OSL_DEBUG_LEVEL > 0 + 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() +{ + 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 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::const_iterator aEnd = aAllFormats.end(); + for (std::set::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"); +} + +SalGtkFilePicker::~SalGtkFilePicker() +{ + SolarMutexGuard g; + + 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 ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/unx/gtk/fpicker/SalGtkFilePicker.hxx b/vcl/unx/gtk/fpicker/SalGtkFilePicker.hxx new file mode 100644 index 000000000000..832e9445c342 --- /dev/null +++ b/vcl/unx/gtk/fpicker/SalGtkFilePicker.hxx @@ -0,0 +1,356 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _SALGTKFILEPICKER_HXX_ +#define _SALGTKFILEPICKER_HXX_ + +//_______________________________________________________________________________________________________________________ +// includes of other projects +//_______________________________________________________________________________________________________________________ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "SalGtkPicker.hxx" + +#include + +#include + +#include + +//---------------------------------------------------------- +// Implementation class for the XFilePicker Interface +//---------------------------------------------------------- + +//---------------------------------------------------------- +// forward declarations +//---------------------------------------------------------- + +using ::rtl::OUString; +using ::rtl::OString; +struct FilterEntry; +struct ElementEntry_Impl; + +typedef ::std::list < FilterEntry > FilterList; +typedef ::std::list < ElementEntry_Impl > ElementList; +typedef ::com::sun::star::beans::StringPair UnoFilterEntry; +typedef ::com::sun::star::uno::Sequence< UnoFilterEntry > UnoFilterList; // can be transported more effectively + + +//---------------------------------------------------------- +// class declaration +//---------------------------------------------------------- + +class SalGtkFilePicker : + public SalGtkPicker, + public cppu::WeakComponentImplHelper10< + ::com::sun::star::ui::dialogs::XFilterManager, + ::com::sun::star::ui::dialogs::XFilterGroupManager, + ::com::sun::star::ui::dialogs::XFilePickerControlAccess, + ::com::sun::star::ui::dialogs::XFilePickerNotifier, + ::com::sun::star::ui::dialogs::XFilePreview, + ::com::sun::star::ui::dialogs::XFilePicker2, + ::com::sun::star::lang::XInitialization, + ::com::sun::star::util::XCancellable, + ::com::sun::star::lang::XEventListener, + ::com::sun::star::lang::XServiceInfo > +{ + public: + + // constructor + SalGtkFilePicker( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceMgr ); + + //------------------------------------------------------------------------------------ + // XFilePickerNotifier + //------------------------------------------------------------------------------------ + + virtual void SAL_CALL addFilePickerListener( const ::com::sun::star::uno::Reference< ::com::sun::star::ui::dialogs::XFilePickerListener >& xListener ) + throw( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL removeFilePickerListener( const ::com::sun::star::uno::Reference< ::com::sun::star::ui::dialogs::XFilePickerListener >& xListener ) + throw( ::com::sun::star::uno::RuntimeException ); + + //------------------------------------------------------------------------------------ + // XExecutableDialog functions + //------------------------------------------------------------------------------------ + + virtual void SAL_CALL setTitle( const ::rtl::OUString& aTitle ) + throw( ::com::sun::star::uno::RuntimeException ); + + virtual sal_Int16 SAL_CALL execute() + throw( ::com::sun::star::uno::RuntimeException ); + + //------------------------------------------------------------------------------------ + // XFilePicker functions + //------------------------------------------------------------------------------------ + + virtual void SAL_CALL setMultiSelectionMode( sal_Bool bMode ) + throw( ::com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL setDefaultName( const ::rtl::OUString& aName ) + throw( ::com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL setDisplayDirectory( const ::rtl::OUString& aDirectory ) + throw( com::sun::star::lang::IllegalArgumentException, + ::com::sun::star::uno::RuntimeException ); + + virtual ::rtl::OUString SAL_CALL getDisplayDirectory( ) + throw( ::com::sun::star::uno::RuntimeException ); + + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getFiles( ) + throw( ::com::sun::star::uno::RuntimeException ); + + //------------------------------------------------------------------------------------ + // XFilePicker2 functions + //------------------------------------------------------------------------------------ + + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSelectedFiles() + throw (::com::sun::star::uno::RuntimeException); + + //------------------------------------------------------------------------------------ + // XFilterManager functions + //------------------------------------------------------------------------------------ + + virtual void SAL_CALL appendFilter( const ::rtl::OUString& aTitle, const ::rtl::OUString& aFilter ) + throw( ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL setCurrentFilter( const ::rtl::OUString& aTitle ) + throw( ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException ); + + virtual ::rtl::OUString SAL_CALL getCurrentFilter( ) + throw( ::com::sun::star::uno::RuntimeException ); + + //------------------------------------------------------------------------------------ + // XFilterGroupManager functions + //------------------------------------------------------------------------------------ + + virtual void SAL_CALL appendFilterGroup( const ::rtl::OUString& sGroupTitle, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::StringPair >& aFilters ) + throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + + //------------------------------------------------------------------------------------ + // XFilePickerControlAccess functions + //------------------------------------------------------------------------------------ + + virtual void SAL_CALL setValue( sal_Int16 nControlId, sal_Int16 nControlAction, const ::com::sun::star::uno::Any& aValue ) + throw (::com::sun::star::uno::RuntimeException); + + virtual ::com::sun::star::uno::Any SAL_CALL getValue( sal_Int16 aControlId, sal_Int16 aControlAction ) + throw (::com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL enableControl( sal_Int16 nControlId, sal_Bool bEnable ) + throw(::com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL setLabel( sal_Int16 nControlId, const ::rtl::OUString& aLabel ) + throw (::com::sun::star::uno::RuntimeException); + + virtual ::rtl::OUString SAL_CALL getLabel( sal_Int16 nControlId ) + throw (::com::sun::star::uno::RuntimeException); + + //------------------------------------------------ + // XFilePreview + //------------------------------------------------ + + virtual ::com::sun::star::uno::Sequence< sal_Int16 > SAL_CALL getSupportedImageFormats( ) + throw (::com::sun::star::uno::RuntimeException); + + virtual sal_Int32 SAL_CALL getTargetColorDepth( ) + throw (::com::sun::star::uno::RuntimeException); + + virtual sal_Int32 SAL_CALL getAvailableWidth( ) + throw (::com::sun::star::uno::RuntimeException); + + virtual sal_Int32 SAL_CALL getAvailableHeight( ) + throw (::com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL setImage( sal_Int16 aImageFormat, const ::com::sun::star::uno::Any& aImage ) + throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL setShowState( sal_Bool bShowState ) + throw (::com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL getShowState( ) + throw (::com::sun::star::uno::RuntimeException); + + //------------------------------------------------ + // XInitialization + //------------------------------------------------ + + virtual void SAL_CALL initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) + throw(::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + + //------------------------------------------------ + // XCancellable + //------------------------------------------------ + + virtual void SAL_CALL cancel( ) + throw( ::com::sun::star::uno::RuntimeException ); + + //------------------------------------------------ + // XEventListener + //------------------------------------------------ + + using cppu::WeakComponentImplHelperBase::disposing; + virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& aEvent ) + throw(::com::sun::star::uno::RuntimeException); + + //------------------------------------------------ + // XServiceInfo + //------------------------------------------------ + + virtual ::rtl::OUString SAL_CALL getImplementationName( ) + throw(::com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) + throw(::com::sun::star::uno::RuntimeException); + + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) + throw(::com::sun::star::uno::RuntimeException); + + //------------------------------------------------------------------------------------ + // FilePicker Event functions + //------------------------------------------------------------------------------------ + + private: + // prevent copy and assignment + SalGtkFilePicker( const SalGtkFilePicker& ); + SalGtkFilePicker& operator=( const SalGtkFilePicker& ); + + sal_Bool FilterNameExists( const ::rtl::OUString& rTitle ); + sal_Bool FilterNameExists( const UnoFilterList& _rGroupedFilters ); + + void ensureFilterList( const ::rtl::OUString& _rInitialCurrentFilter ); + + // to instanciate own services + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > m_xServiceMgr; + + void impl_fileSelectionChanged( ::com::sun::star::ui::dialogs::FilePickerEvent aEvent ); + void impl_directoryChanged( ::com::sun::star::ui::dialogs::FilePickerEvent aEvent ); + void impl_controlStateChanged( ::com::sun::star::ui::dialogs::FilePickerEvent aEvent ); + + + private: + ::com::sun::star::uno::Reference< ::com::sun::star::ui::dialogs::XFilePickerListener > + m_xListener; + ::rtl::OUString msPlayLabel; + FilterList *m_pFilterList; + GtkWidget *m_pVBox; + + GtkWidget *m_pFilterExpander; + GtkWidget *m_pFilterView; + GtkListStore *m_pFilterStore; + + enum { + AUTOEXTENSION, + PASSWORD, + FILTEROPTIONS, + READONLY, + LINK, + PREVIEW, + SELECTION, + TOGGLE_LAST + }; + + GtkWidget *m_pToggles[ TOGGLE_LAST ]; + + bool mbToggleVisibility[TOGGLE_LAST]; + bool mbToggleChecked[TOGGLE_LAST]; + + static const rtl::OString m_ToggleLabels[TOGGLE_LAST]; + + enum { + PLAY, + BUTTON_LAST }; + + GtkWidget *m_pButtons[ BUTTON_LAST ]; + + enum { + VERSION, + TEMPLATE, + IMAGE_TEMPLATE, + LIST_LAST + }; + + GtkWidget *m_pHBoxs[ LIST_LAST ]; + GtkWidget *m_pAligns[ LIST_LAST ]; + GtkWidget *m_pLists[ LIST_LAST ]; + GtkWidget *m_pListLabels[ LIST_LAST ]; + bool mbListVisibility[ LIST_LAST ]; + bool mbButtonVisibility[ BUTTON_LAST ]; + gulong mnHID_FolderChange; + gulong mnHID_SelectionChange; + + ::rtl::OUString m_aCurrentFilter; + ::rtl::OUString m_aInitialFilter; + + bool bVersionWidthUnset; + sal_Bool mbPreviewState; + gulong mHID_Preview; + GtkWidget* m_pPreview; + GtkFileFilter* m_pPseudoFilter; + sal_Int32 m_PreviewImageWidth; + sal_Int32 m_PreviewImageHeight; + + GtkWidget *getWidget( sal_Int16 nControlId, GType *pType = NULL); + + void SetCurFilter( const OUString& rFilter ); + void SetFilters(); + void UpdateFilterfromUI(); + + void implChangeType( GtkTreeSelection *selection ); + GtkFileFilter * implAddFilter( const OUString& rFilter, const OUString& rType ); + void implAddFilterGroup( const OUString& rFilter, + const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::StringPair>& _rFilters ); + void updateCurrentFilterFromName(const gchar* filtername); + void unselect_type(); + void InitialMapping(); + + void HandleSetListValue(GtkComboBox *pWidget, sal_Int16 nControlAction, + const ::com::sun::star::uno::Any& rValue); + ::com::sun::star::uno::Any HandleGetListValue(GtkComboBox *pWidget, sal_Int16 nControlAction) const; + + static void expander_changed_cb( GtkExpander *expander, SalGtkFilePicker *pobjFP ); + static void preview_toggled_cb (GtkObject *cb, SalGtkFilePicker *pobjFP); + static void filter_changed_cb (GtkFileChooser *file_chooser, GParamSpec *pspec, SalGtkFilePicker *pobjFP); + static void type_changed_cb( GtkTreeSelection *selection, SalGtkFilePicker *pobjFP ); + static void folder_changed_cb (GtkFileChooser *file_chooser, SalGtkFilePicker *pobjFP); + static void selection_changed_cb (GtkFileChooser *file_chooser, SalGtkFilePicker *pobjFP); + static void update_preview_cb (GtkFileChooser *file_chooser, SalGtkFilePicker *pobjFP); + static void dialog_mapped_cb(GtkWidget *widget, SalGtkFilePicker *pobjFP); + public: + virtual ~SalGtkFilePicker(); + +}; +#endif // _SALGTKFILEPICKER_HXX_ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/unx/gtk/fpicker/SalGtkFolderPicker.cxx b/vcl/unx/gtk/fpicker/SalGtkFolderPicker.cxx new file mode 100644 index 000000000000..52d9c78ba1e0 --- /dev/null +++ b/vcl/unx/gtk/fpicker/SalGtkFolderPicker.cxx @@ -0,0 +1,253 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_fpicker.hxx" + +#ifdef AIX +#define _LINUX_SOURCE_COMPAT +#include +#undef _LINUX_SOURCE_COMPAT +#endif + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "SalGtkFolderPicker.hxx" +#include "resourceprovider.hxx" + +#include + +//------------------------------------------------------------------------ +// namespace directives +//------------------------------------------------------------------------ + +using namespace ::rtl; +using namespace ::com::sun::star; +using namespace ::com::sun::star::ui::dialogs; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::uno; + +//------------------------------------------------------------------------ +// helper functions +//------------------------------------------------------------------------ + +namespace +{ + // controling event notifications + uno::Sequence SAL_CALL FolderPicker_getSupportedServiceNames() + { + uno::Sequence aRet(2); + aRet[0] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.dialogs.SystemFolderPicker" )); + aRet[1] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.dialogs.GtkFolderPicker" )); + return aRet; + } +} + +//----------------------------------------------------------------------------------------- +// constructor +//----------------------------------------------------------------------------------------- +SalGtkFolderPicker::SalGtkFolderPicker( const uno::Reference& xServiceMgr ) : + SalGtkPicker(xServiceMgr), + m_xServiceMgr(xServiceMgr) +{ + CResourceProvider aResProvider; + + m_pDialog = gtk_file_chooser_dialog_new( + OUStringToOString( aResProvider.getResString( FOLDERPICKER_TITLE ), RTL_TEXTENCODING_UTF8 ).getStr(), + NULL, GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OK, 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 ); +} + +// ------------------------------------------------- +// XEventListener +// ------------------------------------------------- + +void SAL_CALL SalGtkFolderPicker::disposing( const lang::EventObject& ) + throw( uno::RuntimeException ) +{ +} + +void SAL_CALL SalGtkFolderPicker::setDisplayDirectory( const rtl::OUString& aDirectory ) + throw( lang::IllegalArgumentException, uno::RuntimeException ) +{ + SolarMutexGuard g; + + OSL_ASSERT( m_pDialog != NULL ); + + OString aTxt = unicodetouri( aDirectory ); + + if( aTxt.lastIndexOf('/') == aTxt.getLength() - 1 ) + aTxt = aTxt.copy( 0, aTxt.getLength() - 1 ); + + OSL_TRACE( "setting path to %s", aTxt.getStr() ); + + gtk_file_chooser_set_current_folder_uri( GTK_FILE_CHOOSER( m_pDialog ), + aTxt.getStr() ); +} + +rtl::OUString SAL_CALL SalGtkFolderPicker::getDisplayDirectory() throw( uno::RuntimeException ) +{ + SolarMutexGuard g; + + OSL_ASSERT( m_pDialog != NULL ); + + gchar* pCurrentFolder = + gtk_file_chooser_get_current_folder_uri( GTK_FILE_CHOOSER( m_pDialog ) ); + ::rtl::OUString aCurrentFolderName = uritounicode(pCurrentFolder); + g_free( pCurrentFolder ); + + return aCurrentFolderName; +} + +rtl::OUString SAL_CALL SalGtkFolderPicker::getDirectory() throw( uno::RuntimeException ) +{ + return getDisplayDirectory(); +} + +void SAL_CALL SalGtkFolderPicker::setDescription( const rtl::OUString& rDescription ) + throw( uno::RuntimeException ) +{ + ::rtl::OString aDescription = OUStringToOString( rDescription, RTL_TEXTENCODING_UTF8 ); +} + + + +//----------------------------------------------------------------------------------------- +// XExecutableDialog functions +//----------------------------------------------------------------------------------------- + +void SAL_CALL SalGtkFolderPicker::setTitle( const rtl::OUString& aTitle ) throw( uno::RuntimeException ) +{ + SolarMutexGuard g; + + OSL_ASSERT( m_pDialog != NULL ); + + ::rtl::OString aWindowTitle = OUStringToOString( aTitle, RTL_TEXTENCODING_UTF8 ); + + gtk_window_set_title( GTK_WINDOW( m_pDialog ), aWindowTitle.getStr() ); +} + +sal_Int16 SAL_CALL SalGtkFolderPicker::execute() throw( uno::RuntimeException ) +{ + SolarMutexGuard g; + + OSL_TRACE( "1: HERE WE ARE"); + OSL_ASSERT( m_pDialog != NULL ); + + sal_Int16 retVal = 0; + + uno::Reference< awt::XExtendedToolkit > xToolkit( + m_xServiceMgr->createInstance( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.awt.Toolkit")) ), uno::UNO_QUERY); + + uno::Reference< frame::XDesktop > xDesktop( + m_xServiceMgr->createInstance( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop")) ), uno::UNO_QUERY); + + RunDialog* pRunDialog = new RunDialog(m_pDialog, xToolkit, xDesktop); + uno::Reference < awt::XTopWindowListener > xLifeCycle(pRunDialog); + gint nStatus = pRunDialog->run(); + switch( nStatus ) + { + case GTK_RESPONSE_ACCEPT: + retVal = ExecutableDialogResults::OK; + break; + case GTK_RESPONSE_CANCEL: + retVal = ExecutableDialogResults::CANCEL; + break; + default: + retVal = 0; + break; + } + + return retVal; +} + +//------------------------------------------------------------------------------------ +// XCancellable +//------------------------------------------------------------------------------------ + +void SAL_CALL SalGtkFolderPicker::cancel() throw( uno::RuntimeException ) +{ + SolarMutexGuard g; + + OSL_ASSERT( m_pDialog != NULL ); + + // TODO m_pImpl->cancel(); +} + +// ------------------------------------------------- +// XServiceInfo +// ------------------------------------------------- + +rtl::OUString SAL_CALL SalGtkFolderPicker::getImplementationName() + throw( uno::RuntimeException ) +{ + return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( FOLDER_PICKER_IMPL_NAME )); +} + +// ------------------------------------------------- +// XServiceInfo +// ------------------------------------------------- + +sal_Bool SAL_CALL SalGtkFolderPicker::supportsService( const rtl::OUString& ServiceName ) + throw( uno::RuntimeException ) +{ + uno::Sequence SupportedServicesNames = FolderPicker_getSupportedServiceNames(); + + for( sal_Int32 n = SupportedServicesNames.getLength(); n--; ) + if( SupportedServicesNames[n].compareTo( ServiceName ) == 0) + return sal_True; + + return sal_False; +} + +// ------------------------------------------------- +// XServiceInfo +// ------------------------------------------------- + +uno::Sequence SAL_CALL SalGtkFolderPicker::getSupportedServiceNames() + throw( uno::RuntimeException ) +{ + return FolderPicker_getSupportedServiceNames(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/unx/gtk/fpicker/SalGtkFolderPicker.hxx b/vcl/unx/gtk/fpicker/SalGtkFolderPicker.hxx new file mode 100644 index 000000000000..5110ea86a0f6 --- /dev/null +++ b/vcl/unx/gtk/fpicker/SalGtkFolderPicker.hxx @@ -0,0 +1,127 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _SALGTKFOLDERPICKER_HXX_ +#define _SALGTKFOLDERPICKER_HXX_ + +//_______________________________________________________________________________________________________________________ +// includes of other projects +//_______________________________________________________________________________________________________________________ + +#include + +#include "SalGtkPicker.hxx" + +#include + +#include + +#include + +//---------------------------------------------------------- +// class declaration +//---------------------------------------------------------- + +class SalGtkFolderPicker : + public SalGtkPicker, + public cppu::WeakImplHelper3< + ::com::sun::star::ui::dialogs::XFolderPicker, + ::com::sun::star::lang::XServiceInfo, + ::com::sun::star::util::XCancellable > +{ + public: + + // constructor + SalGtkFolderPicker( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceMgr ); + + //------------------------------------------------------------------------------------ + // XExecutableDialog functions + //------------------------------------------------------------------------------------ + + virtual void SAL_CALL setTitle( const ::rtl::OUString& aTitle ) + throw( ::com::sun::star::uno::RuntimeException ); + + virtual sal_Int16 SAL_CALL execute( ) + throw( ::com::sun::star::uno::RuntimeException ); + + //------------------------------------------------------------------------------------ + // XFolderPicker functions + //------------------------------------------------------------------------------------ + + virtual void SAL_CALL setDisplayDirectory( const rtl::OUString& rDirectory ) + throw( com::sun::star::lang::IllegalArgumentException, com::sun::star::uno::RuntimeException ); + + virtual rtl::OUString SAL_CALL getDisplayDirectory( ) + throw( com::sun::star::uno::RuntimeException ); + + virtual rtl::OUString SAL_CALL getDirectory( ) + throw( com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL setDescription( const rtl::OUString& rDescription ) + throw( com::sun::star::uno::RuntimeException ); + + + //------------------------------------------------ + // XServiceInfo + //------------------------------------------------ + + virtual ::rtl::OUString SAL_CALL getImplementationName( ) + throw(::com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) + throw(::com::sun::star::uno::RuntimeException); + + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) + throw(::com::sun::star::uno::RuntimeException); + + //------------------------------------------------ + // XCancellable + //------------------------------------------------ + + virtual void SAL_CALL cancel( ) + throw( ::com::sun::star::uno::RuntimeException ); + + //------------------------------------------------ + // XEventListener + //------------------------------------------------ + + virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& aEvent ) + throw(::com::sun::star::uno::RuntimeException); + + private: + // prevent copy and assignment + SalGtkFolderPicker( const SalGtkFolderPicker& ); + SalGtkFolderPicker& operator=( const SalGtkFolderPicker& ); + private: + // to instanciate own services + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > m_xServiceMgr; +}; + +#endif // _SALGTKFOLDERPICKER_HXX_ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/unx/gtk/fpicker/SalGtkPicker.cxx b/vcl/unx/gtk/fpicker/SalGtkPicker.cxx new file mode 100644 index 000000000000..d52c2c60e37d --- /dev/null +++ b/vcl/unx/gtk/fpicker/SalGtkPicker.cxx @@ -0,0 +1,313 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_fpicker.hxx" + +#ifdef AIX +#define _LINUX_SOURCE_COMPAT +#include +#undef _LINUX_SOURCE_COMPAT +#endif + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "SalGtkPicker.hxx" +#include +#include + +//------------------------------------------------------------------------ +// namespace directives +//------------------------------------------------------------------------ + +using namespace ::rtl; +using namespace ::com::sun::star; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::uno; + +rtl::OUString SalGtkPicker::uritounicode(const gchar* pIn) +{ + if (!pIn) + return rtl::OUString(); + + rtl::OUString sURL( const_cast(pIn), strlen(pIn), + RTL_TEXTENCODING_UTF8 ); + + INetURLObject aURL(sURL); + if (INET_PROT_FILE == aURL.GetProtocol()) + { + // all the URLs are handled by office in UTF-8 + // so the Gnome FP related URLs should be converted accordingly + gchar *pEncodedFileName = g_filename_from_uri(pIn, NULL, NULL); + if ( pEncodedFileName ) + { + rtl::OUString sEncoded(pEncodedFileName, strlen(pEncodedFileName), + osl_getThreadTextEncoding()); + INetURLObject aCurrentURL(sEncoded, INetURLObject::FSYS_UNX); + aCurrentURL.SetHost(aURL.GetHost()); + sURL = aCurrentURL.getExternalURL(); + } + else + { + OUString aNewURL = Reference(Reference(comphelper::getProcessServiceFactory(), UNO_QUERY_THROW)->createInstance(OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uri.ExternalUriReferenceTranslator"))), UNO_QUERY_THROW)->translateToInternal(sURL); + if( aNewURL.getLength() ) + sURL = aNewURL; + } + } + return sURL; +} + +rtl::OString SalGtkPicker::unicodetouri(const rtl::OUString &rURL) +{ + // all the URLs are handled by office in UTF-8 ( and encoded with "%xx" codes based on UTF-8 ) + // so the Gnome FP related URLs should be converted accordingly + OString sURL = OUStringToOString(rURL, RTL_TEXTENCODING_UTF8); + INetURLObject aURL(rURL); + if (INET_PROT_FILE == aURL.GetProtocol()) + { + OUString aNewURL = Reference(Reference(comphelper::getProcessServiceFactory(), UNO_QUERY_THROW)->createInstance(OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uri.ExternalUriReferenceTranslator"))), UNO_QUERY_THROW)->translateToExternal( rURL ); + + if( aNewURL.getLength() ) + { + // At this point the URL should contain ascii characters only actually + sURL = OUStringToOString( aNewURL, osl_getThreadTextEncoding() ); + } + } + return sURL; +} + +extern "C" +{ + struct Display; + extern GdkDisplay* gdk_x11_lookup_xdisplay (void*xdisplay); + + static gboolean canceldialog(RunDialog *pDialog) + { + GdkThreadLock lock; + pDialog->cancel(); + return false; + } +} + +RunDialog::RunDialog( GtkWidget *pDialog, uno::Reference< awt::XExtendedToolkit >& rToolkit, + uno::Reference< frame::XDesktop >& rDesktop ) : + cppu::WeakComponentImplHelper2< awt::XTopWindowListener, frame::XTerminateListener >( maLock ), + mpDialog(pDialog), mpCreatedParent(NULL), mxToolkit(rToolkit), mxDesktop(rDesktop) +{ + awt::SystemDependentXWindow aWindowHandle; + + if (mxToolkit.is()) + { + uno::Reference< awt::XTopWindow > xWindow(mxToolkit->getActiveTopWindow()); + if (xWindow.is()) + { + uno::Reference< awt::XSystemDependentWindowPeer > xSystemDepParent(xWindow, uno::UNO_QUERY); + if (xSystemDepParent.is()) + { + + sal_Int8 processID[16]; + + rtl_getGlobalProcessId( (sal_uInt8*)processID ); + uno::Sequence processIdSeq(processID, 16); + uno::Any anyHandle = xSystemDepParent->getWindowHandle(processIdSeq, SystemDependent::SYSTEM_XWINDOW); + + anyHandle >>= aWindowHandle; + } + } + } + + GdkDisplay *pDisplay = aWindowHandle.DisplayPointer ? gdk_x11_lookup_xdisplay(reinterpret_cast(static_cast(aWindowHandle.DisplayPointer))) : NULL; + GdkWindow* pParent = pDisplay ? gdk_window_lookup_for_display(pDisplay, aWindowHandle.WindowHandle) : NULL; + if (!pParent && pDisplay) + pParent = mpCreatedParent = gdk_window_foreign_new_for_display( pDisplay, aWindowHandle.WindowHandle); + if (pParent) + { + gtk_widget_realize(mpDialog); + gdk_window_set_transient_for(mpDialog->window, pParent); + } +} + + +RunDialog::~RunDialog() +{ + SolarMutexGuard g; + + if (mpCreatedParent) + gdk_window_destroy (mpCreatedParent); + + g_source_remove_by_user_data (this); +} + +void SAL_CALL RunDialog::windowOpened( const ::com::sun::star::lang::EventObject& ) + throw (::com::sun::star::uno::RuntimeException) +{ + SolarMutexGuard g; + + g_timeout_add_full(G_PRIORITY_HIGH_IDLE, 0, (GSourceFunc)canceldialog, this, NULL); +} + +void SAL_CALL RunDialog::queryTermination( const ::com::sun::star::lang::EventObject& ) + throw(::com::sun::star::frame::TerminationVetoException, ::com::sun::star::uno::RuntimeException) +{ +} + +void SAL_CALL RunDialog::notifyTermination( const ::com::sun::star::lang::EventObject& ) + throw(::com::sun::star::uno::RuntimeException) +{ + SolarMutexGuard g; + + g_timeout_add_full(G_PRIORITY_HIGH_IDLE, 0, (GSourceFunc)canceldialog, this, NULL); +} + +void RunDialog::cancel() +{ + gtk_dialog_response( GTK_DIALOG( mpDialog ), GTK_RESPONSE_CANCEL ); + gtk_widget_hide( mpDialog ); +} + +gint RunDialog::run() +{ + if (mxToolkit.is()) + mxToolkit->addTopWindowListener(this); + + gint nStatus = gtk_dialog_run( GTK_DIALOG( mpDialog ) ); + + if (mxToolkit.is()) + mxToolkit->removeTopWindowListener(this); + + if (nStatus != 1) //PLAY + gtk_widget_hide( mpDialog ); + + return nStatus; +} + +static void lcl_setGTKLanguage(const uno::Reference& xServiceMgr) +{ + static bool bSet = false; + if (bSet) + return; + + OUString sUILocale; + try + { + uno::Reference xConfigMgr = + uno::Reference(xServiceMgr->createInstance( + OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.configuration.ConfigurationProvider"))), + UNO_QUERY_THROW ); + + Sequence< Any > theArgs(1); + theArgs[ 0 ] <<= OUString(RTL_CONSTASCII_USTRINGPARAM("org.openoffice.Office.Linguistic/General")); + + uno::Reference< container::XNameAccess > xNameAccess = + uno::Reference< container::XNameAccess >(xConfigMgr->createInstanceWithArguments( + OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.configuration.ConfigurationAccess")), theArgs ), + UNO_QUERY_THROW ); + + if (xNameAccess.is()) + xNameAccess->getByName(OUString(RTL_CONSTASCII_USTRINGPARAM("UILocale"))) >>= sUILocale; + } catch (...) {} + + if (sUILocale.getLength()) + { + sUILocale = sUILocale.replace('-', '_'); + rtl::OUString envVar(RTL_CONSTASCII_USTRINGPARAM("LANGUAGE")); + osl_setEnvironment(envVar.pData, sUILocale.pData); + } + bSet = true; +} + +SalGtkPicker::SalGtkPicker(const uno::Reference& xServiceMgr) : m_pDialog(0) +{ + lcl_setGTKLanguage(xServiceMgr); +} + +SalGtkPicker::~SalGtkPicker() +{ + SolarMutexGuard g; + + if (m_pDialog) + { + gtk_widget_destroy(m_pDialog); + } +} + +void SAL_CALL SalGtkPicker::implsetDisplayDirectory( const rtl::OUString& aDirectory ) + throw( lang::IllegalArgumentException, uno::RuntimeException ) +{ + OSL_ASSERT( m_pDialog != NULL ); + + OString aTxt = unicodetouri(aDirectory); + + if( aTxt.lastIndexOf('/') == aTxt.getLength() - 1 ) + aTxt = aTxt.copy( 0, aTxt.getLength() - 1 ); + + OSL_TRACE( "setting path to %s", aTxt.getStr() ); + + gtk_file_chooser_set_current_folder_uri( GTK_FILE_CHOOSER( m_pDialog ), + aTxt.getStr() ); +} + +rtl::OUString SAL_CALL SalGtkPicker::implgetDisplayDirectory() throw( uno::RuntimeException ) +{ + OSL_ASSERT( m_pDialog != NULL ); + + gchar* pCurrentFolder = + gtk_file_chooser_get_current_folder_uri( GTK_FILE_CHOOSER( m_pDialog ) ); + ::rtl::OUString aCurrentFolderName = uritounicode(pCurrentFolder); + g_free( pCurrentFolder ); + + return aCurrentFolderName; +} + +void SAL_CALL SalGtkPicker::implsetTitle( const rtl::OUString& aTitle ) throw( uno::RuntimeException ) +{ + OSL_ASSERT( m_pDialog != NULL ); + + ::rtl::OString aWindowTitle = OUStringToOString( aTitle, RTL_TEXTENCODING_UTF8 ); + + gtk_window_set_title( GTK_WINDOW( m_pDialog ), aWindowTitle.getStr() ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/unx/gtk/fpicker/SalGtkPicker.hxx b/vcl/unx/gtk/fpicker/SalGtkPicker.hxx new file mode 100644 index 000000000000..cd9e6553a925 --- /dev/null +++ b/vcl/unx/gtk/fpicker/SalGtkPicker.hxx @@ -0,0 +1,138 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _SALGTKFPICKER_HXX_ +#define _SALGTKFPICKER_HXX_ + +//_____________________________________________________________________________ +// includes of other projects +//_____________________________________________________________________________ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +//---------------------------------------------------------- +// class declaration +//---------------------------------------------------------- + +class SalGtkPicker +{ + public: + SalGtkPicker(const ::com::sun::star::uno::Reference& xServiceMgr); + virtual ~SalGtkPicker(); + protected: + osl::Mutex m_rbHelperMtx; + GtkWidget *m_pDialog; + protected: + virtual void SAL_CALL implsetTitle( const ::rtl::OUString& aTitle ) + throw( ::com::sun::star::uno::RuntimeException ); + + virtual void SAL_CALL implsetDisplayDirectory( const rtl::OUString& rDirectory ) + throw( com::sun::star::lang::IllegalArgumentException, com::sun::star::uno::RuntimeException ); + + virtual rtl::OUString SAL_CALL implgetDisplayDirectory( ) + throw( com::sun::star::uno::RuntimeException ); + static rtl::OUString uritounicode(const gchar *pIn); + static rtl::OString unicodetouri(const rtl::OUString &rURL); +}; + +class GdkThreadLock +{ +public: + GdkThreadLock() { gdk_threads_enter(); } + ~GdkThreadLock() { gdk_threads_leave(); } +}; + +//Run the Gtk Dialog. Watch for any "new windows" created while we're +//executing and consider that a CANCEL event to avoid e.g. "file cannot be opened" +//modal dialogs and this one getting locked if some other API call causes this +//to happen while we're opened waiting for user input, e.g. +//https://bugzilla.redhat.com/show_bug.cgi?id=441108 +class RunDialog : + public cppu::WeakComponentImplHelper2< + ::com::sun::star::awt::XTopWindowListener, + ::com::sun::star::frame::XTerminateListener > +{ +private: + osl::Mutex maLock; + GtkWidget *mpDialog; + GdkWindow *mpCreatedParent; + ::com::sun::star::uno::Reference< ::com::sun::star::awt::XExtendedToolkit> mxToolkit; + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDesktop > mxDesktop; +public: + + // XTopWindowListener + using cppu::WeakComponentImplHelperBase::disposing; + virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& ) + throw(::com::sun::star::uno::RuntimeException) {} + virtual void SAL_CALL windowOpened( const ::com::sun::star::lang::EventObject& e ) + throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL windowClosing( const ::com::sun::star::lang::EventObject& ) + throw (::com::sun::star::uno::RuntimeException) {} + virtual void SAL_CALL windowClosed( const ::com::sun::star::lang::EventObject& ) + throw (::com::sun::star::uno::RuntimeException) {} + virtual void SAL_CALL windowMinimized( const ::com::sun::star::lang::EventObject& ) + throw (::com::sun::star::uno::RuntimeException) {} + virtual void SAL_CALL windowNormalized( const ::com::sun::star::lang::EventObject& ) + throw (::com::sun::star::uno::RuntimeException) {} + virtual void SAL_CALL windowActivated( const ::com::sun::star::lang::EventObject& ) + throw (::com::sun::star::uno::RuntimeException) {} + virtual void SAL_CALL windowDeactivated( const ::com::sun::star::lang::EventObject& ) + throw (::com::sun::star::uno::RuntimeException) {} + + // XTerminateListener + virtual void SAL_CALL queryTermination( const ::com::sun::star::lang::EventObject& aEvent ) + throw(::com::sun::star::frame::TerminationVetoException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL notifyTermination( const ::com::sun::star::lang::EventObject& aEvent ) + throw(::com::sun::star::uno::RuntimeException); +public: + RunDialog(GtkWidget *pDialog, + ::com::sun::star::uno::Reference< ::com::sun::star::awt::XExtendedToolkit > &rToolkit, + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDesktop > &rDesktop + ); + virtual ~RunDialog(); + gint run(); + void cancel(); +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/unx/gtk/fpicker/eventnotification.hxx b/vcl/unx/gtk/fpicker/eventnotification.hxx new file mode 100644 index 000000000000..3866ca59946f --- /dev/null +++ b/vcl/unx/gtk/fpicker/eventnotification.hxx @@ -0,0 +1,54 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _EVENTNOTIFICATION_HXX_ +#define _EVENTNOTIFICATION_HXX_ + +#include +#include + +//----------------------------------- +// encapsulate a filepicker event +// notification, because there are +// two types of filepicker notifications +// with and without parameter +// this is an application of the +// "command" pattern see GoF +//----------------------------------- + +class CEventNotification +{ +public: + virtual ~CEventNotification() { }; + + virtual void SAL_CALL notifyEventListener( com::sun::star::uno::Reference< com::sun::star::uno::XInterface > xListener ) = 0; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/unx/gtk/fpicker/fps_gnome.component b/vcl/unx/gtk/fpicker/fps_gnome.component new file mode 100644 index 000000000000..72bca42f8acf --- /dev/null +++ b/vcl/unx/gtk/fpicker/fps_gnome.component @@ -0,0 +1,37 @@ + + + + + + + + + + + diff --git a/vcl/unx/gtk/fpicker/fps_gnome.xml b/vcl/unx/gtk/fpicker/fps_gnome.xml new file mode 100644 index 000000000000..d4dd4f9231d6 --- /dev/null +++ b/vcl/unx/gtk/fpicker/fps_gnome.xml @@ -0,0 +1,79 @@ + + + + fps + + Jan Holesovsky + com.sun.star.comp.ui.dialogs.FilePicker + + The Gnome implementation of the FilePicker service. + + com.sun.star.loader.SharedLibrary + c++ + + com.sun.star.ui.dialogs.FilePicker + ... + com.sun.star.ui.dialogs.XExecutableDialog + com.sun.star.ui.dialogs.XFilePicker + com.sun.star.ui.dialogs.XFilterManager + com.sun.star.ui.dialogs.XFilterGroupManager + com.sun.star.ui.dialogs.XFilePickerListener + com.sun.star.ui.dialogs.ExecutableDialogException + com.sun.star.ui.dialogs.XFilePickerNotifier + com.sun.star.ui.dialogs.XFilePickerControlAccess + com.sun.star.ui.dialogs.XFilePreview + com.sun.star.ui.dialogs.ExtendedFilePickerElementIds + com.sun.star.ui.dialogs.ExecutableDialogResults + com.sun.star.ui.dialogs.FilePickerEvent + com.sun.star.ui.dialogs.CommonFilePickerElementIds + com.sun.star.ui.dialogs.ListboxControlActions + com.sun.star.ui.dialogs.TemplateDescription + com.sun.star.ui.dialogs.FilePreviewImageFormats + com.sun.star.util.XCancellable + com.sun.star.lang.XComponent + com.sun.star.lang.XMultiServiceFactory + com.sun.star.lang.XSingleServiceFactory + com.sun.star.lang.XServiceInfo + com.sun.star.lang.XTypeProvider + com.sun.star.lang.IllegalArgumentException + com.sun.star.uno.TypeClass + com.sun.star.uno.XWeak + com.sun.star.uno.XAggregation + com.sun.star.registry.XRegistryKey + com.sun.star.container.XSet + + + Caolan McNamara + com.sun.star.comp.ui.dialogs.FolderPicker + + The Gnome implementation of the FolderPicker service. + + com.sun.star.loader.SharedLibrary + c++ + + com.sun.star.ui.dialogs.FolderPicker + ... + com.sun.star.ui.dialogs.XExecutableDialog + com.sun.star.ui.dialogs.XFolderPicker + com.sun.star.ui.dialogs.ExecutableDialogException + com.sun.star.ui.dialogs.ExecutableDialogResults + com.sun.star.util.XCancellable + com.sun.star.lang.XComponent + com.sun.star.lang.XMultiServiceFactory + com.sun.star.lang.XSingleServiceFactory + com.sun.star.lang.XServiceInfo + com.sun.star.lang.XTypeProvider + com.sun.star.lang.IllegalArgumentException + com.sun.star.uno.TypeClass + com.sun.star.uno.XWeak + com.sun.star.uno.XAggregation + com.sun.star.registry.XRegistryKey + com.sun.star.container.XSet + + cppuhelper + cppu + sal + cppuhelper + cppu2 + sal2 + diff --git a/vcl/unx/gtk/fpicker/resourceprovider.cxx b/vcl/unx/gtk/fpicker/resourceprovider.cxx new file mode 100644 index 000000000000..4a4f49cc089d --- /dev/null +++ b/vcl/unx/gtk/fpicker/resourceprovider.cxx @@ -0,0 +1,229 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_fpicker.hxx" + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ +#include +#include +#include "resourceprovider.hxx" +#include +#include +#include +#include +#include + +#include +#include + +//------------------------------------------------------------ +// namespace directives +//------------------------------------------------------------ + +using rtl::OUString; +using namespace ::com::sun::star::ui::dialogs::ExtendedFilePickerElementIds; +using namespace ::com::sun::star::ui::dialogs::CommonFilePickerElementIds; + +//------------------------------------------------------------ +// +//------------------------------------------------------------ + +static const char* RES_NAME = "fps_office"; +static const char* OTHER_RES_NAME = "svt"; + +//------------------------------------------------------------ +// we have to translate control ids to resource ids +//------------------------------------------------------------ + +struct _Entry +{ + sal_Int32 ctrlId; + sal_Int16 resId; +}; + +_Entry CtrlIdToResIdTable[] = { + { CHECKBOX_AUTOEXTENSION, STR_SVT_FILEPICKER_AUTO_EXTENSION }, + { CHECKBOX_PASSWORD, STR_SVT_FILEPICKER_PASSWORD }, + { CHECKBOX_FILTEROPTIONS, STR_SVT_FILEPICKER_FILTER_OPTIONS }, + { CHECKBOX_READONLY, STR_SVT_FILEPICKER_READONLY }, + { CHECKBOX_LINK, STR_SVT_FILEPICKER_INSERT_AS_LINK }, + { CHECKBOX_PREVIEW, STR_SVT_FILEPICKER_SHOW_PREVIEW }, + { PUSHBUTTON_PLAY, STR_SVT_FILEPICKER_PLAY }, + { LISTBOX_VERSION_LABEL, STR_SVT_FILEPICKER_VERSION }, + { LISTBOX_TEMPLATE_LABEL, STR_SVT_FILEPICKER_TEMPLATES }, + { LISTBOX_IMAGE_TEMPLATE_LABEL, STR_SVT_FILEPICKER_IMAGE_TEMPLATE }, + { CHECKBOX_SELECTION, STR_SVT_FILEPICKER_SELECTION }, + { FOLDERPICKER_TITLE, STR_SVT_FOLDERPICKER_DEFAULT_TITLE }, + { FOLDER_PICKER_DEF_DESCRIPTION, STR_SVT_FOLDERPICKER_DEFAULT_DESCRIPTION }, + { FILE_PICKER_OVERWRITE, STR_SVT_ALREADYEXISTOVERWRITE }, + { FILE_PICKER_ALLFORMATS, STR_SVT_ALLFORMATS } +}; + +_Entry OtherCtrlIdToResIdTable[] = { + { FILE_PICKER_TITLE_OPEN, STR_FILEDLG_OPEN }, + { FILE_PICKER_TITLE_SAVE, STR_FILEDLG_SAVE }, + { FILE_PICKER_FILE_TYPE, STR_FILEDLG_TYPE }, +}; + + +const sal_Int32 SIZE_TABLE = SAL_N_ELEMENTS( CtrlIdToResIdTable ); +const sal_Int32 OTHER_SIZE_TABLE = SAL_N_ELEMENTS( OtherCtrlIdToResIdTable ); + +//------------------------------------------------------------ +// +//------------------------------------------------------------ + +sal_Int16 CtrlIdToResId( sal_Int32 aControlId ) +{ + sal_Int16 aResId = -1; + + for ( sal_Int32 i = 0; i < SIZE_TABLE; i++ ) + { + if ( CtrlIdToResIdTable[i].ctrlId == aControlId ) + { + aResId = CtrlIdToResIdTable[i].resId; + break; + } + } + + return aResId; +} + +sal_Int16 OtherCtrlIdToResId( sal_Int32 aControlId ) +{ + sal_Int16 aResId = -1; + + for ( sal_Int32 i = 0; i < OTHER_SIZE_TABLE; i++ ) + { + if ( OtherCtrlIdToResIdTable[i].ctrlId == aControlId ) + { + aResId = OtherCtrlIdToResIdTable[i].resId; + break; + } + } + + return aResId; +} + +//------------------------------------------------------------ +// +//------------------------------------------------------------ + +class CResourceProvider_Impl +{ +public: + + //------------------------------------- + // + //------------------------------------- + + CResourceProvider_Impl( ) + { + m_ResMgr = ResMgr::CreateResMgr( RES_NAME ); + m_OtherResMgr = ResMgr::CreateResMgr( OTHER_RES_NAME ); + } + + //------------------------------------- + // + //------------------------------------- + + ~CResourceProvider_Impl( ) + { + delete m_ResMgr; + delete m_OtherResMgr; + } + + //------------------------------------- + // + //------------------------------------- + + OUString getResString( sal_Int16 aId ) + { + String aResString; + OUString aResOUString; + + try + { + OSL_ASSERT( m_ResMgr && m_OtherResMgr ); + + // translate the control id to a resource id + sal_Int16 aResId = CtrlIdToResId( aId ); + if ( aResId > -1 ) + aResString = String( ResId( aResId, *m_ResMgr ) ); + else + { + aResId = OtherCtrlIdToResId( aId ); + if ( aResId > -1 ) + aResString = String( ResId( aResId, *m_OtherResMgr ) ); + } + if ( aResId > -1 ) + aResOUString = OUString( aResString ); + } + catch(...) + { + } + + return aResOUString; + } + +public: + ResMgr* m_ResMgr; + ResMgr* m_OtherResMgr; +}; + +//------------------------------------------------------------ +// +//------------------------------------------------------------ + +CResourceProvider::CResourceProvider( ) : + m_pImpl( new CResourceProvider_Impl() ) +{ +} + +//------------------------------------------------------------ +// +//------------------------------------------------------------ + +CResourceProvider::~CResourceProvider( ) +{ + delete m_pImpl; +} + +//------------------------------------------------------------ +// +//------------------------------------------------------------ + +OUString CResourceProvider::getResString( sal_Int32 aId ) +{ + return m_pImpl->getResString( aId ).replace('~', '_'); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/unx/gtk/fpicker/resourceprovider.hxx b/vcl/unx/gtk/fpicker/resourceprovider.hxx new file mode 100644 index 000000000000..5bbbbfd68e7e --- /dev/null +++ b/vcl/unx/gtk/fpicker/resourceprovider.hxx @@ -0,0 +1,69 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +#ifndef _RESOURCEPROVIDER_HXX_ +#define _RESOURCEPROVIDER_HXX_ + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ + +#include + +#include + +#define FOLDERPICKER_TITLE 500 +#define FOLDER_PICKER_DEF_DESCRIPTION 501 +#define FILE_PICKER_TITLE_OPEN 502 +#define FILE_PICKER_TITLE_SAVE 503 +#define FILE_PICKER_FILE_TYPE 504 +#define FILE_PICKER_OVERWRITE 505 +#define FILE_PICKER_ALLFORMATS 506 + +//------------------------------------------------------------------------ +// deklarations +//------------------------------------------------------------------------ + +class CResourceProvider_Impl; + +class CResourceProvider +{ +public: + CResourceProvider( ); + ~CResourceProvider( ); + + rtl::OUString getResString( sal_Int32 aId ); + +private: + CResourceProvider_Impl* m_pImpl; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ -- cgit v1.2.3