/*************************************************************************** * This file is part of the Lime Report project * * Copyright (C) 2015 by Alexander Arin * * arin_a@bk.ru * * * ** GNU General Public License Usage ** * * * This library is free software: you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation, either version 3 of the License, or * * (at your option) any later version. * * You should have received a copy of the GNU General Public License * * along with this program. If not, see . * * * ** GNU Lesser General Public License ** * * * This library is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of the * * License, or (at your option) any later version. * * You should have received a copy of the GNU Lesser General Public * * License along with this library. * * If not, see . * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * ****************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include "ui_lrdatabrowser.h" #include "lrdatabrowser.h" #include "lrsqleditdialog.h" #include "lrconnectiondialog.h" #include "lrreportengine_p.h" #include "lrvariabledialog.h" #include "lrdatabrowsertree.h" namespace LimeReport{ DataBrowser::DataBrowser(QWidget *parent) : QWidget(parent), ui(new Ui::DataBrowser), m_report(0), m_closingWindows(false), m_settings(0), m_ownedSettings(false) { ui->setupUi(this); connect(ui->addConnection,SIGNAL(clicked()),this,SLOT(slotAddConnection())); connect(ui->deleteConection,SIGNAL(clicked()),this,SLOT(slotDeleteConnection())); connect(ui->addDataSource,SIGNAL(clicked()),this,SLOT(slotAddDataSource())); connect(ui->viewDataSource,SIGNAL(clicked()),this,SLOT(slotViewDatasource())); connect(ui->editDataSource,SIGNAL(clicked()),this,SLOT(slotEditDatasource())); connect(ui->deleteDataSource,SIGNAL(clicked()),this,SLOT(slotDeleteDatasource())); connect(ui->changeConnection,SIGNAL(clicked()),this,SLOT(slotChangeConnection())); connect(ui->pbConnect,SIGNAL(clicked()),this,SLOT(slotChangeConnectionState())); ui->dataTree->setHeaderLabel(tr("Datasources")); ui->pbConnect->setEnabled(false); } DataBrowser::~DataBrowser() { delete ui; if (m_settings && m_ownedSettings) delete m_settings; } QSize DataBrowser::sizeHint() const { return QSize(100,200); } void DataBrowser::slotAddConnection() { ConnectionDialog *connectionEdit = new ConnectionDialog(this,0,this); connectionEdit->setAttribute(Qt::WA_DeleteOnClose,true); #ifdef Q_OS_MAC connectionEdit->setWindowModality(Qt::WindowModal); #else connectionEdit->setWindowModality(Qt::ApplicationModal); #endif //connect(connectionEdit,SIGNAL(finished(int)),this,SLOT(slotConnectionEditFinished(int))); //connect(connectionEdit,SIGNAL(conectionRegistred(QString)),this,SLOT(slotConnectionRegistred(QString))); connectionEdit->exec(); } void DataBrowser::slotSQLEditingFinished(SQLEditResult result) { if (result.dialogMode==SQLEditDialog::AddMode) { switch (result.resultMode) { case SQLEditResult::Query: addQuery(result); break; case SQLEditResult::SubQuery: addSubQuery(result); break; case SQLEditResult::SubProxy: addProxy(result); default: break; } } else { switch(result.resultMode){ case SQLEditResult::Query: changeQuery(result); break; case SQLEditResult::SubQuery: changeSubQuery(result); break; case SQLEditResult::SubProxy: changeProxy(result); } } updateDataTree(); } void DataBrowser::slotDeleteConnection() { if (!getConnectionName(NameForUser).isEmpty()){ if ( QMessageBox::critical( this, tr("Attention"), tr("Do you really want to delete \"%1\" connection ?").arg(getConnectionName(NameForUser)), QMessageBox::Ok|QMessageBox::No, QMessageBox::No ) == QMessageBox::Ok ){ m_report->dataManager()->removeConnection(getConnectionName(NameForReport)); updateDataTree(); } } } void DataBrowser::slotAddDataSource() { SQLEditDialog *sqlEdit = new SQLEditDialog(this,m_report->dataManager(),SQLEditDialog::AddMode); sqlEdit->setAttribute(Qt::WA_DeleteOnClose,true); #ifdef Q_OS_MAC sqlEdit->setWindowModality(Qt::WindowModal); #else sqlEdit->setWindowModality(Qt::ApplicationModal); #endif sqlEdit->setSettings(settings()); sqlEdit->setDataSources(m_report->dataManager()); sqlEdit->setDefaultConnection(getConnectionName(NameForReport)); connect(sqlEdit,SIGNAL(signalSqlEditingFinished(SQLEditResult)),this,SLOT(slotSQLEditingFinished(SQLEditResult))); sqlEdit->exec(); } void DataBrowser::updateDataTree() { QString selectedText = ""; int selectedType = 0; if (ui->dataTree->selectedItems().count()==1){ selectedType = ui->dataTree->selectedItems().at(0)->type(); selectedText = ui->dataTree->selectedItems().at(0)->text(0); } initConnections(); foreach(QString dataSourceName, m_report->datasourcesNames()){ QTreeWidgetItem *item=new QTreeWidgetItem(QStringList(dataSourceName),DataBrowserTree::Table); QTreeWidgetItem *parentItem = findByNameAndType( ConnectionDesc::connectionNameForUser(m_report->dataManager()->connectionName(dataSourceName)), DataBrowserTree::Connection ); if (parentItem){ parentItem->addChild(item); if (!parentItem->isExpanded()) ui->dataTree->expandItem(parentItem); } else { ui->dataTree->addTopLevelItem(item); } try{ IDataSource* datasource = m_report->dataManager()->dataSource(dataSourceName); if (datasource){ fillFields(item,datasource); if (!datasource->isInvalid()) item->setIcon(0,QIcon(":/databrowser/images/table_good")); else item->setIcon(0,QIcon(":/databrowser/images/table_error")); } else item->setIcon(0,QIcon(":/databrowser/images/table_error")); } catch(ReportError& /*exception*/) { item->setIcon(0,QIcon(":/databrowser/images/table_error")); //qDebug()<setSelected(true); ui->dataTree->setCurrentItem(selectedItem); } } void DataBrowser::updateVariablesTree() { ui->variablesTree->clear(); QTreeWidgetItem *reportVariables = new QTreeWidgetItem(QStringList(tr("Report variables")),DataBrowserTree::Category); reportVariables->setIcon(0,QIcon(":/report/images/folder")); QTreeWidgetItem *systemVariables =new QTreeWidgetItem(QStringList(tr("System variables")),DataBrowserTree::Category); systemVariables->setIcon(0,QIcon(":/report/images/folder")); QTreeWidgetItem *externalVariables = new QTreeWidgetItem(QStringList(tr("External variables")),DataBrowserTree::Category); externalVariables->setIcon(0,QIcon(":/report/images/folder")); ui->variablesTree->addTopLevelItem(reportVariables); ui->variablesTree->addTopLevelItem(systemVariables); ui->variablesTree->addTopLevelItem(externalVariables); foreach(QString variableName,m_report->dataManager()->variableNames()){ QStringList values; values<dataManager()->variableIsSystem(variableName))? "": " ["+m_report->dataManager()->variable(variableName).toString()+"]" ) <setIcon(0,QIcon(":/databrowser/images/value")); if (m_report->dataManager()->variableIsSystem(variableName)){ systemVariables->addChild(item); } else { reportVariables->addChild(item); } } foreach(QString variableName,m_report->dataManager()->namesOfUserVariables()){ if (!m_report->dataManager()->variableNames().contains(variableName)){ QStringList values; values<dataManager()->variable(variableName).toString()+"]" <setIcon(0,QIcon(":/databrowser/images/value")); externalVariables->addChild(item); } } ui->variablesTree->expandItem(reportVariables); ui->variablesTree->expandItem(systemVariables); ui->variablesTree->expandItem(externalVariables); } void DataBrowser::closeAllDataWindows() { m_closingWindows = true; QMap::iterator it = m_dataWindows.begin(); for(;it!=m_dataWindows.end();){ (*it)->close(); delete (*it); it = m_dataWindows.erase(it); } m_closingWindows = false; } void DataBrowser::setSettings(QSettings *value, bool owned) { if (m_settings && m_ownedSettings) delete m_settings; m_settings=value; m_ownedSettings = owned; } QSettings *DataBrowser::settings() { if (m_settings){ return m_settings; } else { m_settings = new QSettings("LimeReport",QApplication::applicationName()); m_ownedSettings = true; return m_settings; } } void DataBrowser::slotDatasourcesChanged() { updateDataTree(); } void DataBrowser::fillFields(QTreeWidgetItem *parentItem, LimeReport::IDataSource *dataSource) { if (!dataSource) return; for (int i=0;icolumnCount();i++){ QTreeWidgetItem *item = new QTreeWidgetItem(QStringList(dataSource->columnNameByIndex(i)),DataBrowserTree::Row); item->setIcon(0,QIcon(":/databrowser/images/field")); parentItem->addChild(item); } parentItem->sortChildren(0,Qt::AscendingOrder); } QTreeWidgetItem * DataBrowser::findByNameAndType(QString name, int itemType) { if (name.isEmpty()) return 0; QListitems = ui->dataTree->findItems(name,Qt::MatchContains | Qt::MatchRecursive); if (!items.isEmpty()){ for (int i=0;itype()==itemType)/* && (items.at(0)->text(0)==name)*/){ return items.at(i);} } } return 0; } void DataBrowser::slotViewDatasource() { QString datasourceName=getDatasourceName(); if (!datasourceName.isEmpty()){ showDataWindow(datasourceName); } } QString DataBrowser::getDatasourceName() { if (ui->dataTree->currentItem()){ if (ui->dataTree->currentItem()->type() == DataBrowserTree::Table) return ui->dataTree->currentItem()->text(0); if (ui->dataTree->currentItem()->type() == DataBrowserTree::Row) return ui->dataTree->currentItem()->parent()->text(0); }; return QString(); } QTreeWidgetItem* findConnectionItem(QTreeWidgetItem* item){ if (item->type() == DataBrowserTree::Connection){ return item; } else { if (item->parent()) return findConnectionItem(item->parent()); else return 0; } } QString DataBrowser::getConnectionName(NameType nameType) { if (ui->dataTree->currentItem()){ QTreeWidgetItem * ci = findConnectionItem(ui->dataTree->currentItem()); if (ci) { switch (nameType) { case NameForUser: return ConnectionDesc::connectionNameForUser(ci->text(0)); case NameForReport: return ConnectionDesc::connectionNameForReport(ci->text(0)); } } else return QString(); }; return QString(); } QString DataBrowser::getVariable() { if( ui->variablesTree->currentItem() && (ui->variablesTree->currentItem()->type() == DataBrowserTree::Variable || ui->variablesTree->currentItem()->type() == DataBrowserTree::ExternalVariable) ){ return ui->variablesTree->currentItem()->text(1); } return QString(); } void DataBrowser::slotEditDatasource() { if (!getDatasourceName().isEmpty()){ closeDataWindow(getDatasourceName()); SQLEditDialog *sqlEdit = new SQLEditDialog(this,m_report->dataManager(),SQLEditDialog::EditMode); sqlEdit->setAttribute(Qt::WA_DeleteOnClose); #ifdef Q_OS_MAC sqlEdit->setWindowModality(Qt::WindowModal); #else sqlEdit->setWindowModality(Qt::ApplicationModal); #endif sqlEdit->setSettings(settings()); sqlEdit->setDataSources(m_report->dataManager(),getDatasourceName()); connect(sqlEdit,SIGNAL(signalSqlEditingFinished(SQLEditResult)),this,SLOT(slotSQLEditingFinished(SQLEditResult))); sqlEdit->exec(); } } void DataBrowser::slotDeleteDatasource() { QString datasourceName=getDatasourceName(); QTreeWidgetItem *item = findByNameAndType(datasourceName, DataBrowserTree::Table); if (item){ if ( QMessageBox::critical( this, tr("Attention"), tr("Do you really want to delete \"%1\" datasource ?").arg(datasourceName), QMessageBox::Ok|QMessageBox::No, QMessageBox::No ) == QMessageBox::Ok ){ removeDatasource(datasourceName); } } } void DataBrowser::setReportEditor(LimeReport::ReportDesignWidget *report) { m_report=report; connect(m_report,SIGNAL(cleared()),this,SLOT(slotClear())); connect(m_report->dataManager(), SIGNAL(datasourcesChanged()), this, SLOT(slotDatasourcesChanged())); updateDataTree(); updateVariablesTree(); } void DataBrowser::slotClear() { ui->dataTree->clear(); foreach(QDockWidget* window,m_dataWindows.values()) window->close(); updateDataTree(); updateVariablesTree(); } void DataBrowser::initConnections() { ui->dataTree->clear(); QListitems; foreach(QString connectionName,m_report->dataManager()->connectionNames()){ QTreeWidgetItem *item=new QTreeWidgetItem( ui->dataTree, QStringList(ConnectionDesc::connectionNameForUser(connectionName)), DataBrowserTree::Connection ); if (m_report->dataManager()->isConnectionConnected(connectionName)) item->setIcon(0,QIcon(":/databrowser/images/database_connected")); else item->setIcon(0,QIcon(":/databrowser/images/database_disconnected")); items.append(item); } ui->dataTree->insertTopLevelItems(0,items); } QDockWidget *DataBrowser::createDataWindow(QString datasourceName) { QDockWidget *window = new QDockWidget("Table: "+datasourceName); QTableView *tableView = new QTableView(window); //TODO: exception or message ? try { IDataSourceHolder* holder = m_report->dataManager()->dataSourceHolder(datasourceName); if (holder) holder->update(); IDataSource* datasource = m_report->dataManager()->dataSource(datasourceName); if (datasource){ tableView->setModel(datasource->model()); } } catch (ReportError& exception) { qDebug()<setWidget(tableView); window->setAttribute(Qt::WA_DeleteOnClose); connect(window,SIGNAL(destroyed()),this,SLOT(slotDataWindowClosed())); if (!m_dataWindows.isEmpty()) m_mainWindow->tabifyDockWidget(m_dataWindows.values().at(0),window); else m_mainWindow->addDockWidget(Qt::BottomDockWidgetArea,window); m_dataWindows.insert(datasourceName,window); return window; } QDockWidget *DataBrowser::dataWindow(QString datasourceName) { if (m_dataWindows.contains(datasourceName)){ return m_dataWindows.value(datasourceName); } else return createDataWindow(datasourceName); } void DataBrowser::setMainWindow(QMainWindow *mainWindow) { m_mainWindow=mainWindow; } void DataBrowser::slotDataWindowClosed() { if (isClosingWindows()) return; for (int i=0;idataManager()->connectionByName(getConnectionName(NameForReport)), this ); connectionEdit->setAttribute(Qt::WA_DeleteOnClose,true); #ifdef Q_OS_MAC connectionEdit->setWindowModality(Qt::WindowModal); #else connectionEdit->setWindowModality(Qt::ApplicationModal); #endif //connect(connectionEdit,SIGNAL(finished(int)),this,SLOT(slotConnectionEditFinished(int))); connectionEdit->exec(); } } void DataBrowser::slotChangeConnectionState() { QString connectionName = getConnectionName(NameForReport); if (!connectionName.isEmpty()){ if (!m_report->dataManager()->isConnectionConnected(connectionName)){ setCursor(Qt::WaitCursor); //try { if (!m_report->dataManager()->connectConnection(connectionName)){ //} catch(std::runtime_error &exception) { QMessageBox::critical(this,tr("Attention"),m_report->dataManager()->lastError()); //} } updateDataTree(); setCursor(Qt::ArrowCursor); } else { m_report->dataManager()->disconnectConnection(connectionName); updateDataTree(); } } } void DataBrowser::slotVariableEditorAccept(const QString &variable) { updateVariablesTree(); QList items = ui->variablesTree->findItems(variable, Qt::MatchContains | Qt::MatchRecursive); if (!items.isEmpty()){ ui->variablesTree->setCurrentItem(items.at(0)); } } void DataBrowser::showDataWindow(QString datasourceName) { QDockWidget *window = dataWindow(datasourceName); if (window){ window->show(); window->raise(); } } void DataBrowser::closeDataWindow(QString datasourceName) { if (m_dataWindows.contains(datasourceName)) m_dataWindows.value(datasourceName)->close(); } void DataBrowser::removeDatasource(QString datasourceName) { closeDataWindow(datasourceName); m_report->dataManager()->removeDatasource(datasourceName); } void DataBrowser::addQuery(SQLEditResult result) { try { m_report->dataManager()->addQuery(result.datasourceName, result.sql, result.connectionName); } catch(ReportError &exception){ qDebug()<dataManager()->removeDatasource(result.oldDatasourceName); m_report->dataManager()->addQuery(result.datasourceName, result.sql, result.connectionName); }catch(ReportError &exception){ qDebug()<dataManager()->addSubQuery(result.datasourceName, result.sql, result.connectionName, result.masterDatasource); } catch(ReportError &exception){ qDebug()<dataManager()->removeDatasource(result.oldDatasourceName); m_report->dataManager()->addSubQuery(result.datasourceName, result.sql, result.connectionName, result.masterDatasource); }catch(ReportError &exception){ qDebug()<dataManager()->addProxy(result.datasourceName,result.masterDatasource,result.childDataSource,result.fieldMap); } catch(ReportError &exception){ qDebug()<dataManager()->removeDatasource(result.oldDatasourceName); m_report->dataManager()->addProxy(result.datasourceName,result.masterDatasource,result.childDataSource,result.fieldMap); } catch(ReportError &exception){ qDebug()<dataManager()->addConnectionDesc(connection); updateDataTree(); } void DataBrowser::changeConnectionDesc(ConnectionDesc *connection) { if (connection->autoconnect()) m_report->dataManager()->connectConnection(connection->name()); updateDataTree(); } bool DataBrowser::checkConnectionDesc(ConnectionDesc *connection) { bool result = m_report->dataManager()->checkConnectionDesc(connection); if (!result) setLastError(m_report->dataManager()->lastError()); return result; } bool DataBrowser::containsDefaultConnection() { bool result = m_report->dataManager()->connectionByName(QSqlDatabase::defaultConnection); return result; } QString DataBrowser::lastError() const { return m_lastError; } void DataBrowser::setLastError(const QString &lastError) { m_lastError = lastError; } void DataBrowser::on_dataTree_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous) { Q_UNUSED(previous) if (current&&(current->type() == DataBrowserTree::Connection)) { ui->pbConnect->setEnabled(true); if (m_report->dataManager()->isConnectionConnected(current->text(0))){ ui->pbConnect->setIcon(QIcon(":/databrowser/images/plug-connect.png")); } else { ui->pbConnect->setIcon(QIcon(":/databrowser/images/plug-disconnect.png")); } ui->editDataSource->setEnabled(false); ui->deleteDataSource->setEnabled(false); ui->viewDataSource->setEnabled(false); ui->changeConnection->setEnabled(true); ui->deleteConection->setEnabled(true); ui->errorMessage->setDisabled(true); } else { ui->changeConnection->setEnabled(false); ui->deleteConection->setEnabled(false); ui->pbConnect->setEnabled(false); IDataSourceHolder* holder = m_report->dataManager()->dataSourceHolder(getDatasourceName()); if (holder){ ui->viewDataSource->setEnabled(!holder->isInvalid()); ui->editDataSource->setEnabled(holder->isEditable()); ui->deleteDataSource->setEnabled(holder->isRemovable()); if (!holder->lastError().isEmpty()){ ui->errorMessage->setEnabled(true); } else {ui->errorMessage->setEnabled(false);} } } } void LimeReport::DataBrowser::on_addVariable_clicked() { LRVariableDialog dialog(this); #ifdef Q_OS_MAC dialog.setWindowModality(Qt::WindowModal); #else dialog.setWindowModality(Qt::ApplicationModal); #endif dialog.setVariableContainer(m_report->dataManager()); connect(&dialog,SIGNAL(signalVariableAccepted(QString)),this,SLOT(slotVariableEditorAccept(QString))); dialog.exec(); } void DataBrowser::on_editVariable_clicked() { if (!getVariable().isEmpty()) { LRVariableDialog dialog(this); #ifdef Q_OS_MAC dialog.setWindowModality(Qt::WindowModal); #else dialog.setWindowModality(Qt::ApplicationModal); #endif dialog.setVariableContainer(m_report->dataManager()); QString varName = getVariable(); dialog.setVariableName(varName); connect(&dialog,SIGNAL(signalVariableAccepted(QString)),this,SLOT(slotVariableEditorAccept(QString))); dialog.exec(); } } void DataBrowser::on_deleteVariable_clicked() { QString varName = getVariable(); if (!varName.isEmpty()){ if (QMessageBox::critical(this,tr("Attention"),QString(tr("Do you really want to delete variable \"%1\" ?")).arg(varName), QMessageBox::Ok|QMessageBox::Cancel, QMessageBox::Cancel )==QMessageBox::Ok){ m_report->dataManager()->deleteVariable(varName); updateVariablesTree(); } } } void DataBrowser::on_variablesTree_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous) { Q_UNUSED(previous) if (current){ if (m_report->dataManager()->containsVariable(current->text(1))){ if (m_report->dataManager()->variableType(current->text(1)) == VarDesc::Report){ ui->editVariable->setEnabled(true); ui->deleteVariable->setEnabled(true); } else { ui->editVariable->setEnabled(false); ui->deleteVariable->setEnabled(false); } if (m_report->dataManager()->variableType(current->text(1)) == VarDesc::User){ ui->varToReport->setEnabled(true); } else { ui->varToReport->setEnabled(false); } } else { ui->editVariable->setEnabled(false); ui->deleteVariable->setEnabled(false); ui->varToReport->setEnabled(false); } } } void DataBrowser::on_errorMessage_clicked() { if(!getDatasourceName().isEmpty()&&m_report->dataManager()->dataSourceHolder(getDatasourceName())){ QMessageBox::critical(this,tr("Error"),m_report->dataManager()->dataSourceHolder(getDatasourceName())->lastError()); } } void DataBrowser::on_varToReport_clicked() { QString varName = getVariable(); if (!varName.isEmpty()){ m_report->dataManager()->addVariable(varName,m_report->dataManager()->variable(varName), VarDesc::Report); ui->varToReport->setEnabled(false); updateVariablesTree(); } } void DataBrowser::on_variablesTree_itemDoubleClicked(QTreeWidgetItem *item, int ) { if (item){ QString varName = item->text(1); if ( !varName.isEmpty() && (m_report->dataManager()->variableType(varName) == VarDesc::Report) ){ LRVariableDialog dialog(this); #ifdef Q_OS_MAC dialog.setWindowModality(Qt::WindowModal); #else dialog.setWindowModality(Qt::ApplicationModal); #endif dialog.setVariableContainer(m_report->dataManager()); dialog.setVariableName(varName); connect(&dialog,SIGNAL(signalVariableAccepted(QString)),this,SLOT(slotVariableEditorAccept(QString))); dialog.exec(); } } } } // namespace LimeReport