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 #include "lrdatasourcemanager.h"
31 #include "lrdatadesignintf.h"
32 #include <QStringList>
33 #include <QSqlQuery>
34 #include <QRegExp>
35 #include <QSqlError>
36 #include <QSqlQueryModel>
37 #include <QFileInfo>
38 #include <stdexcept>
39 
40 #ifdef BUILD_WITH_EASY_PROFILER
41 #include "easy/profiler.h"
42 #else
43 # define EASY_BLOCK(...)
44 # define EASY_END_BLOCK
45 #endif
46 
47 namespace LimeReport{
48 
~DataNode()49 DataNode::~DataNode()
50 {
51     for (int i = 0; i<m_childs.count(); ++i){
52         delete m_childs[i];
53     }
54 }
55 
addChild(const QString & name,DataNode::NodeType type,const QIcon & icon)56 DataNode*DataNode::addChild(const QString& name, DataNode::NodeType type, const QIcon& icon)
57 {
58     DataNode* res = new DataNode(name,type,this,icon);
59     m_childs.push_back(res);
60     return res;
61 }
62 
row()63 int DataNode::row()
64 {
65     if (m_parent){
66         return m_parent->m_childs.indexOf(const_cast<DataNode*>(this));
67     }
68     return 0;
69 }
70 
clear()71 void DataNode::clear()
72 {
73     for (int i=0; i<m_childs.count(); ++i){
74         delete m_childs[i];
75     }
76     m_childs.clear();
77 }
78 
79 
DataSourceModel(DataSourceManager * dataManager)80 DataSourceModel::DataSourceModel(DataSourceManager* dataManager)
81     :m_dataManager(0), m_rootNode(new DataNode())
82 {
83     setDataSourceManager(dataManager);
84 }
85 
~DataSourceModel()86 DataSourceModel::~DataSourceModel()
87 {
88     delete m_rootNode;
89 }
90 
index(int row,int column,const QModelIndex & parent) const91 QModelIndex DataSourceModel::index(int row, int column, const QModelIndex& parent) const
92 {
93     if (!m_rootNode)
94         return QModelIndex();
95 
96     if (!hasIndex(row,column,parent))
97         return QModelIndex();
98 
99     DataNode* parentNode;
100     if (parent.isValid()){
101         parentNode = nodeFromIndex(parent);
102     } else {
103         parentNode = m_rootNode;
104     }
105 
106     DataNode* childNode = parentNode->child(row);
107     if (childNode){
108         return createIndex(row,column,childNode);
109     } else return QModelIndex();
110 }
111 
parent(const QModelIndex & child) const112 QModelIndex DataSourceModel::parent(const QModelIndex& child) const
113 {
114     if (!child.isValid()) return QModelIndex();
115 
116     DataNode* childNode = nodeFromIndex(child);
117     if (!childNode) return QModelIndex();
118 
119     DataNode* parentNode = childNode->parent();
120     if ((parentNode == m_rootNode) || (!parentNode)) return QModelIndex();
121     return createIndex(parentNode->row(),0,parentNode);
122 }
123 
rowCount(const QModelIndex & parent) const124 int DataSourceModel::rowCount(const QModelIndex& parent) const
125 {
126     if (!m_rootNode) return 0;
127     DataNode* parentNode;
128     if (parent.isValid())
129         parentNode = nodeFromIndex(parent);
130     else
131         parentNode = m_rootNode;
132     return parentNode->childCount();
133 }
134 
columnCount(const QModelIndex & parent) const135 int DataSourceModel::columnCount(const QModelIndex& parent) const
136 {
137     Q_UNUSED(parent)
138     return 1;
139 }
140 
data(const QModelIndex & index,int role) const141 QVariant DataSourceModel::data(const QModelIndex& index, int role) const
142 {
143     DataNode *node = nodeFromIndex(index);
144     switch (role) {
145     case Qt::DisplayRole:
146         if (!node) return QVariant();
147         return node->name();
148         break;
149     case Qt::DecorationRole :
150         if (!node) return QIcon();
151         return node->icon();
152         break;
153     default:
154         return QVariant();
155     }
156 }
157 
setDataSourceManager(DataSourceManager * dataManager)158 void DataSourceModel::setDataSourceManager(DataSourceManager* dataManager)
159 {
160     m_dataManager = dataManager;
161     connect(m_dataManager,SIGNAL(datasourcesChanged()),this,SLOT(slotDatasourcesChanged()));
162     updateModel();
163 }
164 
slotDatasourcesChanged()165 void DataSourceModel::slotDatasourcesChanged()
166 {
167     beginResetModel();
168     updateModel();
169     endResetModel();
170 }
171 
nodeFromIndex(const QModelIndex & index) const172 DataNode* DataSourceModel::nodeFromIndex(const QModelIndex& index) const
173 {
174     if (index.isValid()){
175         return static_cast<DataNode*>(index.internalPointer());
176     } else return m_rootNode;
177 }
178 
fillFields(DataNode * parent)179 void DataSourceModel::fillFields(DataNode* parent)
180 {
181     foreach(QString name, m_dataManager->fieldNames(parent->name())){
182         parent->addChild(name, DataNode::Field,QIcon(":/report/images/field"));
183     }
184 }
185 
updateModel()186 void DataSourceModel::updateModel()
187 {
188     QMap<QString,DataNode*> connections;
189 
190     m_rootNode->clear();
191     DataNode* ds = m_rootNode->addChild(tr("Datasources"),DataNode::DataSources,QIcon(":/report/images/databases"));
192 
193 
194     foreach (QString name,m_dataManager->connectionNames()) {
195         DataNode* connection = ds->addChild(name,DataNode::Connection,QIcon(":/report/images/database"));
196         connections.insert(name,connection);
197     }
198 
199     foreach (QString name, m_dataManager->dataSourceNames()) {
200         DataNode* datasource;
201         if (m_dataManager->isQuery(name)){
202             DataNode* connection = connections.value(m_dataManager->queryByName(name)->connectionName());
203             if (connection) datasource=connection->addChild(name,DataNode::Query,QIcon(":/report/images/table"));
204             else datasource=ds->addChild(name,DataNode::Query);
205         } else if (m_dataManager->isSubQuery(name)){
206             DataNode* connection = connections.value(m_dataManager->subQueryByName(name)->connectionName());
207             if (connection) datasource=connection->addChild(name,DataNode::SubQuery,QIcon(":/report/images/table"));
208             else datasource=ds->addChild(name,DataNode::SubQuery);
209         } else {
210             datasource=ds->addChild(name,DataNode::Model,QIcon(":/report/images/table"));
211         }
212         fillFields(datasource);
213     }
214 
215     DataNode* vars = m_rootNode->addChild(tr("Variables"),DataNode::Variables,QIcon(":/report/images/folder"));
216     foreach (QString name, m_dataManager->variableNames()){
217         vars->addChild(name,DataNode::Variable,QIcon(":/report/images/value"));
218     }
219 
220     vars = m_rootNode->addChild(tr("External variables"),DataNode::Variables,QIcon(":/report/images/folder"));
221     foreach (QString name, m_dataManager->userVariableNames()){
222         vars->addChild(name,DataNode::Variable,QIcon(":/report/images/value"));
223     }
224 }
225 
DataSourceManager(QObject * parent)226 DataSourceManager::DataSourceManager(QObject *parent) :
227     QObject(parent), m_lastError(""), m_designTime(false), m_needUpdate(false),
228     m_dbCredentialsProvider(0), m_hasChanges(false)
229 {
230     m_groupFunctionFactory.registerFunctionCreator(QLatin1String("COUNT"),new ConstructorGroupFunctionCreator<CountGroupFunction>);
231     m_groupFunctionFactory.registerFunctionCreator(QLatin1String("SUM"),new ConstructorGroupFunctionCreator<SumGroupFunction>);
232     m_groupFunctionFactory.registerFunctionCreator(QLatin1String("AVG"),new ConstructorGroupFunctionCreator<AvgGroupFunction>);
233     m_groupFunctionFactory.registerFunctionCreator(QLatin1String("MIN"),new ConstructorGroupFunctionCreator<MinGroupFunction>);
234     m_groupFunctionFactory.registerFunctionCreator(QLatin1String("MAX"),new ConstructorGroupFunctionCreator<MaxGroupFunction>);
235     setSystemVariable(QLatin1String("#PAGE"),1,SecondPass);
236     setSystemVariable(QLatin1String("#PAGE_COUNT"),0,SecondPass);
237     setSystemVariable(QLatin1String("#IS_LAST_PAGEFOOTER"),false,FirstPass);
238     setSystemVariable(QLatin1String("#IS_FIRST_PAGEFOOTER"),false,FirstPass);
239     m_datasourcesModel.setDataSourceManager(this);
240 
241     connect(&m_reportVariables, SIGNAL(variableHasBeenAdded(QString)),
242             this, SLOT(slotVariableHasBeenAdded(QString)));
243     connect(&m_reportVariables, SIGNAL(variableHasBeenChanged(QString)),
244             this, SLOT(slotVariableHasBeenChanged(QString)));
245     connect(&m_userVariables, SIGNAL(variableHasBeenAdded(QString)),
246             this, SLOT(slotVariableHasBeenAdded(QString)));
247     connect(&m_userVariables, SIGNAL(variableHasBeenChanged(QString)),
248             this, SLOT(slotVariableHasBeenChanged(QString)));
249 
250 
251 }
252 
defaultDatabasePath() const253 QString DataSourceManager::defaultDatabasePath() const
254 {
255     return m_defaultDatabasePath;
256 }
257 
setDefaultDatabasePath(const QString & defaultDatabasePath)258 void DataSourceManager::setDefaultDatabasePath(const QString &defaultDatabasePath)
259 {
260     m_defaultDatabasePath = defaultDatabasePath;
261 }
262 
putGroupFunctionsExpressions(QString expression)263 QString DataSourceManager::putGroupFunctionsExpressions(QString expression)
264 {
265     if (m_groupFunctionsExpressionsMap.contains(expression)){
266         return QString::number(m_groupFunctionsExpressionsMap.value(expression));
267     } else {
268         m_groupFunctionsExpressions.append(expression);
269         m_groupFunctionsExpressionsMap.insert(expression, m_groupFunctionsExpressions.size()-1);
270         return QString::number(m_groupFunctionsExpressions.size()-1);
271     }
272 }
273 
clearGroupFuntionsExpressions()274 void DataSourceManager::clearGroupFuntionsExpressions()
275 {
276     m_groupFunctionsExpressionsMap.clear();
277     m_groupFunctionsExpressions.clear();
278 }
279 
getExpression(QString index)280 QString DataSourceManager::getExpression(QString index)
281 {
282     bool ok = false;
283     int i = index.toInt(&ok);
284     if (ok && m_groupFunctionsExpressions.size()>i)
285         return m_groupFunctionsExpressions.at(index.toInt());
286     else return "";
287 }
288 
designTime() const289 bool DataSourceManager::designTime() const
290 {
291     return m_designTime;
292 }
293 
setDesignTime(bool designTime)294 void DataSourceManager::setDesignTime(bool designTime)
295 {
296     m_designTime = designTime;
297 }
298 
299 
~DataSourceManager()300 DataSourceManager::~DataSourceManager()
301 {
302     clear(All);
303     clearGroupFunction();
304 }
305 
connectAllDatabases()306 void DataSourceManager::connectAllDatabases()
307 {
308     foreach(ConnectionDesc* conn,m_connections){
309         try{
310             connectConnection(conn);
311         } catch (ReportError &e){
312             putError(e.what());
313             setLastError(e.what());
314             qDebug()<<e.what();
315         }
316     }
317 }
318 
addModel(const QString & name,QAbstractItemModel * model,bool owned)319 bool DataSourceManager::addModel(const QString &name, QAbstractItemModel *model, bool owned)
320 {
321     if (m_datasources.contains(name.toLower()))
322         removeDatasource(name.toLower());
323     ModelHolder* mh = new ModelHolder(model,owned);
324     try{
325         putHolder(name, mh);
326         connect(mh, SIGNAL(modelStateChanged()), this, SIGNAL(datasourcesChanged()));
327     } catch (ReportError &e){
328         putError(e.what());
329         setLastError(e.what());
330         return false;
331     }
332     emit datasourcesChanged();
333     return true;
334 }
335 
removeModel(const QString & name)336 void DataSourceManager::removeModel(const QString &name)
337 {
338     if (m_datasources.contains(name.toLower()))
339         removeDatasource(name.toLower());
340 }
341 
createCallbackDatasource(const QString & name)342 ICallbackDatasource *DataSourceManager::createCallbackDatasource(const QString& name)
343 {
344     ICallbackDatasource* ds = new CallbackDatasource();
345     IDataSourceHolder* holder = new CallbackDatasourceHolder(dynamic_cast<IDataSource*>(ds),true);
346     putHolder(name,holder);
347     emit datasourcesChanged();
348     m_needUpdate = true;
349     return ds;
350 }
351 
registerDbCredentialsProvider(IDbCredentialsProvider * provider)352 void DataSourceManager::registerDbCredentialsProvider(IDbCredentialsProvider *provider)
353 {
354     m_dbCredentialsProvider = provider;
355 }
356 
addCallbackDatasource(ICallbackDatasource * datasource,const QString & name)357 void DataSourceManager::addCallbackDatasource(ICallbackDatasource *datasource, const QString& name)
358 {
359     IDataSource* datasourceIntf = dynamic_cast<IDataSource*>(datasource);
360     if (datasourceIntf){
361         IDataSourceHolder* holder = new CallbackDatasourceHolder(datasourceIntf,true);
362         putHolder(name,holder);
363         emit datasourcesChanged();
364     }
365 }
366 
previewSQL(const QString & connectionName,const QString & sqlText,QString masterDatasource)367 QSharedPointer<QAbstractItemModel>DataSourceManager::previewSQL(const QString &connectionName, const QString &sqlText, QString masterDatasource)
368 {
369     QSqlDatabase db = QSqlDatabase::database(connectionName);
370 
371     if (db.isValid() && db.isOpen()){
372 
373         QSqlQueryModel* model = new QSqlQueryModel();
374         QMap<QString,QString> aliasesToParam;
375         QString queryText = replaceVariables(sqlText,aliasesToParam);
376         queryText = replaceFields(queryText,aliasesToParam,masterDatasource);
377         QSqlQuery query(db);
378         query.prepare(queryText);
379 
380         foreach(QString param,aliasesToParam.keys()){
381             QVariant value;
382             if (param.contains(".")){
383                 value = fieldData(aliasesToParam.value(param));
384                 param=param.right(param.length()-param.indexOf('.')-1);
385             } else {
386                 value = variable(aliasesToParam.value(param));
387             }
388             if (value.isValid() || m_designTime)
389                 query.bindValue(':'+param,value);
390         }
391 
392         query.exec();
393         model->setQuery(query);
394         m_lastError = model->lastError().text();
395         putError(m_lastError);
396         if (model->query().isActive())
397             return QSharedPointer<QAbstractItemModel>(model);
398         else
399             return QSharedPointer<QAbstractItemModel>(0);
400     }
401     if (!db.isOpen()){
402         m_lastError = tr("Connection \"%1\" is not open").arg(connectionName);
403         putError(m_lastError);
404     }
405     return QSharedPointer<QAbstractItemModel>(0);
406 }
407 
updateDatasourceModel()408 void DataSourceManager::updateDatasourceModel()
409 {
410     m_datasourcesModel.updateModel();
411     emit datasourcesChanged();
412     m_needUpdate = false;
413 }
414 
extractField(QString source)415 QString DataSourceManager::extractField(QString source)
416 {
417     if (source.contains('.')) {
418         return source.right(source.length()-(source.indexOf('.')+1));
419     }
420     return source;
421 }
422 
replaceVariables(QString value)423 QString DataSourceManager::replaceVariables(QString value){
424     QRegExp rx(Const::VARIABLE_RX);
425 
426     if (value.contains(rx)){
427         int pos = -1;
428         while ((pos=rx.indexIn(value))!=-1){
429             QString var=rx.cap(0);
430             var.remove("$V{");
431             var.remove("}");
432 
433             if (variable(var).isValid()){
434                 value.replace(pos,rx.cap(0).length(),variable(var).toString());
435             } else {
436                 value.replace(pos,rx.cap(0).length(),QString(tr("Variable \"%1\" not found!").arg(var)));
437             }
438         }
439     }
440     return value;
441 }
442 
replaceVariables(QString query,QMap<QString,QString> & aliasesToParam)443 QString DataSourceManager::replaceVariables(QString query, QMap<QString,QString> &aliasesToParam)
444 {
445     QRegExp rx(Const::VARIABLE_RX);
446     int curentAliasIndex = 0;
447     if (query.contains(rx)){
448         int pos = -1;
449         while ((pos=rx.indexIn(query))!=-1){
450 
451             QString var=rx.cap(0);
452             var.remove("$V{");
453             var.remove("}");
454             if (!rx.cap(1).isEmpty()){
455                 if (aliasesToParam.contains(var)){
456                     curentAliasIndex++;
457                     aliasesToParam.insert(var+"_v_alias"+QString::number(curentAliasIndex),var);
458                     var += "_v_alias"+QString::number(curentAliasIndex);
459                 } else {
460                     aliasesToParam.insert(var,var);
461                 }
462                 query.replace(pos,rx.cap(0).length(),":"+var);
463             } else {
464                 QString varName = rx.cap(2).trimmed();
465                 QString varParam = rx.cap(3).trimmed();
466                 if (!varName.isEmpty()){
467                     if (!varParam.isEmpty() && varParam.compare("nobind") == 0 ){
468                         query.replace(pos,rx.cap(0).length(), variable(varName).toString());
469                     } else {
470                         query.replace(pos,rx.cap(0).length(),
471                                       QString(tr("Unknown parameter \"%1\" for variable \"%2\" found!")
472                                               .arg(varName)
473                                               .arg(varParam))
474                                       );
475                     }
476                 } else {
477                     query.replace(pos,rx.cap(0).length(),QString(tr("Variable \"%1\" not found!").arg(var)));
478                 }
479             }
480         }
481     }
482     return query;
483 }
484 
replaceFields(QString query,QMap<QString,QString> & aliasesToParam,QString masterDatasource)485 QString DataSourceManager::replaceFields(QString query, QMap<QString,QString> &aliasesToParam, QString masterDatasource)
486 {
487     QRegExp rx(Const::FIELD_RX);
488     if (query.contains(rx)){
489         int curentAliasIndex=0;
490         int pos;
491         while ((pos=rx.indexIn(query))!=-1){
492             QString field=rx.cap(0);
493             field.remove("$D{");
494             field.remove("}");
495 
496             if (!aliasesToParam.contains(field)){
497                 if (field.contains("."))
498                     aliasesToParam.insert(field,field);
499                 else
500                     aliasesToParam.insert(field,masterDatasource+"."+field);
501             } else {
502                 curentAliasIndex++;
503                 if (field.contains("."))
504                     aliasesToParam.insert(field+"_f_alias"+QString::number(curentAliasIndex),field);
505                 else
506                     aliasesToParam.insert(field+"_f_alias"+QString::number(curentAliasIndex),masterDatasource+"."+field);
507                 field+="_f_alias"+QString::number(curentAliasIndex);
508             }
509             query.replace(pos,rx.cap(0).length(),":"+extractField(field));
510         }
511     }
512     return query;
513 }
514 
setReportVariable(const QString & name,const QVariant & value)515 void DataSourceManager::setReportVariable(const QString &name, const QVariant &value)
516 {
517     if (!containsVariable(name)){
518         addVariable(name,value);
519     } else changeVariable(name,value);
520 }
521 
addQuery(const QString & name,const QString & sqlText,const QString & connectionName)522 void DataSourceManager::addQuery(const QString &name, const QString &sqlText, const QString &connectionName)
523 {
524     QueryDesc *queryDecs = new QueryDesc(name,sqlText,connectionName);
525     putQueryDesc(queryDecs);
526     putHolder(name,new QueryHolder(sqlText, connectionName, this));
527     m_hasChanges = true;
528     m_varToDataSource.clear();
529     emit datasourcesChanged();
530 }
531 
addSubQuery(const QString & name,const QString & sqlText,const QString & connectionName,const QString & masterDatasource)532 void DataSourceManager::addSubQuery(const QString &name, const QString &sqlText, const QString &connectionName, const QString &masterDatasource)
533 {
534     SubQueryDesc *subQueryDesc = new SubQueryDesc(name.toLower(),sqlText,connectionName,masterDatasource);
535     putSubQueryDesc(subQueryDesc);
536     putHolder(name,new SubQueryHolder(sqlText, connectionName, masterDatasource, this));
537     m_hasChanges = true;
538     m_varToDataSource.clear();
539     emit datasourcesChanged();
540 }
541 
addProxy(const QString & name,const QString & master,const QString & detail,QList<FieldsCorrelation> fields)542 void DataSourceManager::addProxy(const QString &name, const QString &master, const QString &detail, QList<FieldsCorrelation> fields)
543 {
544     ProxyDesc *proxyDesc = new ProxyDesc();
545     proxyDesc->setName(name);
546     proxyDesc->setMaster(master);
547     proxyDesc->setDetail(detail);
548     foreach(FieldsCorrelation correlation,fields){
549         proxyDesc->addFieldsCorrelation(correlation);
550     }
551     putProxyDesc(proxyDesc);
552     putHolder(name,new ProxyHolder(proxyDesc, this));
553     m_hasChanges = true;
554     emit datasourcesChanged();
555 }
556 
addCSV(const QString & name,const QString & csvText,const QString & separator,bool firstRowIsHeader)557 void DataSourceManager::addCSV(const QString& name, const QString& csvText, const QString &separator, bool firstRowIsHeader)
558 {
559     CSVDesc* csvDesc = new CSVDesc(name, csvText, separator, firstRowIsHeader);
560     putCSVDesc(csvDesc);
561     putHolder(name, new CSVHolder(*csvDesc, this));
562     m_hasChanges = true;
563     emit datasourcesChanged();
564 }
565 
queryText(const QString & dataSourceName)566 QString DataSourceManager::queryText(const QString &dataSourceName)
567 {
568     if (isQuery(dataSourceName)) return queryByName(dataSourceName)->queryText();
569     if (isSubQuery(dataSourceName)) return subQueryByName(dataSourceName)->queryText();
570     else return QString();
571 }
572 
queryByName(const QString & datasourceName)573 QueryDesc *DataSourceManager::queryByName(const QString &datasourceName)
574 {
575     int queryIndex = queryIndexByName(datasourceName);
576     if (queryIndex!=-1) return m_queries.at(queryIndex);
577     return 0;
578 }
579 
subQueryByName(const QString & datasourceName)580 SubQueryDesc* DataSourceManager::subQueryByName(const QString &datasourceName)
581 {
582     int queryIndex = subQueryIndexByName(datasourceName);
583     if (queryIndex!=-1) return m_subqueries.at(queryIndex);
584     return 0;
585 }
586 
connectionByName(const QString & connectionName)587 ConnectionDesc* DataSourceManager::connectionByName(const QString &connectionName)
588 {
589     int queryIndex = connectionIndexByName(connectionName);
590     if (queryIndex!=-1) return m_connections.at(queryIndex);
591     return 0;
592 }
593 
queryIndexByName(const QString & dataSourceName)594 int DataSourceManager::queryIndexByName(const QString &dataSourceName)
595 {
596     for(int i=0;i<m_queries.count();i++){
597         QueryDesc* desc=m_queries.at(i);
598         if (desc->queryName().compare(dataSourceName,Qt::CaseInsensitive)==0) return i;
599     }
600     return -1;
601 }
602 
subQueryIndexByName(const QString & dataSourceName)603 int DataSourceManager::subQueryIndexByName(const QString &dataSourceName)
604 {
605     for(int i=0;i<m_subqueries.count();++i){
606         QueryDesc* desc=m_subqueries.at(i);
607         if (desc->queryName().compare(dataSourceName,Qt::CaseInsensitive)==0) return i;
608     }
609     return -1;
610 }
611 
proxyIndexByName(const QString & dataSourceName)612 int DataSourceManager::proxyIndexByName(const QString &dataSourceName)
613 {
614     for(int i=0;i<m_proxies.count();++i){
615         ProxyDesc* desc=m_proxies.at(i);
616         if (desc->name().compare(dataSourceName,Qt::CaseInsensitive)==0) return i;
617     }
618     return -1;
619 }
620 
csvIndexByName(const QString & dataSourceName)621 int DataSourceManager::csvIndexByName(const QString &dataSourceName)
622 {
623     for(int i=0; i < m_csvs.count();++i){
624         CSVDesc* desc=m_csvs.at(i);
625         if (desc->name().compare(dataSourceName,Qt::CaseInsensitive)==0) return i;
626     }
627     return -1;
628 }
629 
connectionIndexByName(const QString & connectionName)630 int DataSourceManager::connectionIndexByName(const QString &connectionName)
631 {
632     for(int i=0;i<m_connections.count();++i){
633         ConnectionDesc* desc=m_connections.at(i);
634         if (desc->name().compare(connectionName,Qt::CaseInsensitive)==0) return i;
635     }
636     return -1;
637 }
638 
conections()639 QList<ConnectionDesc *>& DataSourceManager::conections()
640 {
641     return m_connections;
642 }
643 
dataSourceIsValid(const QString & name)644 bool DataSourceManager::dataSourceIsValid(const QString &name)
645 {
646     if (m_datasources.value(name.toLower())) return !m_datasources.value(name.toLower())->isInvalid();
647     else throw ReportError(tr("Datasource \"%1\" not found!").arg(name));
648 }
649 
isQuery(const QString & dataSourceName)650 bool DataSourceManager::isQuery(const QString &dataSourceName)
651 {
652     return (queryByName(dataSourceName));
653 }
654 
connectionName(const QString & dataSourceName)655 QString DataSourceManager::connectionName(const QString &dataSourceName)
656 {
657     if (isQuery(dataSourceName)) return queryByName(dataSourceName)->connectionName();
658     if (isSubQuery(dataSourceName)) return subQueryByName(dataSourceName)->connectionName();
659     return QString();
660 }
661 
proxyByName(const QString & datasourceName)662 ProxyDesc *DataSourceManager::proxyByName(const QString &datasourceName)
663 {
664     int proxyIndex = proxyIndexByName(datasourceName);
665     if (proxyIndex > -1) return m_proxies.at(proxyIndex);
666     else return 0;
667 }
668 
csvByName(const QString & datasourceName)669 CSVDesc *DataSourceManager::csvByName(const QString &datasourceName)
670 {
671     int csvIndex =  csvIndexByName(datasourceName);
672     if (csvIndex > -1) return m_csvs.at(csvIndex);
673     else return 0;
674 }
675 
removeDatasource(const QString & name)676 void DataSourceManager::removeDatasource(const QString &name)
677 {
678     invalidateLinkedDatasources(name);
679 
680     if (m_datasources.contains(name)){
681         IDataSourceHolder *holder;
682         holder=m_datasources.value(name);
683         m_datasources.remove(name);
684         delete holder;
685     }
686     if (isQuery(name)){
687         int queryIndex=queryIndexByName(name);
688         delete m_queries.at(queryIndex);
689         m_queries.removeAt(queryIndex);
690     }
691     if (isSubQuery(name)){
692         int queryIndex=subQueryIndexByName(name);
693         delete m_subqueries.at(queryIndex);
694         m_subqueries.removeAt(queryIndex);
695     }
696     if (isProxy(name)){
697         int proxyIndex=proxyIndexByName(name);
698         delete m_proxies.at(proxyIndex);
699         m_proxies.removeAt(proxyIndex);
700     }
701     if (isCSV(name)){
702         int csvIndex=csvIndexByName(name);
703         delete m_csvs.at(csvIndex);
704         m_csvs.removeAt(csvIndex);
705     }
706     m_hasChanges = true;
707     emit datasourcesChanged();
708 }
709 
removeConnection(const QString & connectionName)710 void DataSourceManager::removeConnection(const QString &connectionName)
711 {
712     QList<ConnectionDesc*>::iterator cit = m_connections.begin();
713     while( cit != m_connections.end() ){
714         if ( ((*cit)->name().compare(connectionName) == 0) ){
715             if ((*cit)->isInternal())
716             {
717                 QSqlDatabase db = QSqlDatabase::database(connectionName);
718                 db.close();
719             }
720             QSqlDatabase::removeDatabase(connectionName);
721             delete (*cit);
722             cit = m_connections.erase(cit);
723         } else {
724             ++cit;
725         }
726     }
727     m_hasChanges = true;
728     emit datasourcesChanged();
729 }
730 
addConnectionDesc(ConnectionDesc * connection)731 void DataSourceManager::addConnectionDesc(ConnectionDesc * connection)
732 {
733     if (!isConnection(connection->name())) {
734         connect(connection,SIGNAL(nameChanged(QString,QString)),this,SLOT(slotConnectionRenamed(QString,QString)));
735         m_connections.append(connection);
736         m_hasChanges = true;
737         if (connection->autoconnect()){
738             try{
739               connectConnection(connection);
740             } catch(ReportError &exception) {
741                 qDebug()<<exception.what();
742             }
743         }
744     } else {
745        throw ReportError(tr("Connection with name \"%1\" already exists!").arg(connection->name()));
746     }
747 }
748 
checkConnectionDesc(ConnectionDesc * connection)749 bool DataSourceManager::checkConnectionDesc(ConnectionDesc *connection)
750 {
751     if (connectConnection(connection)){
752         if (connection->isInternal()){
753             QSqlDatabase::removeDatabase(connection->name());
754             if (designTime()) emit datasourcesChanged();
755         }
756         return true;
757     }
758     if (connection->isInternal())
759         QSqlDatabase::removeDatabase(connection->name());
760     return false;
761 }
762 
putHolder(const QString & name,IDataSourceHolder * dataSource)763 void DataSourceManager::putHolder(const QString& name, IDataSourceHolder *dataSource)
764 {
765     if (!m_datasources.contains(name.toLower())){
766         m_datasources.insert(
767             name.toLower(),
768             dataSource
769         );
770     } else throw ReportError(tr("Datasource with name \"%1\" already exists!").arg(name));
771 }
772 
putQueryDesc(QueryDesc * queryDesc)773 void DataSourceManager::putQueryDesc(QueryDesc* queryDesc)
774 {
775     if (!containsDatasource(queryDesc->queryName())){
776         m_queries.append(queryDesc);
777         connect(queryDesc, SIGNAL(queryTextChanged(QString,QString)),
778                 this, SLOT(slotQueryTextChanged(QString,QString)));
779     } else throw ReportError(tr("Datasource with name \"%1\" already exists!").arg(queryDesc->queryName()));
780 }
781 
putSubQueryDesc(SubQueryDesc * subQueryDesc)782 void DataSourceManager::putSubQueryDesc(SubQueryDesc *subQueryDesc)
783 {
784     if (!containsDatasource(subQueryDesc->queryName())){
785         m_subqueries.append(subQueryDesc);
786         connect(subQueryDesc, SIGNAL(queryTextChanged(QString,QString)),
787                 this, SLOT(slotQueryTextChanged(QString,QString)));
788     } else throw ReportError(tr("Datasource with name \"%1\" already exists!").arg(subQueryDesc->queryName()));
789 }
790 
putProxyDesc(ProxyDesc * proxyDesc)791 void DataSourceManager::putProxyDesc(ProxyDesc *proxyDesc)
792 {
793     if (!containsDatasource(proxyDesc->name())){
794         m_proxies.append(proxyDesc);
795     } else throw ReportError(tr("Datasource with name \"%1\" already exists!").arg(proxyDesc->name()));
796 }
797 
putCSVDesc(CSVDesc * csvDesc)798 void DataSourceManager::putCSVDesc(CSVDesc *csvDesc)
799 {
800     if (!containsDatasource(csvDesc->name())){
801         m_csvs.append(csvDesc);
802         connect(csvDesc, SIGNAL(cvsTextChanged(QString, QString)),
803                 this, SLOT(slotCSVTextChanged(QString, QString)));
804     } else throw ReportError(tr("Datasource with name \"%1\" already exists!").arg(csvDesc->name()));
805 }
806 
initAndOpenDB(QSqlDatabase & db,ConnectionDesc & connectionDesc)807 bool DataSourceManager::initAndOpenDB(QSqlDatabase& db, ConnectionDesc& connectionDesc){
808 
809     bool connected = false;
810 
811 
812     db.setHostName(replaceVariables(connectionDesc.host()));
813     db.setUserName(replaceVariables(connectionDesc.userName()));
814     db.setPassword(replaceVariables(connectionDesc.password()));
815     if (connectionDesc.port()!=-1)
816         db.setPort(connectionDesc.port());
817 
818     if (!connectionDesc.keepDBCredentials() && m_dbCredentialsProvider){
819         if (!m_dbCredentialsProvider->getUserName(connectionDesc.name()).isEmpty())
820             db.setUserName(m_dbCredentialsProvider->getUserName(connectionDesc.name()));
821         if (!m_dbCredentialsProvider->getPassword(connectionDesc.name()).isEmpty())
822             db.setPassword(m_dbCredentialsProvider->getPassword(connectionDesc.name()));
823     }
824 
825     QString dbName = replaceVariables(connectionDesc.databaseName());
826     if (connectionDesc.driver().compare("QSQLITE")==0){
827         if (!defaultDatabasePath().isEmpty()){
828             dbName = !QFileInfo(dbName).exists() ?
829                     defaultDatabasePath()+QFileInfo(dbName).fileName() :
830                     dbName;
831         }
832         if (QFileInfo(dbName).exists()){
833             db.setDatabaseName(dbName);
834         } else {
835             setLastError(tr("Database \"%1\" not found").arg(dbName));
836             return false;
837         }
838     } else {
839         db.setDatabaseName(dbName);
840     }
841 
842     connected=db.open();
843     if (!connected) setLastError(db.lastError().text());
844     return  connected;
845 }
846 
reportSettings() const847 ReportSettings *DataSourceManager::reportSettings() const
848 {
849     return m_reportSettings;
850 }
851 
setReportSettings(ReportSettings * reportSettings)852 void DataSourceManager::setReportSettings(ReportSettings *reportSettings)
853 {
854     m_reportSettings = reportSettings;
855 }
856 
checkConnection(QSqlDatabase db)857 bool DataSourceManager::checkConnection(QSqlDatabase db){
858     QSqlQuery query("Select 1",db);
859     return query.first();
860 }
861 
connectConnection(ConnectionDesc * connectionDesc)862 bool DataSourceManager::connectConnection(ConnectionDesc *connectionDesc)
863 {
864 
865     bool connected = false;
866     clearErrors();
867     QString lastError ="";
868 
869     foreach(QString datasourceName, dataSourceNames()){
870         dataSourceHolder(datasourceName)->clearErrors();
871     }
872 
873     if (!QSqlDatabase::contains(connectionDesc->name())){
874         QString dbError;
875         {
876             QSqlDatabase db = QSqlDatabase::addDatabase(connectionDesc->driver(),connectionDesc->name());
877             connectionDesc->setInternal(true);
878             connected=initAndOpenDB(db, *connectionDesc);
879             dbError = db.lastError().text();
880         }
881         if (!connected){
882             if (!dbError.trimmed().isEmpty())
883                 setLastError(dbError);
884             QSqlDatabase::removeDatabase(connectionDesc->name());
885             return false;
886         }
887     } else {
888         QSqlDatabase db = QSqlDatabase::database(connectionDesc->name());
889         if (!connectionDesc->isEqual(db) && connectionDesc->isInternal()){
890             db.close();
891             connected = initAndOpenDB(db, *connectionDesc);
892         } else {
893             connected = checkConnection(db);
894             if (!connected && connectionDesc->isInternal())
895                 connected = initAndOpenDB(db, *connectionDesc);
896         }
897     }
898 
899     if (!connected) {
900         if (connectionDesc->isInternal())
901             QSqlDatabase::removeDatabase(connectionDesc->name());
902         return false;
903     } else {
904         foreach(QString datasourceName, dataSourceNames()){
905             if (isQuery(datasourceName)){
906                QueryHolder* qh = dynamic_cast<QueryHolder*>(dataSourceHolder(datasourceName));
907                if (qh){
908                    qh->invalidate(designTime()?IDataSource::DESIGN_MODE:IDataSource::RENDER_MODE);
909                    invalidateChildren(datasourceName);
910                }
911             }
912         }
913         foreach(QString datasourceName, dataSourceNames()){
914             if (isProxy(datasourceName)){
915                ProxyHolder* ph = dynamic_cast<ProxyHolder*>(dataSourceHolder(datasourceName));
916                if (ph){
917                    ph->invalidate(designTime()?IDataSource::DESIGN_MODE:IDataSource::RENDER_MODE);
918                }
919             }
920         }
921         if (designTime()) emit datasourcesChanged();
922     }
923     return true;
924 }
925 
clearReportVariables()926 void DataSourceManager::clearReportVariables()
927 {
928     m_reportVariables.clearUserVariables();
929 }
930 
connectAutoConnections()931 void DataSourceManager::connectAutoConnections()
932 {
933     foreach(ConnectionDesc* conn,m_connections){
934         if (conn->autoconnect()) {
935             try {
936                 connectConnection(conn);
937             } catch(ReportError &e){
938                 setLastError(e.what());
939                 putError(e.what());
940                 qDebug()<<e.what();
941             }
942         }
943     }
944 }
945 
childDatasources(const QString & parentDatasourceName)946 QList<QString> DataSourceManager::childDatasources(const QString &parentDatasourceName)
947 {
948     QList<QString> result;
949     foreach(QString datasourceName, dataSourceNames()){
950         if (isSubQuery(datasourceName)){
951             SubQueryHolder* sh = dynamic_cast<SubQueryHolder*>(dataSourceHolder(datasourceName));
952             if (sh && sh->masterDatasource().compare(parentDatasourceName,Qt::CaseInsensitive)==0){
953                 result.append(datasourceName);
954             }
955         }
956     }
957     return result;
958 }
959 
invalidateChildren(const QString & parentDatasourceName)960 void DataSourceManager::invalidateChildren(const QString &parentDatasourceName)
961 {
962     foreach(QString datasourceName, childDatasources(parentDatasourceName)){
963         SubQueryHolder* sh = dynamic_cast<SubQueryHolder*>(dataSourceHolder(datasourceName));
964         if (sh)
965             sh->invalidate(designTime()?IDataSource::DESIGN_MODE:IDataSource::RENDER_MODE);
966         invalidateChildren(datasourceName);
967     }
968 }
969 
containsDatasource(const QString & dataSourceName)970 bool DataSourceManager::containsDatasource(const QString &dataSourceName)
971 {
972     return m_datasources.contains(dataSourceName.toLower());
973 }
974 
isSubQuery(const QString & dataSourceName)975 bool DataSourceManager::isSubQuery(const QString &dataSourceName)
976 {
977     return subQueryIndexByName(dataSourceName) != -1;
978 }
979 
isProxy(const QString & dataSourceName)980 bool DataSourceManager::isProxy(const QString &dataSourceName)
981 {
982     return proxyIndexByName(dataSourceName) != -1;
983 }
984 
isCSV(const QString & datasourceName)985 bool DataSourceManager::isCSV(const QString &datasourceName)
986 {
987     return csvIndexByName(datasourceName) != -1;
988 }
989 
isConnection(const QString & connectionName)990 bool DataSourceManager::isConnection(const QString &connectionName)
991 {
992     return connectionIndexByName(connectionName) != -1;
993 }
994 
isConnectionConnected(const QString & connectionName)995 bool DataSourceManager::isConnectionConnected(const QString &connectionName)
996 {
997     if (isConnection(connectionName) && QSqlDatabase::contains(connectionName)){
998         QSqlDatabase db = QSqlDatabase::database(connectionName);
999         return db.isValid() && QSqlDatabase::database(connectionName).isOpen();
1000     }
1001     return false;
1002 }
1003 
connectConnection(const QString & connectionName)1004 bool DataSourceManager::connectConnection(const QString& connectionName)
1005 {
1006     return connectConnection(connectionByName(connectionName));
1007 }
1008 
disconnectConnection(const QString & connectionName)1009 void DataSourceManager::disconnectConnection(const QString& connectionName)
1010 {
1011     foreach(QString datasourceName, dataSourceNames()){
1012         if (isQuery(datasourceName) || isSubQuery(datasourceName)){
1013             QueryHolder* qh = dynamic_cast<QueryHolder*>(dataSourceHolder(datasourceName));
1014             if (qh && qh->connectionName().compare(connectionName,Qt::CaseInsensitive)==0){
1015                 qh->invalidate(designTime()?IDataSource::DESIGN_MODE:IDataSource::RENDER_MODE);
1016                 qh->setLastError(tr("invalid connection"));
1017             }
1018         }
1019     }
1020 
1021     ConnectionDesc* connectionDesc = connectionByName(connectionName);
1022     if (connectionDesc->isInternal()){
1023         {
1024             QSqlDatabase db = QSqlDatabase::database(connectionName);
1025             if (db.isOpen()) db.close();
1026         }
1027         if (QSqlDatabase::contains(connectionName)) QSqlDatabase::removeDatabase(connectionName);
1028     }
1029 
1030 }
1031 
dataSource(const QString & name)1032 IDataSource *DataSourceManager::dataSource(const QString &name)
1033 {
1034     IDataSourceHolder* holder = m_datasources.value(name.toLower());
1035     if (holder) {
1036         if (holder->isInvalid()) {
1037             setLastError(name+" : "+holder->lastError());
1038             return 0;
1039         } else {
1040             return holder->dataSource(designTime()?IDataSource::DESIGN_MODE:IDataSource::RENDER_MODE);
1041         }
1042     } else {
1043         setLastError(tr("Datasource \"%1\" not found!").arg(name));
1044         return 0;
1045     }
1046 }
1047 
dataSourceHolder(const QString & name)1048 IDataSourceHolder *DataSourceManager::dataSourceHolder(const QString &name)
1049 {
1050     if (m_datasources.value(name.toLower())) return m_datasources.value(name.toLower());
1051     else return 0;
1052 }
1053 
dataSourceNames()1054 QStringList DataSourceManager::dataSourceNames()
1055 {
1056     QStringList result;
1057     for (int i=0;i<m_datasources.keys().count();i++){
1058        result.append(m_datasources.keys().at(i));
1059     }
1060     result.sort();
1061     return result;
1062 }
1063 
dataSourceNames(const QString & connectionName)1064 QStringList DataSourceManager::dataSourceNames(const QString& connectionName)
1065 {
1066     QStringList result;
1067     foreach (QueryDesc* query, m_queries) {
1068         if (query->connectionName().compare(connectionName,Qt::CaseInsensitive)==0){
1069             result.append(query->queryName());
1070         }
1071     }
1072     foreach (QueryDesc* query, m_subqueries) {
1073         if (query->connectionName().compare(connectionName,Qt::CaseInsensitive)==0){
1074             result.append(query->queryName());
1075         }
1076     }
1077     return result;
1078 }
1079 
connectionNames()1080 QStringList DataSourceManager::connectionNames()
1081 {
1082     QStringList result;
1083     foreach(ConnectionDesc* conDesc,m_connections){
1084        result.append(conDesc->name());
1085     }
1086     return result;
1087 }
1088 
fieldNames(const QString & datasourceName)1089 QStringList DataSourceManager::fieldNames(const QString &datasourceName)
1090 {
1091     QStringList result;
1092     IDataSource* ds = dataSource(datasourceName);
1093     if (ds && !ds->isInvalid()){
1094         for(int i=0; i < ds->columnCount(); i++){
1095             result.append(ds->columnNameByIndex(i));
1096         }
1097         result.sort();
1098     }
1099     return result;
1100 }
1101 
addConnection(const QString & connectionName)1102 void DataSourceManager::addConnection(const QString &connectionName)
1103 {
1104     addConnectionDesc(new ConnectionDesc(QSqlDatabase::database(connectionName)));
1105     m_hasChanges = true;
1106     emit datasourcesChanged();
1107 }
1108 
createElement(const QString & collectionName,const QString &)1109 QObject *DataSourceManager::createElement(const QString& collectionName, const QString&)
1110 {
1111     if (collectionName=="connections"){
1112         ConnectionDesc* connection = new ConnectionDesc;
1113         m_connections.append(connection);
1114         return connection;
1115     }
1116     if (collectionName=="queries"){
1117         QueryDesc* queryDesc = new QueryDesc;
1118         m_queries.append(queryDesc);
1119         return queryDesc;
1120     }
1121     if (collectionName=="subqueries"){
1122         SubQueryDesc* subQueryDesc = new SubQueryDesc;
1123         m_subqueries.append(subQueryDesc);
1124         return subQueryDesc;
1125     }
1126     if (collectionName=="subproxies"){
1127         ProxyDesc* proxyDesc = new ProxyDesc;
1128         m_proxies.append(proxyDesc);
1129         return proxyDesc;
1130     }
1131 
1132     if (collectionName=="variables"){
1133         VarDesc* var = new VarDesc;
1134         m_tempVars.append(var);
1135         return var;
1136     }
1137 
1138     if (collectionName=="csvs"){
1139         CSVDesc* csvDesc = new CSVDesc;
1140         m_csvs.append(csvDesc);
1141         return  csvDesc;
1142     }
1143 
1144     return 0;
1145 }
1146 
elementsCount(const QString & collectionName)1147 int DataSourceManager::elementsCount(const QString &collectionName)
1148 {
1149     if (collectionName=="connections"){
1150        return m_connections.count();
1151     }
1152     if (collectionName=="queries"){
1153         return m_queries.count();
1154     }
1155     if (collectionName=="subqueries"){
1156         return m_subqueries.count();
1157     }
1158     if (collectionName=="subproxies"){
1159         return m_proxies.count();
1160     }
1161     if (collectionName=="variables"){
1162         return m_reportVariables.variablesCount();
1163     }
1164     if (collectionName=="csvs"){
1165         return m_csvs.count();
1166     }
1167     return 0;
1168 }
1169 
elementAt(const QString & collectionName,int index)1170 QObject* DataSourceManager::elementAt(const QString &collectionName, int index)
1171 {
1172     if (collectionName=="connections"){
1173         return m_connections.at(index);
1174     }
1175     if (collectionName=="queries"){
1176         return m_queries.at(index);
1177     }
1178     if (collectionName=="subqueries"){
1179         return m_subqueries.at(index);
1180     }
1181     if (collectionName=="subproxies"){
1182         return m_proxies.at(index);
1183     }
1184     if (collectionName=="variables"){
1185         return m_reportVariables.variableAt(index);
1186     }
1187     if (collectionName=="csvs"){
1188         return m_csvs.at(index);
1189     }
1190     return 0;
1191 }
1192 
collectionLoadFinished(const QString & collectionName)1193 void DataSourceManager::collectionLoadFinished(const QString &collectionName)
1194 {
1195     EASY_BLOCK("DataSourceManager::collectionLoadFinished");
1196     if (collectionName.compare("connections",Qt::CaseInsensitive) == 0){
1197 
1198     }
1199     EASY_BLOCK("queryes");
1200     if (collectionName.compare("queries",Qt::CaseInsensitive) == 0){
1201 
1202         QMutableListIterator<QueryDesc*> it(m_queries);
1203         while (it.hasNext()){
1204             it.next();
1205             if (!m_datasources.contains(it.value()->queryName().toLower())){
1206                 connect(it.value(), SIGNAL(queryTextChanged(QString,QString)),
1207                         this, SLOT(slotQueryTextChanged(QString,QString)));
1208                 putHolder(it.value()->queryName(),new QueryHolder(it.value()->queryText(), it.value()->connectionName(), this));
1209             } else {
1210                 delete it.value();
1211                 it.remove();
1212             }
1213         }
1214 
1215     }
1216     EASY_END_BLOCK;
1217     EASY_BLOCK("subqueries")
1218     if (collectionName.compare("subqueries",Qt::CaseInsensitive) == 0){
1219 
1220         QMutableListIterator<SubQueryDesc*> it(m_subqueries);
1221         while (it.hasNext()){
1222             it.next();
1223             if (!m_datasources.contains(it.value()->queryName().toLower())){
1224                 connect(it.value(), SIGNAL(queryTextChanged(QString,QString)),
1225                         this, SLOT(slotQueryTextChanged(QString,QString)));
1226                 putHolder(it.value()->queryName(),new SubQueryHolder(
1227                               it.value()->queryText(),
1228                               it.value()->connectionName(),
1229                               it.value()->master(),
1230                               this)
1231                 );
1232             } else {
1233                 delete it.value();
1234                 it.remove();
1235             }
1236         }
1237 
1238     }
1239     EASY_END_BLOCK;
1240     EASY_BLOCK("subproxies");
1241     if (collectionName.compare("subproxies",Qt::CaseInsensitive) == 0){
1242         QMutableListIterator<ProxyDesc*> it(m_proxies);
1243         while (it.hasNext()){
1244             it.next();
1245             if (!m_datasources.contains(it.value()->name().toLower())){
1246                 putHolder(it.value()->name(),new ProxyHolder(it.value(), this));
1247             } else {
1248                 delete it.value();
1249                 it.remove();
1250             }
1251         }
1252     }
1253     EASY_END_BLOCK;
1254     EASY_BLOCK("variables");
1255     if (collectionName.compare("variables",Qt::CaseInsensitive) == 0){
1256         foreach (VarDesc* item, m_tempVars) {
1257             if (!m_reportVariables.containsVariable(item->name())){
1258                 m_reportVariables.addVariable(item->name(),item->value(),VarDesc::Report,FirstPass);
1259                 VarDesc* currentVar = m_reportVariables.variableByName(item->name());
1260                 currentVar->initFrom(item);
1261             }
1262             delete item;
1263         }
1264         m_tempVars.clear();
1265     }
1266     EASY_END_BLOCK;
1267 
1268     if (collectionName.compare("csvs", Qt::CaseInsensitive) == 0){
1269         QMutableListIterator<CSVDesc*> it(m_csvs);
1270         while (it.hasNext()){
1271             it.next();
1272             if (!m_datasources.contains(it.value()->name().toLower())){
1273                 connect(it.value(), SIGNAL(cvsTextChanged(QString,QString)),
1274                         this, SLOT(slotCSVTextChanged(QString,QString)));
1275                 putHolder(
1276                     it.value()->name(),
1277                     new CSVHolder(*it.value(), this)
1278                 );
1279             } else {
1280                 delete it.value();
1281                 it.remove();
1282             }
1283         }
1284     }
1285 
1286     if (designTime()){
1287         EASY_BLOCK("emit datasourcesChanged()");
1288         emit datasourcesChanged();
1289         EASY_END_BLOCK;
1290     }
1291     EASY_BLOCK("emit loadCollectionFinished(collectionName)");
1292     emit loadCollectionFinished(collectionName);
1293     EASY_END_BLOCK;
1294     EASY_END_BLOCK;
1295 }
1296 
addVariable(const QString & name,const QVariant & value,VarDesc::VarType type,RenderPass pass)1297 void DataSourceManager::addVariable(const QString &name, const QVariant &value, VarDesc::VarType type, RenderPass pass)
1298 {
1299     if (type == VarDesc::User){
1300         m_userVariables.addVariable(name, value, type, pass);
1301     } else {
1302         m_reportVariables.addVariable(name,value,type,pass);
1303     }
1304     if (designTime()){
1305         EASY_BLOCK("DataSourceManager::addVariable emit ds changed");
1306         emit datasourcesChanged();
1307         EASY_END_BLOCK;
1308     }
1309 }
1310 
deleteVariable(const QString & name)1311 void DataSourceManager::deleteVariable(const QString& name)
1312 {
1313     m_userVariables.deleteVariable(name);
1314     if (m_reportVariables.containsVariable(name)&&m_reportVariables.variableType(name)==VarDesc::Report){
1315         m_reportVariables.deleteVariable(name);
1316         if (designTime()){
1317             m_hasChanges = true;
1318             emit datasourcesChanged();
1319         }
1320     }
1321 }
1322 
changeVariable(const QString & name,const QVariant & value)1323 void DataSourceManager::changeVariable(const QString& name,const QVariant& value)
1324 {
1325     if (m_userVariables.containsVariable(name)){
1326         m_userVariables.changeVariable(name,value);
1327     }
1328     if (m_reportVariables.containsVariable(name)){
1329         m_reportVariables.changeVariable(name,value);
1330     }
1331 
1332 }
1333 
setSystemVariable(const QString & name,const QVariant & value,RenderPass pass)1334 void DataSourceManager::setSystemVariable(const QString &name, const QVariant &value, RenderPass pass)
1335 {
1336     addVariable(name,value,VarDesc::System,pass);
1337 }
1338 
setLastError(const QString & value)1339 void DataSourceManager::setLastError(const QString &value){
1340     m_lastError =  value;
1341     if (!value.isEmpty() && !m_errorsList.contains(value)) {
1342         m_errorsList.append(value);
1343     }
1344 }
1345 
invalidateLinkedDatasources(QString datasourceName)1346 void DataSourceManager::invalidateLinkedDatasources(QString datasourceName)
1347 {
1348     foreach(QString name, dataSourceNames()){
1349         if (isSubQuery(name)){
1350            if (subQueryByName(name)->master() == datasourceName)
1351                dataSourceHolder(name)->invalidate(designTime()?IDataSource::DESIGN_MODE:IDataSource::RENDER_MODE);
1352         }
1353         if (isProxy(name)){
1354             ProxyDesc* proxy = proxyByName(name);
1355             if ((proxy->master() == datasourceName) || (proxy->child() == datasourceName))
1356                 dataSourceHolder(name)->invalidate(designTime()?IDataSource::DESIGN_MODE:IDataSource::RENDER_MODE);
1357 
1358         }
1359     }
1360 }
1361 
slotConnectionRenamed(const QString & oldName,const QString & newName)1362 void DataSourceManager::slotConnectionRenamed(const QString &oldName, const QString &newName)
1363 {
1364     foreach(QueryDesc* query, m_queries){
1365         if (query->connectionName().compare(oldName,Qt::CaseInsensitive)==0) query->setConnectionName(newName);
1366     }
1367     foreach(SubQueryDesc* query, m_subqueries){
1368         if (query->connectionName().compare(oldName,Qt::CaseInsensitive)==0) query->setConnectionName(newName);
1369     }
1370 }
1371 
slotQueryTextChanged(const QString & queryName,const QString & queryText)1372 void DataSourceManager::slotQueryTextChanged(const QString &queryName, const QString &queryText)
1373 {
1374     QueryHolder* holder = dynamic_cast<QueryHolder*>(m_datasources.value(queryName));
1375     if (holder){
1376         holder->setQueryText(queryText);
1377     }
1378     m_varToDataSource.clear();
1379 }
1380 
invalidateQueriesContainsVariable(const QString & variableName)1381 void DataSourceManager::invalidateQueriesContainsVariable(const QString& variableName)
1382 {
1383     if (!variableIsSystem(variableName)){
1384 
1385         if (m_varToDataSource.contains(variableName)){
1386             foreach(QString datasourceName, m_varToDataSource.value(variableName)){
1387                 QueryHolder* holder = dynamic_cast<QueryHolder*>(m_datasources.value(datasourceName));
1388                 if (holder) holder->invalidate(designTime() ? IDataSource::DESIGN_MODE : IDataSource::RENDER_MODE);
1389             }
1390         } else {
1391             QVector<QString> datasources;
1392             foreach (const QString& datasourceName, dataSourceNames()){
1393                 QueryHolder* holder = dynamic_cast<QueryHolder*>(m_datasources.value(datasourceName));
1394                 if (holder){
1395                     QRegExp rx(QString(Const::NAMED_VARIABLE_RX).arg(variableName));
1396                     if  (holder->queryText().contains(rx)){
1397                         holder->invalidate(designTime() ? IDataSource::DESIGN_MODE : IDataSource::RENDER_MODE);
1398                         datasources.append(datasourceName);
1399                     }
1400                 }
1401             }
1402             m_varToDataSource.insert(variableName, datasources);
1403         }
1404     }
1405 }
1406 
slotVariableHasBeenAdded(const QString & variableName)1407 void DataSourceManager::slotVariableHasBeenAdded(const QString& variableName)
1408 {
1409     invalidateQueriesContainsVariable(variableName);
1410     if (variableType(variableName) == VarDesc::Report)
1411         m_hasChanges = true;
1412 }
1413 
slotVariableHasBeenChanged(const QString & variableName)1414 void DataSourceManager::slotVariableHasBeenChanged(const QString& variableName)
1415 {
1416     invalidateQueriesContainsVariable(variableName);
1417     if (variableType(variableName) == VarDesc::Report)
1418         m_hasChanges = true;
1419 }
1420 
slotCSVTextChanged(const QString & csvName,const QString & csvText)1421 void DataSourceManager::slotCSVTextChanged(const QString &csvName, const QString &csvText)
1422 {
1423     CSVHolder* holder = dynamic_cast<CSVHolder*>(m_datasources.value(csvName));
1424     if (holder){
1425         holder->setCSVText(csvText);
1426     }
1427 }
1428 
clear(ClearMethod method)1429 void DataSourceManager::clear(ClearMethod method)
1430 {
1431     m_varToDataSource.clear();
1432 
1433     DataSourcesMap::iterator dit;
1434     for( dit = m_datasources.begin(); dit != m_datasources.end(); ){
1435         bool owned = (*dit)->isOwned() && (*dit)->isRemovable();
1436         switch(method){
1437         case All:
1438             invalidateLinkedDatasources(dit.key());
1439             delete dit.value();
1440             m_datasources.erase(dit++);
1441             break;
1442         default:
1443             if (owned){
1444                 invalidateLinkedDatasources(dit.key());
1445                 delete dit.value();
1446                 m_datasources.erase(dit++);
1447             } else {
1448                 ++dit;
1449             }
1450         }
1451 
1452     }
1453 
1454     QList<ConnectionDesc*>::iterator cit = m_connections.begin();
1455     while( cit != m_connections.end() ){
1456         if ( (*cit)->isInternal() )
1457             QSqlDatabase::removeDatabase( (*cit)->name() );
1458         delete (*cit);
1459         cit = m_connections.erase(cit);
1460     }
1461 
1462     //TODO: add smart pointes to collections
1463     foreach(QueryDesc *desc, m_queries) delete desc;
1464     foreach(SubQueryDesc* desc, m_subqueries) delete desc;
1465     foreach(ProxyDesc* desc, m_proxies) delete desc;
1466 
1467     m_queries.clear();
1468     m_subqueries.clear();
1469     m_proxies.clear();
1470 //    if (method == All)
1471 //        clearUserVariables();
1472     clearReportVariables();
1473 
1474     emit cleared();
1475 }
1476 
clearGroupFunction()1477 void DataSourceManager::clearGroupFunction()
1478 {
1479     foreach(GroupFunction* gf ,m_groupFunctions.values()){
1480         delete gf;
1481     }
1482     m_groupFunctions.clear();
1483 }
1484 
clearGroupFunctionValues(const QString & bandObjectName)1485 void DataSourceManager::clearGroupFunctionValues(const QString& bandObjectName)
1486 {
1487     foreach(GroupFunction* gf, m_groupFunctions.values(bandObjectName)){
1488         gf->values().clear();
1489     }
1490 }
1491 
addGroupFunction(const QString & name,const QString & expression,const QString & band,const QString & dataBand)1492 GroupFunction* DataSourceManager::addGroupFunction(const QString &name, const QString &expression, const QString &band, const QString& dataBand)
1493 {
1494     GroupFunction* gf = m_groupFunctionFactory.createGroupFunction(name,expression,dataBand,this);
1495     if (gf){
1496         m_groupFunctions.insert(band,gf);
1497     }
1498     return gf;
1499 }
1500 
groupFunction(const QString & name,const QString & expression,const QString & band)1501 GroupFunction *DataSourceManager::groupFunction(const QString &name, const QString &expression, const QString &band)
1502 {
1503     foreach(GroupFunction* gf,m_groupFunctions.values(band)){
1504         if ((gf->name().compare(name,Qt::CaseInsensitive)==0)&&
1505             (gf->data().compare(expression,Qt::CaseInsensitive)==0)
1506            ) return gf;
1507     }
1508     return 0;
1509 }
1510 
groupFunctionsByBand(const QString & band)1511 QList<GroupFunction *> DataSourceManager::groupFunctionsByBand(const QString &band)
1512 {
1513     return m_groupFunctions.values(band);
1514 }
1515 
updateChildrenData(const QString & datasourceName)1516 void DataSourceManager::updateChildrenData(const QString &datasourceName)
1517 {
1518     foreach(SubQueryDesc* subquery,m_subqueries){
1519         if (subquery->master().compare(datasourceName,Qt::CaseInsensitive)==0){
1520             SubQueryHolder* holder=dynamic_cast<SubQueryHolder*>(dataSourceHolder(subquery->queryName()));
1521             if (holder) holder->runQuery();
1522         }
1523     }
1524     foreach(ProxyDesc* subproxy,m_proxies){
1525         if(subproxy->master().compare(datasourceName,Qt::CaseInsensitive)==0){
1526             ProxyHolder* holder = dynamic_cast<ProxyHolder*>(dataSourceHolder(subproxy->name()));
1527             holder->filterModel();
1528         }
1529     }
1530 }
1531 
extractDataSource(const QString & fieldName)1532 QString DataSourceManager::extractDataSource(const QString &fieldName)
1533 {
1534     return fieldName.left(fieldName.indexOf('.'));
1535 }
1536 
extractFieldName(const QString & fieldName)1537 QString DataSourceManager::extractFieldName(const QString &fieldName)
1538 {
1539     return fieldName.right((fieldName.length()-fieldName.indexOf('.'))-1);
1540 }
1541 
containsField(const QString & fieldName)1542 bool DataSourceManager::containsField(const QString &fieldName)
1543 {
1544     IDataSource* ds = dataSource(extractDataSource(fieldName));
1545     if (ds) {
1546         return ds->columnIndexByName(extractFieldName(fieldName))!=-1;
1547     }
1548     return false;
1549 }
1550 
containsVariable(const QString & variableName)1551 bool DataSourceManager::containsVariable(const QString& variableName)
1552 {
1553     if (m_userVariables.containsVariable(variableName)) return true;
1554     return m_reportVariables.containsVariable(variableName);
1555 }
1556 
clearUserVariables()1557 void DataSourceManager::clearUserVariables()
1558 {
1559     m_userVariables.clearUserVariables();
1560     m_reportVariables.clearUserVariables();
1561 }
1562 
fieldData(const QString & fieldName)1563 QVariant DataSourceManager::fieldData(const QString &fieldName)
1564 {
1565     if (containsField(fieldName)){
1566         IDataSource* ds = dataSource(extractDataSource(fieldName));
1567         if (ds) return ds->data(extractFieldName(fieldName));
1568     }
1569     return QVariant();
1570 }
1571 
fieldDataByRowIndex(const QString & fieldName,int rowIndex)1572 QVariant DataSourceManager::fieldDataByRowIndex(const QString &fieldName, int rowIndex)
1573 {
1574     if (containsField(fieldName)){
1575         IDataSource* ds = dataSource(extractDataSource(fieldName));
1576         if (ds){
1577             return ds->dataByRowIndex(extractFieldName(fieldName), rowIndex);
1578         }
1579     }
1580     return QVariant();
1581 }
1582 
fieldDataByKey(const QString & datasourceName,const QString & valueFieldName,const QString & keyFieldName,QVariant keyValue)1583 QVariant DataSourceManager::fieldDataByKey(const QString& datasourceName, const QString& valueFieldName, const QString& keyFieldName, QVariant keyValue)
1584 {
1585     IDataSource* ds = dataSource(datasourceName);
1586     if (ds){
1587         return ds->dataByKeyField(valueFieldName, keyFieldName, keyValue);
1588     }
1589     return QVariant();
1590 }
1591 
reopenDatasource(const QString & datasourceName)1592 void DataSourceManager::reopenDatasource(const QString& datasourceName)
1593 {
1594     QueryHolder* qh = dynamic_cast<QueryHolder*>(dataSourceHolder(datasourceName));
1595     if (qh){
1596         qh->invalidate(designTime()?IDataSource::DESIGN_MODE:IDataSource::RENDER_MODE);
1597         invalidateChildren(datasourceName);
1598     }
1599 }
1600 
variable(const QString & variableName)1601 QVariant DataSourceManager::variable(const QString &variableName)
1602 {
1603     if (m_userVariables.containsVariable(variableName))
1604         return m_userVariables.variable(variableName);
1605     return m_reportVariables.variable(variableName);
1606 }
1607 
variablePass(const QString & name)1608 RenderPass DataSourceManager::variablePass(const QString &name)
1609 {
1610     if (m_userVariables.containsVariable(name))
1611         return m_userVariables.variablePass(name);
1612     return m_reportVariables.variablePass(name);
1613 }
1614 
variableIsSystem(const QString & name)1615 bool DataSourceManager::variableIsSystem(const QString &name)
1616 {
1617     if (m_reportVariables.containsVariable(name))
1618         return (m_reportVariables.variableType(name)==VarDesc::System);
1619     return false;
1620 }
1621 
variableIsMandatory(const QString & name)1622 bool DataSourceManager::variableIsMandatory(const QString& name)
1623 {
1624     if (m_reportVariables.containsVariable(name))
1625         return m_reportVariables.variableByName(name)->isMandatory();
1626     return false;
1627 }
1628 
setVarableMandatory(const QString & name,bool value)1629 void DataSourceManager::setVarableMandatory(const QString& name, bool value)
1630 {
1631     if (m_reportVariables.containsVariable(name))
1632         m_reportVariables.variableByName(name)->setMandatory(value);
1633 }
1634 
variableNames()1635 QStringList DataSourceManager::variableNames()
1636 {
1637     return m_reportVariables.variableNames();
1638 }
1639 
variableNamesByRenderPass(RenderPass pass)1640 QStringList DataSourceManager::variableNamesByRenderPass(RenderPass pass)
1641 {
1642     QStringList result;
1643     foreach(QString variableName, m_reportVariables.variableNames()){
1644         if (m_reportVariables.variablePass(variableName) == pass){
1645             result.append(variableName);
1646         }
1647     }
1648     return result;
1649 }
1650 
userVariableNames()1651 QStringList DataSourceManager::userVariableNames(){
1652     return m_userVariables.variableNames();
1653 }
1654 
variableType(const QString & name)1655 VarDesc::VarType DataSourceManager::variableType(const QString &name)
1656 {
1657     if (m_reportVariables.containsVariable(name))
1658         return m_reportVariables.variableType(name);
1659     return VarDesc::User;
1660 }
1661 
variableDataType(const QString & name)1662 VariableDataType DataSourceManager::variableDataType(const QString& name)
1663 {
1664     if (m_reportVariables.containsVariable(name))
1665         return m_reportVariables.variableByName(name)->dataType();
1666     return Enums::Undefined;
1667 }
1668 
setVariableDataType(const QString & name,VariableDataType value)1669 void DataSourceManager::setVariableDataType(const QString& name, VariableDataType value)
1670 {
1671     if (m_reportVariables.containsVariable(name))
1672         m_reportVariables.variableByName(name)->setDataType(value);
1673 }
1674 
setAllDatasourcesToFirst()1675 void DataSourceManager::setAllDatasourcesToFirst()
1676 {
1677     foreach(IDataSourceHolder* ds,m_datasources.values()) {
1678         if (ds->dataSource()) ds->dataSource()->first();
1679     }
1680 }
1681 
1682 } //namespace LimeReport
1683