/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include "newhelp.hxx"
#include <sfx2/sfxuno.hxx>
#include <sfx2/sfxresid.hxx>
#include "helpinterceptor.hxx"
#include <helper.hxx>
#include <sfx2/msgpool.hxx>
#include <sfx2/app.hxx>
#include <sfxtypes.hxx>
#include "panelist.hxx"
#include <srchdlg.hxx>
#include <sfx2/sfxhelp.hxx>
#include <svtools/treelistentry.hxx>
#include <sal/log.hxx>
#include <sfx2/strings.hrc>
#include <helpids.h>
#include <bitmaps.hlst>
#include <rtl/ustrbuf.hxx>
#include <comphelper/configurationhelper.hxx>
#include <comphelper/processfactory.hxx>
#include <comphelper/string.hxx>
#include <toolkit/helper/vclunohelper.hxx>
#include <com/sun/star/awt/PosSize.hpp>
#include <com/sun/star/awt/XWindow.hpp>
#include <com/sun/star/beans/Property.hpp>
#include <com/sun/star/beans/PropertyValue.hpp>
#include <com/sun/star/beans/XPropertySetInfo.hpp>
#include <com/sun/star/container/XIndexAccess.hpp>
#include <com/sun/star/frame/XComponentLoader.hpp>
#include <com/sun/star/frame/XTitle.hpp>
#include <com/sun/star/frame/XLayoutManager.hpp>
#include <com/sun/star/frame/XController.hpp>
#include <com/sun/star/frame/XDispatch.hpp>
#include <com/sun/star/frame/XDispatchProvider.hpp>
#include <com/sun/star/frame/Frame.hpp>
#include <com/sun/star/i18n/XBreakIterator.hpp>
#include <com/sun/star/i18n/WordType.hpp>
#include <com/sun/star/lang/XComponent.hpp>
#include <com/sun/star/lang/DisposedException.hpp>
#include <com/sun/star/style/XStyle.hpp>
#include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
#include <com/sun/star/text/XText.hpp>
#include <com/sun/star/text/XTextCursor.hpp>
#include <com/sun/star/text/XTextDocument.hpp>
#include <com/sun/star/text/XTextRange.hpp>
#include <com/sun/star/text/XTextViewCursor.hpp>
#include <com/sun/star/text/XTextViewCursorSupplier.hpp>
#include <com/sun/star/ucb/CommandAbortedException.hpp>
#include <com/sun/star/util/URL.hpp>
#include <com/sun/star/util/XSearchable.hpp>
#include <com/sun/star/util/XSearchDescriptor.hpp>
#include <com/sun/star/util/URLTransformer.hpp>
#include <com/sun/star/util/XURLTransformer.hpp>
#include <com/sun/star/util/XModifiable.hpp>
#include <com/sun/star/util/XCloseable.hpp>
#include <com/sun/star/util/CloseVetoException.hpp>
#include <com/sun/star/ui/XDockingAreaAcceptor.hpp>
#include <com/sun/star/view/XSelectionSupplier.hpp>
#include <com/sun/star/view/XViewSettingsSupplier.hpp>
#include <svtools/helpopt.hxx>
#include <unotools/historyoptions.hxx>
#include <svtools/menuoptions.hxx>
#include <unotools/pathoptions.hxx>
#include <unotools/viewoptions.hxx>
#include <tools/urlobj.hxx>
#include <unotools/streamhelper.hxx>
#include <svtools/imagemgr.hxx>
#include <svtools/miscopt.hxx>
#include <svtools/imgdef.hxx>
#include <vcl/builderfactory.hxx>
#include <vcl/unohelp.hxx>
#include <vcl/i18nhelp.hxx>
#include <vcl/layout.hxx>
#include <vcl/settings.hxx>
#include <vcl/weld.hxx>
#include <ucbhelper/content.hxx>
#include <vcl/waitobj.hxx>
#include <unotools/ucbhelper.hxx>
#include <sfx2/viewfrm.hxx>
#include <sfx2/objsh.hxx>
#include <sfx2/docfac.hxx>
#include <unordered_map>
#include <vector>
using namespace ::ucbhelper;
using namespace ::com::sun::star::ucb;
using namespace ::com::sun::star;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::container;
using namespace ::com::sun::star::frame;
using namespace ::com::sun::star::i18n;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::style;
using namespace ::com::sun::star::text;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::util;
using namespace ::com::sun::star::view;
using namespace ::com::sun::star::ui;
using namespace ::comphelper;
// defines ---------------------------------------------------------------
#define SPLITSET_ID 0
#define COLSET_ID 1
#define INDEXWIN_ID 2
#define TEXTWIN_ID 3
#define TOOLBOX_OFFSET 3
#define TBI_INDEX 1001
#define TBI_BACKWARD 1002
#define TBI_FORWARD 1003
#define TBI_START 1004
#define TBI_PRINT 1005
#define TBI_COPY 1006
#define TBI_BOOKMARKS 1007
#define TBI_SEARCHDIALOG 1008
#define TBI_SOURCEVIEW 1009
#define TBI_SELECTIONMODE 1010
#define CONFIGNAME_HELPWIN "OfficeHelp"
#define CONFIGNAME_INDEXWIN "OfficeHelpIndex"
#define CONFIGNAME_SEARCHPAGE "OfficeHelpSearch"
#define IMAGE_URL "private:factory/"
#define PROPERTY_KEYWORDLIST "KeywordList"
#define PROPERTY_KEYWORDREF "KeywordRef"
#define PROPERTY_ANCHORREF "KeywordAnchorForRef"
#define PROPERTY_TITLEREF "KeywordTitleForRef"
#define PROPERTY_TITLE "Title"
#define HELP_URL "vnd.sun.star.help://"
#define HELP_SEARCH_TAG "/?Query="
#define USERITEM_NAME "UserItem"
#define PACKAGE_SETUP "/org.openoffice.Setup"
#define PATH_OFFICE_FACTORIES "Office/Factories/"
#define KEY_HELP_ON_OPEN "ooSetupFactoryHelpOnOpen"
#define KEY_UI_NAME "ooSetupFactoryUIName"
namespace sfx2
{
void HandleTaskPaneList( vcl::Window* pWindow, bool bAddToList )
{
vcl::Window* pParent = pWindow->GetParent();
DBG_ASSERT( pParent, "HandleTaskPaneList(): every window here should have a parent" );
SystemWindow* pSysWin = pParent->GetSystemWindow();
if( pSysWin )
{
TaskPaneList* pTaskPaneList = pSysWin->GetTaskPaneList();
if( pTaskPaneList )
{
if( bAddToList )
pTaskPaneList->AddWindow( pWindow );
else
pTaskPaneList->RemoveWindow( pWindow );
}
}
}
/** Prepare a search string for searching or selecting.
For searching every search word needs the postfix '*' and the delimiter ' ' if necessary.
For selecting the delimiter '|' is required to search with regular expressions.
Samples:
search string | output for searching | output for selecting
-----------------------------------------------------------
"text" | "text*" | "text"
"text*" | "text*" | "text"
"text menu" | "text* menu*" | "text|menu"
*/
OUString PrepareSearchString( const OUString& rSearchString,
const Reference< XBreakIterator >& xBreak, bool bForSearch )
{
OUStringBuffer sSearchStr;
sal_Int32 nStartPos = 0;
const lang::Locale aLocale = Application::GetSettings().GetUILanguageTag().getLocale();
Boundary aBoundary = xBreak->getWordBoundary(
rSearchString, nStartPos, aLocale, WordType::ANYWORD_IGNOREWHITESPACES, true );
while ( aBoundary.startPos != aBoundary.endPos )
{
nStartPos = aBoundary.endPos;
OUString sSearchToken( rSearchString.copy(
static_cast<sal_uInt16>(aBoundary.startPos), static_cast<sal_uInt16>(aBoundary.endPos) - static_cast<sal_uInt16>(aBoundary.startPos) ) );
if ( !sSearchToken.isEmpty() && ( sSearchToken.getLength() > 1 || sSearchToken[0] != '.' ) )
{
if ( bForSearch && sSearchToken[ sSearchToken.getLength() - 1 ] != '*' )
sSearchToken += "*";
if ( sSearchToken.getLength() > 1 ||
( sSearchToken.getLength() > 0 && sSearchToken[ 0 ] != '*' ) )
{
if ( !sSearchStr.isEmpty() )
{
if ( bForSearch )
sSearchStr.append(" ");
else
sSearchStr.append("|");
}
sSearchStr.append(sSearchToken);
}
}
aBoundary = xBreak->nextWord( rSearchString, nStartPos,
aLocale, WordType::ANYWORD_IGNOREWHITESPACES );
}
return sSearchStr.makeStringAndClear();
}
// namespace sfx2
}
// struct IndexEntry_Impl ------------------------------------------------
struct IndexEntry_Impl
{
bool m_bSubEntry;
OUString m_aURL;
IndexEntry_Impl( const OUString& rURL, bool bSubEntry ) :
m_bSubEntry( bSubEntry ), m_aURL( rURL ) {}
};
// struct ContentEntry_Impl ----------------------------------------------
struct ContentEntry_Impl
{
OUString aURL;
bool bIsFolder;
ContentEntry_Impl( const OUString& rURL, bool bFolder ) :
aURL( rURL ), bIsFolder( bFolder ) {}
};
// ContentListBox_Impl ---------------------------------------------------
ContentListBox_Impl::ContentListBox_Impl(vcl::Window* pParent, WinBits nStyle)
: SvTreeListBox(pParent, nStyle)
, aOpenBookImage(BitmapEx(BMP_HELP_CONTENT_BOOK_OPEN))
, aClosedBookImage(BitmapEx(BMP_HELP_CONTENT_BOOK_CLOSED))
, aDocumentImage(BitmapEx(BMP_HELP_CONTENT_DOC))
{
SetStyle( GetStyle() | WB_HIDESELECTION | WB_HSCROLL );
SetEntryHeight( 16 );
SetSelectionMode( SelectionMode::Single );
SetSpaceBetweenEntries( 2 );
SetNodeBitmaps( aClosedBookImage, aOpenBookImage );
SetSublistOpenWithReturn();
SetSublistOpenWithLeftRight();
InitRoot();
}
extern "C" SAL_DLLPUBLIC_EXPORT void makeContentListBox(VclPtr<vcl::Window> & rRet, VclPtr<vcl::Window> & pParent, VclBuilder::stringmap & rMap)
{
WinBits nWinStyle = WB_TABSTOP;
OUString sBorder = BuilderUtils::extractCustomProperty(rMap);
if (!sBorder.isEmpty())
nWinStyle |= WB_BORDER;
rRet = VclPtr<ContentListBox_Impl>::Create(pParent, nWinStyle);
}
ContentListBox_Impl::~ContentListBox_Impl()
{
disposeOnce();
}
void ContentListBox_Impl::dispose()
{
sal_uInt16 nPos = 0;
SvTreeListEntry* pEntry = GetEntry( nPos++ );
while ( pEntry )
{
ClearChildren( pEntry );
delete static_cast<ContentEntry_Impl*>(pEntry->GetUserData());
pEntry = GetEntry( nPos++ );
}
SvTreeListBox::dispose();
}
void ContentListBox_Impl::InitRoot()
{
OUString const aHelpTreeviewURL( "vnd.sun.star.hier://com.sun.star.help.TreeView/" );
std::vector< OUString > aList =
SfxContentHelper::GetHelpTreeViewContents( aHelpTreeviewURL );
for(const OUString & aRow : aList)
{
sal_Int32 nIdx = 0;
OUString aTitle = aRow.getToken( 0, '\t', nIdx );
OUString aURL = aRow.getToken( 0, '\t', nIdx );
sal_Unicode cFolder = aRow.getToken( 0, '\t', nIdx )[0];
bool bIsFolder = ( '1' == cFolder );
SvTreeListEntry* pEntry = InsertEntry( aTitle, aOpenBookImage, aClosedBookImage, nullptr, true );
if ( bIsFolder )
pEntry->SetUserData( new ContentEntry_Impl( aURL, true ) );
}
}
void ContentListBox_Impl::ClearChildren( SvTreeListEntry* pParent )
{
SvTreeListEntry* pEntry = FirstChild( pParent );
while ( pEntry )
{
ClearChildren( pEntry );
delete static_cast<ContentEntry_Impl*>(pEntry->GetUserData());
pEntry = pEntry->NextSibling();
}
}
void ContentListBox_Impl::RequestingChildren( SvTreeListEntry* pParent )
{
try
{
if ( !pParent->HasChildren() )
{
if ( pParent->GetUserData() )
{
OUString aTmpURL( static_cast<ContentEntry_Impl*>(pParent->GetUserData())->aURL );
std::vector<OUString > aList =
SfxContentHelper::GetHelpTreeViewContents( aTmpURL );
for (const OUString & aRow : aList)
{
sal_Int32 nIdx = 0;
OUString aTitle = aRow.getToken( 0, '\t', nIdx );
OUString aURL = aRow.getToken( 0, '\t', nIdx );
sal_Unicode cFolder = aRow.getToken( 0, '\t', nIdx )[0];
bool bIsFolder = ( '1' == cFolder );
SvTreeListEntry* pEntry = nullptr;
if ( bIsFolder )
{
pEntry = InsertEntry( aTitle, aOpenBookImage, aClosedBookImage, pParent, true );
pEntry->SetUserData( new ContentEntry_Impl( aURL, true ) );
}
else
{
pEntry = InsertEntry( aTitle, aDocumentImage, aDocumentImage, pParent );
Any aAny( ::utl::UCBContentHelper::GetProperty( aURL, "TargetURL" ) );
OUString aTargetURL;
if ( aAny >>= aTargetURL )
pEntry->SetUserData( new ContentEntry_Impl( aTargetURL, false ) );
}
}
}
}
}
catch( Exception& )
{
OSL_FAIL( "ContentListBox_Impl::RequestingChildren(): unexpected exception" );
}
}
bool ContentListBox_Impl::EventNotify( NotifyEvent& rNEvt )
{
bool bHandled = false;
if ( rNEvt.GetType() == MouseNotifyEvent::KEYINPUT &&
KEY_RETURN == rNEvt.GetKeyEvent()->GetKeyCode().GetCode() )
{
GetDoubleClickHdl().Call( nullptr );
bHandled = true;
}
return bHandled || SvTreeListBox::EventNotify( rNEvt );
}
OUString ContentListBox_Impl::GetSelectedEntry() const
{
OUString aRet;
SvTreeListEntry* pEntry = FirstSelected();
if ( pEntry && !static_cast<ContentEntry_Impl*>(pEntry->GetUserData())->bIsFolder )
aRet = static_cast<ContentEntry_Impl*>(pEntry->GetUserData())->aURL;
return aRet;
}
// class HelpTabPage_Impl ------------------------------------------------
HelpTabPage_Impl::HelpTabPage_Impl(vcl::Window* pParent, SfxHelpIndexWindow_Impl* _pIdxWin,
const OString& rID, const OUString& rUIXMLDescription)
: TabPage( pParent, rID, rUIXMLDescription)
, m_pIdxWin( _pIdxWin )
{
}
HelpTabPage_Impl::~HelpTabPage_Impl()
{
disposeOnce();
}
void HelpTabPage_Impl::dispose()
{
m_pIdxWin.clear();
TabPage::dispose();
}
// class ContentTabPage_Impl ---------------------------------------------
ContentTabPage_Impl::ContentTabPage_Impl(vcl::Window* pParent, SfxHelpIndexWindow_Impl* _pIdxWin)
: HelpTabPage_Impl(pParent, _pIdxWin, "HelpContentPage",
"sfx/ui/helpcontentpage.ui")
{
get(m_pContentBox, "content");
Size aSize(LogicToPixel(Size(108 , 188), MapMode(MapUnit::MapAppFont)));
m_pContentBox->set_width_request(aSize.Width());
m_pContentBox->set_height_request(aSize.Height());
}
ContentTabPage_Impl::~ContentTabPage_Impl()
{
disposeOnce();
}
void ContentTabPage_Impl::dispose()
{
m_pContentBox.clear();
HelpTabPage_Impl::dispose();
}
void ContentTabPage_Impl::ActivatePage()
{
if ( !m_pIdxWin->WasCursorLeftOrRight() )
SetFocusOnBox();
}
Control* ContentTabPage_Impl::GetLastFocusControl()
{
return m_pContentBox;
}
// class IndexBox_Impl ---------------------------------------------------
IndexBox_Impl::IndexBox_Impl(vcl::Window* pParent, WinBits nStyle)
: ComboBox(pParent, nStyle)
{
EnableAutocomplete(true);
EnableUserDraw(true);
}
extern "C" SAL_DLLPUBLIC_EXPORT void makeIndexBox(VclPtr<vcl::Window> & rRet, VclPtr<vcl::Window> & pParent, VclBuilder::stringmap & rMap)
{
WinBits nWinBits = WB_CLIPCHILDREN|WB_LEFT|WB_VCENTER|WB_3DLOOK;
OUString sBorder = BuilderUtils::extractCustomProperty(rMap);
if (!sBorder.isEmpty())
nWinBits |= WB_BORDER;
VclPtrInstance<IndexBox_Impl> pListBox(pParent, nWinBits);
pListBox->EnableAutoSize(true);
rRet = pListBox;
}
void IndexBox_Impl::UserDraw( const UserDrawEvent& rUDEvt )
{
IndexEntry_Impl* pEntry = static_cast<IndexEntry_Impl*>(GetEntryData( rUDEvt.GetItemId() ));
if ( pEntry && pEntry->m_bSubEntry )
{
// indent sub entries
Point aPos( rUDEvt.GetRect().TopLeft() );
aPos.AdjustX(8 );
aPos.AdjustY((rUDEvt.GetRect().GetHeight() - rUDEvt.GetRenderContext()->GetTextHeight()) / 2 );
OUString aEntry( GetEntry( rUDEvt.GetItemId() ) );
sal_Int32 nPos = aEntry.indexOf( ';' );
rUDEvt.GetRenderContext()->DrawText(aPos, (nPos !=-1) ? aEntry.copy(nPos + 1) : aEntry);
}
else
DrawEntry( rUDEvt, false, true, true );
}
bool IndexBox_Impl::EventNotify( NotifyEvent& rNEvt )
{
bool bHandled = false;
if ( rNEvt.GetType() == MouseNotifyEvent::KEYINPUT &&
KEY_RETURN == rNEvt.GetKeyEvent()->GetKeyCode().GetCode() )
{
GetDoubleClickHdl().Call( *this );
bHandled = true;
}
return bHandled || ComboBox::EventNotify( rNEvt );
}
void IndexBox_Impl::SelectExecutableEntry()
{
sal_Int32 nPos = GetEntryPos( GetText() );
if ( nPos != COMBOBOX_ENTRY_NOTFOUND )
{
sal_Int32 nOldPos = nPos;
OUString aEntryText;
IndexEntry_Impl* pEntry = static_cast<IndexEntry_Impl*>(GetEntryData( nPos ));
sal_Int32 nCount = GetEntryCount();
while ( nPos < nCount && ( !pEntry || pEntry->m_aURL.isEmpty() ) )
{
pEntry = static_cast<IndexEntry_Impl*>(GetEntryData( ++nPos ));
aEntryText = GetEntry( nPos );
}
if ( nOldPos != nPos )
SetText( aEntryText );
}
}
// class IndexTabPage_Impl -----------------------------------------------
IndexTabPage_Impl::IndexTabPage_Impl(vcl::Window* pParent, SfxHelpIndexWindow_Impl* _pIdxWin)
: HelpTabPage_Impl(pParent, _pIdxWin, "HelpIndexPage",
"sfx/ui/helpindexpage.ui")
, aFactoryIdle("sfx2 appl IndexTabPage_Impl Factory")
, bIsActivated(false)
{
get(m_pIndexCB, "terms");
Size aSize(LogicToPixel(Size(108, 97), MapMode(MapUnit::MapAppFont)));
m_pIndexCB->set_width_request(aSize.Width());
m_pIndexCB->set_height_request(aSize.Height());
get(m_pOpenBtn, "display");
m_pOpenBtn->SetClickHdl( LINK( this, IndexTabPage_Impl, OpenHdl ) );
aFactoryIdle.SetInvokeHandler( LINK(this, IndexTabPage_Impl, IdleHdl ));
aKeywordTimer.SetInvokeHandler( LINK( this, IndexTabPage_Impl, TimeoutHdl ) );
}
IndexTabPage_Impl::~IndexTabPage_Impl()
{
disposeOnce();
}
void IndexTabPage_Impl::dispose()
{
ClearIndex();
m_pIndexCB.clear();
m_pOpenBtn.clear();
HelpTabPage_Impl::dispose();
}
namespace sfx2 {
typedef std::unordered_map< OUString, int > KeywordInfo;
}
void IndexTabPage_Impl::InitializeIndex()
{
WaitObject aWaitCursor( this );
// By now more than 256 equal entries are not allowed
sal_Unicode append[256];
for(sal_Unicode & k : append)
k = ' ';
sfx2::KeywordInfo aInfo;
m_pIndexCB->SetUpdateMode( false );
try
{
OUStringBuffer aURL = HELP_URL;
aURL.append(sFactory);
AppendConfigToken(aURL, true);
Content aCnt( aURL.makeStringAndClear(), Reference< css::ucb::XCommandEnvironment >(), comphelper::getProcessComponentContext() );
css::uno::Reference< css::beans::XPropertySetInfo > xInfo = aCnt.getProperties();
if ( xInfo->hasPropertyByName( PROPERTY_ANCHORREF ) )
{
css::uno::Sequence< OUString > aPropSeq( 4 );
aPropSeq[0] = PROPERTY_KEYWORDLIST;
aPropSeq[1] = PROPERTY_KEYWORDREF;
aPropSeq[2] = PROPERTY_ANCHORREF;
aPropSeq[3] = PROPERTY_TITLEREF;
// abi: use one possibly remote call only
css::uno::Sequence< css::uno::Any > aAnySeq =
aCnt.getPropertyValues( aPropSeq );
css::uno::Sequence< OUString > aKeywordList;
css::uno::Sequence< css::uno::Sequence< OUString > > aKeywordRefList;
css::uno::Sequence< css::uno::Sequence< OUString > > aAnchorRefList;
css::uno::Sequence< css::uno::Sequence< OUString > > aTitleRefList;
if ( ( aAnySeq[0] >>= aKeywordList ) && ( aAnySeq[1] >>= aKeywordRefList ) &&
( aAnySeq[2] >>= aAnchorRefList ) && ( aAnySeq[3] >>= aTitleRefList ) )
{
sal_Int32 nPos;
int ndx,tmp;
OUString aIndex, aTempString;
OUStringBuffer aData( 128 ); // Capacity of up to 128 characters
sfx2::KeywordInfo::iterator it;
for ( int i = 0; i < aKeywordList.getLength(); ++i )
{
// abi: Do not copy, but use references
const OUString& aKeywordPair = aKeywordList[i];
DBG_ASSERT( !aKeywordPair.isEmpty(), "invalid help index" );
const css::uno::Sequence< OUString >& aRefList = aKeywordRefList[i];
const css::uno::Sequence< OUString >& aAnchorList = aAnchorRefList[i];
const css::uno::Sequence< OUString >& aTitleList = aTitleRefList[i];
DBG_ASSERT( aRefList.getLength() == aAnchorList.getLength(),"reference list and title list of different length" );
const bool insert = ( ndx = aKeywordPair.indexOf( ';' ) ) != -1;
if ( insert )
{
aTempString = aKeywordPair.copy( 0, ndx );
if ( aIndex != aTempString )
{
aIndex = aTempString;
it = aInfo.emplace(aTempString, 0).first;
if ( (tmp = it->second++) != 0)
m_pIndexCB->InsertEntry(aTempString + OUString(append, tmp));
else
m_pIndexCB->InsertEntry(aTempString); }
}
else
aIndex.clear();
// Assume the token is trimmed
it = aInfo.emplace(aKeywordPair, 0).first;
if ((tmp = it->second++) != 0)
nPos = m_pIndexCB->InsertEntry(aKeywordPair + OUString(append, tmp));
else
nPos = m_pIndexCB->InsertEntry(aKeywordPair);
sal_uInt32 nRefListLen = aRefList.getLength();
DBG_ASSERT( aAnchorList.getLength(), "*IndexTabPage_Impl::InitializeIndex(): AnchorList is empty!" );
DBG_ASSERT( nRefListLen, "*IndexTabPage_Impl::InitializeIndex(): RefList is empty!" );
if ( aAnchorList.getLength() && nRefListLen )
{
if ( aAnchorList[0].getLength() > 0 )
{
aData.append( aRefList[0] ).append( '#' ).append( aAnchorList[0] );
m_pIndexCB->SetEntryData( nPos, new IndexEntry_Impl( aData.makeStringAndClear(), insert ) );
}
else
m_pIndexCB->SetEntryData( nPos, new IndexEntry_Impl( aRefList[0], insert ) );
}
for ( sal_uInt32 j = 1; j < nRefListLen ; ++j )
{
aData
.append( aKeywordPair )
.append( ' ' )
.append( '-' )
.append( ' ' )
.append( aTitleList[j] );
aTempString = aData.makeStringAndClear();
it = aInfo.emplace(aTempString, 0).first;
if ( (tmp = it->second++) != 0 )
nPos = m_pIndexCB->InsertEntry(aTempString + OUString(append, tmp));
else
nPos = m_pIndexCB->InsertEntry(aTempString);
if ( aAnchorList[j].getLength() > 0 )
{
aData.append( aRefList[j] ).append( '#' ).append( aAnchorList[j] );
m_pIndexCB->SetEntryData( nPos, new IndexEntry_Impl( aData.makeStringAndClear(), insert ) );
}
else
m_pIndexCB->SetEntryData( nPos, new IndexEntry_Impl( aRefList[j], insert ) );
}
}
}
}
}
catch( Exception& )
{
OSL_FAIL( "IndexTabPage_Impl::InitializeIndex(): unexpected exception" );
}
m_pIndexCB->SetUpdateMode( true );
if ( !sKeyword.isEmpty() )
aKeywordLink.Call( *this );
}
void IndexTabPage_Impl::ClearIndex()
{
const sal_Int32 nCount = m_pIndexCB->GetEntryCount();
for ( sal_Int32 i = 0; i < nCount; ++i )
delete static_cast<IndexEntry_Impl*>(m_pIndexCB->GetEntryData(i));
m_pIndexCB->Clear();
}
IMPL_LINK_NOARG(IndexTabPage_Impl, OpenHdl, Button*, void)
{
m_pIndexCB->GetDoubleClickHdl().Call(*m_pIndexCB);
}
IMPL_LINK( IndexTabPage_Impl, IdleHdl, Timer*, pIdle, void )
{
if ( &aFactoryIdle == pIdle )
InitializeIndex();
}
IMPL_LINK( IndexTabPage_Impl, TimeoutHdl, Timer*, pTimer, void)
{
if(&aKeywordTimer == pTimer && !sKeyword.isEmpty())
aKeywordLink.Call(*this);
}
void IndexTabPage_Impl::ActivatePage()
{
if ( !bIsActivated )
{
bIsActivated = true;
aFactoryIdle.Start();
}
if ( !m_pIdxWin->WasCursorLeftOrRight() )
SetFocusOnBox();
}
Control* IndexTabPage_Impl::GetLastFocusControl()
{
return m_pOpenBtn;
}
void IndexTabPage_Impl::SetDoubleClickHdl( const Link<ComboBox&,void>& rLink )
{
m_pIndexCB->SetDoubleClickHdl( rLink );
}
void IndexTabPage_Impl::SetFactory( const OUString& rFactory )
{
OUString sNewFactory( rFactory );
DBG_ASSERT( !sNewFactory.isEmpty(), "empty factory" );
bool bValid = m_pIdxWin->IsValidFactory( rFactory );
if ( sFactory.isEmpty() && !bValid )
{
sNewFactory = SfxHelp::GetDefaultHelpModule();
bValid = true;
}
if ( sNewFactory != sFactory && bValid )
{
sFactory = sNewFactory;
ClearIndex();
if ( bIsActivated )
aFactoryIdle.Start();
}
}
OUString IndexTabPage_Impl::GetSelectedEntry() const
{
OUString aRet;
IndexEntry_Impl* pEntry = static_cast<IndexEntry_Impl*>(m_pIndexCB->GetEntryData( m_pIndexCB->GetEntryPos( m_pIndexCB->GetText() ) ));
if ( pEntry )
aRet = pEntry->m_aURL;
return aRet;
}
void IndexTabPage_Impl::SetKeyword( const OUString& rKeyword )
{
sKeyword = rKeyword;
if ( m_pIndexCB->GetEntryCount() > 0 )
aKeywordTimer.Start();
else if ( !bIsActivated )
aFactoryIdle.Start();
}
bool IndexTabPage_Impl::HasKeyword() const
{
bool bRet = false;
if ( !sKeyword.isEmpty() )
{
sal_Int32 nPos = m_pIndexCB->GetEntryPos( sKeyword );
bRet = ( nPos != LISTBOX_ENTRY_NOTFOUND );
}
return bRet;
}
bool IndexTabPage_Impl::HasKeywordIgnoreCase()
{
bool bRet = false;
if ( !sKeyword.isEmpty() )
{
sal_Int32 nEntries = m_pIndexCB->GetEntryCount();
OUString sIndexItem;
const vcl::I18nHelper& rI18nHelper = GetSettings().GetLocaleI18nHelper();
for ( sal_Int32 n = 0; n < nEntries; n++)
{
sIndexItem = m_pIndexCB->GetEntry( n );
if (rI18nHelper.MatchString( sIndexItem, sKeyword ))
{
sKeyword = sIndexItem;
bRet = true;
}
}
}
return bRet;
}
void IndexTabPage_Impl::OpenKeyword()
{
if ( !sKeyword.isEmpty() )
{
m_pIndexCB->SetText( sKeyword );
m_pIndexCB->GetDoubleClickHdl().Call( *m_pIndexCB );
sKeyword.clear();
}
}
// class SearchBox_Impl --------------------------------------------------
extern "C" SAL_DLLPUBLIC_EXPORT void makeSearchBox(VclPtr<vcl::Window> & rRet, VclPtr<vcl::Window> & pParent, VclBuilder::stringmap &)
{
WinBits nWinBits = WB_CLIPCHILDREN|WB_LEFT|WB_VCENTER|WB_3DLOOK|WB_SIMPLEMODE|WB_DROPDOWN;
VclPtrInstance<SearchBox_Impl> pComboBox(pParent, nWinBits);
pComboBox->EnableAutoSize(true);
rRet = pComboBox;
}
bool SearchBox_Impl::PreNotify( NotifyEvent& rNEvt )
{
bool bHandled = false;
if ( !IsInDropDown() &&
rNEvt.GetWindow() == GetSubEdit() &&
rNEvt.GetType() == MouseNotifyEvent::KEYINPUT &&
KEY_RETURN == rNEvt.GetKeyEvent()->GetKeyCode().GetCode() )
{
aSearchLink.Call( nullptr );
bHandled = true;
}
return bHandled || ComboBox::PreNotify( rNEvt );
}
void SearchBox_Impl::Select()
{
if ( !IsTravelSelect() )
aSearchLink.Call( nullptr );
}
// class SearchResultsBox_Impl -------------------------------------------
extern "C" SAL_DLLPUBLIC_EXPORT void makeSearchResultsBox(VclPtr<vcl::Window> & rRet, VclPtr<vcl::Window> & pParent, VclBuilder::stringmap & rMap)
{
WinBits nWinBits = WB_CLIPCHILDREN|WB_LEFT|WB_VCENTER|WB_3DLOOK;
OUString sBorder = BuilderUtils::extractCustomProperty(rMap);
if (!sBorder.isEmpty())
nWinBits |= WB_BORDER;
VclPtrInstance<SearchResultsBox_Impl> pListBox(pParent, nWinBits);
pListBox->EnableAutoSize(true);
rRet = pListBox;
}
bool SearchResultsBox_Impl::EventNotify( NotifyEvent& rNEvt )
{
bool bHandled = false;
if ( rNEvt.GetType() == MouseNotifyEvent::KEYINPUT &&
KEY_RETURN == rNEvt.GetKeyEvent()->GetKeyCode().GetCode() )
{
GetDoubleClickHdl().Call( *this );
bHandled = true;
}
return bHandled || ListBox::EventNotify( rNEvt );
}
// class SearchTabPage_Impl ----------------------------------------------
SearchTabPage_Impl::SearchTabPage_Impl(vcl::Window* pParent, SfxHelpIndexWindow_Impl* _pIdxWin)
: HelpTabPage_Impl(pParent, _pIdxWin, "HelpSearchPage",
"sfx/ui/helpsearchpage.ui")
, xBreakIterator(vcl::unohelper::CreateBreakIterator())
{
get(m_pSearchED, "search");
get(m_pSearchBtn, "find");
get(m_pFullWordsCB, "completewords");
get(m_pScopeCB, "headings");
get(m_pResultsLB, "results");
Size aSize(LogicToPixel(Size(128 , 30), MapMode(MapUnit::MapAppFont)));
m_pResultsLB->set_width_request(aSize.Width());
m_pResultsLB->set_height_request(aSize.Height());
get(m_pOpenBtn, "display");
m_pSearchED->SetSearchLink( LINK( this, SearchTabPage_Impl, SearchHdl ) );
m_pSearchBtn->SetClickHdl(LINK( this, SearchTabPage_Impl, ClickHdl ));
m_pSearchED->SetModifyHdl( LINK( this, SearchTabPage_Impl, ModifyHdl ) );
m_pOpenBtn->SetClickHdl( LINK( this, SearchTabPage_Impl, OpenHdl ) );
SvtViewOptions aViewOpt( EViewType::TabPage, CONFIGNAME_SEARCHPAGE );
if ( aViewOpt.Exists() )
{
OUString aUserData;
Any aUserItem = aViewOpt.GetUserItem( USERITEM_NAME );
if ( aUserItem >>= aUserData )
{
sal_Int32 nIdx {0};
bool bChecked = aUserData.getToken(0, ';', nIdx).toInt32() == 1;
m_pFullWordsCB->Check( bChecked );
bChecked = aUserData.getToken(0, ';', nIdx).toInt32() == 1;
m_pScopeCB->Check( bChecked );
while ( nIdx > 0 )
{
m_pSearchED->InsertEntry( INetURLObject::decode(
aUserData.getToken(0, ';', nIdx),
INetURLObject::DecodeMechanism::WithCharset ) );
}
}
}
ModifyHdl(*m_pSearchED);
}
SearchTabPage_Impl::~SearchTabPage_Impl()
{
disposeOnce();
}
void SearchTabPage_Impl::dispose()
{
SvtViewOptions aViewOpt( EViewType::TabPage, CONFIGNAME_SEARCHPAGE );
OUStringBuffer aUserData;
aUserData.append(OUString::number( m_pFullWordsCB->IsChecked() ? 1 : 0 ))
.append(";")
.append(OUString::number( m_pScopeCB->IsChecked() ? 1 : 0 ));
sal_Int32 nCount = std::min( m_pSearchED->GetEntryCount(), sal_Int32(10) ); // save only 10 entries
for ( sal_Int32 i = 0; i < nCount; ++i )
{
aUserData.append(";").append(INetURLObject::encode(
m_pSearchED->GetEntry(i),
INetURLObject::PART_UNO_PARAM_VALUE,
INetURLObject::EncodeMechanism::All ));
}
Any aUserItem = makeAny( aUserData.makeStringAndClear() );
aViewOpt.SetUserItem( USERITEM_NAME, aUserItem );
m_pSearchED.clear();
m_pSearchBtn.clear();
m_pFullWordsCB.clear();
m_pScopeCB.clear();
m_pResultsLB.clear();
m_pOpenBtn.clear();
HelpTabPage_Impl::dispose();
}
void SearchTabPage_Impl::ClearSearchResults()
{
const sal_Int32 nCount = m_pResultsLB->GetEntryCount();
for ( sal_Int32 i = 0; i < nCount; ++i )
delete static_cast<OUString*>(m_pResultsLB->GetEntryData(i));
m_pResultsLB->Clear();
m_pResultsLB->Update();
}
void SearchTabPage_Impl::RememberSearchText( const OUString& rSearchText )
{
for ( sal_Int32 i = 0; i < m_pSearchED->GetEntryCount(); ++i )
{
if ( rSearchText == m_pSearchED->GetEntry(i) )
{
m_pSearchED->RemoveEntryAt(i);
break;
}
}
m_pSearchED->InsertEntry( rSearchText, 0 );
}
IMPL_LINK_NOARG(SearchTabPage_Impl, ClickHdl, Button*, void)
{
SearchHdl(nullptr);
}
IMPL_LINK_NOARG(SearchTabPage_Impl, SearchHdl, LinkParamNone*, void)
{
OUString aSearchText = comphelper::string::strip(m_pSearchED->GetText(), ' ');
if ( !aSearchText.isEmpty() )
{
EnterWait();
ClearSearchResults();
RememberSearchText( aSearchText );
OUStringBuffer aSearchURL(HELP_URL);
aSearchURL.append(aFactory);
aSearchURL.append(HELP_SEARCH_TAG);
if ( !m_pFullWordsCB->IsChecked() )
aSearchText = sfx2::PrepareSearchString( aSearchText, xBreakIterator, true );
aSearchURL.append(aSearchText);
AppendConfigToken(aSearchURL, false);
if ( m_pScopeCB->IsChecked() )
aSearchURL.append("&Scope=Heading");
std::vector< OUString > aFactories = SfxContentHelper::GetResultSet(aSearchURL.makeStringAndClear());
for (const OUString & rRow : aFactories)
{
sal_Int32 nIdx = 0;
OUString aTitle = rRow.getToken( 0, '\t', nIdx );
nIdx = 0;
OUString* pURL = new OUString( rRow.getToken( 2, '\t', nIdx ) );
const sal_Int32 nPos = m_pResultsLB->InsertEntry( aTitle );
m_pResultsLB->SetEntryData( nPos, pURL );
}
LeaveWait();
if ( aFactories.empty() )
{
std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(GetFrameWeld(),
VclMessageType::Info, VclButtonsType::Ok,
SfxResId(STR_INFO_NOSEARCHRESULTS)));
xBox->run();
}
}
}
IMPL_LINK_NOARG(SearchTabPage_Impl, OpenHdl, Button*, void)
{
m_pResultsLB->GetDoubleClickHdl().Call(*m_pResultsLB);
}
IMPL_LINK_NOARG(SearchTabPage_Impl, ModifyHdl, Edit&, void)
{
OUString aSearchText = comphelper::string::strip(m_pSearchED->GetText(), ' ');
m_pSearchBtn->Enable(!aSearchText.isEmpty());
}
void SearchTabPage_Impl::ActivatePage()
{
if ( !m_pIdxWin->WasCursorLeftOrRight() )
m_pSearchED->GrabFocus();
}
Control* SearchTabPage_Impl::GetLastFocusControl()
{
return m_pOpenBtn;
}
void SearchTabPage_Impl::SetDoubleClickHdl( const Link<ListBox&,void>& rLink )
{
m_pResultsLB->SetDoubleClickHdl( rLink );
}
OUString SearchTabPage_Impl::GetSelectedEntry() const
{
OUString aRet;
OUString* pData = static_cast<OUString*>(m_pResultsLB->GetSelectedEntryData());
if ( pData )
aRet = *pData;
return aRet;
}
void SearchTabPage_Impl::ClearPage()
{
ClearSearchResults();
m_pSearchED->SetText( OUString() );
}
bool SearchTabPage_Impl::OpenKeyword( const OUString& rKeyword )
{
bool bRet = false;
m_pSearchED->SetText( rKeyword );
SearchHdl( nullptr );
if ( m_pResultsLB->GetEntryCount() > 0 )
{
// found keyword -> open it
m_pResultsLB->SelectEntryPos(0);
OpenHdl( nullptr );
bRet = true;
}
return bRet;
}
// class BookmarksTabPage_Impl -------------------------------------------
void GetBookmarkEntry_Impl
(
Sequence< PropertyValue >& aBookmarkEntry,
OUString& rTitle,
OUString& rURL
)
{
for ( int i = 0; i < aBookmarkEntry.getLength(); i++ )
{
PropertyValue aValue = aBookmarkEntry[i];
if ( aValue.Name == HISTORY_PROPERTYNAME_URL )
aValue.Value >>= rURL;
else if ( aValue.Name == HISTORY_PROPERTYNAME_TITLE )
aValue.Value >>= rTitle;
}
}
BookmarksBox_Impl::BookmarksBox_Impl(vcl::Window* pParent, WinBits nStyle)
: ListBox(pParent, nStyle)
{
}
extern "C" SAL_DLLPUBLIC_EXPORT void makeBookmarksBox(VclPtr<vcl::Window> & rRet, VclPtr<vcl::Window> & pParent, VclBuilder::stringmap & rMap)
{
WinBits nWinBits = WB_CLIPCHILDREN|WB_LEFT|WB_VCENTER|WB_3DLOOK|WB_SIMPLEMODE;
OUString sBorder = BuilderUtils::extractCustomProperty(rMap);
if (!sBorder.isEmpty())
nWinBits |= WB_BORDER;
VclPtrInstance<BookmarksBox_Impl> pListBox(pParent, nWinBits);
pListBox->EnableAutoSize(true);
rRet = pListBox;
}
BookmarksBox_Impl::~BookmarksBox_Impl()
{
disposeOnce();
}
void BookmarksBox_Impl::dispose()
{
// save bookmarks to configuration
SvtHistoryOptions aHistOpt;
aHistOpt.Clear( eHELPBOOKMARKS );
const sal_Int32 nCount = GetEntryCount();
for ( sal_Int32 i = 0; i < nCount; ++i )
{
OUString aTitle = GetEntry(i);
OUString* pURL = static_cast<OUString*>(GetEntryData(i));
aHistOpt.AppendItem(eHELPBOOKMARKS, *pURL, "", aTitle, boost::none);
delete pURL;
}
ListBox::dispose();
}
void BookmarksBox_Impl::DoAction( sal_uInt16 nAction )
{
switch ( nAction )
{
case MID_OPEN :
GetDoubleClickHdl().Call( *this );
break;
case MID_RENAME :
{
sal_Int32 nPos = GetSelectedEntryPos();
if ( nPos != LISTBOX_ENTRY_NOTFOUND )
{
SfxAddHelpBookmarkDialog_Impl aDlg(GetFrameWeld(), true);
aDlg.SetTitle(GetEntry(nPos));
if (aDlg.run() == RET_OK)
{
OUString* pURL = static_cast<OUString*>(GetEntryData( nPos ));
RemoveEntry( nPos );
OUString aImageURL = IMAGE_URL;
aImageURL += INetURLObject( *pURL ).GetHost();
nPos = InsertEntry( aDlg.GetTitle(), SvFileInformationManager::GetImage( INetURLObject(aImageURL) ) );
SetEntryData( nPos, new OUString( *pURL ) );
SelectEntryPos( nPos );
delete pURL;
}
}
break;
}
case MID_DELETE :
{
sal_Int32 nPos = GetSelectedEntryPos();
if ( nPos != LISTBOX_ENTRY_NOTFOUND )
{
RemoveEntry( nPos );
const sal_Int32 nCount = GetEntryCount();
if ( nCount )
{
if ( nPos >= nCount )
nPos = nCount - 1;
SelectEntryPos( nPos );
}
}
break;
}
}
}
bool BookmarksBox_Impl::EventNotify( NotifyEvent& rNEvt )
{
bool bRet = false;
MouseNotifyEvent nType = rNEvt.GetType();
if ( MouseNotifyEvent::KEYINPUT == nType )
{
sal_uInt16 nCode = rNEvt.GetKeyEvent()->GetKeyCode().GetCode();
if ( KEY_DELETE == nCode && GetEntryCount() > 0 )
{
DoAction( MID_DELETE );
bRet = true;
}
else if ( KEY_RETURN == nCode )
{
GetDoubleClickHdl().Call( *this );
bRet = true;
}
}
else if ( MouseNotifyEvent::COMMAND == nType )
{
const CommandEvent* pCEvt = rNEvt.GetCommandEvent();
if ( pCEvt->GetCommand() == CommandEventId::ContextMenu )
{
VclBuilder aBuilder(nullptr, VclBuilderContainer::getUIRootDir(), "sfx/ui/bookmarkmenu.ui", "");
VclPtr<PopupMenu> aMenu(aBuilder.get_menu("menu"));
sal_uInt16 nId = aMenu->Execute(this, pCEvt->GetMousePosPixel());
if (nId != MENU_ITEM_NOTFOUND)
{
OString sIdent = aMenu->GetCurItemIdent();
if (sIdent == "display")
DoAction(MID_OPEN);
else if (sIdent == "rename")
DoAction(MID_RENAME);
else if (sIdent == "delete")
DoAction(MID_DELETE);
}
bRet = true;
}
}
return bRet || ListBox::EventNotify( rNEvt );
}
// class BookmarksTabPage_Impl -------------------------------------------
BookmarksTabPage_Impl::BookmarksTabPage_Impl(vcl::Window* pParent, SfxHelpIndexWindow_Impl* _pIdxWin)
: HelpTabPage_Impl(pParent, _pIdxWin, "HelpBookmarkPage",
"sfx/ui/helpbookmarkpage.ui")
{
get(m_pBookmarksPB, "display");
get(m_pBookmarksBox, "bookmarks");
Size aSize(LogicToPixel(Size(120 , 200), MapMode(MapUnit::MapAppFont)));
m_pBookmarksBox->set_width_request(aSize.Width());
m_pBookmarksBox->set_height_request(aSize.Height());
m_pBookmarksPB->SetClickHdl( LINK( this, BookmarksTabPage_Impl, OpenHdl ) );
// load bookmarks from configuration
Sequence< Sequence< PropertyValue > > aBookmarkSeq;
aBookmarkSeq = SvtHistoryOptions().GetList( eHELPBOOKMARKS );
OUString aTitle;
OUString aURL;
sal_uInt32 i, nCount = aBookmarkSeq.getLength();
for ( i = 0; i < nCount; ++i )
{
GetBookmarkEntry_Impl( aBookmarkSeq[i], aTitle, aURL );
AddBookmarks( aTitle, aURL );
}
}
BookmarksTabPage_Impl::~BookmarksTabPage_Impl()
{
disposeOnce();
}
void BookmarksTabPage_Impl::dispose()
{
m_pBookmarksBox.clear();
m_pBookmarksPB.clear();
HelpTabPage_Impl::dispose();
}
IMPL_LINK_NOARG(BookmarksTabPage_Impl, OpenHdl, Button*, void)
{
m_pBookmarksBox->GetDoubleClickHdl().Call(*m_pBookmarksBox);
}
void BookmarksTabPage_Impl::ActivatePage()
{
if ( !m_pIdxWin->WasCursorLeftOrRight() )
SetFocusOnBox();
}
Control* BookmarksTabPage_Impl::GetLastFocusControl()
{
return m_pBookmarksPB;
}
void BookmarksTabPage_Impl::SetDoubleClickHdl( const Link<ListBox&,void>& rLink )
{
m_pBookmarksBox->SetDoubleClickHdl(rLink);
}
OUString BookmarksTabPage_Impl::GetSelectedEntry() const
{
OUString aRet;
OUString* pData = static_cast<OUString*>(m_pBookmarksBox->GetSelectedEntryData());
if ( pData )
aRet = *pData;
return aRet;
}
void BookmarksTabPage_Impl::AddBookmarks( const OUString& rTitle, const OUString& rURL )
{
OUString aImageURL = IMAGE_URL;
aImageURL += INetURLObject( rURL ).GetHost();
const sal_Int32 nPos = m_pBookmarksBox->InsertEntry( rTitle, SvFileInformationManager::GetImage( INetURLObject(aImageURL) ) );
m_pBookmarksBox->SetEntryData( nPos, new OUString( rURL ) );
}
OUString SfxHelpWindow_Impl::buildHelpURL(const OUString& sFactory ,
const OUString& sContent ,
const OUString& sAnchor)
{
OUStringBuffer sHelpURL(256);
sHelpURL.append(HELP_URL);
sHelpURL.append(sFactory);
sHelpURL.append(sContent);
AppendConfigToken(sHelpURL, true/*bUseQuestionMark*/);
if (!sAnchor.isEmpty())
sHelpURL.append(sAnchor);
return sHelpURL.makeStringAndClear();
}
void SfxHelpWindow_Impl::loadHelpContent(const OUString& sHelpURL, bool bAddToHistory)
{
Reference< XComponentLoader > xLoader(getTextFrame(), UNO_QUERY);
if (!xLoader.is())
return;
// If a print job runs do not open a new page
Reference< XFrame2 > xTextFrame = pTextWin->getFrame();
Reference< XController > xTextController ;
if (xTextFrame.is())
xTextController = xTextFrame->getController ();
if ( xTextController.is() && !xTextController->suspend( true ) )
{
xTextController->suspend( false );
return;
}
// save url to history
if (bAddToHistory)
pHelpInterceptor->addURL(sHelpURL);
if ( !IsWait() )
EnterWait();
bool bSuccess = false;
// TODO implement locale fallback ... see below while(true)
{
try
{
Reference< XComponent > xContent = xLoader->loadComponentFromURL(sHelpURL, "_self", 0, Sequence< PropertyValue >());
if (xContent.is())
{
bSuccess = true;
}
}
catch(const RuntimeException&)
{ throw; }
catch(const Exception&)
{ /*break;*/ }
/* TODO try next locale ...
no further locale available? => break loop and show error page
*/
}
openDone(sHelpURL, bSuccess);
if ( IsWait() )
LeaveWait();
}
SfxHelpIndexWindow_Impl::SfxHelpIndexWindow_Impl(SfxHelpWindow_Impl* _pParent)
: Window(_pParent, 0)
, aIdle("sfx2 appl SfxHelpIndexWindow_Impl")
, aIndexKeywordLink(LINK(this, SfxHelpIndexWindow_Impl, KeywordHdl))
, pParentWin(_pParent)
, pCPage(nullptr)
, pIPage(nullptr)
, pSPage(nullptr)
, pBPage(nullptr)
, bWasCursorLeftOrRight(false)
, bIsInitDone(false)
{
m_pUIBuilder.reset(new VclBuilder(this, getUIRootDir(), "sfx/ui/helpcontrol.ui", "HelpControl"));
get(m_pActiveLB, "active");
get(m_pTabCtrl, "tabcontrol");
sfx2::AddToTaskPaneList( this );
m_pTabCtrl->SetActivatePageHdl( LINK( this, SfxHelpIndexWindow_Impl, ActivatePageHdl ) );
OString sPageId("index");
SvtViewOptions aViewOpt( EViewType::TabDialog, CONFIGNAME_INDEXWIN );
if ( aViewOpt.Exists() )
sPageId = aViewOpt.GetPageID();
m_pTabCtrl->SetCurPageId(m_pTabCtrl->GetPageId(sPageId));
ActivatePageHdl( m_pTabCtrl );
m_pActiveLB->SetSelectHdl( LINK( this, SfxHelpIndexWindow_Impl, SelectHdl ) );
aIdle.SetInvokeHandler( LINK( this, SfxHelpIndexWindow_Impl, InitHdl ) );
aIdle.Start();
Show();
}
SfxHelpIndexWindow_Impl::~SfxHelpIndexWindow_Impl()
{
disposeOnce();
}
void SfxHelpIndexWindow_Impl::dispose()
{
sfx2::RemoveFromTaskPaneList( this );
pCPage.disposeAndClear();
pIPage.disposeAndClear();
pSPage.disposeAndClear();
pBPage.disposeAndClear();
for ( sal_Int32 i = 0; i < m_pActiveLB->GetEntryCount(); ++i )
delete static_cast<OUString*>(m_pActiveLB->GetEntryData(i));
SvtViewOptions aViewOpt( EViewType::TabDialog, CONFIGNAME_INDEXWIN );
aViewOpt.SetPageID(m_pTabCtrl->GetPageName(m_pTabCtrl->GetCurPageId()));
disposeBuilder();
m_pActiveLB.clear();
m_pTabCtrl.clear();
pParentWin.clear();
vcl::Window::dispose();
}
void SfxHelpIndexWindow_Impl::Initialize()
{
OUStringBuffer aHelpURL(HELP_URL);
AppendConfigToken(aHelpURL, true);
std::vector<OUString> aFactories = SfxContentHelper::GetResultSet(aHelpURL.makeStringAndClear());
for (const OUString & rRow : aFactories)
{
sal_Int32 nIdx = 0;
OUString aTitle = rRow.getToken( 0, '\t', nIdx );
nIdx = 0;
OUString aURL = rRow.getToken( 2, '\t', nIdx );
OUString* pFactory = new OUString( INetURLObject( aURL ).GetHost() );
const sal_Int32 nPos = m_pActiveLB->InsertEntry( aTitle );
m_pActiveLB->SetEntryData( nPos, pFactory );
}
m_pActiveLB->SetDropDownLineCount( static_cast<sal_uInt16>(aFactories.size()) );
if ( m_pActiveLB->GetSelectedEntryPos() == LISTBOX_ENTRY_NOTFOUND )
SetActiveFactory();
}
void SfxHelpIndexWindow_Impl::SetActiveFactory()
{
DBG_ASSERT( pIPage, "index page not initialized" );
if ( !bIsInitDone && !m_pActiveLB->GetEntryCount() )
{
aIdle.Stop();
InitHdl( nullptr );
}
for ( sal_Int32 i = 0; i < m_pActiveLB->GetEntryCount(); ++i )
{
OUString* pFactory = static_cast<OUString*>(m_pActiveLB->GetEntryData(i));
*pFactory = pFactory->toAsciiLowerCase();
if ( *pFactory == pIPage->GetFactory() )
{
if ( m_pActiveLB->GetSelectedEntryPos() != i )
{
m_pActiveLB->SelectEntryPos(i);
aSelectFactoryLink.Call( nullptr );
}
break;
}
}
}
HelpTabPage_Impl* SfxHelpIndexWindow_Impl::GetCurrentPage( sal_uInt16& rCurId )
{
rCurId = m_pTabCtrl->GetCurPageId();
HelpTabPage_Impl* pPage = nullptr;
OString sName(m_pTabCtrl->GetPageName(rCurId));
if (sName == "contents")
{
pPage = GetContentPage();
}
else if (sName == "index")
{
pPage = GetIndexPage();
}
else if (sName == "find")
{
pPage = GetSearchPage();
}
else if (sName == "bookmarks")
{
pPage = GetBookmarksPage();
}
DBG_ASSERT( pPage, "SfxHelpIndexWindow_Impl::GetCurrentPage(): no current page" );
return pPage;
}
IMPL_LINK( SfxHelpIndexWindow_Impl, ActivatePageHdl, TabControl *, pTabCtrl, void )
{
sal_uInt16 nId = 0;
TabPage* pPage = GetCurrentPage( nId );
pTabCtrl->SetTabPage( nId, pPage );
}
IMPL_LINK_NOARG(SfxHelpIndexWindow_Impl, SelectHdl, ListBox&, void)
{
aIdle.Start();
}
IMPL_LINK_NOARG(SfxHelpIndexWindow_Impl, InitHdl, Timer *, void)
{
bIsInitDone = true;
Initialize();
// now use the timer for selection
aIdle.SetInvokeHandler( LINK( this, SfxHelpIndexWindow_Impl, SelectFactoryHdl ) );
aIdle.SetPriority( TaskPriority::LOWEST );
}
IMPL_LINK_NOARG(SfxHelpIndexWindow_Impl, SelectFactoryHdl, Timer *, void)
{
OUString* pFactory = static_cast<OUString*>(m_pActiveLB->GetSelectedEntryData());
if ( pFactory )
{
SetFactory( pFactory->toAsciiLowerCase(), false );
aSelectFactoryLink.Call( this );
}
}
IMPL_LINK_NOARG(SfxHelpIndexWindow_Impl, KeywordHdl, IndexTabPage_Impl&, void)
{
// keyword found on index?
bool bIndex = pIPage->HasKeyword();
if( !bIndex)
bIndex = pIPage->HasKeywordIgnoreCase();
// then set index or search page as current.
sal_uInt16 nPageId = bIndex ? m_pTabCtrl->GetPageId("index") : m_pTabCtrl->GetPageId("find");
if ( nPageId != m_pTabCtrl->GetCurPageId() )
{
m_pTabCtrl->SetCurPageId( nPageId );
ActivatePageHdl( m_pTabCtrl );
}
// at last we open the keyword
if ( bIndex )
pIPage->OpenKeyword();
else if ( !pSPage->OpenKeyword( sKeyword ) )
pParentWin->ShowStartPage();
}
IMPL_LINK(SfxHelpIndexWindow_Impl, IndexTabPageDoubleClickHdl, ComboBox&, rBox, void)
{
aPageDoubleClickLink.Call(&rBox);
}
void SfxHelpIndexWindow_Impl::Resize()
{
vcl::Window *pChild = GetWindow(GetWindowType::FirstChild);
if (!pChild)
return;
VclContainer::setLayoutAllocation(*pChild, Point(0,0), GetSizePixel());
}
Size SfxHelpIndexWindow_Impl::GetOptimalSize() const
{
const vcl::Window *pChild = GetWindow(GetWindowType::FirstChild);
if (!pChild)
return Window::GetOptimalSize();
return VclContainer::getLayoutRequisition(*pChild);
}
bool SfxHelpIndexWindow_Impl::PreNotify(NotifyEvent& rNEvt)
{
bool bDone = false;
MouseNotifyEvent nType = rNEvt.GetType();
if ( MouseNotifyEvent::KEYINPUT == nType && rNEvt.GetKeyEvent() )
{
const vcl::KeyCode& rKeyCode = rNEvt.GetKeyEvent()->GetKeyCode();
sal_uInt16 nCode = rKeyCode.GetCode();
if ( KEY_TAB == nCode )
{
// don't exit index pane with <TAB>
sal_uInt16 nPageId = 0;
HelpTabPage_Impl* pCurPage = GetCurrentPage( nPageId );
Control* pControl = pCurPage->GetLastFocusControl();
bool bShift = rKeyCode.IsShift();
bool bCtrl = rKeyCode.IsMod1();
if ( !bCtrl && bShift && m_pActiveLB->HasChildPathFocus() )
{
pControl->GrabFocus();
bDone = true;
}
else if ( !bCtrl && !bShift && pControl->HasChildPathFocus() )
{
m_pActiveLB->GrabFocus();
bDone = true;
}
else if ( bCtrl )
{
sal_uInt16 nPagePos = m_pTabCtrl->GetPagePos(nPageId);
sal_uInt16 nPageCount = m_pTabCtrl->GetPageCount();
++nPageId;
// <CTRL><TAB> moves through the pages
if (nPagePos >= nPageCount)
nPagePos = 0;
m_pTabCtrl->SetCurPageId(m_pTabCtrl->GetPageId(nPagePos));
ActivatePageHdl( m_pTabCtrl );
bDone = true;
}
}
else if ( m_pTabCtrl->HasFocus() && ( KEY_LEFT == nCode || KEY_RIGHT == nCode ) )
{
bWasCursorLeftOrRight = true;
}
}
return bDone || Window::PreNotify( rNEvt );
}
void SfxHelpIndexWindow_Impl::DataChanged( const DataChangedEvent& rDCEvt )
{
Window::DataChanged( rDCEvt );
if ( ( ( rDCEvt.GetType() == DataChangedEventType::SETTINGS ) ||
( rDCEvt.GetType() == DataChangedEventType::DISPLAY ) ) &&
( rDCEvt.GetFlags() & AllSettingsFlags::STYLE ) )
{
SetBackground( Wallpaper( GetSettings().GetStyleSettings().GetFaceColor() ) );
}
}
void SfxHelpIndexWindow_Impl::SetDoubleClickHdl( const Link<Control*,bool>& rLink )
{
aPageDoubleClickLink = rLink;
}
IMPL_LINK(SfxHelpIndexWindow_Impl, ContentTabPageDoubleClickHdl, SvTreeListBox*, p, bool)
{
aPageDoubleClickLink.Call(p);
return true;
}
IMPL_LINK(SfxHelpIndexWindow_Impl, TabPageDoubleClickHdl, ListBox&, r, void)
{
aPageDoubleClickLink.Call(&r);
}
void SfxHelpIndexWindow_Impl::SetFactory( const OUString& rFactory, bool bActive )
{
if ( !rFactory.isEmpty() )
{
GetIndexPage()->SetFactory( rFactory );
// the index page did a check if rFactory is valid,
// so the index page always returns a valid factory
GetSearchPage()->SetFactory( GetIndexPage()->GetFactory() );
if ( bActive )
SetActiveFactory();
}
}
OUString SfxHelpIndexWindow_Impl::GetSelectedEntry() const
{
OUString sRet;
OString sName(m_pTabCtrl->GetPageName(m_pTabCtrl->GetCurPageId()));
if (sName == "contents")
{
sRet = pCPage->GetSelectedEntry();
}
else if (sName == "index")
{
sRet = pIPage->GetSelectedEntry();
}
else if (sName == "find")
{
sRet = pSPage->GetSelectedEntry();
}
else if (sName == "bookmarks")
{
sRet = pBPage->GetSelectedEntry();
}
return sRet;
}
void SfxHelpIndexWindow_Impl::AddBookmarks( const OUString& rTitle, const OUString& rURL )
{
GetBookmarksPage()->AddBookmarks( rTitle, rURL );
}
bool SfxHelpIndexWindow_Impl::IsValidFactory( const OUString& _rFactory )
{
bool bValid = false;
for ( sal_Int32 i = 0; i < m_pActiveLB->GetEntryCount(); ++i )
{
OUString* pFactory = static_cast<OUString*>(m_pActiveLB->GetEntryData(i));
if ( *pFactory == _rFactory )
{
bValid = true;
break;
}
}
return bValid;
}
void SfxHelpIndexWindow_Impl::ClearSearchPage()
{
if ( pSPage )
pSPage->ClearPage();
}
void SfxHelpIndexWindow_Impl::GrabFocusBack()
{
OString sName(m_pTabCtrl->GetPageName(m_pTabCtrl->GetCurPageId()));
if (sName == "contents" && pCPage)
pCPage->SetFocusOnBox();
else if (sName == "index" && pIPage)
pIPage->SetFocusOnBox();
else if (sName == "find" && pSPage)
pSPage->SetFocusOnBox();
else if (sName == "bookmarks" && pBPage)
pBPage->SetFocusOnBox();
}
bool SfxHelpIndexWindow_Impl::HasFocusOnEdit() const
{
bool bRet = false;
OString sName(m_pTabCtrl->GetPageName(m_pTabCtrl->GetCurPageId()));
if (sName == "index" && pIPage)
bRet = pIPage->HasFocusOnEdit();
else if (sName == "find" && pSPage)
bRet = pSPage->HasFocusOnEdit();
return bRet;
}
OUString SfxHelpIndexWindow_Impl::GetSearchText() const
{
OUString sRet;
OString sName(m_pTabCtrl->GetPageName(m_pTabCtrl->GetCurPageId()));
if (sName == "find" && pSPage)
sRet = pSPage->GetSearchText();
return sRet;
}
bool SfxHelpIndexWindow_Impl::IsFullWordSearch() const
{
bool bRet = false;
OString sName(m_pTabCtrl->GetPageName(m_pTabCtrl->GetCurPageId()));
if (sName == "find" && pSPage)
bRet = pSPage->IsFullWordSearch();
return bRet;
}
void SfxHelpIndexWindow_Impl::OpenKeyword( const OUString& rKeyword )
{
sKeyword = rKeyword;
DBG_ASSERT( pIPage, "invalid index page" );
pIPage->SetKeyword( sKeyword );
}
void SfxHelpIndexWindow_Impl::SelectExecutableEntry()
{
OString sName(m_pTabCtrl->GetPageName(m_pTabCtrl->GetCurPageId()));
if (sName == "index" && pIPage )
pIPage->SelectExecutableEntry();
}
// class TextWin_Impl ----------------------------------------------------
TextWin_Impl::TextWin_Impl( vcl::Window* p ) : DockingWindow( p, 0 )
{
}
bool TextWin_Impl::EventNotify( NotifyEvent& rNEvt )
{
if( ( rNEvt.GetType() == MouseNotifyEvent::KEYINPUT ) && rNEvt.GetKeyEvent()->GetKeyCode().GetCode() == KEY_TAB )
return GetParent()->EventNotify( rNEvt );
else
return DockingWindow::EventNotify( rNEvt );
}
// remove docking area acceptor from layoutmanager, so it will not layout anything further .-)
static void lcl_disableLayoutOfFrame(const Reference< XFrame2 >& xFrame)
{
xFrame->setLayoutManager( Reference< XLayoutManager >() );
}
// class SfxHelpTextWindow_Impl ------------------------------------------
SfxHelpTextWindow_Impl::SfxHelpTextWindow_Impl( SfxHelpWindow_Impl* pParent ) :
Window( pParent, WB_CLIPCHILDREN | WB_TABSTOP | WB_DIALOGCONTROL ),
aToolBox ( VclPtr<ToolBox>::Create(this, 0) ),
aOnStartupCB ( VclPtr<CheckBox>::Create(this, WB_HIDE | WB_TABSTOP) ),
aSelectIdle ( "sfx2 appl SfxHelpTextWindow_Impl Select" ),
aIndexOnImage (BitmapEx(BMP_HELP_TOOLBOX_INDEX_ON)),
aIndexOffImage (BitmapEx(BMP_HELP_TOOLBOX_INDEX_OFF)),
aIndexOnText ( SfxResId( STR_HELP_BUTTON_INDEX_ON ) ),
aIndexOffText ( SfxResId( STR_HELP_BUTTON_INDEX_OFF ) ),
aOnStartupText ( SfxResId( RID_HELP_ONSTARTUP_TEXT ) ),
pHelpWin ( pParent ),
pTextWin ( VclPtr<TextWin_Impl>::Create( this ) ),
pSrchDlg ( nullptr ),
nMinPos ( 0 ),
bIsDebug ( false ),
bIsIndexOn ( false ),
bIsInClose ( false ),
bIsFullWordSearch ( false )
{
aOnStartupCB->SetSizePixel(aOnStartupCB->PixelToLogic(Size(200, 10), MapMode(MapUnit::MapAppFont)));
sfx2::AddToTaskPaneList( aToolBox.get() );
xFrame = Frame::create( ::comphelper::getProcessComponentContext() );
xFrame->initialize( VCLUnoHelper::GetInterface ( pTextWin ) );
xFrame->setName( "OFFICE_HELP" );
lcl_disableLayoutOfFrame(xFrame);
aToolBox->SetHelpId( HID_HELP_TOOLBOX );
aToolBox->InsertItem( TBI_INDEX, aIndexOffText );
aToolBox->SetHelpId( TBI_INDEX, HID_HELP_TOOLBOXITEM_INDEX );
aToolBox->InsertSeparator();
aToolBox->InsertItem( TBI_BACKWARD, SfxResId( STR_HELP_BUTTON_PREV ) );
aToolBox->SetHelpId( TBI_BACKWARD, HID_HELP_TOOLBOXITEM_BACKWARD );
aToolBox->InsertItem( TBI_FORWARD, SfxResId( STR_HELP_BUTTON_NEXT ) );
aToolBox->SetHelpId( TBI_FORWARD, HID_HELP_TOOLBOXITEM_FORWARD );
aToolBox->InsertItem( TBI_START, SfxResId( STR_HELP_BUTTON_START ) );
aToolBox->SetHelpId( TBI_START, HID_HELP_TOOLBOXITEM_START );
aToolBox->InsertSeparator();
aToolBox->InsertItem( TBI_PRINT, SfxResId( STR_HELP_BUTTON_PRINT ) );
aToolBox->SetHelpId( TBI_PRINT, HID_HELP_TOOLBOXITEM_PRINT );
aToolBox->InsertItem( TBI_BOOKMARKS, SfxResId( STR_HELP_BUTTON_ADDBOOKMARK ) );
aToolBox->SetHelpId( TBI_BOOKMARKS, HID_HELP_TOOLBOXITEM_BOOKMARKS );
aToolBox->InsertItem( TBI_SEARCHDIALOG, SfxResId( STR_HELP_BUTTON_SEARCHDIALOG ) );
aToolBox->SetHelpId( TBI_SEARCHDIALOG, HID_HELP_TOOLBOXITEM_SEARCHDIALOG );
InitToolBoxImages();
aToolBox->Show();
InitOnStartupBox();
aOnStartupCB->SetClickHdl( LINK( this, SfxHelpTextWindow_Impl, CheckHdl ) );
aSelectIdle.SetInvokeHandler( LINK( this, SfxHelpTextWindow_Impl, SelectHdl ) );
aSelectIdle.SetPriority( TaskPriority::LOWEST );
char* pEnv = getenv( "help_debug" );
if ( pEnv )
bIsDebug = true;
SvtMiscOptions().AddListenerLink( LINK( this, SfxHelpTextWindow_Impl, NotifyHdl ) );
}
SfxHelpTextWindow_Impl::~SfxHelpTextWindow_Impl()
{
disposeOnce();
}
void SfxHelpTextWindow_Impl::dispose()
{
sfx2::RemoveFromTaskPaneList( aToolBox.get() );
bIsInClose = true;
SvtMiscOptions().RemoveListenerLink( LINK( this, SfxHelpTextWindow_Impl, NotifyHdl ) );
pSrchDlg.disposeAndClear();
aToolBox.disposeAndClear();
aOnStartupCB.disposeAndClear();
pHelpWin.clear();
pTextWin.disposeAndClear();
vcl::Window::dispose();
}
bool SfxHelpTextWindow_Impl::HasSelection() const
{
// is there any selection in the text and not only a cursor?
bool bRet = false;
Reference < XTextRange > xRange = getCursor();
if ( xRange.is() )
{
Reference < XText > xText = xRange->getText();
Reference < XTextCursor > xCursor = xText->createTextCursorByRange( xRange );
bRet = !xCursor->isCollapsed();
}
return bRet;
}
void SfxHelpTextWindow_Impl::InitToolBoxImages()
{
bool bLarge = SvtMiscOptions().AreCurrentSymbolsLarge();
aIndexOnImage = Image(BitmapEx(bLarge ? OUString(BMP_HELP_TOOLBOX_L_INDEX_ON) : OUString(BMP_HELP_TOOLBOX_INDEX_ON)));
aIndexOffImage = Image(BitmapEx(bLarge ? OUString(BMP_HELP_TOOLBOX_L_INDEX_OFF) : OUString(BMP_HELP_TOOLBOX_INDEX_OFF)));
aToolBox->SetItemImage( TBI_INDEX, bIsIndexOn ? aIndexOffImage : aIndexOnImage );
aToolBox->SetItemImage( TBI_BACKWARD,
Image(BitmapEx(bLarge ? OUString(BMP_HELP_TOOLBOX_L_PREV) : OUString(BMP_HELP_TOOLBOX_PREV)))
);
aToolBox->SetItemImage( TBI_FORWARD,
Image(BitmapEx(bLarge ? OUString(BMP_HELP_TOOLBOX_L_NEXT) : OUString(BMP_HELP_TOOLBOX_NEXT)))
);
aToolBox->SetItemImage( TBI_START,
Image(BitmapEx(bLarge ? OUString(BMP_HELP_TOOLBOX_L_START) : OUString(BMP_HELP_TOOLBOX_START)))
);
aToolBox->SetItemImage( TBI_PRINT,
Image(BitmapEx(bLarge ? OUString(BMP_HELP_TOOLBOX_L_PRINT) : OUString(BMP_HELP_TOOLBOX_PRINT)))
);
aToolBox->SetItemImage( TBI_BOOKMARKS,
Image(BitmapEx(bLarge ? OUString(BMP_HELP_TOOLBOX_L_BOOKMARKS) : OUString(BMP_HELP_TOOLBOX_BOOKMARKS)))
);
aToolBox->SetItemImage( TBI_SEARCHDIALOG,
Image(BitmapEx(bLarge ? OUString(BMP_HELP_TOOLBOX_L_SEARCHDIALOG) : OUString(BMP_HELP_TOOLBOX_SEARCHDIALOG)))
);
Size aSize = aToolBox->CalcWindowSizePixel();
aSize.AdjustHeight(TOOLBOX_OFFSET );
aToolBox->SetPosSizePixel( Point( 0, TOOLBOX_OFFSET ), aSize );
SvtMiscOptions aMiscOptions;
if ( aMiscOptions.GetToolboxStyle() != aToolBox->GetOutStyle() )
aToolBox->SetOutStyle( aMiscOptions.GetToolboxStyle() );
}
void SfxHelpTextWindow_Impl::InitOnStartupBox()
{
sCurrentFactory = SfxHelp::GetCurrentModuleIdentifier();
Reference< XComponentContext > xContext = ::comphelper::getProcessComponentContext();
OUString sPath( PATH_OFFICE_FACTORIES );
sPath += sCurrentFactory;
OUString sKey( KEY_HELP_ON_OPEN );
// Attention: This check boy knows two states:
// 1) Reading of the config key fails with an exception or by getting an empty Any (!) => check box must be hidden
// 2) We read sal_True/sal_False => check box must be shown and enabled/disabled
bool bHideBox = true;
bool bHelpAtStartup = false;
try
{
xConfiguration = ConfigurationHelper::openConfig(
xContext, PACKAGE_SETUP, EConfigurationModes::Standard );
if ( xConfiguration.is() )
{
Any aAny = ConfigurationHelper::readRelativeKey( xConfiguration, sPath, sKey );
if (aAny >>= bHelpAtStartup)
bHideBox = false;
}
}
catch( Exception& )
{
bHideBox = true;
}
if ( bHideBox )
aOnStartupCB->Hide();
else
{
// detect module name
OUString sModuleName;
if ( xConfiguration.is() )
{
OUString sTemp;
sKey = KEY_UI_NAME;
try
{
Any aAny = ConfigurationHelper::readRelativeKey( xConfiguration, sPath, sKey );
aAny >>= sTemp;
}
catch( Exception& )
{
SAL_WARN( "sfx.appl", "SfxHelpTextWindow_Impl::InitOnStartupBox(): unexpected exception" );
}
sModuleName = sTemp;
}
if ( !sModuleName.isEmpty() )
{
// set module name in checkbox text
OUString sText( aOnStartupText );
sText = sText.replaceFirst( "%MODULENAME", sModuleName );
aOnStartupCB->SetText( sText );
// and show it
aOnStartupCB->Show();
// set check state
aOnStartupCB->Check( bHelpAtStartup );
aOnStartupCB->SaveValue();
// calculate and set optimal width of the onstartup checkbox
OUString sCBText( "XXX" );
sCBText += aOnStartupCB->GetText();
long nTextWidth = aOnStartupCB->GetTextWidth( sCBText );
Size aSize = aOnStartupCB->GetSizePixel();
aSize.setWidth( nTextWidth );
aOnStartupCB->SetSizePixel( aSize );
SetOnStartupBoxPosition();
}
// set position of the checkbox
Size a3Size = LogicToPixel(Size(3, 3), MapMode(MapUnit::MapAppFont));
Size aTBSize = aToolBox->GetSizePixel();
Size aCBSize = aOnStartupCB->GetSizePixel();
Point aPnt = aToolBox->GetPosPixel();
aPnt.AdjustX(aTBSize.Width() + a3Size.Width() );
aPnt.AdjustY( ( aTBSize.Height() - aCBSize.Height() ) / 2 );
aOnStartupCB->SetPosPixel( aPnt );
nMinPos = aPnt.X();
}
}
void SfxHelpTextWindow_Impl::SetOnStartupBoxPosition()
{
long nX = std::max( GetOutputSizePixel().Width() - aOnStartupCB->GetSizePixel().Width(), nMinPos );
Point aPos = aOnStartupCB->GetPosPixel();
aPos.setX( nX );
aOnStartupCB->SetPosPixel( aPos );
}
Reference< XBreakIterator > const & SfxHelpTextWindow_Impl::GetBreakIterator()
{
if ( !xBreakIterator.is() )
xBreakIterator = vcl::unohelper::CreateBreakIterator();
DBG_ASSERT( xBreakIterator.is(), "Could not create BreakIterator" );
return xBreakIterator;
}
Reference< XTextRange > SfxHelpTextWindow_Impl::getCursor() const
{
// return the current cursor
Reference< XTextRange > xCursor;
try
{
Reference < XSelectionSupplier > xSelSup( xFrame->getController(), UNO_QUERY );
if ( xSelSup.is() )
{
Any aAny = xSelSup->getSelection();
Reference < XIndexAccess > xSelection;
if ( aAny >>= xSelection )
{
if ( xSelection->getCount() == 1 )
{
aAny = xSelection->getByIndex(0);
aAny >>= xCursor;
}
}
}
}
catch( Exception& )
{
OSL_FAIL( "SfxHelpTextWindow_Impl::getCursor(): unexpected exception" );
}
return xCursor;
}
bool SfxHelpTextWindow_Impl::isHandledKey( const vcl::KeyCode& _rKeyCode )
{
bool bRet = false;
sal_uInt16 nCode = _rKeyCode.GetCode();
// the keys <CTRL><A> (select all), <CTRL><C> (copy),
// <CTRL><F> (find), <CTRL><P> (print) and <CTRL><W> (close window)
// were handled in help
if ( _rKeyCode.IsMod1() &&
( KEY_A == nCode || KEY_C == nCode || KEY_F == nCode || KEY_P == nCode || KEY_W == nCode ) )
{
if ( KEY_F == nCode )
DoSearch();
else
bRet = true;
}
return bRet;
}
IMPL_LINK_NOARG(SfxHelpTextWindow_Impl, SelectHdl, Timer *, void)
{
try
{
// select the words, which are equal to the search text of the search page
Reference < XController > xController = xFrame->getController();
if ( xController.is() )
{
// get document
Reference < XSearchable > xSearchable( xController->getModel(), UNO_QUERY );
if ( xSearchable.is() )
{
// create descriptor, set string and find all words
Reference < XSearchDescriptor > xSrchDesc = xSearchable->createSearchDescriptor();
xSrchDesc->setPropertyValue( "SearchRegularExpression", makeAny( true ) );
if ( bIsFullWordSearch )
xSrchDesc->setPropertyValue( "SearchWords", makeAny( true ) );
OUString sSearchString = sfx2::PrepareSearchString( aSearchText, GetBreakIterator(), false );
xSrchDesc->setSearchString( sSearchString );
Reference< XIndexAccess > xSelection = xSearchable->findAll( xSrchDesc );
// then select all found words
Reference < XSelectionSupplier > xSelectionSup( xController, UNO_QUERY );
if ( xSelectionSup.is() )
{
xSelectionSup->select( Any(xSelection) );
}
}
}
}
catch( Exception& )
{
OSL_FAIL( "SfxHelpTextWindow_Impl::SelectHdl(): unexpected exception" );
}
}
IMPL_LINK_NOARG( SfxHelpTextWindow_Impl, NotifyHdl, LinkParamNone*, void )
{
InitToolBoxImages();
Resize();
aToolBox->Invalidate();
}
IMPL_LINK( SfxHelpTextWindow_Impl, FindHdl, sfx2::SearchDialog&, rDlg, void )
{
FindHdl(&rDlg);
}
void SfxHelpTextWindow_Impl::FindHdl(sfx2::SearchDialog* pDlg)
{
bool bWrapAround = ( nullptr == pDlg );
if ( bWrapAround )
pDlg = pSrchDlg;
DBG_ASSERT( pDlg, "invalid search dialog" );
OUString sSearchText = pDlg->GetSearchText();
try
{
// select the words, which are equal to the search text of the search page
Reference < XController > xController = xFrame->getController();
if ( xController.is() )
{
// get document
Reference < XSearchable > xSearchable( xController->getModel(), UNO_QUERY );
if ( xSearchable.is() )
{
// create descriptor, set string and find all words
Reference < XSearchDescriptor > xSrchDesc = xSearchable->createSearchDescriptor();
xSrchDesc->setPropertyValue( "SearchWords", makeAny(pDlg->IsOnlyWholeWords()) );
xSrchDesc->setPropertyValue( "SearchCaseSensitive", makeAny(pDlg->IsMarchCase()) );
xSrchDesc->setPropertyValue( "SearchBackwards", makeAny(pDlg->IsSearchBackwards()) );
xSrchDesc->setSearchString( sSearchText );
Reference< XInterface > xSelection;
Reference< XTextRange > xCursor = getCursor();
if ( xCursor.is() )
{
if ( pDlg->IsSearchBackwards() )
xCursor = xCursor->getStart();
xSelection = xSearchable->findNext( xCursor, xSrchDesc );
}
else
xSelection = xSearchable->findFirst( xSrchDesc );
// then select the found word
if ( xSelection.is() )
{
Reference < XSelectionSupplier > xSelectionSup( xController, UNO_QUERY );
if ( xSelectionSup.is() )
{
xSelectionSup->select( Any(xSelection) );
}
}
else if ( pDlg->IsWrapAround() && !bWrapAround )
{
Reference < text::XTextViewCursorSupplier > xCrsrSupp( xController, uno::UNO_QUERY );
Reference < text::XTextViewCursor > xTVCrsr( xCrsrSupp->getViewCursor(), uno::UNO_QUERY );
if ( xTVCrsr.is() )
{
Reference < text::XTextDocument > xDoc( xController->getModel(), uno::UNO_QUERY );
Reference < text::XText > xText = xDoc->getText();
if ( xText.is() )
{
if ( pDlg->IsSearchBackwards() )
xTVCrsr->gotoRange( xText->getEnd(), false );
else
xTVCrsr->gotoRange( xText->getStart(), false );
FindHdl( nullptr );
}
}
}
else
{
assert(pSrchDlg && "no search dialog");
std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(pSrchDlg->GetFrameWeld(),
VclMessageType::Info, VclButtonsType::Ok, SfxResId(STR_INFO_NOSEARCHTEXTFOUND)));
xBox->run();
pSrchDlg->SetFocusOnEdit();
}
}
}
}
catch( Exception& )
{
OSL_FAIL( "SfxHelpTextWindow_Impl::SelectHdl(): unexpected exception" );
}
}
IMPL_LINK_NOARG( SfxHelpTextWindow_Impl, CloseHdl, LinkParamNone*, void )
{
pSrchDlg.clear();
}
IMPL_LINK( SfxHelpTextWindow_Impl, CheckHdl, Button*, pButton, void )
{
CheckBox* pBox = static_cast<CheckBox*>(pButton);
if ( xConfiguration.is() )
{
bool bChecked = pBox->IsChecked();
OUString sPath( PATH_OFFICE_FACTORIES );
sPath += sCurrentFactory;
try
{
ConfigurationHelper::writeRelativeKey(
xConfiguration, sPath, KEY_HELP_ON_OPEN, makeAny( bChecked ) );
ConfigurationHelper::flush( xConfiguration );
}
catch( Exception& )
{
SAL_WARN( "sfx.appl", "SfxHelpTextWindow_Impl::CheckHdl(): unexpected exception" );
}
}
}
void SfxHelpTextWindow_Impl::Resize()
{
Size aSize = GetOutputSizePixel();
long nToolBoxHeight = aToolBox->GetSizePixel().Height() + TOOLBOX_OFFSET;
aSize.AdjustHeight( -nToolBoxHeight );
pTextWin->SetPosSizePixel( Point( 0, nToolBoxHeight ), aSize );
SetOnStartupBoxPosition();
}
bool SfxHelpTextWindow_Impl::PreNotify( NotifyEvent& rNEvt )
{
bool bDone = false;
MouseNotifyEvent nType = rNEvt.GetType();
if ( MouseNotifyEvent::COMMAND == nType && rNEvt.GetCommandEvent() )
{
const CommandEvent* pCmdEvt = rNEvt.GetCommandEvent();
vcl::Window* pCmdWin = rNEvt.GetWindow();
if ( pCmdEvt->GetCommand() == CommandEventId::ContextMenu && pCmdWin != this && pCmdWin != aToolBox.get() )
{
Point aPos;
if ( pCmdEvt->IsMouseEvent() )
aPos = pCmdEvt->GetMousePosPixel();
else
aPos = Point( pTextWin->GetPosPixel().X() + 20, 20 );
aPos.AdjustY(pTextWin->GetPosPixel().Y() );
ScopedVclPtrInstance<PopupMenu> aMenu;
if ( bIsIndexOn )
aMenu->InsertItem(TBI_INDEX, aIndexOffText, Image(BitmapEx(BMP_HELP_TOOLBOX_INDEX_OFF)));
else
aMenu->InsertItem(TBI_INDEX, aIndexOnText, Image(BitmapEx(BMP_HELP_TOOLBOX_INDEX_ON)));
aMenu->SetHelpId( TBI_INDEX, HID_HELP_TOOLBOXITEM_INDEX );
aMenu->InsertSeparator();
aMenu->InsertItem( TBI_BACKWARD,
SfxResId( STR_HELP_BUTTON_PREV ),
Image(BitmapEx(BMP_HELP_TOOLBOX_PREV))
);
aMenu->SetHelpId( TBI_BACKWARD, HID_HELP_TOOLBOXITEM_BACKWARD );
aMenu->EnableItem( TBI_BACKWARD, pHelpWin->HasHistoryPredecessor() );
aMenu->InsertItem( TBI_FORWARD,
SfxResId( STR_HELP_BUTTON_NEXT ),
Image(BitmapEx(BMP_HELP_TOOLBOX_NEXT))
);
aMenu->SetHelpId( TBI_FORWARD, HID_HELP_TOOLBOXITEM_FORWARD );
aMenu->EnableItem( TBI_FORWARD, pHelpWin->HasHistorySuccessor() );
aMenu->InsertItem( TBI_START,
SfxResId( STR_HELP_BUTTON_START ),
Image(BitmapEx(BMP_HELP_TOOLBOX_START))
);
aMenu->SetHelpId( TBI_START, HID_HELP_TOOLBOXITEM_START );
aMenu->InsertSeparator();
aMenu->InsertItem( TBI_PRINT,
SfxResId( STR_HELP_BUTTON_PRINT ),
Image(BitmapEx(BMP_HELP_TOOLBOX_PRINT))
);
aMenu->SetHelpId( TBI_PRINT, HID_HELP_TOOLBOXITEM_PRINT );
aMenu->InsertItem( TBI_BOOKMARKS,
SfxResId( STR_HELP_BUTTON_ADDBOOKMARK ),
Image(BitmapEx(BMP_HELP_TOOLBOX_BOOKMARKS))
);
aMenu->SetHelpId( TBI_BOOKMARKS, HID_HELP_TOOLBOXITEM_BOOKMARKS );
aMenu->InsertItem( TBI_SEARCHDIALOG,
SfxResId( STR_HELP_BUTTON_SEARCHDIALOG ),
Image(BitmapEx(BMP_HELP_TOOLBOX_SEARCHDIALOG))
);
aMenu->SetHelpId( TBI_SEARCHDIALOG, HID_HELP_TOOLBOXITEM_SEARCHDIALOG );
aMenu->InsertSeparator();
aMenu->InsertItem( TBI_SELECTIONMODE, SfxResId( STR_HELP_MENU_TEXT_SELECTION_MODE ) );
aMenu->SetHelpId( TBI_SELECTIONMODE, HID_HELP_TEXT_SELECTION_MODE );
URL aURL;
aURL.Complete = ".uno:SelectTextMode";
Reference< util::XURLTransformer > xTrans( util::URLTransformer::create( ::comphelper::getProcessComponentContext() ) );
xTrans->parseStrict(aURL);
Reference < XDispatch > xDisp = xFrame->queryDispatch( aURL, OUString(), 0 );
if(xDisp.is())
{
rtl::Reference<HelpStatusListener_Impl> pStateListener =
new HelpStatusListener_Impl(xDisp, aURL );
FeatureStateEvent rEvent = pStateListener->GetStateEvent();
bool bCheck = false;
rEvent.State >>= bCheck;
aMenu->CheckItem(TBI_SELECTIONMODE, bCheck);
}
aMenu->InsertSeparator();
aMenu->InsertItem( TBI_COPY,
SfxResId(STR_HELP_MENU_TEXT_COPY),
Image(BitmapEx(BMP_HELP_TOOLBOX_COPY))
);
aMenu->SetHelpId( TBI_COPY, ".uno:Copy" );
aMenu->EnableItem( TBI_COPY, HasSelection() );
if ( bIsDebug )
{
aMenu->InsertSeparator();
aMenu->InsertItem( TBI_SOURCEVIEW, SfxResId(STR_HELP_BUTTON_SOURCEVIEW) );
}
if( ! SvtMenuOptions().IsEntryHidingEnabled() )
aMenu->SetMenuFlags( aMenu->GetMenuFlags() | MenuFlags::HideDisabledEntries );
sal_uInt16 nId = aMenu->Execute( this, aPos );
pHelpWin->DoAction( nId );
bDone = true;
}
}
else if ( MouseNotifyEvent::KEYINPUT == nType && rNEvt.GetKeyEvent() )
{
const KeyEvent* pKEvt = rNEvt.GetKeyEvent();
const vcl::KeyCode& rKeyCode = pKEvt->GetKeyCode();
sal_uInt16 nKeyGroup = rKeyCode.GetGroup();
sal_uInt16 nKey = rKeyCode.GetCode();
if ( KEYGROUP_ALPHA == nKeyGroup && !isHandledKey( rKeyCode ) )
{
// do nothing disables the writer accelerators
bDone = true;
}
else if ( rKeyCode.IsMod1() && ( KEY_F4 == nKey || KEY_W == nKey ) )
{
// <CTRL><F4> or <CTRL><W> -> close top frame
pHelpWin->CloseWindow();
bDone = true;
}
else if ( KEY_TAB == nKey && aOnStartupCB->HasChildPathFocus() )
{
aToolBox->GrabFocus();
bDone = true;
}
}
return bDone || Window::PreNotify( rNEvt );
}
void SfxHelpTextWindow_Impl::GetFocus()
{
if ( !bIsInClose )
{
try
{
if( xFrame.is() )
{
Reference< css::awt::XWindow > xWindow = xFrame->getComponentWindow();
if( xWindow.is() )
xWindow->setFocus();
}
}
catch( Exception& )
{
SAL_WARN( "sfx.appl", "SfxHelpTextWindow_Impl::GetFocus(): unexpected exception" );
}
}
}
void SfxHelpTextWindow_Impl::DataChanged( const DataChangedEvent& rDCEvt )
{
Window::DataChanged( rDCEvt );
if ( ( ( rDCEvt.GetType() == DataChangedEventType::SETTINGS ) ||
( rDCEvt.GetType() == DataChangedEventType::DISPLAY ) ) &&
( rDCEvt.GetFlags() & AllSettingsFlags::STYLE ) )
{
SetBackground( Wallpaper( GetSettings().GetStyleSettings().GetFaceColor() ) );
InitToolBoxImages();
}
}
void SfxHelpTextWindow_Impl::ToggleIndex( bool bOn )
{
bIsIndexOn = bOn;
if ( bIsIndexOn )
{
aToolBox->SetItemImage( TBI_INDEX, aIndexOffImage );
aToolBox->SetItemText( TBI_INDEX, aIndexOffText );
}
else
{
aToolBox->SetItemImage( TBI_INDEX, aIndexOnImage );
aToolBox->SetItemText( TBI_INDEX, aIndexOnText );
}
}
void SfxHelpTextWindow_Impl::SelectSearchText( const OUString& rSearchText, bool _bIsFullWordSearch )
{
aSearchText = rSearchText;
bIsFullWordSearch = _bIsFullWordSearch;
aSelectIdle.Start();
}
void SfxHelpTextWindow_Impl::SetPageStyleHeaderOff() const
{
bool bSetOff = false;
// set off the pagestyle header to prevent print output of the help URL
try
{
Reference < XController > xController = xFrame->getController();
Reference < XSelectionSupplier > xSelSup( xController, UNO_QUERY );
if ( xSelSup.is() )
{
Reference < XIndexAccess > xSelection;
if ( xSelSup->getSelection() >>= xSelection )
{
Reference < XTextRange > xRange;
if ( xSelection->getByIndex(0) >>= xRange )
{
Reference < XText > xText = xRange->getText();
Reference < XPropertySet > xProps( xText->createTextCursorByRange( xRange ), UNO_QUERY );
OUString sStyleName;
if ( xProps->getPropertyValue( "PageStyleName" ) >>= sStyleName )
{
Reference < XStyleFamiliesSupplier > xStyles( xController->getModel(), UNO_QUERY );
Reference < XNameContainer > xContainer;
if ( xStyles->getStyleFamilies()->getByName( "PageStyles" )
>>= xContainer )
{
Reference < XStyle > xStyle;
if ( xContainer->getByName( sStyleName ) >>= xStyle )
{
Reference < XPropertySet > xPropSet( xStyle, UNO_QUERY );
xPropSet->setPropertyValue( "HeaderIsOn", makeAny( false ) );
Reference< XModifiable > xReset(xStyles, UNO_QUERY);
xReset->setModified(false);
bSetOff = true;
}
}
}
}
}
}
}
catch( Exception& )
{
SAL_WARN( "sfx.appl", "SfxHelpTextWindow_Impl::SetPageStyleHeaderOff(): unexpected exception" );
}
SAL_WARN_IF( !bSetOff, "sfx.appl", "SfxHelpTextWindow_Impl::SetPageStyleHeaderOff(): set off failed" );
}
void SfxHelpTextWindow_Impl::CloseFrame()
{
bIsInClose = true;
try
{
css::uno::Reference< css::util::XCloseable > xCloseable ( xFrame, css::uno::UNO_QUERY );
if (xCloseable.is())
xCloseable->close(true);
}
catch( css::util::CloseVetoException& )
{
}
}
void SfxHelpTextWindow_Impl::DoSearch()
{
if ( !pSrchDlg )
{
// create the search dialog
pSrchDlg = VclPtr<sfx2::SearchDialog>::Create( pTextWin, "HelpSearchDialog" );
// set handler
pSrchDlg->SetFindHdl( LINK( this, SfxHelpTextWindow_Impl, FindHdl ) );
pSrchDlg->SetCloseHdl( LINK( this, SfxHelpTextWindow_Impl, CloseHdl ) );
// get selected text of the help page to set it as the search text
Reference< XTextRange > xCursor = getCursor();
if ( xCursor.is() )
{
OUString sText = xCursor->getString();
if ( !sText.isEmpty() )
pSrchDlg->SetSearchText( sText );
}
pSrchDlg->Show();
}
}
// class SfxHelpWindow_Impl ----------------------------------------------
void SfxHelpWindow_Impl::Resize()
{
SplitWindow::Resize();
InitSizes();
}
void SfxHelpWindow_Impl::Split()
{
static long nMinSplitSize = 5;
static long nMaxSplitSize = 99 - nMinSplitSize;
SplitWindow::Split();
nIndexSize = GetItemSize( INDEXWIN_ID );
nTextSize = GetItemSize( TEXTWIN_ID );
bool bMod = false;
if( nIndexSize < nMinSplitSize )
{
nIndexSize = nMinSplitSize;
nTextSize = nMaxSplitSize;
bMod = true;
}
else if( nTextSize < nMinSplitSize )
{
nTextSize = nMinSplitSize;
nIndexSize = nMaxSplitSize;
bMod = true;
}
else
bMod = false;
if( bMod )
{
SetItemSize( INDEXWIN_ID, nIndexSize );
SetItemSize( TEXTWIN_ID, nTextSize );
}
InitSizes();
}
void SfxHelpWindow_Impl::GetFocus()
{
if( pTextWin )
pTextWin->GrabFocus();
else
vcl::Window::GetFocus();
}
void SfxHelpWindow_Impl::MakeLayout()
{
if ( nHeight > 0 && xWindow.is() )
{
VclPtr<vcl::Window> pScreenWin = VCLUnoHelper::GetWindow(xWindow);
/* #i55528#
Hide() / Show() will produce strange effects.
The returned size (used later to be written back into the configuration)
is not the right after a resize during the window is hidden.
If this resize is done if the window is visible everything works as expected.
Some VCL-patches could not solve this problem so I've established the
workaround: resize the help window if it's visible .-)
*/
css::awt::Rectangle aRect = xWindow->getPosSize();
sal_Int32 nOldWidth = bIndex ? nCollapseWidth : nExpandWidth;
sal_Int32 nWidth = bIndex ? nExpandWidth : nCollapseWidth;
xWindow->setPosSize( aRect.X, aRect.Y, nWidth, nHeight, css::awt::PosSize::SIZE );
if ( aRect.Width > 0 && aRect.Height > 0 )
{
tools::Rectangle aScreenRect = pScreenWin->GetClientWindowExtentsRelative();
Point aNewPos = aScreenRect.TopLeft();
sal_Int32 nDiffWidth = nOldWidth - nWidth;
aNewPos.AdjustX(nDiffWidth );
pScreenWin->SetPosPixel( aNewPos );
}
else if ( aWinPos.X() > 0 && aWinPos.Y() > 0 )
pScreenWin->SetPosPixel( aWinPos );
}
Clear();
if ( bIndex )
{
pIndexWin->Show();
InsertItem( COLSET_ID, 100, SPLITWINDOW_APPEND, SPLITSET_ID, SplitWindowItemFlags::PercentSize | SplitWindowItemFlags::ColSet );
InsertItem( INDEXWIN_ID, pIndexWin, nIndexSize, SPLITWINDOW_APPEND, COLSET_ID, SplitWindowItemFlags::PercentSize );
InsertItem( TEXTWIN_ID, pTextWin, nTextSize, SPLITWINDOW_APPEND, COLSET_ID, SplitWindowItemFlags::PercentSize );
}
else
{
pIndexWin->Hide();
InsertItem( COLSET_ID, 100, SPLITWINDOW_APPEND, SPLITSET_ID, SplitWindowItemFlags::PercentSize | SplitWindowItemFlags::ColSet );
InsertItem( TEXTWIN_ID, pTextWin, 100, SPLITWINDOW_APPEND, 1, SplitWindowItemFlags::PercentSize );
}
}
void SfxHelpWindow_Impl::InitSizes()
{
if ( xWindow.is() )
{
css::awt::Rectangle aRect = xWindow->getPosSize();
nHeight = aRect.Height;
if ( bIndex )
{
nExpandWidth = aRect.Width;
nCollapseWidth = nExpandWidth * nTextSize / 100;
}
else
{
nCollapseWidth = aRect.Width;
nExpandWidth = nTextSize ? nCollapseWidth * 100 / nTextSize : 0;
}
}
}
void SfxHelpWindow_Impl::LoadConfig()
{
SvtViewOptions aViewOpt( EViewType::Window, CONFIGNAME_HELPWIN );
if ( aViewOpt.Exists() )
{
bIndex = aViewOpt.IsVisible();
OUString aUserData;
Any aUserItem = aViewOpt.GetUserItem( USERITEM_NAME );
OUString aTemp;
if ( aUserItem >>= aTemp )
{
aUserData = aTemp;
DBG_ASSERT( comphelper::string::getTokenCount(aUserData, ';') == 6, "invalid user data" );
sal_Int32 nIdx = 0;
nIndexSize = aUserData.getToken( 0, ';', nIdx ).toInt32();
nTextSize = aUserData.getToken( 0, ';', nIdx ).toInt32();
sal_Int32 nWidth = aUserData.getToken( 0, ';', nIdx ).toInt32();
nHeight = aUserData.getToken( 0, ';', nIdx ).toInt32();
aWinPos.setX( aUserData.getToken( 0, ';', nIdx ).toInt32() );
aWinPos.setY( aUserData.getToken( 0, ';', nIdx ).toInt32() );
if ( bIndex )
{
nExpandWidth = nWidth;
nCollapseWidth = nExpandWidth * nTextSize / 100;
}
else if (nTextSize != 0)
{
nCollapseWidth = nWidth;
nExpandWidth = nCollapseWidth * 100 / nTextSize;
}
}
pTextWin->ToggleIndex( bIndex );
}
}
void SfxHelpWindow_Impl::SaveConfig()
{
SvtViewOptions aViewOpt( EViewType::Window, CONFIGNAME_HELPWIN );
sal_Int32 nW = 0, nH = 0;
if ( xWindow.is() )
{
css::awt::Rectangle aRect = xWindow->getPosSize();
nW = aRect.Width;
nH = aRect.Height;
}
aViewOpt.SetVisible( bIndex );
OUString aUserData = OUString::number( nIndexSize );
aUserData += ";";
aUserData += OUString::number( nTextSize );
aUserData += ";";
aUserData += OUString::number( nW );
aUserData += ";";
aUserData += OUString::number( nH );
VclPtr<vcl::Window> pScreenWin = VCLUnoHelper::GetWindow( xWindow );
aWinPos = pScreenWin->GetWindowExtentsRelative( nullptr ).TopLeft();
aUserData += ";";
aUserData += OUString::number( aWinPos.X() );
aUserData += ";";
aUserData += OUString::number( aWinPos.Y() );
aViewOpt.SetUserItem( USERITEM_NAME, makeAny( aUserData ) );
}
void SfxHelpWindow_Impl::ShowStartPage()
{
OUString sHelpURL = SfxHelpWindow_Impl::buildHelpURL(pIndexWin->GetFactory(),
"/start",
OUString());
loadHelpContent(sHelpURL);
}
IMPL_LINK( SfxHelpWindow_Impl, SelectHdl, ToolBox* , pToolBox, void )
{
if ( pToolBox )
{
bGrabFocusToToolBox = pToolBox->HasChildPathFocus();
DoAction( pToolBox->GetCurItemId() );
}
}
IMPL_LINK_NOARG(SfxHelpWindow_Impl, OpenHdl, Control*, bool)
{
pIndexWin->SelectExecutableEntry();
OUString aEntry = pIndexWin->GetSelectedEntry();
if ( aEntry.isEmpty() )
return false;
OUString sHelpURL;
bool bComplete = aEntry.toAsciiLowerCase().match("vnd.sun.star.help");
if (bComplete)
sHelpURL = aEntry;
else
{
OUString aId;
OUString aAnchor = OUString('#');
if ( comphelper::string::getTokenCount(aEntry, '#') == 2 )
{
aId = aEntry.getToken( 0, '#' );
aAnchor += aEntry.getToken( 1, '#' );
}
else
aId = aEntry;
aEntry = "/";
aEntry += aId;
sHelpURL = SfxHelpWindow_Impl::buildHelpURL(pIndexWin->GetFactory(),
aEntry,
aAnchor);
}
loadHelpContent(sHelpURL);
return false;
}
IMPL_LINK( SfxHelpWindow_Impl, SelectFactoryHdl, SfxHelpIndexWindow_Impl* , pWin, void )
{
if ( sTitle.isEmpty() )
sTitle = GetParent()->GetText();
OUString aNewTitle = sTitle + " - " + pIndexWin->GetActiveFactoryTitle();
Reference< XTitle > xTitle(xFrame, UNO_QUERY);
if (xTitle.is ())
xTitle->setTitle (aNewTitle);
if ( pWin )
ShowStartPage();
pIndexWin->ClearSearchPage();
}
IMPL_LINK( SfxHelpWindow_Impl, ChangeHdl, HelpListener_Impl&, rListener, void )
{
SetFactory( rListener.GetFactory() );
}
void SfxHelpWindow_Impl::openDone(const OUString& sURL ,
bool bSuccess)
{
INetURLObject aObj( sURL );
if ( aObj.GetProtocol() == INetProtocol::VndSunStarHelp )
SetFactory( aObj.GetHost() );
if ( IsWait() )
LeaveWait();
if ( bGrabFocusToToolBox )
{
pTextWin->GetToolBox().GrabFocus();
bGrabFocusToToolBox = false;
}
else
pIndexWin->GrabFocusBack();
if ( bSuccess )
{
// set some view settings: "prevent help tips" and "helpid == 68245"
try
{
Reference < XController > xController = pTextWin->getFrame()->getController();
if ( xController.is() )
{
Reference < XViewSettingsSupplier > xSettings( xController, UNO_QUERY );
Reference < XPropertySet > xViewProps = xSettings->getViewSettings();
Reference< XPropertySetInfo > xInfo = xViewProps->getPropertySetInfo();
xViewProps->setPropertyValue( "ShowContentTips", makeAny( false ) );
xViewProps->setPropertyValue( "ShowGraphics", makeAny( true ) );
xViewProps->setPropertyValue( "ShowTables", makeAny( true ) );
xViewProps->setPropertyValue( "HelpURL", makeAny( OUString("HID:SFX2_HID_HELP_ONHELP") ) );
OUString sProperty( "IsExecuteHyperlinks" );
if ( xInfo->hasPropertyByName( sProperty ) )
xViewProps->setPropertyValue( sProperty, makeAny( true ) );
xController->restoreViewData(Any());
}
}
catch( Exception& )
{
OSL_FAIL( "SfxHelpWindow_Impl::OpenDoneHdl(): unexpected exception" );
}
// When the SearchPage opens the help doc, then select all words, which are equal to its text
OUString sSearchText = comphelper::string::strip(pIndexWin->GetSearchText(), ' ');
if ( !sSearchText.isEmpty() )
pTextWin->SelectSearchText( sSearchText, pIndexWin->IsFullWordSearch() );
// no page style header -> this prevents a print output of the URL
pTextWin->SetPageStyleHeaderOff();
}
}
SfxHelpWindow_Impl::SfxHelpWindow_Impl(
const css::uno::Reference < css::frame::XFrame2 >& rFrame,
vcl::Window* pParent ) :
SplitWindow( pParent, WB_3DLOOK | WB_NOSPLITDRAW ),
xFrame ( rFrame ),
pIndexWin ( nullptr ),
pTextWin ( nullptr ),
pHelpInterceptor ( new HelpInterceptor_Impl() ),
pHelpListener ( new HelpListener_Impl( pHelpInterceptor ) ),
nExpandWidth ( 0 ),
nCollapseWidth ( 0 ),
nHeight ( 0 ),
nIndexSize ( 40 ),
nTextSize ( 60 ),
bIndex ( true ),
bGrabFocusToToolBox ( false ),
aWinPos ( 0, 0 ),
sTitle ( pParent->GetText() )
{
SetHelpId( HID_HELP_WINDOW );
SetStyle( GetStyle() | WB_DIALOGCONTROL );
pHelpInterceptor->InitWaiter( this );
pIndexWin = VclPtr<SfxHelpIndexWindow_Impl>::Create( this );
pIndexWin->SetDoubleClickHdl( LINK( this, SfxHelpWindow_Impl, OpenHdl ) );
pIndexWin->SetSelectFactoryHdl( LINK( this, SfxHelpWindow_Impl, SelectFactoryHdl ) );
pIndexWin->SetSizePixel(LogicToPixel(Size(120, 200), MapMode(MapUnit::MapAppFont)));
pIndexWin->Show();
pTextWin = VclPtr<SfxHelpTextWindow_Impl>::Create( this );
Reference < XFrames > xFrames = rFrame->getFrames();
xFrames->append( Reference<XFrame>(pTextWin->getFrame(), UNO_QUERY_THROW) );
pTextWin->SetSelectHdl( LINK( this, SfxHelpWindow_Impl, SelectHdl ) );
pTextWin->Show();
pHelpInterceptor->setInterception( Reference<XFrame>(pTextWin->getFrame(), UNO_QUERY_THROW) );
pHelpListener->SetChangeHdl( LINK( this, SfxHelpWindow_Impl, ChangeHdl ) );
LoadConfig();
}
SfxHelpWindow_Impl::~SfxHelpWindow_Impl()
{
disposeOnce();
}
void SfxHelpWindow_Impl::dispose()
{
SaveConfig();
pIndexWin.disposeAndClear();
pTextWin->CloseFrame();
pTextWin.disposeAndClear();
SplitWindow::dispose();
}
bool SfxHelpWindow_Impl::PreNotify( NotifyEvent& rNEvt )
{
bool bHandled = false;
if ( rNEvt.GetType() == MouseNotifyEvent::KEYINPUT )
{
// Backward == <ALT><LEFT> or <BACKSPACE> Forward == <ALT><RIGHT>
const vcl::KeyCode& rKeyCode = rNEvt.GetKeyEvent()->GetKeyCode();
sal_uInt16 nKey = rKeyCode.GetCode();
if ( ( rKeyCode.IsMod2() && ( KEY_LEFT == nKey || KEY_RIGHT == nKey ) ) ||
( !rKeyCode.GetModifier() && KEY_BACKSPACE == nKey && !pIndexWin->HasFocusOnEdit() ) )
{
DoAction( rKeyCode.GetCode() == KEY_RIGHT ? TBI_FORWARD : TBI_BACKWARD );
bHandled = true;
}
else if ( rKeyCode.IsMod1() && ( KEY_F4 == nKey || KEY_W == nKey ) )
{
// <CTRL><F4> or <CTRL><W> -> close top frame
CloseWindow();
bHandled = true;
}
}
return bHandled || Window::PreNotify( rNEvt );
}
void SfxHelpWindow_Impl::setContainerWindow( const Reference < css::awt::XWindow >& xWin )
{
xWindow = xWin;
MakeLayout();
}
void SfxHelpWindow_Impl::SetFactory( const OUString& rFactory )
{
pIndexWin->SetFactory( rFactory, true );
}
void SfxHelpWindow_Impl::SetHelpURL( const OUString& rURL )
{
INetURLObject aObj( rURL );
if ( aObj.GetProtocol() == INetProtocol::VndSunStarHelp )
SetFactory( aObj.GetHost() );
}
void SfxHelpWindow_Impl::DoAction( sal_uInt16 nActionId )
{
switch ( nActionId )
{
case TBI_INDEX :
{
bIndex = !bIndex;
MakeLayout();
pTextWin->ToggleIndex( bIndex );
break;
}
case TBI_START :
{
ShowStartPage();
break;
}
case TBI_BACKWARD :
case TBI_FORWARD :
{
URL aURL;
aURL.Complete = ".uno:Backward";
if ( TBI_FORWARD == nActionId )
aURL.Complete = ".uno:Forward";
Reference< util::XURLTransformer > xTrans( util::URLTransformer::create( ::comphelper::getProcessComponentContext() ) );
xTrans->parseStrict(aURL);
pHelpInterceptor->dispatch( aURL, Sequence < PropertyValue >() );
break;
}
case TBI_SEARCHDIALOG :
{
pTextWin->DoSearch();
break;
}
case TBI_PRINT :
case TBI_SOURCEVIEW :
case TBI_COPY :
case TBI_SELECTIONMODE:
{
Reference < XDispatchProvider > xProv( pTextWin->getFrame(), UNO_QUERY );
if ( xProv.is() )
{
URL aURL;
if ( TBI_PRINT == nActionId )
aURL.Complete = ".uno:Print";
else if ( TBI_SOURCEVIEW == nActionId )
aURL.Complete = ".uno:SourceView";
else if ( TBI_COPY == nActionId )
aURL.Complete = ".uno:Copy";
else if ( TBI_SELECTIONMODE == nActionId )
aURL.Complete = ".uno:SelectTextMode";
else
aURL.Complete = ".uno:SearchDialog";
Reference< util::XURLTransformer > xTrans( util::URLTransformer::create( ::comphelper::getProcessComponentContext() ) );
xTrans->parseStrict(aURL);
Reference < XDispatch > xDisp = xProv->queryDispatch( aURL, OUString(), 0 );
if ( xDisp.is() )
xDisp->dispatch( aURL, Sequence < PropertyValue >() );
}
break;
}
case TBI_BOOKMARKS :
{
OUString aURL = pHelpInterceptor->GetCurrentURL();
if ( !aURL.isEmpty() )
{
try
{
Content aCnt( aURL, Reference< css::ucb::XCommandEnvironment >(), comphelper::getProcessComponentContext() );
css::uno::Reference< css::beans::XPropertySetInfo > xInfo = aCnt.getProperties();
if ( xInfo->hasPropertyByName( PROPERTY_TITLE ) )
{
css::uno::Any aAny = aCnt.getPropertyValue( PROPERTY_TITLE );
OUString aValue;
if ( aAny >>= aValue )
{
OUString aTitle(aValue);
SfxAddHelpBookmarkDialog_Impl aDlg(GetFrameWeld(), false);
aDlg.SetTitle(aTitle);
if (aDlg.run() == RET_OK )
{
aTitle = aDlg.GetTitle();
pIndexWin->AddBookmarks( aTitle, aURL );
}
}
}
}
catch( Exception& )
{
OSL_FAIL( "SfxHelpWindow_Impl::DoAction(): unexpected exception" );
}
}
break;
}
}
}
void SfxHelpWindow_Impl::CloseWindow()
{
try
{
// search for top frame
Reference< XFramesSupplier > xCreator = getTextFrame()->getCreator();
while ( xCreator.is() && !xCreator->isTop() )
{
xCreator = xCreator->getCreator();
}
// when found, close it
if ( xCreator.is() && xCreator->isTop() )
{
Reference < XCloseable > xCloser( xCreator, UNO_QUERY );
if ( xCloser.is() )
xCloser->close( false );
}
}
catch( Exception& )
{
SAL_WARN( "sfx.appl", "SfxHelpWindow_Impl::CloseWindow(): caught an exception" );
}
}
void SfxHelpWindow_Impl::UpdateToolbox()
{
pTextWin->GetToolBox().EnableItem( TBI_BACKWARD, pHelpInterceptor->HasHistoryPred() );
pTextWin->GetToolBox().EnableItem( TBI_FORWARD, pHelpInterceptor->HasHistorySucc() );
}
bool SfxHelpWindow_Impl::HasHistoryPredecessor() const
{
return pHelpInterceptor->HasHistoryPred();
}
bool SfxHelpWindow_Impl::HasHistorySuccessor() const
{
return pHelpInterceptor->HasHistorySucc();
}
// class SfxAddHelpBookmarkDialog_Impl -----------------------------------
SfxAddHelpBookmarkDialog_Impl::SfxAddHelpBookmarkDialog_Impl(weld::Window* pParent, bool bRename)
: GenericDialogController(pParent, "sfx/ui/bookmarkdialog.ui", "BookmarkDialog")
, m_xTitleED(m_xBuilder->weld_entry("entry"))
, m_xAltTitle(m_xBuilder->weld_label("alttitle"))
{
if (bRename)
m_xDialog->set_title(m_xAltTitle->get_label());
}
void SfxAddHelpBookmarkDialog_Impl::SetTitle(const OUString& rTitle)
{
m_xTitleED->set_text(rTitle);
m_xTitleED->select_region(0, -1);
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
↑ V547 Expression '1010 == nActionId' is always true.
↑ V1019 Compound assignment expression 'aAnySeq[2] >>= aAnchorRefList' is used inside condition.
↑ V1019 Compound assignment expression 'aAnySeq[3] >>= aTitleRefList' is used inside condition.
↑ V1020 The function exited without calling the 'LeaveWait' function. Check lines: 1404, 1382.
↑ V1019 Compound assignment expression 'aAnySeq[1] >>= aKeywordRefList' is used inside condition.