Coverage Report

Created: 2025-07-07 10:01

/src/libreoffice/sfx2/source/appl/newhelp.cxx
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/*
3
 * This file is part of the LibreOffice project.
4
 *
5
 * This Source Code Form is subject to the terms of the Mozilla Public
6
 * License, v. 2.0. If a copy of the MPL was not distributed with this
7
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8
 *
9
 * This file incorporates work covered by the following license notice:
10
 *
11
 *   Licensed to the Apache Software Foundation (ASF) under one or more
12
 *   contributor license agreements. See the NOTICE file distributed
13
 *   with this work for additional information regarding copyright
14
 *   ownership. The ASF licenses this file to you under the Apache
15
 *   License, Version 2.0 (the "License"); you may not use this file
16
 *   except in compliance with the License. You may obtain a copy of
17
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18
 */
19
20
21
#include "newhelp.hxx"
22
#include <sfx2/sfxresid.hxx>
23
#include "helpinterceptor.hxx"
24
#include <helper.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>
31
32
#include <sfx2/strings.hrc>
33
#include <helpids.h>
34
#include <bitmaps.hlst>
35
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 <utility>
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>
85
86
#include <ucbhelper/content.hxx>
87
#include <unotools/ucbhelper.hxx>
88
89
#include <string_view>
90
#include <unordered_map>
91
#include <vector>
92
93
using namespace ::ucbhelper;
94
using namespace ::com::sun::star::ucb;
95
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;
107
108
using namespace ::comphelper;
109
110
// defines ---------------------------------------------------------------
111
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;
116
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;
125
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";
130
131
namespace sfx2
132
{
133
134
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.
138
        Samples:
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"
144
    */
145
    static OUString PrepareSearchString( const OUString& rSearchString,
146
                                const Reference< XBreakIterator >& xBreak, bool bForSearch )
147
0
    {
148
0
        OUStringBuffer sSearchStr;
149
0
        sal_Int32 nStartPos = 0;
150
0
        const lang::Locale aLocale = Application::GetSettings().GetUILanguageTag().getLocale();
151
0
        Boundary aBoundary = xBreak->getWordBoundary(
152
0
            rSearchString, nStartPos, aLocale, WordType::ANYWORD_IGNOREWHITESPACES, true );
153
154
0
        while ( aBoundary.startPos < aBoundary.endPos )
155
0
        {
156
0
            nStartPos = aBoundary.endPos;
157
0
            OUString sSearchToken( rSearchString.copy(
158
0
                static_cast<sal_uInt16>(aBoundary.startPos), static_cast<sal_uInt16>(aBoundary.endPos) - static_cast<sal_uInt16>(aBoundary.startPos) ) );
159
0
            if ( !sSearchToken.isEmpty() && ( sSearchToken.getLength() > 1 || sSearchToken[0] != '.' ) )
160
0
            {
161
0
                if ( bForSearch && sSearchToken[ sSearchToken.getLength() - 1 ] != '*' )
162
0
                    sSearchToken += "*";
163
164
0
                if ( sSearchToken.getLength() > 1 ||
165
0
                     ( sSearchToken.getLength() > 0 && sSearchToken[ 0 ] != '*' ) )
166
0
                {
167
0
                    if ( !sSearchStr.isEmpty() )
168
0
                    {
169
0
                        if ( bForSearch )
170
0
                            sSearchStr.append(" ");
171
0
                        else
172
0
                            sSearchStr.append("|");
173
0
                    }
174
0
                    sSearchStr.append(sSearchToken);
175
0
                }
176
0
            }
177
0
            aBoundary = xBreak->nextWord( rSearchString, nStartPos,
178
0
                                          aLocale, WordType::ANYWORD_IGNOREWHITESPACES );
179
0
        }
180
181
0
        return sSearchStr.makeStringAndClear();
182
0
    }
183
184
// namespace sfx2
185
}
186
187
188
// struct IndexEntry_Impl ------------------------------------------------
189
190
namespace {
191
192
struct IndexEntry_Impl
193
{
194
    bool            m_bSubEntry;
195
    OUString        m_aURL;
196
197
    IndexEntry_Impl( OUString aURL, bool bSubEntry ) :
198
0
        m_bSubEntry( bSubEntry ), m_aURL(std::move( aURL )) {}
199
};
200
201
// struct ContentEntry_Impl ----------------------------------------------
202
203
struct ContentEntry_Impl
204
{
205
    OUString    aURL;
206
    bool        bIsFolder;
207
208
    ContentEntry_Impl( OUString _aURL, bool bFolder ) :
209
0
        aURL(std::move( _aURL )), bIsFolder( bFolder ) {}
210
};
211
212
}
213
214
void ContentTabPage_Impl::InitRoot()
215
0
{
216
0
    std::vector< OUString > aList =
217
0
        SfxContentHelper::GetHelpTreeViewContents( u"vnd.sun.star.hier://com.sun.star.help.TreeView/"_ustr );
218
219
0
    for (const OUString & aRow : aList)
220
0
    {
221
0
        sal_Int32 nIdx = 0;
222
0
        OUString aTitle = aRow.getToken( 0, '\t', nIdx );
223
0
        OUString aURL = aRow.getToken( 0, '\t', nIdx );
224
0
        sal_Unicode cFolder = o3tl::getToken(aRow, 0, '\t', nIdx )[0];
225
0
        bool bIsFolder = ( '1' == cFolder );
226
0
        OUString sId;
227
0
        if (bIsFolder)
228
0
            sId = weld::toId(new ContentEntry_Impl(aURL, true));
229
0
        m_xContentBox->insert(nullptr, -1, &aTitle, &sId, nullptr, nullptr, true, m_xScratchIter.get());
230
0
        m_xContentBox->set_image(*m_xScratchIter, aClosedBookImage);
231
0
    }
232
0
}
233
234
void ContentTabPage_Impl::ClearChildren(const weld::TreeIter* pParent)
235
0
{
236
0
    std::unique_ptr<weld::TreeIter> xEntry = m_xContentBox->make_iterator(pParent);
237
0
    bool bEntry = m_xContentBox->iter_children(*xEntry);
238
0
    while (bEntry)
239
0
    {
240
0
        ClearChildren(xEntry.get());
241
0
        delete weld::fromId<ContentEntry_Impl*>(m_xContentBox->get_id(*xEntry));
242
0
        bEntry = m_xContentBox->iter_next_sibling(*xEntry);
243
0
    }
244
245
0
}
246
247
IMPL_LINK(ContentTabPage_Impl, ExpandingHdl, const weld::TreeIter&, rIter, bool)
248
0
{
249
0
    ContentEntry_Impl* pContentEntry = weld::fromId<ContentEntry_Impl*>(m_xContentBox->get_id(rIter));
250
0
    if (!m_xContentBox->iter_has_child(rIter))
251
0
    {
252
0
        try
253
0
        {
254
0
            if (pContentEntry)
255
0
            {
256
0
                std::vector<OUString > aList = SfxContentHelper::GetHelpTreeViewContents(pContentEntry->aURL);
257
258
0
                for (const OUString & aRow : aList)
259
0
                {
260
0
                    sal_Int32 nIdx = 0;
261
0
                    OUString aTitle = aRow.getToken( 0, '\t', nIdx );
262
0
                    OUString aURL = aRow.getToken( 0, '\t', nIdx );
263
0
                    sal_Unicode cFolder = o3tl::getToken(aRow, 0, '\t', nIdx )[0];
264
0
                    bool bIsFolder = ( '1' == cFolder );
265
0
                    if ( bIsFolder )
266
0
                    {
267
0
                        OUString sId = weld::toId(new ContentEntry_Impl(aURL, true));
268
0
                        m_xContentBox->insert(&rIter, -1, &aTitle, &sId, nullptr, nullptr, true, m_xScratchIter.get());
269
0
                        m_xContentBox->set_image(*m_xScratchIter, aClosedBookImage);
270
0
                    }
271
0
                    else
272
0
                    {
273
0
                        Any aAny( ::utl::UCBContentHelper::GetProperty( aURL, u"TargetURL"_ustr ) );
274
0
                        OUString sId;
275
0
                        OUString aTargetURL;
276
0
                        if ( aAny >>= aTargetURL )
277
0
                            sId = weld::toId(new ContentEntry_Impl(aTargetURL, false));
278
0
                        m_xContentBox->insert(&rIter, -1, &aTitle, &sId, nullptr, nullptr, false, m_xScratchIter.get());
279
0
                        m_xContentBox->set_image(*m_xScratchIter, aDocumentImage);
280
0
                    }
281
0
                }
282
0
            }
283
0
        }
284
0
        catch (const Exception&)
285
0
        {
286
0
            TOOLS_WARN_EXCEPTION( "sfx.appl", "ContentListBox_Impl::RequestingChildren(): unexpected exception" );
287
0
        }
288
0
    }
289
290
0
    if (!pContentEntry || pContentEntry->bIsFolder)
291
0
        m_xContentBox->set_image(rIter, aOpenBookImage);
292
293
0
    return true;
294
0
}
295
296
IMPL_LINK(ContentTabPage_Impl, CollapsingHdl, const weld::TreeIter&, rIter, bool)
297
0
{
298
0
    ContentEntry_Impl* pContentEntry = weld::fromId<ContentEntry_Impl*>(m_xContentBox->get_id(rIter));
299
0
    if (!pContentEntry || pContentEntry->bIsFolder)
300
0
        m_xContentBox->set_image(rIter, aClosedBookImage);
301
302
0
    return true;
303
0
}
304
305
OUString ContentTabPage_Impl::GetSelectedEntry() const
306
0
{
307
0
    OUString aRet;
308
0
    ContentEntry_Impl* pEntry = weld::fromId<ContentEntry_Impl*>(m_xContentBox->get_selected_id());
309
0
    if (pEntry && !pEntry->bIsFolder)
310
0
        aRet = pEntry->aURL;
311
0
    return aRet;
312
0
}
313
314
// class HelpTabPage_Impl ------------------------------------------------
315
HelpTabPage_Impl::HelpTabPage_Impl(weld::Widget* pParent, SfxHelpIndexWindow_Impl* pIdxWin,
316
    const OUString& rID, const OUString& rUIXMLDescription)
317
0
    : BuilderPage(pParent, nullptr, rUIXMLDescription, rID)
318
0
    , m_pIdxWin(pIdxWin)
319
0
{
320
0
}
321
322
HelpTabPage_Impl::~HelpTabPage_Impl()
323
0
{
324
0
}
325
326
// class ContentTabPage_Impl ---------------------------------------------
327
ContentTabPage_Impl::ContentTabPage_Impl(weld::Widget* pParent, SfxHelpIndexWindow_Impl* pIdxWin)
328
0
    : HelpTabPage_Impl(pParent, pIdxWin, u"HelpContentPage"_ustr,
329
0
        u"sfx/ui/helpcontentpage.ui"_ustr)
330
0
    , m_xContentBox(m_xBuilder->weld_tree_view(u"content"_ustr))
331
0
    , m_xScratchIter(m_xContentBox->make_iterator())
332
0
    , aOpenBookImage(BMP_HELP_CONTENT_BOOK_OPEN)
333
0
    , aClosedBookImage(BMP_HELP_CONTENT_BOOK_CLOSED)
334
0
    , aDocumentImage(BMP_HELP_CONTENT_DOC)
335
0
{
336
0
    m_xContentBox->set_size_request(m_xContentBox->get_approximate_digit_width() * 30,
337
0
                                    m_xContentBox->get_height_rows(20));
338
0
    m_xContentBox->connect_row_activated(LINK(this, ContentTabPage_Impl, DoubleClickHdl));
339
0
    m_xContentBox->connect_expanding(LINK(this, ContentTabPage_Impl, ExpandingHdl));
340
0
    m_xContentBox->connect_collapsing(LINK(this, ContentTabPage_Impl, CollapsingHdl));
341
342
0
    InitRoot();
343
0
}
344
345
IMPL_LINK_NOARG(ContentTabPage_Impl, DoubleClickHdl, weld::TreeView&, bool)
346
0
{
347
0
    aDoubleClickHdl.Call(nullptr);
348
0
    return false;
349
0
}
350
351
void ContentTabPage_Impl::SetDoubleClickHdl(const Link<LinkParamNone*, void>& rLink)
352
0
{
353
0
    aDoubleClickHdl = rLink;
354
0
}
355
356
ContentTabPage_Impl::~ContentTabPage_Impl()
357
0
{
358
0
    std::unique_ptr<weld::TreeIter> xEntry = m_xContentBox->make_iterator();
359
0
    bool bEntry = m_xContentBox->get_iter_first(*xEntry);
360
0
    while (bEntry)
361
0
    {
362
0
        ClearChildren(xEntry.get());
363
0
        delete weld::fromId<ContentEntry_Impl*>(m_xContentBox->get_id(*xEntry));
364
0
        bEntry = m_xContentBox->iter_next_sibling(*xEntry);
365
0
    }
366
0
}
367
368
void IndexTabPage_Impl::SelectExecutableEntry()
369
0
{
370
0
    sal_Int32 nPos = m_xIndexList->find_text(m_xIndexEntry->get_text());
371
0
    if (nPos == -1)
372
0
        return;
373
374
0
    sal_Int32 nOldPos = nPos;
375
0
    OUString aEntryText;
376
0
    IndexEntry_Impl* pEntry = weld::fromId<IndexEntry_Impl*>(m_xIndexList->get_id(nPos));
377
0
    sal_Int32 nCount = m_xIndexList->n_children();
378
0
    while ( nPos < nCount && ( !pEntry || pEntry->m_aURL.isEmpty() ) )
379
0
    {
380
0
        pEntry = weld::fromId<IndexEntry_Impl*>(m_xIndexList->get_id(++nPos));
381
0
        aEntryText = m_xIndexList->get_text(nPos);
382
0
    }
383
384
0
    if ( nOldPos != nPos )
385
0
        m_xIndexEntry->set_text(aEntryText);
386
0
}
387
388
// class IndexTabPage_Impl -----------------------------------------------
389
IndexTabPage_Impl::IndexTabPage_Impl(weld::Widget* pParent, SfxHelpIndexWindow_Impl* pIdxWin)
390
0
    : HelpTabPage_Impl(pParent, pIdxWin, u"HelpIndexPage"_ustr, u"sfx/ui/helpindexpage.ui"_ustr)
391
0
    , m_xIndexEntry(m_xBuilder->weld_entry(u"termentry"_ustr))
392
0
    , m_xIndexList(m_xBuilder->weld_tree_view(u"termlist"_ustr))
393
0
    , m_xOpenBtn(m_xBuilder->weld_button(u"display"_ustr))
394
0
    , aFactoryIdle("sfx2 appl IndexTabPage_Impl Factory")
395
0
    , aAutoCompleteIdle("sfx2 appl IndexTabPage_Impl AutoComplete")
396
0
    , aKeywordTimer("sfx2::IndexTabPage_Impl aKeywordTimer")
397
0
    , bIsActivated(false)
398
0
    , nRowHeight(m_xIndexList->get_height_rows(1))
399
0
    , nAllHeight(0)
400
0
    , nLastCharCode(0)
401
0
{
402
0
    m_xIndexList->set_size_request(m_xIndexList->get_approximate_digit_width() * 30, -1);
403
404
0
    m_xOpenBtn->connect_clicked(LINK(this, IndexTabPage_Impl, OpenHdl));
405
0
    aFactoryIdle.SetInvokeHandler( LINK(this, IndexTabPage_Impl, IdleHdl ));
406
0
    aAutoCompleteIdle.SetInvokeHandler( LINK(this, IndexTabPage_Impl, AutoCompleteHdl ));
407
0
    aKeywordTimer.SetInvokeHandler( LINK( this, IndexTabPage_Impl, TimeoutHdl ) );
408
0
    m_xIndexList->connect_row_activated(LINK(this, IndexTabPage_Impl, DoubleClickHdl));
409
0
    m_xIndexList->connect_selection_changed(LINK(this, IndexTabPage_Impl, TreeChangeHdl));
410
0
    m_xIndexList->connect_custom_get_size(LINK(this, IndexTabPage_Impl, CustomGetSizeHdl));
411
0
    m_xIndexList->connect_custom_render(LINK(this, IndexTabPage_Impl, CustomRenderHdl));
412
0
    m_xIndexList->set_column_custom_renderer(0, true);
413
0
    m_xIndexList->connect_size_allocate(LINK(this, IndexTabPage_Impl, ResizeHdl));
414
0
    m_xIndexEntry->connect_key_press(LINK(this, IndexTabPage_Impl, KeyInputHdl));
415
0
    m_xIndexEntry->connect_changed(LINK(this, IndexTabPage_Impl, EntryChangeHdl));
416
0
    m_xIndexEntry->connect_activate(LINK(this, IndexTabPage_Impl, ActivateHdl));
417
0
}
418
419
IMPL_LINK(IndexTabPage_Impl, ResizeHdl, const Size&, rSize, void)
420
0
{
421
0
    nAllHeight = rSize.Height();
422
0
}
423
424
IMPL_LINK_NOARG(IndexTabPage_Impl, CustomGetSizeHdl, weld::TreeView::get_size_args, Size)
425
0
{
426
0
    return Size(m_xIndexList->get_size_request().Width(), nRowHeight);
427
0
}
428
429
IMPL_LINK(IndexTabPage_Impl, CustomRenderHdl, weld::TreeView::render_args, aPayload, void)
430
0
{
431
0
    vcl::RenderContext& rRenderContext = std::get<0>(aPayload);
432
0
    const ::tools::Rectangle& rRect = std::get<1>(aPayload);
433
0
    bool bSelected = std::get<2>(aPayload);
434
0
    const OUString& rId = std::get<3>(aPayload);
435
436
0
    rRenderContext.Push(vcl::PushFlags::TEXTCOLOR);
437
0
    const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
438
0
    if (bSelected)
439
0
        rRenderContext.SetTextColor(rStyleSettings.GetHighlightTextColor());
440
0
    else
441
0
        rRenderContext.SetTextColor(rStyleSettings.GetDialogTextColor());
442
443
0
    Point aPos(rRect.TopLeft());
444
0
    aPos.AdjustY((rRect.GetHeight() - rRenderContext.GetTextHeight()) / 2);
445
446
0
    int nIndex = m_xIndexList->find_id(rId);
447
0
    OUString aEntry(m_xIndexList->get_text(nIndex));
448
449
0
    IndexEntry_Impl* pEntry = weld::fromId<IndexEntry_Impl*>(rId);
450
0
    if (pEntry && pEntry->m_bSubEntry)
451
0
    {
452
        // indent sub entries
453
0
        aPos.AdjustX(8);
454
0
        sal_Int32 nPos = aEntry.indexOf(';');
455
0
        rRenderContext.DrawText(aPos, (nPos !=-1) ? aEntry.copy(nPos + 1) : aEntry);
456
0
    }
457
0
    else
458
0
        rRenderContext.DrawText(aPos, aEntry);
459
460
0
    rRenderContext.Pop();
461
0
}
462
463
IMPL_LINK_NOARG(IndexTabPage_Impl, TreeChangeHdl, weld::TreeView&, void)
464
0
{
465
0
    m_xIndexEntry->set_text(m_xIndexList->get_selected_text());
466
0
}
467
468
IMPL_LINK_NOARG(IndexTabPage_Impl, EntryChangeHdl, weld::Entry&, void)
469
0
{
470
0
    switch (nLastCharCode)
471
0
    {
472
0
        case css::awt::Key::DELETE_WORD_BACKWARD:
473
0
        case css::awt::Key::DELETE_WORD_FORWARD:
474
0
        case css::awt::Key::DELETE_TO_BEGIN_OF_LINE:
475
0
        case css::awt::Key::DELETE_TO_END_OF_LINE:
476
0
        case KEY_BACKSPACE:
477
0
        case KEY_DELETE:
478
0
            aAutoCompleteIdle.Stop();
479
0
            break;
480
0
        default:
481
0
            aAutoCompleteIdle.Start();
482
0
            break;
483
0
    }
484
0
}
485
486
IMPL_LINK(IndexTabPage_Impl, KeyInputHdl, const KeyEvent&, rKEvt, bool)
487
0
{
488
0
    const vcl::KeyCode& rKCode = rKEvt.GetKeyCode();
489
0
    if (rKCode.GetModifier()) // only with no modifiers held
490
0
        return false;
491
492
0
    sal_uInt16 nCode = rKCode.GetCode();
493
494
0
    if (nCode == KEY_UP || nCode == KEY_PAGEUP ||
495
0
        nCode == KEY_DOWN || nCode == KEY_PAGEDOWN)
496
0
    {
497
//        disable_notify_events();
498
0
        sal_Int32 nIndex = m_xIndexList->get_selected_index();
499
0
        sal_Int32 nOrigIndex = nIndex;
500
0
        sal_Int32 nCount = m_xIndexList->n_children();
501
0
        if (nIndex == -1)
502
0
        {
503
0
            m_xIndexList->set_cursor(0);
504
0
            m_xIndexList->select(0);
505
0
            m_xIndexEntry->set_text(m_xIndexList->get_selected_text());
506
0
        }
507
0
        else
508
0
        {
509
0
            if (nCode == KEY_UP)
510
0
                --nIndex;
511
0
            else if (nCode == KEY_DOWN)
512
0
                ++nIndex;
513
0
            else if (nCode == KEY_PAGEUP)
514
0
            {
515
0
                int nVisRows = nAllHeight / nRowHeight;
516
0
                nIndex -= nVisRows;
517
0
            }
518
0
            else if (nCode == KEY_PAGEDOWN)
519
0
            {
520
0
                int nVisRows = nAllHeight / nRowHeight;
521
0
                nIndex += nVisRows;
522
0
            }
523
524
0
            if (nIndex < 0)
525
0
                nIndex = 0;
526
0
            if (nIndex >= nCount)
527
0
                nIndex = nCount - 1;
528
529
0
            if (nIndex != nOrigIndex)
530
0
            {
531
0
                m_xIndexList->set_cursor(nIndex);
532
0
                m_xIndexList->select(nIndex);
533
0
                m_xIndexEntry->set_text(m_xIndexList->get_selected_text());
534
0
            }
535
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();
540
0
        }
541
0
        m_xIndexEntry->select_region(0, -1);
542
//        enable_notify_events();
543
//        m_bTreeChange = true;
544
//        m_pEntry->fire_signal_changed();
545
//        m_bTreeChange = false;
546
0
        return true;
547
0
    }
548
549
0
    nLastCharCode = nCode;
550
0
    return false;
551
0
}
552
553
IndexTabPage_Impl::~IndexTabPage_Impl()
554
0
{
555
0
    ClearIndex();
556
0
}
557
558
namespace sfx2 {
559
560
    typedef std::unordered_map< OUString, int > KeywordInfo;
561
}
562
563
void IndexTabPage_Impl::InitializeIndex()
564
0
{
565
0
    weld::WaitObject aWaitCursor(m_pIdxWin->GetFrameWeld());
566
567
    // By now more than 256 equal entries are not allowed
568
0
    sal_Unicode append[256];
569
0
    for(sal_Unicode & k : append)
570
0
        k =  ' ';
571
572
0
    sfx2::KeywordInfo aInfo;
573
0
    m_xIndexList->freeze();
574
575
0
    try
576
0
    {
577
0
        OUStringBuffer aURL(HELP_URL + sFactory);
578
0
        AppendConfigToken(aURL, true);
579
580
0
        Content aCnt( aURL.makeStringAndClear(), Reference< css::ucb::XCommandEnvironment >(), comphelper::getProcessComponentContext() );
581
0
        css::uno::Reference< css::beans::XPropertySetInfo > xInfo = aCnt.getProperties();
582
0
        if ( xInfo->hasPropertyByName( PROPERTY_ANCHORREF ) )
583
0
        {
584
0
            css::uno::Sequence< OUString > aPropSeq{ PROPERTY_KEYWORDLIST, PROPERTY_KEYWORDREF,
585
0
                                                     PROPERTY_ANCHORREF, PROPERTY_TITLEREF };
586
587
            // abi: use one possibly remote call only
588
0
            css::uno::Sequence< css::uno::Any > aAnySeq =
589
0
                  aCnt.getPropertyValues( aPropSeq );
590
591
0
            css::uno::Sequence< OUString > aKeywordList;
592
0
            css::uno::Sequence< css::uno::Sequence< OUString > > aKeywordRefList;
593
0
            css::uno::Sequence< css::uno::Sequence< OUString > > aAnchorRefList;
594
0
            css::uno::Sequence< css::uno::Sequence< OUString > > aTitleRefList;
595
596
0
            if ( ( aAnySeq[0] >>= aKeywordList ) && ( aAnySeq[1] >>= aKeywordRefList ) &&
597
0
                 ( aAnySeq[2] >>= aAnchorRefList ) && ( aAnySeq[3] >>= aTitleRefList ) )
598
0
            {
599
0
                int ndx,tmp;
600
0
                OUString aIndex, aTempString;
601
0
                sfx2::KeywordInfo::iterator it;
602
603
0
                for ( int i = 0; i < aKeywordList.getLength(); ++i )
604
0
                {
605
                    // abi: Do not copy, but use references
606
0
                    const OUString& aKeywordPair = aKeywordList[i];
607
0
                    DBG_ASSERT( !aKeywordPair.isEmpty(), "invalid help index" );
608
0
                    const css::uno::Sequence< OUString >& aRefList = aKeywordRefList[i];
609
0
                    const css::uno::Sequence< OUString >& aAnchorList = aAnchorRefList[i];
610
0
                    const css::uno::Sequence< OUString >& aTitleList = aTitleRefList[i];
611
612
0
                    DBG_ASSERT( aRefList.getLength() == aAnchorList.getLength(),"reference list and title list of different length" );
613
614
0
                    ndx = aKeywordPair.indexOf( ';' );
615
0
                    const bool insert = ndx != -1;
616
617
0
                    OUString sId;
618
619
0
                    if ( insert )
620
0
                    {
621
0
                        aTempString = aKeywordPair.copy( 0, ndx );
622
0
                        if ( aIndex != aTempString )
623
0
                        {
624
0
                            aIndex = aTempString;
625
0
                            it = aInfo.emplace(aTempString, 0).first;
626
0
                            sId = weld::toId(new IndexEntry_Impl(OUString(), false));
627
0
                            if ( (tmp = it->second++) != 0)
628
0
                                m_xIndexList->append(
629
0
                                    sId, aTempString + std::u16string_view(append, tmp));
630
0
                            else
631
0
                                m_xIndexList->append(sId, aTempString);
632
0
                        }
633
0
                    }
634
0
                    else
635
0
                        aIndex.clear();
636
637
0
                    sal_uInt32 nRefListLen = aRefList.getLength();
638
639
0
                    DBG_ASSERT( aAnchorList.hasElements(), "*IndexTabPage_Impl::InitializeIndex(): AnchorList is empty!" );
640
0
                    DBG_ASSERT( nRefListLen, "*IndexTabPage_Impl::InitializeIndex(): RefList is empty!" );
641
642
0
                    if ( aAnchorList.hasElements() && nRefListLen )
643
0
                    {
644
0
                        if ( aAnchorList[0].getLength() > 0 )
645
0
                        {
646
0
                            sId = weld::toId(new IndexEntry_Impl(aRefList[0] + "#" + aAnchorList[0], insert));
647
0
                        }
648
0
                        else
649
0
                            sId = weld::toId(new IndexEntry_Impl(aRefList[0], insert));
650
0
                    }
651
652
                    // Assume the token is trimmed
653
0
                    it = aInfo.emplace(aKeywordPair, 0).first;
654
0
                    if ((tmp = it->second++) != 0)
655
0
                        m_xIndexList->append(sId, aKeywordPair + std::u16string_view(append, tmp));
656
0
                    else
657
0
                        m_xIndexList->append(sId, aKeywordPair);
658
659
0
                    for ( sal_uInt32 j = 1; j < nRefListLen ; ++j )
660
0
                    {
661
0
                        aTempString = aKeywordPair + " - " + aTitleList[j];
662
663
0
                        if ( aAnchorList[j].getLength() > 0 )
664
0
                            sId = weld::toId(new IndexEntry_Impl(aRefList[j] + "#" + aAnchorList[j], insert));
665
0
                        else
666
0
                            sId = weld::toId(new IndexEntry_Impl(aRefList[j], insert));
667
668
0
                        it = aInfo.emplace(aTempString, 0).first;
669
0
                        if ( (tmp = it->second++) != 0 )
670
0
                            m_xIndexList->append(
671
0
                                sId, aTempString + std::u16string_view(append, tmp));
672
0
                        else
673
0
                            m_xIndexList->append(sId, aTempString);
674
0
                    }
675
0
                }
676
0
            }
677
0
        }
678
0
    }
679
0
    catch( Exception& )
680
0
    {
681
0
        TOOLS_WARN_EXCEPTION( "sfx.appl", "IndexTabPage_Impl::InitializeIndex(): unexpected exception" );
682
0
    }
683
684
0
    m_xIndexList->thaw();
685
686
0
    if ( !sKeyword.isEmpty() )
687
0
        aKeywordLink.Call( *this );
688
0
}
689
690
void IndexTabPage_Impl::ClearIndex()
691
0
{
692
0
    const sal_Int32 nCount = m_xIndexList->n_children();
693
0
    for ( sal_Int32 i = 0; i < nCount; ++i )
694
0
        delete weld::fromId<IndexEntry_Impl*>(m_xIndexList->get_id(i));
695
0
    m_xIndexList->clear();
696
0
}
697
698
IMPL_LINK_NOARG(IndexTabPage_Impl, OpenHdl, weld::Button&, void)
699
0
{
700
0
    aDoubleClickHdl.Call(nullptr);
701
0
}
702
703
IMPL_LINK_NOARG(IndexTabPage_Impl, ActivateHdl, weld::Entry&, bool)
704
0
{
705
0
    aDoubleClickHdl.Call(nullptr);
706
0
    return true;
707
0
}
708
709
IMPL_LINK_NOARG(IndexTabPage_Impl, DoubleClickHdl, weld::TreeView&, bool)
710
0
{
711
0
    aDoubleClickHdl.Call(nullptr);
712
0
    return true;
713
0
}
714
715
IMPL_LINK_NOARG(IndexTabPage_Impl, IdleHdl, Timer*, void)
716
0
{
717
0
    InitializeIndex();
718
0
}
719
720
int IndexTabPage_Impl::starts_with(const OUString& rStr, int nStartRow, bool bCaseSensitive)
721
0
{
722
0
    const vcl::I18nHelper& rI18nHelper = Application::GetSettings().GetUILocaleI18nHelper();
723
724
0
    int nRet = nStartRow;
725
0
    int nCount = m_xIndexList->n_children();
726
0
    while (nRet < nCount)
727
0
    {
728
0
        OUString aStr(m_xIndexList->get_text(nRet));
729
0
        const bool bMatch = !bCaseSensitive ? rI18nHelper.MatchString(rStr, aStr) : aStr.startsWith(rStr);
730
0
        if (bMatch)
731
0
            return nRet;
732
0
        ++nRet;
733
0
    }
734
735
0
    return -1;
736
0
}
737
738
IMPL_LINK_NOARG(IndexTabPage_Impl, AutoCompleteHdl, Timer*, void)
739
0
{
740
0
    OUString aStartText = m_xIndexEntry->get_text();
741
0
    int nStartPos, nEndPos;
742
0
    m_xIndexEntry->get_selection_bounds(nStartPos, nEndPos);
743
0
    int nMaxSelection = std::max(nStartPos, nEndPos);
744
0
    if (nMaxSelection != aStartText.getLength())
745
0
        return;
746
747
0
    int nActive = m_xIndexList->get_selected_index();
748
0
    int nStart = nActive;
749
750
0
    if (nStart == -1)
751
0
        nStart = 0;
752
753
    // Try match case insensitive from current position
754
0
    int nPos = starts_with(aStartText, nStart, false);
755
0
    if (nPos == -1 && nStart != 0)
756
0
    {
757
        // Try match case insensitive, but from start
758
0
        nPos = starts_with(aStartText, 0, false);
759
0
    }
760
761
0
    if (nPos == -1)
762
0
    {
763
        // Try match case sensitive from current position
764
0
        nPos = starts_with(aStartText, nStart, true);
765
0
        if (nPos == -1 && nStart != 0)
766
0
        {
767
            // Try match case sensitive, but from start
768
0
            nPos = starts_with(aStartText, 0, true);
769
0
        }
770
0
    }
771
772
0
    if (nPos != -1)
773
0
    {
774
0
        m_xIndexList->set_cursor(nPos);
775
0
        m_xIndexList->select(nPos);
776
0
        OUString aText = m_xIndexList->get_text(nPos);
777
0
        if (aText != aStartText)
778
0
            m_xIndexEntry->set_text(aText);
779
0
        m_xIndexEntry->select_region(aText.getLength(), aStartText.getLength());
780
0
    }
781
0
}
782
783
IMPL_LINK( IndexTabPage_Impl, TimeoutHdl, Timer*, pTimer, void)
784
0
{
785
0
    if(&aKeywordTimer == pTimer && !sKeyword.isEmpty())
786
0
        aKeywordLink.Call(*this);
787
0
}
788
789
void IndexTabPage_Impl::Activate()
790
0
{
791
0
    if ( !bIsActivated )
792
0
    {
793
0
        bIsActivated = true;
794
0
        aFactoryIdle.Start();
795
0
    }
796
0
}
797
798
void IndexTabPage_Impl::SetDoubleClickHdl(const Link<LinkParamNone*, void>& rLink)
799
0
{
800
0
    aDoubleClickHdl = rLink;
801
0
}
802
803
void IndexTabPage_Impl::SetFactory( const OUString& rFactory )
804
0
{
805
0
    OUString sNewFactory( rFactory );
806
0
    DBG_ASSERT( !sNewFactory.isEmpty(), "empty factory" );
807
0
    bool bValid = m_pIdxWin->IsValidFactory( rFactory );
808
809
0
    if ( sFactory.isEmpty() && !bValid )
810
0
    {
811
0
        sNewFactory = SfxHelp::GetDefaultHelpModule();
812
0
        bValid = true;
813
0
    }
814
815
0
    if ( sNewFactory != sFactory && bValid )
816
0
    {
817
0
        sFactory = sNewFactory;
818
0
        ClearIndex();
819
0
        if ( bIsActivated )
820
0
            aFactoryIdle.Start();
821
0
    }
822
0
}
823
824
OUString IndexTabPage_Impl::GetSelectedEntry() const
825
0
{
826
0
    OUString aRet;
827
0
    IndexEntry_Impl* pEntry = weld::fromId<IndexEntry_Impl*>(m_xIndexList->get_id(m_xIndexList->find_text(m_xIndexEntry->get_text())));
828
0
    if (pEntry)
829
0
        aRet = pEntry->m_aURL;
830
0
    return aRet;
831
0
}
832
833
void IndexTabPage_Impl::SetKeyword( const OUString& rKeyword )
834
0
{
835
0
    sKeyword = rKeyword;
836
837
0
    if (m_xIndexList->n_children() > 0)
838
0
        aKeywordTimer.Start();
839
0
    else if ( !bIsActivated )
840
0
        aFactoryIdle.Start();
841
0
}
842
843
844
bool IndexTabPage_Impl::HasKeyword() const
845
0
{
846
0
    bool bRet = false;
847
0
    if ( !sKeyword.isEmpty() )
848
0
    {
849
0
        sal_Int32 nPos = m_xIndexList->find_text( sKeyword );
850
0
        bRet = nPos != -1;
851
0
    }
852
853
0
    return bRet;
854
0
}
855
856
857
bool IndexTabPage_Impl::HasKeywordIgnoreCase()
858
0
{
859
0
    bool bRet = false;
860
0
    if ( !sKeyword.isEmpty() )
861
0
    {
862
0
        sal_Int32 nEntries = m_xIndexList->n_children();
863
0
        const vcl::I18nHelper& rI18nHelper = Application::GetSettings().GetLocaleI18nHelper();
864
0
        for ( sal_Int32 n = 0; n < nEntries; n++)
865
0
        {
866
0
            const OUString sIndexItem {m_xIndexList->get_text(n)};
867
0
            if (rI18nHelper.MatchString( sIndexItem, sKeyword ))
868
0
            {
869
0
                sKeyword = sIndexItem;
870
0
                bRet = true;
871
0
            }
872
0
        }
873
0
    }
874
875
0
    return bRet;
876
0
}
877
878
void IndexTabPage_Impl::OpenKeyword()
879
0
{
880
0
    if ( !sKeyword.isEmpty() )
881
0
    {
882
0
        m_xIndexEntry->set_text(sKeyword);
883
0
        aDoubleClickHdl.Call(nullptr);
884
0
        sKeyword.clear();
885
0
    }
886
0
}
887
888
IMPL_LINK_NOARG(SearchTabPage_Impl, ActivateHdl, weld::ComboBox&, bool)
889
0
{
890
0
    Search();
891
0
    return true;
892
0
}
893
894
// class SearchTabPage_Impl ----------------------------------------------
895
896
SearchTabPage_Impl::SearchTabPage_Impl(weld::Widget* pParent, SfxHelpIndexWindow_Impl* pIdxWin)
897
0
    : HelpTabPage_Impl(pParent, pIdxWin, u"HelpSearchPage"_ustr,
898
0
        u"sfx/ui/helpsearchpage.ui"_ustr)
899
0
    , m_xSearchED(m_xBuilder->weld_combo_box(u"search"_ustr))
900
0
    , m_xSearchBtn(m_xBuilder->weld_button(u"find"_ustr))
901
0
    , m_xFullWordsCB(m_xBuilder->weld_check_button(u"completewords"_ustr))
902
0
    , m_xScopeCB(m_xBuilder->weld_check_button(u"headings"_ustr))
903
0
    , m_xResultsLB(m_xBuilder->weld_tree_view(u"results"_ustr))
904
0
    , m_xOpenBtn(m_xBuilder->weld_button(u"display"_ustr))
905
0
    , xBreakIterator(vcl::unohelper::CreateBreakIterator())
906
0
{
907
0
    m_xResultsLB->set_size_request(m_xResultsLB->get_approximate_digit_width() * 30,
908
0
                                   m_xResultsLB->get_height_rows(15));
909
910
0
    m_xSearchBtn->connect_clicked(LINK(this, SearchTabPage_Impl, ClickHdl));
911
0
    m_xSearchED->connect_changed(LINK(this, SearchTabPage_Impl, ModifyHdl));
912
0
    m_xSearchED->connect_entry_activate(LINK(this, SearchTabPage_Impl, ActivateHdl));
913
0
    m_xOpenBtn->connect_clicked(LINK(this, SearchTabPage_Impl, OpenHdl));
914
0
    m_xResultsLB->connect_row_activated(LINK(this, SearchTabPage_Impl, DoubleClickHdl));
915
916
0
    SvtViewOptions aViewOpt( EViewType::TabPage, CONFIGNAME_SEARCHPAGE );
917
0
    if ( aViewOpt.Exists() )
918
0
    {
919
0
        OUString aUserData;
920
0
        Any aUserItem = aViewOpt.GetUserItem( USERITEM_NAME );
921
0
        if ( aUserItem >>= aUserData )
922
0
        {
923
0
            sal_Int32 nIdx {0};
924
0
            bool bChecked = o3tl::toInt32(o3tl::getToken(aUserData, 0, ';', nIdx)) == 1;
925
0
            m_xFullWordsCB->set_active(bChecked);
926
0
            bChecked = o3tl::toInt32(o3tl::getToken(aUserData, 0, ';', nIdx)) == 1;
927
0
            m_xScopeCB->set_active(bChecked);
928
929
0
            while ( nIdx > 0 )
930
0
            {
931
0
                m_xSearchED->append_text( INetURLObject::decode(
932
0
                    o3tl::getToken(aUserData, 0, ';', nIdx),
933
0
                    INetURLObject::DecodeMechanism::WithCharset ) );
934
0
            }
935
0
        }
936
0
    }
937
938
0
    ModifyHdl(*m_xSearchED);
939
0
}
940
941
SearchTabPage_Impl::~SearchTabPage_Impl()
942
0
{
943
0
    SvtViewOptions aViewOpt( EViewType::TabPage, CONFIGNAME_SEARCHPAGE );
944
0
    OUStringBuffer aUserData =
945
0
            OUString::number(m_xFullWordsCB->get_active() ? 1 : 0) +
946
0
            ";" +
947
0
            OUString::number(m_xScopeCB->get_active() ? 1 : 0);
948
0
    sal_Int32 nCount = std::min(m_xSearchED->get_count(), 10);  // save only 10 entries
949
950
0
    for ( sal_Int32 i = 0; i < nCount; ++i )
951
0
    {
952
0
        aUserData.append(";" +
953
0
            INetURLObject::encode(
954
0
                m_xSearchED->get_text(i),
955
0
                INetURLObject::PART_UNO_PARAM_VALUE,
956
0
                INetURLObject::EncodeMechanism::All ));
957
0
    }
958
959
0
    Any aUserItem( aUserData.makeStringAndClear() );
960
0
    aViewOpt.SetUserItem( USERITEM_NAME, aUserItem );
961
962
0
    m_xSearchED.reset();
963
0
    m_xSearchBtn.reset();
964
0
    m_xFullWordsCB.reset();
965
0
    m_xScopeCB.reset();
966
0
    m_xResultsLB.reset();
967
0
    m_xOpenBtn.reset();
968
0
}
969
970
void SearchTabPage_Impl::ClearSearchResults()
971
0
{
972
0
    m_xResultsLB->clear();
973
0
}
974
975
void SearchTabPage_Impl::RememberSearchText( const OUString& rSearchText )
976
0
{
977
0
    for (sal_Int32 i = 0, nEntryCount = m_xSearchED->get_count(); i < nEntryCount; ++i)
978
0
    {
979
0
        if (rSearchText == m_xSearchED->get_text(i))
980
0
        {
981
0
            m_xSearchED->remove(i);
982
0
            break;
983
0
        }
984
0
    }
985
986
0
    m_xSearchED->insert_text(0, rSearchText);
987
0
}
988
989
IMPL_LINK_NOARG(SearchTabPage_Impl, ClickHdl, weld::Button&, void)
990
0
{
991
0
    Search();
992
0
}
993
994
void SearchTabPage_Impl::Search()
995
0
{
996
0
    OUString aSearchText = comphelper::string::strip(m_xSearchED->get_active_text(), ' ');
997
0
    if ( aSearchText.isEmpty() )
998
0
        return;
999
1000
0
    std::unique_ptr<weld::WaitObject> xWaitCursor(new weld::WaitObject(m_pIdxWin->GetFrameWeld()));
1001
0
    ClearSearchResults();
1002
0
    RememberSearchText( aSearchText );
1003
0
    OUStringBuffer aSearchURL(HELP_URL + aFactory + HELP_SEARCH_TAG);
1004
0
    if (!m_xFullWordsCB->get_active())
1005
0
        aSearchText = sfx2::PrepareSearchString( aSearchText, xBreakIterator, true );
1006
0
    aSearchURL.append(aSearchText);
1007
0
    AppendConfigToken(aSearchURL, false);
1008
0
    if (m_xScopeCB->get_active())
1009
0
        aSearchURL.append("&Scope=Heading");
1010
0
    std::vector< OUString > aFactories = SfxContentHelper::GetResultSet(aSearchURL.makeStringAndClear());
1011
0
    for (const OUString & rRow : aFactories)
1012
0
    {
1013
0
        sal_Int32 nIdx = 0;
1014
0
        OUString aTitle = rRow.getToken(0, '\t', nIdx);
1015
0
        OUString sURL(rRow.getToken(1, '\t', nIdx));
1016
0
        m_xResultsLB->append(sURL, aTitle);
1017
0
    }
1018
0
    xWaitCursor.reset();
1019
1020
0
    if ( aFactories.empty() )
1021
0
    {
1022
0
        std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xContainer.get(),
1023
0
                                                                 VclMessageType::Info, VclButtonsType::Ok,
1024
0
                                                                 SfxResId(STR_INFO_NOSEARCHRESULTS)));
1025
0
        xBox->run();
1026
0
    }
1027
0
}
1028
1029
IMPL_LINK_NOARG(SearchTabPage_Impl, OpenHdl, weld::Button&, void)
1030
0
{
1031
0
    aDoubleClickHdl.Call(nullptr);
1032
0
}
1033
1034
IMPL_LINK(SearchTabPage_Impl, ModifyHdl, weld::ComboBox&, rComboBox, void)
1035
0
{
1036
0
    OUString aSearchText = comphelper::string::strip(m_xSearchED->get_active_text(), ' ');
1037
0
    m_xSearchBtn->set_sensitive(!aSearchText.isEmpty());
1038
1039
0
    if (rComboBox.changed_by_direct_pick())
1040
0
        Search();
1041
0
}
1042
1043
IMPL_LINK_NOARG(SearchTabPage_Impl, DoubleClickHdl, weld::TreeView&, bool)
1044
0
{
1045
0
    aDoubleClickHdl.Call(nullptr);
1046
0
    return true;
1047
0
}
1048
1049
void SearchTabPage_Impl::SetDoubleClickHdl(const Link<LinkParamNone*, void>& rLink)
1050
0
{
1051
0
    aDoubleClickHdl = rLink;
1052
0
}
1053
1054
OUString SearchTabPage_Impl::GetSelectedEntry() const
1055
0
{
1056
0
    return m_xResultsLB->get_selected_id();
1057
0
}
1058
1059
void SearchTabPage_Impl::ClearPage()
1060
0
{
1061
0
    ClearSearchResults();
1062
0
    m_xSearchED->set_entry_text(OUString());
1063
0
}
1064
1065
bool SearchTabPage_Impl::OpenKeyword( const OUString& rKeyword )
1066
0
{
1067
0
    bool bRet = false;
1068
0
    m_xSearchED->set_entry_text(rKeyword);
1069
0
    Search();
1070
0
    if (m_xResultsLB->n_children() > 0)
1071
0
    {
1072
        // found keyword -> open it
1073
0
        m_xResultsLB->select(0);
1074
0
        OpenHdl(*m_xOpenBtn);
1075
0
        bRet = true;
1076
0
    }
1077
0
    return bRet;
1078
0
}
1079
1080
// class BookmarksTabPage_Impl -------------------------------------------
1081
1082
void BookmarksTabPage_Impl::DoAction(std::u16string_view rAction)
1083
0
{
1084
0
    if (rAction == u"display")
1085
0
        aDoubleClickHdl.Call(nullptr);
1086
0
    else if (rAction == u"rename")
1087
0
    {
1088
0
        sal_Int32 nPos = m_xBookmarksBox->get_selected_index();
1089
0
        if (nPos != -1)
1090
0
        {
1091
0
            SfxAddHelpBookmarkDialog_Impl aDlg(m_xBookmarksBox.get(), true);
1092
0
            aDlg.SetTitle(m_xBookmarksBox->get_text(nPos));
1093
0
            if (aDlg.run() == RET_OK)
1094
0
            {
1095
0
                OUString sURL = m_xBookmarksBox->get_id(nPos);
1096
0
                m_xBookmarksBox->remove(nPos);
1097
0
                m_xBookmarksBox->append(sURL, aDlg.GetTitle(),
1098
0
                    SvFileInformationManager::GetImageId(INetURLObject(rtl::Concat2View(IMAGE_URL+INetURLObject(sURL).GetHost()))));
1099
0
                m_xBookmarksBox->select(m_xBookmarksBox->n_children() - 1);
1100
0
            }
1101
0
        }
1102
0
    }
1103
0
    else if (rAction == u"delete")
1104
0
    {
1105
0
        sal_Int32 nPos = m_xBookmarksBox->get_selected_index();
1106
0
        if (nPos != -1)
1107
0
        {
1108
0
            m_xBookmarksBox->remove(nPos);
1109
0
            const sal_Int32 nCount = m_xBookmarksBox->n_children();
1110
0
            if (nCount)
1111
0
            {
1112
0
                if (nPos >= nCount)
1113
0
                    nPos = nCount - 1;
1114
0
                m_xBookmarksBox->select(nPos);
1115
0
            }
1116
0
        }
1117
0
    }
1118
0
}
1119
1120
IMPL_LINK(BookmarksTabPage_Impl, CommandHdl, const CommandEvent&, rCEvt, bool)
1121
0
{
1122
0
    if (rCEvt.GetCommand() != CommandEventId::ContextMenu)
1123
0
        return false;
1124
1125
0
    std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(m_xBookmarksBox.get(), u"sfx/ui/bookmarkmenu.ui"_ustr));
1126
0
    std::unique_ptr<weld::Menu> xMenu = xBuilder->weld_menu(u"menu"_ustr);
1127
1128
0
    OUString sIdent = xMenu->popup_at_rect(m_xBookmarksBox.get(), ::tools::Rectangle(rCEvt.GetMousePosPixel(), Size(1,1)));
1129
0
    if (!sIdent.isEmpty())
1130
0
        DoAction(sIdent);
1131
0
    return true;
1132
0
}
1133
1134
IMPL_LINK(BookmarksTabPage_Impl, KeyInputHdl, const KeyEvent&, rKEvt, bool)
1135
0
{
1136
0
    bool bHandled = false;
1137
0
    sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode();
1138
0
    if (KEY_DELETE == nCode && m_xBookmarksBox->n_children() > 0)
1139
0
    {
1140
0
        DoAction(u"delete");
1141
0
        bHandled = true;
1142
0
    }
1143
0
    return bHandled;
1144
0
}
1145
1146
// class BookmarksTabPage_Impl -------------------------------------------
1147
BookmarksTabPage_Impl::BookmarksTabPage_Impl(weld::Widget* pParent, SfxHelpIndexWindow_Impl* _pIdxWin)
1148
0
    : HelpTabPage_Impl(pParent, _pIdxWin, u"HelpBookmarkPage"_ustr,
1149
0
        u"sfx/ui/helpbookmarkpage.ui"_ustr)
1150
0
    , m_xBookmarksBox(m_xBuilder->weld_tree_view(u"bookmarks"_ustr))
1151
0
    , m_xBookmarksPB(m_xBuilder->weld_button(u"display"_ustr))
1152
0
{
1153
0
    m_xBookmarksBox->set_size_request(m_xBookmarksBox->get_approximate_digit_width() * 30,
1154
0
                                      m_xBookmarksBox->get_height_rows(20));
1155
1156
0
    m_xBookmarksPB->connect_clicked( LINK(this, BookmarksTabPage_Impl, OpenHdl));
1157
0
    m_xBookmarksBox->connect_row_activated(LINK(this, BookmarksTabPage_Impl, DoubleClickHdl));
1158
0
    m_xBookmarksBox->connect_popup_menu(LINK(this, BookmarksTabPage_Impl, CommandHdl));
1159
0
    m_xBookmarksBox->connect_key_press(LINK(this, BookmarksTabPage_Impl, KeyInputHdl));
1160
1161
    // load bookmarks from configuration
1162
0
    const std::vector< SvtHistoryOptions::HistoryItem > aBookmarkSeq = SvtHistoryOptions::GetList( EHistoryType::HelpBookmarks );
1163
0
    for ( const auto& rBookmark : aBookmarkSeq )
1164
0
    {
1165
0
        AddBookmarks( rBookmark.sTitle, rBookmark.sURL );
1166
0
    }
1167
0
}
1168
1169
BookmarksTabPage_Impl::~BookmarksTabPage_Impl()
1170
0
{
1171
    // save bookmarks to configuration
1172
0
    SvtHistoryOptions::Clear( EHistoryType::HelpBookmarks );
1173
0
    const sal_Int32 nCount = m_xBookmarksBox->n_children();
1174
0
    for (sal_Int32 i = 0; i < nCount; ++i)
1175
0
    {
1176
0
        SvtHistoryOptions::AppendItem(EHistoryType::HelpBookmarks, m_xBookmarksBox->get_id(i), u""_ustr,
1177
0
                                      m_xBookmarksBox->get_text(i), std::nullopt, std::nullopt);
1178
0
    }
1179
1180
0
    m_xBookmarksBox.reset();
1181
0
    m_xBookmarksPB.reset();
1182
0
}
1183
1184
IMPL_LINK_NOARG(BookmarksTabPage_Impl, OpenHdl, weld::Button&, void)
1185
0
{
1186
0
    aDoubleClickHdl.Call(nullptr);
1187
0
}
1188
1189
IMPL_LINK_NOARG(BookmarksTabPage_Impl, DoubleClickHdl, weld::TreeView&, bool)
1190
0
{
1191
0
    aDoubleClickHdl.Call(nullptr);
1192
0
    return true;
1193
0
}
1194
1195
void BookmarksTabPage_Impl::SetDoubleClickHdl(const Link<LinkParamNone*, void>& rLink)
1196
0
{
1197
0
    aDoubleClickHdl = rLink;
1198
0
}
1199
1200
OUString BookmarksTabPage_Impl::GetSelectedEntry() const
1201
0
{
1202
0
    return m_xBookmarksBox->get_selected_id();
1203
0
}
1204
1205
void BookmarksTabPage_Impl::AddBookmarks(const OUString& rTitle, const OUString& rURL)
1206
0
{
1207
0
    const OUString aImageURL {IMAGE_URL + INetURLObject(rURL).GetHost()};
1208
0
    m_xBookmarksBox->append(rURL, rTitle, SvFileInformationManager::GetImageId(INetURLObject(aImageURL)));
1209
0
}
1210
1211
OUString SfxHelpWindow_Impl::buildHelpURL(std::u16string_view sFactory        ,
1212
                                          std::u16string_view sContent        ,
1213
                                          std::u16string_view sAnchor)
1214
0
{
1215
0
    OUStringBuffer sHelpURL(256);
1216
0
    sHelpURL.append(HELP_URL + sFactory + sContent);
1217
0
    AppendConfigToken(sHelpURL, true/*bUseQuestionMark*/);
1218
0
    if (!sAnchor.empty())
1219
0
        sHelpURL.append(sAnchor);
1220
0
    return sHelpURL.makeStringAndClear();
1221
0
}
1222
1223
void SfxHelpWindow_Impl::loadHelpContent(const OUString& sHelpURL, bool bAddToHistory)
1224
0
{
1225
0
    Reference< XComponentLoader > xLoader(getTextFrame(), UNO_QUERY);
1226
0
    if (!xLoader.is())
1227
0
        return;
1228
1229
    // If a print job runs do not open a new page
1230
0
    Reference< XFrame2 >     xTextFrame      = pTextWin->getFrame();
1231
0
    Reference< XController > xTextController ;
1232
0
    if (xTextFrame.is())
1233
0
        xTextController = xTextFrame->getController ();
1234
0
    if ( xTextController.is() && !xTextController->suspend( true ) )
1235
0
    {
1236
0
        xTextController->suspend( false );
1237
0
        return;
1238
0
    }
1239
1240
    // save url to history
1241
0
    if (bAddToHistory)
1242
0
        pHelpInterceptor->addURL(sHelpURL);
1243
1244
0
    if ( !IsWait() )
1245
0
        EnterWait();
1246
0
    bool bSuccess = false;
1247
// TODO implement locale fallback ... see below    while(true)
1248
0
    {
1249
0
        try
1250
0
        {
1251
0
            Reference< XComponent > xContent = xLoader->loadComponentFromURL(sHelpURL, u"_self"_ustr, 0, Sequence< PropertyValue >());
1252
0
            if (xContent.is())
1253
0
            {
1254
0
                bSuccess = true;
1255
0
            }
1256
0
        }
1257
0
        catch(const RuntimeException&)
1258
0
            { throw; }
1259
0
        catch(const Exception&)
1260
0
            { /*break;*/ }
1261
1262
        /* TODO try next locale ...
1263
                no further locale available? => break loop and show error page
1264
        */
1265
0
    }
1266
0
    openDone(sHelpURL, bSuccess);
1267
0
    if ( IsWait() )
1268
0
        LeaveWait();
1269
0
}
1270
1271
IMPL_LINK(SfxHelpIndexWindow_Impl, ActivatePageHdl, const OUString&, rPage, void)
1272
0
{
1273
0
    GetPage(rPage)->Activate();
1274
0
}
1275
1276
SfxHelpIndexWindow_Impl::SfxHelpIndexWindow_Impl(SfxHelpWindow_Impl* _pParent, weld::Container* pContainer)
1277
0
    : m_xBuilder(Application::CreateBuilder(pContainer, u"sfx/ui/helpcontrol.ui"_ustr))
1278
0
    , m_xContainer(m_xBuilder->weld_container(u"HelpControl"_ustr))
1279
0
    , m_xActiveLB(m_xBuilder->weld_combo_box(u"active"_ustr))
1280
0
    , m_xTabCtrl(m_xBuilder->weld_notebook(u"tabcontrol"_ustr))
1281
0
    , aIdle("sfx2 appl SfxHelpIndexWindow_Impl")
1282
0
    , aIndexKeywordLink(LINK(this, SfxHelpIndexWindow_Impl, KeywordHdl))
1283
0
    , pParentWin(_pParent)
1284
0
    , bIsInitDone(false)
1285
0
{
1286
    // create the pages
1287
0
    GetContentPage();
1288
0
    GetIndexPage();
1289
0
    GetSearchPage();
1290
0
    GetBookmarksPage();
1291
1292
0
    OUString sPageId(u"index"_ustr);
1293
0
    SvtViewOptions aViewOpt( EViewType::TabDialog, CONFIGNAME_INDEXWIN );
1294
0
    if ( aViewOpt.Exists() )
1295
0
    {
1296
0
        OUString sSavedPageId = aViewOpt.GetPageID();
1297
0
        if (m_xTabCtrl->get_page_index(sSavedPageId) != -1)
1298
0
            sPageId = sSavedPageId;
1299
0
    }
1300
0
    m_xTabCtrl->set_current_page(sPageId);
1301
0
    ActivatePageHdl(sPageId);
1302
0
    m_xActiveLB->connect_changed(LINK(this, SfxHelpIndexWindow_Impl, SelectHdl));
1303
1304
0
    m_xTabCtrl->connect_enter_page(LINK(this, SfxHelpIndexWindow_Impl, ActivatePageHdl));
1305
1306
0
    aIdle.SetInvokeHandler( LINK( this, SfxHelpIndexWindow_Impl, InitHdl ) );
1307
0
    aIdle.Start();
1308
1309
0
    m_xContainer->show();
1310
0
}
1311
1312
SfxHelpIndexWindow_Impl::~SfxHelpIndexWindow_Impl()
1313
0
{
1314
0
    SvtViewOptions aViewOpt(EViewType::TabDialog, CONFIGNAME_INDEXWIN);
1315
0
    aViewOpt.SetPageID(m_xTabCtrl->get_current_page_ident());
1316
1317
0
    xCPage.reset();
1318
0
    xIPage.reset();
1319
0
    xSPage.reset();
1320
0
    xBPage.reset();
1321
0
}
1322
1323
void SfxHelpIndexWindow_Impl::Initialize()
1324
0
{
1325
0
    OUStringBuffer aHelpURL(HELP_URL);
1326
0
    AppendConfigToken(aHelpURL, true);
1327
0
    std::vector<OUString> aFactories = SfxContentHelper::GetResultSet(aHelpURL.makeStringAndClear());
1328
0
    for (const OUString & rRow : aFactories)
1329
0
    {
1330
0
        sal_Int32 nIdx = 0;
1331
0
        OUString aTitle = rRow.getToken( 0, '\t', nIdx ); // token 0
1332
0
        std::u16string_view aURL = o3tl::getToken(rRow, 1, '\t', nIdx ); // token 2
1333
0
        OUString aFactory(INetURLObject(aURL).GetHost());
1334
0
        m_xActiveLB->append(aFactory, aTitle);
1335
0
    }
1336
1337
0
    if (m_xActiveLB->get_active() == -1)
1338
0
        SetActiveFactory();
1339
0
}
1340
1341
void SfxHelpIndexWindow_Impl::SetActiveFactory()
1342
0
{
1343
0
    DBG_ASSERT( xIPage, "index page not initialized" );
1344
0
    if (!bIsInitDone && !m_xActiveLB->get_count())
1345
0
    {
1346
0
        aIdle.Stop();
1347
0
        InitHdl( nullptr );
1348
0
    }
1349
1350
0
    for (sal_Int32 i = 0, nEntryCount = m_xActiveLB->get_count(); i < nEntryCount; ++i)
1351
0
    {
1352
0
        OUString aFactory = m_xActiveLB->get_id(i);
1353
0
        aFactory = aFactory.toAsciiLowerCase();
1354
0
        if (aFactory == xIPage->GetFactory())
1355
0
        {
1356
0
            if (m_xActiveLB->get_active() != i)
1357
0
            {
1358
0
                m_xActiveLB->set_active(i);
1359
0
                aSelectFactoryLink.Call(nullptr);
1360
0
            }
1361
0
            break;
1362
0
        }
1363
0
    }
1364
0
}
1365
1366
HelpTabPage_Impl* SfxHelpIndexWindow_Impl::GetPage(std::u16string_view  rName)
1367
0
{
1368
0
    HelpTabPage_Impl* pPage = nullptr;
1369
1370
0
    if (rName == u"contents")
1371
0
        pPage = GetContentPage();
1372
0
    else if (rName == u"index")
1373
0
        pPage = GetIndexPage();
1374
0
    else if (rName == u"find")
1375
0
        pPage = GetSearchPage();
1376
0
    else if (rName == u"bookmarks")
1377
0
        pPage = GetBookmarksPage();
1378
1379
0
    assert(pPage && "SfxHelpIndexWindow_Impl::GetCurrentPage(): no current page");
1380
1381
0
    return pPage;
1382
0
}
1383
1384
IMPL_LINK_NOARG(SfxHelpIndexWindow_Impl, SelectHdl, weld::ComboBox&, void)
1385
0
{
1386
0
    aIdle.Start();
1387
0
}
1388
1389
IMPL_LINK_NOARG(SfxHelpIndexWindow_Impl, InitHdl, Timer *, void)
1390
0
{
1391
0
    bIsInitDone = true;
1392
0
    Initialize();
1393
1394
    // now use the timer for selection
1395
0
    aIdle.SetInvokeHandler( LINK( this, SfxHelpIndexWindow_Impl, SelectFactoryHdl ) );
1396
0
    aIdle.SetPriority( TaskPriority::LOWEST );
1397
0
}
1398
1399
IMPL_LINK_NOARG(SfxHelpIndexWindow_Impl, SelectFactoryHdl, Timer *, void)
1400
0
{
1401
0
    OUString aFactory = m_xActiveLB->get_active_id();
1402
0
    if (!aFactory.isEmpty())
1403
0
    {
1404
0
        SetFactory(aFactory.toAsciiLowerCase(), false);
1405
0
        aSelectFactoryLink.Call(this);
1406
0
    }
1407
0
}
1408
1409
IMPL_LINK_NOARG(SfxHelpIndexWindow_Impl, KeywordHdl, IndexTabPage_Impl&, void)
1410
0
{
1411
    // keyword found on index?
1412
0
    bool bIndex = xIPage->HasKeyword();
1413
1414
0
    if( !bIndex)
1415
0
        bIndex = xIPage->HasKeywordIgnoreCase();
1416
    // then set index or search page as current.
1417
0
    OUString sPageId = bIndex ? u"index"_ustr : u"find"_ustr;
1418
0
    if (sPageId != m_xTabCtrl->get_current_page_ident())
1419
0
        m_xTabCtrl->set_current_page(sPageId);
1420
1421
    // at last we open the keyword
1422
0
    if ( bIndex )
1423
0
        xIPage->OpenKeyword();
1424
0
    else if ( !xSPage->OpenKeyword( sKeyword ) )
1425
0
        pParentWin->ShowStartPage();
1426
0
}
1427
1428
IMPL_LINK_NOARG(SfxHelpIndexWindow_Impl, IndexTabPageDoubleClickHdl, LinkParamNone*, void)
1429
0
{
1430
0
    aPageDoubleClickLink.Call(nullptr);
1431
0
}
1432
1433
void SfxHelpIndexWindow_Impl::SetDoubleClickHdl(const Link<LinkParamNone*, void>& rLink)
1434
0
{
1435
0
    aPageDoubleClickLink = rLink;
1436
0
}
1437
1438
IMPL_LINK_NOARG(SfxHelpIndexWindow_Impl, ContentTabPageDoubleClickHdl, LinkParamNone*, void)
1439
0
{
1440
0
    aPageDoubleClickLink.Call(nullptr);
1441
0
}
1442
1443
IMPL_LINK_NOARG(SfxHelpIndexWindow_Impl, TabPageDoubleClickHdl, LinkParamNone*, void)
1444
0
{
1445
0
    aPageDoubleClickLink.Call(nullptr);
1446
0
}
1447
1448
void SfxHelpIndexWindow_Impl::SetFactory( const OUString& rFactory, bool bActive )
1449
0
{
1450
0
    if ( !rFactory.isEmpty() )
1451
0
    {
1452
0
        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
0
        GetSearchPage()->SetFactory( GetIndexPage()->GetFactory() );
1456
0
        if ( bActive )
1457
0
            SetActiveFactory();
1458
0
    }
1459
0
}
1460
1461
OUString SfxHelpIndexWindow_Impl::GetSelectedEntry() const
1462
0
{
1463
0
    OUString sRet;
1464
1465
0
    OUString sName(m_xTabCtrl->get_current_page_ident());
1466
1467
0
    if (sName == "contents")
1468
0
    {
1469
0
        sRet = xCPage->GetSelectedEntry();
1470
0
    }
1471
0
    else if (sName == "index")
1472
0
    {
1473
0
        sRet = xIPage->GetSelectedEntry();
1474
0
    }
1475
0
    else if (sName == "find")
1476
0
    {
1477
0
        sRet = xSPage->GetSelectedEntry();
1478
0
    }
1479
0
    else if (sName == "bookmarks")
1480
0
    {
1481
0
        sRet = xBPage->GetSelectedEntry();
1482
0
    }
1483
1484
0
    return sRet;
1485
0
}
1486
1487
void SfxHelpIndexWindow_Impl::AddBookmarks( const OUString& rTitle, const OUString& rURL )
1488
0
{
1489
0
    GetBookmarksPage()->AddBookmarks( rTitle, rURL );
1490
0
}
1491
1492
bool SfxHelpIndexWindow_Impl::IsValidFactory( std::u16string_view _rFactory )
1493
0
{
1494
0
    bool bValid = false;
1495
0
    for (sal_Int32 i = 0, nEntryCount = m_xActiveLB->get_count(); i < nEntryCount; ++i)
1496
0
    {
1497
0
        OUString aFactory = m_xActiveLB->get_id(i);
1498
0
        if (aFactory == _rFactory)
1499
0
        {
1500
0
            bValid = true;
1501
0
            break;
1502
0
        }
1503
0
    }
1504
0
    return bValid;
1505
0
}
1506
1507
void SfxHelpIndexWindow_Impl::ClearSearchPage()
1508
0
{
1509
0
    if ( xSPage )
1510
0
        xSPage->ClearPage();
1511
0
}
1512
1513
void SfxHelpIndexWindow_Impl::GrabFocusBack()
1514
0
{
1515
0
    OUString sName(m_xTabCtrl->get_current_page_ident());
1516
1517
0
    if (sName == "contents" && xCPage)
1518
0
        xCPage->SetFocusOnBox();
1519
0
    else if (sName == "index" && xIPage)
1520
0
        xIPage->SetFocusOnBox();
1521
0
    else if (sName == "find" && xSPage)
1522
0
        xSPage->SetFocusOnBox();
1523
0
    else if (sName == "bookmarks" && xBPage)
1524
0
        xBPage->SetFocusOnBox();
1525
0
}
1526
1527
bool SfxHelpIndexWindow_Impl::HasFocusOnEdit() const
1528
0
{
1529
0
    bool bRet = false;
1530
0
    OUString sName(m_xTabCtrl->get_current_page_ident());
1531
0
    if (sName == "index" && xIPage)
1532
0
        bRet = xIPage->HasFocusOnEdit();
1533
0
    else if (sName == "find" && xSPage)
1534
0
        bRet = xSPage->HasFocusOnEdit();
1535
0
    return bRet;
1536
0
}
1537
1538
OUString SfxHelpIndexWindow_Impl::GetSearchText() const
1539
0
{
1540
0
    OUString sRet;
1541
0
    OUString sName(m_xTabCtrl->get_current_page_ident());
1542
0
    if (sName == "find" && xSPage)
1543
0
        sRet = xSPage->GetSearchText();
1544
0
    return sRet;
1545
0
}
1546
1547
bool SfxHelpIndexWindow_Impl::IsFullWordSearch() const
1548
0
{
1549
0
    bool bRet = false;
1550
0
    OUString sName(m_xTabCtrl->get_current_page_ident());
1551
0
    if (sName == "find" && xSPage)
1552
0
        bRet = xSPage->IsFullWordSearch();
1553
0
    return bRet;
1554
0
}
1555
1556
void SfxHelpIndexWindow_Impl::OpenKeyword( const OUString& rKeyword )
1557
0
{
1558
0
    sKeyword = rKeyword;
1559
0
    DBG_ASSERT( xIPage, "invalid index page" );
1560
0
    xIPage->SetKeyword( sKeyword );
1561
0
}
1562
1563
void SfxHelpIndexWindow_Impl::SelectExecutableEntry()
1564
0
{
1565
0
    OUString sName(m_xTabCtrl->get_current_page_ident());
1566
0
    if (sName == "index" && xIPage )
1567
0
        xIPage->SelectExecutableEntry();
1568
0
}
1569
1570
weld::Window* SfxHelpIndexWindow_Impl::GetFrameWeld() const
1571
0
{
1572
0
    return pParentWin->GetFrameWeld();
1573
0
}
1574
1575
// class TextWin_Impl ----------------------------------------------------
1576
0
TextWin_Impl::TextWin_Impl( vcl::Window* p ) : DockingWindow( p, 0 )
1577
0
{
1578
0
}
Unexecuted instantiation: TextWin_Impl::TextWin_Impl(vcl::Window*)
Unexecuted instantiation: TextWin_Impl::TextWin_Impl(vcl::Window*)
1579
1580
bool TextWin_Impl::EventNotify( NotifyEvent& rNEvt )
1581
0
{
1582
0
    if( ( rNEvt.GetType() == NotifyEventType::KEYINPUT ) && rNEvt.GetKeyEvent()->GetKeyCode().GetCode() == KEY_TAB )
1583
0
        return GetParent()->EventNotify( rNEvt );
1584
0
    else
1585
0
        return DockingWindow::EventNotify( rNEvt );
1586
0
}
1587
1588
1589
// remove docking area acceptor from layoutmanager, so it will not layout anything further .-)
1590
static void lcl_disableLayoutOfFrame(const Reference< XFrame2 >& xFrame)
1591
0
{
1592
0
    xFrame->setLayoutManager( Reference< XLayoutManager >() );
1593
0
}
1594
1595
// class SfxHelpTextWindow_Impl ------------------------------------------
1596
1597
SfxHelpTextWindow_Impl::SfxHelpTextWindow_Impl(SfxHelpWindow_Impl* pHelpWin, weld::Builder& rBuilder, vcl::Window* pParent) :
1598
1599
0
    Window( pParent, WB_CLIPCHILDREN | WB_TABSTOP | WB_DIALOGCONTROL ),
1600
1601
0
    xToolBox            ( rBuilder.weld_toolbar(u"toolbar"_ustr) ),
1602
0
    xOnStartupCB        ( rBuilder.weld_check_button(u"checkbutton"_ustr) ),
1603
0
    xMenu               ( rBuilder.weld_menu(u"menu"_ustr) ),
1604
0
    aSelectIdle         ( "sfx2 appl SfxHelpTextWindow_Impl Select" ),
1605
0
    aIndexOnImage       ( BMP_HELP_TOOLBOX_INDEX_ON ),
1606
0
    aIndexOffImage      ( BMP_HELP_TOOLBOX_INDEX_OFF ),
1607
0
    aIndexOnText        ( SfxResId( STR_HELP_BUTTON_INDEX_ON ) ),
1608
0
    aIndexOffText       ( SfxResId( STR_HELP_BUTTON_INDEX_OFF ) ),
1609
0
    aOnStartupText      ( SfxResId( RID_HELP_ONSTARTUP_TEXT ) ),
1610
0
    xHelpWin            ( pHelpWin ),
1611
0
    pTextWin            ( VclPtr<TextWin_Impl>::Create( this ) ),
1612
0
    bIsDebug            ( false ),
1613
0
    bIsIndexOn          ( false ),
1614
0
    bIsInClose          ( false ),
1615
0
    bIsFullWordSearch   ( false )
1616
0
{
1617
0
    xFrame = Frame::create( ::comphelper::getProcessComponentContext() );
1618
0
    xFrame->initialize( VCLUnoHelper::GetInterface ( pTextWin ) );
1619
0
    xFrame->setName( u"OFFICE_HELP"_ustr );
1620
0
    lcl_disableLayoutOfFrame(xFrame);
1621
1622
0
    xToolBox->set_help_id(HID_HELP_TOOLBOX);
1623
1624
0
    xToolBox->set_item_tooltip_text(u"index"_ustr, aIndexOffText );
1625
0
    xToolBox->set_item_help_id(u"index"_ustr, HID_HELP_TOOLBOXITEM_INDEX);
1626
0
    xToolBox->set_item_help_id(u"backward"_ustr, HID_HELP_TOOLBOXITEM_BACKWARD);
1627
0
    xToolBox->set_item_help_id(u"forward"_ustr, HID_HELP_TOOLBOXITEM_FORWARD);
1628
0
    xToolBox->set_item_help_id(u"start"_ustr, HID_HELP_TOOLBOXITEM_START);
1629
0
    xToolBox->set_item_help_id(u"print"_ustr, HID_HELP_TOOLBOXITEM_PRINT);
1630
0
    xToolBox->set_item_help_id(u"bookmarks"_ustr, HID_HELP_TOOLBOXITEM_BOOKMARKS );
1631
0
    xToolBox->set_item_help_id(u"searchdialog"_ustr, HID_HELP_TOOLBOXITEM_SEARCHDIALOG);
1632
1633
0
    InitToolBoxImages();
1634
0
    InitOnStartupBox();
1635
0
    xOnStartupCB->connect_toggled(LINK(this, SfxHelpTextWindow_Impl, CheckHdl));
1636
1637
0
    aSelectIdle.SetInvokeHandler( LINK( this, SfxHelpTextWindow_Impl, SelectHdl ) );
1638
0
    aSelectIdle.SetPriority( TaskPriority::LOWEST );
1639
1640
0
    char* pEnv = getenv( "help_debug" );
1641
0
    if ( pEnv )
1642
0
        bIsDebug = true;
1643
1644
0
    SvtMiscOptions().AddListenerLink( LINK( this, SfxHelpTextWindow_Impl, NotifyHdl ) );
1645
0
}
Unexecuted instantiation: SfxHelpTextWindow_Impl::SfxHelpTextWindow_Impl(SfxHelpWindow_Impl*, weld::Builder&, vcl::Window*)
Unexecuted instantiation: SfxHelpTextWindow_Impl::SfxHelpTextWindow_Impl(SfxHelpWindow_Impl*, weld::Builder&, vcl::Window*)
1646
1647
SfxHelpTextWindow_Impl::~SfxHelpTextWindow_Impl()
1648
0
{
1649
0
    disposeOnce();
1650
0
}
1651
1652
void SfxHelpTextWindow_Impl::dispose()
1653
0
{
1654
0
    bIsInClose = true;
1655
0
    SvtMiscOptions().RemoveListenerLink( LINK( this, SfxHelpTextWindow_Impl, NotifyHdl ) );
1656
0
    m_xSrchDlg.reset();
1657
0
    xToolBox.reset();
1658
0
    xOnStartupCB.reset();
1659
0
    xHelpWin.reset();
1660
0
    pTextWin.disposeAndClear();
1661
0
    vcl::Window::dispose();
1662
0
}
1663
1664
bool SfxHelpTextWindow_Impl::HasSelection() const
1665
0
{
1666
    // is there any selection in the text and not only a cursor?
1667
0
    bool bRet = false;
1668
0
    Reference < XTextRange > xRange = getCursor();
1669
0
    if ( xRange.is() )
1670
0
    {
1671
0
        Reference < XText > xText = xRange->getText();
1672
0
        Reference < XTextCursor > xCursor = xText->createTextCursorByRange( xRange );
1673
0
        bRet = !xCursor->isCollapsed();
1674
0
    }
1675
1676
0
    return bRet;
1677
0
}
1678
1679
void SfxHelpTextWindow_Impl::InitToolBoxImages()
1680
0
{
1681
0
    xToolBox->set_item_icon_name(u"index"_ustr, bIsIndexOn ? aIndexOffImage : aIndexOnImage);
1682
0
}
1683
1684
void SfxHelpTextWindow_Impl::InitOnStartupBox()
1685
0
{
1686
0
    sCurrentFactory = SfxHelp::GetCurrentModuleIdentifier();
1687
1688
0
    const Reference< XComponentContext >& xContext = ::comphelper::getProcessComponentContext();
1689
0
    const OUString sPath { PATH_OFFICE_FACTORIES + sCurrentFactory };
1690
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
1694
1695
0
    bool bHideBox = true;
1696
0
    bool bHelpAtStartup = false;
1697
0
    try
1698
0
    {
1699
0
        xConfiguration = ConfigurationHelper::openConfig(
1700
0
            xContext, PACKAGE_SETUP, EConfigurationModes::Standard );
1701
0
        if ( xConfiguration.is() )
1702
0
        {
1703
0
            Any aAny = ConfigurationHelper::readRelativeKey( xConfiguration, sPath, KEY_HELP_ON_OPEN );
1704
0
            if (aAny >>= bHelpAtStartup)
1705
0
                bHideBox = false;
1706
0
        }
1707
0
    }
1708
0
    catch( Exception& )
1709
0
    {
1710
0
        bHideBox = true;
1711
0
    }
1712
1713
0
    if ( bHideBox )
1714
0
        xOnStartupCB->hide();
1715
0
    else
1716
0
    {
1717
        // detect module name
1718
0
        OUString sModuleName;
1719
1720
0
        if ( xConfiguration.is() )
1721
0
        {
1722
0
            OUString sTemp;
1723
0
            try
1724
0
            {
1725
0
                Any aAny = ConfigurationHelper::readRelativeKey( xConfiguration, sPath, KEY_UI_NAME );
1726
0
                aAny >>= sTemp;
1727
0
            }
1728
0
            catch( Exception const & )
1729
0
            {
1730
0
                TOOLS_WARN_EXCEPTION( "sfx.appl", "SfxHelpTextWindow_Impl::InitOnStartupBox()" );
1731
0
            }
1732
0
            sModuleName = sTemp;
1733
0
        }
1734
1735
0
        if ( !sModuleName.isEmpty() )
1736
0
        {
1737
            // set module name in checkbox text
1738
0
            xOnStartupCB->set_label(aOnStartupText.replaceFirst("%MODULENAME", sModuleName));
1739
            // and show it
1740
0
            xOnStartupCB->show();
1741
            // set check state
1742
0
            xOnStartupCB->set_active(bHelpAtStartup);
1743
0
            xOnStartupCB->save_state();
1744
0
        }
1745
0
    }
1746
0
}
1747
1748
Reference< XBreakIterator > const & SfxHelpTextWindow_Impl::GetBreakIterator()
1749
0
{
1750
0
    if ( !xBreakIterator.is() )
1751
0
        xBreakIterator = vcl::unohelper::CreateBreakIterator();
1752
0
    DBG_ASSERT( xBreakIterator.is(), "Could not create BreakIterator" );
1753
0
    return xBreakIterator;
1754
0
}
1755
1756
Reference< XTextRange > SfxHelpTextWindow_Impl::getCursor() const
1757
0
{
1758
    // return the current cursor
1759
0
    Reference< XTextRange > xCursor;
1760
1761
0
    try
1762
0
    {
1763
0
        Reference < XSelectionSupplier > xSelSup( xFrame->getController(), UNO_QUERY );
1764
0
        if ( xSelSup.is() )
1765
0
        {
1766
0
            Any aAny = xSelSup->getSelection();
1767
0
            Reference < XIndexAccess > xSelection;
1768
0
            if ( aAny >>= xSelection )
1769
0
            {
1770
0
                if ( xSelection->getCount() == 1 )
1771
0
                {
1772
0
                    aAny = xSelection->getByIndex(0);
1773
0
                    aAny >>= xCursor;
1774
0
                }
1775
0
            }
1776
0
        }
1777
0
    }
1778
0
    catch( Exception& )
1779
0
    {
1780
0
        TOOLS_WARN_EXCEPTION( "sfx.appl", "SfxHelpTextWindow_Impl::getCursor(): unexpected exception" );
1781
0
    }
1782
1783
0
    return xCursor;
1784
0
}
1785
1786
1787
bool SfxHelpTextWindow_Impl::isHandledKey( const vcl::KeyCode& _rKeyCode )
1788
0
{
1789
0
    bool bRet = false;
1790
0
    sal_uInt16 nCode = _rKeyCode.GetCode();
1791
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
0
    if ( _rKeyCode.IsMod1() &&
1796
0
         ( KEY_A == nCode || KEY_C == nCode || KEY_F == nCode || KEY_P == nCode || KEY_W == nCode ) )
1797
0
    {
1798
0
        if ( KEY_F == nCode )
1799
0
            DoSearch();
1800
0
        else
1801
0
            bRet = true;
1802
0
    }
1803
1804
0
    return bRet;
1805
0
}
1806
1807
1808
IMPL_LINK_NOARG(SfxHelpTextWindow_Impl, SelectHdl, Timer *, void)
1809
0
{
1810
0
    try
1811
0
    {
1812
        // select the words, which are equal to the search text of the search page
1813
0
        Reference < XController > xController = xFrame->getController();
1814
0
        if ( xController.is() )
1815
0
        {
1816
            // get document
1817
0
            Reference < XSearchable > xSearchable( xController->getModel(), UNO_QUERY );
1818
0
            if ( xSearchable.is() )
1819
0
            {
1820
                // create descriptor, set string and find all words
1821
0
                Reference < XSearchDescriptor > xSrchDesc = xSearchable->createSearchDescriptor();
1822
0
                xSrchDesc->setPropertyValue( u"SearchRegularExpression"_ustr, Any( true ) );
1823
0
                if ( bIsFullWordSearch )
1824
0
                    xSrchDesc->setPropertyValue( u"SearchWords"_ustr, Any( true ) );
1825
1826
0
                xSrchDesc->setSearchString( sfx2::PrepareSearchString( aSearchText, GetBreakIterator(), false ) );
1827
0
                Reference< XIndexAccess > xSelection = xSearchable->findAll( xSrchDesc );
1828
1829
                // then select all found words
1830
0
                Reference < XSelectionSupplier > xSelectionSup( xController, UNO_QUERY );
1831
0
                if ( xSelectionSup.is() )
1832
0
                {
1833
0
                    xSelectionSup->select( Any(xSelection) );
1834
0
                }
1835
0
            }
1836
0
        }
1837
0
    }
1838
0
    catch( Exception& )
1839
0
    {
1840
0
        TOOLS_WARN_EXCEPTION( "sfx.appl", "SfxHelpTextWindow_Impl::SelectHdl(): unexpected exception" );
1841
0
    }
1842
0
}
1843
1844
1845
IMPL_LINK_NOARG( SfxHelpTextWindow_Impl, NotifyHdl, LinkParamNone*, void )
1846
0
{
1847
0
    InitToolBoxImages();
1848
0
    Resize();
1849
0
}
1850
1851
IMPL_LINK( SfxHelpTextWindow_Impl, FindHdl, sfx2::SearchDialog&, rDlg, void )
1852
0
{
1853
0
    FindHdl(&rDlg);
1854
0
}
1855
void SfxHelpTextWindow_Impl::FindHdl(sfx2::SearchDialog* pDlg)
1856
0
{
1857
0
    try
1858
0
    {
1859
        // select the words, which are equal to the search text of the search page
1860
0
        Reference < XController > xController = xFrame->getController();
1861
0
        if ( xController.is() )
1862
0
        {
1863
            // get document
1864
0
            Reference < XSearchable > xSearchable( xController->getModel(), UNO_QUERY );
1865
0
            if ( xSearchable.is() )
1866
0
            {
1867
0
                bool bWrapAround = ( nullptr == pDlg );
1868
0
                if ( bWrapAround )
1869
0
                    pDlg = m_xSrchDlg.get();
1870
0
                assert(pDlg && "invalid search dialog");
1871
1872
                // create descriptor, set string and find all words
1873
0
                Reference < XSearchDescriptor > xSrchDesc = xSearchable->createSearchDescriptor();
1874
0
                xSrchDesc->setPropertyValue( u"SearchWords"_ustr, Any(pDlg->IsOnlyWholeWords()) );
1875
0
                xSrchDesc->setPropertyValue( u"SearchCaseSensitive"_ustr, Any(pDlg->IsMarchCase()) );
1876
0
                xSrchDesc->setPropertyValue( u"SearchBackwards"_ustr, Any(pDlg->IsSearchBackwards()) );
1877
0
                xSrchDesc->setSearchString( pDlg->GetSearchText() );
1878
0
                Reference< XInterface > xSelection;
1879
0
                Reference< XTextRange > xCursor = getCursor();
1880
1881
0
                if ( xCursor.is() )
1882
0
                {
1883
0
                    if ( pDlg->IsSearchBackwards() )
1884
0
                        xCursor = xCursor->getStart();
1885
0
                    xSelection = xSearchable->findNext( xCursor, xSrchDesc );
1886
0
                }
1887
0
                else
1888
0
                    xSelection = xSearchable->findFirst( xSrchDesc );
1889
1890
                // then select the found word
1891
0
                if ( xSelection.is() )
1892
0
                {
1893
0
                    Reference < XSelectionSupplier > xSelectionSup( xController, UNO_QUERY );
1894
0
                    if ( xSelectionSup.is() )
1895
0
                    {
1896
0
                        xSelectionSup->select( Any(xSelection) );
1897
0
                    }
1898
0
                }
1899
0
                else if ( pDlg->IsWrapAround() && !bWrapAround )
1900
0
                {
1901
0
                    Reference < text::XTextViewCursorSupplier > xCrsrSupp( xController, uno::UNO_QUERY );
1902
0
                    Reference < text::XTextViewCursor > xTVCrsr = xCrsrSupp->getViewCursor();
1903
0
                    if ( xTVCrsr.is() )
1904
0
                    {
1905
0
                        Reference < text::XTextDocument > xDoc( xController->getModel(), uno::UNO_QUERY );
1906
0
                        Reference < text::XText > xText = xDoc->getText();
1907
0
                        if ( xText.is() )
1908
0
                        {
1909
0
                            if ( pDlg->IsSearchBackwards() )
1910
0
                                xTVCrsr->gotoRange( xText->getEnd(), false );
1911
0
                            else
1912
0
                                xTVCrsr->gotoRange( xText->getStart(), false );
1913
0
                            FindHdl( nullptr );
1914
0
                        }
1915
0
                    }
1916
0
                }
1917
0
                else
1918
0
                {
1919
0
                    assert(m_xSrchDlg && "no search dialog");
1920
0
                    std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xSrchDlg->getDialog(),
1921
0
                                                              VclMessageType::Info, VclButtonsType::Ok, SfxResId(STR_INFO_NOSEARCHTEXTFOUND)));
1922
0
                    xBox->run();
1923
0
                    m_xSrchDlg->SetFocusOnEdit();
1924
0
                }
1925
0
            }
1926
0
        }
1927
0
    }
1928
0
    catch( Exception& )
1929
0
    {
1930
0
        TOOLS_WARN_EXCEPTION( "sfx.appl", "SfxHelpTextWindow_Impl::SelectHdl(): unexpected exception" );
1931
0
    }
