merge the formfield patch from ooo-build
[ooovba.git] / sfx2 / source / appl / sfxpicklist.cxx
blobb96a5e7d03f4e0c9e50869f1d28251c10de63220
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: sfxpicklist.cxx,v $
10 * $Revision: 1.34 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sfx2.hxx"
34 #include <com/sun/star/document/XDocumentProperties.hpp>
35 #include <svtools/historyoptions.hxx>
36 #include <svtools/useroptions.hxx>
37 #include <tools/urlobj.hxx>
38 #include <framework/menuconfiguration.hxx>
39 #include <svtools/inethist.hxx>
40 #include <svtools/stritem.hxx>
41 #include <svtools/eitem.hxx>
42 #include <osl/file.hxx>
43 #include <unotools/localfilehelper.hxx>
44 #include <cppuhelper/implbase1.hxx>
46 // ----------------------------------------------------------------------------
48 #include <sfx2/app.hxx>
49 #include "sfxpicklist.hxx"
50 #include <sfx2/sfxuno.hxx>
51 #include "sfxtypes.hxx"
52 #include <sfx2/request.hxx>
53 #include <sfx2/sfxsids.hrc>
54 #include <sfx2/sfx.hrc>
55 #include <sfx2/event.hxx>
56 #include <sfx2/objsh.hxx>
57 #include <sfx2/bindings.hxx>
58 #include "referers.hxx"
59 #include <sfx2/docfile.hxx>
60 #include "objshimp.hxx"
61 #include <sfx2/docfilt.hxx>
63 #include <algorithm>
65 // ----------------------------------------------------------------------------
67 using namespace ::com::sun::star::uno;
68 using namespace ::com::sun::star::beans;
69 using namespace ::com::sun::star::util;
71 // ----------------------------------------------------------------------------
73 osl::Mutex* SfxPickList::pMutex = 0;
74 SfxPickList* SfxPickList::pUniqueInstance = 0;
76 // ----------------------------------------------------------------------------
78 class StringLength : public ::cppu::WeakImplHelper1< XStringWidth >
80 public:
81 StringLength() {}
82 virtual ~StringLength() {}
84 // XStringWidth
85 sal_Int32 SAL_CALL queryStringWidth( const ::rtl::OUString& aString )
86 throw (::com::sun::star::uno::RuntimeException)
88 return aString.getLength();
92 // ----------------------------------------------------------------------------
94 osl::Mutex* SfxPickList::GetOrCreateMutex()
96 if ( !pMutex )
98 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
99 if ( !pMutex )
100 pMutex = new osl::Mutex;
103 return pMutex;
106 void SfxPickList::CreatePicklistMenuTitle( Menu* pMenu, USHORT nItemId, const String& aURLString, sal_uInt32 nNo )
108 String aPickEntry;
110 if ( nNo < 9 )
112 aPickEntry += '~';
113 aPickEntry += String::CreateFromInt32( nNo + 1 );
115 else if ( nNo == 9 )
116 aPickEntry += DEFINE_CONST_UNICODE("1~0");
117 else
118 aPickEntry += String::CreateFromInt32( nNo + 1 );
119 aPickEntry += DEFINE_CONST_UNICODE(": ");
121 INetURLObject aURL( aURLString );
122 rtl::OUString aTipHelpText;
123 rtl::OUString aAccessibleName( aPickEntry );
125 if ( aURL.GetProtocol() == INET_PROT_FILE )
127 // Do handle file URL differently => convert it to a system
128 // path and abbreviate it with a special function:
129 String aFileSystemPath( aURL.getFSysPath( INetURLObject::FSYS_DETECT ) );
131 // ::utl::LocalFileHelper::ConvertURLToPhysicalName( aURLString, aPhysicalName );
133 ::rtl::OUString aSystemPath( aFileSystemPath );
134 ::rtl::OUString aCompactedSystemPath;
136 aTipHelpText = aSystemPath;
137 aAccessibleName += aSystemPath;
138 oslFileError nError = osl_abbreviateSystemPath( aSystemPath.pData, &aCompactedSystemPath.pData, 46, NULL );
139 if ( !nError )
140 aPickEntry += String( aCompactedSystemPath );
141 else
142 aPickEntry += aFileSystemPath;
144 if ( aPickEntry.Len() > 50 )
146 aPickEntry.Erase( 47 );
147 aPickEntry += DEFINE_CONST_UNICODE("...");
150 else
152 // Use INetURLObject to abbreviate all other URLs
153 String aShortURL;
154 aShortURL = aURL.getAbbreviated( m_xStringLength, 46, INetURLObject::DECODE_UNAMBIGUOUS );
155 aPickEntry += aShortURL;
156 aTipHelpText = aURLString;
157 aAccessibleName += aURLString;
160 // Set menu item text, tip help and accessible name
161 pMenu->SetItemText( nItemId, aPickEntry );
162 pMenu->SetTipHelpText( nItemId, aTipHelpText );
163 pMenu->SetAccessibleName( nItemId, aAccessibleName );
166 void SfxPickList::RemovePickListEntries()
168 ::osl::MutexGuard aGuard( GetOrCreateMutex() );
169 for ( sal_uInt32 i = 0; i < m_aPicklistVector.size(); i++ )
170 delete m_aPicklistVector[i];
171 m_aPicklistVector.clear();
174 SfxPickList::PickListEntry* SfxPickList::GetPickListEntry( sal_uInt32 nIndex )
176 OSL_ASSERT( m_aPicklistVector.size() > nIndex );
178 if ( nIndex < m_aPicklistVector.size() )
179 return m_aPicklistVector[ nIndex ];
180 else
181 return 0;
184 SfxPickList* SfxPickList::GetOrCreate( const sal_uInt32 nMenuSize )
186 if ( !pUniqueInstance )
188 ::osl::MutexGuard aGuard( GetOrCreateMutex() );
189 if ( !pUniqueInstance )
190 pUniqueInstance = new SfxPickList( nMenuSize );
193 return pUniqueInstance;
196 SfxPickList* SfxPickList::Get()
198 ::osl::MutexGuard aGuard( GetOrCreateMutex() );
199 return pUniqueInstance;
202 void SfxPickList::Delete()
204 ::osl::MutexGuard aGuard( GetOrCreateMutex() );
205 DELETEZ( pUniqueInstance );
208 SfxPickList::SfxPickList( sal_uInt32 nAllowedMenuSize ) :
209 m_nAllowedMenuSize( nAllowedMenuSize )
211 m_xStringLength = new StringLength;
212 m_nAllowedMenuSize = ::std::min( m_nAllowedMenuSize, (sal_uInt32)PICKLIST_MAXSIZE );
213 StartListening( *SFX_APP() );
216 SfxPickList::~SfxPickList()
218 RemovePickListEntries();
221 void SfxPickList::CreatePickListEntries()
223 RemovePickListEntries();
225 // Einlesen der Pickliste
226 Sequence< Sequence< PropertyValue > > seqPicklist = SvtHistoryOptions().GetList( ePICKLIST );
228 sal_uInt32 nCount = seqPicklist.getLength();
229 sal_uInt32 nEntries = ::std::min( m_nAllowedMenuSize, nCount );
231 for( sal_uInt32 nItem=0; nItem < nEntries; ++nItem )
233 Sequence< PropertyValue > seqPropertySet = seqPicklist[ nItem ];
235 INetURLObject aURL;
236 ::rtl::OUString sURL;
237 ::rtl::OUString sFilter;
238 ::rtl::OUString sTitle;
239 ::rtl::OUString sPassword;
241 sal_uInt32 nPropertyCount = seqPropertySet.getLength();
242 for( sal_uInt32 nProperty=0; nProperty<nPropertyCount; ++nProperty )
244 if( seqPropertySet[nProperty].Name == HISTORY_PROPERTYNAME_URL )
246 seqPropertySet[nProperty].Value >>= sURL;
248 else if( seqPropertySet[nProperty].Name == HISTORY_PROPERTYNAME_FILTER )
250 seqPropertySet[nProperty].Value >>= sFilter;
252 else if( seqPropertySet[nProperty].Name == HISTORY_PROPERTYNAME_TITLE )
254 seqPropertySet[nProperty].Value >>= sTitle;
256 else if( seqPropertySet[nProperty].Name == HISTORY_PROPERTYNAME_PASSWORD )
258 seqPropertySet[nProperty].Value >>= sPassword;
262 aURL.SetSmartURL( sURL );
263 aURL.SetPass( SfxStringDecode( sPassword ) );
265 PickListEntry *pPick = new PickListEntry( aURL.GetMainURL( INetURLObject::NO_DECODE ), sFilter, sTitle );
266 m_aPicklistVector.push_back( pPick );
270 void SfxPickList::CreateMenuEntries( Menu* pMenu )
272 static sal_Bool bPickListMenuInitializing = sal_False;
274 ::osl::MutexGuard aGuard( GetOrCreateMutex() );
276 if ( bPickListMenuInitializing ) // method is not reentrant!
277 return;
279 bPickListMenuInitializing = sal_True;
280 CreatePickListEntries();
282 for ( sal_uInt16 nId = START_ITEMID_PICKLIST; nId <= END_ITEMID_PICKLIST; ++nId )
283 pMenu->RemoveItem( pMenu->GetItemPos( nId ) );
285 if ( pMenu->GetItemType( pMenu->GetItemCount()-1 ) == MENUITEM_SEPARATOR )
286 pMenu->RemoveItem( pMenu->GetItemCount()-1 );
288 if ( m_aPicklistVector.size() > 0 &&
289 pMenu->GetItemType( pMenu->GetItemCount()-1 )
290 != MENUITEM_SEPARATOR && m_nAllowedMenuSize )
291 pMenu->InsertSeparator();
293 rtl::OUString aEmptyString;
294 for ( sal_uInt32 i = 0; i < m_aPicklistVector.size(); i++ )
296 PickListEntry* pEntry = GetPickListEntry( i );
298 pMenu->InsertItem( (USHORT)(START_ITEMID_PICKLIST + i), aEmptyString );
299 CreatePicklistMenuTitle( pMenu, (USHORT)(START_ITEMID_PICKLIST + i), pEntry->aName, i );
302 bPickListMenuInitializing = sal_False;
305 void SfxPickList::ExecuteEntry( sal_uInt32 nIndex )
307 ::osl::ClearableMutexGuard aGuard( GetOrCreateMutex() );
309 PickListEntry *pPick = SfxPickList::Get()->GetPickListEntry( nIndex );
311 if ( pPick )
313 SfxRequest aReq( SID_OPENDOC, SFX_CALLMODE_ASYNCHRON, SFX_APP()->GetPool() );
314 aReq.AppendItem( SfxStringItem( SID_FILE_NAME, pPick->aName ));
315 aReq.AppendItem( SfxStringItem( SID_REFERER, DEFINE_CONST_UNICODE( SFX_REFERER_USER ) ) );
316 aReq.AppendItem( SfxStringItem( SID_TARGETNAME, DEFINE_CONST_UNICODE("_default") ) );
317 String aFilter( pPick->aFilter );
318 aGuard.clear();
320 USHORT nPos=aFilter.Search('|');
321 if( nPos != STRING_NOTFOUND )
323 String aOptions(aFilter.Copy( nPos ).GetBuffer()+1);
324 aFilter.Erase( nPos );
325 aReq.AppendItem( SfxStringItem(SID_FILE_FILTEROPTIONS, aOptions));
328 aReq.AppendItem(SfxStringItem( SID_FILTER_NAME, aFilter ));
329 aReq.AppendItem( SfxBoolItem( SID_TEMPLATE, sal_False ) );
330 SFX_APP()->ExecuteSlot( aReq );
334 void SfxPickList::ExecuteMenuEntry( USHORT nId )
336 ExecuteEntry( (sal_uInt32)( nId - START_ITEMID_PICKLIST ) );
339 String SfxPickList::GetMenuEntryTitle( sal_uInt32 nIndex )
341 PickListEntry *pPick = SfxPickList::Get()->GetPickListEntry( nIndex );
343 if ( pPick )
344 return pPick->aTitle;
345 else
346 return String();
349 void SfxPickList::Notify( SfxBroadcaster&, const SfxHint& rHint )
351 if ( rHint.IsA( TYPE( SfxStringHint )))
353 SfxStringHint* pStringHint = (SfxStringHint*) &rHint;
355 if ( pStringHint->GetId() == SID_OPENURL )
356 INetURLHistory::GetOrCreate()->PutUrl( INetURLObject( pStringHint->GetObject() ));
359 if ( rHint.IsA( TYPE( SfxEventHint )))
361 SfxEventHint* pEventHint = PTR_CAST(SfxEventHint,&rHint);
362 // nur ObjectShell-bezogene Events mit Medium interessieren
363 SfxObjectShell* pDocSh = pEventHint->GetObjShell();
364 if( !pDocSh )
365 return;
367 switch ( pEventHint->GetEventId() )
369 case SFX_EVENT_CREATEDOC:
371 sal_Bool bAllowModif = pDocSh->IsEnableSetModified();
372 if ( bAllowModif )
373 pDocSh->EnableSetModified( sal_False );
375 using namespace ::com::sun::star;
376 uno::Reference<document::XDocumentProperties> xDocProps(
377 pDocSh->getDocProperties());
378 if (xDocProps.is()) {
379 xDocProps->setAuthor( SvtUserOptions().GetFullName() );
380 ::DateTime now;
381 xDocProps->setCreationDate( util::DateTime(
382 now.Get100Sec(), now.GetSec(), now.GetMin(),
383 now.GetHour(), now.GetDay(), now.GetMonth(),
384 now.GetYear() ) );
387 if ( bAllowModif )
388 pDocSh->EnableSetModified( bAllowModif );
390 break;
392 case SFX_EVENT_OPENDOC:
394 SfxMedium *pMed = pDocSh->GetMedium();
395 if( !pMed )
396 return;
398 // unbenannt-Docs und embedded-Docs nicht in History
399 if ( !pDocSh->HasName() ||
400 SFX_CREATE_MODE_STANDARD != pDocSh->GetCreateMode() )
401 return;
403 // Hilfe nicht in History
404 INetURLObject aURL( pDocSh->IsDocShared() ? pDocSh->GetSharedFileURL() : ::rtl::OUString( pMed->GetOrigURL() ) );
405 if ( aURL.GetProtocol() == INET_PROT_VND_SUN_STAR_HELP )
406 return;
408 ::rtl::OUString aTitle = pDocSh->GetTitle(SFX_TITLE_PICKLIST);
409 ::rtl::OUString aFilter;
410 const SfxFilter* pFilter = pMed->GetOrigFilter();
411 if ( pFilter )
412 aFilter = pFilter->GetFilterName();
414 // add to svtool history options
415 SvtHistoryOptions().AppendItem( eHISTORY,
416 aURL.GetURLNoPass( INetURLObject::NO_DECODE ),
417 aFilter,
418 aTitle,
419 SfxStringEncode( aURL.GetPass() ) );
421 break;
423 case SFX_EVENT_CLOSEDOC:
425 SfxMedium *pMed = pDocSh->GetMedium();
426 if( !pMed )
427 return;
429 // unbenannt-Docs und embedded-Docs nicht in Pickliste
430 if ( !pDocSh->HasName() ||
431 SFX_CREATE_MODE_STANDARD != pDocSh->GetCreateMode() )
432 return;
434 // Hilfe nicht in History
435 INetURLObject aURL( pDocSh->IsDocShared() ? pDocSh->GetSharedFileURL() : ::rtl::OUString( pMed->GetOrigURL() ) );
436 if ( aURL.GetProtocol() == INET_PROT_VND_SUN_STAR_HELP )
437 return;
439 // only add r/w document into picklist
440 if ( pDocSh->IsReadOnly() || !pMed->IsUpdatePickList() )
441 return;
443 // add no document that forbids this (for example Message-Body)
444 SFX_ITEMSET_ARG( pMed->GetItemSet(), pPicklistItem, SfxBoolItem, SID_PICKLIST, sal_False );
445 if (
446 (pPicklistItem && !pPicklistItem->GetValue()) ||
447 (!(pDocSh->Get_Impl()->bWaitingForPicklist) )
449 return;
451 // ignore hidden documents
452 if ( !SfxViewFrame::GetFirst( pDocSh, 0, TRUE ) )
453 return;
455 ::rtl::OUString aTitle = pDocSh->GetTitle(SFX_TITLE_PICKLIST);
456 ::rtl::OUString aFilter;
457 const SfxFilter* pFilter = pMed->GetOrigFilter();
458 if ( pFilter )
459 aFilter = pFilter->GetFilterName();
461 // add to svtool history options
462 SvtHistoryOptions().AppendItem( ePICKLIST,
463 aURL.GetURLNoPass( INetURLObject::NO_DECODE ),
464 aFilter,
465 aTitle,
466 SfxStringEncode( aURL.GetPass() ) );
468 pDocSh->Get_Impl()->bWaitingForPicklist = sal_False;
470 if ( aURL.GetProtocol() == INET_PROT_FILE )
471 Application::AddToRecentDocumentList( aURL.GetURLNoPass( INetURLObject::NO_DECODE ), (pFilter) ? pFilter->GetMimeType() : String() );
473 break;