Coverage Report

Created: 2025-11-16 09:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sc/source/ui/StatisticsDialogs/StatisticsTwoVariableDialog.cxx
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/*
3
 * This file is part of the LibreOffice project.
4
 *
5
 * This Source Code Form is subject to the terms of the Mozilla Public
6
 * License, v. 2.0. If a copy of the MPL was not distributed with this
7
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8
 *
9
 */
10
11
#include <svl/undo.hxx>
12
13
#include <rangelst.hxx>
14
#include <docsh.hxx>
15
#include <document.hxx>
16
#include <scresid.hxx>
17
#include <tabvwsh.hxx>
18
19
#include <StatisticsTwoVariableDialog.hxx>
20
21
ScStatisticsTwoVariableDialog::ScStatisticsTwoVariableDialog(
22
                    SfxBindings* pSfxBindings, SfxChildWindow* pChildWindow,
23
                    weld::Window* pParent, ScViewData& rViewData, const OUString& rUIXMLDescription, const OUString& rID)
24
0
    : ScAnyRefDlgController(pSfxBindings, pChildWindow, pParent, rUIXMLDescription, rID)
25
0
    , mxVariable1RangeLabel(m_xBuilder->weld_label(u"variable1-range-label"_ustr))
26
0
    , mxVariable1RangeEdit(new formula::RefEdit(m_xBuilder->weld_entry(u"variable1-range-edit"_ustr)))
27
0
    , mxVariable1RangeButton(new formula::RefButton(m_xBuilder->weld_button(u"variable1-range-button"_ustr)))
28
0
    , mxVariable2RangeLabel(m_xBuilder->weld_label(u"variable2-range-label"_ustr))
29
0
    , mxVariable2RangeEdit(new formula::RefEdit(m_xBuilder->weld_entry(u"variable2-range-edit"_ustr)))
30
0
    , mxVariable2RangeButton(new formula::RefButton(m_xBuilder->weld_button(u"variable2-range-button"_ustr)))
31
0
    , mxOutputRangeLabel(m_xBuilder->weld_label(u"output-range-label"_ustr))
32
0
    , mxOutputRangeEdit(new formula::RefEdit(m_xBuilder->weld_entry(u"output-range-edit"_ustr)))
33
0
    , mxOutputRangeButton(new formula::RefButton(m_xBuilder->weld_button(u"output-range-button"_ustr)))
34
0
    , mViewData(rViewData)
35
0
    , mDocument(rViewData.GetDocument())
36
0
    , mVariable1Range(ScAddress::INITIALIZE_INVALID)
37
0
    , mVariable2Range(ScAddress::INITIALIZE_INVALID)
38
0
    , mAddressDetails(mDocument.GetAddressConvention(), 0, 0 )
39
0
    , mOutputAddress(ScAddress::INITIALIZE_INVALID)
40
0
    , mGroupedBy(GroupedBy::BY_COLUMN)
41
0
    , mxButtonOk(m_xBuilder->weld_button(u"ok"_ustr))
42
0
    , mxButtonCancel(m_xBuilder->weld_button(u"cancel"_ustr))
43
0
    , mxGroupByColumnsRadio(m_xBuilder->weld_radio_button(u"groupedby-columns-radio"_ustr))
44
0
    , mxGroupByRowsRadio(m_xBuilder->weld_radio_button(u"groupedby-rows-radio"_ustr))
45
0
    , mpActiveEdit(nullptr)
46
0
    , mCurrentAddress(rViewData.GetCurX(), rViewData.GetCurY(), rViewData.CurrentTabForData() )
47
0
    , mDialogLostFocus(false)
48
0
{
49
0
    mxVariable1RangeEdit->SetReferences(this, mxVariable1RangeLabel.get());
50
0
    mxVariable1RangeButton->SetReferences(this, mxVariable1RangeEdit.get());
51
52
0
    mxVariable2RangeEdit->SetReferences(this, mxVariable2RangeLabel.get());
53
0
    mxVariable2RangeButton->SetReferences(this, mxVariable2RangeEdit.get());
54
55
0
    mxOutputRangeEdit->SetReferences(this, mxOutputRangeLabel.get());
56
0
    mxOutputRangeButton->SetReferences(this, mxOutputRangeEdit.get());
57
58
0
    Init();
59
0
    GetRangeFromSelection();
60
0
}
61
62
ScStatisticsTwoVariableDialog::~ScStatisticsTwoVariableDialog()
63
0
{
64
0
}
65
66
void ScStatisticsTwoVariableDialog::Init()
67
0
{
68
0
    mxButtonCancel->connect_clicked( LINK( this, ScStatisticsTwoVariableDialog, ButtonClicked ) );
69
0
    mxButtonOk->connect_clicked( LINK( this, ScStatisticsTwoVariableDialog, ButtonClicked ) );
70
0
    mxButtonOk->set_sensitive(false);
71
72
0
    Link<formula::RefEdit&,void> aEditLink = LINK( this, ScStatisticsTwoVariableDialog, GetEditFocusHandler );
73
0
    mxVariable1RangeEdit->SetGetFocusHdl( aEditLink );
74
0
    mxVariable2RangeEdit->SetGetFocusHdl( aEditLink );
75
0
    mxOutputRangeEdit->SetGetFocusHdl( aEditLink );
76
77
0
    Link<formula::RefButton&,void> aButtonLink = LINK( this, ScStatisticsTwoVariableDialog, GetButtonFocusHandler );
78
0
    mxVariable1RangeButton->SetGetFocusHdl( aButtonLink );
79
0
    mxVariable2RangeButton->SetGetFocusHdl( aButtonLink );
80
0
    mxOutputRangeButton->SetGetFocusHdl( aButtonLink );
81
82
0
    aEditLink = LINK( this, ScStatisticsTwoVariableDialog, LoseEditFocusHandler );
83
0
    mxVariable1RangeEdit->SetLoseFocusHdl( aEditLink );
84
0
    mxVariable2RangeEdit->SetLoseFocusHdl( aEditLink );
85
0
    mxOutputRangeEdit->SetLoseFocusHdl( aEditLink );
86
87
0
    aButtonLink = LINK( this, ScStatisticsTwoVariableDialog, LoseButtonFocusHandler );
88
0
    mxVariable1RangeButton->SetLoseFocusHdl( aButtonLink );
89
0
    mxVariable2RangeButton->SetLoseFocusHdl( aButtonLink );
90
0
    mxOutputRangeButton->SetLoseFocusHdl( aButtonLink );
91
92
0
    Link<formula::RefEdit&,void> aLink2 = LINK( this, ScStatisticsTwoVariableDialog, RefInputModifyHandler);
93
0
    mxVariable1RangeEdit->SetModifyHdl( aLink2);
94
0
    mxVariable2RangeEdit->SetModifyHdl( aLink2);
95
0
    mxOutputRangeEdit->SetModifyHdl( aLink2);
96
97
0
    mxOutputRangeEdit->GrabFocus();
98
99
0
    mxGroupByColumnsRadio->connect_toggled( LINK( this, ScStatisticsTwoVariableDialog, GroupByChanged ) );
100
0
    mxGroupByRowsRadio->connect_toggled( LINK( this, ScStatisticsTwoVariableDialog, GroupByChanged ) );
101
102
0
    mxGroupByColumnsRadio->set_active(true);
103
0
    mxGroupByRowsRadio->set_active(false);
104
0
}
105
106
void ScStatisticsTwoVariableDialog::GetRangeFromSelection()
107
0
{
108
0
    OUString aCurrentString;
109
110
0
    ScRange aCurrentRange;
111
0
    mViewData.GetSimpleArea(aCurrentRange);
112
113
0
    if (aCurrentRange.aEnd.Col() - aCurrentRange.aStart.Col() == 1)
114
0
    {
115
0
        mVariable1Range = aCurrentRange;
116
0
        mVariable1Range.aEnd.SetCol(mVariable1Range.aStart.Col());
117
0
        aCurrentString = mVariable1Range.Format(mDocument, ScRefFlags::RANGE_ABS_3D, mAddressDetails);
118
0
        mxVariable1RangeEdit->SetText(aCurrentString);
119
120
0
        mVariable2Range = aCurrentRange;
121
0
        mVariable2Range.aStart.SetCol(mVariable2Range.aEnd.Col());
122
0
        aCurrentString = mVariable2Range.Format(mDocument, ScRefFlags::RANGE_ABS_3D, mAddressDetails);
123
0
        mxVariable2RangeEdit->SetText(aCurrentString);
124
0
    }
125
0
    else
126
0
    {
127
0
        mVariable1Range = aCurrentRange;
128
0
        aCurrentString = mVariable1Range.Format(mDocument, ScRefFlags::RANGE_ABS_3D, mAddressDetails);
129
0
        mxVariable1RangeEdit->SetText(aCurrentString);
130
0
    }
131
0
}
132
133
void ScStatisticsTwoVariableDialog::SetActive()
134
0
{
135
0
    if ( mDialogLostFocus )
136
0
    {
137
0
        mDialogLostFocus = false;
138
0
        if( mpActiveEdit )
139
0
            mpActiveEdit->GrabFocus();
140
0
    }
141
0
    else
142
0
    {
143
0
        m_xDialog->grab_focus();
144
0
    }
145
0
    RefInputDone();
146
0
}
147
148
void ScStatisticsTwoVariableDialog::SetReference( const ScRange& rReferenceRange, ScDocument& rDocument )
149
0
{
150
0
    if ( mpActiveEdit != nullptr )
151
0
    {
152
0
        if ( rReferenceRange.aStart != rReferenceRange.aEnd )
153
0
            RefInputStart( mpActiveEdit );
154
155
0
        OUString aReferenceString;
156
157
0
        if ( mpActiveEdit == mxVariable1RangeEdit.get() )
158
0
        {
159
0
            mVariable1Range = rReferenceRange;
160
0
            aReferenceString = mVariable1Range.Format(rDocument, ScRefFlags::RANGE_ABS_3D, mAddressDetails);
161
0
            mxVariable1RangeEdit->SetRefString(aReferenceString);
162
0
        }
163
0
        else if ( mpActiveEdit == mxVariable2RangeEdit.get() )
164
0
        {
165
0
            mVariable2Range = rReferenceRange;
166
0
            aReferenceString = mVariable2Range.Format(rDocument, ScRefFlags::RANGE_ABS_3D, mAddressDetails);
167
0
            mxVariable2RangeEdit->SetRefString(aReferenceString);
168
0
        }
169
0
        else if ( mpActiveEdit == mxOutputRangeEdit.get() )
170
0
        {
171
0
            mOutputAddress = rReferenceRange.aStart;
172
173
0
            ScRefFlags nFormat = ( mOutputAddress.Tab() == mCurrentAddress.Tab() ) ?
174
0
                                                             ScRefFlags::ADDR_ABS :
175
0
                                                             ScRefFlags::ADDR_ABS_3D;
176
0
            aReferenceString = mOutputAddress.Format(nFormat, &rDocument, rDocument.GetAddressConvention());
177
0
            mxOutputRangeEdit->SetRefString( aReferenceString );
178
0
        }
179
0
    }
180
181
0
    ValidateDialogInput();
182
0
}
183
184
IMPL_LINK( ScStatisticsTwoVariableDialog, ButtonClicked, weld::Button&, rButton, void )
185
0
{
186
0
    if (&rButton == mxButtonOk.get())
187
0
    {
188
0
        CalculateInputAndWriteToOutput();
189
0
        response(RET_OK);
190
0
    }
191
0
    else
192
0
        response(RET_CANCEL);
193
0
}
194
195
IMPL_LINK(ScStatisticsTwoVariableDialog, GetEditFocusHandler, formula::RefEdit&, rCtrl, void)
196
0
{
197
0
    mpActiveEdit = nullptr;
198
0
    if (&rCtrl == mxVariable1RangeEdit.get())
199
0
    {
200
0
        mpActiveEdit = mxVariable1RangeEdit.get();
201
0
    }
202
0
    else if (&rCtrl == mxVariable2RangeEdit.get())
203
0
    {
204
0
        mpActiveEdit = mxVariable2RangeEdit.get();
205
0
    }
206
0
    else if (&rCtrl == mxOutputRangeEdit.get())
207
0
    {
208
0
        mpActiveEdit = mxOutputRangeEdit.get();
209
0
    }
210
211
0
    if( mpActiveEdit )
212
0
        mpActiveEdit->SelectAll();
213
0
}
214
215
IMPL_LINK( ScStatisticsTwoVariableDialog, GetButtonFocusHandler, formula::RefButton&, rCtrl, void )
216
0
{
217
0
    mpActiveEdit = nullptr;
218
0
    if (&rCtrl == mxVariable1RangeButton.get())
219
0
    {
220
0
        mpActiveEdit = mxVariable1RangeEdit.get();
221
0
    }
222
0
    else if (&rCtrl == mxVariable2RangeButton.get())
223
0
    {
224
0
        mpActiveEdit = mxVariable2RangeEdit.get();
225
0
    }
226
0
    else if (&rCtrl == mxOutputRangeButton.get())
227
0
    {
228
0
        mpActiveEdit = mxOutputRangeEdit.get();
229
0
    }
230
231
0
    if( mpActiveEdit )
232
0
        mpActiveEdit->SelectAll();
233
0
}
234
235
IMPL_LINK_NOARG( ScStatisticsTwoVariableDialog, LoseEditFocusHandler, formula::RefEdit&, void )
236
0
{
237
0
    mDialogLostFocus = !m_xDialog->has_toplevel_focus();
238
0
}
239
240
IMPL_LINK_NOARG( ScStatisticsTwoVariableDialog, LoseButtonFocusHandler, formula::RefButton&, void )
241
0
{
242
0
    mDialogLostFocus = !m_xDialog->has_toplevel_focus();
243
0
}
244
245
IMPL_LINK_NOARG(ScStatisticsTwoVariableDialog, GroupByChanged, weld::Toggleable&, void)
246
0
{
247
0
    if (mxGroupByColumnsRadio->get_active())
248
0
        mGroupedBy = GroupedBy::BY_COLUMN;
249
0
    else if (mxGroupByRowsRadio->get_active())
250
0
        mGroupedBy = GroupedBy::BY_ROW;
251
252
0
    ValidateDialogInput();
253
0
}
254
255
IMPL_LINK_NOARG( ScStatisticsTwoVariableDialog, RefInputModifyHandler, formula::RefEdit&, void )
256
0
{
257
0
    if ( mpActiveEdit )
258
0
    {
259
0
        if (mpActiveEdit == mxVariable1RangeEdit.get())
260
0
        {
261
0
            ScRangeList aRangeList;
262
0
            bool bValid = ParseWithNames( aRangeList, mxVariable1RangeEdit->GetText(), mDocument);
263
0
            const ScRange* pRange = (bValid && aRangeList.size() == 1) ? &aRangeList[0] : nullptr;
264
0
            if (pRange)
265
0
            {
266
0
                mVariable1Range = *pRange;
267
                // Highlight the resulting range.
268
0
                mxVariable1RangeEdit->StartUpdateData();
269
0
            }
270
0
            else
271
0
            {
272
0
                mVariable1Range = ScRange( ScAddress::INITIALIZE_INVALID);
273
0
            }
274
0
        }
275
0
        else if ( mpActiveEdit == mxVariable2RangeEdit.get() )
276
0
        {
277
0
            ScRangeList aRangeList;
278
0
            bool bValid = ParseWithNames( aRangeList, mxVariable2RangeEdit->GetText(), mDocument);
279
0
            const ScRange* pRange = (bValid && aRangeList.size() == 1) ? &aRangeList[0] : nullptr;
280
0
            if (pRange)
281
0
            {
282
0
                mVariable2Range = *pRange;
283
                // Highlight the resulting range.
284
0
                mxVariable2RangeEdit->StartUpdateData();
285
0
            }
286
0
            else
287
0
            {
288
0
                mVariable2Range = ScRange( ScAddress::INITIALIZE_INVALID);
289
0
            }
290
0
        }
291
0
        else if ( mpActiveEdit == mxOutputRangeEdit.get() )
292
0
        {
293
0
            ScRangeList aRangeList;
294
0
            bool bValid = ParseWithNames( aRangeList, mxOutputRangeEdit->GetText(), mDocument);
295
0
            const ScRange* pRange = (bValid && aRangeList.size() == 1) ? &aRangeList[0] : nullptr;
296
0
            if (pRange)
297
0
            {
298
0
                mOutputAddress = pRange->aStart;
299
300
                // Crop output range to top left address for Edit field.
301
0
                if (pRange->aStart != pRange->aEnd)
302
0
                {
303
0
                    ScRefFlags nFormat = ( mOutputAddress.Tab() == mCurrentAddress.Tab() ) ?
304
0
                                                                     ScRefFlags::ADDR_ABS :
305
0
                                                                     ScRefFlags::ADDR_ABS_3D;
306
0
                    OUString aReferenceString = mOutputAddress.Format(nFormat, &mDocument, mDocument.GetAddressConvention());
307
0
                    mxOutputRangeEdit->SetRefString( aReferenceString );
308
0
                }
309
310
                // Highlight the resulting range.
311
0
                mxOutputRangeEdit->StartUpdateData();
312
0
            }
313
0
            else
314
0
            {
315
0
                mOutputAddress = ScAddress( ScAddress::INITIALIZE_INVALID);
316
0
            }
317
0
        }
318
0
    }
319
320
0
    ValidateDialogInput();
321
0
}
322
323
void ScStatisticsTwoVariableDialog::CalculateInputAndWriteToOutput()
324
0
{
325
0
    OUString aUndo(ScResId(GetUndoNameId()));
326
0
    ScDocShell& rDocShell = mViewData.GetDocShell();
327
0
    SfxUndoManager* pUndoManager = rDocShell.GetUndoManager();
328
0
    pUndoManager->EnterListAction( aUndo, aUndo, 0, mViewData.GetViewShell()->GetViewShellId() );
329
330
0
    ScRange aOutputRange = ApplyOutput(rDocShell);
331
332
0
    pUndoManager->LeaveListAction();
333
0
    rDocShell.PostPaint( aOutputRange, PaintPartFlags::Grid );
334
0
}
335
336
bool ScStatisticsTwoVariableDialog::InputRangesValid()
337
0
{
338
0
    return mVariable1Range.IsValid() && mVariable2Range.IsValid() && mOutputAddress.IsValid();
339
0
}
340
341
void ScStatisticsTwoVariableDialog::ValidateDialogInput()
342
0
{
343
    // Enable OK button if all inputs are ok.
344
0
    mxButtonOk->set_sensitive(InputRangesValid());
345
0
}
346
347
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */