1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include "newhelp.hxx"
22 #include <sfx2/sfxresid.hxx>
23 #include "helpinterceptor.hxx"
25 #include <srchdlg.hxx>
26 #include <sfx2/sfxhelp.hxx>
27 #include <sal/log.hxx>
28 #include <osl/diagnose.h>
29 #include <tools/debug.hxx>
30 #include <tools/diagnose_ex.h>
32 #include <sfx2/strings.hrc>
34 #include <bitmaps.hlst>
36 #include <rtl/ustrbuf.hxx>
37 #include <comphelper/configurationhelper.hxx>
38 #include <comphelper/processfactory.hxx>
39 #include <comphelper/string.hxx>
40 #include <toolkit/helper/vclunohelper.hxx>
41 #include <com/sun/star/beans/PropertyValue.hpp>
42 #include <com/sun/star/beans/XPropertySetInfo.hpp>
43 #include <com/sun/star/container/XIndexAccess.hpp>
44 #include <com/sun/star/frame/XComponentLoader.hpp>
45 #include <com/sun/star/frame/XTitle.hpp>
46 #include <com/sun/star/frame/XLayoutManager.hpp>
47 #include <com/sun/star/frame/XController.hpp>
48 #include <com/sun/star/frame/XDispatch.hpp>
49 #include <com/sun/star/frame/XDispatchProvider.hpp>
50 #include <com/sun/star/frame/Frame.hpp>
51 #include <com/sun/star/i18n/XBreakIterator.hpp>
52 #include <com/sun/star/i18n/WordType.hpp>
53 #include <com/sun/star/lang/XComponent.hpp>
54 #include <com/sun/star/style/XStyle.hpp>
55 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
56 #include <com/sun/star/text/XText.hpp>
57 #include <com/sun/star/text/XTextCursor.hpp>
58 #include <com/sun/star/text/XTextDocument.hpp>
59 #include <com/sun/star/text/XTextViewCursor.hpp>
60 #include <com/sun/star/text/XTextViewCursorSupplier.hpp>
61 #include <com/sun/star/ucb/CommandAbortedException.hpp>
62 #include <com/sun/star/util/URL.hpp>
63 #include <com/sun/star/util/XSearchable.hpp>
64 #include <com/sun/star/util/XSearchDescriptor.hpp>
65 #include <com/sun/star/util/URLTransformer.hpp>
66 #include <com/sun/star/util/XURLTransformer.hpp>
67 #include <com/sun/star/util/XModifiable.hpp>
68 #include <com/sun/star/util/XCloseable.hpp>
69 #include <com/sun/star/util/CloseVetoException.hpp>
70 #include <com/sun/star/view/XSelectionSupplier.hpp>
71 #include <com/sun/star/view/XViewSettingsSupplier.hpp>
72 #include <unotools/historyoptions.hxx>
73 #include <unotools/viewoptions.hxx>
74 #include <tools/urlobj.hxx>
75 #include <svtools/imagemgr.hxx>
76 #include <svtools/miscopt.hxx>
77 #include <vcl/commandevent.hxx>
78 #include <vcl/event.hxx>
79 #include <vcl/i18nhelp.hxx>
80 #include <vcl/settings.hxx>
81 #include <vcl/svapp.hxx>
82 #include <vcl/unohelp.hxx>
83 #include <vcl/weld.hxx>
85 #include <ucbhelper/content.hxx>
86 #include <unotools/ucbhelper.hxx>
88 #include <string_view>
89 #include <unordered_map>
92 using namespace ::ucbhelper
;
93 using namespace ::com::sun::star::ucb
;
95 using namespace ::com::sun::star
;
96 using namespace ::com::sun::star::beans
;
97 using namespace ::com::sun::star::container
;
98 using namespace ::com::sun::star::frame
;
99 using namespace ::com::sun::star::i18n
;
100 using namespace ::com::sun::star::lang
;
101 using namespace ::com::sun::star::style
;
102 using namespace ::com::sun::star::text
;
103 using namespace ::com::sun::star::uno
;
104 using namespace ::com::sun::star::util
;
105 using namespace ::com::sun::star::view
;
106 using namespace ::com::sun::star::ui
;
108 using namespace ::comphelper
;
110 // defines ---------------------------------------------------------------
112 constexpr OUStringLiteral CONFIGNAME_HELPWIN
= u
"OfficeHelp";
113 constexpr OUStringLiteral CONFIGNAME_INDEXWIN
= u
"OfficeHelpIndex";
114 constexpr OUStringLiteral CONFIGNAME_SEARCHPAGE
= u
"OfficeHelpSearch";
115 constexpr OUStringLiteral IMAGE_URL
= u
"private:factory/";
117 constexpr OUStringLiteral PROPERTY_KEYWORDLIST
= u
"KeywordList";
118 constexpr OUStringLiteral PROPERTY_KEYWORDREF
= u
"KeywordRef";
119 constexpr OUStringLiteral PROPERTY_ANCHORREF
= u
"KeywordAnchorForRef";
120 constexpr OUStringLiteral PROPERTY_TITLEREF
= u
"KeywordTitleForRef";
121 constexpr OUStringLiteral PROPERTY_TITLE
= u
"Title";
122 constexpr OUStringLiteral HELP_URL
= u
"vnd.sun.star.help://";
123 constexpr OUStringLiteral HELP_SEARCH_TAG
= u
"/?Query=";
124 constexpr OUStringLiteral USERITEM_NAME
= u
"UserItem";
126 constexpr OUStringLiteral PACKAGE_SETUP
= u
"/org.openoffice.Setup";
127 constexpr OUStringLiteral PATH_OFFICE_FACTORIES
= u
"Office/Factories/";
128 constexpr OUStringLiteral KEY_HELP_ON_OPEN
= u
"ooSetupFactoryHelpOnOpen";
129 constexpr OUStringLiteral KEY_UI_NAME
= u
"ooSetupFactoryUIName";
135 /** Prepare a search string for searching or selecting.
136 For searching every search word needs the postfix '*' and the delimiter ' ' if necessary.
137 For selecting the delimiter '|' is required to search with regular expressions.
139 search string | output for searching | output for selecting
140 -----------------------------------------------------------
141 "text" | "text*" | "text"
142 "text*" | "text*" | "text"
143 "text menu" | "text* menu*" | "text|menu"
145 static OUString
PrepareSearchString( const OUString
& rSearchString
,
146 const Reference
< XBreakIterator
>& xBreak
, bool bForSearch
)
148 OUStringBuffer sSearchStr
;
149 sal_Int32 nStartPos
= 0;
150 const lang::Locale aLocale
= Application::GetSettings().GetUILanguageTag().getLocale();
151 Boundary aBoundary
= xBreak
->getWordBoundary(
152 rSearchString
, nStartPos
, aLocale
, WordType::ANYWORD_IGNOREWHITESPACES
, true );
154 while ( aBoundary
.startPos
< aBoundary
.endPos
)
156 nStartPos
= aBoundary
.endPos
;
157 OUString
sSearchToken( rSearchString
.copy(
158 static_cast<sal_uInt16
>(aBoundary
.startPos
), static_cast<sal_uInt16
>(aBoundary
.endPos
) - static_cast<sal_uInt16
>(aBoundary
.startPos
) ) );
159 if ( !sSearchToken
.isEmpty() && ( sSearchToken
.getLength() > 1 || sSearchToken
[0] != '.' ) )
161 if ( bForSearch
&& sSearchToken
[ sSearchToken
.getLength() - 1 ] != '*' )
164 if ( sSearchToken
.getLength() > 1 ||
165 ( sSearchToken
.getLength() > 0 && sSearchToken
[ 0 ] != '*' ) )
167 if ( !sSearchStr
.isEmpty() )
170 sSearchStr
.append(" ");
172 sSearchStr
.append("|");
174 sSearchStr
.append(sSearchToken
);
177 aBoundary
= xBreak
->nextWord( rSearchString
, nStartPos
,
178 aLocale
, WordType::ANYWORD_IGNOREWHITESPACES
);
181 return sSearchStr
.makeStringAndClear();
188 // struct IndexEntry_Impl ------------------------------------------------
192 struct IndexEntry_Impl
197 IndexEntry_Impl( const OUString
& rURL
, bool bSubEntry
) :
198 m_bSubEntry( bSubEntry
), m_aURL( rURL
) {}
201 // struct ContentEntry_Impl ----------------------------------------------
203 struct ContentEntry_Impl
208 ContentEntry_Impl( const OUString
& rURL
, bool bFolder
) :
209 aURL( rURL
), bIsFolder( bFolder
) {}
214 void ContentTabPage_Impl::InitRoot()
216 std::vector
< OUString
> aList
=
217 SfxContentHelper::GetHelpTreeViewContents( "vnd.sun.star.hier://com.sun.star.help.TreeView/" );
219 for (const OUString
& aRow
: aList
)
222 OUString aTitle
= aRow
.getToken( 0, '\t', nIdx
);
223 OUString aURL
= aRow
.getToken( 0, '\t', nIdx
);
224 sal_Unicode cFolder
= aRow
.getToken( 0, '\t', nIdx
)[0];
225 bool bIsFolder
= ( '1' == cFolder
);
228 sId
= OUString::number(reinterpret_cast<sal_Int64
>(new ContentEntry_Impl(aURL
, true)));
229 m_xContentBox
->insert(nullptr, -1, &aTitle
, &sId
, nullptr, nullptr, true, m_xScratchIter
.get());
230 m_xContentBox
->set_image(*m_xScratchIter
, aClosedBookImage
);
234 void ContentTabPage_Impl::ClearChildren(const weld::TreeIter
* pParent
)
236 std::unique_ptr
<weld::TreeIter
> xEntry
= m_xContentBox
->make_iterator(pParent
);
237 bool bEntry
= m_xContentBox
->iter_children(*xEntry
);
240 ClearChildren(xEntry
.get());
241 delete reinterpret_cast<ContentEntry_Impl
*>(m_xContentBox
->get_id(*xEntry
).toInt64());
242 bEntry
= m_xContentBox
->iter_next_sibling(*xEntry
);
247 IMPL_LINK(ContentTabPage_Impl
, ExpandingHdl
, const weld::TreeIter
&, rIter
, bool)
249 ContentEntry_Impl
* pContentEntry
= reinterpret_cast<ContentEntry_Impl
*>(m_xContentBox
->get_id(rIter
).toInt64());
250 if (!m_xContentBox
->iter_has_child(rIter
))
256 std::vector
<OUString
> aList
= SfxContentHelper::GetHelpTreeViewContents(pContentEntry
->aURL
);
258 for (const OUString
& aRow
: aList
)
261 OUString aTitle
= aRow
.getToken( 0, '\t', nIdx
);
262 OUString aURL
= aRow
.getToken( 0, '\t', nIdx
);
263 sal_Unicode cFolder
= aRow
.getToken( 0, '\t', nIdx
)[0];
264 bool bIsFolder
= ( '1' == cFolder
);
267 OUString sId
= OUString::number(reinterpret_cast<sal_Int64
>(new ContentEntry_Impl(aURL
, true)));
268 m_xContentBox
->insert(&rIter
, -1, &aTitle
, &sId
, nullptr, nullptr, true, m_xScratchIter
.get());
269 m_xContentBox
->set_image(*m_xScratchIter
, aClosedBookImage
);
273 Any
aAny( ::utl::UCBContentHelper::GetProperty( aURL
, "TargetURL" ) );
276 if ( aAny
>>= aTargetURL
)
277 sId
= OUString::number(reinterpret_cast<sal_Int64
>(new ContentEntry_Impl(aTargetURL
, false)));
278 m_xContentBox
->insert(&rIter
, -1, &aTitle
, &sId
, nullptr, nullptr, false, m_xScratchIter
.get());
279 m_xContentBox
->set_image(*m_xScratchIter
, aDocumentImage
);
284 catch (const Exception
&)
286 TOOLS_WARN_EXCEPTION( "sfx.appl", "ContentListBox_Impl::RequestingChildren(): unexpected exception" );
290 if (!pContentEntry
|| pContentEntry
->bIsFolder
)
291 m_xContentBox
->set_image(rIter
, aOpenBookImage
);
296 IMPL_LINK(ContentTabPage_Impl
, CollapsingHdl
, const weld::TreeIter
&, rIter
, bool)
298 ContentEntry_Impl
* pContentEntry
= reinterpret_cast<ContentEntry_Impl
*>(m_xContentBox
->get_id(rIter
).toInt64());
299 if (!pContentEntry
|| pContentEntry
->bIsFolder
)
300 m_xContentBox
->set_image(rIter
, aClosedBookImage
);
305 OUString
ContentTabPage_Impl::GetSelectedEntry() const
308 ContentEntry_Impl
* pEntry
= reinterpret_cast<ContentEntry_Impl
*>(m_xContentBox
->get_selected_id().toInt64());
309 if (pEntry
&& !pEntry
->bIsFolder
)
314 // class HelpTabPage_Impl ------------------------------------------------
315 HelpTabPage_Impl::HelpTabPage_Impl(weld::Widget
* pParent
, SfxHelpIndexWindow_Impl
* pIdxWin
,
316 const OString
& rID
, const OUString
& rUIXMLDescription
)
317 : BuilderPage(pParent
, nullptr, rUIXMLDescription
, rID
)
322 HelpTabPage_Impl::~HelpTabPage_Impl()
326 // class ContentTabPage_Impl ---------------------------------------------
327 ContentTabPage_Impl::ContentTabPage_Impl(weld::Widget
* pParent
, SfxHelpIndexWindow_Impl
* pIdxWin
)
328 : HelpTabPage_Impl(pParent
, pIdxWin
, "HelpContentPage",
329 "sfx/ui/helpcontentpage.ui")
330 , m_xContentBox(m_xBuilder
->weld_tree_view("content"))
331 , m_xScratchIter(m_xContentBox
->make_iterator())
332 , aOpenBookImage(BMP_HELP_CONTENT_BOOK_OPEN
)
333 , aClosedBookImage(BMP_HELP_CONTENT_BOOK_CLOSED
)
334 , aDocumentImage(BMP_HELP_CONTENT_DOC
)
336 m_xContentBox
->set_size_request(m_xContentBox
->get_approximate_digit_width() * 30,
337 m_xContentBox
->get_height_rows(20));
338 m_xContentBox
->connect_row_activated(LINK(this, ContentTabPage_Impl
, DoubleClickHdl
));
339 m_xContentBox
->connect_expanding(LINK(this, ContentTabPage_Impl
, ExpandingHdl
));
340 m_xContentBox
->connect_collapsing(LINK(this, ContentTabPage_Impl
, CollapsingHdl
));
345 IMPL_LINK_NOARG(ContentTabPage_Impl
, DoubleClickHdl
, weld::TreeView
&, bool)
347 aDoubleClickHdl
.Call(nullptr);
351 void ContentTabPage_Impl::SetDoubleClickHdl(const Link
<LinkParamNone
*, void>& rLink
)
353 aDoubleClickHdl
= rLink
;
356 ContentTabPage_Impl::~ContentTabPage_Impl()
358 std::unique_ptr
<weld::TreeIter
> xEntry
= m_xContentBox
->make_iterator();
359 bool bEntry
= m_xContentBox
->get_iter_first(*xEntry
);
362 ClearChildren(xEntry
.get());
363 delete reinterpret_cast<ContentEntry_Impl
*>(m_xContentBox
->get_id(*xEntry
).toInt64());
364 bEntry
= m_xContentBox
->iter_next_sibling(*xEntry
);
368 void IndexTabPage_Impl::SelectExecutableEntry()
370 sal_Int32 nPos
= m_xIndexList
->find_text(m_xIndexEntry
->get_text());
374 sal_Int32 nOldPos
= nPos
;
376 IndexEntry_Impl
* pEntry
= reinterpret_cast<IndexEntry_Impl
*>(m_xIndexList
->get_id(nPos
).toInt64());
377 sal_Int32 nCount
= m_xIndexList
->n_children();
378 while ( nPos
< nCount
&& ( !pEntry
|| pEntry
->m_aURL
.isEmpty() ) )
380 pEntry
= reinterpret_cast<IndexEntry_Impl
*>(m_xIndexList
->get_id(++nPos
).toInt64());
381 aEntryText
= m_xIndexList
->get_text(nPos
);
384 if ( nOldPos
!= nPos
)
385 m_xIndexEntry
->set_text(aEntryText
);
388 // class IndexTabPage_Impl -----------------------------------------------
389 IndexTabPage_Impl::IndexTabPage_Impl(weld::Widget
* pParent
, SfxHelpIndexWindow_Impl
* pIdxWin
)
390 : HelpTabPage_Impl(pParent
, pIdxWin
, "HelpIndexPage", "sfx/ui/helpindexpage.ui")
391 , m_xIndexEntry(m_xBuilder
->weld_entry("termentry"))
392 , m_xIndexList(m_xBuilder
->weld_tree_view("termlist"))
393 , m_xOpenBtn(m_xBuilder
->weld_button("display"))
394 , aFactoryIdle("sfx2 appl IndexTabPage_Impl Factory")
395 , aAutoCompleteIdle("sfx2 appl IndexTabPage_Impl AutoComplete")
396 , aKeywordTimer("sfx2::IndexTabPage_Impl aKeywordTimer")
397 , bIsActivated(false)
398 , nRowHeight(m_xIndexList
->get_height_rows(1))
402 m_xIndexList
->set_size_request(m_xIndexList
->get_approximate_digit_width() * 30, -1);
404 m_xOpenBtn
->connect_clicked(LINK(this, IndexTabPage_Impl
, OpenHdl
));
405 aFactoryIdle
.SetInvokeHandler( LINK(this, IndexTabPage_Impl
, IdleHdl
));
406 aAutoCompleteIdle
.SetInvokeHandler( LINK(this, IndexTabPage_Impl
, AutoCompleteHdl
));
407 aKeywordTimer
.SetInvokeHandler( LINK( this, IndexTabPage_Impl
, TimeoutHdl
) );
408 m_xIndexList
->connect_row_activated(LINK(this, IndexTabPage_Impl
, DoubleClickHdl
));
409 m_xIndexList
->connect_changed(LINK(this, IndexTabPage_Impl
, TreeChangeHdl
));
410 m_xIndexList
->connect_custom_get_size(LINK(this, IndexTabPage_Impl
, CustomGetSizeHdl
));
411 m_xIndexList
->connect_custom_render(LINK(this, IndexTabPage_Impl
, CustomRenderHdl
));
412 m_xIndexList
->set_column_custom_renderer(0, true);
413 m_xIndexList
->connect_size_allocate(LINK(this, IndexTabPage_Impl
, ResizeHdl
));
414 m_xIndexEntry
->connect_key_press(LINK(this, IndexTabPage_Impl
, KeyInputHdl
));
415 m_xIndexEntry
->connect_changed(LINK(this, IndexTabPage_Impl
, EntryChangeHdl
));
416 m_xIndexEntry
->connect_activate(LINK(this, IndexTabPage_Impl
, ActivateHdl
));
419 IMPL_LINK(IndexTabPage_Impl
, ResizeHdl
, const Size
&, rSize
, void)
421 nAllHeight
= rSize
.Height();
424 IMPL_LINK_NOARG(IndexTabPage_Impl
, CustomGetSizeHdl
, weld::TreeView::get_size_args
, Size
)
426 return Size(m_xIndexList
->get_size_request().Width(), nRowHeight
);
429 IMPL_LINK(IndexTabPage_Impl
, CustomRenderHdl
, weld::TreeView::render_args
, aPayload
, void)
431 vcl::RenderContext
& rRenderContext
= std::get
<0>(aPayload
);
432 const ::tools::Rectangle
& rRect
= std::get
<1>(aPayload
);
433 bool bSelected
= std::get
<2>(aPayload
);
434 const OUString
& rId
= std::get
<3>(aPayload
);
436 rRenderContext
.Push(vcl::PushFlags::TEXTCOLOR
);
437 const StyleSettings
& rStyleSettings
= Application::GetSettings().GetStyleSettings();
439 rRenderContext
.SetTextColor(rStyleSettings
.GetHighlightTextColor());
441 rRenderContext
.SetTextColor(rStyleSettings
.GetDialogTextColor());
443 Point
aPos(rRect
.TopLeft());
444 aPos
.AdjustY((rRect
.GetHeight() - rRenderContext
.GetTextHeight()) / 2);
446 int nIndex
= m_xIndexList
->find_id(rId
);
447 OUString
aEntry(m_xIndexList
->get_text(nIndex
));
449 IndexEntry_Impl
* pEntry
= reinterpret_cast<IndexEntry_Impl
*>(rId
.toInt64());
450 if (pEntry
&& pEntry
->m_bSubEntry
)
452 // indent sub entries
454 sal_Int32 nPos
= aEntry
.indexOf(';');
455 rRenderContext
.DrawText(aPos
, (nPos
!=-1) ? aEntry
.copy(nPos
+ 1) : aEntry
);
458 rRenderContext
.DrawText(aPos
, aEntry
);
460 rRenderContext
.Pop();
463 IMPL_LINK_NOARG(IndexTabPage_Impl
, TreeChangeHdl
, weld::TreeView
&, void)
465 m_xIndexEntry
->set_text(m_xIndexList
->get_selected_text());
468 IMPL_LINK_NOARG(IndexTabPage_Impl
, EntryChangeHdl
, weld::Entry
&, void)
470 switch (nLastCharCode
)
472 case css::awt::Key::DELETE_WORD_BACKWARD
:
473 case css::awt::Key::DELETE_WORD_FORWARD
:
474 case css::awt::Key::DELETE_TO_BEGIN_OF_LINE
:
475 case css::awt::Key::DELETE_TO_END_OF_LINE
:
478 aAutoCompleteIdle
.Stop();
481 aAutoCompleteIdle
.Start();
486 IMPL_LINK(IndexTabPage_Impl
, KeyInputHdl
, const KeyEvent
&, rKEvt
, bool)
488 const vcl::KeyCode
& rKCode
= rKEvt
.GetKeyCode();
489 if (rKCode
.GetModifier()) // only with no modifiers held
492 sal_uInt16 nCode
= rKCode
.GetCode();
494 if (nCode
== KEY_UP
|| nCode
== KEY_PAGEUP
||
495 nCode
== KEY_DOWN
|| nCode
== KEY_PAGEDOWN
)
497 // disable_notify_events();
498 sal_Int32 nIndex
= m_xIndexList
->get_selected_index();
499 sal_Int32 nOrigIndex
= nIndex
;
500 sal_Int32 nCount
= m_xIndexList
->n_children();
503 m_xIndexList
->set_cursor(0);
504 m_xIndexList
->select(0);
505 m_xIndexEntry
->set_text(m_xIndexList
->get_selected_text());
511 else if (nCode
== KEY_DOWN
)
513 else if (nCode
== KEY_PAGEUP
)
515 int nVisRows
= nAllHeight
/ nRowHeight
;
518 else if (nCode
== KEY_PAGEDOWN
)
520 int nVisRows
= nAllHeight
/ nRowHeight
;
526 if (nIndex
>= nCount
)
529 if (nIndex
!= nOrigIndex
)
531 m_xIndexList
->set_cursor(nIndex
);
532 m_xIndexList
->select(nIndex
);
533 m_xIndexEntry
->set_text(m_xIndexList
->get_selected_text());
536 // m_xIndexList->grab_focus();
537 // g_signal_emit_by_name(pWidget, "key-press-event", pEvent, &ret);
538 // m_xIndexEntry->set_text(m_xIndexList->get_selected_text());
539 // m_xIndexEntry->grab_focus();
541 m_xIndexEntry
->select_region(0, -1);
542 // enable_notify_events();
543 // m_bTreeChange = true;
544 // m_pEntry->fire_signal_changed();
545 // m_bTreeChange = false;
549 nLastCharCode
= nCode
;
553 IndexTabPage_Impl::~IndexTabPage_Impl()
560 typedef std::unordered_map
< OUString
, int > KeywordInfo
;
563 void IndexTabPage_Impl::InitializeIndex()
565 weld::WaitObject
aWaitCursor(m_pIdxWin
->GetFrameWeld());
567 // By now more than 256 equal entries are not allowed
568 sal_Unicode append
[256];
569 for(sal_Unicode
& k
: append
)
572 sfx2::KeywordInfo aInfo
;
573 m_xIndexList
->freeze();
577 OUStringBuffer
aURL(HELP_URL
);
578 aURL
.append(sFactory
);
579 AppendConfigToken(aURL
, true);
581 Content
aCnt( aURL
.makeStringAndClear(), Reference
< css::ucb::XCommandEnvironment
>(), comphelper::getProcessComponentContext() );
582 css::uno::Reference
< css::beans::XPropertySetInfo
> xInfo
= aCnt
.getProperties();
583 if ( xInfo
->hasPropertyByName( PROPERTY_ANCHORREF
) )
585 css::uno::Sequence
< OUString
> aPropSeq
{ PROPERTY_KEYWORDLIST
, PROPERTY_KEYWORDREF
,
586 PROPERTY_ANCHORREF
, PROPERTY_TITLEREF
};
588 // abi: use one possibly remote call only
589 css::uno::Sequence
< css::uno::Any
> aAnySeq
=
590 aCnt
.getPropertyValues( aPropSeq
);
592 css::uno::Sequence
< OUString
> aKeywordList
;
593 css::uno::Sequence
< css::uno::Sequence
< OUString
> > aKeywordRefList
;
594 css::uno::Sequence
< css::uno::Sequence
< OUString
> > aAnchorRefList
;
595 css::uno::Sequence
< css::uno::Sequence
< OUString
> > aTitleRefList
;
597 if ( ( aAnySeq
[0] >>= aKeywordList
) && ( aAnySeq
[1] >>= aKeywordRefList
) &&
598 ( aAnySeq
[2] >>= aAnchorRefList
) && ( aAnySeq
[3] >>= aTitleRefList
) )
601 OUString aIndex
, aTempString
;
602 OUStringBuffer
aData( 128 ); // Capacity of up to 128 characters
603 sfx2::KeywordInfo::iterator it
;
605 for ( int i
= 0; i
< aKeywordList
.getLength(); ++i
)
607 // abi: Do not copy, but use references
608 const OUString
& aKeywordPair
= aKeywordList
[i
];
609 DBG_ASSERT( !aKeywordPair
.isEmpty(), "invalid help index" );
610 const css::uno::Sequence
< OUString
>& aRefList
= aKeywordRefList
[i
];
611 const css::uno::Sequence
< OUString
>& aAnchorList
= aAnchorRefList
[i
];
612 const css::uno::Sequence
< OUString
>& aTitleList
= aTitleRefList
[i
];
614 DBG_ASSERT( aRefList
.getLength() == aAnchorList
.getLength(),"reference list and title list of different length" );
616 ndx
= aKeywordPair
.indexOf( ';' );
617 const bool insert
= ndx
!= -1;
623 aTempString
= aKeywordPair
.copy( 0, ndx
);
624 if ( aIndex
!= aTempString
)
626 aIndex
= aTempString
;
627 it
= aInfo
.emplace(aTempString
, 0).first
;
628 sId
= OUString::number(reinterpret_cast<sal_Int64
>(new IndexEntry_Impl(OUString(), false)));
629 if ( (tmp
= it
->second
++) != 0)
630 m_xIndexList
->append(
631 sId
, aTempString
+ std::u16string_view(append
, tmp
));
633 m_xIndexList
->append(sId
, aTempString
);
639 sal_uInt32 nRefListLen
= aRefList
.getLength();
641 DBG_ASSERT( aAnchorList
.hasElements(), "*IndexTabPage_Impl::InitializeIndex(): AnchorList is empty!" );
642 DBG_ASSERT( nRefListLen
, "*IndexTabPage_Impl::InitializeIndex(): RefList is empty!" );
644 if ( aAnchorList
.hasElements() && nRefListLen
)
646 if ( aAnchorList
[0].getLength() > 0 )
648 aData
.append( aRefList
[0] ).append( '#' ).append( aAnchorList
[0] );
649 sId
= OUString::number(reinterpret_cast<sal_Int64
>(new IndexEntry_Impl(aData
.makeStringAndClear(), insert
)));
652 sId
= OUString::number(reinterpret_cast<sal_Int64
>(new IndexEntry_Impl(aRefList
[0], insert
)));
655 // Assume the token is trimmed
656 it
= aInfo
.emplace(aKeywordPair
, 0).first
;
657 if ((tmp
= it
->second
++) != 0)
658 m_xIndexList
->append(sId
, aKeywordPair
+ std::u16string_view(append
, tmp
));
660 m_xIndexList
->append(sId
, aKeywordPair
);
662 for ( sal_uInt32 j
= 1; j
< nRefListLen
; ++j
)
665 .append( aKeywordPair
)
669 .append( aTitleList
[j
] );
671 aTempString
= aData
.makeStringAndClear();
673 if ( aAnchorList
[j
].getLength() > 0 )
675 aData
.append( aRefList
[j
] ).append( '#' ).append( aAnchorList
[j
] );
676 sId
= OUString::number(reinterpret_cast<sal_Int64
>(new IndexEntry_Impl(aData
.makeStringAndClear(), insert
)));
679 sId
= OUString::number(reinterpret_cast<sal_Int64
>(new IndexEntry_Impl(aRefList
[j
], insert
)));
681 it
= aInfo
.emplace(aTempString
, 0).first
;
682 if ( (tmp
= it
->second
++) != 0 )
683 m_xIndexList
->append(
684 sId
, aTempString
+ std::u16string_view(append
, tmp
));
686 m_xIndexList
->append(sId
, aTempString
);
694 TOOLS_WARN_EXCEPTION( "sfx.appl", "IndexTabPage_Impl::InitializeIndex(): unexpected exception" );
697 m_xIndexList
->thaw();
699 if ( !sKeyword
.isEmpty() )
700 aKeywordLink
.Call( *this );
703 void IndexTabPage_Impl::ClearIndex()
705 const sal_Int32 nCount
= m_xIndexList
->n_children();
706 for ( sal_Int32 i
= 0; i
< nCount
; ++i
)
707 delete reinterpret_cast<IndexEntry_Impl
*>(m_xIndexList
->get_id(i
).toInt64());
708 m_xIndexList
->clear();
711 IMPL_LINK_NOARG(IndexTabPage_Impl
, OpenHdl
, weld::Button
&, void)
713 aDoubleClickHdl
.Call(nullptr);
716 IMPL_LINK_NOARG(IndexTabPage_Impl
, ActivateHdl
, weld::Entry
&, bool)
718 aDoubleClickHdl
.Call(nullptr);
722 IMPL_LINK_NOARG(IndexTabPage_Impl
, DoubleClickHdl
, weld::TreeView
&, bool)
724 aDoubleClickHdl
.Call(nullptr);
728 IMPL_LINK_NOARG(IndexTabPage_Impl
, IdleHdl
, Timer
*, void)
733 int IndexTabPage_Impl::starts_with(const OUString
& rStr
, int nStartRow
, bool bCaseSensitive
)
735 const vcl::I18nHelper
& rI18nHelper
= Application::GetSettings().GetUILocaleI18nHelper();
737 int nRet
= nStartRow
;
738 int nCount
= m_xIndexList
->n_children();
739 while (nRet
< nCount
)
741 OUString
aStr(m_xIndexList
->get_text(nRet
));
742 const bool bMatch
= !bCaseSensitive
? rI18nHelper
.MatchString(rStr
, aStr
) : aStr
.startsWith(rStr
);
751 IMPL_LINK_NOARG(IndexTabPage_Impl
, AutoCompleteHdl
, Timer
*, void)
753 OUString aStartText
= m_xIndexEntry
->get_text();
754 int nStartPos
, nEndPos
;
755 m_xIndexEntry
->get_selection_bounds(nStartPos
, nEndPos
);
756 int nMaxSelection
= std::max(nStartPos
, nEndPos
);
757 if (nMaxSelection
!= aStartText
.getLength())
760 int nActive
= m_xIndexList
->get_selected_index();
761 int nStart
= nActive
;
766 // Try match case insensitive from current position
767 int nPos
= starts_with(aStartText
, nStart
, false);
768 if (nPos
== -1 && nStart
!= 0)
770 // Try match case insensitive, but from start
771 nPos
= starts_with(aStartText
, 0, false);
776 // Try match case sensitive from current position
777 nPos
= starts_with(aStartText
, nStart
, true);
778 if (nPos
== -1 && nStart
!= 0)
780 // Try match case sensitive, but from start
781 nPos
= starts_with(aStartText
, 0, true);
787 m_xIndexList
->set_cursor(nPos
);
788 m_xIndexList
->select(nPos
);
789 OUString aText
= m_xIndexList
->get_text(nPos
);
790 if (aText
!= aStartText
)
791 m_xIndexEntry
->set_text(aText
);
792 m_xIndexEntry
->select_region(aText
.getLength(), aStartText
.getLength());
796 IMPL_LINK( IndexTabPage_Impl
, TimeoutHdl
, Timer
*, pTimer
, void)
798 if(&aKeywordTimer
== pTimer
&& !sKeyword
.isEmpty())
799 aKeywordLink
.Call(*this);
802 void IndexTabPage_Impl::Activate()
807 aFactoryIdle
.Start();
811 void IndexTabPage_Impl::SetDoubleClickHdl(const Link
<LinkParamNone
*, void>& rLink
)
813 aDoubleClickHdl
= rLink
;
816 void IndexTabPage_Impl::SetFactory( const OUString
& rFactory
)
818 OUString
sNewFactory( rFactory
);
819 DBG_ASSERT( !sNewFactory
.isEmpty(), "empty factory" );
820 bool bValid
= m_pIdxWin
->IsValidFactory( rFactory
);
822 if ( sFactory
.isEmpty() && !bValid
)
824 sNewFactory
= SfxHelp::GetDefaultHelpModule();
828 if ( sNewFactory
!= sFactory
&& bValid
)
830 sFactory
= sNewFactory
;
833 aFactoryIdle
.Start();
837 OUString
IndexTabPage_Impl::GetSelectedEntry() const
840 IndexEntry_Impl
* pEntry
= reinterpret_cast<IndexEntry_Impl
*>(m_xIndexList
->get_id(m_xIndexList
->find_text(m_xIndexEntry
->get_text())).toInt64());
842 aRet
= pEntry
->m_aURL
;
846 void IndexTabPage_Impl::SetKeyword( const OUString
& rKeyword
)
850 if (m_xIndexList
->n_children() > 0)
851 aKeywordTimer
.Start();
852 else if ( !bIsActivated
)
853 aFactoryIdle
.Start();
857 bool IndexTabPage_Impl::HasKeyword() const
860 if ( !sKeyword
.isEmpty() )
862 sal_Int32 nPos
= m_xIndexList
->find_text( sKeyword
);
870 bool IndexTabPage_Impl::HasKeywordIgnoreCase()
873 if ( !sKeyword
.isEmpty() )
875 sal_Int32 nEntries
= m_xIndexList
->n_children();
876 const vcl::I18nHelper
& rI18nHelper
= Application::GetSettings().GetLocaleI18nHelper();
877 for ( sal_Int32 n
= 0; n
< nEntries
; n
++)
879 const OUString sIndexItem
{m_xIndexList
->get_text(n
)};
880 if (rI18nHelper
.MatchString( sIndexItem
, sKeyword
))
882 sKeyword
= sIndexItem
;
891 void IndexTabPage_Impl::OpenKeyword()
893 if ( !sKeyword
.isEmpty() )
895 m_xIndexEntry
->set_text(sKeyword
);
896 aDoubleClickHdl
.Call(nullptr);
901 IMPL_LINK_NOARG(SearchTabPage_Impl
, ActivateHdl
, weld::ComboBox
&, bool)
907 // class SearchTabPage_Impl ----------------------------------------------
909 SearchTabPage_Impl::SearchTabPage_Impl(weld::Widget
* pParent
, SfxHelpIndexWindow_Impl
* pIdxWin
)
910 : HelpTabPage_Impl(pParent
, pIdxWin
, "HelpSearchPage",
911 "sfx/ui/helpsearchpage.ui")
912 , m_xSearchED(m_xBuilder
->weld_combo_box("search"))
913 , m_xSearchBtn(m_xBuilder
->weld_button("find"))
914 , m_xFullWordsCB(m_xBuilder
->weld_check_button("completewords"))
915 , m_xScopeCB(m_xBuilder
->weld_check_button("headings"))
916 , m_xResultsLB(m_xBuilder
->weld_tree_view("results"))
917 , m_xOpenBtn(m_xBuilder
->weld_button("display"))
918 , xBreakIterator(vcl::unohelper::CreateBreakIterator())
920 m_xResultsLB
->set_size_request(m_xResultsLB
->get_approximate_digit_width() * 30,
921 m_xResultsLB
->get_height_rows(15));
923 m_xSearchBtn
->connect_clicked(LINK(this, SearchTabPage_Impl
, ClickHdl
));
924 m_xSearchED
->connect_changed(LINK(this, SearchTabPage_Impl
, ModifyHdl
));
925 m_xSearchED
->connect_entry_activate(LINK(this, SearchTabPage_Impl
, ActivateHdl
));
926 m_xOpenBtn
->connect_clicked(LINK(this, SearchTabPage_Impl
, OpenHdl
));
927 m_xResultsLB
->connect_row_activated(LINK(this, SearchTabPage_Impl
, DoubleClickHdl
));
929 SvtViewOptions
aViewOpt( EViewType::TabPage
, CONFIGNAME_SEARCHPAGE
);
930 if ( aViewOpt
.Exists() )
933 Any aUserItem
= aViewOpt
.GetUserItem( USERITEM_NAME
);
934 if ( aUserItem
>>= aUserData
)
937 bool bChecked
= aUserData
.getToken(0, ';', nIdx
).toInt32() == 1;
938 m_xFullWordsCB
->set_active(bChecked
);
939 bChecked
= aUserData
.getToken(0, ';', nIdx
).toInt32() == 1;
940 m_xScopeCB
->set_active(bChecked
);
944 m_xSearchED
->append_text( INetURLObject::decode(
945 aUserData
.getToken(0, ';', nIdx
),
946 INetURLObject::DecodeMechanism::WithCharset
) );
951 ModifyHdl(*m_xSearchED
);
954 SearchTabPage_Impl::~SearchTabPage_Impl()
956 SvtViewOptions
aViewOpt( EViewType::TabPage
, CONFIGNAME_SEARCHPAGE
);
957 OUStringBuffer aUserData
=
958 OUString::number(m_xFullWordsCB
->get_active() ? 1 : 0) +
960 OUString::number(m_xScopeCB
->get_active() ? 1 : 0);
961 sal_Int32 nCount
= std::min(m_xSearchED
->get_count(), 10); // save only 10 entries
963 for ( sal_Int32 i
= 0; i
< nCount
; ++i
)
965 aUserData
.append(";" +
966 INetURLObject::encode(
967 m_xSearchED
->get_text(i
),
968 INetURLObject::PART_UNO_PARAM_VALUE
,
969 INetURLObject::EncodeMechanism::All
));
972 Any aUserItem
= makeAny( aUserData
.makeStringAndClear() );
973 aViewOpt
.SetUserItem( USERITEM_NAME
, aUserItem
);
976 m_xSearchBtn
.reset();
977 m_xFullWordsCB
.reset();
979 m_xResultsLB
.reset();
983 void SearchTabPage_Impl::ClearSearchResults()
985 m_xResultsLB
->clear();
988 void SearchTabPage_Impl::RememberSearchText( const OUString
& rSearchText
)
990 for (sal_Int32 i
= 0, nEntryCount
= m_xSearchED
->get_count(); i
< nEntryCount
; ++i
)
992 if (rSearchText
== m_xSearchED
->get_text(i
))
994 m_xSearchED
->remove(i
);
999 m_xSearchED
->insert_text(0, rSearchText
);
1002 IMPL_LINK_NOARG(SearchTabPage_Impl
, ClickHdl
, weld::Button
&, void)
1007 void SearchTabPage_Impl::Search()
1009 OUString aSearchText
= comphelper::string::strip(m_xSearchED
->get_active_text(), ' ');
1010 if ( aSearchText
.isEmpty() )
1013 std::unique_ptr
<weld::WaitObject
> xWaitCursor(new weld::WaitObject(m_pIdxWin
->GetFrameWeld()));
1014 ClearSearchResults();
1015 RememberSearchText( aSearchText
);
1016 OUStringBuffer
aSearchURL(HELP_URL
);
1017 aSearchURL
.append(aFactory
);
1018 aSearchURL
.append(HELP_SEARCH_TAG
);
1019 if (!m_xFullWordsCB
->get_active())
1020 aSearchText
= sfx2::PrepareSearchString( aSearchText
, xBreakIterator
, true );
1021 aSearchURL
.append(aSearchText
);
1022 AppendConfigToken(aSearchURL
, false);
1023 if (m_xScopeCB
->get_active())
1024 aSearchURL
.append("&Scope=Heading");
1025 std::vector
< OUString
> aFactories
= SfxContentHelper::GetResultSet(aSearchURL
.makeStringAndClear());
1026 for (const OUString
& rRow
: aFactories
)
1029 OUString aTitle
= rRow
.getToken(0, '\t', nIdx
);
1030 OUString
sURL(rRow
.getToken(1, '\t', nIdx
));
1031 m_xResultsLB
->append(sURL
, aTitle
);
1033 xWaitCursor
.reset();
1035 if ( aFactories
.empty() )
1037 std::unique_ptr
<weld::MessageDialog
> xBox(Application::CreateMessageDialog(m_xContainer
.get(),
1038 VclMessageType::Info
, VclButtonsType::Ok
,
1039 SfxResId(STR_INFO_NOSEARCHRESULTS
)));
1044 IMPL_LINK_NOARG(SearchTabPage_Impl
, OpenHdl
, weld::Button
&, void)
1046 aDoubleClickHdl
.Call(nullptr);
1049 IMPL_LINK(SearchTabPage_Impl
, ModifyHdl
, weld::ComboBox
&, rComboBox
, void)
1051 OUString aSearchText
= comphelper::string::strip(m_xSearchED
->get_active_text(), ' ');
1052 m_xSearchBtn
->set_sensitive(!aSearchText
.isEmpty());
1054 if (rComboBox
.changed_by_direct_pick())
1058 IMPL_LINK_NOARG(SearchTabPage_Impl
, DoubleClickHdl
, weld::TreeView
&, bool)
1060 aDoubleClickHdl
.Call(nullptr);
1064 void SearchTabPage_Impl::SetDoubleClickHdl(const Link
<LinkParamNone
*, void>& rLink
)
1066 aDoubleClickHdl
= rLink
;
1069 OUString
SearchTabPage_Impl::GetSelectedEntry() const
1071 return m_xResultsLB
->get_selected_id();
1074 void SearchTabPage_Impl::ClearPage()
1076 ClearSearchResults();
1077 m_xSearchED
->set_entry_text(OUString());
1080 bool SearchTabPage_Impl::OpenKeyword( const OUString
& rKeyword
)
1083 m_xSearchED
->set_entry_text(rKeyword
);
1085 if (m_xResultsLB
->n_children() > 0)
1087 // found keyword -> open it
1088 m_xResultsLB
->select(0);
1089 OpenHdl(*m_xOpenBtn
);
1095 // class BookmarksTabPage_Impl -------------------------------------------
1097 void BookmarksTabPage_Impl::DoAction(std::string_view rAction
)
1099 if (rAction
== "display")
1100 aDoubleClickHdl
.Call(nullptr);
1101 else if (rAction
== "rename")
1103 sal_Int32 nPos
= m_xBookmarksBox
->get_selected_index();
1106 SfxAddHelpBookmarkDialog_Impl
aDlg(m_xBookmarksBox
.get(), true);
1107 aDlg
.SetTitle(m_xBookmarksBox
->get_text(nPos
));
1108 if (aDlg
.run() == RET_OK
)
1110 OUString sURL
= m_xBookmarksBox
->get_id(nPos
);
1111 m_xBookmarksBox
->remove(nPos
);
1112 m_xBookmarksBox
->append(sURL
, aDlg
.GetTitle(), SvFileInformationManager::GetImageId(INetURLObject(IMAGE_URL
+INetURLObject(sURL
).GetHost())));
1113 m_xBookmarksBox
->select(m_xBookmarksBox
->n_children() - 1);
1117 else if (rAction
== "delete")
1119 sal_Int32 nPos
= m_xBookmarksBox
->get_selected_index();
1122 m_xBookmarksBox
->remove(nPos
);
1123 const sal_Int32 nCount
= m_xBookmarksBox
->n_children();
1128 m_xBookmarksBox
->select(nPos
);
1134 IMPL_LINK(BookmarksTabPage_Impl
, CommandHdl
, const CommandEvent
&, rCEvt
, bool)
1136 if (rCEvt
.GetCommand() != CommandEventId::ContextMenu
)
1139 std::unique_ptr
<weld::Builder
> xBuilder(Application::CreateBuilder(m_xBookmarksBox
.get(), "sfx/ui/bookmarkmenu.ui"));
1140 std::unique_ptr
<weld::Menu
> xMenu
= xBuilder
->weld_menu("menu");
1142 OString sIdent
= xMenu
->popup_at_rect(m_xBookmarksBox
.get(), ::tools::Rectangle(rCEvt
.GetMousePosPixel(), Size(1,1)));
1143 if (!sIdent
.isEmpty())
1148 IMPL_LINK(BookmarksTabPage_Impl
, KeyInputHdl
, const KeyEvent
&, rKEvt
, bool)
1150 bool bHandled
= false;
1151 sal_uInt16 nCode
= rKEvt
.GetKeyCode().GetCode();
1152 if (KEY_DELETE
== nCode
&& m_xBookmarksBox
->n_children() > 0)
1160 // class BookmarksTabPage_Impl -------------------------------------------
1161 BookmarksTabPage_Impl::BookmarksTabPage_Impl(weld::Widget
* pParent
, SfxHelpIndexWindow_Impl
* _pIdxWin
)
1162 : HelpTabPage_Impl(pParent
, _pIdxWin
, "HelpBookmarkPage",
1163 "sfx/ui/helpbookmarkpage.ui")
1164 , m_xBookmarksBox(m_xBuilder
->weld_tree_view("bookmarks"))
1165 , m_xBookmarksPB(m_xBuilder
->weld_button("display"))
1167 m_xBookmarksBox
->set_size_request(m_xBookmarksBox
->get_approximate_digit_width() * 30,
1168 m_xBookmarksBox
->get_height_rows(20));
1170 m_xBookmarksPB
->connect_clicked( LINK(this, BookmarksTabPage_Impl
, OpenHdl
));
1171 m_xBookmarksBox
->connect_row_activated(LINK(this, BookmarksTabPage_Impl
, DoubleClickHdl
));
1172 m_xBookmarksBox
->connect_popup_menu(LINK(this, BookmarksTabPage_Impl
, CommandHdl
));
1173 m_xBookmarksBox
->connect_key_press(LINK(this, BookmarksTabPage_Impl
, KeyInputHdl
));
1175 // load bookmarks from configuration
1176 const std::vector
< SvtHistoryOptions::HistoryItem
> aBookmarkSeq
= SvtHistoryOptions::GetList( EHistoryType::HelpBookmarks
);
1177 for ( const auto& rBookmark
: aBookmarkSeq
)
1179 AddBookmarks( rBookmark
.sTitle
, rBookmark
.sURL
);
1183 BookmarksTabPage_Impl::~BookmarksTabPage_Impl()
1185 // save bookmarks to configuration
1186 SvtHistoryOptions::Clear( EHistoryType::HelpBookmarks
);
1187 const sal_Int32 nCount
= m_xBookmarksBox
->n_children();
1188 for (sal_Int32 i
= 0; i
< nCount
; ++i
)
1189 SvtHistoryOptions::AppendItem(EHistoryType::HelpBookmarks
, m_xBookmarksBox
->get_id(i
), "", m_xBookmarksBox
->get_text(i
), std::nullopt
);
1191 m_xBookmarksBox
.reset();
1192 m_xBookmarksPB
.reset();
1195 IMPL_LINK_NOARG(BookmarksTabPage_Impl
, OpenHdl
, weld::Button
&, void)
1197 aDoubleClickHdl
.Call(nullptr);
1200 IMPL_LINK_NOARG(BookmarksTabPage_Impl
, DoubleClickHdl
, weld::TreeView
&, bool)
1202 aDoubleClickHdl
.Call(nullptr);
1206 void BookmarksTabPage_Impl::SetDoubleClickHdl(const Link
<LinkParamNone
*, void>& rLink
)
1208 aDoubleClickHdl
= rLink
;
1211 OUString
BookmarksTabPage_Impl::GetSelectedEntry() const
1213 return m_xBookmarksBox
->get_selected_id();
1216 void BookmarksTabPage_Impl::AddBookmarks(const OUString
& rTitle
, const OUString
& rURL
)
1218 const OUString aImageURL
{IMAGE_URL
+ INetURLObject(rURL
).GetHost()};
1219 m_xBookmarksBox
->append(rURL
, rTitle
, SvFileInformationManager::GetImageId(INetURLObject(aImageURL
)));
1222 OUString
SfxHelpWindow_Impl::buildHelpURL(std::u16string_view sFactory
,
1223 std::u16string_view sContent
,
1224 std::u16string_view sAnchor
)
1226 OUStringBuffer
sHelpURL(256);
1227 sHelpURL
.append(HELP_URL
);
1228 sHelpURL
.append(sFactory
);
1229 sHelpURL
.append(sContent
);
1230 AppendConfigToken(sHelpURL
, true/*bUseQuestionMark*/);
1231 if (!sAnchor
.empty())
1232 sHelpURL
.append(sAnchor
);
1233 return sHelpURL
.makeStringAndClear();
1236 void SfxHelpWindow_Impl::loadHelpContent(const OUString
& sHelpURL
, bool bAddToHistory
)
1238 Reference
< XComponentLoader
> xLoader(getTextFrame(), UNO_QUERY
);
1242 // If a print job runs do not open a new page
1243 Reference
< XFrame2
> xTextFrame
= pTextWin
->getFrame();
1244 Reference
< XController
> xTextController
;
1245 if (xTextFrame
.is())
1246 xTextController
= xTextFrame
->getController ();
1247 if ( xTextController
.is() && !xTextController
->suspend( true ) )
1249 xTextController
->suspend( false );
1253 // save url to history
1255 pHelpInterceptor
->addURL(sHelpURL
);
1259 bool bSuccess
= false;
1260 // TODO implement locale fallback ... see below while(true)
1264 Reference
< XComponent
> xContent
= xLoader
->loadComponentFromURL(sHelpURL
, "_self", 0, Sequence
< PropertyValue
>());
1270 catch(const RuntimeException
&)
1272 catch(const Exception
&)
1275 /* TODO try next locale ...
1276 no further locale available? => break loop and show error page
1279 openDone(sHelpURL
, bSuccess
);
1284 IMPL_LINK(SfxHelpIndexWindow_Impl
, ActivatePageHdl
, const OString
&, rPage
, void)
1286 GetPage(rPage
)->Activate();
1289 SfxHelpIndexWindow_Impl::SfxHelpIndexWindow_Impl(SfxHelpWindow_Impl
* _pParent
, weld::Container
* pContainer
)
1290 : m_xBuilder(Application::CreateBuilder(pContainer
, "sfx/ui/helpcontrol.ui"))
1291 , m_xContainer(m_xBuilder
->weld_container("HelpControl"))
1292 , m_xActiveLB(m_xBuilder
->weld_combo_box("active"))
1293 , m_xTabCtrl(m_xBuilder
->weld_notebook("tabcontrol"))
1294 , aIdle("sfx2 appl SfxHelpIndexWindow_Impl")
1295 , aIndexKeywordLink(LINK(this, SfxHelpIndexWindow_Impl
, KeywordHdl
))
1296 , pParentWin(_pParent
)
1297 , bIsInitDone(false)
1305 OString
sPageId("index");
1306 SvtViewOptions
aViewOpt( EViewType::TabDialog
, CONFIGNAME_INDEXWIN
);
1307 if ( aViewOpt
.Exists() )
1309 OString sSavedPageId
= aViewOpt
.GetPageID();
1310 if (m_xTabCtrl
->get_page_index(sSavedPageId
) != -1)
1311 sPageId
= sSavedPageId
;
1313 m_xTabCtrl
->set_current_page(sPageId
);
1314 ActivatePageHdl(sPageId
);
1315 m_xActiveLB
->connect_changed(LINK(this, SfxHelpIndexWindow_Impl
, SelectHdl
));
1317 m_xTabCtrl
->connect_enter_page(LINK(this, SfxHelpIndexWindow_Impl
, ActivatePageHdl
));
1319 aIdle
.SetInvokeHandler( LINK( this, SfxHelpIndexWindow_Impl
, InitHdl
) );
1322 m_xContainer
->show();
1325 SfxHelpIndexWindow_Impl::~SfxHelpIndexWindow_Impl()
1327 SvtViewOptions
aViewOpt(EViewType::TabDialog
, CONFIGNAME_INDEXWIN
);
1328 aViewOpt
.SetPageID(m_xTabCtrl
->get_current_page_ident());
1336 void SfxHelpIndexWindow_Impl::Initialize()
1338 OUStringBuffer
aHelpURL(HELP_URL
);
1339 AppendConfigToken(aHelpURL
, true);
1340 std::vector
<OUString
> aFactories
= SfxContentHelper::GetResultSet(aHelpURL
.makeStringAndClear());
1341 for (const OUString
& rRow
: aFactories
)
1344 OUString aTitle
= rRow
.getToken( 0, '\t', nIdx
); // token 0
1345 OUString aURL
= rRow
.getToken( 1, '\t', nIdx
); // token 2
1346 OUString
aFactory(INetURLObject(aURL
).GetHost());
1347 m_xActiveLB
->append(aFactory
, aTitle
);
1350 if (m_xActiveLB
->get_active() == -1)
1354 void SfxHelpIndexWindow_Impl::SetActiveFactory()
1356 DBG_ASSERT( xIPage
, "index page not initialized" );
1357 if (!bIsInitDone
&& !m_xActiveLB
->get_count())
1363 for (sal_Int32 i
= 0, nEntryCount
= m_xActiveLB
->get_count(); i
< nEntryCount
; ++i
)
1365 OUString aFactory
= m_xActiveLB
->get_id(i
);
1366 aFactory
= aFactory
.toAsciiLowerCase();
1367 if (aFactory
== xIPage
->GetFactory())
1369 if (m_xActiveLB
->get_active() != i
)
1371 m_xActiveLB
->set_active(i
);
1372 aSelectFactoryLink
.Call(nullptr);
1379 HelpTabPage_Impl
* SfxHelpIndexWindow_Impl::GetPage(std::string_view rName
)
1381 HelpTabPage_Impl
* pPage
= nullptr;
1383 if (rName
== "contents")
1384 pPage
= GetContentPage();
1385 else if (rName
== "index")
1386 pPage
= GetIndexPage();
1387 else if (rName
== "find")
1388 pPage
= GetSearchPage();
1389 else if (rName
== "bookmarks")
1390 pPage
= GetBookmarksPage();
1392 assert(pPage
&& "SfxHelpIndexWindow_Impl::GetCurrentPage(): no current page");
1397 IMPL_LINK_NOARG(SfxHelpIndexWindow_Impl
, SelectHdl
, weld::ComboBox
&, void)
1402 IMPL_LINK_NOARG(SfxHelpIndexWindow_Impl
, InitHdl
, Timer
*, void)
1407 // now use the timer for selection
1408 aIdle
.SetInvokeHandler( LINK( this, SfxHelpIndexWindow_Impl
, SelectFactoryHdl
) );
1409 aIdle
.SetPriority( TaskPriority::LOWEST
);
1412 IMPL_LINK_NOARG(SfxHelpIndexWindow_Impl
, SelectFactoryHdl
, Timer
*, void)
1414 OUString aFactory
= m_xActiveLB
->get_active_id();
1415 if (!aFactory
.isEmpty())
1417 SetFactory(aFactory
.toAsciiLowerCase(), false);
1418 aSelectFactoryLink
.Call(this);
1422 IMPL_LINK_NOARG(SfxHelpIndexWindow_Impl
, KeywordHdl
, IndexTabPage_Impl
&, void)
1424 // keyword found on index?
1425 bool bIndex
= xIPage
->HasKeyword();
1428 bIndex
= xIPage
->HasKeywordIgnoreCase();
1429 // then set index or search page as current.
1430 OString sPageId
= bIndex
? "index" : "find";
1431 if (sPageId
!= m_xTabCtrl
->get_current_page_ident())
1432 m_xTabCtrl
->set_current_page(sPageId
);
1434 // at last we open the keyword
1436 xIPage
->OpenKeyword();
1437 else if ( !xSPage
->OpenKeyword( sKeyword
) )
1438 pParentWin
->ShowStartPage();
1441 IMPL_LINK_NOARG(SfxHelpIndexWindow_Impl
, IndexTabPageDoubleClickHdl
, LinkParamNone
*, void)
1443 aPageDoubleClickLink
.Call(nullptr);
1446 void SfxHelpIndexWindow_Impl::SetDoubleClickHdl(const Link
<LinkParamNone
*, void>& rLink
)
1448 aPageDoubleClickLink
= rLink
;
1451 IMPL_LINK_NOARG(SfxHelpIndexWindow_Impl
, ContentTabPageDoubleClickHdl
, LinkParamNone
*, void)
1453 aPageDoubleClickLink
.Call(nullptr);
1456 IMPL_LINK_NOARG(SfxHelpIndexWindow_Impl
, TabPageDoubleClickHdl
, LinkParamNone
*, void)
1458 aPageDoubleClickLink
.Call(nullptr);
1461 void SfxHelpIndexWindow_Impl::SetFactory( const OUString
& rFactory
, bool bActive
)
1463 if ( !rFactory
.isEmpty() )
1465 GetIndexPage()->SetFactory( rFactory
);
1466 // the index page made a check if rFactory is valid,
1467 // so the index page always returns a valid factory
1468 GetSearchPage()->SetFactory( GetIndexPage()->GetFactory() );
1474 OUString
SfxHelpIndexWindow_Impl::GetSelectedEntry() const
1478 OString
sName(m_xTabCtrl
->get_current_page_ident());
1480 if (sName
== "contents")
1482 sRet
= xCPage
->GetSelectedEntry();
1484 else if (sName
== "index")
1486 sRet
= xIPage
->GetSelectedEntry();
1488 else if (sName
== "find")
1490 sRet
= xSPage
->GetSelectedEntry();
1492 else if (sName
== "bookmarks")
1494 sRet
= xBPage
->GetSelectedEntry();
1500 void SfxHelpIndexWindow_Impl::AddBookmarks( const OUString
& rTitle
, const OUString
& rURL
)
1502 GetBookmarksPage()->AddBookmarks( rTitle
, rURL
);
1505 bool SfxHelpIndexWindow_Impl::IsValidFactory( std::u16string_view _rFactory
)
1507 bool bValid
= false;
1508 for (sal_Int32 i
= 0, nEntryCount
= m_xActiveLB
->get_count(); i
< nEntryCount
; ++i
)
1510 OUString aFactory
= m_xActiveLB
->get_id(i
);
1511 if (aFactory
== _rFactory
)
1520 void SfxHelpIndexWindow_Impl::ClearSearchPage()
1523 xSPage
->ClearPage();
1526 void SfxHelpIndexWindow_Impl::GrabFocusBack()
1528 OString
sName(m_xTabCtrl
->get_current_page_ident());
1530 if (sName
== "contents" && xCPage
)
1531 xCPage
->SetFocusOnBox();
1532 else if (sName
== "index" && xIPage
)
1533 xIPage
->SetFocusOnBox();
1534 else if (sName
== "find" && xSPage
)
1535 xSPage
->SetFocusOnBox();
1536 else if (sName
== "bookmarks" && xBPage
)
1537 xBPage
->SetFocusOnBox();
1540 bool SfxHelpIndexWindow_Impl::HasFocusOnEdit() const
1543 OString
sName(m_xTabCtrl
->get_current_page_ident());
1544 if (sName
== "index" && xIPage
)
1545 bRet
= xIPage
->HasFocusOnEdit();
1546 else if (sName
== "find" && xSPage
)
1547 bRet
= xSPage
->HasFocusOnEdit();
1551 OUString
SfxHelpIndexWindow_Impl::GetSearchText() const
1554 OString
sName(m_xTabCtrl
->get_current_page_ident());
1555 if (sName
== "find" && xSPage
)
1556 sRet
= xSPage
->GetSearchText();
1560 bool SfxHelpIndexWindow_Impl::IsFullWordSearch() const
1563 OString
sName(m_xTabCtrl
->get_current_page_ident());
1564 if (sName
== "find" && xSPage
)
1565 bRet
= xSPage
->IsFullWordSearch();
1569 void SfxHelpIndexWindow_Impl::OpenKeyword( const OUString
& rKeyword
)
1571 sKeyword
= rKeyword
;
1572 DBG_ASSERT( xIPage
, "invalid index page" );
1573 xIPage
->SetKeyword( sKeyword
);
1576 void SfxHelpIndexWindow_Impl::SelectExecutableEntry()
1578 OString
sName(m_xTabCtrl
->get_current_page_ident());
1579 if (sName
== "index" && xIPage
)
1580 xIPage
->SelectExecutableEntry();
1583 weld::Window
* SfxHelpIndexWindow_Impl::GetFrameWeld() const
1585 return pParentWin
->GetFrameWeld();
1588 // class TextWin_Impl ----------------------------------------------------
1589 TextWin_Impl::TextWin_Impl( vcl::Window
* p
) : DockingWindow( p
, 0 )
1593 bool TextWin_Impl::EventNotify( NotifyEvent
& rNEvt
)
1595 if( ( rNEvt
.GetType() == MouseNotifyEvent::KEYINPUT
) && rNEvt
.GetKeyEvent()->GetKeyCode().GetCode() == KEY_TAB
)
1596 return GetParent()->EventNotify( rNEvt
);
1598 return DockingWindow::EventNotify( rNEvt
);
1602 // remove docking area acceptor from layoutmanager, so it will not layout anything further .-)
1603 static void lcl_disableLayoutOfFrame(const Reference
< XFrame2
>& xFrame
)
1605 xFrame
->setLayoutManager( Reference
< XLayoutManager
>() );
1608 // class SfxHelpTextWindow_Impl ------------------------------------------
1610 SfxHelpTextWindow_Impl::SfxHelpTextWindow_Impl(SfxHelpWindow_Impl
* pHelpWin
, weld::Builder
& rBuilder
, vcl::Window
* pParent
) :
1612 Window( pParent
, WB_CLIPCHILDREN
| WB_TABSTOP
| WB_DIALOGCONTROL
),
1614 xToolBox ( rBuilder
.weld_toolbar("toolbar") ),
1615 xOnStartupCB ( rBuilder
.weld_check_button("checkbutton") ),
1616 xMenu ( rBuilder
.weld_menu("menu") ),
1617 aSelectIdle ( "sfx2 appl SfxHelpTextWindow_Impl Select" ),
1618 aIndexOnImage ( BMP_HELP_TOOLBOX_INDEX_ON
),
1619 aIndexOffImage ( BMP_HELP_TOOLBOX_INDEX_OFF
),
1620 aIndexOnText ( SfxResId( STR_HELP_BUTTON_INDEX_ON
) ),
1621 aIndexOffText ( SfxResId( STR_HELP_BUTTON_INDEX_OFF
) ),
1622 aOnStartupText ( SfxResId( RID_HELP_ONSTARTUP_TEXT
) ),
1623 xHelpWin ( pHelpWin
),
1624 pTextWin ( VclPtr
<TextWin_Impl
>::Create( this ) ),
1626 bIsIndexOn ( false ),
1627 bIsInClose ( false ),
1628 bIsFullWordSearch ( false )
1630 xFrame
= Frame::create( ::comphelper::getProcessComponentContext() );
1631 xFrame
->initialize( VCLUnoHelper::GetInterface ( pTextWin
) );
1632 xFrame
->setName( "OFFICE_HELP" );
1633 lcl_disableLayoutOfFrame(xFrame
);
1635 xToolBox
->set_help_id(HID_HELP_TOOLBOX
);
1637 xToolBox
->set_item_tooltip_text("index", aIndexOffText
);
1638 xToolBox
->set_item_help_id("index", HID_HELP_TOOLBOXITEM_INDEX
);
1639 xToolBox
->set_item_help_id("backward", HID_HELP_TOOLBOXITEM_BACKWARD
);
1640 xToolBox
->set_item_help_id("forward", HID_HELP_TOOLBOXITEM_FORWARD
);
1641 xToolBox
->set_item_help_id("start", HID_HELP_TOOLBOXITEM_START
);
1642 xToolBox
->set_item_help_id("print", HID_HELP_TOOLBOXITEM_PRINT
);
1643 xToolBox
->set_item_help_id("bookmarks", HID_HELP_TOOLBOXITEM_BOOKMARKS
);
1644 xToolBox
->set_item_help_id("searchdialog", HID_HELP_TOOLBOXITEM_SEARCHDIALOG
);
1646 InitToolBoxImages();
1648 xOnStartupCB
->connect_toggled(LINK(this, SfxHelpTextWindow_Impl
, CheckHdl
));
1650 aSelectIdle
.SetInvokeHandler( LINK( this, SfxHelpTextWindow_Impl
, SelectHdl
) );
1651 aSelectIdle
.SetPriority( TaskPriority::LOWEST
);
1653 char* pEnv
= getenv( "help_debug" );
1657 SvtMiscOptions().AddListenerLink( LINK( this, SfxHelpTextWindow_Impl
, NotifyHdl
) );
1660 SfxHelpTextWindow_Impl::~SfxHelpTextWindow_Impl()
1665 void SfxHelpTextWindow_Impl::dispose()
1668 SvtMiscOptions().RemoveListenerLink( LINK( this, SfxHelpTextWindow_Impl
, NotifyHdl
) );
1671 xOnStartupCB
.reset();
1673 pTextWin
.disposeAndClear();
1674 vcl::Window::dispose();
1677 bool SfxHelpTextWindow_Impl::HasSelection() const
1679 // is there any selection in the text and not only a cursor?
1681 Reference
< XTextRange
> xRange
= getCursor();
1684 Reference
< XText
> xText
= xRange
->getText();
1685 Reference
< XTextCursor
> xCursor
= xText
->createTextCursorByRange( xRange
);
1686 bRet
= !xCursor
->isCollapsed();
1692 void SfxHelpTextWindow_Impl::InitToolBoxImages()
1694 xToolBox
->set_item_icon_name("index", bIsIndexOn
? aIndexOffImage
: aIndexOnImage
);
1697 void SfxHelpTextWindow_Impl::InitOnStartupBox()
1699 sCurrentFactory
= SfxHelp::GetCurrentModuleIdentifier();
1701 Reference
< XComponentContext
> xContext
= ::comphelper::getProcessComponentContext();
1702 const OUString sPath
{ PATH_OFFICE_FACTORIES
+ sCurrentFactory
};
1704 // Attention: This check boy knows two states:
1705 // 1) Reading of the config key fails with an exception or by getting an empty Any (!) => check box must be hidden
1706 // 2) We read sal_True/sal_False => check box must be shown and enabled/disabled
1708 bool bHideBox
= true;
1709 bool bHelpAtStartup
= false;
1712 xConfiguration
= ConfigurationHelper::openConfig(
1713 xContext
, PACKAGE_SETUP
, EConfigurationModes::Standard
);
1714 if ( xConfiguration
.is() )
1716 Any aAny
= ConfigurationHelper::readRelativeKey( xConfiguration
, sPath
, KEY_HELP_ON_OPEN
);
1717 if (aAny
>>= bHelpAtStartup
)
1727 xOnStartupCB
->hide();
1730 // detect module name
1731 OUString sModuleName
;
1733 if ( xConfiguration
.is() )
1738 Any aAny
= ConfigurationHelper::readRelativeKey( xConfiguration
, sPath
, KEY_UI_NAME
);
1741 catch( Exception
const & )
1743 TOOLS_WARN_EXCEPTION( "sfx.appl", "SfxHelpTextWindow_Impl::InitOnStartupBox()" );
1745 sModuleName
= sTemp
;
1748 if ( !sModuleName
.isEmpty() )
1750 // set module name in checkbox text
1751 xOnStartupCB
->set_label(aOnStartupText
.replaceFirst("%MODULENAME", sModuleName
));
1753 xOnStartupCB
->show();
1755 xOnStartupCB
->set_active(bHelpAtStartup
);
1756 xOnStartupCB
->save_state();
1761 Reference
< XBreakIterator
> const & SfxHelpTextWindow_Impl::GetBreakIterator()
1763 if ( !xBreakIterator
.is() )
1764 xBreakIterator
= vcl::unohelper::CreateBreakIterator();
1765 DBG_ASSERT( xBreakIterator
.is(), "Could not create BreakIterator" );
1766 return xBreakIterator
;
1769 Reference
< XTextRange
> SfxHelpTextWindow_Impl::getCursor() const
1771 // return the current cursor
1772 Reference
< XTextRange
> xCursor
;
1776 Reference
< XSelectionSupplier
> xSelSup( xFrame
->getController(), UNO_QUERY
);
1779 Any aAny
= xSelSup
->getSelection();
1780 Reference
< XIndexAccess
> xSelection
;
1781 if ( aAny
>>= xSelection
)
1783 if ( xSelection
->getCount() == 1 )
1785 aAny
= xSelection
->getByIndex(0);
1793 TOOLS_WARN_EXCEPTION( "sfx.appl", "SfxHelpTextWindow_Impl::getCursor(): unexpected exception" );
1800 bool SfxHelpTextWindow_Impl::isHandledKey( const vcl::KeyCode
& _rKeyCode
)
1803 sal_uInt16 nCode
= _rKeyCode
.GetCode();
1805 // the keys <CTRL><A> (select all), <CTRL><C> (copy),
1806 // <CTRL><F> (find), <CTRL><P> (print) and <CTRL><W> (close window)
1807 // were handled in help
1808 if ( _rKeyCode
.IsMod1() &&
1809 ( KEY_A
== nCode
|| KEY_C
== nCode
|| KEY_F
== nCode
|| KEY_P
== nCode
|| KEY_W
== nCode
) )
1811 if ( KEY_F
== nCode
)
1821 IMPL_LINK_NOARG(SfxHelpTextWindow_Impl
, SelectHdl
, Timer
*, void)
1825 // select the words, which are equal to the search text of the search page
1826 Reference
< XController
> xController
= xFrame
->getController();
1827 if ( xController
.is() )
1830 Reference
< XSearchable
> xSearchable( xController
->getModel(), UNO_QUERY
);
1831 if ( xSearchable
.is() )
1833 // create descriptor, set string and find all words
1834 Reference
< XSearchDescriptor
> xSrchDesc
= xSearchable
->createSearchDescriptor();
1835 xSrchDesc
->setPropertyValue( "SearchRegularExpression", makeAny( true ) );
1836 if ( bIsFullWordSearch
)
1837 xSrchDesc
->setPropertyValue( "SearchWords", makeAny( true ) );
1839 xSrchDesc
->setSearchString( sfx2::PrepareSearchString( aSearchText
, GetBreakIterator(), false ) );
1840 Reference
< XIndexAccess
> xSelection
= xSearchable
->findAll( xSrchDesc
);
1842 // then select all found words
1843 Reference
< XSelectionSupplier
> xSelectionSup( xController
, UNO_QUERY
);
1844 if ( xSelectionSup
.is() )
1846 xSelectionSup
->select( Any(xSelection
) );
1853 TOOLS_WARN_EXCEPTION( "sfx.appl", "SfxHelpTextWindow_Impl::SelectHdl(): unexpected exception" );
1858 IMPL_LINK_NOARG( SfxHelpTextWindow_Impl
, NotifyHdl
, LinkParamNone
*, void )
1860 InitToolBoxImages();
1864 IMPL_LINK( SfxHelpTextWindow_Impl
, FindHdl
, sfx2::SearchDialog
&, rDlg
, void )
1868 void SfxHelpTextWindow_Impl::FindHdl(sfx2::SearchDialog
* pDlg
)
1870 bool bWrapAround
= ( nullptr == pDlg
);
1872 pDlg
= m_xSrchDlg
.get();
1873 DBG_ASSERT( pDlg
, "invalid search dialog" );
1876 // select the words, which are equal to the search text of the search page
1877 Reference
< XController
> xController
= xFrame
->getController();
1878 if ( xController
.is() )
1881 Reference
< XSearchable
> xSearchable( xController
->getModel(), UNO_QUERY
);
1882 if ( xSearchable
.is() )
1884 // create descriptor, set string and find all words
1885 Reference
< XSearchDescriptor
> xSrchDesc
= xSearchable
->createSearchDescriptor();
1886 xSrchDesc
->setPropertyValue( "SearchWords", makeAny(pDlg
->IsOnlyWholeWords()) );
1887 xSrchDesc
->setPropertyValue( "SearchCaseSensitive", makeAny(pDlg
->IsMarchCase()) );
1888 xSrchDesc
->setPropertyValue( "SearchBackwards", makeAny(pDlg
->IsSearchBackwards()) );
1889 xSrchDesc
->setSearchString( pDlg
->GetSearchText() );
1890 Reference
< XInterface
> xSelection
;
1891 Reference
< XTextRange
> xCursor
= getCursor();
1895 if ( pDlg
->IsSearchBackwards() )
1896 xCursor
= xCursor
->getStart();
1897 xSelection
= xSearchable
->findNext( xCursor
, xSrchDesc
);
1900 xSelection
= xSearchable
->findFirst( xSrchDesc
);
1902 // then select the found word
1903 if ( xSelection
.is() )
1905 Reference
< XSelectionSupplier
> xSelectionSup( xController
, UNO_QUERY
);
1906 if ( xSelectionSup
.is() )
1908 xSelectionSup
->select( Any(xSelection
) );
1911 else if ( pDlg
->IsWrapAround() && !bWrapAround
)
1913 Reference
< text::XTextViewCursorSupplier
> xCrsrSupp( xController
, uno::UNO_QUERY
);
1914 Reference
< text::XTextViewCursor
> xTVCrsr
= xCrsrSupp
->getViewCursor();
1917 Reference
< text::XTextDocument
> xDoc( xController
->getModel(), uno::UNO_QUERY
);
1918 Reference
< text::XText
> xText
= xDoc
->getText();
1921 if ( pDlg
->IsSearchBackwards() )
1922 xTVCrsr
->gotoRange( xText
->getEnd(), false );
1924 xTVCrsr
->gotoRange( xText
->getStart(), false );
1931 assert(m_xSrchDlg
&& "no search dialog");
1932 std::unique_ptr
<weld::MessageDialog
> xBox(Application::CreateMessageDialog(m_xSrchDlg
->getDialog(),
1933 VclMessageType::Info
, VclButtonsType::Ok
, SfxResId(STR_INFO_NOSEARCHTEXTFOUND
)));
1935 m_xSrchDlg
->SetFocusOnEdit();
1942 TOOLS_WARN_EXCEPTION( "sfx.appl", "SfxHelpTextWindow_Impl::SelectHdl(): unexpected exception" );
1946 IMPL_LINK_NOARG(SfxHelpTextWindow_Impl
, CloseHdl
, LinkParamNone
*, void)
1951 IMPL_LINK_NOARG(SfxHelpTextWindow_Impl
, CheckHdl
, weld::Toggleable
&, void)
1953 if ( !xConfiguration
.is() )
1956 bool bChecked
= xOnStartupCB
->get_active();
1959 ConfigurationHelper::writeRelativeKey(
1960 xConfiguration
, PATH_OFFICE_FACTORIES
+ sCurrentFactory
, KEY_HELP_ON_OPEN
, makeAny( bChecked
) );
1961 ConfigurationHelper::flush( xConfiguration
);
1963 catch( Exception
const & )
1965 TOOLS_WARN_EXCEPTION( "sfx.appl", "SfxHelpTextWindow_Impl::CheckHdl()" );
1969 void SfxHelpTextWindow_Impl::Resize()
1971 Size aSize
= GetOutputSizePixel();
1972 pTextWin
->SetPosSizePixel( Point(0, 0), aSize
);
1975 bool SfxHelpTextWindow_Impl::PreNotify( NotifyEvent
& rNEvt
)
1978 MouseNotifyEvent nType
= rNEvt
.GetType();
1979 if ( MouseNotifyEvent::COMMAND
== nType
&& rNEvt
.GetCommandEvent() )
1981 const CommandEvent
* pCmdEvt
= rNEvt
.GetCommandEvent();
1982 vcl::Window
* pCmdWin
= rNEvt
.GetWindow();
1984 if ( pCmdEvt
->GetCommand() == CommandEventId::ContextMenu
&& pCmdWin
!= this )
1987 if ( pCmdEvt
->IsMouseEvent() )
1988 aPos
= pCmdEvt
->GetMousePosPixel();
1990 aPos
= Point( pTextWin
->GetPosPixel().X() + 20, 20 );
1995 xMenu
->append("index", aIndexOffText
, BMP_HELP_TOOLBOX_INDEX_OFF
);
1997 xMenu
->append("index", aIndexOnText
, BMP_HELP_TOOLBOX_INDEX_ON
);
1999 xMenu
->append_separator("separator1");
2000 xMenu
->append("backward", SfxResId(STR_HELP_BUTTON_PREV
), BMP_HELP_TOOLBOX_PREV
);
2001 xMenu
->set_sensitive("backward", xHelpWin
->HasHistoryPredecessor());
2002 xMenu
->append("forward", SfxResId(STR_HELP_BUTTON_NEXT
), BMP_HELP_TOOLBOX_NEXT
);
2003 xMenu
->set_sensitive("forward", xHelpWin
->HasHistorySuccessor());
2004 xMenu
->append("start", SfxResId(STR_HELP_BUTTON_START
), BMP_HELP_TOOLBOX_START
);
2005 xMenu
->append_separator("separator2");
2006 xMenu
->append("print", SfxResId(STR_HELP_BUTTON_PRINT
), BMP_HELP_TOOLBOX_PRINT
);
2007 xMenu
->append("bookmarks", SfxResId(STR_HELP_BUTTON_ADDBOOKMARK
), BMP_HELP_TOOLBOX_BOOKMARKS
);
2008 xMenu
->append("searchdialog", SfxResId(STR_HELP_BUTTON_SEARCHDIALOG
), BMP_HELP_TOOLBOX_SEARCHDIALOG
);
2009 xMenu
->append_separator("separator3");
2010 xMenu
->append_check("selectionmode", SfxResId(STR_HELP_MENU_TEXT_SELECTION_MODE
));
2012 aURL
.Complete
= ".uno:SelectTextMode";
2013 Reference
< util::XURLTransformer
> xTrans( util::URLTransformer::create( ::comphelper::getProcessComponentContext() ) );
2014 xTrans
->parseStrict(aURL
);
2015 Reference
< XDispatch
> xDisp
= xFrame
->queryDispatch( aURL
, OUString(), 0 );
2018 rtl::Reference
<HelpStatusListener_Impl
> pStateListener
=
2019 new HelpStatusListener_Impl(xDisp
, aURL
);
2020 FeatureStateEvent rEvent
= pStateListener
->GetStateEvent();
2021 bool bCheck
= false;
2022 rEvent
.State
>>= bCheck
;
2023 xMenu
->set_active("selectionmode", bCheck
);
2025 xMenu
->append_separator("separator4");
2026 xMenu
->append("copy", SfxResId(STR_HELP_MENU_TEXT_COPY
), BMP_HELP_TOOLBOX_COPY
);
2027 xMenu
->set_sensitive("copy", HasSelection());
2031 xMenu
->append_separator("separator5");
2032 xMenu
->append("sourceview", SfxResId(STR_HELP_BUTTON_SOURCEVIEW
));
2035 int x
, y
, width
, height
;
2036 weld::Window
* pTopLevel
= GetFrameWeld();
2037 xHelpWin
->GetContainer()->get_extents_relative_to(*pTopLevel
, x
, y
, width
, height
);
2041 xHelpWin
->DoAction(xMenu
->popup_at_rect(pTopLevel
, tools::Rectangle(aPos
, Size(1,1))));
2045 else if ( MouseNotifyEvent::KEYINPUT
== nType
&& rNEvt
.GetKeyEvent() )
2047 const KeyEvent
* pKEvt
= rNEvt
.GetKeyEvent();
2048 const vcl::KeyCode
& rKeyCode
= pKEvt
->GetKeyCode();
2049 sal_uInt16 nKeyGroup
= rKeyCode
.GetGroup();
2050 sal_uInt16 nKey
= rKeyCode
.GetCode();
2051 if ( KEYGROUP_ALPHA
== nKeyGroup
&& !isHandledKey( rKeyCode
) )
2053 // do nothing disables the writer accelerators
2056 else if ( rKeyCode
.IsMod1() && ( KEY_F4
== nKey
|| KEY_W
== nKey
) )
2058 // <CTRL><F4> or <CTRL><W> -> close top frame
2059 xHelpWin
->CloseWindow();
2062 else if ( KEY_TAB
== nKey
&& xOnStartupCB
->has_focus() )
2064 xToolBox
->grab_focus();
2069 return bDone
|| Window::PreNotify( rNEvt
);
2073 void SfxHelpTextWindow_Impl::GetFocus()
2082 Reference
< css::awt::XWindow
> xWindow
= xFrame
->getComponentWindow();
2084 xWindow
->setFocus();
2087 catch( Exception
const & )
2089 TOOLS_WARN_EXCEPTION( "sfx.appl", "SfxHelpTextWindow_Impl::GetFocus()" );
2094 void SfxHelpTextWindow_Impl::DataChanged( const DataChangedEvent
& rDCEvt
)
2096 Window::DataChanged( rDCEvt
);
2098 if ( ( ( rDCEvt
.GetType() == DataChangedEventType::SETTINGS
) ||
2099 ( rDCEvt
.GetType() == DataChangedEventType::DISPLAY
) ) &&
2100 ( rDCEvt
.GetFlags() & AllSettingsFlags::STYLE
) )
2102 SetBackground( Wallpaper( GetSettings().GetStyleSettings().GetFaceColor() ) );
2103 InitToolBoxImages();
2107 void SfxHelpTextWindow_Impl::ToggleIndex( bool bOn
)
2112 xToolBox
->set_item_icon_name("index", aIndexOffImage
);
2113 xToolBox
->set_item_tooltip_text("index", aIndexOffText
);
2117 xToolBox
->set_item_icon_name("index", aIndexOnImage
);
2118 xToolBox
->set_item_tooltip_text("index", aIndexOnText
);
2122 void SfxHelpTextWindow_Impl::SelectSearchText( const OUString
& rSearchText
, bool _bIsFullWordSearch
)
2124 aSearchText
= rSearchText
;
2125 bIsFullWordSearch
= _bIsFullWordSearch
;
2126 aSelectIdle
.Start();
2130 void SfxHelpTextWindow_Impl::SetPageStyleHeaderOff() const
2132 bool bSetOff
= false;
2133 // set off the pagestyle header to prevent print output of the help URL
2136 Reference
< XController
> xController
= xFrame
->getController();
2137 Reference
< XSelectionSupplier
> xSelSup( xController
, UNO_QUERY
);
2140 Reference
< XIndexAccess
> xSelection
;
2141 if ( xSelSup
->getSelection() >>= xSelection
)
2143 Reference
< XTextRange
> xRange
;
2144 if ( xSelection
->getByIndex(0) >>= xRange
)
2146 Reference
< XText
> xText
= xRange
->getText();
2147 Reference
< XPropertySet
> xProps( xText
->createTextCursorByRange( xRange
), UNO_QUERY
);
2148 OUString sStyleName
;
2149 if ( xProps
->getPropertyValue( "PageStyleName" ) >>= sStyleName
)
2151 Reference
< XStyleFamiliesSupplier
> xStyles( xController
->getModel(), UNO_QUERY
);
2152 Reference
< XNameContainer
> xContainer
;
2153 if ( xStyles
->getStyleFamilies()->getByName( "PageStyles" )
2156 Reference
< XStyle
> xStyle
;
2157 if ( xContainer
->getByName( sStyleName
) >>= xStyle
)
2159 Reference
< XPropertySet
> xPropSet( xStyle
, UNO_QUERY
);
2160 xPropSet
->setPropertyValue( "HeaderIsOn", makeAny( false ) );
2162 Reference
< XModifiable
> xReset(xStyles
, UNO_QUERY
);
2163 xReset
->setModified(false);
2172 catch( Exception
const & )
2174 TOOLS_WARN_EXCEPTION( "sfx.appl", "SfxHelpTextWindow_Impl::SetPageStyleHeaderOff()" );
2177 SAL_WARN_IF( !bSetOff
, "sfx.appl", "SfxHelpTextWindow_Impl::SetPageStyleHeaderOff(): set off failed" );
2181 void SfxHelpTextWindow_Impl::CloseFrame()
2186 css::uno::Reference
< css::util::XCloseable
> xCloseable ( xFrame
, css::uno::UNO_QUERY
);
2187 if (xCloseable
.is())
2188 xCloseable
->close(true);
2190 catch( css::util::CloseVetoException
& )
2196 void SfxHelpTextWindow_Impl::DoSearch()
2201 // create the search dialog
2202 m_xSrchDlg
= std::make_shared
<sfx2::SearchDialog
>(pTextWin
->GetFrameWeld(), "HelpSearchDialog");
2204 m_xSrchDlg
->SetFindHdl( LINK( this, SfxHelpTextWindow_Impl
, FindHdl
) );
2205 m_xSrchDlg
->SetCloseHdl( LINK( this, SfxHelpTextWindow_Impl
, CloseHdl
) );
2206 // get selected text of the help page to set it as the search text
2207 Reference
< XTextRange
> xCursor
= getCursor();
2210 OUString sText
= xCursor
->getString();
2211 if ( !sText
.isEmpty() )
2212 m_xSrchDlg
->SetSearchText( sText
);
2214 sfx2::SearchDialog::runAsync(m_xSrchDlg
);
2217 void SfxHelpWindow_Impl::GetFocus()
2220 pTextWin
->GrabFocus();
2222 ResizableDockingWindow::GetFocus();
2225 void SfxHelpWindow_Impl::MakeLayout()
2229 m_xHelpPaneWindow
->set_visible(bIndex
);
2232 IMPL_LINK(SfxHelpWindow_Impl
, ResizeHdl
, const Size
&, rSize
, void)
2234 int nNewWidth
= rSize
.Width();
2238 nIndexSize
= round(m_xContainer
->get_position() * 100.0 / nNewWidth
);
2241 nIndexSize
= round(m_xContainer
->get_position() * 100.0 / nWidth
);
2244 void SfxHelpWindow_Impl::Split()
2248 m_xContainer
->set_position(nWidth
* nIndexSize
/ 100);
2252 void SfxHelpWindow_Impl::LoadConfig()
2254 SvtViewOptions
aViewOpt( EViewType::Window
, CONFIGNAME_HELPWIN
);
2255 if ( !aViewOpt
.Exists() )
2257 bIndex
= aViewOpt
.IsVisible();
2259 Any aUserItem
= aViewOpt
.GetUserItem( USERITEM_NAME
);
2261 if ( aUserItem
>>= aUserData
)
2263 DBG_ASSERT( comphelper::string::getTokenCount(aUserData
, ';') == 6, "invalid user data" );
2265 nIndexSize
= aUserData
.getToken( 0, ';', nIdx
).toInt32();
2266 aUserData
.getToken(0, ';', nIdx
); // ignore nTextSize
2267 sal_Int32 nOldWidth
= aUserData
.getToken( 0, ';', nIdx
).toInt32();
2268 sal_Int32 nOldHeight
= aUserData
.getToken( 0, ';', nIdx
).toInt32();
2269 aWinSize
= Size(nOldWidth
, nOldHeight
);
2270 aWinPos
.setX( aUserData
.getToken( 0, ';', nIdx
).toInt32() );
2271 aWinPos
.setY( aUserData
.getToken( 0, ';', nIdx
).toInt32() );
2274 pTextWin
->ToggleIndex( bIndex
);
2277 void SfxHelpWindow_Impl::SaveConfig()
2279 SvtViewOptions
aViewOpt( EViewType::Window
, CONFIGNAME_HELPWIN
);
2280 sal_Int32 nW
= 0, nH
= 0;
2284 css::awt::Rectangle aRect
= xWindow
->getPosSize();
2289 aViewOpt
.SetVisible( bIndex
);
2290 VclPtr
<vcl::Window
> pScreenWin
= VCLUnoHelper::GetWindow( xWindow
);
2291 aWinPos
= pScreenWin
->GetWindowExtentsRelative( nullptr ).TopLeft();
2293 nIndexSize
= round(m_xContainer
->get_position() * 100.0 / nWidth
);
2294 const OUString aUserData
= OUString::number( nIndexSize
)
2295 + ";" + OUString::number( 100 - nIndexSize
)
2296 + ";" + OUString::number( nW
)
2297 + ";" + OUString::number( nH
)
2298 + ";" + OUString::number( aWinPos
.X() )
2299 + ";" + OUString::number( aWinPos
.Y() );
2301 aViewOpt
.SetUserItem( USERITEM_NAME
, makeAny( aUserData
) );
2304 void SfxHelpWindow_Impl::ShowStartPage()
2306 loadHelpContent(SfxHelpWindow_Impl::buildHelpURL(xIndexWin
->GetFactory(), u
"/start", u
""));
2309 IMPL_LINK(SfxHelpWindow_Impl
, SelectHdl
, const OString
&, rCurItem
, void)
2311 bGrabFocusToToolBox
= pTextWin
->GetToolBox().has_focus();
2315 IMPL_LINK_NOARG(SfxHelpWindow_Impl
, OpenHdl
, LinkParamNone
*, void)
2317 xIndexWin
->SelectExecutableEntry();
2318 OUString aEntry
= xIndexWin
->GetSelectedEntry();
2320 if ( aEntry
.isEmpty() )
2325 bool bComplete
= aEntry
.toAsciiLowerCase().match("vnd.sun.star.help");
2332 OUString
aAnchor('#');
2333 if ( comphelper::string::getTokenCount(aEntry
, '#') == 2 )
2335 sal_Int32 nIdx
{ 0 };
2336 aId
= aEntry
.getToken( 0, '#', nIdx
);
2337 aAnchor
+= aEntry
.getToken( 0, '#', nIdx
);
2342 sHelpURL
= SfxHelpWindow_Impl::buildHelpURL(xIndexWin
->GetFactory(), OUStringConcatenation("/" + aId
), aAnchor
);
2345 loadHelpContent(sHelpURL
);
2348 IMPL_LINK( SfxHelpWindow_Impl
, SelectFactoryHdl
, SfxHelpIndexWindow_Impl
* , pWin
, void )
2350 if ( sTitle
.isEmpty() )
2351 sTitle
= GetParent()->GetText();
2353 Reference
< XTitle
> xTitle(xFrame
, UNO_QUERY
);
2355 xTitle
->setTitle(sTitle
+ " - " + xIndexWin
->GetActiveFactoryTitle());
2359 xIndexWin
->ClearSearchPage();
2363 IMPL_LINK( SfxHelpWindow_Impl
, ChangeHdl
, HelpListener_Impl
&, rListener
, void )
2365 SetFactory( rListener
.GetFactory() );
2369 void SfxHelpWindow_Impl::openDone(const OUString
& sURL
,
2372 INetURLObject
aObj( sURL
);
2373 if ( aObj
.GetProtocol() == INetProtocol::VndSunStarHelp
)
2374 SetFactory( aObj
.GetHost() );
2377 if ( bGrabFocusToToolBox
)
2379 pTextWin
->GetToolBox().grab_focus();
2380 bGrabFocusToToolBox
= false;
2383 xIndexWin
->GrabFocusBack();
2387 // set some view settings: "prevent help tips" and "helpid == 68245"
2390 Reference
< XController
> xController
= pTextWin
->getFrame()->getController();
2391 if ( xController
.is() )
2393 Reference
< XViewSettingsSupplier
> xSettings( xController
, UNO_QUERY
);
2394 Reference
< XPropertySet
> xViewProps
= xSettings
->getViewSettings();
2395 Reference
< XPropertySetInfo
> xInfo
= xViewProps
->getPropertySetInfo();
2396 xViewProps
->setPropertyValue( "ShowContentTips", makeAny( false ) );
2397 xViewProps
->setPropertyValue( "ShowGraphics", makeAny( true ) );
2398 xViewProps
->setPropertyValue( "ShowTables", makeAny( true ) );
2399 xViewProps
->setPropertyValue( "HelpURL", makeAny( OUString("HID:SFX2_HID_HELP_ONHELP") ) );
2400 OUString
sProperty( "IsExecuteHyperlinks" );
2401 if ( xInfo
->hasPropertyByName( sProperty
) )
2402 xViewProps
->setPropertyValue( sProperty
, makeAny( true ) );
2403 xController
->restoreViewData(Any());
2408 TOOLS_WARN_EXCEPTION( "sfx.appl", "SfxHelpWindow_Impl::OpenDoneHdl(): unexpected exception" );
2411 // When the SearchPage opens the help doc, then select all words, which are equal to its text
2412 OUString sSearchText
= comphelper::string::strip(xIndexWin
->GetSearchText(), ' ');
2413 if ( !sSearchText
.isEmpty() )
2414 pTextWin
->SelectSearchText( sSearchText
, xIndexWin
->IsFullWordSearch() );
2416 // no page style header -> this prevents a print output of the URL
2417 pTextWin
->SetPageStyleHeaderOff();
2421 SfxHelpWindow_Impl::SfxHelpWindow_Impl(
2422 const css::uno::Reference
< css::frame::XFrame2
>& rFrame
,
2423 vcl::Window
* pParent
) :
2425 ResizableDockingWindow(pParent
),
2428 pTextWin ( nullptr ),
2429 pHelpInterceptor ( new HelpInterceptor_Impl() ),
2430 pHelpListener ( new HelpListener_Impl( pHelpInterceptor
) ),
2432 bGrabFocusToToolBox ( false ),
2435 nIndexSize ( 40 ), // % of width
2438 sTitle ( pParent
->GetText() )
2440 SetStyle(GetStyle() & ~WB_DOCKABLE
);
2442 SetHelpId( HID_HELP_WINDOW
);
2444 m_xBuilder
= Application::CreateInterimBuilder(m_xBox
.get(), "sfx/ui/helpwindow.ui", false);
2445 m_xContainer
= m_xBuilder
->weld_paned("HelpWindow");
2446 m_xContainer
->connect_size_allocate(LINK(this, SfxHelpWindow_Impl
, ResizeHdl
));
2447 m_xHelpPaneWindow
= m_xBuilder
->weld_container("helppanewindow");
2448 m_xHelpTextWindow
= m_xBuilder
->weld_container("helptextwindow");
2449 m_xHelpTextXWindow
= m_xHelpTextWindow
->CreateChildFrame();
2451 pHelpInterceptor
->InitWaiter( this );
2452 xIndexWin
.reset(new SfxHelpIndexWindow_Impl(this, m_xHelpPaneWindow
.get()));
2453 xIndexWin
->SetDoubleClickHdl( LINK( this, SfxHelpWindow_Impl
, OpenHdl
) );
2454 xIndexWin
->SetSelectFactoryHdl( LINK( this, SfxHelpWindow_Impl
, SelectFactoryHdl
) );
2456 pTextWin
= VclPtr
<SfxHelpTextWindow_Impl
>::Create(this, *m_xBuilder
, VCLUnoHelper::GetWindow(m_xHelpTextXWindow
));
2457 Reference
< XFrames
> xFrames
= rFrame
->getFrames();
2458 xFrames
->append( Reference
<XFrame
>(pTextWin
->getFrame(), UNO_QUERY_THROW
) );
2459 pTextWin
->SetSelectHdl( LINK( this, SfxHelpWindow_Impl
, SelectHdl
) );
2461 pHelpInterceptor
->setInterception( Reference
<XFrame
>(pTextWin
->getFrame(), UNO_QUERY_THROW
) );
2462 pHelpListener
->SetChangeHdl( LINK( this, SfxHelpWindow_Impl
, ChangeHdl
) );
2466 SfxHelpWindow_Impl::~SfxHelpWindow_Impl()
2471 void SfxHelpWindow_Impl::dispose()
2475 pTextWin
->CloseFrame();
2476 pTextWin
.disposeAndClear();
2478 m_xHelpTextXWindow
->dispose();
2479 m_xHelpTextXWindow
.clear();
2480 m_xHelpTextWindow
.reset();
2481 m_xHelpPaneWindow
.reset();
2482 m_xContainer
.reset();
2485 ResizableDockingWindow::dispose();
2488 bool SfxHelpWindow_Impl::PreNotify( NotifyEvent
& rNEvt
)
2490 bool bHandled
= false;
2491 if ( rNEvt
.GetType() == MouseNotifyEvent::KEYINPUT
)
2493 // Backward == <ALT><LEFT> or <BACKSPACE> Forward == <ALT><RIGHT>
2494 const vcl::KeyCode
& rKeyCode
= rNEvt
.GetKeyEvent()->GetKeyCode();
2495 sal_uInt16 nKey
= rKeyCode
.GetCode();
2496 if ( ( rKeyCode
.IsMod2() && ( KEY_LEFT
== nKey
|| KEY_RIGHT
== nKey
) ) ||
2497 ( !rKeyCode
.GetModifier() && KEY_BACKSPACE
== nKey
&& !xIndexWin
->HasFocusOnEdit() ) )
2499 DoAction( rKeyCode
.GetCode() == KEY_RIGHT
? "forward" : "backward" );
2502 else if ( rKeyCode
.IsMod1() && ( KEY_F4
== nKey
|| KEY_W
== nKey
) )
2504 // <CTRL><F4> or <CTRL><W> -> close top frame
2509 return bHandled
|| Window::PreNotify( rNEvt
);
2512 void SfxHelpWindow_Impl::setContainerWindow( const Reference
< css::awt::XWindow
>& xWin
)
2518 VclPtr
<vcl::Window
> pScreenWin
= VCLUnoHelper::GetWindow(xWindow
);
2519 if (aWinSize
.Width() && aWinSize
.Height())
2520 pScreenWin
->SetPosSizePixel(aWinPos
, aWinSize
);
2522 pScreenWin
->SetPosPixel(aWinPos
);
2526 void SfxHelpWindow_Impl::SetFactory( const OUString
& rFactory
)
2528 xIndexWin
->SetFactory( rFactory
, true );
2531 void SfxHelpWindow_Impl::SetHelpURL( const OUString
& rURL
)
2533 INetURLObject
aObj( rURL
);
2534 if ( aObj
.GetProtocol() == INetProtocol::VndSunStarHelp
)
2535 SetFactory( aObj
.GetHost() );
2538 void SfxHelpWindow_Impl::DoAction(std::string_view rActionId
)
2540 if (rActionId
== "index")
2544 pTextWin
->ToggleIndex( bIndex
);
2546 else if (rActionId
== "start")
2550 else if (rActionId
== "backward" || rActionId
== "forward")
2553 aURL
.Complete
= ".uno:Backward";
2554 if (rActionId
== "forward")
2555 aURL
.Complete
= ".uno:Forward";
2556 Reference
< util::XURLTransformer
> xTrans( util::URLTransformer::create( ::comphelper::getProcessComponentContext() ) );
2557 xTrans
->parseStrict(aURL
);
2558 pHelpInterceptor
->dispatch( aURL
, Sequence
< PropertyValue
>() );
2560 else if (rActionId
== "searchdialog")
2562 pTextWin
->DoSearch();
2564 else if (rActionId
== "print" || rActionId
== "sourceview" || rActionId
== "copy" || rActionId
== "selectionmode")
2566 Reference
< XDispatchProvider
> xProv
= pTextWin
->getFrame();
2570 if (rActionId
== "print")
2571 aURL
.Complete
= ".uno:Print";
2572 else if (rActionId
== "sourceview")
2573 aURL
.Complete
= ".uno:SourceView";
2574 else if (rActionId
== "copy")
2575 aURL
.Complete
= ".uno:Copy";
2576 else // rActionId == "selectionmode"
2577 aURL
.Complete
= ".uno:SelectTextMode";
2578 Reference
< util::XURLTransformer
> xTrans( util::URLTransformer::create( ::comphelper::getProcessComponentContext() ) );
2579 xTrans
->parseStrict(aURL
);
2580 Reference
< XDispatch
> xDisp
= xProv
->queryDispatch( aURL
, OUString(), 0 );
2582 xDisp
->dispatch( aURL
, Sequence
< PropertyValue
>() );
2585 else if (rActionId
== "bookmarks")
2587 OUString aURL
= pHelpInterceptor
->GetCurrentURL();
2588 if ( !aURL
.isEmpty() )
2592 Content
aCnt( aURL
, Reference
< css::ucb::XCommandEnvironment
>(), comphelper::getProcessComponentContext() );
2593 css::uno::Reference
< css::beans::XPropertySetInfo
> xInfo
= aCnt
.getProperties();
2594 if ( xInfo
->hasPropertyByName( PROPERTY_TITLE
) )
2596 css::uno::Any aAny
= aCnt
.getPropertyValue( PROPERTY_TITLE
);
2598 if ( aAny
>>= aValue
)
2600 SfxAddHelpBookmarkDialog_Impl
aDlg(GetFrameWeld(), false);
2601 aDlg
.SetTitle(aValue
);
2602 if (aDlg
.run() == RET_OK
)
2604 xIndexWin
->AddBookmarks( aDlg
.GetTitle(), aURL
);
2611 TOOLS_WARN_EXCEPTION( "sfx.appl", "SfxHelpWindow_Impl::DoAction(): unexpected exception" );
2617 void SfxHelpWindow_Impl::CloseWindow()
2621 // search for top frame
2622 Reference
< XFramesSupplier
> xCreator
= getTextFrame()->getCreator();
2623 while ( xCreator
.is() && !xCreator
->isTop() )
2625 xCreator
= xCreator
->getCreator();
2628 // when found, close it
2629 if ( xCreator
.is() && xCreator
->isTop() )
2631 Reference
< XCloseable
> xCloser( xCreator
, UNO_QUERY
);
2633 xCloser
->close( false );
2636 catch( Exception
const & )
2638 TOOLS_WARN_EXCEPTION( "sfx.appl", "SfxHelpWindow_Impl::CloseWindow()" );
2643 void SfxHelpWindow_Impl::UpdateToolbox()
2645 pTextWin
->GetToolBox().set_item_sensitive("backward", pHelpInterceptor
->HasHistoryPred());
2646 pTextWin
->GetToolBox().set_item_sensitive("forward", pHelpInterceptor
->HasHistorySucc());
2650 bool SfxHelpWindow_Impl::HasHistoryPredecessor() const
2652 return pHelpInterceptor
->HasHistoryPred();
2656 bool SfxHelpWindow_Impl::HasHistorySuccessor() const
2658 return pHelpInterceptor
->HasHistorySucc();
2661 // class SfxAddHelpBookmarkDialog_Impl -----------------------------------
2663 SfxAddHelpBookmarkDialog_Impl::SfxAddHelpBookmarkDialog_Impl(weld::Widget
* pParent
, bool bRename
)
2664 : GenericDialogController(pParent
, "sfx/ui/bookmarkdialog.ui", "BookmarkDialog")
2665 , m_xTitleED(m_xBuilder
->weld_entry("entry"))
2666 , m_xAltTitle(m_xBuilder
->weld_label("alttitle"))
2669 m_xDialog
->set_title(m_xAltTitle
->get_label());
2672 void SfxAddHelpBookmarkDialog_Impl::SetTitle(const OUString
& rTitle
)
2674 m_xTitleED
->set_text(rTitle
);
2675 m_xTitleED
->select_region(0, -1);
2678 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */