1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_framework.hxx"
26 
27 //_______________________________________________
28 // includes
29 
30 #include <framework/titlehelper.hxx>
31 #include <services.h>
32 #include <properties.h>
33 
34 #include <com/sun/star/frame/UntitledNumbersConst.hpp>
35 #include <com/sun/star/frame/XStorable.hpp>
36 #include <com/sun/star/frame/XModuleManager.hpp>
37 #include <com/sun/star/container/XNameAccess.hpp>
38 #include <com/sun/star/document/XEventBroadcaster.hpp>
39 #include <com/sun/star/beans/XMaterialHolder.hpp>
40 
41 #include <unotools/configmgr.hxx>
42 #include <unotools/bootstrap.hxx>
43 #include <comphelper/sequenceashashmap.hxx>
44 #include <rtl/ustrbuf.hxx>
45 #include <osl/mutex.hxx>
46 #include <tools/urlobj.hxx>
47 
48 //_______________________________________________
49 // namespace
50 
51 namespace framework{
52 
53 namespace css = ::com::sun::star;
54 
55 //_______________________________________________
56 // definitions
57 
58 static const ::rtl::OUString ERRMSG_INVALID_COMPONENT_PARAM = ::rtl::OUString::createFromAscii("NULL as component reference not allowed.");
59 static const ::rtl::OUString ERRMSG_INVALID_NUMBER_PARAM    = ::rtl::OUString::createFromAscii("Special valkud INVALID_NUMBER not allowed as input parameter.");
60 
61 //-----------------------------------------------
62 TitleHelper::TitleHelper(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR)
63     : ::cppu::BaseMutex ()
64     , m_xSMGR           (xSMGR)
65     , m_xOwner          ()
66     , m_xUntitledNumbers()
67     , m_xSubTitle       ()
68     , m_bExternalTitle  (sal_False)
69     , m_sTitle          ()
70     , m_nLeasedNumber   (css::frame::UntitledNumbersConst::INVALID_NUMBER)
71     , m_aListener       (m_aMutex)
72 {
73 }
74 
75 //-----------------------------------------------
76 TitleHelper::~TitleHelper()
77 {
78 }
79 
80 //-----------------------------------------------
81 void TitleHelper::setOwner(const css::uno::Reference< css::uno::XInterface >& xOwner)
82 {
83     // SYNCHRONIZED ->
84     ::osl::ResettableMutexGuard aLock(m_aMutex);
85 
86         m_xOwner = xOwner;
87 
88     aLock.clear ();
89     // <- SYNCHRONIZED
90 
91     css::uno::Reference< css::frame::XModel > xModel(xOwner, css::uno::UNO_QUERY);
92     if (xModel.is ())
93     {
94         impl_startListeningForModel (xModel);
95         return;
96     }
97 
98     css::uno::Reference< css::frame::XController > xController(xOwner, css::uno::UNO_QUERY);
99     if (xController.is ())
100     {
101         impl_startListeningForController (xController);
102         return;
103     }
104 
105     css::uno::Reference< css::frame::XFrame > xFrame(xOwner, css::uno::UNO_QUERY);
106     if (xFrame.is ())
107     {
108         impl_startListeningForFrame (xFrame);
109         return;
110     }
111 }
112 
113 //-----------------------------------------------
114 ::rtl::OUString SAL_CALL TitleHelper::getTitle()
115     throw (css::uno::RuntimeException)
116 {
117     // SYNCHRONIZED ->
118     ::osl::ResettableMutexGuard aLock(m_aMutex);
119 
120         // An external title will win always and disable all internal logic about
121         // creating/using a title value.
122         // Even an empty string will be accepted as valid title !
123         if (m_bExternalTitle)
124             return m_sTitle;
125 
126         // Title seams to be up-to-date. Return it directly.
127         if (m_sTitle.getLength() > 0)
128             return m_sTitle;
129 
130         // Title seams to be unused till now ... do bootstraping
131         impl_updateTitle ();
132 
133         return m_sTitle;
134 
135     // <- SYNCHRONIZED
136 }
137 
138 //-----------------------------------------------
139 void TitleHelper::connectWithUntitledNumbers (const css::uno::Reference< css::frame::XUntitledNumbers >& xNumbers)
140 {
141     // SYNCHRONIZED ->
142     ::osl::ResettableMutexGuard aLock(m_aMutex);
143 
144         m_xUntitledNumbers = xNumbers;
145 
146     // <- SYNCHRONIZED
147 }
148 
149 //-----------------------------------------------
150 void SAL_CALL TitleHelper::setTitle(const ::rtl::OUString& sTitle)
151     throw (css::uno::RuntimeException)
152 {
153     // SYNCHRONIZED ->
154     ::osl::ResettableMutexGuard aLock(m_aMutex);
155 
156         m_bExternalTitle = sal_True;
157         m_sTitle         = sTitle;
158 
159     aLock.clear ();
160     // <- SYNCHRONIZED
161 
162     impl_sendTitleChangedEvent ();
163 }
164 
165 //-----------------------------------------------
166 void SAL_CALL TitleHelper::addTitleChangeListener(const css::uno::Reference< css::frame::XTitleChangeListener >& xListener)
167     throw (css::uno::RuntimeException)
168 {
169     // container is threadsafe by himself
170     m_aListener.addInterface( ::getCppuType( (const css::uno::Reference< css::frame::XTitleChangeListener >*)NULL ), xListener );
171 }
172 
173 //-----------------------------------------------
174 void SAL_CALL TitleHelper::removeTitleChangeListener(const css::uno::Reference< css::frame::XTitleChangeListener >& xListener)
175     throw (css::uno::RuntimeException)
176 {
177     // container is threadsafe by himself
178     m_aListener.removeInterface( ::getCppuType( (const css::uno::Reference< css::frame::XTitleChangeListener >*)NULL ), xListener );
179 }
180 
181 //-----------------------------------------------
182 void SAL_CALL TitleHelper::titleChanged(const css::frame::TitleChangedEvent& aEvent)
183     throw (css::uno::RuntimeException)
184 {
185     // SYNCHRONIZED ->
186     ::osl::ResettableMutexGuard aLock(m_aMutex);
187 
188         css::uno::Reference< css::frame::XTitle > xSubTitle(m_xSubTitle.get (), css::uno::UNO_QUERY);
189 
190     aLock.clear ();
191     // <- SYNCHRONIZED
192 
193     if (aEvent.Source != xSubTitle)
194         return;
195 
196     impl_updateTitle ();
197 }
198 
199 //-----------------------------------------------
200 void SAL_CALL TitleHelper::notifyEvent(const css::document::EventObject& aEvent)
201     throw (css::uno::RuntimeException)
202 {
203     if ( ! aEvent.EventName.equalsIgnoreAsciiCaseAscii ("OnSaveAsDone")
204       && ! aEvent.EventName.equalsIgnoreAsciiCaseAscii ("OnTitleChanged"))
205         return;
206 
207     // SYNCHRONIZED ->
208     ::osl::ResettableMutexGuard aLock(m_aMutex);
209 
210         css::uno::Reference< css::frame::XModel > xOwner(m_xOwner.get (), css::uno::UNO_QUERY);
211 
212     aLock.clear ();
213     // <- SYNCHRONIZED
214 
215     if (
216          aEvent.Source != xOwner ||
217          (aEvent.EventName.equalsIgnoreAsciiCaseAscii ("OnTitleChanged") && !xOwner.is())
218        )
219     {
220         return;
221     }
222 
223     impl_updateTitle ();
224 }
225 
226 //-----------------------------------------------
227 void SAL_CALL TitleHelper::frameAction(const css::frame::FrameActionEvent& aEvent)
228     throw(css::uno::RuntimeException)
229 {
230     // SYNCHRONIZED ->
231     ::osl::ResettableMutexGuard aLock(m_aMutex);
232 
233         css::uno::Reference< css::frame::XFrame > xOwner(m_xOwner.get (), css::uno::UNO_QUERY);
234 
235     aLock.clear ();
236     // <- SYNCHRONIZED
237 
238 	if (aEvent.Source != xOwner)
239 		return;
240 
241     // we are interested on events only, which must trigger a title bar update
242     // because component was changed.
243     if (
244         (aEvent.Action == css::frame::FrameAction_COMPONENT_ATTACHED  ) ||
245         (aEvent.Action == css::frame::FrameAction_COMPONENT_REATTACHED) ||
246         (aEvent.Action == css::frame::FrameAction_COMPONENT_DETACHING )
247        )
248     {
249 		impl_updateListeningForFrame (xOwner);
250 		impl_updateTitle ();
251     }
252 }
253 
254 //-----------------------------------------------
255 void SAL_CALL TitleHelper::disposing(const css::lang::EventObject& aEvent)
256     throw (css::uno::RuntimeException)
257 {
258     // SYNCHRONIZED ->
259     ::osl::ResettableMutexGuard aLock(m_aMutex);
260         css::uno::Reference< css::uno::XInterface >         xOwner        (m_xOwner.get()          , css::uno::UNO_QUERY);
261         css::uno::Reference< css::frame::XUntitledNumbers > xNumbers      (m_xUntitledNumbers.get(), css::uno::UNO_QUERY);
262         ::sal_Int32                                         nLeasedNumber = m_nLeasedNumber;
263     aLock.clear ();
264     // <- SYNCHRONIZED
265 
266     if ( ! xOwner.is ())
267         return;
268 
269     if (xOwner != aEvent.Source)
270         return;
271 
272     if (
273         (xNumbers.is ()                                                   ) &&
274         (nLeasedNumber != css::frame::UntitledNumbersConst::INVALID_NUMBER)
275        )
276        xNumbers->releaseNumber (nLeasedNumber);
277 
278     // SYNCHRONIZED ->
279     aLock.reset ();
280 
281          m_sTitle        = ::rtl::OUString ();
282          m_nLeasedNumber = css::frame::UntitledNumbersConst::INVALID_NUMBER;
283 
284     aLock.clear ();
285     // <- SYNCHRONIZED
286 
287     impl_sendTitleChangedEvent ();
288 }
289 
290 //-----------------------------------------------
291 void TitleHelper::impl_sendTitleChangedEvent ()
292 {
293     // SYNCHRONIZED ->
294     ::osl::ResettableMutexGuard aLock(m_aMutex);
295 
296         css::frame::TitleChangedEvent aEvent(m_xOwner.get (), m_sTitle);
297 
298     aLock.clear ();
299     // <- SYNCHRONIZED
300 
301     ::cppu::OInterfaceContainerHelper* pContainer = m_aListener.getContainer( ::getCppuType( ( const css::uno::Reference< css::frame::XTitleChangeListener >*) NULL ) );
302 	if ( ! pContainer)
303         return;
304 
305     ::cppu::OInterfaceIteratorHelper pIt( *pContainer );
306     while ( pIt.hasMoreElements() )
307     {
308         try
309         {
310             ((css::frame::XTitleChangeListener*)pIt.next())->titleChanged( aEvent );
311         }
312         catch(const css::uno::Exception&)
313         {
314             pIt.remove();
315         }
316     }
317 }
318 
319 //-----------------------------------------------
320 void TitleHelper::impl_updateTitle ()
321 {
322     // SYNCHRONIZED ->
323     ::osl::ResettableMutexGuard aLock(m_aMutex);
324 
325         css::uno::Reference< css::frame::XModel >      xModel     (m_xOwner.get(), css::uno::UNO_QUERY);
326         css::uno::Reference< css::frame::XController > xController(m_xOwner.get(), css::uno::UNO_QUERY);
327         css::uno::Reference< css::frame::XFrame >      xFrame     (m_xOwner.get(), css::uno::UNO_QUERY);
328 
329     aLock.clear ();
330     // <- SYNCHRONIZED
331 
332     if (xModel.is ())
333     {
334         impl_updateTitleForModel (xModel);
335         return;
336     }
337 
338     if (xController.is ())
339     {
340         impl_updateTitleForController (xController);
341         return;
342     }
343 
344     if (xFrame.is ())
345     {
346         impl_updateTitleForFrame (xFrame);
347         return;
348     }
349 }
350 
351 //-----------------------------------------------
352 void TitleHelper::impl_updateTitleForModel (const css::uno::Reference< css::frame::XModel >& xModel)
353 {
354     // SYNCHRONIZED ->
355     ::osl::ResettableMutexGuard aLock(m_aMutex);
356 
357         // external title wont be updated internaly !
358         // It has to be set from outside new.
359         if (m_bExternalTitle)
360             return;
361 
362         css::uno::Reference< css::uno::XInterface >         xOwner        (m_xOwner.get()          , css::uno::UNO_QUERY);
363         css::uno::Reference< css::frame::XUntitledNumbers > xNumbers      (m_xUntitledNumbers.get(), css::uno::UNO_QUERY);
364         ::sal_Int32                                         nLeasedNumber = m_nLeasedNumber;
365 
366     aLock.clear ();
367     // <- SYNCHRONIZED
368 
369     if (
370         ( ! xOwner.is    ()) ||
371         ( ! xNumbers.is  ()) ||
372         ( ! xModel.is    ())
373        )
374         return;
375 
376     ::rtl::OUString sTitle;
377     ::rtl::OUString sURL  ;
378 
379     css::uno::Reference< css::frame::XStorable > xURLProvider(xModel , css::uno::UNO_QUERY);
380     if (xURLProvider.is())
381         sURL = xURLProvider->getLocation ();
382 
383     if (sURL.getLength () > 0)
384     {
385         sTitle = impl_convertURL2Title(sURL);
386         if (nLeasedNumber != css::frame::UntitledNumbersConst::INVALID_NUMBER)
387             xNumbers->releaseNumber (nLeasedNumber);
388 		nLeasedNumber = css::frame::UntitledNumbersConst::INVALID_NUMBER;
389     }
390     else
391     {
392         if (nLeasedNumber == css::frame::UntitledNumbersConst::INVALID_NUMBER)
393             nLeasedNumber = xNumbers->leaseNumber (xOwner);
394 
395         ::rtl::OUStringBuffer sNewTitle(256);
396         sNewTitle.append (xNumbers->getUntitledPrefix ());
397         if (nLeasedNumber != css::frame::UntitledNumbersConst::INVALID_NUMBER)
398             sNewTitle.append ((::sal_Int32)nLeasedNumber);
399         else
400             sNewTitle.appendAscii ("?");
401 
402         sTitle = sNewTitle.makeStringAndClear ();
403     }
404 
405     // SYNCHRONIZED ->
406     aLock.reset ();
407 
408     // WORKAROUND: the notification is currently sent always,
409     //             can be changed after shared mode is supported per UNO API
410     sal_Bool bChanged        = sal_True; // (! m_sTitle.equals(sTitle));
411 
412              m_sTitle        = sTitle;
413              m_nLeasedNumber = nLeasedNumber;
414 
415     aLock.clear ();
416     // <- SYNCHRONIZED
417 
418     if (bChanged)
419         impl_sendTitleChangedEvent ();
420 }
421 
422 //-----------------------------------------------
423 void TitleHelper::impl_updateTitleForController (const css::uno::Reference< css::frame::XController >& xController)
424 {
425     // SYNCHRONIZED ->
426     ::osl::ResettableMutexGuard aLock(m_aMutex);
427 
428         // external title wont be updated internaly !
429         // It has to be set from outside new.
430         if (m_bExternalTitle)
431             return;
432 
433         css::uno::Reference< css::uno::XInterface >         xOwner        (m_xOwner.get()          , css::uno::UNO_QUERY);
434         css::uno::Reference< css::frame::XUntitledNumbers > xNumbers      (m_xUntitledNumbers.get(), css::uno::UNO_QUERY);
435         ::sal_Int32                                         nLeasedNumber = m_nLeasedNumber;
436 
437     aLock.clear ();
438     // <- SYNCHRONIZED
439 
440     if (
441         ( ! xOwner.is      ()) ||
442         ( ! xNumbers.is    ()) ||
443         ( ! xController.is ())
444        )
445         return;
446 
447     ::rtl::OUStringBuffer sTitle(256);
448 
449     if (nLeasedNumber == css::frame::UntitledNumbersConst::INVALID_NUMBER)
450         nLeasedNumber = xNumbers->leaseNumber (xOwner);
451 
452     css::uno::Reference< css::frame::XTitle > xModelTitle(xController->getModel (), css::uno::UNO_QUERY);
453     if (!xModelTitle.is ())
454         xModelTitle.set(xController, css::uno::UNO_QUERY);
455     if (xModelTitle.is ())
456     {
457         sTitle.append      (xModelTitle->getTitle ());
458         if ( nLeasedNumber > 1 )
459         {
460             sTitle.appendAscii (" : ");
461             sTitle.append      ((::sal_Int32)nLeasedNumber);
462         }
463     }
464     else
465     {
466         sTitle.append (xNumbers->getUntitledPrefix ());
467         if ( nLeasedNumber > 1 )
468         {
469             sTitle.append ((::sal_Int32)nLeasedNumber  );
470         }
471     }
472 
473     // SYNCHRONIZED ->
474     aLock.reset ();
475 
476         ::rtl::OUString sNewTitle       = sTitle.makeStringAndClear ();
477         sal_Bool        bChanged        = (! m_sTitle.equals(sNewTitle));
478                         m_sTitle        = sNewTitle;
479                         m_nLeasedNumber = nLeasedNumber;
480 
481     aLock.clear ();
482     // <- SYNCHRONIZED
483 
484     if (bChanged)
485         impl_sendTitleChangedEvent ();
486 }
487 
488 //-----------------------------------------------
489 void TitleHelper::impl_updateTitleForFrame (const css::uno::Reference< css::frame::XFrame >& xFrame)
490 {
491     if ( ! xFrame.is ())
492         return;
493 
494     // SYNCHRONIZED ->
495     ::osl::ResettableMutexGuard aLock(m_aMutex);
496 
497         // external title wont be updated internaly !
498         // It has to be set from outside new.
499         if (m_bExternalTitle)
500             return;
501 
502     aLock.clear ();
503     // <- SYNCHRONIZED
504 
505     css::uno::Reference< css::uno::XInterface > xComponent;
506     xComponent = xFrame->getController ();
507     if ( ! xComponent.is ())
508         xComponent = xFrame->getComponentWindow ();
509 
510     ::rtl::OUStringBuffer sTitle (256);
511 
512     impl_appendComponentTitle   (sTitle, xComponent);
513     impl_appendProductName      (sTitle);
514     impl_appendModuleName       (sTitle);
515     impl_appendProductExtension (sTitle);
516     //impl_appendEvalVersion      (sTitle);
517     impl_appendDebugVersion     (sTitle);
518 
519     // SYNCHRONIZED ->
520     aLock.reset ();
521 
522         ::rtl::OUString sNewTitle = sTitle.makeStringAndClear ();
523         sal_Bool        bChanged  = (! m_sTitle.equals(sNewTitle));
524                         m_sTitle  = sNewTitle;
525 
526     aLock.clear ();
527     // <- SYNCHRONIZED
528 
529     if (bChanged)
530         impl_sendTitleChangedEvent ();
531 }
532 
533 //*****************************************************************************************************************
534 void TitleHelper::impl_appendComponentTitle (      ::rtl::OUStringBuffer&                       sTitle    ,
535                                              const css::uno::Reference< css::uno::XInterface >& xComponent)
536 {
537     css::uno::Reference< css::frame::XTitle > xTitle(xComponent, css::uno::UNO_QUERY);
538 
539 	// Note: Title has to be used (even if it's empty) if the right interface is supported.
540     if (xTitle.is ())
541         sTitle.append (xTitle->getTitle ());
542 }
543 
544 //*****************************************************************************************************************
545 void TitleHelper::impl_appendProductName (::rtl::OUStringBuffer& sTitle)
546 {
547     ::rtl::OUString sProductName;
548     ::utl::ConfigManager::GetDirectConfigProperty(::utl::ConfigManager::PRODUCTNAME) >>= sProductName;
549 
550     if (sProductName.getLength ())
551     {
552         if (sTitle.getLength() > 0)
553             sTitle.appendAscii (" - ");
554 
555         sTitle.append (sProductName);
556     }
557 }
558 
559 //*****************************************************************************************************************
560 void TitleHelper::impl_appendProductExtension (::rtl::OUStringBuffer& sTitle)
561 {
562     ::rtl::OUString sProductExtension;
563     ::utl::ConfigManager::GetDirectConfigProperty(::utl::ConfigManager::PRODUCTEXTENSION) >>= sProductExtension;
564 
565     if (sProductExtension.getLength ())
566     {
567         sTitle.appendAscii (" ");
568         sTitle.append      (sProductExtension);
569     }
570 }
571 
572 //*****************************************************************************************************************
573 void TitleHelper::impl_appendModuleName (::rtl::OUStringBuffer& sTitle)
574 {
575     // SYNCHRONIZED ->
576     ::osl::ResettableMutexGuard aLock(m_aMutex);
577 
578         css::uno::Reference< css::uno::XInterface >            xOwner = m_xOwner.get();
579         css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR  = m_xSMGR;
580 
581     aLock.clear ();
582     // <- SYNCHRONIZED
583 
584     try
585     {
586         css::uno::Reference< css::frame::XModuleManager > xModuleManager(
587             xSMGR->createInstance(SERVICENAME_MODULEMANAGER),
588             css::uno::UNO_QUERY_THROW);
589 
590         css::uno::Reference< css::container::XNameAccess > xConfig(
591             xModuleManager,
592             css::uno::UNO_QUERY_THROW);
593 
594         const ::rtl::OUString                 sID     = xModuleManager->identify(xOwner);
595               ::comphelper::SequenceAsHashMap lProps  = xConfig->getByName (sID);
596         const ::rtl::OUString                 sUIName = lProps.getUnpackedValueOrDefault (OFFICEFACTORY_PROPNAME_UINAME, ::rtl::OUString());
597 
598         // An UIname property is an optional value !
599         // So please add it to the title in case it does realy exists only.
600         if (sUIName.getLength() > 0)
601         {
602             sTitle.appendAscii (" "    );
603             sTitle.append      (sUIName);
604         }
605     }
606     catch(const css::uno::Exception&)
607     {}
608 }
609 
610 //*****************************************************************************************************************
611 #ifdef DBG_UTIL
612 void TitleHelper::impl_appendDebugVersion (::rtl::OUStringBuffer& sTitle)
613 {
614         ::rtl::OUString sDefault ;
615 		::rtl::OUString sVersion = ::utl::Bootstrap::getBuildIdData( sDefault );
616 
617 		sTitle.appendAscii (" ["    );
618 		sTitle.append      (sVersion);
619 		sTitle.appendAscii ("]"     );
620 }
621 #else
622 void TitleHelper::impl_appendDebugVersion (::rtl::OUStringBuffer&)
623 {
624 }
625 #endif
626 
627 //*****************************************************************************************************************
628 void TitleHelper::impl_appendEvalVersion (::rtl::OUStringBuffer& /*sTitle*/)
629 {
630     // SYNCHRONIZED ->
631  //   ::osl::ResettableMutexGuard aLock(m_aMutex);
632  //   css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR ;
633 	//aLock.clear ();
634 	//// <- SYNCHRONIZED
635 
636 	//css::uno::Reference< css::beans::XMaterialHolder > xHolder(
637  //       xSMGR->createInstance(SERVICENAME_TABREG),
638 	//	css::uno::UNO_QUERY);
639 
640  //   if ( ! xHolder.is())
641 	//	return;
642 
643 	//	  ::comphelper::SequenceAsHashMap aMaterial(xHolder->getMaterial());
644 	//const ::rtl::OUString				  sEvalTitle = aMaterial.getUnpackedValueOrDefault(TABREG_PROPNAME_TITLE, ::rtl::OUString());
645 
646 	//if (sEvalTitle.getLength())
647 	//{
648 	//	sTitle.appendAscii (" "		  );
649 	//	sTitle.append	   (sEvalTitle);
650 	//}
651 }
652 
653 //-----------------------------------------------
654 void TitleHelper::impl_startListeningForModel (const css::uno::Reference< css::frame::XModel >& xModel)
655 {
656     css::uno::Reference< css::document::XEventBroadcaster > xBroadcaster(xModel, css::uno::UNO_QUERY);
657     if ( ! xBroadcaster.is ())
658         return;
659 
660     xBroadcaster->addEventListener (static_cast< css::document::XEventListener* >(this));
661 }
662 
663 //-----------------------------------------------
664 void TitleHelper::impl_startListeningForController (const css::uno::Reference< css::frame::XController >& xController)
665 {
666     css::uno::Reference< css::frame::XTitle > xSubTitle(xController->getModel (), css::uno::UNO_QUERY);
667     impl_setSubTitle (xSubTitle);
668 }
669 
670 //-----------------------------------------------
671 void TitleHelper::impl_startListeningForFrame (const css::uno::Reference< css::frame::XFrame >& xFrame)
672 {
673 	xFrame->addFrameActionListener(this  );
674 	impl_updateListeningForFrame  (xFrame);
675 }
676 
677 //-----------------------------------------------
678 void TitleHelper::impl_updateListeningForFrame (const css::uno::Reference< css::frame::XFrame >& xFrame)
679 {
680     css::uno::Reference< css::frame::XTitle > xSubTitle(xFrame->getController (), css::uno::UNO_QUERY);
681     impl_setSubTitle (xSubTitle);
682 }
683 
684 //-----------------------------------------------
685 void TitleHelper::impl_setSubTitle (const css::uno::Reference< css::frame::XTitle >& xSubTitle)
686 {
687     // SYNCHRONIZED ->
688     ::osl::ResettableMutexGuard aLock(m_aMutex);
689 
690         // ignore duplicate calls. Makes outside using of this helper more easy :-)
691         css::uno::Reference< css::frame::XTitle > xOldSubTitle(m_xSubTitle.get(), css::uno::UNO_QUERY);
692         if (xOldSubTitle == xSubTitle)
693             return;
694 
695         m_xSubTitle = xSubTitle;
696 
697     aLock.clear ();
698     // <- SYNCHRONIZED
699 
700     css::uno::Reference< css::frame::XTitleChangeBroadcaster > xOldBroadcaster(xOldSubTitle                                          , css::uno::UNO_QUERY      );
701     css::uno::Reference< css::frame::XTitleChangeBroadcaster > xNewBroadcaster(xSubTitle                                             , css::uno::UNO_QUERY      );
702     css::uno::Reference< css::frame::XTitleChangeListener >    xThis          (static_cast< css::frame::XTitleChangeListener* >(this), css::uno::UNO_QUERY_THROW);
703 
704     if (xOldBroadcaster.is())
705         xOldBroadcaster->removeTitleChangeListener (xThis);
706 
707     if (xNewBroadcaster.is())
708         xNewBroadcaster->addTitleChangeListener (xThis);
709 }
710 
711 //-----------------------------------------------
712 ::rtl::OUString TitleHelper::impl_getSubTitle ()
713 {
714     // SYNCHRONIZED ->
715     ::osl::ResettableMutexGuard aLock(m_aMutex);
716 
717         css::uno::Reference< css::frame::XTitle > xSubTitle(m_xSubTitle.get (), css::uno::UNO_QUERY);
718 
719     aLock.clear ();
720     // <- SYNCHRONIZED
721 
722     if (xSubTitle.is ())
723         return xSubTitle->getTitle ();
724 
725     return ::rtl::OUString ();
726 }
727 
728 //-----------------------------------------------
729 ::rtl::OUString TitleHelper::impl_convertURL2Title(const ::rtl::OUString& sURL)
730 {
731     INetURLObject   aURL (sURL);
732     ::rtl::OUString sTitle;
733 
734     if (aURL.GetProtocol() == INET_PROT_FILE)
735     {
736         if (aURL.HasMark())
737             aURL = INetURLObject(aURL.GetURLNoMark());
738 
739         sTitle = aURL.getName(INetURLObject::LAST_SEGMENT, sal_True, INetURLObject::DECODE_WITH_CHARSET);
740     }
741     else
742     {
743         if (aURL.hasExtension(INetURLObject::LAST_SEGMENT))
744             sTitle = aURL.getName(INetURLObject::LAST_SEGMENT, sal_True, INetURLObject::DECODE_WITH_CHARSET);
745 
746         if ( ! sTitle.getLength() )
747 		    sTitle = aURL.GetHostPort(INetURLObject::DECODE_WITH_CHARSET);
748 
749         if ( ! sTitle.getLength() )
750             sTitle = aURL.GetURLNoPass(INetURLObject::DECODE_WITH_CHARSET);
751     }
752 
753     return sTitle;
754 }
755 
756 } // namespace framework
757