| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_sfx2.hxx" |
| |
| #include <com/sun/star/document/XDocumentProperties.hpp> |
| #include <unotools/historyoptions.hxx> |
| #include <unotools/useroptions.hxx> |
| #include <tools/urlobj.hxx> |
| #include <framework/menuconfiguration.hxx> |
| #include <svl/inethist.hxx> |
| #include <svl/stritem.hxx> |
| #include <svl/eitem.hxx> |
| #include <osl/file.hxx> |
| #include <unotools/localfilehelper.hxx> |
| #include <cppuhelper/implbase1.hxx> |
| |
| // ---------------------------------------------------------------------------- |
| |
| #include <sfx2/app.hxx> |
| #include "sfxpicklist.hxx" |
| #include <sfx2/sfxuno.hxx> |
| #include "sfxtypes.hxx" |
| #include <sfx2/request.hxx> |
| #include <sfx2/sfxsids.hrc> |
| #include <sfx2/sfx.hrc> |
| #include <sfx2/event.hxx> |
| #include <sfx2/objsh.hxx> |
| #include <sfx2/bindings.hxx> |
| #include "referers.hxx" |
| #include <sfx2/docfile.hxx> |
| #include "objshimp.hxx" |
| #include <sfx2/docfilt.hxx> |
| |
| #include <algorithm> |
| |
| // ---------------------------------------------------------------------------- |
| |
| using namespace ::com::sun::star::uno; |
| using namespace ::com::sun::star::beans; |
| using namespace ::com::sun::star::util; |
| |
| // ---------------------------------------------------------------------------- |
| |
| osl::Mutex* SfxPickList::pMutex = 0; |
| SfxPickList* SfxPickList::pUniqueInstance = 0; |
| |
| // ---------------------------------------------------------------------------- |
| |
| class StringLength : public ::cppu::WeakImplHelper1< XStringWidth > |
| { |
| public: |
| StringLength() {} |
| virtual ~StringLength() {} |
| |
| // XStringWidth |
| sal_Int32 SAL_CALL queryStringWidth( const ::rtl::OUString& aString ) |
| throw (::com::sun::star::uno::RuntimeException) |
| { |
| return aString.getLength(); |
| } |
| }; |
| |
| // ---------------------------------------------------------------------------- |
| |
| osl::Mutex* SfxPickList::GetOrCreateMutex() |
| { |
| if ( !pMutex ) |
| { |
| ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); |
| if ( !pMutex ) |
| pMutex = new osl::Mutex; |
| } |
| |
| return pMutex; |
| } |
| |
| void SfxPickList::CreatePicklistMenuTitle( Menu* pMenu, sal_uInt16 nItemId, const String& aURLString, sal_uInt32 nNo ) |
| { |
| String aPickEntry; |
| |
| if ( nNo < 9 ) |
| { |
| aPickEntry += '~'; |
| aPickEntry += String::CreateFromInt32( nNo + 1 ); |
| } |
| else if ( nNo == 9 ) |
| aPickEntry += DEFINE_CONST_UNICODE("1~0"); |
| else |
| aPickEntry += String::CreateFromInt32( nNo + 1 ); |
| aPickEntry += DEFINE_CONST_UNICODE(": "); |
| |
| INetURLObject aURL( aURLString ); |
| rtl::OUString aTipHelpText; |
| rtl::OUString aAccessibleName( aPickEntry ); |
| |
| if ( aURL.GetProtocol() == INET_PROT_FILE ) |
| { |
| // Do handle file URL differently => convert it to a system |
| // path and abbreviate it with a special function: |
| String aFileSystemPath( aURL.getFSysPath( INetURLObject::FSYS_DETECT ) ); |
| |
| // ::utl::LocalFileHelper::ConvertURLToPhysicalName( aURLString, aPhysicalName ); |
| |
| ::rtl::OUString aSystemPath( aFileSystemPath ); |
| ::rtl::OUString aCompactedSystemPath; |
| |
| aTipHelpText = aSystemPath; |
| aAccessibleName += aSystemPath; |
| oslFileError nError = osl_abbreviateSystemPath( aSystemPath.pData, &aCompactedSystemPath.pData, 46, NULL ); |
| if ( !nError ) |
| aPickEntry += String( aCompactedSystemPath ); |
| else |
| aPickEntry += aFileSystemPath; |
| |
| if ( aPickEntry.Len() > 50 ) |
| { |
| aPickEntry.Erase( 47 ); |
| aPickEntry += DEFINE_CONST_UNICODE("..."); |
| } |
| } |
| else |
| { |
| // Use INetURLObject to abbreviate all other URLs |
| String aShortURL; |
| aShortURL = aURL.getAbbreviated( m_xStringLength, 46, INetURLObject::DECODE_UNAMBIGUOUS ); |
| aPickEntry += aShortURL; |
| aTipHelpText = aURLString; |
| aAccessibleName += aURLString; |
| } |
| |
| // Set menu item text, tip help and accessible name |
| pMenu->SetItemText( nItemId, aPickEntry ); |
| pMenu->SetTipHelpText( nItemId, aTipHelpText ); |
| pMenu->SetAccessibleName( nItemId, aAccessibleName ); |
| } |
| |
| void SfxPickList::RemovePickListEntries() |
| { |
| ::osl::MutexGuard aGuard( GetOrCreateMutex() ); |
| for ( sal_uInt32 i = 0; i < m_aPicklistVector.size(); i++ ) |
| delete m_aPicklistVector[i]; |
| m_aPicklistVector.clear(); |
| } |
| |
| SfxPickList::PickListEntry* SfxPickList::GetPickListEntry( sal_uInt32 nIndex ) |
| { |
| OSL_ASSERT( m_aPicklistVector.size() > nIndex ); |
| |
| if ( nIndex < m_aPicklistVector.size() ) |
| return m_aPicklistVector[ nIndex ]; |
| else |
| return 0; |
| } |
| |
| SfxPickList* SfxPickList::GetOrCreate( const sal_uInt32 nMenuSize ) |
| { |
| if ( !pUniqueInstance ) |
| { |
| ::osl::MutexGuard aGuard( GetOrCreateMutex() ); |
| if ( !pUniqueInstance ) |
| pUniqueInstance = new SfxPickList( nMenuSize ); |
| } |
| |
| return pUniqueInstance; |
| } |
| |
| SfxPickList* SfxPickList::Get() |
| { |
| ::osl::MutexGuard aGuard( GetOrCreateMutex() ); |
| return pUniqueInstance; |
| } |
| |
| void SfxPickList::Delete() |
| { |
| ::osl::MutexGuard aGuard( GetOrCreateMutex() ); |
| DELETEZ( pUniqueInstance ); |
| } |
| |
| SfxPickList::SfxPickList( sal_uInt32 nAllowedMenuSize ) : |
| m_nAllowedMenuSize( nAllowedMenuSize ) |
| { |
| m_xStringLength = new StringLength; |
| m_nAllowedMenuSize = ::std::min( m_nAllowedMenuSize, (sal_uInt32)PICKLIST_MAXSIZE ); |
| StartListening( *SFX_APP() ); |
| } |
| |
| SfxPickList::~SfxPickList() |
| { |
| RemovePickListEntries(); |
| } |
| |
| void SfxPickList::CreatePickListEntries() |
| { |
| RemovePickListEntries(); |
| |
| // Einlesen der Pickliste |
| Sequence< Sequence< PropertyValue > > seqPicklist = SvtHistoryOptions().GetList( ePICKLIST ); |
| |
| sal_uInt32 nCount = seqPicklist.getLength(); |
| sal_uInt32 nEntries = ::std::min( m_nAllowedMenuSize, nCount ); |
| |
| for( sal_uInt32 nItem=0; nItem < nEntries; ++nItem ) |
| { |
| Sequence< PropertyValue > seqPropertySet = seqPicklist[ nItem ]; |
| |
| INetURLObject aURL; |
| ::rtl::OUString sURL; |
| ::rtl::OUString sFilter; |
| ::rtl::OUString sTitle; |
| ::rtl::OUString sPassword; |
| |
| sal_uInt32 nPropertyCount = seqPropertySet.getLength(); |
| for( sal_uInt32 nProperty=0; nProperty<nPropertyCount; ++nProperty ) |
| { |
| if( seqPropertySet[nProperty].Name == HISTORY_PROPERTYNAME_URL ) |
| { |
| seqPropertySet[nProperty].Value >>= sURL; |
| } |
| else if( seqPropertySet[nProperty].Name == HISTORY_PROPERTYNAME_FILTER ) |
| { |
| seqPropertySet[nProperty].Value >>= sFilter; |
| } |
| else if( seqPropertySet[nProperty].Name == HISTORY_PROPERTYNAME_TITLE ) |
| { |
| seqPropertySet[nProperty].Value >>= sTitle; |
| } |
| else if( seqPropertySet[nProperty].Name == HISTORY_PROPERTYNAME_PASSWORD ) |
| { |
| seqPropertySet[nProperty].Value >>= sPassword; |
| } |
| } |
| |
| aURL.SetSmartURL( sURL ); |
| aURL.SetPass( SfxStringDecode( sPassword ) ); |
| |
| PickListEntry *pPick = new PickListEntry( aURL.GetMainURL( INetURLObject::NO_DECODE ), sFilter, sTitle ); |
| m_aPicklistVector.push_back( pPick ); |
| } |
| } |
| |
| void SfxPickList::CreateMenuEntries( Menu* pMenu ) |
| { |
| static sal_Bool bPickListMenuInitializing = sal_False; |
| |
| ::osl::MutexGuard aGuard( GetOrCreateMutex() ); |
| |
| if ( bPickListMenuInitializing ) // method is not reentrant! |
| return; |
| |
| bPickListMenuInitializing = sal_True; |
| CreatePickListEntries(); |
| |
| for ( sal_uInt16 nId = START_ITEMID_PICKLIST; nId <= END_ITEMID_PICKLIST; ++nId ) |
| pMenu->RemoveItem( pMenu->GetItemPos( nId ) ); |
| |
| if ( pMenu->GetItemType( pMenu->GetItemCount()-1 ) == MENUITEM_SEPARATOR ) |
| pMenu->RemoveItem( pMenu->GetItemCount()-1 ); |
| |
| if ( m_aPicklistVector.size() > 0 && |
| pMenu->GetItemType( pMenu->GetItemCount()-1 ) |
| != MENUITEM_SEPARATOR && m_nAllowedMenuSize ) |
| pMenu->InsertSeparator(); |
| |
| rtl::OUString aEmptyString; |
| for ( sal_uInt32 i = 0; i < m_aPicklistVector.size(); i++ ) |
| { |
| PickListEntry* pEntry = GetPickListEntry( i ); |
| |
| pMenu->InsertItem( (sal_uInt16)(START_ITEMID_PICKLIST + i), aEmptyString ); |
| CreatePicklistMenuTitle( pMenu, (sal_uInt16)(START_ITEMID_PICKLIST + i), pEntry->aName, i ); |
| } |
| |
| bPickListMenuInitializing = sal_False; |
| } |
| |
| void SfxPickList::ExecuteEntry( sal_uInt32 nIndex ) |
| { |
| ::osl::ClearableMutexGuard aGuard( GetOrCreateMutex() ); |
| |
| PickListEntry *pPick = SfxPickList::Get()->GetPickListEntry( nIndex ); |
| |
| if ( pPick ) |
| { |
| SfxRequest aReq( SID_OPENDOC, SFX_CALLMODE_ASYNCHRON, SFX_APP()->GetPool() ); |
| aReq.AppendItem( SfxStringItem( SID_FILE_NAME, pPick->aName )); |
| aReq.AppendItem( SfxStringItem( SID_REFERER, DEFINE_CONST_UNICODE( SFX_REFERER_USER ) ) ); |
| aReq.AppendItem( SfxStringItem( SID_TARGETNAME, DEFINE_CONST_UNICODE("_default") ) ); |
| String aFilter( pPick->aFilter ); |
| aGuard.clear(); |
| |
| sal_uInt16 nPos=aFilter.Search('|'); |
| if( nPos != STRING_NOTFOUND ) |
| { |
| String aOptions(aFilter.Copy( nPos ).GetBuffer()+1); |
| aFilter.Erase( nPos ); |
| aReq.AppendItem( SfxStringItem(SID_FILE_FILTEROPTIONS, aOptions)); |
| } |
| |
| aReq.AppendItem(SfxStringItem( SID_FILTER_NAME, aFilter )); |
| aReq.AppendItem( SfxBoolItem( SID_TEMPLATE, sal_False ) ); |
| SFX_APP()->ExecuteSlot( aReq ); |
| } |
| } |
| |
| void SfxPickList::ExecuteMenuEntry( sal_uInt16 nId ) |
| { |
| ExecuteEntry( (sal_uInt32)( nId - START_ITEMID_PICKLIST ) ); |
| } |
| |
| String SfxPickList::GetMenuEntryTitle( sal_uInt32 nIndex ) |
| { |
| PickListEntry *pPick = SfxPickList::Get()->GetPickListEntry( nIndex ); |
| |
| if ( pPick ) |
| return pPick->aTitle; |
| else |
| return String(); |
| } |
| |
| void SfxPickList::Notify( SfxBroadcaster&, const SfxHint& rHint ) |
| { |
| if ( rHint.IsA( TYPE( SfxStringHint ))) |
| { |
| SfxStringHint* pStringHint = (SfxStringHint*) &rHint; |
| |
| if ( pStringHint->GetId() == SID_OPENURL ) |
| INetURLHistory::GetOrCreate()->PutUrl( INetURLObject( pStringHint->GetObject() )); |
| } |
| |
| if ( rHint.IsA( TYPE( SfxEventHint ))) |
| { |
| SfxEventHint* pEventHint = PTR_CAST(SfxEventHint,&rHint); |
| // nur ObjectShell-bezogene Events mit Medium interessieren |
| SfxObjectShell* pDocSh = pEventHint->GetObjShell(); |
| if( !pDocSh ) |
| return; |
| |
| switch ( pEventHint->GetEventId() ) |
| { |
| case SFX_EVENT_CREATEDOC: |
| { |
| sal_Bool bAllowModif = pDocSh->IsEnableSetModified(); |
| if ( bAllowModif ) |
| pDocSh->EnableSetModified( sal_False ); |
| |
| using namespace ::com::sun::star; |
| uno::Reference<document::XDocumentProperties> xDocProps( |
| pDocSh->getDocProperties()); |
| if (xDocProps.is()) { |
| xDocProps->setAuthor( SvtUserOptions().GetFullName() ); |
| ::DateTime now; |
| xDocProps->setCreationDate( util::DateTime( |
| now.Get100Sec(), now.GetSec(), now.GetMin(), |
| now.GetHour(), now.GetDay(), now.GetMonth(), |
| now.GetYear() ) ); |
| } |
| |
| if ( bAllowModif ) |
| pDocSh->EnableSetModified( bAllowModif ); |
| } |
| break; |
| |
| case SFX_EVENT_OPENDOC: |
| { |
| SfxMedium *pMed = pDocSh->GetMedium(); |
| if( !pMed ) |
| return; |
| |
| // unbenannt-Docs und embedded-Docs nicht in History |
| if ( !pDocSh->HasName() || |
| SFX_CREATE_MODE_STANDARD != pDocSh->GetCreateMode() ) |
| return; |
| |
| // Hilfe nicht in History |
| INetURLObject aURL( pDocSh->IsDocShared() ? pDocSh->GetSharedFileURL() : ::rtl::OUString( pMed->GetOrigURL() ) ); |
| if ( aURL.GetProtocol() == INET_PROT_VND_SUN_STAR_HELP ) |
| return; |
| |
| ::rtl::OUString aTitle = pDocSh->GetTitle(SFX_TITLE_PICKLIST); |
| ::rtl::OUString aFilter; |
| const SfxFilter* pFilter = pMed->GetOrigFilter(); |
| if ( pFilter ) |
| aFilter = pFilter->GetFilterName(); |
| |
| // add to svtool history options |
| SvtHistoryOptions().AppendItem( eHISTORY, |
| aURL.GetURLNoPass( INetURLObject::NO_DECODE ), |
| aFilter, |
| aTitle, |
| SfxStringEncode( aURL.GetPass() ) ); |
| } |
| break; |
| |
| case SFX_EVENT_CLOSEDOC: |
| { |
| SfxMedium *pMed = pDocSh->GetMedium(); |
| if( !pMed ) |
| return; |
| |
| // unbenannt-Docs und embedded-Docs nicht in Pickliste |
| if ( !pDocSh->HasName() || |
| SFX_CREATE_MODE_STANDARD != pDocSh->GetCreateMode() ) |
| return; |
| |
| // Hilfe nicht in History |
| INetURLObject aURL( pDocSh->IsDocShared() ? pDocSh->GetSharedFileURL() : ::rtl::OUString( pMed->GetOrigURL() ) ); |
| if ( aURL.GetProtocol() == INET_PROT_VND_SUN_STAR_HELP ) |
| return; |
| |
| // only add r/w document into picklist |
| if ( pDocSh->IsReadOnly() || !pMed->IsUpdatePickList() ) |
| return; |
| |
| // add no document that forbids this (for example Message-Body) |
| SFX_ITEMSET_ARG( pMed->GetItemSet(), pPicklistItem, SfxBoolItem, SID_PICKLIST, sal_False ); |
| if ( |
| (pPicklistItem && !pPicklistItem->GetValue()) || |
| (!(pDocSh->Get_Impl()->bWaitingForPicklist) ) |
| ) |
| return; |
| |
| // ignore hidden documents |
| if ( !SfxViewFrame::GetFirst( pDocSh, sal_True ) ) |
| return; |
| |
| ::rtl::OUString aTitle = pDocSh->GetTitle(SFX_TITLE_PICKLIST); |
| ::rtl::OUString aFilter; |
| const SfxFilter* pFilter = pMed->GetOrigFilter(); |
| if ( pFilter ) |
| aFilter = pFilter->GetFilterName(); |
| |
| // add to svtool history options |
| SvtHistoryOptions().AppendItem( ePICKLIST, |
| aURL.GetURLNoPass( INetURLObject::NO_DECODE ), |
| aFilter, |
| aTitle, |
| SfxStringEncode( aURL.GetPass() ) ); |
| |
| pDocSh->Get_Impl()->bWaitingForPicklist = sal_False; |
| |
| if ( aURL.GetProtocol() == INET_PROT_FILE ) |
| Application::AddToRecentDocumentList( aURL.GetURLNoPass( INetURLObject::NO_DECODE ), (pFilter) ? pFilter->GetMimeType() : String() ); |
| } |
| break; |
| } |
| } |
| } |