cui/source/inc/grfpage.hxx | 3 cui/source/tabpages/grfpage.cxx | 32 + include/sfx2/sfxsids.hrc | 1 include/svx/GenericCheckDialog.hxx | 83 +++ include/svx/strings.hrc | 7 include/svx/svdmodel.hxx | 2 officecfg/registry/data/org/openoffice/Office/UI/GenericCommands.xcu | 8 sd/Library_sd.mk | 1 sd/inc/drawdoc.hxx | 2 sd/sdi/_drvwsh.sdi | 5 sd/source/ui/inc/tools/GraphicSizeCheck.hxx | 103 ++++ sd/source/ui/tools/GraphicSizeCheck.cxx | 213 ++++++++++ sd/source/ui/view/drviews2.cxx | 12 sd/source/ui/view/drviewsj.cxx | 4 sd/uiconfig/sdraw/menubar/menubar.xml | 1 sd/uiconfig/simpress/menubar/menubar.xml | 1 svx/Library_svx.mk | 1 svx/UIConfig_svx.mk | 2 svx/sdi/svx.sdi | 17 svx/source/dialog/GenericCheckDialog.cxx | 70 +++ svx/source/tbxctrls/grafctrl.cxx | 2 svx/uiconfig/ui/genericcheckdialog.ui | 132 ++++++ svx/uiconfig/ui/genericcheckentry.ui | 56 ++ sw/Library_sw.mk | 1 sw/sdi/_basesh.sdi | 7 sw/source/core/graphic/GraphicSizeCheck.cxx | 164 +++++++ sw/source/core/inc/GraphicSizeCheck.hxx | 99 ++++ sw/source/ui/frmdlg/frmdlg.cxx | 7 sw/source/uibase/shells/basesh.cxx | 17 sw/uiconfig/sglobal/menubar/menubar.xml | 1 sw/uiconfig/swriter/menubar/menubar.xml | 1 31 files changed, 1047 insertions(+), 8 deletions(-)
New commits: commit e34067483ef78c1569641becfe99b79a97600aed Author: Tomaž Vajngerl <[email protected]> AuthorDate: Sun Dec 19 22:31:31 2021 +0900 Commit: Tomaž Vajngerl <[email protected]> CommitDate: Mon Dec 20 06:21:49 2021 +0100 Set the original size in crop dialog to preferred DPI calc. size If we have the document setting preferred image size set, then use that as the default DPI and recalcualte the logical image size using the DPI and the size in pixels. This is useful so we have the preferred DPI size as 100% in the crop dialog, so we can adjust the size in relation to that value. Change-Id: I50806f194032e228ee2cf56a39e5735a57358d46 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/127096 Tested-by: Jenkins Reviewed-by: Tomaž Vajngerl <[email protected]> diff --git a/cui/source/inc/grfpage.hxx b/cui/source/inc/grfpage.hxx index 35653eaf6ade..2c7017a57189 100644 --- a/cui/source/inc/grfpage.hxx +++ b/cui/source/inc/grfpage.hxx @@ -56,6 +56,7 @@ class SvxGrfCropPage : public SfxTabPage tools::Long nOldWidth; tools::Long nOldHeight; bool bSetOrigSize; + sal_Int32 m_aPreferredDPI; SvxCropExample m_aExampleWN; @@ -92,7 +93,7 @@ class SvxGrfCropPage : public SfxTabPage void GraphicHasChanged(bool bFound); virtual void ActivatePage(const SfxItemSet& rSet) override; - static Size GetGrfOrigSize(const Graphic&); + Size GetGrfOrigSize(const Graphic& rGraphic); public: SvxGrfCropPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet &rSet); static std::unique_ptr<SfxTabPage> Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet *rSet ); diff --git a/cui/source/tabpages/grfpage.cxx b/cui/source/tabpages/grfpage.cxx index 8742044ab1c3..b83e0bbc0426 100644 --- a/cui/source/tabpages/grfpage.cxx +++ b/cui/source/tabpages/grfpage.cxx @@ -57,6 +57,7 @@ SvxGrfCropPage::SvxGrfCropPage(weld::Container* pPage, weld::DialogController* p , nOldWidth(0) , nOldHeight(0) , bSetOrigSize(false) + , m_aPreferredDPI(0) , m_xCropFrame(m_xBuilder->weld_widget("cropframe")) , m_xZoomConstRB(m_xBuilder->weld_radio_button("keepscale")) , m_xSizeConstRB(m_xBuilder->weld_radio_button("keepsize")) @@ -287,6 +288,11 @@ void SvxGrfCropPage::ActivatePage(const SfxItemSet& rSet) DBG_ASSERT( pPool, "Where is the pool?" ); #endif + if (!GetUserData().isEmpty()) + { + m_aPreferredDPI = GetUserData().toInt32(); + } + bSetOrigSize = false; // Size @@ -670,13 +676,27 @@ void SvxGrfCropPage::GraphicHasChanged( bool bFound ) Size SvxGrfCropPage::GetGrfOrigSize(const Graphic& rGrf) { - const MapMode aMapTwip( MapUnit::MapTwip ); - Size aSize( rGrf.GetPrefSize() ); - if( MapUnit::MapPixel == rGrf.GetPrefMapMode().GetMapUnit() ) - aSize = Application::GetDefaultDevice()->PixelToLogic(aSize, aMapTwip); + Size aSize; + + if (m_aPreferredDPI > 0) + { + Size aPixelSize = rGrf.GetSizePixel(); + double fWidth = aPixelSize.Width() / double(m_aPreferredDPI); + double fHeight = aPixelSize.Height() / double(m_aPreferredDPI); + fWidth = o3tl::convert(fWidth, o3tl::Length::in, o3tl::Length::twip); + fHeight = o3tl::convert(fHeight, o3tl::Length::in, o3tl::Length::twip); + aSize = Size(fWidth, fHeight); + } else - aSize = OutputDevice::LogicToLogic( aSize, - rGrf.GetPrefMapMode(), aMapTwip ); + { + const MapMode aMapTwip( MapUnit::MapTwip ); + aSize = rGrf.GetPrefSize(); + if( MapUnit::MapPixel == rGrf.GetPrefMapMode().GetMapUnit() ) + aSize = Application::GetDefaultDevice()->PixelToLogic(aSize, aMapTwip); + else + aSize = OutputDevice::LogicToLogic( aSize, + rGrf.GetPrefMapMode(), aMapTwip ); + } return aSize; } diff --git a/include/svx/svdmodel.hxx b/include/svx/svdmodel.hxx index ab9578a7bc93..831201de4d60 100644 --- a/include/svx/svdmodel.hxx +++ b/include/svx/svdmodel.hxx @@ -609,6 +609,8 @@ public: bool DoesMakePageObjectsNamesUnique() const { return mbMakePageObjectsNamesUnique; } void DoMakePageObjectsNamesUnique(bool bDo) { mbMakePageObjectsNamesUnique = bDo; } + virtual sal_Int32 getImagePreferredDPI() const { return 0; } + virtual void dumpAsXml(xmlTextWriterPtr pWriter) const; }; diff --git a/sd/inc/drawdoc.hxx b/sd/inc/drawdoc.hxx index aaed07cae960..a99c27c49bd1 100644 --- a/sd/inc/drawdoc.hxx +++ b/sd/inc/drawdoc.hxx @@ -616,7 +616,7 @@ public: SAL_DLLPRIVATE void SetEmbedFontScriptAsian(bool bUse) { mbEmbedFontScriptAsian = bUse; } SAL_DLLPRIVATE void SetEmbedFontScriptComplex(bool bUse) { mbEmbedFontScriptComplex = bUse; } - sal_Int32 getImagePreferredDPI() { return mnImagePreferredDPI; } + sal_Int32 getImagePreferredDPI() const override { return mnImagePreferredDPI; } void setImagePreferredDPI(sal_Int32 nValue) { mnImagePreferredDPI = nValue; } void dumpAsXml(xmlTextWriterPtr pWriter) const override; diff --git a/svx/source/tbxctrls/grafctrl.cxx b/svx/source/tbxctrls/grafctrl.cxx index 7f644be79052..0d1913fb4780 100644 --- a/svx/source/tbxctrls/grafctrl.cxx +++ b/svx/source/tbxctrls/grafctrl.cxx @@ -654,6 +654,8 @@ void SvxGrafAttrHelper::ExecuteGrafAttr( SfxRequest& rReq, SdrView& rView ) SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create(); ::CreateTabPage fnCreatePage = pFact->GetTabPageCreatorFunc( RID_SVXPAGE_GRFCROP ); std::unique_ptr<SfxTabPage> xTabPage = (*fnCreatePage)(aCropDialog.get_content_area(), &aCropDialog, &aCropDlgAttr); + OUString sPreferredDPI = OUString::number(rView.getSdrModelFromSdrView().getImagePreferredDPI()); + xTabPage->SetUserData(sPreferredDPI); xTabPage->SetPageTitle(aCropStr); aCropDialog.SetTabPage(std::move(xTabPage)); diff --git a/sw/source/ui/frmdlg/frmdlg.cxx b/sw/source/ui/frmdlg/frmdlg.cxx index ffb5a8ed76c9..fbb27c7d5f94 100644 --- a/sw/source/ui/frmdlg/frmdlg.cxx +++ b/sw/source/ui/frmdlg/frmdlg.cxx @@ -31,6 +31,7 @@ #include <wrap.hxx> #include <column.hxx> #include <macassgn.hxx> +#include <IDocumentSettingAccess.hxx> #include <strings.hrc> #include <svl/eitem.hxx> @@ -189,6 +190,12 @@ void SwFrameDlg::PageCreated(const OString& rId, SfxTabPage &rPage) { rPage.PageCreated(m_rSet); } + else if (rId == "crop") + { + sal_Int32 nDPI = m_pWrtShell->GetDoc()->getIDocumentSettingAccess().getImagePreferredDPI(); + if (nDPI) + rPage.SetUserData(OUString::number(nDPI)); + } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ commit 046e6cfa544d2ffd67fd29ba7dde41b495744618 Author: Tomaž Vajngerl <[email protected]> AuthorDate: Tue Dec 7 23:25:54 2021 +0100 Commit: Tomaž Vajngerl <[email protected]> CommitDate: Mon Dec 20 06:21:34 2021 +0100 Add graphic size checker for the preferred document DPI This change adds a graphic size checker, which checks all the images in the document, if they largely differ (outside of 50% and 110% of the image size) from the set preferred image DPI document setting. For all images that don't fall under this bounds, list them in the dialog and offer the posibility to select/goto the image and pop-up the properties dialog for the image to change its size. Change-Id: I06efce77c291fdb6ec3864d72c2f4d15dba9c42b Reviewed-on: https://gerrit.libreoffice.org/c/core/+/127094 Tested-by: Jenkins Reviewed-by: Tomaž Vajngerl <[email protected]> diff --git a/include/sfx2/sfxsids.hrc b/include/sfx2/sfxsids.hrc index d9a8b14eb514..e4bf9bbbe71b 100644 --- a/include/sfx2/sfxsids.hrc +++ b/include/sfx2/sfxsids.hrc @@ -447,6 +447,7 @@ class SvxSearchItem; // Used for redaction #define SID_SHAPE_NAME (SID_SFX_START + 808) // FREE: SID_SFX_START + 809 +#define SID_GRAPHIC_SIZE_CHECK (SID_SFX_START + 809) #define SID_ACCESSIBILITY_CHECK (SID_SFX_START + 810) #define SID_ASYNCHRON (SID_SFX_START + 811) diff --git a/include/svx/GenericCheckDialog.hxx b/include/svx/GenericCheckDialog.hxx new file mode 100644 index 000000000000..ef2a41159737 --- /dev/null +++ b/include/svx/GenericCheckDialog.hxx @@ -0,0 +1,83 @@ +/* -*- 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/. + * + */ + +#pragma once + +#include <svx/svxdllapi.h> +#include <tools/link.hxx> +#include <vcl/weld.hxx> + +namespace svx +{ +class CheckData +{ +public: + virtual ~CheckData() {} + + virtual OUString getText() = 0; + + virtual bool canMarkObject() = 0; + virtual void markObject() = 0; + + virtual bool hasProperties() = 0; + virtual void runProperties() = 0; +}; + +class CheckDataCollection +{ +protected: + std::vector<std::unique_ptr<CheckData>> m_aCollection; + +public: + virtual ~CheckDataCollection() {} + + std::vector<std::unique_ptr<CheckData>>& getCollection() { return m_aCollection; } + + virtual OUString getTitle() = 0; +}; + +class GenericCheckEntry final +{ +private: + std::unique_ptr<weld::Builder> m_xBuilder; + std::unique_ptr<weld::Container> m_xContainer; + std::unique_ptr<weld::Label> m_xLabel; + std::unique_ptr<weld::Button> m_xMarkButton; + std::unique_ptr<weld::Button> m_xPropertiesButton; + + std::unique_ptr<CheckData>& m_pCheckData; + +public: + GenericCheckEntry(weld::Container* pParent, std::unique_ptr<CheckData>& rCheckData); + + weld::Widget* get_widget() const { return m_xContainer.get(); } + + DECL_LINK(MarkButtonClicked, weld::Button&, void); + DECL_LINK(PropertiesButtonClicked, weld::Button&, void); +}; + +class SVX_DLLPUBLIC GenericCheckDialog final : public weld::GenericDialogController +{ +private: + std::vector<std::unique_ptr<GenericCheckEntry>> m_aCheckEntries; + CheckDataCollection& m_rCheckDataCollection; + + // Controls + std::unique_ptr<weld::Box> m_xCheckBox; + +public: + GenericCheckDialog(weld::Window* pParent, CheckDataCollection& rCheckDataCollection); + virtual ~GenericCheckDialog() override; + virtual short run() override; +}; + +} // end svx namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/svx/strings.hrc b/include/svx/strings.hrc index 2e00e3c4c1a7..49c170b0a4bb 100644 --- a/include/svx/strings.hrc +++ b/include/svx/strings.hrc @@ -1816,6 +1816,13 @@ #define RID_SVXSTR_HOR_PRESET_ONLYHOR NC_("RID_SVXSTR_HOR_PRESET_ONLYHOR", "Top and Bottom Borders, and All Inner Lines") #define RID_SVXSTR_VER_PRESET_ONLYVER NC_("RID_SVXSTR_VER_PRESET_ONLYVER", "Left and Right Borders, and All Inner Lines") +/*-------------------------------------------------------------------- + Description: GraphicSizeCheck strings + --------------------------------------------------------------------*/ +#define STR_GRAPHIC_SIZE_CHECK_DIALOG_TITLE NC_("STR_GRAPHIC_SIZE_CHECK_DIALOG_TITLE", "Graphic Size Check") +#define STR_WARNING_GRAPHIC_PIXEL_COUNT_LOW NC_("STR_WARNING_GRAPHIC_PIXEL_COUNT_LOW", "Image '%NAME%' has too few pixels for the current size (%DPIX% x %DPIY% DPI)") +#define STR_WARNING_GRAPHIC_PIXEL_COUNT_HIGH NC_("STR_WARNING_GRAPHIC_PIXEL_COUNT_HIGH", "Image '%NAME%' has too many pixels for the current size (%DPIX% x %DPIY% DPI)") + #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/officecfg/registry/data/org/openoffice/Office/UI/GenericCommands.xcu b/officecfg/registry/data/org/openoffice/Office/UI/GenericCommands.xcu index 2e3bf1f57647..a51ab13d077c 100644 --- a/officecfg/registry/data/org/openoffice/Office/UI/GenericCommands.xcu +++ b/officecfg/registry/data/org/openoffice/Office/UI/GenericCommands.xcu @@ -7389,6 +7389,14 @@ bit 3 (0x8): #define UICOMMANDDESCRIPTION_PROPERTIES_TOGGLEBUTTON 8 <value>1</value> </prop> </node> + <node oor:name=".uno:GraphicSizeCheck" oor:op="replace"> + <prop oor:name="Label" oor:type="xs:string"> + <value xml:lang="en-US">Graphic Size Check...</value> + </prop> + <prop oor:name="Properties" oor:type="xs:int"> + <value>1</value> + </prop> + </node> <node oor:name=".uno:SidebarDeck.PropertyDeck" oor:op="replace"> <prop oor:name="Label" oor:type="xs:string"> <value xml:lang="en-US">Open the Properties Deck</value> diff --git a/sd/Library_sd.mk b/sd/Library_sd.mk index f8e77848e4d3..da11d900f564 100644 --- a/sd/Library_sd.mk +++ b/sd/Library_sd.mk @@ -401,6 +401,7 @@ $(eval $(call gb_Library_add_exception_objects,sd,\ sd/source/ui/tools/AsynchronousCall \ sd/source/ui/tools/ConfigurationAccess \ sd/source/ui/tools/EventMultiplexer \ + sd/source/ui/tools/GraphicSizeCheck \ sd/source/ui/tools/IconCache \ sd/source/ui/tools/IdleDetection \ sd/source/ui/tools/PreviewRenderer \ diff --git a/sd/sdi/_drvwsh.sdi b/sd/sdi/_drvwsh.sdi index 7060d8dd6434..73c2181d0743 100644 --- a/sd/sdi/_drvwsh.sdi +++ b/sd/sdi/_drvwsh.sdi @@ -76,6 +76,11 @@ interface DrawView ExecMethod = FuTemporary ; StateMethod = GetMenuState ; ] + SID_GRAPHIC_SIZE_CHECK + [ + ExecMethod = FuTemporary ; + StateMethod = GetMenuState ; + ] SID_EXTERNAL_EDIT [ ExecMethod = FuTemporary ; diff --git a/sd/source/ui/inc/tools/GraphicSizeCheck.hxx b/sd/source/ui/inc/tools/GraphicSizeCheck.hxx new file mode 100644 index 000000000000..9da3d569bd3a --- /dev/null +++ b/sd/source/ui/inc/tools/GraphicSizeCheck.hxx @@ -0,0 +1,103 @@ +/* -*- 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/. + * + */ + +#pragma once + +#include <memory> +#include <drawdoc.hxx> +#include <svx/GenericCheckDialog.hxx> +#include <svx/svdograf.hxx> + +namespace sd +{ +class GraphicSizeViolation final +{ +private: + SdrGrafObj* m_pGraphicObject; + + sal_Int32 m_nLowDPILimit = 0; + sal_Int32 m_nHighDPILimit = 0; + + sal_Int32 m_nDPIX = 0; + sal_Int32 m_nDPIY = 0; + +public: + GraphicSizeViolation(sal_Int32 nDPI, SdrGrafObj* pGraphicObject); + bool check(); + + OUString getGraphicName(); + + SdrGrafObj* getObject() const { return m_pGraphicObject; } + + bool isDPITooLow() { return m_nDPIX < m_nLowDPILimit || m_nDPIY < m_nLowDPILimit; } + + bool isDPITooHigh() { return m_nDPIX > m_nHighDPILimit || m_nDPIY > m_nHighDPILimit; } + + sal_Int32 getDPIX() { return m_nDPIX; } + + sal_Int32 getDPIY() { return m_nDPIY; } +}; + +class GraphicSizeCheck final +{ +private: + SdDrawDocument* m_pDocument; + std::vector<std::unique_ptr<GraphicSizeViolation>> m_aGraphicSizeViolationList; + +public: + GraphicSizeCheck(SdDrawDocument* pDocument) + : m_pDocument(pDocument) + { + } + + void check(); + + std::vector<std::unique_ptr<GraphicSizeViolation>>& getViolationList() + { + return m_aGraphicSizeViolationList; + } +}; + +class GraphicSizeCheckGUIEntry : public svx::CheckData +{ +private: + SdDrawDocument* m_pDocument; + std::unique_ptr<GraphicSizeViolation> m_pViolation; + +public: + GraphicSizeCheckGUIEntry(SdDrawDocument* pDocument, + std::unique_ptr<GraphicSizeViolation>&& pViolation) + : m_pDocument(pDocument) + , m_pViolation(std::move(pViolation)) + { + } + + OUString getText() override; + + bool canMarkObject() override { return true; } + + void markObject() override; + + bool hasProperties() override { return true; } + + void runProperties() override; +}; + +class GraphicSizeCheckGUIResult : public svx::CheckDataCollection +{ +public: + GraphicSizeCheckGUIResult(SdDrawDocument* m_pDocument); + + OUString getTitle() override; +}; + +} // end of namespace sd + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/tools/GraphicSizeCheck.cxx b/sd/source/ui/tools/GraphicSizeCheck.cxx new file mode 100644 index 000000000000..14bfcf3353b9 --- /dev/null +++ b/sd/source/ui/tools/GraphicSizeCheck.cxx @@ -0,0 +1,213 @@ +/* -*- 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/. + * + */ + +#include <memory> +#include <tools/GraphicSizeCheck.hxx> +#include <svx/strings.hrc> +#include <svx/svdobj.hxx> +#include <svx/svdpage.hxx> +#include <svx/svxids.hrc> +#include <sfx2/dispatch.hxx> + +#include <sdresid.hxx> +#include <DrawViewShell.hxx> +#include <DrawDocShell.hxx> + +namespace sd +{ +namespace +{ +class ModelTraverseHandler +{ +public: + virtual ~ModelTraverseHandler() {} + + virtual void handleSdrObject(SdrObject* pObject) = 0; +}; + +class ModelTraverser +{ +private: + std::vector<std::shared_ptr<ModelTraverseHandler>> m_pNodeHandler; + SdDrawDocument* m_pDocument; + +public: + ModelTraverser(SdDrawDocument* pDocument) + : m_pDocument(pDocument) + { + } + + void traverse() + { + if (!m_pDocument) + return; + + for (sal_uInt16 nPage = 0; nPage < m_pDocument->GetPageCount(); ++nPage) + { + SdrPage* pPage = m_pDocument->GetPage(nPage); + if (pPage) + { + for (size_t nObject = 0; nObject < pPage->GetObjCount(); ++nObject) + { + SdrObject* pObject = pPage->GetObj(nObject); + if (pObject) + { + for (auto& pNodeHandler : m_pNodeHandler) + { + pNodeHandler->handleSdrObject(pObject); + } + } + } + } + } + } + + void addNodeHandler(std::shared_ptr<ModelTraverseHandler> pHandler) + { + m_pNodeHandler.push_back(pHandler); + } +}; +} + +GraphicSizeViolation::GraphicSizeViolation(sal_Int32 nDPI, SdrGrafObj* pGraphicObject) + : m_pGraphicObject(pGraphicObject) +{ + constexpr double fLowPercentage = 110; + constexpr double fHighPercentage = 50; + + m_nLowDPILimit = sal_Int32(100.0 / fLowPercentage * nDPI); + m_nHighDPILimit = sal_Int32(100.0 / fHighPercentage * nDPI); +} + +bool GraphicSizeViolation::check() +{ + Graphic aGraphic = m_pGraphicObject->GetGraphic(); + Size aSizePixel = aGraphic.GetSizePixel(); + Size aGraphicSize = m_pGraphicObject->GetLogicRect().GetSize(); + + double nSizeXInch + = o3tl::convert(double(aGraphicSize.Width()), o3tl::Length::mm100, o3tl::Length::in); + double nSizeYInch + = o3tl::convert(double(aGraphicSize.Height()), o3tl::Length::mm100, o3tl::Length::in); + + m_nDPIX = sal_Int32(aSizePixel.Width() / nSizeXInch); + m_nDPIY = sal_Int32(aSizePixel.Height() / nSizeYInch); + + return isDPITooLow() || isDPITooHigh(); +} + +OUString GraphicSizeViolation::getGraphicName() { return m_pGraphicObject->GetName(); } + +namespace +{ +class GraphicSizeCheckHandler : public ModelTraverseHandler +{ + sal_Int32 m_nDPI; + std::vector<std::unique_ptr<GraphicSizeViolation>>& m_rGraphicSizeViolationList; + +public: + GraphicSizeCheckHandler( + sal_Int32 nDPI, + std::vector<std::unique_ptr<GraphicSizeViolation>>& rGraphicSizeViolationList) + : m_nDPI(nDPI) + , m_rGraphicSizeViolationList(rGraphicSizeViolationList) + { + } + + void handleSdrObject(SdrObject* pObject) override + { + auto* pGraphicObject = dynamic_cast<SdrGrafObj*>(pObject); + if (!pGraphicObject) + return; + + auto pEntry = std::make_unique<GraphicSizeViolation>(m_nDPI, pGraphicObject); + if (pEntry->check()) + { + m_rGraphicSizeViolationList.push_back(std::move(pEntry)); + } + } +}; + +} // end anonymous namespace + +void GraphicSizeCheck::check() +{ + if (!m_pDocument) + return; + + sal_Int32 nDPI = m_pDocument->getImagePreferredDPI(); + if (nDPI == 0) + return; + + auto pHandler = std::make_shared<GraphicSizeCheckHandler>(nDPI, m_aGraphicSizeViolationList); + + ModelTraverser aModelTraverser(m_pDocument); + aModelTraverser.addNodeHandler(pHandler); + aModelTraverser.traverse(); +} + +OUString GraphicSizeCheckGUIEntry::getText() +{ + OUString sText; + + if (m_pViolation->isDPITooLow()) + { + sText = SdResId(STR_WARNING_GRAPHIC_PIXEL_COUNT_LOW); + } + else if (m_pViolation->isDPITooHigh()) + { + sText = SdResId(STR_WARNING_GRAPHIC_PIXEL_COUNT_HIGH); + } + + sText = sText.replaceAll("%NAME%", m_pViolation->getGraphicName()); + sText = sText.replaceAll("%DPIX%", OUString::number(m_pViolation->getDPIX())); + sText = sText.replaceAll("%DPIY%", OUString::number(m_pViolation->getDPIY())); + + return sText; +} + +void GraphicSizeCheckGUIEntry::markObject() +{ + sd::ViewShell* pViewShell = m_pDocument->GetDocSh()->GetViewShell(); + SdrView* pView = pViewShell->GetView(); + pView->ShowSdrPage(m_pViolation->getObject()->getSdrPageFromSdrObject()); + pView->UnmarkAll(); + pView->MarkObj(m_pViolation->getObject(), pView->GetSdrPageView()); +} + +void GraphicSizeCheckGUIEntry::runProperties() +{ + markObject(); + sd::ViewShell* pViewShell = m_pDocument->GetDocSh()->GetViewShell(); + pViewShell->GetDispatcher()->Execute(SID_ATTR_GRAF_CROP, SfxCallMode::SYNCHRON); +} + +GraphicSizeCheckGUIResult::GraphicSizeCheckGUIResult(SdDrawDocument* pDocument) +{ + GraphicSizeCheck aCheck(pDocument); + aCheck.check(); + + auto& rCollection = getCollection(); + for (auto& rpViolation : aCheck.getViolationList()) + { + auto rGUIEntry + = std::make_unique<GraphicSizeCheckGUIEntry>(pDocument, std::move(rpViolation)); + rCollection.push_back(std::move(rGUIEntry)); + } +} + +OUString GraphicSizeCheckGUIResult::getTitle() +{ + return SdResId(STR_GRAPHIC_SIZE_CHECK_DIALOG_TITLE); +} + +} // end of namespace sd + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/view/drviews2.cxx b/sd/source/ui/view/drviews2.cxx index b951231f2c5b..87d1a34e2ebe 100644 --- a/sd/source/ui/view/drviews2.cxx +++ b/sd/source/ui/view/drviews2.cxx @@ -183,6 +183,7 @@ #include <SlideSorterViewShell.hxx> #include <controller/SlideSorterController.hxx> #include <controller/SlsPageSelector.hxx> +#include <tools/GraphicSizeCheck.hxx> #include <ViewShellBase.hxx> #include <memory> @@ -1462,6 +1463,17 @@ void DrawViewShell::FuTemporary(SfxRequest& rReq) } break; + case SID_GRAPHIC_SIZE_CHECK: + { + sd::GraphicSizeCheckGUIResult aResult(GetDoc()); + svx::GenericCheckDialog aDialog(GetFrameWeld(), aResult); + aDialog.run(); + + Cancel(); + rReq.Ignore(); + } + break; + case SID_ATTRIBUTES_LINE: // BASIC { SetCurrentFunction( FuLine::Create( this, GetActiveWindow(), mpDrawView.get(), GetDoc(), rReq ) ); diff --git a/sd/source/ui/view/drviewsj.cxx b/sd/source/ui/view/drviewsj.cxx index 9eebdbc57c29..6bbf88338f06 100644 --- a/sd/source/ui/view/drviewsj.cxx +++ b/sd/source/ui/view/drviewsj.cxx @@ -539,6 +539,10 @@ void DrawViewShell::GetMenuStateSel( SfxItemSet &rSet ) rSet.DisableItem(SID_SAVE_GRAPHIC); rSet.DisableItem(SID_EXTERNAL_EDIT); } + if (GetDoc()->getImagePreferredDPI() <= 0) + { + rSet.DisableItem(SID_GRAPHIC_SIZE_CHECK); + } } } // end of namespace sd diff --git a/sd/uiconfig/sdraw/menubar/menubar.xml b/sd/uiconfig/sdraw/menubar/menubar.xml index fd327d6bc91b..9c5a997bcc5a 100644 --- a/sd/uiconfig/sdraw/menubar/menubar.xml +++ b/sd/uiconfig/sdraw/menubar/menubar.xml @@ -417,6 +417,7 @@ <menu:menuitem menu:id=".uno:ColorSettings"/> <menu:menuseparator/> <menu:menuitem menu:id=".uno:GrafAttrCrop"/> + <menu:menuitem menu:id=".uno:GraphicSizeCheck"/> </menu:menupopup> </menu:menu> <menu:menuseparator/> diff --git a/sd/uiconfig/simpress/menubar/menubar.xml b/sd/uiconfig/simpress/menubar/menubar.xml index fc64d6050e6e..855a26991a0b 100644 --- a/sd/uiconfig/simpress/menubar/menubar.xml +++ b/sd/uiconfig/simpress/menubar/menubar.xml @@ -448,6 +448,7 @@ <menu:menuitem menu:id=".uno:ColorSettings"/> <menu:menuseparator/> <menu:menuitem menu:id=".uno:GrafAttrCrop"/> + <menu:menuitem menu:id=".uno:GraphicSizeCheck"/> </menu:menupopup> </menu:menu> <menu:menu menu:id=".uno:FormatObjectMenu"> diff --git a/svx/Library_svx.mk b/svx/Library_svx.mk index efb5a6e1b031..a13f1cade697 100644 --- a/svx/Library_svx.mk +++ b/svx/Library_svx.mk @@ -105,6 +105,7 @@ $(eval $(call gb_Library_add_exception_objects,svx,\ svx/source/customshapes/EnhancedCustomShapeFontWork \ svx/source/customshapes/EnhancedCustomShapeHandle \ svx/source/dialog/AccessibilityCheckDialog \ + svx/source/dialog/GenericCheckDialog \ svx/source/dialog/_bmpmask \ svx/source/dialog/charmap \ svx/source/dialog/searchcharmap \ diff --git a/svx/UIConfig_svx.mk b/svx/UIConfig_svx.mk index 2186185f10c2..33bc1797f20f 100644 --- a/svx/UIConfig_svx.mk +++ b/svx/UIConfig_svx.mk @@ -78,6 +78,8 @@ $(eval $(call gb_UIConfig_add_uifiles,svx,\ svx/uiconfig/ui/functionmenu \ svx/uiconfig/ui/gallerymenu1 \ svx/uiconfig/ui/gallerymenu2 \ + svx/uiconfig/ui/genericcheckdialog \ + svx/uiconfig/ui/genericcheckentry \ svx/uiconfig/ui/grafctrlbox \ svx/uiconfig/ui/grafmodebox \ svx/uiconfig/ui/headfootformatpage \ diff --git a/svx/sdi/svx.sdi b/svx/sdi/svx.sdi index 1e08145d3644..f0314fe63360 100644 --- a/svx/sdi/svx.sdi +++ b/svx/sdi/svx.sdi @@ -12425,6 +12425,23 @@ SfxVoidItem SpellCheckApplySuggestion SID_SPELLCHECK_APPLY_SUGGESTION GroupId = SfxGroupId::Format; ] +SfxVoidItem GraphicSizeCheck SID_GRAPHIC_SIZE_CHECK +() +[ + AutoUpdate = FALSE, + FastCall = FALSE, + ReadOnlyDoc = TRUE, + Toggle = FALSE, + Container = FALSE, + RecordAbsolute = FALSE, + RecordPerSet; + + AccelConfig = FALSE, + MenuConfig = FALSE, + ToolBoxConfig = FALSE, + GroupId = SfxGroupId::Modify; +] + SfxVoidItem AccessibilityCheck SID_ACCESSIBILITY_CHECK () [ diff --git a/svx/source/dialog/GenericCheckDialog.cxx b/svx/source/dialog/GenericCheckDialog.cxx new file mode 100644 index 000000000000..09fc3d678769 --- /dev/null +++ b/svx/source/dialog/GenericCheckDialog.cxx @@ -0,0 +1,70 @@ +/* -*- 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/. + * + */ + +#include <svx/GenericCheckDialog.hxx> +#include <vcl/svapp.hxx> + +namespace svx +{ +GenericCheckEntry::GenericCheckEntry(weld::Container* pParent, + std::unique_ptr<CheckData>& pCheckData) + : m_xBuilder(Application::CreateBuilder(pParent, "svx/ui/genericcheckentry.ui")) + , m_xContainer(m_xBuilder->weld_container("checkEntryBox")) + , m_xLabel(m_xBuilder->weld_label("label")) + , m_xMarkButton(m_xBuilder->weld_button("markButton")) + , m_xPropertiesButton(m_xBuilder->weld_button("propertiesButton")) + , m_pCheckData(pCheckData) +{ + m_xLabel->set_label(m_pCheckData->getText()); + m_xMarkButton->set_visible(m_pCheckData->canMarkObject()); + m_xMarkButton->connect_clicked(LINK(this, GenericCheckEntry, MarkButtonClicked)); + m_xPropertiesButton->set_visible(m_pCheckData->hasProperties()); + m_xPropertiesButton->connect_clicked(LINK(this, GenericCheckEntry, PropertiesButtonClicked)); + + m_xContainer->show(); +} + +IMPL_LINK_NOARG(GenericCheckEntry, MarkButtonClicked, weld::Button&, void) +{ + m_pCheckData->markObject(); +} + +IMPL_LINK_NOARG(GenericCheckEntry, PropertiesButtonClicked, weld::Button&, void) +{ + m_pCheckData->runProperties(); +} + +GenericCheckDialog::GenericCheckDialog(weld::Window* pParent, + CheckDataCollection& rCheckDataCollection) + : GenericDialogController(pParent, "svx/ui/genericcheckdialog.ui", "GenericCheckDialog") + , m_rCheckDataCollection(rCheckDataCollection) + , m_xCheckBox(m_xBuilder->weld_box("checkBox")) +{ + set_title(m_rCheckDataCollection.getTitle()); +} + +GenericCheckDialog::~GenericCheckDialog() {} + +short GenericCheckDialog::run() +{ + sal_Int32 i = 0; + + for (std::unique_ptr<CheckData>& pCheckData : m_rCheckDataCollection.getCollection()) + { + auto xEntry = std::make_unique<GenericCheckEntry>(m_xCheckBox.get(), pCheckData); + m_xCheckBox->reorder_child(xEntry->get_widget(), i++); + m_aCheckEntries.push_back(std::move(xEntry)); + } + return GenericDialogController::run(); +} + +} // end svx namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/uiconfig/ui/genericcheckdialog.ui b/svx/uiconfig/ui/genericcheckdialog.ui new file mode 100644 index 000000000000..232221c0a878 --- /dev/null +++ b/svx/uiconfig/ui/genericcheckdialog.ui @@ -0,0 +1,132 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Generated with glade 3.38.2 --> +<interface domain="svx"> + <requires lib="gtk+" version="3.20"/> + <object class="GtkDialog" id="GenericCheckDialog"> + <property name="width-request">850</property> + <property name="height-request">480</property> + <property name="can-focus">False</property> + <property name="hexpand">True</property> + <property name="vexpand">True</property> + <property name="border-width">6</property> + <property name="modal">True</property> + <property name="type-hint">dialog</property> + <child internal-child="vbox"> + <object class="GtkBox" id="dialogBox1"> + <property name="can-focus">False</property> + <property name="hexpand">True</property> + <property name="vexpand">True</property> + <property name="orientation">vertical</property> + <property name="spacing">12</property> + <child internal-child="action_area"> + <object class="GtkButtonBox" id="dialogButtons"> + <property name="can-focus">False</property> + <property name="layout-style">end</property> + <child> + <object class="GtkButton" id="ok"> + <property name="label" translatable="yes" context="stock">_OK</property> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="can-default">True</property> + <property name="has-default">True</property> + <property name="receives-default">True</property> + <property name="use-underline">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkButton" id="cancel"> + <property name="label" translatable="yes" context="stock">_Cancel</property> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="receives-default">True</property> + <property name="use-underline">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkButton" id="help"> + <property name="label" translatable="yes" context="stock">_Help</property> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="receives-default">True</property> + <property name="use-underline">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">2</property> + <property name="secondary">True</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="pack-type">end</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="hexpand">True</property> + <property name="vexpand">True</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkScrolledWindow"> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="hexpand">True</property> + <property name="vexpand">True</property> + <property name="shadow-type">in</property> + <child> + <object class="GtkViewport"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="hexpand">True</property> + <property name="vexpand">True</property> + <child> + <object class="GtkBox" id="checkBox"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="orientation">vertical</property> + <child> + <placeholder/> + </child> + </object> + </child> + </object> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + </child> + <action-widgets> + <action-widget response="-5">ok</action-widget> + <action-widget response="-6">cancel</action-widget> + <action-widget response="-11">help</action-widget> + </action-widgets> + </object> +</interface> diff --git a/svx/uiconfig/ui/genericcheckentry.ui b/svx/uiconfig/ui/genericcheckentry.ui new file mode 100644 index 000000000000..1b02ca13eeac --- /dev/null +++ b/svx/uiconfig/ui/genericcheckentry.ui @@ -0,0 +1,56 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Generated with glade 3.38.2 --> +<interface domain="svx"> + <requires lib="gtk+" version="3.20"/> + <object class="GtkBox" id="checkEntryBox"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="border-width">3</property> + <property name="spacing">6</property> + <child> + <object class="GtkLabel" id="label"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="hexpand">True</property> + <property name="selectable">True</property> + <property name="xalign">0</property> + <child internal-child="accessible"> + <object class="AtkObject" id="label-atkobject"> + <property name="AtkObject::accessible-role">static</property> + </object> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkButton" id="markButton"> + <property name="label" translatable="yes" context="genericcheckentry|markButton">Mark</property> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="receives-default">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkButton" id="propertiesButton"> + <property name="label" translatable="yes" context="genericcheckentry|propertiesButton">Properties</property> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="receives-default">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">2</property> + </packing> + </child> + </object> +</interface> diff --git a/sw/Library_sw.mk b/sw/Library_sw.mk index 6989bce49cea..58639859bb0e 100644 --- a/sw/Library_sw.mk +++ b/sw/Library_sw.mk @@ -312,6 +312,7 @@ $(eval $(call gb_Library_add_exception_objects,sw,\ sw/source/core/frmedt/tblsel \ sw/source/core/graphic/grfatr \ sw/source/core/graphic/ndgrf \ + sw/source/core/graphic/GraphicSizeCheck \ sw/source/core/layout/anchoreddrawobject \ sw/source/core/layout/anchoredobject \ sw/source/core/layout/atrfrm \ diff --git a/sw/sdi/_basesh.sdi b/sw/sdi/_basesh.sdi index 44d6c5338e18..dd195496d1a8 100644 --- a/sw/sdi/_basesh.sdi +++ b/sw/sdi/_basesh.sdi @@ -605,4 +605,11 @@ interface BaseTextSelection ExecMethod = ExecDlg; DisableFlags="SfxDisableFlags::SwOnProtectedCursor"; ] + + SID_GRAPHIC_SIZE_CHECK + [ + ExecMethod = ExecDlg; + StateMethod = GetState; + DisableFlags="SfxDisableFlags::SwOnProtectedCursor"; + ] } diff --git a/sw/source/core/graphic/GraphicSizeCheck.cxx b/sw/source/core/graphic/GraphicSizeCheck.cxx new file mode 100644 index 000000000000..50b1cb70a8f2 --- /dev/null +++ b/sw/source/core/graphic/GraphicSizeCheck.cxx @@ -0,0 +1,164 @@ +/* -*- 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/. + * + */ + +#include <GraphicSizeCheck.hxx> +#include <svx/strings.hrc> +#include <svx/svdobj.hxx> +#include <unotools/viewoptions.hxx> +#include <sfx2/viewfrm.hxx> +#include <sfx2/dispatch.hxx> + +#include <ModelTraverser.hxx> +#include <ndgrf.hxx> +#include <IDocumentSettingAccess.hxx> +#include <fmtfsize.hxx> +#include <wrtsh.hxx> +#include <wview.hxx> +#include <cmdid.h> + +using namespace css; + +namespace sw +{ +GraphicSizeViolation::GraphicSizeViolation(sal_Int32 nDPI, const SwGrfNode* pGraphicNode) + : m_pGraphicNode(pGraphicNode) +{ + constexpr double fLowPercentage = 110; + constexpr double fHighPercentage = 50; + + m_nLowDPILimit = sal_Int32(100.0 / fLowPercentage * nDPI); + m_nHighDPILimit = sal_Int32(100.0 / fHighPercentage * nDPI); +} + +bool GraphicSizeViolation::check() +{ + auto pFrameFormat = m_pGraphicNode->GetFlyFormat(); + Graphic aGraphic = m_pGraphicNode->GetGraphic(); + Size aSizePixel = aGraphic.GetSizePixel(); + Size aFrameSize(pFrameFormat->GetFrameSize().GetSize()); + + double nSizeXInch + = o3tl::convert(double(aFrameSize.Width()), o3tl::Length::twip, o3tl::Length::in); + double nSizeYInch + = o3tl::convert(double(aFrameSize.Height()), o3tl::Length::twip, o3tl::Length::in); + + m_nDPIX = sal_Int32(aSizePixel.Width() / nSizeXInch); + m_nDPIY = sal_Int32(aSizePixel.Height() / nSizeYInch); + + return isDPITooLow() || isDPITooHigh(); +} + +OUString GraphicSizeViolation::getGraphicName() +{ + return m_pGraphicNode->GetFlyFormat()->GetName(); +} + +namespace +{ +class GraphicSizeCheckHandler : public ModelTraverseHandler +{ +private: + sal_Int32 m_nDPI; + std::vector<std::unique_ptr<GraphicSizeViolation>>& m_rGraphicSizeViolationList; + +public: + GraphicSizeCheckHandler( + sal_Int32 nDPI, + std::vector<std::unique_ptr<GraphicSizeViolation>>& rGraphicSizeViolationList) + : m_nDPI(nDPI) + , m_rGraphicSizeViolationList(rGraphicSizeViolationList) + { + } + + void handleNode(SwNode* pNode) override + { + if (!pNode->IsGrfNode()) + return; + + auto pEntry = std::make_unique<GraphicSizeViolation>(m_nDPI, pNode->GetGrfNode()); + if (pEntry->check()) + { + m_rGraphicSizeViolationList.push_back(std::move(pEntry)); + } + } + + void handleSdrObject(SdrObject* /*pObject*/) override {} +}; + +} // end anonymous namespace + +void GraphicSizeCheck::check() +{ + sal_Int32 nDPI = m_pDocument->getIDocumentSettingAccess().getImagePreferredDPI(); + if (nDPI == 0) + return; + + auto pHandler = std::make_shared<GraphicSizeCheckHandler>(nDPI, m_aGraphicSizeViolationList); + ModelTraverser aModelTraverser(m_pDocument); + aModelTraverser.addNodeHandler(pHandler); + aModelTraverser.traverse(); +} + +OUString GraphicSizeCheckGUIEntry::getText() +{ + OUString sText; + + if (m_pViolation->isDPITooLow()) + { + sText = SwResId(STR_WARNING_GRAPHIC_PIXEL_COUNT_LOW); + } + else if (m_pViolation->isDPITooHigh()) + { + sText = SwResId(STR_WARNING_GRAPHIC_PIXEL_COUNT_HIGH); + } + + sText = sText.replaceAll("%NAME%", m_pViolation->getGraphicName()); + sText = sText.replaceAll("%DPIX%", OUString::number(m_pViolation->getDPIX())); + sText = sText.replaceAll("%DPIY%", OUString::number(m_pViolation->getDPIY())); + + return sText; +} + +void GraphicSizeCheckGUIEntry::markObject() +{ + SwWrtShell* pWrtShell = m_pDocument->GetDocShell()->GetWrtShell(); + pWrtShell->GotoFly(m_pViolation->getGraphicName(), FLYCNTTYPE_ALL, true); +} + +void GraphicSizeCheckGUIEntry::runProperties() +{ + markObject(); + SwWrtShell* pWrtShell = m_pDocument->GetDocShell()->GetWrtShell(); + pWrtShell->GetView().GetViewFrame()->GetDispatcher()->Execute(FN_FORMAT_GRAFIC_DLG, + SfxCallMode::SYNCHRON); +} + +GraphicSizeCheckGUIResult::GraphicSizeCheckGUIResult(SwDoc* pDocument) +{ + GraphicSizeCheck aCheck(pDocument); + aCheck.check(); + + auto& rCollection = getCollection(); + for (auto& rpViolation : aCheck.getViolationList()) + { + auto rGUIEntry + = std::make_unique<GraphicSizeCheckGUIEntry>(pDocument, std::move(rpViolation)); + rCollection.push_back(std::move(rGUIEntry)); + } +} + +OUString GraphicSizeCheckGUIResult::getTitle() +{ + return SwResId(STR_GRAPHIC_SIZE_CHECK_DIALOG_TITLE); +} + +} // end sw namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/inc/GraphicSizeCheck.hxx b/sw/source/core/inc/GraphicSizeCheck.hxx new file mode 100644 index 000000000000..f708b0a5f4dc --- /dev/null +++ b/sw/source/core/inc/GraphicSizeCheck.hxx @@ -0,0 +1,99 @@ +/* -*- 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/. + * + */ + +#pragma once + +#include <doc.hxx> +#include "ModelTraverser.hxx" +#include <svx/GenericCheckDialog.hxx> + +namespace sw +{ +class GraphicSizeViolation final +{ +private: + const SwGrfNode* m_pGraphicNode; + + sal_Int32 m_nLowDPILimit = 0; + sal_Int32 m_nHighDPILimit = 0; + + sal_Int32 m_nDPIX = 0; + sal_Int32 m_nDPIY = 0; + +public: + GraphicSizeViolation(sal_Int32 nDPI, const SwGrfNode* pGraphicNode); + bool check(); + + OUString getGraphicName(); + + bool isDPITooLow() { return m_nDPIX < m_nLowDPILimit || m_nDPIY < m_nLowDPILimit; } + + bool isDPITooHigh() { return m_nDPIX > m_nHighDPILimit || m_nDPIY > m_nHighDPILimit; } + + sal_Int32 getDPIX() { return m_nDPIX; } + + sal_Int32 getDPIY() { return m_nDPIY; } +}; + +class GraphicSizeCheck final +{ +private: + SwDoc* m_pDocument; + std::vector<std::unique_ptr<GraphicSizeViolation>> m_aGraphicSizeViolationList; + +public: + GraphicSizeCheck(SwDoc* pDocument) + : m_pDocument(pDocument) + { + } + + void check(); + + std::vector<std::unique_ptr<GraphicSizeViolation>>& getViolationList() + { + return m_aGraphicSizeViolationList; + } +}; + +class GraphicSizeCheckGUIEntry : public svx::CheckData +{ +private: + SwDoc* m_pDocument; + std::unique_ptr<GraphicSizeViolation> m_pViolation; + +public: + GraphicSizeCheckGUIEntry(SwDoc* pDocument, std::unique_ptr<GraphicSizeViolation>&& pViolation) + : m_pDocument(pDocument) + , m_pViolation(std::move(pViolation)) + { + } + + OUString getText() override; + + bool canMarkObject() override { return true; } + + void markObject() override; + + bool hasProperties() override { return true; } + + void runProperties() override; +}; + +class GraphicSizeCheckGUIResult : public svx::CheckDataCollection +{ +public: + GraphicSizeCheckGUIResult(SwDoc* pDocument); + + OUString getTitle() override; +}; + +} // end sw namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/shells/basesh.cxx b/sw/source/uibase/shells/basesh.cxx index 05d631bd7b3e..5b4911ff70ad 100644 --- a/sw/source/uibase/shells/basesh.cxx +++ b/sw/source/uibase/shells/basesh.cxx @@ -85,6 +85,7 @@ #include <modcfg.hxx> #include <svx/fmshell.hxx> #include <SwRewriter.hxx> +#include <GraphicSizeCheck.hxx> #include <svx/galleryitem.hxx> #include <sfx2/devtools/DevelopmentToolChildWindow.hxx> #include <com/sun/star/gallery/GalleryItemType.hpp> @@ -1963,6 +1964,13 @@ void SwBaseShell::GetState( SfxItemSet &rSet ) else rSet.Put( SfxVisibilityItem( nWhich, false ) ); break; + case SID_GRAPHIC_SIZE_CHECK: + { + sal_Int32 nDPI = rSh.GetDoc()->getIDocumentSettingAccess().getImagePreferredDPI(); + if (nDPI <= 0) + rSet.DisableItem(nWhich); + } + break; } nWhich = aIter.NextWhich(); } @@ -2785,6 +2793,15 @@ void SwBaseShell::ExecDlg(SfxRequest &rReq) aDialog.run(); } break; + + case SID_GRAPHIC_SIZE_CHECK: + { + sw::GraphicSizeCheckGUIResult aResult(rSh.GetDoc()); + svx::GenericCheckDialog aDialog(pMDI, aResult); + aDialog.run(); + } + break; + default:OSL_FAIL("wrong Dispatcher (basesh.cxx)"); } if(!bDone) diff --git a/sw/uiconfig/sglobal/menubar/menubar.xml b/sw/uiconfig/sglobal/menubar/menubar.xml index b8dafe715afe..852877152a3c 100644 --- a/sw/uiconfig/sglobal/menubar/menubar.xml +++ b/sw/uiconfig/sglobal/menubar/menubar.xml @@ -479,6 +479,7 @@ <menu:menuitem menu:id=".uno:ColorSettings"/> <menu:menuseparator/> <menu:menuitem menu:id=".uno:GraphicDialog"/> + <menu:menuitem menu:id=".uno:GraphicSizeCheck"/> </menu:menupopup> </menu:menu> <menu:menu menu:id=".uno:FormatObjectMenu"> diff --git a/sw/uiconfig/swriter/menubar/menubar.xml b/sw/uiconfig/swriter/menubar/menubar.xml index e27ca8aa3cad..2fb1d51d8cc6 100644 --- a/sw/uiconfig/swriter/menubar/menubar.xml +++ b/sw/uiconfig/swriter/menubar/menubar.xml @@ -490,6 +490,7 @@ <menu:menuitem menu:id=".uno:ColorSettings"/> <menu:menuseparator/> <menu:menuitem menu:id=".uno:GraphicDialog"/> + <menu:menuitem menu:id=".uno:GraphicSizeCheck"/> </menu:menupopup> </menu:menu> <menu:menu menu:id=".uno:FormatObjectMenu">