1932
0
}
1933
1934
IMPL_LINK_NOARG(SfxHelpTextWindow_Impl, CloseHdl, LinkParamNone*, void)
1935
0
{
1936
0
    m_xSrchDlg.reset();
1937
0
}
1938
1939
IMPL_LINK_NOARG(SfxHelpTextWindow_Impl, CheckHdl, weld::Toggleable&, void)
1940
0
{
1941
0
    if ( !xConfiguration.is() )
1942
0
        return;
1943
1944
0
    bool bChecked = xOnStartupCB->get_active();
1945
0
    try
1946
0
    {
1947
0
        ConfigurationHelper::writeRelativeKey(
1948
0
            xConfiguration, PATH_OFFICE_FACTORIES + sCurrentFactory, KEY_HELP_ON_OPEN, Any( bChecked ) );
1949
0
        ConfigurationHelper::flush( xConfiguration );
1950
0
    }
1951
0
    catch( Exception const & )
1952
0
    {
1953
0
        TOOLS_WARN_EXCEPTION( "sfx.appl", "SfxHelpTextWindow_Impl::CheckHdl()" );
1954
0
    }
1955
0
}
1956
1957
void SfxHelpTextWindow_Impl::Resize()
1958
0
{
1959
0
    Size aSize = GetOutputSizePixel();
1960
0
    pTextWin->SetPosSizePixel( Point(0, 0), aSize );
1961
0
}
1962
1963
bool SfxHelpTextWindow_Impl::PreNotify( NotifyEvent& rNEvt )
1964
0
{
1965
0
    bool bDone = false;
1966
0
    NotifyEventType nType = rNEvt.GetType();
1967
0
    if ( NotifyEventType::COMMAND == nType && rNEvt.GetCommandEvent() )
1968
0
    {
1969
0
        const CommandEvent* pCmdEvt = rNEvt.GetCommandEvent();
1970
0
        vcl::Window* pCmdWin = rNEvt.GetWindow();
1971
1972
0
        if ( pCmdEvt->GetCommand() == CommandEventId::ContextMenu && pCmdWin != this )
1973
0
        {
1974
0
            Point aPos;
1975
0
            if ( pCmdEvt->IsMouseEvent() )
1976
0
                aPos = pCmdEvt->GetMousePosPixel();
1977
0
            else
1978
0
                aPos = Point( pTextWin->GetPosPixel().X() + 20, 20 );
1979
1980
0
            xMenu->clear();
1981
1982
0
            if (bIsIndexOn)
1983
0
                xMenu->append(u"index"_ustr, aIndexOffText, BMP_HELP_TOOLBOX_INDEX_OFF);
1984
0
            else
1985
0
                xMenu->append(u"index"_ustr, aIndexOnText, BMP_HELP_TOOLBOX_INDEX_ON);
1986
1987
0
            xMenu->append_separator(u"separator1"_ustr);
1988
0
            xMenu->append(u"backward"_ustr, SfxResId(STR_HELP_BUTTON_PREV), BMP_HELP_TOOLBOX_PREV);
1989
0
            xMenu->set_sensitive(u"backward"_ustr, xHelpWin->HasHistoryPredecessor());
1990
0
            xMenu->append(u"forward"_ustr, SfxResId(STR_HELP_BUTTON_NEXT), BMP_HELP_TOOLBOX_NEXT);
1991
0
            xMenu->set_sensitive(u"forward"_ustr, xHelpWin->HasHistorySuccessor());
1992
0
            xMenu->append(u"start"_ustr, SfxResId(STR_HELP_BUTTON_START), BMP_HELP_TOOLBOX_START);
1993
0
            xMenu->append_separator(u"separator2"_ustr);
1994
0
            xMenu->append(u"print"_ustr, SfxResId(STR_HELP_BUTTON_PRINT), BMP_HELP_TOOLBOX_PRINT);
1995
0
            xMenu->append(u"bookmarks"_ustr, SfxResId(STR_HELP_BUTTON_ADDBOOKMARK), BMP_HELP_TOOLBOX_BOOKMARKS);
1996
0
            xMenu->append(u"searchdialog"_ustr, SfxResId(STR_HELP_BUTTON_SEARCHDIALOG), BMP_HELP_TOOLBOX_SEARCHDIALOG);
1997
0
            xMenu->append_separator(u"separator3"_ustr);
1998
0
            xMenu->append_check(u"selectionmode"_ustr, SfxResId(STR_HELP_MENU_TEXT_SELECTION_MODE));
1999
0
            URL aURL;
2000
0
            aURL.Complete = ".uno:SelectTextMode";
2001
0
            Reference< util::XURLTransformer > xTrans( util::URLTransformer::create( ::comphelper::getProcessComponentContext() ) );
2002
0
            xTrans->parseStrict(aURL);
2003
0
            Reference < XDispatch > xDisp = xFrame->queryDispatch( aURL, OUString(), 0 );
2004
0
            if(xDisp.is())
2005
0
            {
2006
0
                rtl::Reference<HelpStatusListener_Impl> pStateListener =
2007
0
                                        new HelpStatusListener_Impl(xDisp, aURL );
2008
0
                FeatureStateEvent rEvent = pStateListener->GetStateEvent();
2009
0
                bool bCheck = false;
2010
0
                rEvent.State >>= bCheck;
2011
0
                xMenu->set_active(u"selectionmode"_ustr, bCheck);
2012
0
            }
2013
0
            xMenu->append_separator(u"separator4"_ustr);
2014
0
            xMenu->append(u"copy"_ustr, SfxResId(STR_HELP_MENU_TEXT_COPY), BMP_HELP_TOOLBOX_COPY);
2015
0
            xMenu->set_sensitive(u"copy"_ustr, HasSelection());
2016
2017
0
            if ( bIsDebug )
2018
0
            {
2019
0
                xMenu->append_separator(u"separator5"_ustr);
2020
0
                xMenu->append(u"sourceview"_ustr, SfxResId(STR_HELP_BUTTON_SOURCEVIEW));
2021
0
            }
2022
2023
0
            int x, y, width, height;
2024
0
            weld::Window* pTopLevel = GetFrameWeld();
2025
0
            xHelpWin->GetContainer()->get_extents_relative_to(*pTopLevel, x, y, width, height);
2026
0
            aPos.AdjustX(x);
2027
0
            aPos.AdjustY(y);
2028
2029
0
            xHelpWin->DoAction(xMenu->popup_at_rect(pTopLevel, tools::Rectangle(aPos, Size(1,1))));
2030
0
            bDone = true;
2031
0
        }
2032
0
    }
2033
0
    else if ( NotifyEventType::KEYINPUT == nType && rNEvt.GetKeyEvent() )
2034
0
    {
2035
0
        const KeyEvent* pKEvt = rNEvt.GetKeyEvent();
2036
0
        const vcl::KeyCode& rKeyCode = pKEvt->GetKeyCode();
2037
0
        sal_uInt16 nKeyGroup = rKeyCode.GetGroup();
2038
0
        sal_uInt16 nKey = rKeyCode.GetCode();
2039
0
        if ( KEYGROUP_ALPHA == nKeyGroup &&  !isHandledKey( rKeyCode ) )
2040
0
        {
2041
            // do nothing disables the writer accelerators
2042
0
            bDone = true;
2043
0
        }
2044
0
        else if ( rKeyCode.IsMod1() && ( KEY_F4 == nKey || KEY_W == nKey ) )
2045
0
        {
2046
            // <CTRL><F4> or <CTRL><W> -> close top frame
2047
0
            xHelpWin->CloseWindow();
2048
0
            bDone = true;
2049
0
        }
2050
0
        else if ( KEY_TAB == nKey && xOnStartupCB->has_focus() )
2051
0
        {
2052
0
            xToolBox->grab_focus();
2053
0
            bDone = true;
2054
0
        }
2055
0
    }
2056
2057
0
    return bDone || Window::PreNotify( rNEvt );
2058
0
}
2059
2060
2061
void SfxHelpTextWindow_Impl::GetFocus()
2062
0
{
2063
0
    if ( bIsInClose )
2064
0
        return;
2065
2066
0
    try
2067
0
    {
2068
0
        if( xFrame.is() )
2069
0
        {
2070
0
            Reference< css::awt::XWindow > xWindow = xFrame->getComponentWindow();
2071
0
            if( xWindow.is() )
2072
0
                xWindow->setFocus();
2073
0
        }
2074
0
    }
2075
0
    catch( Exception const & )
2076
0
    {
2077
0
        TOOLS_WARN_EXCEPTION( "sfx.appl", "SfxHelpTextWindow_Impl::GetFocus()" );
2078
0
    }
2079
0
}
2080
2081
2082
void SfxHelpTextWindow_Impl::DataChanged( const DataChangedEvent& rDCEvt )
2083
0
{
2084
0
    Window::DataChanged( rDCEvt );
2085
2086
0
    if ( ( ( rDCEvt.GetType() == DataChangedEventType::SETTINGS ) ||
2087
0
           ( rDCEvt.GetType() == DataChangedEventType::DISPLAY ) ) &&
2088
0
         ( rDCEvt.GetFlags() & AllSettingsFlags::STYLE ) )
2089
0
    {
2090
0
        SetBackground( Wallpaper( GetSettings().GetStyleSettings().GetFaceColor() ) );
2091
0
        InitToolBoxImages();
2092
0
    }
2093
0
}
2094
2095
void SfxHelpTextWindow_Impl::ToggleIndex( bool bOn )
2096
0
{
2097
0
    bIsIndexOn = bOn;
2098
0
    if ( bIsIndexOn )
2099
0
    {
2100
0
        xToolBox->set_item_icon_name(u"index"_ustr, aIndexOffImage);
2101
0
        xToolBox->set_item_tooltip_text(u"index"_ustr, aIndexOffText);
2102
0
    }
2103
0
    else
2104
0
    {
2105
0
        xToolBox->set_item_icon_name(u"index"_ustr, aIndexOnImage);
2106
0
        xToolBox->set_item_tooltip_text(u"index"_ustr, aIndexOnText);
2107
0
    }
2108
0
}
2109
2110
void SfxHelpTextWindow_Impl::SelectSearchText( const OUString& rSearchText, bool _bIsFullWordSearch )
2111
0
{
2112
0
    aSearchText = rSearchText;
2113
0
    bIsFullWordSearch = _bIsFullWordSearch;
2114
0
    aSelectIdle.Start();
2115
0
}
2116
2117
2118
void SfxHelpTextWindow_Impl::SetPageStyleHeaderOff() const
2119
0
{
2120
0
    bool bSetOff = false;
2121
    // set off the pagestyle header to prevent print output of the help URL
2122
0
    try
2123
0
    {
2124
0
        Reference < XController > xController = xFrame->getController();
2125
0
        Reference < XSelectionSupplier > xSelSup( xController, UNO_QUERY );
2126
0
        if ( xSelSup.is() )
2127
0
        {
2128
0
            Reference < XIndexAccess > xSelection;
2129
0
            if ( xSelSup->getSelection() >>= xSelection )
2130
0
            {
2131
0
                Reference < XTextRange > xRange;
2132
0
                if ( xSelection->getByIndex(0) >>= xRange )
2133
0
                {
2134
0
                    Reference < XText > xText = xRange->getText();
2135
0
                    Reference < XPropertySet > xProps( xText->createTextCursorByRange( xRange ), UNO_QUERY );
2136
0
                    OUString sStyleName;
2137
0
                    if ( xProps->getPropertyValue( u"PageStyleName"_ustr ) >>= sStyleName )
2138
0
                    {
2139
0
                        Reference < XStyleFamiliesSupplier > xStyles( xController->getModel(), UNO_QUERY );
2140
0
                        Reference < XNameContainer > xContainer;
2141
0
                        if ( xStyles->getStyleFamilies()->getByName( u"PageStyles"_ustr )
2142
0
                             >>= xContainer )
2143
0
                        {
2144
0
                            Reference < XStyle > xStyle;
2145
0
                            if ( xContainer->getByName( sStyleName ) >>= xStyle )
2146
0
                            {
2147
0
                                Reference < XPropertySet > xPropSet( xStyle, UNO_QUERY );
2148
0
                                xPropSet->setPropertyValue( u"HeaderIsOn"_ustr,  Any( false ) );
2149
2150
0
                                Reference< XModifiable > xReset(xStyles, UNO_QUERY);
2151
0
                                xReset->setModified(false);
2152
0
                                bSetOff = true;
2153
0
                            }
2154
0
                        }
2155
0
                    }
2156
0
                }
2157
0
            }
2158
0
        }
2159
0
    }
2160
0
    catch( Exception const & )
2161
0
    {
2162
0
        TOOLS_WARN_EXCEPTION( "sfx.appl", "SfxHelpTextWindow_Impl::SetPageStyleHeaderOff()" );
2163
0
    }
2164
2165
0
    SAL_WARN_IF( !bSetOff, "sfx.appl", "SfxHelpTextWindow_Impl::SetPageStyleHeaderOff(): set off failed" );
2166
0
}
2167
2168
2169
void SfxHelpTextWindow_Impl::CloseFrame()
2170
0
{
2171
0
    bIsInClose = true;
2172
0
    try
2173
0
    {
2174
0
        css::uno::Reference< css::util::XCloseable > xCloseable  ( xFrame, css::uno::UNO_QUERY );
2175
0
        if (xCloseable.is())
2176
0
            xCloseable->close(true);
2177
0
    }
2178
0
    catch( css::util::CloseVetoException& )
2179
0
    {
2180
0
    }
2181
0
}
2182
2183
2184
void SfxHelpTextWindow_Impl::DoSearch()
2185
0
{
2186
0
    if (m_xSrchDlg)
2187
0
        return;
2188
2189
    // create the search dialog
2190
0
    m_xSrchDlg = std::make_shared<sfx2::SearchDialog>(pTextWin->GetFrameWeld(), "HelpSearchDialog");
2191
    // set handler
2192
0
    m_xSrchDlg->SetFindHdl( LINK( this, SfxHelpTextWindow_Impl, FindHdl ) );
2193
0
    m_xSrchDlg->SetCloseHdl( LINK( this, SfxHelpTextWindow_Impl, CloseHdl ) );
2194
    // get selected text of the help page to set it as the search text
2195
0
    Reference< XTextRange > xCursor = getCursor();
2196
0
    if ( xCursor.is() )
2197
0
    {
2198
0
        OUString sText = xCursor->getString();
2199
0
        if ( !sText.isEmpty() )
2200
0
            m_xSrchDlg->SetSearchText( sText );
2201
0
    }
2202
0
    sfx2::SearchDialog::runAsync(m_xSrchDlg);
2203
0
}
2204
2205
void SfxHelpWindow_Impl::GetFocus()
2206
0
{
2207
0
    if (pTextWin)
2208
0
        pTextWin->GrabFocus();
2209
0
    else
2210
0
        ResizableDockingWindow::GetFocus();
2211
0
}
2212
2213
void SfxHelpWindow_Impl::MakeLayout()
2214
0
{
2215
0
    Split();
2216
2217
0
    m_xHelpPaneWindow->set_visible(bIndex);
2218
0
}
2219
2220
IMPL_LINK(SfxHelpWindow_Impl, ResizeHdl, const Size&, rSize, void)
2221
0
{
2222
0
    int nNewWidth = rSize.Width();
2223
0
    if (!nNewWidth)
2224
0
        return;
2225
0
    if (bSplit)
2226
0
        nIndexSize = round(m_xContainer->get_position() * 100.0 / nNewWidth);
2227
0
    nWidth = nNewWidth;
2228
0
    Split();
2229
0
    nIndexSize = round(m_xContainer->get_position() * 100.0 / nWidth);
2230
0
}
2231
2232
void SfxHelpWindow_Impl::Split()
2233
0
{
2234
0
    if (!nWidth)
2235
0
        return;
2236
0
    m_xContainer->set_position(nWidth * nIndexSize / 100);
2237
0
    bSplit = true;
2238
0
}
2239
2240
void SfxHelpWindow_Impl::LoadConfig()
2241
0
{
2242
0
    SvtViewOptions aViewOpt( EViewType::Window, CONFIGNAME_HELPWIN );
2243
0
    if ( !aViewOpt.Exists() )
2244
0
        return;
2245
0
    bIndex = aViewOpt.IsVisible();
2246
2247
0
    Any aUserItem = aViewOpt.GetUserItem( USERITEM_NAME );
2248
0
    OUString aUserData;
2249
0
    if ( aUserItem >>= aUserData )
2250
0
    {
2251
0
        DBG_ASSERT( comphelper::string::getTokenCount(aUserData, ';') == 6, "invalid user data" );
2252
0
        sal_Int32 nIdx = 0;
2253
0
        nIndexSize = o3tl::toInt32(o3tl::getToken(aUserData, 0, ';', nIdx ));
2254
0
        o3tl::getToken(aUserData, 0, ';', nIdx); // ignore nTextSize
2255
0
        sal_Int32 nOldWidth = o3tl::toInt32(o3tl::getToken(aUserData, 0, ';', nIdx ));
2256
0
        sal_Int32 nOldHeight = o3tl::toInt32(o3tl::getToken(aUserData, 0, ';', nIdx ));
2257
0
        aWinSize = Size(nOldWidth, nOldHeight);
2258
0
        aWinPos.setX( o3tl::toInt32(o3tl::getToken(aUserData, 0, ';', nIdx )) );
2259
0
        aWinPos.setY( o3tl::toInt32(o3tl::getToken(aUserData, 0, ';', nIdx )) );
2260
0
    }
2261
2262
0
    pTextWin->ToggleIndex( bIndex );
2263
0
}
2264
2265
void SfxHelpWindow_Impl::SaveConfig()
2266
0
{
2267
0
    SvtViewOptions aViewOpt( EViewType::Window, CONFIGNAME_HELPWIN );
2268
0
    sal_Int32 nW = 0, nH = 0;
2269
2270
0
    if ( xWindow.is() )
2271
0
    {
2272
0
        css::awt::Rectangle aRect = xWindow->getPosSize();
2273
0
        nW = aRect.Width;
2274
0
        nH = aRect.Height;
2275
0
    }
2276
2277
0
    aViewOpt.SetVisible( bIndex );
2278
0
    VclPtr<vcl::Window> pScreenWin = VCLUnoHelper::GetWindow( xWindow );
2279
0
    aWinPos = pScreenWin->GetWindowExtentsAbsolute().TopLeft();
2280
0
    if (bSplit)
2281
0
        nIndexSize = round(m_xContainer->get_position() * 100.0 / nWidth);
2282
0
    const OUString aUserData = OUString::number( nIndexSize )
2283
0
        + ";" + OUString::number( 100 - nIndexSize )
2284
0
        + ";" + OUString::number( nW )
2285
0
        + ";" + OUString::number( nH )
2286
0
        + ";" + OUString::number( aWinPos.X() )
2287
0
        + ";" + OUString::number( aWinPos.Y() );
2288
2289
0
    aViewOpt.SetUserItem( USERITEM_NAME, Any( aUserData ) );
2290
0
}
2291
2292
void SfxHelpWindow_Impl::ShowStartPage()
2293
0
{
2294
0
    loadHelpContent(SfxHelpWindow_Impl::buildHelpURL(xIndexWin->GetFactory(), u"/start", u""));
2295
0
}
2296
2297
IMPL_LINK(SfxHelpWindow_Impl, SelectHdl, const OUString&, rCurItem, void)
2298
0
{
2299
0
    bGrabFocusToToolBox = pTextWin->GetToolBox().has_focus();
2300
0
    DoAction(rCurItem);
2301
0
}
2302
2303
IMPL_LINK_NOARG(SfxHelpWindow_Impl, OpenHdl, LinkParamNone*, void)
2304
0
{
2305
0
    xIndexWin->SelectExecutableEntry();
2306
0
    OUString aEntry = xIndexWin->GetSelectedEntry();
2307
2308
0
    if ( aEntry.isEmpty() )
2309
0
        return;
2310
2311
0
    OUString sHelpURL;
2312
2313
0
    bool bComplete = aEntry.toAsciiLowerCase().match("vnd.sun.star.help");
2314
2315
0
    if (bComplete)
2316
0
        sHelpURL = aEntry;
2317
0
    else
2318
0
    {
2319
0
        std::u16string_view aId;
2320
0
        OUString aAnchor('#');
2321
0
        if ( comphelper::string::getTokenCount(aEntry, '#') == 2 )
2322
0
        {
2323
0
            sal_Int32 nIdx{ 0 };
2324
0
            aId = o3tl::getToken(aEntry, 0, '#', nIdx );
2325
0
            aAnchor += o3tl::getToken(aEntry, 0, '#', nIdx );
2326
0
        }
2327
0
        else
2328
0
            aId = aEntry;
2329
2330
0
        sHelpURL = SfxHelpWindow_Impl::buildHelpURL(xIndexWin->GetFactory(), Concat2View(OUString::Concat("/") + aId), aAnchor);
2331
0
    }
2332
2333
0
    loadHelpContent(sHelpURL);
2334
0
}
2335
2336
IMPL_LINK( SfxHelpWindow_Impl, SelectFactoryHdl, SfxHelpIndexWindow_Impl* , pWin, void )
2337
0
{
2338
0
    if ( sTitle.isEmpty() )
2339
0
        sTitle = GetParent()->GetText();
2340
2341
0
    Reference< XTitle > xTitle(xFrame, UNO_QUERY);
2342
0
    if (xTitle.is ())
2343
0
        xTitle->setTitle(sTitle + " - " + xIndexWin->GetActiveFactoryTitle());
2344
2345
0
    if ( pWin )
2346
0
        ShowStartPage();
2347
0
    xIndexWin->ClearSearchPage();
2348
0
}
2349
2350
2351
IMPL_LINK( SfxHelpWindow_Impl, ChangeHdl, HelpListener_Impl&, rListener, void )
2352
0
{
2353
0
    SetFactory( rListener.GetFactory() );
2354
0
}
2355
2356
2357
void SfxHelpWindow_Impl::openDone(std::u16string_view sURL    ,
2358
                                        bool         bSuccess)
