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