LibreOffice Module sw (master)  1
titlepage.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  */
9 
10 #include <view.hxx>
11 #include <swmodule.hxx>
12 #include <wrtsh.hxx>
13 #include <poolfmt.hxx>
14 #include <docsh.hxx>
15 
16 #include <titlepage.hxx>
17 #include <fmtpdsc.hxx>
18 #include <pagedesc.hxx>
19 
20 namespace
21 {
22  bool lcl_GetPageDesc(SwWrtShell& rSh, sal_uInt16 &rPageNo, std::unique_ptr<const SwFormatPageDesc>* ppPageFormatDesc)
23  {
24  bool bRet = false;
26  if (rSh.GetCurAttr(aSet))
27  {
28  if (const SwFormatPageDesc* pDescItem = aSet.GetItemIfSet( RES_PAGEDESC ))
29  {
30  ::std::optional<sal_uInt16> oNumOffset = pDescItem->GetNumOffset();
31  if (oNumOffset)
32  rPageNo = *oNumOffset;
33  if (ppPageFormatDesc)
34  ppPageFormatDesc->reset(static_cast<const SwFormatPageDesc *>(pDescItem->Clone()));
35  bRet = true;
36  }
37  }
38  return bRet;
39  }
40 
41  void lcl_ChangePage(SwWrtShell& rSh, sal_uInt16 nNewNumber, const SwPageDesc *pNewDesc)
42  {
43  const size_t nCurIdx = rSh.GetCurPageDesc();
44  const SwPageDesc &rCurrentDesc = rSh.GetPageDesc(nCurIdx);
45 
46  std::unique_ptr<const SwFormatPageDesc> pPageFormatDesc;
47  sal_uInt16 nDontCare;
48  lcl_GetPageDesc(rSh, nDontCare, &pPageFormatDesc);
49 
50  // If we want a new number then set it, otherwise reuse the existing one
51  sal_uInt16 nPgNo = 0;
52  if (nNewNumber)
53  {
54  // -1: Allow special case to prevent inheriting re-numbering from the existing page.
55  nPgNo = nNewNumber == SAL_MAX_UINT16 ? 0 : nNewNumber;
56  }
57  else if (pPageFormatDesc)
58  {
59  ::std::optional<sal_uInt16> oNumOffset = pPageFormatDesc->GetNumOffset();
60  if (oNumOffset)
61  nPgNo = *oNumOffset;
62  }
63 
64  // If we want a new descriptor then set it, otherwise reuse the existing one
65  if (pNewDesc || nPgNo)
66  {
67  SwFormatPageDesc aPageFormatDesc(pNewDesc ? pNewDesc : &rCurrentDesc);
68  if (nPgNo) aPageFormatDesc.SetNumOffset(nPgNo);
69  rSh.SetAttrItem(aPageFormatDesc);
70  }
71  }
72 
73  void lcl_PushCursor(SwWrtShell& rSh)
74  {
75  rSh.LockView(true);
76  rSh.StartAllAction();
77  rSh.SwCursorShell::Push();
78  }
79 
80  void lcl_PopCursor(SwWrtShell& rSh)
81  {
82  rSh.SwCursorShell::Pop(SwCursorShell::PopMode::DeleteCurrent);
83  rSh.EndAllAction();
84  rSh.LockView(false);
85  }
86 
87  sal_uInt16 lcl_GetCurrentPage(const SwWrtShell& rSh)
88  {
89  OUString sDummy;
90  sal_uInt16 nPhyNum=1, nVirtNum=1;
91  rSh.GetPageNumber(0, true, nPhyNum, nVirtNum, sDummy);
92  return nPhyNum;
93  }
94 
95 bool lcl_GotoPage(SwWrtShell& rSh, const sal_uInt16 nStartingPage, sal_uInt16 nOffset = 0)
96 {
97  rSh.GotoPage(nStartingPage, /*bRecord=*/false);
98 
99  sal_uInt16 nCurrentPage = lcl_GetCurrentPage(rSh);
100  // return false if at document end (unless that was the requested destination)
101  if (nCurrentPage == rSh.GetPageCnt())
102  return nCurrentPage == nStartingPage + nOffset;
103 
104  if (nCurrentPage != nStartingPage)
105  {
106  assert(nStartingPage != 1 && "Physical page 1 couldn't be found/moved to?");
107  // Probably there is an auto-inserted blank page to handle odd/even, which Goto doesn't understand.
108  rSh.GotoPage(nStartingPage + 1, /*bRecord=*/false);
109 
110  nCurrentPage = lcl_GetCurrentPage(rSh);
111  assert(nCurrentPage == nStartingPage + 1 && "Impossible, since unknown goes to last page");
112  if (nCurrentPage != nStartingPage + 1)
113  return false;
114  }
115  // Now that we have the correct starting point, move to the correct offset.
116  while (nOffset--)
117  rSh.SttNxtPg();
118  return true;
119 }
120 } // namespace
121 
122 /*
123  * Only include the Index page in the list if the page count implies one
124  * to reduce confusing things
125  */
127 {
128  sal_uInt16 nTitlePages = m_xPageCountNF->get_value();
129  m_xPagePropertiesLB->clear();
130  if (mpTitleDesc)
131  m_xPagePropertiesLB->append_text(mpTitleDesc->GetName());
132  if (nTitlePages > 1 && mpIndexDesc)
133  m_xPagePropertiesLB->append_text(mpIndexDesc->GetName());
134  if (mpNormalDesc)
135  m_xPagePropertiesLB->append_text(mpNormalDesc->GetName());
136  m_xPagePropertiesLB->set_active(0);
137 }
138 
140 {
141  sal_uInt16 nPage = 1;
142  if (m_xPageStartNF->get_sensitive())
143  nPage = m_xPageStartNF->get_value();
144  return nPage;
145 }
146 
148  : SfxDialogController(pParent, "modules/swriter/ui/titlepage.ui", "DLG_TITLEPAGE")
149  , mrSh(*::GetActiveView()->GetWrtShellPtr())
150  , m_xUseExistingPagesRB(m_xBuilder->weld_radio_button("RB_USE_EXISTING_PAGES"))
151  , m_xPageCountNF(m_xBuilder->weld_spin_button("NF_PAGE_COUNT"))
152  , m_xDocumentStartRB(m_xBuilder->weld_radio_button("RB_DOCUMENT_START"))
153  , m_xPageStartRB(m_xBuilder->weld_radio_button("RB_PAGE_START"))
154  , m_xPageStartNF(m_xBuilder->weld_spin_button("NF_PAGE_START"))
155  , m_xRestartNumberingCB(m_xBuilder->weld_check_button("CB_RESTART_NUMBERING"))
156  , m_xRestartNumberingNF(m_xBuilder->weld_spin_button("NF_RESTART_NUMBERING"))
157  , m_xSetPageNumberCB(m_xBuilder->weld_check_button("CB_SET_PAGE_NUMBER"))
158  , m_xSetPageNumberNF(m_xBuilder->weld_spin_button("NF_SET_PAGE_NUMBER"))
159  , m_xPagePropertiesLB(m_xBuilder->weld_combo_box("LB_PAGE_PROPERTIES"))
160  , m_xPagePropertiesPB(m_xBuilder->weld_button("PB_PAGE_PROPERTIES"))
161  , m_xOkPB(m_xBuilder->weld_button("ok"))
162 {
163  m_xOkPB->connect_clicked(LINK(this, SwTitlePageDlg, OKHdl));
164  m_xRestartNumberingCB->connect_toggled(LINK(this, SwTitlePageDlg, RestartNumberingHdl));
165  m_xSetPageNumberCB->connect_toggled(LINK(this, SwTitlePageDlg, SetPageNumberHdl));
166  m_xPageStartNF->set_max(mrSh.GetPageCnt() + 1);
167 
168  sal_uInt16 nSetPage = 1;
169  sal_uInt16 nResetPage = 1;
170  sal_uInt16 nTitlePages = 1;
171  lcl_PushCursor(mrSh);
172 
173  SwView& rView = mrSh.GetView();
174  rView.InvalidateRulerPos();
175 
176  bool bMaybeResetNumbering = false;
177 
181 
183  if (lcl_GetPageDesc(mrSh, nSetPage, &mpPageFormatDesc))
184  {
185  if (mpPageFormatDesc->GetPageDesc() == mpTitleDesc)
186  {
187  while (mrSh.SttNxtPg())
188  {
189  const size_t nCurIdx = mrSh.GetCurPageDesc();
190  const SwPageDesc& rPageDesc = mrSh.GetPageDesc(nCurIdx);
191 
192  if (mpIndexDesc != &rPageDesc)
193  {
194  mpNormalDesc = &rPageDesc;
195  bMaybeResetNumbering = lcl_GetPageDesc(mrSh, nResetPage, nullptr);
196  break;
197  }
198  ++nTitlePages;
199  }
200  }
201  }
202  lcl_PopCursor(mrSh);
203 
204  m_xUseExistingPagesRB->set_active(true);
205  m_xPageCountNF->set_value(nTitlePages);
206  m_xPageCountNF->connect_value_changed(LINK(this, SwTitlePageDlg, ValueChangeHdl));
207 
208  m_xDocumentStartRB->set_active(true);
209  m_xPageStartNF->set_sensitive(false);
210  m_xPageStartNF->set_value(lcl_GetCurrentPage(mrSh));
211  Link<weld::Toggleable&,void> aStartPageHdl = LINK(this, SwTitlePageDlg, StartPageHdl);
212  m_xDocumentStartRB->connect_toggled(aStartPageHdl);
213  m_xPageStartRB->connect_toggled(aStartPageHdl);
214 
215  m_xRestartNumberingNF->set_value(nResetPage);
216  if (bMaybeResetNumbering && nResetPage > 0)
217  {
218  m_xRestartNumberingCB->set_active(true);
219  }
220  m_xRestartNumberingNF->set_sensitive(m_xRestartNumberingCB->get_active());
221 
222  m_xSetPageNumberNF->set_value(nSetPage);
223  if (nSetPage > 1)
224  m_xSetPageNumberCB->set_active(true);
225  m_xSetPageNumberNF->set_sensitive(m_xSetPageNumberCB->get_active());
226 
227  FillList();
228  m_xPagePropertiesPB->connect_clicked(LINK(this, SwTitlePageDlg, EditHdl));
229 }
230 
232 {
233  if (m_xPageCountNF->get_value() == 1 || m_xPageCountNF->get_value() == 2)
234  FillList();
235 }
236 
237 IMPL_LINK_NOARG(SwTitlePageDlg, RestartNumberingHdl, weld::Toggleable&, void)
238 {
239  m_xRestartNumberingNF->set_sensitive(m_xRestartNumberingCB->get_active());
240 }
241 
243 {
244  m_xSetPageNumberNF->set_sensitive(m_xSetPageNumberCB->get_active());
245 }
246 
248 {
249  m_xPageStartNF->set_sensitive(m_xPageStartRB->get_active());
250 }
251 
253 {
254 }
255 
257 {
258  SwView& rView = mrSh.GetView();
259  rView.GetDocShell()->FormatPage(getDialog(), m_xPagePropertiesLB->get_active_text(), "page", mrSh);
260  rView.InvalidateRulerPos();
261 }
262 
264 {
265  lcl_PushCursor(mrSh);
266 
267  mrSh.StartUndo();
268 
269  SwFormatPageDesc aTitleDesc(mpTitleDesc);
270 
271  if (m_xSetPageNumberCB->get_active())
272  aTitleDesc.SetNumOffset(m_xSetPageNumberNF->get_value());
273  else if (mpPageFormatDesc)
274  aTitleDesc.SetNumOffset(mpPageFormatDesc->GetNumOffset());
275 
276  sal_uInt16 nNumTitlePages = m_xPageCountNF->get_value();
277  if (!m_xUseExistingPagesRB->get_active())
278  {
279  // Assuming that a failure to GotoPage means the end of the document,
280  // insert new pages after the last page.
281  if (!lcl_GotoPage(mrSh, GetInsertPosition()))
282  {
283  mrSh.EndPg();
284  // Add one more page as a content page to follow the new title pages.
285  mrSh.InsertPageBreak();
286  }
287  for (sal_uInt16 nI = 0; nI < nNumTitlePages; ++nI)
288  mrSh.InsertPageBreak();
289  // In order to be able to access these new pages, the layout needs to be recalculated first.
290  mrSh.CalcLayout();
291  }
292 
293  if (lcl_GotoPage(mrSh, GetInsertPosition()))
294  {
295  mrSh.SetAttrItem(aTitleDesc);
296  for (sal_uInt16 nI = 1; nI < nNumTitlePages; ++nI)
297  {
298  if (mrSh.SttNxtPg())
299  lcl_ChangePage(mrSh, SAL_MAX_UINT16, mpIndexDesc);
300  }
301  }
302 
303  if ((m_xRestartNumberingCB->get_active() || nNumTitlePages > 1)
304  && lcl_GotoPage(mrSh, GetInsertPosition(), nNumTitlePages))
305  {
306  sal_uInt16 nPgNo
307  = m_xRestartNumberingCB->get_active() ? m_xRestartNumberingNF->get_value() : 0;
308  const SwPageDesc* pNewDesc = nNumTitlePages > 1 ? mpNormalDesc : nullptr;
309  lcl_ChangePage(mrSh, nPgNo, pNewDesc);
310  }
311 
312  mrSh.EndUndo();
313  lcl_PopCursor(mrSh);
314  if (!m_xUseExistingPagesRB->get_active())
315  lcl_GotoPage(mrSh, GetInsertPosition());
316  m_xDialog->response(RET_OK);
317 }
318 
319 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
constexpr TypedWhichId< SwFormatPageDesc > RES_PAGEDESC(93)
std::unique_ptr< weld::CheckButton > m_xSetPageNumberCB
Definition: titlepage.hxx:42
Pagedescriptor Client of SwPageDesc that is "described" by the attribute.
Definition: fmtpdsc.hxx:35
SwView * GetActiveView()
Definition: swmodul1.cxx:116
SwWrtShell & mrSh
Definition: titlepage.hxx:27
bool SttNxtPg(bool bSelect=false)
Definition: move.cxx:320
std::unique_ptr< weld::ComboBox > m_xPagePropertiesLB
Definition: titlepage.hxx:44
std::unique_ptr< weld::Button > m_xPagePropertiesPB
Definition: titlepage.hxx:45
std::unique_ptr< weld::SpinButton > m_xPageCountNF
Definition: titlepage.hxx:36
void EndAllAction()
Definition: edws.cxx:97
SwTitlePageDlg(weld::Window *pParent)
Definition: titlepage.cxx:147
const OUString & GetName() const
Definition: pagedesc.hxx:196
Used by the UI to modify the document model.
Definition: wrtsh.hxx:96
const SwView & GetView() const
Definition: wrtsh.hxx:437
#define SAL_MAX_UINT16
std::unique_ptr< weld::RadioButton > m_xDocumentStartRB
Definition: titlepage.hxx:37
void FormatPage(weld::Window *pDialogParent, const OUString &rPage, const OString &rPageId, SwWrtShell &rActShell, SfxRequest *pRequest=nullptr)
Show page style format dialog.
Definition: docst.cxx:1627
IMPL_LINK_NOARG(SwTitlePageDlg, ValueChangeHdl, weld::SpinButton &, void)
Definition: titlepage.cxx:231
std::unique_ptr< weld::SpinButton > m_xPageStartNF
Definition: titlepage.hxx:39
sal_uInt16 GetInsertPosition() const
Definition: titlepage.cxx:139
std::unique_ptr< weld::CheckButton > m_xRestartNumberingCB
Definition: titlepage.hxx:40
const SfxItemPool & GetAttrPool() const
Definition: viewsh.hxx:617
sal_uInt16 GetPageCnt()
Definition: crsrsh.cxx:1291
First page.
Definition: poolfmt.hxx:171
void SetAttrItem(const SfxPoolItem &, SetAttrMode nFlags=SetAttrMode::DEFAULT, const bool bParagraphSetting=false)
Definition: edatmisc.cxx:112
const SwPageDesc & GetPageDesc(size_t i) const
Definition: fedesc.cxx:126
const SwPageDesc * mpIndexDesc
Definition: titlepage.hxx:32
std::unique_ptr< weld::RadioButton > m_xPageStartRB
Definition: titlepage.hxx:38
bool StartOfSection(bool bSelect=false)
Definition: move.cxx:308
SwDocShell * GetDocShell()
Definition: view.cxx:1132
const SwPageDesc * mpNormalDesc
Definition: titlepage.hxx:33
std::unique_ptr< weld::SpinButton > m_xSetPageNumberNF
Definition: titlepage.hxx:43
void LockView(bool b)
Definition: viewsh.hxx:467
std::unique_ptr< weld::SpinButton > m_xRestartNumberingNF
Definition: titlepage.hxx:41
std::unique_ptr< const SwFormatPageDesc > mpPageFormatDesc
Definition: titlepage.hxx:29
RET_OK
virtual ~SwTitlePageDlg() override
Definition: titlepage.cxx:252
SwPageDesc * GetPageDescFromPool(sal_uInt16 nId)
Definition: edfmt.cxx:132
Reference< XExecutableDialog > m_xDialog
void InvalidateRulerPos()
Definition: viewport.cxx:107
static SwPageDesc * lcl_GetPageDesc(SwDoc *pDoc, const uno::Any &aValue)
Definition: unosett.cxx:226
bool GetCurAttr(SfxItemSet &, const bool bMergeIndentValuesOfNumRule=false) const
Definition: edattr.cxx:171
std::unique_ptr< weld::RadioButton > m_xUseExistingPagesRB
Definition: titlepage.hxx:35
std::unique_ptr< weld::Button > m_xOkPB
Definition: titlepage.hxx:46
bool GotoPage(sal_uInt16 nPage, bool bRecord)
Definition: move.cxx:573
void SetNumOffset(const ::std::optional< sal_uInt16 > &oNum)
Definition: fmtpdsc.hxx:65
sal_uInt16 GetPageNumber(const Point &rPoint) const
Page number of the page containing Point, O if no page.
Definition: fews.cxx:185
void StartAllAction()
For all views of this document.
Definition: edws.cxx:86
size_t GetCurPageDesc(const bool bCalcFrame=true) const
Definition: fedesc.cxx:167
Standard page.
Definition: poolfmt.hxx:170
SwPageDesc * mpTitleDesc
Definition: titlepage.hxx:31
Definition: view.hxx:144