xref: /trunk/main/framework/source/fwe/helper/titlehelper.cxx (revision 45c5a00162811bd03b87fcb4fe9996782f2b59ec)
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 {
116     // SYNCHRONIZED ->
117     ::osl::ResettableMutexGuard aLock(m_aMutex);
118 
119         // An external title will win always and disable all internal logic about
120         // creating/using a title value.
121         // Even an empty string will be accepted as valid title !
122         if (m_bExternalTitle)
123             return m_sTitle;
124 
125         // Title seems to be up-to-date. Return it directly.
126         if (m_sTitle.getLength() > 0)
127             return m_sTitle;
128 
129         // Title seems to be unused till now ... do bootstraping
130         impl_updateTitle ();
131 
132         return m_sTitle;
133 
134     // <- SYNCHRONIZED
135 }
136 
137 //-----------------------------------------------
138 void TitleHelper::connectWithUntitledNumbers (const css::uno::Reference< css::frame::XUntitledNumbers >& xNumbers)
139 {
140     // SYNCHRONIZED ->
141     ::osl::ResettableMutexGuard aLock(m_aMutex);
142 
143         m_xUntitledNumbers = xNumbers;
144 
145     // <- SYNCHRONIZED
146 }
147 
148 //-----------------------------------------------
149 void SAL_CALL TitleHelper::setTitle(const ::rtl::OUString& sTitle)
150 {
151     // SYNCHRONIZED ->
152     ::osl::ResettableMutexGuard aLock(m_aMutex);
153 
154         m_bExternalTitle = sal_True;
155         m_sTitle         = sTitle;
156 
157     aLock.clear ();
158     // <- SYNCHRONIZED
159 
160     impl_sendTitleChangedEvent ();
161 }
162 
163 //-----------------------------------------------
164 void SAL_CALL TitleHelper::addTitleChangeListener(const css::uno::Reference< css::frame::XTitleChangeListener >& xListener)
165 {
166     // container is threadsafe by himself
167     m_aListener.addInterface( ::getCppuType( (const css::uno::Reference< css::frame::XTitleChangeListener >*)NULL ), xListener );
168 }
169 
170 //-----------------------------------------------
171 void SAL_CALL TitleHelper::removeTitleChangeListener(const css::uno::Reference< css::frame::XTitleChangeListener >& xListener)
172 {
173     // container is threadsafe by himself
174     m_aListener.removeInterface( ::getCppuType( (const css::uno::Reference< css::frame::XTitleChangeListener >*)NULL ), xListener );
175 }
176 
177 //-----------------------------------------------
178 void SAL_CALL TitleHelper::titleChanged(const css::frame::TitleChangedEvent& aEvent)
179 {
180     // SYNCHRONIZED ->
181     ::osl::ResettableMutexGuard aLock(m_aMutex);
182 
183         css::uno::Reference< css::frame::XTitle > xSubTitle(m_xSubTitle.get (), css::uno::UNO_QUERY);
184 
185     aLock.clear ();
186     // <- SYNCHRONIZED
187 
188     if (aEvent.Source != xSubTitle)
189         return;
190 
191     impl_updateTitle ();
192 }
193 
194 //-----------------------------------------------
195 void SAL_CALL TitleHelper::notifyEvent(const css::document::EventObject& aEvent)
196 {
197     if ( ! aEvent.EventName.equalsIgnoreAsciiCaseAscii ("OnSaveAsDone")
198       && ! aEvent.EventName.equalsIgnoreAsciiCaseAscii ("OnTitleChanged"))
199         return;
200 
201     // SYNCHRONIZED ->
202     ::osl::ResettableMutexGuard aLock(m_aMutex);
203 
204         css::uno::Reference< css::frame::XModel > xOwner(m_xOwner.get (), css::uno::UNO_QUERY);
205 
206     aLock.clear ();
207     // <- SYNCHRONIZED
208 
209     if (
210          aEvent.Source != xOwner ||
211          (aEvent.EventName.equalsIgnoreAsciiCaseAscii ("OnTitleChanged") && !xOwner.is())
212        )
213     {
214         return;
215     }
216 
217     impl_updateTitle ();
218 }
219 
220 //-----------------------------------------------
221 void SAL_CALL TitleHelper::frameAction(const css::frame::FrameActionEvent& aEvent)
222 {
223     // SYNCHRONIZED ->
224     ::osl::ResettableMutexGuard aLock(m_aMutex);
225 
226         css::uno::Reference< css::frame::XFrame > xOwner(m_xOwner.get (), css::uno::UNO_QUERY);
227 
228     aLock.clear ();
229     // <- SYNCHRONIZED
230 
231     if (aEvent.Source != xOwner)
232         return;
233 
234     // we are interested on events only, which must trigger a title bar update
235     // because component was changed.
236     if (
237         (aEvent.Action == css::frame::FrameAction_COMPONENT_ATTACHED  ) ||
238         (aEvent.Action == css::frame::FrameAction_COMPONENT_REATTACHED) ||
239         (aEvent.Action == css::frame::FrameAction_COMPONENT_DETACHING )
240        )
241     {
242         impl_updateListeningForFrame (xOwner);
243         impl_updateTitle ();
244     }
245 }
246 
247 //-----------------------------------------------
248 void SAL_CALL TitleHelper::disposing(const css::lang::EventObject& aEvent)
249 {
250     // SYNCHRONIZED ->
251     ::osl::ResettableMutexGuard aLock(m_aMutex);
252         css::uno::Reference< css::uno::XInterface >         xOwner        (m_xOwner.get()          , css::uno::UNO_QUERY);
253         css::uno::Reference< css::frame::XUntitledNumbers > xNumbers      (m_xUntitledNumbers.get(), css::uno::UNO_QUERY);
254         ::sal_Int32                                         nLeasedNumber = m_nLeasedNumber;
255     aLock.clear ();
256     // <- SYNCHRONIZED
257 
258     if ( ! xOwner.is ())
259         return;
260 
261     if (xOwner != aEvent.Source)
262         return;
263 
264     if (
265         (xNumbers.is ()                                                   ) &&
266         (nLeasedNumber != css::frame::UntitledNumbersConst::INVALID_NUMBER)
267        )
268        xNumbers->releaseNumber (nLeasedNumber);
269 
270     // SYNCHRONIZED ->
271     aLock.reset ();
272 
273          m_sTitle        = ::rtl::OUString ();
274          m_nLeasedNumber = css::frame::UntitledNumbersConst::INVALID_NUMBER;
275 
276     aLock.clear ();
277     // <- SYNCHRONIZED
278 
279     impl_sendTitleChangedEvent ();
280 }
281 
282 //-----------------------------------------------
283 void TitleHelper::impl_sendTitleChangedEvent ()
284 {
285     // SYNCHRONIZED ->
286     ::osl::ResettableMutexGuard aLock(m_aMutex);
287 
288         css::frame::TitleChangedEvent aEvent(m_xOwner.get (), m_sTitle);
289 
290     aLock.clear ();
291     // <- SYNCHRONIZED
292 
293     ::cppu::OInterfaceContainerHelper* pContainer = m_aListener.getContainer( ::getCppuType( ( const css::uno::Reference< css::frame::XTitleChangeListener >*) NULL ) );
294     if ( ! pContainer)
295         return;
296 
297     ::cppu::OInterfaceIteratorHelper pIt( *pContainer );
298     while ( pIt.hasMoreElements() )
299     {
300         try
301         {
302             ((css::frame::XTitleChangeListener*)pIt.next())->titleChanged( aEvent );
303         }
304         catch(const css::uno::Exception&)
305         {
306             pIt.remove();
307         }
308     }
309 }
310 
311 //-----------------------------------------------
312 void TitleHelper::impl_updateTitle ()
313 {
314     // SYNCHRONIZED ->
315     ::osl::ResettableMutexGuard aLock(m_aMutex);
316 
317         css::uno::Reference< css::frame::XModel >      xModel     (m_xOwner.get(), css::uno::UNO_QUERY);
318         css::uno::Reference< css::frame::XController > xController(m_xOwner.get(), css::uno::UNO_QUERY);
319         css::uno::Reference< css::frame::XFrame >      xFrame     (m_xOwner.get(), css::uno::UNO_QUERY);
320 
321     aLock.clear ();
322     // <- SYNCHRONIZED
323 
324     if (xModel.is ())
325     {
326         impl_updateTitleForModel (xModel);
327         return;
328     }
329 
330     if (xController.is ())
331     {
332         impl_updateTitleForController (xController);
333         return;
334     }
335 
336     if (xFrame.is ())
337     {
338         impl_updateTitleForFrame (xFrame);
339         return;
340     }
341 }
342 
343 //-----------------------------------------------
344 void TitleHelper::impl_updateTitleForModel (const css::uno::Reference< css::frame::XModel >& xModel)
345 {
346     // SYNCHRONIZED ->
347     ::osl::ResettableMutexGuard aLock(m_aMutex);
348 
349         // external title won't be updated internally !
350         // It has to be set from outside new.
351         if (m_bExternalTitle)
352             return;
353 
354         css::uno::Reference< css::uno::XInterface >         xOwner        (m_xOwner.get()          , css::uno::UNO_QUERY);
355         css::uno::Reference< css::frame::XUntitledNumbers > xNumbers      (m_xUntitledNumbers.get(), css::uno::UNO_QUERY);
356         ::sal_Int32                                         nLeasedNumber = m_nLeasedNumber;
357 
358     aLock.clear ();
359     // <- SYNCHRONIZED
360 
361     if (
362         ( ! xOwner.is    ()) ||
363         ( ! xNumbers.is  ()) ||
364         ( ! xModel.is    ())
365        )
366         return;
367 
368     ::rtl::OUString sTitle;
369     ::rtl::OUString sURL  ;
370 
371     css::uno::Reference< css::frame::XStorable > xURLProvider(xModel , css::uno::UNO_QUERY);
372     if (xURLProvider.is())
373         sURL = xURLProvider->getLocation ();
374 
375     if (sURL.getLength () > 0)
376     {
377         sTitle = impl_convertURL2Title(sURL);
378         if (nLeasedNumber != css::frame::UntitledNumbersConst::INVALID_NUMBER)
379             xNumbers->releaseNumber (nLeasedNumber);
380         nLeasedNumber = css::frame::UntitledNumbersConst::INVALID_NUMBER;
381     }
382     else
383     {
384         if (nLeasedNumber == css::frame::UntitledNumbersConst::INVALID_NUMBER)
385             nLeasedNumber = xNumbers->leaseNumber (xOwner);
386 
387         ::rtl::OUStringBuffer sNewTitle(256);
388         sNewTitle.append (xNumbers->getUntitledPrefix ());
389         if (nLeasedNumber != css::frame::UntitledNumbersConst::INVALID_NUMBER)
390             sNewTitle.append ((::sal_Int32)nLeasedNumber);
391         else
392             sNewTitle.appendAscii ("?");
393 
394         sTitle = sNewTitle.makeStringAndClear ();
395     }
396 
397     // SYNCHRONIZED ->
398     aLock.reset ();
399 
400     // WORKAROUND: the notification is currently sent always,
401     //             can be changed after shared mode is supported per UNO API
402     sal_Bool bChanged        = sal_True; // (! m_sTitle.equals(sTitle));
403 
404              m_sTitle        = sTitle;
405              m_nLeasedNumber = nLeasedNumber;
406 
407     aLock.clear ();
408     // <- SYNCHRONIZED
409 
410     if (bChanged)
411         impl_sendTitleChangedEvent ();
412 }
413 
414 //-----------------------------------------------
415 void TitleHelper::impl_updateTitleForController (const css::uno::Reference< css::frame::XController >& xController)
416 {
417     // SYNCHRONIZED ->
418     ::osl::ResettableMutexGuard aLock(m_aMutex);
419 
420         // external title won't be updated internally !
421         // It has to be set from outside new.
422         if (m_bExternalTitle)
423             return;
424 
425         css::uno::Reference< css::uno::XInterface >         xOwner        (m_xOwner.get()          , css::uno::UNO_QUERY);
426         css::uno::Reference< css::frame::XUntitledNumbers > xNumbers      (m_xUntitledNumbers.get(), css::uno::UNO_QUERY);
427         ::sal_Int32                                         nLeasedNumber = m_nLeasedNumber;
428 
429     aLock.clear ();
430     // <- SYNCHRONIZED
431 
432     if (
433         ( ! xOwner.is      ()) ||
434         ( ! xNumbers.is    ()) ||
435         ( ! xController.is ())
436        )
437         return;
438 
439     ::rtl::OUStringBuffer sTitle(256);
440 
441     if (nLeasedNumber == css::frame::UntitledNumbersConst::INVALID_NUMBER)
442         nLeasedNumber = xNumbers->leaseNumber (xOwner);
443 
444     css::uno::Reference< css::frame::XTitle > xModelTitle(xController->getModel (), css::uno::UNO_QUERY);
445     if (!xModelTitle.is ())
446         xModelTitle.set(xController, css::uno::UNO_QUERY);
447     if (xModelTitle.is ())
448     {
449         sTitle.append      (xModelTitle->getTitle ());
450         if ( nLeasedNumber > 1 )
451         {
452             sTitle.appendAscii (" : ");
453             sTitle.append      ((::sal_Int32)nLeasedNumber);
454         }
455     }
456     else
457     {
458         sTitle.append (xNumbers->getUntitledPrefix ());
459         if ( nLeasedNumber > 1 )
460         {
461             sTitle.append ((::sal_Int32)nLeasedNumber  );
462         }
463     }
464 
465     // SYNCHRONIZED ->
466     aLock.reset ();
467 
468         ::rtl::OUString sNewTitle       = sTitle.makeStringAndClear ();
469         sal_Bool        bChanged        = (! m_sTitle.equals(sNewTitle));
470                         m_sTitle        = sNewTitle;
471                         m_nLeasedNumber = nLeasedNumber;
472 
473     aLock.clear ();
474     // <- SYNCHRONIZED
475 
476     if (bChanged)
477         impl_sendTitleChangedEvent ();
478 }
479 
480 //-----------------------------------------------
481 void TitleHelper::impl_updateTitleForFrame (const css::uno::Reference< css::frame::XFrame >& xFrame)
482 {
483     if ( ! xFrame.is ())
484         return;
485 
486     // SYNCHRONIZED ->
487     ::osl::ResettableMutexGuard aLock(m_aMutex);
488 
489         // external title won't be updated internally !
490         // It has to be set from outside new.
491         if (m_bExternalTitle)
492             return;
493 
494     aLock.clear ();
495     // <- SYNCHRONIZED
496 
497     css::uno::Reference< css::uno::XInterface > xComponent;
498     xComponent = xFrame->getController ();
499     if ( ! xComponent.is ())
500         xComponent = xFrame->getComponentWindow ();
501 
502     ::rtl::OUStringBuffer sTitle (256);
503 
504     impl_appendComponentTitle   (sTitle, xComponent);
505     impl_appendProductName      (sTitle);
506     impl_appendModuleName       (sTitle);
507     impl_appendProductExtension (sTitle);
508     //impl_appendEvalVersion      (sTitle);
509     impl_appendDebugVersion     (sTitle);
510 
511     // SYNCHRONIZED ->
512     aLock.reset ();
513 
514         ::rtl::OUString sNewTitle = sTitle.makeStringAndClear ();
515         sal_Bool        bChanged  = (! m_sTitle.equals(sNewTitle));
516                         m_sTitle  = sNewTitle;
517 
518     aLock.clear ();
519     // <- SYNCHRONIZED
520 
521     if (bChanged)
522         impl_sendTitleChangedEvent ();
523 }
524 
525 //*****************************************************************************************************************
526 void TitleHelper::impl_appendComponentTitle (      ::rtl::OUStringBuffer&                       sTitle    ,
527                                              const css::uno::Reference< css::uno::XInterface >& xComponent)
528 {
529     css::uno::Reference< css::frame::XTitle > xTitle(xComponent, css::uno::UNO_QUERY);
530 
531     // Note: Title has to be used (even if it's empty) if the right interface is supported.
532     if (xTitle.is ())
533         sTitle.append (xTitle->getTitle ());
534 }
535 
536 //*****************************************************************************************************************
537 void TitleHelper::impl_appendProductName (::rtl::OUStringBuffer& sTitle)
538 {
539     ::rtl::OUString sProductName;
540     ::utl::ConfigManager::GetDirectConfigProperty(::utl::ConfigManager::PRODUCTNAME) >>= sProductName;
541 
542     if (sProductName.getLength ())
543     {
544         if (sTitle.getLength() > 0)
545             sTitle.appendAscii (" - ");
546 
547         sTitle.append (sProductName);
548     }
549 }
550 
551 //*****************************************************************************************************************
552 void TitleHelper::impl_appendProductExtension (::rtl::OUStringBuffer& sTitle)
553 {
554     ::rtl::OUString sProductExtension;
555     ::utl::ConfigManager::GetDirectConfigProperty(::utl::ConfigManager::PRODUCTEXTENSION) >>= sProductExtension;
556 
557     if (sProductExtension.getLength ())
558     {
559         sTitle.appendAscii (" ");
560         sTitle.append      (sProductExtension);
561     }
562 }
563 
564 //*****************************************************************************************************************
565 void TitleHelper::impl_appendModuleName (::rtl::OUStringBuffer& sTitle)
566 {
567     // SYNCHRONIZED ->
568     ::osl::ResettableMutexGuard aLock(m_aMutex);
569 
570         css::uno::Reference< css::uno::XInterface >            xOwner = m_xOwner.get();
571         css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR  = m_xSMGR;
572 
573     aLock.clear ();
574     // <- SYNCHRONIZED
575 
576     try
577     {
578         css::uno::Reference< css::frame::XModuleManager > xModuleManager(
579             xSMGR->createInstance(SERVICENAME_MODULEMANAGER),
580             css::uno::UNO_QUERY_THROW);
581 
582         css::uno::Reference< css::container::XNameAccess > xConfig(
583             xModuleManager,
584             css::uno::UNO_QUERY_THROW);
585 
586         const ::rtl::OUString                 sID     = xModuleManager->identify(xOwner);
587               ::comphelper::SequenceAsHashMap lProps  = xConfig->getByName (sID);
588         const ::rtl::OUString                 sUIName = lProps.getUnpackedValueOrDefault (OFFICEFACTORY_PROPNAME_UINAME, ::rtl::OUString());
589 
590         // An UIname property is an optional value !
591         // So please add it to the title in case it does really exists only.
592         if (sUIName.getLength() > 0)
593         {
594             sTitle.appendAscii (" "    );
595             sTitle.append      (sUIName);
596         }
597     }
598     catch(const css::uno::Exception&)
599     {}
600 }
601 
602 //*****************************************************************************************************************
603 #ifdef DBG_UTIL
604 void TitleHelper::impl_appendDebugVersion (::rtl::OUStringBuffer& sTitle)
605 {
606         ::rtl::OUString sDefault ;
607         ::rtl::OUString sVersion = ::utl::Bootstrap::getBuildIdData( sDefault );
608 
609         sTitle.appendAscii (" ["    );
610         sTitle.append      (sVersion);
611         sTitle.appendAscii ("]"     );
612 }
613 #else
614 void TitleHelper::impl_appendDebugVersion (::rtl::OUStringBuffer&)
615 {
616 }
617 #endif
618 
619 //*****************************************************************************************************************
620 void TitleHelper::impl_appendEvalVersion (::rtl::OUStringBuffer& /*sTitle*/)
621 {
622     // SYNCHRONIZED ->
623  //   ::osl::ResettableMutexGuard aLock(m_aMutex);
624  //   css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR ;
625     //aLock.clear ();
626     //// <- SYNCHRONIZED
627 
628     //css::uno::Reference< css::beans::XMaterialHolder > xHolder(
629  //       xSMGR->createInstance(SERVICENAME_TABREG),
630     //  css::uno::UNO_QUERY);
631 
632  //   if ( ! xHolder.is())
633     //  return;
634 
635     //    ::comphelper::SequenceAsHashMap aMaterial(xHolder->getMaterial());
636     //const ::rtl::OUString               sEvalTitle = aMaterial.getUnpackedValueOrDefault(TABREG_PROPNAME_TITLE, ::rtl::OUString());
637 
638     //if (sEvalTitle.getLength())
639     //{
640     //  sTitle.appendAscii (" "       );
641     //  sTitle.append      (sEvalTitle);
642     //}
643 }
644 
645 //-----------------------------------------------
646 void TitleHelper::impl_startListeningForModel (const css::uno::Reference< css::frame::XModel >& xModel)
647 {
648     css::uno::Reference< css::document::XEventBroadcaster > xBroadcaster(xModel, css::uno::UNO_QUERY);
649     if ( ! xBroadcaster.is ())
650         return;
651 
652     xBroadcaster->addEventListener (static_cast< css::document::XEventListener* >(this));
653 }
654 
655 //-----------------------------------------------
656 void TitleHelper::impl_startListeningForController (const css::uno::Reference< css::frame::XController >& xController)
657 {
658     css::uno::Reference< css::frame::XTitle > xSubTitle(xController->getModel (), css::uno::UNO_QUERY);
659     impl_setSubTitle (xSubTitle);
660 }
661 
662 //-----------------------------------------------
663 void TitleHelper::impl_startListeningForFrame (const css::uno::Reference< css::frame::XFrame >& xFrame)
664 {
665     xFrame->addFrameActionListener(this  );
666     impl_updateListeningForFrame  (xFrame);
667 }
668 
669 //-----------------------------------------------
670 void TitleHelper::impl_updateListeningForFrame (const css::uno::Reference< css::frame::XFrame >& xFrame)
671 {
672     css::uno::Reference< css::frame::XTitle > xSubTitle(xFrame->getController (), css::uno::UNO_QUERY);
673     impl_setSubTitle (xSubTitle);
674 }
675 
676 //-----------------------------------------------
677 void TitleHelper::impl_setSubTitle (const css::uno::Reference< css::frame::XTitle >& xSubTitle)
678 {
679     // SYNCHRONIZED ->
680     ::osl::ResettableMutexGuard aLock(m_aMutex);
681 
682         // ignore duplicate calls. Makes outside using of this helper more easy :-)
683         css::uno::Reference< css::frame::XTitle > xOldSubTitle(m_xSubTitle.get(), css::uno::UNO_QUERY);
684         if (xOldSubTitle == xSubTitle)
685             return;
686 
687         m_xSubTitle = xSubTitle;
688 
689     aLock.clear ();
690     // <- SYNCHRONIZED
691 
692     css::uno::Reference< css::frame::XTitleChangeBroadcaster > xOldBroadcaster(xOldSubTitle                                          , css::uno::UNO_QUERY      );
693     css::uno::Reference< css::frame::XTitleChangeBroadcaster > xNewBroadcaster(xSubTitle                                             , css::uno::UNO_QUERY      );
694     css::uno::Reference< css::frame::XTitleChangeListener >    xThis          (static_cast< css::frame::XTitleChangeListener* >(this), css::uno::UNO_QUERY_THROW);
695 
696     if (xOldBroadcaster.is())
697         xOldBroadcaster->removeTitleChangeListener (xThis);
698 
699     if (xNewBroadcaster.is())
700         xNewBroadcaster->addTitleChangeListener (xThis);
701 }
702 
703 //-----------------------------------------------
704 ::rtl::OUString TitleHelper::impl_getSubTitle ()
705 {
706     // SYNCHRONIZED ->
707     ::osl::ResettableMutexGuard aLock(m_aMutex);
708 
709         css::uno::Reference< css::frame::XTitle > xSubTitle(m_xSubTitle.get (), css::uno::UNO_QUERY);
710 
711     aLock.clear ();
712     // <- SYNCHRONIZED
713 
714     if (xSubTitle.is ())
715         return xSubTitle->getTitle ();
716 
717     return ::rtl::OUString ();
718 }
719 
720 //-----------------------------------------------
721 ::rtl::OUString TitleHelper::impl_convertURL2Title(const ::rtl::OUString& sURL)
722 {
723     INetURLObject   aURL (sURL);
724     ::rtl::OUString sTitle;
725 
726     if (aURL.GetProtocol() == INET_PROT_FILE)
727     {
728         if (aURL.HasMark())
729             aURL = INetURLObject(aURL.GetURLNoMark());
730 
731         sTitle = aURL.getName(INetURLObject::LAST_SEGMENT, sal_True, INetURLObject::DECODE_WITH_CHARSET);
732     }
733     else
734     {
735         if (aURL.hasExtension(INetURLObject::LAST_SEGMENT))
736             sTitle = aURL.getName(INetURLObject::LAST_SEGMENT, sal_True, INetURLObject::DECODE_WITH_CHARSET);
737 
738         if ( ! sTitle.getLength() )
739             sTitle = aURL.GetHostPort(INetURLObject::DECODE_WITH_CHARSET);
740 
741         if ( ! sTitle.getLength() )
742             sTitle = aURL.GetURLNoPass(INetURLObject::DECODE_WITH_CHARSET);
743     }
744 
745     return sTitle;
746 }
747 
748 } // namespace framework
749