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  const SfxPoolItem* pItem(nullptr);
29  if (SfxItemState::SET == aSet.GetItemState( RES_PAGEDESC, true, &pItem ) && pItem)
30  {
31  ::std::optional<sal_uInt16> oNumOffset = static_cast<const SwFormatPageDesc *>(pItem)->GetNumOffset();
32  if (oNumOffset)
33  rPageNo = *oNumOffset;
34  if (ppPageFormatDesc)
35  ppPageFormatDesc->reset(static_cast<const SwFormatPageDesc *>(pItem->Clone()));
36  bRet = true;
37  }
38  }
39  return bRet;
40  }
41 
42  void lcl_ChangePage(SwWrtShell& rSh, sal_uInt16 nNewNumber, const SwPageDesc *pNewDesc)
43  {
44  const size_t nCurIdx = rSh.GetCurPageDesc();
45  const SwPageDesc &rCurrentDesc = rSh.GetPageDesc(nCurIdx);
46 
47  std::unique_ptr<const SwFormatPageDesc> pPageFormatDesc;
48  sal_uInt16 nDontCare;
49  lcl_GetPageDesc(rSh, nDontCare, &pPageFormatDesc);
50 
51  // If we want a new number then set it, otherwise reuse the existing one
52  sal_uInt16 nPgNo = 0;
53  if (nNewNumber)
54  {
55  // -1: Allow special case to prevent inheriting re-numbering from the existing page.
56  nPgNo = nNewNumber == SAL_MAX_UINT16 ? 0 : nNewNumber;
57  }
58  else if (pPageFormatDesc)
59  {
60  ::std::optional<sal_uInt16> oNumOffset = pPageFormatDesc->GetNumOffset();
61  if (oNumOffset)
62  nPgNo = *oNumOffset;
63  }
64 
65  // If we want a new descriptor then set it, otherwise reuse the existing one
66  if (pNewDesc || nPgNo)
67  {
68  SwFormatPageDesc aPageFormatDesc(pNewDesc ? pNewDesc : &rCurrentDesc);
69  if (nPgNo) aPageFormatDesc.SetNumOffset(nPgNo);
70  rSh.SetAttrItem(aPageFormatDesc);
71  }
72  }
73 
74  void lcl_PushCursor(SwWrtShell& rSh)
75  {
76  rSh.LockView(true);
77  rSh.StartAllAction();
78  rSh.SwCursorShell::Push();
79  }
80 
81  void lcl_PopCursor(SwWrtShell& rSh)
82  {
83  rSh.SwCursorShell::Pop(SwCursorShell::PopMode::DeleteCurrent);
84  rSh.EndAllAction();
85  rSh.LockView(false);
86  }
87 
88  sal_uInt16 lcl_GetCurrentPage(const SwWrtShell& rSh)
89  {
90  OUString sDummy;
91  sal_uInt16 nPhyNum=1, nVirtNum=1;
92  rSh.GetPageNumber(0, true, nPhyNum, nVirtNum, sDummy);
93  return nPhyNum;
94  }
95 
96 bool lcl_GotoPage(SwWrtShell& rSh, const sal_uInt16 nStartingPage, sal_uInt16 nOffset = 0)
97 {
98  rSh.GotoPage(nStartingPage, /*bRecord=*/false);
99 
100  sal_uInt16 nCurrentPage = lcl_GetCurrentPage(rSh);
101  // return false if at document end (unless that was the requested destination)
102  if (nCurrentPage == rSh.GetPageCnt())
103  return nCurrentPage == nStartingPage + nOffset;
104 
105  if (nCurrentPage != nStartingPage)
106  {
107  assert(nStartingPage != 1 && "Physical page 1 couldn't be found/moved to?");
108  // Probably there is an auto-inserted blank page to handle odd/even, which Goto doesn't understand.
109  rSh.GotoPage(nStartingPage + 1, /*bRecord=*/false);
110 
111  nCurrentPage = lcl_GetCurrentPage(rSh);
112  assert(nCurrentPage == nStartingPage + 1 && "Impossible, since unknown goes to last page");
113  if (nCurrentPage != nStartingPage + 1)
114  return false;
115  }
116  // Now that we have the correct starting point, move to the correct offset.
117  while (nOffset--)
118  rSh.SttNxtPg();
119  return true;
120 }
121 } // namespace
122 
123 /*
124  * Only include the Index page in the list if the page count implies one
125  * to reduce confusing things
126  */
128 {
129  sal_uInt16 nTitlePages = m_xPageCountNF->get_value();
130  m_xPagePropertiesLB->clear();
131  if (mpTitleDesc)
132  m_xPagePropertiesLB->append_text(mpTitleDesc->GetName());
133  if (nTitlePages > 1 && mpIndexDesc)
134  m_xPagePropertiesLB->append_text(mpIndexDesc->GetName());
135  if (mpNormalDesc)
136  m_xPagePropertiesLB->append_text(mpNormalDesc->GetName());
137  m_xPagePropertiesLB->set_active(0);
138 }
139 
141 {
142  sal_uInt16 nPage = 1;
143  if (m_xPageStartNF->get_sensitive())
144  nPage = m_xPageStartNF->get_value();
145  return nPage;
146 }
147 
149  : SfxDialogController(pParent, "modules/swriter/ui/titlepage.ui", "DLG_TITLEPAGE")
150  , mrSh(*::GetActiveView()->GetWrtShellPtr())
151  , m_xUseExistingPagesRB(m_xBuilder->weld_radio_button("RB_USE_EXISTING_PAGES"))
152  , m_xPageCountNF(m_xBuilder->weld_spin_button("NF_PAGE_COUNT"))
153  , m_xDocumentStartRB(m_xBuilder->weld_radio_button("RB_DOCUMENT_START"))
154  , m_xPageStartRB(m_xBuilder->weld_radio_button("RB_PAGE_START"))
155  , m_xPageStartNF(m_xBuilder->weld_spin_button("NF_PAGE_START"))
156  , m_xRestartNumberingCB(m_xBuilder->weld_check_button("CB_RESTART_NUMBERING"))
157  , m_xRestartNumberingNF(m_xBuilder->weld_spin_button("NF_RESTART_NUMBERING"))
158  , m_xSetPageNumberCB(m_xBuilder->weld_check_button("CB_SET_PAGE_NUMBER"))
159  , m_xSetPageNumberNF(m_xBuilder->weld_spin_button("NF_SET_PAGE_NUMBER"))
160  , m_xPagePropertiesLB(m_xBuilder->weld_combo_box("LB_PAGE_PROPERTIES"))
161  , m_xPagePropertiesPB(m_xBuilder->weld_button("PB_PAGE_PROPERTIES"))
162  , m_xOkPB(m_xBuilder->weld_button("ok"))
163 {
164  m_xOkPB->connect_clicked(LINK(this, SwTitlePageDlg, OKHdl));
165  m_xRestartNumberingCB->connect_toggled(LINK(this, SwTitlePageDlg, RestartNumberingHdl));
166  m_xSetPageNumberCB->connect_toggled(LINK(this, SwTitlePageDlg, SetPageNumberHdl));
167  m_xPageStartNF->set_max(mrSh.GetPageCnt() + 1);
168 
169  sal_uInt16 nSetPage = 1;
170  sal_uInt16 nResetPage = 1;
171  sal_uInt16 nTitlePages = 1;
172  lcl_PushCursor(mrSh);
173 
174  SwView& rView = mrSh.GetView();
175  rView.InvalidateRulerPos();
176 
177  bool bMaybeResetNumbering = false;
178 
182 
184  if (lcl_GetPageDesc(mrSh, nSetPage, &mpPageFormatDesc))
185  {
186  if (mpPageFormatDesc->GetPageDesc() == mpTitleDesc)
187  {
188  while (mrSh.SttNxtPg())
189  {
190  const size_t nCurIdx = mrSh.GetCurPageDesc();
191  const SwPageDesc& rPageDesc = mrSh.GetPageDesc(nCurIdx);
192 
193  if (mpIndexDesc != &rPageDesc)
194  {
195  mpNormalDesc = &rPageDesc;
196  bMaybeResetNumbering = lcl_GetPageDesc(mrSh, nResetPage, nullptr);
197  break;
198  }
199  ++nTitlePages;
200  }
201  }
202  }
203  lcl_PopCursor(mrSh);
204 
205  m_xUseExistingPagesRB->set_active(true);
206  m_xPageCountNF->set_value(nTitlePages);
207  m_xPageCountNF->connect_value_changed(LINK(this, SwTitlePageDlg, ValueChangeHdl));
208 
209  m_xDocumentStartRB->set_active(true);
210  m_xPageStartNF->set_sensitive(false);
211  m_xPageStartNF->set_value(lcl_GetCurrentPage(mrSh));
212  Link<weld::ToggleButton&,void> aStartPageHdl = LINK(this, SwTitlePageDlg, StartPageHdl);
213  m_xDocumentStartRB->connect_toggled(aStartPageHdl);
214  m_xPageStartRB->connect_toggled(aStartPageHdl);
215 
216  m_xRestartNumberingNF->set_value(nResetPage);
217  if (bMaybeResetNumbering && nResetPage > 0)
218  {
219  m_xRestartNumberingCB->set_active(true);
220  }
221  m_xRestartNumberingNF->set_sensitive(m_xRestartNumberingCB->get_active());
222 
223  m_xSetPageNumberNF->set_value(nSetPage);
224  if (nSetPage > 1)
225  m_xSetPageNumberCB->set_active(true);
226  m_xSetPageNumberNF->set_sensitive(m_xSetPageNumberCB->get_active());
227 
228  FillList();
229  m_xPagePropertiesPB->connect_clicked(LINK(this, SwTitlePageDlg, EditHdl));
230 }
231 
233 {
234  if (m_xPageCountNF->get_value() == 1 || m_xPageCountNF->get_value() == 2)
235  FillList();
236 }
237 
238 IMPL_LINK_NOARG(SwTitlePageDlg, RestartNumberingHdl, weld::ToggleButton&, void)
239 {
240  m_xRestartNumberingNF->set_sensitive(m_xRestartNumberingCB->get_active());
241 }
242 
244 {
245  m_xSetPageNumberNF->set_sensitive(m_xSetPageNumberCB->get_active());
246 }
247 
249 {
250  m_xPageStartNF->set_sensitive(m_xPageStartRB->get_active());
251 }
252 
254 {
255 }
256 
258 {
259  SwView& rView = mrSh.GetView();
260  rView.GetDocShell()->FormatPage(m_xPagePropertiesLB->get_active_text(), "page", mrSh);
261  rView.InvalidateRulerPos();
262 }
263 
265 {
266  lcl_PushCursor(mrSh);
267 
268  mrSh.StartUndo();
269 
270  SwFormatPageDesc aTitleDesc(mpTitleDesc);
271 
272  if (m_xSetPageNumberCB->get_active())
273  aTitleDesc.SetNumOffset(m_xSetPageNumberNF->get_value());
274  else if (mpPageFormatDesc)
275  aTitleDesc.SetNumOffset(mpPageFormatDesc->GetNumOffset());
276 
277  sal_uInt16 nNumTitlePages = m_xPageCountNF->get_value();
278  if (!m_xUseExistingPagesRB->get_active())
279  {
280  // Assuming that a failure to GotoPage means the end of the document,
281  // insert new pages after the last page.
282  if (!lcl_GotoPage(mrSh, GetInsertPosition()))
283  {
284  mrSh.EndPg();
285  // Add one more page as a content page to follow the new title pages.
286  mrSh.InsertPageBreak();
287  }
288  for (sal_uInt16 nI = 0; nI < nNumTitlePages; ++nI)
289  mrSh.InsertPageBreak();
290  // In order to be able to access these new pages, the layout needs to be recalculated first.
291  mrSh.CalcLayout();
292  }
293 
294  if (lcl_GotoPage(mrSh, GetInsertPosition()))
295  {
296  mrSh.SetAttrItem(aTitleDesc);
297  for (sal_uInt16 nI = 1; nI < nNumTitlePages; ++nI)
298  {
299  if (mrSh.SttNxtPg())
300  lcl_ChangePage(mrSh, SAL_MAX_UINT16, mpIndexDesc);
301  }
302  }
303 
304  if ((m_xRestartNumberingCB->get_active() || nNumTitlePages > 1)
305  && lcl_GotoPage(mrSh, GetInsertPosition(), nNumTitlePages))
306  {
307  sal_uInt16 nPgNo
308  = m_xRestartNumberingCB->get_active() ? m_xRestartNumberingNF->get_value() : 0;
309  const SwPageDesc* pNewDesc = nNumTitlePages > 1 ? mpNormalDesc : nullptr;
310  lcl_ChangePage(mrSh, nPgNo, pNewDesc);
311  }
312 
313  mrSh.EndUndo();
314  lcl_PopCursor(mrSh);
315  if (!m_xUseExistingPagesRB->get_active())
316  lcl_GotoPage(mrSh, GetInsertPosition());
317  m_xDialog->response(RET_OK);
318 }
319 
320 /* 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:148
const OUString & GetName() const
Definition: pagedesc.hxx:197
Used by the UI to modify the document model.
Definition: wrtsh.hxx:91
const SwView & GetView() const
Definition: wrtsh.hxx:429
#define SAL_MAX_UINT16
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
std::unique_ptr< weld::RadioButton > m_xDocumentStartRB
Definition: titlepage.hxx:37
IMPL_LINK_NOARG(SwTitlePageDlg, ValueChangeHdl, weld::SpinButton &, void)
Definition: titlepage.cxx:232
std::unique_ptr< weld::SpinButton > m_xPageStartNF
Definition: titlepage.hxx:39
sal_uInt16 GetInsertPosition() const
Definition: titlepage.cxx:140
std::unique_ptr< weld::CheckButton > m_xRestartNumberingCB
Definition: titlepage.hxx:40
const SfxItemPool & GetAttrPool() const
Definition: viewsh.hxx:612
sal_uInt16 GetPageCnt()
Definition: crsrsh.cxx:1290
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:1126
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:462
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:253
SwPageDesc * GetPageDescFromPool(sal_uInt16 nId)
Definition: edfmt.cxx:134
Reference< XExecutableDialog > m_xDialog
void InvalidateRulerPos()
Definition: viewport.cxx:105
static SwPageDesc * lcl_GetPageDesc(SwDoc *pDoc, const uno::Any &aValue)
Definition: unosett.cxx:235
bool GetCurAttr(SfxItemSet &, const bool bMergeIndentValuesOfNumRule=false) const
Definition: edattr.cxx:177
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 FormatPage(const OUString &rPage, const OString &rPageId, SwWrtShell &rActShell, SfxRequest *pRequest=nullptr)
Show page style format dialog.
Definition: docst.cxx:1602
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