1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_fpicker.hxx" 30 31 //------------------------------------------------------------------------ 32 // includes 33 //------------------------------------------------------------------------ 34 #include <com/sun/star/lang/DisposedException.hpp> 35 #include <com/sun/star/lang/XMultiServiceFactory.hpp> 36 #include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp> 37 #include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp> 38 #include <com/sun/star/ui/dialogs/CommonFilePickerElementIds.hpp> 39 #include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp> 40 #include <cppuhelper/interfacecontainer.h> 41 #include <osl/diagnose.h> 42 #include <osl/process.h> 43 #include <com/sun/star/ui/dialogs/TemplateDescription.hpp> 44 #include <com/sun/star/ui/dialogs/ControlActions.hpp> 45 #include <com/sun/star/uno/Any.hxx> 46 #include <FPServiceInfo.hxx> 47 #include <vos/mutex.hxx> 48 #include <vcl/svapp.hxx> 49 #include <SalGtkFilePicker.hxx> 50 51 #include <tools/urlobj.hxx> 52 53 #include <iostream> 54 #include <algorithm> 55 #include "resourceprovider.hxx" 56 #ifndef _SV_RC_H 57 #include <tools/rc.hxx> 58 #endif 59 60 //------------------------------------------------------------------------ 61 // namespace directives 62 //------------------------------------------------------------------------ 63 64 using namespace ::com::sun::star; 65 using namespace ::com::sun::star::ui::dialogs; 66 using namespace ::com::sun::star::ui::dialogs::TemplateDescription; 67 using namespace ::com::sun::star::ui::dialogs::ExtendedFilePickerElementIds; 68 using namespace ::com::sun::star::ui::dialogs::CommonFilePickerElementIds; 69 using namespace ::com::sun::star::lang; 70 using namespace ::com::sun::star::beans; 71 using namespace ::com::sun::star::uno; 72 73 //------------------------------------------------------------------------ 74 // helper functions 75 //------------------------------------------------------------------------ 76 77 namespace 78 { 79 // controling event notifications 80 const bool STARTUP_SUSPENDED = true; 81 const bool STARTUP_ALIVE = false; 82 83 uno::Sequence<rtl::OUString> SAL_CALL FilePicker_getSupportedServiceNames() 84 { 85 uno::Sequence<rtl::OUString> aRet(3); 86 aRet[0] = rtl::OUString::createFromAscii( "com.sun.star.ui.dialogs.FilePicker" ); 87 aRet[1] = rtl::OUString::createFromAscii( "com.sun.star.ui.dialogs.SystemFilePicker" ); 88 aRet[2] = rtl::OUString::createFromAscii( "com.sun.star.ui.dialogs.GtkFilePicker" ); 89 return aRet; 90 } 91 } 92 93 //----------------------------------------------------------------------------------------- 94 // constructor 95 //----------------------------------------------------------------------------------------- 96 97 static void expandexpanders(GtkContainer *pWidget) 98 { 99 GdkThreadLock aLock; 100 101 GList *pChildren = gtk_container_get_children(pWidget); 102 for( GList *p = pChildren; p; p = p->next ) 103 { 104 if GTK_IS_CONTAINER(GTK_WIDGET(p->data)) 105 expandexpanders(GTK_CONTAINER(GTK_WIDGET(p->data))); 106 if GTK_IS_EXPANDER(GTK_WIDGET(p->data)) 107 gtk_expander_set_expanded(GTK_EXPANDER(GTK_WIDGET(p->data)), sal_True); 108 } 109 g_list_free(pChildren); 110 } 111 112 void SalGtkFilePicker::dialog_mapped_cb(GtkWidget *, SalGtkFilePicker *pobjFP) 113 { 114 pobjFP->InitialMapping(); 115 } 116 117 void SalGtkFilePicker::InitialMapping() 118 { 119 GdkThreadLock aLock; 120 121 if (!mbPreviewState ) 122 { 123 gtk_widget_hide( m_pPreview ); 124 gtk_file_chooser_set_preview_widget_active( GTK_FILE_CHOOSER( m_pDialog ), false); 125 } 126 gtk_widget_set_size_request (m_pPreview, -1, -1); 127 } 128 129 SalGtkFilePicker::SalGtkFilePicker( const uno::Reference<lang::XMultiServiceFactory>& xServiceMgr ) : 130 SalGtkPicker(xServiceMgr), 131 cppu::WeakComponentImplHelper10< 132 XFilterManager, 133 XFilterGroupManager, 134 XFilePickerControlAccess, 135 XFilePickerNotifier, 136 XFilePreview, 137 XFilePicker2, 138 lang::XInitialization, 139 util::XCancellable, 140 lang::XEventListener, 141 lang::XServiceInfo>( m_rbHelperMtx ), 142 m_xServiceMgr( xServiceMgr ), 143 m_pFilterList( NULL ), 144 m_pVBox ( NULL ), 145 mnHID_FolderChange( 0 ), 146 mnHID_SelectionChange( 0 ), 147 bVersionWidthUnset( false ), 148 mbPreviewState( sal_False ), 149 mHID_Preview( 0 ), 150 m_pPreview( NULL ), 151 m_PreviewImageWidth( 256 ), 152 m_PreviewImageHeight( 256 ) 153 { 154 int i; 155 156 for( i = 0; i < TOGGLE_LAST; i++ ) 157 { 158 m_pToggles[i] = NULL; 159 mbToggleVisibility[i] = false; 160 } 161 162 for( i = 0; i < BUTTON_LAST; i++ ) 163 { 164 m_pButtons[i] = NULL; 165 mbButtonVisibility[i] = false; 166 } 167 168 for( i = 0; i < LIST_LAST; i++ ) 169 { 170 m_pHBoxs[i] = NULL; 171 m_pAligns[i] = NULL; 172 m_pLists[i] = NULL; 173 m_pListLabels[i] = NULL; 174 mbListVisibility[i] = false; 175 } 176 177 CResourceProvider aResProvider; 178 OUString aFilePickerTitle = aResProvider.getResString( FILE_PICKER_TITLE_OPEN ); 179 180 GdkThreadLock aLock; 181 182 m_pDialog = gtk_file_chooser_dialog_new( 183 OUStringToOString( aFilePickerTitle, RTL_TEXTENCODING_UTF8 ).getStr(), 184 NULL, 185 GTK_FILE_CHOOSER_ACTION_OPEN, 186 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, 187 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, 188 (char *)NULL ); 189 190 gtk_dialog_set_default_response( GTK_DIALOG (m_pDialog), GTK_RESPONSE_ACCEPT ); 191 192 gtk_file_chooser_set_local_only( GTK_FILE_CHOOSER( m_pDialog ), sal_False ); 193 gtk_file_chooser_set_select_multiple( GTK_FILE_CHOOSER( m_pDialog ), sal_False ); 194 195 m_pVBox = gtk_vbox_new( sal_False, 0 ); 196 197 // We don't want clickable items to have a huge hit-area 198 GtkWidget *pHBox = gtk_hbox_new( sal_False, 0 ); 199 GtkWidget *pThinVBox = gtk_vbox_new( sal_False, 0 ); 200 201 gtk_box_pack_end (GTK_BOX( m_pVBox ), pHBox, sal_False, sal_False, 0); 202 gtk_box_pack_start (GTK_BOX( pHBox ), pThinVBox, sal_False, sal_False, 0); 203 gtk_widget_show( pHBox ); 204 gtk_widget_show( pThinVBox ); 205 206 OUString aLabel; 207 208 for( i = 0; i < TOGGLE_LAST; i++ ) 209 { 210 m_pToggles[i] = gtk_check_button_new(); 211 212 #define LABEL_TOGGLE( elem ) \ 213 case elem : \ 214 aLabel = aResProvider.getResString( CHECKBOX_##elem ); \ 215 setLabel( CHECKBOX_##elem, aLabel ); \ 216 break 217 218 switch( i ) { 219 220 LABEL_TOGGLE( AUTOEXTENSION ); 221 LABEL_TOGGLE( PASSWORD ); 222 LABEL_TOGGLE( FILTEROPTIONS ); 223 LABEL_TOGGLE( READONLY ); 224 LABEL_TOGGLE( LINK ); 225 LABEL_TOGGLE( PREVIEW ); 226 LABEL_TOGGLE( SELECTION ); 227 default: 228 OSL_TRACE("Handle unknown control %d\n", i); 229 break; 230 } 231 232 gtk_box_pack_end( GTK_BOX( pThinVBox ), m_pToggles[i], sal_False, sal_False, 0 ); 233 } 234 235 for( i = 0; i < LIST_LAST; i++ ) 236 { 237 m_pHBoxs[i] = gtk_hbox_new( sal_False, 0 ); 238 239 m_pAligns[i] = gtk_alignment_new(0, 0, 0, 1); 240 241 m_pLists[i] = gtk_combo_box_new_text(); 242 243 m_pListLabels[i] = gtk_label_new( "" ); 244 245 #define LABEL_LIST( elem ) \ 246 case elem : \ 247 aLabel = aResProvider.getResString( LISTBOX_##elem##_LABEL ); \ 248 setLabel( LISTBOX_##elem##_LABEL, aLabel ); \ 249 break 250 251 switch( i ) 252 { 253 LABEL_LIST( VERSION ); 254 LABEL_LIST( TEMPLATE ); 255 LABEL_LIST( IMAGE_TEMPLATE ); 256 default: 257 OSL_TRACE("Handle unknown control %d\n", i); 258 break; 259 } 260 261 gtk_container_add( GTK_CONTAINER( m_pAligns[i]), m_pLists[i] ); 262 gtk_box_pack_end( GTK_BOX( m_pHBoxs[i] ), m_pAligns[i], sal_False, sal_False, 0 ); 263 264 gtk_box_pack_end( GTK_BOX( m_pHBoxs[i] ), m_pListLabels[i], sal_False, sal_False, 0 ); 265 266 gtk_box_pack_end( GTK_BOX( m_pVBox ), m_pHBoxs[i], sal_False, sal_False, 0 ); 267 } 268 269 aLabel = aResProvider.getResString( FILE_PICKER_FILE_TYPE ); 270 m_pFilterExpander = gtk_expander_new_with_mnemonic( 271 OUStringToOString( aLabel, RTL_TEXTENCODING_UTF8 ).getStr()); 272 273 gtk_box_pack_end( GTK_BOX( m_pVBox ), m_pFilterExpander, sal_False, sal_True, 0 ); 274 275 GtkWidget *scrolled_window = gtk_scrolled_window_new (NULL, NULL); 276 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), 277 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); 278 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window), 279 GTK_SHADOW_IN); 280 gtk_container_add (GTK_CONTAINER (m_pFilterExpander), scrolled_window); 281 gtk_widget_show (scrolled_window); 282 283 ByteString sExpand(getenv("SAL_EXPANDFPICKER")); 284 sal_Int32 nExpand = sExpand.ToInt32(); 285 switch (nExpand) 286 { 287 default: 288 case 0: 289 break; 290 case 1: 291 gtk_expander_set_expanded(GTK_EXPANDER(m_pFilterExpander), sal_True); 292 break; 293 case 2: 294 expandexpanders(GTK_CONTAINER(m_pDialog)); 295 gtk_expander_set_expanded(GTK_EXPANDER(m_pFilterExpander), sal_True); 296 break; 297 } 298 299 m_pFilterStore = gtk_list_store_new (4, G_TYPE_STRING, G_TYPE_STRING, 300 G_TYPE_STRING, G_TYPE_STRING); 301 m_pFilterView = gtk_tree_view_new_with_model (GTK_TREE_MODEL(m_pFilterStore)); 302 gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(m_pFilterView), false); 303 gtk_tree_view_set_rules_hint (GTK_TREE_VIEW(m_pFilterView), true); 304 305 GtkTreeViewColumn *column; 306 GtkCellRenderer *cell; 307 308 for (i = 0; i < 2; ++i) 309 { 310 column = gtk_tree_view_column_new (); 311 cell = gtk_cell_renderer_text_new (); 312 gtk_tree_view_column_set_expand (column, sal_True); 313 gtk_tree_view_column_pack_start (column, cell, sal_False); 314 gtk_tree_view_column_set_attributes (column, cell, "text", i, (char *)NULL); 315 gtk_tree_view_append_column (GTK_TREE_VIEW(m_pFilterView), column); 316 } 317 318 gtk_container_add (GTK_CONTAINER (scrolled_window), m_pFilterView); 319 gtk_widget_show (m_pFilterView); 320 321 gtk_file_chooser_set_extra_widget( GTK_FILE_CHOOSER( m_pDialog ), m_pVBox ); 322 323 m_pPreview = gtk_image_new(); 324 gtk_file_chooser_set_preview_widget( GTK_FILE_CHOOSER( m_pDialog ), m_pPreview ); 325 326 g_signal_connect( G_OBJECT( m_pToggles[PREVIEW] ), "toggled", 327 G_CALLBACK( preview_toggled_cb ), this ); 328 g_signal_connect (gtk_tree_view_get_selection (GTK_TREE_VIEW(m_pFilterView)), "changed", 329 G_CALLBACK ( type_changed_cb ), this); 330 g_signal_connect( G_OBJECT( m_pDialog ), "notify::filter", 331 G_CALLBACK( filter_changed_cb ), this); 332 g_signal_connect( G_OBJECT( m_pFilterExpander ), "activate", 333 G_CALLBACK( expander_changed_cb ), this); 334 g_signal_connect (G_OBJECT( m_pDialog ), "map", 335 G_CALLBACK (dialog_mapped_cb), this); 336 337 gtk_widget_show( m_pVBox ); 338 339 PangoLayout *layout = gtk_widget_create_pango_layout (m_pFilterView, NULL); 340 guint ypad; 341 PangoRectangle row_height; 342 pango_layout_set_markup (layout, "All Files", -1); 343 pango_layout_get_pixel_extents (layout, NULL, &row_height); 344 g_object_get (cell, "ypad", &ypad, (char *)NULL); 345 guint height = (row_height.height + 2*ypad) * 5; 346 gtk_widget_set_size_request (m_pFilterView, -1, height); 347 gtk_widget_set_size_request (m_pPreview, 1, height); 348 349 gtk_file_chooser_set_preview_widget_active( GTK_FILE_CHOOSER( m_pDialog ), true); 350 } 351 352 //------------------------------------------------------------------------------------ 353 // XFilePickerNotifier 354 //------------------------------------------------------------------------------------ 355 356 void SAL_CALL SalGtkFilePicker::addFilePickerListener( const uno::Reference<XFilePickerListener>& xListener ) 357 throw( uno::RuntimeException ) 358 { 359 m_xListener = xListener; 360 } 361 362 void SAL_CALL SalGtkFilePicker::removeFilePickerListener( const uno::Reference<XFilePickerListener>& ) 363 throw( uno::RuntimeException ) 364 { 365 m_xListener.clear(); 366 } 367 368 // ------------------------------------------------- 369 // XEventListener 370 // ------------------------------------------------- 371 372 void SAL_CALL SalGtkFilePicker::disposing( const lang::EventObject& aEvent ) throw( uno::RuntimeException ) 373 { 374 uno::Reference<XFilePickerListener> xFilePickerListener( aEvent.Source, ::com::sun::star::uno::UNO_QUERY ); 375 376 if( xFilePickerListener.is() ) 377 removeFilePickerListener( xFilePickerListener ); 378 } 379 380 //----------------------------------------------------------------------------------------- 381 // FilePicker Event functions 382 //----------------------------------------------------------------------------------------- 383 384 void SAL_CALL SalGtkFilePicker::fileSelectionChanged( FilePickerEvent aEvent ) 385 { 386 OSL_TRACE( "file selection changed"); 387 if (m_xListener.is()) m_xListener->fileSelectionChanged( aEvent ); 388 } 389 390 void SAL_CALL SalGtkFilePicker::directoryChanged( FilePickerEvent aEvent ) 391 { 392 OSL_TRACE("directory changed"); 393 if (m_xListener.is()) m_xListener->directoryChanged( aEvent ); 394 } 395 396 void SAL_CALL SalGtkFilePicker::controlStateChanged( FilePickerEvent aEvent ) 397 { 398 OSL_TRACE("control state changed"); 399 if (m_xListener.is()) m_xListener->controlStateChanged( aEvent ); 400 } 401 402 //----------------------------------------------------------------------------------------- 403 // If there are more then one listener the return value of the last one wins 404 //----------------------------------------------------------------------------------------- 405 406 rtl::OUString SAL_CALL SalGtkFilePicker::helpRequested( FilePickerEvent aEvent ) const 407 { 408 rtl::OUString aHelpText; 409 410 ::cppu::OInterfaceContainerHelper* pICHelper = 411 rBHelper.getContainer( getCppuType( ( uno::Reference<XFilePickerListener> * )0 ) ); 412 413 if( pICHelper ) 414 { 415 ::cppu::OInterfaceIteratorHelper iter( *pICHelper ); 416 417 while( iter.hasMoreElements() ) 418 { 419 try 420 { 421 /* 422 if there are multiple listeners responding 423 to this notification the next response 424 overwrittes the one before if it is not empty 425 */ 426 427 rtl::OUString aTempString; 428 429 uno::Reference<XFilePickerListener> xFPListener( iter.next(), uno::UNO_QUERY ); 430 if( xFPListener.is() ) 431 { 432 aTempString = xFPListener->helpRequested( aEvent ); 433 if( aTempString.getLength() ) 434 aHelpText = aTempString; 435 } 436 437 } 438 catch( uno::RuntimeException& ) 439 { 440 OSL_ENSURE( false, "RuntimeException during event dispatching" ); 441 } 442 } 443 } 444 445 return aHelpText; 446 } 447 448 //===================================================================== 449 450 struct FilterEntry 451 { 452 protected: 453 ::rtl::OUString m_sTitle; 454 ::rtl::OUString m_sFilter; 455 456 UnoFilterList m_aSubFilters; 457 458 public: 459 FilterEntry( const ::rtl::OUString& _rTitle, const ::rtl::OUString& _rFilter ) 460 :m_sTitle( _rTitle ) 461 ,m_sFilter( _rFilter ) 462 { 463 } 464 465 FilterEntry( const ::rtl::OUString& _rTitle, const UnoFilterList& _rSubFilters ); 466 467 ::rtl::OUString getTitle() const { return m_sTitle; } 468 ::rtl::OUString getFilter() const { return m_sFilter; } 469 470 /// determines if the filter has sub filter (i.e., the filter is a filter group in real) 471 sal_Bool hasSubFilters( ) const; 472 473 /** retrieves the filters belonging to the entry 474 @return 475 the number of sub filters 476 */ 477 sal_Int32 getSubFilters( UnoFilterList& _rSubFilterList ); 478 479 // helpers for iterating the sub filters 480 const UnoFilterEntry* beginSubFilters() const { return m_aSubFilters.getConstArray(); } 481 const UnoFilterEntry* endSubFilters() const { return m_aSubFilters.getConstArray() + m_aSubFilters.getLength(); } 482 }; 483 484 //===================================================================== 485 486 //--------------------------------------------------------------------- 487 FilterEntry::FilterEntry( const ::rtl::OUString& _rTitle, const UnoFilterList& _rSubFilters ) 488 :m_sTitle( _rTitle ) 489 ,m_aSubFilters( _rSubFilters ) 490 { 491 } 492 493 //--------------------------------------------------------------------- 494 sal_Bool FilterEntry::hasSubFilters() const 495 { 496 return( 0 < m_aSubFilters.getLength() ); 497 } 498 499 //--------------------------------------------------------------------- 500 sal_Int32 FilterEntry::getSubFilters( UnoFilterList& _rSubFilterList ) 501 { 502 _rSubFilterList = m_aSubFilters; 503 return m_aSubFilters.getLength(); 504 } 505 506 static bool 507 isFilterString( const rtl::OUString &rFilterString, const char *pMatch ) 508 { 509 sal_Int32 nIndex = 0; 510 rtl::OUString aToken; 511 bool bIsFilter = true; 512 513 rtl::OUString aMatch(rtl::OUString::createFromAscii(pMatch)); 514 515 do 516 { 517 aToken = rFilterString.getToken( 0, ';', nIndex ); 518 if( !aToken.match( aMatch ) ) 519 { 520 bIsFilter = false; 521 break; 522 } 523 } 524 while( nIndex >= 0 ); 525 526 return bIsFilter; 527 } 528 529 static rtl::OUString 530 shrinkFilterName( const rtl::OUString &rFilterName, bool bAllowNoStar = false ) 531 { 532 int i; 533 int nBracketLen = -1; 534 int nBracketEnd = -1; 535 const sal_Unicode *pStr = rFilterName; 536 OUString aRealName = rFilterName; 537 538 for( i = aRealName.getLength() - 1; i > 0; i-- ) 539 { 540 if( pStr[i] == ')' ) 541 nBracketEnd = i; 542 else if( pStr[i] == '(' ) 543 { 544 nBracketLen = nBracketEnd - i; 545 if( nBracketEnd <= 0 ) 546 continue; 547 if( isFilterString( rFilterName.copy( i + 1, nBracketLen - 1 ), "*." ) ) 548 aRealName = aRealName.replaceAt( i, nBracketLen + 1, rtl::OUString() ); 549 else if (bAllowNoStar) 550 { 551 if( isFilterString( rFilterName.copy( i + 1, nBracketLen - 1 ), ".") ) 552 aRealName = aRealName.replaceAt( i, nBracketLen + 1, rtl::OUString() ); 553 } 554 } 555 } 556 557 return aRealName; 558 } 559 560 static void 561 dialog_remove_buttons( GtkDialog *pDialog ) 562 { 563 GdkThreadLock aLock; 564 565 g_return_if_fail( GTK_IS_DIALOG( pDialog ) ); 566 567 GList *pChildren = 568 gtk_container_get_children( GTK_CONTAINER( pDialog->action_area ) ); 569 570 for( GList *p = pChildren; p; p = p->next ) 571 gtk_widget_destroy( GTK_WIDGET( p->data ) ); 572 573 g_list_free( pChildren ); 574 } 575 576 //------------------------------------------------------------------------------------ 577 namespace { 578 //................................................................................ 579 struct FilterTitleMatch : public ::std::unary_function< FilterEntry, bool > 580 { 581 protected: 582 const ::rtl::OUString& rTitle; 583 584 public: 585 FilterTitleMatch( const ::rtl::OUString& _rTitle ) : rTitle( _rTitle ) { } 586 587 //............................................................................ 588 bool operator () ( const FilterEntry& _rEntry ) 589 { 590 sal_Bool bMatch; 591 if( !_rEntry.hasSubFilters() ) 592 // a real filter 593 bMatch = ( _rEntry.getTitle() == rTitle ); 594 else 595 // a filter group -> search the sub filters 596 bMatch = 597 _rEntry.endSubFilters() != ::std::find_if( 598 _rEntry.beginSubFilters(), 599 _rEntry.endSubFilters(), 600 *this 601 ); 602 603 return bMatch ? true : false; 604 } 605 bool operator () ( const UnoFilterEntry& _rEntry ) 606 { 607 OUString aShrunkName = shrinkFilterName( _rEntry.First ); 608 return aShrunkName == rTitle ? true : false; 609 } 610 }; 611 } 612 613 614 //------------------------------------------------------------------------------------ 615 sal_Bool SalGtkFilePicker::FilterNameExists( const ::rtl::OUString& rTitle ) 616 { 617 sal_Bool bRet = sal_False; 618 619 if( m_pFilterList ) 620 bRet = 621 m_pFilterList->end() != ::std::find_if( 622 m_pFilterList->begin(), 623 m_pFilterList->end(), 624 FilterTitleMatch( rTitle ) 625 ); 626 627 return bRet; 628 } 629 630 //------------------------------------------------------------------------------------ 631 sal_Bool SalGtkFilePicker::FilterNameExists( const UnoFilterList& _rGroupedFilters ) 632 { 633 sal_Bool bRet = sal_False; 634 635 if( m_pFilterList ) 636 { 637 const UnoFilterEntry* pStart = _rGroupedFilters.getConstArray(); 638 const UnoFilterEntry* pEnd = pStart + _rGroupedFilters.getLength(); 639 for( ; pStart != pEnd; ++pStart ) 640 if( m_pFilterList->end() != ::std::find_if( 641 m_pFilterList->begin(), 642 m_pFilterList->end(), 643 FilterTitleMatch( pStart->First ) ) ) 644 break; 645 646 bRet = pStart != pEnd; 647 } 648 649 return bRet; 650 } 651 652 //------------------------------------------------------------------------------------ 653 void SalGtkFilePicker::ensureFilterList( const ::rtl::OUString& _rInitialCurrentFilter ) 654 { 655 if( !m_pFilterList ) 656 { 657 m_pFilterList = new FilterList; 658 659 // set the first filter to the current filter 660 if( ( !m_aCurrentFilter ) || ( !m_aCurrentFilter.getLength() ) ) 661 m_aCurrentFilter = _rInitialCurrentFilter; 662 } 663 } 664 665 666 //----------------------------------------------------------------------------------------- 667 // 668 //----------------------------------------------------------------------------------------- 669 670 void SAL_CALL SalGtkFilePicker::appendFilter( const rtl::OUString& aTitle, const rtl::OUString& aFilter ) 671 throw( lang::IllegalArgumentException, uno::RuntimeException ) 672 { 673 OSL_ASSERT( m_pDialog != NULL ); 674 675 if( FilterNameExists( aTitle ) ) 676 throw IllegalArgumentException(); 677 678 // ensure that we have a filter list 679 ensureFilterList( aTitle ); 680 681 // append the filter 682 m_pFilterList->insert( m_pFilterList->end(), FilterEntry( aTitle, aFilter ) ); 683 // implAddFilter( aTitle, aFilter ); 684 } 685 686 //----------------------------------------------------------------------------------------- 687 // 688 //----------------------------------------------------------------------------------------- 689 690 void SAL_CALL SalGtkFilePicker::setCurrentFilter( const rtl::OUString& aTitle ) 691 throw( lang::IllegalArgumentException, uno::RuntimeException ) 692 { 693 OSL_ASSERT( m_pDialog != NULL ); 694 695 OSL_TRACE( "Setting current filter to %s\n", 696 OUStringToOString( aTitle, RTL_TEXTENCODING_UTF8 ).getStr() ); 697 698 if( aTitle != m_aCurrentFilter ) 699 { 700 m_aCurrentFilter = aTitle; 701 SetCurFilter( m_aCurrentFilter ); 702 OSL_TRACE( "REALLY Setting current filter to %s\n", 703 OUStringToOString( aTitle, RTL_TEXTENCODING_UTF8 ).getStr() ); 704 705 } 706 707 // TODO m_pImpl->setCurrentFilter( aTitle ); 708 } 709 710 //----------------------------------------------------------------------------------------- 711 // 712 //----------------------------------------------------------------------------------------- 713 714 void SalGtkFilePicker::updateCurrentFilterFromName(const gchar* filtername) 715 { 716 OUString aFilterName(filtername, strlen(filtername), RTL_TEXTENCODING_UTF8); 717 FilterList::iterator aEnd = m_pFilterList->end(); 718 for (FilterList::iterator aIter = m_pFilterList->begin(); aIter != aEnd; ++aIter) 719 { 720 if (aFilterName == shrinkFilterName( aIter->getTitle())) 721 { 722 m_aCurrentFilter = aIter->getTitle(); 723 break; 724 } 725 } 726 } 727 728 void SalGtkFilePicker::UpdateFilterfromUI() 729 { 730 // Update the filtername from the users selection if they have had a chance to do so. 731 // If the user explicitly sets a type then use that, if not then take the implicit type 732 // from the filter of the files glob on which he is currently searching 733 if (!mnHID_FolderChange || !mnHID_SelectionChange) 734 return; 735 736 GdkThreadLock aLock; 737 738 GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(m_pFilterView)); 739 GtkTreeIter iter; 740 GtkTreeModel *model; 741 if (gtk_tree_selection_get_selected (selection, &model, &iter)) 742 { 743 gchar *title; 744 gtk_tree_model_get (model, &iter, 2, &title, -1); 745 updateCurrentFilterFromName(title); 746 g_free (title); 747 } 748 else if( GtkFileFilter *filter = gtk_file_chooser_get_filter(GTK_FILE_CHOOSER(m_pDialog))) 749 { 750 updateCurrentFilterFromName(gtk_file_filter_get_name( filter )); 751 } 752 } 753 754 rtl::OUString SAL_CALL SalGtkFilePicker::getCurrentFilter() throw( uno::RuntimeException ) 755 { 756 OSL_ASSERT( m_pDialog != NULL ); 757 758 OSL_TRACE( "GetCURRENTfilter\n" ); 759 760 UpdateFilterfromUI(); 761 762 OSL_TRACE( "Returning current filter of %s\n", 763 OUStringToOString( m_aCurrentFilter, RTL_TEXTENCODING_UTF8 ).getStr() ); 764 765 return m_aCurrentFilter; 766 } 767 768 //----------------------------------------------------------------------------------------- 769 // XFilterGroupManager functions 770 //----------------------------------------------------------------------------------------- 771 772 void SAL_CALL SalGtkFilePicker::appendFilterGroup( const rtl::OUString& /*sGroupTitle*/, const uno::Sequence<beans::StringPair>& aFilters ) 773 throw( lang::IllegalArgumentException, uno::RuntimeException ) 774 { 775 OSL_ASSERT( m_pDialog != NULL ); 776 777 // TODO m_pImpl->appendFilterGroup( sGroupTitle, aFilters ); 778 // check the names 779 if( FilterNameExists( aFilters ) ) 780 // TODO: a more precise exception message 781 throw IllegalArgumentException(); 782 783 // ensure that we have a filter list 784 ::rtl::OUString sInitialCurrentFilter; 785 if( aFilters.getLength() ) 786 sInitialCurrentFilter = aFilters[0].First; 787 788 ensureFilterList( sInitialCurrentFilter ); 789 790 // append the filter 791 const StringPair* pSubFilters = aFilters.getConstArray(); 792 const StringPair* pSubFiltersEnd = pSubFilters + aFilters.getLength(); 793 for( ; pSubFilters != pSubFiltersEnd; ++pSubFilters ) 794 m_pFilterList->insert( m_pFilterList->end(), FilterEntry( pSubFilters->First, pSubFilters->Second ) ); 795 796 } 797 798 //----------------------------------------------------------------------------------------- 799 // XFilePicker functions 800 //----------------------------------------------------------------------------------------- 801 802 void SAL_CALL SalGtkFilePicker::setMultiSelectionMode( sal_Bool bMode ) throw( uno::RuntimeException ) 803 { 804 OSL_ASSERT( m_pDialog != NULL ); 805 806 GdkThreadLock aLock; 807 808 gtk_file_chooser_set_select_multiple( GTK_FILE_CHOOSER(m_pDialog), bMode ); 809 } 810 811 void SAL_CALL SalGtkFilePicker::setDefaultName( const rtl::OUString& aName ) 812 throw( uno::RuntimeException ) 813 { 814 OSL_ASSERT( m_pDialog != NULL ); 815 816 GdkThreadLock aLock; 817 818 OString aStr = OUStringToOString( aName, RTL_TEXTENCODING_UTF8 ); 819 GtkFileChooserAction eAction = gtk_file_chooser_get_action( GTK_FILE_CHOOSER( m_pDialog ) ); 820 821 // set_current_name launches a Gtk critical error if called for other than save 822 if( GTK_FILE_CHOOSER_ACTION_SAVE == eAction ) 823 gtk_file_chooser_set_current_name( GTK_FILE_CHOOSER( m_pDialog ), aStr.getStr() ); 824 } 825 826 void SAL_CALL SalGtkFilePicker::setDisplayDirectory( const rtl::OUString& rDirectory ) 827 throw( lang::IllegalArgumentException, uno::RuntimeException ) 828 { 829 implsetDisplayDirectory(rDirectory); 830 } 831 832 rtl::OUString SAL_CALL SalGtkFilePicker::getDisplayDirectory() throw( uno::RuntimeException ) 833 { 834 return implgetDisplayDirectory(); 835 } 836 837 uno::Sequence<rtl::OUString> SAL_CALL SalGtkFilePicker::getFiles() throw( uno::RuntimeException ) 838 { 839 uno::Sequence< rtl::OUString > aFiles = getSelectedFiles(); 840 /* 841 The previous multiselection API design was completely broken 842 and unimplementable for some hetrogenous pseudo-URIs eg. search:// 843 Thus crop unconditionally to a single selection. 844 */ 845 aFiles.realloc (1); 846 return aFiles; 847 } 848 849 uno::Sequence<rtl::OUString> SAL_CALL SalGtkFilePicker::getSelectedFiles() throw( uno::RuntimeException ) 850 { 851 OSL_ASSERT( m_pDialog != NULL ); 852 853 GdkThreadLock aLock; 854 855 GSList* pPathList = gtk_file_chooser_get_uris( GTK_FILE_CHOOSER(m_pDialog) ); 856 857 int nCount = g_slist_length( pPathList ); 858 int nIndex = 0; 859 OSL_TRACE( "GETFILES called %d files\n", nCount ); 860 861 // get the current action setting 862 GtkFileChooserAction eAction = gtk_file_chooser_get_action( 863 GTK_FILE_CHOOSER( m_pDialog )); 864 865 uno::Sequence< rtl::OUString > aSelectedFiles(nCount); 866 867 // Convert to OOo 868 for( GSList *pElem = pPathList; pElem; pElem = pElem->next) 869 { 870 gchar *pURI = reinterpret_cast<gchar*>(pElem->data); 871 aSelectedFiles[ nIndex ] = uritounicode(pURI); 872 873 if( GTK_FILE_CHOOSER_ACTION_SAVE == eAction ) 874 { 875 OUString sFilterName; 876 sal_Int32 nTokenIndex = 0; 877 bool bExtensionTypedIn = false; 878 879 GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(m_pFilterView)); 880 GtkTreeIter iter; 881 GtkTreeModel *model; 882 if (gtk_tree_selection_get_selected (selection, &model, &iter)) 883 { 884 gchar *title; 885 gtk_tree_model_get (model, &iter, 2, &title, -1); 886 sFilterName = OUString( title, strlen( title), RTL_TEXTENCODING_UTF8 ); 887 g_free (title); 888 } 889 else 890 { 891 if( aSelectedFiles[nIndex].indexOf('.') > 0 ) 892 { 893 rtl::OUString sExtension; 894 nTokenIndex = 0; 895 do 896 sExtension = aSelectedFiles[nIndex].getToken( 0, '.', nTokenIndex ); 897 while( nTokenIndex >= 0 ); 898 899 if( sExtension.getLength() >= 3 ) // 3 = typical/minimum extension length 900 { 901 static const OUString aStarDot = OUString::createFromAscii( "*." ); 902 903 ::rtl::OUString aNewFilter; 904 ::rtl::OUString aOldFilter = getCurrentFilter(); 905 sal_Bool bChangeFilter = sal_True; 906 for ( FilterList::iterator aListIter = m_pFilterList->begin(); 907 aListIter != m_pFilterList->end(); 908 ++aListIter 909 ) 910 { 911 if( aListIter->getFilter().indexOf( aStarDot+sExtension ) >= 0 ) 912 { 913 if( !aNewFilter.getLength() ) 914 aNewFilter = aListIter->getTitle(); 915 916 if( aOldFilter == aListIter->getTitle() ) 917 bChangeFilter = sal_False; 918 919 bExtensionTypedIn = true; 920 } 921 } 922 if( bChangeFilter ) 923 setCurrentFilter( aNewFilter ); 924 } 925 } 926 927 const gchar* filtername = 928 gtk_file_filter_get_name( gtk_file_chooser_get_filter( GTK_FILE_CHOOSER( m_pDialog ) ) ); 929 sFilterName = OUString( filtername, strlen( filtername ), RTL_TEXTENCODING_UTF8 ); 930 } 931 932 OSL_TRACE( "2: current filter is %s\n", 933 OUStringToOString( sFilterName, RTL_TEXTENCODING_UTF8 ).getStr() ); 934 935 FilterList::iterator aListIter = ::std::find_if( 936 m_pFilterList->begin(), m_pFilterList->end(), FilterTitleMatch(sFilterName) ); 937 938 OUString aFilter; 939 if (aListIter != m_pFilterList->end()) 940 aFilter = aListIter->getFilter(); 941 942 OSL_TRACE( "turned into %s\n", 943 OUStringToOString( aFilter, RTL_TEXTENCODING_UTF8 ).getStr() ); 944 945 nTokenIndex = 0; 946 rtl::OUString sToken; 947 // rtl::OUString strExt; 948 do 949 { 950 sToken = aFilter.getToken( 0, '.', nTokenIndex ); 951 952 if ( sToken.lastIndexOf( ';' ) != -1 ) 953 { 954 sal_Int32 nZero = 0; 955 OUString aCurrentToken = sToken.getToken( 0, ';', nZero); 956 957 sToken = aCurrentToken; 958 break; 959 } 960 } 961 while( nTokenIndex >= 0 ); 962 963 if( !bExtensionTypedIn && ( !sToken.equalsAscii( "*" ) ) ) 964 { 965 //if the filename does not already have the auto extension, stick it on 966 OUString sExtension = OUString::createFromAscii( "." ) + sToken; 967 OUString &rBase = aSelectedFiles[nIndex]; 968 sal_Int32 nExtensionIdx = rBase.getLength() - sExtension.getLength(); 969 OSL_TRACE( "idx are %d %d\n", rBase.lastIndexOf( sExtension ), nExtensionIdx ); 970 971 if( rBase.lastIndexOf( sExtension ) != nExtensionIdx ) 972 rBase += sExtension; 973 } 974 975 } 976 977 nIndex++; 978 g_free( pURI ); 979 } 980 981 g_slist_free( pPathList ); 982 983 return aSelectedFiles; 984 } 985 986 //----------------------------------------------------------------------------------------- 987 // XExecutableDialog functions 988 //----------------------------------------------------------------------------------------- 989 990 void SAL_CALL SalGtkFilePicker::setTitle( const rtl::OUString& rTitle ) throw( uno::RuntimeException ) 991 { 992 implsetTitle(rTitle); 993 } 994 995 sal_Int16 SAL_CALL SalGtkFilePicker::execute() throw( uno::RuntimeException ) 996 { 997 OSL_TRACE( "1: HERE WE ARE\n"); 998 OSL_ASSERT( m_pDialog != NULL ); 999 1000 GdkThreadLock aLock; 1001 1002 sal_Int16 retVal = 0; 1003 1004 SetFilters(); 1005 1006 mnHID_FolderChange = 1007 g_signal_connect( GTK_FILE_CHOOSER( m_pDialog ), "current-folder-changed", 1008 G_CALLBACK( folder_changed_cb ), ( gpointer )this ); 1009 1010 mnHID_SelectionChange = 1011 g_signal_connect( GTK_FILE_CHOOSER( m_pDialog ), "selection-changed", 1012 G_CALLBACK( selection_changed_cb ), ( gpointer )this ); 1013 1014 int btn = GTK_RESPONSE_NO; 1015 1016 uno::Reference< awt::XExtendedToolkit > xToolkit( 1017 m_xServiceMgr->createInstance( ::rtl::OUString::createFromAscii("com.sun.star.awt.Toolkit") ), uno::UNO_QUERY); 1018 1019 RunDialog* pRunDialog = new RunDialog(m_pDialog, xToolkit); 1020 uno::Reference < awt::XTopWindowListener > xLifeCycle(pRunDialog); 1021 while( GTK_RESPONSE_NO == btn ) 1022 { 1023 btn = GTK_RESPONSE_YES; // we dont want to repeat unless user clicks NO for file save. 1024 1025 gint nStatus = pRunDialog->run(); 1026 switch( nStatus ) 1027 { 1028 case GTK_RESPONSE_ACCEPT: 1029 if( GTK_FILE_CHOOSER_ACTION_SAVE == gtk_file_chooser_get_action( GTK_FILE_CHOOSER( m_pDialog ) ) ) 1030 { 1031 Sequence < OUString > aPathSeq = getFiles(); 1032 if( aPathSeq.getLength() == 1 ) 1033 { 1034 OString sFileName = unicodetouri( aPathSeq[0] ); 1035 if( g_file_test( g_filename_from_uri( sFileName.getStr(), NULL, NULL ), G_FILE_TEST_IS_REGULAR ) ) 1036 { 1037 CResourceProvider aResProvider; 1038 GtkWidget *dlg; 1039 1040 dlg = gtk_message_dialog_new( NULL, 1041 GTK_DIALOG_MODAL, 1042 GTK_MESSAGE_QUESTION, 1043 GTK_BUTTONS_YES_NO, 1044 OUStringToOString( 1045 aResProvider.getResString( FILE_PICKER_OVERWRITE ), 1046 RTL_TEXTENCODING_UTF8 ).getStr() ); 1047 1048 gtk_window_set_title( GTK_WINDOW( dlg ), 1049 OUStringToOString(aResProvider.getResString(FILE_PICKER_TITLE_SAVE ), 1050 RTL_TEXTENCODING_UTF8 ).getStr() ); 1051 1052 RunDialog* pAnotherDialog = new RunDialog(dlg, xToolkit); 1053 uno::Reference < awt::XTopWindowListener > xAnotherLifeCycle(pAnotherDialog); 1054 btn = pAnotherDialog->run(); 1055 1056 gtk_widget_destroy( dlg ); 1057 } 1058 1059 if( btn == GTK_RESPONSE_YES ) 1060 retVal = ExecutableDialogResults::OK; 1061 } 1062 } 1063 else 1064 retVal = ExecutableDialogResults::OK; 1065 break; 1066 1067 case GTK_RESPONSE_CANCEL: 1068 retVal = ExecutableDialogResults::CANCEL; 1069 break; 1070 1071 case 1: //PLAY 1072 { 1073 FilePickerEvent evt; 1074 evt.ElementId = PUSHBUTTON_PLAY; 1075 OSL_TRACE( "filter_changed, isn't it great %x\n", this); 1076 controlStateChanged( evt ); 1077 btn = GTK_RESPONSE_NO; 1078 } 1079 break; 1080 1081 default: 1082 retVal = 0; 1083 break; 1084 } 1085 } 1086 1087 if (mnHID_FolderChange) 1088 g_signal_handler_disconnect(GTK_FILE_CHOOSER( m_pDialog ), mnHID_FolderChange); 1089 if (mnHID_SelectionChange) 1090 g_signal_handler_disconnect(GTK_FILE_CHOOSER( m_pDialog ), mnHID_SelectionChange); 1091 1092 return retVal; 1093 } 1094 1095 //------------------------------------------------------------------------------------ 1096 1097 // cf. offapi/com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.idl 1098 GtkWidget *SalGtkFilePicker::getWidget( sal_Int16 nControlId, GType *pType ) 1099 { 1100 OSL_TRACE("control id is %d", nControlId); 1101 GType tType = GTK_TYPE_TOGGLE_BUTTON; //prevent waring by initializing 1102 GtkWidget *pWidget = 0; 1103 1104 #define MAP_TOGGLE( elem ) \ 1105 case ExtendedFilePickerElementIds::CHECKBOX_##elem: \ 1106 pWidget = m_pToggles[elem]; tType = GTK_TYPE_TOGGLE_BUTTON; \ 1107 break 1108 #define MAP_BUTTON( elem ) \ 1109 case ExtendedFilePickerElementIds::PUSHBUTTON_##elem: \ 1110 pWidget = m_pButtons[elem]; tType = GTK_TYPE_BUTTON; \ 1111 break 1112 #define MAP_LIST( elem ) \ 1113 case ExtendedFilePickerElementIds::LISTBOX_##elem: \ 1114 pWidget = m_pLists[elem]; tType = GTK_TYPE_COMBO_BOX; \ 1115 break 1116 #define MAP_LIST_LABEL( elem ) \ 1117 case ExtendedFilePickerElementIds::LISTBOX_##elem##_LABEL: \ 1118 pWidget = m_pListLabels[elem]; tType = GTK_TYPE_LABEL; \ 1119 break 1120 1121 switch( nControlId ) 1122 { 1123 MAP_TOGGLE( AUTOEXTENSION ); 1124 MAP_TOGGLE( PASSWORD ); 1125 MAP_TOGGLE( FILTEROPTIONS ); 1126 MAP_TOGGLE( READONLY ); 1127 MAP_TOGGLE( LINK ); 1128 MAP_TOGGLE( PREVIEW ); 1129 MAP_TOGGLE( SELECTION ); 1130 MAP_BUTTON( PLAY ); 1131 MAP_LIST( VERSION ); 1132 MAP_LIST( TEMPLATE ); 1133 MAP_LIST( IMAGE_TEMPLATE ); 1134 MAP_LIST_LABEL( VERSION ); 1135 MAP_LIST_LABEL( TEMPLATE ); 1136 MAP_LIST_LABEL( IMAGE_TEMPLATE ); 1137 default: 1138 OSL_TRACE("Handle unknown control %d\n", nControlId); 1139 break; 1140 } 1141 #undef MAP 1142 1143 if( pType ) 1144 *pType = tType; 1145 return pWidget; 1146 } 1147 1148 1149 1150 //------------------------------------------------------------------------------------ 1151 // XFilePickerControlAccess functions 1152 //------------------------------------------------------------------------------------ 1153 namespace 1154 { 1155 void HackWidthToFirst(GtkComboBox *pWidget) 1156 { 1157 GdkThreadLock aLock; 1158 1159 GtkRequisition requisition; 1160 gtk_widget_size_request(GTK_WIDGET(pWidget), &requisition); 1161 gtk_widget_set_size_request(GTK_WIDGET(pWidget), requisition.width, -1); 1162 } 1163 } 1164 1165 void SalGtkFilePicker::HandleSetListValue(GtkComboBox *pWidget, sal_Int16 nControlAction, const uno::Any& rValue) 1166 { 1167 GdkThreadLock aLock; 1168 1169 switch (nControlAction) 1170 { 1171 case ControlActions::ADD_ITEM: 1172 { 1173 OUString sItem; 1174 rValue >>= sItem; 1175 gtk_combo_box_append_text(pWidget, rtl::OUStringToOString(sItem, RTL_TEXTENCODING_UTF8).getStr()); 1176 if (!bVersionWidthUnset) 1177 { 1178 HackWidthToFirst(pWidget); 1179 bVersionWidthUnset = true; 1180 } 1181 } 1182 break; 1183 case ControlActions::ADD_ITEMS: 1184 { 1185 Sequence< OUString > aStringList; 1186 rValue >>= aStringList; 1187 sal_Int32 nItemCount = aStringList.getLength(); 1188 for (sal_Int32 i = 0; i < nItemCount; ++i) 1189 { 1190 gtk_combo_box_append_text(pWidget, 1191 rtl::OUStringToOString(aStringList[i], RTL_TEXTENCODING_UTF8).getStr()); 1192 if (!bVersionWidthUnset) 1193 { 1194 HackWidthToFirst(pWidget); 1195 bVersionWidthUnset = true; 1196 } 1197 } 1198 } 1199 break; 1200 case ControlActions::DELETE_ITEM: 1201 { 1202 sal_Int32 nPos=0; 1203 rValue >>= nPos; 1204 gtk_combo_box_remove_text(pWidget, nPos); 1205 } 1206 break; 1207 case ControlActions::DELETE_ITEMS: 1208 { 1209 gtk_combo_box_set_active(pWidget, -1); 1210 gint nItems = 0; 1211 do 1212 { 1213 nItems = 1214 gtk_tree_model_iter_n_children( 1215 gtk_combo_box_get_model(pWidget), NULL); 1216 for (gint nI = 0; nI < nItems; ++nI) 1217 gtk_combo_box_remove_text(pWidget, nI); 1218 } 1219 while (nItems); 1220 } 1221 break; 1222 case ControlActions::SET_SELECT_ITEM: 1223 { 1224 sal_Int32 nPos=0; 1225 rValue >>= nPos; 1226 gtk_combo_box_set_active(pWidget, nPos); 1227 } 1228 break; 1229 default: 1230 OSL_TRACE("undocumented/unimplemented ControlAction for a list"); 1231 break; 1232 } 1233 1234 //I think its best to make it insensitive unless there is the chance to 1235 //actually select something from the list. 1236 gint nItems = gtk_tree_model_iter_n_children( 1237 gtk_combo_box_get_model(pWidget), NULL); 1238 gtk_widget_set_sensitive(GTK_WIDGET(pWidget), nItems > 1 ? true : false); 1239 } 1240 1241 uno::Any SalGtkFilePicker::HandleGetListValue(GtkComboBox *pWidget, sal_Int16 nControlAction) const 1242 { 1243 GdkThreadLock aLock; 1244 1245 uno::Any aAny; 1246 switch (nControlAction) 1247 { 1248 case ControlActions::GET_ITEMS: 1249 { 1250 Sequence< OUString > aItemList; 1251 1252 GtkTreeModel *pTree = gtk_combo_box_get_model(pWidget); 1253 GtkTreeIter iter; 1254 if (gtk_tree_model_get_iter_first(pTree, &iter)) 1255 { 1256 sal_Int32 nSize = gtk_tree_model_iter_n_children( 1257 pTree, NULL); 1258 1259 aItemList.realloc(nSize); 1260 for (sal_Int32 i=0; i < nSize; ++i) 1261 { 1262 gchar *item; 1263 gtk_tree_model_get(gtk_combo_box_get_model(pWidget), 1264 &iter, 0, &item, -1); 1265 aItemList[i] = OUString(item, strlen(item), RTL_TEXTENCODING_UTF8); 1266 g_free(item); 1267 gtk_tree_model_iter_next(pTree, &iter); 1268 } 1269 } 1270 aAny <<= aItemList; 1271 } 1272 break; 1273 case ControlActions::GET_SELECTED_ITEM: 1274 { 1275 GtkTreeIter iter; 1276 if (gtk_combo_box_get_active_iter(pWidget, &iter)) 1277 { 1278 gchar *item; 1279 gtk_tree_model_get(gtk_combo_box_get_model(pWidget), 1280 &iter, 0, &item, -1); 1281 OUString sItem(item, strlen(item), RTL_TEXTENCODING_UTF8); 1282 aAny <<= sItem; 1283 g_free(item); 1284 } 1285 } 1286 break; 1287 case ControlActions::GET_SELECTED_ITEM_INDEX: 1288 { 1289 gint nActive = gtk_combo_box_get_active(pWidget); 1290 aAny <<= static_cast< sal_Int32 >(nActive); 1291 } 1292 break; 1293 default: 1294 OSL_TRACE("undocumented/unimplemented ControlAction for a list"); 1295 break; 1296 } 1297 return aAny; 1298 } 1299 1300 void SAL_CALL SalGtkFilePicker::setValue( sal_Int16 nControlId, sal_Int16 nControlAction, const uno::Any& rValue ) 1301 throw( uno::RuntimeException ) 1302 { 1303 OSL_ASSERT( m_pDialog != NULL ); 1304 1305 OSL_TRACE( "SETTING VALUE %d\n", nControlAction ); 1306 GType tType; 1307 GtkWidget *pWidget; 1308 1309 GdkThreadLock aLock; 1310 1311 if( !( pWidget = getWidget( nControlId, &tType ) ) ) 1312 OSL_TRACE("enable unknown control %d\n", nControlId); 1313 else if( tType == GTK_TYPE_TOGGLE_BUTTON ) 1314 { 1315 sal_Bool bChecked = false; 1316 rValue >>= bChecked; 1317 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( pWidget ), bChecked ); 1318 } 1319 else if( tType == GTK_TYPE_COMBO_BOX ) 1320 HandleSetListValue(GTK_COMBO_BOX(pWidget), nControlAction, rValue); 1321 else 1322 { 1323 OSL_TRACE("Can't set value on button / list %d %d\n", 1324 nControlId, nControlAction); 1325 } 1326 } 1327 1328 uno::Any SAL_CALL SalGtkFilePicker::getValue( sal_Int16 nControlId, sal_Int16 nControlAction ) 1329 throw( uno::RuntimeException ) 1330 { 1331 OSL_ASSERT( m_pDialog != NULL ); 1332 1333 uno::Any aRetval; 1334 1335 GType tType; 1336 GtkWidget *pWidget; 1337 1338 GdkThreadLock aLock; 1339 1340 if( !( pWidget = getWidget( nControlId, &tType ) ) ) 1341 OSL_TRACE("enable unknown control %d\n", nControlId); 1342 else if( tType == GTK_TYPE_TOGGLE_BUTTON ) 1343 aRetval <<= (sal_Bool) gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( pWidget ) ); 1344 else if( tType == GTK_TYPE_COMBO_BOX ) 1345 aRetval = HandleGetListValue(GTK_COMBO_BOX(pWidget), nControlAction); 1346 else 1347 OSL_TRACE("Can't get value on button / list %d %d\n", 1348 nControlId, nControlAction ); 1349 1350 return aRetval; 1351 } 1352 1353 void SAL_CALL SalGtkFilePicker::enableControl( sal_Int16 nControlId, sal_Bool bEnable ) 1354 throw( uno::RuntimeException ) 1355 { 1356 OSL_ASSERT( m_pDialog != NULL ); 1357 1358 GtkWidget *pWidget; 1359 1360 GdkThreadLock aLock; 1361 1362 if ( nControlId == ExtendedFilePickerElementIds::LISTBOX_FILTER_SELECTOR ) 1363 gtk_expander_set_expanded( GTK_EXPANDER( m_pFilterExpander ), bEnable ); 1364 else if( ( pWidget = getWidget( nControlId ) ) ) 1365 { 1366 if( bEnable ) 1367 { 1368 OSL_TRACE( "enable\n" ); 1369 gtk_widget_set_sensitive( pWidget, sal_True ); 1370 } 1371 else 1372 { 1373 OSL_TRACE( "disable\n" ); 1374 gtk_widget_set_sensitive( pWidget, sal_False ); 1375 } 1376 } 1377 else 1378 OSL_TRACE("enable unknown control %d\n", nControlId ); 1379 } 1380 1381 void SAL_CALL SalGtkFilePicker::setLabel( sal_Int16 nControlId, const ::rtl::OUString& rLabel ) 1382 throw( uno::RuntimeException ) 1383 { 1384 OSL_ASSERT( m_pDialog != NULL ); 1385 1386 GType tType; 1387 GtkWidget *pWidget; 1388 1389 GdkThreadLock aLock; 1390 1391 if( !( pWidget = getWidget( nControlId, &tType ) ) ) 1392 { 1393 OSL_TRACE("Set label on unknown control %d\n", nControlId); 1394 return; 1395 } 1396 1397 OString aTxt = OUStringToOString( rLabel.replace('~', '_'), RTL_TEXTENCODING_UTF8 ); 1398 if (nControlId == ExtendedFilePickerElementIds::PUSHBUTTON_PLAY) 1399 { 1400 #ifdef GTK_STOCK_MEDIA_PLAY 1401 if (!msPlayLabel.getLength()) 1402 msPlayLabel = rLabel; 1403 if (msPlayLabel == rLabel) 1404 gtk_button_set_label(GTK_BUTTON(pWidget), GTK_STOCK_MEDIA_PLAY); 1405 else 1406 gtk_button_set_label(GTK_BUTTON(pWidget), GTK_STOCK_MEDIA_STOP); 1407 #else 1408 gtk_button_set_label(GTK_BUTTON(pWidget), aTxt.getStr()); 1409 #endif 1410 } 1411 else if( tType == GTK_TYPE_TOGGLE_BUTTON || tType == GTK_TYPE_BUTTON || tType == GTK_TYPE_LABEL ) 1412 g_object_set( pWidget, "label", aTxt.getStr(), 1413 "use_underline", sal_True, (char *)NULL ); 1414 else 1415 OSL_TRACE("Can't set label on list\n"); 1416 } 1417 1418 rtl::OUString SAL_CALL SalGtkFilePicker::getLabel( sal_Int16 nControlId ) 1419 throw( uno::RuntimeException ) 1420 { 1421 OSL_ASSERT( m_pDialog != NULL ); 1422 1423 GType tType; 1424 OString aTxt; 1425 GtkWidget *pWidget; 1426 1427 GdkThreadLock aLock; 1428 1429 if( !( pWidget = getWidget( nControlId, &tType ) ) ) 1430 OSL_TRACE("Get label on unknown control %d\n", nControlId); 1431 else if( tType == GTK_TYPE_TOGGLE_BUTTON || tType == GTK_TYPE_BUTTON || tType == GTK_TYPE_LABEL ) 1432 aTxt = gtk_button_get_label( GTK_BUTTON( pWidget ) ); 1433 else 1434 OSL_TRACE("Can't get label on list\n"); 1435 1436 return OStringToOUString( aTxt, RTL_TEXTENCODING_UTF8 ); 1437 } 1438 1439 //------------------------------------------------------------------------------------ 1440 // XFilePreview functions 1441 //------------------------------------------------------------------------------------ 1442 1443 uno::Sequence<sal_Int16> SAL_CALL SalGtkFilePicker::getSupportedImageFormats() throw( uno::RuntimeException ) 1444 { 1445 OSL_ASSERT( m_pDialog != NULL ); 1446 1447 // TODO return m_pImpl->getSupportedImageFormats(); 1448 return uno::Sequence<sal_Int16>(); 1449 } 1450 1451 sal_Int32 SAL_CALL SalGtkFilePicker::getTargetColorDepth() throw( uno::RuntimeException ) 1452 { 1453 OSL_ASSERT( m_pDialog != NULL ); 1454 1455 // TODO return m_pImpl->getTargetColorDepth(); 1456 return 0; 1457 } 1458 1459 sal_Int32 SAL_CALL SalGtkFilePicker::getAvailableWidth() throw( uno::RuntimeException ) 1460 { 1461 OSL_ASSERT( m_pDialog != NULL ); 1462 1463 return m_PreviewImageWidth; 1464 } 1465 1466 sal_Int32 SAL_CALL SalGtkFilePicker::getAvailableHeight() throw( uno::RuntimeException ) 1467 { 1468 OSL_ASSERT( m_pDialog != NULL ); 1469 1470 return m_PreviewImageHeight; 1471 } 1472 1473 void SAL_CALL SalGtkFilePicker::setImage( sal_Int16 /*aImageFormat*/, const uno::Any& /*aImage*/ ) 1474 throw( lang::IllegalArgumentException, uno::RuntimeException ) 1475 { 1476 OSL_ASSERT( m_pDialog != NULL ); 1477 1478 // TODO m_pImpl->setImage( aImageFormat, aImage ); 1479 } 1480 1481 void SalGtkFilePicker::implChangeType( GtkTreeSelection *selection ) 1482 { 1483 CResourceProvider aResProvider; 1484 OUString aLabel = aResProvider.getResString( FILE_PICKER_FILE_TYPE ); 1485 1486 GdkThreadLock aLock; 1487 1488 GtkTreeIter iter; 1489 GtkTreeModel *model; 1490 if (gtk_tree_selection_get_selected (selection, &model, &iter)) 1491 { 1492 gchar *title; 1493 gtk_tree_model_get (model, &iter, 2, &title, -1); 1494 aLabel += rtl::OUString::createFromAscii( ": " ); 1495 aLabel += rtl::OUString( title, strlen(title), RTL_TEXTENCODING_UTF8 ); 1496 g_free (title); 1497 } 1498 gtk_expander_set_label (GTK_EXPANDER (m_pFilterExpander), 1499 OUStringToOString( aLabel, RTL_TEXTENCODING_UTF8 ).getStr()); 1500 FilePickerEvent evt; 1501 evt.ElementId = LISTBOX_FILTER; 1502 controlStateChanged( evt ); 1503 } 1504 1505 void SalGtkFilePicker::type_changed_cb( GtkTreeSelection *selection, SalGtkFilePicker *pobjFP ) 1506 { 1507 pobjFP->implChangeType(selection); 1508 } 1509 1510 void SalGtkFilePicker::unselect_type() 1511 { 1512 GdkThreadLock aLock; 1513 1514 gtk_tree_selection_unselect_all(gtk_tree_view_get_selection(GTK_TREE_VIEW(m_pFilterView))); 1515 } 1516 1517 void SalGtkFilePicker::expander_changed_cb( GtkExpander *expander, SalGtkFilePicker *pobjFP ) 1518 { 1519 if (gtk_expander_get_expanded(expander)) 1520 pobjFP->unselect_type(); 1521 } 1522 1523 void SalGtkFilePicker::filter_changed_cb( GtkFileChooser *, GParamSpec *, 1524 SalGtkFilePicker *pobjFP ) 1525 { 1526 FilePickerEvent evt; 1527 evt.ElementId = LISTBOX_FILTER; 1528 OSL_TRACE( "filter_changed, isn't it great %x\n", pobjFP ); 1529 pobjFP->controlStateChanged( evt ); 1530 } 1531 1532 void SalGtkFilePicker::folder_changed_cb( GtkFileChooser *, SalGtkFilePicker *pobjFP ) 1533 { 1534 FilePickerEvent evt; 1535 OSL_TRACE( "folder_changed, isn't it great %x\n", pobjFP ); 1536 pobjFP->directoryChanged( evt ); 1537 } 1538 1539 void SalGtkFilePicker::selection_changed_cb( GtkFileChooser *, SalGtkFilePicker *pobjFP ) 1540 { 1541 FilePickerEvent evt; 1542 OSL_TRACE( "selection_changed, isn't it great %x\n", pobjFP ); 1543 pobjFP->fileSelectionChanged( evt ); 1544 } 1545 1546 void SalGtkFilePicker::update_preview_cb( GtkFileChooser *file_chooser, SalGtkFilePicker* pobjFP ) 1547 { 1548 GtkWidget *preview; 1549 char *filename; 1550 GdkPixbuf *pixbuf; 1551 gboolean have_preview = sal_False; 1552 1553 preview = pobjFP->m_pPreview; 1554 filename = gtk_file_chooser_get_preview_filename( file_chooser ); 1555 1556 if( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( pobjFP->m_pToggles[PREVIEW] ) ) && g_file_test( filename, G_FILE_TEST_IS_REGULAR ) ) 1557 { 1558 pixbuf = gdk_pixbuf_new_from_file_at_size( 1559 filename, 1560 pobjFP->m_PreviewImageWidth, 1561 pobjFP->m_PreviewImageHeight, NULL ); 1562 1563 have_preview = ( pixbuf != NULL ); 1564 1565 gtk_image_set_from_pixbuf( GTK_IMAGE( preview ), pixbuf ); 1566 if( pixbuf ) 1567 gdk_pixbuf_unref( pixbuf ); 1568 1569 } 1570 1571 gtk_file_chooser_set_preview_widget_active( file_chooser, have_preview ); 1572 1573 if( filename ) 1574 g_free( filename ); 1575 } 1576 1577 sal_Bool SAL_CALL SalGtkFilePicker::setShowState( sal_Bool bShowState ) throw( uno::RuntimeException ) 1578 { 1579 OSL_ASSERT( m_pDialog != NULL ); 1580 1581 // TODO return m_pImpl->setShowState( bShowState ); 1582 if( bShowState != mbPreviewState ) 1583 { 1584 GdkThreadLock aLock; 1585 1586 if( bShowState ) 1587 { 1588 // Show 1589 if( !mHID_Preview ) 1590 { 1591 mHID_Preview = g_signal_connect( 1592 GTK_FILE_CHOOSER( m_pDialog ), "update-preview", 1593 G_CALLBACK( update_preview_cb ), ( gpointer )this ); 1594 } 1595 gtk_widget_show( m_pPreview ); 1596 } 1597 else 1598 { 1599 // Hide 1600 gtk_widget_hide( m_pPreview ); 1601 } 1602 1603 // also emit the signal 1604 g_signal_emit_by_name( GTK_OBJECT( m_pDialog ), "update-preview" ); 1605 1606 mbPreviewState = bShowState; 1607 } 1608 return true; 1609 } 1610 1611 sal_Bool SAL_CALL SalGtkFilePicker::getShowState() throw( uno::RuntimeException ) 1612 { 1613 OSL_ASSERT( m_pDialog != NULL ); 1614 1615 return mbPreviewState; 1616 } 1617 1618 //------------------------------------------------------------------------------------ 1619 // XInitialization 1620 //------------------------------------------------------------------------------------ 1621 1622 void SAL_CALL SalGtkFilePicker::initialize( const uno::Sequence<uno::Any>& aArguments ) 1623 throw( uno::Exception, uno::RuntimeException ) 1624 { 1625 // parameter checking 1626 uno::Any aAny; 1627 if( 0 == aArguments.getLength() ) 1628 throw lang::IllegalArgumentException( 1629 rtl::OUString::createFromAscii( "no arguments" ), 1630 static_cast<XFilePicker2*>( this ), 1 ); 1631 1632 aAny = aArguments[0]; 1633 1634 if( ( aAny.getValueType() != ::getCppuType( ( sal_Int16* )0 ) ) && 1635 (aAny.getValueType() != ::getCppuType( ( sal_Int8* )0 ) ) ) 1636 throw lang::IllegalArgumentException( 1637 rtl::OUString::createFromAscii( "invalid argument type" ), 1638 static_cast<XFilePicker2*>( this ), 1 ); 1639 1640 sal_Int16 templateId = -1; 1641 aAny >>= templateId; 1642 1643 GtkFileChooserAction eAction = GTK_FILE_CHOOSER_ACTION_OPEN; 1644 const gchar *first_button_text = GTK_STOCK_OPEN; 1645 1646 1647 // TODO: extract full semantic from 1648 // svtools/source/filepicker/filepicker.cxx (getWinBits) 1649 switch( templateId ) 1650 { 1651 case FILEOPEN_SIMPLE: 1652 eAction = GTK_FILE_CHOOSER_ACTION_OPEN; 1653 first_button_text = GTK_STOCK_OPEN; 1654 OSL_TRACE( "3all true\n" ); 1655 break; 1656 case FILESAVE_SIMPLE: 1657 eAction = GTK_FILE_CHOOSER_ACTION_SAVE; 1658 first_button_text = GTK_STOCK_SAVE; 1659 OSL_TRACE( "2all true\n" ); 1660 break; 1661 case FILESAVE_AUTOEXTENSION_PASSWORD: 1662 eAction = GTK_FILE_CHOOSER_ACTION_SAVE; 1663 first_button_text = GTK_STOCK_SAVE; 1664 mbToggleVisibility[PASSWORD] = true; 1665 OSL_TRACE( "1all true\n" ); 1666 // TODO 1667 break; 1668 case FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS: 1669 eAction = GTK_FILE_CHOOSER_ACTION_SAVE; 1670 first_button_text = GTK_STOCK_SAVE; 1671 mbToggleVisibility[PASSWORD] = true; 1672 mbToggleVisibility[FILTEROPTIONS] = true; 1673 OSL_TRACE( "4all true\n" ); 1674 // TODO 1675 break; 1676 case FILESAVE_AUTOEXTENSION_SELECTION: 1677 eAction = GTK_FILE_CHOOSER_ACTION_SAVE; // SELECT_FOLDER ? 1678 first_button_text = GTK_STOCK_SAVE; 1679 mbToggleVisibility[SELECTION] = true; 1680 OSL_TRACE( "5all true\n" ); 1681 // TODO 1682 break; 1683 case FILESAVE_AUTOEXTENSION_TEMPLATE: 1684 eAction = GTK_FILE_CHOOSER_ACTION_SAVE; 1685 first_button_text = GTK_STOCK_SAVE; 1686 mbListVisibility[TEMPLATE] = true; 1687 OSL_TRACE( "6all true\n" ); 1688 // TODO 1689 break; 1690 case FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE: 1691 eAction = GTK_FILE_CHOOSER_ACTION_OPEN; 1692 first_button_text = GTK_STOCK_OPEN; 1693 mbToggleVisibility[LINK] = true; 1694 mbToggleVisibility[PREVIEW] = true; 1695 mbListVisibility[IMAGE_TEMPLATE] = true; 1696 // TODO 1697 break; 1698 case FILEOPEN_PLAY: 1699 eAction = GTK_FILE_CHOOSER_ACTION_OPEN; 1700 first_button_text = GTK_STOCK_OPEN; 1701 mbButtonVisibility[PLAY] = true; 1702 // TODO 1703 break; 1704 case FILEOPEN_READONLY_VERSION: 1705 eAction = GTK_FILE_CHOOSER_ACTION_OPEN; 1706 first_button_text = GTK_STOCK_OPEN; 1707 mbToggleVisibility[READONLY] = true; 1708 mbListVisibility[VERSION] = true; 1709 break; 1710 case FILEOPEN_LINK_PREVIEW: 1711 eAction = GTK_FILE_CHOOSER_ACTION_OPEN; 1712 first_button_text = GTK_STOCK_OPEN; 1713 mbToggleVisibility[LINK] = true; 1714 mbToggleVisibility[PREVIEW] = true; 1715 // TODO 1716 break; 1717 case FILESAVE_AUTOEXTENSION: 1718 eAction = GTK_FILE_CHOOSER_ACTION_SAVE; 1719 first_button_text = GTK_STOCK_SAVE; 1720 OSL_TRACE( "7all true\n" ); 1721 // TODO 1722 break; 1723 default: 1724 throw lang::IllegalArgumentException( 1725 rtl::OUString::createFromAscii( "Unknown template" ), 1726 static_cast< XFilePicker2* >( this ), 1727 1 ); 1728 } 1729 1730 GdkThreadLock aLock; 1731 1732 if( GTK_FILE_CHOOSER_ACTION_SAVE == eAction ) 1733 { 1734 CResourceProvider aResProvider; 1735 OUString aFilePickerTitle(aResProvider.getResString( FILE_PICKER_TITLE_SAVE )); 1736 gtk_window_set_title ( GTK_WINDOW( m_pDialog ), 1737 OUStringToOString( aFilePickerTitle, RTL_TEXTENCODING_UTF8 ).getStr() ); 1738 } 1739 1740 gtk_file_chooser_set_action( GTK_FILE_CHOOSER( m_pDialog ), eAction); 1741 dialog_remove_buttons( GTK_DIALOG( m_pDialog ) ); 1742 gtk_dialog_add_button( GTK_DIALOG( m_pDialog ), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL ); 1743 for( int nTVIndex = 0; nTVIndex < BUTTON_LAST; nTVIndex++ ) 1744 { 1745 if( mbButtonVisibility[nTVIndex] ) 1746 { 1747 #ifdef GTK_STOCK_MEDIA_PLAY 1748 m_pButtons[ nTVIndex ] = gtk_dialog_add_button( GTK_DIALOG( m_pDialog ), GTK_STOCK_MEDIA_PLAY, 1 ); 1749 #else 1750 CResourceProvider aResProvider; 1751 OString aPlay = OUStringToOString( aResProvider.getResString( PUSHBUTTON_PLAY ), RTL_TEXTENCODING_UTF8 ); 1752 m_pButtons[ nTVIndex ] = gtk_dialog_add_button( GTK_DIALOG( m_pDialog ), aPlay.getStr(), 1 ); 1753 #endif 1754 } 1755 } 1756 gtk_dialog_add_button( GTK_DIALOG( m_pDialog ), first_button_text, GTK_RESPONSE_ACCEPT ); 1757 1758 gtk_dialog_set_default_response( GTK_DIALOG (m_pDialog), GTK_RESPONSE_ACCEPT ); 1759 1760 // Setup special flags 1761 for( int nTVIndex = 0; nTVIndex < TOGGLE_LAST; nTVIndex++ ) 1762 { 1763 if( mbToggleVisibility[nTVIndex] ) 1764 gtk_widget_show( m_pToggles[ nTVIndex ] ); 1765 } 1766 1767 for( int nTVIndex = 0; nTVIndex < LIST_LAST; nTVIndex++ ) 1768 { 1769 if( mbListVisibility[nTVIndex] ) 1770 { 1771 gtk_widget_set_sensitive( m_pLists[ nTVIndex ], false ); 1772 gtk_widget_show( m_pLists[ nTVIndex ] ); 1773 gtk_widget_show( m_pListLabels[ nTVIndex ] ); 1774 gtk_widget_show( m_pAligns[ nTVIndex ] ); 1775 gtk_widget_show( m_pHBoxs[ nTVIndex ] ); 1776 } 1777 } 1778 } 1779 1780 void SalGtkFilePicker::preview_toggled_cb( GtkObject *cb, SalGtkFilePicker* pobjFP ) 1781 { 1782 if( pobjFP->mbToggleVisibility[PREVIEW] ) 1783 pobjFP->setShowState( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( cb ) ) ); 1784 } 1785 1786 //------------------------------------------------------------------------------------ 1787 // XCancellable 1788 //------------------------------------------------------------------------------------ 1789 1790 void SAL_CALL SalGtkFilePicker::cancel() throw( uno::RuntimeException ) 1791 { 1792 OSL_ASSERT( m_pDialog != NULL ); 1793 1794 // TODO m_pImpl->cancel(); 1795 } 1796 1797 // ------------------------------------------------- 1798 // XServiceInfo 1799 // ------------------------------------------------- 1800 1801 rtl::OUString SAL_CALL SalGtkFilePicker::getImplementationName() 1802 throw( uno::RuntimeException ) 1803 { 1804 return rtl::OUString::createFromAscii( FILE_PICKER_IMPL_NAME ); 1805 } 1806 1807 // ------------------------------------------------- 1808 // XServiceInfo 1809 // ------------------------------------------------- 1810 1811 sal_Bool SAL_CALL SalGtkFilePicker::supportsService( const rtl::OUString& ServiceName ) 1812 throw( uno::RuntimeException ) 1813 { 1814 uno::Sequence <rtl::OUString> SupportedServicesNames = FilePicker_getSupportedServiceNames(); 1815 1816 for( sal_Int32 n = SupportedServicesNames.getLength(); n--; ) 1817 if( SupportedServicesNames[n].compareTo( ServiceName ) == 0) 1818 return sal_True; 1819 1820 return sal_False; 1821 } 1822 1823 // ------------------------------------------------- 1824 // XServiceInfo 1825 // ------------------------------------------------- 1826 1827 uno::Sequence<rtl::OUString> SAL_CALL SalGtkFilePicker::getSupportedServiceNames() 1828 throw( uno::RuntimeException ) 1829 { 1830 return FilePicker_getSupportedServiceNames(); 1831 } 1832 1833 1834 //-------------------------------------------------- 1835 // Misc 1836 //------------------------------------------------- 1837 void SalGtkFilePicker::SetCurFilter( const OUString& rFilter ) 1838 { 1839 GdkThreadLock aLock; 1840 1841 // Get all the filters already added 1842 GSList *filters = gtk_file_chooser_list_filters ( GTK_FILE_CHOOSER( m_pDialog ) ); 1843 bool bFound = false; 1844 1845 for( GSList *iter = filters; !bFound && iter; iter = iter->next ) 1846 { 1847 GtkFileFilter* pFilter = reinterpret_cast<GtkFileFilter *>( iter->data ); 1848 G_CONST_RETURN gchar * filtername = gtk_file_filter_get_name( pFilter ); 1849 OUString sFilterName( filtername, strlen( filtername ), RTL_TEXTENCODING_UTF8 ); 1850 1851 OUString aShrunkName = shrinkFilterName( rFilter ); 1852 if( aShrunkName.equals( sFilterName) ) 1853 { 1854 OSL_TRACE( "actually setting %s\n", filtername ); 1855 gtk_file_chooser_set_filter( GTK_FILE_CHOOSER( m_pDialog ), pFilter ); 1856 bFound = true; 1857 } 1858 } 1859 1860 g_slist_free( filters ); 1861 } 1862 1863 extern "C" 1864 { 1865 static gboolean 1866 case_insensitive_filter (const GtkFileFilterInfo *filter_info, gpointer data) 1867 { 1868 gboolean bRetval = sal_False; 1869 const char *pFilter = (const char *) data; 1870 1871 g_return_val_if_fail( data != NULL, sal_False ); 1872 g_return_val_if_fail( filter_info != NULL, sal_False ); 1873 1874 if( !filter_info->uri ) 1875 return sal_False; 1876 1877 const char *pExtn = strrchr( filter_info->uri, '.' ); 1878 if( !pExtn ) 1879 return sal_False; 1880 pExtn++; 1881 1882 if( !g_ascii_strcasecmp( pFilter, pExtn ) ) 1883 bRetval = sal_True; 1884 1885 #ifdef DEBUG 1886 fprintf( stderr, "'%s' match extn '%s' vs '%s' yeilds %d\n", 1887 filter_info->uri, pExtn, pFilter, bRetval ); 1888 #endif 1889 1890 return bRetval; 1891 } 1892 } 1893 1894 int SalGtkFilePicker::implAddFilter( const OUString& rFilter, const OUString& rType ) 1895 { 1896 GdkThreadLock aLock; 1897 1898 GtkFileFilter *filter = gtk_file_filter_new(); 1899 1900 OUString aShrunkName = shrinkFilterName( rFilter ); 1901 OString aFilterName = rtl::OUStringToOString( aShrunkName, RTL_TEXTENCODING_UTF8 ); 1902 gtk_file_filter_set_name( filter, aFilterName ); 1903 1904 static const OUString aStarDot = OUString::createFromAscii( "*." ); 1905 OUString aTokens; 1906 1907 bool bAllGlob = !rType.compareToAscii( "*.*" ) || !rType.compareToAscii( "*" ); 1908 if (bAllGlob) 1909 gtk_file_filter_add_pattern( filter, "*" ); 1910 else 1911 { 1912 sal_Int32 nIndex = 0; 1913 rtl::OUString aToken; 1914 do 1915 { 1916 aToken = rType.getToken( 0, ';', nIndex ); 1917 // Assume all have the "*.<extn>" syntax 1918 aToken = aToken.copy( aToken.lastIndexOf( aStarDot ) + 2 ); 1919 if (aToken.getLength()) 1920 { 1921 if (aTokens.getLength()) 1922 aTokens += OUString::createFromAscii(","); 1923 aTokens = aTokens += aToken; 1924 gtk_file_filter_add_custom (filter, GTK_FILE_FILTER_URI, 1925 case_insensitive_filter, 1926 g_strdup( rtl::OUStringToOString( aToken, RTL_TEXTENCODING_UTF8 ) ), 1927 (GDestroyNotify) g_free ); 1928 1929 OSL_TRACE( "fustering with %s\n", rtl::OUStringToOString( aToken, RTL_TEXTENCODING_UTF8 ).getStr()); 1930 } 1931 #ifdef DEBUG 1932 else 1933 { 1934 g_warning( "Duff filter token '%s'\n", 1935 (const sal_Char *) rtl::OUStringToOString( 1936 rType.getToken( 0, ';', nIndex ), RTL_TEXTENCODING_UTF8 ) ); 1937 } 1938 #endif 1939 } 1940 while( nIndex >= 0 ); 1941 } 1942 1943 gtk_file_chooser_add_filter( GTK_FILE_CHOOSER( m_pDialog ), filter ); 1944 1945 int nAdded = 0; 1946 if (!bAllGlob) 1947 { 1948 GtkTreeIter iter; 1949 gtk_list_store_append (m_pFilterStore, &iter); 1950 gtk_list_store_set (m_pFilterStore, &iter, 1951 0, OUStringToOString(shrinkFilterName( rFilter, true ), RTL_TEXTENCODING_UTF8).getStr(), 1952 1, OUStringToOString(aTokens, RTL_TEXTENCODING_UTF8).getStr(), 1953 2, aFilterName.getStr(), 1954 3, OUStringToOString(rType, RTL_TEXTENCODING_UTF8).getStr(), 1955 -1); 1956 nAdded = 1; 1957 } 1958 return nAdded; 1959 } 1960 1961 int SalGtkFilePicker::implAddFilterGroup( const OUString& /*_rFilter*/, const Sequence< StringPair >& _rFilters ) 1962 { 1963 // Gtk+ has no filter group concept I think so ... 1964 // implAddFilter( _rFilter, String() ); 1965 int nAdded = 0; 1966 const StringPair* pSubFilters = _rFilters.getConstArray(); 1967 const StringPair* pSubFiltersEnd = pSubFilters + _rFilters.getLength(); 1968 for( ; pSubFilters != pSubFiltersEnd; ++pSubFilters ) 1969 nAdded += implAddFilter( pSubFilters->First, pSubFilters->Second ); 1970 return nAdded; 1971 } 1972 1973 void SalGtkFilePicker::SetFilters() 1974 { 1975 OSL_TRACE( "start setting filters\n"); 1976 1977 GdkThreadLock aLock; 1978 1979 int nAdded = 0; 1980 if( m_pFilterList && !m_pFilterList->empty() ) 1981 { 1982 for ( FilterList::iterator aListIter = m_pFilterList->begin(); 1983 aListIter != m_pFilterList->end(); 1984 ++aListIter 1985 ) 1986 { 1987 if( aListIter->hasSubFilters() ) 1988 { // it's a filter group 1989 1990 UnoFilterList aSubFilters; 1991 aListIter->getSubFilters( aSubFilters ); 1992 1993 nAdded += implAddFilterGroup( aListIter->getTitle(), aSubFilters ); 1994 } 1995 else 1996 { 1997 // it's a single filter 1998 1999 nAdded += implAddFilter( aListIter->getTitle(), aListIter->getFilter() ); 2000 } 2001 } 2002 } 2003 2004 if (nAdded) 2005 gtk_widget_show( m_pFilterExpander ); 2006 else 2007 gtk_widget_hide( m_pFilterExpander ); 2008 2009 // set the default filter 2010 if( m_aCurrentFilter && (m_aCurrentFilter.getLength() > 0) ) 2011 { 2012 OSL_TRACE( "Setting current filter to %s\n", 2013 OUStringToOString( m_aCurrentFilter, RTL_TEXTENCODING_UTF8 ).getStr() ); 2014 2015 SetCurFilter( m_aCurrentFilter ); 2016 } 2017 2018 OSL_TRACE( "end setting filters\n"); 2019 } 2020 2021 SalGtkFilePicker::~SalGtkFilePicker() 2022 { 2023 int i; 2024 2025 for( i = 0; i < TOGGLE_LAST; i++ ) 2026 gtk_widget_destroy( m_pToggles[i] ); 2027 2028 for( i = 0; i < LIST_LAST; i++ ) 2029 { 2030 gtk_widget_destroy( m_pListLabels[i] ); 2031 gtk_widget_destroy( m_pAligns[i] ); //m_pAligns[i] owns m_pLists[i] 2032 gtk_widget_destroy( m_pHBoxs[i] ); 2033 } 2034 2035 delete m_pFilterList; 2036 2037 gtk_widget_destroy( m_pVBox ); 2038 } 2039 2040 /* vi:set tabstop=4 shiftwidth=4 expandtab: */ 2041