update dev300-m58
[ooovba.git] / sfx2 / source / appl / sfxpicklist.cxx
blobc571b921b83d4ee4c4f642ed67f0c9ba13c0152b
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 #include <shell/systemshell.hxx>
48 // ----------------------------------------------------------------------------
50 #include <sfx2/app.hxx>
51 #include "sfxpicklist.hxx"
52 #include <sfx2/sfxuno.hxx>
53 #include "sfxtypes.hxx"
54 #include <sfx2/request.hxx>
55 #include <sfx2/sfxsids.hrc>
56 #include <sfx2/sfx.hrc>
57 #include <sfx2/event.hxx>
58 #include <sfx2/objsh.hxx>
59 #include <sfx2/bindings.hxx>
60 #include "referers.hxx"
61 #include <sfx2/docfile.hxx>
62 #include "objshimp.hxx"
63 #include <sfx2/docfilt.hxx>
65 #include <algorithm>
67 // ----------------------------------------------------------------------------
69 using namespace ::com::sun::star::uno;
70 using namespace ::com::sun::star::beans;
71 using namespace ::com::sun::star::util;
73 // ----------------------------------------------------------------------------
75 osl::Mutex* SfxPickList::pMutex = 0;
76 SfxPickList* SfxPickList::pUniqueInstance = 0;
78 // ----------------------------------------------------------------------------
80 class StringLength : public ::cppu::WeakImplHelper1< XStringWidth >
82 public:
83 StringLength() {}
84 virtual ~StringLength() {}
86 // XStringWidth
87 sal_Int32 SAL_CALL queryStringWidth( const ::rtl::OUString& aString )
88 throw (::com::sun::star::uno::RuntimeException)
90 return aString.getLength();
94 // ----------------------------------------------------------------------------
96 osl::Mutex* SfxPickList::GetOrCreateMutex()
98 if ( !pMutex )
100 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
101 if ( !pMutex )
102 pMutex = new osl::Mutex;
105 return pMutex;
108 void SfxPickList::CreatePicklistMenuTitle( Menu* pMenu, USHORT nItemId, const String& aURLString, sal_uInt32 nNo )
110 String aPickEntry;
112 if ( nNo < 9 )
114 aPickEntry += '~';
115 aPickEntry += String::CreateFromInt32( nNo + 1 );
117 else if ( nNo == 9 )
118 aPickEntry += DEFINE_CONST_UNICODE("1~0");
119 else
120 aPickEntry += String::CreateFromInt32( nNo + 1 );
121 aPickEntry += DEFINE_CONST_UNICODE(": ");
123 INetURLObject aURL( aURLString );
124 rtl::OUString aTipHelpText;
125 rtl::OUString aAccessibleName( aPickEntry );
127 if ( aURL.GetProtocol() == INET_PROT_FILE )
129 // Do handle file URL differently => convert it to a system
130 // path and abbreviate it with a special function:
131 String aFileSystemPath( aURL.getFSysPath( INetURLObject::FSYS_DETECT ) );
133 // ::utl::LocalFileHelper::ConvertURLToPhysicalName( aURLString, aPhysicalName );
135 ::rtl::OUString aSystemPath( aFileSystemPath );
136 ::rtl::OUString aCompactedSystemPath;
138 aTipHelpText = aSystemPath;
139 aAccessibleName += aSystemPath;
140 oslFileError nError = osl_abbreviateSystemPath( aSystemPath.pData, &aCompactedSystemPath.pData, 46, NULL );
141 if ( !nError )
142 aPickEntry += String( aCompactedSystemPath );
143 else
144 aPickEntry += aFileSystemPath;
146 if ( aPickEntry.Len() > 50 )
148 aPickEntry.Erase( 47 );
149 aPickEntry += DEFINE_CONST_UNICODE("...");
152 else
154 // Use INetURLObject to abbreviate all other URLs
155 String aShortURL;
156 aShortURL = aURL.getAbbreviated( m_xStringLength, 46, INetURLObject::DECODE_UNAMBIGUOUS );
157 aPickEntry += aShortURL;
158 aTipHelpText = aURLString;
159 aAccessibleName += aURLString;
162 // Set menu item text, tip help and accessible name
163 pMenu->SetItemText( nItemId, aPickEntry );
164 pMenu->SetTipHelpText( nItemId, aTipHelpText );
165 pMenu->SetAccessibleName( nItemId, aAccessibleName );
168 void SfxPickList::RemovePickListEntries()
170 ::osl::MutexGuard aGuard( GetOrCreateMutex() );
171 for ( sal_uInt32 i = 0; i < m_aPicklistVector.size(); i++ )
172 delete m_aPicklistVector[i];
173 m_aPicklistVector.clear();
176 SfxPickList::PickListEntry* SfxPickList::GetPickListEntry( sal_uInt32 nIndex )
178 OSL_ASSERT( m_aPicklistVector.size() > nIndex );
180 if ( nIndex < m_aPicklistVector.size() )
181 return m_aPicklistVector[ nIndex ];
182 else
183 return 0;
186 SfxPickList* SfxPickList::GetOrCreate( const sal_uInt32 nMenuSize )
188 if ( !pUniqueInstance )
190 ::osl::MutexGuard aGuard( GetOrCreateMutex() );
191 if ( !pUniqueInstance )
192 pUniqueInstance = new SfxPickList( nMenuSize );
195 return pUniqueInstance;
198 SfxPickList* SfxPickList::Get()
200 ::osl::MutexGuard aGuard( GetOrCreateMutex() );
201 return pUniqueInstance;
204 void SfxPickList::Delete()
206 ::osl::MutexGuard aGuard( GetOrCreateMutex() );
207 DELETEZ( pUniqueInstance );
210 SfxPickList::SfxPickList( sal_uInt32 nAllowedMenuSize ) :
211 m_nAllowedMenuSize( nAllowedMenuSize )
213 m_xStringLength = new StringLength;
214 m_nAllowedMenuSize = ::std::min( m_nAllowedMenuSize, (sal_uInt32)PICKLIST_MAXSIZE );
215 StartListening( *SFX_APP() );
218 SfxPickList::~SfxPickList()
220 RemovePickListEntries();
223 void SfxPickList::CreatePickListEntries()
225 RemovePickListEntries();
227 // Einlesen der Pickliste
228 Sequence< Sequence< PropertyValue > > seqPicklist = SvtHistoryOptions().GetList( ePICKLIST );
230 sal_uInt32 nCount = seqPicklist.getLength();
231 sal_uInt32 nEntries = ::std::min( m_nAllowedMenuSize, nCount );
233 for( sal_uInt32 nItem=0; nItem < nEntries; ++nItem )
235 Sequence< PropertyValue > seqPropertySet = seqPicklist[ nItem ];
237 INetURLObject aURL;
238 ::rtl::OUString sURL;
239 ::rtl::OUString sFilter;
240 ::rtl::OUString sTitle;
241 ::rtl::OUString sPassword;
243 sal_uInt32 nPropertyCount = seqPropertySet.getLength();
244 for( sal_uInt32 nProperty=0; nProperty<nPropertyCount; ++nProperty )
246 if( seqPropertySet[nProperty].Name == HISTORY_PROPERTYNAME_URL )
248 seqPropertySet[nProperty].Value >>= sURL;
250 else if( seqPropertySet[nProperty].Name == HISTORY_PROPERTYNAME_FILTER )
252 seqPropertySet[nProperty].Value >>= sFilter;
254 else if( seqPropertySet[nProperty].Name == HISTORY_PROPERTYNAME_TITLE )
256 seqPropertySet[nProperty].Value >>= sTitle;
258 else if( seqPropertySet[nProperty].Name == HISTORY_PROPERTYNAME_PASSWORD )
260 seqPropertySet[nProperty].Value >>= sPassword;
264 aURL.SetSmartURL( sURL );
265 aURL.SetPass( SfxStringDecode( sPassword ) );
267 PickListEntry *pPick = new PickListEntry( aURL.GetMainURL( INetURLObject::NO_DECODE ), sFilter, sTitle );
268 m_aPicklistVector.push_back( pPick );
272 void SfxPickList::CreateMenuEntries( Menu* pMenu )
274 static sal_Bool bPickListMenuInitializing = sal_False;
276 ::osl::MutexGuard aGuard( GetOrCreateMutex() );
278 if ( bPickListMenuInitializing ) // method is not reentrant!
279 return;
281 bPickListMenuInitializing = sal_True;
282 CreatePickListEntries();
284 for ( sal_uInt16 nId = START_ITEMID_PICKLIST; nId <= END_ITEMID_PICKLIST; ++nId )
285 pMenu->RemoveItem( pMenu->GetItemPos( nId ) );
287 if ( pMenu->GetItemType( pMenu->GetItemCount()-1 ) == MENUITEM_SEPARATOR )
288 pMenu->RemoveItem( pMenu->GetItemCount()-1 );
290 if ( m_aPicklistVector.size() > 0 &&
291 pMenu->GetItemType( pMenu->GetItemCount()-1 )
292 != MENUITEM_SEPARATOR && m_nAllowedMenuSize )
293 pMenu->InsertSeparator();
295 rtl::OUString aEmptyString;
296 for ( sal_uInt32 i = 0; i < m_aPicklistVector.size(); i++ )
298 PickListEntry* pEntry = GetPickListEntry( i );
300 pMenu->InsertItem( (USHORT)(START_ITEMID_PICKLIST + i), aEmptyString );
301 CreatePicklistMenuTitle( pMenu, (USHORT)(START_ITEMID_PICKLIST + i), pEntry->aName, i );
304 bPickListMenuInitializing = sal_False;
307 void SfxPickList::ExecuteEntry( sal_uInt32 nIndex )
309 ::osl::ClearableMutexGuard aGuard( GetOrCreateMutex() );
311 PickListEntry *pPick = SfxPickList::Get()->GetPickListEntry( nIndex );
313 if ( pPick )
315 SfxRequest aReq( SID_OPENDOC, SFX_CALLMODE_ASYNCHRON, SFX_APP()->GetPool() );
316 aReq.AppendItem( SfxStringItem( SID_FILE_NAME, pPick->aName ));
317 aReq.AppendItem( SfxStringItem( SID_REFERER, DEFINE_CONST_UNICODE( SFX_REFERER_USER ) ) );
318 aReq.AppendItem( SfxStringItem( SID_TARGETNAME, DEFINE_CONST_UNICODE("_default") ) );
319 String aFilter( pPick->aFilter );
320 aGuard.clear();
322 USHORT nPos=aFilter.Search('|');
323 if( nPos != STRING_NOTFOUND )
325 String aOptions(aFilter.Copy( nPos ).GetBuffer()+1);
326 aFilter.Erase( nPos );
327 aReq.AppendItem( SfxStringItem(SID_FILE_FILTEROPTIONS, aOptions));
330 aReq.AppendItem(SfxStringItem( SID_FILTER_NAME, aFilter ));
331 aReq.AppendItem( SfxBoolItem( SID_TEMPLATE, sal_False ) );
332 SFX_APP()->ExecuteSlot( aReq );
336 void SfxPickList::ExecuteMenuEntry( USHORT nId )
338 ExecuteEntry( (sal_uInt32)( nId - START_ITEMID_PICKLIST ) );
341 String SfxPickList::GetMenuEntryTitle( sal_uInt32 nIndex )
343 PickListEntry *pPick = SfxPickList::Get()->GetPickListEntry( nIndex );
345 if ( pPick )
346 return pPick->aTitle;
347 else
348 return String();
351 void SfxPickList::Notify( SfxBroadcaster&, const SfxHint& rHint )
353 if ( rHint.IsA( TYPE( SfxStringHint )))
355 SfxStringHint* pStringHint = (SfxStringHint*) &rHint;
357 if ( pStringHint->GetId() == SID_OPENURL )
358 INetURLHistory::GetOrCreate()->PutUrl( INetURLObject( pStringHint->GetObject() ));
361 if ( rHint.IsA( TYPE( SfxEventHint )))
363 SfxEventHint* pEventHint = PTR_CAST(SfxEventHint,&rHint);
364 // nur ObjectShell-bezogene Events mit Medium interessieren
365 SfxObjectShell* pDocSh = pEventHint->GetObjShell();
366 if( !pDocSh )
367 return;
369 switch ( pEventHint->GetEventId() )
371 case SFX_EVENT_CREATEDOC:
373 sal_Bool bAllowModif = pDocSh->IsEnableSetModified();
374 if ( bAllowModif )
375 pDocSh->EnableSetModified( sal_False );
377 using namespace ::com::sun::star;
378 uno::Reference<document::XDocumentProperties> xDocProps(
379 pDocSh->getDocProperties());
380 if (xDocProps.is()) {
381 xDocProps->setAuthor( SvtUserOptions().GetFullName() );
382 ::DateTime now;
383 xDocProps->setCreationDate( util::DateTime(
384 now.Get100Sec(), now.GetSec(), now.GetMin(),
385 now.GetHour(), now.GetDay(), now.GetMonth(),
386 now.GetYear() ) );
389 if ( bAllowModif )
390 pDocSh->EnableSetModified( bAllowModif );
392 break;
394 case SFX_EVENT_OPENDOC:
396 SfxMedium *pMed = pDocSh->GetMedium();
397 if( !pMed )
398 return;
400 // unbenannt-Docs und embedded-Docs nicht in History
401 if ( !pDocSh->HasName() ||
402 SFX_CREATE_MODE_STANDARD != pDocSh->GetCreateMode() )
403 return;
405 // Hilfe nicht in History
406 INetURLObject aURL( pDocSh->IsDocShared() ? pDocSh->GetSharedFileURL() : ::rtl::OUString( pMed->GetOrigURL() ) );
407 if ( aURL.GetProtocol() == INET_PROT_VND_SUN_STAR_HELP )
408 return;
410 ::rtl::OUString aTitle = pDocSh->GetTitle(SFX_TITLE_PICKLIST);
411 ::rtl::OUString aFilter;
412 const SfxFilter* pFilter = pMed->GetOrigFilter();
413 if ( pFilter )
414 aFilter = pFilter->GetFilterName();
416 // add to svtool history options
417 SvtHistoryOptions().AppendItem( eHISTORY,
418 aURL.GetURLNoPass( INetURLObject::NO_DECODE ),
419 aFilter,
420 aTitle,
421 SfxStringEncode( aURL.GetPass() ) );
423 break;
425 case SFX_EVENT_CLOSEDOC:
427 SfxMedium *pMed = pDocSh->GetMedium();
428 if( !pMed )
429 return;
431 // unbenannt-Docs und embedded-Docs nicht in Pickliste
432 if ( !pDocSh->HasName() ||
433 SFX_CREATE_MODE_STANDARD != pDocSh->GetCreateMode() )
434 return;
436 // Hilfe nicht in History
437 INetURLObject aURL( pDocSh->IsDocShared() ? pDocSh->GetSharedFileURL() : ::rtl::OUString( pMed->GetOrigURL() ) );
438 if ( aURL.GetProtocol() == INET_PROT_VND_SUN_STAR_HELP )
439 return;
441 // only add r/w document into picklist
442 if ( pDocSh->IsReadOnly() || !pMed->IsUpdatePickList() )
443 return;
445 // add no document that forbids this (for example Message-Body)
446 SFX_ITEMSET_ARG( pMed->GetItemSet(), pPicklistItem, SfxBoolItem, SID_PICKLIST, sal_False );
447 if (
448 (pPicklistItem && !pPicklistItem->GetValue()) ||
449 (!(pDocSh->Get_Impl()->bWaitingForPicklist) )
451 return;
453 // ignore hidden documents
454 if ( !SfxViewFrame::GetFirst( pDocSh, 0, TRUE ) )
455 return;
457 ::rtl::OUString aTitle = pDocSh->GetTitle(SFX_TITLE_PICKLIST);
458 ::rtl::OUString aFilter;
459 const SfxFilter* pFilter = pMed->GetOrigFilter();
460 if ( pFilter )
461 aFilter = pFilter->GetFilterName();
463 // add to svtool history options
464 SvtHistoryOptions().AppendItem( ePICKLIST,
465 aURL.GetURLNoPass( INetURLObject::NO_DECODE ),
466 aFilter,
467 aTitle,
468 SfxStringEncode( aURL.GetPass() ) );
470 pDocSh->Get_Impl()->bWaitingForPicklist = sal_False;
472 if ( aURL.GetProtocol() == INET_PROT_FILE )
473 SystemShell::AddToRecentDocumentList( aURL.GetURLNoPass( INetURLObject::NO_DECODE ), (pFilter) ? pFilter->GetMimeType() : String() );
475 break;