1 /***************************************************************************
2  *   This file is part of the Lime Report project                          *
3  *   Copyright (C) 2015 by Alexander Arin                                  *
4  *   arin_a@bk.ru                                                          *
5  *                                                                         *
6  **                   GNU General Public License Usage                    **
7  *                                                                         *
8  *   This library is free software: you can redistribute it and/or modify  *
9  *   it under the terms of the GNU General Public License as published by  *
10  *   the Free Software Foundation, either version 3 of the License, or     *
11  *   (at your option) any later version.                                   *
12  *   You should have received a copy of the GNU General Public License     *
13  *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
14  *                                                                         *
15  **                  GNU Lesser General Public License                    **
16  *                                                                         *
17  *   This library is free software: you can redistribute it and/or modify  *
18  *   it under the terms of the GNU Lesser General Public License as        *
19  *   published by the Free Software Foundation, either version 3 of the    *
20  *   License, or (at your option) any later version.                       *
21  *   You should have received a copy of the GNU Lesser General Public      *
22  *   License along with this library.                                      *
23  *   If not, see <http://www.gnu.org/licenses/>.                           *
24  *                                                                         *
25  *   This library is distributed in the hope that it will be useful,       *
26  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
27  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
28  *   GNU General Public License for more details.                          *
29  ****************************************************************************/
30 #ifndef LRDATADESIGNINTF_H
31 #define LRDATADESIGNINTF_H
32 
33 #include <QObject>
34 #include <QMap>
35 #include <QAbstractItemModel>
36 #include <QStandardItemModel>
37 #include <QtSql/QSqlQuery>
38 #include <QDebug>
39 #include <QSharedPointer>
40 #include <QSortFilterProxyModel>
41 #include <QVariant>
42 #include "lrcollection.h"
43 #include "lrcallbackdatasourceintf.h"
44 #include "lrdatasourceintf.h"
45 
46 namespace LimeReport{
47 
48 class DataSourceManager;
49 
50 class ModelHolder: public QObject, public IDataSourceHolder{
51     Q_OBJECT
52 public:
53     ModelHolder(QAbstractItemModel* model, bool owned=false);
54     ~ModelHolder();
55     IDataSource* dataSource(IDataSource::DatasourceMode mode);
isOwned()56     bool isOwned() const { return m_owned; }
isInvalid()57     bool isInvalid() const { return m_dataSource->isInvalid(); }
lastError()58     QString lastError() const { return m_dataSource->lastError(); }
isEditable()59     bool isEditable() const { return false; }
isRemovable()60     bool isRemovable() const { return false; }
61     void invalidate(IDataSource::DatasourceMode mode, bool dbWillBeClosed = false){Q_UNUSED(mode) Q_UNUSED(dbWillBeClosed)}
update()62     void update(){}
clearErrors()63     void clearErrors(){}
64 signals:
65     void modelStateChanged();
66 private:
67     IDataSource* m_dataSource;
68     bool m_owned;
69 };
70 
71 class ConnectionDesc : public QObject{
72     Q_OBJECT
73     Q_PROPERTY(QString name READ name WRITE setName )
74     Q_PROPERTY(QString driver READ driver WRITE setDriver)
75     Q_PROPERTY(QString databaseName READ databaseName WRITE setDatabaseName)
76     Q_PROPERTY(QString userName READ userName WRITE setUserName)
77     Q_PROPERTY(QString password READ password WRITE setPassword)
78     Q_PROPERTY(QString host READ host WRITE setHost)
79     Q_PROPERTY(bool autoconnect READ autoconnect WRITE setAutoconnect)
80     Q_PROPERTY(bool keepDBCredentials READ keepDBCredentials WRITE setKeepDBCredentials)
81     Q_PROPERTY(int port READ port WRITE setPort)
82 public:
83     typedef QSharedPointer<ConnectionDesc> Ptr;
84     ConnectionDesc(QSqlDatabase db, QObject* parent=0);
85     ConnectionDesc(QObject* parent=0);
86     Ptr create(QSqlDatabase db, QObject* parent=0);
87     void    setName(const QString &value);
name()88     QString name(){return m_connectionName;}
setDriver(const QString & value)89     void    setDriver(const QString &value){m_connectionDriver=value;}
driver()90     QString driver(){return m_connectionDriver;}
setHost(const QString & value)91     void    setHost(const QString &value){m_connectionHost=value;}
host()92     QString host(){return m_connectionHost;}
setDatabaseName(const QString & value)93     void    setDatabaseName(const QString &value){m_databaseName=value;}
databaseName()94     QString databaseName(){return m_databaseName;}
setUserName(const QString & value)95     void    setUserName(const QString &value){m_user=value;}
userName()96     QString userName(){ return m_user; }
setPassword(const QString & value)97     void    setPassword(const QString &value){m_password=value;}
password()98     QString password(){ return m_password; }
setAutoconnect(bool value)99     void    setAutoconnect(bool value){m_autoconnect=value;}
autoconnect()100     bool    autoconnect(){return m_autoconnect;}
101     bool    isEqual(const QSqlDatabase& db);
isInternal()102     bool    isInternal(){ return m_internal; }
setInternal(bool value)103     void    setInternal(bool value) {m_internal = value;}
104     bool    keepDBCredentials() const;
105     void    setKeepDBCredentials(bool keepDBCredentials);
106     int     port() const;
107     void    setPort(int port);
108 public:
109     static QString connectionNameForUser(const QString& connectionName);
110     static QString connectionNameForReport(const QString& connectionName);
111 signals:
112     void nameChanged(const QString& oldName,const QString& newName);
113 private:
114     QString m_connectionName;
115     QString m_connectionHost;
116     QString m_connectionDriver;
117     QString m_databaseName;
118     QString m_user;
119     QString m_password;
120     int     m_port;
121     bool    m_autoconnect;
122     bool    m_internal;
123     bool    m_keepDBCredentials;
124 };
125 
126 class IConnectionController{
127 public:
128     virtual void addConnectionDesc(ConnectionDesc* connection) = 0;
129     virtual void changeConnectionDesc(ConnectionDesc* connection) = 0;
130     virtual bool checkConnectionDesc(ConnectionDesc* connection) = 0;
131     virtual bool containsDefaultConnection() = 0;
132     virtual QString lastError() const = 0;
133 };
134 
135 class CSVDesc: public QObject{
136     Q_OBJECT
Q_PROPERTY(QString name READ name WRITE setName)137     Q_PROPERTY(QString name READ name WRITE setName)
138     Q_PROPERTY(QString csvText READ csvText WRITE setCsvText)
139     Q_PROPERTY(QString separator READ separator WRITE setSeparator)
140     Q_PROPERTY(bool firstRowIsHeader READ firstRowIsHeader WRITE setFirstRowIsHeader)
141 public:
142     CSVDesc(const QString name, const QString csvText, QString separator, bool firstRowIsHeader)
143         : m_csvName(name), m_csvText(csvText), m_separator(separator), m_firstRowIsHeader(firstRowIsHeader){}
QObject(parent)144     explicit CSVDesc(QObject* parent = 0):QObject(parent) {}
145     QString name() const;
146     void setName(const QString &name);
147     QString csvText() const;
148     void setCsvText(const QString &csvText);
149     QString separator() const;
150     void setSeparator(const QString &separator);
151     bool firstRowIsHeader() const;
152     void setFirstRowIsHeader(bool firstRowIsHeader);
153 signals:
154     void cvsTextChanged(const QString& cvsName, const QString& cvsText);
155 private:
156     QString m_csvName;
157     QString m_csvText;
158     QString m_separator;
159     bool m_firstRowIsHeader;
160 };
161 
162 class CSVHolder: public IDataSourceHolder{
163 public:
164     CSVHolder(const CSVDesc& desc, DataSourceManager* dataManager);
165     void setCSVText(QString csvText);
csvText()166     QString csvText() { return m_csvText;}
167     QString separator() const;
168     void setSeparator(const QString &separator);
169     bool firsRowIsHeader() const;
170     void setFirsRowIsHeader(bool firstRowIsHeader);
171     // IDataSourceHolder interface
172 public:
173     IDataSource *dataSource(IDataSource::DatasourceMode mode = IDataSource::RENDER_MODE);
lastError()174     QString lastError() const {return "";}
isInvalid()175     bool isInvalid() const {return false;}
isOwned()176     bool isOwned() const {return true;}
isEditable()177     bool isEditable() const {return true;}
isRemovable()178     bool isRemovable() const {return true;}
invalidate(IDataSource::DatasourceMode,bool)179     void invalidate(IDataSource::DatasourceMode /*mode*/, bool /*dbWillBeClosed*/){ updateModel();}
update()180     void update(){ updateModel(); }
clearErrors()181     void clearErrors(){}
182 private:
183     void updateModel();
184 private:
185     QString m_csvText;
186     QStandardItemModel m_model;
187     QString m_separator;
188     IDataSource::Ptr m_dataSource;
189     DataSourceManager* m_dataManager;
190     bool m_firstRowIsHeader;
191 };
192 
193 class QueryDesc : public QObject{
194     Q_OBJECT
195     Q_PROPERTY(QString queryName READ queryName WRITE setQueryName)
196     Q_PROPERTY(QString queryText READ queryText WRITE setQueryText)
197     Q_PROPERTY(QString connectionName READ connectionName WRITE setConnectionName)
198 public:
199     QueryDesc(QString queryName, QString queryText, QString connection);
QObject(parent)200     explicit QueryDesc(QObject* parent=0):QObject(parent){}
setQueryName(QString value)201     void    setQueryName(QString value){m_queryName=value;}
queryName()202     QString queryName() const {return m_queryName;}
setQueryText(QString value)203     void    setQueryText(QString value){m_queryText=value; emit queryTextChanged(m_queryName, m_queryText);}
queryText()204     QString queryText() const {return m_queryText;}
setConnectionName(QString value)205     void    setConnectionName(QString value){m_connectionName=value;}
connectionName()206     QString connectionName() const {return m_connectionName;}
207 signals:
208     void queryTextChanged(const QString& queryName, const QString& queryText);
209 private:
210     QString m_queryName;
211     QString m_queryText;
212     QString m_connectionName;
213 };
214 
215 class QueryHolder:public IDataSourceHolder{
216 public:
217     QueryHolder(QString queryText, QString connectionName, DataSourceManager* dataManager);
218     ~QueryHolder();
219     virtual bool runQuery(IDataSource::DatasourceMode mode = IDataSource::RENDER_MODE);
220     IDataSource* dataSource(IDataSource::DatasourceMode mode = IDataSource::RENDER_MODE);
221     QString connectionName();
222     QString queryText();
223     void setQueryText(QString queryText);
224     void setConnectionName(QString connectionName);
isOwned()225     bool isOwned() const { return true; }
isInvalid()226     bool isInvalid() const { return !m_lastError.isEmpty(); }
isEditable()227     bool isEditable() const { return true; }
isRemovable()228     bool isRemovable() const { return true; }
isPrepared()229     bool isPrepared() const {return m_prepared;}
lastError()230     QString lastError() const { return m_lastError; }
setLastError(QString value)231     void setLastError(QString value){m_lastError=value;}
232     void invalidate(IDataSource::DatasourceMode mode, bool dbWillBeClosed = false);
233     void update();
clearErrors()234     void clearErrors(){setLastError("");}
dataManager()235     DataSourceManager* dataManager() const {return m_dataManager;}
236 protected:
237     void setDatasource(IDataSource::Ptr value);
setPrepared(bool prepared)238     void setPrepared(bool prepared){ m_prepared = prepared;}
239     virtual void fillParams(QSqlQuery* query);
240     virtual void extractParams();
241     QString replaceVariables(QString query);
242     QMap<QString,QString> m_aliasesToParam;
243     QString m_preparedSQL;
244 private:
245     QString m_queryText;
246     QString m_connectionName;
247     QString m_lastError;
248     IDataSource::Ptr m_dataSource;
249     IDataSource::DatasourceMode m_mode;
250     DataSourceManager* m_dataManager;
251     bool m_prepared;
252 };
253 
254 class SubQueryDesc : public QueryDesc{
255     Q_OBJECT
256     Q_PROPERTY(QString master READ master WRITE setMaster)
257 public:
258     SubQueryDesc(QString queryName, QString queryText, QString connection, QString master);
QueryDesc(parent)259     explicit SubQueryDesc(QObject* parent=0):QueryDesc(parent){}
setMaster(QString value)260     void setMaster(QString value){m_masterDatasourceName=value;}
master()261     QString master(){return m_masterDatasourceName;}
262 private:
263     QString m_masterDatasourceName;
264 };
265 
266 class SubQueryHolder:public QueryHolder{
267 public:
268     SubQueryHolder(QString queryText, QString connectionName, QString masterDatasource, DataSourceManager *dataManager);
masterDatasource()269     QString masterDatasource(){return m_masterDatasource;}
270     void setMasterDatasource(const QString& value);
271     //void invalidate(){m_invalid = true;}
isInvalid()272     bool isInvalid() const{ return QueryHolder::isInvalid(); /*|| m_invalid;*/}
273 protected:
274     void extractParams();
275     QString extractField(QString source);
276     QString replaceFields(QString query);
277 private:
278     QString m_masterDatasource;
279     //bool m_invalid;
280 };
281 
282 struct FieldsCorrelation{
283     QString master;
284     QString detail;
285 };
286 
287 class FieldMapDesc : public QObject{
288     Q_OBJECT
Q_PROPERTY(QString master READ master WRITE setMaster)289     Q_PROPERTY(QString master READ master WRITE setMaster)
290     Q_PROPERTY(QString detail READ detail WRITE setDetail)
291 public:
292     FieldMapDesc(){}
FieldMapDesc(FieldsCorrelation correlation)293     FieldMapDesc(FieldsCorrelation correlation):m_fieldsCorrelation(correlation){}
master()294     QString master(){return m_fieldsCorrelation.master;}
setMaster(QString value)295     void setMaster(QString value){m_fieldsCorrelation.master=value;}
detail()296     QString detail(){return m_fieldsCorrelation.detail;}
setDetail(QString value)297     void setDetail(QString value){m_fieldsCorrelation.detail=value;}
298 private:
299     FieldsCorrelation m_fieldsCorrelation;
300 };
301 
302 class ProxyDesc : public QObject, public ICollectionContainer{
303     Q_OBJECT
Q_PROPERTY(ACollectionProperty fields READ fakeCollectionReader)304     Q_PROPERTY(ACollectionProperty fields READ fakeCollectionReader)
305     Q_PROPERTY(QString master READ master WRITE setMaster)
306     Q_PROPERTY(QString child READ child WRITE setDetail)
307     Q_PROPERTY(QString name READ name WRITE setName)
308 public:
309     void setMaster(QString value){m_master=value;}
master()310     QString master(){return m_master;}
setDetail(QString value)311     void setDetail(QString value){m_detail=value;}
child()312     QString child(){return m_detail;}
name()313     QString name(){return m_name;}
setName(QString value)314     void setName(QString value){m_name=value;}
315     void addFieldsCorrelation(const FieldsCorrelation &fieldsCorrelation);
fieldsMap()316     QList<FieldMapDesc*>* fieldsMap(){return &m_maps;}
317     //ICollectionContainer
318     virtual QObject* createElement(const QString& collectionName,const QString&);
319     virtual int elementsCount(const QString& collectionName);
320     virtual QObject *elementAt(const QString& collectionName,int index);
321 private:
322     QList<FieldMapDesc*> m_maps;
323     QString m_master;
324     QString m_detail;
325     QString m_name;
326 };
327 
328 class MasterDetailProxyModel : public QSortFilterProxyModel{
329     Q_OBJECT
330 public:
MasterDetailProxyModel(DataSourceManager * dataManager)331     MasterDetailProxyModel(DataSourceManager* dataManager):m_maps(0),m_dataManager(dataManager){}
332     void setMaster(QString name);
setChildName(QString name)333     void setChildName(QString name){m_childName=name;}
setFieldsMap(QList<FieldMapDesc * > * fieldsMap)334     void setFieldsMap(QList<FieldMapDesc*> *fieldsMap){m_maps=fieldsMap;}
335     bool isInvalid() const;
dataManager()336     DataSourceManager* dataManager() const {return m_dataManager;}
337 protected:
338     bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const;
339     int fieldIndexByName(QString fieldName) const;
340     QVariant sourceData(QString fieldName, int row) const;
341     QVariant masterData(QString fieldName) const;
342 private:
343     QList<FieldMapDesc*>* m_maps;
344     QString m_masterName;
345     QString m_childName;
346     DataSourceManager* m_dataManager;
347 };
348 
349 class ProxyHolder: public QObject, public IDataSourceHolder{
350     Q_OBJECT
351 public:
352     ProxyHolder(ProxyDesc *desc, DataSourceManager *dataManager);
353     QString masterDatasource();
354     void filterModel();
355     IDataSource* dataSource(IDataSource::DatasourceMode mode = IDataSource::RENDER_MODE);
isOwned()356     bool isOwned() const { return true; }
isInvalid()357     bool isInvalid() const { return !m_lastError.isEmpty() || m_invalid; }
isEditable()358     bool isEditable() const { return true; }
isRemovable()359     bool isRemovable() const { return true; }
lastError()360     QString lastError() const { return m_lastError; }
361     void invalidate(IDataSource::DatasourceMode mode, bool dbWillBeClosed = false);
update()362     void update(){}
clearErrors()363     void clearErrors(){m_lastError = "";}
dataManager()364     DataSourceManager* dataManager() const {return m_dataManager;}
365 private slots:
366     void slotChildModelDestoroyed();
367 private:
368     IDataSource::Ptr m_datasource;
369     MasterDetailProxyModel  *m_model;
370     ProxyDesc *m_desc;
371     QString m_lastError;
372     IDataSource::DatasourceMode m_mode;
373     bool m_invalid;
374     DataSourceManager* m_dataManager;
375 };
376 
377 class ModelToDataSource : public QObject, public IDataSource{
378     Q_OBJECT
379 public:
380     ModelToDataSource(QAbstractItemModel* model, bool owned);
381     ~ModelToDataSource();
382     bool next();
383     bool hasNext();
384     bool prior();
385     void first();
386     void last();
387     bool eof();
388     bool bof();
389     QVariant data(const QString& columnName);
390     QVariant dataByRowIndex(const QString &columnName, int rowIndex);
391     QVariant dataByKeyField(const QString& columnName, const QString& keyColumnName, QVariant keyData);
392     int columnCount();
393     QString columnNameByIndex(int columnIndex);
394     int columnIndexByName(QString name);
395     QString lastError();
396     virtual QAbstractItemModel* model();
397     int currentRow();
398     bool isInvalid() const;
399 signals:
400     void modelStateChanged();
401 private slots:
402     void slotModelDestroed();
403 private:
404     QAbstractItemModel* m_model;
405     bool m_owned;
406     int  m_curRow;
407     QString m_lastError;
408 };
409 
410 class CallbackDatasource :public ICallbackDatasource, public IDataSource {
411     Q_OBJECT
412 public:
CallbackDatasource()413     CallbackDatasource():  m_currentRow(-1), m_eof(false), m_columnCount(-1),
414                            m_rowCount(-1), m_getDataFromCache(false), m_lastKeyRow(0){}
415     bool next();
hasNext()416     bool hasNext(){ if (!m_eof) return checkNextRecord(m_currentRow); else return false;}
417     bool prior();
418     void first();
last()419     void last(){}
bof()420     bool bof(){return m_currentRow == -1;}
eof()421     bool eof(){return m_eof;}
422     QVariant data(const QString &columnName);
423     QVariant dataByRowIndex(const QString& columnName, int rowIndex);
424     QVariant dataByKeyField(const QString& columnName, const QString& keyColumnName, QVariant keyData);
425     int columnCount();
426     QString columnNameByIndex(int columnIndex);
427     int columnIndexByName(QString name);
isInvalid()428     bool isInvalid() const{ return false;}
lastError()429     QString lastError(){ return "";}
model()430     QAbstractItemModel *model(){return 0;}
431 private:
432     bool checkNextRecord(int recordNum);
433     bool checkIfEmpty();
434     QVariant callbackData(const QString& columnName, int row);
435 private:
436     QVector<QString> m_headers;
437     int m_currentRow;
438     bool m_eof;
439     int m_columnCount;
440     int m_rowCount;
441     QHash<QString, QVariant> m_valuesCache;
442     bool m_getDataFromCache;
443     int m_lastKeyRow;
444 };
445 
446 class CallbackDatasourceHolder :public QObject, public IDataSourceHolder{
447     Q_OBJECT
448     // IDataSourceHolder interface
449 public:
CallbackDatasourceHolder(IDataSource * datasource,bool owned)450     CallbackDatasourceHolder(IDataSource* datasource, bool owned):m_owned(owned){ m_datasource = datasource;}
dataSource(IDataSource::DatasourceMode)451     IDataSource *dataSource(IDataSource::DatasourceMode){ return m_datasource;}
lastError()452     QString lastError() const{ return m_datasource->lastError();}
isInvalid()453     bool isInvalid() const {return m_datasource->isInvalid();}
isOwned()454     bool isOwned() const {return m_owned;}
isEditable()455     bool isEditable() const {return false;}
isRemovable()456     bool isRemovable() const {return false;}
457     void invalidate(IDataSource::DatasourceMode mode, bool dbWillBeClosed = false){Q_UNUSED(mode) Q_UNUSED(dbWillBeClosed)}
~CallbackDatasourceHolder()458     ~CallbackDatasourceHolder(){delete m_datasource;}
update()459     void update(){}
clearErrors()460     void clearErrors(){}
461 private:
462     IDataSource* m_datasource;
463     bool m_owned;
464 };
465 
466 }
467 #endif // LRDATADESIGNINTF_H
468