1 /***************************************************************************
2  * SPDX-FileCopyrightText: 2021 S. MANKOWSKI stephane@mankowski.fr
3  * SPDX-FileCopyrightText: 2021 G. DE BURE support@mankowski.fr
4  * SPDX-License-Identifier: GPL-3.0-or-later
5  ***************************************************************************/
6 #ifndef SKGDOCUMENT_H
7 #define SKGDOCUMENT_H
8 /** @file
9  * This file defines classes SKGDocument.
10  *
11  * @author Stephane MANKOWSKI / Guillaume DE BURE
12  */
13 #include <qdatetime.h>
14 #include <qfuturewatcher.h>
15 #include <qhash.h>
16 #include <qicon.h>
17 #include <qsqldatabase.h>
18 #include <qstringlist.h>
19 #include <qvariant.h>
20 
21 #include <functional>
22 
23 #include "skgbasemodeler_export.h"
24 #include "skgobjectbase.h"
25 #include "skgservices.h"
26 
27 class SKGObjectBase;
28 class SKGError;
29 class SKGPropertyObject;
30 class SKGReport;
31 class SKGDocumentPrivate;
32 
33 using FuncSelect = std::function<void (const SKGStringListList&)>;  // NOLINT(whitespace/parens)
34 using FuncExist =  std::function<void (bool)>;  // NOLINT(whitespace/parens)
35 using FuncProgress = std::function<int (int, qint64, const QString&, void*)>;  // NOLINT(whitespace/parens)
36 /**
37 * This class manages skg documents
38 */
39 class SKGBASEMODELER_EXPORT SKGDocument : public QObject
40 {
41     Q_OBJECT
42     Q_CLASSINFO("D-Bus Interface", "org.skg.SKGDocument")
43 
44     using progressFunction = int (*)(int, qint64, const QString&, void*);
45     /**
46      * The unique identifier
47      */
48     Q_PROPERTY(QString uuid READ getUniqueIdentifier NOTIFY modified)
49 
50     /**
51      * The current file name
52      */
53     Q_PROPERTY(QString fileName READ getCurrentFileName NOTIFY modified)
54 
55     /**
56      * To know if the document is read only
57      */
58     Q_PROPERTY(bool readOnly READ isReadOnly NOTIFY modified)
59 
60     /**
61      * To know if the document is modifier
62      */
63     Q_PROPERTY(bool modified READ isFileModified NOTIFY transactionSuccessfullyEnded)
64 
65 public:
66     /**
67      * This enumerate defines a type of modification
68      */
69     enum ModificationType {
70         U, /**< Update */
71         I, /**< Insert */
72         D  /**< Delete */
73     };
74     /**
75      * This enumerate defines a type of modification
76      */
77     Q_ENUM(ModificationType)
78 
79     /**
80      * This enumerate defines a type of message
81      */
82     enum MessageType {
83         Positive,     /**< Positive */
84         Information,  /**< Information */
85         Warning,      /**< Warning */
86         Error,        /**< Error */
87         Hidden        /**< Hidden */
88     };
89 
90     /**
91      * This enumerate defines a type of message
92      */
93     Q_ENUM(MessageType)
94 
95     /**
96      * Describe a modification of an object
97      */
98     struct SKGObjectModification {
99         QString uuid;               /**< The uuid of the object */
100         int id{};                     /**< The id of the object */
101         QString table;              /**< The table of the object */
102         ModificationType type;      /**< The type of modification */
103     };
104 
105     /**
106      * Describe a modification of an object
107      */
108     struct SKGMessage {
109         QString Text;               /**< The text of the message */
110         MessageType Type;           /**< The type of the message */
111         QString Action;             /**< The action associated */
112     };
113 
114     /**
115      * This structure represents a template to display data
116      */
117     struct SKGModelTemplate {
118         QString id;         /**< Identifier of the schema */
119         QString name;       /**< The nls name */
120         QString icon;       /**< The icon */
121         QString schema;     /**< The schema. The format of this string is the following one: attribute name[|visibility Y or N[|size]];attribute name[|visibility Y or N[|size]];... */
122     };
123 
124     /**
125      * A list of SKGModelTemplate ==> SKGModelTemplateList
126      */
127     using SKGModelTemplateList = QVector<SKGModelTemplate>;
128 
129     /**
130      * A list of SKGObjectModification ==> SKGObjectModificationList
131      */
132     using SKGObjectModificationList = QVector<SKGObjectModification>;
133 
134     /**
135      * A list of SKGMessage ==> SKGObjectModificationList
136      */
137     using SKGMessageList = QVector<SKGMessage>;
138 
139     /**
140      * This enumerate defines the direction of the UNDO / REDO mechanism
141      */
142     enum UndoRedoMode {
143         UNDOLASTSAVE,   /**< To do/get an undo=cancel of the last successfully extecuted transactions until last save */
144         UNDO,       /**< To do/get an undo=cancel of the last successfully extecuted transaction */
145         REDO        /**< To do/get a redo=replay the last cancelled transaction */
146     };
147     /**
148      * This enumerate defines the direction of the UNDO / REDO mechanism
149      */
150     Q_ENUM(UndoRedoMode)
151 
152     /**
153      * Constructor
154      */
155     explicit SKGDocument();
156 
157     /**
158      * Destructor
159      */
160     ~SKGDocument() override;
161 
162     /**
163      * Set the callback function to follow the progress of the transaction.
164      * the first parameter is the progress between 0% and 100%.
165      * the callback must return 0 to continue and !=0 to cancel the transaction.
166      * @param iProgressFunction the pointer of the function
167      * @param iData the data for the progress call back
168      * @return an object managing the error
169      *   @see SKGError
170      */
171     virtual SKGError setProgressCallback(FuncProgress iProgressFunction, void* iData);
172 
173     /**
174      * Add a check function at the end of successfully executed transaction.
175      * If an error is returned, the transaction will be cancelled.
176      * @param iCheckFunction the pointer of the function
177      * @return an object managing the error
178      *   @see SKGError
179      */
180     virtual SKGError addEndOfTransactionCheck(SKGError(*iCheckFunction)(SKGDocument*));
181 
182     /**
183      * Get unique identifier
184      * @return the unique identifier
185      */
186     virtual QString getUniqueIdentifier() const;
187 
188     /**
189      * Get database identifier
190      * @return the database identifier
191      */
192     virtual QString getDatabaseIdentifier() const;
193 
194     /**
195      * Get message attached to a transaction.
196      * @param iIdTransaction the identifier of a transaction
197      * @param oMessages the messages
198      * @param iAll to get all message (true) or only non hidden messages (false)
199      * @return an object managing the error
200      *   @see SKGError
201      */
202     virtual SKGError getMessages(int iIdTransaction, SKGMessageList& oMessages, bool iAll = true);
203 
204     /**
205      * Remove all message attached to a transaction.
206      * @param iIdTransaction the identifier of a transaction
207      * @return an object managing the error
208      *   @see SKGError
209      */
210     virtual SKGError removeMessages(int iIdTransaction);
211 
212     /**
213      * Get list of direct modifications done in a transaction
214      * @param iIdTransaction the identifier of a transaction
215      * @param oModifications list of modifications
216      * @return an object managing the error
217      *   @see SKGError
218      */
219     virtual SKGError getModifications(int iIdTransaction, SKGObjectModificationList& oModifications) const;
220 
221     /**
222      * Undo or redo the last transaction.
223      * @param iMode the mode
224      * @return an object managing the error
225      *   @see SKGError
226      */
227     virtual SKGError undoRedoTransaction(UndoRedoMode iMode = SKGDocument::UNDO);
228 
229     /**
230      * Group transactions
231      * @param iFrom the first id transaction of the group, it will be the master of the group.
232      * @param iTo the last id transaction of the group.
233      * @return an object managing the error
234      *   @see SKGError
235      */
236     virtual SKGError groupTransactions(int iFrom, int iTo);
237 
238     /**
239      * Return the number of transaction stored including the current one
240     * @param iMode the mode
241     * @return the number of transaction
242      */
243     virtual int getNbTransaction(UndoRedoMode iMode = SKGDocument::UNDO) const;
244 
245     /**
246      * Return the internal identifier of the transaction
247      * which must be treated for an undo or a redo
248      * @param iMode the mode
249      * @param oName if you want also the name of the transaction
250      * @param oSaveStep if you want also to know if it is a save step
251      * @param oDate if you want also the date of the transaction
252      * @param oRefreshViews if you want also to know if views must be refreshed
253      * @return the internal identifier of the last transaction
254      * 0 if no transaction found
255      */
256     virtual int getTransactionToProcess(UndoRedoMode iMode, QString* oName = nullptr, bool* oSaveStep = nullptr, QDateTime* oDate = nullptr, bool* oRefreshViews = nullptr) const;
257 
258     /**
259      * Return the identifier of the current transaction
260      * @return the internal identifier of the current transaction
261      * 0 if no transaction found
262      */
263     virtual int getCurrentTransaction() const;
264 
265     /**
266      * Return the depth of the current transaction
267      * @return the depth
268      */
269     virtual int getDepthTransaction() const;
270 
271     /**
272      * To know if a transaction is opened or not
273      * @return an object managing the error.
274      *   @see SKGError
275      */
276     virtual SKGError checkExistingTransaction() const;
277 
278     /**
279      * Get the current password.
280      * @return the password
281      */
282     virtual QString getPassword() const;
283 
284     /**
285      * To know if the current document has been modified or not.
286      * @return true: the document has been modified, save is possible/needed.
287      *         false: the document hasn't been modified, save is not needed.
288      */
289     virtual bool isFileModified() const;
290 
291     /**
292      * To know if the document is loaded in read only.
293      * @return true: the document is loaded in read only.
294      *         false: the document is loaded in read write.
295      */
296     virtual bool isReadOnly() const;
297 
298     /**
299      * Return the file name of the current document.
300      * To set it, you must use saveAs.
301      * @return the file name of the current document.
302      */
303     virtual QString getCurrentFileName() const;
304 
305     /**
306      * Set a parameter.
307      * WARNING: This method must be used in a transaction.
308      * @see beginTransaction
309      * @param iName the parameter unique identifier.
310      * @param iValue the parameter value.
311      * @param iFileName the file name.
312      * @param iParentUUID the unique identifier of the object owning this parameter.
313      * @param oObjectCreated the parameter object created. Can be nullptr
314      * @return an object managing the error.
315      *   @see SKGError
316      */
317     virtual SKGError setParameter(const QString& iName, const QString& iValue,
318                                   const QString& iFileName = QString(),
319                                   const QString& iParentUUID = QStringLiteral("document"),
320                                   SKGPropertyObject* oObjectCreated = nullptr) const;
321 
322     /**
323      * Set a parameter.
324      * WARNING: This method must be used in a transaction.
325      * @see beginTransaction
326      * @param iName the parameter unique identifier.
327      * @param iValue the parameter value.
328      * @param iBlob the parameter blob.
329      * @param iParentUUID the unique identifier of the object owning this parameter.
330      * @param oObjectCreated the parameter object created. Can be nullptr
331      * @return an object managing the error.
332      *   @see SKGError
333      */
334     virtual SKGError setParameter(const QString& iName, const QString& iValue,
335                                   const QVariant& iBlob,
336                                   const QString& iParentUUID = QStringLiteral("document"),
337                                   SKGPropertyObject* oObjectCreated = nullptr) const;
338 
339     /**
340      * Get the list of parameters
341      * @param iParentUUID the unique identifier of the object owning parameters.
342      * @param iWhereClause the additional where clause.
343      * @return the list of parameters.
344      */
345     virtual QStringList getParameters(const QString& iParentUUID, const QString& iWhereClause = QString());
346 
347     /**
348      * Get a parameter value
349      * @param iName the parameter unique identifier.
350      * @param iParentUUID the unique identifier of the object owning this parameter.
351      * @return the value.
352      */
353     virtual QString getParameter(const QString& iName, const QString& iParentUUID = QStringLiteral("document")) const;
354 
355     /**
356      * Get a parameter blob
357      * @param iName the parameter unique identifier.
358      * @param iParentUUID the unique identifier of the object owning this parameter.
359      * @return the blob.
360      */
361     virtual QVariant getParameterBlob(const QString& iName, const QString& iParentUUID = QStringLiteral("document")) const;
362 
363     /**
364      * Get the database pointer.
365      * This is the database connection of the main thread
366      * @return the database pointer.
367      *   MUST NOT BE REMOVED
368      */
369     QSqlDatabase* getMainDatabase() const;
370 
371     /**
372      * Get the database pointer.
373      * This is the database connection of the current thread
374      * @return the database pointer.
375      */
376     virtual QSqlDatabase getThreadDatabase() const;
377 
378     /**
379      * dump the document in the std output.
380      * It is useful for debug.
381      * @param iMode the select what you want to dump.
382      * @code
383      * document->dump (DUMPPARAMETERS|DUMPTRANSACTIONS);
384      * @endcode
385      * @return an object managing the error.
386      *   @see SKGError
387      */
388     virtual SKGError dump(int iMode = DUMPPARAMETERS | DUMPTRANSACTIONS) const;
389 
390     /**
391      * Create a consolidated view
392      * @param iTable Table name
393      * @param iAsColumn Attribute used as column names
394      * @param iAsRow Attribute used as lines names
395      * @param iAttribute Attribute
396      * @param iOpAtt Operation to apply on @p iAttribute
397      * @param iWhereClause Where clause
398      * @param oTable the consolidated view
399      * @param iMissingValue value to put if no value found
400      * @return an object managing the error.
401      *   @see SKGError
402      */
403     virtual SKGError getConsolidatedView(const QString& iTable,
404                                          const QString& iAsColumn,
405                                          const QString& iAsRow,
406                                          const QString& iAttribute,
407                                          const QString& iOpAtt,
408                                          const QString& iWhereClause,
409                                          SKGStringListList& oTable,
410                                          const QString& iMissingValue = QStringLiteral("0")) const;
411 
412     /**
413      * Get the display string for any modeler object (table, attribute)
414      * @param iString the name of the object (example: v_operation, v_unit.t_name)
415      * @return the display string
416      */
417     virtual QString getDisplay(const QString& iString) const;
418 
419     /**
420      * Get display schemas
421      * @param iRealTable the real table name
422      * @return list of schemas
423      */
424     virtual SKGDocument::SKGModelTemplateList getDisplaySchemas(const QString& iRealTable) const;
425 
426     /**
427      * Get the icon for attribute
428      * @param iString the name of the attribute
429      * @return the icon name
430      */
431     virtual QString getIconName(const QString& iString) const;
432 
433     /**
434      * Get the icon for attribute
435      * @param iString the name of the attribute
436      * @return the icon
437      */
438     virtual QIcon getIcon(const QString& iString) const;
439 
440     /**
441      * Get the real attribute
442      * @param iString the name of the attribute (something like t_BANK)
443      * @return the real attribute (something like bank.rd_bank_id.t_name)
444      */
445     virtual QString getRealAttribute(const QString& iString) const;
446 
447     /**
448      * Get the attribute type
449      * @param iAttributeName the name of an attribute
450      * @return the type
451      */
452     virtual SKGServices::AttributeType getAttributeType(const QString& iAttributeName) const;
453 
454     /**
455      * Get unit. WARNING: This value can be not uptodated in a transaction.
456      * @param iPrefixInCache the prefix of the unit in the cache
457      * @return unit.
458      */
459     virtual SKGServices::SKGUnitInfo getUnit(const QString& iPrefixInCache) const;
460 
461     /**
462      * Get the cached sql result
463      * @param iKey key
464      * @return the sql result
465      */
466     virtual SKGStringListList getCachedSqlResult(const QString& iKey) const;
467 
468     /**
469      * Get the cached value
470      * @param iKey key
471      * @return the value
472      */
473     virtual QString getCachedValue(const QString& iKey) const;
474 
475     /**
476      * Get the corresponding backup file
477      * @param iFileName the file to save
478      * @return the corresponding backup file
479      */
480     virtual QString getBackupFile(const QString& iFileName) const;
481 
482     /**
483      * Get the temporary file for a file
484      * @param iFileName the file
485      * @param iForceReadOnly force the read only mode
486      * @return the temporary file
487      */
488     static QString getTemporaryFile(const QString& iFileName, bool iForceReadOnly = false);
489 
490     /**
491      * Get the temporary file for a document
492      * @return the temporary file
493      */
494     virtual QString getCurrentTemporaryFile() const;
495 
496     /**
497      * Get the file extension for this kind of document (must be overwritten)
498      * @return file extension (like skg)
499      */
500     virtual QString getFileExtension() const;
501 
502     /**
503      * Get the header of the file (useful for magic mime type).
504      * @return document header
505      */
506     virtual QString getDocumentHeader() const;
507 
508     /**
509      * Return a number of objects (@p oNbObjects) corresponding to a where clause (@p iWhereClause )
510      * @param iTable the table where to search
511      * @param iWhereClause the where clause
512      * @param oNbObjects the result
513      * @return an object managing the error
514      *   @see SKGError
515      */
516     virtual SKGError getNbObjects(const QString& iTable, const QString& iWhereClause, int& oNbObjects) const;
517 
518     /**
519      * To execute a function when at least one object exist corresponding to a where clause (@p iWhereClause)
520      * @param iTable the table where to search
521      * @param iWhereClause the where clause
522      * @param iFunction the function to call
523      * @param iExecuteInMainThread to execute the function in the main thread or not
524      */
525     virtual void concurrentExistObjects(const QString& iTable, const QString& iWhereClause, const FuncExist& iFunction, bool iExecuteInMainThread = true);
526 
527     /**
528      * To know if at least one object exist corresponding to a where clause (@p iWhereClause)
529      * @param iTable the table where to search
530      * @param iWhereClause the where clause
531      * @param oExist the result
532      * @return an object managing the error
533      *   @see SKGError
534      */
535     virtual SKGError existObjects(const QString& iTable, const QString& iWhereClause, bool& oExist) const;
536 
537     /**
538      * Return a list of objects (@p oListObject) corresponding to a where clause (@p iWhereClause )
539      * @param iTable the table where to search
540      * @param iWhereClause the where clause
541      * @param oListObject the result
542      * @return an object managing the error
543      *   @see SKGError
544      */
545     virtual SKGError getObjects(const QString& iTable, const QString& iWhereClause, SKGObjectBase::SKGListSKGObjectBase& oListObject) const;
546 
547     /**
548      * Return the object (@p oObject) corresponding to a where clause (@p iWhereClause ).
549      * If more than one objects are returned by the query, then an error is generated
550      * If 0 object is returned by the query, then an error is generated
551      * @param iTable the table where to search
552      * @param iWhereClause the where clause
553      * @param oObject the result
554      * @return an object managing the error
555      *   @see SKGError
556      */
557     virtual SKGError getObject(const QString& iTable, const QString& iWhereClause, SKGObjectBase& oObject) const;
558 
559     /**
560      * Return the object (@p oObject) corresponding to an id (@p iId ).
561      * If more than one objects are returned by the query, then an error is generated
562      * If 0 object is returned by the query, then an error is generated
563      * @param iTable the table where to search
564      * @param iId id of the object in @p iTable
565      * @param oObject the result
566      * @return an object managing the error
567      *   @see SKGError
568      */
569     virtual SKGError getObject(const QString& iTable, int iId, SKGObjectBase& oObject) const;
570 
571     /**
572      * Retrieve list of tables
573      * @param oResult the output result
574      * @return An object managing the error
575      *   @see SKGError
576      */
577     virtual SKGError getTablesList(QStringList& oResult) const;
578 
579     /**
580      * Retrieve all distinct values of an attribute of a table
581      * @param iTable the table where to look for
582      * @param iAttribute the attribute wanted (only one)
583      * @param iWhereClause a whereclause
584      * @param oResult the output result
585      * @return An object managing the error
586      *   @see SKGError
587      */
588     virtual SKGError getDistinctValues(const QString& iTable, const QString& iAttribute, const QString& iWhereClause, QStringList& oResult) const;
589 
590     /**
591      * Retrieve all distinct values of an attribute of a table
592      * @param iTable the table where to look for
593      * @param iAttribute the attribute wanted (only one)
594      * @param oResult the output result
595      * @return An object managing the error
596      *   @see SKGError
597      */
598     virtual SKGError getDistinctValues(const QString& iTable, const QString& iAttribute, QStringList& oResult) const;
599 
600     /**
601      * Execute a sqlite orders
602      * @param iSqlOrders the sql orders
603      * @return An object managing the error
604      *   @see SKGError
605      */
606     virtual SKGError executeSqliteOrders(const QStringList& iSqlOrders) const;
607 
608     /**
609      * Execute a sqlite order
610      * @param iSqlOrder the sql order
611      * @param iBind the binded variables and values
612      * @param iLastId to retrieve the id of the last created object
613      * @return An object managing the error
614      *   @see SKGError
615      */
616     virtual SKGError executeSqliteOrder(const QString& iSqlOrder, const QMap<QString, QVariant>& iBind, int* iLastId) const;
617 
618     /**
619      * Execute a sqlite order
620      * @param iSqlOrder the sql order
621      * @param iLastId to retrieve the id of the last created object. Can be nullptr
622      * @return An object managing the error
623      *   @see SKGError
624      */
625     virtual SKGError executeSqliteOrder(const QString& iSqlOrder, int* iLastId) const;
626 
627     /**
628      * Execute a sqlite order
629      * @param iSqlOrder the sql order
630      * @return An object managing the error
631      *   @see SKGError
632      */
633     virtual SKGError executeSqliteOrder(const QString& iSqlOrder) const;
634 
635     /**
636      * Execute a select sqlite order returning one value and return the result in @p oResult
637      * @param iSqlOrder the sql order
638      * @param oResult the result of the select
639      * @param iUseCache to use the cache
640      * @return An object managing the error
641      *   @see SKGError
642      */
643     virtual SKGError executeSingleSelectSqliteOrder(const QString& iSqlOrder, QString& oResult, bool iUseCache = true) const;
644 
645     /**
646     * Execute a select sqlite order and return the result in @p oResult
647     * @param iSqlOrder the sql order
648     * @param oResult the result of the select. It is a vector of vector of QString
649     * @param iUseCache to use the cache
650     * @return An object managing the error
651     *   @see SKGError
652     */
653     virtual SKGError executeSelectSqliteOrder(const QString& iSqlOrder, SKGStringListList& oResult, bool iUseCache = true) const;
654 
655 
656     /**
657     * Execute a select sqlite order and pass the result to the function @p iFunction. This is done in another thread.
658     * @param iSqlOrder the sql order
659     * @param iFunction the function to call
660     * @param iExecuteInMainThread to execute the function in the main thread or not
661     */
662     virtual void concurrentExecuteSelectSqliteOrder(const QString& iSqlOrder, const FuncSelect& iFunction, bool iExecuteInMainThread = true) const;
663 
664     /**
665     * dump a select sqlite order
666     * @param iSqlOrder the sql order
667     * @param oStream the output stream, nullptr for std output (cout)
668     * @param iMode dump mode
669     * @return An object managing the error
670     *   @see SKGError
671     */
672     virtual SKGError dumpSelectSqliteOrder(const QString& iSqlOrder, QTextStream* oStream = nullptr, SKGServices::DumpMode iMode = SKGServices::DUMP_TEXT) const;
673 
674     /**
675      * dump a select sqlite order
676      * @param iSqlOrder the sql order
677      * @param oResult the output
678      * @param iMode dump mode
679      * @return An object managing the error
680      *   @see SKGError
681      */
682     virtual SKGError dumpSelectSqliteOrder(const QString& iSqlOrder, QString& oResult, SKGServices::DumpMode iMode = SKGServices::DUMP_TEXT) const;
683 
684     /**
685      * dump a select sqlite order
686      * @param iSqlOrder the sql order
687      * @param oResult the output
688      * @param iMode dump mode
689      * @return An object managing the error
690      *   @see SKGError
691      */
692     virtual SKGError dumpSelectSqliteOrder(const QString& iSqlOrder, QStringList& oResult, SKGServices::DumpMode iMode = SKGServices::DUMP_TEXT) const;
693 
694     /**
695      * Retrieve description of each attribute of a table
696      * @param iTable the table where to look for
697      * @param oResult the output result
698      * @return An object managing the error
699      *   @see SKGError
700      */
701     virtual SKGError getAttributesDescription(const QString& iTable, SKGServices::SKGAttributesList& oResult) const;
702 
703     /**
704      * Retrieve list of attributes
705      * @param iTable the table where to look for
706      * @param oResult the output result
707      * @return An object managing the error
708      *   @see SKGError
709      */
710     virtual SKGError getAttributesList(const QString& iTable, QStringList& oResult) const;
711 
712     /**
713      * Get the report
714      * Do not forget to delete the pointer
715      * @return the report
716      */
717     virtual SKGReport* getReport() const;
718 
719     /**
720      * Copy a document into an JSON document.
721      * @param oDocument the json document
722      * @return An object managing the error
723      *   @see SKGError
724      */
725     virtual SKGError copyToJson(QString& oDocument) const;
726 
727     /**
728      * Refresh all views and indexes in the database
729      * @param iForce force the refresh
730      * @return an object managing the error.
731      *   @see SKGError
732      */
733     virtual SKGError refreshViewsIndexesAndTriggers(bool iForce = false) const;
734 
735     /**
736      * Get formated money
737      * @param iValue value
738      * @param iUnit unit
739      * @param iHtml colored output
740      * @return formated value in red or black
741      */
742     Q_INVOKABLE virtual QString formatMoney(double iValue, const SKGServices::SKGUnitInfo& iUnit, bool iHtml = true) const;
743 
744     /**
745      * Get formated money in primary unit
746      * @param iValue value
747      * @return formated value in red or black
748      */
749     Q_INVOKABLE virtual QString formatPrimaryMoney(double iValue) const;
750 
751     /**
752      * Get formated money in primary unit
753      * @param iValue value
754      * @return formated value in red or black
755      */
756     Q_INVOKABLE virtual QString formatSecondaryMoney(double iValue) const;
757 
758     /**
759      * Get formated percentage
760      * @param iValue value
761      * @param iInvertColors to set positive value in red and negative values in green
762      * @return formated value in red or black
763      */
764     Q_INVOKABLE virtual QString formatPercentage(double iValue, bool iInvertColors = false) const;
765 
766 public Q_SLOTS:
767 
768     /**
769      * Call the progress callstack.
770      * @param iPosition the position in the current transaction.
771      * The value must be between 0 and the value passed to beginTransaction.
772      * @param iText the text to display. If empty then the name of the last transaction is used.
773      * @return an object managing the error
774      *   @see SKGError
775      */
776     virtual SKGError stepForward(int iPosition, const QString& iText = QString());
777 
778     /**
779      * Start a transaction.
780      * A transaction is needed to modify the SKGDocument.
781      * This transaction is also used to manage the undo/redo.
782      * @see endTransaction
783      * @param iName the name of the transaction
784      * @param iNbStep the number of step in this transaction.
785      * It is used to call the progress callback.
786      * @param iDate date of the transaction.
787      * @param iRefreshViews at the end of the transaction, computed views will be recomputed.
788      * @return an object managing the error
789      *   @see SKGError
790      */
791     virtual SKGError beginTransaction(const QString& iName,
792                                       int iNbStep = 0,
793                                       const QDateTime& iDate = QDateTime::currentDateTime(),
794                                       bool iRefreshViews = true);
795 
796     /**
797      * Close the current transaction.
798      * A transaction is needed to modify the SKGDocument.
799      * This transaction is also used to manage the undo/redo.
800      * @see beginTransaction
801      * @param succeedded : true to indicate that current transaction has been successfully executed
802      *                   : false to indicate that current transaction has failed
803      * @return an object managing the error
804      *   @see SKGError
805      */
806     virtual SKGError endTransaction(bool succeedded);
807 
808     /**
809      * Remove all transactions of the history.
810      * @return an object managing the error
811      *   @see SKGError
812      */
813     virtual SKGError removeAllTransactions();
814 
815     /**
816      * Send a message attached to the current transaction.
817      * @param iMessage the message
818      * @param iMessageType the message type
819      * @param iAction the associated action
820      * @return an object managing the error
821      *   @see SKGError
822      */
823     virtual SKGError sendMessage(const QString& iMessage, SKGDocument::MessageType iMessageType = SKGDocument::Information, const QString& iAction = QString());
824 
825     /**
826      * Change the passord of the document.
827      * WARNING: This method must NOT be used in a transaction.
828      * @see beginTransaction
829      * @param iNewPassword the new password
830      * @return an object managing the error
831      *   @see SKGError
832      */
833     virtual SKGError changePassword(const QString& iNewPassword);
834 
835     /**
836      * Change the language of the document.
837      * @param iLanguage the new language
838      * @return an object managing the error
839      *   @see SKGError
840      */
841     virtual SKGError setLanguage(const QString& iLanguage);
842 
843     /**
844      * Initialize a new document.
845      * WARNING: This method must NOT be used in a transaction.
846      * @see endTransaction
847      * @return an object managing the error
848      *   @see SKGError
849      */
850     virtual SKGError initialize();
851 
852     /**
853      * Recover a corrupted file.
854      * WARNING: This method must NOT be used in a transaction.
855      * @see endTransaction
856      * @param iName the file name to load.
857      * @param iPassword the password of the SKGDocument.
858      * @param oRecoveredFile the recovered file.
859      * @return an object managing the error.
860      *   @see SKGError
861      */
862     virtual SKGError recover(const QString& iName, const QString& iPassword, QString& oRecoveredFile);
863 
864     /**
865      * Load an existing document.
866      * WARNING: This method must NOT be used in a transaction.
867      * @see endTransaction
868      * @param iName the file name to load.
869      * @param iPassword the password of the SKGDocument.
870      * @param iRestoreTmpFile restore the temporary file if existing.
871      * @param iForceReadOnly force the read only mode.
872      * @return an object managing the error.
873      *   @see SKGError
874      */
875     virtual SKGError load(const QString& iName, const QString& iPassword = QString(), bool iRestoreTmpFile = false, bool iForceReadOnly = false);
876 
877     /**
878      * Set the file not modified.
879      */
880     virtual void setFileNotModified() const;
881 
882     /**
883      * save the current SKGDocument.
884      * WARNING: This method must NOT be used in a transaction.
885      * @see endTransaction.
886      * @return an object managing the error.
887      *   @see SKGError
888      */
889     virtual SKGError save();
890 
891     /**
892      * save the current SKGDocument.
893      * WARNING: This method must NOT be used in a transaction.
894      * @see endTransaction
895      * @param iName the file name to save.
896      * @param iOverwrite to authorize the overwrite or not.
897      * @return an object managing the error.
898      *   @see SKGError
899      */
900     virtual SKGError saveAs(const QString& iName, bool iOverwrite = false);
901 
902     /**
903      * close the current SKGDocument.
904      * @return an object managing the error.
905      *   @see SKGError
906      */
907     SKGError close();
908 
909     /**
910      * Add a sql result in the cache. Cache is cleaned after each transaction
911      * @param iKey the key
912      * @param iValue the sql result
913      */
914     virtual void addSqlResultInCache(const QString& iKey, const SKGStringListList& iValue) const;
915 
916     /**
917      * Add a value in the cache. Cache is cleaned after each transaction
918      * @param iKey the key
919      * @param iValue the value
920      */
921     virtual void addValueInCache(const QString& iKey, const QString& iValue) const;
922 
923     /**
924      * Refresh the case.
925      * @param iTable the modified table triggering the cache refresh.
926      */
927     virtual void refreshCache(const QString& iTable) const;
928 
929     /**
930      * Set backup parameters.
931      * The key word \<DATE\> is supported.
932      * Call setBackupParameters() to avoid backup creation.
933      * @param iPrefix the prefix for the backup file
934      * @param iSuffix the suffix for backup file
935      */
936     void setBackupParameters(const QString& iPrefix = QString(), const QString& iSuffix = QString()) const;
937 
938 Q_SIGNALS:
939     /**
940      * This signal is launched by endTransaction on all tables modified when a huge modification occures on the model
941      * @param iTableName the name of the modified table. iTableName="" if all tables must be refreshed
942      * @param iIdTransaction the id of the transaction for direct modifications of the table (update of modify objects is enough)
943      * @param iLightTransaction to if the transaction is light
944      *or 0 in case of modifications by impact (full table must be refreshed)
945      */
946     void tableModified(const QString& iTableName, int iIdTransaction, bool iLightTransaction);
947 
948     /**
949      * This signal is launched by endTransaction when a transaction is successfully ended
950      * @param iIdTransaction the id of the transaction for direct modifications of the table (update of modify objects is enough)
951      */
952     void transactionSuccessfullyEnded(int iIdTransaction);
953 
954     /**
955      * This signal is launched when the status of the document is changed (read only, modified)
956      */
957     void modified();
958 
959 protected:
960     /**
961      * Drop views and indexes attached to a list of tables
962      * @param iTables the list of tables.
963      * @return an object managing the error.
964      *   @see SKGError
965      */
966     virtual SKGError dropViewsAndIndexes(const QStringList& iTables) const;
967 
968     /**
969      * Migrate the current SKGDocument to the latest version of the data model.
970      * WARNING: This method must be used in a transaction.
971      * @see beginTransaction
972      * @param oMigrationDone to know if a migration has been done or not.
973      * @return an object managing the error.
974      *   @see SKGError
975      */
976     virtual SKGError migrate(bool& oMigrationDone);
977 
978     /**
979      * Create dynamic triggers for "undoable" tables.
980      * @return an object managing the error.
981      *   @see SKGError
982      */
983     virtual SKGError createUndoRedoTemporaryTriggers() const;
984 
985     /**
986      * This list must contain a list of object
987      * where the undo / redo is NOT applicable.
988      * For a full table, the syntax is: T.nameofthetable
989      * For an attribute, the syntax is: A.nameofthetable.nameoftheattribute
990      */
991     QStringList SKGListNotUndoable;
992 
993     /**
994      * Get impacted views if one object of @p iTable is modifier.
995      * @param iTable name of a table
996      * @return impacted views
997      */
998     virtual QStringList getImpactedViews(const QString& iTable) const;
999 
1000     /**
1001      * Compute all materialized views.
1002      * @param iTable Compute only materialized views linked to this table. If empty then compute all materialized views
1003      * @return an object managing the error.
1004      *   @see SKGError
1005      */
1006     virtual SKGError computeMaterializedViews(const QString& iTable = QString()) const;
1007 
1008 private:
1009     Q_DISABLE_COPY(SKGDocument)
1010 
1011     SKGMessageList m_unTransactionnalMessages;
1012     SKGDocumentPrivate* d;
1013 };
1014 /**
1015  * Declare the class
1016  */
1017 Q_DECLARE_TYPEINFO(SKGDocument, Q_MOVABLE_TYPE);
1018 #endif
1019