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

Quelle  GroupsSorting.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 <GroupsSorting.hxx>
#include <svtools/editbrowsebox.hxx>
#include <toolkit/helper/vclunohelper.hxx>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/container/XContainerListener.hpp>
#include <com/sun/star/report/GroupOn.hpp>
#include <com/sun/star/sdbc/DataType.hpp>

#include <strings.hrc>
#include <rptui_slotid.hrc>
#include <core_resource.hxx>
#include <helpids.h>
#include "GroupExchange.hxx"
#include <UITools.hxx>
#include <UndoActions.hxx>
#include <strings.hxx>
#include <ReportController.hxx>
#include <ColumnInfo.hxx>

#include <comphelper/propertyvalue.hxx>
#include <cppuhelper/implbase.hxx>
#include <vcl/commandevent.hxx>
#include <vcl/svapp.hxx>
#include <comphelper/diagnose_ex.hxx>

#include <algorithm>

#define HANDLE_ID           0
#define FIELD_EXPRESSION    1
#define GROUPS_START_LEN    5
#define NO_GROUP            -1

namespace rptui
{
using namespace ::com::sun::star;
using namespace svt;
using namespace ::comphelper;

    static void lcl_addToList_throw( weld::ComboBox& _rListBox, ::std::vector<ColumnInfo>& o_aColumnList,const uno::Reference< container::XNameAccess>& i_xColumns )
    {
        const uno::Sequence< OUString > aEntries = i_xColumns->getElementNames();
        for ( const OUString& rEntry : aEntries )
        {
            uno::Reference< beans::XPropertySet> xColumn(i_xColumns->getByName(rEntry),uno::UNO_QUERY_THROW);
            OUString sLabel;
            if ( xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_LABEL) )
                xColumn->getPropertyValue(PROPERTY_LABEL) >>= sLabel;
            o_aColumnList.emplace_back(rEntry,sLabel );
            if ( !sLabel.isEmpty() )
                _rListBox.append_text( sLabel );
            else
                _rListBox.append_text( rEntry );
        }
    }

/**
  * Separated out from OFieldExpressionControl to prevent collision of ref-counted base classes
  */

class OFieldExpressionControl;

namespace {

class OFieldExpressionControlContainerListener : public ::cppu::WeakImplHelper< container::XContainerListener >
{
    VclPtr<OFieldExpressionControl> mpParent;
public:
    explicit OFieldExpressionControlContainerListener(OFieldExpressionControl* pParent) : mpParent(pParent) {}

    // XEventListener
    virtual void SAL_CALL disposing(const css::lang::EventObject& Source) override;
    // XContainerListener
    virtual void SAL_CALL elementInserted(const css::container::ContainerEvent& rEvent) override;
    virtual void SAL_CALL elementReplaced(const css::container::ContainerEvent& rEvent) override;
    virtual void SAL_CALL elementRemoved(const css::container::ContainerEvent& rEvent) override;
};

}

class OFieldExpressionControl : public ::svt::EditBrowseBox
{
    ::osl::Mutex                    m_aMutex;
    ::std::vector<sal_Int32>        m_aGroupPositions;
    ::std::vector<ColumnInfo>       m_aColumnInfo;
    VclPtr< ::svt::ComboBoxControl>  m_pComboCell;
    sal_Int32                       m_nDataPos;
    sal_Int32                       m_nCurrentPos;
    ImplSVEvent *                   m_nDeleteEvent;
    OGroupsSortingDialog*           m_pParent;
    bool                            m_bIgnoreEvent;
    rtl::Reference<OFieldExpressionControlContainerListener> aContainerListener;

public:
    OFieldExpressionControl(OGroupsSortingDialog* pParentDialog, const css::uno::Reference<css::awt::XWindow> &rParent);
    virtual ~OFieldExpressionControl() override;
    virtual void dispose() override;

    // XContainerListener
    /// @throws css::uno::RuntimeException
    void elementInserted(const css::container::ContainerEvent& rEvent);
    /// @throws css::uno::RuntimeException
    void elementRemoved(const css::container::ContainerEvent& rEvent);

    virtual Size GetOptimalSize() const override;

    void        fillColumns(const uno::Reference< container::XNameAccess>& _xColumns);
    void        lateInit();
    bool    IsDeleteAllowed( ) const;
    void        DeleteRows();

    sal_Int32   getGroupPosition(sal_Int32 _nRow) const { return _nRow != BROWSER_ENDOFSELECTION ? m_aGroupPositions[_nRow] : sal_Int32(NO_GROUP); }

    /** returns the sequence with the selected groups
    */

    uno::Sequence<uno::Any> fillSelectedGroups();

    /** move groups given by _aGroups
    */

    void moveGroups(const uno::Sequence<uno::Any>& _aGroups,sal_Int32 _nRow,bool _bSelect = true);

    virtual bool CursorMoving(sal_Int32 nNewRow, sal_uInt16 nNewCol) override;
    using ::svt::EditBrowseBox::GetRowCount;
protected:
    virtual bool IsTabAllowed(bool bForward) const override;

    virtual void InitController( ::svt::CellControllerRef& rController, sal_Int32 nRow, sal_uInt16 nCol ) override;
    virtual ::svt::CellController* GetController( sal_Int32 nRow, sal_uInt16 nCol ) override;
    virtual void PaintCell( OutputDevice& rDev, const tools::Rectangle& rRect, sal_uInt16 nColId ) const override;
    virtual bool SeekRow( sal_Int32 nRow ) override;
    virtual bool SaveModified() override;
    virtual OUString GetCellText( sal_Int32 nRow, sal_uInt16 nColId ) const override;
    virtual RowStatus GetRowStatus(sal_Int32 nRow) const override;

    virtual void KeyInput(const KeyEvent& rEvt) override;
    virtual void Command( const CommandEvent& rEvt ) override;

    // D&D
    virtual void     StartDrag( sal_Int8 nAction, const Point& rPosPixel ) override;
    virtual sal_Int8 AcceptDrop( const BrowserAcceptDropEvent& rEvt ) override;
    virtual sal_Int8 ExecuteDrop( const BrowserExecuteDropEvent& rEvt ) override;

    using BrowseBox::AcceptDrop;
    using BrowseBox::ExecuteDrop;

private:

    DECL_LINK( CBChangeHdl, weld::ComboBox&, void);

public:
    DECL_LINK( DelayedDelete, void*, void );

};


void OFieldExpressionControlContainerListener::disposing(const css::lang::EventObject& )
{}

void OFieldExpressionControlContainerListener::elementInserted(const css::container::ContainerEvent& rEvent)
{ mpParent->elementInserted(rEvent); }

void OFieldExpressionControlContainerListener::elementReplaced(const css::container::ContainerEvent& )
{}

void OFieldExpressionControlContainerListener::elementRemoved(const css::container::ContainerEvent& rEvent)
{ mpParent->elementRemoved(rEvent); }

OFieldExpressionControl::OFieldExpressionControl(OGroupsSortingDialog* pParentDialog, const css::uno::Reference<css::awt::XWindow> &rParent)
    :EditBrowseBox( VCLUnoHelper::GetWindow(rParent), EditBrowseBoxFlags::NONE, WB_TABSTOP,
                    BrowserMode::COLUMNSELECTION | BrowserMode::MULTISELECTION | BrowserMode::AUTOSIZE_LASTCOL |
                              BrowserMode::KEEPHIGHLIGHT | BrowserMode::HLINES | BrowserMode::VLINES)
    ,m_aGroupPositions(GROUPS_START_LEN,-1)
    ,m_pComboCell(nullptr)
    ,m_nDataPos(-1)
    ,m_nCurrentPos(-1)
    ,m_nDeleteEvent(nullptr)
    ,m_pParent(pParentDialog)
    ,m_bIgnoreEvent(false)
    ,aContainerListener(new OFieldExpressionControlContainerListener(this))
{
    SetBorderStyle(WindowBorderStyle::MONO);
}

OFieldExpressionControl::~OFieldExpressionControl()
{
    disposeOnce();
}

void OFieldExpressionControl::dispose()
{
    uno::Reference< report::XGroups > xGroups = m_pParent->getGroups();
    xGroups->removeContainerListener(aContainerListener);

    // delete events from queue
    if( m_nDeleteEvent )
        Application::RemoveUserEvent( m_nDeleteEvent );

    m_pComboCell.disposeAndClear();
    m_pParent = nullptr;
    ::svt::EditBrowseBox::dispose();
}

uno::Sequence<uno::Any> OFieldExpressionControl::fillSelectedGroups()
{
    uno::Sequence<uno::Any> aList;
    ::std::vector<uno::Any> vClipboardList;
    vClipboardList.reserve(GetSelectRowCount());

    uno::Reference<report::XGroups> xGroups = m_pParent->getGroups();
    sal_Int32 nCount = xGroups->getCount();
    if ( nCount >= 1 )
    {
        for( tools::Long nIndex=FirstSelectedRow(); nIndex != SFX_ENDOFSELECTION; nIndex=NextSelectedRow() )
        {
            try
            {
                if ( m_aGroupPositions[nIndex] != NO_GROUP )
                {
                    uno::Reference< report::XGroup> xOrgGroup(xGroups->getByIndex(m_aGroupPositions[nIndex]),uno::UNO_QUERY);
                    /*uno::Reference< report::XGroup> xCopy = xGroups->createGroup();
                    ::comphelper::copyProperties(xOrgGroup.get(),xCopy.get());*/

                    vClipboardList.push_back( uno::Any(xOrgGroup) );
                }
            }
            catch(uno::Exception&)
            {
                OSL_FAIL("Can not access group!");
            }
        }
        if ( !vClipboardList.empty() )
            aList = uno::Sequence< uno::Any >(vClipboardList.data(), vClipboardList.size());
    }
    return aList;
}

void OFieldExpressionControl::StartDrag( sal_Int8 /*_nAction*/ , const Point& /*_rPosPixel*/ )
{
    if ( m_pParent && !m_pParent->isReadOnly( ) )
    {
        uno::Sequence<uno::Any> aClipboardList = fillSelectedGroups();

        if( aClipboardList.hasElements() )
        {
            rtl::Reference<OGroupExchange> pData = new OGroupExchange(aClipboardList);
            pData->StartDrag(this, DND_ACTION_MOVE );
        }
    }
}

sal_Int8 OFieldExpressionControl::AcceptDrop( const BrowserAcceptDropEvent& rEvt )
{
    sal_Int8 nAction = DND_ACTION_NONE;
    if ( IsEditing() )
    {
        weld::ComboBox& rComboBox = m_pComboCell->get_widget();
        sal_Int32 nPos = rComboBox.get_active();
        if (nPos != -1 || !rComboBox.get_active_text().isEmpty())
            SaveModified();
        DeactivateCell();
    }
    if ( IsDropFormatSupported( OGroupExchange::getReportGroupId() ) && m_pParent->getGroups()->getCount() > 1 && rEvt.GetWindow() == &GetDataWindow() )
    {
        nAction = DND_ACTION_MOVE;
    }
    return nAction;
}

sal_Int8 OFieldExpressionControl::ExecuteDrop( const BrowserExecuteDropEvent& rEvt )
{
    sal_Int8 nAction = DND_ACTION_NONE;
    if ( IsDropFormatSupported( OGroupExchange::getReportGroupId() ) )
    {
        sal_Int32   nRow = GetRowAtYPosPixel(rEvt.maPosPixel.Y(), false);
        SetNoSelection();

        TransferableDataHelper aDropped( rEvt.maDropEvent.Transferable );
        uno::Any aDrop = aDropped.GetAny(OGroupExchange::getReportGroupId(), OUString());
        uno::Sequence< uno::Any > aGroups;
        aDrop >>= aGroups;
        if ( aGroups.hasElements() )
        {
            moveGroups(aGroups,nRow);
            nAction = DND_ACTION_MOVE;
        }
    }
    return nAction;
}

