ICF 3.1.1.10
Technical documentation of ICF Libraries
TMultiPageDocumentWrap.h
Go to the documentation of this file.
1/********************************************************************************
2** This file is part of the ICF Framework. Copyright (C) Witold Gantzke & Kirill Lepskiy
3** ICF Framework may be used under the terms of the LGPL License v. 2.1 by the Free Software Foundation.
4********************************************************************************/
5
6#pragma once
7
8
9// Qt includes
10#include <QtCore/QList>
11
12// ICF includes
14#include <iser/IArchive.h>
15#include <iser/CArchiveTag.h>
16#include <iprm/IOptionsList.h>
20
21
22namespace idoc
23{
24
25
29template <class Base>
31 virtual public Base,
33 virtual public iprm::IOptionsList
34{
35public:
36 typedef Base BaseClass;
38
39 // pseudo-reimplemented (idoc::IMultiPageDocument)
40 int GetPagesCount() const override;
41 const istd::IChangeable& GetDocumentPage(int pageIndex) const override;
42 const idoc::IDocumentMetaInfo* GetPageMetaInfo(int pageIndex) const override;
43 void ResetPages() override;
44 bool RemovePage(int pageIndex) override;
45 const IDocumentMetaInfo& GetDocumentMetaInfo() const override;
46
47 // reimplemented (iprm::IOptionsList)
48 int GetOptionsFlags() const override;
49 int GetOptionsCount() const override;
50 QString GetOptionName(int index) const override;
51 QString GetOptionDescription(int index) const override;
52 QByteArray GetOptionId(int index) const override;
53 bool IsOptionEnabled(int index) const override;
54
55 // reimplemented (iser::ISerializable)
56 bool Serialize(iser::IArchive& archive) override;
57
58 // reimplemented (istd::IChangeable)
59 bool CopyFrom(const istd::IChangeable& object, CompatibilityMode mode = CM_WITHOUT_REFS) override;
60 bool ResetData(CompatibilityMode mode) override;
61
62protected:
63 struct Page
64 {
66 std::unique_ptr<istd::IChangeable> pagePtr;
67 };
68
69protected:
73 virtual bool SerializePage(iser::IArchive& archive, Page& pageItem);
74
75protected:
76 typedef std::vector<Page> Pages;
77
79};
80
81
82// public methods
83
84// pseudo-reimplemented (idoc::IMultiPageDocument)
85
86template <class Base>
88{
89 return int(m_documentPages.size());
90}
91
92
93template <class Base>
95{
96 Q_ASSERT(pageIndex < int(m_documentPages.size()));
97 Q_ASSERT(pageIndex >= 0);
98 Q_ASSERT(m_documentPages.at(pageIndex).pagePtr != nullptr);
99
100 return *m_documentPages.at(pageIndex).pagePtr.get();
101}
102
103
104template <class Base>
106{
107 Q_ASSERT(pageIndex < int(m_documentPages.size()));
108 Q_ASSERT(pageIndex >= 0);
109
110 return &m_documentPages.at(pageIndex).pageMetaInfo;
111}
112
113
114template <class Base>
116{
117 istd::CChangeNotifier changePtr(this);
118
119 m_documentPages.clear();
120}
121
122
123template <class Base>
125{
126 Q_ASSERT(pageIndex < int(m_documentPages.size()));
127 Q_ASSERT(pageIndex >= 0);
128
129 istd::CChangeNotifier changePtr(this);
130
131 auto it = m_documentPages.begin();
132 it += pageIndex;
133 m_documentPages.erase(it);
134
135 return true;
136}
137
138
139template <class Base>
144
145
146// reimplemented (iprm::IOptionsList)
147
148template <class Base>
150{
151 return SCF_NONE;
152}
153
154
155template <class Base>
157{
158 return GetPagesCount();
159}
160
161
162template <class Base>
164{
165 Q_ASSERT(index < int(m_documentPages.size()));
166 Q_ASSERT(index >= 0);
167
168 return m_documentPages[index].pageMetaInfo.GetMetaInfo(idoc::IDocumentMetaInfo::MIT_TITLE).toString();
169}
170
171
172template <class Base>
174{
175 return QString();
176}
177
178
179template <class Base>
181{
182 return GetOptionName(index).toUtf8();
183}
184
185
186template <class Base>
188{
189 return true;
190}
191
192
193// reimplemented (iser::ISerializable)
194
195template <class Base>
197{
198 static iser::CArchiveTag metaInfoTag("MetaInfo", "Meta information about the document", iser::CArchiveTag::Type::Group);
199 static iser::CArchiveTag pagesTag("Pages", "Container of the document pages", iser::CArchiveTag::Type::Multiple);
200 static iser::CArchiveTag pageTag("Page", "Single document page", iser::CArchiveTag::Type::Group, &pagesTag);
201
202 istd::CChangeNotifier changePtr(archive.IsChanging() ? this : nullptr);
203
204 // Serialize meta info:
205 bool isMetaInfoOk = archive.ProcessGroup(metaInfoTag,
206 [&](auto& archive) {
207 return BaseClass2::Serialize(archive);
208 });
209
210 // Serialize document pages:
211 return isMetaInfoOk && archive.ProcessGroupList(pagesTag, pageTag, GetPagesCount(),
212 [&](int pageIndex, auto& archive) {
213 this->InsertPage(nullptr, nullptr, pageIndex);
214
215 return SerializePage(archive, m_documentPages[pageIndex]);
216 },
217 [&](int pagesCount) {
218 if (pagesCount <= 0) {
219 ResetPages();
220 }
221 else {
222 int oldCount = GetPagesCount();
223 for (int i = pagesCount - 1; i >= oldCount; --i) {
224 RemovePage(i);
225 }
226 for (int i = oldCount; i < pagesCount; ++i) {
227 this->InsertPage(nullptr, nullptr, i);
228 }
229 }
230
231 return true;
232 });
233}
234
235
236// reimplemented (istd::IChangeable)
237
238template <class Base>
240{
241 // native copy
242 const TMultiPageDocumentWrap<Base>* sourcePtr = dynamic_cast<const TMultiPageDocumentWrap<Base>*>(&object);
243 if (sourcePtr != nullptr) {
244 istd::CChangeNotifier changePtr(this);
245
246 m_documentPages.clear();
247
248 for (auto& sourcePageInfo : sourcePtr->m_documentPages) {
249 Q_ASSERT(sourcePageInfo.pagePtr != nullptr);
250
251 istd::IChangeable* pagePtr = this->InsertPage();
252 if (pagePtr == nullptr) {
253 return false;
254 }
255
256 if (!pagePtr->CopyFrom(*sourcePageInfo.pagePtr)) {
257 return false;
258 }
259
260 if (!m_documentPages[m_documentPages.size()].pageMetaInfo.CopyFrom(sourcePageInfo.pageMetaInfo)) {
261 return false;
262 }
263 }
264
265 if (!BaseClass2::CopyFrom(object, mode)) {
266 return false;
267 }
268
269 return true;
270 }
271
272 // copy via idoc::IMultiPageDocument
273 const idoc::IMultiPageDocument* docPtr = dynamic_cast<const idoc::IMultiPageDocument*>(&object);
274 if (docPtr != nullptr) {
275 istd::CChangeNotifier changePtr(this);
276
277 m_documentPages.clear();
278
279 int pagesCount = docPtr->GetPagesCount();
280 for (int pageIndex = 0; pageIndex < pagesCount; ++pageIndex) {
281 istd::IChangeable* pagePtr = this->InsertPage();
282 if (pagePtr == nullptr) {
283 return false;
284 }
285
286 const istd::IChangeable& sourcePage = docPtr->GetDocumentPage(pageIndex);
287 if (!pagePtr->CopyFrom(sourcePage)) {
288 return false;
289 }
290
291 const idoc::IDocumentMetaInfo* metaInfoPtr = docPtr->GetPageMetaInfo(pageIndex);
292 if (metaInfoPtr != nullptr) {
293 if (!m_documentPages[pageIndex].pageMetaInfo.CopyFrom(*metaInfoPtr)) {
294 return false;
295 }
296 }
297 }
298
299 if (!BaseClass2::CopyFrom(object, mode)) {
300 return false;
301 }
302
303 return true;
304 }
305
306 // copy via idoc::IMultiPageDocumentProvider
307 const idoc::IMultiPageDocumentProvider* docProviderPtr = dynamic_cast<const idoc::IMultiPageDocumentProvider*>(&object);
308 if (docProviderPtr != nullptr) {
309 const idoc::IMultiPageDocument* sourceDocPtr = docProviderPtr->GetDocument();
310 if (sourceDocPtr != nullptr) {
311 // recursive call
312 return CopyFrom(*sourceDocPtr, mode);
313 }
314 }
315
316 return false;
317}
318
319
320template <class Base>
322{
323 ResetPages();
324
325 return true;
326}
327
328
329// protected methods
330
331template <class Base>
333{
334 static iser::CArchiveTag pageTitleTag("PageTitle", "Title of the page", iser::CArchiveTag::Type::Group);
335 static iser::CArchiveTag pageContentTag("PageContent", "The contents of the page", iser::CArchiveTag::Type::Group);
336
337 bool retVal = archive.ProcessObject(pageTitleTag, pageItem.pageMetaInfo);
338
339 iser::ISerializable* serializablePagePtr = dynamic_cast<iser::ISerializable*>(pageItem.pagePtr.get());
340 if (serializablePagePtr != nullptr) {
341 retVal = retVal && archive.ProcessObject(pageContentTag, *serializablePagePtr);
342 }
343 else {
344 qWarning("Page object doesn't support serialization");
345
346 return false;
347 }
348
349 return retVal;
350}
351
352
354
355
356} // namespace idoc
357
358
Implementation of the basic document's meta information.
Interface for document meta-information.
@ MIT_TITLE
Title of the document.
Simple interface for a structured document.
virtual const istd::IChangeable & GetDocumentPage(int pageIndex) const =0
Get the document page.
virtual const idoc::IDocumentMetaInfo * GetPageMetaInfo(int pageIndex) const =0
Get meta info of the given page if exists.
virtual int GetPagesCount() const =0
Get number of pages in the document.
Common interface for a provider of a multi-page document.
virtual const IMultiPageDocument * GetDocument() const =0
Get multi-page document instance.
Generic implementation of IMultiPageDocument interface.
bool IsOptionEnabled(int index) const override
Return true if the option is enabled and can be selected.
bool ResetData(CompatibilityMode mode) override
Reset data to its default state.
bool CopyFrom(const istd::IChangeable &object, CompatibilityMode mode=CM_WITHOUT_REFS) override
Copy this object from another one.
CStandardDocumentMetaInfo BaseClass2
virtual bool SerializePage(iser::IArchive &archive, Page &pageItem)
Serialize a single page item into or from the archive.
bool Serialize(iser::IArchive &archive) override
Load or store state of this object as a archive stream.
bool RemovePage(int pageIndex) override
int GetOptionsFlags() const override
Get constraints flags.
QString GetOptionDescription(int index) const override
Get human readable description for a option with the index index.
QByteArray GetOptionId(int index) const override
Get option ID.
const idoc::IDocumentMetaInfo * GetPageMetaInfo(int pageIndex) const override
const istd::IChangeable & GetDocumentPage(int pageIndex) const override
QString GetOptionName(int index) const override
Get name of specified option.
int GetOptionsCount() const override
Get number of managed options.
const IDocumentMetaInfo & GetDocumentMetaInfo() const override
Constraints of selection from set of possibilities.
Process tag used to group data in archive stream.
Definition CArchiveTag.h:25
@ Group
Normal tag used for grouping of tags or processed elements.
@ Multiple
Multiple tag containing variable number of child tags.
Represent input/output persistence archive.
Definition IArchive.h:34
virtual bool ProcessGroupList(const CArchiveTag &listTag, const CArchiveTag &groupTag, int count, std::function< bool(int, IArchive &)> groupArchiveFn, std::function< bool(int)> resizeFn=nullptr)=0
Process list of elements in groups.
virtual bool ProcessObject(const CArchiveTag &tag, ISerializable &object)=0
Process object enclosed by some tag.
virtual bool ProcessGroup(const CArchiveTag &tag, std::function< bool(IArchive &)> groupArchiveFn)=0
Process some group of elements encapsulated in single tag.
virtual bool IsChanging() const =0
Check if this archive processing change the object state.
Common class for all classes which objects can be archived or restored from archive.
Help class which provides the automatic update mechanism of the model.
Common interface for data model objects, which can be changed.
Definition IChangeable.h:32
CompatibilityMode
Control how relationship betweeen objects are interpreted.
@ CM_WITHOUT_REFS
External references are simple ignored.
virtual bool CopyFrom(const IChangeable &object, CompatibilityMode mode=CM_WITHOUT_REFS)
Copy this object from another one.
Contains the system indenendent basic implementations of Document/View design pattern.
idoc::TMultiPageDocumentWrap< idoc::IMultiPageDocument > CMultiPageDocumentBase
idoc::CStandardDocumentMetaInfo pageMetaInfo
std::unique_ptr< istd::IChangeable > pagePtr

© Witold Gantzke and Kirill Lepskiy