tdf#76898 standard filter: add buttons to remove conditions

Change-Id: If59ff911c66537a6449231bc9d54817c4fa86d7b
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/94892
Tested-by: Jenkins
Reviewed-by: Heiko Tietze <heiko.tietze@documentfoundation.org>
diff --git a/sc/source/ui/dbgui/filtdlg.cxx b/sc/source/ui/dbgui/filtdlg.cxx
index 2b0d561..2e4ac47 100644
--- a/sc/source/ui/dbgui/filtdlg.cxx
+++ b/sc/source/ui/dbgui/filtdlg.cxx
@@ -65,18 +65,22 @@ ScFilterDlg::ScFilterDlg(SfxBindings* pB, SfxChildWindow* pCW, weld::Window* pPa
    , m_xLbField1(m_xBuilder->weld_combo_box("field1"))
    , m_xLbCond1(m_xBuilder->weld_combo_box("cond1"))
    , m_xEdVal1(m_xBuilder->weld_combo_box("val1"))
    , m_xBtnRemove1(m_xBuilder->weld_button("remove1"))
    , m_xLbConnect2(m_xBuilder->weld_combo_box("connect2"))
    , m_xLbField2(m_xBuilder->weld_combo_box("field2"))
    , m_xLbCond2(m_xBuilder->weld_combo_box("cond2"))
    , m_xEdVal2(m_xBuilder->weld_combo_box("val2"))
    , m_xBtnRemove2(m_xBuilder->weld_button("remove2"))
    , m_xLbConnect3(m_xBuilder->weld_combo_box("connect3"))
    , m_xLbField3(m_xBuilder->weld_combo_box("field3"))
    , m_xLbCond3(m_xBuilder->weld_combo_box("cond3"))
    , m_xEdVal3(m_xBuilder->weld_combo_box("val3"))
    , m_xBtnRemove3(m_xBuilder->weld_button("remove3"))
    , m_xLbConnect4(m_xBuilder->weld_combo_box("connect4"))
    , m_xLbField4(m_xBuilder->weld_combo_box("field4"))
    , m_xLbCond4(m_xBuilder->weld_combo_box("cond4"))
    , m_xEdVal4(m_xBuilder->weld_combo_box("val4"))
    , m_xBtnRemove4(m_xBuilder->weld_button("remove4"))
    , m_xContents(m_xBuilder->weld_widget("grid"))
    , m_xScrollBar(m_xBuilder->weld_scrolled_window("scrollbar"))
    , m_xExpander(m_xBuilder->weld_expander("more"))
@@ -152,6 +156,11 @@ void ScFilterDlg::Init( const SfxItemSet& rArgSet )
    m_xLbCond3->connect_changed( LINK( this, ScFilterDlg, LbSelectHdl ) );
    m_xLbCond4->connect_changed( LINK( this, ScFilterDlg, LbSelectHdl ) );

    m_xBtnRemove1->connect_clicked( LINK( this, ScFilterDlg, BtnRemoveHdl ) );
    m_xBtnRemove2->connect_clicked( LINK( this, ScFilterDlg, BtnRemoveHdl ) );
    m_xBtnRemove3->connect_clicked( LINK( this, ScFilterDlg, BtnRemoveHdl ) );
    m_xBtnRemove4->connect_clicked( LINK( this, ScFilterDlg, BtnRemoveHdl ) );

    pViewData   = rQueryItem.GetViewData();
    pDoc        = pViewData ? pViewData->GetDocument() : nullptr;
    nSrcTab     = pViewData ? pViewData->GetTabNo() : static_cast<SCTAB>(0);
@@ -177,6 +186,11 @@ void ScFilterDlg::Init( const SfxItemSet& rArgSet )
    maConnLbArr.push_back(m_xLbConnect2.get());
    maConnLbArr.push_back(m_xLbConnect3.get());
    maConnLbArr.push_back(m_xLbConnect4.get());
    maRemoveBtnArr.reserve(QUERY_ENTRY_COUNT);
    maRemoveBtnArr.push_back(m_xBtnRemove1.get());
    maRemoveBtnArr.push_back(m_xBtnRemove2.get());
    maRemoveBtnArr.push_back(m_xBtnRemove3.get());
    maRemoveBtnArr.push_back(m_xBtnRemove4.get());

    // Option initialization:
    pOptionsMgr.reset( new ScFilterOptionsMgr(
@@ -223,37 +237,7 @@ void ScFilterDlg::Init( const SfxItemSet& rArgSet )
            else
            {
                OUString aQueryStr = rItem.maString.getString();
                if (aQueryStr.isEmpty())
                {
                    if (rItem.meType == ScQueryEntry::ByValue)
                    {
                        if (pDoc)
                        {
                            pDoc->GetFormatTable()->GetInputLineString(rItem.mfVal, 0, aValStr);
                        }
                    }
                    else if (rItem.meType == ScQueryEntry::ByDate)
                    {
                        if (pDoc)
                        {
                            SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
                            pFormatter->GetInputLineString(rItem.mfVal,
                                                           pFormatter->GetStandardFormat( SvNumFormatType::DATE), aValStr);
                        }
                    }
                    else
                    {
                        SAL_WARN( "sc", "ScFilterDlg::Init: empty query string, really?");
                        aValStr = aQueryStr;
                    }
                }
                else
                {
                    // XXX NOTE: if not ByString we just assume this has been
                    // set to a proper string corresponding to the numeric
                    // value earlier!
                    aValStr = aQueryStr;
                }
                SetValString(aQueryStr, rItem, aValStr);
            }
        }
        else if ( i == 0 )
@@ -304,12 +288,14 @@ void ScFilterDlg::Init( const SfxItemSet& rArgSet )
        m_xLbField2->set_sensitive(false);
        m_xLbCond2->set_sensitive(false);
        m_xEdVal2->set_sensitive(false);
        m_xBtnRemove2->set_sensitive(false);
    }
    else if ( m_xLbConnect2->get_active() == -1 )
    {
        m_xLbField2->set_sensitive(false);
        m_xLbCond2->set_sensitive(false);
        m_xEdVal2->set_sensitive(false);
        m_xBtnRemove2->set_sensitive(false);
    }

    if ( m_xLbField2->get_active() == 0 )
@@ -318,12 +304,14 @@ void ScFilterDlg::Init( const SfxItemSet& rArgSet )
        m_xLbField3->set_sensitive(false);
        m_xLbCond3->set_sensitive(false);
        m_xEdVal3->set_sensitive(false);
        m_xBtnRemove3->set_sensitive(false);
    }
    else if ( m_xLbConnect3->get_active() == -1 )
    {
        m_xLbField3->set_sensitive(false);
        m_xLbCond3->set_sensitive(false);
        m_xEdVal3->set_sensitive(false);
        m_xBtnRemove3->set_sensitive(false);
    }
    if ( m_xLbField3->get_active() == 0 )
    {
@@ -331,12 +319,14 @@ void ScFilterDlg::Init( const SfxItemSet& rArgSet )
        m_xLbField4->set_sensitive(false);
        m_xLbCond4->set_sensitive(false);
        m_xEdVal4->set_sensitive(false);
        m_xBtnRemove4->set_sensitive(false);
    }
    else if ( m_xLbConnect4->get_active() == -1 )
    {
        m_xLbField4->set_sensitive(false);
        m_xLbCond4->set_sensitive(false);
        m_xEdVal4->set_sensitive(false);
        m_xBtnRemove4->set_sensitive(false);
    }

    m_xEdVal1->set_entry_width_chars(10);
@@ -670,6 +660,9 @@ IMPL_LINK( ScFilterDlg, BtnClearHdl, weld::Button&, rBtn, void )
    m_xEdVal2->set_sensitive(false);
    m_xEdVal3->set_sensitive(false);
    m_xEdVal4->set_sensitive(false);
    m_xBtnRemove2->set_sensitive(false);
    m_xBtnRemove3->set_sensitive(false);
    m_xBtnRemove4->set_sensitive(false);

    // clear query data objects
    SCSIZE nCount = theQueryData.GetEntryCount();
@@ -757,6 +750,7 @@ IMPL_LINK(ScFilterDlg, LbSelectHdl, weld::ComboBox&, rLb, void)
        m_xLbField1->set_sensitive(true);
        m_xLbCond1->set_sensitive(true);
        m_xEdVal1->set_sensitive(true);
        m_xBtnRemove1->set_sensitive(true);

        const sal_Int32 nConnect1 = m_xLbConnect1->get_active();
        size_t nQE = nOffset;
@@ -770,6 +764,7 @@ IMPL_LINK(ScFilterDlg, LbSelectHdl, weld::ComboBox&, rLb, void)
        m_xLbField2->set_sensitive(true);
        m_xLbCond2->set_sensitive(true);
        m_xEdVal2->set_sensitive(true);
        m_xBtnRemove2->set_sensitive(true);

        const sal_Int32 nConnect2 = m_xLbConnect2->get_active();
        size_t nQE = 1+nOffset;
@@ -783,6 +778,7 @@ IMPL_LINK(ScFilterDlg, LbSelectHdl, weld::ComboBox&, rLb, void)
        m_xLbField3->set_sensitive(true);
        m_xLbCond3->set_sensitive(true);
        m_xEdVal3->set_sensitive(true);
        m_xBtnRemove3->set_sensitive(true);

        const sal_Int32 nConnect3 = m_xLbConnect3->get_active();
        size_t nQE = 2 + nOffset;
@@ -797,6 +793,7 @@ IMPL_LINK(ScFilterDlg, LbSelectHdl, weld::ComboBox&, rLb, void)
        m_xLbField4->set_sensitive(true);
        m_xLbCond4->set_sensitive(true);
        m_xEdVal4->set_sensitive(true);
        m_xBtnRemove4->set_sensitive(true);

        const sal_Int32 nConnect4 = m_xLbConnect4->get_active();
        size_t nQE = 3 + nOffset;
@@ -835,6 +832,9 @@ IMPL_LINK(ScFilterDlg, LbSelectHdl, weld::ComboBox&, rLb, void)
            m_xEdVal2->set_sensitive(false);
            m_xEdVal3->set_sensitive(false);
            m_xEdVal4->set_sensitive(false);
            m_xBtnRemove2->set_sensitive(false);
            m_xBtnRemove3->set_sensitive(false);
            m_xBtnRemove4->set_sensitive(false);
            SCSIZE nCount = theQueryData.GetEntryCount();
            if (maRefreshExceptQuery.size() < nCount + 1)
                maRefreshExceptQuery.resize(nCount + 1, false);
@@ -880,6 +880,8 @@ IMPL_LINK(ScFilterDlg, LbSelectHdl, weld::ComboBox&, rLb, void)
            m_xLbCond4->set_sensitive(false);
            m_xEdVal3->set_sensitive(false);
            m_xEdVal4->set_sensitive(false);
            m_xBtnRemove3->set_sensitive(false);
            m_xBtnRemove4->set_sensitive(false);

            sal_uInt16 nTemp=nOffset+1;
            SCSIZE nCount = theQueryData.GetEntryCount();
@@ -920,6 +922,7 @@ IMPL_LINK(ScFilterDlg, LbSelectHdl, weld::ComboBox&, rLb, void)
            m_xLbField4->set_sensitive(false);
            m_xLbCond4->set_sensitive(false);
            m_xEdVal4->set_sensitive(false);
            m_xBtnRemove4->set_sensitive(false);

            sal_uInt16 nTemp=nOffset+2;
            SCSIZE nCount = theQueryData.GetEntryCount();
@@ -1115,6 +1118,84 @@ IMPL_LINK( ScFilterDlg, ValModifyHdl, weld::ComboBox&, rEd, void )
        rItem.meType = ScQueryEntry::ByDate;
}

IMPL_LINK( ScFilterDlg, BtnRemoveHdl, weld::Button&, rBtn, void )
{
    // Calculate the row to delete
    sal_uInt16 nOffset = GetSliderPos();
    int nButtonIndex = 0;
    if ( &rBtn == m_xBtnRemove2.get() )
        nButtonIndex = 1;
    if ( &rBtn == m_xBtnRemove3.get() )
        nButtonIndex = 2;
    if ( &rBtn == m_xBtnRemove4.get() )
        nButtonIndex = 3;
    SCSIZE nRowToDelete = nOffset + nButtonIndex;

    // Check that the index is sensible
    SCSIZE nCount = theQueryData.GetEntryCount();
    if (nRowToDelete >= nCount)
    {
        SAL_WARN( "sc", "ScFilterDlg::BtnRemoveHdl: could not delete row - invalid index.");
        return;
    }

    // Resize maRefreshExceptQuery
    if (maRefreshExceptQuery.size() < nCount + 1)
        maRefreshExceptQuery.resize(nCount + 1, false);

    // Move all the subsequent rows back one position;
    // also find the last row, which we will delete
    SCSIZE nRowToClear = nCount-1;
    for (SCSIZE i = nRowToDelete; i < nCount-1; ++i)
    {
        if (theQueryData.GetEntry(i+1).bDoQuery)
        {
            theQueryData.GetEntry(i) = theQueryData.GetEntry(i+1);
        }
        else
        {
            nRowToClear = i;
            break;
        }
    }

    // If the next row is being edited, but not confirmed, move it back
    // one position
    if (nRowToClear < nCount-1  &&  maRefreshExceptQuery[nRowToClear+1])
    {
        theQueryData.GetEntry(nRowToClear) = theQueryData.GetEntry(nRowToClear+1);
        maRefreshExceptQuery[nRowToClear] = true;
        maRefreshExceptQuery[nRowToClear+1] = false;
    }
    else
    {
        // Remove the very last one, since everything has moved back
        theQueryData.GetEntry(nRowToClear).bDoQuery = false;
        theQueryData.GetEntry(nRowToClear).nField =  static_cast<SCCOL>(0);
        maRefreshExceptQuery[nRowToClear] = false;
    }

    // Always enable the very first row
    if (!theQueryData.GetEntry(0).bDoQuery)
    {
        maRefreshExceptQuery[0] = true;
    }

    // Refresh the UI
    RefreshEditRow( nOffset );

    // Special handling if the very first row was cleared
    if (!theQueryData.GetEntry(0).bDoQuery)
    {
        m_xLbConnect1->set_active(-1);
        m_xLbField1->set_active(0);
        m_xLbField1->set_sensitive(true);
        m_xLbCond1->set_active(0);
        m_xLbCond1->set_sensitive(true);
        ClearValueList(1);
    }
}

IMPL_LINK_NOARG(ScFilterDlg, ScrollHdl, weld::ScrolledWindow&, void)
{
    SliderMoved();
@@ -1169,11 +1250,12 @@ void ScFilterDlg::RefreshEditRow( size_t nOffset )
            }
            else
            {
                aValStr = aQueryStr;
                SetValString(aQueryStr, rItem, aValStr);
                maCondLbArr[i]->set_sensitive(true);
            }
            maFieldLbArr[i]->set_sensitive(true);
            maValueEdArr[i]->set_sensitive(true);
            maRemoveBtnArr[i]->set_sensitive(true);

            if (nOffset==0)
            {
@@ -1229,6 +1311,7 @@ void ScFilterDlg::RefreshEditRow( size_t nOffset )
            maFieldLbArr[i]->set_sensitive(false);
            maCondLbArr[i]->set_sensitive(false);
            maValueEdArr[i]->set_sensitive(false);
            maRemoveBtnArr[i]->set_sensitive(false);
        }
        maFieldLbArr[i]->set_active( nFieldSelPos );
        maCondLbArr [i]->set_active( nCondPos );
@@ -1237,4 +1320,41 @@ void ScFilterDlg::RefreshEditRow( size_t nOffset )
    }
}

void ScFilterDlg::SetValString( const OUString& rQueryStr, const ScQueryEntry::Item& rItem,
    OUString& rValStr )
{
    if (rQueryStr.isEmpty())
    {
        pDoc = pViewData ? pViewData->GetDocument() : nullptr;
        if (rItem.meType == ScQueryEntry::ByValue)
        {
            if (pDoc)
            {
                pDoc->GetFormatTable()->GetInputLineString(rItem.mfVal, 0, rValStr);
            }
        }
        else if (rItem.meType == ScQueryEntry::ByDate)
        {
            if (pDoc)
            {
                SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
                pFormatter->GetInputLineString(rItem.mfVal,
                                               pFormatter->GetStandardFormat( SvNumFormatType::DATE), rValStr);
            }
        }
        else
        {
            SAL_WARN( "sc", "ScFilterDlg::SetValString: empty query string, really?");
            rValStr = rQueryStr;
        }
    }
    else
    {
        // XXX NOTE: if not ByString we just assume this has been
        // set to a proper string corresponding to the numeric
        // value earlier!
        rValStr = rQueryStr;
    }
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/inc/filtdlg.hxx b/sc/source/ui/inc/filtdlg.hxx
index e6c2d37..5885318 100644
--- a/sc/source/ui/inc/filtdlg.hxx
+++ b/sc/source/ui/inc/filtdlg.hxx
@@ -24,6 +24,7 @@
#include "anyrefdg.hxx"
#include <queryparam.hxx>
#include <filterentries.hxx>
#include <queryentry.hxx>

#include <memory>
#include <deque>
@@ -84,6 +85,7 @@ private:
    std::vector<weld::ComboBox*> maFieldLbArr;
    std::vector<weld::ComboBox*> maCondLbArr;
    std::vector<weld::ComboBox*> maConnLbArr;
    std::vector<weld::Button*>   maRemoveBtnArr;

    std::deque<bool>   maHasDates;
    std::deque<bool>   maRefreshExceptQuery;
@@ -98,21 +100,25 @@ private:
    std::unique_ptr<weld::ComboBox> m_xLbField1;
    std::unique_ptr<weld::ComboBox> m_xLbCond1;
    std::unique_ptr<weld::ComboBox> m_xEdVal1;
    std::unique_ptr<weld::Button>   m_xBtnRemove1;

    std::unique_ptr<weld::ComboBox> m_xLbConnect2;
    std::unique_ptr<weld::ComboBox> m_xLbField2;
    std::unique_ptr<weld::ComboBox> m_xLbCond2;
    std::unique_ptr<weld::ComboBox> m_xEdVal2;
    std::unique_ptr<weld::Button>   m_xBtnRemove2;

    std::unique_ptr<weld::ComboBox> m_xLbConnect3;
    std::unique_ptr<weld::ComboBox> m_xLbField3;
    std::unique_ptr<weld::ComboBox> m_xLbCond3;
    std::unique_ptr<weld::ComboBox> m_xEdVal3;
    std::unique_ptr<weld::Button>   m_xBtnRemove3;

    std::unique_ptr<weld::ComboBox> m_xLbConnect4;
    std::unique_ptr<weld::ComboBox> m_xLbField4;
    std::unique_ptr<weld::ComboBox> m_xLbCond4;
    std::unique_ptr<weld::ComboBox> m_xEdVal4;
    std::unique_ptr<weld::Button>   m_xBtnRemove4;

    std::unique_ptr<weld::Widget> m_xContents;
    std::unique_ptr<weld::ScrolledWindow> m_xScrollBar;
@@ -142,12 +148,16 @@ private:
    void            ClearValueList  ( size_t nList );
    size_t          GetFieldSelPos  ( SCCOL nField );
    ScQueryItem*    GetOutputItem   ();
    void            SetValString    ( const OUString& rQueryStr,
                                      const ScQueryEntry::Item& rItem,
                                      OUString& rValStr );

    // Handler:
    DECL_LINK( LbSelectHdl,  weld::ComboBox&, void );
    DECL_LINK( ValModifyHdl, weld::ComboBox&, void );
    DECL_LINK( CheckBoxHdl,  weld::Button&, void );
    DECL_LINK( BtnClearHdl,  weld::Button&, void );
    DECL_LINK( BtnRemoveHdl, weld::Button&, void );
    DECL_LINK( EndDlgHdl,    weld::Button&, void );
    DECL_LINK( ScrollHdl, weld::ScrolledWindow&, void );
    DECL_LINK( MoreExpandedHdl, weld::Expander&, void );
diff --git a/sc/uiconfig/scalc/ui/standardfilterdialog.ui b/sc/uiconfig/scalc/ui/standardfilterdialog.ui
index bc996a9..3fe741b 100644
--- a/sc/uiconfig/scalc/ui/standardfilterdialog.ui
+++ b/sc/uiconfig/scalc/ui/standardfilterdialog.ui
@@ -2,6 +2,26 @@
<!-- Generated with glade 3.36.0 -->
<interface domain="sc">
  <requires lib="gtk+" version="3.18"/>
  <object class="GtkImage" id="image1">
    <property name="visible">True</property>
    <property name="can_focus">False</property>
    <property name="icon_name">cmd/sc_delete.png</property>
  </object>
  <object class="GtkImage" id="image2">
    <property name="visible">True</property>
    <property name="can_focus">False</property>
    <property name="icon_name">cmd/sc_delete.png</property>
  </object>
  <object class="GtkImage" id="image3">
    <property name="visible">True</property>
    <property name="can_focus">False</property>
    <property name="icon_name">cmd/sc_delete.png</property>
  </object>
  <object class="GtkImage" id="image4">
    <property name="visible">True</property>
    <property name="can_focus">False</property>
    <property name="icon_name">cmd/sc_delete.png</property>
  </object>
  <object class="GtkDialog" id="StandardFilterDialog">
    <property name="can_focus">False</property>
    <property name="border_width">6</property>
@@ -593,6 +613,65 @@
                                    <property name="top_attach">4</property>
                                  </packing>
                                </child>
                                <child>
                                  <object class="GtkButton" id="remove1">
                                    <property name="visible">True</property>
                                    <property name="can_focus">True</property>
                                    <property name="receives_default">True</property>
                                    <property name="tooltip_text" translatable="yes" context="standardfilterdialog|remove1|tooltip_text">Remove</property>
                                    <property name="margin_right">8</property>
                                    <property name="image">image1</property>
                                  </object>
                                  <packing>
                                    <property name="left_attach">4</property>
                                    <property name="top_attach">1</property>
                                  </packing>
                                </child>
                                <child>
                                  <object class="GtkButton" id="remove2">
                                    <property name="visible">True</property>
                                    <property name="can_focus">True</property>
                                    <property name="receives_default">True</property>
                                    <property name="tooltip_text" translatable="yes" context="standardfilterdialog|remove2|tooltip_text">Remove</property>
                                    <property name="margin_right">8</property>
                                    <property name="image">image2</property>
                                  </object>
                                  <packing>
                                    <property name="left_attach">4</property>
                                    <property name="top_attach">2</property>
                                  </packing>
                                </child>
                                <child>
                                  <object class="GtkButton" id="remove3">
                                    <property name="visible">True</property>
                                    <property name="can_focus">True</property>
                                    <property name="receives_default">True</property>
                                    <property name="tooltip_text" translatable="yes" context="standardfilterdialog|remove3|tooltip_text">Remove</property>
                                    <property name="margin_right">8</property>
                                    <property name="image">image3</property>
                                  </object>
                                  <packing>
                                    <property name="left_attach">4</property>
                                    <property name="top_attach">3</property>
                                  </packing>
                                </child>
                                <child>
                                  <object class="GtkButton" id="remove4">
                                    <property name="visible">True</property>
                                    <property name="can_focus">True</property>
                                    <property name="receives_default">True</property>
                                    <property name="tooltip_text" translatable="yes" context="standardfilterdialog|remove4|tooltip_text">Remove</property>
                                    <property name="margin_right">8</property>
                                    <property name="image">image4</property>
                                  </object>
                                  <packing>
                                    <property name="left_attach">4</property>
                                    <property name="top_attach">4</property>
                                  </packing>
                                </child>
                                <child>
                                  <placeholder/>
                                </child>
                              </object>
                              <packing>
                                <property name="left_attach">0</property>