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 <tools/debug.hxx>
29 #include <comphelper/diagnose_ex.hxx>
30 #include <o3tl/string_view.hxx>
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>
78 #include <vcl/commandevent.hxx>
79 #include <vcl/event.hxx>
80 #include <vcl/i18nhelp.hxx>
81 #include <vcl/settings.hxx>
82 #include <vcl/svapp.hxx>
83 #include <vcl/unohelp.hxx>
84 #include <vcl/weld.hxx>
86 #include <ucbhelper/content.hxx>
87 #include <unotools/ucbhelper.hxx>
89 #include <string_view>
90 #include <unordered_map>
93 using namespace ::ucbhelper
;
94 using namespace ::com::sun::star::ucb
;
96 using namespace ::com::sun::star
;
97 using namespace ::com::sun::star::beans
;
98 using namespace ::com::sun::star::container
;
99 using namespace ::com::sun::star::frame
;
100 using namespace ::com::sun::star::i18n
;
101 using namespace ::com::sun::star::lang
;
102 using namespace ::com::sun::star::style
;
103 using namespace ::com::sun::star::text
;
104 using namespace ::com::sun::star::uno
;
105 using namespace ::com::sun::star::util
;
106 using namespace ::com::sun::star::view
;
108 using namespace ::comphelper
;
110 // defines ---------------------------------------------------------------
112 constexpr OUString CONFIGNAME_HELPWIN
= u
"OfficeHelp"_ustr
;
113 constexpr OUString CONFIGNAME_INDEXWIN
= u
"OfficeHelpIndex"_ustr
;
114 constexpr OUString CONFIGNAME_SEARCHPAGE
= u
"OfficeHelpSearch"_ustr
;
115 constexpr OUString IMAGE_URL
= u
"private:factory/"_ustr
;
117 constexpr OUString PROPERTY_KEYWORDLIST
= u
"KeywordList"_ustr
;
118 constexpr OUString PROPERTY_KEYWORDREF
= u
"KeywordRef"_ustr
;
119 constexpr OUString PROPERTY_ANCHORREF
= u
"KeywordAnchorForRef"_ustr
;
120 constexpr OUString PROPERTY_TITLEREF
= u
"KeywordTitleForRef"_ustr
;
121 constexpr OUString PROPERTY_TITLE
= u
"Title"_ustr
;
122 constexpr OUString HELP_URL
= u
"vnd.sun.star.help://"_ustr
;
123 constexpr OUStringLiteral HELP_SEARCH_TAG
= u
"/?Query=";
124 constexpr OUString USERITEM_NAME
= u
"UserItem"_ustr
;
126 constexpr OUStringLiteral PACKAGE_SETUP
= u
"/org.openoffice.Setup";
127 constexpr OUString PATH_OFFICE_FACTORIES
= u
"Office/Factories/"_ustr
;
128 constexpr OUString KEY_HELP_ON_OPEN
= u
"ooSetupFactoryHelpOnOpen"_ustr
;
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( OUString aURL
, bool bSubEntry
) :
198 m_bSubEntry( bSubEntry
), m_aURL(std::move( aURL
)) {}
201 // struct ContentEntry_Impl ----------------------------------------------
203 struct ContentEntry_Impl
208 ContentEntry_Impl( OUString _aURL
, bool bFolder
) :
209 aURL(std::move( _aURL
)), bIsFolder( bFolder
) {}
214 void ContentTabPage_Impl::InitRoot()
216 std::vector
< OUString
> aList
=
217 SfxContentHelper::GetHelpTreeViewContents( u
"vnd.sun.star.hier://com.sun.star.help.TreeView/"_ustr
);
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
= o3tl::getToken(aRow
, 0, '\t', nIdx
)[0];
225 bool bIsFolder
= ( '1' == cFolder
);
228 sId
= weld::toId(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 weld::fromId
<ContentEntry_Impl
*>(m_xContentBox
->get_id(*xEntry
));
242 bEntry
= m_xContentBox
->iter_next_sibling(*xEntry
);
247 IMPL_LINK(ContentTabPage_Impl
, ExpandingHdl
, const weld::TreeIter
&, rIter
, bool)
249 ContentEntry_Impl
* pContentEntry
= weld::fromId
<ContentEntry_Impl
*>(m_xContentBox
->get_id(rIter
));
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
= o3tl::getToken(aRow
, 0, '\t', nIdx
)[0];
264 bool bIsFolder
= ( '1' == cFolder
);
267 OUString sId
= weld::toId(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
, u
"TargetURL"_ustr
) );
276 if ( aAny
>>= aTargetURL
)
277 sId
= weld::toId(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
= weld::fromId
<ContentEntry_Impl
*>(m_xContentBox
->get_id(rIter
));
299 if (!pContentEntry
|| pContentEntry
->bIsFolder
)
300 m_xContentBox
->set_image(rIter
, aClosedBookImage
);
305 OUString
ContentTabPage_Impl::GetSelectedEntry() const
308 ContentEntry_Impl
* pEntry
= weld::fromId
<ContentEntry_Impl
*>(m_xContentBox
->get_selected_id());
309 if (pEntry
&& !pEntry
->bIsFolder
)
314 // class HelpTabPage_Impl ------------------------------------------------
315 HelpTabPage_Impl::HelpTabPage_Impl(weld::Widget
* pParent
, SfxHelpIndexWindow_Impl
* pIdxWin
,
316 const OUString
& 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
, u
"HelpContentPage"_ustr
,
329 u
"sfx/ui/helpcontentpage.ui"_ustr
)
330 , m_xContentBox(m_xBuilder
->weld_tree_view(u
"content"_ustr
))
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 weld::fromId
<ContentEntry_Impl
*>(m_xContentBox
->get_id(*xEntry
));
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
= weld::fromId
<IndexEntry_Impl
*>(m_xIndexList
->get_id(nPos
));
377 sal_Int32 nCount
= m_xIndexList
->n_children();
378 while ( nPos
< nCount
&& ( !pEntry
|| pEntry
->m_aURL
.isEmpty() ) )
380 pEntry
= weld::fromId
<IndexEntry_Impl
*>(m_xIndexList
->get_id(++nPos
));
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
, u
"HelpIndexPage"_ustr
, u
"sfx/ui/helpindexpage.ui"_ustr
)
391 , m_xIndexEntry(m_xBuilder
->weld_entry(u
"termentry"_ustr
))
392 , m_xIndexList(m_xBuilder
->weld_tree_view(u
"termlist"_ustr
))
393 , m_xOpenBtn(m_xBuilder
->weld_button(u
"display"_ustr
))
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_selection_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
= weld::fromId
<IndexEntry_Impl
*>(rId
);
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
+ sFactory
);
578 AppendConfigToken(aURL
, true);
580 Content
aCnt( aURL
.makeStringAndClear(), Reference
< css::ucb::XCommandEnvironment
>(), comphelper::getProcessComponentContext() );
581 css::uno::Reference
< css::beans::XPropertySetInfo
> xInfo
= aCnt
.getProperties();
582 if ( xInfo
->hasPropertyByName( PROPERTY_ANCHORREF
) )
584 css::uno::Sequence
< OUString
> aPropSeq
{ PROPERTY_KEYWORDLIST
, PROPERTY_KEYWORDREF
,
585 PROPERTY_ANCHORREF
, PROPERTY_TITLEREF
};
587 // abi: use one possibly remote call only
588 css::uno::Sequence
< css::uno::Any
> aAnySeq
=
589 aCnt
.getPropertyValues( aPropSeq
);
591 css::uno::Sequence
< OUString
> aKeywordList
;
592 css::uno::Sequence
< css::uno::Sequence
< OUString
> > aKeywordRefList
;
593 css::uno::Sequence
< css::uno::Sequence
< OUString
> > aAnchorRefList
;
594 css::uno::Sequence
< css::uno::Sequence
< OUString
> > aTitleRefList
;
596 if ( ( aAnySeq
[0] >>= aKeywordList
) && ( aAnySeq
[1] >>= aKeywordRefList
) &&
597 ( aAnySeq
[2] >>= aAnchorRefList
) && ( aAnySeq
[3] >>= aTitleRefList
) )
600 OUString aIndex
, aTempString
;
601 sfx2::KeywordInfo::iterator it
;
603 for ( int i
= 0; i
< aKeywordList
.getLength(); ++i
)
605 // abi: Do not copy, but use references
606 const OUString
& aKeywordPair
= aKeywordList
[i
];
607 DBG_ASSERT( !aKeywordPair
.isEmpty(), "invalid help index" );
608 const css::uno::Sequence
< OUString
>& aRefList
= aKeywordRefList
[i
];
609 const css::uno::Sequence
< OUString
>& aAnchorList
= aAnchorRefList
[i
];
610 const css::uno::Sequence
< OUString
>& aTitleList
= aTitleRefList
[i
];
612 DBG_ASSERT( aRefList
.getLength() == aAnchorList
.getLength(),"reference list and title list of different length" );
614 ndx
= aKeywordPair
.indexOf( ';' );
615 const bool insert
= ndx
!= -1;
621 aTempString
= aKeywordPair
.copy( 0, ndx
);
622 if ( aIndex
!= aTempString
)
624 aIndex
= aTempString
;
625 it
= aInfo
.emplace(aTempString
, 0).first
;
626 sId
= weld::toId(new IndexEntry_Impl(OUString(), false));
627 if ( (tmp
= it
->second
++) != 0)
628 m_xIndexList
->append(
629 sId
, aTempString
+ std::u16string_view(append
, tmp
));
631 m_xIndexList
->append(sId
, aTempString
);
637 sal_uInt32 nRefListLen
= aRefList
.getLength();
639 DBG_ASSERT( aAnchorList
.hasElements(), "*IndexTabPage_Impl::InitializeIndex(): AnchorList is empty!" );
640 DBG_ASSERT( nRefListLen
, "*IndexTabPage_Impl::InitializeIndex(): RefList is empty!" );
642 if ( aAnchorList
.hasElements() && nRefListLen
)
644 if ( aAnchorList
[0].getLength() > 0 )
646 sId
= weld::toId(new IndexEntry_Impl(aRefList
[0] + "#" + aAnchorList
[0], insert
));
649 sId
= weld::toId(new IndexEntry_Impl(aRefList
[0], insert
));
652 // Assume the token is trimmed
653 it
= aInfo
.emplace(aKeywordPair
, 0).first
;
654 if ((tmp
= it
->second
++) != 0)
655 m_xIndexList
->append(sId
, aKeywordPair
+ std::u16string_view(append
, tmp
));
657 m_xIndexList
->append(sId
, aKeywordPair
);
659 for ( sal_uInt32 j
= 1; j
< nRefListLen
; ++j
)
661 aTempString
= aKeywordPair
+ " - " + aTitleList
[j
];
663 if ( aAnchorList
[j
].getLength() > 0 )
664 sId
= weld::toId(new IndexEntry_Impl(aRefList
[j
] + "#" + aAnchorList
[j
], insert
));
666 sId
= weld::toId(new IndexEntry_Impl(aRefList
[j
], insert
));
668 it
= aInfo
.emplace(aTempString
, 0).first
;
669 if ( (tmp
= it
->second
++) != 0 )
670 m_xIndexList
->append(
671 sId
, aTempString
+ std::u16string_view(append
, tmp
));
673 m_xIndexList
->append(sId
, aTempString
);
681 TOOLS_WARN_EXCEPTION( "sfx.appl", "IndexTabPage_Impl::InitializeIndex(): unexpected exception" );
684 m_xIndexList
->thaw();
686 if ( !sKeyword
.isEmpty() )
687 aKeywordLink
.Call( *this );
690 void IndexTabPage_Impl::ClearIndex()
692 const sal_Int32 nCount
= m_xIndexList
->n_children();
693 for ( sal_Int32 i
= 0; i
< nCount
; ++i
)
694 delete weld::fromId
<IndexEntry_Impl
*>(m_xIndexList
->get_id(i
));
695 m_xIndexList
->clear();
698 IMPL_LINK_NOARG(IndexTabPage_Impl
, OpenHdl
, weld::Button
&, void)
700 aDoubleClickHdl
.Call(nullptr);
703 IMPL_LINK_NOARG(IndexTabPage_Impl
, ActivateHdl
, weld::Entry
&, bool)
705 aDoubleClickHdl
.Call(nullptr);
709 IMPL_LINK_NOARG(IndexTabPage_Impl
, DoubleClickHdl
, weld::TreeView
&, bool)
711 aDoubleClickHdl
.Call(nullptr);
715 IMPL_LINK_NOARG(IndexTabPage_Impl
, IdleHdl
, Timer
*, void)
720 int IndexTabPage_Impl::starts_with(const OUString
& rStr
, int nStartRow
, bool bCaseSensitive
)
722 const vcl::I18nHelper
& rI18nHelper
= Application::GetSettings().GetUILocaleI18nHelper();
724 int nRet
= nStartRow
;
725 int nCount
= m_xIndexList
->n_children();
726 while (nRet
< nCount
)
728 OUString
aStr(m_xIndexList
->get_text(nRet
));
729 const bool bMatch
= !bCaseSensitive
? rI18nHelper
.MatchString(rStr
, aStr
) : aStr
.startsWith(rStr
);
738 IMPL_LINK_NOARG(IndexTabPage_Impl
, AutoCompleteHdl
, Timer
*, void)
740 OUString aStartText
= m_xIndexEntry
->get_text();
741 int nStartPos
, nEndPos
;
742 m_xIndexEntry
->get_selection_bounds(nStartPos
, nEndPos
);
743 int nMaxSelection
= std::max(nStartPos
, nEndPos
);
744 if (nMaxSelection
!= aStartText
.getLength())
747 int nActive
= m_xIndexList
->get_selected_index();
748 int nStart
= nActive
;
753 // Try match case insensitive from current position
754 int nPos
= starts_with(aStartText
, nStart
, false);
755 if (nPos
== -1 && nStart
!= 0)
757 // Try match case insensitive, but from start
758 nPos
= starts_with(aStartText
, 0, false);
763 // Try match case sensitive from current position
764 nPos
= starts_with(aStartText
, nStart
, true);
765 if (nPos
== -1 && nStart
!= 0)
767 // Try match case sensitive, but from start
768 nPos
= starts_with(aStartText
, 0, true);
774 m_xIndexList
->set_cursor(nPos
);
775 m_xIndexList
->select(nPos
);
776 OUString aText
= m_xIndexList
->get_text(nPos
);
777 if (aText
!= aStartText
)
778 m_xIndexEntry
->set_text(aText
);
779 m_xIndexEntry
->select_region(aText
.getLength(), aStartText
.getLength());
783 IMPL_LINK( IndexTabPage_Impl
, TimeoutHdl
, Timer
*, pTimer
, void)
785 if(&aKeywordTimer
== pTimer
&& !sKeyword
.isEmpty())
786 aKeywordLink
.Call(*this);
789 void IndexTabPage_Impl::Activate()
794 aFactoryIdle
.Start();
798 void IndexTabPage_Impl::SetDoubleClickHdl(const Link
<LinkParamNone
*, void>& rLink
)
800 aDoubleClickHdl
= rLink
;
803 void IndexTabPage_Impl::SetFactory( const OUString
& rFactory
)
805 OUString
sNewFactory( rFactory
);
806 DBG_ASSERT( !sNewFactory
.isEmpty(), "empty factory" );
807 bool bValid
= m_pIdxWin
->IsValidFactory( rFactory
);
809 if ( sFactory
.isEmpty() && !bValid
)
811 sNewFactory
= SfxHelp::GetDefaultHelpModule();
815 if ( sNewFactory
!= sFactory
&& bValid
)
817 sFactory
= sNewFactory
;
820 aFactoryIdle
.Start();
824 OUString
IndexTabPage_Impl::GetSelectedEntry() const
827 IndexEntry_Impl
* pEntry
= weld::fromId
<IndexEntry_Impl
*>(m_xIndexList
->get_id(m_xIndexList
->find_text(m_xIndexEntry
->get_text())));
829 aRet
= pEntry
->m_aURL
;
833 void IndexTabPage_Impl::SetKeyword( const OUString
& rKeyword
)
837 if (m_xIndexList
->n_children() > 0)
838 aKeywordTimer
.Start();
839 else if ( !bIsActivated
)
840 aFactoryIdle
.Start();
844 bool IndexTabPage_Impl::HasKeyword() const
847 if ( !sKeyword
.isEmpty() )
849 sal_Int32 nPos
= m_xIndexList
->find_text( sKeyword
);
857 bool IndexTabPage_Impl::HasKeywordIgnoreCase()
860 if ( !sKeyword
.isEmpty() )
862 sal_Int32 nEntries
= m_xIndexList
->n_children();
863 const vcl::I18nHelper
& rI18nHelper
= Application::GetSettings().GetLocaleI18nHelper();
864 for ( sal_Int32 n
= 0; n
< nEntries
; n
++)
866 const OUString sIndexItem
{m_xIndexList
->get_text(n
)};
867 if (rI18nHelper
.MatchString( sIndexItem
, sKeyword
))
869 sKeyword
= sIndexItem
;
878 void IndexTabPage_Impl::OpenKeyword()
880 if ( !sKeyword
.isEmpty() )
882 m_xIndexEntry
->set_text(sKeyword
);
883 aDoubleClickHdl
.Call(nullptr);
888 IMPL_LINK_NOARG(SearchTabPage_Impl
, ActivateHdl
, weld::ComboBox
&, bool)
894 // class SearchTabPage_Impl ----------------------------------------------
896 SearchTabPage_Impl::SearchTabPage_Impl(weld::Widget
* pParent
, SfxHelpIndexWindow_Impl
* pIdxWin
)
897 : HelpTabPage_Impl(pParent
, pIdxWin
, u
"HelpSearchPage"_ustr
,
898 u
"sfx/ui/helpsearchpage.ui"_ustr
)
899 , m_xSearchED(m_xBuilder
->weld_combo_box(u
"search"_ustr
))
900 , m_xSearchBtn(m_xBuilder
->weld_button(u
"find"_ustr
))
901 , m_xFullWordsCB(m_xBuilder
->weld_check_button(u
"completewords"_ustr
))
902 , m_xScopeCB(m_xBuilder
->weld_check_button(u
"headings"_ustr
))
903 , m_xResultsLB(m_xBuilder
->weld_tree_view(u
"results"_ustr
))
904 , m_xOpenBtn(m_xBuilder
->weld_button(u
"display"_ustr
))
905 , xBreakIterator(vcl::unohelper::CreateBreakIterator())
907 m_xResultsLB
->set_size_request(m_xResultsLB
->get_approximate_digit_width() * 30,
908 m_xResultsLB
->get_height_rows(15));
910 m_xSearchBtn
->connect_clicked(LINK(this, SearchTabPage_Impl
, ClickHdl
));
911 m_xSearchED
->connect_changed(LINK(this, SearchTabPage_Impl
, ModifyHdl
));
912 m_xSearchED
->connect_entry_activate(LINK(this, SearchTabPage_Impl
, ActivateHdl
));
913 m_xOpenBtn
->connect_clicked(LINK(this, SearchTabPage_Impl
, OpenHdl
));
914 m_xResultsLB
->connect_row_activated(LINK(this, SearchTabPage_Impl
, DoubleClickHdl
));
916 SvtViewOptions
aViewOpt( EViewType::TabPage
, CONFIGNAME_SEARCHPAGE
);
917 if ( aViewOpt
.Exists() )
920 Any aUserItem
= aViewOpt
.GetUserItem( USERITEM_NAME
);
921 if ( aUserItem
>>= aUserData
)
924 bool bChecked
= o3tl::toInt32(o3tl::getToken(aUserData
, 0, ';', nIdx
)) == 1;
925 m_xFullWordsCB
->set_active(bChecked
);
926 bChecked
= o3tl::toInt32(o3tl::getToken(aUserData
, 0, ';', nIdx
)) == 1;
927 m_xScopeCB
->set_active(bChecked
);
931 m_xSearchED
->append_text( INetURLObject::decode(
932 o3tl::getToken(aUserData
, 0, ';', nIdx
),
933 INetURLObject::DecodeMechanism::WithCharset
) );
938 ModifyHdl(*m_xSearchED
);
941 SearchTabPage_Impl::~SearchTabPage_Impl()
943 SvtViewOptions
aViewOpt( EViewType::TabPage
, CONFIGNAME_SEARCHPAGE
);
944 OUStringBuffer aUserData
=
945 OUString::number(m_xFullWordsCB
->get_active() ? 1 : 0) +
947 OUString::number(m_xScopeCB
->get_active() ? 1 : 0);
948 sal_Int32 nCount
= std::min(m_xSearchED
->get_count(), 10); // save only 10 entries
950 for ( sal_Int32 i
= 0; i
< nCount
; ++i
)
952 aUserData
.append(";" +
953 INetURLObject::encode(
954 m_xSearchED
->get_text(i
),
955 INetURLObject::PART_UNO_PARAM_VALUE
,
956 INetURLObject::EncodeMechanism::All
));
959 Any
aUserItem( aUserData
.makeStringAndClear() );
960 aViewOpt
.SetUserItem( USERITEM_NAME
, aUserItem
);
963 m_xSearchBtn
.reset();
964 m_xFullWordsCB
.reset();
966 m_xResultsLB
.reset();
970 void SearchTabPage_Impl::ClearSearchResults()
972 m_xResultsLB
->clear();
975 void SearchTabPage_Impl::RememberSearchText( const OUString
& rSearchText
)
977 for (sal_Int32 i
= 0, nEntryCount
= m_xSearchED
->get_count(); i
< nEntryCount
; ++i
)
979 if (rSearchText
== m_xSearchED
->get_text(i
))
981 m_xSearchED
->remove(i
);
986 m_xSearchED
->insert_text(0, rSearchText
);
989 IMPL_LINK_NOARG(SearchTabPage_Impl
, ClickHdl
, weld::Button
&, void)
994 void SearchTabPage_Impl::Search()
996 OUString aSearchText
= comphelper::string::strip(m_xSearchED
->get_active_text(), ' ');
997 if ( aSearchText
.isEmpty() )
1000 std::unique_ptr
<weld::WaitObject
> xWaitCursor(new weld::WaitObject(m_pIdxWin
->GetFrameWeld()));
1001 ClearSearchResults();
1002 RememberSearchText( aSearchText
);
1003 OUStringBuffer
aSearchURL(HELP_URL
+ aFactory
+ HELP_SEARCH_TAG
);
1004 if (!m_xFullWordsCB
->get_active())
1005 aSearchText
= sfx2::PrepareSearchString( aSearchText
, xBreakIterator
, true );
1006 aSearchURL
.append(aSearchText
);
1007 AppendConfigToken(aSearchURL
, false);
1008 if (m_xScopeCB
->get_active())
1009 aSearchURL
.append("&Scope=Heading");
1010 std::vector
< OUString
> aFactories
= SfxContentHelper::GetResultSet(aSearchURL
.makeStringAndClear());
1011 for (const OUString
& rRow
: aFactories
)
1014 OUString aTitle
= rRow
.getToken(0, '\t', nIdx
);
1015 OUString
sURL(rRow
.getToken(1, '\t', nIdx
));
1016 m_xResultsLB
->append(sURL
, aTitle
);
1018 xWaitCursor
.reset();
1020 if ( aFactories
.empty() )
1022 std::unique_ptr
<weld::MessageDialog
> xBox(Application::CreateMessageDialog(m_xContainer
.get(),
1023 VclMessageType::Info
, VclButtonsType::Ok
,
1024 SfxResId(STR_INFO_NOSEARCHRESULTS
)));
1029 IMPL_LINK_NOARG(SearchTabPage_Impl
, OpenHdl
, weld::Button
&, void)
1031 aDoubleClickHdl
.Call(nullptr);
1034 IMPL_LINK(SearchTabPage_Impl
, ModifyHdl
, weld::ComboBox
&, rComboBox
, void)
1036 OUString aSearchText
= comphelper::string::strip(m_xSearchED
->get_active_text(), ' ');
1037 m_xSearchBtn
->set_sensitive(!aSearchText
.isEmpty());
1039 if (rComboBox
.changed_by_direct_pick())
1043 IMPL_LINK_NOARG(SearchTabPage_Impl
, DoubleClickHdl
, weld::TreeView
&, bool)
1045 aDoubleClickHdl
.Call(nullptr);
1049 void SearchTabPage_Impl::SetDoubleClickHdl(const Link
<LinkParamNone
*, void>& rLink
)
1051 aDoubleClickHdl
= rLink
;
1054 OUString
SearchTabPage_Impl::GetSelectedEntry() const
1056 return m_xResultsLB
->get_selected_id();
1059 void SearchTabPage_Impl::ClearPage()
1061 ClearSearchResults();
1062 m_xSearchED
->set_entry_text(OUString());
1065 bool SearchTabPage_Impl::OpenKeyword( const OUString
& rKeyword
)
1068 m_xSearchED
->set_entry_text(rKeyword
);
1070 if (m_xResultsLB
->n_children() > 0)
1072 // found keyword -> open it
1073 m_xResultsLB
->select(0);
1074 OpenHdl(*m_xOpenBtn
);
1080 // class BookmarksTabPage_Impl -------------------------------------------
1082 void BookmarksTabPage_Impl::DoAction(std::u16string_view rAction
)
1084 if (rAction
== u
"display")
1085 aDoubleClickHdl
.Call(nullptr);
1086 else if (rAction
== u
"rename")
1088 sal_Int32 nPos
= m_xBookmarksBox
->get_selected_index();
1091 SfxAddHelpBookmarkDialog_Impl
aDlg(m_xBookmarksBox
.get(), true);
1092 aDlg
.SetTitle(m_xBookmarksBox
->get_text(nPos
));
1093 if (aDlg
.run() == RET_OK
)
1095 OUString sURL
= m_xBookmarksBox
->get_id(nPos
);
1096 m_xBookmarksBox
->remove(nPos
);
1097 m_xBookmarksBox
->append(sURL
, aDlg
.GetTitle(),
1098 SvFileInformationManager::GetImageId(INetURLObject(rtl::Concat2View(IMAGE_URL
+INetURLObject(sURL
).GetHost()))));
1099 m_xBookmarksBox
->select(m_xBookmarksBox
->n_children() - 1);
1103 else if (rAction
== u
"delete")
1105 sal_Int32 nPos
= m_xBookmarksBox
->get_selected_index();
1108 m_xBookmarksBox
->remove(nPos
);
1109 const sal_Int32 nCount
= m_xBookmarksBox
->n_children();
1114 m_xBookmarksBox
->select(nPos
);
1120 IMPL_LINK(BookmarksTabPage_Impl
, CommandHdl
, const CommandEvent
&, rCEvt
, bool)
1122 if (rCEvt
.GetCommand() != CommandEventId::ContextMenu
)
1125 std::unique_ptr
<weld::Builder
> xBuilder(Application::CreateBuilder(m_xBookmarksBox
.get(), u
"sfx/ui/bookmarkmenu.ui"_ustr
));
1126 std::unique_ptr
<weld::Menu
> xMenu
= xBuilder
->weld_menu(u
"menu"_ustr
);
1128 OUString sIdent
= xMenu
->popup_at_rect(m_xBookmarksBox
.get(), ::tools::Rectangle(rCEvt
.GetMousePosPixel(), Size(1,1)));
1129 if (!sIdent
.isEmpty())
1134 IMPL_LINK(BookmarksTabPage_Impl
, KeyInputHdl
, const KeyEvent
&, rKEvt
, bool)
1136 bool bHandled
= false;
1137 sal_uInt16 nCode
= rKEvt
.GetKeyCode().GetCode();
1138 if (KEY_DELETE
== nCode
&& m_xBookmarksBox
->n_children() > 0)
1140 DoAction(u
"delete");
1146 // class BookmarksTabPage_Impl -------------------------------------------
1147 BookmarksTabPage_Impl::BookmarksTabPage_Impl(weld::Widget
* pParent
, SfxHelpIndexWindow_Impl
* _pIdxWin
)
1148 : HelpTabPage_Impl(pParent
, _pIdxWin
, u
"HelpBookmarkPage"_ustr
,
1149 u
"sfx/ui/helpbookmarkpage.ui"_ustr
)
1150 , m_xBookmarksBox(m_xBuilder
->weld_tree_view(u
"bookmarks"_ustr
))
1151 , m_xBookmarksPB(m_xBuilder
->weld_button(u
"display"_ustr
))
1153 m_xBookmarksBox
->set_size_request(m_xBookmarksBox
->get_approximate_digit_width() * 30,
1154 m_xBookmarksBox
->get_height_rows(20));
1156 m_xBookmarksPB
->connect_clicked( LINK(this, BookmarksTabPage_Impl
, OpenHdl
));
1157 m_xBookmarksBox
->connect_row_activated(LINK(this, BookmarksTabPage_Impl
, DoubleClickHdl
));
1158 m_xBookmarksBox
->connect_popup_menu(LINK(this, BookmarksTabPage_Impl
, CommandHdl
));
1159 m_xBookmarksBox
->connect_key_press(LINK(this, BookmarksTabPage_Impl
, KeyInputHdl
));
1161 // load bookmarks from configuration
1162 const std::vector
< SvtHistoryOptions::HistoryItem
> aBookmarkSeq
= SvtHistoryOptions::GetList( EHistoryType::HelpBookmarks
);
1163 for ( const auto& rBookmark
: aBookmarkSeq
)
1165 AddBookmarks( rBookmark
.sTitle
, rBookmark
.sURL
);
1169 BookmarksTabPage_Impl::~BookmarksTabPage_Impl()
1171 // save bookmarks to configuration
1172 SvtHistoryOptions::Clear( EHistoryType::HelpBookmarks
);
1173 const sal_Int32 nCount
= m_xBookmarksBox
->n_children();
1174 for (sal_Int32 i
= 0; i
< nCount
; ++i
)
1176 SvtHistoryOptions::AppendItem(EHistoryType::HelpBookmarks
, m_xBookmarksBox
->get_id(i
), u
""_ustr
,
1177 m_xBookmarksBox
->get_text(i
), std::nullopt
, std::nullopt
);
1180 m_xBookmarksBox
.reset();
1181 m_xBookmarksPB
.reset();
1184 IMPL_LINK_NOARG(BookmarksTabPage_Impl
, OpenHdl
, weld::Button
&, void)
1186 aDoubleClickHdl
.Call(nullptr);
1189 IMPL_LINK_NOARG(BookmarksTabPage_Impl
, DoubleClickHdl
, weld::TreeView
&, bool)
1191 aDoubleClickHdl
.Call(nullptr);
1195 void BookmarksTabPage_Impl::SetDoubleClickHdl(const Link
<LinkParamNone
*, void>& rLink
)
1197 aDoubleClickHdl
= rLink
;
1200 OUString
BookmarksTabPage_Impl::GetSelectedEntry() const
1202 return m_xBookmarksBox
->get_selected_id();
1205 void BookmarksTabPage_Impl::AddBookmarks(const OUString
& rTitle
, const OUString
& rURL
)
1207 const OUString aImageURL
{IMAGE_URL
+ INetURLObject(rURL
).GetHost()};
1208 m_xBookmarksBox
->append(rURL
, rTitle
, SvFileInformationManager::GetImageId(INetURLObject(aImageURL
)));
1211 OUString
SfxHelpWindow_Impl::buildHelpURL(std::u16string_view sFactory
,
1212 std::u16string_view sContent
,
1213 std::u16string_view sAnchor
)
1215 OUStringBuffer
sHelpURL(256);
1216 sHelpURL
.append(HELP_URL
+ sFactory
+ sContent
);
1217 AppendConfigToken(sHelpURL
, true/*bUseQuestionMark*/);
1218 if (!sAnchor
.empty())
1219 sHelpURL
.append(sAnchor
);
1220 return sHelpURL
.makeStringAndClear();
1223 void SfxHelpWindow_Impl::loadHelpContent(const OUString
& sHelpURL
, bool bAddToHistory
)
1225 Reference
< XComponentLoader
> xLoader(getTextFrame(), UNO_QUERY
);
1229 // If a print job runs do not open a new page
1230 Reference
< XFrame2
> xTextFrame
= pTextWin
->getFrame();
1231 Reference
< XController
> xTextController
;
1232 if (xTextFrame
.is())
1233 xTextController
= xTextFrame
->getController ();
1234 if ( xTextController
.is() && !xTextController
->suspend( true ) )
1236 xTextController
->suspend( false );
1240 // save url to history
1242 pHelpInterceptor
->addURL(sHelpURL
);
1246 bool bSuccess
= false;
1247 // TODO implement locale fallback ... see below while(true)
1251 Reference
< XComponent
> xContent
= xLoader
->loadComponentFromURL(sHelpURL
, u
"_self"_ustr
, 0, Sequence
< PropertyValue
>());
1257 catch(const RuntimeException
&)
1259 catch(const Exception
&)
1262 /* TODO try next locale ...
1263 no further locale available? => break loop and show error page
1266 openDone(sHelpURL
, bSuccess
);
1271 IMPL_LINK(SfxHelpIndexWindow_Impl
, ActivatePageHdl
, const OUString
&, rPage
, void)
1273 GetPage(rPage
)->Activate();
1276 SfxHelpIndexWindow_Impl::SfxHelpIndexWindow_Impl(SfxHelpWindow_Impl
* _pParent
, weld::Container
* pContainer
)
1277 : m_xBuilder(Application::CreateBuilder(pContainer
, u
"sfx/ui/helpcontrol.ui"_ustr
))
1278 , m_xContainer(m_xBuilder
->weld_container(u
"HelpControl"_ustr
))
1279 , m_xActiveLB(m_xBuilder
->weld_combo_box(u
"active"_ustr
))
1280 , m_xTabCtrl(m_xBuilder
->weld_notebook(u
"tabcontrol"_ustr
))
1281 , aIdle("sfx2 appl SfxHelpIndexWindow_Impl")
1282 , aIndexKeywordLink(LINK(this, SfxHelpIndexWindow_Impl
, KeywordHdl
))
1283 , pParentWin(_pParent
)
1284 , bIsInitDone(false)
1292 OUString
sPageId(u
"index"_ustr
);
1293 SvtViewOptions
aViewOpt( EViewType::TabDialog
, CONFIGNAME_INDEXWIN
);
1294 if ( aViewOpt
.Exists() )
1296 OUString sSavedPageId
= aViewOpt
.GetPageID();
1297 if (m_xTabCtrl
->get_page_index(sSavedPageId
) != -1)
1298 sPageId
= sSavedPageId
;
1300 m_xTabCtrl
->set_current_page(sPageId
);
1301 ActivatePageHdl(sPageId
);
1302 m_xActiveLB
->connect_changed(LINK(this, SfxHelpIndexWindow_Impl
, SelectHdl
));
1304 m_xTabCtrl
->connect_enter_page(LINK(this, SfxHelpIndexWindow_Impl
, ActivatePageHdl
));
1306 aIdle
.SetInvokeHandler( LINK( this, SfxHelpIndexWindow_Impl
, InitHdl
) );
1309 m_xContainer
->show();
1312 SfxHelpIndexWindow_Impl::~SfxHelpIndexWindow_Impl()
1314 SvtViewOptions
aViewOpt(EViewType::TabDialog
, CONFIGNAME_INDEXWIN
);
1315 aViewOpt
.SetPageID(m_xTabCtrl
->get_current_page_ident());
1323 void SfxHelpIndexWindow_Impl::Initialize()
1325 OUStringBuffer
aHelpURL(HELP_URL
);
1326 AppendConfigToken(aHelpURL
, true);
1327 std::vector
<OUString
> aFactories
= SfxContentHelper::GetResultSet(aHelpURL
.makeStringAndClear());
1328 for (const OUString
& rRow
: aFactories
)
1331 OUString aTitle
= rRow
.getToken( 0, '\t', nIdx
); // token 0
1332 std::u16string_view aURL
= o3tl::getToken(rRow
, 1, '\t', nIdx
); // token 2
1333 OUString
aFactory(INetURLObject(aURL
).GetHost());
1334 m_xActiveLB
->append(aFactory
, aTitle
);
1337 if (m_xActiveLB
->get_active() == -1)
1341 void SfxHelpIndexWindow_Impl::SetActiveFactory()
1343 DBG_ASSERT( xIPage
, "index page not initialized" );
1344 if (!bIsInitDone
&& !m_xActiveLB
->get_count())
1350 for (sal_Int32 i
= 0, nEntryCount
= m_xActiveLB
->get_count(); i
< nEntryCount
; ++i
)
1352 OUString aFactory
= m_xActiveLB
->get_id(i
);
1353 aFactory
= aFactory
.toAsciiLowerCase();
1354 if (aFactory
== xIPage
->GetFactory())
1356 if (m_xActiveLB
->get_active() != i
)
1358 m_xActiveLB
->set_active(i
);
1359 aSelectFactoryLink
.Call(nullptr);
1366 HelpTabPage_Impl
* SfxHelpIndexWindow_Impl::GetPage(std::u16string_view rName
)
1368 HelpTabPage_Impl
* pPage
= nullptr;
1370 if (rName
== u
"contents")
1371 pPage
= GetContentPage();
1372 else if (rName
== u
"index")
1373 pPage
= GetIndexPage();
1374 else if (rName
== u
"find")
1375 pPage
= GetSearchPage();
1376 else if (rName
== u
"bookmarks")
1377 pPage
= GetBookmarksPage();
1379 assert(pPage
&& "SfxHelpIndexWindow_Impl::GetCurrentPage(): no current page");
1384 IMPL_LINK_NOARG(SfxHelpIndexWindow_Impl
, SelectHdl
, weld::ComboBox
&, void)
1389 IMPL_LINK_NOARG(SfxHelpIndexWindow_Impl
, InitHdl
, Timer
*, void)
1394 // now use the timer for selection
1395 aIdle
.SetInvokeHandler( LINK( this, SfxHelpIndexWindow_Impl
, SelectFactoryHdl
) );
1396 aIdle
.SetPriority( TaskPriority::LOWEST
);
1399 IMPL_LINK_NOARG(SfxHelpIndexWindow_Impl
, SelectFactoryHdl
, Timer
*, void)
1401 OUString aFactory
= m_xActiveLB
->get_active_id();
1402 if (!aFactory
.isEmpty())
1404 SetFactory(aFactory
.toAsciiLowerCase(), false);
1405 aSelectFactoryLink
.Call(this);
1409 IMPL_LINK_NOARG(SfxHelpIndexWindow_Impl
, KeywordHdl
, IndexTabPage_Impl
&, void)
1411 // keyword found on index?
1412 bool bIndex
= xIPage
->HasKeyword();
1415 bIndex
= xIPage
->HasKeywordIgnoreCase();
1416 // then set index or search page as current.
1417 OUString sPageId
= bIndex
? u
"index"_ustr
: u
"find"_ustr
;
1418 if (sPageId
!= m_xTabCtrl
->get_current_page_ident())
1419 m_xTabCtrl
->set_current_page(sPageId
);
1421 // at last we open the keyword
1423 xIPage
->OpenKeyword();
1424 else if ( !xSPage
->OpenKeyword( sKeyword
) )
1425 pParentWin
->ShowStartPage();
1428 IMPL_LINK_NOARG(SfxHelpIndexWindow_Impl
, IndexTabPageDoubleClickHdl
, LinkParamNone
*, void)
1430 aPageDoubleClickLink
.Call(nullptr);
1433 void SfxHelpIndexWindow_Impl::SetDoubleClickHdl(const Link
<LinkParamNone
*, void>& rLink
)
1435 aPageDoubleClickLink
= rLink
;
1438 IMPL_LINK_NOARG(SfxHelpIndexWindow_Impl
, ContentTabPageDoubleClickHdl
, LinkParamNone
*, void)
1440 aPageDoubleClickLink
.Call(nullptr);
1443 IMPL_LINK_NOARG(SfxHelpIndexWindow_Impl
, TabPageDoubleClickHdl
, LinkParamNone
*, void)
1445 aPageDoubleClickLink
.Call(nullptr);
1448 void SfxHelpIndexWindow_Impl::SetFactory( const OUString
& rFactory
, bool bActive
)
1450 if ( !rFactory
.isEmpty() )
1452 GetIndexPage()->SetFactory( rFactory
);
1453 // the index page made a check if rFactory is valid,
1454 // so the index page always returns a valid factory
1455 GetSearchPage()->SetFactory( GetIndexPage()->GetFactory() );
1461 OUString
SfxHelpIndexWindow_Impl::GetSelectedEntry() const
1465 OUString
sName(m_xTabCtrl
->get_current_page_ident());
1467 if (sName
== "contents")
1469 sRet
= xCPage
->GetSelectedEntry();
1471 else if (sName
== "index")
1473 sRet
= xIPage
->GetSelectedEntry();
1475 else if (sName
== "find")
1477 sRet
= xSPage
->GetSelectedEntry();
1479 else if (sName
== "bookmarks")
1481 sRet
= xBPage
->GetSelectedEntry();
1487 void SfxHelpIndexWindow_Impl::AddBookmarks( const OUString
& rTitle
, const OUString
& rURL
)
1489 GetBookmarksPage()->AddBookmarks( rTitle
, rURL
);
1492 bool SfxHelpIndexWindow_Impl::IsValidFactory( std::u16string_view _rFactory
)
1494 bool bValid
= false;
1495 for (sal_Int32 i
= 0, nEntryCount
= m_xActiveLB
->get_count(); i
< nEntryCount
; ++i
)
1497 OUString aFactory
= m_xActiveLB
->get_id(i
);
1498 if (aFactory
== _rFactory
)
1507 void SfxHelpIndexWindow_Impl::ClearSearchPage()
1510 xSPage
->ClearPage();
1513 void SfxHelpIndexWindow_Impl::GrabFocusBack()
1515 OUString
sName(m_xTabCtrl
->get_current_page_ident());
1517 if (sName
== "contents" && xCPage
)
1518 xCPage
->SetFocusOnBox();
1519 else if (sName
== "index" && xIPage
)
1520 xIPage
->SetFocusOnBox();
1521 else if (sName
== "find" && xSPage
)
1522 xSPage
->SetFocusOnBox();
1523 else if (sName
== "bookmarks" && xBPage
)
1524 xBPage
->SetFocusOnBox();
1527 bool SfxHelpIndexWindow_Impl::HasFocusOnEdit() const
1530 OUString
sName(m_xTabCtrl
->get_current_page_ident());
1531 if (sName
== "index" && xIPage
)
1532 bRet
= xIPage
->HasFocusOnEdit();
1533 else if (sName
== "find" && xSPage
)
1534 bRet
= xSPage
->HasFocusOnEdit();
1538 OUString
SfxHelpIndexWindow_Impl::GetSearchText() const
1541 OUString
sName(m_xTabCtrl
->get_current_page_ident());
1542 if (sName
== "find" && xSPage
)
1543 sRet
= xSPage
->GetSearchText();
1547 bool SfxHelpIndexWindow_Impl::IsFullWordSearch() const
1550 OUString
sName(m_xTabCtrl
->get_current_page_ident());
1551 if (sName
== "find" && xSPage
)
1552 bRet
= xSPage
->IsFullWordSearch();
1556 void SfxHelpIndexWindow_Impl::OpenKeyword( const OUString
& rKeyword
)
1558 sKeyword
= rKeyword
;
1559 DBG_ASSERT( xIPage
, "invalid index page" );
1560 xIPage
->SetKeyword( sKeyword
);
1563 void SfxHelpIndexWindow_Impl::SelectExecutableEntry()
1565 OUString
sName(m_xTabCtrl
->get_current_page_ident());
1566 if (sName
== "index" && xIPage
)
1567 xIPage
->SelectExecutableEntry();
1570 weld::Window
* SfxHelpIndexWindow_Impl::GetFrameWeld() const
1572 return pParentWin
->GetFrameWeld();
1575 // class TextWin_Impl ----------------------------------------------------
1576 TextWin_Impl::TextWin_Impl( vcl::Window
* p
) : DockingWindow( p
, 0 )
1580 bool TextWin_Impl::EventNotify( NotifyEvent
& rNEvt
)
1582 if( ( rNEvt
.GetType() == NotifyEventType::KEYINPUT
) && rNEvt
.GetKeyEvent()->GetKeyCode().GetCode() == KEY_TAB
)
1583 return GetParent()->EventNotify( rNEvt
);
1585 return DockingWindow::EventNotify( rNEvt
);
1589 // remove docking area acceptor from layoutmanager, so it will not layout anything further .-)
1590 static void lcl_disableLayoutOfFrame(const Reference
< XFrame2
>& xFrame
)
1592 xFrame
->setLayoutManager( Reference
< XLayoutManager
>() );
1595 // class SfxHelpTextWindow_Impl ------------------------------------------
1597 SfxHelpTextWindow_Impl::SfxHelpTextWindow_Impl(SfxHelpWindow_Impl
* pHelpWin
, weld::Builder
& rBuilder
, vcl::Window
* pParent
) :
1599 Window( pParent
, WB_CLIPCHILDREN
| WB_TABSTOP
| WB_DIALOGCONTROL
),
1601 xToolBox ( rBuilder
.weld_toolbar(u
"toolbar"_ustr
) ),
1602 xOnStartupCB ( rBuilder
.weld_check_button(u
"checkbutton"_ustr
) ),
1603 xMenu ( rBuilder
.weld_menu(u
"menu"_ustr
) ),
1604 aSelectIdle ( "sfx2 appl SfxHelpTextWindow_Impl Select" ),
1605 aIndexOnImage ( BMP_HELP_TOOLBOX_INDEX_ON
),
1606 aIndexOffImage ( BMP_HELP_TOOLBOX_INDEX_OFF
),
1607 aIndexOnText ( SfxResId( STR_HELP_BUTTON_INDEX_ON
) ),
1608 aIndexOffText ( SfxResId( STR_HELP_BUTTON_INDEX_OFF
) ),
1609 aOnStartupText ( SfxResId( RID_HELP_ONSTARTUP_TEXT
) ),
1610 xHelpWin ( pHelpWin
),
1611 pTextWin ( VclPtr
<TextWin_Impl
>::Create( this ) ),
1613 bIsIndexOn ( false ),
1614 bIsInClose ( false ),
1615 bIsFullWordSearch ( false )
1617 xFrame
= Frame::create( ::comphelper::getProcessComponentContext() );
1618 xFrame
->initialize( VCLUnoHelper::GetInterface ( pTextWin
) );
1619 xFrame
->setName( u
"OFFICE_HELP"_ustr
);
1620 lcl_disableLayoutOfFrame(xFrame
);
1622 xToolBox
->set_help_id(HID_HELP_TOOLBOX
);
1624 xToolBox
->set_item_tooltip_text(u
"index"_ustr
, aIndexOffText
);
1625 xToolBox
->set_item_help_id(u
"index"_ustr
, HID_HELP_TOOLBOXITEM_INDEX
);
1626 xToolBox
->set_item_help_id(u
"backward"_ustr
, HID_HELP_TOOLBOXITEM_BACKWARD
);
1627 xToolBox
->set_item_help_id(u
"forward"_ustr
, HID_HELP_TOOLBOXITEM_FORWARD
);
1628 xToolBox
->set_item_help_id(u
"start"_ustr
, HID_HELP_TOOLBOXITEM_START
);
1629 xToolBox
->set_item_help_id(u
"print"_ustr
, HID_HELP_TOOLBOXITEM_PRINT
);
1630 xToolBox
->set_item_help_id(u
"bookmarks"_ustr
, HID_HELP_TOOLBOXITEM_BOOKMARKS
);
1631 xToolBox
->set_item_help_id(u
"searchdialog"_ustr
, HID_HELP_TOOLBOXITEM_SEARCHDIALOG
);
1633 InitToolBoxImages();
1635 xOnStartupCB
->connect_toggled(LINK(this, SfxHelpTextWindow_Impl
, CheckHdl
));
1637 aSelectIdle
.SetInvokeHandler( LINK( this, SfxHelpTextWindow_Impl
, SelectHdl
) );
1638 aSelectIdle
.SetPriority( TaskPriority::LOWEST
);
1640 char* pEnv
= getenv( "help_debug" );
1644 SvtMiscOptions().AddListenerLink( LINK( this, SfxHelpTextWindow_Impl
, NotifyHdl
) );
1647 SfxHelpTextWindow_Impl::~SfxHelpTextWindow_Impl()
1652 void SfxHelpTextWindow_Impl::dispose()
1655 SvtMiscOptions().RemoveListenerLink( LINK( this, SfxHelpTextWindow_Impl
, NotifyHdl
) );
1658 xOnStartupCB
.reset();
1660 pTextWin
.disposeAndClear();
1661 vcl::Window::dispose();
1664 bool SfxHelpTextWindow_Impl::HasSelection() const
1666 // is there any selection in the text and not only a cursor?
1668 Reference
< XTextRange
> xRange
= getCursor();
1671 Reference
< XText
> xText
= xRange
->getText();
1672 Reference
< XTextCursor
> xCursor
= xText
->createTextCursorByRange( xRange
);
1673 bRet
= !xCursor
->isCollapsed();
1679 void SfxHelpTextWindow_Impl::InitToolBoxImages()
1681 xToolBox
->set_item_icon_name(u
"index"_ustr
, bIsIndexOn
? aIndexOffImage
: aIndexOnImage
);
1684 void SfxHelpTextWindow_Impl::InitOnStartupBox()
1686 sCurrentFactory
= SfxHelp::GetCurrentModuleIdentifier();
1688 const Reference
< XComponentContext
>& xContext
= ::comphelper::getProcessComponentContext();
1689 const OUString sPath
{ PATH_OFFICE_FACTORIES
+ sCurrentFactory
};
1691 // Attention: This check boy knows two states:
1692 // 1) Reading of the config key fails with an exception or by getting an empty Any (!) => check box must be hidden
1693 // 2) We read sal_True/sal_False => check box must be shown and enabled/disabled
1695 bool bHideBox
= true;
1696 bool bHelpAtStartup
= false;
1699 xConfiguration
= ConfigurationHelper::openConfig(
1700 xContext
, PACKAGE_SETUP
, EConfigurationModes::Standard
);
1701 if ( xConfiguration
.is() )
1703 Any aAny
= ConfigurationHelper::readRelativeKey( xConfiguration
, sPath
, KEY_HELP_ON_OPEN
);
1704 if (aAny
>>= bHelpAtStartup
)
1714 xOnStartupCB
->hide();
1717 // detect module name
1718 OUString sModuleName
;
1720 if ( xConfiguration
.is() )
1725 Any aAny
= ConfigurationHelper::readRelativeKey( xConfiguration
, sPath
, KEY_UI_NAME
);
1728 catch( Exception
const & )
1730 TOOLS_WARN_EXCEPTION( "sfx.appl", "SfxHelpTextWindow_Impl::InitOnStartupBox()" );
1732 sModuleName
= sTemp
;
1735 if ( !sModuleName
.isEmpty() )
1737 // set module name in checkbox text
1738 xOnStartupCB
->set_label(aOnStartupText
.replaceFirst("%MODULENAME", sModuleName
));
1740 xOnStartupCB
->show();
1742 xOnStartupCB
->set_active(bHelpAtStartup
);
1743 xOnStartupCB
->save_state();
1748 Reference
< XBreakIterator
> const & SfxHelpTextWindow_Impl::GetBreakIterator()
1750 if ( !xBreakIterator
.is() )
1751 xBreakIterator
= vcl::unohelper::CreateBreakIterator();
1752 DBG_ASSERT( xBreakIterator
.is(), "Could not create BreakIterator" );
1753 return xBreakIterator
;
1756 Reference
< XTextRange
> SfxHelpTextWindow_Impl::getCursor() const
1758 // return the current cursor
1759 Reference
< XTextRange
> xCursor
;
1763 Reference
< XSelectionSupplier
> xSelSup( xFrame
->getController(), UNO_QUERY
);
1766 Any aAny
= xSelSup
->getSelection();
1767 Reference
< XIndexAccess
> xSelection
;
1768 if ( aAny
>>= xSelection
)
1770 if ( xSelection
->getCount() == 1 )
1772 aAny
= xSelection
->getByIndex(0);
1780 TOOLS_WARN_EXCEPTION( "sfx.appl", "SfxHelpTextWindow_Impl::getCursor(): unexpected exception" );
1787 bool SfxHelpTextWindow_Impl::isHandledKey( const vcl::KeyCode
& _rKeyCode
)
1790 sal_uInt16 nCode
= _rKeyCode
.GetCode();
1792 // the keys <CTRL><A> (select all), <CTRL><C> (copy),
1793 // <CTRL><F> (find), <CTRL><P> (print) and <CTRL><W> (close window)
1794 // were handled in help
1795 if ( _rKeyCode
.IsMod1() &&
1796 ( KEY_A
== nCode
|| KEY_C
== nCode
|| KEY_F
== nCode
|| KEY_P
== nCode
|| KEY_W
== nCode
) )
1798 if ( KEY_F
== nCode
)
1808 IMPL_LINK_NOARG(SfxHelpTextWindow_Impl
, SelectHdl
, Timer
*, void)
1812 // select the words, which are equal to the search text of the search page
1813 Reference
< XController
> xController
= xFrame
->getController();
1814 if ( xController
.is() )
1817 Reference
< XSearchable
> xSearchable( xController
->getModel(), UNO_QUERY
);
1818 if ( xSearchable
.is() )
1820 // create descriptor, set string and find all words
1821 Reference
< XSearchDescriptor
> xSrchDesc
= xSearchable
->createSearchDescriptor();
1822 xSrchDesc
->setPropertyValue( u
"SearchRegularExpression"_ustr
, Any( true ) );
1823 if ( bIsFullWordSearch
)
1824 xSrchDesc
->setPropertyValue( u
"SearchWords"_ustr
, Any( true ) );
1826 xSrchDesc
->setSearchString( sfx2::PrepareSearchString( aSearchText
, GetBreakIterator(), false ) );
1827 Reference
< XIndexAccess
> xSelection
= xSearchable
->findAll( xSrchDesc
);
1829 // then select all found words
1830 Reference
< XSelectionSupplier
> xSelectionSup( xController
, UNO_QUERY
);
1831 if ( xSelectionSup
.is() )
1833 xSelectionSup
->select( Any(xSelection
) );
1840 TOOLS_WARN_EXCEPTION( "sfx.appl", "SfxHelpTextWindow_Impl::SelectHdl(): unexpected exception" );
1845 IMPL_LINK_NOARG( SfxHelpTextWindow_Impl
, NotifyHdl
, LinkParamNone
*, void )
1847 InitToolBoxImages();
1851 IMPL_LINK( SfxHelpTextWindow_Impl
, FindHdl
, sfx2::SearchDialog
&, rDlg
, void )
1855 void SfxHelpTextWindow_Impl::FindHdl(sfx2::SearchDialog
* pDlg
)
1859 // select the words, which are equal to the search text of the search page
1860 Reference
< XController
> xController
= xFrame
->getController();
1861 if ( xController
.is() )
1864 Reference
< XSearchable
> xSearchable( xController
->getModel(), UNO_QUERY
);
1865 if ( xSearchable
.is() )
1867 bool bWrapAround
= ( nullptr == pDlg
);
1869 pDlg
= m_xSrchDlg
.get();
1870 assert(pDlg
&& "invalid search dialog");
1872 // create descriptor, set string and find all words
1873 Reference
< XSearchDescriptor
> xSrchDesc
= xSearchable
->createSearchDescriptor();
1874 xSrchDesc
->setPropertyValue( u
"SearchWords"_ustr
, Any(pDlg
->IsOnlyWholeWords()) );
1875 xSrchDesc
->setPropertyValue( u
"SearchCaseSensitive"_ustr
, Any(pDlg
->IsMarchCase()) );
1876 xSrchDesc
->setPropertyValue( u
"SearchBackwards"_ustr
, Any(pDlg
->IsSearchBackwards()) );
1877 xSrchDesc
->setSearchString( pDlg
->GetSearchText() );
1878 Reference
< XInterface
> xSelection
;
1879 Reference
< XTextRange
> xCursor
= getCursor();
1883 if ( pDlg
->IsSearchBackwards() )
1884 xCursor
= xCursor
->getStart();
1885 xSelection
= xSearchable
->findNext( xCursor
, xSrchDesc
);
1888 xSelection
= xSearchable
->findFirst( xSrchDesc
);
1890 // then select the found word
1891 if ( xSelection
.is() )
1893 Reference
< XSelectionSupplier
> xSelectionSup( xController
, UNO_QUERY
);
1894 if ( xSelectionSup
.is() )
1896 xSelectionSup
->select( Any(xSelection
) );
1899 else if ( pDlg
->IsWrapAround() && !bWrapAround
)
1901 Reference
< text::XTextViewCursorSupplier
> xCrsrSupp( xController
, uno::UNO_QUERY
);
1902 Reference
< text::XTextViewCursor
> xTVCrsr
= xCrsrSupp
->getViewCursor();
1905 Reference
< text::XTextDocument
> xDoc( xController
->getModel(), uno::UNO_QUERY
);
1906 Reference
< text::XText
> xText
= xDoc
->getText();
1909 if ( pDlg
->IsSearchBackwards() )
1910 xTVCrsr
->gotoRange( xText
->getEnd(), false );
1912 xTVCrsr
->gotoRange( xText
->getStart(), false );
1919 assert(m_xSrchDlg
&& "no search dialog");
1920 std::unique_ptr
<weld::MessageDialog
> xBox(Application::CreateMessageDialog(m_xSrchDlg
->getDialog(),
1921 VclMessageType::Info
, VclButtonsType::Ok
, SfxResId(STR_INFO_NOSEARCHTEXTFOUND
)));
1923 m_xSrchDlg
->SetFocusOnEdit();
1930 TOOLS_WARN_EXCEPTION( "sfx.appl", "SfxHelpTextWindow_Impl::SelectHdl(): unexpected exception" );
1934 IMPL_LINK_NOARG(SfxHelpTextWindow_Impl
, CloseHdl
, LinkParamNone
*, void)
1939 IMPL_LINK_NOARG(SfxHelpTextWindow_Impl
, CheckHdl
, weld::Toggleable
&, void)
1941 if ( !xConfiguration
.is() )
1944 bool bChecked
= xOnStartupCB
->get_active();
1947 ConfigurationHelper::writeRelativeKey(
1948 xConfiguration
, PATH_OFFICE_FACTORIES
+ sCurrentFactory
, KEY_HELP_ON_OPEN
, Any( bChecked
) );
1949 ConfigurationHelper::flush( xConfiguration
);
1951 catch( Exception
const & )
1953 TOOLS_WARN_EXCEPTION( "sfx.appl", "SfxHelpTextWindow_Impl::CheckHdl()" );
1957 void SfxHelpTextWindow_Impl::Resize()
1959 Size aSize
= GetOutputSizePixel();
1960 pTextWin
->SetPosSizePixel( Point(0, 0), aSize
);
1963 bool SfxHelpTextWindow_Impl::PreNotify( NotifyEvent
& rNEvt
)
1966 NotifyEventType nType
= rNEvt
.GetType();
1967 if ( NotifyEventType::COMMAND
== nType
&& rNEvt
.GetCommandEvent() )
1969 const CommandEvent
* pCmdEvt
= rNEvt
.GetCommandEvent();
1970 vcl::Window
* pCmdWin
= rNEvt
.GetWindow();
1972 if ( pCmdEvt
->GetCommand() == CommandEventId::ContextMenu
&& pCmdWin
!= this )
1975 if ( pCmdEvt
->IsMouseEvent() )
1976 aPos
= pCmdEvt
->GetMousePosPixel();
1978 aPos
= Point( pTextWin
->GetPosPixel().X() + 20, 20 );
1983 xMenu
->append(u
"index"_ustr
, aIndexOffText
, BMP_HELP_TOOLBOX_INDEX_OFF
);
1985 xMenu
->append(u
"index"_ustr
, aIndexOnText
, BMP_HELP_TOOLBOX_INDEX_ON
);
1987 xMenu
->append_separator(u
"separator1"_ustr
);
1988 xMenu
->append(u
"backward"_ustr
, SfxResId(STR_HELP_BUTTON_PREV
), BMP_HELP_TOOLBOX_PREV
);
1989 xMenu
->set_sensitive(u
"backward"_ustr
, xHelpWin
->HasHistoryPredecessor());
1990 xMenu
->append(u
"forward"_ustr
, SfxResId(STR_HELP_BUTTON_NEXT
), BMP_HELP_TOOLBOX_NEXT
);
1991 xMenu
->set_sensitive(u
"forward"_ustr
, xHelpWin
->HasHistorySuccessor());
1992 xMenu
->append(u
"start"_ustr
, SfxResId(STR_HELP_BUTTON_START
), BMP_HELP_TOOLBOX_START
);
1993 xMenu
->append_separator(u
"separator2"_ustr
);
1994 xMenu
->append(u
"print"_ustr
, SfxResId(STR_HELP_BUTTON_PRINT
), BMP_HELP_TOOLBOX_PRINT
);
1995 xMenu
->append(u
"bookmarks"_ustr
, SfxResId(STR_HELP_BUTTON_ADDBOOKMARK
), BMP_HELP_TOOLBOX_BOOKMARKS
);
1996 xMenu
->append(u
"searchdialog"_ustr
, SfxResId(STR_HELP_BUTTON_SEARCHDIALOG
), BMP_HELP_TOOLBOX_SEARCHDIALOG
);
1997 xMenu
->append_separator(u
"separator3"_ustr
);
1998 xMenu
->append_check(u
"selectionmode"_ustr
, SfxResId(STR_HELP_MENU_TEXT_SELECTION_MODE
));
2000 aURL
.Complete
= ".uno:SelectTextMode";
2001 Reference
< util::XURLTransformer
> xTrans( util::URLTransformer::create( ::comphelper::getProcessComponentContext() ) );
2002 xTrans
->parseStrict(aURL
);
2003 Reference
< XDispatch
> xDisp
= xFrame
->queryDispatch( aURL
, OUString(), 0 );
2006 rtl::Reference
<HelpStatusListener_Impl
> pStateListener
=
2007 new HelpStatusListener_Impl(xDisp
, aURL
);
2008 FeatureStateEvent rEvent
= pStateListener
->GetStateEvent();
2009 bool bCheck
= false;
2010 rEvent
.State
>>= bCheck
;
2011 xMenu
->set_active(u
"selectionmode"_ustr
, bCheck
);
2013 xMenu
->append_separator(u
"separator4"_ustr
);
2014 xMenu
->append(u
"copy"_ustr
, SfxResId(STR_HELP_MENU_TEXT_COPY
), BMP_HELP_TOOLBOX_COPY
);
2015 xMenu
->set_sensitive(u
"copy"_ustr
, HasSelection());
2019 xMenu
->append_separator(u
"separator5"_ustr
);
2020 xMenu
->append(u
"sourceview"_ustr
, SfxResId(STR_HELP_BUTTON_SOURCEVIEW
));
2023 int x
, y
, width
, height
;
2024 weld::Window
* pTopLevel
= GetFrameWeld();
2025 xHelpWin
->GetContainer()->get_extents_relative_to(*pTopLevel
, x
, y
, width
, height
);
2029 xHelpWin
->DoAction(xMenu
->popup_at_rect(pTopLevel
, tools::Rectangle(aPos
, Size(1,1))));
2033 else if ( NotifyEventType::KEYINPUT
== nType
&& rNEvt
.GetKeyEvent() )
2035 const KeyEvent
* pKEvt
= rNEvt
.GetKeyEvent();
2036 const vcl::KeyCode
& rKeyCode
= pKEvt
->GetKeyCode();
2037 sal_uInt16 nKeyGroup
= rKeyCode
.GetGroup();
2038 sal_uInt16 nKey
= rKeyCode
.GetCode();
2039 if ( KEYGROUP_ALPHA
== nKeyGroup
&& !isHandledKey( rKeyCode
) )
2041 // do nothing disables the writer accelerators
2044 else if ( rKeyCode
.IsMod1() && ( KEY_F4
== nKey
|| KEY_W
== nKey
) )
2046 // <CTRL><F4> or <CTRL><W> -> close top frame
2047 xHelpWin
->CloseWindow();
2050 else if ( KEY_TAB
== nKey
&& xOnStartupCB
->has_focus() )
2052 xToolBox
->grab_focus();
2057 return bDone
|| Window::PreNotify( rNEvt
);
2061 void SfxHelpTextWindow_Impl::GetFocus()
2070 Reference
< css::awt::XWindow
> xWindow
= xFrame
->getComponentWindow();
2072 xWindow
->setFocus();
2075 catch( Exception
const & )
2077 TOOLS_WARN_EXCEPTION( "sfx.appl", "SfxHelpTextWindow_Impl::GetFocus()" );
2082 void SfxHelpTextWindow_Impl::DataChanged( const DataChangedEvent
& rDCEvt
)
2084 Window::DataChanged( rDCEvt
);
2086 if ( ( ( rDCEvt
.GetType() == DataChangedEventType::SETTINGS
) ||
2087 ( rDCEvt
.GetType() == DataChangedEventType::DISPLAY
) ) &&
2088 ( rDCEvt
.GetFlags() & AllSettingsFlags::STYLE
) )
2090 SetBackground( Wallpaper( GetSettings().GetStyleSettings().GetFaceColor() ) );
2091 InitToolBoxImages();
2095 void SfxHelpTextWindow_Impl::ToggleIndex( bool bOn
)
2100 xToolBox
->set_item_icon_name(u
"index"_ustr
, aIndexOffImage
);
2101 xToolBox
->set_item_tooltip_text(u
"index"_ustr
, aIndexOffText
);
2105 xToolBox
->set_item_icon_name(u
"index"_ustr
, aIndexOnImage
);
2106 xToolBox
->set_item_tooltip_text(u
"index"_ustr
, aIndexOnText
);
2110 void SfxHelpTextWindow_Impl::SelectSearchText( const OUString
& rSearchText
, bool _bIsFullWordSearch
)
2112 aSearchText
= rSearchText
;
2113 bIsFullWordSearch
= _bIsFullWordSearch
;
2114 aSelectIdle
.Start();
2118 void SfxHelpTextWindow_Impl::SetPageStyleHeaderOff() const
2120 bool bSetOff
= false;
2121 // set off the pagestyle header to prevent print output of the help URL
2124 Reference
< XController
> xController
= xFrame
->getController();
2125 Reference
< XSelectionSupplier
> xSelSup( xController
, UNO_QUERY
);
2128 Reference
< XIndexAccess
> xSelection
;
2129 if ( xSelSup
->getSelection() >>= xSelection
)
2131 Reference
< XTextRange
> xRange
;
2132 if ( xSelection
->getByIndex(0) >>= xRange
)
2134 Reference
< XText
> xText
= xRange
->getText();
2135 Reference
< XPropertySet
> xProps( xText
->createTextCursorByRange( xRange
), UNO_QUERY
);
2136 OUString sStyleName
;
2137 if ( xProps
->getPropertyValue( u
"PageStyleName"_ustr
) >>= sStyleName
)
2139 Reference
< XStyleFamiliesSupplier
> xStyles( xController
->getModel(), UNO_QUERY
);
2140 Reference
< XNameContainer
> xContainer
;
2141 if ( xStyles
->getStyleFamilies()->getByName( u
"PageStyles"_ustr
)
2144 Reference
< XStyle
> xStyle
;
2145 if ( xContainer
->getByName( sStyleName
) >>= xStyle
)
2147 Reference
< XPropertySet
> xPropSet( xStyle
, UNO_QUERY
);
2148 xPropSet
->setPropertyValue( u
"HeaderIsOn"_ustr
, Any( false ) );
2150 Reference
< XModifiable
> xReset(xStyles
, UNO_QUERY
);
2151 xReset
->setModified(false);
2160 catch( Exception
const & )
2162 TOOLS_WARN_EXCEPTION( "sfx.appl", "SfxHelpTextWindow_Impl::SetPageStyleHeaderOff()" );
2165 SAL_WARN_IF( !bSetOff
, "sfx.appl", "SfxHelpTextWindow_Impl::SetPageStyleHeaderOff(): set off failed" );
2169 void SfxHelpTextWindow_Impl::CloseFrame()
2174 css::uno::Reference
< css::util::XCloseable
> xCloseable ( xFrame
, css::uno::UNO_QUERY
);
2175 if (xCloseable
.is())
2176 xCloseable
->close(true);
2178 catch( css::util::CloseVetoException
& )
2184 void SfxHelpTextWindow_Impl::DoSearch()
2189 // create the search dialog
2190 m_xSrchDlg
= std::make_shared
<sfx2::SearchDialog
>(pTextWin
->GetFrameWeld(), "HelpSearchDialog");
2192 m_xSrchDlg
->SetFindHdl( LINK( this, SfxHelpTextWindow_Impl
, FindHdl
) );
2193 m_xSrchDlg
->SetCloseHdl( LINK( this, SfxHelpTextWindow_Impl
, CloseHdl
) );
2194 // get selected text of the help page to set it as the search text
2195 Reference
< XTextRange
> xCursor
= getCursor();
2198 OUString sText
= xCursor
->getString();
2199 if ( !sText
.isEmpty() )
2200 m_xSrchDlg
->SetSearchText( sText
);
2202 sfx2::SearchDialog::runAsync(m_xSrchDlg
);
2205 void SfxHelpWindow_Impl::GetFocus()
2208 pTextWin
->GrabFocus();
2210 ResizableDockingWindow::GetFocus();
2213 void SfxHelpWindow_Impl::MakeLayout()
2217 m_xHelpPaneWindow
->set_visible(bIndex
);
2220 IMPL_LINK(SfxHelpWindow_Impl
, ResizeHdl
, const Size
&, rSize
, void)
2222 int nNewWidth
= rSize
.Width();
2226 nIndexSize
= round(m_xContainer
->get_position() * 100.0 / nNewWidth
);
2229 nIndexSize
= round(m_xContainer
->get_position() * 100.0 / nWidth
);
2232 void SfxHelpWindow_Impl::Split()
2236 m_xContainer
->set_position(nWidth
* nIndexSize
/ 100);
2240 void SfxHelpWindow_Impl::LoadConfig()
2242 SvtViewOptions
aViewOpt( EViewType::Window
, CONFIGNAME_HELPWIN
);
2243 if ( !aViewOpt
.Exists() )
2245 bIndex
= aViewOpt
.IsVisible();
2247 Any aUserItem
= aViewOpt
.GetUserItem( USERITEM_NAME
);
2249 if ( aUserItem
>>= aUserData
)
2251 DBG_ASSERT( comphelper::string::getTokenCount(aUserData
, ';') == 6, "invalid user data" );
2253 nIndexSize
= o3tl::toInt32(o3tl::getToken(aUserData
, 0, ';', nIdx
));
2254 o3tl::getToken(aUserData
, 0, ';', nIdx
); // ignore nTextSize
2255 sal_Int32 nOldWidth
= o3tl::toInt32(o3tl::getToken(aUserData
, 0, ';', nIdx
));
2256 sal_Int32 nOldHeight
= o3tl::toInt32(o3tl::getToken(aUserData
, 0, ';', nIdx
));
2257 aWinSize
= Size(nOldWidth
, nOldHeight
);
2258 aWinPos
.setX( o3tl::toInt32(o3tl::getToken(aUserData
, 0, ';', nIdx
)) );
2259 aWinPos
.setY( o3tl::toInt32(o3tl::getToken(aUserData
, 0, ';', nIdx
)) );
2262 pTextWin
->ToggleIndex( bIndex
);
2265 void SfxHelpWindow_Impl::SaveConfig()
2267 SvtViewOptions
aViewOpt( EViewType::Window
, CONFIGNAME_HELPWIN
);
2268 sal_Int32 nW
= 0, nH
= 0;
2272 css::awt::Rectangle aRect
= xWindow
->getPosSize();
2277 aViewOpt
.SetVisible( bIndex
);
2278 VclPtr
<vcl::Window
> pScreenWin
= VCLUnoHelper::GetWindow( xWindow
);
2279 aWinPos
= pScreenWin
->GetWindowExtentsAbsolute().TopLeft();
2281 nIndexSize
= round(m_xContainer
->get_position() * 100.0 / nWidth
);
2282 const OUString aUserData
= OUString::number( nIndexSize
)
2283 + ";" + OUString::number( 100 - nIndexSize
)
2284 + ";" + OUString::number( nW
)
2285 + ";" + OUString::number( nH
)
2286 + ";" + OUString::number( aWinPos
.X() )
2287 + ";" + OUString::number( aWinPos
.Y() );
2289 aViewOpt
.SetUserItem( USERITEM_NAME
, Any( aUserData
) );
2292 void SfxHelpWindow_Impl::ShowStartPage()
2294 loadHelpContent(SfxHelpWindow_Impl::buildHelpURL(xIndexWin
->GetFactory(), u
"/start", u
""));
2297 IMPL_LINK(SfxHelpWindow_Impl
, SelectHdl
, const OUString
&, rCurItem
, void)
2299 bGrabFocusToToolBox
= pTextWin
->GetToolBox().has_focus();
2303 IMPL_LINK_NOARG(SfxHelpWindow_Impl
, OpenHdl
, LinkParamNone
*, void)
2305 xIndexWin
->SelectExecutableEntry();
2306 OUString aEntry
= xIndexWin
->GetSelectedEntry();
2308 if ( aEntry
.isEmpty() )
2313 bool bComplete
= aEntry
.toAsciiLowerCase().match("vnd.sun.star.help");
2319 std::u16string_view aId
;
2320 OUString
aAnchor('#');
2321 if ( comphelper::string::getTokenCount(aEntry
, '#') == 2 )
2323 sal_Int32 nIdx
{ 0 };
2324 aId
= o3tl::getToken(aEntry
, 0, '#', nIdx
);
2325 aAnchor
+= o3tl::getToken(aEntry
, 0, '#', nIdx
);
2330 sHelpURL
= SfxHelpWindow_Impl::buildHelpURL(xIndexWin
->GetFactory(), Concat2View(OUString::Concat("/") + aId
), aAnchor
);
2333 loadHelpContent(sHelpURL
);
2336 IMPL_LINK( SfxHelpWindow_Impl
, SelectFactoryHdl
, SfxHelpIndexWindow_Impl
* , pWin
, void )
2338 if ( sTitle
.isEmpty() )
2339 sTitle
= GetParent()->GetText();
2341 Reference
< XTitle
> xTitle(xFrame
, UNO_QUERY
);
2343 xTitle
->setTitle(sTitle
+ " - " + xIndexWin
->GetActiveFactoryTitle());
2347 xIndexWin
->ClearSearchPage();
2351 IMPL_LINK( SfxHelpWindow_Impl
, ChangeHdl
, HelpListener_Impl
&, rListener
, void )
2353 SetFactory( rListener
.GetFactory() );
2357 void SfxHelpWindow_Impl::openDone(std::u16string_view sURL
,
2360 INetURLObject
aObj( sURL
);
2361 if ( aObj
.GetProtocol() == INetProtocol::VndSunStarHelp
)
2362 SetFactory( aObj
.GetHost() );
2365 if ( bGrabFocusToToolBox
)
2367 pTextWin
->GetToolBox().grab_focus();
2368 bGrabFocusToToolBox
= false;
2371 xIndexWin
->GrabFocusBack();
2375 // set some view settings: "prevent help tips" and "helpid == 68245"
2378 Reference
< XController
> xController
= pTextWin
->getFrame()->getController();
2379 if ( xController
.is() )
2381 Reference
< XViewSettingsSupplier
> xSettings( xController
, UNO_QUERY
);
2382 Reference
< XPropertySet
> xViewProps
= xSettings
->getViewSettings();
2383 Reference
< XPropertySetInfo
> xInfo
= xViewProps
->getPropertySetInfo();
2384 xViewProps
->setPropertyValue( u
"ShowContentTips"_ustr
, Any( false ) );
2385 xViewProps
->setPropertyValue( u
"ShowGraphics"_ustr
, Any( true ) );
2386 xViewProps
->setPropertyValue( u
"ShowTables"_ustr
, Any( true ) );
2387 xViewProps
->setPropertyValue( u
"HelpURL"_ustr
, Any( u
"HID:SFX2_HID_HELP_ONHELP"_ustr
) );
2388 OUString
sProperty( u
"IsExecuteHyperlinks"_ustr
);
2389 if ( xInfo
->hasPropertyByName( sProperty
) )
2390 xViewProps
->setPropertyValue( sProperty
, Any( true ) );
2391 xController
->restoreViewData(Any());
2396 TOOLS_WARN_EXCEPTION( "sfx.appl", "SfxHelpWindow_Impl::OpenDoneHdl(): unexpected exception" );
2399 // When the SearchPage opens the help doc, then select all words, which are equal to its text
2400 OUString sSearchText
= comphelper::string::strip(xIndexWin
->GetSearchText(), ' ');
2401 if ( !sSearchText
.isEmpty() )
2402 pTextWin
->SelectSearchText( sSearchText
, xIndexWin
->IsFullWordSearch() );
2404 // no page style header -> this prevents a print output of the URL
2405 pTextWin
->SetPageStyleHeaderOff();
2409 SfxHelpWindow_Impl::SfxHelpWindow_Impl(
2410 const css::uno::Reference
< css::frame::XFrame2
>& rFrame
,
2411 vcl::Window
* pParent
) :
2413 ResizableDockingWindow(pParent
),
2416 pTextWin ( nullptr ),
2417 pHelpInterceptor ( new HelpInterceptor_Impl() ),
2418 pHelpListener ( new HelpListener_Impl( pHelpInterceptor
) ),
2420 bGrabFocusToToolBox ( false ),
2423 nIndexSize ( 40 ), // % of width
2426 sTitle ( pParent
->GetText() )
2428 SetStyle(GetStyle() & ~WB_DOCKABLE
);
2430 SetHelpId( HID_HELP_WINDOW
);
2432 m_xBuilder
= Application::CreateInterimBuilder(m_xBox
.get(), u
"sfx/ui/helpwindow.ui"_ustr
, false);
2433 m_xContainer
= m_xBuilder
->weld_paned(u
"HelpWindow"_ustr
);
2434 m_xContainer
->connect_size_allocate(LINK(this, SfxHelpWindow_Impl
, ResizeHdl
));
2435 m_xHelpPaneWindow
= m_xBuilder
->weld_container(u
"helppanewindow"_ustr
);
2436 m_xHelpTextWindow
= m_xBuilder
->weld_container(u
"helptextwindow"_ustr
);
2437 m_xHelpTextXWindow
= m_xHelpTextWindow
->CreateChildFrame();
2439 pHelpInterceptor
->InitWaiter( this );
2440 xIndexWin
.reset(new SfxHelpIndexWindow_Impl(this, m_xHelpPaneWindow
.get()));
2441 xIndexWin
->SetDoubleClickHdl( LINK( this, SfxHelpWindow_Impl
, OpenHdl
) );
2442 xIndexWin
->SetSelectFactoryHdl( LINK( this, SfxHelpWindow_Impl
, SelectFactoryHdl
) );
2444 pTextWin
= VclPtr
<SfxHelpTextWindow_Impl
>::Create(this, *m_xBuilder
, VCLUnoHelper::GetWindow(m_xHelpTextXWindow
));
2445 Reference
< XFrames
> xFrames
= rFrame
->getFrames();
2446 xFrames
->append( Reference
<XFrame
>(pTextWin
->getFrame(), UNO_QUERY_THROW
) );
2447 pTextWin
->SetSelectHdl( LINK( this, SfxHelpWindow_Impl
, SelectHdl
) );
2449 pHelpInterceptor
->setInterception( Reference
<XFrame
>(pTextWin
->getFrame(), UNO_QUERY_THROW
) );
2450 pHelpListener
->SetChangeHdl( LINK( this, SfxHelpWindow_Impl
, ChangeHdl
) );
2454 SfxHelpWindow_Impl::~SfxHelpWindow_Impl()
2459 void SfxHelpWindow_Impl::dispose()
2463 pTextWin
->CloseFrame();
2464 pTextWin
.disposeAndClear();
2466 m_xHelpTextXWindow
->dispose();
2467 m_xHelpTextXWindow
.clear();
2468 m_xHelpTextWindow
.reset();
2469 m_xHelpPaneWindow
.reset();
2470 m_xContainer
.reset();
2473 ResizableDockingWindow::dispose();
2476 bool SfxHelpWindow_Impl::PreNotify( NotifyEvent
& rNEvt
)
2478 bool bHandled
= false;
2479 if ( rNEvt
.GetType() == NotifyEventType::KEYINPUT
)
2481 // Backward == <ALT><LEFT> or <BACKSPACE> Forward == <ALT><RIGHT>
2482 const vcl::KeyCode
& rKeyCode
= rNEvt
.GetKeyEvent()->GetKeyCode();
2483 sal_uInt16 nKey
= rKeyCode
.GetCode();
2484 if ( ( rKeyCode
.IsMod2() && ( KEY_LEFT
== nKey
|| KEY_RIGHT
== nKey
) ) ||
2485 ( !rKeyCode
.GetModifier() && KEY_BACKSPACE
== nKey
&& !xIndexWin
->HasFocusOnEdit() ) )
2487 DoAction( rKeyCode
.GetCode() == KEY_RIGHT
? u
"forward" : u
"backward" );
2490 else if ( rKeyCode
.IsMod1() && ( KEY_F4
== nKey
|| KEY_W
== nKey
) )
2492 // <CTRL><F4> or <CTRL><W> -> close top frame
2497 return bHandled
|| Window::PreNotify( rNEvt
);
2500 void SfxHelpWindow_Impl::setContainerWindow( const Reference
< css::awt::XWindow
>& xWin
)
2506 VclPtr
<vcl::Window
> pScreenWin
= VCLUnoHelper::GetWindow(xWindow
);
2507 if (aWinSize
.Width() && aWinSize
.Height())
2508 pScreenWin
->SetPosSizePixel(Point(aWinPos
), aWinSize
);
2510 pScreenWin
->SetPosPixel(Point(aWinPos
));
2514 void SfxHelpWindow_Impl::SetFactory( const OUString
& rFactory
)
2516 xIndexWin
->SetFactory( rFactory
, true );
2519 void SfxHelpWindow_Impl::SetHelpURL( std::u16string_view rURL
)
2521 INetURLObject
aObj( rURL
);
2522 if ( aObj
.GetProtocol() == INetProtocol::VndSunStarHelp
)
2523 SetFactory( aObj
.GetHost() );
2526 void SfxHelpWindow_Impl::DoAction(std::u16string_view rActionId
)
2528 if (rActionId
== u
"index")
2532 pTextWin
->ToggleIndex( bIndex
);
2534 else if (rActionId
== u
"start")
2538 else if (rActionId
== u
"backward" || rActionId
== u
"forward")
2541 aURL
.Complete
= ".uno:Backward";
2542 if (rActionId
== u
"forward")
2543 aURL
.Complete
= ".uno:Forward";
2544 Reference
< util::XURLTransformer
> xTrans( util::URLTransformer::create( ::comphelper::getProcessComponentContext() ) );
2545 xTrans
->parseStrict(aURL
);
2546 pHelpInterceptor
->dispatch( aURL
, Sequence
< PropertyValue
>() );
2548 else if (rActionId
== u
"searchdialog")
2550 pTextWin
->DoSearch();
2552 else if (rActionId
== u
"print" || rActionId
== u
"sourceview" || rActionId
== u
"copy" || rActionId
== u
"selectionmode")
2554 Reference
< XDispatchProvider
> xProv
= pTextWin
->getFrame();
2558 if (rActionId
== u
"print")
2559 aURL
.Complete
= ".uno:Print";
2560 else if (rActionId
== u
"sourceview")
2561 aURL
.Complete
= ".uno:SourceView";
2562 else if (rActionId
== u
"copy")
2563 aURL
.Complete
= ".uno:Copy";
2564 else // rActionId == "selectionmode"
2565 aURL
.Complete
= ".uno:SelectTextMode";
2566 Reference
< util::XURLTransformer
> xTrans( util::URLTransformer::create( ::comphelper::getProcessComponentContext() ) );
2567 xTrans
->parseStrict(aURL
);
2568 Reference
< XDispatch
> xDisp
= xProv
->queryDispatch( aURL
, OUString(), 0 );
2570 xDisp
->dispatch( aURL
, Sequence
< PropertyValue
>() );
2573 else if (rActionId
== u
"bookmarks")
2575 OUString aURL
= pHelpInterceptor
->GetCurrentURL();
2576 if ( !aURL
.isEmpty() )
2580 Content
aCnt( aURL
, Reference
< css::ucb::XCommandEnvironment
>(), comphelper::getProcessComponentContext() );
2581 css::uno::Reference
< css::beans::XPropertySetInfo
> xInfo
= aCnt
.getProperties();
2582 if ( xInfo
->hasPropertyByName( PROPERTY_TITLE
) )
2584 css::uno::Any aAny
= aCnt
.getPropertyValue( PROPERTY_TITLE
);
2586 if ( aAny
>>= aValue
)
2588 SfxAddHelpBookmarkDialog_Impl
aDlg(GetFrameWeld(), false);
2589 aDlg
.SetTitle(aValue
);
2590 if (aDlg
.run() == RET_OK
)
2592 xIndexWin
->AddBookmarks( aDlg
.GetTitle(), aURL
);
2599 TOOLS_WARN_EXCEPTION( "sfx.appl", "SfxHelpWindow_Impl::DoAction(): unexpected exception" );
2605 void SfxHelpWindow_Impl::CloseWindow()
2609 // search for top frame
2610 Reference
< XFramesSupplier
> xCreator
= getTextFrame()->getCreator();
2611 while ( xCreator
.is() && !xCreator
->isTop() )
2613 xCreator
= xCreator
->getCreator();
2616 // when found, close it
2617 if ( xCreator
.is() && xCreator
->isTop() )
2619 Reference
< XCloseable
> xCloser( xCreator
, UNO_QUERY
);
2621 xCloser
->close( false );
2624 catch( Exception
const & )
2626 TOOLS_WARN_EXCEPTION( "sfx.appl", "SfxHelpWindow_Impl::CloseWindow()" );
2631 void SfxHelpWindow_Impl::UpdateToolbox()
2633 pTextWin
->GetToolBox().set_item_sensitive(u
"backward"_ustr
, pHelpInterceptor
->HasHistoryPred());
2634 pTextWin
->GetToolBox().set_item_sensitive(u
"forward"_ustr
, pHelpInterceptor
->HasHistorySucc());
2638 bool SfxHelpWindow_Impl::HasHistoryPredecessor() const
2640 return pHelpInterceptor
->HasHistoryPred();
2644 bool SfxHelpWindow_Impl::HasHistorySuccessor() const
2646 return pHelpInterceptor
->HasHistorySucc();
2649 // class SfxAddHelpBookmarkDialog_Impl -----------------------------------
2651 SfxAddHelpBookmarkDialog_Impl::SfxAddHelpBookmarkDialog_Impl(weld::Widget
* pParent
, bool bRename
)
2652 : GenericDialogController(pParent
, u
"sfx/ui/bookmarkdialog.ui"_ustr
, u
"BookmarkDialog"_ustr
)
2653 , m_xTitleED(m_xBuilder
->weld_entry(u
"entry"_ustr
))
2654 , m_xAltTitle(m_xBuilder
->weld_label(u
"alttitle"_ustr
))
2657 m_xDialog
->set_title(m_xAltTitle
->get_label());
2660 void SfxAddHelpBookmarkDialog_Impl::SetTitle(const OUString
& rTitle
)
2662 m_xTitleED
->set_text(rTitle
);
2663 m_xTitleED
->select_region(0, -1);
2666 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */