Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/LibreOffice/cui/source/dialogs/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 16 kB image not shown  

Quelle  hlmarkwn.cxx   Sprache: C

 
/* -*- 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 <dialmgr.hxx>
#include <o3tl/any.hxx>
#include <comphelper/propertyvalue.hxx>
#include <unotools/viewoptions.hxx>
#include <vcl/graph.hxx>

// UNO-Stuff
#include <comphelper/processfactory.hxx>
#include <comphelper/sequence.hxx>
#include <com/sun/star/awt/XBitmap.hpp>
#include <com/sun/star/frame/Desktop.hpp>
#include <com/sun/star/beans/NamedValue.hpp>
#include <com/sun/star/beans/PropertyValue.hpp>
#include <com/sun/star/document/XLinkTargetSupplier.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/io/IOException.hpp>

#include <toolkit/helper/vclunohelper.hxx>

#include <strings.hrc>
#include <hlmarkwn.hxx>
#include <hltpbase.hxx>
#include <hlmarkwn_def.hxx>

#include <stack>

using namespace ::com::sun::star;

namespace {

// Userdata-struct for tree-entries
struct TargetData
{
    OUString aUStrLinkname;
    bool     bIsTarget;

    TargetData (const OUString& aUStrLName, bool bTarget)
        : bIsTarget(bTarget)
    {
        if (bIsTarget)
            aUStrLinkname = aUStrLName;
    }
};

}

//*** Window-Class ***
// Constructor / Destructor
SvxHlinkDlgMarkWnd::SvxHlinkDlgMarkWnd(weld::Window* pParentDialog, SvxHyperlinkTabPageBase *pParentPage)
    : GenericDialogController(pParentDialog, u"cui/ui/hyperlinkmarkdialog.ui"_ustr, u"HyperlinkMark"_ustr)
    , mpParent(pParentPage)
    , mnError(LERR_NOERROR)
    , mxBtApply(m_xBuilder->weld_button(u"ok"_ustr))
    , mxBtClose(m_xBuilder->weld_button(u"close"_ustr))
    , mxLbTree(m_xBuilder->weld_tree_view(u"TreeListBox"_ustr))
    , mxError(m_xBuilder->weld_label(u"error"_ustr))
{
    mxLbTree->set_size_request(mxLbTree->get_approximate_digit_width() * 25,
                               mxLbTree->get_height_rows(12));
    mxBtApply->connect_clicked( LINK ( this, SvxHlinkDlgMarkWnd, ClickApplyHdl_Impl ) );
    mxBtClose->connect_clicked( LINK ( this, SvxHlinkDlgMarkWnd, ClickCloseHdl_Impl ) );
    mxLbTree->connect_row_activated( LINK ( this, SvxHlinkDlgMarkWnd, DoubleClickApplyHdl_Impl ) );

    // tdf#149935 - remember last used position and size
    SvtViewOptions aDlgOpt(EViewType::Dialog, m_xDialog->get_help_id());
    if (aDlgOpt.Exists())
        m_xDialog->set_window_state(aDlgOpt.GetWindowState());
}

SvxHlinkDlgMarkWnd::~SvxHlinkDlgMarkWnd()
{
    ClearTree();
    // tdf#149935 - remember last used position and size
    SvtViewOptions aDlgOpt(EViewType::Dialog, m_xDialog->get_help_id());
    aDlgOpt.SetWindowState(m_xDialog->get_window_state(vcl::WindowDataMask::PosSize));
}

void SvxHlinkDlgMarkWnd::ErrorChanged()
{
    if (mnError == LERR_NOENTRIES)
    {
        OUString aStrMessage = CuiResId( RID_CUISTR_HYPDLG_ERR_LERR_NOENTRIES );
        mxError->set_label(aStrMessage);
        mxError->show();
        mxLbTree->hide();
    }
    else if (mnError == LERR_DOCNOTOPEN)
    {
        OUString aStrMessage = CuiResId( RID_CUISTR_HYPDLG_ERR_LERR_DOCNOTOPEN );
        mxError->set_label(aStrMessage);
        mxError->show();
        mxLbTree->hide();
    }
    else
    {
        mxLbTree->show();
        mxError->hide();
    }
}

// Set an errorstatus
sal_uInt16 SvxHlinkDlgMarkWnd::SetError( sal_uInt16 nError)
{
    sal_uInt16 nOldError = mnError;
    mnError = nError;

    if( mnError != LERR_NOERROR )
        ClearTree();

    ErrorChanged();

    return nOldError;
}

// Move window
void SvxHlinkDlgMarkWnd::MoveTo(const Point& rNewPos)
{
    // tdf#149935 - remember last used position and size
    SvtViewOptions aDlgOpt(EViewType::Dialog, m_xDialog->get_help_id());
    if (aDlgOpt.Exists())
        m_xDialog->set_window_state(aDlgOpt.GetWindowState());
    else
        m_xDialog->window_move(rNewPos.X(), rNewPos.Y());
}

namespace
{
    void SelectPath(weld::TreeIter* pEntry, weld::TreeView& rLbTree,
        std::deque<OUString> &rLastSelectedPath)
    {
        OUString sTitle(rLastSelectedPath.front());
        rLastSelectedPath.pop_front();
        if (sTitle.isEmpty())
            return;
        while (pEntry)
        {
            if (sTitle == rLbTree.get_text(*pEntry))
            {
                rLbTree.select(*pEntry);
                rLbTree.scroll_to_row(*pEntry);
                if (!rLastSelectedPath.empty())
                {
                    rLbTree.expand_row(*pEntry);
                    if (!rLbTree.iter_children(*pEntry))
                        pEntry = nullptr;
                    SelectPath(pEntry, rLbTree, rLastSelectedPath);
                }
                break;
            }
            if (!rLbTree.iter_next_sibling(*pEntry))
                pEntry = nullptr;
        }
    }
}

constexpr OUString TG_SETTING_MANAGER = u"TargetInDocument"_ustr;
constexpr OUString TG_SETTING_LASTMARK = u"LastSelectedMark"_ustr;
constexpr OUString TG_SETTING_LASTPATH = u"LastSelectedPath"_ustr;

void SvxHlinkDlgMarkWnd::RestoreLastSelection()
{
    bool bSelectedEntry = false;

    OUString sLastSelectedMark;
    std::deque<OUString> aLastSelectedPath;
    SvtViewOptions aViewSettings( EViewType::Dialog, TG_SETTING_MANAGER );
    if (aViewSettings.Exists())
    {
        //Maybe we might want to have some sort of mru list and keep a mapping
        //per document, rather than the current reuse of "the last thing
        //selected, regardless of the document"
        aViewSettings.GetUserItem(TG_SETTING_LASTMARK) >>= sLastSelectedMark;
        uno::Sequence<OUString> aTmp;
        aViewSettings.GetUserItem(TG_SETTING_LASTPATH) >>= aTmp;
        aLastSelectedPath = comphelper::sequenceToContainer< std::deque<OUString> >(aTmp);
    }
    //fallback to previous entry selected the last time we executed this dialog.
    //First see if the exact mark exists and re-use that
    if (!sLastSelectedMark.isEmpty())
        bSelectedEntry = SelectEntry(sLastSelectedMark);
    //Otherwise just select the closest path available
    //now to what was available at dialog close time
    if (!bSelectedEntry && !aLastSelectedPath.empty())
    {
        std::deque<OUString> aTmpSelectedPath(std::move(aLastSelectedPath));
        std::unique_ptr<weld::TreeIter> xEntry(mxLbTree->make_iterator());
        if (!mxLbTree->get_iter_first(*xEntry))
            xEntry.reset();
        SelectPath(xEntry.get(), *mxLbTree, aTmpSelectedPath);
    }
}

// Interface to refresh tree
void SvxHlinkDlgMarkWnd::RefreshTree (const OUString& aStrURL)
{
    OUString aUStrURL;

    weld::WaitObject aWait(m_xDialog.get());

    ClearTree();

    sal_Int32 nPos = aStrURL.indexOf('#');

    if (nPos != 0)
        aUStrURL = aStrURL;

    if (!RefreshFromDoc(aUStrURL))
        ErrorChanged();

    bool bSelectedEntry = false;

    if ( nPos != -1 )
    {
        OUString aStrMark = aStrURL.copy(nPos+1);
        bSelectedEntry = SelectEntry(aStrMark);
    }

    if (!bSelectedEntry)
        RestoreLastSelection();
}

// get links from document
bool SvxHlinkDlgMarkWnd::RefreshFromDoc(const OUString& aURL)
{
    mnError = LERR_NOERROR;

    uno::Reference< frame::XDesktop2 > xDesktop = frame::Desktop::create( ::comphelper::getProcessComponentContext() );
    uno::Reference< lang::XComponent > xComp;

    if( !aURL.isEmpty() )
    {
        // load from url
        if( xDesktop.is() )
        {
            try
            {
                uno::Sequence< beans::PropertyValue > aArg { comphelper::makePropertyValue(u"Hidden"_ustr, true) };
                xComp = xDesktop->loadComponentFromURL( aURL, u"_blank"_ustr, 0, aArg );
            }
            catchconst io::IOException& )
            {

            }
            catchconst lang::IllegalArgumentException& )
            {

            }
        }
    }
    else
    {
        // the component with user focus ( current document )
        xComp = xDesktop->getCurrentComponent();
    }

    if( xComp.is() )
    {
        uno::Reference< document::XLinkTargetSupplier > xLTS( xComp, uno::UNO_QUERY );

        if( xLTS.is() )
        {
            if( FillTree( xLTS->getLinks() ) == 0 )
                mnError = LERR_NOENTRIES;
        }
        else
            mnError = LERR_DOCNOTOPEN;

        if ( !aURL.isEmpty() )
            xComp->dispose();
    }
    else
    {
        if( !aURL.isEmpty() )
            mnError=LERR_DOCNOTOPEN;
    }
    return (mnError==0);
}

// Fill Tree-Control
int SvxHlinkDlgMarkWnd::FillTree( const uno::Reference< container::XNameAccess >& xLinks, const weld::TreeIter* pParentEntry )
{
    // used to create the Headings outline parent children tree view relation
    std::stack<std::pair<std::unique_ptr<weld::TreeIter>, const sal_Int32>> aHeadingsParentEntryStack;

    int nEntries=0;

    static constexpr OUStringLiteral aProp_LinkDisplayName( u"LinkDisplayName" );
    static constexpr OUStringLiteral aProp_LinkTarget( u"com.sun.star.document.LinkTarget" );
    static constexpr OUStringLiteral aProp_LinkDisplayBitmap( u"LinkDisplayBitmap" );
    for (auto& aLink : xLinks->getElementNames())
    {
        uno::Any aAny;

        try
        {
            aAny = xLinks->getByName( aLink );
        }
        catch(const uno::Exception&)
        {
            // if the name of the target was invalid (like empty headings)
            // no object can be provided
            continue;
        }

        uno::Reference< beans::XPropertySet > xTarget;

        if( aAny >>= xTarget )
        {
            try
            {
                // get name to display
                aAny = xTarget->getPropertyValue( aProp_LinkDisplayName );
                OUString aDisplayName;
                aAny >>= aDisplayName;
                OUString aStrDisplayname ( aDisplayName );

                // is it a target ?
                uno::Reference< lang::XServiceInfo > xSI( xTarget, uno::UNO_QUERY );
                bool bIsTarget = xSI->supportsService( aProp_LinkTarget );

                // create userdata
                TargetData *pData = new TargetData ( aLink, bIsTarget );
                OUString sId(weld::toId(pData));

                std::unique_ptr<weld::TreeIter> xEntry(mxLbTree->make_iterator());
                if (pParentEntry)
                {
                    OUString sContentType = mxLbTree->get_text(*pParentEntry);
                    if (sContentType == "Headings")
                    {
                        if (aHeadingsParentEntryStack.empty())
                            aHeadingsParentEntryStack.push(
                                        std::pair(mxLbTree->make_iterator(pParentEntry), -1));

                        // get the headings name to display
                        aAny = xTarget->getPropertyValue(u"ActualOutlineName"_ustr);
                        OUString sActualOutlineName;
                        aAny >>= sActualOutlineName;

                        // get the headings outline level
                        aAny = xTarget->getPropertyValue(u"OutlineLevel"_ustr);
                        sal_Int32 nOutlineLevel = *o3tl::doAccess<sal_Int32>(aAny);

                        // pop until the top of stack entry has an outline level less than
                        // the to be inserted heading outline level
                        while (nOutlineLevel <= aHeadingsParentEntryStack.top().second)
                            aHeadingsParentEntryStack.pop();

                        mxLbTree->insert(aHeadingsParentEntryStack.top().first.get(), -1,
                                         &sActualOutlineName, &sId, nullptr, nullptr, false,
                                         xEntry.get());

                        // push if the inserted entry is a child
                        if (nOutlineLevel > aHeadingsParentEntryStack.top().second)
                            aHeadingsParentEntryStack.push(
                                        std::pair(mxLbTree->make_iterator(xEntry.get()), nOutlineLevel));
                    }
                    else
                    {
                        mxLbTree->insert(pParentEntry, -1, &aStrDisplayname, &sId, nullptr,
                                         nullptr, false, xEntry.get());
                    }
                }
                else
                {
                    mxLbTree->insert(pParentEntry, -1, &aStrDisplayname, &sId, nullptr, nullptr,
                                     false, xEntry.get());
                }

                try
                {
                    // get bitmap for the tree-entry
                    uno::Reference< awt::XBitmap >
                        aXBitmap( xTarget->getPropertyValue( aProp_LinkDisplayBitmap ), uno::UNO_QUERY );
                    if (aXBitmap.is())
                    {
                        Graphic aBmp(Graphic(VCLUnoHelper::GetBitmap(aXBitmap)));
                        // insert Displayname into treelist with bitmaps
                        mxLbTree->set_image(*xEntry, aBmp.GetXGraphic(), -1);
                    }
                }
                catch(const css::uno::Exception&)
                {
                }

                nEntries++;

                uno::Reference< document::XLinkTargetSupplier > xLTS( xTarget, uno::UNO_QUERY );
                if( xLTS.is() )
                    nEntries += FillTree( xLTS->getLinks(), xEntry.get() );
            }
            catch(const css::uno::Exception&)
            {
            }
        }
    }

    return nEntries;
}

// Clear Tree
void SvxHlinkDlgMarkWnd::ClearTree()
{
    std::unique_ptr<weld::TreeIter> xEntry = mxLbTree->make_iterator();
    bool bEntry = mxLbTree->get_iter_first(*xEntry);

    while (bEntry)
    {
        TargetData* pUserData = weld::fromId<TargetData*>(mxLbTree->get_id(*xEntry));
        delete pUserData;

        bEntry = mxLbTree->iter_next(*xEntry);
    }

    mxLbTree->clear();
}

// Find Entry for String
std::unique_ptr<weld::TreeIter> SvxHlinkDlgMarkWnd::FindEntry (std::u16string_view aStrName)
{
    bool bFound=false;
    std::unique_ptr<weld::TreeIter> xEntry = mxLbTree->make_iterator();
    bool bEntry = mxLbTree->get_iter_first(*xEntry);

    while (bEntry && !bFound)
    {
        TargetData* pUserData = weld::fromId<TargetData*>(mxLbTree->get_id(*xEntry));
        if (aStrName == pUserData->aUStrLinkname)
            bFound = true;
        else
            bEntry = mxLbTree->iter_next(*xEntry);
    }

    if (!bFound)
        xEntry.reset();

    return xEntry;
}

// Select Entry
bool SvxHlinkDlgMarkWnd::SelectEntry(std::u16string_view aStrMark)
{
    std::unique_ptr<weld::TreeIter> xEntry = FindEntry(aStrMark);
    if (!xEntry)
        return false;
    mxLbTree->set_cursor(*xEntry);
    return true;
}

// Click on Apply-Button / Double-click on item in tree
IMPL_LINK_NOARG(SvxHlinkDlgMarkWnd, DoubleClickApplyHdl_Impl, weld::TreeView&, bool)
{
    ClickApplyHdl_Impl(*mxBtApply);
    return true;
}

IMPL_LINK_NOARG(SvxHlinkDlgMarkWnd, ClickApplyHdl_Impl, weld::Button&, void)
{
    std::unique_ptr<weld::TreeIter> xEntry(mxLbTree->make_iterator());
    bool bEntry = mxLbTree->get_cursor(xEntry.get());
    if (bEntry)
    {
        TargetData* pData = weld::fromId<TargetData*>(mxLbTree->get_id(*xEntry));
        if (pData->bIsTarget)
        {
            mpParent->SetMarkStr(pData->aUStrLinkname);
        }
    }
}

// Click on Close-Button
IMPL_LINK_NOARG(SvxHlinkDlgMarkWnd, ClickCloseHdl_Impl, weld::Button&, void)
{
    std::unique_ptr<weld::TreeIter> xEntry(mxLbTree->make_iterator());
    bool bEntry = mxLbTree->get_cursor(xEntry.get());
    if (bEntry)
    {
        TargetData* pUserData = weld::fromId<TargetData*>(mxLbTree->get_id(*xEntry));
        OUString sLastSelectedMark = pUserData->aUStrLinkname;

        std::deque<OUString> aLastSelectedPath;
        //If the bottommost entry is expanded but nothing
        //underneath it is selected leave a dummy entry
        if (mxLbTree->get_row_expanded(*xEntry))
            aLastSelectedPath.push_front(OUString());
        while (bEntry)
        {
            aLastSelectedPath.push_front(mxLbTree->get_text(*xEntry));
            bEntry = mxLbTree->iter_parent(*xEntry);
        }

        uno::Sequence< beans::NamedValue > aSettings
        {
            { TG_SETTING_LASTMARK, css::uno::Any(sLastSelectedMark) },
            { TG_SETTING_LASTPATH, css::uno::Any(comphelper::containerToSequence(aLastSelectedPath)) }
        };

        // write
        SvtViewOptions aViewSettings( EViewType::Dialog, TG_SETTING_MANAGER );
        aViewSettings.SetUserData( aSettings );
    }

    m_xDialog->response(RET_CANCEL);
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Messung V0.5
C=93 H=92 G=92

¤ Dauer der Verarbeitung: 0.11 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.