include/vcl/weld.hxx                                           |    7 ++++++-
 sc/source/ui/StatisticsDialogs/FTestDialog.cxx                 |    4 ++--
 sc/source/ui/StatisticsDialogs/RegressionDialog.cxx            |    8 ++++----
 sc/source/ui/StatisticsDialogs/StatisticsTwoVariableDialog.cxx |    6 +++---
 sc/source/ui/StatisticsDialogs/TTestDialog.cxx                 |    4 ++--
 sc/source/ui/StatisticsDialogs/ZTestDialog.cxx                 |    4 ++--
 sc/source/ui/inc/StatisticsTwoVariableDialog.hxx               |    2 +-
 7 files changed, 20 insertions(+), 15 deletions(-)

New commits:
commit c0e7bf13239fadcb2db434ee80cd7d212646748f
Author:     Michael Weghorn <[email protected]>
AuthorDate: Tue Oct 21 21:24:25 2025 +0200
Commit:     Michael Weghorn <[email protected]>
CommitDate: Wed Oct 22 07:23:01 2025 +0200

    tdf#130857 qt weld: Don't call Entry::signal_changed while blocked
    
    As is the case for most of the signal handlers, don't call
    the actual handler in weld::Entry::signal_changed when
    signals are currently blocked.
    
    This means that e.g. when setting new text using
    weld::Entry::set_text, this will not result in
    the handler getting called.
    
    For the SalInstanceEntry case, weld::signal_changed
    wasn't called anyway, but for QtInstanceEntry that
    was the case, so this aligns the behavior by making
    sure that the handlers set in dialog implementations
    don't get called for the case of native Qt dialogs
    with SAL_VCL_QT_USE_WELDED_WIDGETS=1 either.
    
    The GTK implementation has its own logic that was
    preventing the method from getting called,
    as GtkInstanceEditable::do_set_text results in
    GtkInstanceEditable::disable_notify_events
    getting called, which blocks the signal handler
    with id GtkInstanceEditable::m_nChangedSignalId,
    which is the one that the GtkInstanceEditable
    ctor connects to the "changed" signal of the
    GtkEditable [1].
    
    Prior to this commit, the dialog newly supported
    since
    
        commit d24e74b16b728ebca060bd5349cba945a55a018b
        Author: Michael Weghorn <[email protected]>
        Date:   Fri Oct 17 17:57:17 2025 +0200
    
            tdf#130857 qt weld: Support Calc "F-Test" dialog
    
    would behave differently for the qt6 VCL plugin with
    SAL_VCL_QT_USE_WELDED_WIDGETS=1:
    
    When starting the dialog using "Data" -> "Statistics" -> "F-Test"
    in Calc, then clicking the button to select a "Variable 1 range",
    then clicking into one cell and dragging the mouse to select more cells,
    only a single cell would ever be selected, instead of selecting
    all cells from the first to the last one the mouse was moved over
    while the left mouse button was still pressed.
    
    This was due to the weld::Entry::signal_changed getting
    called and calling the handler set in RefEdit.
    
    Relevant backtrace:
    
        1 formula::RefEdit::LinkStubModify funcutl.cxx 348 0x7f2f9c458f30
        2 Link<weld::Entry&, void>::Call link.hxx 105 0x7f2fd529c6f1
        3 weld::Entry::signal_changed weld.hxx 2069 0x7f2fd529c3ac
        4 QtInstanceEntry::handleTextChanged QtInstanceEntry.cxx 194 
0x7f2fd52969cd
        5 QtPrivate::FunctorCall<std::integer_sequence<unsigned long>, 
QtPrivate::List<>, void, void (QtInstanceEntry:: *)()>::call(void 
(QtInstanceEntry:: *)(), QtInstanceEntry *, void * 
*)::{lambda()#1}::operator()() const qobjectdefs_impl.h 127 0x7f2fd529cb61
        6 QtPrivate::FunctorCallBase::call_internal<void, 
QtPrivate::FunctorCall<std::integer_sequence<unsigned long>, QtPrivate::List<>, 
void, void (QtInstanceEntry:: *)()>::call(void (QtInstanceEntry:: *)(), 
QtInstanceEntry *, void * *)::{lambda()#1}>(void * *, 
QtPrivate::FunctorCall<std::integer_sequence<unsigned long>, QtPrivate::List<>, 
void, void (QtInstanceEntry:: *)()>::call(void (QtInstanceEntry:: *)(), 
QtInstanceEntry *, void * *)::{lambda()#1}&&) qobjectdefs_impl.h 65 
0x7f2fd529ca99
        7 QtPrivate::FunctorCall<std::integer_sequence<unsigned long>, 
QtPrivate::List<>, void, void (QtInstanceEntry:: *)()>::call(void 
(QtInstanceEntry:: *)(), QtInstanceEntry *, void * *) qobjectdefs_impl.h 126 
0x7f2fd529c9cb
        8 QtPrivate::FunctionPointer<void (QtInstanceEntry:: 
*)()>::call<QtPrivate::List<>, void>(void (QtInstanceEntry:: *)(), 
QtInstanceEntry *, void * *) qobjectdefs_impl.h 174 0x7f2fd529c94d
        9 QtPrivate::QCallableObject<void (QtInstanceEntry:: *)(), 
QtPrivate::List<>, void>::impl(int, QtPrivate::QSlotObjectBase *, QObject *, 
void * *, bool *) qobjectdefs_impl.h 545 0x7f2fd529c876
        10 QtPrivate::QSlotObjectBase::call qobjectdefs_impl.h 461 
0x7f2fd40e9722
        11 doActivate<false> qobject.cpp 4342 0x7f2fd4315812
        12 QMetaObject::activate qobject.cpp 4402 0x7f2fd430bb23
        13 QMetaObject::activate<void, QString> qobjectdefs.h 319 0x7f2fd22819bb
        14 QLineEdit::textChanged moc_qlineedit.cpp 333 0x7f2fd24d299e
        15 QtPrivate::FunctorCall<std::integer_sequence<unsigned long, 0ul>, 
QtPrivate::List<QString const&>, void, void (QLineEdit:: *)(QString 
const&)>::call(void (QLineEdit:: *)(QString const&), QLineEdit *, void * 
*)::{lambda()#1}::operator()() const qobjectdefs_impl.h 127 0x7f2fd24e0f18
        16 QtPrivate::FunctorCallBase::call_internal<void, 
QtPrivate::FunctorCall<std::integer_sequence<unsigned long, 0ul>, 
QtPrivate::List<QString const&>, void, void (QLineEdit:: *)(QString 
const&)>::call(void (QLineEdit:: *)(QString const&), QLineEdit *, void * 
*)::{lambda()#1}>(void * *, 
QtPrivate::FunctorCall<std::integer_sequence<unsigned long, 0ul>, 
QtPrivate::List<QString const&>, void, void (QLineEdit:: *)(QString 
const&)>::call(void (QLineEdit:: *)(QString const&), QLineEdit *, void * 
*)::{lambda()#1}&&) qobjectdefs_impl.h 65 0x7f2fd24e0e8d
        17 QtPrivate::FunctorCall<std::integer_sequence<unsigned long, 0ul>, 
QtPrivate::List<QString const&>, void, void (QLineEdit:: *)(QString 
const&)>::call qobjectdefs_impl.h 126 0x7f2fd24e0e47
        18 QtPrivate::FunctionPointer<void (QLineEdit:: *)(QString 
const&)>::call<QtPrivate::List<QString const&>, void> qobjectdefs_impl.h 174 
0x7f2fd24e0db1
        19 QtPrivate::QCallableObject<void (QLineEdit:: *)(QString const&), 
QtPrivate::List<QString const&>, void>::impl qobjectdefs_impl.h 545 
0x7f2fd24e0cdb
        20 QtPrivate::QSlotObjectBase::call qobjectdefs_impl.h 461 
0x7f2fd40e9722
        21 doActivate<false> qobject.cpp 4342 0x7f2fd4315812
        22 QMetaObject::activate qobject.cpp 4402 0x7f2fd430bb23
        23 QMetaObject::activate<void, QString> qobjectdefs.h 319 0x7f2fd22819bb
        24 QWidgetLineControl::textChanged moc_qwidgetlinecontrol_p.cpp 211 
0x7f2fd24e9911
        25 QWidgetLineControl::finishChange qwidgetlinecontrol.cpp 716 
0x7f2fd24e7006
        26 QWidgetLineControl::internalSetText qwidgetlinecontrol.cpp 752 
0x7f2fd24e876b
        27 QWidgetLineControl::setText qwidgetlinecontrol_p.h 221 0x7f2fd24d5798
        28 QLineEditPrivate::setText qlineedit_p.cpp 277 0x7f2fd24dad4a
        29 QLineEdit::setText qlineedit.cpp 296 0x7f2fd24cb03e
        30 QtInstanceEntry::do_set_text(rtl::OUString 
const&)::$_0::operator()() const QtInstanceEntry.cxx 32 0x7f2fd5299156
        31 std::__invoke_impl<void, QtInstanceEntry::do_set_text(rtl::OUString 
const&)::$_0&>(std::__invoke_other, QtInstanceEntry::do_set_text(rtl::OUString 
const&)::$_0&) invoke.h 63 0x7f2fd5299105
        32 std::__invoke_r<void, QtInstanceEntry::do_set_text(rtl::OUString 
const&)::$_0&>(QtInstanceEntry::do_set_text(rtl::OUString const&)::$_0&) 
invoke.h 113 0x7f2fd52990b5
        33 std::_Function_handler<void(), 
QtInstanceEntry::do_set_text(rtl::OUString const&)::$_0>::_M_invoke 
std_function.h 292 0x7f2fd5298fcd
        34 std::function<void()>::operator() std_function.h 593 0x7f2fd522eb9e
        35 QtInstance::RunInMainThread QtInstance.cxx 205 0x7f2fd5225dcf
        36 QtInstanceEntry::do_set_text QtInstanceEntry.cxx 32 0x7f2fd529717a
        37 weld::Entry::set_text weld.hxx 2086 0x7f2f9c439961
        38 formula::RefEdit::SetRefString funcutl.cxx 293 0x7f2f9c45872f
        39 ScStatisticsTwoVariableDialog::SetReference 
StatisticsTwoVariableDialog.cxx 161 0x7f2f7368d440
        40 ScModule::SetReference scmod.cxx 1819 0x7f2f7324bdef
        41 ScTabView::InitRefMode tabview4.cxx 385 0x7f2f73bb6cce
        42 ScViewFunctionSet::SetCursorAtCell select.cxx 494 0x7f2f73b5f45a
        43 ScViewFunctionSet::SetCursorAtPoint select.cxx 425 0x7f2f73b5f029
        44 SelectionEngine::SelMouseButtonDown seleng.cxx 172 0x7f2fdd575f04
        45 ScTabView::SelMouseButtonDown tabview3.cxx 1227 0x7f2f73ba1281
        46 ScGridWindow::HandleMouseButtonDown gridwin.cxx 2219 0x7f2f73a495df
        47 ScGridWindow::MouseButtonDown gridwin.cxx 1840 0x7f2f73a47e92
        48 ImplHandleMouseEvent winproc.cxx 733 0x7f2fdd622d31
        49 ImplHandleSalMouseButtonDown winproc.cxx 2365 0x7f2fdd6272e1
        50 ImplWindowFrameProc winproc.cxx 2703 0x7f2fdd625f51
        51 SalFrame::CallCallback salframe.hxx 310 0x7f2fd520721c
        52 QtFrame::CallCallback QtFrame.hxx 234 0x7f2fd52040f5
        53 QtWidget::handleMouseButtonEvent QtWidget.cxx 112 0x7f2fd537070a
        54 QtWidget::mousePressEvent QtWidget.cxx 117 0x7f2fd537075e
        55 QWidget::event qwidget.cpp 9021 0x7f2fd226f1d1
        56 QtWidget::event QtWidget.cxx 501 0x7f2fd53723aa
        [...]
    
    With this commit in place, this works as expected now
    and a range of multiple cells can be selected this way.
    
    [1] https://docs.gtk.org/gtk3/signal.Editable.changed.html
    
    Change-Id: I9040eeac6979479b663756968693965cabf5c286
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/192807
    Reviewed-by: Michael Weghorn <[email protected]>
    Tested-by: Jenkins

diff --git a/include/vcl/weld.hxx b/include/vcl/weld.hxx
index 893890d1268c..672307aca740 100644
--- a/include/vcl/weld.hxx
+++ b/include/vcl/weld.hxx
@@ -2066,7 +2066,12 @@ protected:
 
     friend class ::LOKTrigger;
 
-    void signal_changed() { m_aChangeHdl.Call(*this); }
+    void signal_changed()
+    {
+        if (notify_events_disabled())
+            return;
+        m_aChangeHdl.Call(*this);
+    }
 
     void signal_cursor_position()
     {
commit faea3b508ee90859f3702d01d93d7d96cce0526c
Author:     Michael Weghorn <[email protected]>
AuthorDate: Tue Oct 21 21:17:07 2025 +0200
Commit:     Michael Weghorn <[email protected]>
CommitDate: Wed Oct 22 07:22:52 2025 +0200

    sc: Make ScStatisticsTwoVariableDialog::GroupedBy an enum class
    
    Change-Id: Ic4af87637bd3a499a90319aea533a9e659481009
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/192806
    Tested-by: Jenkins
    Reviewed-by: Michael Weghorn <[email protected]>

diff --git a/sc/source/ui/StatisticsDialogs/FTestDialog.cxx 
b/sc/source/ui/StatisticsDialogs/FTestDialog.cxx
index a4e527dab9b3..cc6382400c06 100644
--- a/sc/source/ui/StatisticsDialogs/FTestDialog.cxx
+++ b/sc/source/ui/StatisticsDialogs/FTestDialog.cxx
@@ -46,13 +46,13 @@ ScRange ScFTestDialog::ApplyOutput(ScDocShell& rDocShell)
     FormulaTemplate aTemplate(&mDocument);
 
     std::unique_ptr<DataRangeIterator> pVariable1Iterator;
-    if (mGroupedBy == BY_COLUMN)
+    if (mGroupedBy == GroupedBy::BY_COLUMN)
         pVariable1Iterator.reset(new 
DataRangeByColumnIterator(mVariable1Range));
     else
         pVariable1Iterator.reset(new DataRangeByRowIterator(mVariable1Range));
 
     std::unique_ptr<DataRangeIterator> pVariable2Iterator;
-    if (mGroupedBy == BY_COLUMN)
+    if (mGroupedBy == GroupedBy::BY_COLUMN)
         pVariable2Iterator.reset(new 
DataRangeByColumnIterator(mVariable2Range));
     else
         pVariable2Iterator.reset(new DataRangeByRowIterator(mVariable2Range));
diff --git a/sc/source/ui/StatisticsDialogs/RegressionDialog.cxx 
b/sc/source/ui/StatisticsDialogs/RegressionDialog.cxx
index b32e53a046f6..03d0fbdbc3a4 100644
--- a/sc/source/ui/StatisticsDialogs/RegressionDialog.cxx
+++ b/sc/source/ui/StatisticsDialogs/RegressionDialog.cxx
@@ -240,7 +240,7 @@ bool ScRegressionDialog::InputRangesValid()
     mVariable1Range.PutInOrder();
     mVariable2Range.PutInOrder();
 
-    bool bGroupedByColumn = mGroupedBy == BY_COLUMN;
+    bool bGroupedByColumn = mGroupedBy == GroupedBy::BY_COLUMN;
 
     bool bYHasSingleDim = (
         (bGroupedByColumn &&
@@ -298,7 +298,7 @@ ScRange ScRegressionDialog::GetDataRange(const ScRange& 
rRange)
         return rRange;
 
     ScRange aDataRange(rRange);
-    if (mGroupedBy == BY_COLUMN)
+    if (mGroupedBy == GroupedBy::BY_COLUMN)
         aDataRange.aStart.IncRow(1);
     else
         aDataRange.aStart.IncCol(1);
@@ -314,7 +314,7 @@ OUString ScRegressionDialog::GetVariableNameFormula(bool 
bXVar, size_t nIndex, b
     if (mxWithLabelsCheckBox->get_active())
     {
         ScAddress aAddr(bXVar ? mVariable1Range.aStart : 
mVariable2Range.aStart);
-        if (mGroupedBy == BY_COLUMN)
+        if (mGroupedBy == GroupedBy::BY_COLUMN)
             aAddr.IncCol(nIndex - 1);
         else
             aAddr.IncRow(nIndex - 1);
@@ -617,7 +617,7 @@ void 
ScRegressionDialog::WriteRegressionEstimatesWithCI(AddressWalkerWriter& rOu
 void ScRegressionDialog::WritePredictionsWithResiduals(AddressWalkerWriter& 
rOutput, FormulaTemplate& rTemplate,
                                                        size_t nRegressionIndex)
 {
-    bool bGroupedByColumn = mGroupedBy == BY_COLUMN;
+    bool bGroupedByColumn = mGroupedBy == GroupedBy::BY_COLUMN;
     rOutput.newLine();
     rOutput.push();
 
diff --git a/sc/source/ui/StatisticsDialogs/StatisticsTwoVariableDialog.cxx 
b/sc/source/ui/StatisticsDialogs/StatisticsTwoVariableDialog.cxx
index 5e00ac1968d1..950506022429 100644
--- a/sc/source/ui/StatisticsDialogs/StatisticsTwoVariableDialog.cxx
+++ b/sc/source/ui/StatisticsDialogs/StatisticsTwoVariableDialog.cxx
@@ -37,7 +37,7 @@ ScStatisticsTwoVariableDialog::ScStatisticsTwoVariableDialog(
     , mVariable2Range(ScAddress::INITIALIZE_INVALID)
     , mAddressDetails(mDocument.GetAddressConvention(), 0, 0 )
     , mOutputAddress(ScAddress::INITIALIZE_INVALID)
-    , mGroupedBy(BY_COLUMN)
+    , mGroupedBy(GroupedBy::BY_COLUMN)
     , mxButtonOk(m_xBuilder->weld_button(u"ok"_ustr))
     , mxButtonCancel(m_xBuilder->weld_button(u"cancel"_ustr))
     , 
mxGroupByColumnsRadio(m_xBuilder->weld_radio_button(u"groupedby-columns-radio"_ustr))
@@ -245,9 +245,9 @@ IMPL_LINK_NOARG( ScStatisticsTwoVariableDialog, 
LoseButtonFocusHandler, formula:
 IMPL_LINK_NOARG(ScStatisticsTwoVariableDialog, GroupByChanged, 
weld::Toggleable&, void)
 {
     if (mxGroupByColumnsRadio->get_active())
-        mGroupedBy = BY_COLUMN;
+        mGroupedBy = GroupedBy::BY_COLUMN;
     else if (mxGroupByRowsRadio->get_active())
-        mGroupedBy = BY_ROW;
+        mGroupedBy = GroupedBy::BY_ROW;
 
     ValidateDialogInput();
 }
diff --git a/sc/source/ui/StatisticsDialogs/TTestDialog.cxx 
b/sc/source/ui/StatisticsDialogs/TTestDialog.cxx
index b354f4ee02a8..c3207eb0043c 100644
--- a/sc/source/ui/StatisticsDialogs/TTestDialog.cxx
+++ b/sc/source/ui/StatisticsDialogs/TTestDialog.cxx
@@ -46,13 +46,13 @@ ScRange ScTTestDialog::ApplyOutput(ScDocShell& rDocShell)
     FormulaTemplate aTemplate(&mDocument);
 
     std::unique_ptr<DataRangeIterator> pVariable1Iterator;
-    if (mGroupedBy == BY_COLUMN)
+    if (mGroupedBy == GroupedBy::BY_COLUMN)
         pVariable1Iterator.reset(new 
DataRangeByColumnIterator(mVariable1Range));
     else
         pVariable1Iterator.reset(new DataRangeByRowIterator(mVariable1Range));
 
     std::unique_ptr<DataRangeIterator> pVariable2Iterator;
-    if (mGroupedBy == BY_COLUMN)
+    if (mGroupedBy == GroupedBy::BY_COLUMN)
         pVariable2Iterator.reset(new 
DataRangeByColumnIterator(mVariable2Range));
     else
         pVariable2Iterator.reset(new DataRangeByRowIterator(mVariable2Range));
diff --git a/sc/source/ui/StatisticsDialogs/ZTestDialog.cxx 
b/sc/source/ui/StatisticsDialogs/ZTestDialog.cxx
index 0966af0aaf1b..a849453073c4 100644
--- a/sc/source/ui/StatisticsDialogs/ZTestDialog.cxx
+++ b/sc/source/ui/StatisticsDialogs/ZTestDialog.cxx
@@ -46,13 +46,13 @@ ScRange ScZTestDialog::ApplyOutput(ScDocShell& rDocShell)
     FormulaTemplate aTemplate(&mDocument);
 
     std::unique_ptr<DataRangeIterator> pVariable1Iterator;
-    if (mGroupedBy == BY_COLUMN)
+    if (mGroupedBy == GroupedBy::BY_COLUMN)
         pVariable1Iterator.reset(new 
DataRangeByColumnIterator(mVariable1Range));
     else
         pVariable1Iterator.reset(new DataRangeByRowIterator(mVariable1Range));
 
     std::unique_ptr<DataRangeIterator> pVariable2Iterator;
-    if (mGroupedBy == BY_COLUMN)
+    if (mGroupedBy == GroupedBy::BY_COLUMN)
         pVariable2Iterator.reset(new 
DataRangeByColumnIterator(mVariable2Range));
     else
         pVariable2Iterator.reset(new DataRangeByRowIterator(mVariable2Range));
diff --git a/sc/source/ui/inc/StatisticsTwoVariableDialog.hxx 
b/sc/source/ui/inc/StatisticsTwoVariableDialog.hxx
index dde63e9c8ced..0ed7d6b242e9 100644
--- a/sc/source/ui/inc/StatisticsTwoVariableDialog.hxx
+++ b/sc/source/ui/inc/StatisticsTwoVariableDialog.hxx
@@ -17,7 +17,7 @@
 class ScStatisticsTwoVariableDialog : public ScAnyRefDlgController
 {
 public:
-    enum GroupedBy {
+    enum class GroupedBy {
         BY_COLUMN,
         BY_ROW
     };

Reply via email to