sd: add initial theme UI for master slides

Click Sidebar -> properties -> slide -> master view, then launch the
Slide -> Slide properties menu item, this adds a new Theme tab page
there.

This is just an initial UI, only the theme name can be edited as a
start.

Change-Id: Ia2faa828c57a0e858881fb8640431f046b5739a8
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/126798
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
Tested-by: Jenkins
This commit is contained in:
Miklos Vajna 2021-12-14 09:55:45 +01:00
parent aed4c2d80c
commit 64fcf27883
18 changed files with 369 additions and 8 deletions

View file

@ -219,6 +219,7 @@ $(eval $(call gb_Library_add_exception_objects,cui,\
cui/source/tabpages/textanim \
cui/source/tabpages/textattr \
cui/source/tabpages/TextColumnsPage \
cui/source/tabpages/themepage \
cui/source/tabpages/tparea \
cui/source/tabpages/tpbitmap \
cui/source/tabpages/tpcolor \

View file

@ -29,6 +29,7 @@ $(eval $(call gb_Module_add_screenshot_targets,cui,\
$(eval $(call gb_Module_add_uicheck_targets,cui,\
UITest_cui_dialogs \
UITest_cui_tabpages \
))
# vim: set noet sw=4 ts=4:

View file

@ -212,6 +212,7 @@ $(eval $(call gb_UIConfig_add_uifiles,cui,\
cui/uiconfig/ui/textcolumnstabpage \
cui/uiconfig/ui/textdialog \
cui/uiconfig/ui/textflowpage \
cui/uiconfig/ui/themetabpage \
cui/uiconfig/ui/thesaurus \
cui/uiconfig/ui/toolbarmodedialog \
cui/uiconfig/ui/transparencytabpage \

View file

@ -0,0 +1,16 @@
# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
#
# 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/.
#
$(eval $(call gb_UITest_UITest,cui_tabpages))
$(eval $(call gb_UITest_add_modules,cui_tabpages,$(SRCDIR)/cui/qa/uitest,\
tabpages/ \
))
# vim: set noet sw=4 ts=4:

View file

@ -0,0 +1,47 @@
#
# 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 libreoffice.uno.propertyvalue import convert_property_values_to_dict
from libreoffice.uno.propertyvalue import mkPropertyValues
from uitest.framework import UITestCase
from uitest.uihelper.common import get_state_as_dict
from uitest.uihelper.common import select_pos
# Test for cui/source/tabpages/themepage.cxx.
class Test(UITestCase):
def testThemePage(self):
# Given an Impress document with a master page that has a theme:
with self.ui_test.create_doc_in_start_center("impress") as component:
template = self.xUITest.getTopFocusWindow()
self.ui_test.close_dialog_through_button(template.getChild("close"))
doc = self.xUITest.getTopFocusWindow()
editWin = doc.getChild("impress_win")
drawPage = component.getDrawPages().getByIndex(0)
master = drawPage.MasterPage
theme = mkPropertyValues({
"Name": "nameA"
})
master.Theme = theme
# When changing the name of the theme:
self.xUITest.executeCommand(".uno:SlideMasterPage")
with self.ui_test.execute_dialog_through_command(".uno:PageSetup") as xDialog:
xTabs = xDialog.getChild("tabcontrol")
# Select RID_SVXPAGE_THEME.
select_pos(xTabs, "3")
themeName = xDialog.getChild("themeName")
themeName.executeAction("TYPE", mkPropertyValues({"TEXT": "nameB"}))
# Then make sure the doc model is updated accordingly:
# Without the accompanying fix in place, this test would have failed with:
# AssertionError: 'nameA' != 'nameB'
# i.e. the UI didn't update the theme name.
theme = convert_property_values_to_dict(master.Theme)
self.assertEqual(theme["Name"], "nameB")
# vim: set shiftwidth=4 softtabstop=4 expandtab:

View file

@ -92,6 +92,7 @@
#include <DiagramDialog.hxx>
#include <fileextcheckdlg.hxx>
#include <TextColumnsPage.hxx>
#include <themepage.hxx>
using namespace ::com::sun::star;
using namespace ::com::sun::star::frame;
@ -1289,6 +1290,8 @@ CreateTabPage AbstractDialogFactory_Impl::GetTabPageCreatorFunc( sal_uInt16 nId
return SfxMacroTabPage::Create;
case RID_SVXPAGE_TEXTCOLUMNS:
return SvxTextColumnsPage::Create;
case RID_SVXPAGE_THEME:
return SvxThemePage::Create;
default:
break;
}
@ -1354,6 +1357,8 @@ GetTabPageRanges AbstractDialogFactory_Impl::GetTabPageRangesFunc( sal_uInt16 nI
return SvxAsianLayoutPage::GetRanges;
case RID_SVXPAGE_TEXTCOLUMNS:
return SvxTextColumnsPage::GetRanges;
case RID_SVXPAGE_THEME:
return SvxThemePage::GetRanges;
default:
break;
}

View file

@ -0,0 +1,38 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
/*
* 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 <sal/config.h>
#include <sfx2/tabdlg.hxx>
#include <memory>
/// Tab page for themes
class SvxThemePage : public SfxTabPage
{
static const WhichRangesContainer m_pRanges;
std::unique_ptr<weld::Entry> m_xThemeName;
public:
SvxThemePage(weld::Container* pPage, weld::DialogController* pController,
const SfxItemSet& rInAttrs);
virtual ~SvxThemePage() override;
static std::unique_ptr<SfxTabPage>
Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet*);
static WhichRangesContainer GetRanges() { return m_pRanges; }
virtual bool FillItemSet(SfxItemSet*) override;
virtual void Reset(const SfxItemSet*) override;
};
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */

View file

@ -0,0 +1,95 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
/*
* 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 <sal/config.h>
#include <com/sun/star/beans/PropertyValues.hpp>
#include <comphelper/sequenceashashmap.hxx>
#include <editeng/editids.hrc>
#include <sal/log.hxx>
#include <svl/grabbagitem.hxx>
#include <themepage.hxx>
using namespace com::sun::star;
const WhichRangesContainer
SvxThemePage::m_pRanges(svl::Items<SID_ATTR_CHAR_GRABBAG, SID_ATTR_CHAR_GRABBAG>);
SvxThemePage::SvxThemePage(weld::Container* pPage, weld::DialogController* pController,
const SfxItemSet& rInAttrs)
: SfxTabPage(pPage, pController, "cui/ui/themetabpage.ui", "ThemePage", &rInAttrs)
, m_xThemeName(m_xBuilder->weld_entry("themeName"))
{
}
SvxThemePage::~SvxThemePage() = default;
void SvxThemePage::Reset(const SfxItemSet* pAttrs)
{
const SfxPoolItem* pItem = nullptr;
if (!pAttrs->HasItem(SID_ATTR_CHAR_GRABBAG, &pItem))
{
SAL_WARN("cui.tabpages", "SvxThemePage::Reset: no SfxGrabBagItem");
return;
}
const auto& rGrabBagItem = static_cast<const SfxGrabBagItem&>(*pItem);
auto itTheme = rGrabBagItem.GetGrabBag().find("Theme");
if (itTheme == rGrabBagItem.GetGrabBag().end())
{
SAL_WARN("cui.tabpages", "SvxThemePage::Reset: no Theme");
return;
}
comphelper::SequenceAsHashMap aMap(itTheme->second);
auto it = aMap.find("Name");
if (it != aMap.end())
{
OUString aName;
it->second >>= aName;
m_xThemeName->set_text(aName);
}
}
bool SvxThemePage::FillItemSet(SfxItemSet* pAttrs)
{
const SfxItemSet& rOldSet = GetItemSet();
if (rOldSet.HasItem(SID_ATTR_CHAR_GRABBAG))
{
SfxGrabBagItem aGrabBagItem(
static_cast<const SfxGrabBagItem&>(rOldSet.Get(SID_ATTR_CHAR_GRABBAG)));
comphelper::SequenceAsHashMap aMap;
auto it = aGrabBagItem.GetGrabBag().find("Theme");
if (it != aGrabBagItem.GetGrabBag().end())
{
aMap << it->second;
}
aMap["Name"] <<= m_xThemeName->get_text();
beans::PropertyValues aTheme = aMap.getAsConstPropertyValueList();
aGrabBagItem.GetGrabBag()["Theme"] <<= aTheme;
pAttrs->Put(aGrabBagItem);
}
return true;
}
std::unique_ptr<SfxTabPage> SvxThemePage::Create(weld::Container* pPage,
weld::DialogController* pController,
const SfxItemSet* rAttrs)
{
return std::make_unique<SvxThemePage>(pPage, pController, *rAttrs);
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */

View file

@ -0,0 +1,72 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.1 -->
<interface domain="cui">
<requires lib="gtk+" version="3.20"/>
<object class="GtkBox" id="ThemePage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="border_width">6</property>
<property name="orientation">vertical</property>
<property name="spacing">12</property>
<child>
<object class="GtkFrame" id="frmGeneral">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label_xalign">0</property>
<property name="shadow_type">none</property>
<child>
<object class="GtkGrid" id="gdGeneral">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_start">6</property>
<property name="margin_end">6</property>
<property name="row_spacing">3</property>
<property name="column_spacing">6</property>
<child>
<object class="GtkLabel" id="lbThemeName">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes" context="themetabpage|lbThemeName">Name:</property>
<accessibility>
<relation type="label-for" target="themeName"/>
</accessibility>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="themeName">
<property name="visible">True</property>
<property name="can_focus">True</property>
<accessibility>
<relation type="labelled-by" target="lbThemeName"/>
</accessibility>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
</packing>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel" id="general">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes" context="themetabpage|general">General</property>
<attributes>
<attribute name="weight" value="bold"/>
</attributes>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
</object>
</interface>

View file

@ -43,6 +43,7 @@
#define RID_SVXPAGE_BKG (RID_SVX_START + 57)
#define RID_SVXPAGE_SHADOW (RID_SVX_START + 61)
#define RID_SVXPAGE_TRANSPARENCE (RID_SVX_START + 54)
#define RID_SVXPAGE_THEME (RID_SVX_START + 55)
#define RID_SVXPAGE_TEXTATTR (RID_SVX_START + 153)
#define RID_SVXPAGE_TEXTANIMATION (RID_SVX_START + 184)
#define RID_SVXPAGE_TEXTCOLUMNS (RID_SVX_START + 154)

View file

@ -171,7 +171,7 @@ public:
virtual VclPtr<AbstractCopyDlg> CreateCopyDlg(weld::Window* pWindow, const SfxItemSet& rInAttrs, ::sd::View* pView ) = 0;
virtual VclPtr<AbstractSdCustomShowDlg> CreateSdCustomShowDlg(weld::Window* pWindow, SdDrawDocument& rDrawDoc) = 0;
virtual VclPtr<SfxAbstractTabDialog> CreateSdTabCharDialog(weld::Window* pWindow, const SfxItemSet* pAttr, SfxObjectShell* pDocShell) = 0;
virtual VclPtr<SfxAbstractTabDialog> CreateSdTabPageDialog(weld::Window* pWindow, const SfxItemSet* pAttr, SfxObjectShell* pDocShell, bool bAreaPage, bool bIsImpressDoc) = 0;
virtual VclPtr<SfxAbstractTabDialog> CreateSdTabPageDialog(weld::Window* pWindow, const SfxItemSet* pAttr, SfxObjectShell* pDocShell, bool bAreaPage, bool bIsImpressDoc, bool bIsImpressMaster) = 0;
virtual VclPtr<AbstractSdModifyFieldDlg> CreateSdModifyFieldDlg(weld::Window* pWindow, const SvxFieldData* pInField, const SfxItemSet& rSet) = 0;
virtual VclPtr<AbstractSdSnapLineDlg> CreateSdSnapLineDlg(weld::Window* pParent, const SfxItemSet& rInAttrs, ::sd::View* pView) = 0;
virtual VclPtr<AbstractSdInsertLayerDlg> CreateSdInsertLayerDlg(weld::Window* pParent, const SfxItemSet& rInAttrs, bool bDeletable, const OUString& rStr) = 0;

View file

@ -308,7 +308,7 @@ VclPtr<VclAbstractDialog> SdDialogsTest::createDialogByID(sal_uInt32 nID)
getViewShell()->GetFrameWeld(),
&getEmptyFillStyleSfxItemSet(),
getDocShell(),
true, false);
true, /*bIsImpressDoc=*/false, /*bIsImpressMaster=*/false);
break;
}
case 6:

View file

@ -36,7 +36,7 @@
* Constructor of tab dialog: appends pages to the dialog
*/
SdPageDlg::SdPageDlg(SfxObjectShell const* pDocSh, weld::Window* pParent, const SfxItemSet* pAttr,
bool bAreaPage, bool bIsImpressDoc)
bool bAreaPage, bool bIsImpressDoc, bool bIsImpressMaster)
: SfxTabDialogController(pParent, "modules/sdraw/ui/drawpagedialog.ui", "DrawPageDialog", pAttr)
, mbIsImpressDoc(bIsImpressDoc)
{
@ -58,6 +58,7 @@ SdPageDlg::SdPageDlg(SfxObjectShell const* pDocSh, weld::Window* pParent, const
AddTabPage("RID_SVXPAGE_AREA", pFact->GetTabPageCreatorFunc(RID_SVXPAGE_AREA), nullptr);
AddTabPage("RID_SVXPAGE_TRANSPARENCE", pFact->GetTabPageCreatorFunc(RID_SVXPAGE_TRANSPARENCE),
nullptr);
AddTabPage("RID_SVXPAGE_THEME", pFact->GetTabPageCreatorFunc(RID_SVXPAGE_THEME), nullptr);
if (!bAreaPage) // I have to add the page before I remove it !
{
@ -65,6 +66,12 @@ SdPageDlg::SdPageDlg(SfxObjectShell const* pDocSh, weld::Window* pParent, const
RemoveTabPage("RID_SVXPAGE_TRANSPARENCE");
}
if (!bIsImpressMaster)
{
// Only slide masters can have a theme.
RemoveTabPage("RID_SVXPAGE_THEME");
}
if (mbIsImpressDoc)
{
set_title(SdResId(STR_SLIDE_SETUP_TITLE));

View file

@ -618,9 +618,9 @@ VclPtr<SfxAbstractTabDialog> SdAbstractDialogFactory_Impl::CreateSdTabCharDialo
return VclPtr<SdAbstractTabController_Impl>::Create(std::make_shared<SdCharDlg>(pParent, pAttr, pDocShell));
}
VclPtr<SfxAbstractTabDialog> SdAbstractDialogFactory_Impl::CreateSdTabPageDialog(weld::Window* pParent, const SfxItemSet* pAttr, SfxObjectShell* pDocShell, bool bAreaPage, bool bIsImpressDoc )
VclPtr<SfxAbstractTabDialog> SdAbstractDialogFactory_Impl::CreateSdTabPageDialog(weld::Window* pParent, const SfxItemSet* pAttr, SfxObjectShell* pDocShell, bool bAreaPage, bool bIsImpressDoc, bool bIsImpressMaster )
{
return VclPtr<SdAbstractTabController_Impl>::Create(std::make_shared<SdPageDlg>(pDocShell, pParent, pAttr, bAreaPage, bIsImpressDoc));
return VclPtr<SdAbstractTabController_Impl>::Create(std::make_shared<SdPageDlg>(pDocShell, pParent, pAttr, bAreaPage, bIsImpressDoc, bIsImpressMaster));
}
VclPtr<AbstractSdModifyFieldDlg> SdAbstractDialogFactory_Impl::CreateSdModifyFieldDlg(weld::Window* pParent, const SvxFieldData* pInField, const SfxItemSet& rSet)

View file

@ -410,7 +410,7 @@ public:
virtual VclPtr<AbstractCopyDlg> CreateCopyDlg(weld::Window* pParent, const SfxItemSet& rInAttrs, ::sd::View* pView) override;
virtual VclPtr<AbstractSdCustomShowDlg> CreateSdCustomShowDlg(weld::Window* pParent, SdDrawDocument& rDrawDoc) override;
virtual VclPtr<SfxAbstractTabDialog> CreateSdTabCharDialog(weld::Window* pWindow, const SfxItemSet* pAttr, SfxObjectShell* pDocShell) override;
virtual VclPtr<SfxAbstractTabDialog> CreateSdTabPageDialog(weld::Window* pWindow, const SfxItemSet* pAttr, SfxObjectShell* pDocShell, bool bAreaPage, bool bIsImpressDoc) override;
virtual VclPtr<SfxAbstractTabDialog> CreateSdTabPageDialog(weld::Window* pWindow, const SfxItemSet* pAttr, SfxObjectShell* pDocShell, bool bAreaPage, bool bIsImpressDoc, bool bIsImpressMaster) override;
virtual VclPtr<AbstractSdModifyFieldDlg> CreateSdModifyFieldDlg(weld::Window* pWindow, const SvxFieldData* pInField, const SfxItemSet& rSet) override;
virtual VclPtr<AbstractSdSnapLineDlg> CreateSdSnapLineDlg(weld::Window* pParent, const SfxItemSet& rInAttrs, ::sd::View* pView) override;
virtual VclPtr<AbstractSdInsertLayerDlg> CreateSdInsertLayerDlg(weld::Window* pParent, const SfxItemSet& rInAttrs, bool bDeletable, const OUString& aStr) override;

View file

@ -47,6 +47,7 @@
#include <editeng/sizeitem.hxx>
#include <editeng/pbinitem.hxx>
#include <sfx2/opengrf.hxx>
#include <sal/log.hxx>
#include <strings.hrc>
#include <sdpage.hxx>
@ -261,6 +262,19 @@ const SfxItemSet* FuPage::ExecuteDialog(weld::Window* pParent, const SfxRequest&
SfxGrabBagItem grabBag(SID_ATTR_CHAR_GRABBAG);
grabBag.GetGrabBag()["BackgroundFullSize"] <<= bFullSize;
if (mpDoc->GetDocumentType() == DocumentType::Impress && mpPage->IsMasterPage())
{
// A master slide may have a theme.
svx::Theme* pTheme = mpPage->getSdrPageProperties().GetTheme();
if (pTheme)
{
uno::Any aTheme;
pTheme->ToAny(aTheme);
grabBag.GetGrabBag()["Theme"] = aTheme;
}
}
aNewAttr.Put(grabBag);
// Merge ItemSet for dialog
@ -350,7 +364,7 @@ const SfxItemSet* FuPage::ExecuteDialog(weld::Window* pParent, const SfxRequest&
// create the dialog
SdAbstractDialogFactory* pFact = SdAbstractDialogFactory::Create();
ScopedVclPtr<SfxAbstractTabDialog> pDlg( pFact->CreateSdTabPageDialog(mpViewShell->GetFrameWeld(), &aMergedAttr, mpDocSh, mbDisplayBackgroundTabPage, bIsImpressDoc) );
ScopedVclPtr<SfxAbstractTabDialog> pDlg( pFact->CreateSdTabPageDialog(mpViewShell->GetFrameWeld(), &aMergedAttr, mpDocSh, mbDisplayBackgroundTabPage, bIsImpressDoc, mbMasterPage) );
if( pDlg->Execute() == RET_OK )
pTempSet.emplace( *pDlg->GetOutputItemSet() );
}
@ -554,6 +568,21 @@ void FuPage::ApplyItemSet( const SfxItemSet* pArgs )
bSetPageSizeAndBorder = true;
}
}
if (mpDoc->GetDocumentType() == DocumentType::Impress && mpPage->IsMasterPage())
{
// The item set may have a theme.
auto it = pGrabBag->GetGrabBag().find("Theme");
if (it != pGrabBag->GetGrabBag().end())
{
std::unique_ptr<svx::Theme> pTheme = svx::Theme::FromAny(it->second);
pMasterPage->getSdrPageProperties().SetTheme(std::move(pTheme));
}
else
{
SAL_WARN("sd.ui", "FuPage::ApplyItemSet: got no theme");
}
}
}
// Paper Bin

View file

@ -40,7 +40,7 @@ private:
XPatternListRef mpPatternList;
public:
SdPageDlg(SfxObjectShell const * pDocSh, weld::Window* pParent, const SfxItemSet* pAttr, bool bAreaPage, bool bIsImpressDoc);
SdPageDlg(SfxObjectShell const * pDocSh, weld::Window* pParent, const SfxItemSet* pAttr, bool bAreaPage, bool bIsImpressDoc, bool bIsImpressMaster);
virtual void PageCreated(const OString& rId, SfxTabPage& rPage) override;
};

View file

@ -235,6 +235,54 @@
<property name="tab_fill">False</property>
</packing>
</child>
<child>
<!-- n-columns=1 n-rows=1 -->
<object class="GtkGrid">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="position">3</property>
</packing>
</child>
<child type="tab">
<object class="GtkLabel" id="RID_SVXPAGE_THEME">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes" context="drawpagedialog|RID_SVXPAGE_THEME">Theme</property>
</object>
<packing>
<property name="position">3</property>
<property name="tab_fill">False</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>