void OFieldExpressionControl::moveGroups(const uno::Sequence<uno::Any>& _aGroups,sal_Int32 _nRow,bool _bSelect)
{
    if ( !_aGroups.hasElements() )
        return;

    m_bIgnoreEvent = true;
    {
        sal_Int32 nRow = _nRow;
        const OUString sUndoAction(RptResId(RID_STR_UNDO_MOVE_GROUP));
        const UndoContext aUndoContext( m_pParent->m_pController->getUndoManager(), sUndoAction );

        uno::Reference< report::XGroups> xGroups = m_pParent->getGroups();
        for(const uno::Any& rGroup : _aGroups)
        {
            uno::Reference< report::XGroup> xGroup(rGroup,uno::UNO_QUERY);
            if ( xGroup.is() )
            {
                uno::Sequence< beans::PropertyValue > aArgs{ comphelper::makePropertyValue(
                    PROPERTY_GROUP, xGroup) };
                // we use this way to create undo actions
                m_pParent->m_pController->executeChecked(SID_GROUP_REMOVE,aArgs);
                aArgs.realloc(2);
                auto pArgs = aArgs.getArray();
                if ( nRow > xGroups->getCount() )
                    nRow = xGroups->getCount();
                if ( _bSelect )
                    SelectRow(nRow);
                pArgs[1].Name = PROPERTY_POSITIONY;
                pArgs[1].Value <<= nRow;
                m_pParent->m_pController->executeChecked(SID_GROUP_APPEND,aArgs);
                ++nRow;
            }
        }
    }
    m_bIgnoreEvent = false;
    Invalidate();
}

void OFieldExpressionControl::fillColumns(const uno::Reference< container::XNameAccess>& _xColumns)
{
    weld::ComboBox& rComboBox = m_pComboCell->get_widget();
    rComboBox.clear();
    if ( _xColumns.is() )
        lcl_addToList_throw(rComboBox, m_aColumnInfo, _xColumns);
}

void OFieldExpressionControl::lateInit()
{
    uno::Reference< report::XGroups > xGroups = m_pParent->getGroups();
    sal_Int32 nGroupsCount = xGroups->getCount();
    m_aGroupPositions.resize(::std::max<sal_Int32>(nGroupsCount,sal_Int32(GROUPS_START_LEN)),NO_GROUP);
    ::std::vector<sal_Int32>::iterator aIter = m_aGroupPositions.begin();
    for (sal_Int32 i = 0; i < nGroupsCount; ++i,++aIter)
        *aIter = i;

    if ( ColCount() == 0 )
    {
        vcl::Font aFont( GetDataWindow().GetFont() );
        aFont.SetWeight( WEIGHT_NORMAL );
        GetDataWindow().SetFont( aFont );

        // Set font of the headline to light
        aFont = GetFont();
        aFont.SetWeight( WEIGHT_LIGHT );
        SetFont(aFont);

        InsertHandleColumn(static_cast<sal_uInt16>(GetTextWidth(OUString('0')) * 4)/*, sal_True */);
        InsertDataColumn( FIELD_EXPRESSION, RptResId(STR_RPT_EXPRESSION), 100);

        m_pComboCell = VclPtr<ComboBoxControl>::Create( &GetDataWindow() );
        weld::ComboBox& rComboBox = m_pComboCell->get_widget();
        rComboBox.connect_changed(LINK(this,OFieldExpressionControl,CBChangeHdl));
        m_pComboCell->SetHelpId(HID_RPT_FIELDEXPRESSION);

        m_pComboCell->SetFocusInHdl(LINK(m_pParent, OGroupsSortingDialog, OnControlFocusGot));


        // set browse mode
        BrowserMode nMode(BrowserMode::COLUMNSELECTION | BrowserMode::MULTISELECTION  | BrowserMode::KEEPHIGHLIGHT |
                          BrowserMode::HLINES | BrowserMode::VLINES       | BrowserMode::AUTOSIZE_LASTCOL | BrowserMode::AUTO_VSCROLL | BrowserMode::AUTO_HSCROLL);
        if( m_pParent->isReadOnly() )
            nMode |= BrowserMode::HIDECURSOR;
        SetMode(nMode);
        xGroups->addContainerListener(aContainerListener);
    }
    else
        // not the first call
        RowRemoved(0, GetRowCount());

    RowInserted(0, m_aGroupPositions.size());
}

IMPL_LINK_NOARG( OFieldExpressionControl, CBChangeHdl, weld::ComboBox&, void )
{
    SaveModified();
}

bool OFieldExpressionControl::IsTabAllowed(bool /*bForward*/) const
{
    return false;
}

bool OFieldExpressionControl::SaveModified()
{
    sal_Int32 nRow = GetCurRow();
    if ( nRow == BROWSER_ENDOFSELECTION )
        return true;

    try
    {
        bool bAppend = false;
        uno::Reference< report::XGroup> xGroup;
        if ( m_aGroupPositions[nRow] == NO_GROUP )
        {
            bAppend = true;
            OUString sUndoAction(RptResId(RID_STR_UNDO_APPEND_GROUP));
            m_pParent->m_pController->getUndoManager().EnterListAction( sUndoAction, OUString(), 0, ViewShellId(-1) );
            xGroup = m_pParent->getGroups()->createGroup();
            xGroup->setHeaderOn(true);

            // find position where to insert the new group
            sal_Int32 nGroupPos = 0;
            ::std::vector<sal_Int32>::iterator aIter = m_aGroupPositions.begin();
            ::std::vector<sal_Int32>::const_iterator aEnd  = m_aGroupPositions.begin() + nRow;
            for(;aIter != aEnd;++aIter)
                if ( *aIter != NO_GROUP )
                    nGroupPos = *aIter + 1;
            uno::Sequence< beans::PropertyValue > aArgs{
                comphelper::makePropertyValue(PROPERTY_GROUP, xGroup),
                comphelper::makePropertyValue(PROPERTY_POSITIONY, nGroupPos)
            };
            m_bIgnoreEvent = true;
            m_pParent->m_pController->executeChecked(SID_GROUP_APPEND,aArgs);
            m_bIgnoreEvent = false;
            OSL_ENSURE(*aIter == NO_GROUP ,"Illegal iterator!");
            *aIter++ = nGroupPos;

            aEnd  = m_aGroupPositions.end();
            for(;aIter != aEnd;++aIter)
                if ( *aIter != NO_GROUP )
                    ++*aIter;
        }
        else
            xGroup = m_pParent->getGroup(m_aGroupPositions[nRow]);
        if ( xGroup.is() )
        {
            weld::ComboBox& rComboBox = m_pComboCell->get_widget();
            sal_Int32 nPos = rComboBox.get_active();
            OUString sExpression;
            if (nPos == -1)
                sExpression = rComboBox.get_active_text();
            else
            {
                sExpression = m_aColumnInfo[nPos].sColumnName;
            }
            xGroup->setExpression( sExpression );

            ::rptui::adjustSectionName(xGroup,nPos);

            if ( bAppend )
                m_pParent->m_pController->getUndoManager().LeaveListAction();
        }

        if (Controller().is())
            Controller()->SaveValue();
        if ( GetRowCount() == m_pParent->getGroups()->getCount() )
        {
            RowInserted( GetRowCount()-1);
            m_aGroupPositions.push_back(NO_GROUP);
        }

        GoToRow(nRow);
        m_pParent->DisplayData(nRow);
    }
    catch(uno::Exception&)
    {
        TOOLS_WARN_EXCEPTION( "reportdesign""OFieldExpressionControl::SaveModified");
    }

    return true;
}

OUString OFieldExpressionControl::GetCellText( sal_Int32 nRow, sal_uInt16 /*nColId*/ ) const
{
    OUString sText;
    if ( nRow != BROWSER_ENDOFSELECTION && m_aGroupPositions[nRow] != NO_GROUP )
    {
        try
        {
            uno::Reference< report::XGroup> xGroup = m_pParent->getGroup(m_aGroupPositions[nRow]);
            OUString sExpression = xGroup->getExpression();

            auto aIter = std::find_if(m_aColumnInfo.begin(), m_aColumnInfo.end(),
                [&sExpression](const ColumnInfo& rColumnInfo) { return rColumnInfo.sColumnName == sExpression; });
            if (aIter != m_aColumnInfo.end() && !aIter->sLabel.isEmpty())
                sExpression = aIter->sLabel;
            sText = sExpression;
        }
        catch (const uno::Exception&)
        {
            TOOLS_WARN_EXCEPTION( "reportdesign""Exception caught while getting expression value from the group");
        }
    }
    return sText;
}

void OFieldExpressionControl::InitController( CellControllerRef& /*rController*/, sal_Int32 nRow, sal_uInt16 nColumnId )
{
    weld::ComboBox& rComboBox = m_pComboCell->get_widget();
    rComboBox.set_entry_text(GetCellText(nRow, nColumnId));
}

bool OFieldExpressionControl::CursorMoving(sal_Int32 nNewRow, sal_uInt16 nNewCol)
{

    if (!EditBrowseBox::CursorMoving(nNewRow, nNewCol))
        return false;
    m_nDataPos = nNewRow;
    tools::Long nOldDataPos = GetCurRow();
    InvalidateStatusCell( m_nDataPos );
    InvalidateStatusCell( nOldDataPos );

    m_pParent->SaveData( nOldDataPos );
    m_pParent->DisplayData( m_nDataPos );
    return true;
}

CellController* OFieldExpressionControl::GetController( sal_Int32 /*nRow*/, sal_uInt16 /*nColumnId*/ )
{
    ComboBoxCellController* pCellController = new ComboBoxCellController( m_pComboCell );
    pCellController->GetComboBox().set_entry_editable(m_pParent->m_pController->isEditable());
    return pCellController;
}

bool OFieldExpressionControl::SeekRow( sal_Int32 _nRow )
{
    // the basis class needs the call, because that's how the class knows which line will be painted
    EditBrowseBox::SeekRow(_nRow);
    m_nCurrentPos = _nRow;
    return true;
}

void OFieldExpressionControl::PaintCell( OutputDevice& rDev, const tools::Rectangle& rRect, sal_uInt16 nColumnId ) const
{
    OUString aText  =GetCellText( m_nCurrentPos, nColumnId );

    Point aPos( rRect.TopLeft() );
    Size aTextSize( GetDataWindow().GetTextWidth( aText ), GetDataWindow().GetTextHeight() );

    if( aPos.X() < rRect.Left() || aPos.X() + aTextSize.Width() > rRect.Right() ||
        aPos.Y() < rRect.Top() || aPos.Y() + aTextSize.Height() > rRect.Bottom() )
        rDev.SetClipRegion(vcl::Region(rRect));

    rDev.DrawText( aPos, aText );

    if( rDev.IsClipRegion() )
        rDev.SetClipRegion();
}

EditBrowseBox::RowStatus OFieldExpressionControl::GetRowStatus(sal_Int32 nRow) const
{
    if (nRow >= 0 && nRow == m_nDataPos)
        return EditBrowseBox::CURRENT;
    if ( nRow != BROWSER_ENDOFSELECTION && nRow < static_cast<tools::Long>(m_aGroupPositions.size()) && m_aGroupPositions[nRow] != NO_GROUP )
    {
        try
        {
            uno::Reference< report::XGroup> xGroup = m_pParent->getGroup(m_aGroupPositions[nRow]);
            return (xGroup->getHeaderOn() || xGroup->getFooterOn())? EditBrowseBox::HEADERFOOTER : EditBrowseBox::CLEAN;
        }
        catch(uno::Exception&)
        {
            TOOLS_WARN_EXCEPTION( "reportdesign""Exception caught while try to get a group!");
        }
    }
    return EditBrowseBox::CLEAN;
}

// XContainerListener