2359
0
{
2360
0
    INetURLObject aObj( sURL );
2361
0
    if ( aObj.GetProtocol() == INetProtocol::VndSunStarHelp )
2362
0
        SetFactory( aObj.GetHost() );
2363
0
    if ( IsWait() )
2364
0
        LeaveWait();
2365
0
    if ( bGrabFocusToToolBox )
2366
0
    {
2367
0
        pTextWin->GetToolBox().grab_focus();
2368
0
        bGrabFocusToToolBox = false;
2369
0
    }
2370
0
    else
2371
0
        xIndexWin->GrabFocusBack();
2372
0
    if ( !bSuccess )
2373
0
        return;
2374
2375
    // set some view settings: "prevent help tips" and "helpid == 68245"
2376
0
    try
2377
0
    {
2378
0
        Reference < XController > xController = pTextWin->getFrame()->getController();
2379
0
        if ( xController.is() )
2380
0
        {
2381
0
            Reference < XViewSettingsSupplier > xSettings( xController, UNO_QUERY );
2382
0
            Reference < XPropertySet > xViewProps = xSettings->getViewSettings();
2383
0
            Reference< XPropertySetInfo > xInfo = xViewProps->getPropertySetInfo();
2384
0
            xViewProps->setPropertyValue( u"ShowContentTips"_ustr, Any( false ) );
2385
0
            xViewProps->setPropertyValue( u"ShowGraphics"_ustr, Any( true ) );
2386
0
            xViewProps->setPropertyValue( u"ShowTables"_ustr, Any( true ) );
2387
0
            xViewProps->setPropertyValue( u"HelpURL"_ustr, Any( u"HID:SFX2_HID_HELP_ONHELP"_ustr ) );
2388
0
            OUString sProperty( u"IsExecuteHyperlinks"_ustr );
2389
0
            if ( xInfo->hasPropertyByName( sProperty ) )
2390
0
                xViewProps->setPropertyValue( sProperty, Any( true ) );
2391
0
            xController->restoreViewData(Any());
2392
0
        }
2393
0
    }
2394
0
    catch( Exception& )
2395
0
    {
2396
0
        TOOLS_WARN_EXCEPTION( "sfx.appl", "SfxHelpWindow_Impl::OpenDoneHdl(): unexpected exception" );
2397
0
    }
2398
2399
    // When the SearchPage opens the help doc, then select all words, which are equal to its text
2400
0
    OUString sSearchText = comphelper::string::strip(xIndexWin->GetSearchText(), ' ');
2401
0
    if ( !sSearchText.isEmpty() )
2402
0
        pTextWin->SelectSearchText( sSearchText, xIndexWin->IsFullWordSearch() );
2403
2404
    // no page style header -> this prevents a print output of the URL
2405
0
    pTextWin->SetPageStyleHeaderOff();
2406
0
}
2407
2408
2409
SfxHelpWindow_Impl::SfxHelpWindow_Impl(
2410
    const css::uno::Reference < css::frame::XFrame2 >& rFrame,
2411
    vcl::Window* pParent ) :
2412
2413
0
    ResizableDockingWindow(pParent),
2414
2415
0
    xFrame              ( rFrame ),
2416
0
    pTextWin            ( nullptr ),
2417
0
    pHelpInterceptor    ( new HelpInterceptor_Impl() ),
2418
0
    pHelpListener       ( new HelpListener_Impl( pHelpInterceptor ) ),
2419
0
    bIndex              ( true ),
2420
0
    bGrabFocusToToolBox ( false ),
2421
0
    bSplit              ( false ),
2422
0
    nWidth              ( 0 ),
2423
0
    nIndexSize          ( 40 ), // % of width
2424
0
    aWinPos             ( 0, 0 ),
2425
0
    aWinSize            ( 0, 0 ),
2426
0
    sTitle              ( pParent->GetText() )
2427
0
{
2428
0
    SetStyle(GetStyle() & ~WB_DOCKABLE);
2429
2430
0
    SetHelpId( HID_HELP_WINDOW );
2431
2432
0
    m_xBuilder = Application::CreateInterimBuilder(m_xBox.get(), u"sfx/ui/helpwindow.ui"_ustr, false);
2433
0
    m_xContainer = m_xBuilder->weld_paned(u"HelpWindow"_ustr);
2434
0
    m_xContainer->connect_size_allocate(LINK(this, SfxHelpWindow_Impl, ResizeHdl));
2435
0
    m_xHelpPaneWindow = m_xBuilder->weld_container(u"helppanewindow"_ustr);
2436
0
    m_xHelpTextWindow = m_xBuilder->weld_container(u"helptextwindow"_ustr);
2437
0
    m_xHelpTextXWindow = m_xHelpTextWindow->CreateChildFrame();
2438
2439
0
    pHelpInterceptor->InitWaiter( this );
2440
0
    xIndexWin.reset(new SfxHelpIndexWindow_Impl(this, m_xHelpPaneWindow.get()));
2441
0
    xIndexWin->SetDoubleClickHdl( LINK( this, SfxHelpWindow_Impl, OpenHdl ) );
2442
0
    xIndexWin->SetSelectFactoryHdl( LINK( this, SfxHelpWindow_Impl, SelectFactoryHdl ) );
2443
2444
0
    pTextWin = VclPtr<SfxHelpTextWindow_Impl>::Create(this, *m_xBuilder, VCLUnoHelper::GetWindow(m_xHelpTextXWindow));
2445
0
    Reference < XFrames > xFrames = rFrame->getFrames();
2446
0
    xFrames->append( Reference<XFrame>(pTextWin->getFrame(), UNO_QUERY_THROW) );
2447
0
    pTextWin->SetSelectHdl( LINK( this, SfxHelpWindow_Impl, SelectHdl ) );
2448
0
    pTextWin->Show();
2449
0
    pHelpInterceptor->setInterception( Reference<XFrame>(pTextWin->getFrame(), UNO_QUERY_THROW) );
2450
0
    pHelpListener->SetChangeHdl( LINK( this, SfxHelpWindow_Impl, ChangeHdl ) );
2451
0
    LoadConfig();
2452
0
}
Unexecuted instantiation: SfxHelpWindow_Impl::SfxHelpWindow_Impl(com::sun::star::uno::Reference<com::sun::star::frame::XFrame2> const&, vcl::Window*)
Unexecuted instantiation: SfxHelpWindow_Impl::SfxHelpWindow_Impl(com::sun::star::uno::Reference<com::sun::star::frame::XFrame2> const&, vcl::Window*)
2453
2454
SfxHelpWindow_Impl::~SfxHelpWindow_Impl()
2455
0
{
2456
0
    disposeOnce();
2457
0
}
2458
2459
void SfxHelpWindow_Impl::dispose()
2460
0
{
2461
0
    SaveConfig();
2462
0
    xIndexWin.reset();
2463
0
    pTextWin->CloseFrame();
2464
0
    pTextWin.disposeAndClear();
2465
2466
0
    m_xHelpTextXWindow->dispose();
2467
0
    m_xHelpTextXWindow.clear();
2468
0
    m_xHelpTextWindow.reset();
2469
0
    m_xHelpPaneWindow.reset();
2470
0
    m_xContainer.reset();
2471
0
    m_xBuilder.reset();
2472
2473
0
    ResizableDockingWindow::dispose();
2474
0
}
2475
2476
bool SfxHelpWindow_Impl::PreNotify( NotifyEvent& rNEvt )
2477
0
{
2478
0
    bool bHandled = false;
2479
0
    if ( rNEvt.GetType() == NotifyEventType::KEYINPUT )
2480
0
    {
2481
        // Backward == <ALT><LEFT> or <BACKSPACE> Forward == <ALT><RIGHT>
2482
0
        const vcl::KeyCode& rKeyCode = rNEvt.GetKeyEvent()->GetKeyCode();
2483
0
        sal_uInt16 nKey = rKeyCode.GetCode();
2484
0
        if ( ( rKeyCode.IsMod2() && ( KEY_LEFT == nKey || KEY_RIGHT == nKey ) ) ||
2485
0
             ( !rKeyCode.GetModifier() && KEY_BACKSPACE == nKey && !xIndexWin->HasFocusOnEdit() ) )
2486
0
        {
2487
0
            DoAction( rKeyCode.GetCode() == KEY_RIGHT ? u"forward" : u"backward" );
2488
0
            bHandled = true;
2489
0
        }
2490
0
        else if ( rKeyCode.IsMod1() && ( KEY_F4 == nKey || KEY_W == nKey ) )
2491
0
        {
2492
            // <CTRL><F4> or <CTRL><W> -> close top frame
2493
0
            CloseWindow();
2494
0
            bHandled = true;
2495
0
        }
2496
0
    }
2497
0
    return bHandled || Window::PreNotify( rNEvt );
2498
0
}
2499
2500
void SfxHelpWindow_Impl::setContainerWindow( const Reference < css::awt::XWindow >& xWin )
2501
0
{
2502
0
    xWindow = xWin;
2503
0
    MakeLayout();
2504
0
    if (xWindow.is())
2505
0
    {
2506
0
        VclPtr<vcl::Window> pScreenWin = VCLUnoHelper::GetWindow(xWindow);
2507
0
        if (aWinSize.Width() && aWinSize.Height())
2508
0
            pScreenWin->SetPosSizePixel(Point(aWinPos), aWinSize);
2509
0
        else
2510
0
            pScreenWin->SetPosPixel(Point(aWinPos));
2511
0
    }
2512
0
}
2513
2514
void SfxHelpWindow_Impl::SetFactory( const OUString& rFactory )
2515
0
{
2516
0
    xIndexWin->SetFactory( rFactory, true );
2517
0
}
2518
2519
void SfxHelpWindow_Impl::SetHelpURL( std::u16string_view rURL )
2520
0
{
2521
0
    INetURLObject aObj( rURL );
2522
0
    if ( aObj.GetProtocol() == INetProtocol::VndSunStarHelp )
2523
0
        SetFactory( aObj.GetHost() );
2524
0
}
2525
2526
void SfxHelpWindow_Impl::DoAction(std::u16string_view  rActionId)
2527
0
{
2528
0
    if (rActionId == u"index")
2529
0
    {
2530
0
        bIndex = !bIndex;
2531
0
        MakeLayout();
2532
0
        pTextWin->ToggleIndex( bIndex );
2533
0
    }
2534
0
    else if (rActionId == u"start")
2535
0
    {
2536
0
        ShowStartPage();
2537
0
    }
2538
0
    else if (rActionId == u"backward" || rActionId == u"forward")
2539
0
    {
2540
0
        URL aURL;
2541
0
        aURL.Complete = ".uno:Backward";
2542
0
        if (rActionId == u"forward")
2543
0
            aURL.Complete = ".uno:Forward";
2544
0
        Reference< util::XURLTransformer > xTrans( util::URLTransformer::create( ::comphelper::getProcessComponentContext() ) );
2545
0
        xTrans->parseStrict(aURL);
2546
0
        pHelpInterceptor->dispatch( aURL, Sequence < PropertyValue >() );
2547
0
    }
2548
0
    else if (rActionId == u"searchdialog")
2549
0
    {
2550
0
        pTextWin->DoSearch();
2551
0
    }
2552
0
    else if (rActionId == u"print" || rActionId == u"sourceview" || rActionId == u"copy" || rActionId == u"selectionmode")
2553
0
    {
2554
0
        Reference < XDispatchProvider > xProv = pTextWin->getFrame();
2555
0
        if ( xProv.is() )
2556
0
        {
2557
0
            URL aURL;
2558
0
            if (rActionId == u"print")
2559
0
                aURL.Complete = ".uno:Print";
2560
0
            else if (rActionId == u"sourceview")
2561
0
                aURL.Complete = ".uno:SourceView";
2562
0
            else if (rActionId == u"copy")
2563
0
                aURL.Complete = ".uno:Copy";
2564
0
            else // rActionId == "selectionmode"
2565
0
                aURL.Complete = ".uno:SelectTextMode";
2566
0
            Reference< util::XURLTransformer > xTrans( util::URLTransformer::create( ::comphelper::getProcessComponentContext() ) );
2567
0
            xTrans->parseStrict(aURL);
2568
0
            Reference < XDispatch > xDisp = xProv->queryDispatch( aURL, OUString(), 0 );
2569
0
            if ( xDisp.is() )
2570
0
                xDisp->dispatch( aURL, Sequence < PropertyValue >() );
2571
0
        }
2572
0
    }
2573
0
    else if (rActionId == u"bookmarks")
2574
0
    {
2575
0
        OUString aURL = pHelpInterceptor->GetCurrentURL();
2576
0
        if ( !aURL.isEmpty() )
2577
0
        {
2578
0
            try
2579
0
            {
2580
0
                Content aCnt( aURL, Reference< css::ucb::XCommandEnvironment >(), comphelper::getProcessComponentContext() );
2581
0
                css::uno::Reference< css::beans::XPropertySetInfo > xInfo = aCnt.getProperties();
2582
0
                if ( xInfo->hasPropertyByName( PROPERTY_TITLE ) )
2583
0
                {
2584
0
                    css::uno::Any aAny = aCnt.getPropertyValue( PROPERTY_TITLE );
2585
0
                    OUString aValue;
2586
0
                    if ( aAny >>= aValue )
2587
0
                    {
2588
0
                        SfxAddHelpBookmarkDialog_Impl aDlg(GetFrameWeld(), false);
2589
0
                        aDlg.SetTitle(aValue);
2590
0
                        if (aDlg.run() == RET_OK )
2591
0
                        {
2592
0
                            xIndexWin->AddBookmarks( aDlg.GetTitle(), aURL );
2593
0
                        }
2594
0
                    }
2595
0
                }
2596
0
            }
2597
0
            catch( Exception& )
2598
0
            {
2599
0
                TOOLS_WARN_EXCEPTION( "sfx.appl", "SfxHelpWindow_Impl::DoAction(): unexpected exception" );
2600
0
            }
2601
0
        }
2602
0
    }
2603
0
}
2604
2605
void SfxHelpWindow_Impl::CloseWindow()
2606
0
{
2607
0
    try
2608
0
    {
2609
        // search for top frame
2610
0
        Reference< XFramesSupplier > xCreator = getTextFrame()->getCreator();
2611
0
        while ( xCreator.is() && !xCreator->isTop() )
2612
0
        {
2613
0
            xCreator = xCreator->getCreator();
2614
0
        }
2615
2616
        // when found, close it
2617
0
        if ( xCreator.is() && xCreator->isTop() )
2618
0
        {
2619
0
            Reference < XCloseable > xCloser( xCreator, UNO_QUERY );
2620
0
            if ( xCloser.is() )
2621
0
                xCloser->close( false );
2622
0
        }
2623
0
    }
2624
0
    catch( Exception const & )
2625
0
    {
2626
0
        TOOLS_WARN_EXCEPTION( "sfx.appl", "SfxHelpWindow_Impl::CloseWindow()" );
2627
0
    }
2628
0
}
2629
2630
2631
void SfxHelpWindow_Impl::UpdateToolbox()
2632
0
{
2633
0
    pTextWin->GetToolBox().set_item_sensitive(u"backward"_ustr, pHelpInterceptor->HasHistoryPred());
2634
0
    pTextWin->GetToolBox().set_item_sensitive(u"forward"_ustr, pHelpInterceptor->HasHistorySucc());
2635
0
}
2636
2637
2638
bool SfxHelpWindow_Impl::HasHistoryPredecessor() const
2639
0
{
2640
0
    return pHelpInterceptor->HasHistoryPred();
2641
0
}
2642
2643
2644
bool SfxHelpWindow_Impl::HasHistorySuccessor() const
2645
0
{
2646
0
    return pHelpInterceptor->HasHistorySucc();
2647
0
}
2648
2649
// class SfxAddHelpBookmarkDialog_Impl -----------------------------------
2650
2651
SfxAddHelpBookmarkDialog_Impl::SfxAddHelpBookmarkDialog_Impl(weld::Widget* pParent, bool bRename)
2652
0
    : GenericDialogController(pParent, u"sfx/ui/bookmarkdialog.ui"_ustr, u"BookmarkDialog"_ustr)
2653
0
    , m_xTitleED(m_xBuilder->weld_entry(u"entry"_ustr))
2654
0
    , m_xAltTitle(m_xBuilder->weld_label(u"alttitle"_ustr))
2655
0
{
2656
0
    if (bRename)
2657
0
        m_xDialog->set_title(m_xAltTitle->get_label());
2658
0
}
2659
2660
void SfxAddHelpBookmarkDialog_Impl::SetTitle(const OUString& rTitle)
2661
0
{
2662
0
    m_xTitleED->set_text(rTitle);
2663
0
    m_xTitleED->select_region(0, -1);
2664
0
}
2665
2666
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */