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
:
480 aAutoCompleteIdle
.Start();
485 IMPL_LINK(IndexTabPage_Impl
, KeyInputHdl
, const KeyEvent
&, rKEvt
, bool)
487 const vcl::KeyCode
& rKCode
= rKEvt
.GetKeyCode();
488 if (rKCode
.GetModifier()) // only with no modifiers held
491 sal_uInt16 nCode
= rKCode
.GetCode();
493 if (nCode
== KEY_UP
|| nCode
== KEY_PAGEUP
||
494 nCode
== KEY_DOWN
|| nCode
== KEY_PAGEDOWN
)
496 // disable_notify_events();
497 sal_Int32 nIndex
= m_xIndexList
->get_selected_index();
498 sal_Int32 nOrigIndex
= nIndex
;
499 sal_Int32 nCount
= m_xIndexList
->n_children();
502 m_xIndexList
->set_cursor(0);
503 m_xIndexList
->select(0);
504 m_xIndexEntry
->set_text(m_xIndexList
->get_selected_text());
510 else if (nCode
== KEY_DOWN
)
512 else if (nCode
== KEY_PAGEUP
)
514 int nVisRows
= nAllHeight
/ nRowHeight
;
517 else if (nCode
== KEY_PAGEDOWN
)
519 int nVisRows
= nAllHeight
/ nRowHeight
;
525 if (nIndex
>= nCount
)
528 if (nIndex
!= nOrigIndex
)
530 m_xIndexList
->set_cursor(nIndex
);
531 m_xIndexList
->select(nIndex
);
532 m_xIndexEntry
->set_text(m_xIndexList
->get_selected_text());
535 // m_xIndexList->grab_focus();
536 // g_signal_emit_by_name(pWidget, "key-press-event", pEvent, &ret);
537 // m_xIndexEntry->set_text(m_xIndexList->get_selected_text());
538 // m_xIndexEntry->grab_focus();
540 m_xIndexEntry
->select_region(0, -1);
541 // enable_notify_events();
542 // m_bTreeChange = true;
543 // m_pEntry->fire_signal_changed();
544 // m_bTreeChange = false;
548 nLastCharCode
= nCode
;
552 IndexTabPage_Impl::~IndexTabPage_Impl()
559 typedef std::unordered_map
< OUString
, int > KeywordInfo
;
562 void IndexTabPage_Impl::InitializeIndex()
564 weld::WaitObject
aWaitCursor(m_pIdxWin
->GetFrameWeld());
566 // By now more than 256 equal entries are not allowed
567 sal_Unicode append
[256];
568 for(sal_Unicode
& k
: append
)
571 sfx2::KeywordInfo aInfo
;
572 m_xIndexList
->freeze();
576 OUStringBuffer
aURL(HELP_URL
);
577 aURL
.append(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 OUStringBuffer
aData( 128 ); // Capacity of up to 128 characters
602 sfx2::KeywordInfo::iterator it
;
604 for ( int i
= 0; i
< aKeywordList
.getLength(); ++i
)
606 // abi: Do not copy, but use references
607 const OUString
& aKeywordPair
= aKeywordList
[i
];
608 DBG_ASSERT( !aKeywordPair
.isEmpty(), "invalid help index" );
609 const css::uno::Sequence
< OUString
>& aRefList
= aKeywordRefList
[i
];
610 const css::uno::Sequence
< OUString
>& aAnchorList
= aAnchorRefList
[i
];
611 const css::uno::Sequence
< OUString
>& aTitleList
= aTitleRefList
[i
];
613 DBG_ASSERT( aRefList
.getLength() == aAnchorList
.getLength(),"reference list and title list of different length" );
615 ndx
= aKeywordPair
.indexOf( ';' );
616 const bool insert
= ndx
!= -1;
622 aTempString
= aKeywordPair
.copy( 0, ndx
);
623 if ( aIndex
!= aTempString
)
625 aIndex
= aTempString
;
626 it
= aInfo
.emplace(aTempString
, 0).first
;
627 sId
= OUString::number(reinterpret_cast<sal_Int64
>(new IndexEntry_Impl(OUString(), false)));
628 if ( (tmp
= it
->second
++) != 0)
629 m_xIndexList
->append(
630 sId
, aTempString
+ std::u16string_view(append
, tmp
));
632 m_xIndexList
->append(sId
, aTempString
);
638 sal_uInt32 nRefListLen
= aRefList
.getLength();
640 DBG_ASSERT( aAnchorList
.hasElements(), "*IndexTabPage_Impl::InitializeIndex(): AnchorList is empty!" );
641 DBG_ASSERT( nRefListLen
, "*IndexTabPage_Impl::InitializeIndex(): RefList is empty!" );
643 if ( aAnchorList
.hasElements() && nRefListLen
)
645 if ( aAnchorList
[0].getLength() > 0 )
647 aData
.append( aRefList
[0] ).append( '#' ).append( aAnchorList
[0] );
648 sId
= OUString::number(reinterpret_cast<sal_Int64
>(new IndexEntry_Impl(aData
.makeStringAndClear(), insert
)));
651 sId
= OUString::number(reinterpret_cast<sal_Int64
>(new IndexEntry_Impl(aRefList
[0], insert
)));
654 // Assume the token is trimmed
655 it
= aInfo
.emplace(aKeywordPair
, 0).first
;
656 if ((tmp
= it
->second
++) != 0)
657 m_xIndexList
->append(sId
, aKeywordPair
+ std::u16string_view(append
, tmp
));
659 m_xIndexList
->append(sId
, aKeywordPair
);
661 for ( sal_uInt32 j
= 1; j
< nRefListLen
; ++j
)
664 .append( aKeywordPair
)
668 .append( aTitleList
[j
] );
670 aTempString
= aData
.makeStringAndClear();
672 if ( aAnchorList
[j
].getLength() > 0 )
674 aData
.append( aRefList
[j
] ).append( '#' ).append( aAnchorList
[j
] );
675 sId
= OUString::number(reinterpret_cast<sal_Int64
>(new IndexEntry_Impl(aData
.makeStringAndClear(), insert
)));
678 sId
= OUString::number(reinterpret_cast<sal_Int64
>(new IndexEntry_Impl(aRefList
[j
], insert
)));
680 it
= aInfo
.emplace(aTempString
, 0).first
;
681 if ( (tmp
= it
->second
++) != 0 )
682 m_xIndexList
->append(
683 sId
, aTempString
+ std::u16string_view(append
, tmp
));
685 m_xIndexList
->append(sId
, aTempString
);
693 TOOLS_WARN_EXCEPTION( "sfx.appl", "IndexTabPage_Impl::InitializeIndex(): unexpected exception" );
696 m_xIndexList
->thaw();
698 if ( !sKeyword
.isEmpty() )
699 aKeywordLink
.Call( *this );
702 void IndexTabPage_Impl::ClearIndex()
704 const sal_Int32 nCount
= m_xIndexList
->n_children();
705 for ( sal_Int32 i
= 0; i
< nCount
; ++i
)
706 delete reinterpret_cast<IndexEntry_Impl
*>(m_xIndexList
->get_id(i
).toInt64());
707 m_xIndexList
->clear();
710 IMPL_LINK_NOARG(IndexTabPage_Impl
, OpenHdl
, weld::Button
&, void)
712 aDoubleClickHdl
.Call(nullptr);
715 IMPL_LINK_NOARG(IndexTabPage_Impl
, ActivateHdl
, weld::Entry
&, bool)
717 aDoubleClickHdl
.Call(nullptr);
721 IMPL_LINK_NOARG(IndexTabPage_Impl
, DoubleClickHdl
, weld::TreeView
&, bool)
723 aDoubleClickHdl
.Call(nullptr);
727 IMPL_LINK_NOARG(IndexTabPage_Impl
, IdleHdl
, Timer
*, void)
732 int IndexTabPage_Impl::starts_with(const OUString
& rStr
, int nStartRow
, bool bCaseSensitive
)
734 const vcl::I18nHelper
& rI18nHelper
= Application::GetSettings().GetUILocaleI18nHelper();
736 int nRet
= nStartRow
;
737 int nCount
= m_xIndexList
->n_children();
738 while (nRet
< nCount
)
740 OUString
aStr(m_xIndexList
->get_text(nRet
));
741 const bool bMatch
= !bCaseSensitive
? rI18nHelper
.MatchString(rStr
, aStr
) : aStr
.startsWith(rStr
);
750 IMPL_LINK_NOARG(IndexTabPage_Impl
, AutoCompleteHdl
, Timer
*, void)
752 OUString aStartText
= m_xIndexEntry
->get_text();
753 int nStartPos
, nEndPos
;
754 m_xIndexEntry
->get_selection_bounds(nStartPos
, nEndPos
);
755 int nMaxSelection
= std::max(nStartPos
, nEndPos
);
756 if (nMaxSelection
!= aStartText
.getLength())
759 int nActive
= m_xIndexList
->get_selected_index();
760 int nStart
= nActive
;
765 // Try match case insensitive from current position
766 int nPos
= starts_with(aStartText
, nStart
, false);
767 if (nPos
== -1 && nStart
!= 0)
769 // Try match case insensitive, but from start
770 nPos
= starts_with(aStartText
, 0, false);
775 // Try match case sensitive from current position
776 nPos
= starts_with(aStartText
, nStart
, true);
777 if (nPos
== -1 && nStart
!= 0)
779 // Try match case sensitive, but from start
780 nPos
= starts_with(aStartText
, 0, true);
786 m_xIndexList
->set_cursor(nPos
);
787 m_xIndexList
->select(nPos
);
788 OUString aText
= m_xIndexList
->get_text(nPos
);
789 if (aText
!= aStartText
)
790 m_xIndexEntry
->set_text(aText
);
791 m_xIndexEntry
->select_region(aText
.getLength(), aStartText
.getLength());
795 IMPL_LINK( IndexTabPage_Impl
, TimeoutHdl
, Timer
*, pTimer
, void)
797 if(&aKeywordTimer
== pTimer
&& !sKeyword
.isEmpty())
798 aKeywordLink
.Call(*this);
801 void IndexTabPage_Impl::Activate()
806 aFactoryIdle
.Start();
810 void IndexTabPage_Impl::SetDoubleClickHdl(const Link
<LinkParamNone
*, void>& rLink
)
812 aDoubleClickHdl
= rLink
;
815 void IndexTabPage_Impl::SetFactory( const OUString
& rFactory
)
817 OUString
sNewFactory( rFactory
);
818 DBG_ASSERT( !sNewFactory
.isEmpty(), "empty factory" );
819 bool bValid
= m_pIdxWin
->IsValidFactory( rFactory
);
821 if ( sFactory
.isEmpty() && !bValid
)
823 sNewFactory
= SfxHelp::GetDefaultHelpModule();
827 if ( sNewFactory
!= sFactory
&& bValid
)
829 sFactory
= sNewFactory
;
832 aFactoryIdle
.Start();
836 OUString
IndexTabPage_Impl::GetSelectedEntry() const
839 IndexEntry_Impl
* pEntry
= reinterpret_cast<IndexEntry_Impl
*>(m_xIndexList
->get_id(m_xIndexList
->find_text(m_xIndexEntry
->get_text())).toInt64());
841 aRet
= pEntry
->m_aURL
;
845 void IndexTabPage_Impl::SetKeyword( const OUString
& rKeyword
)
849 if (m_xIndexList
->n_children() > 0)
850 aKeywordTimer
.Start();
851 else if ( !bIsActivated
)
852 aFactoryIdle
.Start();
856 bool IndexTabPage_Impl::HasKeyword() const
859 if ( !sKeyword
.isEmpty() )
861 sal_Int32 nPos
= m_xIndexList
->find_text( sKeyword
);
869 bool IndexTabPage_Impl::HasKeywordIgnoreCase()
872 if ( !sKeyword
.isEmpty() )
874 sal_Int32 nEntries
= m_xIndexList
->n_children();
875 const vcl::I18nHelper
& rI18nHelper
= Application::GetSettings().GetLocaleI18nHelper();
876 for ( sal_Int32 n
= 0; n
< nEntries
; n
++)
878 const OUString sIndexItem
{m_xIndexList
->get_text(n
)};
879 if (rI18nHelper
.MatchString( sIndexItem
, sKeyword
))
881 sKeyword
= sIndexItem
;
890 void IndexTabPage_Impl::OpenKeyword()
892 if ( !sKeyword
.isEmpty() )
894 m_xIndexEntry
->set_text(sKeyword
);
895 aDoubleClickHdl
.Call(nullptr);
900 IMPL_LINK_NOARG(SearchTabPage_Impl
, ActivateHdl
, weld::ComboBox
&, bool)
906 // class SearchTabPage_Impl ----------------------------------------------
908 SearchTabPage_Impl::SearchTabPage_Impl(weld::Widget
* pParent
, SfxHelpIndexWindow_Impl
* pIdxWin
)
909 : HelpTabPage_Impl(pParent
, pIdxWin
, "HelpSearchPage",
910 "sfx/ui/helpsearchpage.ui")
911 , m_xSearchED(m_xBuilder
->weld_combo_box("search"))
912 , m_xSearchBtn(m_xBuilder
->weld_button("find"))
913 , m_xFullWordsCB(m_xBuilder
->weld_check_button("completewords"))
914 , m_xScopeCB(m_xBuilder
->weld_check_button("headings"))
915 , m_xResultsLB(m_xBuilder
->weld_tree_view("results"))
916 , m_xOpenBtn(m_xBuilder
->weld_button("display"))
917 , xBreakIterator(vcl::unohelper::CreateBreakIterator())
919 m_xResultsLB
->set_size_request(m_xResultsLB
->get_approximate_digit_width() * 30,
920 m_xResultsLB
->get_height_rows(15));
922 m_xSearchBtn
->connect_clicked(LINK(this, SearchTabPage_Impl
, ClickHdl
));
923 m_xSearchED
->connect_changed(LINK(this, SearchTabPage_Impl
, ModifyHdl
));
924 m_xSearchED
->connect_entry_activate(LINK(this, SearchTabPage_Impl
, ActivateHdl
));
925 m_xOpenBtn
->connect_clicked(LINK(this, SearchTabPage_Impl
, OpenHdl
));
926 m_xResultsLB
->connect_row_activated(LINK(this, SearchTabPage_Impl
, DoubleClickHdl
));
928 SvtViewOptions
aViewOpt( EViewType::TabPage
, CONFIGNAME_SEARCHPAGE
);
929 if ( aViewOpt
.Exists() )
932 Any aUserItem
= aViewOpt
.GetUserItem( USERITEM_NAME
);
933 if ( aUserItem
>>= aUserData
)
936 bool bChecked
= aUserData
.getToken(0, ';', nIdx
).toInt32() == 1;
937 m_xFullWordsCB
->set_active(bChecked
);
938 bChecked
= aUserData
.getToken(0, ';', nIdx
).toInt32() == 1;
939 m_xScopeCB
->set_active(bChecked
);
943 m_xSearchED
->append_text( INetURLObject::decode(
944 aUserData
.getToken(0, ';', nIdx
),
945 INetURLObject::DecodeMechanism::WithCharset
) );
950 ModifyHdl(*m_xSearchED
);
953 SearchTabPage_Impl::~SearchTabPage_Impl()
955 SvtViewOptions
aViewOpt( EViewType::TabPage
, CONFIGNAME_SEARCHPAGE
);
956 OUStringBuffer aUserData
=
957 OUString::number(m_xFullWordsCB
->get_active() ? 1 : 0) +
959 OUString::number(m_xScopeCB
->get_active() ? 1 : 0);
960 sal_Int32 nCount
= std::min(m_xSearchED
->get_count(), 10); // save only 10 entries
962 for ( sal_Int32 i
= 0; i
< nCount
; ++i
)
964 aUserData
.append(";" +
965 INetURLObject::encode(
966 m_xSearchED
->get_text(i
),
967 INetURLObject::PART_UNO_PARAM_VALUE
,
968 INetURLObject::EncodeMechanism::All
));
971 Any aUserItem
= makeAny( aUserData
.makeStringAndClear() );
972 aViewOpt
.SetUserItem( USERITEM_NAME
, aUserItem
);
975 m_xSearchBtn
.reset();
976 m_xFullWordsCB
.reset();
978 m_xResultsLB
.reset();
982 void SearchTabPage_Impl::ClearSearchResults()
984 m_xResultsLB
->clear();
987 void SearchTabPage_Impl::RememberSearchText( const OUString
& rSearchText
)
989 for (sal_Int32 i
= 0, nEntryCount
= m_xSearchED
->get_count(); i
< nEntryCount
; ++i
)
991 if (rSearchText
== m_xSearchED
->get_text(i
))
993 m_xSearchED
->remove(i
);
998 m_xSearchED
->insert_text(0, rSearchText
);
1001 IMPL_LINK_NOARG(SearchTabPage_Impl
, ClickHdl
, weld::Button
&, void)
1006 void SearchTabPage_Impl::Search()
1008 OUString aSearchText
= comphelper::string::strip(m_xSearchED
->get_active_text(), ' ');
1009 if ( aSearchText
.isEmpty() )
1012 std::unique_ptr
<weld::WaitObject
> xWaitCursor(new weld::WaitObject(m_pIdxWin
->GetFrameWeld()));
1013 ClearSearchResults();
1014 RememberSearchText( aSearchText
);
1015 OUStringBuffer
aSearchURL(HELP_URL
);
1016 aSearchURL
.append(aFactory
);
1017 aSearchURL
.append(HELP_SEARCH_TAG
);
1018 if (!m_xFullWordsCB
->get_active())
1019 aSearchText
= sfx2::PrepareSearchString( aSearchText
, xBreakIterator
, true );
1020 aSearchURL
.append(aSearchText
);
1021 AppendConfigToken(aSearchURL
, false);
1022 if (m_xScopeCB
->get_active())
1023 aSearchURL
.append("&Scope=Heading");
1024 std::vector
< OUString
> aFactories
= SfxContentHelper::GetResultSet(aSearchURL
.makeStringAndClear());
1025 for (const OUString
& rRow
: aFactories
)
1028 OUString aTitle
= rRow
.getToken(0, '\t', nIdx
);
1029 OUString
sURL(rRow
.getToken(1, '\t', nIdx
));
1030 m_xResultsLB
->append(sURL
, aTitle
);
1032 xWaitCursor
.reset();
1034 if ( aFactories
.empty() )
1036 std::unique_ptr
<weld::MessageDialog
> xBox(Application::CreateMessageDialog(m_xContainer
.get(),
1037 VclMessageType::Info
, VclButtonsType::Ok
,
1038 SfxResId(STR_INFO_NOSEARCHRESULTS
)));
1043 IMPL_LINK_NOARG(SearchTabPage_Impl
, OpenHdl
, weld::Button
&, void)
1045 aDoubleClickHdl
.Call(nullptr);
1048 IMPL_LINK(SearchTabPage_Impl
, ModifyHdl
, weld::ComboBox
&, rComboBox
, void)
1050 OUString aSearchText
= comphelper::string::strip(m_xSearchED
->get_active_text(), ' ');
1051 m_xSearchBtn
->set_sensitive(!aSearchText
.isEmpty());
1053 if (rComboBox
.changed_by_direct_pick())
1057 IMPL_LINK_NOARG(SearchTabPage_Impl
, DoubleClickHdl
, weld::TreeView
&, bool)
1059 aDoubleClickHdl
.Call(nullptr);
1063 void SearchTabPage_Impl::SetDoubleClickHdl(const Link
<LinkParamNone
*, void>& rLink
)
1065 aDoubleClickHdl
= rLink
;
1068 OUString
SearchTabPage_Impl::GetSelectedEntry() const
1070 return m_xResultsLB
->get_selected_id();
1073 void SearchTabPage_Impl::ClearPage()
1075 ClearSearchResults();
1076 m_xSearchED
->set_entry_text(OUString());
1079 bool SearchTabPage_Impl::OpenKeyword( const OUString
& rKeyword
)
1082 m_xSearchED
->set_entry_text(rKeyword
);
1084 if (m_xResultsLB
->n_children() > 0)
1086 // found keyword -> open it
1087 m_xResultsLB
->select(0);
1088 OpenHdl(*m_xOpenBtn
);
1094 // class BookmarksTabPage_Impl -------------------------------------------
1096 void BookmarksTabPage_Impl::DoAction(std::string_view rAction
)
1098 if (rAction
== "display")
1099 aDoubleClickHdl
.Call(nullptr);
1100 else if (rAction
== "rename")
1102 sal_Int32 nPos
= m_xBookmarksBox
->get_selected_index();
1105 SfxAddHelpBookmarkDialog_Impl
aDlg(m_xBookmarksBox
.get(), true);
1106 aDlg
.SetTitle(m_xBookmarksBox
->get_text(nPos
));
1107 if (aDlg
.run() == RET_OK
)
1109 OUString sURL
= m_xBookmarksBox
->get_id(nPos
);
1110 m_xBookmarksBox
->remove(nPos
);
1111 m_xBookmarksBox
->append(sURL
, aDlg
.GetTitle(), SvFileInformationManager::GetImageId(INetURLObject(IMAGE_URL
+INetURLObject(sURL
).GetHost())));
1112 m_xBookmarksBox
->select(m_xBookmarksBox
->n_children() - 1);
1116 else if (rAction
== "delete")
1118 sal_Int32 nPos
= m_xBookmarksBox
->get_selected_index();
1121 m_xBookmarksBox
->remove(nPos
);
1122 const sal_Int32 nCount
= m_xBookmarksBox
->n_children();
1127 m_xBookmarksBox
->select(nPos
);
1133 IMPL_LINK(BookmarksTabPage_Impl
, CommandHdl
, const CommandEvent
&, rCEvt
, bool)
1135 if (rCEvt
.GetCommand() != CommandEventId::ContextMenu
)
1138 std::unique_ptr
<weld::Builder
> xBuilder(Application::CreateBuilder(m_xBookmarksBox
.get(), "sfx/ui/bookmarkmenu.ui"));
1139 std::unique_ptr
<weld::Menu
> xMenu
= xBuilder
->weld_menu("menu");
1141 OString sIdent
= xMenu
->popup_at_rect(m_xBookmarksBox
.get(), ::tools::Rectangle(rCEvt
.GetMousePosPixel(), Size(1,1)));
1142 if (!sIdent
.isEmpty())
1147 IMPL_LINK(BookmarksTabPage_Impl
, KeyInputHdl
, const KeyEvent
&, rKEvt
, bool)
1149 bool bHandled
= false;
1150 sal_uInt16 nCode
= rKEvt
.GetKeyCode().GetCode();
1151 if (KEY_DELETE
== nCode
&& m_xBookmarksBox
->n_children() > 0)
1159 // class BookmarksTabPage_Impl -------------------------------------------
1160 BookmarksTabPage_Impl::BookmarksTabPage_Impl(weld::Widget
* pParent
, SfxHelpIndexWindow_Impl
* _pIdxWin
)
1161 : HelpTabPage_Impl(pParent
, _pIdxWin
, "HelpBookmarkPage",
1162 "sfx/ui/helpbookmarkpage.ui")
1163 , m_xBookmarksBox(m_xBuilder
->weld_tree_view("bookmarks"))
1164 , m_xBookmarksPB(m_xBuilder
->weld_button("display"))
1166 m_xBookmarksBox
->set_size_request(m_xBookmarksBox
->get_approximate_digit_width() * 30,
1167 m_xBookmarksBox
->get_height_rows(20));
1169 m_xBookmarksPB
->connect_clicked( LINK(this, BookmarksTabPage_Impl
, OpenHdl
));
1170 m_xBookmarksBox
->connect_row_activated(LINK(this, BookmarksTabPage_Impl
, DoubleClickHdl
));
1171 m_xBookmarksBox
->connect_popup_menu(LINK(this, BookmarksTabPage_Impl
, CommandHdl
));
1172 m_xBookmarksBox
->connect_key_press(LINK(this, BookmarksTabPage_Impl
, KeyInputHdl
));
1174 // load bookmarks from configuration
1175 const std::vector
< SvtHistoryOptions::HistoryItem
> aBookmarkSeq
= SvtHistoryOptions::GetList( EHistoryType::HelpBookmarks
);
1176 for ( const auto& rBookmark
: aBookmarkSeq
)
1178 AddBookmarks( rBookmark
.sTitle
, rBookmark
.sURL
);
1182 BookmarksTabPage_Impl::~BookmarksTabPage_Impl()
1184 // save bookmarks to configuration
1185 SvtHistoryOptions::Clear( EHistoryType::HelpBookmarks
);
1186 const sal_Int32 nCount
= m_xBookmarksBox
->n_children();
1187 for (sal_Int32 i
= 0; i
< nCount
; ++i
)
1188 SvtHistoryOptions::AppendItem(EHistoryType::HelpBookmarks
, m_xBookmarksBox
->get_id(i
), "", m_xBookmarksBox
->get_text(i
), std::nullopt
);
1190 m_xBookmarksBox
.reset();
1191 m_xBookmarksPB
.reset();
1194 IMPL_LINK_NOARG(BookmarksTabPage_Impl
, OpenHdl
, weld::Button
&, void)
1196 aDoubleClickHdl
.Call(nullptr);
1199 IMPL_LINK_NOARG(BookmarksTabPage_Impl
, DoubleClickHdl
, weld::TreeView
&, bool)
1201 aDoubleClickHdl
.Call(nullptr);
1205 void BookmarksTabPage_Impl::SetDoubleClickHdl(const Link
<LinkParamNone
*, void>& rLink
)
1207 aDoubleClickHdl
= rLink
;
1210 OUString
BookmarksTabPage_Impl::GetSelectedEntry() const
1212 return m_xBookmarksBox
->get_selected_id();
1215 void BookmarksTabPage_Impl::AddBookmarks(const OUString
& rTitle
, const OUString
& rURL
)
1217 const OUString aImageURL
{IMAGE_URL
+ INetURLObject(rURL
).GetHost()};
1218 m_xBookmarksBox
->append(rURL
, rTitle
, SvFileInformationManager::GetImageId(INetURLObject(aImageURL
)));
1221 OUString
SfxHelpWindow_Impl::buildHelpURL(std::u16string_view sFactory
,
1222 std::u16string_view sContent
,
1223 std::u16string_view sAnchor
)
1225 OUStringBuffer
sHelpURL(256);
1226 sHelpURL
.append(HELP_URL
);
1227 sHelpURL
.append(sFactory
);
1228 sHelpURL
.append(sContent
);
1229 AppendConfigToken(sHelpURL
, true/*bUseQuestionMark*/);
1230 if (!sAnchor
.empty())
1231 sHelpURL
.append(sAnchor
);
1232 return sHelpURL
.makeStringAndClear();
1235 void SfxHelpWindow_Impl::loadHelpContent(const OUString
& sHelpURL
, bool bAddToHistory
)
1237 Reference
< XComponentLoader
> xLoader(getTextFrame(), UNO_QUERY
);
1241 // If a print job runs do not open a new page
1242 Reference
< XFrame2
> xTextFrame
= pTextWin
->getFrame();
1243 Reference
< XController
> xTextController
;
1244 if (xTextFrame
.is())
1245 xTextController
= xTextFrame
->getController ();
1246 if ( xTextController
.is() && !xTextController
->suspend( true ) )
1248 xTextController
->suspend( false );
1252 // save url to history
1254 pHelpInterceptor
->addURL(sHelpURL
);
1258 bool bSuccess
= false;
1259 // TODO implement locale fallback ... see below while(true)
1263 Reference
< XComponent
> xContent
= xLoader
->loadComponentFromURL(sHelpURL
, "_self", 0, Sequence
< PropertyValue
>());
1269 catch(const RuntimeException
&)
1271 catch(const Exception
&)
1274 /* TODO try next locale ...
1275 no further locale available? => break loop and show error page
1278 openDone(sHelpURL
, bSuccess
);
1283 IMPL_LINK(SfxHelpIndexWindow_Impl
, ActivatePageHdl
, const OString
&, rPage
, void)
1285 GetPage(rPage
)->Activate();
1288 SfxHelpIndexWindow_Impl::SfxHelpIndexWindow_Impl(SfxHelpWindow_Impl
* _pParent
, weld::Container
* pContainer
)
1289 : m_xBuilder(Application::CreateBuilder(pContainer
, "sfx/ui/helpcontrol.ui"))
1290 , m_xContainer(m_xBuilder
->weld_container("HelpControl"))
1291 , m_xActiveLB(m_xBuilder
->weld_combo_box("active"))
1292 , m_xTabCtrl(m_xBuilder
->weld_notebook("tabcontrol"))
1293 , aIdle("sfx2 appl SfxHelpIndexWindow_Impl")
1294 , aIndexKeywordLink(LINK(this, SfxHelpIndexWindow_Impl
, KeywordHdl
))
1295 , pParentWin(_pParent
)
1296 , bIsInitDone(false)
1304 OString
sPageId("index");
1305 SvtViewOptions
aViewOpt( EViewType::TabDialog
, CONFIGNAME_INDEXWIN
);
1306 if ( aViewOpt
.Exists() )
1307 sPageId
= aViewOpt
.GetPageID();
1308 m_xTabCtrl
->set_current_page(sPageId
);
1309 ActivatePageHdl(sPageId
);
1310 m_xActiveLB
->connect_changed(LINK(this, SfxHelpIndexWindow_Impl
, SelectHdl
));
1312 m_xTabCtrl
->connect_enter_page(LINK(this, SfxHelpIndexWindow_Impl
, ActivatePageHdl
));
1314 aIdle
.SetInvokeHandler( LINK( this, SfxHelpIndexWindow_Impl
, InitHdl
) );
1317 m_xContainer
->show();
1320 SfxHelpIndexWindow_Impl::~SfxHelpIndexWindow_Impl()
1322 SvtViewOptions
aViewOpt(EViewType::TabDialog
, CONFIGNAME_INDEXWIN
);
1323 aViewOpt
.SetPageID(m_xTabCtrl
->get_current_page_ident());
1331 void SfxHelpIndexWindow_Impl::Initialize()
1333 OUStringBuffer
aHelpURL(HELP_URL
);
1334 AppendConfigToken(aHelpURL
, true);
1335 std::vector
<OUString
> aFactories
= SfxContentHelper::GetResultSet(aHelpURL
.makeStringAndClear());
1336 for (const OUString
& rRow
: aFactories
)
1339 OUString aTitle
= rRow
.getToken( 0, '\t', nIdx
); // token 0
1340 OUString aURL
= rRow
.getToken( 1, '\t', nIdx
); // token 2
1341 OUString
aFactory(INetURLObject(aURL
).GetHost());
1342 m_xActiveLB
->append(aFactory
, aTitle
);
1345 if (m_xActiveLB
->get_active() == -1)
1349 void SfxHelpIndexWindow_Impl::SetActiveFactory()
1351 DBG_ASSERT( xIPage
, "index page not initialized" );
1352 if (!bIsInitDone
&& !m_xActiveLB
->get_count())
1358 for (sal_Int32 i
= 0, nEntryCount
= m_xActiveLB
->get_count(); i
< nEntryCount
; ++i
)
1360 OUString aFactory
= m_xActiveLB
->get_id(i
);
1361 aFactory
= aFactory
.toAsciiLowerCase();
1362 if (aFactory
== xIPage
->GetFactory())
1364 if (m_xActiveLB
->get_active() != i
)
1366 m_xActiveLB
->set_active(i
);
1367 aSelectFactoryLink
.Call(nullptr);
1374 HelpTabPage_Impl
* SfxHelpIndexWindow_Impl::GetPage(std::string_view rName
)
1376 HelpTabPage_Impl
* pPage
= nullptr;
1378 if (rName
== "contents")
1379 pPage
= GetContentPage();
1380 else if (rName
== "index")
1381 pPage
= GetIndexPage();
1382 else if (rName
== "find")
1383 pPage
= GetSearchPage();
1384 else if (rName
== "bookmarks")
1385 pPage
= GetBookmarksPage();
1387 assert(pPage
&& "SfxHelpIndexWindow_Impl::GetCurrentPage(): no current page");
1392 IMPL_LINK_NOARG(SfxHelpIndexWindow_Impl
, SelectHdl
, weld::ComboBox
&, void)
1397 IMPL_LINK_NOARG(SfxHelpIndexWindow_Impl
, InitHdl
, Timer
*, void)
1402 // now use the timer for selection
1403 aIdle
.SetInvokeHandler( LINK( this, SfxHelpIndexWindow_Impl
, SelectFactoryHdl
) );
1404 aIdle
.SetPriority( TaskPriority::LOWEST
);
1407 IMPL_LINK_NOARG(SfxHelpIndexWindow_Impl
, SelectFactoryHdl
, Timer
*, void)
1409 OUString aFactory
= m_xActiveLB
->get_active_id();
1410 if (!aFactory
.isEmpty())
1412 SetFactory(aFactory
.toAsciiLowerCase(), false);
1413 aSelectFactoryLink
.Call(this);
1417 IMPL_LINK_NOARG(SfxHelpIndexWindow_Impl
, KeywordHdl
, IndexTabPage_Impl
&, void)
1419 // keyword found on index?
1420 bool bIndex
= xIPage
->HasKeyword();
1423 bIndex
= xIPage
->HasKeywordIgnoreCase();
1424 // then set index or search page as current.
1425 OString sPageId
= bIndex
? "index" : "find";
1426 if (sPageId
!= m_xTabCtrl
->get_current_page_ident())
1427 m_xTabCtrl
->set_current_page(sPageId
);
1429 // at last we open the keyword
1431 xIPage
->OpenKeyword();
1432 else if ( !xSPage
->OpenKeyword( sKeyword
) )
1433 pParentWin
->ShowStartPage();
1436 IMPL_LINK_NOARG(SfxHelpIndexWindow_Impl
, IndexTabPageDoubleClickHdl
, LinkParamNone
*, void)
1438 aPageDoubleClickLink
.Call(nullptr);
1441 void SfxHelpIndexWindow_Impl::SetDoubleClickHdl(const Link
<LinkParamNone
*, void>& rLink
)
1443 aPageDoubleClickLink
= rLink
;
1446 IMPL_LINK_NOARG(SfxHelpIndexWindow_Impl
, ContentTabPageDoubleClickHdl
, LinkParamNone
*, void)
1448 aPageDoubleClickLink
.Call(nullptr);
1451 IMPL_LINK_NOARG(SfxHelpIndexWindow_Impl
, TabPageDoubleClickHdl
, LinkParamNone
*, void)
1453 aPageDoubleClickLink
.Call(nullptr);
1456 void SfxHelpIndexWindow_Impl::SetFactory( const OUString
& rFactory
, bool bActive
)
1458 if ( !rFactory
.isEmpty() )
1460 GetIndexPage()->SetFactory( rFactory
);
1461 // the index page made a check if rFactory is valid,
1462 // so the index page always returns a valid factory
1463 GetSearchPage()->SetFactory( GetIndexPage()->GetFactory() );
1469 OUString
SfxHelpIndexWindow_Impl::GetSelectedEntry() const
1473 OString
sName(m_xTabCtrl
->get_current_page_ident());
1475 if (sName
== "contents")
1477 sRet
= xCPage
->GetSelectedEntry();
1479 else if (sName
== "index")
1481 sRet
= xIPage
->GetSelectedEntry();
1483 else if (sName
== "find")
1485 sRet
= xSPage
->GetSelectedEntry();
1487 else if (sName
== "bookmarks")
1489 sRet
= xBPage
->GetSelectedEntry();
1495 void SfxHelpIndexWindow_Impl::AddBookmarks( const OUString
& rTitle
, const OUString
& rURL
)
1497 GetBookmarksPage()->AddBookmarks( rTitle
, rURL
);
1500 bool SfxHelpIndexWindow_Impl::IsValidFactory( std::u16string_view _rFactory
)
1502 bool bValid
= false;
1503 for (sal_Int32 i
= 0, nEntryCount
= m_xActiveLB
->get_count(); i
< nEntryCount
; ++i
)
1505 OUString aFactory
= m_xActiveLB
->get_id(i
);
1506 if (aFactory
== _rFactory
)
1515 void SfxHelpIndexWindow_Impl::ClearSearchPage()
1518 xSPage
->ClearPage();
1521 void SfxHelpIndexWindow_Impl::GrabFocusBack()
1523 OString
sName(m_xTabCtrl
->get_current_page_ident());
1525 if (sName
== "contents" && xCPage
)
1526 xCPage
->SetFocusOnBox();
1527 else if (sName
== "index" && xIPage
)
1528 xIPage
->SetFocusOnBox();
1529 else if (sName
== "find" && xSPage
)
1530 xSPage
->SetFocusOnBox();
1531 else if (sName
== "bookmarks" && xBPage
)
1532 xBPage
->SetFocusOnBox();
1535 bool SfxHelpIndexWindow_Impl::HasFocusOnEdit() const
1538 OString
sName(m_xTabCtrl
->get_current_page_ident());
1539 if (sName
== "index" && xIPage
)
1540 bRet
= xIPage
->HasFocusOnEdit();
1541 else if (sName
== "find" && xSPage
)
1542 bRet
= xSPage
->HasFocusOnEdit();
1546 OUString
SfxHelpIndexWindow_Impl::GetSearchText() const
1549 OString
sName(m_xTabCtrl
->get_current_page_ident());
1550 if (sName
== "find" && xSPage
)
1551 sRet
= xSPage
->GetSearchText();
1555 bool SfxHelpIndexWindow_Impl::IsFullWordSearch() const
1558 OString
sName(m_xTabCtrl
->get_current_page_ident());
1559 if (sName
== "find" && xSPage
)
1560 bRet
= xSPage
->IsFullWordSearch();
1564 void SfxHelpIndexWindow_Impl::OpenKeyword( const OUString
& rKeyword
)
1566 sKeyword
= rKeyword
;
1567 DBG_ASSERT( xIPage
, "invalid index page" );
1568 xIPage
->SetKeyword( sKeyword
);
1571 void SfxHelpIndexWindow_Impl::SelectExecutableEntry()
1573 OString
sName(m_xTabCtrl
->get_current_page_ident());
1574 if (sName
== "index" && xIPage
)
1575 xIPage
->SelectExecutableEntry();
1578 weld::Window
* SfxHelpIndexWindow_Impl::GetFrameWeld() const
1580 return pParentWin
->GetFrameWeld();
1583 // class TextWin_Impl ----------------------------------------------------
1584 TextWin_Impl::TextWin_Impl( vcl::Window
* p
) : DockingWindow( p
, 0 )
1588 bool TextWin_Impl::EventNotify( NotifyEvent
& rNEvt
)
1590 if( ( rNEvt
.GetType() == MouseNotifyEvent::KEYINPUT
) && rNEvt
.GetKeyEvent()->GetKeyCode().GetCode() == KEY_TAB
)
1591 return GetParent()->EventNotify( rNEvt
);
1593 return DockingWindow::EventNotify( rNEvt
);
1597 // remove docking area acceptor from layoutmanager, so it will not layout anything further .-)
1598 static void lcl_disableLayoutOfFrame(const Reference
< XFrame2
>& xFrame
)
1600 xFrame
->setLayoutManager( Reference
< XLayoutManager
>() );
1603 // class SfxHelpTextWindow_Impl ------------------------------------------
1605 SfxHelpTextWindow_Impl::SfxHelpTextWindow_Impl(SfxHelpWindow_Impl
* pHelpWin
, weld::Builder
& rBuilder
, vcl::Window
* pParent
) :
1607 Window( pParent
, WB_CLIPCHILDREN
| WB_TABSTOP
| WB_DIALOGCONTROL
),
1609 xToolBox ( rBuilder
.weld_toolbar("toolbar") ),
1610 xOnStartupCB ( rBuilder
.weld_check_button("checkbutton") ),
1611 xMenu ( rBuilder
.weld_menu("menu") ),
1612 aSelectIdle ( "sfx2 appl SfxHelpTextWindow_Impl Select" ),
1613 aIndexOnImage ( BMP_HELP_TOOLBOX_INDEX_ON
),
1614 aIndexOffImage ( BMP_HELP_TOOLBOX_INDEX_OFF
),
1615 aIndexOnText ( SfxResId( STR_HELP_BUTTON_INDEX_ON
) ),
1616 aIndexOffText ( SfxResId( STR_HELP_BUTTON_INDEX_OFF
) ),
1617 aOnStartupText ( SfxResId( RID_HELP_ONSTARTUP_TEXT
) ),
1618 xHelpWin ( pHelpWin
),
1619 pTextWin ( VclPtr
<TextWin_Impl
>::Create( this ) ),
1621 bIsIndexOn ( false ),
1622 bIsInClose ( false ),
1623 bIsFullWordSearch ( false )
1625 xFrame
= Frame::create( ::comphelper::getProcessComponentContext() );
1626 xFrame
->initialize( VCLUnoHelper::GetInterface ( pTextWin
) );
1627 xFrame
->setName( "OFFICE_HELP" );
1628 lcl_disableLayoutOfFrame(xFrame
);
1630 xToolBox
->set_help_id(HID_HELP_TOOLBOX
);
1632 xToolBox
->set_item_tooltip_text("index", aIndexOffText
);
1633 xToolBox
->set_item_help_id("index", HID_HELP_TOOLBOXITEM_INDEX
);
1634 xToolBox
->set_item_help_id("backward", HID_HELP_TOOLBOXITEM_BACKWARD
);
1635 xToolBox
->set_item_help_id("forward", HID_HELP_TOOLBOXITEM_FORWARD
);
1636 xToolBox
->set_item_help_id("start", HID_HELP_TOOLBOXITEM_START
);
1637 xToolBox
->set_item_help_id("print", HID_HELP_TOOLBOXITEM_PRINT
);
1638 xToolBox
->set_item_help_id("bookmarks", HID_HELP_TOOLBOXITEM_BOOKMARKS
);
1639 xToolBox
->set_item_help_id("searchdialog", HID_HELP_TOOLBOXITEM_SEARCHDIALOG
);
1641 InitToolBoxImages();
1643 xOnStartupCB
->connect_toggled(LINK(this, SfxHelpTextWindow_Impl
, CheckHdl
));
1645 aSelectIdle
.SetInvokeHandler( LINK( this, SfxHelpTextWindow_Impl
, SelectHdl
) );
1646 aSelectIdle
.SetPriority( TaskPriority::LOWEST
);
1648 char* pEnv
= getenv( "help_debug" );
1652 SvtMiscOptions().AddListenerLink( LINK( this, SfxHelpTextWindow_Impl
, NotifyHdl
) );
1655 SfxHelpTextWindow_Impl::~SfxHelpTextWindow_Impl()
1660 void SfxHelpTextWindow_Impl::dispose()
1663 SvtMiscOptions().RemoveListenerLink( LINK( this, SfxHelpTextWindow_Impl
, NotifyHdl
) );
1666 xOnStartupCB
.reset();
1668 pTextWin
.disposeAndClear();
1669 vcl::Window::dispose();
1672 bool SfxHelpTextWindow_Impl::HasSelection() const
1674 // is there any selection in the text and not only a cursor?
1676 Reference
< XTextRange
> xRange
= getCursor();
1679 Reference
< XText
> xText
= xRange
->getText();
1680 Reference
< XTextCursor
> xCursor
= xText
->createTextCursorByRange( xRange
);
1681 bRet
= !xCursor
->isCollapsed();
1687 void SfxHelpTextWindow_Impl::InitToolBoxImages()
1689 xToolBox
->set_item_icon_name("index", bIsIndexOn
? aIndexOffImage
: aIndexOnImage
);
1692 void SfxHelpTextWindow_Impl::InitOnStartupBox()
1694 sCurrentFactory
= SfxHelp::GetCurrentModuleIdentifier();
1696 Reference
< XComponentContext
> xContext
= ::comphelper::getProcessComponentContext();
1697 const OUString sPath
{ PATH_OFFICE_FACTORIES
+ sCurrentFactory
};
1699 // Attention: This check boy knows two states:
1700 // 1) Reading of the config key fails with an exception or by getting an empty Any (!) => check box must be hidden
1701 // 2) We read sal_True/sal_False => check box must be shown and enabled/disabled
1703 bool bHideBox
= true;
1704 bool bHelpAtStartup
= false;
1707 xConfiguration
= ConfigurationHelper::openConfig(
1708 xContext
, PACKAGE_SETUP
, EConfigurationModes::Standard
);
1709 if ( xConfiguration
.is() )
1711 Any aAny
= ConfigurationHelper::readRelativeKey( xConfiguration
, sPath
, KEY_HELP_ON_OPEN
);
1712 if (aAny
>>= bHelpAtStartup
)
1722 xOnStartupCB
->hide();
1725 // detect module name
1726 OUString sModuleName
;
1728 if ( xConfiguration
.is() )
1733 Any aAny
= ConfigurationHelper::readRelativeKey( xConfiguration
, sPath
, KEY_UI_NAME
);
1736 catch( Exception
const & )
1738 TOOLS_WARN_EXCEPTION( "sfx.appl", "SfxHelpTextWindow_Impl::InitOnStartupBox()" );
1740 sModuleName
= sTemp
;
1743 if ( !sModuleName
.isEmpty() )
1745 // set module name in checkbox text
1746 xOnStartupCB
->set_label(aOnStartupText
.replaceFirst("%MODULENAME", sModuleName
));
1748 xOnStartupCB
->show();
1750 xOnStartupCB
->set_active(bHelpAtStartup
);
1751 xOnStartupCB
->save_state();
1756 Reference
< XBreakIterator
> const & SfxHelpTextWindow_Impl::GetBreakIterator()
1758 if ( !xBreakIterator
.is() )
1759 xBreakIterator
= vcl::unohelper::CreateBreakIterator();
1760 DBG_ASSERT( xBreakIterator
.is(), "Could not create BreakIterator" );
1761 return xBreakIterator
;
1764 Reference
< XTextRange
> SfxHelpTextWindow_Impl::getCursor() const
1766 // return the current cursor
1767 Reference
< XTextRange
> xCursor
;
1771 Reference
< XSelectionSupplier
> xSelSup( xFrame
->getController(), UNO_QUERY
);
1774 Any aAny
= xSelSup
->getSelection();
1775 Reference
< XIndexAccess
> xSelection
;
1776 if ( aAny
>>= xSelection
)
1778 if ( xSelection
->getCount() == 1 )
1780 aAny
= xSelection
->getByIndex(0);
1788 TOOLS_WARN_EXCEPTION( "sfx.appl", "SfxHelpTextWindow_Impl::getCursor(): unexpected exception" );
1795 bool SfxHelpTextWindow_Impl::isHandledKey( const vcl::KeyCode
& _rKeyCode
)
1798 sal_uInt16 nCode
= _rKeyCode
.GetCode();
1800 // the keys <CTRL><A> (select all), <CTRL><C> (copy),
1801 // <CTRL><F> (find), <CTRL><P> (print) and <CTRL><W> (close window)
1802 // were handled in help
1803 if ( _rKeyCode
.IsMod1() &&
1804 ( KEY_A
== nCode
|| KEY_C
== nCode
|| KEY_F
== nCode
|| KEY_P
== nCode
|| KEY_W
== nCode
) )
1806 if ( KEY_F
== nCode
)
1816 IMPL_LINK_NOARG(SfxHelpTextWindow_Impl
, SelectHdl
, Timer
*, void)
1820 // select the words, which are equal to the search text of the search page
1821 Reference
< XController
> xController
= xFrame
->getController();
1822 if ( xController
.is() )
1825 Reference
< XSearchable
> xSearchable( xController
->getModel(), UNO_QUERY
);
1826 if ( xSearchable
.is() )
1828 // create descriptor, set string and find all words
1829 Reference
< XSearchDescriptor
> xSrchDesc
= xSearchable
->createSearchDescriptor();
1830 xSrchDesc
->setPropertyValue( "SearchRegularExpression", makeAny( true ) );
1831 if ( bIsFullWordSearch
)
1832 xSrchDesc
->setPropertyValue( "SearchWords", makeAny( true ) );
1834 xSrchDesc
->setSearchString( sfx2::PrepareSearchString( aSearchText
, GetBreakIterator(), false ) );
1835 Reference
< XIndexAccess
> xSelection
= xSearchable
->findAll( xSrchDesc
);
1837 // then select all found words
1838 Reference
< XSelectionSupplier
> xSelectionSup( xController
, UNO_QUERY
);
1839 if ( xSelectionSup
.is() )
1841 xSelectionSup
->select( Any(xSelection
) );
1848 TOOLS_WARN_EXCEPTION( "sfx.appl", "SfxHelpTextWindow_Impl::SelectHdl(): unexpected exception" );
1853 IMPL_LINK_NOARG( SfxHelpTextWindow_Impl
, NotifyHdl
, LinkParamNone
*, void )
1855 InitToolBoxImages();
1859 IMPL_LINK( SfxHelpTextWindow_Impl
, FindHdl
, sfx2::SearchDialog
&, rDlg
, void )
1863 void SfxHelpTextWindow_Impl::FindHdl(sfx2::SearchDialog
* pDlg
)
1865 bool bWrapAround
= ( nullptr == pDlg
);
1867 pDlg
= m_xSrchDlg
.get();
1868 DBG_ASSERT( pDlg
, "invalid search dialog" );
1871 // select the words, which are equal to the search text of the search page
1872 Reference
< XController
> xController
= xFrame
->getController();
1873 if ( xController
.is() )
1876 Reference
< XSearchable
> xSearchable( xController
->getModel(), UNO_QUERY
);
1877 if ( xSearchable
.is() )
1879 // create descriptor, set string and find all words
1880 Reference
< XSearchDescriptor
> xSrchDesc
= xSearchable
->createSearchDescriptor();
1881 xSrchDesc
->setPropertyValue( "SearchWords", makeAny(pDlg
->IsOnlyWholeWords()) );
1882 xSrchDesc
->setPropertyValue( "SearchCaseSensitive", makeAny(pDlg
->IsMarchCase()) );
1883 xSrchDesc
->setPropertyValue( "SearchBackwards", makeAny(pDlg
->IsSearchBackwards()) );
1884 xSrchDesc
->setSearchString( pDlg
->GetSearchText() );
1885 Reference
< XInterface
> xSelection
;
1886 Reference
< XTextRange
> xCursor
= getCursor();
1890 if ( pDlg
->IsSearchBackwards() )
1891 xCursor
= xCursor
->getStart();
1892 xSelection
= xSearchable
->findNext( xCursor
, xSrchDesc
);
1895 xSelection
= xSearchable
->findFirst( xSrchDesc
);
1897 // then select the found word
1898 if ( xSelection
.is() )
1900 Reference
< XSelectionSupplier
> xSelectionSup( xController
, UNO_QUERY
);
1901 if ( xSelectionSup
.is() )
1903 xSelectionSup
->select( Any(xSelection
) );
1906 else if ( pDlg
->IsWrapAround() && !bWrapAround
)
1908 Reference
< text::XTextViewCursorSupplier
> xCrsrSupp( xController
, uno::UNO_QUERY
);
1909 Reference
< text::XTextViewCursor
> xTVCrsr
= xCrsrSupp
->getViewCursor();
1912 Reference
< text::XTextDocument
> xDoc( xController
->getModel(), uno::UNO_QUERY
);
1913 Reference
< text::XText
> xText
= xDoc
->getText();
1916 if ( pDlg
->IsSearchBackwards() )
1917 xTVCrsr
->gotoRange( xText
->getEnd(), false );
1919 xTVCrsr
->gotoRange( xText
->getStart(), false );
1926 assert(m_xSrchDlg
&& "no search dialog");
1927 std::unique_ptr
<weld::MessageDialog
> xBox(Application::CreateMessageDialog(m_xSrchDlg
->getDialog(),
1928 VclMessageType::Info
, VclButtonsType::Ok
, SfxResId(STR_INFO_NOSEARCHTEXTFOUND
)));
1930 m_xSrchDlg
->SetFocusOnEdit();
1937 TOOLS_WARN_EXCEPTION( "sfx.appl", "SfxHelpTextWindow_Impl::SelectHdl(): unexpected exception" );
1941 IMPL_LINK_NOARG(SfxHelpTextWindow_Impl
, CloseHdl
, LinkParamNone
*, void)
1946 IMPL_LINK_NOARG(SfxHelpTextWindow_Impl
, CheckHdl
, weld::Toggleable
&, void)
1948 if ( !xConfiguration
.is() )
1951 bool bChecked
= xOnStartupCB
->get_active();
1954 ConfigurationHelper::writeRelativeKey(
1955 xConfiguration
, PATH_OFFICE_FACTORIES
+ sCurrentFactory
, KEY_HELP_ON_OPEN
, makeAny( bChecked
) );
1956 ConfigurationHelper::flush( xConfiguration
);
1958 catch( Exception
const & )
1960 TOOLS_WARN_EXCEPTION( "sfx.appl", "SfxHelpTextWindow_Impl::CheckHdl()" );
1964 void SfxHelpTextWindow_Impl::Resize()
1966 Size aSize
= GetOutputSizePixel();
1967 pTextWin
->SetPosSizePixel( Point(0, 0), aSize
);
1970 bool SfxHelpTextWindow_Impl::PreNotify( NotifyEvent
& rNEvt
)
1973 MouseNotifyEvent nType
= rNEvt
.GetType();
1974 if ( MouseNotifyEvent::COMMAND
== nType
&& rNEvt
.GetCommandEvent() )
1976 const CommandEvent
* pCmdEvt
= rNEvt
.GetCommandEvent();
1977 vcl::Window
* pCmdWin
= rNEvt
.GetWindow();
1979 if ( pCmdEvt
->GetCommand() == CommandEventId::ContextMenu
&& pCmdWin
!= this )
1982 if ( pCmdEvt
->IsMouseEvent() )
1983 aPos
= pCmdEvt
->GetMousePosPixel();
1985 aPos
= Point( pTextWin
->GetPosPixel().X() + 20, 20 );
1990 xMenu
->append("index", aIndexOffText
, BMP_HELP_TOOLBOX_INDEX_OFF
);
1992 xMenu
->append("index", aIndexOnText
, BMP_HELP_TOOLBOX_INDEX_ON
);
1994 xMenu
->append_separator("separator1");
1995 xMenu
->append("backward", SfxResId(STR_HELP_BUTTON_PREV
), BMP_HELP_TOOLBOX_PREV
);
1996 xMenu
->set_sensitive("backward", xHelpWin
->HasHistoryPredecessor());
1997 xMenu
->append("forward", SfxResId(STR_HELP_BUTTON_NEXT
), BMP_HELP_TOOLBOX_NEXT
);
1998 xMenu
->set_sensitive("forward", xHelpWin
->HasHistorySuccessor());
1999 xMenu
->append("start", SfxResId(STR_HELP_BUTTON_START
), BMP_HELP_TOOLBOX_START
);
2000 xMenu
->append_separator("separator2");
2001 xMenu
->append("print", SfxResId(STR_HELP_BUTTON_PRINT
), BMP_HELP_TOOLBOX_PRINT
);
2002 xMenu
->append("bookmarks", SfxResId(STR_HELP_BUTTON_ADDBOOKMARK
), BMP_HELP_TOOLBOX_BOOKMARKS
);
2003 xMenu
->append("searchdialog", SfxResId(STR_HELP_BUTTON_SEARCHDIALOG
), BMP_HELP_TOOLBOX_SEARCHDIALOG
);
2004 xMenu
->append_separator("separator3");
2005 xMenu
->append_check("selectionmode", SfxResId(STR_HELP_MENU_TEXT_SELECTION_MODE
));
2007 aURL
.Complete
= ".uno:SelectTextMode";
2008 Reference
< util::XURLTransformer
> xTrans( util::URLTransformer::create( ::comphelper::getProcessComponentContext() ) );
2009 xTrans
->parseStrict(aURL
);
2010 Reference
< XDispatch
> xDisp
= xFrame
->queryDispatch( aURL
, OUString(), 0 );
2013 rtl::Reference
<HelpStatusListener_Impl
> pStateListener
=
2014 new HelpStatusListener_Impl(xDisp
, aURL
);
2015 FeatureStateEvent rEvent
= pStateListener
->GetStateEvent();
2016 bool bCheck
= false;
2017 rEvent
.State
>>= bCheck
;
2018 xMenu
->set_active("selectionmode", bCheck
);
2020 xMenu
->append_separator("separator4");
2021 xMenu
->append("copy", SfxResId(STR_HELP_MENU_TEXT_COPY
), BMP_HELP_TOOLBOX_COPY
);
2022 xMenu
->set_sensitive("copy", HasSelection());
2026 xMenu
->append_separator("separator5");
2027 xMenu
->append("sourceview", SfxResId(STR_HELP_BUTTON_SOURCEVIEW
));
2030 int x
, y
, width
, height
;
2031 weld::Window
* pTopLevel
= GetFrameWeld();
2032 xHelpWin
->GetContainer()->get_extents_relative_to(*pTopLevel
, x
, y
, width
, height
);
2036 xHelpWin
->DoAction(xMenu
->popup_at_rect(pTopLevel
, tools::Rectangle(aPos
, Size(1,1))));
2040 else if ( MouseNotifyEvent::KEYINPUT
== nType
&& rNEvt
.GetKeyEvent() )
2042 const KeyEvent
* pKEvt
= rNEvt
.GetKeyEvent();
2043 const vcl::KeyCode
& rKeyCode
= pKEvt
->GetKeyCode();
2044 sal_uInt16 nKeyGroup
= rKeyCode
.GetGroup();
2045 sal_uInt16 nKey
= rKeyCode
.GetCode();
2046 if ( KEYGROUP_ALPHA
== nKeyGroup
&& !isHandledKey( rKeyCode
) )
2048 // do nothing disables the writer accelerators
2051 else if ( rKeyCode
.IsMod1() && ( KEY_F4
== nKey
|| KEY_W
== nKey
) )
2053 // <CTRL><F4> or <CTRL><W> -> close top frame
2054 xHelpWin
->CloseWindow();
2057 else if ( KEY_TAB
== nKey
&& xOnStartupCB
->has_focus() )
2059 xToolBox
->grab_focus();
2064 return bDone
|| Window::PreNotify( rNEvt
);
2068 void SfxHelpTextWindow_Impl::GetFocus()
2077 Reference
< css::awt::XWindow
> xWindow
= xFrame
->getComponentWindow();
2079 xWindow
->setFocus();
2082 catch( Exception
const & )
2084 TOOLS_WARN_EXCEPTION( "sfx.appl", "SfxHelpTextWindow_Impl::GetFocus()" );
2089 void SfxHelpTextWindow_Impl::DataChanged( const DataChangedEvent
& rDCEvt
)
2091 Window::DataChanged( rDCEvt
);
2093 if ( ( ( rDCEvt
.GetType() == DataChangedEventType::SETTINGS
) ||
2094 ( rDCEvt
.GetType() == DataChangedEventType::DISPLAY
) ) &&
2095 ( rDCEvt
.GetFlags() & AllSettingsFlags::STYLE
) )
2097 SetBackground( Wallpaper( GetSettings().GetStyleSettings().GetFaceColor() ) );
2098 InitToolBoxImages();
2102 void SfxHelpTextWindow_Impl::ToggleIndex( bool bOn
)
2107 xToolBox
->set_item_icon_name("index", aIndexOffImage
);
2108 xToolBox
->set_item_tooltip_text("index", aIndexOffText
);
2112 xToolBox
->set_item_icon_name("index", aIndexOnImage
);
2113 xToolBox
->set_item_tooltip_text("index", aIndexOnText
);
2117 void SfxHelpTextWindow_Impl::SelectSearchText( const OUString
& rSearchText
, bool _bIsFullWordSearch
)
2119 aSearchText
= rSearchText
;
2120 bIsFullWordSearch
= _bIsFullWordSearch
;
2121 aSelectIdle
.Start();
2125 void SfxHelpTextWindow_Impl::SetPageStyleHeaderOff() const
2127 bool bSetOff
= false;
2128 // set off the pagestyle header to prevent print output of the help URL
2131 Reference
< XController
> xController
= xFrame
->getController();
2132 Reference
< XSelectionSupplier
> xSelSup( xController
, UNO_QUERY
);
2135 Reference
< XIndexAccess
> xSelection
;
2136 if ( xSelSup
->getSelection() >>= xSelection
)
2138 Reference
< XTextRange
> xRange
;
2139 if ( xSelection
->getByIndex(0) >>= xRange
)
2141 Reference
< XText
> xText
= xRange
->getText();
2142 Reference
< XPropertySet
> xProps( xText
->createTextCursorByRange( xRange
), UNO_QUERY
);
2143 OUString sStyleName
;
2144 if ( xProps
->getPropertyValue( "PageStyleName" ) >>= sStyleName
)
2146 Reference
< XStyleFamiliesSupplier
> xStyles( xController
->getModel(), UNO_QUERY
);
2147 Reference
< XNameContainer
> xContainer
;
2148 if ( xStyles
->getStyleFamilies()->getByName( "PageStyles" )
2151 Reference
< XStyle
> xStyle
;
2152 if ( xContainer
->getByName( sStyleName
) >>= xStyle
)
2154 Reference
< XPropertySet
> xPropSet( xStyle
, UNO_QUERY
);
2155 xPropSet
->setPropertyValue( "HeaderIsOn", makeAny( false ) );
2157 Reference
< XModifiable
> xReset(xStyles
, UNO_QUERY
);
2158 xReset
->setModified(false);
2167 catch( Exception
const & )
2169 TOOLS_WARN_EXCEPTION( "sfx.appl", "SfxHelpTextWindow_Impl::SetPageStyleHeaderOff()" );
2172 SAL_WARN_IF( !bSetOff
, "sfx.appl", "SfxHelpTextWindow_Impl::SetPageStyleHeaderOff(): set off failed" );
2176 void SfxHelpTextWindow_Impl::CloseFrame()
2181 css::uno::Reference
< css::util::XCloseable
> xCloseable ( xFrame
, css::uno::UNO_QUERY
);
2182 if (xCloseable
.is())
2183 xCloseable
->close(true);
2185 catch( css::util::CloseVetoException
& )
2191 void SfxHelpTextWindow_Impl::DoSearch()
2196 // create the search dialog
2197 m_xSrchDlg
= std::make_shared
<sfx2::SearchDialog
>(pTextWin
->GetFrameWeld(), "HelpSearchDialog");
2199 m_xSrchDlg
->SetFindHdl( LINK( this, SfxHelpTextWindow_Impl
, FindHdl
) );
2200 m_xSrchDlg
->SetCloseHdl( LINK( this, SfxHelpTextWindow_Impl
, CloseHdl
) );
2201 // get selected text of the help page to set it as the search text
2202 Reference
< XTextRange
> xCursor
= getCursor();
2205 OUString sText
= xCursor
->getString();
2206 if ( !sText
.isEmpty() )
2207 m_xSrchDlg
->SetSearchText( sText
);
2209 sfx2::SearchDialog::runAsync(m_xSrchDlg
);
2212 void SfxHelpWindow_Impl::GetFocus()
2215 pTextWin
->GrabFocus();
2217 ResizableDockingWindow::GetFocus();
2220 void SfxHelpWindow_Impl::MakeLayout()
2224 m_xHelpPaneWindow
->set_visible(bIndex
);
2227 IMPL_LINK(SfxHelpWindow_Impl
, ResizeHdl
, const Size
&, rSize
, void)
2229 int nNewWidth
= rSize
.Width();
2233 nIndexSize
= round(m_xContainer
->get_position() * 100.0 / nNewWidth
);
2236 nIndexSize
= round(m_xContainer
->get_position() * 100.0 / nWidth
);
2239 void SfxHelpWindow_Impl::Split()
2243 m_xContainer
->set_position(nWidth
* nIndexSize
/ 100);
2247 void SfxHelpWindow_Impl::LoadConfig()
2249 SvtViewOptions
aViewOpt( EViewType::Window
, CONFIGNAME_HELPWIN
);
2250 if ( !aViewOpt
.Exists() )
2252 bIndex
= aViewOpt
.IsVisible();
2254 Any aUserItem
= aViewOpt
.GetUserItem( USERITEM_NAME
);
2256 if ( aUserItem
>>= aUserData
)
2258 DBG_ASSERT( comphelper::string::getTokenCount(aUserData
, ';') == 6, "invalid user data" );
2260 nIndexSize
= aUserData
.getToken( 0, ';', nIdx
).toInt32();
2261 aUserData
.getToken(0, ';', nIdx
); // ignore nTextSize
2262 sal_Int32 nOldWidth
= aUserData
.getToken( 0, ';', nIdx
).toInt32();
2263 sal_Int32 nOldHeight
= aUserData
.getToken( 0, ';', nIdx
).toInt32();
2264 aWinSize
= Size(nOldWidth
, nOldHeight
);
2265 aWinPos
.setX( aUserData
.getToken( 0, ';', nIdx
).toInt32() );
2266 aWinPos
.setY( aUserData
.getToken( 0, ';', nIdx
).toInt32() );
2269 pTextWin
->ToggleIndex( bIndex
);
2272 void SfxHelpWindow_Impl::SaveConfig()
2274 SvtViewOptions
aViewOpt( EViewType::Window
, CONFIGNAME_HELPWIN
);
2275 sal_Int32 nW
= 0, nH
= 0;
2279 css::awt::Rectangle aRect
= xWindow
->getPosSize();
2284 aViewOpt
.SetVisible( bIndex
);
2285 VclPtr
<vcl::Window
> pScreenWin
= VCLUnoHelper::GetWindow( xWindow
);
2286 aWinPos
= pScreenWin
->GetWindowExtentsRelative( nullptr ).TopLeft();
2288 nIndexSize
= round(m_xContainer
->get_position() * 100.0 / nWidth
);
2289 const OUString aUserData
= OUString::number( nIndexSize
)
2290 + ";" + OUString::number( 100 - nIndexSize
)
2291 + ";" + OUString::number( nW
)
2292 + ";" + OUString::number( nH
)
2293 + ";" + OUString::number( aWinPos
.X() )
2294 + ";" + OUString::number( aWinPos
.Y() );
2296 aViewOpt
.SetUserItem( USERITEM_NAME
, makeAny( aUserData
) );
2299 void SfxHelpWindow_Impl::ShowStartPage()
2301 loadHelpContent(SfxHelpWindow_Impl::buildHelpURL(xIndexWin
->GetFactory(), u
"/start", u
""));
2304 IMPL_LINK(SfxHelpWindow_Impl
, SelectHdl
, const OString
&, rCurItem
, void)
2306 bGrabFocusToToolBox
= pTextWin
->GetToolBox().has_focus();
2310 IMPL_LINK_NOARG(SfxHelpWindow_Impl
, OpenHdl
, LinkParamNone
*, void)
2312 xIndexWin
->SelectExecutableEntry();
2313 OUString aEntry
= xIndexWin
->GetSelectedEntry();
2315 if ( aEntry
.isEmpty() )
2320 bool bComplete
= aEntry
.toAsciiLowerCase().match("vnd.sun.star.help");
2327 OUString
aAnchor('#');
2328 if ( comphelper::string::getTokenCount(aEntry
, '#') == 2 )
2330 sal_Int32 nIdx
{ 0 };
2331 aId
= aEntry
.getToken( 0, '#', nIdx
);
2332 aAnchor
+= aEntry
.getToken( 0, '#', nIdx
);
2337 sHelpURL
= SfxHelpWindow_Impl::buildHelpURL(xIndexWin
->GetFactory(), OUStringConcatenation("/" + aId
), aAnchor
);
2340 loadHelpContent(sHelpURL
);
2343 IMPL_LINK( SfxHelpWindow_Impl
, SelectFactoryHdl
, SfxHelpIndexWindow_Impl
* , pWin
, void )
2345 if ( sTitle
.isEmpty() )
2346 sTitle
= GetParent()->GetText();
2348 Reference
< XTitle
> xTitle(xFrame
, UNO_QUERY
);
2350 xTitle
->setTitle(sTitle
+ " - " + xIndexWin
->GetActiveFactoryTitle());
2354 xIndexWin
->ClearSearchPage();
2358 IMPL_LINK( SfxHelpWindow_Impl
, ChangeHdl
, HelpListener_Impl
&, rListener
, void )
2360 SetFactory( rListener
.GetFactory() );
2364 void SfxHelpWindow_Impl::openDone(const OUString
& sURL
,
2367 INetURLObject
aObj( sURL
);
2368 if ( aObj
.GetProtocol() == INetProtocol::VndSunStarHelp
)
2369 SetFactory( aObj
.GetHost() );
2372 if ( bGrabFocusToToolBox
)
2374 pTextWin
->GetToolBox().grab_focus();
2375 bGrabFocusToToolBox
= false;
2378 xIndexWin
->GrabFocusBack();
2382 // set some view settings: "prevent help tips" and "helpid == 68245"
2385 Reference
< XController
> xController
= pTextWin
->getFrame()->getController();
2386 if ( xController
.is() )
2388 Reference
< XViewSettingsSupplier
> xSettings( xController
, UNO_QUERY
);
2389 Reference
< XPropertySet
> xViewProps
= xSettings
->getViewSettings();
2390 Reference
< XPropertySetInfo
> xInfo
= xViewProps
->getPropertySetInfo();
2391 xViewProps
->setPropertyValue( "ShowContentTips", makeAny( false ) );
2392 xViewProps
->setPropertyValue( "ShowGraphics", makeAny( true ) );
2393 xViewProps
->setPropertyValue( "ShowTables", makeAny( true ) );
2394 xViewProps
->setPropertyValue( "HelpURL", makeAny( OUString("HID:SFX2_HID_HELP_ONHELP") ) );
2395 OUString
sProperty( "IsExecuteHyperlinks" );
2396 if ( xInfo
->hasPropertyByName( sProperty
) )
2397 xViewProps
->setPropertyValue( sProperty
, makeAny( true ) );
2398 xController
->restoreViewData(Any());
2403 TOOLS_WARN_EXCEPTION( "sfx.appl", "SfxHelpWindow_Impl::OpenDoneHdl(): unexpected exception" );
2406 // When the SearchPage opens the help doc, then select all words, which are equal to its text
2407 OUString sSearchText
= comphelper::string::strip(xIndexWin
->GetSearchText(), ' ');
2408 if ( !sSearchText
.isEmpty() )
2409 pTextWin
->SelectSearchText( sSearchText
, xIndexWin
->IsFullWordSearch() );
2411 // no page style header -> this prevents a print output of the URL
2412 pTextWin
->SetPageStyleHeaderOff();
2416 SfxHelpWindow_Impl::SfxHelpWindow_Impl(
2417 const css::uno::Reference
< css::frame::XFrame2
>& rFrame
,
2418 vcl::Window
* pParent
) :
2420 ResizableDockingWindow(pParent
),
2423 pTextWin ( nullptr ),
2424 pHelpInterceptor ( new HelpInterceptor_Impl() ),
2425 pHelpListener ( new HelpListener_Impl( pHelpInterceptor
) ),
2427 bGrabFocusToToolBox ( false ),
2430 nIndexSize ( 40 ), // % of width
2433 sTitle ( pParent
->GetText() )
2435 SetStyle(GetStyle() & ~WB_DOCKABLE
);
2437 SetHelpId( HID_HELP_WINDOW
);
2439 m_xBuilder
= Application::CreateInterimBuilder(m_xBox
.get(), "sfx/ui/helpwindow.ui", false);
2440 m_xContainer
= m_xBuilder
->weld_paned("HelpWindow");
2441 m_xContainer
->connect_size_allocate(LINK(this, SfxHelpWindow_Impl
, ResizeHdl
));
2442 m_xHelpPaneWindow
= m_xBuilder
->weld_container("helppanewindow");
2443 m_xHelpTextWindow
= m_xBuilder
->weld_container("helptextwindow");
2444 m_xHelpTextXWindow
= m_xHelpTextWindow
->CreateChildFrame();
2446 pHelpInterceptor
->InitWaiter( this );
2447 xIndexWin
.reset(new SfxHelpIndexWindow_Impl(this, m_xHelpPaneWindow
.get()));
2448 xIndexWin
->SetDoubleClickHdl( LINK( this, SfxHelpWindow_Impl
, OpenHdl
) );
2449 xIndexWin
->SetSelectFactoryHdl( LINK( this, SfxHelpWindow_Impl
, SelectFactoryHdl
) );
2451 pTextWin
= VclPtr
<SfxHelpTextWindow_Impl
>::Create(this, *m_xBuilder
, VCLUnoHelper::GetWindow(m_xHelpTextXWindow
));
2452 Reference
< XFrames
> xFrames
= rFrame
->getFrames();
2453 xFrames
->append( Reference
<XFrame
>(pTextWin
->getFrame(), UNO_QUERY_THROW
) );
2454 pTextWin
->SetSelectHdl( LINK( this, SfxHelpWindow_Impl
, SelectHdl
) );
2456 pHelpInterceptor
->setInterception( Reference
<XFrame
>(pTextWin
->getFrame(), UNO_QUERY_THROW
) );
2457 pHelpListener
->SetChangeHdl( LINK( this, SfxHelpWindow_Impl
, ChangeHdl
) );
2461 SfxHelpWindow_Impl::~SfxHelpWindow_Impl()
2466 void SfxHelpWindow_Impl::dispose()
2470 pTextWin
->CloseFrame();
2471 pTextWin
.disposeAndClear();
2473 m_xHelpTextXWindow
->dispose();
2474 m_xHelpTextXWindow
.clear();
2475 m_xHelpTextWindow
.reset();
2476 m_xHelpPaneWindow
.reset();
2477 m_xContainer
.reset();
2480 ResizableDockingWindow::dispose();
2483 bool SfxHelpWindow_Impl::PreNotify( NotifyEvent
& rNEvt
)
2485 bool bHandled
= false;
2486 if ( rNEvt
.GetType() == MouseNotifyEvent::KEYINPUT
)
2488 // Backward == <ALT><LEFT> or <BACKSPACE> Forward == <ALT><RIGHT>
2489 const vcl::KeyCode
& rKeyCode
= rNEvt
.GetKeyEvent()->GetKeyCode();
2490 sal_uInt16 nKey
= rKeyCode
.GetCode();
2491 if ( ( rKeyCode
.IsMod2() && ( KEY_LEFT
== nKey
|| KEY_RIGHT
== nKey
) ) ||
2492 ( !rKeyCode
.GetModifier() && KEY_BACKSPACE
== nKey
&& !xIndexWin
->HasFocusOnEdit() ) )
2494 DoAction( rKeyCode
.GetCode() == KEY_RIGHT
? "forward" : "backward" );
2497 else if ( rKeyCode
.IsMod1() && ( KEY_F4
== nKey
|| KEY_W
== nKey
) )
2499 // <CTRL><F4> or <CTRL><W> -> close top frame
2504 return bHandled
|| Window::PreNotify( rNEvt
);
2507 void SfxHelpWindow_Impl::setContainerWindow( const Reference
< css::awt::XWindow
>& xWin
)
2513 VclPtr
<vcl::Window
> pScreenWin
= VCLUnoHelper::GetWindow(xWindow
);
2514 if (aWinSize
.Width() && aWinSize
.Height())
2515 pScreenWin
->SetPosSizePixel(aWinPos
, aWinSize
);
2517 pScreenWin
->SetPosPixel(aWinPos
);
2521 void SfxHelpWindow_Impl::SetFactory( const OUString
& rFactory
)
2523 xIndexWin
->SetFactory( rFactory
, true );
2526 void SfxHelpWindow_Impl::SetHelpURL( const OUString
& rURL
)
2528 INetURLObject
aObj( rURL
);
2529 if ( aObj
.GetProtocol() == INetProtocol::VndSunStarHelp
)
2530 SetFactory( aObj
.GetHost() );
2533 void SfxHelpWindow_Impl::DoAction(std::string_view rActionId
)
2535 if (rActionId
== "index")
2539 pTextWin
->ToggleIndex( bIndex
);
2541 else if (rActionId
== "start")
2545 else if (rActionId
== "backward" || rActionId
== "forward")
2548 aURL
.Complete
= ".uno:Backward";
2549 if (rActionId
== "forward")
2550 aURL
.Complete
= ".uno:Forward";
2551 Reference
< util::XURLTransformer
> xTrans( util::URLTransformer::create( ::comphelper::getProcessComponentContext() ) );
2552 xTrans
->parseStrict(aURL
);
2553 pHelpInterceptor
->dispatch( aURL
, Sequence
< PropertyValue
>() );
2555 else if (rActionId
== "searchdialog")
2557 pTextWin
->DoSearch();
2559 else if (rActionId
== "print" || rActionId
== "sourceview" || rActionId
== "copy" || rActionId
== "selectionmode")
2561 Reference
< XDispatchProvider
> xProv
= pTextWin
->getFrame();
2565 if (rActionId
== "print")
2566 aURL
.Complete
= ".uno:Print";
2567 else if (rActionId
== "sourceview")
2568 aURL
.Complete
= ".uno:SourceView";
2569 else if (rActionId
== "copy")
2570 aURL
.Complete
= ".uno:Copy";
2571 else // rActionId == "selectionmode"
2572 aURL
.Complete
= ".uno:SelectTextMode";
2573 Reference
< util::XURLTransformer
> xTrans( util::URLTransformer::create( ::comphelper::getProcessComponentContext() ) );
2574 xTrans
->parseStrict(aURL
);
2575 Reference
< XDispatch
> xDisp
= xProv
->queryDispatch( aURL
, OUString(), 0 );
2577 xDisp
->dispatch( aURL
, Sequence
< PropertyValue
>() );
2580 else if (rActionId
== "bookmarks")
2582 OUString aURL
= pHelpInterceptor
->GetCurrentURL();
2583 if ( !aURL
.isEmpty() )
2587 Content
aCnt( aURL
, Reference
< css::ucb::XCommandEnvironment
>(), comphelper::getProcessComponentContext() );
2588 css::uno::Reference
< css::beans::XPropertySetInfo
> xInfo
= aCnt
.getProperties();
2589 if ( xInfo
->hasPropertyByName( PROPERTY_TITLE
) )
2591 css::uno::Any aAny
= aCnt
.getPropertyValue( PROPERTY_TITLE
);
2593 if ( aAny
>>= aValue
)
2595 SfxAddHelpBookmarkDialog_Impl
aDlg(GetFrameWeld(), false);
2596 aDlg
.SetTitle(aValue
);
2597 if (aDlg
.run() == RET_OK
)
2599 xIndexWin
->AddBookmarks( aDlg
.GetTitle(), aURL
);
2606 TOOLS_WARN_EXCEPTION( "sfx.appl", "SfxHelpWindow_Impl::DoAction(): unexpected exception" );
2612 void SfxHelpWindow_Impl::CloseWindow()
2616 // search for top frame
2617 Reference
< XFramesSupplier
> xCreator
= getTextFrame()->getCreator();
2618 while ( xCreator
.is() && !xCreator
->isTop() )
2620 xCreator
= xCreator
->getCreator();
2623 // when found, close it
2624 if ( xCreator
.is() && xCreator
->isTop() )
2626 Reference
< XCloseable
> xCloser( xCreator
, UNO_QUERY
);
2628 xCloser
->close( false );
2631 catch( Exception
const & )
2633 TOOLS_WARN_EXCEPTION( "sfx.appl", "SfxHelpWindow_Impl::CloseWindow()" );
2638 void SfxHelpWindow_Impl::UpdateToolbox()
2640 pTextWin
->GetToolBox().set_item_sensitive("backward", pHelpInterceptor
->HasHistoryPred());
2641 pTextWin
->GetToolBox().set_item_sensitive("forward", pHelpInterceptor
->HasHistorySucc());
2645 bool SfxHelpWindow_Impl::HasHistoryPredecessor() const
2647 return pHelpInterceptor
->HasHistoryPred();
2651 bool SfxHelpWindow_Impl::HasHistorySuccessor() const
2653 return pHelpInterceptor
->HasHistorySucc();
2656 // class SfxAddHelpBookmarkDialog_Impl -----------------------------------
2658 SfxAddHelpBookmarkDialog_Impl::SfxAddHelpBookmarkDialog_Impl(weld::Widget
* pParent
, bool bRename
)
2659 : GenericDialogController(pParent
, "sfx/ui/bookmarkdialog.ui", "BookmarkDialog")
2660 , m_xTitleED(m_xBuilder
->weld_entry("entry"))
2661 , m_xAltTitle(m_xBuilder
->weld_label("alttitle"))
2664 m_xDialog
->set_title(m_xAltTitle
->get_label());
2667 void SfxAddHelpBookmarkDialog_Impl::SetTitle(const OUString
& rTitle
)
2669 m_xTitleED
->set_text(rTitle
);
2670 m_xTitleED
->select_region(0, -1);
2673 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */