include/svx/weldeditview.hxx | 2 sc/qa/uitest/calc_tests6/tdf85976.py | 65 +++++++++++++++++++ sc/qa/uitest/data/tdf85976.ods |binary svx/source/dialog/weldeditview.cxx | 114 ++++++++++++++++++----------------- 4 files changed, 128 insertions(+), 53 deletions(-)
New commits: commit 99078d06e984f7596e57cb342671ccdd291ae176 Author: Xisco Fauli <xiscofa...@libreoffice.org> AuthorDate: Fri Apr 4 10:56:48 2025 +0200 Commit: Xisco Fauli <xiscofa...@libreoffice.org> CommitDate: Fri Apr 4 13:07:06 2025 +0200 tdf#85976, tdf#165678: sc: Add UItest Change-Id: I137d45babe4fc1b54ecda9ab32977035e38c998c Reviewed-on: https://gerrit.libreoffice.org/c/core/+/183701 Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org> Tested-by: Jenkins diff --git a/sc/qa/uitest/calc_tests6/tdf85976.py b/sc/qa/uitest/calc_tests6/tdf85976.py new file mode 100644 index 000000000000..7b8a997b1e89 --- /dev/null +++ b/sc/qa/uitest/calc_tests6/tdf85976.py @@ -0,0 +1,65 @@ +# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-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/. +# + +from uitest.framework import UITestCase +from libreoffice.calc.document import get_cell_by_position +from uitest.uihelper.common import get_url_for_data_file +from uitest.uihelper.common import get_state_as_dict + +class tdf85976(UITestCase): + def test_tdf85976(self): + with self.ui_test.load_file(get_url_for_data_file("tdf85976.ods")) as calc_doc: + with self.ui_test.execute_dialog_through_command(".uno:HandleDuplicateRecords") as xDialog: + xColumn = xDialog.getChild("column") + xRow = xDialog.getChild("row") + xIncludesHeaders = xDialog.getChild("includesheaders") + xAllCheckBtn = xDialog.getChild("allcheckbtn") + xCheckList = xDialog.getChild("checklist") + xSelect = xDialog.getChild("select") + xRemove = xDialog.getChild("remove") + self.assertEqual("false", get_state_as_dict(xColumn)["Checked"]) + self.assertEqual("true", get_state_as_dict(xRow)["Checked"]) + self.assertEqual("false", get_state_as_dict(xIncludesHeaders)["Selected"]) + self.assertEqual("true", get_state_as_dict(xAllCheckBtn)["Selected"]) + self.assertEqual("6", get_state_as_dict(xCheckList)["Children"]) + self.assertEqual("false", get_state_as_dict(xSelect)["Checked"]) + self.assertEqual("true", get_state_as_dict(xRemove)["Checked"]) + + expectedText = ["A", "B", "C", "D", "E", "F"] + for i in range(6): + self.assertEqual(expectedText[i], get_state_as_dict(xCheckList.getChild(i))["Text"]) + self.assertEqual("true", get_state_as_dict(xCheckList.getChild(i))["IsChecked"]) + + xIncludesHeaders.executeAction("CLICK", tuple()) + + expectedText = ["Id", "SepalLengthCm", "SepalWidthCm", "PetalLengthCm", "PetalWidthCm", "Species"] + for i in range(6): + self.assertEqual(expectedText[i], get_state_as_dict(xCheckList.getChild(i))["Text"]) + self.assertEqual("true", get_state_as_dict(xCheckList.getChild(i))["IsChecked"]) + + xAllCheckBtn.executeAction("CLICK", tuple()) + for i in range(6): + self.assertEqual(expectedText[i], get_state_as_dict(xCheckList.getChild(i))["Text"]) + self.assertEqual("false", get_state_as_dict(xCheckList.getChild(i))["IsChecked"]) + + xCheckList.getChild(5).executeAction("CLICK", tuple()) + + for i in range(5): + self.assertEqual(expectedText[i], get_state_as_dict(xCheckList.getChild(i))["Text"]) + self.assertEqual("false", get_state_as_dict(xCheckList.getChild(i))["IsChecked"]) + + self.assertEqual("Species", get_state_as_dict(xCheckList.getChild(5))["Text"]) + self.assertEqual("true", get_state_as_dict(xCheckList.getChild(5))["IsChecked"]) + + self.assertEqual("Id", get_cell_by_position(calc_doc, 0, 0, 0).getString()) + self.assertEqual("1", get_cell_by_position(calc_doc, 0, 0, 1).getString()) + self.assertEqual("51", get_cell_by_position(calc_doc, 0, 0, 2).getString()) + self.assertEqual("101", get_cell_by_position(calc_doc, 0, 0, 3).getString()) + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/sc/qa/uitest/data/tdf85976.ods b/sc/qa/uitest/data/tdf85976.ods new file mode 100644 index 000000000000..cc4feeadb8c2 Binary files /dev/null and b/sc/qa/uitest/data/tdf85976.ods differ commit 79ed1d0ddab3813cfb92f5d0f486046fb880d07d Author: Michael Stahl <michael.st...@allotropia.de> AuthorDate: Fri Feb 14 15:31:53 2025 +0100 Commit: Michael Stahl <michael.st...@allotropia.de> CommitDate: Fri Apr 4 13:06:58 2025 +0200 svx: factor out WeldEditView::PaintSelection() Change-Id: I51b71b20f6bb2b0e86611a052221f1e3785c84d1 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/181677 Tested-by: Jenkins Reviewed-by: Michael Stahl <michael.st...@allotropia.de> diff --git a/include/svx/weldeditview.hxx b/include/svx/weldeditview.hxx index 43002a95e58c..8bfc56fc35c4 100644 --- a/include/svx/weldeditview.hxx +++ b/include/svx/weldeditview.hxx @@ -59,6 +59,8 @@ protected: void InitAccessible(); + static void PaintSelection(vcl::RenderContext& rRenderContext, tools::Rectangle const& rRect, + std::vector<tools::Rectangle> const& rLogicRects, Color const color); void DoPaint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect); public: diff --git a/svx/source/dialog/weldeditview.cxx b/svx/source/dialog/weldeditview.cxx index 77e0971ab799..1e4af457d560 100644 --- a/svx/source/dialog/weldeditview.cxx +++ b/svx/source/dialog/weldeditview.cxx @@ -164,6 +164,65 @@ void WeldEditView::Paint(vcl::RenderContext& rRenderContext, const tools::Rectan DoPaint(rRenderContext, rRect); } +void WeldEditView::PaintSelection(vcl::RenderContext& rRenderContext, tools::Rectangle const& rRect, + std::vector<tools::Rectangle> const& rLogicRects, + Color const color) +{ + if (rLogicRects.empty()) + { + return; + } + + std::vector<basegfx::B2DRange> aLogicRanges; + aLogicRanges.reserve(rLogicRects.size()); + + tools::Long nMinX(LONG_MAX), nMaxX(0), nMinY(LONG_MAX), nMaxY(0); + for (const auto& aRect : rLogicRects) + { + nMinX = std::min(nMinX, aRect.Left()); + nMinY = std::min(nMinY, aRect.Top()); + nMaxX = std::max(nMaxX, aRect.Right()); + nMaxY = std::max(nMaxY, aRect.Bottom()); + } + + const Size aLogicPixel(rRenderContext.PixelToLogic(Size(1, 1))); + for (const auto& aRect : rLogicRects) + { + // Extend each range by one pixel so multiple lines touch each + // other if adjacent, so the whole set is drawn with a single + // border around the lot. But keep the selection within the + // original max extents. + auto nTop = aRect.Top(); + if (nTop > nMinY) + nTop -= aLogicPixel.Height(); + auto nBottom = aRect.Bottom(); + if (nBottom < nMaxY) + nBottom += aLogicPixel.Height(); + auto nLeft = aRect.Left(); + if (nLeft > nMinX) + nLeft -= aLogicPixel.Width(); + auto nRight = aRect.Right(); + if (nRight < nMaxX) + nRight += aLogicPixel.Width(); + + aLogicRanges.emplace_back(nLeft, nTop, nRight, nBottom); + } + + // get the system's highlight color + sdr::overlay::OverlaySelection aCursorOverlay(sdr::overlay::OverlayType::Transparent, color, + std::move(aLogicRanges), true); + + drawinglayer::geometry::ViewInformation2D aViewInformation2D; + aViewInformation2D.setViewTransformation(rRenderContext.GetViewTransformation()); + aViewInformation2D.setViewport(vcl::unotools::b2DRectangleFromRectangle(rRect)); + + std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> xProcessor( + drawinglayer::processor2d::createProcessor2DFromOutputDevice(rRenderContext, + aViewInformation2D)); + + xProcessor->process(aCursorOverlay.getOverlayObjectPrimitive2DSequence()); +} + void WeldEditView::DoPaint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) { rRenderContext.Push(vcl::PushFlags::ALL); @@ -188,59 +247,8 @@ void WeldEditView::DoPaint(vcl::RenderContext& rRenderContext, const tools::Rect pEditView->GetSelectionRectangles(aLogicRects); } - if (!aLogicRects.empty()) - { - std::vector<basegfx::B2DRange> aLogicRanges; - aLogicRanges.reserve(aLogicRects.size()); - - tools::Long nMinX(LONG_MAX), nMaxX(0), nMinY(LONG_MAX), nMaxY(0); - for (const auto& aRect : aLogicRects) - { - nMinX = std::min(nMinX, aRect.Left()); - nMinY = std::min(nMinY, aRect.Top()); - nMaxX = std::max(nMaxX, aRect.Right()); - nMaxY = std::max(nMaxY, aRect.Bottom()); - } - - const Size aLogicPixel(rRenderContext.PixelToLogic(Size(1, 1))); - for (const auto& aRect : aLogicRects) - { - // Extend each range by one pixel so multiple lines touch each - // other if adjacent, so the whole set is drawn with a single - // border around the lot. But keep the selection within the - // original max extents. - auto nTop = aRect.Top(); - if (nTop > nMinY) - nTop -= aLogicPixel.Height(); - auto nBottom = aRect.Bottom(); - if (nBottom < nMaxY) - nBottom += aLogicPixel.Height(); - auto nLeft = aRect.Left(); - if (nLeft > nMinX) - nLeft -= aLogicPixel.Width(); - auto nRight = aRect.Right(); - if (nRight < nMaxX) - nRight += aLogicPixel.Width(); - - aLogicRanges.emplace_back(nLeft, nTop, nRight, nBottom); - } - - // get the system's highlight color - const Color aHighlight(SvtOptionsDrawinglayer::getHilightColor()); - - sdr::overlay::OverlaySelection aCursorOverlay(sdr::overlay::OverlayType::Transparent, - aHighlight, std::move(aLogicRanges), true); - - drawinglayer::geometry::ViewInformation2D aViewInformation2D; - aViewInformation2D.setViewTransformation(rRenderContext.GetViewTransformation()); - aViewInformation2D.setViewport(vcl::unotools::b2DRectangleFromRectangle(rRect)); - - std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> xProcessor( - drawinglayer::processor2d::createProcessor2DFromOutputDevice(rRenderContext, - aViewInformation2D)); - - xProcessor->process(aCursorOverlay.getOverlayObjectPrimitive2DSequence()); - } + const Color aHighlight(SvtOptionsDrawinglayer::getHilightColor()); + PaintSelection(rRenderContext, rRect, aLogicRects, aHighlight); rRenderContext.Pop(); }