diff --git a/CMakeLists.txt b/CMakeLists.txt index 6ba0f51..00f0869 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,15 +3,17 @@ cmake_minimum_required(VERSION 3.14) set(LIMEREPORT_VERSION_MAJOR 1) set(LIMEREPORT_VERSION_MINOR 6) -set(LIMEREPORT_VERSION_RELEASE 6) +set(LIMEREPORT_VERSION_RELEASE 8) option(ENABLE_ZINT "Enable libzint build for barcode support" OFF) option(LIMEREPORT_STATIC "Build LimeReport as static library" OFF) +option(USE_QT6 "Use Qt6" OFF) -find_package( - QT NAMES Qt6 Qt5 - COMPONENTS Core Widgets Sql Network Xml Svg Qml PrintSupport REQUIRED - ) +if(USE_QT6) + find_package(QT NAMES Qt6) +else() + find_package(QT NAMES Qt5) +endif(USE_QT6) find_package( Qt${QT_VERSION_MAJOR} COMPONENTS Core Widgets Sql Network Xml Svg Qml PrintSupport REQUIRED @@ -36,7 +38,7 @@ endif() add_subdirectory(3rdparty) add_subdirectory(designer EXCLUDE_FROM_ALL) -add_subdirectory(demo_r1 EXCLUDE_FROM_ALL) +add_subdirectory(demo_r1 EXCLUDE_FROM_ALL) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOUIC ON) @@ -78,6 +80,7 @@ ${PROJECT_NAME}/items/editors/lrtextalignmenteditorwidget.cpp ${PROJECT_NAME}/items/lrabstractlayout.cpp ${PROJECT_NAME}/items/lralignpropitem.cpp ${PROJECT_NAME}/items/lrchartitem.cpp +${PROJECT_NAME}/items/lrchartaxiseditor.cpp ${PROJECT_NAME}/items/lrchartitemeditor.cpp ${PROJECT_NAME}/items/lrhorizontallayout.cpp ${PROJECT_NAME}/items/lrimageitem.cpp @@ -189,6 +192,7 @@ ${PROJECT_NAME}/items/editors/lrtextalignmenteditorwidget.h ${PROJECT_NAME}/items/lrabstractlayout.h ${PROJECT_NAME}/items/lralignpropitem.h ${PROJECT_NAME}/items/lrchartitem.h +${PROJECT_NAME}/items/lrchartaxiseditor.h ${PROJECT_NAME}/items/lrchartitemeditor.h ${PROJECT_NAME}/items/lreditableimageitemintf.h ${PROJECT_NAME}/items/lrhorizontallayout.h @@ -285,6 +289,7 @@ ${PROJECT_NAME}/databrowser/lrsqleditdialog.ui ${PROJECT_NAME}/databrowser/lrvariabledialog.ui ${PROJECT_NAME}/dialogdesigner/templates/Dialog.ui ${PROJECT_NAME}/items/lrchartitemeditor.ui +${PROJECT_NAME}/items/lrchartaxiseditor.ui ${PROJECT_NAME}/items/lrimageitemeditor.ui ${PROJECT_NAME}/items/lrtextitemeditor.ui ${PROJECT_NAME}/lraboutdialog.ui @@ -340,6 +345,8 @@ set(GLOBAL_HEADERS ${CMAKE_CURRENT_BINARY_DIR}/config.h ) +set(PROJECT_NAME ${PROJECT_NAME}-qt${QT_VERSION_MAJOR}) + if (LIMEREPORT_STATIC) message(STATUS "STATIC LIBRARY") add_library(${PROJECT_NAME} STATIC ${EXTRA_FILES} ${LIMEREPORT_SOURCES}) diff --git a/README.md b/README.md index b5b6c10..f03702b 100644 --- a/README.md +++ b/README.md @@ -3,8 +3,6 @@ ## Official LimeReport web site [http://limereport.ru](http://limereport.ru) -## Donation [![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.me/arinalex) - ## Features * Multi-platform support diff --git a/common.pri b/common.pri index ebf1c89..160fdce 100644 --- a/common.pri +++ b/common.pri @@ -141,7 +141,7 @@ RCC_DIR = $${ARCH_DIR}/$${BUILD_TYPE}/rcc LIMEREPORT_VERSION_MAJOR = 1 LIMEREPORT_VERSION_MINOR = 6 -LIMEREPORT_VERSION_RELEASE = 0 +LIMEREPORT_VERSION_RELEASE = 8 LIMEREPORT_VERSION = '$${LIMEREPORT_VERSION_MAJOR}.$${LIMEREPORT_VERSION_MINOR}.$${LIMEREPORT_VERSION_RELEASE}' DEFINES *= LIMEREPORT_VERSION_STR=\\\"$${LIMEREPORT_VERSION}\\\" diff --git a/demo_r1/CMakeLists.txt b/demo_r1/CMakeLists.txt index a694da1..da749ac 100644 --- a/demo_r1/CMakeLists.txt +++ b/demo_r1/CMakeLists.txt @@ -18,6 +18,6 @@ target_link_libraries(demo_r1 PRIVATE Qt${QT_VERSION_MAJOR}::PrintSupport Qt${QT_VERSION_MAJOR}::Qml Qt${QT_VERSION_MAJOR}::Sql - ${PROJECT_NAME} + ${PROJECT_NAME}-qt${QT_VERSION_MAJOR} ) diff --git a/designer/CMakeLists.txt b/designer/CMakeLists.txt index 3f3ffe4..d63ea0b 100644 --- a/designer/CMakeLists.txt +++ b/designer/CMakeLists.txt @@ -14,5 +14,7 @@ target_include_directories(LRDesigner PUBLIC ${PROJECT_SOURCE_DIR}/include) target_link_libraries(LRDesigner PUBLIC Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Widgets - ${PROJECT_NAME} + Qt${QT_VERSION_MAJOR}::PrintSupport + Qt${QT_VERSION_MAJOR}::Qml + ${PROJECT_NAME}-qt${QT_VERSION_MAJOR} ) diff --git a/include/lrglobal.h b/include/lrglobal.h index ed0254a..b2fe56c 100644 --- a/include/lrglobal.h +++ b/include/lrglobal.h @@ -104,7 +104,7 @@ namespace Const{ QString extractClassName(QString className); QString escapeSimbols(const QString& value); QString replaceHTMLSymbols(const QString &value); -#if QT_VERSION >= QT_VERSION_CHECK(5, 12, 3) +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 1) QVector normalizeCaptures(const QRegularExpressionMatch ®); #else QVector normalizeCaptures(const QRegExp ®); @@ -157,6 +157,16 @@ namespace Const{ #else typedef QStyleOptionViewItem StyleOptionViewItem; #endif +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 1) + QRegularExpression getRegEx(QString expression); + QRegularExpression getVariableRegEx(); + QRegularExpression getFieldRegEx(); + QRegularExpression getScriptRegEx(); + QRegularExpression getGroupFunctionRegEx(QString functionName); + QRegularExpression getGroupFunctionNameRegEx(QString functionName); + QRegularExpression getNamedVariableRegEx(QString variableName); +#endif + class Enums { diff --git a/limereport/databrowser/lrdatabrowsertree.cpp b/limereport/databrowser/lrdatabrowsertree.cpp index 2625602..53934f3 100644 --- a/limereport/databrowser/lrdatabrowsertree.cpp +++ b/limereport/databrowser/lrdatabrowsertree.cpp @@ -36,7 +36,11 @@ namespace LimeReport { DataBrowserTree::DataBrowserTree(QWidget *parent) : QTreeWidget(parent){} +#if QT_VERSION >= QT_VERSION_CHECK(6,0,0) +QMimeData *DataBrowserTree::mimeData(const QList &items) const +#else QMimeData *DataBrowserTree::mimeData(const QList items) const +#endif { QMimeData* result = QTreeWidget::mimeData(items); if (items.at(0)->type()==Row){ diff --git a/limereport/databrowser/lrdatabrowsertree.h b/limereport/databrowser/lrdatabrowsertree.h index 3cbcdff..eb03791 100644 --- a/limereport/databrowser/lrdatabrowsertree.h +++ b/limereport/databrowser/lrdatabrowsertree.h @@ -42,7 +42,11 @@ public: enum NodeType{Connection, Table, Row, Category, Variable, ExternalVariable}; explicit DataBrowserTree(QWidget *parent = 0); protected: - QMimeData* mimeData(const QList items) const; +#if QT_VERSION >= QT_VERSION_CHECK(6,0,0) + virtual QMimeData *mimeData(const QList &items) const; +#else + virtual QMimeData *mimeData(const QList items) const; +#endif public slots: diff --git a/limereport/databrowser/lrsqleditdialog.cpp b/limereport/databrowser/lrsqleditdialog.cpp index 7fe874f..92e5b3a 100644 --- a/limereport/databrowser/lrsqleditdialog.cpp +++ b/limereport/databrowser/lrsqleditdialog.cpp @@ -28,20 +28,18 @@ * GNU General Public License for more details. * ****************************************************************************/ #include "lrsqleditdialog.h" -#include "ui_lrsqleditdialog.h" #include "lrreportengine_p.h" +#include "ui_lrsqleditdialog.h" #include -#include #include +#include -namespace LimeReport{ +namespace LimeReport { -SQLEditDialog::SQLEditDialog(QWidget *parent, LimeReport::DataSourceManager *dataSources, SQLDialogMode dialogMode) : - QDialog(parent), - ui(new Ui::SQLEditDialog),m_datasources(dataSources),m_dialogMode(dialogMode), m_oldDatasourceName(""), - m_settings(0), m_ownedSettings(false) -{ +SQLEditDialog::SQLEditDialog(QWidget *parent, LimeReport::DataSourceManager *dataSources, SQLDialogMode dialogMode) + : QDialog(parent), ui(new Ui::SQLEditDialog), m_datasources(dataSources), m_dialogMode(dialogMode), + m_oldDatasourceName(""), m_settings(0), m_ownedSettings(false) { ui->setupUi(this); m_masterDatasources = new QCompleter(this); ui->leMaster->setCompleter(m_masterDatasources); @@ -54,72 +52,72 @@ SQLEditDialog::SQLEditDialog(QWidget *parent, LimeReport::DataSourceManager *dat ui->rbSubQuery->setVisible(false); ui->leMaster->setVisible(false); ui->lbMaster->setVisible(false); - ui->fieldsMap->setHorizontalHeaderItem(0,new QTableWidgetItem("master")); - ui->fieldsMap->setHorizontalHeaderItem(1,new QTableWidgetItem("detail")); + ui->fieldsMap->setHorizontalHeaderItem(0, new QTableWidgetItem("master")); + ui->fieldsMap->setHorizontalHeaderItem(1, new QTableWidgetItem("detail")); -#ifdef HAVE_QT5 ui->fieldsMap->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); -#else - ui->fieldsMap->horizontalHeader()->setResizeMode(QHeaderView::Stretch); -#endif + ui->pnlChildDatasource->setVisible(false); connect(ui->pbPreview, SIGNAL(pressed()), this, SLOT(slotPreviewData())); connect(ui->pbHidePreview, SIGNAL(pressed()), this, SLOT(slotHidePreview())); } -SQLEditDialog::~SQLEditDialog() -{ +SQLEditDialog::~SQLEditDialog() { delete ui; if (m_settings && m_ownedSettings) delete m_settings; } -QSettings *SQLEditDialog::settings(){ - if (m_settings){ +QSettings *SQLEditDialog::settings() { + if (m_settings) { return m_settings; } else { - m_settings = new QSettings("LimeReport",QCoreApplication::applicationName()); + m_settings = new QSettings("LimeReport", QCoreApplication::applicationName()); m_ownedSettings = true; return m_settings; } } -void SQLEditDialog::setSettings(QSettings *value, bool owned){ - if (m_settings && m_ownedSettings) delete m_settings; +void SQLEditDialog::setSettings(QSettings *value, bool owned) { + if (m_settings && m_ownedSettings) + delete m_settings; m_settings = value; m_ownedSettings = owned; } -void SQLEditDialog::accept() -{ +void SQLEditDialog::accept() { SQLEditResult result; - if (ui->tabWidget->currentIndex() == 1){ + if (ui->tabWidget->currentIndex() == 1) { result.resultMode = SQLEditResult::CSVText; - } else if (!ui->cbSubdetail->isChecked()){ - result.resultMode=SQLEditResult::Query; + } else if (!ui->cbSubdetail->isChecked()) { + result.resultMode = SQLEditResult::Query; } else { - if (ui->rbSubQuery->isChecked()) result.resultMode = SQLEditResult::SubQuery; - else result.resultMode=SQLEditResult::SubProxy; + if (ui->rbSubQuery->isChecked()) + result.resultMode = SQLEditResult::SubQuery; + else + result.resultMode = SQLEditResult::SubProxy; } result.connectionName = ConnectionDesc::connectionNameForReport(ui->cbbConnection->currentText()); - result.datasourceName=ui->leDatasourceName->text(); + result.datasourceName = ui->leDatasourceName->text(); result.sql = ui->sqlText->toPlainText(); result.csv = ui->csvText->toPlainText(); result.dialogMode = m_dialogMode; result.oldDatasourceName = m_oldDatasourceName; result.subdetail = ui->cbSubdetail->isChecked(); - result.masterDatasource=ui->leMaster->text(); - result.childDataSource=ui->leChild->text(); + result.masterDatasource = ui->leMaster->text(); + result.childDataSource = ui->leChild->text(); result.separator = ui->leSeparator->text(); result.firstRowIsHeader = ui->cbUseFirstRowAsHeader->isChecked(); - if (ui->fieldsMap->rowCount() > 0){ - for(int i=0; i< ui->fieldsMap->rowCount(); ++i){ + if (ui->fieldsMap->rowCount() > 0) { + for (int i = 0; i < ui->fieldsMap->rowCount(); ++i) { LimeReport::FieldsCorrelation fieldsCorrelation; - fieldsCorrelation.master = ui->fieldsMap->item(i,0) ? ui->fieldsMap->item(i,0)->data(Qt::DisplayRole).toString() : ""; - fieldsCorrelation.detail = ui->fieldsMap->item(i,1) ? ui->fieldsMap->item(i,1)->data(Qt::DisplayRole).toString() : ""; + fieldsCorrelation.master = + ui->fieldsMap->item(i, 0) ? ui->fieldsMap->item(i, 0)->data(Qt::DisplayRole).toString() : ""; + fieldsCorrelation.detail = + ui->fieldsMap->item(i, 1) ? ui->fieldsMap->item(i, 1)->data(Qt::DisplayRole).toString() : ""; result.fieldMap.append(fieldsCorrelation); } } @@ -128,87 +126,83 @@ void SQLEditDialog::accept() check(); emit signalSqlEditingFinished(result); QDialog::accept(); - }catch(LimeReport::ReportError &exception){ - QMessageBox::critical(this,tr("Error"),exception.what()); + } catch (LimeReport::ReportError &exception) { + QMessageBox::critical(this, tr("Error"), exception.what()); } } -void SQLEditDialog::showEvent(QShowEvent *) -{ +void SQLEditDialog::showEvent(QShowEvent *) { ui->lblInfo->setVisible(false); initConnections(); readSettings(); } -void SQLEditDialog::closeEvent(QCloseEvent *) -{ - writeSetting(); -} +void SQLEditDialog::closeEvent(QCloseEvent *) { writeSetting(); } -void SQLEditDialog::hideEvent(QHideEvent *) -{ - writeSetting(); -} +void SQLEditDialog::hideEvent(QHideEvent *) { writeSetting(); } -void SQLEditDialog::check() -{ - if (ui->leDatasourceName->text().isEmpty()) throw LimeReport::ReportError(tr("Datasource Name is empty!")); - if (ui->sqlText->toPlainText().isEmpty() && (!ui->rbProxy) ) throw LimeReport::ReportError(tr("SQL is empty!")); - if (m_dialogMode==AddMode){ - if (m_datasources->containsDatasource(ui->leDatasourceName->text())){ - throw LimeReport::ReportError(QString(tr("Datasource with name: \"%1\" already exists!")).arg(ui->leDatasourceName->text())); +void SQLEditDialog::check() { + if (ui->leDatasourceName->text().isEmpty()) + throw LimeReport::ReportError(tr("Datasource Name is empty!")); + if (ui->sqlText->toPlainText().isEmpty() && (!ui->rbProxy)) + throw LimeReport::ReportError(tr("SQL is empty!")); + if (m_dialogMode == AddMode) { + if (m_datasources->containsDatasource(ui->leDatasourceName->text())) { + throw LimeReport::ReportError( + QString(tr("Datasource with name: \"%1\" already exists!")).arg(ui->leDatasourceName->text())); } } } -void SQLEditDialog::initConnections() -{ - foreach(QString connectionName, QSqlDatabase::connectionNames()){ - ui->cbbConnection->addItem(QIcon(":/databrowser/images/plug-connect.png"),ConnectionDesc::connectionNameForUser(connectionName)); +void SQLEditDialog::initConnections() { + foreach (QString connectionName, QSqlDatabase::connectionNames()) { + ui->cbbConnection->addItem(QIcon(":/databrowser/images/plug-connect.png"), + ConnectionDesc::connectionNameForUser(connectionName)); } - foreach(QString connectionName, m_datasources->connectionNames()){ - connectionName = (connectionName.compare(QSqlDatabase::defaultConnection)==0) ? - tr("defaultConnection") : connectionName; - if (ui->cbbConnection->findText(connectionName,Qt::MatchExactly )==-1) - ui->cbbConnection->addItem(QIcon(":/databrowser/images/plug-disconnect.png"),ConnectionDesc::connectionNameForUser(connectionName)); + foreach (QString connectionName, m_datasources->connectionNames()) { + connectionName = + (connectionName.compare(QSqlDatabase::defaultConnection) == 0) ? tr("defaultConnection") : connectionName; + if (ui->cbbConnection->findText(connectionName, Qt::MatchExactly) == -1) + ui->cbbConnection->addItem(QIcon(":/databrowser/images/plug-disconnect.png"), + ConnectionDesc::connectionNameForUser(connectionName)); } ui->cbbConnection->setCurrentIndex(ui->cbbConnection->findText(m_defaultConnection)); - if (!m_oldDatasourceName.isEmpty()){ - ui->cbbConnection->setCurrentIndex(ui->cbbConnection->findText(ConnectionDesc::connectionNameForUser(m_datasources->connectionName(m_oldDatasourceName)))); + if (!m_oldDatasourceName.isEmpty()) { + ui->cbbConnection->setCurrentIndex(ui->cbbConnection->findText( + ConnectionDesc::connectionNameForUser(m_datasources->connectionName(m_oldDatasourceName)))); } } -void SQLEditDialog::setDataSources(LimeReport::DataSourceManager *dataSources, QString datasourceName) -{ - m_datasources=dataSources; - if (!datasourceName.isEmpty()){ +void SQLEditDialog::setDataSources(LimeReport::DataSourceManager *dataSources, QString datasourceName) { + m_datasources = dataSources; + if (!datasourceName.isEmpty()) { ui->cbSubdetail->setEnabled(true); - m_oldDatasourceName=datasourceName; + m_oldDatasourceName = datasourceName; ui->leDatasourceName->setText(datasourceName); ui->sqlText->setText(dataSources->queryText(datasourceName)); - if (dataSources->isQuery(datasourceName)){ + if (dataSources->isQuery(datasourceName)) { initQueryMode(); } - if (dataSources->isSubQuery(datasourceName)){ + if (dataSources->isSubQuery(datasourceName)) { initSubQueryMode(); ui->leMaster->setText(dataSources->subQueryByName(datasourceName)->master()); } - if (dataSources->isProxy(datasourceName)){ + if (dataSources->isProxy(datasourceName)) { initProxyMode(); - LimeReport::ProxyDesc* proxyDesc = dataSources->proxyByName(datasourceName); + LimeReport::ProxyDesc *proxyDesc = dataSources->proxyByName(datasourceName); ui->leChild->setText(proxyDesc->child()); ui->leMaster->setText(proxyDesc->master()); - int curIndex=0; - foreach(LimeReport::FieldMapDesc* fields, *proxyDesc->fieldsMap()){ - ui->fieldsMap->setRowCount(curIndex+1); - ui->fieldsMap->setItem(curIndex,0,new QTableWidgetItem(fields->master())); - ui->fieldsMap->setItem(curIndex,1,new QTableWidgetItem(fields->detail())); + int curIndex = 0; + foreach (LimeReport::FieldMapDesc *fields, *proxyDesc->fieldsMap()) { + ui->fieldsMap->setRowCount(curIndex + 1); + ui->fieldsMap->setItem(curIndex, 0, new QTableWidgetItem(fields->master())); + ui->fieldsMap->setItem(curIndex, 1, new QTableWidgetItem(fields->detail())); curIndex++; } } - if (dataSources->isCSV(datasourceName)){ + if (dataSources->isCSV(datasourceName)) { ui->csvText->setPlainText(dataSources->csvByName(datasourceName)->csvText()); ui->leSeparator->setText(dataSources->csvByName(datasourceName)->separator()); ui->cbUseFirstRowAsHeader->setChecked(dataSources->csvByName(datasourceName)->firstRowIsHeader()); @@ -217,59 +211,55 @@ void SQLEditDialog::setDataSources(LimeReport::DataSourceManager *dataSources, Q } } -void SQLEditDialog::setDefaultConnection(QString defaultConnection) -{ +void SQLEditDialog::setDefaultConnection(QString defaultConnection) { m_defaultConnection = ConnectionDesc::connectionNameForUser(defaultConnection); } -void SQLEditDialog::slotDataSourceNameEditing() -{ - if (m_dialogMode==AddMode){ - QPalette palette=ui->leDatasourceName->palette(); - if (m_datasources->containsDatasource(ui->leDatasourceName->text())){ - palette.setColor(QPalette::Text,Qt::red); +void SQLEditDialog::slotDataSourceNameEditing() { + if (m_dialogMode == AddMode) { + QPalette palette = ui->leDatasourceName->palette(); + if (m_datasources->containsDatasource(ui->leDatasourceName->text())) { + palette.setColor(QPalette::Text, Qt::red); ui->leDatasourceName->setPalette(palette); - ui->lblInfo->setText(QString(tr("Datasource with name %1 already exist")).arg(ui->leDatasourceName->text())); + ui->lblInfo->setText( + QString(tr("Datasource with name %1 already exist")).arg(ui->leDatasourceName->text())); ui->lblInfo->setVisible(true); } else { - palette.setColor(QPalette::Text,QApplication::palette().text().color()); + palette.setColor(QPalette::Text, QApplication::palette().text().color()); ui->leDatasourceName->setPalette(palette); ui->lblInfo->setVisible(false); } } } -void SQLEditDialog::on_cbSubdetail_clicked(bool checked) -{ - if (checked){ - m_masterDatasources->setModel(new QStringListModel(m_datasources->dataSourceNames(),m_datasources)); +void SQLEditDialog::on_cbSubdetail_clicked(bool checked) { + if (checked) { + m_masterDatasources->setModel(new QStringListModel(m_datasources->dataSourceNames(), m_datasources)); } ui->leMaster->setEnabled(checked); ui->rbProxy->setEnabled(checked); ui->rbSubQuery->setEnabled(checked); - if ((checked)&&(ui->rbProxy->isChecked())) initProxyMode(); - if ((checked)&&(ui->rbSubQuery->isChecked())) initSubQueryMode(); - if (!checked) initQueryMode(); + if ((checked) && (ui->rbProxy->isChecked())) + initProxyMode(); + if ((checked) && (ui->rbSubQuery->isChecked())) + initSubQueryMode(); + if (!checked) + initQueryMode(); } -void SQLEditDialog::on_rbProxy_clicked(bool checked) -{ - if (checked) initProxyMode(); +void SQLEditDialog::on_rbProxy_clicked(bool checked) { + if (checked) + initProxyMode(); } -void SQLEditDialog::on_rbSubQuery_clicked(bool checked) -{ - if (checked) initSubQueryMode(); +void SQLEditDialog::on_rbSubQuery_clicked(bool checked) { + if (checked) + initSubQueryMode(); } -void SQLEditDialog::on_pbAddField_clicked() -{ - ui->fieldsMap->setRowCount(ui->fieldsMap->rowCount()+1); -} +void SQLEditDialog::on_pbAddField_clicked() { ui->fieldsMap->setRowCount(ui->fieldsMap->rowCount() + 1); } - -void SQLEditDialog::initQueryMode() -{ +void SQLEditDialog::initQueryMode() { ui->gbSQL->setVisible(true); ui->gbFieldsMap->setVisible(false); ui->pnlChildDatasource->setVisible(false); @@ -278,12 +268,11 @@ void SQLEditDialog::initQueryMode() ui->cbSubdetail->setChecked(false); ui->leMaster->setVisible(false); ui->lbMaster->setVisible(false); - //ui->tabWidget->removeTab(1); + // ui->tabWidget->removeTab(1); ui->tabWidget->addTab(ui->csvTab, tr("CSV")); } -void SQLEditDialog::initSubQueryMode() -{ +void SQLEditDialog::initSubQueryMode() { ui->gbSQL->setVisible(true); ui->gbFieldsMap->setVisible(false); ui->pnlChildDatasource->setVisible(false); @@ -297,8 +286,7 @@ void SQLEditDialog::initSubQueryMode() ui->tabWidget->removeTab(1); } -void SQLEditDialog::initProxyMode() -{ +void SQLEditDialog::initProxyMode() { ui->gbSQL->setVisible(false); ui->gbFieldsMap->setVisible(true); ui->pnlChildDatasource->setVisible(true); @@ -313,23 +301,17 @@ void SQLEditDialog::initProxyMode() ui->tabWidget->removeTab(1); } -void SQLEditDialog::initCSVMode() -{ - ui->tabWidget->setCurrentWidget(ui->csvTab); -} +void SQLEditDialog::initCSVMode() { ui->tabWidget->setCurrentWidget(ui->csvTab); } -void SQLEditDialog::slotPreviewData() -{ - if (ui->cbbConnection->currentText().isEmpty()){ - QMessageBox::critical(this,tr("Attention"),tr("Connection is not specified")); +void SQLEditDialog::slotPreviewData() { + if (ui->cbbConnection->currentText().isEmpty()) { + QMessageBox::critical(this, tr("Attention"), tr("Connection is not specified")); return; } - m_previewModel = m_datasources->previewSQL( - ConnectionDesc::connectionNameForReport(ui->cbbConnection->currentText()), - ui->sqlText->toPlainText(), - ui->leMaster->text() - ); - if (m_previewModel){ + m_previewModel = + m_datasources->previewSQL(ConnectionDesc::connectionNameForReport(ui->cbbConnection->currentText()), + ui->sqlText->toPlainText(), ui->leMaster->text()); + if (m_previewModel) { ui->tvPreview->setModel(m_previewModel.data()); ui->gbDataPreview->setVisible(true); ui->pbPreview->setText(tr("Refresh")); @@ -337,49 +319,37 @@ void SQLEditDialog::slotPreviewData() } else { if (ui->gbDataPreview->isVisible()) hidePreview(); - QMessageBox::critical(this,tr("Attention"),m_datasources->lastError()); + QMessageBox::critical(this, tr("Attention"), m_datasources->lastError()); } } -void SQLEditDialog::slotHidePreview() -{ - hidePreview(); -} +void SQLEditDialog::slotHidePreview() { hidePreview(); } -void SQLEditDialog::writeSetting() -{ - if (settings()!=0){ +void SQLEditDialog::writeSetting() { + if (settings() != 0) { settings()->beginGroup("SQLEditor"); - settings()->setValue("Geometry",saveGeometry()); + settings()->setValue("Geometry", saveGeometry()); settings()->endGroup(); } } -void SQLEditDialog::readSettings() -{ - if (settings()==0) return; +void SQLEditDialog::readSettings() { + if (settings() == 0) + return; settings()->beginGroup("SQLEditor"); QVariant v = settings()->value("Geometry"); - if (v.isValid()){ + if (v.isValid()) { restoreGeometry(v.toByteArray()); } settings()->endGroup(); } -void SQLEditDialog::hidePreview() -{ +void SQLEditDialog::hidePreview() { ui->gbDataPreview->setVisible(false); ui->pbPreview->setText(tr("Preview")); ui->pbHidePreview->setVisible(false); } -void SQLEditDialog::on_pbDelField_clicked() -{ - ui->fieldsMap->removeRow(ui->fieldsMap->currentRow()); -} +void SQLEditDialog::on_pbDelField_clicked() { ui->fieldsMap->removeRow(ui->fieldsMap->currentRow()); } } // namespace LimeReport - - - - diff --git a/limereport/designer.pri b/limereport/designer.pri index 13bf6ea..ab07ed6 100644 --- a/limereport/designer.pri +++ b/limereport/designer.pri @@ -30,6 +30,7 @@ SOURCES += \ $$REPORT_PATH/objectinspector/propertyItems/lrcontentpropitem.cpp \ $$REPORT_PATH/objectinspector/propertyItems/lrmarginpropitem.cpp \ $$REPORT_PATH/objectinspector/propertyItems/lrseriespropitem.cpp \ + $$REPORT_PATH/objectinspector/propertyItems/lraxispropitem.cpp \ $$REPORT_PATH/objectinspector/editors/lrtextitempropertyeditor.cpp \ $$REPORT_PATH/objectinspector/editors/lrcomboboxeditor.cpp \ $$REPORT_PATH/objectinspector/editors/lrcheckboxeditor.cpp \ @@ -80,6 +81,7 @@ HEADERS += \ $$REPORT_PATH/objectinspector/propertyItems/lrcolorpropitem.h \ $$REPORT_PATH/objectinspector/propertyItems/lrmarginpropitem.h \ $$REPORT_PATH/objectinspector/propertyItems/lrseriespropitem.h \ + $$REPORT_PATH/objectinspector/propertyItems/lraxispropitem.h \ $$REPORT_PATH/objectinspector/editors/lrtextitempropertyeditor.h \ $$REPORT_PATH/objectinspector/editors/lrcomboboxeditor.h \ $$REPORT_PATH/objectinspector/editors/lrcheckboxeditor.h \ diff --git a/limereport/items/charts/lrlineschart.cpp b/limereport/items/charts/lrlineschart.cpp index 36aabc6..18c8692 100644 --- a/limereport/items/charts/lrlineschart.cpp +++ b/limereport/items/charts/lrlineschart.cpp @@ -70,7 +70,12 @@ void LinesChart::drawDesignMode(QPainter* painter, qreal hStep, qreal vStep, qre qreal LinesChart::calculatePos(const AxisData &data, qreal value, qreal rectSize) const { - return (data.rangeMax() - value) / data.delta() * rectSize; + if (data.type() == AxisData::XAxis || (data.reverseDirection() && data.rangeMin() >= 0)) { + // Not flipping for minimum less than 0 because lower number is at the bottom. + return (1 - (data.rangeMax() - value) / data.delta()) * rectSize; + } else { + return (data.rangeMax() - value) / data.delta() * rectSize; + } } void LinesChart::paintSeries(QPainter *painter, SeriesItem *series, QRectF barsRect) diff --git a/limereport/items/charts/lrpiechart.cpp b/limereport/items/charts/lrpiechart.cpp index 5932c9e..dbc7687 100644 --- a/limereport/items/charts/lrpiechart.cpp +++ b/limereport/items/charts/lrpiechart.cpp @@ -143,7 +143,7 @@ void PieChart::paintChartLegend(QPainter *painter, QRectF legendRect) } } -QSizeF PieChart::calcChartLegendSize(const QFont &font) +QSizeF PieChart::calcChartLegendSize(const QFont &font, qreal) { QFontMetrics fm(font); diff --git a/limereport/items/charts/lrpiechart.h b/limereport/items/charts/lrpiechart.h index 2b3fb6f..88337f2 100644 --- a/limereport/items/charts/lrpiechart.h +++ b/limereport/items/charts/lrpiechart.h @@ -8,7 +8,7 @@ namespace LimeReport{ class PieChart : public AbstractChart{ public: PieChart(ChartItem* chartItem):AbstractChart(chartItem){} - QSizeF calcChartLegendSize(const QFont &font); + QSizeF calcChartLegendSize(const QFont &font, qreal maxWidth = 0); void paintChart(QPainter *painter, QRectF chartRect); void paintChartLegend(QPainter *painter, QRectF legendRect); protected: diff --git a/limereport/items/charts/lrverticalbarchart.cpp b/limereport/items/charts/lrverticalbarchart.cpp index 36109b0..bccc244 100644 --- a/limereport/items/charts/lrverticalbarchart.cpp +++ b/limereport/items/charts/lrverticalbarchart.cpp @@ -71,8 +71,6 @@ void VerticalBarChart::paintVerticalBars(QPainter *painter, QRectF barsRect) qreal hStep = (barsRect.width() / valuesCount()) / (barSeriesCount == 0 ? 1 : barSeriesCount); qreal topShift = (delta - (maxValue() - minValue())) * vStep + barsRect.top(); - qDebug() << "vStep" << vStep << "hStep" << hStep; - if (!m_chartItem->series().isEmpty() && (m_chartItem->itemMode() != DesignMode)){ int curSeries = 0; foreach (SeriesItem* series, m_chartItem->series()) { diff --git a/limereport/items/lrabstractlayout.cpp b/limereport/items/lrabstractlayout.cpp index 22d17a2..1f59848 100644 --- a/limereport/items/lrabstractlayout.cpp +++ b/limereport/items/lrabstractlayout.cpp @@ -48,7 +48,6 @@ void AbstractLayout::setLayoutType(const LayoutType& layoutType) void AbstractLayout::addChild(BaseDesignIntf* item, bool updateSize) { - placeItemInLayout(item); m_children.append(item); @@ -57,22 +56,7 @@ void AbstractLayout::addChild(BaseDesignIntf* item, bool updateSize) item->setFixedPos(true); item->setPossibleResizeDirectionFlags(ResizeRight | ResizeBottom); - connect( - item, SIGNAL(destroyed(QObject*)), - this, SLOT(slotOnChildDestroy(QObject*)) - ); - connect( - item,SIGNAL(geometryChanged(QObject*,QRectF,QRectF)), - this,SLOT(slotOnChildGeometryChanged(QObject*,QRectF,QRectF)) - ); - connect( - item, SIGNAL(itemVisibleHasChanged(BaseDesignIntf*)), - this, SLOT(slotOnChildVisibleHasChanged(BaseDesignIntf*)) - ); - connect( - item, SIGNAL(itemSelectedHasBeenChanged(BaseDesignIntf*,bool)), - this, SLOT(slotOnChildSelectionHasChanged(BaseDesignIntf*,bool)) - ); + connectToLayout(item); if (updateSize){ relocateChildren(); @@ -80,19 +64,23 @@ void AbstractLayout::addChild(BaseDesignIntf* item, bool updateSize) } } +void AbstractLayout::removeChild(BaseDesignIntf *item) +{ + if (!item) { + return; + } + m_children.removeAll(item); + disconnectFromLayout(item); +} + void AbstractLayout::restoreChild(BaseDesignIntf* item) { if (m_children.contains(item)) return; - m_isRelocating=true; insertItemInLayout(item); - connect(item,SIGNAL(destroyed(QObject*)),this,SLOT(slotOnChildDestroy(QObject*))); - connect(item,SIGNAL(geometryChanged(QObject*,QRectF,QRectF)), - this,SLOT(slotOnChildGeometryChanged(QObject*,QRectF,QRectF))); - connect(item, SIGNAL(itemAlignChanged(BaseDesignIntf*,ItemAlign,ItemAlign)), - this, SLOT(slotOnChildItemAlignChanged(BaseDesignIntf*,ItemAlign,ItemAlign))); + connectToLayout(item); item->setFixedPos(true); item->setPossibleResizeDirectionFlags(ResizeRight | ResizeBottom); @@ -267,6 +255,54 @@ void AbstractLayout::rebuildChildrenIfNeeded(){ } } +void AbstractLayout::connectToLayout(BaseDesignIntf *item) +{ + connect( + item, SIGNAL(destroyed(QObject*)), + this, SLOT(slotOnChildDestroy(QObject*)) + ); + connect( + item,SIGNAL(geometryChanged(QObject*,QRectF,QRectF)), + this,SLOT(slotOnChildGeometryChanged(QObject*,QRectF,QRectF)) + ); + connect( + item, SIGNAL(itemVisibleHasChanged(BaseDesignIntf*)), + this, SLOT(slotOnChildVisibleHasChanged(BaseDesignIntf*)) + ); + connect( + item, SIGNAL(itemSelectedHasBeenChanged(BaseDesignIntf*,bool)), + this, SLOT(slotOnChildSelectionHasChanged(BaseDesignIntf*,bool)) + ); + connect( + item, SIGNAL(itemAlignChanged(BaseDesignIntf*, const ItemAlign&, const ItemAlign&)), + this, SLOT(slotOnChildItemAlignChanged(BaseDesignIntf*,const ItemAlign&,const ItemAlign&)) + ); +} + +void AbstractLayout::disconnectFromLayout(BaseDesignIntf *item) +{ + disconnect( + item, SIGNAL(destroyed(QObject*)), + this, SLOT(slotOnChildDestroy(QObject*)) + ); + disconnect( + item,SIGNAL(geometryChanged(QObject*,QRectF,QRectF)), + this,SLOT(slotOnChildGeometryChanged(QObject*,QRectF,QRectF)) + ); + disconnect( + item, SIGNAL(itemVisibleHasChanged(BaseDesignIntf*)), + this, SLOT(slotOnChildVisibleHasChanged(BaseDesignIntf*)) + ); + disconnect( + item, SIGNAL(itemSelectedHasBeenChanged(BaseDesignIntf*,bool)), + this, SLOT(slotOnChildSelectionHasChanged(BaseDesignIntf*,bool)) + ); + disconnect( + item, SIGNAL(itemAlignChanged(BaseDesignIntf*, const ItemAlign&, const ItemAlign&)), + this, SLOT(slotOnChildItemAlignChanged(BaseDesignIntf*,const ItemAlign&,const ItemAlign&)) + ); +} + BaseDesignIntf *AbstractLayout::findNext(BaseDesignIntf *item) { rebuildChildrenIfNeeded(); @@ -288,7 +324,7 @@ BaseDesignIntf *AbstractLayout::findPrior(BaseDesignIntf *item) void AbstractLayout::slotOnChildDestroy(QObject* child) { m_children.removeAll(static_cast(child)); - if (m_children.count()<2){ + if (m_children.count() < 2 && !static_cast(child)){ beforeDelete(); } else { relocateChildren(); @@ -316,7 +352,7 @@ void AbstractLayout::slotOnChildGeometryChanged(QObject* item, QRectF newGeometr } } -void AbstractLayout::slotOnChildItemAlignChanged(BaseDesignIntf* item, const BaseDesignIntf::ItemAlign&, const BaseDesignIntf::ItemAlign&) +void AbstractLayout::slotOnChildItemAlignChanged(BaseDesignIntf* item, const ItemAlign&, const ItemAlign&) { item->setPossibleResizeDirectionFlags(ResizeBottom | ResizeRight); } diff --git a/limereport/items/lrabstractlayout.h b/limereport/items/lrabstractlayout.h index fcda489..84e8807 100644 --- a/limereport/items/lrabstractlayout.h +++ b/limereport/items/lrabstractlayout.h @@ -28,6 +28,7 @@ public: void setLayoutType(const LayoutType& layoutType); void addChild(BaseDesignIntf *item,bool updateSize=true); + void removeChild(BaseDesignIntf *item); void restoreChild(BaseDesignIntf *item); bool isEmpty() const; void paintChild(BaseDesignIntf* child, QPointF parentPos, QPainter* painter); @@ -52,6 +53,8 @@ protected: QVariant itemChange(GraphicsItemChange change, const QVariant &value); void updateItemSize(DataSourceManager* dataManager, RenderPass pass, int maxHeight); void rebuildChildrenIfNeeded(); + void connectToLayout(BaseDesignIntf* item); + void disconnectFromLayout(BaseDesignIntf* item); private: virtual void sortChildren() = 0; virtual void divideSpace() = 0; diff --git a/limereport/items/lrchartaxiseditor.cpp b/limereport/items/lrchartaxiseditor.cpp new file mode 100644 index 0000000..548a0f5 --- /dev/null +++ b/limereport/items/lrchartaxiseditor.cpp @@ -0,0 +1,142 @@ +#include "lrchartaxiseditor.h" + +#include "ui_lrchartaxiseditor.h" +#include "lraxisdata.h" + +#include "lrbasedesignintf.h" + +ChartAxisEditor::ChartAxisEditor(LimeReport::ChartItem *item, LimeReport::PageDesignIntf *page, bool isXAxis, QSettings *settings, QWidget *parent): + QWidget(parent), ui(new Ui::ChartAxisEditor), m_chartItem(item), m_page(page), + m_settings(settings), m_isXAxis(isXAxis) +{ + ui->setupUi(this); + readSetting(); + init(); +} + +ChartAxisEditor::~ChartAxisEditor() +{ +#if defined(Q_OS_WIN) || defined(Q_OS_MAC) + writeSetting(); +#endif + delete ui; +} + +QSettings* ChartAxisEditor::settings() +{ + if (m_settings){ + return m_settings; + } + m_settings = new QSettings("LimeReport",QCoreApplication::applicationName()); + return m_settings; +} + +void ChartAxisEditor::readSetting() +{ + if (settings() == 0) return; + + settings()->beginGroup("ChartAxisEditor"); + QVariant v = settings()->value("Geometry"); + if (v.isValid()) { + restoreGeometry(v.toByteArray()); + } + + settings()->endGroup(); +} + +void ChartAxisEditor::writeSetting() +{ + if (settings() == 0) { + return; + } + settings()->beginGroup("ChartAxisEditor"); + settings()->setValue("Geometry",saveGeometry()); + settings()->endGroup(); +} + +void ChartAxisEditor::init() +{ + ui->gbAxis->setTitle(m_isXAxis ? QObject::tr("X Axis") : QObject::tr("Y Axis")); + ui->direction_checkbox->setVisible(!m_isXAxis); + + LimeReport::AxisData *axisData = m_isXAxis ? m_chartItem->xAxisData() : m_chartItem->yAxisData(); + + ui->minimumSpinBox->setValue(axisData->manualMinimum()); + ui->maximumSpinBox->setValue(axisData->manualMaximum()); + ui->stepSpinBox->setValue(axisData->manualStep()); + + ui->minimumCheckBox->setChecked(axisData->isMinimumAutomatic()); + ui->maximumCheckBox->setChecked(axisData->isMaximumAutomatic()); + ui->stepCheckBox->setChecked(axisData->isStepAutomatic()); + + ui->direction_checkbox->setChecked(axisData->reverseDirection()); + + const bool isScaleCalcEnabled = axisData->calculateAxisScale(); + ui->enableScaleCalculation_checkbox->setChecked(isScaleCalcEnabled); + on_enableScaleCalculation_checkbox_stateChanged(isScaleCalcEnabled); +} + +void ChartAxisEditor::on_minimumCheckBox_stateChanged(int arg1) +{ + const bool isAutomatic = (bool)arg1; + ui->minimumSpinBox->setEnabled(!isAutomatic); +} + +void ChartAxisEditor::on_maximumCheckBox_stateChanged(int arg1) +{ + const bool isAutomatic = (bool)arg1; + ui->maximumSpinBox->setEnabled(!isAutomatic); +} + +void ChartAxisEditor::on_stepCheckBox_stateChanged(int arg1) +{ + const bool isAutomatic = (bool)arg1; + ui->stepSpinBox->setEnabled(!isAutomatic); +} + +void ChartAxisEditor::on_pushButtonOk_clicked() +{ + LimeReport::AxisData *axisData = m_isXAxis ? m_chartItem->xAxisData() : m_chartItem->yAxisData(); + if (!m_isXAxis) { + axisData->setReverseDirection(ui->direction_checkbox->isChecked()); + } + + axisData->setIsStepAutomatic(ui->stepCheckBox->isChecked()); + axisData->setManualStep(ui->stepSpinBox->value()); + axisData->setIsMinimumAutomatic(ui->minimumCheckBox->isChecked()); + axisData->setManualMinimum(ui->minimumSpinBox->value()); + axisData->setIsMaximumAutomatic(ui->maximumCheckBox->isChecked()); + axisData->setManualMaximum(ui->maximumSpinBox->value()); + + axisData->setCalculateAxisScale(ui->enableScaleCalculation_checkbox->isChecked()); + + if (m_chartItem->itemMode() == LimeReport::DesignMode) { + axisData->updateForDesignMode(); + } else { + axisData->update(); + } + m_chartItem->update(); + close(); +} + +void ChartAxisEditor::on_enableScaleCalculation_checkbox_stateChanged(int arg1) +{ + const bool isEnabled = (bool)arg1; + ui->minimumCheckBox->setEnabled(isEnabled); + ui->maximumCheckBox->setEnabled(isEnabled); + ui->stepCheckBox->setEnabled(isEnabled); + + ui->minimumSpinBox->setEnabled(!ui->minimumCheckBox->isChecked() && isEnabled); + ui->maximumSpinBox->setEnabled(!ui->maximumCheckBox->isChecked() && isEnabled); + ui->stepSpinBox->setEnabled(!ui->stepCheckBox->isChecked() && isEnabled); + + ui->minimumCheckBox->setEnabled(isEnabled); + ui->maximumCheckBox->setEnabled(isEnabled); + ui->stepCheckBox->setEnabled(isEnabled); +} + +void ChartAxisEditor::on_cancelButton_clicked() +{ + close(); +} + diff --git a/limereport/items/lrchartaxiseditor.h b/limereport/items/lrchartaxiseditor.h new file mode 100644 index 0000000..5eeb58b --- /dev/null +++ b/limereport/items/lrchartaxiseditor.h @@ -0,0 +1,41 @@ +#ifndef CHARTAXISEDITOR_H +#define CHARTAXISEDITOR_H + +#include +#include "lrchartitem.h" + +namespace Ui { +class ChartAxisEditor; +} + +class ChartAxisEditor : public QWidget +{ + Q_OBJECT + public: + ChartAxisEditor(LimeReport::ChartItem* item, LimeReport::PageDesignIntf* page, bool isXAxis, + QSettings* settings=0, QWidget *parent = 0); + ~ChartAxisEditor(); + + QSettings *settings(); +private slots: + void on_minimumCheckBox_stateChanged(int arg1); + void on_maximumCheckBox_stateChanged(int arg1); + void on_stepCheckBox_stateChanged(int arg1); + void on_pushButtonOk_clicked(); + void on_enableScaleCalculation_checkbox_stateChanged(int arg1); + + void on_cancelButton_clicked(); + +private: + void readSetting(); + void writeSetting(); + void init(); + + Ui::ChartAxisEditor *ui; + LimeReport::ChartItem* m_chartItem; + LimeReport::PageDesignIntf* m_page; + QSettings* m_settings; + bool m_isXAxis; +}; + +#endif // CHARTAXISEDITOR_H diff --git a/limereport/items/lrchartaxiseditor.ui b/limereport/items/lrchartaxiseditor.ui new file mode 100755 index 0000000..35dda3c --- /dev/null +++ b/limereport/items/lrchartaxiseditor.ui @@ -0,0 +1,212 @@ + + + ChartAxisEditor + + + + 0 + 0 + 380 + 268 + + + + Axis editor + + + + + + + 0 + 0 + + + + Axis + + + + + + true + + + Reverse direction + + + + + + + true + + + Enable scale calculation + + + + + + + QLayout::SetFixedSize + + + + + Step + + + + + + + Maximum + + + + + + + false + + + -99999999.000000000000000 + + + 99999999.000000000000000 + + + + + + + Minimum + + + + + + + Automatic + + + true + + + + + + + Automatic + + + true + + + + + + + Automatic + + + true + + + + + + + 0.000000000000000 + + + 9999999.990000000223517 + + + + + + + -9999999.000000000000000 + + + 99999999.000000000000000 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Cancel + + + + + + + Ok + + + + + + + + + + + + + slotAddSeries() + slotDeleteSeries() + + diff --git a/limereport/items/lrchartitem.cpp b/limereport/items/lrchartitem.cpp index 565b3cf..a438d5f 100644 --- a/limereport/items/lrchartitem.cpp +++ b/limereport/items/lrchartitem.cpp @@ -8,6 +8,7 @@ #include "lrpagedesignintf.h" #include "lrreportengine_p.h" #include "lrdatadesignintf.h" +#include "lrchartaxiseditor.h" #include "charts/lrpiechart.h" #include "charts/lrverticalbarchart.h" @@ -141,13 +142,18 @@ void SeriesItem::setPreferredType(const SeriesItemPreferredType& type) ChartItem::ChartItem(QObject *owner, QGraphicsItem *parent) : ItemDesignIntf(xmlTag, owner, parent), m_legendBorder(true), - m_legendAlign(LegendAlignCenter), m_titleAlign(TitleAlignCenter), + m_legendAlign(LegendAlignRightCenter), m_titleAlign(TitleAlignCenter), m_chartType(Pie), m_labelsField(""), m_isEmpty(true), m_showLegend(true), m_drawPoints(true), m_seriesLineWidth(4), - m_horizontalAxisOnTop(false), m_gridChartLines(AllLines) + m_horizontalAxisOnTop(false), m_gridChartLines(AllLines), + m_legendStyle(LegendPoints) { + m_xAxisData = new AxisData(AxisData::XAxis, this); + m_xAxisData->setReverseDirection(true); + m_yAxisData = new AxisData(AxisData::YAxis, this); m_labels<<"First"<<"Second"<<"Thrid"; m_chart = new PieChart(this); + m_chart->setTitleFont(font()); } ChartItem::~ChartItem() @@ -182,20 +188,36 @@ void ChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, painter->setRenderHint(QPainter::Antialiasing,true); painter->setRenderHint(QPainter::TextAntialiasing,true); qreal borderMargin = (rect().height()*0.01>10)?(10):(rect().height()*0.01); - qreal maxTitleHeight = rect().height()*0.2; + qreal maxTitleHeight = rect().height()*0.5; QFont tmpFont = painter->font(); - qreal titleOffset = !m_title.isEmpty()?(((painter->fontMetrics().height()+borderMargin*2)fontMetrics().height()+borderMargin*2): - (maxTitleHeight)):0; + qreal titleOffset = 0; + if (!m_title.isEmpty()) { + QFontMetrics fm(titleFont()); + const qreal titleHeight = fm.boundingRect(rect().toRect(), Qt::TextWordWrap,chartTitle()).height() + borderMargin * 2; + titleOffset = std::min(titleHeight, maxTitleHeight); + } - QRectF titleRect = QRectF(borderMargin,borderMargin,rect().width()-borderMargin*2,titleOffset); - QRectF legendRect = QRectF(0,0,0,0); - if (m_showLegend) + const QRectF titleRect = QRectF(borderMargin,borderMargin,rect().width()-borderMargin*2,titleOffset); + QRectF legendRect = QRectF(0, 0, 0, 0); + QRectF diagramRect = rect().adjusted(borderMargin, titleOffset + borderMargin, + -(borderMargin * 2), -borderMargin); + if (m_showLegend) { legendRect = m_chart->calcChartLegendRect(painter->font(), rect(), false, borderMargin, titleOffset); - QRectF diagramRect = rect().adjusted(borderMargin,titleOffset+borderMargin, - -(legendRect.width()+borderMargin*2),-borderMargin); + switch(legendAlign()) { + case LegendAlignRightTop: + case LegendAlignRightBottom: + case LegendAlignRightCenter: + diagramRect.adjust(0, 0, -legendRect.width(), 0); + break; + case LegendAlignBottomLeft: + case LegendAlignBottomCenter: + case LegendAlignBottomRight: + diagramRect.adjust(0, 0, 0, -(legendRect.height() + borderMargin * 2)); + break; + } + } paintChartTitle(painter, titleRect); if (m_showLegend) @@ -206,6 +228,47 @@ void ChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, ItemDesignIntf::paint(painter,option,widget); } +QObject *ChartItem::xAxisSettings() +{ + return m_xAxisData; +} + +void ChartItem::setYAxisSettings(QObject *axis) +{ + AxisData *data = dynamic_cast(axis); + if (data) { + m_yAxisData->copy(data); + } +} + +QObject *ChartItem::yAxisSettings() +{ + return m_yAxisData; +} + +void ChartItem::setXAxisSettings(QObject *axis) +{ + AxisData *data = static_cast(axis); + if (data) { + m_xAxisData->copy(data); + } +} + +AxisData *ChartItem::xAxisData() +{ + return m_xAxisData; +} + +AxisData *ChartItem::yAxisData() +{ + return m_yAxisData; +} + +void ChartItem::showAxisEditorDialog(bool isXAxis) +{ + showDialog(new ChartAxisEditor(this, page(), isXAxis, settings())); +} + BaseDesignIntf *ChartItem::createSameTypeItem(QObject *owner, QGraphicsItem *parent) { ChartItem* result = new ChartItem(owner,parent); @@ -271,10 +334,7 @@ void ChartItem::fillLabels(IDataSource *dataSource) QWidget *ChartItem::defaultEditor() { - QSettings* l_settings = (page()->settings() != 0) ? - page()->settings() : - (page()->reportEditor()!=0) ? page()->reportEditor()->settings() : 0; - QWidget* editor = new ChartItemEditor(this, page(), l_settings); + QWidget* editor = new ChartItemEditor(this, page(), settings()); editor->setAttribute(Qt::WA_DeleteOnClose); return editor; } @@ -284,6 +344,18 @@ bool ChartItem::isNeedUpdateSize(RenderPass pass) const return pass == FirstPass && m_isEmpty; } +QSettings *ChartItem::settings() +{ + PageDesignIntf *page = this->page(); + if (page->settings()) { + return page->settings(); + } + if (page->reportEditor()) { + return page->reportEditor()->settings(); + } + return 0; +} + bool ChartItem::showLegend() const { return m_showLegend; @@ -329,6 +401,7 @@ void ChartItem::setChartType(const ChartType &chartType) if (m_chartType != chartType){ ChartType oldValue = m_chartType; m_chartType = chartType; + QFont oldTitleFont = m_chart->titleFont(); delete m_chart; switch (m_chartType) { case Pie: @@ -347,6 +420,7 @@ void ChartItem::setChartType(const ChartType &chartType) m_chart = new GridLinesChart(this); break; } + m_chart->setTitleFont(oldTitleFont); notify("chartType",oldValue,m_chartType); update(); } @@ -365,13 +439,16 @@ void ChartItem::setDatasource(const QString &datasource) void ChartItem::paintChartTitle(QPainter *painter, QRectF titleRect) { painter->save(); - QFont tmpFont = painter->font(); - QFontMetrics fm(tmpFont); - while ((fm.height()>titleRect.height() || fm.boundingRect(m_title).width()>titleRect.width()) - && tmpFont.pixelSize()>1) { + QFont tmpFont = transformToSceneFont(titleFont()); + QRect titleBoundingRect = QFontMetrics(tmpFont).boundingRect(rect().toRect(), Qt::TextWordWrap, chartTitle()); + + while ((titleBoundingRect.height() > titleRect.height() || titleBoundingRect.width() > titleRect.width()) + && tmpFont.pixelSize() > 1) + { tmpFont.setPixelSize(tmpFont.pixelSize()-1); - fm = QFontMetrics(tmpFont); + titleBoundingRect = QFontMetrics(tmpFont).boundingRect(rect().toRect(), Qt::TextWordWrap, chartTitle()); } + painter->setFont(tmpFont); Qt::AlignmentFlag align = Qt::AlignCenter; switch (m_titleAlign) { @@ -385,7 +462,7 @@ void ChartItem::paintChartTitle(QPainter *painter, QRectF titleRect) align = Qt::AlignRight; break; } - painter->drawText(titleRect, align, m_title); + painter->drawText(titleRect, align | Qt::TextWordWrap, m_title); painter->restore(); } @@ -405,6 +482,22 @@ void ChartItem::setLegendAlign(const LegendAlign &legendAlign) } } +ChartItem::LegendStyle ChartItem::legendStyle() const +{ + return m_legendStyle; +} + +void ChartItem::setLegendStyle(const LegendStyle &legendStyle) +{ + if (m_legendStyle == legendStyle) { + return; + } + LegendStyle oldValue = m_legendStyle; + m_legendStyle = legendStyle; + notify("legendStyle", oldValue, m_legendStyle); + update(); +} + bool ChartItem::drawLegendBorder() const { return m_legendBorder; @@ -527,6 +620,33 @@ void ChartItem::setGridChartLines(GridChartLines flags) notify("gridChartLines",QVariant(oldValue),QVariant(flags)); } +void ChartItem::setCharItemFont(QFont value) +{ + if (font() == value) { + return; + } + QFont oldValue = font(); + setFont(value); + if (!isLoading()) update(); + notify("font",oldValue,value); +} + +QFont ChartItem::titleFont() const +{ + return m_chart->titleFont(); +} + +void ChartItem::setTitleFont(QFont value) +{ + if (m_chart->titleFont() == value){ + return; + } + QFont oldValue = value; + m_chart->setTitleFont(value); + if (!isLoading()) update(); + notify("titleFont", oldValue, value); +} + AbstractChart::AbstractChart(ChartItem *chartItem) :m_chartItem(chartItem) { @@ -535,54 +655,110 @@ AbstractChart::AbstractChart(ChartItem *chartItem) QRectF AbstractChart::calcChartLegendRect(const QFont &font, const QRectF &parentRect, bool takeAllRect, qreal borderMargin, qreal titleOffset) { - QSizeF legendSize = calcChartLegendSize(font); + const QSizeF legendSize = calcChartLegendSize(font, parentRect.width() * 0.9); qreal legendTopMargin = 0; qreal legendBottomMargin = 0; + qreal legendLeftMargin = 0; + bool isVertical = true; switch (m_chartItem->legendAlign()) { - case ChartItem::LegendAlignTop: - legendTopMargin = titleOffset+borderMargin; - legendBottomMargin = parentRect.height()-(legendSize.height()+titleOffset); + case ChartItem::LegendAlignRightTop: + legendTopMargin = titleOffset + borderMargin; + legendBottomMargin = parentRect.height() - (legendSize.height() + titleOffset); + isVertical = true; break; - case ChartItem::LegendAlignCenter: - legendTopMargin = titleOffset+(parentRect.height()-titleOffset-legendSize.height())/2; - legendBottomMargin = (parentRect.height()-titleOffset-legendSize.height())/2; + case ChartItem::LegendAlignRightCenter: + legendTopMargin = titleOffset + (parentRect.height() - titleOffset - legendSize.height()) / 2; + legendBottomMargin = (parentRect.height() - titleOffset - legendSize.height()) / 2; + isVertical = true; break; - case ChartItem::LegendAlignBottom: - legendTopMargin = parentRect.height()-(legendSize.height()+titleOffset); - legendBottomMargin = borderMargin; + case ChartItem::LegendAlignRightBottom: + legendTopMargin = parentRect.height() - (legendSize.height() + titleOffset); + legendBottomMargin = borderMargin; + isVertical = true; + break; + case ChartItem::LegendAlignBottomLeft: + legendLeftMargin = QFontMetrics(font).height() / 2; + isVertical = false; + break; + case ChartItem::LegendAlignBottomCenter: + legendLeftMargin = (parentRect.width() - legendSize.width()) / 2; + isVertical = false; + break; + case ChartItem::LegendAlignBottomRight: + legendLeftMargin = parentRect.width() - legendSize.width() - QFontMetrics(font).height() / 2; + isVertical = false; break; } - qreal rightOffset = !takeAllRect?((legendSize.width()>parentRect.width()/2-borderMargin)? - (parentRect.width()/2): - (parentRect.width()-legendSize.width())):0; + if (isVertical) { + qreal rightOffset = !takeAllRect ? ((legendSize.width() > parentRect.width() / 2 - borderMargin) ? + (parentRect.width() / 2) : + (parentRect.width() - legendSize.width())) : 0; + return parentRect.adjusted( + rightOffset, + (legendSize.height()>(parentRect.height()-titleOffset))?(titleOffset):(legendTopMargin), + -borderMargin, + (legendSize.height()>(parentRect.height()-titleOffset))?(0):(-legendBottomMargin) + ); + } else { + const qreal verticalOffset = borderMargin * 2; + return parentRect.adjusted( + legendLeftMargin, + (parentRect.height()) - (legendSize.height() + verticalOffset), + -(parentRect.width() - (legendSize.width() + legendLeftMargin)), + -verticalOffset + ); + } +} - QRectF legendRect = parentRect.adjusted( - rightOffset, - (legendSize.height()>(parentRect.height()-titleOffset))?(titleOffset):(legendTopMargin), - -borderMargin, - (legendSize.height()>(parentRect.height()-titleOffset))?(0):(-legendBottomMargin) - ); - return legendRect; +QFont AbstractChart::titleFont() +{ + return m_titleFont; +} + +void AbstractChart::setTitleFont(const QFont &value) +{ + m_titleFont = value; } void AbstractChart::prepareLegendToPaint(QRectF &legendRect, QPainter *painter) { QFont tmpFont = painter->font(); - QSizeF legendSize = calcChartLegendSize(tmpFont); - - if ((legendSize.height()>legendRect.height() || legendSize.width()>legendRect.width())){ - while ( (legendSize.height()>legendRect.height() || legendSize.width()>legendRect.width()) - && tmpFont.pixelSize()>1) + switch(m_chartItem->legendAlign()) { + case ChartItem::LegendAlignBottomLeft: + case ChartItem::LegendAlignBottomCenter: + case ChartItem::LegendAlignBottomRight: { + const qreal maxWidth = legendRect.width() * 0.95; + qreal legendWidth = std::accumulate(m_legendColumnWidths.cbegin(), m_legendColumnWidths.cend(), 0.0); + if (legendWidth < maxWidth) { + return; + } + while ( (legendWidth > maxWidth) && tmpFont.pixelSize() > 1) { + tmpFont.setPixelSize(tmpFont.pixelSize() - 1); + calcChartLegendSize(tmpFont, legendRect.width()); + legendWidth = std::accumulate(m_legendColumnWidths.cbegin(), m_legendColumnWidths.cend(), 0.0); + } + painter->setFont(tmpFont); + break; + } + case ChartItem::LegendAlignRightTop: + case ChartItem::LegendAlignRightCenter: + case ChartItem::LegendAlignRightBottom: + QSizeF legendSize = calcChartLegendSize(tmpFont, legendRect.width()); + if ((legendSize.height() <= legendRect.height() && legendSize.width() <= legendRect.width())) { + return; + } + while ((legendSize.height() > legendRect.height() || legendSize.width() > legendRect.width()) + && tmpFont.pixelSize() > 1) { - tmpFont.setPixelSize(tmpFont.pixelSize()-1); - painter->setFont(tmpFont); - legendSize = calcChartLegendSize(tmpFont); + tmpFont.setPixelSize(tmpFont.pixelSize() - 1); + legendSize = calcChartLegendSize(tmpFont, legendRect.width()); } painter->setFont(tmpFont); legendRect = calcChartLegendRect(tmpFont, legendRect, true, 0, 0); + break; } } @@ -602,56 +778,58 @@ AbstractSeriesChart::AbstractSeriesChart(ChartItem *chartItem) qreal AbstractSeriesChart::maxValue() { - return m_yAxisData.maxValue(); + return m_chartItem->yAxisData()->maxValue(); } qreal AbstractSeriesChart::minValue() { - return m_yAxisData.minValue(); + return m_chartItem->yAxisData()->minValue(); } -AxisData AbstractSeriesChart::yAxisData() +AxisData &AbstractSeriesChart::xAxisData() const { - return m_yAxisData; + return *m_chartItem->xAxisData(); } -AxisData AbstractSeriesChart::xAxisData() +AxisData &AbstractSeriesChart::yAxisData() const { - return m_xAxisData; + return *m_chartItem->yAxisData(); } void AbstractSeriesChart::updateMinAndMaxValues() { - qreal maxYValue = 0; - qreal minYValue = 0; - qreal maxXValue = 0; - qreal minXValue = 0; if (m_chartItem->itemMode() == DesignMode) { - maxYValue = 40; - maxXValue = 40; - } else { - for (SeriesItem* series : m_chartItem->series()){ - for (qreal value : series->data()->values()){ - minYValue = std::min(minYValue, value); - maxYValue = std::max(maxYValue, value); - } - if (series->data()->xAxisValues().isEmpty()) { - // Grid plot starts from 0 on x axis so x range must be decresed by 1 - const bool startingFromZero = m_chartItem->chartType() == ChartItem::GridLines; - const qreal valuesCount = this->valuesCount() - (startingFromZero ? 1 : 0); - minXValue = std::min(0.0, minXValue); - maxXValue = std::max(valuesCount, maxXValue); - } else { - for (qreal value : series->data()->xAxisValues()){ - minXValue = std::min(value, minXValue); - maxXValue = std::max(value, maxXValue); - } + m_chartItem->xAxisData()->updateForDesignMode(); + m_chartItem->yAxisData()->updateForDesignMode(); + return; + } + + qreal maxYValue = 0; + qreal minYValue = std::numeric_limits::max(); + qreal maxXValue = 0; + qreal minXValue = std::numeric_limits::max(); + + for (SeriesItem* series : m_chartItem->series()){ + for (qreal value : series->data()->values()){ + minYValue = std::min(minYValue, value); + maxYValue = std::max(maxYValue, value); + } + if (series->data()->xAxisValues().isEmpty()) { + // Grid plot starts from 0 on x axis so x range must be decresed by 1 + const bool startingFromZero = m_chartItem->chartType() == ChartItem::GridLines; + const qreal valuesCount = this->valuesCount() - (startingFromZero ? 1 : 0); + minXValue = std::min(0.0, minXValue); + maxXValue = std::max(valuesCount, maxXValue); + } else { + for (qreal value : series->data()->xAxisValues()){ + minXValue = std::min(value, minXValue); + maxXValue = std::max(value, maxXValue); } } } - m_yAxisData = AxisData(minYValue, maxYValue); - m_xAxisData = AxisData(minXValue, maxXValue); + m_chartItem->xAxisData()->update(minXValue, maxXValue); + m_chartItem->yAxisData()->update(minYValue, maxYValue); } qreal AbstractSeriesChart::hPadding(QRectF chartRect) @@ -676,28 +854,54 @@ int AbstractSeriesChart::seriesCount() return m_chartItem->series().count(); } -QSizeF AbstractSeriesChart::calcChartLegendSize(const QFont &font) +QSizeF AbstractSeriesChart::calcChartLegendSize(const QFont &font, const qreal maxWidth) { QFontMetrics fm(font); - qreal cw = 0; - qreal maxWidth = 0; - - if (!m_chartItem->series().isEmpty()){ - foreach(SeriesItem* series, m_chartItem->series()){ - cw += fm.height(); - if (maxWidthname()).width()) - maxWidth = fm.boundingRect(series->name()).width()+10; + switch(m_chartItem->legendAlign()) { + case ChartItem::LegendAlignBottomLeft: + case ChartItem::LegendAlignBottomCenter: + case ChartItem::LegendAlignBottomRight: { + const qreal seriesCount = m_chartItem->series().isEmpty() ? m_designLabels.size() : m_chartItem->series().size(); + const qreal indicatorWidth = fm.height() * 1.5; + m_legendColumnWidths.clear(); + while (!calculateLegendColumnWidths(indicatorWidth, maxWidth, fm)) { + // Nothing to do here } - } else { - foreach(QString label, m_designLabels){ - cw += fm.height(); - if (maxWidth maxWidth) { + legendSize.setWidth(maxWidth); + } + return legendSize; } - cw += fm.height(); - return QSizeF(maxWidth+fm.height()*2,cw); + default: { + qreal cw = 0; + qreal maxWidth = 0; + + if (m_chartItem->series().isEmpty()) { + foreach(QString label, m_designLabels){ + cw += fm.height(); + if (maxWidthseries()){ + cw += fm.height(); + if (maxWidthname()).width()) + maxWidth = fm.boundingRect(series->name()).width()+10; + } + } + cw += fm.height(); + return QSizeF(maxWidth+fm.height()*2,cw); + } + } + return QSizeF(); } bool AbstractSeriesChart::verticalLabels(QPainter* painter, QRectF labelsRect) @@ -829,7 +1033,7 @@ void AbstractSeriesChart::paintGrid(QPainter *painter, QRectF gridRect) painter->save(); const AxisData &yAxisData = this->yAxisData(); - const AxisData &xAxisData = this->xAxisData(); + AxisData &xAxisData = this->xAxisData(); painter->setRenderHint(QPainter::Antialiasing,false); @@ -874,20 +1078,19 @@ void AbstractSeriesChart::paintGrid(QPainter *painter, QRectF gridRect) if (m_chartItem->horizontalAxisOnTop()) { painter->drawLine(x, gridRect.top() - gridOffset.height(), x, (drawFullLine ? gridRect.bottom() : gridRect.top())); - painter->drawText(QRectF(x - painter->fontMetrics().width(text) / 2, + painter->drawText(QRectF(x - painter->fontMetrics().boundingRect(text).width() / 2, gridRect.top() - (fontHeight + gridOffset.height()), hStep, fontHeight), text); } else { painter->drawLine(x, gridRect.bottom() + gridOffset.height(), x, (drawFullLine ? gridRect.top() : gridRect.bottom())); - painter->drawText(QRectF(x - painter->fontMetrics().width(text) / 2, + painter->drawText(QRectF(x - painter->fontMetrics().boundingRect(text).width() / 2, gridRect.bottom() + halfFontHeight * 0 + gridOffset.height(), hStep, fontHeight), text); } } - painter->restore(); } @@ -973,7 +1176,12 @@ QString AbstractSeriesChart::axisLabel(int i, const AxisData &axisData) { const qreal min = axisData.rangeMin(); const qreal step = axisData.step(); - qreal value = min + i * step; + qreal value = 0; + if (axisData.type() == AxisData::YAxis && axisData.reverseDirection() && min >= 0) { + value = min + (axisData.segmentCount() - i) * step; + } else { + value = min + i * step; + } if (std::floor(step) == step) { return QString::number(value); } @@ -981,48 +1189,128 @@ QString AbstractSeriesChart::axisLabel(int i, const AxisData &axisData) return QString::number(round(value * 100.0) / 100.0); } +bool AbstractSeriesChart::calculateLegendColumnWidths(qreal indicatorWidth, qreal maxWidth, const QFontMetrics &fm) +{ + // This method is called in the loop, because to handle case when we get + // 3 small series names in first row and then in second row small name and long name. + // In this case we need to set maximum column count to 2 and iterate from the start to recalculate + // all the sizes + qreal currentRowWidth = 0; + int currentColumn = 0; + // During first iteration it is updated when moving to second row + // After first iteration some column width are already calculated and are set as max, + // because all rows need to have same column count (except last one) + int maxColumnCount = m_legendColumnWidths.size(); + if (m_chartItem->series().isEmpty()) { + for (int i=0 ; i < m_designLabels.size() ; ++i) { + const qreal itemWidth = (qreal)(fm.boundingRect(m_designLabels[i]).width()) + indicatorWidth; + if (!calculateLegendSingleColumnWidth(currentRowWidth, currentColumn, maxColumnCount, itemWidth, maxWidth)) { + return false; + } + } + } else { + for (int i = 0 ; i < m_chartItem->series().size() ; ++i) { + SeriesItem* series = m_chartItem->series().at(i); + const qreal itemWidth = (qreal)(fm.boundingRect(series->name()).width()) + indicatorWidth; + if (!calculateLegendSingleColumnWidth(currentRowWidth, currentColumn, maxColumnCount, itemWidth, maxWidth)) { + return false; + } + } + } + return true; +} + +bool AbstractSeriesChart::calculateLegendSingleColumnWidth(qreal ¤tRowWidth, int ¤tColumn, int &maxColumnCount, + const qreal itemWidth, const qreal maxRowWidth) +{ + const bool maxColumnCountDefined = maxColumnCount > 0; + // Check if there is enough space for current item in the row + const bool isEnoughSpaceInRowForItem = currentRowWidth + itemWidth > maxRowWidth; + // Check if it is last column already + const bool lastColumnReached = (maxColumnCountDefined && currentColumn >= maxColumnCount); + if (isEnoughSpaceInRowForItem || lastColumnReached) { + // Move to next row + currentColumn = 0; + // Set column count when moving to second row (next rows cannot have more columns) + if (!maxColumnCountDefined) { + maxColumnCount = currentColumn + 1; + } + currentRowWidth = itemWidth; + } else { + // Add next column in the row + currentRowWidth += itemWidth; + } + + // Add new column or update already existing column width + if (currentColumn >= m_legendColumnWidths.size()) { + // Append new column + m_legendColumnWidths.append(itemWidth); + } else if (m_legendColumnWidths.at(currentColumn) < itemWidth) { + // Update size if item in column is bigger than items in same column in previous rows + m_legendColumnWidths[currentColumn] = itemWidth; + // After any updating column size we must recheck if all columns fit in the max row width + qreal rowWidth = itemWidth; + for (int c = 1 ; c < m_legendColumnWidths.size() ; c++) { + rowWidth += m_legendColumnWidths.at(c); + // When column widths exceed max row width remove columns at the end + if (rowWidth > maxRowWidth) { + m_legendColumnWidths.remove(c, m_legendColumnWidths.size() - c); + break; + } + } + // Return back and re-iterate from start to make sure everything fits + return false; + } + ++currentColumn; + return true; +} + +QVector AbstractChart::legendColumnWidths() const +{ + return m_legendColumnWidths; +} + void AbstractBarChart::paintChartLegend(QPainter *painter, QRectF legendRect) { prepareLegendToPaint(legendRect, painter); - int indicatorSize = painter->fontMetrics().height()/2; painter->setPen(Qt::black); painter->setRenderHint(QPainter::Antialiasing,false); if (m_chartItem->drawLegendBorder()) painter->drawRect(legendRect); painter->setRenderHint(QPainter::Antialiasing,true); - QRectF indicatorsRect = legendRect.adjusted(painter->fontMetrics().height()/2,painter->fontMetrics().height()/2,0,0); + + const qreal halfFontSize = painter->fontMetrics().height() / 2; + int indicatorSize = halfFontSize; + const QRectF indicatorsRect = legendRect.adjusted(halfFontSize, halfFontSize, 0, 0); + + bool isHorizontal = false; + switch(m_chartItem->legendAlign()) { + case ChartItem::LegendAlignBottomLeft: + case ChartItem::LegendAlignBottomCenter: + case ChartItem::LegendAlignBottomRight: + isHorizontal = true; + break; + default: + isHorizontal = false; + break; + } if (!m_chartItem->series().isEmpty()){ - qreal cw = 0; - foreach(SeriesItem* series, m_chartItem->series()){ - QString label = series->name(); - painter->drawText(indicatorsRect.adjusted(indicatorSize+indicatorSize/2,cw,0,0),label); - painter->setBrush(series->color()); - painter->drawEllipse( - indicatorsRect.adjusted( - 0, - cw+indicatorSize/2, - -(indicatorsRect.width()-indicatorSize), - -(indicatorsRect.height()-(cw+indicatorSize+indicatorSize/2)) - ) - ); - cw += painter->fontMetrics().height(); + for (int i = 0 ; i < m_chartItem->series().size() ; ++i) { + SeriesItem* series = m_chartItem->series().at(i); + if (isHorizontal) { + drawHorizontalLegendItem(painter, i, series->name(), indicatorSize, indicatorsRect, series->color()); + } else { + drawVerticalLegendItem(painter, i, series->name(), indicatorSize, indicatorsRect, series->color()); + } } - } else if (m_chartItem->itemMode() == DesignMode){ - qreal cw = 0; - for (int i=0;idrawText(indicatorsRect.adjusted(indicatorSize+indicatorSize/2,cw,0,0),label); - painter->setBrush(color_map[i]); - painter->drawEllipse( - indicatorsRect.adjusted( - 0, - cw+indicatorSize/2, - -(indicatorsRect.width()-indicatorSize), - -(indicatorsRect.height()-(cw+indicatorSize+indicatorSize/2)) - ) - ); - cw += painter->fontMetrics().height(); + } else if (m_chartItem->itemMode() == DesignMode) { + for (int i = 0 ; i < m_designLabels.size() ; ++i){ + if (isHorizontal) { + drawHorizontalLegendItem(painter, i, m_designLabels.at(i), indicatorSize, indicatorsRect, color_map[i]); + } else { + drawVerticalLegendItem(painter, i, m_designLabels.at(i), indicatorSize, indicatorsRect, color_map[i]); + } } } @@ -1058,4 +1346,66 @@ QRectF AbstractBarChart::horizontalLabelsRect(QPainter *painter, QRectF labelsRe return labelsRect.adjusted(0, (labelsRect.height() - maxWidth), 0, 0); } +void AbstractBarChart::drawVerticalLegendItem(QPainter *painter, int i, const QString &text, int indicatorSize, + const QRectF &indicatorsRect, const QColor &indicatorColor) +{ + const qreal y = i * painter->fontMetrics().height(); + painter->drawText(indicatorsRect.adjusted(indicatorSize+indicatorSize * 1.5, y, 0, 0),text); + switch(m_chartItem->legendStyle()) { + case ChartItem::LegendPoints: { + painter->setBrush(indicatorColor); + painter->drawEllipse( + indicatorsRect.adjusted( + 0, + y+indicatorSize/2, + -(indicatorsRect.width()-indicatorSize), + -(indicatorsRect.height()-(y+indicatorSize+indicatorSize/2)) + ) + ); + break; + } + case ChartItem::LegendLines: { + const QPen tmpPen = painter->pen(); + QPen indicatorPen(indicatorColor); + indicatorPen.setWidth(4); + painter->setPen(indicatorPen); + const QPointF linePos = QPointF(indicatorsRect.left(), indicatorsRect.top() + y + painter->fontMetrics().height()/2); + painter->drawLine(linePos, linePos + QPointF(indicatorSize, 0)); + painter->setPen(tmpPen); + break; + } + } +} + +void AbstractBarChart::drawHorizontalLegendItem(QPainter *painter, int i, const QString &text, + int indicatorSize, const QRectF &indicatorsRect, const QColor &indicatorColor) +{ + const QVector &columnWidths = legendColumnWidths(); + if (columnWidths.isEmpty()) + return; + const int column = i % columnWidths.size(); + const int row = std::floor(i / columnWidths.size()); + const qreal halfTextSize = painter->fontMetrics().height() / 2; + + const qreal x = indicatorsRect.x() + std::accumulate(columnWidths.cbegin(), columnWidths.cbegin() + column, 0.0); + const qreal y = indicatorsRect.y() + (row + 1) * painter->fontMetrics().height(); + painter->drawText(QPointF(x + indicatorSize * 1.5, y), text); + switch(m_chartItem->legendStyle()) { + case ChartItem::LegendPoints: { + painter->setBrush(indicatorColor); + painter->drawEllipse(x, y - halfTextSize, indicatorSize, indicatorSize); + break; + } + case ChartItem::LegendLines: { + const QPen tmpPen = painter->pen(); + QPen indicatorPen(indicatorColor); + indicatorPen.setWidth(4); + painter->setPen(indicatorPen); + painter->drawLine(x, y - halfTextSize * 0.7, x + indicatorSize, y - halfTextSize * 0.7); + painter->setPen(tmpPen); + break; + } + } +} + } // namespace LimeReport diff --git a/limereport/items/lrchartitem.h b/limereport/items/lrchartitem.h index a2f40a8..8194f64 100644 --- a/limereport/items/lrchartitem.h +++ b/limereport/items/lrchartitem.h @@ -76,28 +76,36 @@ public: virtual ~AbstractChart(){} virtual void paintChart(QPainter *painter, QRectF rect) = 0; virtual void paintChartLegend(QPainter *painter, QRectF legendRect) =0; - virtual QSizeF calcChartLegendSize(const QFont &font) = 0; + virtual QSizeF calcChartLegendSize(const QFont &font, qreal maxWidth = 0) = 0; virtual QRectF calcChartLegendRect(const QFont& font, const QRectF& parentRect, bool takeAllRect, qreal borderMargin, qreal titleOffset); + + QFont titleFont(); + void setTitleFont(const QFont &value); protected: + QVector legendColumnWidths() const; virtual void prepareLegendToPaint(QRectF& legendRect, QPainter *painter); protected: + // Title font must be placed here instead of CharItem, becuase + // it would cause crash when creating CharItem object on embedded + QFont m_titleFont; ChartItem* m_chartItem; QList m_designLabels; + QVector m_legendColumnWidths; }; class AbstractSeriesChart: public AbstractChart{ public: AbstractSeriesChart(ChartItem* chartItem); protected: - AxisData yAxisData(); - AxisData xAxisData(); + AxisData &xAxisData() const; + AxisData &yAxisData() const; qreal maxValue(); qreal minValue(); void updateMinAndMaxValues(); int valuesCount(); int seriesCount(); bool verticalLabels(QPainter* painter, QRectF labelsRect); - QSizeF calcChartLegendSize(const QFont &font); + QSizeF calcChartLegendSize(const QFont &font, qreal maxWidth); qreal* designValues(){ return m_designValues;} virtual qreal hPadding(QRectF chartRect); virtual qreal vPadding(QRectF chartRect); @@ -114,7 +122,9 @@ protected: virtual QString axisLabel(int i, const AxisData &axisData); private: - AxisData m_yAxisData, m_xAxisData; + bool calculateLegendColumnWidths(qreal indicatorWidth, qreal maxWidth, const QFontMetrics &fm); + bool calculateLegendSingleColumnWidth(qreal ¤tRowWidth, int ¤tColumn, int &maxColumnCount, + const qreal itemWidth, const qreal maxRowWidth); qreal m_designValues [9]; }; @@ -125,20 +135,30 @@ public: protected: QRectF verticalLabelsRect(QPainter* painter, QRectF horizontalLabelsRect); virtual QRectF horizontalLabelsRect(QPainter* painter, QRectF horizontalLabelsRect); +private: + void drawVerticalLegendItem(QPainter *painter, int i, const QString &text, + int indicatorSize, const QRectF &indicatorsRect, const QColor &indicatorColor); + void drawHorizontalLegendItem(QPainter *painter, int i, const QString &text, + int indicatorSize, const QRectF &indicatorsRect, const QColor &indicatorColor); }; class ChartItem : public LimeReport::ItemDesignIntf { Q_OBJECT + Q_PROPERTY(QObject* xAxisSettings READ xAxisSettings WRITE setXAxisSettings) + Q_PROPERTY(QObject* yAxisSettings READ yAxisSettings WRITE setYAxisSettings) Q_PROPERTY(ACollectionProperty series READ fakeCollectionReader WRITE setSeries) Q_PROPERTY(QString datasource READ datasource WRITE setDatasource) Q_PROPERTY(QString chartTitle READ chartTitle WRITE setChartTitle) Q_PROPERTY(bool drawLegendBorder READ drawLegendBorder WRITE setDrawLegendBorder) Q_PROPERTY(LegendAlign legendAlign READ legendAlign WRITE setLegendAlign) + Q_PROPERTY(LegendStyle legendStyle READ legendStyle WRITE setLegendStyle) Q_PROPERTY(TitleAlign titleAlign READ titleAlign WRITE setTitleAlign) Q_PROPERTY(ChartType chartType READ chartType WRITE setChartType) Q_PROPERTY(QString labelsField READ labelsField WRITE setLabelsField) Q_PROPERTY(bool showLegend READ showLegend WRITE setShowLegend) + Q_PROPERTY(QFont titleFont READ titleFont WRITE setTitleFont) + Q_PROPERTY(QFont font READ font WRITE setCharItemFont) //linesChart Q_PROPERTY(bool drawPoints READ drawPoints WRITE setDrawPoints) @@ -152,7 +172,8 @@ class ChartItem : public LimeReport::ItemDesignIntf friend class AbstractChart; public: - enum LegendAlign{LegendAlignTop,LegendAlignCenter,LegendAlignBottom}; + enum LegendAlign{LegendAlignRightTop,LegendAlignRightCenter,LegendAlignRightBottom, + LegendAlignBottomLeft,LegendAlignBottomCenter,LegendAlignBottomRight}; enum LegendStyle{LegendPoints, LegendLines}; enum TitleAlign{TitleAlignLeft, TitleAlignCenter, TitleAlignRight}; enum ChartType{Pie, VerticalBar, HorizontalBar, Lines, GridLines}; @@ -164,11 +185,13 @@ public: }; #if QT_VERSION >= 0x050500 Q_ENUM(LegendAlign) + Q_ENUM(LegendStyle) Q_ENUM(TitleAlign) Q_ENUM(ChartType) Q_ENUM(LineType) #else Q_ENUMS(LegendAlign) + Q_ENUMS(LegendStyle) Q_ENUMS(TitleAlign) Q_ENUMS(ChartType) Q_ENUMS(LineType) @@ -179,6 +202,16 @@ public: ~ChartItem(); virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); + QObject* xAxisSettings(); + void setYAxisSettings(QObject *axis); + QObject* yAxisSettings(); + void setXAxisSettings(QObject *axis); + + AxisData *xAxisData(); + AxisData *yAxisData(); + + void showAxisEditorDialog(bool isXAxis); + QList &series(); void setSeries(const QList &series); bool isSeriesExists(const QString& name); @@ -195,6 +228,9 @@ public: LegendAlign legendAlign() const; void setLegendAlign(const LegendAlign &legendAlign); + LegendStyle legendStyle() const; + void setLegendStyle(const LegendStyle &legendStyle); + TitleAlign titleAlign() const; void setTitleAlign(const TitleAlign &titleAlign); @@ -226,6 +262,12 @@ public: GridChartLines gridChartLines() const; void setGridChartLines(GridChartLines flags); + QFont titleFont() const; + void setTitleFont(QFont value); + void setCharItemFont(QFont value); + + QSettings *settings(); + protected: void paintChartTitle(QPainter* painter, QRectF titleRect); virtual BaseDesignIntf* createSameTypeItem(QObject *owner, QGraphicsItem *parent); @@ -257,6 +299,8 @@ private: QString m_xAxisField; bool m_horizontalAxisOnTop; GridChartLines m_gridChartLines; + LegendStyle m_legendStyle; + AxisData *m_xAxisData, *m_yAxisData; }; } //namespace LimeReport #endif // LRCHARTITEM_H diff --git a/limereport/items/lrchartitemeditor.cpp b/limereport/items/lrchartitemeditor.cpp index c609c46..b2f35cb 100644 --- a/limereport/items/lrchartitemeditor.cpp +++ b/limereport/items/lrchartitemeditor.cpp @@ -295,4 +295,15 @@ void ChartItemEditor::on_xAxisFieldComboBox_currentTextChanged(const QString &ar { if (!m_initing) m_charItem->setXAxisField(arg1); -} \ No newline at end of file +} +void ChartItemEditor::on_tableWidget_itemChanged(QTableWidgetItem *item) +{ + if (ui->seriesNameLineEdit->hasFocus()) + return; + + const QString dataStr = item->data(Qt::DisplayRole).toString(); + if (dataStr == ui->seriesNameLineEdit->text()) + return; + + ui->seriesNameLineEdit->setText(dataStr); +} diff --git a/limereport/items/lrchartitemeditor.h b/limereport/items/lrchartitemeditor.h index 64e0549..7c72556 100644 --- a/limereport/items/lrchartitemeditor.h +++ b/limereport/items/lrchartitemeditor.h @@ -40,8 +40,8 @@ private slots: void on_labelsFieldComboBox_currentTextChanged(const QString &arg1); void slotChangeSeriesColor(); void on_seriesTypeComboBox_currentIndexChanged(const QString &arg1); - void on_xAxisFieldComboBox_currentTextChanged(const QString &arg1); + void on_tableWidget_itemChanged(QTableWidgetItem *item); private: void readSetting(); diff --git a/limereport/items/lrhorizontallayout.cpp b/limereport/items/lrhorizontallayout.cpp index 11a29d9..5326070 100644 --- a/limereport/items/lrhorizontallayout.cpp +++ b/limereport/items/lrhorizontallayout.cpp @@ -171,9 +171,14 @@ void HorizontalLayout::updateLayoutSize() void HorizontalLayout::relocateChildren() { int spaceBorder = (borderLines() != 0) ? borderLineSize() : 0; + QList newChildren; if (layoutsChildren().count() < childItems().size()-1){ + auto oldChildren = layoutsChildren(); layoutsChildren().clear(); foreach (BaseDesignIntf* item, childBaseItems()) { + if (!oldChildren.contains(item)) { + newChildren.append(item); + } layoutsChildren().append(item); } } @@ -188,6 +193,10 @@ void HorizontalLayout::relocateChildren() } } setIsRelocating(false); + + for (BaseDesignIntf* item : newChildren) { + connectToLayout(item); + } } void HorizontalLayout::divideSpace(){ diff --git a/limereport/items/lrimageitem.cpp b/limereport/items/lrimageitem.cpp index 02f7daa..0459b67 100644 --- a/limereport/items/lrimageitem.cpp +++ b/limereport/items/lrimageitem.cpp @@ -61,8 +61,13 @@ BaseDesignIntf *ImageItem::createSameTypeItem(QObject *owner, QGraphicsItem *par } void ImageItem::loadPictureFromVariant(QVariant& data){ + //TODO: Migrate to QMetaType if (data.isValid()){ - if (data.type()==QVariant::Image){ +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + if (data.typeId() == QMetaType::QImage){ +#else + if (data.type() == QVariant::Image){ +#endif m_picture = data.value(); } else { switch (m_format) { @@ -178,11 +183,22 @@ void ImageItem::updateItemSize(DataSourceManager* dataManager, RenderPass pass, m_resourcePath = expandDataFields(m_resourcePath, NoEscapeSymbols, dataManager); m_picture = QImage(m_resourcePath); } else if (!m_variable.isEmpty()){ + //TODO: Migrate to QMetaType QVariant data = dataManager->variable(m_variable); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + if (data.typeId() == QMetaType::QString){ +#else if (data.type() == QVariant::String){ +#endif m_picture = QImage(data.toString()); - } else if (data.type() == QVariant::Image){ - loadPictureFromVariant(data); + } else { +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + if (data.typeId() == QMetaType::QImage){ +#else + if (data.type() == QVariant::Image){ +#endif + loadPictureFromVariant(data); + } } } } diff --git a/limereport/items/lrsvgitem.cpp b/limereport/items/lrsvgitem.cpp index fe3c1a1..9bf1ea6 100644 --- a/limereport/items/lrsvgitem.cpp +++ b/limereport/items/lrsvgitem.cpp @@ -107,11 +107,22 @@ void SVGItem::updateItemSize(DataSourceManager *dataManager, RenderPass pass, in m_resourcePath = expandDataFields(m_resourcePath, NoEscapeSymbols, dataManager); m_image = imageFromResource(m_resourcePath); } else if (!m_variable.isEmpty()){ + //TODO: Migrate to QMetaType QVariant data = dataManager->variable(m_variable); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + if (data.typeId() == QMetaType::QString){ +#else if (data.type() == QVariant::String){ +#endif m_image = imageFromResource(data.toString()); - } else if (data.type() == QVariant::ByteArray) { - m_image = data.value() ; + } else { +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + if (data.typeId() == QMetaType::QByteArray) { +#else + if (data.type() == QVariant::ByteArray) { +#endif + m_image = data.value() ; + } } } } diff --git a/limereport/items/lrtextitem.cpp b/limereport/items/lrtextitem.cpp index 086adca..fb14eb6 100644 --- a/limereport/items/lrtextitem.cpp +++ b/limereport/items/lrtextitem.cpp @@ -276,10 +276,6 @@ void TextItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* style, Q BaseDesignIntf::paint(painter, style, widget); } -QString TextItem::content() const{ - return m_strText; -} - void TextItem::Init() { m_autoWidth = NoneAutoWidth; @@ -299,14 +295,8 @@ void TextItem::setContent(const QString &value) { if (m_strText.compare(value)!=0){ QString oldValue = m_strText; - if (m_trimValue) - m_strText=value.trimmed(); - else - m_strText=value; -// if (itemMode() == DesignMode && (autoHeight())){ -// initTextSizes(); -// } + m_strText = value; if (!isLoading()){ if (autoHeight() || autoWidth() || hasFollower()) @@ -317,6 +307,10 @@ void TextItem::setContent(const QString &value) } } +QString TextItem::content() const{ + return m_strText; +} + void TextItem::updateItemSize(DataSourceManager* dataManager, RenderPass pass, int maxHeight) { @@ -493,29 +487,43 @@ QString TextItem::formatFieldValue() } } +#if QT_VERSION < QT_VERSION_CHECK(6,0,0) switch (value.type()) { - case QVariant::Date: - case QVariant::DateTime: - return formatDateTime(value.toDateTime()); - case QVariant::Double: - return formatNumber(value.toDouble()); - default: - return value.toString(); + case QVariant::Date: + case QVariant::DateTime: + return formatDateTime(value.toDateTime()); + case QVariant::Double: + return formatNumber(value.toDouble()); + default: + return value.toString(); } +#else + switch (value.typeId()) { + case QMetaType::QDate: + case QMetaType::QDateTime: + return formatDateTime(value.toDateTime()); + case QMetaType::Double: + return formatNumber(value.toDouble()); + default: + return value.toString(); + } +#endif + } TextItem::TextPtr TextItem::textDocument() const { TextPtr text(new QTextDocument); + QString content = m_trimValue ? m_strText.trimmed() : m_strText; if (allowHTML()) if (isReplaceCarriageReturns()){ - text->setHtml(replaceReturns(m_strText)); + text->setHtml(replaceReturns(content)); } else { - text->setHtml(m_strText); + text->setHtml(content); } else - text->setPlainText(m_strText); + text->setPlainText(content); QTextOption to; to.setAlignment(m_alignment); @@ -785,6 +793,7 @@ void TextItem::setTrimValue(bool value) { bool oldValue = m_trimValue; m_trimValue = value; + update(); notify("trimValue",oldValue,value); } @@ -827,7 +836,7 @@ void TextItem::expandContent(DataSourceManager* dataManager, RenderPass pass) #if (QT_VERSION < QT_VERSION_CHECK(5, 15, 1)) QRegExp rx(QString(Const::NAMED_VARIABLE_RX).arg(variableName)); #else - QRegularExpression rx(QString(Const::NAMED_VARIABLE_RX).arg(variableName)); + QRegularExpression rx = getNamedVariableRegEx(variableName); #endif if (context.contains(rx) && pass == FirstPass){ backupContent(); diff --git a/limereport/items/lrverticallayout.cpp b/limereport/items/lrverticallayout.cpp index 1b1971e..f4a6325 100644 --- a/limereport/items/lrverticallayout.cpp +++ b/limereport/items/lrverticallayout.cpp @@ -57,9 +57,14 @@ void VerticalLayout::updateLayoutSize() void VerticalLayout::relocateChildren() { int spaceBorder = (borderLines() != 0) ? borderLineSize() : 0; + QList newChildren; if (layoutsChildren().count() < childItems().size() - 1){ + auto oldChildren = layoutsChildren(); layoutsChildren().clear(); foreach (BaseDesignIntf* item, childBaseItems()) { + if (!oldChildren.contains(item)) { + newChildren.append(item); + } layoutsChildren().append(item); } } @@ -74,6 +79,10 @@ void VerticalLayout::relocateChildren() } } setIsRelocating(false); + + for (BaseDesignIntf* item : newChildren) { + connectToLayout(item); + } } bool VerticalLayout::canBeSplitted(int height) const diff --git a/limereport/limereport.pri b/limereport/limereport.pri index 4a7c156..960699b 100644 --- a/limereport/limereport.pri +++ b/limereport/limereport.pri @@ -55,6 +55,7 @@ SOURCES += \ $$REPORT_PATH/items/lrabstractlayout.cpp \ $$REPORT_PATH/items/lrchartitem.cpp \ $$REPORT_PATH/items/lrchartitemeditor.cpp \ + $$REPORT_PATH/items/lrchartaxiseditor.cpp \ $$REPORT_PATH/items/charts/lrhorizontalbarchart.cpp \ $$REPORT_PATH/items/charts/lrlineschart.cpp \ $$REPORT_PATH/items/charts/lrgridlineschart.cpp \ @@ -148,6 +149,7 @@ HEADERS += \ $$REPORT_PATH/items/lrabstractlayout.h \ $$REPORT_PATH/items/lrchartitem.h \ $$REPORT_PATH/items/lrchartitemeditor.h \ + $$REPORT_PATH/items/lrchartaxiseditor.h \ $$REPORT_PATH/items/charts/lrhorizontalbarchart.h \ $$REPORT_PATH/items/charts/lrlineschart.h \ $$REPORT_PATH/items/charts/lrgridlineschart.h \ @@ -219,6 +221,7 @@ FORMS += \ $$REPORT_PATH/lraboutdialog.ui \ $$REPORT_PATH/lrsettingdialog.ui \ $$REPORT_PATH/items/lrchartitemeditor.ui \ + $$REPORT_PATH/items/lrchartaxiseditor.ui \ $$REPORT_PATH/items/lrimageitemeditor.ui \ $$REPORT_PATH/scripteditor/lrscripteditor.ui diff --git a/limereport/lraxisdata.cpp b/limereport/lraxisdata.cpp index fbe7f2a..692003c 100644 --- a/limereport/lraxisdata.cpp +++ b/limereport/lraxisdata.cpp @@ -1,21 +1,84 @@ #include "lraxisdata.h" -namespace LimeReport { -AxisData::AxisData() - : m_rangeMin(0), m_rangeMax(0), - m_minValue(0), m_maxValue(0), m_step(0), - m_delta(0), m_segmentCount(4) -{ +#include +#include +namespace LimeReport { +AxisData::AxisData(AxisType type, QObject *parent) + : QObject(parent), m_rangeMin(0), m_rangeMax(0), + m_minValue(0), m_maxValue(0), m_step(0), + m_delta(0), m_segmentCount(4), m_calculateAxisScale(false), + m_reverseDirection(false), m_manualMaximum(0), + m_manualMinimum(0), m_manualStep(0), m_isMaximumAutomatic(true), + m_isMinimumAutomatic(true), m_isStepAutomatic(true), + m_type(type) +{ } -AxisData::AxisData(qreal minValue, qreal maxValue) - : AxisData() +QString AxisData::toString() const +{ + // Just for debug purposes + QString str; + QTextStream stream(&str); + stream << "{ " + << "min: " << m_minValue << ", max: " << m_maxValue << ", step: " << m_step + << ", range min: " << m_rangeMin << ", range max: " << m_rangeMax << ", segments: " << m_segmentCount + << ", reverseDiection: " << m_reverseDirection << ", calculateAxisScale: " << m_calculateAxisScale + << ", manualMaxEnabled: " << !m_isMaximumAutomatic << ", manualMinEnabled: " << !m_isMinimumAutomatic + << ", manualStepEnabled: " << !m_isStepAutomatic << ", manualMax: " << m_manualMaximum + << ", manualMin: " << m_manualMinimum << ", manualStep: " << m_manualStep + << " }"; + return str; +} + +void AxisData::copy(AxisData *other) +{ + m_calculateAxisScale = other->calculateAxisScale(); + m_reverseDirection = other->reverseDirection(); + m_manualMaximum = other->manualMaximum(); + m_manualMinimum = other->manualMinimum(); + m_manualStep = other->manualStep(); + m_isMaximumAutomatic = other->isMaximumAutomatic(); + m_isMinimumAutomatic = other->isMinimumAutomatic(); + m_isStepAutomatic = other->isStepAutomatic(); +} + +void AxisData::update() +{ + if (m_calculateAxisScale) { + calculateRoundedAxisScale(); + } else { + calculateSimpleAxisScale(); + } + m_delta = m_step * m_segmentCount; + + // Update manual values if they are automatic + if (m_isStepAutomatic) { + m_manualStep = m_step; + } + if (m_isMinimumAutomatic) { + m_manualMinimum = m_rangeMin; + } + if (m_isMaximumAutomatic) { + m_manualMaximum = m_rangeMax; + } +} + +void AxisData::update(qreal minValue, qreal maxValue) { m_minValue = minValue; m_maxValue = maxValue; - calculateValuesAboveMax(minValue, maxValue, 4); - m_delta = m_step * m_segmentCount; + update(); +} + +void AxisData::updateForDesignMode() +{ + m_minValue = 0; + m_maxValue = 40; + const bool tmp = m_calculateAxisScale; + m_calculateAxisScale = false; + update(); + m_calculateAxisScale = tmp; } int AxisData::segmentCount() const @@ -23,6 +86,11 @@ int AxisData::segmentCount() const return m_segmentCount; } +bool AxisData::calculateAxisScale() const +{ + return m_calculateAxisScale; +} + qreal AxisData::rangeMin() const { return m_rangeMin; @@ -53,16 +121,229 @@ qreal AxisData::delta() const return m_delta; } -void AxisData::calculateValuesAboveMax(qreal minValue, qreal maxValue, int segments) +void AxisData::calculateRoundedAxisScale() { - const int delta = maxValue - minValue; + const int maximumSegmentCount = 10; + + bool calculateStep = isStepAutomatic(); + const bool calculateMinimum = isMinimumAutomatic(); + const bool calculateMaximum = isMaximumAutomatic(); + + qreal temporaryMin = 0; + qreal temporaryMax = 0; + if (calculateMinimum) { + temporaryMin = qMin(0.0, minValue()); + } else { + temporaryMin = qMin(manualMinimum(), minValue()); + } + if (calculateMaximum) { + temporaryMax = maxValue(); + } else { + temporaryMax = qMax(manualMaximum(), maxValue()); + } + m_step = calculateStep ? 0 : manualStep(); + + if (temporaryMax == temporaryMin) { + if (temporaryMax == 0) { + temporaryMax = 1; + } else { + temporaryMax *= 2; + } + } + + const qreal minAndMaxSpacingOffset = 0.95; + + qreal stepMagnitude = 0.0; + qreal normalizedStep = 0.0; + bool isStepNormalized = false; + bool isLoopFinished = false; + + // Calculate until segment count is below maximum + while( !isLoopFinished ) { + if (calculateStep) { + if(isStepNormalized) { + if( normalizedStep == 1.0 ) { + normalizedStep = 2.0; + } else if( normalizedStep == 2.0 ) { + normalizedStep = 5.0; + } else { + normalizedStep = 1.0; + stepMagnitude *= 10; + } + } else { + const double startingStep = (temporaryMax - temporaryMin) / maximumSegmentCount; + const int exponent = static_cast< int >( floor( log10( startingStep ) ) ); + stepMagnitude = pow(10.0, static_cast(exponent)); + normalizedStep = startingStep / stepMagnitude; + if( normalizedStep <= 1.0 ) { + normalizedStep = 1.0; + } else if( normalizedStep <= 2.0 ) { + normalizedStep = 2.0; + } else if( normalizedStep <= 5.0 ) { + normalizedStep = 5.0; + } else { + normalizedStep = 1.0; + stepMagnitude *= 10; + } + isStepNormalized = true; + } + m_step = normalizedStep * stepMagnitude; + } + + qreal currentAxisMinimum = temporaryMin; + qreal currentAxisMaximum = temporaryMax; + + if (calculateMinimum) { + currentAxisMinimum = calculateNewMinimum(currentAxisMinimum, m_step); + const qreal currentDelta = currentAxisMaximum - currentAxisMinimum; + const qreal actualDelta = currentAxisMaximum - minValue(); + if ((currentAxisMinimum != 0.0) && ((actualDelta / currentDelta) > minAndMaxSpacingOffset)) { + currentAxisMinimum -= m_step; + } + } + + if (calculateMaximum) { + currentAxisMaximum = calculateNewMaximum(currentAxisMaximum, m_step); + const qreal currentDelta = currentAxisMaximum - currentAxisMinimum; + const qreal actualDelta = maxValue() - currentAxisMinimum; + if ((currentAxisMaximum != 0.0) && ((actualDelta / currentDelta) > minAndMaxSpacingOffset)) { + currentAxisMaximum += m_step; + } + } + + m_segmentCount = static_cast(round((currentAxisMaximum - currentAxisMinimum) / m_step)); + m_rangeMin = currentAxisMinimum; + m_rangeMax = currentAxisMaximum; + // Check also if step is correctly calucalted. It is possible for float steps that + // there might be a difference. Recalculate the step in that case. + const qreal tmpStep = (m_rangeMax - m_rangeMin) / m_segmentCount; + isLoopFinished = m_segmentCount <= maximumSegmentCount && qFuzzyCompare(tmpStep, m_step); + if (!isLoopFinished) { + // Configured step may be invalid, calculating it automatically + calculateStep = true; + } + } +} + +void AxisData::calculateSimpleAxisScale() +{ + qreal min = 0; + if (m_minValue < 0) { + min = minValue(); + } + m_segmentCount = 4; + const int delta = maxValue() - min; int max = delta; - while (max % segments != 0){ + while (max % m_segmentCount != 0){ max++; } - m_rangeMax = max; - m_step = max / segments; - m_rangeMin = minValue; - m_segmentCount = segments; + m_rangeMax = minValue() + max; + m_step = max / m_segmentCount; + m_rangeMin = minValue(); } + +double AxisData::calculateNewMinimum(qreal min, qreal step) const +{ + if (step <= 0.0) + return min; + + double ret = floor(min / step) * step; + if (ret > min && !qFuzzyCompare(ret, min)) { + ret -= step; + } + return ret; +} + +double AxisData::calculateNewMaximum(qreal max, qreal step) const +{ + if (step <= 0.0) + return max; + + double ret = floor(max / step) * step; + if (ret < max && !qFuzzyCompare(ret, max)) { + ret += step; + } + return ret; +} + +void AxisData::setCalculateAxisScale(bool newCalculateAxisScale) +{ + m_calculateAxisScale = newCalculateAxisScale; +} + +bool AxisData::reverseDirection() const +{ + return m_reverseDirection; +} + +void AxisData::setReverseDirection(bool reverseDirection) +{ + m_reverseDirection = reverseDirection; +} + +qreal AxisData::manualMaximum() const +{ + return m_manualMaximum; +} + +void AxisData::setManualMaximum(qreal newManualMaximum) +{ + m_manualMaximum = newManualMaximum; +} + +qreal AxisData::manualMinimum() const +{ + return m_manualMinimum; +} + +void AxisData::setManualMinimum(qreal newManualMinimum) +{ + m_manualMinimum = newManualMinimum; +} + +qreal AxisData::manualStep() const +{ + return m_manualStep; +} + +void AxisData::setManualStep(qreal newManualStep) +{ + m_manualStep = newManualStep; +} + +bool AxisData::isMaximumAutomatic() const +{ + return m_isMaximumAutomatic; +} + +void AxisData::setIsMaximumAutomatic(bool newIsMaximumAutomatic) +{ + m_isMaximumAutomatic = newIsMaximumAutomatic; +} + +bool AxisData::isMinimumAutomatic() const +{ + return m_isMinimumAutomatic; +} + +void AxisData::setIsMinimumAutomatic(bool newIsMinimumAutomatic) +{ + m_isMinimumAutomatic = newIsMinimumAutomatic; +} + +bool AxisData::isStepAutomatic() const +{ + return m_isStepAutomatic; +} + +void AxisData::setIsStepAutomatic(bool newIsStepAutomatic) +{ + m_isStepAutomatic = newIsStepAutomatic; +} + +AxisData::AxisType AxisData::type() const +{ + return m_type; +} + } diff --git a/limereport/lraxisdata.h b/limereport/lraxisdata.h index 820eeb1..d7342a4 100644 --- a/limereport/lraxisdata.h +++ b/limereport/lraxisdata.h @@ -1,14 +1,33 @@ #ifndef AXISDATA_H #define AXISDATA_H -#include +#include namespace LimeReport { -class AxisData +class AxisData : public QObject { + Q_OBJECT + Q_PROPERTY(bool reverseDirection READ reverseDirection WRITE setReverseDirection) + Q_PROPERTY(bool calculateAxisScale READ calculateAxisScale WRITE setCalculateAxisScale) + Q_PROPERTY(bool isStepAutomatic READ isStepAutomatic WRITE setIsStepAutomatic) + Q_PROPERTY(bool isMinimumAutomatic READ isMinimumAutomatic WRITE setIsMinimumAutomatic) + Q_PROPERTY(bool isMaximumAutomatic READ isMaximumAutomatic WRITE setIsMaximumAutomatic) + Q_PROPERTY(qreal manualStep READ manualStep WRITE setManualStep) + Q_PROPERTY(qreal manualMinimum READ manualMinimum WRITE setManualMinimum) + Q_PROPERTY(qreal manualMaximum READ manualMaximum WRITE setManualMaximum) public: - AxisData(); - AxisData(qreal minValue, qreal maxValue); + enum AxisType { + YAxis = 0, + XAxis = 1 + }; + + AxisData(AxisType type, QObject *parent = nullptr); + + QString toString() const; + void copy(AxisData *other); + void update(); + void update(qreal minValue, qreal maxValue); + void updateForDesignMode(); int segmentCount() const; @@ -21,8 +40,36 @@ public: qreal delta() const; + bool reverseDirection() const; + void setReverseDirection(bool newReverseDirection); + bool calculateAxisScale() const; + void setCalculateAxisScale(bool newCalculateAxisScale); + + qreal manualMaximum() const; + void setManualMaximum(qreal newManualMaximum); + + qreal manualMinimum() const; + void setManualMinimum(qreal newManualMinimum); + + qreal manualStep() const; + void setManualStep(qreal newManualStep); + + bool isMaximumAutomatic() const; + void setIsMaximumAutomatic(bool newIsMaximumAutomatic); + + bool isMinimumAutomatic() const; + void setIsMinimumAutomatic(bool newIsMinimumAutomatic); + + bool isStepAutomatic() const; + void setIsStepAutomatic(bool newIsStepAutomatic); + + AxisType type() const; + private: - void calculateValuesAboveMax(qreal minValue, qreal maxValue, int segments); + void calculateRoundedAxisScale(); + void calculateSimpleAxisScale(); + qreal calculateNewMinimum(qreal min, qreal step) const; + qreal calculateNewMaximum(qreal max, qreal step) const; qreal m_rangeMin; qreal m_rangeMax; @@ -31,6 +78,15 @@ private: qreal m_step; qreal m_delta; int m_segmentCount; + bool m_calculateAxisScale; + bool m_reverseDirection; + qreal m_manualMaximum; + qreal m_manualMinimum; + qreal m_manualStep; + bool m_isMaximumAutomatic; + bool m_isMinimumAutomatic; + bool m_isStepAutomatic; + const AxisType m_type; }; }; diff --git a/limereport/lrbanddesignintf.h b/limereport/lrbanddesignintf.h index 71d02e1..8960eeb 100644 --- a/limereport/lrbanddesignintf.h +++ b/limereport/lrbanddesignintf.h @@ -261,7 +261,6 @@ public: void setAlternateBackgroundColor(const QColor &alternateBackgroundColor); bool useAlternateBackgroundColor() const; void setUseAlternateBackgroundColor(bool useAlternateBackgroundColor); - void replaceGroupsFunction(BandDesignIntf *band); qreal bottomSpace() const; void setBackgroundModeProperty(BGMode value); void setBackgroundOpacity(int value); diff --git a/limereport/lrbasedesignintf.cpp b/limereport/lrbasedesignintf.cpp index 8d35fab..bc1328a 100644 --- a/limereport/lrbasedesignintf.cpp +++ b/limereport/lrbasedesignintf.cpp @@ -1290,32 +1290,41 @@ void BaseDesignIntf::setItemPos(const QPointF &newPos) } -QWidget* findRootWidget(QWidget* widget){ +QWidget* BaseDesignIntf::findRootWidget(QWidget* widget) +{ while (widget->parentWidget()) { widget = widget->parentWidget(); } return widget; } -void BaseDesignIntf::showEditorDialog(){ - QWidget *editor = defaultEditor(); - if (editor) { - editor->setStyleSheet(findRootWidget(scene()->views().at(0))->styleSheet()); - QDialog* dialog = new QDialog(QApplication::activeWindow()); - dialog->setAttribute(Qt::WA_DeleteOnClose); -#ifdef Q_OS_MAC - dialog->setWindowModality(Qt::WindowModal); -#else - dialog->setWindowModality(Qt::ApplicationModal); -#endif - dialog->setLayout(new QVBoxLayout()); - dialog->resize(editor->size()); - dialog->layout()->setContentsMargins(2,2,2,2); - dialog->layout()->addWidget(editor); - connect(editor,SIGNAL(destroyed()),dialog,SLOT(close())); - dialog->setWindowTitle(editor->windowTitle()); - dialog->exec(); +void BaseDesignIntf::showDialog(QWidget *widget) +{ + if (!widget) { + return; } + widget->setStyleSheet(findRootWidget(scene()->views().at(0))->styleSheet()); + QDialog *dialog = new QDialog(QApplication::activeWindow()); + widget->setParent(dialog); + widget->setAttribute(Qt::WA_DeleteOnClose); +#ifdef Q_OS_MAC + dialog->setWindowModality(Qt::WindowModal); +#else + dialog->setWindowModality(Qt::ApplicationModal); +#endif + dialog->setLayout(new QVBoxLayout()); + dialog->resize(widget->size()); + dialog->layout()->setContentsMargins(2,2,2,2); + dialog->layout()->addWidget(widget); + connect(widget,SIGNAL(destroyed()),dialog,SLOT(close())); + dialog->setWindowTitle(widget->windowTitle()); + dialog->exec(); + dialog->deleteLater(); +} + +void BaseDesignIntf::showEditorDialog() +{ + showDialog(defaultEditor()); } void BaseDesignIntf::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) @@ -1340,18 +1349,27 @@ void BaseDesignIntf::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) QAction* lockGeometryAction = menu.addAction(tr("Lock item geometry")); lockGeometryAction->setCheckable(true); - lockGeometryAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_L)); + lockGeometryAction->setChecked(isGeometryLocked()); menu.addSeparator(); QAction* copyAction = menu.addAction(QIcon(":/report/images/copy"), tr("Copy")); - copyAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_C)); - QAction* cutAction = menu.addAction(QIcon(":/report/images/cut"), tr("Cut")); - cutAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_X)); + QAction* cutAction = menu.addAction(QIcon(":/report/images/cut"), tr("Cut")); QAction* pasteAction = menu.addAction(QIcon(":/report/images/paste"), tr("Paste")); - pasteAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_V)); pasteAction->setEnabled(false); +#if QT_VERSION >=QT_VERSION_CHECK(5,0,0) + lockGeometryAction->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_L)); + copyAction->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_C)); + cutAction->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_X)); + pasteAction->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_V)); +#else + lockGeometryAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_L)); + copyAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_C)); + cutAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_X)); + pasteAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_V)); +#endif + QClipboard *clipboard = QApplication::clipboard(); ItemsReaderIntf::Ptr reader = StringXMLreader::create(clipboard->text()); if (reader->first() && reader->itemType() == "Object"){ diff --git a/limereport/lrbasedesignintf.h b/limereport/lrbasedesignintf.h index 6a2b3ea..c311f16 100644 --- a/limereport/lrbasedesignintf.h +++ b/limereport/lrbasedesignintf.h @@ -397,6 +397,9 @@ protected: qreal calcAbsolutePosY(qreal currentOffset, BaseDesignIntf* item); qreal calcAbsolutePosX(qreal currentOffset, BaseDesignIntf* item); + QWidget* findRootWidget(QWidget* widget); + void showDialog(QWidget *widget); + private: int resizeDirectionFlags(QPointF position); void moveSelectedItems(QPointF delta); @@ -480,7 +483,7 @@ signals: void propertyChanged(const QString& propertName, const QVariant& oldValue,const QVariant& newValue); void propertyObjectNameChanged(const QString& oldValue, const QString& newValue); void propertyesChanged(QVector propertyNames); - void itemAlignChanged(BaseDesignIntf* item, const BaseDesignIntf::ItemAlign& oldValue, const BaseDesignIntf::ItemAlign& newValue); + void itemAlignChanged(BaseDesignIntf* item, const ItemAlign& oldValue, const ItemAlign& newValue); void itemVisibleHasChanged(BaseDesignIntf* item); void beforeRender(); void afterData(); diff --git a/limereport/lrdatadesignintf.cpp b/limereport/lrdatadesignintf.cpp index f970c86..0315c27 100644 --- a/limereport/lrdatadesignintf.cpp +++ b/limereport/lrdatadesignintf.cpp @@ -85,7 +85,12 @@ bool QueryHolder::runQuery(IDataSource::DatasourceMode mode) query.exec(); QSqlQueryModel *model = new QSqlQueryModel; + +#if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0) + model->setQuery(std::move(query)); +#else model->setQuery(query); +#endif while (model->canFetchMore()) model->fetchMore(); diff --git a/limereport/lrdatasourcemanager.cpp b/limereport/lrdatasourcemanager.cpp index b3e3738..91f1189 100644 --- a/limereport/lrdatasourcemanager.cpp +++ b/limereport/lrdatasourcemanager.cpp @@ -392,7 +392,13 @@ QSharedPointerDataSourceManager::previewSQL(const QString &c } query.exec(); + +#if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0) + model->setQuery(std::move(query)); +#else model->setQuery(query); +#endif + m_lastError = model->lastError().text(); putError(m_lastError); if (model->query().isActive()) @@ -423,8 +429,8 @@ QString DataSourceManager::extractField(QString source) } QString DataSourceManager::replaceVariables(QString value){ -#if QT_VERSION >= QT_VERSION_CHECK(5, 12, 3) - QRegularExpression rx(Const::VARIABLE_RX); +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 1) + QRegularExpression rx = getVariableRegEx(); QRegularExpressionMatchIterator iter = rx.globalMatch(value); qsizetype pos = 0; QString result; @@ -443,7 +449,6 @@ QString DataSourceManager::replaceVariables(QString value){ } result += value.mid(pos); return result; - // TODO: Qt6 port - done #else QRegExp rx(Const::VARIABLE_RX); @@ -468,8 +473,8 @@ QString DataSourceManager::replaceVariables(QString value){ QString DataSourceManager::replaceVariables(QString query, QMap &aliasesToParam) { -#if QT_VERSION >= QT_VERSION_CHECK(5, 12, 3) - QRegularExpression rx(Const::VARIABLE_RX); +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 1) + QRegularExpression rx = getVariableRegEx(); int curentAliasIndex = 0; if (query.contains(rx)){ int pos = -1; @@ -508,7 +513,6 @@ QString DataSourceManager::replaceVariables(QString query, QMap match = rx.match(query); } } - // TODO: Qt6 port - done #else QRegExp rx(Const::VARIABLE_RX); int curentAliasIndex = 0; @@ -553,9 +557,8 @@ QString DataSourceManager::replaceVariables(QString query, QMap QString DataSourceManager::replaceFields(QString query, QMap &aliasesToParam, QString masterDatasource) { -#if QT_VERSION >= QT_VERSION_CHECK(5, 12, 3) - - QRegularExpression rx(Const::FIELD_RX); +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 1) + QRegularExpression rx = getFieldRegEx(); int curentAliasIndex = 0; if (query.contains(rx)){ int pos = -1; @@ -583,7 +586,6 @@ QString DataSourceManager::replaceFields(QString query, QMap &a match = rx.match(query); } } - // TODO: Qt6 port - done #else QRegExp rx(Const::FIELD_RX); if (query.contains(rx)){ @@ -1498,7 +1500,7 @@ void DataSourceManager::invalidateQueriesContainsVariable(const QString& variabl #if (QT_VERSION < QT_VERSION_CHECK(5, 15, 1)) QRegExp rx(QString(Const::NAMED_VARIABLE_RX).arg(variableName)); #else - QRegularExpression rx(QString(Const::NAMED_VARIABLE_RX).arg(variableName)); + QRegularExpression rx = getNamedVariableRegEx(variableName); #endif if (holder->queryText().contains(rx)){ holder->invalidate(designTime() ? IDataSource::DESIGN_MODE : IDataSource::RENDER_MODE); diff --git a/limereport/lrfactoryinitializer.cpp b/limereport/lrfactoryinitializer.cpp index fef87c2..597f764 100644 --- a/limereport/lrfactoryinitializer.cpp +++ b/limereport/lrfactoryinitializer.cpp @@ -169,7 +169,7 @@ void initReportItems(){ #ifdef HAVE_SVG DesignElementsFactory::instance().registerCreator( - "BarcodeItem", + "SVGItem", LimeReport::ItemAttribs(QObject::tr("SVG Item"),"Item"), createSVGItem ); diff --git a/limereport/lrglobal.cpp b/limereport/lrglobal.cpp index cd2b6c0..ac78588 100644 --- a/limereport/lrglobal.cpp +++ b/limereport/lrglobal.cpp @@ -67,7 +67,7 @@ QString replaceHTMLSymbols(const QString &value) return result; } -#if QT_VERSION >= QT_VERSION_CHECK(5, 12, 3) +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 1) QVector normalizeCaptures(const QRegularExpressionMatch& reg){ #else QVector normalizeCaptures(const QRegExp& reg){ @@ -93,4 +93,53 @@ ReportError::ReportError(const QString& message):std::runtime_error(message.toSt IExternalPainter::~IExternalPainter(){} IPainterProxy::~IPainterProxy(){} + +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 1) +QRegularExpression getRegEx(QString expression){ + return QRegularExpression(expression, QRegularExpression::DotMatchesEverythingOption); +} +QRegularExpression getVariableRegEx(){ + return QRegularExpression( + Const::VARIABLE_RX, + QRegularExpression::DotMatchesEverythingOption | + QRegularExpression::CaseInsensitiveOption + ); +} +QRegularExpression getFieldRegEx(){ + return QRegularExpression( + Const::FIELD_RX, + QRegularExpression::DotMatchesEverythingOption | + QRegularExpression::CaseInsensitiveOption + ); +} +QRegularExpression getScriptRegEx(){ + return QRegularExpression( + Const::SCRIPT_RX, + QRegularExpression::DotMatchesEverythingOption | + QRegularExpression::CaseInsensitiveOption + ); +} +QRegularExpression getGroupFunctionRegEx(QString functionName){ + return QRegularExpression( + QString(Const::GROUP_FUNCTION_RX).arg(functionName), + QRegularExpression::DotMatchesEverythingOption | + QRegularExpression::InvertedGreedinessOption + ); +} +QRegularExpression getGroupFunctionNameRegEx(QString functionName){ + return QRegularExpression( + QString(Const::GROUP_FUNCTION_NAME_RX).arg(functionName), + QRegularExpression::DotMatchesEverythingOption | + QRegularExpression::InvertedGreedinessOption + ); +} +QRegularExpression getNamedVariableRegEx(QString variableName){ + return QRegularExpression( + QString(Const::NAMED_VARIABLE_RX).arg(variableName), + QRegularExpression::DotMatchesEverythingOption + ); +} +#endif + + } //namespace LimeReport diff --git a/limereport/lrglobal.h b/limereport/lrglobal.h index ed0254a..b2fe56c 100644 --- a/limereport/lrglobal.h +++ b/limereport/lrglobal.h @@ -104,7 +104,7 @@ namespace Const{ QString extractClassName(QString className); QString escapeSimbols(const QString& value); QString replaceHTMLSymbols(const QString &value); -#if QT_VERSION >= QT_VERSION_CHECK(5, 12, 3) +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 1) QVector normalizeCaptures(const QRegularExpressionMatch ®); #else QVector normalizeCaptures(const QRegExp ®); @@ -157,6 +157,16 @@ namespace Const{ #else typedef QStyleOptionViewItem StyleOptionViewItem; #endif +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 1) + QRegularExpression getRegEx(QString expression); + QRegularExpression getVariableRegEx(); + QRegularExpression getFieldRegEx(); + QRegularExpression getScriptRegEx(); + QRegularExpression getGroupFunctionRegEx(QString functionName); + QRegularExpression getGroupFunctionNameRegEx(QString functionName); + QRegularExpression getNamedVariableRegEx(QString variableName); +#endif + class Enums { diff --git a/limereport/lrgroupfunctions.cpp b/limereport/lrgroupfunctions.cpp index 3130832..f893d12 100644 --- a/limereport/lrgroupfunctions.cpp +++ b/limereport/lrgroupfunctions.cpp @@ -48,8 +48,8 @@ void GroupFunction::slotBandRendered(BandDesignIntf *band) QRegExp rxField(Const::FIELD_RX); QRegExp rxVar(Const::VARIABLE_RX); #else - QRegularExpression rxField(Const::FIELD_RX); - QRegularExpression rxVar(Const::VARIABLE_RX); + QRegularExpression rxField = getFieldRegEx(); + QRegularExpression rxVar = getVariableRegEx(); #endif switch (m_dataType){ @@ -154,9 +154,9 @@ GroupFunction::GroupFunction(const QString &expression, const QString &dataBandN QRegExp rxVariable(Const::VARIABLE_RX,Qt::CaseInsensitive); QRegExp rxScript(Const::SCRIPT_RX,Qt::CaseInsensitive); #else - QRegularExpression rxField(Const::FIELD_RX, QRegularExpression::CaseInsensitiveOption); - QRegularExpression rxVariable(Const::VARIABLE_RX, QRegularExpression::CaseInsensitiveOption); - QRegularExpression rxScript(Const::SCRIPT_RX, QRegularExpression::CaseInsensitiveOption); + QRegularExpression rxField = getFieldRegEx(); + QRegularExpression rxVariable = getVariableRegEx(); + QRegularExpression rxScript = getScriptRegEx(); #endif #if (QT_VERSION < QT_VERSION_CHECK(5, 15, 1)) if (rxScript.indexIn(expression) != -1){ diff --git a/limereport/lritemdesignintf.h b/limereport/lritemdesignintf.h index 0687651..55ebe5a 100644 --- a/limereport/lritemdesignintf.h +++ b/limereport/lritemdesignintf.h @@ -97,6 +97,7 @@ public: LayoutDesignIntf(const QString& xmlTypeName, QObject* owner = 0,QGraphicsItem* parent = 0): ItemDesignIntf(xmlTypeName,owner,parent){} virtual void addChild(BaseDesignIntf *item,bool updateSize=true) = 0; + virtual void removeChild(BaseDesignIntf *item) = 0; virtual void restoreChild(BaseDesignIntf *item) = 0; virtual int childrenCount() = 0; friend class BaseDesignIntf; diff --git a/limereport/lrpagedesignintf.cpp b/limereport/lrpagedesignintf.cpp index 785b4a4..659244d 100644 --- a/limereport/lrpagedesignintf.cpp +++ b/limereport/lrpagedesignintf.cpp @@ -554,17 +554,16 @@ CommandIf::Ptr PageDesignIntf::removeReportItemCommand(BaseDesignIntf *item){ CommandIf::Ptr command = createBandDeleteCommand(this,band); return command; } else { - LayoutDesignIntf* layout = dynamic_cast(item->parent()); - if (layout && (layout->childrenCount()==2)){ + LayoutDesignIntf* parentLayout = dynamic_cast(item->parent()); + LayoutDesignIntf* layout = dynamic_cast(item); + // When removing layout child all his children will be assigned to parent + if (!layout && parentLayout && (parentLayout->childrenCount() == 2)) { CommandGroup::Ptr commandGroup = CommandGroup::create(); - commandGroup->addCommand(DeleteLayoutCommand::create(this, layout),false); + commandGroup->addCommand(DeleteLayoutCommand::create(this, parentLayout),false); commandGroup->addCommand(DeleteItemCommand::create(this,item),false); return commandGroup; } else { - CommandIf::Ptr command = (dynamic_cast(item))? - DeleteLayoutCommand::create(this, dynamic_cast(item)) : - DeleteItemCommand::create(this, item) ; - return command; + return layout ? DeleteLayoutCommand::create(this, layout) : DeleteItemCommand::create(this, item) ; } } } @@ -727,7 +726,6 @@ ReportEnginePrivate *PageDesignIntf::reportEditor() void PageDesignIntf::dragEnterEvent(QGraphicsSceneDragDropEvent *event) { - if (!event->mimeData()->text().isEmpty()){ event->setDropAction(Qt::CopyAction); event->accept(); @@ -756,7 +754,7 @@ void PageDesignIntf::dropEvent(QGraphicsSceneDragDropEvent* event) #if (QT_VERSION < QT_VERSION_CHECK(5, 15, 1)) if (isVar) data = data.remove(QRegExp(" \\[.*\\]")); #else - if (isVar) data = data.remove(QRegularExpression(" \\[.*\\]")); + if (isVar) data = data.remove(QRegularExpression(" \\[.*\\]", QRegularExpression::DotMatchesEverythingOption)); #endif ti->setContent(data); if (!isVar){ @@ -768,7 +766,7 @@ void PageDesignIntf::dropEvent(QGraphicsSceneDragDropEvent* event) parentBand->setProperty("datasource",dataSource.cap(1)); } #else - QRegularExpression dataSource("(?:\\$D\\{\\s*(.*)\\..*\\})"); + QRegularExpression dataSource("(?:\\$D\\{\\s*(.*)\\..*\\})", QRegularExpression::DotMatchesEverythingOption); QRegularExpressionMatch match = dataSource.match(data); if(match.hasMatch()){ parentBand->setProperty("datasource", match.captured(1)); @@ -2008,6 +2006,9 @@ CommandIf::Ptr DeleteLayoutCommand::create(PageDesignIntf *page, LayoutDesignInt foreach (BaseDesignIntf* childItem, item->childBaseItems()){ command->m_childItems.append(childItem->objectName()); } + LayoutDesignIntf* layout = dynamic_cast(item->parent()); + if (layout) + command->m_layoutName = layout->objectName(); return CommandIf::Ptr(command); } @@ -2032,9 +2033,20 @@ void DeleteLayoutCommand::undoIt() BaseDesignIntf *item = page()->addReportItem(m_itemType); ItemsReaderIntf::Ptr reader = StringXMLreader::create(m_itemXML); if (reader->first()) reader->readItem(item); + if (!m_layoutName.isEmpty()) { + LayoutDesignIntf* layout = dynamic_cast(page()->reportItemByName(m_layoutName)); + if (layout){ + layout->restoreChild(item); + } + page()->emitRegisterdItem(item); + } foreach(QString ci, m_childItems){ BaseDesignIntf* ri = page()->reportItemByName(ci); if (ri){ + LayoutDesignIntf* parentLayout = dynamic_cast(ri->parent()); + if (parentLayout) { + parentLayout->removeChild(ri); + } dynamic_cast(item)->addChild(ri); } page()->emitRegisterdItem(item); diff --git a/limereport/lrpagedesignintf.h b/limereport/lrpagedesignintf.h index 4d8fd19..0a49b4d 100644 --- a/limereport/lrpagedesignintf.h +++ b/limereport/lrpagedesignintf.h @@ -415,6 +415,7 @@ namespace LimeReport { void setItem(BaseDesignIntf* item); private: QStringList m_childItems; + QString m_layoutName; QString m_itemXML; QString m_itemType; QString m_itemName; diff --git a/limereport/lrreportengine.cpp b/limereport/lrreportengine.cpp index 3ff5d34..6f622bc 100644 --- a/limereport/lrreportengine.cpp +++ b/limereport/lrreportengine.cpp @@ -492,7 +492,7 @@ bool ReportEnginePrivate::showPreviewWindow(ReportPages pages, PreviewHints hint Q_UNUSED(printer) if (pages.count()>0){ Q_Q(ReportEngine); - PreviewReportWindow* w = new PreviewReportWindow(q, 0, settings()); + PreviewReportWindow* w = new PreviewReportWindow(q, QApplication::activeWindow(), settings()); w->setWindowFlags(Qt::Dialog|Qt::WindowMaximizeButtonHint|Qt::WindowCloseButtonHint| Qt::WindowMinMaxButtonsHint); w->setAttribute(Qt::WA_DeleteOnClose,true); w->setWindowModality(Qt::ApplicationModal); diff --git a/limereport/lrreportrender.cpp b/limereport/lrreportrender.cpp index 917bf04..d412b19 100644 --- a/limereport/lrreportrender.cpp +++ b/limereport/lrreportrender.cpp @@ -196,13 +196,11 @@ void ReportRender::analizeItem(ContentItemDesignIntf* contentItem, BandDesignInt QString content = contentItem->content(); QVector functions; foreach(const QString &functionName, m_datasources->groupFunctionNames()){ -#if QT_VERSION >= QT_VERSION_CHECK(5, 12, 3) - QRegularExpression rx(QString(Const::GROUP_FUNCTION_RX).arg(functionName)); - rx.setPatternOptions(rx.InvertedGreedinessOption); +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 1) + QRegularExpression rx = getGroupFunctionRegEx(functionName); if(content.indexOf(rx)>=0){ functions.append(functionName); } - // TODO: Qt6 port - done #else QRegExp rx(QString(Const::GROUP_FUNCTION_RX).arg(functionName)); rx.setMinimal(true); @@ -368,13 +366,11 @@ void ReportRender::clearPageMap() bool checkContentItem(ContentItemDesignIntf* item, DataSourceManager* datasources){ QString content = item->content(); foreach(QString functionName, datasources->groupFunctionNames()){ -#if QT_VERSION >= QT_VERSION_CHECK(5, 12, 3) - QRegularExpression rx(QString(Const::GROUP_FUNCTION_RX).arg(functionName)); - rx.setPatternOptions(rx.InvertedGreedinessOption); +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 1) + QRegularExpression rx = getGroupFunctionRegEx(functionName); if(content.indexOf(rx)>=0){ return true; } - // TODO: Qt6 port - done #else QRegExp rx(QString(Const::GROUP_FUNCTION_RX).arg(functionName)); if (rx.indexIn(content)>=0){ @@ -400,16 +396,14 @@ bool ReportRender::containsGroupFunctions(BaseDesignIntf *container){ } void ReportRender::extractGroupFuntionsFromItem(ContentItemDesignIntf* contentItem, BandDesignIntf* band){ -#if QT_VERSION >= QT_VERSION_CHECK(5, 12, 3) - - if ( contentItem && contentItem->content().contains(QRegularExpression("\\$S\\s*\\{.*\\}"))){ +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 1) + if ( contentItem && contentItem->content().contains(getScriptRegEx())){ foreach(const QString &functionName, m_datasources->groupFunctionNames()){ - QRegularExpression rx(QString(Const::GROUP_FUNCTION_RX).arg(functionName)); - rx.setPatternOptions(rx.InvertedGreedinessOption); - QRegularExpression rxName(QString(Const::GROUP_FUNCTION_NAME_RX).arg(functionName)); - rxName.setPatternOptions(rx.InvertedGreedinessOption); + QRegularExpression rx = getGroupFunctionRegEx(functionName); + QRegularExpression rxName = getGroupFunctionNameRegEx(functionName); QRegularExpressionMatch match = rx.match(contentItem->content()); + if (match.hasMatch()){ QRegularExpressionMatchIterator iter = rx.globalMatch(contentItem->content()); @@ -437,31 +431,7 @@ void ReportRender::extractGroupFuntionsFromItem(ContentItemDesignIntf* contentIt } } } -// int pos = 0; -// while ( (pos = match.capturedStart()) != -1){ -// QVector captures = normalizeCaptures(match); -// if (captures.size() >= 3){ -// int dsIndex = captures.size() == 3 ? Const::DATASOURCE_INDEX - 1 : Const::DATASOURCE_INDEX; -// BandDesignIntf* dataBand = m_patternPageItem->bandByName(captures.at(dsIndex)); -// if (dataBand){ -// GroupFunction* gf = datasources()->addGroupFunction( -// functionName, captures.at(Const::VALUE_INDEX), band->objectName(), dataBand->objectName() -// ); -// if (gf){ -// connect(dataBand, SIGNAL(bandRendered(BandDesignIntf*)), -// gf, SLOT(slotBandRendered(BandDesignIntf*))); -// connect(dataBand, SIGNAL(bandReRendered(BandDesignIntf*, BandDesignIntf*)), -// gf, SLOT(slotBandReRendered(BandDesignIntf*, BandDesignIntf*))); -// } -// } else { -// GroupFunction* gf = datasources()->addGroupFunction( -// functionName, captures.at(Const::VALUE_INDEX), band->objectName(), captures.at(dsIndex) -// ); -// gf->setInvalid(tr("Databand \"%1\" not found").arg(captures.at(dsIndex))); -// } -// } -// match = rx.match(contentItem->content(), pos + match.capturedLength()); -// } + } else if (contentItem->content().indexOf(rxName)>=0){ match = rxName.match(contentItem->content()); GroupFunction* gf = datasources()->addGroupFunction(functionName, match.captured(1), band->objectName(), ""); @@ -470,7 +440,6 @@ void ReportRender::extractGroupFuntionsFromItem(ContentItemDesignIntf* contentIt } } - // TODO: Qt6 port - done #else if ( contentItem && contentItem->content().contains(QRegExp("\\$S\\s*\\{.*\\}"))){ foreach(const QString &functionName, m_datasources->groupFunctionNames()){ @@ -529,10 +498,8 @@ void ReportRender::replaceGroupFunctionsInItem(ContentItemDesignIntf* contentIte if (m_groupfunctionItems.contains(contentItem->patternName())){ QString content = contentItem->content(); foreach(QString functionName, m_groupfunctionItems.value(contentItem->patternName())){ -#if QT_VERSION >= QT_VERSION_CHECK(5, 12, 3) - - QRegularExpression rx(QString(Const::GROUP_FUNCTION_RX).arg(functionName)); - rx.setPatternOptions(rx.InvertedGreedinessOption); +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 1) + QRegularExpression rx = getGroupFunctionRegEx(functionName); QRegularExpressionMatch match = rx.match(content); if (match.capturedStart() != -1){ @@ -556,7 +523,6 @@ void ReportRender::replaceGroupFunctionsInItem(ContentItemDesignIntf* contentIte match = rx.match(content, pos + match.capturedLength()); } } - // TODO: Qt6 port - done #else QRegExp rx(QString(Const::GROUP_FUNCTION_RX).arg(functionName)); rx.setMinimal(true); diff --git a/limereport/lrscriptenginemanager.cpp b/limereport/lrscriptenginemanager.cpp index 2abc084..05e8cde 100644 --- a/limereport/lrscriptenginemanager.cpp +++ b/limereport/lrscriptenginemanager.cpp @@ -398,7 +398,7 @@ QString ScriptEngineManager::expandUserVariables(QString context, RenderPass /* } return context; #else - QRegularExpression rx(Const::VARIABLE_RX); + QRegularExpression rx = getVariableRegEx(); if (context.contains(rx)){ int pos = 0; QRegularExpressionMatch match = rx.match(context, pos); @@ -504,8 +504,7 @@ QString ScriptEngineManager::expandDataFields(QString context, ExpandType expand return context; #else - QRegularExpression rx(Const::FIELD_RX); - + QRegularExpression rx = getFieldRegEx(); if (context.contains(rx)){ QRegularExpressionMatch match = rx.match(context); while (match.hasMatch()){ @@ -520,17 +519,32 @@ QString ScriptEngineManager::expandDataFields(QString context, ExpandType expand fieldValue="\"\""; } else { fieldValue = escapeSimbols(varValue.toString()); - switch (dataManager()->fieldData(field).type()) { - case QVariant::Char: - case QVariant::String: - case QVariant::StringList: - case QVariant::Date: - case QVariant::DateTime: - fieldValue = "\""+fieldValue+"\""; - break; - default: - break; + //TODO: Migrate to QMetaType +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + switch (dataManager()->fieldData(field).typeId()) { + case QMetaType::QChar: + case QMetaType::QString: + case QMetaType::QStringList: + case QMetaType::QDate: + case QMetaType::QDateTime: + fieldValue = "\""+fieldValue+"\""; + break; + default: + break; } +#else + switch (dataManager()->fieldData(field).type()) { + case QVariant::Char: + case QVariant::String: + case QVariant::StringList: + case QVariant::Date: + case QVariant::DateTime: + fieldValue = "\""+fieldValue+"\""; + break; + default: + break; + } +#endif } } else { if (expandType == ReplaceHTMLSymbols) @@ -567,8 +581,7 @@ QString ScriptEngineManager::expandScripts(QString context, QVariant& varValue, if (context.contains(rx)){ #else - QRegularExpression rx(Const::SCRIPT_RX, QRegularExpression::DotMatchesEverythingOption); - + QRegularExpression rx = getScriptRegEx(); if(context.contains(rx)){ #endif @@ -636,8 +649,8 @@ QVariant ScriptEngineManager::evaluateScript(const QString& script){ QVariant varValue; if (script.contains(rx)){ -#else - QRegularExpression rx(Const::SCRIPT_RX); +#else + QRegularExpression rx = getScriptRegEx(); QVariant varValue; if (script.contains(rx)){ @@ -1110,7 +1123,7 @@ bool ScriptExtractor::parse() bool ScriptExtractor::parse(int &curPos, const State& state, ScriptNode::Ptr scriptNode) { - while (curPosisValid()){ return gf->calculate(pageItem); - }else{ + } else{ return gf->error(); } - } - else { + } else { return QString(QObject::tr("Function %1 not found or have wrong arguments").arg(name)); } } else { diff --git a/limereport/lrscriptenginemanager.h b/limereport/lrscriptenginemanager.h index 7c3bccd..59979ae 100644 --- a/limereport/lrscriptenginemanager.h +++ b/limereport/lrscriptenginemanager.h @@ -401,7 +401,11 @@ private: class ScriptNode{ public: typedef QSharedPointer Ptr; - QString body(){return m_body;} + QString body(){ + if (m_body.isEmpty() && m_children.count() > 0) + return m_children.at(0)->body(); + return m_body; + } void setBody(const QString& body){ m_body = body;} void setStartLex(const QString startLex){ m_startLex = startLex;} QString script(){return m_startLex + m_body + '}';} diff --git a/limereport/objectinspector/editors/lrcomboboxeditor.cpp b/limereport/objectinspector/editors/lrcomboboxeditor.cpp index d034c50..3a4748a 100644 --- a/limereport/objectinspector/editors/lrcomboboxeditor.cpp +++ b/limereport/objectinspector/editors/lrcomboboxeditor.cpp @@ -56,7 +56,12 @@ ComboBoxEditor::ComboBoxEditor(QWidget *parent, bool clearable) : connect(m_buttonClear,SIGNAL(clicked()),this,SLOT(slotClearButtonClicked())); } - connect(m_comboBox,SIGNAL(currentIndexChanged(QString)),this,SLOT(slotCurrentIndexChanged(QString))); +#if QT_VERSION >= QT_VERSION_CHECK(5,0,0) + connect(m_comboBox, SIGNAL(currentTextChanged(QString)), this, SLOT(slotCurrentIndexChanged(QString))); +#else + connect(m_comboBox, SIGNAL(currentIndexChanged(QString)), this, SLOT(slotCurrentIndexChanged(QString))); +#endif + m_comboBox->installEventFilter(this); QHBoxLayout *layout = new QHBoxLayout(this); layout->addWidget(m_comboBox); diff --git a/limereport/objectinspector/lrobjectitemmodel.cpp b/limereport/objectinspector/lrobjectitemmodel.cpp index 122a921..c0e5398 100644 --- a/limereport/objectinspector/lrobjectitemmodel.cpp +++ b/limereport/objectinspector/lrobjectitemmodel.cpp @@ -222,6 +222,10 @@ void QObjectPropertyModel::setMultiObjects(QList* list) m_objects.clear(); submit(); + if (list->isEmpty()) { + return; + } + if (!list->contains(m_object)){ m_object=list->at(0); list->removeAt(0); diff --git a/limereport/objectinspector/propertyItems/lraxispropitem.cpp b/limereport/objectinspector/propertyItems/lraxispropitem.cpp new file mode 100644 index 0000000..40466c4 --- /dev/null +++ b/limereport/objectinspector/propertyItems/lraxispropitem.cpp @@ -0,0 +1,57 @@ +#include "lraxispropitem.h" + +#include + +#include +#include +#include + +namespace { +LimeReport::ObjectPropItem * createYAxisPropItem( + QObject *object, LimeReport::ObjectPropItem::ObjectsList* objects, const QString& name, const QString& displayName, const QVariant& data, LimeReport::ObjectPropItem* parent, bool readonly) +{ + return new LimeReport::AxisPropItem(object, objects, name, displayName, data, parent, readonly, false); +} + +LimeReport::ObjectPropItem * createXAxisPropItem( + QObject *object, LimeReport::ObjectPropItem::ObjectsList* objects, const QString& name, const QString& displayName, const QVariant& data, LimeReport::ObjectPropItem* parent, bool readonly) +{ + return new LimeReport::AxisPropItem(object, objects, name, displayName, data, parent, readonly, true); +} +bool VARIABLE_IS_NOT_USED registredXAxisProp = LimeReport::ObjectPropFactory::instance().registerCreator(LimeReport::APropIdent("xAxisSettings", "LimeReport::ChartItem"), QObject::tr("X axis"), createXAxisPropItem); +bool VARIABLE_IS_NOT_USED registredYAxisProp = LimeReport::ObjectPropFactory::instance().registerCreator(LimeReport::APropIdent("yAxisSettings", "LimeReport::ChartItem"), QObject::tr("Y axis"), createYAxisPropItem); +} + +namespace LimeReport { + +QWidget *AxisPropItem::createProperyEditor(QWidget *parent) const +{ + return new AxisPropEditor(qobject_cast(object()), m_isXAxis, parent); +} + +QString AxisPropItem::displayValue() const +{ + return QObject::tr("Axis"); +} + +AxisPropEditor::AxisPropEditor(ChartItem *chart, bool isXAxis, QWidget *parent) + : QWidget(parent), m_button(new QPushButton(this)), m_chart(chart), m_isXAxis(isXAxis) +{ + m_button->setText("..."); + QHBoxLayout* layout = new QHBoxLayout(this); + layout->addWidget(m_button); + layout->setSpacing(1); + layout->setContentsMargins(1,0,1,1); + setLayout(layout); + setFocusProxy(m_button); + setAutoFillBackground(true); + connect(m_button,SIGNAL(clicked()),this,SLOT(slotButtonClicked())); +} + +void AxisPropEditor::slotButtonClicked() +{ + m_chart->showAxisEditorDialog(m_isXAxis); + emit editingFinished(); +} + +} diff --git a/limereport/objectinspector/propertyItems/lraxispropitem.h b/limereport/objectinspector/propertyItems/lraxispropitem.h new file mode 100644 index 0000000..93fc08d --- /dev/null +++ b/limereport/objectinspector/propertyItems/lraxispropitem.h @@ -0,0 +1,43 @@ +#ifndef AXISPROPITEM_H +#define AXISPROPITEM_H + +#include +#include +#include +#include + + +namespace LimeReport { + +class AxisPropEditor : public QWidget +{ + Q_OBJECT +public: + AxisPropEditor(ChartItem* chart, bool isXAxis, QWidget *parent = 0); +signals: + void editingFinished(); +private slots: + void slotButtonClicked(); +private: + QPushButton* m_button; + ChartItem* m_chart; + bool m_isXAxis; +}; + +class AxisPropItem: public LimeReport::ObjectPropItem +{ + Q_OBJECT +public: + AxisPropItem():ObjectPropItem(){} + AxisPropItem(QObject* object, ObjectsList* objects, const QString& name, const QString& displayName, const QVariant& value, ObjectPropItem* parent, bool readonly, bool isXAxis) + :ObjectPropItem(object, objects, name, displayName, value, parent, readonly), m_isXAxis(isXAxis){} + QWidget* createProperyEditor(QWidget *parent) const; + QString displayValue() const; + +private: + bool m_isXAxis = false; +}; + +} // namespace LimeReport + +#endif // AXISPROPITEM_H diff --git a/limereport/objectinspector/propertyItems/lrrectproptem.cpp b/limereport/objectinspector/propertyItems/lrrectproptem.cpp index 20c2b56..d95e487 100644 --- a/limereport/objectinspector/propertyItems/lrrectproptem.cpp +++ b/limereport/objectinspector/propertyItems/lrrectproptem.cpp @@ -85,6 +85,17 @@ LimeReport::RectPropItem::RectPropItem(QObject *object, ObjectsList* objects, co QString LimeReport::RectPropItem::displayValue() const { + //TODO: Migrate to QMetaType +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + switch(propertyValue().typeId()){ + case QMetaType::QRect: + return rectToString(propertyValue().toRect()); + case QMetaType::QRectF: + return rectToString(propertyValue().toRect()); + default : + return ObjectPropItem::displayValue(); + } +#else switch(propertyValue().type()){ case QVariant::Rect: return rectToString(propertyValue().toRect()); @@ -93,6 +104,7 @@ QString LimeReport::RectPropItem::displayValue() const default : return ObjectPropItem::displayValue(); } +#endif } LimeReport::RectUnitPropItem::RectUnitPropItem(QObject *object, ObjectsList* objects, const QString &name, const QString &displayName, const QVariant &value, ObjectPropItem *parent, bool /*readonly*/): diff --git a/limereport/serializators/lrxmlwriter.cpp b/limereport/serializators/lrxmlwriter.cpp index 7da6046..fdae62c 100644 --- a/limereport/serializators/lrxmlwriter.cpp +++ b/limereport/serializators/lrxmlwriter.cpp @@ -193,13 +193,23 @@ bool XMLWriter::enumOrFlag(QString name, QObject *item) bool XMLWriter::isCollection(QString propertyName, QObject* item) { QMetaProperty prop=item->metaObject()->property(item->metaObject()->indexOfProperty(propertyName.toLatin1())); - return QMetaType::type(prop.typeName())==COLLECTION_TYPE_ID; + //TODO: Migrate to QMetaType +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + return QMetaType::fromName(prop.typeName()).id() == COLLECTION_TYPE_ID; +#else + return QMetaType::type(prop.typeName()) == COLLECTION_TYPE_ID; +#endif } bool XMLWriter::isTranslation(QString propertyName, QObject* item) { QMetaProperty prop=item->metaObject()->property(item->metaObject()->indexOfProperty(propertyName.toLatin1())); - return QMetaType::type(prop.typeName())==TRANSLATION_TYPE_ID; + //TODO: Migrate to QMetaType +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + return QMetaType::fromName(prop.typeName()).id() == TRANSLATION_TYPE_ID; +#else + return QMetaType::type(prop.typeName()) == TRANSLATION_TYPE_ID; +#endif } void XMLWriter::saveCollection(QString propertyName, QObject *item, QDomElement *node) @@ -254,7 +264,13 @@ void XMLWriter::saveTranslation(QString propertyName, QObject* item, QDomElement bool XMLWriter::isQObject(QString propertyName, QObject *item) { QMetaProperty prop=item->metaObject()->property(item->metaObject()->indexOfProperty(propertyName.toLatin1())); - return QMetaType::type(prop.typeName())==QMetaType::QObjectStar; + //TODO: Migrate to QMetaType +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + return QMetaType::fromName(prop.typeName()).id() == QMetaType::QObjectStar; +#else + return QMetaType::type(prop.typeName()) == QMetaType::QObjectStar; +#endif + } bool XMLWriter::replaceNode(QDomElement node, QObject* item) diff --git a/limereport/translationeditor/languageselectdialog.h b/limereport/translationeditor/languageselectdialog.h index 0402327..48d53b4 100644 --- a/limereport/translationeditor/languageselectdialog.h +++ b/limereport/translationeditor/languageselectdialog.h @@ -8,18 +8,20 @@ namespace Ui { class LanguageSelectDialog; } -class LanguageSelectDialog : public QDialog -{ +class LanguageSelectDialog : public QDialog { Q_OBJECT -public: + public: explicit LanguageSelectDialog(QWidget *parent = 0); ~LanguageSelectDialog(); QLocale::Language getSelectedLanguage(); -private: + + private: Ui::LanguageSelectDialog *ui; }; +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) Q_DECLARE_METATYPE(QLocale::Language) +#endif #endif // LANGUAGESELECTDIALOG_H diff --git a/limereport/translationeditor/translationeditor.cpp b/limereport/translationeditor/translationeditor.cpp index 8006c3b..a2e693e 100644 --- a/limereport/translationeditor/translationeditor.cpp +++ b/limereport/translationeditor/translationeditor.cpp @@ -29,7 +29,11 @@ TranslationEditor::TranslationEditor(QWidget *parent) : ui->tbStrings->setHorizontalHeaderItem(1,new QTableWidgetItem(tr("Report Item"))); ui->tbStrings->setHorizontalHeaderItem(2,new QTableWidgetItem(tr("Property"))); ui->tbStrings->setHorizontalHeaderItem(3,new QTableWidgetItem(tr("Source text"))); - new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_Return), this, SLOT(slotItemChecked())); +#if QT_VERSION >= QT_VERSION_CHECK(5,0,0) + m_clrReturn = new QShortcut(QKeySequence(Qt::CTRL | Qt::Key_Return), this, SLOT(slotItemChecked())); +#else + m_clrReturn = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_Return), this, SLOT(slotItemChecked())); +#endif //ui->tbStrings->setSortingEnabled(true); } @@ -50,6 +54,7 @@ void TranslationEditor::setReportEngine(ITranslationContainer* translationContai TranslationEditor::~TranslationEditor() { delete ui; + delete m_clrReturn; } QLocale::Language TranslationEditor::getLanguageByName(const QString& languageName){ diff --git a/limereport/translationeditor/translationeditor.h b/limereport/translationeditor/translationeditor.h index 48fbb0b..2288b25 100644 --- a/limereport/translationeditor/translationeditor.h +++ b/limereport/translationeditor/translationeditor.h @@ -4,6 +4,7 @@ #include #include #include +#include #include "lrreporttranslation.h" namespace LimeReport { @@ -46,6 +47,7 @@ private: PageTranslation* m_currentPageTranslation; PropertyTranslation* m_currentPropertyTranslation; bool m_translationChanging; + QShortcut* m_clrReturn; }; } //namespace LimeReport