/src/libreoffice/framework/source/fwe/helper/titlehelper.cxx
Line | Count | Source |
1 | | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | /* |
3 | | * This file is part of the LibreOffice project. |
4 | | * |
5 | | * This Source Code Form is subject to the terms of the Mozilla Public |
6 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
7 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
8 | | * |
9 | | * This file incorporates work covered by the following license notice: |
10 | | * |
11 | | * Licensed to the Apache Software Foundation (ASF) under one or more |
12 | | * contributor license agreements. See the NOTICE file distributed |
13 | | * with this work for additional information regarding copyright |
14 | | * ownership. The ASF licenses this file to you under the Apache |
15 | | * License, Version 2.0 (the "License"); you may not use this file |
16 | | * except in compliance with the License. You may obtain a copy of |
17 | | * the License at http://www.apache.org/licenses/LICENSE-2.0 . |
18 | | */ |
19 | | |
20 | | #include <framework/titlehelper.hxx> |
21 | | #include <classes/fwkresid.hxx> |
22 | | #include <strings.hrc> |
23 | | #include <properties.h> |
24 | | |
25 | | #include <com/sun/star/frame/UntitledNumbersConst.hpp> |
26 | | #include <com/sun/star/frame/XStorable.hpp> |
27 | | #include <com/sun/star/frame/ModuleManager.hpp> |
28 | | #include <com/sun/star/frame/XUntitledNumbers.hpp> |
29 | | #include <com/sun/star/frame/XModel3.hpp> |
30 | | #include <com/sun/star/document/XDocumentEventBroadcaster.hpp> |
31 | | |
32 | | #include <comphelper/configuration.hxx> |
33 | | #include <unotools/configmgr.hxx> |
34 | | #include <unotools/bootstrap.hxx> |
35 | | #include <unotools/mediadescriptor.hxx> |
36 | | #include <comphelper/sequenceashashmap.hxx> |
37 | | #include <rtl/ustrbuf.hxx> |
38 | | #include <osl/mutex.hxx> |
39 | | #include <tools/urlobj.hxx> |
40 | | #include <utility> |
41 | | #include <vcl/svapp.hxx> |
42 | | |
43 | | |
44 | | using namespace css; |
45 | | using namespace css::uno; |
46 | | using namespace css::frame; |
47 | | |
48 | | namespace framework{ |
49 | | |
50 | | TitleHelper::TitleHelper(css::uno::Reference< css::uno::XComponentContext > xContext, |
51 | | const css::uno::Reference< css::uno::XInterface >& xOwner, |
52 | | const css::uno::Reference< css::frame::XUntitledNumbers >& xNumbers) |
53 | | : |
54 | 16.0k | m_xContext (std::move(xContext)) |
55 | 16.0k | , m_xOwner (xOwner) |
56 | 16.0k | , m_xUntitledNumbers(xNumbers) |
57 | 16.0k | , m_bExternalTitle (false) |
58 | 16.0k | , m_nLeasedNumber (css::frame::UntitledNumbersConst::INVALID_NUMBER) |
59 | 16.0k | { |
60 | 16.0k | if (css::uno::Reference<css::frame::XModel> xModel{ xOwner, css::uno::UNO_QUERY }) |
61 | 3.93k | { |
62 | 3.93k | impl_startListeningForModel (xModel); |
63 | 3.93k | } |
64 | 12.1k | else if (css::uno::Reference<css::frame::XController> xController{ xOwner, |
65 | 12.1k | css::uno::UNO_QUERY }) |
66 | 3.93k | { |
67 | 3.93k | impl_startListeningForController (xController); |
68 | 3.93k | } |
69 | 8.22k | else if (css::uno::Reference<css::frame::XFrame> xFrame{ xOwner, css::uno::UNO_QUERY }) |
70 | 8.22k | { |
71 | 8.22k | impl_startListeningForFrame (xFrame); |
72 | 8.22k | } |
73 | 16.0k | } Unexecuted instantiation: framework::TitleHelper::TitleHelper(com::sun::star::uno::Reference<com::sun::star::uno::XComponentContext>, com::sun::star::uno::Reference<com::sun::star::uno::XInterface> const&, com::sun::star::uno::Reference<com::sun::star::frame::XUntitledNumbers> const&) framework::TitleHelper::TitleHelper(com::sun::star::uno::Reference<com::sun::star::uno::XComponentContext>, com::sun::star::uno::Reference<com::sun::star::uno::XInterface> const&, com::sun::star::uno::Reference<com::sun::star::frame::XUntitledNumbers> const&) Line | Count | Source | 54 | 16.0k | m_xContext (std::move(xContext)) | 55 | 16.0k | , m_xOwner (xOwner) | 56 | 16.0k | , m_xUntitledNumbers(xNumbers) | 57 | 16.0k | , m_bExternalTitle (false) | 58 | 16.0k | , m_nLeasedNumber (css::frame::UntitledNumbersConst::INVALID_NUMBER) | 59 | 16.0k | { | 60 | 16.0k | if (css::uno::Reference<css::frame::XModel> xModel{ xOwner, css::uno::UNO_QUERY }) | 61 | 3.93k | { | 62 | 3.93k | impl_startListeningForModel (xModel); | 63 | 3.93k | } | 64 | 12.1k | else if (css::uno::Reference<css::frame::XController> xController{ xOwner, | 65 | 12.1k | css::uno::UNO_QUERY }) | 66 | 3.93k | { | 67 | 3.93k | impl_startListeningForController (xController); | 68 | 3.93k | } | 69 | 8.22k | else if (css::uno::Reference<css::frame::XFrame> xFrame{ xOwner, css::uno::UNO_QUERY }) | 70 | 8.22k | { | 71 | 8.22k | impl_startListeningForFrame (xFrame); | 72 | 8.22k | } | 73 | 16.0k | } |
|
74 | | |
75 | | TitleHelper::~TitleHelper() |
76 | 3.93k | { |
77 | 3.93k | } |
78 | | |
79 | | OUString SAL_CALL TitleHelper::getTitle() |
80 | 23.6k | { |
81 | | // SYNCHRONIZED -> |
82 | 23.6k | std::unique_lock aLock(m_aMutex); |
83 | | |
84 | | // An external title will win always and disable all internal logic about |
85 | | // creating/using a title value. |
86 | | // Even an empty string will be accepted as valid title ! |
87 | 23.6k | if (m_bExternalTitle) |
88 | 0 | return m_sTitle; |
89 | | |
90 | | // Title seems to be up-to-date. Return it directly. |
91 | 23.6k | if (!m_sTitle.isEmpty()) |
92 | 11.8k | return m_sTitle; |
93 | | |
94 | | // Title seems to be unused till now ... do bootstrapping |
95 | 11.8k | aLock.unlock(); |
96 | 11.8k | impl_updateTitle (true); |
97 | 11.8k | aLock.lock(); |
98 | | |
99 | 11.8k | return m_sTitle; |
100 | | // <- SYNCHRONIZED |
101 | 23.6k | } |
102 | | |
103 | | void SAL_CALL TitleHelper::setTitle(const OUString& sTitle) |
104 | 0 | { |
105 | | // SYNCHRONIZED -> |
106 | 0 | { |
107 | 0 | std::unique_lock aLock(m_aMutex); |
108 | |
|
109 | 0 | m_bExternalTitle = true; |
110 | 0 | m_sTitle = sTitle; |
111 | 0 | } |
112 | | // <- SYNCHRONIZED |
113 | |
|
114 | 0 | impl_sendTitleChangedEvent (); |
115 | 0 | } |
116 | | |
117 | | void SAL_CALL TitleHelper::addTitleChangeListener(const css::uno::Reference< css::frame::XTitleChangeListener >& xListener) |
118 | 16.0k | { |
119 | 16.0k | std::unique_lock aLock(m_aMutex); |
120 | 16.0k | m_aTitleChangeListeners.addInterface( aLock, xListener ); |
121 | 16.0k | } |
122 | | |
123 | | void SAL_CALL TitleHelper::removeTitleChangeListener(const css::uno::Reference< css::frame::XTitleChangeListener >& xListener) |
124 | 0 | { |
125 | 0 | std::unique_lock aLock(m_aMutex); |
126 | 0 | m_aTitleChangeListeners.removeInterface( aLock, xListener ); |
127 | 0 | } |
128 | | |
129 | | void SAL_CALL TitleHelper::titleChanged(const css::frame::TitleChangedEvent& aEvent) |
130 | 0 | { |
131 | 0 | css::uno::Reference< css::frame::XTitle > xSubTitle; |
132 | | // SYNCHRONIZED -> |
133 | 0 | { |
134 | 0 | std::unique_lock aLock(m_aMutex); |
135 | |
|
136 | 0 | xSubTitle = m_xSubTitle; |
137 | 0 | } |
138 | | // <- SYNCHRONIZED |
139 | |
|
140 | 0 | if (aEvent.Source != xSubTitle) |
141 | 0 | return; |
142 | | |
143 | 0 | impl_updateTitle (); |
144 | 0 | } |
145 | | |
146 | | void SAL_CALL TitleHelper::documentEventOccured(const css::document::DocumentEvent& aEvent) |
147 | 0 | { |
148 | 0 | if ( ! aEvent.EventName.equalsIgnoreAsciiCase("OnSaveAsDone") |
149 | 0 | && ! aEvent.EventName.equalsIgnoreAsciiCase("OnModeChanged") |
150 | 0 | && ! aEvent.EventName.equalsIgnoreAsciiCase("OnTitleChanged")) |
151 | 0 | return; |
152 | | |
153 | 0 | css::uno::Reference< css::frame::XModel > xOwner; |
154 | | // SYNCHRONIZED -> |
155 | 0 | { |
156 | 0 | std::unique_lock aLock(m_aMutex); |
157 | |
|
158 | 0 | xOwner.set(m_xOwner, css::uno::UNO_QUERY); |
159 | 0 | } |
160 | | // <- SYNCHRONIZED |
161 | |
|
162 | 0 | if (aEvent.Source != xOwner |
163 | 0 | || ((aEvent.EventName.equalsIgnoreAsciiCase("OnModeChanged") |
164 | 0 | || aEvent.EventName.equalsIgnoreAsciiCase("OnTitleChanged")) |
165 | 0 | && !xOwner.is())) |
166 | 0 | { |
167 | 0 | return; |
168 | 0 | } |
169 | | |
170 | 0 | impl_updateTitle (); |
171 | 0 | } |
172 | | |
173 | | void SAL_CALL TitleHelper::frameAction(const css::frame::FrameActionEvent& aEvent) |
174 | 15.7k | { |
175 | 15.7k | css::uno::Reference< css::frame::XFrame > xOwner; |
176 | | // SYNCHRONIZED -> |
177 | 15.7k | { |
178 | 15.7k | std::unique_lock aLock(m_aMutex); |
179 | | |
180 | 15.7k | xOwner.set(m_xOwner, css::uno::UNO_QUERY); |
181 | 15.7k | } |
182 | | // <- SYNCHRONIZED |
183 | | |
184 | 15.7k | if (aEvent.Source != xOwner) |
185 | 0 | return; |
186 | | |
187 | | // we are interested on events only, which must trigger a title bar update |
188 | | // because component was changed. |
189 | 15.7k | if ( |
190 | 15.7k | (aEvent.Action == css::frame::FrameAction_COMPONENT_ATTACHED ) || |
191 | 11.8k | (aEvent.Action == css::frame::FrameAction_COMPONENT_REATTACHED) || |
192 | 11.8k | (aEvent.Action == css::frame::FrameAction_COMPONENT_DETACHING ) |
193 | 15.7k | ) |
194 | 7.87k | { |
195 | 7.87k | impl_updateListeningForFrame (xOwner); |
196 | 7.87k | impl_updateTitle (); |
197 | 7.87k | } |
198 | 15.7k | } |
199 | | |
200 | | void SAL_CALL TitleHelper::disposing(const css::lang::EventObject& aEvent) |
201 | 11.8k | { |
202 | 11.8k | css::uno::Reference< css::uno::XInterface > xOwner; |
203 | 11.8k | css::uno::Reference< css::frame::XUntitledNumbers > xNumbers; |
204 | 11.8k | ::sal_Int32 nLeasedNumber; |
205 | | // SYNCHRONIZED -> |
206 | 11.8k | { |
207 | 11.8k | std::unique_lock aLock(m_aMutex); |
208 | | |
209 | 11.8k | xOwner = m_xOwner; |
210 | 11.8k | xNumbers = m_xUntitledNumbers; |
211 | 11.8k | nLeasedNumber = m_nLeasedNumber; |
212 | 11.8k | } |
213 | | // <- SYNCHRONIZED |
214 | | |
215 | 11.8k | if ( ! xOwner.is ()) |
216 | 0 | return; |
217 | | |
218 | 11.8k | css::uno::Reference< css::frame::XFrame > xFrame(xOwner, css::uno::UNO_QUERY); |
219 | 11.8k | if (xFrame.is()) |
220 | 3.93k | xFrame->removeFrameActionListener(this); |
221 | | |
222 | 11.8k | if (xOwner != aEvent.Source) |
223 | 0 | return; |
224 | | |
225 | 11.8k | if ( |
226 | 11.8k | (xNumbers.is () ) && |
227 | 7.87k | (nLeasedNumber != css::frame::UntitledNumbersConst::INVALID_NUMBER) |
228 | 11.8k | ) |
229 | 7.87k | xNumbers->releaseNumber (nLeasedNumber); |
230 | | |
231 | | // SYNCHRONIZED -> |
232 | 11.8k | { |
233 | 11.8k | std::unique_lock aLock(m_aMutex); |
234 | | |
235 | 11.8k | m_xOwner.clear(); |
236 | 11.8k | m_sTitle.clear(); |
237 | 11.8k | m_nLeasedNumber = css::frame::UntitledNumbersConst::INVALID_NUMBER; |
238 | 11.8k | } |
239 | | // <- SYNCHRONIZED |
240 | 11.8k | } |
241 | | |
242 | | void TitleHelper::impl_sendTitleChangedEvent () |
243 | 0 | { |
244 | 0 | css::uno::Reference<css::uno::XInterface> xOwner; |
245 | 0 | OUString sTitle; |
246 | | // SYNCHRONIZED -> |
247 | 0 | { |
248 | 0 | std::unique_lock aLock(m_aMutex); |
249 | |
|
250 | 0 | xOwner = m_xOwner; |
251 | |
|
252 | 0 | sTitle = m_sTitle; |
253 | 0 | } |
254 | | // <- SYNCHRONIZED |
255 | |
|
256 | 0 | css::frame::TitleChangedEvent aEvent(xOwner, sTitle); |
257 | |
|
258 | 0 | if( ! aEvent.Source.is() ) |
259 | 0 | return; |
260 | | |
261 | 0 | std::unique_lock aLock(m_aMutex); |
262 | 0 | comphelper::OInterfaceIteratorHelper4 pIt( aLock, m_aTitleChangeListeners ); |
263 | 0 | while ( pIt.hasMoreElements() ) |
264 | 0 | { |
265 | 0 | aLock.unlock(); |
266 | 0 | try |
267 | 0 | { |
268 | 0 | uno::Reference<css::frame::XTitleChangeListener> i = pIt.next(); |
269 | 0 | i->titleChanged( aEvent ); |
270 | 0 | } |
271 | 0 | catch(const css::uno::Exception&) |
272 | 0 | { |
273 | 0 | aLock.lock(); |
274 | 0 | pIt.remove(aLock); |
275 | 0 | aLock.unlock(); |
276 | 0 | } |
277 | 0 | aLock.lock(); |
278 | 0 | } |
279 | 0 | } |
280 | | |
281 | | void TitleHelper::impl_updateTitle (bool init) |
282 | 19.6k | { |
283 | 19.6k | css::uno::Reference<css::uno::XInterface> xOwner; |
284 | | |
285 | | // SYNCHRONIZED -> |
286 | 19.6k | { |
287 | 19.6k | std::unique_lock aLock(m_aMutex); |
288 | | |
289 | 19.6k | xOwner = m_xOwner; |
290 | 19.6k | } |
291 | | // <- SYNCHRONIZED |
292 | | |
293 | 19.6k | if (css::uno::Reference<css::frame::XModel3> xModel{ xOwner, css::uno::UNO_QUERY }) |
294 | 3.93k | { |
295 | 3.93k | impl_updateTitleForModel (xModel, init); |
296 | 3.93k | } |
297 | 15.7k | else if (css::uno::Reference<css::frame::XController> xController{ xOwner, |
298 | 15.7k | css::uno::UNO_QUERY }) |
299 | 3.93k | { |
300 | 3.93k | impl_updateTitleForController (xController, init); |
301 | 3.93k | } |
302 | 11.8k | else if (css::uno::Reference<css::frame::XFrame> xFrame{ xOwner, css::uno::UNO_QUERY }) |
303 | 11.8k | { |
304 | 11.8k | impl_updateTitleForFrame (xFrame, init); |
305 | 11.8k | } |
306 | 19.6k | } |
307 | | |
308 | | static OUString getURLFromModel(const css::uno::Reference< css::frame::XModel3 >& xModel) |
309 | 3.93k | { |
310 | 3.93k | if (css::uno::Reference<css::frame::XStorable> xURLProvider{ xModel, css::uno::UNO_QUERY }) |
311 | 3.93k | return xURLProvider->getLocation(); |
312 | 0 | return {}; |
313 | 3.93k | } |
314 | | |
315 | | void TitleHelper::impl_updateTitleForModel (const css::uno::Reference< css::frame::XModel3 >& xModel, bool init) |
316 | 3.93k | { |
317 | 3.93k | css::uno::Reference< css::uno::XInterface > xOwner; |
318 | 3.93k | css::uno::Reference< css::frame::XUntitledNumbers > xNumbers; |
319 | 3.93k | ::sal_Int32 nLeasedNumber; |
320 | | // SYNCHRONIZED -> |
321 | 3.93k | { |
322 | 3.93k | std::unique_lock aLock(m_aMutex); |
323 | | |
324 | | // external title won't be updated internally! |
325 | | // It has to be set from outside new. |
326 | 3.93k | if (m_bExternalTitle) |
327 | 0 | return; |
328 | | |
329 | 3.93k | xOwner = m_xOwner; |
330 | 3.93k | xNumbers = m_xUntitledNumbers; |
331 | 3.93k | nLeasedNumber = m_nLeasedNumber; |
332 | 3.93k | } |
333 | | // <- SYNCHRONIZED |
334 | | |
335 | 0 | if ( |
336 | 3.93k | ( ! xOwner.is ()) || |
337 | 3.93k | ( ! xNumbers.is ()) || |
338 | 3.93k | ( ! xModel.is ()) |
339 | 3.93k | ) |
340 | 0 | return; |
341 | | |
342 | 3.93k | OUString sTitle; |
343 | | |
344 | 3.93k | comphelper::SequenceAsHashMap aDescriptor( |
345 | 3.93k | xModel->getArgs2({ utl::MediaDescriptor::PROP_DOCUMENTTITLE, |
346 | 3.93k | utl::MediaDescriptor::PROP_SUGGESTEDSAVEASNAME })); |
347 | | |
348 | 3.93k | if (const OUString sMediaTitle = aDescriptor.getUnpackedValueOrDefault( |
349 | 3.93k | utl::MediaDescriptor::PROP_DOCUMENTTITLE, OUString()); |
350 | 3.93k | !sMediaTitle.isEmpty()) |
351 | 0 | { |
352 | 0 | sTitle = sMediaTitle; |
353 | 0 | } |
354 | 3.93k | else if (const OUString sURL = getURLFromModel(xModel); !sURL.isEmpty()) |
355 | 0 | { |
356 | 0 | sTitle = impl_convertURL2Title(sURL); |
357 | 0 | if (nLeasedNumber != css::frame::UntitledNumbersConst::INVALID_NUMBER) |
358 | 0 | xNumbers->releaseNumber (nLeasedNumber); |
359 | 0 | nLeasedNumber = css::frame::UntitledNumbersConst::INVALID_NUMBER; |
360 | 0 | } |
361 | 3.93k | else if (const OUString sSuggestedSaveAsName = aDescriptor.getUnpackedValueOrDefault( |
362 | 3.93k | utl::MediaDescriptor::PROP_SUGGESTEDSAVEASNAME, OUString()); |
363 | 3.93k | !sSuggestedSaveAsName.isEmpty()) |
364 | 0 | { |
365 | | // tdf#121537 Use suggested save as name for title if file has not yet been saved |
366 | 0 | sTitle = sSuggestedSaveAsName; |
367 | 0 | } |
368 | 3.93k | else |
369 | 3.93k | { |
370 | 3.93k | if (nLeasedNumber == css::frame::UntitledNumbersConst::INVALID_NUMBER) |
371 | 3.93k | nLeasedNumber = xNumbers->leaseNumber (xOwner); |
372 | | |
373 | 3.93k | if (nLeasedNumber != css::frame::UntitledNumbersConst::INVALID_NUMBER) |
374 | 3.93k | sTitle = xNumbers->getUntitledPrefix() + OUString::number(nLeasedNumber); |
375 | 0 | else |
376 | 0 | sTitle = xNumbers->getUntitledPrefix() + "?"; |
377 | 3.93k | } |
378 | | |
379 | 3.93k | bool bChanged; |
380 | | // SYNCHRONIZED -> |
381 | 3.93k | { |
382 | 3.93k | std::unique_lock aLock(m_aMutex); |
383 | | |
384 | | // WORKAROUND: the notification is currently sent always, |
385 | | // can be changed after shared mode is supported per UNO API |
386 | 3.93k | bChanged = !init; // && m_sTitle != sTitle |
387 | | |
388 | 3.93k | m_sTitle = sTitle; |
389 | 3.93k | m_nLeasedNumber = nLeasedNumber; |
390 | 3.93k | } |
391 | | // <- SYNCHRONIZED |
392 | | |
393 | 3.93k | if (bChanged) |
394 | 0 | impl_sendTitleChangedEvent (); |
395 | 3.93k | } |
396 | | |
397 | | void TitleHelper::impl_updateTitleForController (const css::uno::Reference< css::frame::XController >& xController, bool init) |
398 | 3.93k | { |
399 | 3.93k | css::uno::Reference< css::uno::XInterface > xOwner; |
400 | 3.93k | css::uno::Reference< css::frame::XUntitledNumbers > xNumbers; |
401 | 3.93k | ::sal_Int32 nLeasedNumber; |
402 | | // SYNCHRONIZED -> |
403 | 3.93k | { |
404 | 3.93k | std::unique_lock aLock(m_aMutex); |
405 | | |
406 | | // external title won't be updated internally! |
407 | | // It has to be set from outside new. |
408 | 3.93k | if (m_bExternalTitle) |
409 | 0 | return; |
410 | | |
411 | 3.93k | xOwner = m_xOwner; |
412 | 3.93k | xNumbers = m_xUntitledNumbers; |
413 | 3.93k | nLeasedNumber = m_nLeasedNumber; |
414 | 3.93k | } |
415 | | // <- SYNCHRONIZED |
416 | | |
417 | 0 | if ( |
418 | 3.93k | ( ! xOwner.is ()) || |
419 | 3.93k | ( ! xNumbers.is ()) || |
420 | 3.93k | ( ! xController.is ()) |
421 | 3.93k | ) |
422 | 0 | return; |
423 | | |
424 | 3.93k | OUStringBuffer sTitle(256); |
425 | | |
426 | 3.93k | if (nLeasedNumber == css::frame::UntitledNumbersConst::INVALID_NUMBER) |
427 | 3.93k | nLeasedNumber = xNumbers->leaseNumber (xOwner); |
428 | | |
429 | 3.93k | css::uno::Reference< css::frame::XTitle > xModelTitle(xController->getModel (), css::uno::UNO_QUERY); |
430 | 3.93k | css::uno::Reference< css::frame::XModel > xModel = xController->getModel (); |
431 | 3.93k | if (!xModelTitle.is ()) |
432 | 0 | xModelTitle.set(xController, css::uno::UNO_QUERY); |
433 | 3.93k | if (xModelTitle.is ()) |
434 | 3.93k | { |
435 | 3.93k | sTitle.append (xModelTitle->getTitle ()); |
436 | 3.93k | if ( nLeasedNumber > 1 ) |
437 | 0 | { |
438 | 0 | sTitle.append(" : " + OUString::number(nLeasedNumber)); |
439 | 0 | } |
440 | 3.93k | if (xModel.is ()) |
441 | 3.93k | { |
442 | 3.93k | INetURLObject aURL (xModel->getURL ()); |
443 | 3.93k | if (aURL.GetProtocol () != INetProtocol::File |
444 | 3.93k | && aURL.GetProtocol() != INetProtocol::PrivSoffice |
445 | 3.93k | && aURL.GetProtocol () != INetProtocol::NotValid) |
446 | 0 | { |
447 | 0 | OUString sRemoteText (FwkResId (STR_REMOTE_TITLE)); |
448 | 0 | sTitle.append (sRemoteText); |
449 | 0 | } |
450 | 3.93k | } |
451 | 3.93k | } |
452 | 0 | else |
453 | 0 | { |
454 | 0 | sTitle.append (xNumbers->getUntitledPrefix ()); |
455 | 0 | if ( nLeasedNumber > 1 ) |
456 | 0 | { |
457 | 0 | sTitle.append(nLeasedNumber ); |
458 | 0 | } |
459 | 0 | } |
460 | | |
461 | 3.93k | bool bChanged; |
462 | | // SYNCHRONIZED -> |
463 | 3.93k | { |
464 | 3.93k | std::unique_lock aLock(m_aMutex); |
465 | | |
466 | 3.93k | OUString sNewTitle = sTitle.makeStringAndClear (); |
467 | 3.93k | bChanged = !init && m_sTitle != sNewTitle; |
468 | 3.93k | m_sTitle = sNewTitle; |
469 | 3.93k | m_nLeasedNumber = nLeasedNumber; |
470 | 3.93k | } |
471 | | // <- SYNCHRONIZED |
472 | | |
473 | 3.93k | if (bChanged) |
474 | 0 | impl_sendTitleChangedEvent (); |
475 | 3.93k | } |
476 | | |
477 | | void TitleHelper::impl_updateTitleForFrame (const css::uno::Reference< css::frame::XFrame >& xFrame, bool init) |
478 | 11.8k | { |
479 | 11.8k | if ( ! xFrame.is ()) |
480 | 0 | return; |
481 | | |
482 | | // SYNCHRONIZED -> |
483 | 11.8k | { |
484 | 11.8k | std::unique_lock aLock(m_aMutex); |
485 | | |
486 | | // external title won't be updated internally! |
487 | | // It has to be set from outside new. |
488 | 11.8k | if (m_bExternalTitle) |
489 | 0 | return; |
490 | 11.8k | } |
491 | | // <- SYNCHRONIZED |
492 | | |
493 | 11.8k | css::uno::Reference< css::uno::XInterface > xComponent = xFrame->getController (); |
494 | 11.8k | if ( ! xComponent.is ()) |
495 | 0 | xComponent = xFrame->getComponentWindow (); |
496 | | |
497 | 11.8k | OUStringBuffer sTitle (256); |
498 | | |
499 | 11.8k | impl_appendComponentTitle (sTitle, xComponent); |
500 | 11.8k | #ifndef MACOSX |
501 | 11.8k | if (!comphelper::IsFuzzing()) |
502 | 0 | { |
503 | | // fdo#70376: We want the window title to contain just the |
504 | | // document name (from the above "component title"). |
505 | 0 | impl_appendProductName (sTitle); |
506 | 0 | impl_appendModuleName (sTitle); |
507 | 0 | impl_appendDebugVersion (sTitle); |
508 | 0 | } |
509 | 11.8k | #endif |
510 | 11.8k | impl_appendSafeMode (sTitle); |
511 | | |
512 | 11.8k | bool bChanged; |
513 | | // SYNCHRONIZED -> |
514 | 11.8k | { |
515 | 11.8k | std::unique_lock aLock(m_aMutex); |
516 | | |
517 | 11.8k | OUString sNewTitle = sTitle.makeStringAndClear (); |
518 | 11.8k | bChanged = !init && m_sTitle != sNewTitle; |
519 | 11.8k | m_sTitle = sNewTitle; |
520 | 11.8k | } |
521 | | // <- SYNCHRONIZED |
522 | | |
523 | 11.8k | if (bChanged) |
524 | 0 | impl_sendTitleChangedEvent (); |
525 | 11.8k | } |
526 | | |
527 | | // static |
528 | | void TitleHelper::impl_appendComponentTitle ( OUStringBuffer& sTitle , |
529 | | const css::uno::Reference< css::uno::XInterface >& xComponent) |
530 | 11.8k | { |
531 | 11.8k | css::uno::Reference< css::frame::XTitle > xTitle(xComponent, css::uno::UNO_QUERY); |
532 | | |
533 | | // Note: Title has to be used (even if it's empty) if the right interface is supported. |
534 | 11.8k | if (xTitle.is ()) |
535 | 11.8k | sTitle.append (xTitle->getTitle ()); |
536 | 11.8k | } |
537 | | |
538 | | // static |
539 | | void TitleHelper::impl_appendProductName (OUStringBuffer& sTitle) |
540 | 0 | { |
541 | 0 | OUString name(utl::ConfigManager::getProductName()); |
542 | 0 | if (!name.isEmpty()) |
543 | 0 | { |
544 | 0 | if (!sTitle.isEmpty()) |
545 | 0 | { |
546 | 0 | OUString separator (FwkResId (STR_EMDASH_SEPARATOR)); |
547 | 0 | sTitle.append(separator); |
548 | 0 | } |
549 | 0 | sTitle.append(name); |
550 | 0 | } |
551 | 0 | } |
552 | | |
553 | | void TitleHelper::impl_appendModuleName (OUStringBuffer& sTitle) |
554 | 0 | { |
555 | 0 | css::uno::Reference< css::uno::XInterface > xOwner; |
556 | 0 | css::uno::Reference< css::uno::XComponentContext > xContext; |
557 | | // SYNCHRONIZED -> |
558 | 0 | { |
559 | 0 | std::unique_lock aLock(m_aMutex); |
560 | |
|
561 | 0 | xOwner = m_xOwner; |
562 | 0 | xContext = m_xContext; |
563 | 0 | } |
564 | | // <- SYNCHRONIZED |
565 | |
|
566 | 0 | try |
567 | 0 | { |
568 | 0 | css::uno::Reference< css::frame::XModuleManager2 > xModuleManager = |
569 | 0 | css::frame::ModuleManager::create(xContext); |
570 | |
|
571 | 0 | const OUString sID = xModuleManager->identify(xOwner); |
572 | 0 | ::comphelper::SequenceAsHashMap lProps = xModuleManager->getByName (sID); |
573 | 0 | const OUString sUIName = lProps.getUnpackedValueOrDefault (OFFICEFACTORY_PROPNAME_ASCII_UINAME, OUString()); |
574 | | |
575 | | // An UIname property is an optional value ! |
576 | | // So please add it to the title in case it does really exists only. |
577 | 0 | if (!sUIName.isEmpty()) |
578 | 0 | { |
579 | 0 | sTitle.append (" " ); |
580 | 0 | sTitle.append (sUIName); |
581 | 0 | } |
582 | 0 | } |
583 | 0 | catch(const css::uno::Exception&) |
584 | 0 | {} |
585 | 0 | } |
586 | | |
587 | | #ifdef DBG_UTIL |
588 | | // static |
589 | | void TitleHelper::impl_appendDebugVersion (OUStringBuffer& sTitle) |
590 | | { |
591 | | OUString version(utl::ConfigManager::getProductVersion()); |
592 | | sTitle.append(' '); |
593 | | sTitle.append(version); |
594 | | OUString sVersion = ::utl::Bootstrap::getBuildIdData(u"development"_ustr); |
595 | | sTitle.append(" ["); |
596 | | sTitle.append(sVersion); |
597 | | sTitle.append("]"); |
598 | | } |
599 | | #else |
600 | | void TitleHelper::impl_appendDebugVersion (OUStringBuffer&) |
601 | 0 | { |
602 | 0 | } |
603 | | #endif |
604 | | |
605 | | // static |
606 | | void TitleHelper::impl_appendSafeMode (OUStringBuffer& sTitle) |
607 | 11.8k | { |
608 | 11.8k | if (Application::IsSafeModeEnabled()) |
609 | 0 | sTitle.append(FwkResId (STR_SAFEMODE_TITLE)); |
610 | 11.8k | } |
611 | | |
612 | | void TitleHelper::impl_startListeningForModel (const css::uno::Reference< css::frame::XModel >& xModel) |
613 | 3.93k | { |
614 | 3.93k | css::uno::Reference< css::document::XDocumentEventBroadcaster > xBroadcaster(xModel, css::uno::UNO_QUERY); |
615 | 3.93k | if ( ! xBroadcaster.is ()) |
616 | 0 | return; |
617 | | |
618 | 3.93k | xBroadcaster->addDocumentEventListener (static_cast< css::document::XDocumentEventListener* >(this)); |
619 | 3.93k | } |
620 | | |
621 | | void TitleHelper::impl_startListeningForController (const css::uno::Reference< css::frame::XController >& xController) |
622 | 3.93k | { |
623 | 3.93k | xController->addEventListener (static_cast< css::lang::XEventListener* > (static_cast< css::frame::XFrameActionListener* > (this) ) ); |
624 | 3.93k | css::uno::Reference< css::frame::XTitle > xSubTitle(xController->getModel (), css::uno::UNO_QUERY); |
625 | 3.93k | impl_setSubTitle (xSubTitle); |
626 | 3.93k | } |
627 | | |
628 | | void TitleHelper::impl_startListeningForFrame (const css::uno::Reference< css::frame::XFrame >& xFrame) |
629 | 8.22k | { |
630 | 8.22k | xFrame->addFrameActionListener(this ); |
631 | 8.22k | impl_updateListeningForFrame (xFrame); |
632 | 8.22k | } |
633 | | |
634 | | void TitleHelper::impl_updateListeningForFrame (const css::uno::Reference< css::frame::XFrame >& xFrame) |
635 | 16.0k | { |
636 | 16.0k | css::uno::Reference< css::frame::XTitle > xSubTitle(xFrame->getController (), css::uno::UNO_QUERY); |
637 | 16.0k | impl_setSubTitle (xSubTitle); |
638 | 16.0k | } |
639 | | |
640 | | void TitleHelper::impl_setSubTitle (const css::uno::Reference< css::frame::XTitle >& xSubTitle) |
641 | 20.0k | { |
642 | 20.0k | css::uno::Reference< css::frame::XTitle > xOldSubTitle; |
643 | | // SYNCHRONIZED -> |
644 | 20.0k | { |
645 | 20.0k | std::unique_lock aLock(m_aMutex); |
646 | | |
647 | | // ignore duplicate calls. Makes outside using of this helper more easy :-) |
648 | 20.0k | xOldSubTitle = m_xSubTitle; |
649 | 20.0k | if (xOldSubTitle == xSubTitle) |
650 | 12.1k | return; |
651 | | |
652 | 7.87k | m_xSubTitle = xSubTitle; |
653 | 7.87k | } |
654 | | // <- SYNCHRONIZED |
655 | | |
656 | 0 | css::uno::Reference< css::frame::XTitleChangeBroadcaster > xOldBroadcaster(xOldSubTitle , css::uno::UNO_QUERY ); |
657 | 7.87k | css::uno::Reference< css::frame::XTitleChangeBroadcaster > xNewBroadcaster(xSubTitle , css::uno::UNO_QUERY ); |
658 | 7.87k | css::uno::Reference< css::frame::XTitleChangeListener > xThis(this); |
659 | | |
660 | 7.87k | if (xOldBroadcaster.is()) |
661 | 0 | xOldBroadcaster->removeTitleChangeListener (xThis); |
662 | | |
663 | 7.87k | if (xNewBroadcaster.is()) |
664 | 7.87k | xNewBroadcaster->addTitleChangeListener (xThis); |
665 | 7.87k | } |
666 | | |
667 | | // static |
668 | | OUString TitleHelper::impl_convertURL2Title(std::u16string_view sURL) |
669 | 0 | { |
670 | 0 | INetURLObject aURL (sURL); |
671 | 0 | OUString sTitle; |
672 | |
|
673 | 0 | if (aURL.GetProtocol() == INetProtocol::File) |
674 | 0 | { |
675 | 0 | if (aURL.HasMark()) |
676 | 0 | aURL = INetURLObject(aURL.GetURLNoMark()); |
677 | |
|
678 | 0 | sTitle = aURL.getName(INetURLObject::LAST_SEGMENT, true, INetURLObject::DecodeMechanism::WithCharset); |
679 | 0 | } |
680 | 0 | else |
681 | 0 | { |
682 | 0 | if (aURL.hasExtension()) |
683 | 0 | sTitle = aURL.getName(INetURLObject::LAST_SEGMENT, true, INetURLObject::DecodeMechanism::WithCharset); |
684 | |
|
685 | 0 | if ( sTitle.isEmpty() ) |
686 | 0 | sTitle = aURL.GetHostPort(INetURLObject::DecodeMechanism::WithCharset); |
687 | |
|
688 | 0 | if ( sTitle.isEmpty() ) |
689 | 0 | sTitle = aURL.GetURLNoPass(INetURLObject::DecodeMechanism::WithCharset); |
690 | 0 | } |
691 | |
|
692 | 0 | return sTitle; |
693 | 0 | } |
694 | | |
695 | | } // namespace framework |
696 | | |
697 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |