1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
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.
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).
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.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_framework.hxx"
31 //_______________________________________________
34 #include <helper/titlehelper.hxx>
36 #include <properties.h>
38 #include <com/sun/star/frame/UntitledNumbersConst.hpp>
39 #include <com/sun/star/frame/XStorable.hpp>
40 #include <com/sun/star/frame/XModuleManager.hpp>
41 #include <com/sun/star/container/XNameAccess.hpp>
42 #include <com/sun/star/document/XEventBroadcaster.hpp>
43 #include <com/sun/star/beans/XMaterialHolder.hpp>
45 #include <unotools/configmgr.hxx>
46 #include <unotools/bootstrap.hxx>
47 #include <comphelper/sequenceashashmap.hxx>
48 #include <rtl/ustrbuf.hxx>
49 #include <osl/mutex.hxx>
50 #include <tools/urlobj.hxx>
52 //_______________________________________________
57 namespace css
= ::com::sun::star
;
59 //_______________________________________________
62 static const ::rtl::OUString ERRMSG_INVALID_COMPONENT_PARAM
= ::rtl::OUString::createFromAscii("NULL as component reference not allowed.");
63 static const ::rtl::OUString ERRMSG_INVALID_NUMBER_PARAM
= ::rtl::OUString::createFromAscii("Special valkud INVALID_NUMBER not allowed as input parameter.");
65 //-----------------------------------------------
66 TitleHelper::TitleHelper(const css::uno::Reference
< css::lang::XMultiServiceFactory
>& xSMGR
)
67 : ::cppu::BaseMutex ()
70 , m_xUntitledNumbers()
72 , m_bExternalTitle (sal_False
)
74 , m_nLeasedNumber (css::frame::UntitledNumbersConst::INVALID_NUMBER
)
75 , m_aListener (m_aMutex
)
79 //-----------------------------------------------
80 TitleHelper::~TitleHelper()
84 //-----------------------------------------------
85 void TitleHelper::setOwner(const css::uno::Reference
< css::uno::XInterface
>& xOwner
)
88 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
95 css::uno::Reference
< css::frame::XModel
> xModel(xOwner
, css::uno::UNO_QUERY
);
98 impl_startListeningForModel (xModel
);
102 css::uno::Reference
< css::frame::XController
> xController(xOwner
, css::uno::UNO_QUERY
);
103 if (xController
.is ())
105 impl_startListeningForController (xController
);
109 css::uno::Reference
< css::frame::XFrame
> xFrame(xOwner
, css::uno::UNO_QUERY
);
112 impl_startListeningForFrame (xFrame
);
117 //-----------------------------------------------
118 ::rtl::OUString SAL_CALL
TitleHelper::getTitle()
119 throw (css::uno::RuntimeException
)
122 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
124 // An external title will win always and disable all internal logic about
125 // creating/using a title value.
126 // Even an empty string will be accepted as valid title !
127 if (m_bExternalTitle
)
130 // Title seams to be up-to-date. Return it directly.
131 if (m_sTitle
.getLength() > 0)
134 // Title seams to be unused till now ... do bootstraping
142 //-----------------------------------------------
143 void TitleHelper::connectWithUntitledNumbers (const css::uno::Reference
< css::frame::XUntitledNumbers
>& xNumbers
)
146 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
148 m_xUntitledNumbers
= xNumbers
;
153 //-----------------------------------------------
154 void SAL_CALL
TitleHelper::setTitle(const ::rtl::OUString
& sTitle
)
155 throw (css::uno::RuntimeException
)
158 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
160 m_bExternalTitle
= sal_True
;
166 impl_sendTitleChangedEvent ();
169 //-----------------------------------------------
170 void SAL_CALL
TitleHelper::addTitleChangeListener(const css::uno::Reference
< css::frame::XTitleChangeListener
>& xListener
)
171 throw (css::uno::RuntimeException
)
173 // container is threadsafe by himself
174 m_aListener
.addInterface( ::getCppuType( (const css::uno::Reference
< css::frame::XTitleChangeListener
>*)NULL
), xListener
);
177 //-----------------------------------------------
178 void SAL_CALL
TitleHelper::removeTitleChangeListener(const css::uno::Reference
< css::frame::XTitleChangeListener
>& xListener
)
179 throw (css::uno::RuntimeException
)
181 // container is threadsafe by himself
182 m_aListener
.removeInterface( ::getCppuType( (const css::uno::Reference
< css::frame::XTitleChangeListener
>*)NULL
), xListener
);
185 //-----------------------------------------------
186 void SAL_CALL
TitleHelper::titleChanged(const css::frame::TitleChangedEvent
& aEvent
)
187 throw (css::uno::RuntimeException
)
190 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
192 css::uno::Reference
< css::frame::XTitle
> xSubTitle(m_xSubTitle
.get (), css::uno::UNO_QUERY
);
197 if (aEvent
.Source
!= xSubTitle
)
203 //-----------------------------------------------
204 void SAL_CALL
TitleHelper::notifyEvent(const css::document::EventObject
& aEvent
)
205 throw (css::uno::RuntimeException
)
207 if ( ! aEvent
.EventName
.equalsIgnoreAsciiCaseAscii ("OnSaveAsDone")
208 && ! aEvent
.EventName
.equalsIgnoreAsciiCaseAscii ("OnTitleChanged"))
212 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
214 css::uno::Reference
< css::frame::XModel
> xOwner(m_xOwner
.get (), css::uno::UNO_QUERY
);
220 aEvent
.Source
!= xOwner
||
221 (aEvent
.EventName
.equalsIgnoreAsciiCaseAscii ("OnTitleChanged") && !xOwner
.is())
230 //-----------------------------------------------
231 void SAL_CALL
TitleHelper::frameAction(const css::frame::FrameActionEvent
& aEvent
)
232 throw(css::uno::RuntimeException
)
235 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
237 css::uno::Reference
< css::frame::XFrame
> xOwner(m_xOwner
.get (), css::uno::UNO_QUERY
);
242 if (aEvent
.Source
!= xOwner
)
245 // we are interested on events only, which must trigger a title bar update
246 // because component was changed.
248 (aEvent
.Action
== css::frame::FrameAction_COMPONENT_ATTACHED
) ||
249 (aEvent
.Action
== css::frame::FrameAction_COMPONENT_REATTACHED
) ||
250 (aEvent
.Action
== css::frame::FrameAction_COMPONENT_DETACHING
)
253 impl_updateListeningForFrame (xOwner
);
258 //-----------------------------------------------
259 void SAL_CALL
TitleHelper::disposing(const css::lang::EventObject
& aEvent
)
260 throw (css::uno::RuntimeException
)
263 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
264 css::uno::Reference
< css::uno::XInterface
> xOwner (m_xOwner
.get() , css::uno::UNO_QUERY
);
265 css::uno::Reference
< css::frame::XUntitledNumbers
> xNumbers (m_xUntitledNumbers
.get(), css::uno::UNO_QUERY
);
266 ::sal_Int32 nLeasedNumber
= m_nLeasedNumber
;
273 if (xOwner
!= aEvent
.Source
)
278 (nLeasedNumber
!= css::frame::UntitledNumbersConst::INVALID_NUMBER
)
280 xNumbers
->releaseNumber (nLeasedNumber
);
285 m_sTitle
= ::rtl::OUString ();
286 m_nLeasedNumber
= css::frame::UntitledNumbersConst::INVALID_NUMBER
;
291 impl_sendTitleChangedEvent ();
294 //-----------------------------------------------
295 void TitleHelper::impl_sendTitleChangedEvent ()
298 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
300 css::frame::TitleChangedEvent
aEvent(m_xOwner
.get (), m_sTitle
);
305 ::cppu::OInterfaceContainerHelper
* pContainer
= m_aListener
.getContainer( ::getCppuType( ( const css::uno::Reference
< css::frame::XTitleChangeListener
>*) NULL
) );
309 ::cppu::OInterfaceIteratorHelper
pIt( *pContainer
);
310 while ( pIt
.hasMoreElements() )
314 ((css::frame::XTitleChangeListener
*)pIt
.next())->titleChanged( aEvent
);
316 catch(const css::uno::Exception
&)
323 //-----------------------------------------------
324 void TitleHelper::impl_updateTitle ()
327 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
329 css::uno::Reference
< css::frame::XModel
> xModel (m_xOwner
.get(), css::uno::UNO_QUERY
);
330 css::uno::Reference
< css::frame::XController
> xController(m_xOwner
.get(), css::uno::UNO_QUERY
);
331 css::uno::Reference
< css::frame::XFrame
> xFrame (m_xOwner
.get(), css::uno::UNO_QUERY
);
338 impl_updateTitleForModel (xModel
);
342 if (xController
.is ())
344 impl_updateTitleForController (xController
);
350 impl_updateTitleForFrame (xFrame
);
355 //-----------------------------------------------
356 void TitleHelper::impl_updateTitleForModel (const css::uno::Reference
< css::frame::XModel
>& xModel
)
359 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
361 // external title wont be updated internaly !
362 // It has to be set from outside new.
363 if (m_bExternalTitle
)
366 css::uno::Reference
< css::uno::XInterface
> xOwner (m_xOwner
.get() , css::uno::UNO_QUERY
);
367 css::uno::Reference
< css::frame::XUntitledNumbers
> xNumbers (m_xUntitledNumbers
.get(), css::uno::UNO_QUERY
);
368 ::sal_Int32 nLeasedNumber
= m_nLeasedNumber
;
375 ( ! xNumbers
.is ()) ||
380 ::rtl::OUString sTitle
;
381 ::rtl::OUString sURL
;
383 css::uno::Reference
< css::frame::XStorable
> xURLProvider(xModel
, css::uno::UNO_QUERY
);
384 if (xURLProvider
.is())
385 sURL
= xURLProvider
->getLocation ();
387 if (sURL
.getLength () > 0)
389 sTitle
= impl_convertURL2Title(sURL
);
390 if (nLeasedNumber
!= css::frame::UntitledNumbersConst::INVALID_NUMBER
)
391 xNumbers
->releaseNumber (nLeasedNumber
);
392 nLeasedNumber
= css::frame::UntitledNumbersConst::INVALID_NUMBER
;
396 if (nLeasedNumber
== css::frame::UntitledNumbersConst::INVALID_NUMBER
)
397 nLeasedNumber
= xNumbers
->leaseNumber (xOwner
);
399 ::rtl::OUStringBuffer
sNewTitle(256);
400 sNewTitle
.append (xNumbers
->getUntitledPrefix ());
401 if (nLeasedNumber
!= css::frame::UntitledNumbersConst::INVALID_NUMBER
)
402 sNewTitle
.append ((::sal_Int32
)nLeasedNumber
);
404 sNewTitle
.appendAscii ("?");
406 sTitle
= sNewTitle
.makeStringAndClear ();
412 // WORKAROUND: the notification is currently sent always,
413 // can be changed after shared mode is supported per UNO API
414 sal_Bool bChanged
= sal_True
; // (! m_sTitle.equals(sTitle));
417 m_nLeasedNumber
= nLeasedNumber
;
423 impl_sendTitleChangedEvent ();
426 //-----------------------------------------------
427 void TitleHelper::impl_updateTitleForController (const css::uno::Reference
< css::frame::XController
>& xController
)
430 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
432 // external title wont be updated internaly !
433 // It has to be set from outside new.
434 if (m_bExternalTitle
)
437 css::uno::Reference
< css::uno::XInterface
> xOwner (m_xOwner
.get() , css::uno::UNO_QUERY
);
438 css::uno::Reference
< css::frame::XUntitledNumbers
> xNumbers (m_xUntitledNumbers
.get(), css::uno::UNO_QUERY
);
439 ::sal_Int32 nLeasedNumber
= m_nLeasedNumber
;
446 ( ! xNumbers
.is ()) ||
447 ( ! xController
.is ())
451 ::rtl::OUStringBuffer
sTitle(256);
453 if (nLeasedNumber
== css::frame::UntitledNumbersConst::INVALID_NUMBER
)
454 nLeasedNumber
= xNumbers
->leaseNumber (xOwner
);
456 css::uno::Reference
< css::frame::XTitle
> xModelTitle(xController
->getModel (), css::uno::UNO_QUERY
);
457 if (!xModelTitle
.is ())
458 xModelTitle
.set(xController
, css::uno::UNO_QUERY
);
459 if (xModelTitle
.is ())
461 sTitle
.append (xModelTitle
->getTitle ());
462 if ( nLeasedNumber
> 1 )
464 sTitle
.appendAscii (" : ");
465 sTitle
.append ((::sal_Int32
)nLeasedNumber
);
470 sTitle
.append (xNumbers
->getUntitledPrefix ());
471 if ( nLeasedNumber
> 1 )
473 sTitle
.append ((::sal_Int32
)nLeasedNumber
);
480 ::rtl::OUString sNewTitle
= sTitle
.makeStringAndClear ();
481 sal_Bool bChanged
= (! m_sTitle
.equals(sNewTitle
));
482 m_sTitle
= sNewTitle
;
483 m_nLeasedNumber
= nLeasedNumber
;
489 impl_sendTitleChangedEvent ();
492 //-----------------------------------------------
493 void TitleHelper::impl_updateTitleForFrame (const css::uno::Reference
< css::frame::XFrame
>& xFrame
)
499 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
501 // external title wont be updated internaly !
502 // It has to be set from outside new.
503 if (m_bExternalTitle
)
509 css::uno::Reference
< css::uno::XInterface
> xComponent
;
510 xComponent
= xFrame
->getController ();
511 if ( ! xComponent
.is ())
512 xComponent
= xFrame
->getComponentWindow ();
514 ::rtl::OUStringBuffer
sTitle (256);
516 impl_appendComponentTitle (sTitle
, xComponent
);
517 impl_appendProductName (sTitle
);
518 impl_appendModuleName (sTitle
);
519 impl_appendProductExtension (sTitle
);
520 //impl_appendEvalVersion (sTitle);
521 impl_appendDebugVersion (sTitle
);
526 ::rtl::OUString sNewTitle
= sTitle
.makeStringAndClear ();
527 sal_Bool bChanged
= (! m_sTitle
.equals(sNewTitle
));
528 m_sTitle
= sNewTitle
;
534 impl_sendTitleChangedEvent ();
537 //*****************************************************************************************************************
538 void TitleHelper::impl_appendComponentTitle ( ::rtl::OUStringBuffer
& sTitle
,
539 const css::uno::Reference
< css::uno::XInterface
>& xComponent
)
541 css::uno::Reference
< css::frame::XTitle
> xTitle(xComponent
, css::uno::UNO_QUERY
);
543 // Note: Title has to be used (even if it's empty) if the right interface is supported.
545 sTitle
.append (xTitle
->getTitle ());
548 //*****************************************************************************************************************
549 void TitleHelper::impl_appendProductName (::rtl::OUStringBuffer
& sTitle
)
551 ::rtl::OUString sProductName
;
552 ::utl::ConfigManager::GetDirectConfigProperty(::utl::ConfigManager::PRODUCTNAME
) >>= sProductName
;
554 if (sProductName
.getLength ())
556 if (sTitle
.getLength() > 0)
557 sTitle
.appendAscii (" - ");
559 sTitle
.append (sProductName
);
563 //*****************************************************************************************************************
564 void TitleHelper::impl_appendProductExtension (::rtl::OUStringBuffer
& sTitle
)
566 ::rtl::OUString sProductExtension
;
567 ::utl::ConfigManager::GetDirectConfigProperty(::utl::ConfigManager::PRODUCTEXTENSION
) >>= sProductExtension
;
569 if (sProductExtension
.getLength ())
571 sTitle
.appendAscii (" ");
572 sTitle
.append (sProductExtension
);
576 //*****************************************************************************************************************
577 void TitleHelper::impl_appendModuleName (::rtl::OUStringBuffer
& sTitle
)
580 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
582 css::uno::Reference
< css::uno::XInterface
> xOwner
= m_xOwner
.get();
583 css::uno::Reference
< css::lang::XMultiServiceFactory
> xSMGR
= m_xSMGR
;
590 css::uno::Reference
< css::frame::XModuleManager
> xModuleManager(
591 xSMGR
->createInstance(SERVICENAME_MODULEMANAGER
),
592 css::uno::UNO_QUERY_THROW
);
594 css::uno::Reference
< css::container::XNameAccess
> xConfig(
596 css::uno::UNO_QUERY_THROW
);
598 const ::rtl::OUString sID
= xModuleManager
->identify(xOwner
);
599 ::comphelper::SequenceAsHashMap lProps
= xConfig
->getByName (sID
);
600 const ::rtl::OUString sUIName
= lProps
.getUnpackedValueOrDefault (OFFICEFACTORY_PROPNAME_UINAME
, ::rtl::OUString());
602 // An UIname property is an optional value !
603 // So please add it to the title in case it does realy exists only.
604 if (sUIName
.getLength() > 0)
606 sTitle
.appendAscii (" " );
607 sTitle
.append (sUIName
);
610 catch(const css::uno::Exception
&)
614 //*****************************************************************************************************************
616 void TitleHelper::impl_appendDebugVersion (::rtl::OUStringBuffer
& sTitle
)
618 ::rtl::OUString sDefault
;
619 ::rtl::OUString sVersion
= ::utl::Bootstrap::getBuildIdData( sDefault
);
621 sTitle
.appendAscii (" [" );
622 sTitle
.append (sVersion
);
623 sTitle
.appendAscii ("]" );
626 void TitleHelper::impl_appendDebugVersion (::rtl::OUStringBuffer
&)
631 //*****************************************************************************************************************
632 void TitleHelper::impl_appendEvalVersion (::rtl::OUStringBuffer
& /*sTitle*/)
635 // ::osl::ResettableMutexGuard aLock(m_aMutex);
636 // css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR ;
640 //css::uno::Reference< css::beans::XMaterialHolder > xHolder(
641 // xSMGR->createInstance(SERVICENAME_TABREG),
642 // css::uno::UNO_QUERY);
644 // if ( ! xHolder.is())
647 // ::comphelper::SequenceAsHashMap aMaterial(xHolder->getMaterial());
648 //const ::rtl::OUString sEvalTitle = aMaterial.getUnpackedValueOrDefault(TABREG_PROPNAME_TITLE, ::rtl::OUString());
650 //if (sEvalTitle.getLength())
652 // sTitle.appendAscii (" " );
653 // sTitle.append (sEvalTitle);
657 //-----------------------------------------------
658 void TitleHelper::impl_startListeningForModel (const css::uno::Reference
< css::frame::XModel
>& xModel
)
660 css::uno::Reference
< css::document::XEventBroadcaster
> xBroadcaster(xModel
, css::uno::UNO_QUERY
);
661 if ( ! xBroadcaster
.is ())
664 xBroadcaster
->addEventListener (static_cast< css::document::XEventListener
* >(this));
667 //-----------------------------------------------
668 void TitleHelper::impl_startListeningForController (const css::uno::Reference
< css::frame::XController
>& xController
)
670 css::uno::Reference
< css::frame::XTitle
> xSubTitle(xController
->getModel (), css::uno::UNO_QUERY
);
671 impl_setSubTitle (xSubTitle
);
674 //-----------------------------------------------
675 void TitleHelper::impl_startListeningForFrame (const css::uno::Reference
< css::frame::XFrame
>& xFrame
)
677 xFrame
->addFrameActionListener(this );
678 impl_updateListeningForFrame (xFrame
);
681 //-----------------------------------------------
682 void TitleHelper::impl_updateListeningForFrame (const css::uno::Reference
< css::frame::XFrame
>& xFrame
)
684 css::uno::Reference
< css::frame::XTitle
> xSubTitle(xFrame
->getController (), css::uno::UNO_QUERY
);
685 impl_setSubTitle (xSubTitle
);
688 //-----------------------------------------------
689 void TitleHelper::impl_setSubTitle (const css::uno::Reference
< css::frame::XTitle
>& xSubTitle
)
692 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
694 // ignore duplicate calls. Makes outside using of this helper more easy :-)
695 css::uno::Reference
< css::frame::XTitle
> xOldSubTitle(m_xSubTitle
.get(), css::uno::UNO_QUERY
);
696 if (xOldSubTitle
== xSubTitle
)
699 m_xSubTitle
= xSubTitle
;
704 css::uno::Reference
< css::frame::XTitleChangeBroadcaster
> xOldBroadcaster(xOldSubTitle
, css::uno::UNO_QUERY
);
705 css::uno::Reference
< css::frame::XTitleChangeBroadcaster
> xNewBroadcaster(xSubTitle
, css::uno::UNO_QUERY
);
706 css::uno::Reference
< css::frame::XTitleChangeListener
> xThis (static_cast< css::frame::XTitleChangeListener
* >(this), css::uno::UNO_QUERY_THROW
);
708 if (xOldBroadcaster
.is())
709 xOldBroadcaster
->removeTitleChangeListener (xThis
);
711 if (xNewBroadcaster
.is())
712 xNewBroadcaster
->addTitleChangeListener (xThis
);
715 //-----------------------------------------------
716 ::rtl::OUString
TitleHelper::impl_getSubTitle ()
719 ::osl::ResettableMutexGuard
aLock(m_aMutex
);
721 css::uno::Reference
< css::frame::XTitle
> xSubTitle(m_xSubTitle
.get (), css::uno::UNO_QUERY
);
727 return xSubTitle
->getTitle ();
729 return ::rtl::OUString ();
732 //-----------------------------------------------
733 ::rtl::OUString
TitleHelper::impl_convertURL2Title(const ::rtl::OUString
& sURL
)
735 INetURLObject
aURL (sURL
);
736 ::rtl::OUString sTitle
;
738 if (aURL
.GetProtocol() == INET_PROT_FILE
)
741 aURL
= INetURLObject(aURL
.GetURLNoMark());
743 sTitle
= aURL
.getName(INetURLObject::LAST_SEGMENT
, sal_True
, INetURLObject::DECODE_WITH_CHARSET
);
747 if (aURL
.hasExtension(INetURLObject::LAST_SEGMENT
))
748 sTitle
= aURL
.getName(INetURLObject::LAST_SEGMENT
, sal_True
, INetURLObject::DECODE_WITH_CHARSET
);
750 if ( ! sTitle
.getLength() )
751 sTitle
= aURL
.GetHostPort(INetURLObject::DECODE_WITH_CHARSET
);
753 if ( ! sTitle
.getLength() )
754 sTitle
= aURL
.GetURLNoPass(INetURLObject::DECODE_WITH_CHARSET
);
760 } // namespace framework