1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: sfxpicklist.cxx,v $
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>
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
>
82 virtual ~StringLength() {}
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()
98 ::osl::MutexGuard
aGuard( ::osl::Mutex::getGlobalMutex() );
100 pMutex
= new osl::Mutex
;
106 void SfxPickList::CreatePicklistMenuTitle( Menu
* pMenu
, USHORT nItemId
, const String
& aURLString
, sal_uInt32 nNo
)
113 aPickEntry
+= String::CreateFromInt32( nNo
+ 1 );
116 aPickEntry
+= DEFINE_CONST_UNICODE("1~0");
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
);
140 aPickEntry
+= String( aCompactedSystemPath
);
142 aPickEntry
+= aFileSystemPath
;
144 if ( aPickEntry
.Len() > 50 )
146 aPickEntry
.Erase( 47 );
147 aPickEntry
+= DEFINE_CONST_UNICODE("...");
152 // Use INetURLObject to abbreviate all other URLs
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
];
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
];
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!
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
);
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
);
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
);
344 return pPick
->aTitle
;
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();
367 switch ( pEventHint
->GetEventId() )
369 case SFX_EVENT_CREATEDOC
:
371 sal_Bool bAllowModif
= pDocSh
->IsEnableSetModified();
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() );
381 xDocProps
->setCreationDate( util::DateTime(
382 now
.Get100Sec(), now
.GetSec(), now
.GetMin(),
383 now
.GetHour(), now
.GetDay(), now
.GetMonth(),
388 pDocSh
->EnableSetModified( bAllowModif
);
392 case SFX_EVENT_OPENDOC
:
394 SfxMedium
*pMed
= pDocSh
->GetMedium();
398 // unbenannt-Docs und embedded-Docs nicht in History
399 if ( !pDocSh
->HasName() ||
400 SFX_CREATE_MODE_STANDARD
!= pDocSh
->GetCreateMode() )
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
)
408 ::rtl::OUString aTitle
= pDocSh
->GetTitle(SFX_TITLE_PICKLIST
);
409 ::rtl::OUString aFilter
;
410 const SfxFilter
* pFilter
= pMed
->GetOrigFilter();
412 aFilter
= pFilter
->GetFilterName();
414 // add to svtool history options
415 SvtHistoryOptions().AppendItem( eHISTORY
,
416 aURL
.GetURLNoPass( INetURLObject::NO_DECODE
),
419 SfxStringEncode( aURL
.GetPass() ) );
423 case SFX_EVENT_CLOSEDOC
:
425 SfxMedium
*pMed
= pDocSh
->GetMedium();
429 // unbenannt-Docs und embedded-Docs nicht in Pickliste
430 if ( !pDocSh
->HasName() ||
431 SFX_CREATE_MODE_STANDARD
!= pDocSh
->GetCreateMode() )
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
)
439 // only add r/w document into picklist
440 if ( pDocSh
->IsReadOnly() || !pMed
->IsUpdatePickList() )
443 // add no document that forbids this (for example Message-Body)
444 SFX_ITEMSET_ARG( pMed
->GetItemSet(), pPicklistItem
, SfxBoolItem
, SID_PICKLIST
, sal_False
);
446 (pPicklistItem
&& !pPicklistItem
->GetValue()) ||
447 (!(pDocSh
->Get_Impl()->bWaitingForPicklist
) )
451 // ignore hidden documents
452 if ( !SfxViewFrame::GetFirst( pDocSh
, 0, TRUE
) )
455 ::rtl::OUString aTitle
= pDocSh
->GetTitle(SFX_TITLE_PICKLIST
);
456 ::rtl::OUString aFilter
;
457 const SfxFilter
* pFilter
= pMed
->GetOrigFilter();
459 aFilter
= pFilter
->GetFilterName();
461 // add to svtool history options
462 SvtHistoryOptions().AppendItem( ePICKLIST
,
463 aURL
.GetURLNoPass( INetURLObject::NO_DECODE
),
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() );