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