void OFieldExpressionControl::elementInserted(const container::ContainerEvent& evt)
{
    if ( m_bIgnoreEvent )
        return;
    SolarMutexGuard aSolarGuard;
    ::osl::MutexGuard aGuard( m_aMutex );
    sal_Int32 nGroupPos = 0;
    if ( !(evt.Accessor >>= nGroupPos) )
        return;

    if ( nGroupPos >= GetRowCount() )
    {
        sal_Int32 nAddedRows = nGroupPos - GetRowCount();
        RowInserted(nAddedRows);
        for (sal_Int32 i = 0; i < nAddedRows; ++i)
            m_aGroupPositions.push_back(NO_GROUP);
        m_aGroupPositions[nGroupPos] = nGroupPos;
    }
    else
    {
        ::std::vector<sal_Int32>::iterator aFind = m_aGroupPositions.begin()+ nGroupPos;
        if ( aFind == m_aGroupPositions.end() )
            aFind = ::std::find(m_aGroupPositions.begin(),m_aGroupPositions.end(),NO_GROUP);

        if ( aFind != m_aGroupPositions.end() )
        {
            if ( *aFind != NO_GROUP )
                aFind = m_aGroupPositions.insert(aFind,nGroupPos);
            else
                *aFind = nGroupPos;

            ::std::vector<sal_Int32>::const_iterator aEnd  = m_aGroupPositions.end();
            for(++aFind;aFind != aEnd;++aFind)
                if ( *aFind != NO_GROUP )
                    ++*aFind;
        }
    }
    Invalidate();
}

void OFieldExpressionControl::elementRemoved(const container::ContainerEvent& evt)
{
    SolarMutexGuard aSolarGuard;
    ::osl::MutexGuard aGuard( m_aMutex );

    if ( m_bIgnoreEvent )
        return;

    sal_Int32 nGroupPos = 0;
    if ( !(evt.Accessor >>= nGroupPos) )
        return;

    std::vector<sal_Int32>::iterator aEnd = m_aGroupPositions.end();
    std::vector<sal_Int32>::iterator aFind = std::find(m_aGroupPositions.begin(), aEnd, nGroupPos);
    if (aFind != aEnd)
    {
        *aFind = NO_GROUP;
        for(++aFind;aFind != aEnd;++aFind)
            if ( *aFind != NO_GROUP )
                --*aFind;
        Invalidate();
    }
}

bool OFieldExpressionControl::IsDeleteAllowed( ) const
{
    return !m_pParent->isReadOnly() && GetSelectRowCount() > 0;
}

void OFieldExpressionControl::KeyInput( const KeyEvent& rEvt )
{
    if (IsDeleteAllowed())
    {
        if (rEvt.GetKeyCode().GetCode() == KEY_DELETE &&    // Delete rows
            !rEvt.GetKeyCode().IsShift() &&
            !rEvt.GetKeyCode().IsMod1())
        {
            DeleteRows();
            return;
        }
    }
    EditBrowseBox::KeyInput(rEvt);
}

void OFieldExpressionControl::Command(const CommandEvent& rEvt)
{
    switch (rEvt.GetCommand())
    {
        case CommandEventId::ContextMenu:
        {
            if (!rEvt.IsMouseEvent())
            {
                EditBrowseBox::Command(rEvt);
                return;
            }

            sal_uInt16 nColId = GetColumnId(GetColumnAtXPosPixel(rEvt.GetMousePosPixel().X()));

            if ( nColId == HANDLE_ID )
            {
                bool bEnable = false;
                tools::Long nIndex = FirstSelectedRow();
                while( nIndex != SFX_ENDOFSELECTION && !bEnable )
                {
                    if ( m_aGroupPositions[nIndex] != NO_GROUP )
                        bEnable = true;
                    nIndex = NextSelectedRow();
                }

                ::tools::Rectangle aRect(rEvt.GetMousePosPixel(), Size(1, 1));
                weld::Window* pPopupParent = weld::GetPopupParent(*this, aRect);
                std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(pPopupParent, u"modules/dbreport/ui/groupsortmenu.ui"_ustr));
                std::unique_ptr<weld::Menu> xContextMenu(xBuilder->weld_menu(u"menu"_ustr));
                xContextMenu->set_sensitive(u"delete"_ustr, IsDeleteAllowed() && bEnable);
                if (!xContextMenu->popup_at_rect(pPopupParent, aRect).isEmpty())
                {
                    if( m_nDeleteEvent )
                        Application::RemoveUserEvent( m_nDeleteEvent );
                    m_nDeleteEvent = Application::PostUserEvent( LINK(this, OFieldExpressionControl, DelayedDelete), nullptr, true );
                }
            }
            [[fallthrough]];
        }
        default:
            EditBrowseBox::Command(rEvt);
    }

}

void OFieldExpressionControl::DeleteRows()
{

    bool bIsEditing = IsEditing();
    if (bIsEditing)
    {
        DeactivateCell();
    }
    tools::Long nIndex = FirstSelectedRow();
    if (nIndex == SFX_ENDOFSELECTION)
    {
        nIndex = GetCurRow();
    }
    bool bFirstTime = true;

    tools::Long nOldDataPos = nIndex;
    m_bIgnoreEvent = true;
    while( nIndex >= 0 )
    {
        if ( m_aGroupPositions[nIndex] != NO_GROUP )
        {
            if ( bFirstTime )
            {
                bFirstTime = false;
                OUString sUndoAction(RptResId(RID_STR_UNDO_REMOVE_SELECTION));
                m_pParent->m_pController->getUndoManager().EnterListAction( sUndoAction, OUString(), 0, ViewShellId(-1) );
            }

            sal_Int32 nGroupPos = m_aGroupPositions[nIndex];
            uno::Reference< report::XGroup> xGroup = m_pParent->getGroup(nGroupPos);
            uno::Sequence< beans::PropertyValue > aArgs{ comphelper::makePropertyValue(
                PROPERTY_GROUP, xGroup) };
            // we use this way to create undo actions
            m_pParent->m_pController->executeChecked(SID_GROUP_REMOVE,aArgs);

            std::vector<sal_Int32>::iterator aEnd  = m_aGroupPositions.end();
            std::vector<sal_Int32>::iterator aFind = std::find(m_aGroupPositions.begin(), aEnd, nGroupPos);
            if (aFind != aEnd)
            {
                *aFind = NO_GROUP;
                for(++aFind;aFind != aEnd;++aFind)
                    if ( *aFind != NO_GROUP )
                        --*aFind;
            }
        }
        nIndex = NextSelectedRow();
    }

    if ( !bFirstTime )
        m_pParent->m_pController->getUndoManager().LeaveListAction();

    m_nDataPos = GetCurRow();
    InvalidateStatusCell( nOldDataPos );
    InvalidateStatusCell( m_nDataPos );
    ActivateCell();
    m_pParent->DisplayData( m_nDataPos );
    m_bIgnoreEvent = false;
    Invalidate();
}

IMPL_LINK_NOARG( OFieldExpressionControl, DelayedDelete, void*, void )
{
    m_nDeleteEvent = nullptr;
    DeleteRows();
}

Size OFieldExpressionControl::GetOptimalSize() const
{
    return LogicToPixel(Size(106, 75), MapMode(MapUnit::MapAppFont));
}

OGroupsSortingDialog::OGroupsSortingDialog(weld::Window* pParent, bool bReadOnly,
                                           OReportController* pController)
    : GenericDialogController(pParent, u"modules/dbreport/ui/floatingsort.ui"_ustr, u"FloatingSort"_ustr)
    , OPropertyChangeListener()
    , m_pController(pController)
    , m_xGroups(m_pController->getReportDefinition()->getGroups())
    , m_bReadOnly(bReadOnly)
    , m_xToolBox(m_xBuilder->weld_toolbar(u"toolbox"_ustr))
    , m_xProperties(m_xBuilder->weld_widget(u"properties"_ustr))
    , m_xOrderLst(m_xBuilder->weld_combo_box(u"sorting"_ustr))
    , m_xHeaderLst(m_xBuilder->weld_combo_box(u"header"_ustr))
    , m_xFooterLst(m_xBuilder->weld_combo_box(u"footer"_ustr))
    , m_xGroupOnLst(m_xBuilder->weld_combo_box(u"group"_ustr))
    , m_xGroupIntervalEd(m_xBuilder->weld_spin_button(u"interval"_ustr))
    , m_xKeepTogetherLst(m_xBuilder->weld_combo_box(u"keep"_ustr))
    , m_xHelpWindow(m_xBuilder->weld_label(u"helptext"_ustr))
    , m_xBox(m_xBuilder->weld_container(u"box"_ustr))
    , m_xTableCtrlParent(m_xBox->CreateChildFrame())
    , m_xFieldExpression(VclPtr<OFieldExpressionControl>::Create(this, m_xTableCtrlParent))
{
    m_xHelpWindow->set_size_request(-1, m_xHelpWindow->get_text_height() * 4);
    m_xFieldExpression->set_hexpand(true);
    m_xFieldExpression->set_vexpand(true);

    weld::Widget* pControlsLst[] = { m_xHeaderLst.get(), m_xFooterLst.get(), m_xGroupOnLst.get(),
                                     m_xKeepTogetherLst.get(), m_xOrderLst.get(), m_xGroupIntervalEd.get() };
    for (weld::Widget* i : pControlsLst)
    {
        i->connect_focus_in(LINK(this, OGroupsSortingDialog, OnWidgetFocusGot));
        i->show();
    }

    m_xGroupIntervalEd->connect_focus_out(LINK(this, OGroupsSortingDialog, OnWidgetFocusLost));

    for (size_t i = 0; i < SAL_N_ELEMENTS(pControlsLst) - 1; ++i)
        dynamic_cast<weld::ComboBox&>(*pControlsLst[i]).connect_changed(LINK(this,OGroupsSortingDialog,LBChangeHdl));

    m_pReportListener = new OPropertyChangeMultiplexer(this, m_pController->getReportDefinition());
    m_pReportListener->addProperty(PROPERTY_COMMAND);
    m_pReportListener->addProperty(PROPERTY_COMMANDTYPE);

    m_xFieldExpression->lateInit();
    fillColumns();
    Size aPrefSize = m_xFieldExpression->GetOptimalSize();
    m_xBox->set_size_request(aPrefSize.Width(), aPrefSize.Height());
    m_xFieldExpression->Show();

    m_xToolBox->connect_clicked(LINK(this, OGroupsSortingDialog, OnFormatAction));

    checkButtons(0);
}

OGroupsSortingDialog::~OGroupsSortingDialog()
{
    m_pReportListener->dispose();
    if ( m_pCurrentGroupListener.is() )
        m_pCurrentGroupListener->dispose();
    m_xFieldExpression.disposeAndClear();
    m_xTableCtrlParent->dispose();
    m_xTableCtrlParent.clear();
}

void OGroupsSortingDialog::UpdateData( )
{
    m_xFieldExpression->Invalidate();
    sal_Int32 nCurRow = m_xFieldExpression->GetCurRow();
    m_xFieldExpression->DeactivateCell();
    m_xFieldExpression->ActivateCell(nCurRow, m_xFieldExpression->GetCurColumnId());
    DisplayData(nCurRow);
}

void OGroupsSortingDialog::DisplayData( sal_Int32 _nRow )
{
    const sal_Int32 nGroupPos = m_xFieldExpression->getGroupPosition(_nRow);
    const bool bEmpty = nGroupPos == NO_GROUP;
    m_xProperties->set_sensitive(!bEmpty);

    checkButtons(_nRow);

    if ( m_pCurrentGroupListener.is() )
        m_pCurrentGroupListener->dispose();
    m_pCurrentGroupListener = nullptr;
    if (!bEmpty)
    {
        uno::Reference< report::XGroup> xGroup = getGroup(nGroupPos);

        m_pCurrentGroupListener = new OPropertyChangeMultiplexer(this, xGroup);
        m_pCurrentGroupListener->addProperty(PROPERTY_HEADERON);
        m_pCurrentGroupListener->addProperty(PROPERTY_FOOTERON);

        displayGroup(xGroup);
    }
}

void OGroupsSortingDialog::SaveData( sal_Int32 _nRow)
{
    sal_Int32 nGroupPos = m_xFieldExpression->getGroupPosition(_nRow);
    if ( nGroupPos == NO_GROUP )
        return;

    uno::Reference< report::XGroup> xGroup = getGroup(nGroupPos);
    if (m_xHeaderLst->get_value_changed_from_saved())
        xGroup->setHeaderOn( m_xHeaderLst->get_active() == 0 );
    if (m_xFooterLst->get_value_changed_from_saved())
        xGroup->setFooterOn( m_xFooterLst->get_active() == 0 );
    if (m_xKeepTogetherLst->get_value_changed_from_saved())
        xGroup->setKeepTogether( m_xKeepTogetherLst->get_active() );
    if (m_xGroupOnLst->get_value_changed_from_saved())
    {
        auto nGroupOn = m_xGroupOnLst->get_active_id().toInt32();
        xGroup->setGroupOn( nGroupOn );
    }
    if (m_xGroupIntervalEd->get_value_changed_from_saved())
    {
        xGroup->setGroupInterval(m_xGroupIntervalEd->get_value());
        m_xGroupIntervalEd->save_value();
    }
    if ( m_xOrderLst->get_value_changed_from_saved() )
        xGroup->setSortAscending( m_xOrderLst->get_active() == 0 );

    weld::ComboBox* pControls[] = { m_xHeaderLst.get(), m_xFooterLst.get(), m_xGroupOnLst.get(),
                                    m_xKeepTogetherLst.get(), m_xOrderLst.get() };
    for (weld::ComboBox* pControl : pControls)
        pControl->save_value();
}

sal_Int32 OGroupsSortingDialog::getColumnDataType(const OUString& _sColumnName)
{
    sal_Int32 nDataType = sdbc::DataType::VARCHAR;
    try
    {
        if ( !m_xColumns.is() )
            fillColumns();
        if ( m_xColumns.is() && m_xColumns->hasByName(_sColumnName) )
        {
            uno::Reference< beans::XPropertySet> xColumn(m_xColumns->getByName(_sColumnName),uno::UNO_QUERY);
            if ( xColumn.is() )
                xColumn->getPropertyValue(PROPERTY_TYPE) >>= nDataType;
        }
    }
    catch(uno::Exception&)
    {
        TOOLS_WARN_EXCEPTION( "reportdesign""Exception caught while getting the type of a column");
    }

    return nDataType;
}

IMPL_LINK_NOARG(OGroupsSortingDialog, OnControlFocusGot, LinkParamNone*, void )
{
    m_xHelpWindow->set_label(RptResId(STR_RPT_HELP_FIELD));
}

IMPL_LINK(OGroupsSortingDialog, OnWidgetFocusGot, weld::Widget&, rControl, void )
{
    const std::pair<weld::Widget*, TranslateId> pControls[] = {
        { m_xHeaderLst.get(), STR_RPT_HELP_HEADER },
        { m_xFooterLst.get(), STR_RPT_HELP_FOOTER },
        { m_xGroupOnLst.get(), STR_RPT_HELP_GROUPON },
        { m_xGroupIntervalEd.get(), STR_RPT_HELP_INTERVAL },
        { m_xKeepTogetherLst.get(), STR_RPT_HELP_KEEP },
        { m_xOrderLst.get(), STR_RPT_HELP_SORT }
    };
    for (size_t i = 0; i < SAL_N_ELEMENTS(pControls); ++i)
    {
        if (&rControl == pControls[i].first)
        {
            weld::ComboBox* pListBox = dynamic_cast<weld::ComboBox*>( &rControl );
            if ( pListBox )
                pListBox->save_value();
            weld::SpinButton* pNumericField = dynamic_cast<weld::SpinButton*>(&rControl);
            if ( pNumericField )
                pNumericField->save_value();
            //shows the text given by the id in the multiline edit
            m_xHelpWindow->set_label(RptResId(pControls[i].second));
            break;
        }
    }
}

IMPL_LINK_NOARG(OGroupsSortingDialog, OnWidgetFocusLost, weld::Widget&, void)
{
    if (m_xFieldExpression)
    {
        if (m_xGroupIntervalEd->get_value_changed_from_saved())
            SaveData(m_xFieldExpression->GetCurRow());
    }
}

IMPL_LINK(OGroupsSortingDialog, OnFormatAction, const OUString&, rCommand, void)
{
    if ( !m_xFieldExpression )
        return;

    tools::Long nIndex = m_xFieldExpression->GetCurrRow();
    sal_Int32 nGroupPos = m_xFieldExpression->getGroupPosition(nIndex);
    uno::Sequence<uno::Any> aClipboardList;
    if ( nIndex >= 0 && nGroupPos != NO_GROUP )
    {
        aClipboardList = { m_xGroups->getByIndex(nGroupPos) };
    }
    if (rCommand == "up")
    {
        --nIndex;
    }
    if (rCommand == "down")
    {
        ++nIndex;
    }
    if (rCommand == "delete")
    {
        Application::PostUserEvent(LINK(m_xFieldExpression, OFieldExpressionControl, DelayedDelete));
    }
    else
    {
        if ( nIndex >= 0 && aClipboardList.hasElements() )
        {
            m_xFieldExpression->SetNoSelection();
            m_xFieldExpression->moveGroups(aClipboardList,nIndex,false);
            m_xFieldExpression->DeactivateCell();
            m_xFieldExpression->GoToRow(nIndex);
            m_xFieldExpression->ActivateCell(nIndex, m_xFieldExpression->GetCurColumnId());
            DisplayData(nIndex);
        }
    }
}

IMPL_LINK( OGroupsSortingDialog, LBChangeHdl, weld::ComboBox&, rListBox, void )
{
    if ( !rListBox.get_value_changed_from_saved() )
        return;

    sal_Int32 nRow = m_xFieldExpression->GetCurRow();
    sal_Int32 nGroupPos = m_xFieldExpression->getGroupPosition(nRow);
    if (&rListBox != m_xHeaderLst.get() && &rListBox != m_xFooterLst.get())
    {
        if ( rListBox.get_value_changed_from_saved() )
            SaveData(nRow);
        if ( &rListBox == m_xGroupOnLst.get() )
            m_xGroupIntervalEd->set_sensitive(rListBox.get_active() != 0);
    }
    else if ( nGroupPos != NO_GROUP )
    {
        uno::Reference< report::XGroup> xGroup = getGroup(nGroupPos);
        const OUString aHeaderFooterOnName(( m_xHeaderLst.get() == &rListBox )
                                               ? std::u16string_view(PROPERTY_HEADERON)
                                               : std::u16string_view(PROPERTY_FOOTERON));
        uno::Sequence< beans::PropertyValue > aArgs{
            comphelper::makePropertyValue(aHeaderFooterOnName, rListBox.get_active() == 0),
            comphelper::makePropertyValue(PROPERTY_GROUP, xGroup)
        };
        m_pController->executeChecked(m_xHeaderLst.get() == &rListBox ? SID_GROUPHEADER : SID_GROUPFOOTER, aArgs);
        m_xFieldExpression->InvalidateHandleColumn();
    }
}

void OGroupsSortingDialog::_propertyChanged(const beans::PropertyChangeEvent& _rEvent)
{
    uno::Reference< report::XGroup > xGroup(_rEvent.Source,uno::UNO_QUERY);
    if ( xGroup.is() )
        displayGroup(xGroup);
    else
        fillColumns();
}

void OGroupsSortingDialog::fillColumns()
{
    m_xColumns = m_pController->getColumns();
    m_xFieldExpression->fillColumns(m_xColumns);
}

void OGroupsSortingDialog::displayGroup(const uno::Reference<report::XGroup>& _xGroup)
{
    m_xHeaderLst->set_active(_xGroup->getHeaderOn() ? 0 : 1 );
    m_xFooterLst->set_active(_xGroup->getFooterOn() ? 0 : 1 );
    sal_Int32 nDataType = getColumnDataType(_xGroup->getExpression());

    // first clear whole group on list
    while (m_xGroupOnLst->get_count() > 1 )
    {
        m_xGroupOnLst->remove(1);
    }

    switch(nDataType)
    {
        case sdbc::DataType::LONGVARCHAR:
        case sdbc::DataType::VARCHAR:
        case sdbc::DataType::CHAR:
            m_xGroupOnLst->append(OUString::number(report::GroupOn::PREFIX_CHARACTERS), RptResId(STR_RPT_PREFIXCHARS));
            break;
        case sdbc::DataType::DATE:
        case sdbc::DataType::TIME:
        case sdbc::DataType::TIMESTAMP:
            {
                const TranslateId aIds[] = { STR_RPT_YEAR, STR_RPT_QUARTER,STR_RPT_MONTH,STR_RPT_WEEK,STR_RPT_DAY,STR_RPT_HOUR,STR_RPT_MINUTE };
                for (size_t i = 0; i < SAL_N_ELEMENTS(aIds); ++i)
                {
                    m_xGroupOnLst->append(OUString::number(i+2), RptResId(aIds[i]));
                }
            }
            break;
        default:
            m_xGroupOnLst->append(OUString::number(report::GroupOn::INTERVAL), RptResId(STR_RPT_INTERVAL));
            break;
    }
    sal_Int32 nPos = 0;
    switch(_xGroup->getGroupOn())
    {
        case report::GroupOn::DEFAULT:
            nPos = 0;
            break;
        case report::GroupOn::INTERVAL:
        case report::GroupOn::PREFIX_CHARACTERS:
        case report::GroupOn::YEAR:
            nPos = 1;
            break;
        case report::GroupOn::QUARTAL:
            nPos = 2;
            break;
        case report::GroupOn::MONTH:
            nPos = 3;
            break;
        case report::GroupOn::WEEK:
            nPos = 4;
            break;
        case report::GroupOn::DAY:
            nPos = 5;
            break;
        case report::GroupOn::HOUR:
            nPos = 6;
            break;
        case report::GroupOn::MINUTE:
            nPos = 7;
            break;
        default:
            nPos = 0;
    }
    m_xGroupOnLst->set_active(nPos);
    m_xGroupIntervalEd->set_value(_xGroup->getGroupInterval());
    m_xGroupIntervalEd->save_value();
    m_xGroupIntervalEd->set_sensitive( nPos != 0 );
    m_xKeepTogetherLst->set_active(_xGroup->getKeepTogether());
    m_xOrderLst->set_active(_xGroup->getSortAscending() ? 0 : 1);

    weld::ComboBox* pControls[] = { m_xHeaderLst.get(), m_xFooterLst.get(), m_xGroupOnLst.get(),
                                    m_xKeepTogetherLst.get(), m_xOrderLst.get() };
    for (weld::ComboBox* pControl : pControls)
        pControl->save_value();

    bool bReadOnly = !m_pController->isEditable();
    for (weld::ComboBox* pControl : pControls)
        pControl->set_sensitive(!bReadOnly);
    m_xGroupIntervalEd->set_editable(!bReadOnly);
}

void OGroupsSortingDialog::checkButtons(sal_Int32 _nRow)
{
    sal_Int32 nGroupCount = m_xGroups->getCount();
    sal_Int32 nRowCount = m_xFieldExpression->GetRowCount();
    bool bEnabled = nGroupCount > 1;

    if (bEnabled && _nRow > 0 )
    {
        m_xToolBox->set_item_sensitive(u"up"_ustr, true);
    }
    else
    {
        m_xToolBox->set_item_sensitive(u"up"_ustr, false);
    }
    if (bEnabled && _nRow < (nRowCount - 1) )
    {
        m_xToolBox->set_item_sensitive(u"down"_ustr, true);
    }
    else
    {
        m_xToolBox->set_item_sensitive(u"down"_ustr, false);
    }

    sal_Int32 nGroupPos = m_xFieldExpression->getGroupPosition(_nRow);
    if ( nGroupPos != NO_GROUP )
    {
        bool bEnableDelete = nGroupCount > 0;
        m_xToolBox->set_item_sensitive(u"delete"_ustr, bEnableDelete);
    }
    else
    {
        m_xToolBox->set_item_sensitive(u"delete"_ustr, false);
    }
}

// rptui

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

Messung V0.5
C=97 H=94 G=95

¤ Dauer der Verarbeitung: 0.20 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.