diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e15d5ca6..1cf0b389 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,370 +1,372 @@ # Options simple_option(KREPORT_SCRIPTING "Scripting support using JavaScript language" ON) if(KREPORT_SCRIPTING) find_package(Qt5Qml REQUIRED) set(SCRIPTING_LIBS Qt5::Qml) endif() set(kreport_LIB_SRCS common/kreport_debug.cpp common/kreportplugin_debug.cpp common/KReportItemBase.cpp common/KReportAsyncItemBase.cpp common/KReportSectionData.cpp common/KReportLabelSizeInfo.cpp common/KReportDocument.cpp common/KReportDetailSectionData.cpp common/KReportPluginInterface.cpp common/KReportItemLine.cpp common/KReportRenderObjects.cpp common/KReportPluginManager.cpp common/KReportJsonTrader_p.cpp common/KReportPluginMetaData.cpp common/KReportDataSource.cpp common/KReportUtils.cpp common/KReportPageSize.cpp common/KReportUnit.cpp common/KReportDesign.cpp common/KReportDesign_p.cpp common/KReportLineStyle.cpp common/KReportElement.cpp ${PROJECT_BINARY_DIR}/src/KReportElement_sdc.cpp common/KReportSection.cpp renderer/KReportPrintRenderer_p.cpp renderer/KReportPreRenderer.cpp renderer/KReportAsyncItemManager_p.cpp renderer/KReportScreenRenderer_p.cpp renderer/KReportHTMLTableRenderer_p.cpp renderer/KReportHTMLCSSRenderer_p.cpp #TODO renderer/KReportKSpreadRenderer.cpp #TODO renderer/KReportODTRenderer.cpp #TODO renderer/KOdtFrameReportRenderer.cpp renderer/KReportRendererBase.cpp renderer/KReportPage.cpp renderer/KReportView.cpp renderer/KReportOneRecordDataSource_p.cpp wrtembed/KReportDetailGroupSectionDialog.cpp wrtembed/KReportDesignerItemBase.cpp wrtembed/KReportDesignerItemRectBase.cpp wrtembed/KReportDesignerItemLine.cpp wrtembed/KReportDesignerSection.cpp wrtembed/KReportDesignerSectionDetailGroup.cpp wrtembed/KReportDesignerSectionDetail.cpp wrtembed/KReportDesignerSectionScene.cpp wrtembed/KReportDesignerSectionView.cpp wrtembed/KReportDesigner.cpp wrtembed/KReportPropertiesButton.cpp wrtembed/KReportSectionEditor.cpp wrtembed/KReportRuler_p.cpp wrtembed/KReportZoomHandler_p.cpp wrtembed/KReportZoomMode_p.cpp items/label/KReportItemLabel.cpp items/label/KReportDesignerItemLabel.cpp items/label/KReportLabelPlugin.cpp items/label/KReportBoundedTextItem.cpp items/label/KReportLabelElement.cpp items/label/label.json items/check/KReportItemCheck.cpp items/check/KReportDesignerItemCheckBox.cpp items/check/KReportCheckBoxPlugin.cpp items/check/check.json items/field/KReportItemField.cpp items/field/KReportDesignerItemField.cpp items/field/KReportFieldPlugin.cpp items/field/field.json items/image/KReportItemImage.cpp items/image/KReportDesignerItemImage.cpp items/image/KReportImagePlugin.cpp items/image/image.json items/text/KReportItemText.cpp items/text/KReportDesignerItemText.cpp items/text/KReportTextPlugin.cpp items/text/text.json # non-source: Mainpage.dox Messages.sh ) set(kreport_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/common ${CMAKE_CURRENT_SOURCE_DIR}/wrtembed ${CMAKE_CURRENT_SOURCE_DIR}/renderer ) set(kreport_TARGET_INCLUDE_DIRS common renderer wrtembed ) if(KREPORT_SCRIPTING) list(APPEND kreport_LIB_SRCS renderer/scripting/KReportScriptHandler.cpp renderer/scripting/KReportScriptConstants.cpp renderer/scripting/KReportScriptDebug.cpp renderer/scripting/KReportScriptDraw.cpp renderer/scripting/KReportScriptReport.cpp renderer/scripting/KReportScriptSection.cpp renderer/scripting/KReportScriptLine.cpp #renderer/odtframe/KoOdtFrameReportDocument.cpp #renderer/odtframe/KoOdtFrameReportCheckBox.cpp #renderer/odtframe/KoOdtFrameReportImage.cpp #renderer/odtframe/KoOdtFrameReportTextBox.cpp #renderer/odtframe/KoOdtFrameReportLine.cpp #renderer/odtframe/KoOdtFrameReportPicture.cpp #renderer/odtframe/KoOdtFrameReportPrimitive.cpp #renderer/ods/KoSimpleOdsDocument.cpp #renderer/ods/KoSimpleOdsSheet.cpp #renderer/ods/KoSimpleOdsCell.cpp items/label/KReportScriptLabel.cpp items/check/KReportScriptCheck.cpp items/field/KReportScriptField.cpp items/image/KReportScriptImage.cpp items/text/KReportScriptText.cpp ) qt_wrap_cpp(KReport kreport_LIB_SRCS renderer/scripting/KReportGroupTracker.h ) list(APPEND kreport_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/renderer/scripting ) list(APPEND kreport_TARGET_INCLUDE_DIRS renderer/scripting ) endif() qt5_wrap_ui(kreport_LIB_SRCS wrtembed/KReportDetailGroupSectionDialog.ui wrtembed/KReportSectionEditor.ui ) ecm_create_qm_loader(kreport_LIB_SRCS kreport_qt) add_library(KReport SHARED ${kreport_LIB_SRCS}) set_coinstallable_lib_version(KReport) add_library(KReportUtilsPrivate STATIC common/KReportUtils_p.cpp ) kdb_create_shared_data_classes( kreport_GENERATED_SHARED_DATA_CLASS_HEADERS # output variable with list of headers NO_PREFIX # subdirectory in which the headers should be generated common/KReportLineStyle.shared.h common/KReportElement.shared.h common/KReportSection.shared.h items/label/KReportLabelElement.shared.h ) kdb_remove_extensions( kreport_GENERATED_SHARED_DATA_CLASS_BASENAMES ${kreport_GENERATED_SHARED_DATA_CLASS_HEADERS} ) generate_export_header(KReport) target_include_directories(KReport PUBLIC "$" INTERFACE "$" PRIVATE ${kreport_TARGET_INCLUDE_DIRS} ) target_link_libraries(KReport PUBLIC Qt5::PrintSupport Qt5::Xml KF5::CoreAddons KPropertyWidgets PRIVATE ${SCRIPTING_LIBS} KReportUtilsPrivate ) target_link_libraries(KReportUtilsPrivate PUBLIC Qt5::Widgets KF5::ConfigGui KF5::WidgetsAddons + PRIVATE + Qt5::PrintSupport ) ecm_setup_version(${PROJECT_VERSION} VARIABLE_PREFIX KREPORT VERSION_HEADER "${CMAKE_CURRENT_BINARY_DIR}/kreport_version.h" PACKAGE_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/KReportConfigVersion.cmake" ) install(TARGETS KReport EXPORT KReportTargets ${KDE_INSTALL_TARGETS_DEFAULT_ARGS}) # Create a Config.cmake and a ConfigVersion.cmake file and install them set(CMAKECONFIG_INSTALL_DIR "${CMAKECONFIG_INSTALL_PREFIX}/${KREPORT_BASE_NAME}") # A place for KReport plugins set(KREPORT_PLUGIN_INSTALL_DIR ${PLUGIN_INSTALL_DIR}/${PROJECT_NAME_LOWER}${PROJECT_STABLE_VERSION_MAJOR}) configure_package_config_file( "${CMAKE_CURRENT_SOURCE_DIR}/KReportConfig.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/KReportConfig.cmake" INSTALL_DESTINATION "${CMAKECONFIG_INSTALL_DIR}" ) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/KReportConfig.cmake" "${CMAKE_CURRENT_BINARY_DIR}/KReportConfigVersion.cmake" DESTINATION "${CMAKECONFIG_INSTALL_DIR}" COMPONENT Devel) install(EXPORT KReportTargets DESTINATION "${CMAKECONFIG_INSTALL_DIR}" FILE KReportTargets.cmake) ecm_generate_pri_file( BASE_NAME ${KREPORT_BASE_NAME} LIB_NAME ${KREPORT_BASE_NAME} DEPS "widgets" FILENAME_VAR PRI_FILENAME INCLUDE_INSTALL_DIR ${KREPORT_INCLUDE_INSTALL_DIR} ) install(FILES ${PRI_FILENAME} DESTINATION ${ECM_MKSPECS_INSTALL_DIR}) install(FILES kreport_elementplugin.desktop DESTINATION ${SERVICETYPES_INSTALL_DIR}) ecm_generate_headers(kreport_FORWARDING_HEADERS REQUIRED_HEADERS kreport_HEADERS ORIGINAL CAMELCASE RELATIVE common HEADER_NAMES KReportPageSize KReportDataSource KReportItemBase KReportItemLine KReportPluginMetaData KReportPluginManager KReportPluginInterface KReportUnit KReportUtils KReportDesign KReportDocument KReportSectionData KReportRenderObjects KReportAsyncItemBase ) ecm_generate_headers(kreport_FORWARDING_HEADERS REQUIRED_HEADERS kreport_HEADERS ORIGINAL CAMELCASE RELATIVE renderer HEADER_NAMES KReportPage KReportRendererBase KReportPreRenderer KReportView ) if(KREPORT_SCRIPTING) ecm_generate_headers(kreport_FORWARDING_HEADERS REQUIRED_HEADERS kreport_HEADERS ORIGINAL CAMELCASE RELATIVE renderer/scripting HEADER_NAMES KReportGroupTracker KReportScriptConstants KReportScriptDraw KReportScriptHandler KReportScriptSource ) endif() ecm_generate_headers(kreport_FORWARDING_HEADERS REQUIRED_HEADERS kreport_HEADERS ORIGINAL CAMELCASE RELATIVE wrtembed HEADER_NAMES KReportDesignerSectionDetail KReportDesignerSection KReportDesignerItemBase KReportDesignerSectionDetailGroup KReportDesignerItemRectBase KReportDesigner ) ecm_generate_headers(kreport_FORWARDING_HEADERS_FROM_BUILDDIR REQUIRED_HEADERS kreport_HEADERS_FROM_BUILDDIR ORIGINAL CAMELCASE SOURCE_DIR ${PROJECT_BINARY_DIR}/src HEADER_NAMES ${kreport_GENERATED_SHARED_DATA_CLASS_BASENAMES} ) list(APPEND kreport_HEADERS ${CMAKE_CURRENT_BINARY_DIR}/kreport_version.h) install( FILES ${kreport_HEADERS} ${kreport_HEADERS_FROM_BUILDDIR} ${kreport_FORWARDING_HEADERS} ${kreport_FORWARDING_HEADERS_FROM_BUILDDIR} ${PROJECT_BINARY_DIR}/src/kreport_export.h ${PROJECT_BINARY_DIR}/src/config-kreport.h DESTINATION ${KREPORT_INCLUDE_INSTALL_DIR} COMPONENT Devel ) if(BUILD_QCH) kreport_add_qch( KReport_QCH NAME KReport BASE_NAME ${KREPORT_BASE_NAME} VERSION ${PROJECT_VERSION} NAMESPACE org.kde.${KREPORT_BASE_NAME} SOURCES Mainpage.dox ${kreport_HEADERS} ${kreport_HEADERS_FROM_BUILDDIR} LINK_QCHS Qt5Core_QCH Qt5Xml_QCH Qt5Gui_QCH Qt5Widgets_QCH Qt5PrintSupport_QCH KF5CoreAddons_QCH KPropertyCore_QCH KPropertyWidgets_QCH BLANK_MACROS KREPORT_EXPORT KREPORT_DEPRECATED TAGFILE_INSTALL_DESTINATION ${KREPORT_QTQCH_FULL_INSTALL_DIR} QCH_INSTALL_DESTINATION ${KREPORT_QTQCH_FULL_INSTALL_DIR} ) set(kreport_qch_targets KReport_QCH) endif() kreport_install_qch_export( TARGETS ${kreport_qch_targets} FILE KReportQCHTargets.cmake DESTINATION "${CMAKECONFIG_INSTALL_DIR}" COMPONENT Devel ) add_subdirectory(plugins) add_subdirectory(pics) enable_testing() configure_file(config-kreport.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-kreport.h) diff --git a/src/common/KReportDesign.cpp b/src/common/KReportDesign.cpp index 841fb500..ef26247c 100644 --- a/src/common/KReportDesign.cpp +++ b/src/common/KReportDesign.cpp @@ -1,267 +1,266 @@ /* This file is part of the KDE project * Copyright (C) 2001-2007 by OpenMFG, LLC * Copyright (C) 2007-2010 by Adam Pigg * Copyright (C) 2011-2015 Jarosław Staniek * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . */ #include "KReportDesign.h" #include "KReportDesign_p.h" #include "KReportElement.h" #include "KReportUnit.h" #include "KReportUtils.h" #include "KReportPluginManager.h" #include "KReportPluginInterface.h" #include #include -#include #include class Q_DECL_HIDDEN KReportDesignReadingStatus::Private { public: QString errorMessage; QString errorDetails; int errorLineNumber = -1; int errorColumnNumber = -1; }; KReportDesignReadingStatus::KReportDesignReadingStatus() : d(new Private) { } KReportDesignReadingStatus::~KReportDesignReadingStatus() { delete d; } KReportDesignReadingStatus::KReportDesignReadingStatus(const KReportDesignReadingStatus& other) : d(new Private) { *this = other; } KReportDesignReadingStatus& KReportDesignReadingStatus::operator=(const KReportDesignReadingStatus &other) { if (this != &other) { setErrorMessage(other.errorMessage()); setErrorDetails(other.errorDetails()); setErrorLineNumber(other.errorLineNumber()); setErrorColumnNumber(other.errorColumnNumber()); } - + return *this; } bool KReportDesignReadingStatus::isError() const { return d->errorLineNumber >= 0 && d->errorColumnNumber >= 0; } int KReportDesignReadingStatus::errorColumnNumber() const { return d->errorColumnNumber; } QString KReportDesignReadingStatus::errorDetails() const { return d->errorDetails; } QString KReportDesignReadingStatus::errorMessage() const { return d->errorMessage; } int KReportDesignReadingStatus::errorLineNumber() const { return d->errorLineNumber; } void KReportDesignReadingStatus::setErrorColumnNumber(int column) { d->errorColumnNumber = column; } void KReportDesignReadingStatus::setErrorDetails(const QString& details) { d->errorDetails = details; } void KReportDesignReadingStatus::setErrorLineNumber(int line) { d->errorLineNumber = line; } void KReportDesignReadingStatus::setErrorMessage(const QString& msg) { d->errorMessage = msg; } QDebug operator<<(QDebug dbg, const KReportDesignReadingStatus& status) { if (status.isError()) { dbg.nospace() << qPrintable( QString::fromLatin1("KReportDesignReadingStatus: errorMessage=\"%1\" " "errorDetails=\"%2\" line=%3 column=%4") .arg(status.errorMessage()).arg(status.errorDetails()) .arg(status.errorLineNumber()).arg(status.errorColumnNumber())); } else { dbg.nospace() << "KReportDesignReadingStatus: OK"; } return dbg.space(); } //----------------------------------- KReportDesign::KReportDesign() : d(new Private(this)) { } KReportDesign::~KReportDesign() { delete d; } bool KReportDesign::setContent(const QString &text, KReportDesignReadingStatus *status) { QDomDocument doc; QString errorDetails; int errorLine; int errorColumn; - + if (!doc.setContent(text, &errorDetails, &errorLine, &errorColumn)) { if (status) { status->setErrorMessage(tr("Could not parse XML document.")); status->setErrorDetails(errorDetails); status->setErrorLineNumber(errorLine); status->setErrorColumnNumber(errorColumn); } return false; } bool ret = d->processDocument(doc, status); if (!ret && status) { status->setErrorMessage(tr("Error in XML document.")); } return ret; } QString KReportDesign::toString(int indent) const { Q_UNUSED(indent); //! @todo return QString(); } QPageLayout KReportDesign::pageLayout() const { return d->pageLayout; } QString KReportDesign::title() const { return d->title; } void KReportDesign::setTitle(const QString &title) { d->title = title; } void KReportDesign::setPageLayout(const QPageLayout &pageLayout) { d->pageLayout = pageLayout; d->pageLayout.setUnits(QPageLayout::Point); } KReportElement KReportDesign::createElement(const QString &typeName, QString *errorMessage) { QDomElement el; KReportDesignReadingStatus status; KReportPluginInterface* plugin = d->findPlugin(typeName, el, &status); if (!plugin) { if (errorMessage) { *errorMessage = status.errorMessage(); } return KReportElement(); } return plugin->createElement(); } bool KReportDesign::hasSection(KReportSection::Type type) const { const int index = static_cast(type) - 1; if (0 <= index && index < d->sections.length()) { return d->sections[index]; } return false; } KReportSection KReportDesign::section(KReportSection::Type type) const { const int index = static_cast(type) - 1; if (0 <= index && index < d->sections.length()) { KReportSection *section = d->sections[index]; if (section) { return *section; } } return KReportSection(); } void KReportDesign::addSection(const KReportSection §ion) { const int index = static_cast(section.type()) - 1; if (0 <= index && index < d->sections.length()) { if (d->sections[index]) { *d->sections[index] = section; } else { d->sections[index] = new KReportSection(section); } } } // static QPageLayout KReportDesign::defaultPageLayout() { QPageLayout layout = KReportDesignGlobal::self()->defaultPageLayout; if (!layout.pageSize().isValid()) { if (!QPrinterInfo::defaultPrinter().isNull()) { layout.setPageSize(QPrinterInfo::defaultPrinter().defaultPageSize()); } else { layout.setPageSize(QPageSize(DEFAULT_PAGE_SIZE)); } } return layout; } // static void KReportDesign::setDefaultPageLayout(const QPageLayout &pageLayout) { KReportDesignGlobal::self()->defaultPageLayout = pageLayout; KReportDesignGlobal::self()->defaultPageLayout.setUnits(QPageLayout::Point); } #ifdef KREPORT_SCRIPTING QString KReportDesign::script() const { return d->script; } #endif diff --git a/src/common/KReportUtils_p.cpp b/src/common/KReportUtils_p.cpp index 5ac288bb..0fd90c2f 100644 --- a/src/common/KReportUtils_p.cpp +++ b/src/common/KReportUtils_p.cpp @@ -1,346 +1,354 @@ /* This file is part of the KDE project - Copyright (C) 2015-2016 Jarosław Staniek + Copyright (C) 2015-2019 Jarosław Staniek Copyright (C) 2016 Adam Pigg This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "KReportUtils_p.h" #include "config-kreport.h" #include #include #include #include +#include #include #include +#include +#include #include #include #include -#include -#include #ifdef Q_WS_X11 #include #else #include #endif #ifdef Q_OS_WIN #define KPATH_SEPARATOR ';' #else #define KPATH_SEPARATOR ':' #endif class KReportDpiSingleton { public: KReportDpiSingleton(); int m_dpiX; int m_dpiY; }; KReportDpiSingleton::KReportDpiSingleton() { // Another way to get the DPI of the display would be QPaintDeviceMetrics, // but we have no widget here (and moving this to KoView wouldn't allow // using this from the document easily). #ifdef Q_WS_X11 m_dpiX = QX11Info::appDpiX(); m_dpiY = QX11Info::appDpiY(); #else QDesktopWidget *w = QApplication::desktop(); if (w) { m_dpiX = w->logicalDpiX(); m_dpiY = w->logicalDpiY(); } else { m_dpiX = 96; m_dpiY = 96; } #endif } Q_GLOBAL_STATIC(KReportDpiSingleton, s_instance) namespace KReportPrivate { bool fileReadable(const QString &path) { return !path.isEmpty() && QFileInfo(path).isReadable(); } QStringList correctStandardLocations(const QString &privateName, QStandardPaths::StandardLocation location, const QString &extraLocation) { QStringList result; if (!privateName.isEmpty()) { QRegularExpression re(QLatin1Char('/') + QCoreApplication::applicationName() + QLatin1Char('$')); QStringList standardLocations(QStandardPaths::standardLocations(location)); if (!extraLocation.isEmpty()) { standardLocations.append(extraLocation); } for(const QString &dir : standardLocations) { if (dir.indexOf(re) != -1) { QString realDir(dir); realDir.replace(re, QLatin1Char('/') + privateName); result.append(realDir); } } } return result; } QString locateFile(const QString &privateName, const QString& path, QStandardPaths::StandardLocation location, const QString &extraLocation) { // let QStandardPaths handle this, it will look for app local stuff QString fullPath = QFileInfo( QStandardPaths::locate(location, path)).canonicalFilePath(); if (fileReadable(fullPath)) { return fullPath; } // Try extra location fullPath = QFileInfo(extraLocation + QLatin1Char('/') + path).canonicalFilePath(); if (fileReadable(fullPath)) { return fullPath; } // Try in PATH subdirs, useful for running apps from the build dir, without installing for(const QByteArray &pathDir : qgetenv("PATH").split(KPATH_SEPARATOR)) { const QString dataDirFromPath = QFileInfo(QFile::decodeName(pathDir) + QStringLiteral("/data/") + path).canonicalFilePath(); if (fileReadable(dataDirFromPath)) { return dataDirFromPath; } } const QStringList correctedStandardLocations(correctStandardLocations(privateName, location, extraLocation)); for(const QString &dir : correctedStandardLocations) { fullPath = QFileInfo(dir + QLatin1Char('/') + path).canonicalFilePath(); if (fileReadable(fullPath)) { return fullPath; } } return QString(); } bool registerIconsResource(const QString &privateName, const QString& path, QStandardPaths::StandardLocation location, const QString &resourceRoot, const QString &extraLocation, QString *errorMessage, QString *detailedErrorMessage) { const QString fullPath = locateFile(privateName, path, location, extraLocation); if (fullPath.isEmpty() || !QFileInfo(fullPath).isReadable() || !QResource::registerResource(fullPath, resourceRoot)) { QStringList triedLocations(QStandardPaths::standardLocations(location)); if (!extraLocation.isEmpty()) { triedLocations.append(extraLocation); } triedLocations.append(correctStandardLocations(privateName, location, extraLocation)); const QString triedLocationsString = QLocale().createSeparatedList(triedLocations); #ifdef QT_ONLY *errorMessage = QString("Could not open icon resource file %1.").arg(path); *detailedErrorMessage = QString("Tried to find in %1.").arg(triedLocationsString); #else //! @todo 3.1 Re-add translation *errorMessage = /*QObject::tr*/ QString::fromLatin1( "Could not open icon resource file \"%1\". " "Application will not start. " "Please check if it is properly installed.") .arg(QFileInfo(path).fileName()); //! @todo 3.1 Re-add translation *detailedErrorMessage = QString::fromLatin1("Tried to find in %1.").arg(triedLocationsString); #endif return false; } *errorMessage = QString(); *detailedErrorMessage = QString(); return true; } bool registerGlobalIconsResource(const QString &themeName, QString *errorMessage, QString *detailedErrorMessage) { QString extraLocation; #ifdef CMAKE_INSTALL_FULL_ICONDIR extraLocation = QDir::fromNativeSeparators(QFile::decodeName(CMAKE_INSTALL_FULL_ICONDIR)); if (extraLocation.endsWith("/icons")) { extraLocation.chop(QLatin1String("/icons").size()); } #elif defined(Q_OS_WIN) extraLocation = QCoreApplication::applicationDirPath() + QStringLiteral("/data"); #endif return registerIconsResource(QString(), QString::fromLatin1("icons/%1/%1-icons.rcc").arg(themeName), QStandardPaths::GenericDataLocation, QStringLiteral("/icons/") + themeName, extraLocation, errorMessage, detailedErrorMessage); } bool registerGlobalIconsResource(const QString &themeName) { QString errorMessage; QString detailedErrorMessage; if (!registerGlobalIconsResource(themeName, &errorMessage, &detailedErrorMessage)) { if (detailedErrorMessage.isEmpty()) { KMessageBox::error(nullptr, errorMessage); } else { KMessageBox::detailedError(nullptr, errorMessage, detailedErrorMessage); } qWarning() << qPrintable(errorMessage); return false; } return true; } bool registerGlobalIconsResource() { return registerGlobalIconsResource(supportedIconTheme); } bool setupPrivateIconsResource(const QString &privateName, const QString& path, const QString &themeName, QString *errorMessage, QString *detailedErrorMessage, const QString &prefix) { // Register application's resource first to have priority over the theme. // Some icons may exists in both resources. if (!registerIconsResource(privateName, path, QStandardPaths::AppDataLocation, QString(), QString(), errorMessage, detailedErrorMessage)) { return false; } bool changeTheme = false; #ifdef QT_GUI_LIB QIcon::setThemeSearchPaths(QStringList() << prefix << QIcon::themeSearchPaths()); changeTheme = 0 != QIcon::themeName().compare(themeName, Qt::CaseInsensitive); if (changeTheme) { QIcon::setThemeName(themeName); } #endif KConfigGroup cg(KSharedConfig::openConfig(), "Icons"); changeTheme = changeTheme || 0 != cg.readEntry("Theme", QString()).compare(themeName, Qt::CaseInsensitive); // tell KIconLoader an co. about the theme if (changeTheme) { cg.writeEntry("Theme", themeName); cg.sync(); } return true; } bool setupPrivateIconsResourceWithMessage(const QString &privateName, const QString& path, const QString &themeName, QString *errorMessage, QString *detailedErrorMessage, const QString &prefix) { if (!setupPrivateIconsResource(privateName, path, themeName, errorMessage, detailedErrorMessage, prefix)) { if (detailedErrorMessage->isEmpty()) { KMessageBox::error(nullptr, *errorMessage); } else { KMessageBox::detailedError(nullptr, *errorMessage, *detailedErrorMessage); } return false; } return true; } bool setupPrivateIconsResourceWithMessage(const QString &privateName, const QString& path, QString *errorMessage, QString *detailedErrorMessage, const QString &prefix) { return setupPrivateIconsResourceWithMessage(privateName, path, supportedIconTheme, errorMessage, detailedErrorMessage, prefix); } bool setupPrivateIconsResourceWithMessage(const QString &privateName, const QString& path, QtMsgType messageType, const QString &prefix) { QString errorMessage; QString detailedErrorMessage; if (!setupPrivateIconsResourceWithMessage(privateName, path, &errorMessage, &detailedErrorMessage, prefix)) { if (messageType == QtFatalMsg) { qFatal("%s %s", qPrintable(errorMessage), qPrintable(detailedErrorMessage)); } else { qWarning() << qPrintable(errorMessage) << qPrintable(detailedErrorMessage); } return false; } return true; } bool setupGlobalIconTheme() { if (0 != QIcon::themeName().compare(supportedIconTheme, Qt::CaseInsensitive)) { const QString message = QString::fromLatin1( "\"%1\" supports only \"%2\" icon theme but current system theme is \"%3\". " "Application's icon theme will be changed to \"%2\". " "Please consider adding support for other themes to %4.") .arg(QLatin1String(KREPORT_BASE_NAME)).arg(supportedIconTheme).arg(QIcon::themeName()) .arg(QCoreApplication::applicationName()); qDebug() << qPrintable(message); if (!registerGlobalIconsResource()) { // don't fail, just warn const QString message = QString::fromLatin1( "Failed to set icon theme to \"%1\". Icons in the application will be inconsistent. " "Please install .rcc file(s) for the system theme.") .arg(supportedIconTheme); qDebug() << qPrintable(message); return false; } } return true; } int dpiX() { return s_instance->m_dpiX; } int dpiY() { return s_instance->m_dpiY; } +Q_GLOBAL_STATIC_WITH_ARGS(QPrinter, s_printerInstance, (QPrinter::HighResolution)) + +QPrinter* highResolutionPrinter() +{ + return s_printerInstance; +} + PageLayout::PageLayout() : QPageLayout(QPageSize(QPageSize::A4), QPageLayout::Portrait, QMarginsF(0,0,0,0)) { } PageLayout::PageLayout(const QPageLayout& pageLayout) : QPageLayout(pageLayout) { } KReportPrivate::PageLayout & PageLayout::operator=(const QPageLayout& other) { QPageLayout::operator=(other); return *this; } } diff --git a/src/common/KReportUtils_p.h b/src/common/KReportUtils_p.h index 1d223f6e..9e4b111b 100644 --- a/src/common/KReportUtils_p.h +++ b/src/common/KReportUtils_p.h @@ -1,189 +1,199 @@ /* This file is part of the KDE project - Copyright (C) 2015-2016 Jarosław Staniek + Copyright (C) 2015-2019 Jarosław Staniek This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KREPORTUTILS_P_H #define KREPORTUTILS_P_H #include "KReportUnit.h" #include #include #include +class QPrinter; + const bool DEFAULT_SHOW_GRID = true; const bool DEFAULT_SNAP_TO_GRID = true; const int DEFAULT_GRID_DIVISIONS = 4; const KReportUnit::Type DEFAULT_UNIT_TYPE = KReportUnit::Type::Centimeter; #define DEFAULT_UNIT KReportUnit(DEFAULT_UNIT_TYPE) #define DEFAULT_UNIT_STRING QLatin1String("cm") const QPointF DEFAULT_ELEMENT_POS_PT(CM_TO_POINT(1.0), CM_TO_POINT(1.0)); const QSizeF DEFAULT_ELEMENT_SIZE_PT(CM_TO_POINT(1.0), CM_TO_POINT(1.0)); const QRectF DEFAULT_ELEMENT_RECT_PT(DEFAULT_ELEMENT_POS_PT, DEFAULT_ELEMENT_SIZE_PT); #define DEFAULT_ELEMENT_POS_STRING QLatin1String("1.0cm") // both X and Y #define DEFAULT_ELEMENT_SIZE_STRING QLatin1String("1.0cm") // both width and height const qreal DEFAULT_SECTION_SIZE_PT = CM_TO_POINT(2.0); #define DEFAULT_SECTION_SIZE_STRING QLatin1String("2.0cm") const qreal DEFAULT_PAGE_MARGIN_PT = CM_TO_POINT(1.0); #define DEFAULT_PAGE_MARGIN_STRING QLatin1String("1.0cm") const QPageSize::PageSizeId DEFAULT_PAGE_SIZE = QPageSize::A4; const QPageLayout::Orientation DEFAULT_PAGE_ORIENTATION = QPageLayout::Landscape; const QSizeF DEFAULT_CUSTOM_PAGE_SIZE(10.0,10.0); const qreal SMALLEST_PAGE_SIZE_PT = MM_TO_POINT(5); // This is a private code made inline for use in the lib and examples. //! @todo Move to a shared lib to use in other Kexi libraries as well. namespace KReportPrivate { //! @todo Support other themes const QString supportedIconTheme = QLatin1String("breeze"); //! @brief @return true if @a path is readable bool fileReadable(const QString &path); //! @brief Used for a workaround: locations for QStandardPaths::AppDataLocation end with app name. //! If this is not an expected app but for example a test app, replace //! the subdir name with app name so we can find resource file(s). QStringList correctStandardLocations(const QString &privateName, QStandardPaths::StandardLocation location, const QString &extraLocation); /*! @brief Locates a file path for specified parameters * @param privateName Name to be used instead of application name for resource lookup * @param path Relative path to the resource file * @param location Standard file location to use for file lookup * @param extraLocation Extra directory path for file lookup * @return Empty string on failure */ QString locateFile(const QString &privateName, const QString& path, QStandardPaths::StandardLocation location, const QString &extraLocation); /*! @brief Registers icons resource file * @param privateName Name to be used instead of application name for resource lookup * @param path Relative path to the resource file * @param location Standard file location to use for file lookup * @param resourceRoot A resource root for QResource::registerResource() * @param errorMessage On failure it is set to a brief error message. * @param errorDescription On failure it is set to a detailed error message. * other for warning */ bool registerIconsResource(const QString &privateName, const QString& path, QStandardPaths::StandardLocation location, const QString &resourceRoot, const QString &extraLocation, QString *errorMessage, QString *detailedErrorMessage); /*! @brief Registers a global icon resource file * @param themeName A name of icon theme to use. * @param errorMessage On failure it is set to a brief error message. * @param errorDescription On failure it is set to a detailed error message. * other for warning */ bool registerGlobalIconsResource(const QString &themeName, QString *errorMessage, QString *detailedErrorMessage); /*! @brief Registers a global icon resource file * @param themeName A name of icon theme to use. */ bool registerGlobalIconsResource(const QString &themeName); /*! @brief Registers a global icon resource file for default theme name. */ bool registerGlobalIconsResource(); /*! @brief Sets up a private icon resource file * @return @c false on failure and sets error message. Does not warn or exit on failure. * @param privateName Name to be used instead of application name for resource lookup * @param path Relative path to the resource file * @param themeName Icon theme to use. It affects filename. * @param errorMessage On failure it is set to a brief error message * @param errorDescription On failure it is set to a detailed error message * other for warning * @param prefix Resource path prefix. The default is useful for library-global resource, * other values is useful for plugins. */ bool setupPrivateIconsResource(const QString &privateName, const QString& path, const QString &themeName, QString *errorMessage, QString *detailedErrorMessage, const QString &prefix = QLatin1String(":/icons")); /*! @brief Sets up a private icon resource file * @return @c false on failure and sets error message. * @param privateName Name to be used instead of application name for resource lookup * @param path Relative path to the resource file * @param themeName Icon theme to use. It affects filename. * @param errorMessage On failure it is set to a brief error message. * @param errorDescription On failure it is set to a detailed error message. * other for warning * @param prefix Resource path prefix. The default is useful for library-global resource, * other values is useful for plugins. */ bool setupPrivateIconsResourceWithMessage(const QString &privateName, const QString& path, const QString &themeName, QString *errorMessage, QString *detailedErrorMessage, const QString &prefix = QLatin1String(":/icons")); /*! @overload setupPrivateIconsResourceWithMessage(QString &privateName, const QString& path, const QString &themeName, QString *errorMessage, QString *detailedErrorMessage, const QString &prefix = QLatin1String(":/icons")) Uses default theme name. */ bool setupPrivateIconsResourceWithMessage(const QString &privateName, const QString& path, QString *errorMessage, QString *detailedErrorMessage, const QString &prefix = QLatin1String(":/icons")); /*! @brief Sets up a private icon resource file * Warns on failure and returns @c false. * @param privateName Name to be used instead of application name for resource lookup * @param path Relative path to the resource file * @param messageType Type of message to use on error, QtFatalMsg for fatal exit and any * other for warning * @param prefix Resource path prefix. The default is useful for library-global resource, * other values is useful for plugins. */ bool setupPrivateIconsResourceWithMessage(const QString &privateName, const QString& path, QtMsgType messageType, const QString &prefix = QLatin1String(":/icons")); //! Sets up a global icon theme if it is different from supported. //! Warns on failure and returns @c false. bool setupGlobalIconTheme(); int dpiX(); int dpiY(); +/*! + * Returns a high-resolution printer + * + * The QPrinter(QPrinter::HighResolution)) instance is created on first call. + * The global printer helps to optimize access to QPrinter when report items need it. + */ +QPrinter* highResolutionPrinter(); + //! This class is wrapper that fixes a critical QTBUG-47551 bug in default constructor of QPageLayout //! Default constructor of QPageLayout does not initialize units. //! https://bugreports.qt.io/browse/QTBUG-47551 //! @todo remove this class and go back to QPageLayout when the faulty QPageLayout implementations are no longer on the wild. That's probably for Qt 6. class PageLayout: public QPageLayout { public: PageLayout(); PageLayout(const QPageLayout& pageLayout); PageLayout& operator=(const QPageLayout& other); }; } // KReportPrivate #endif diff --git a/src/items/text/KReportItemText.cpp b/src/items/text/KReportItemText.cpp index 29f63998..e05088fa 100644 --- a/src/items/text/KReportItemText.cpp +++ b/src/items/text/KReportItemText.cpp @@ -1,309 +1,310 @@ /* This file is part of the KDE project * Copyright (C) 2007-2008 by Adam Pigg (adam@piggz.co.uk) + * Copyright (C) 2019 Jarosław Staniek * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . */ #include "KReportItemText.h" #include "KReportRenderObjects.h" -#include "kreportplugin_debug.h" #include "KReportUtils.h" +#include "KReportUtils_p.h" +#include "kreportplugin_debug.h" #include #include #include #include #include #include #include #include KReportItemText::KReportItemText() : m_bottomPadding(0.0) { createProperties(); } KReportItemText::KReportItemText(const QDomNode & element) : KReportItemText() { nameProperty()->setValue(KReportUtils::readNameAttribute(element.toElement())); setItemDataSource(element.toElement().attribute(QLatin1String("report:item-data-source"))); m_itemValue->setValue(element.toElement().attribute(QLatin1String("report:value"))); setZ(element.toElement().attribute(QLatin1String("report:z-index")).toDouble()); m_horizontalAlignment->setValue(element.toElement().attribute(QLatin1String("report:horizontal-align"))); m_verticalAlignment->setValue(element.toElement().attribute(QLatin1String("report:vertical-align"))); m_bottomPadding = element.toElement().attribute(QLatin1String("report:bottom-padding")).toDouble(); parseReportRect(element.toElement()); QDomNodeList nl = element.childNodes(); QString n; QDomNode node; for (int i = 0; i < nl.count(); i++) { node = nl.item(i); n = node.nodeName(); if (n == QLatin1String("report:text-style")) { KReportTextStyleData ts; if (parseReportTextStyleData(node.toElement(), &ts)) { m_backgroundColor->setValue(ts.backgroundColor); m_foregroundColor->setValue(ts.foregroundColor); m_backgroundOpacity->setValue(ts.backgroundOpacity); m_font->setValue(ts.font); } } else if (n == QLatin1String("report:line-style")) { KReportLineStyle ls; if (parseReportLineStyleData(node.toElement(), &ls)) { m_lineWeight->setValue(ls.weight()); m_lineColor->setValue(ls.color()); m_lineStyle->setValue(static_cast(ls.penStyle())); } } else { kreportpluginWarning() << "while parsing field element encountered unknown element: " << n; } } } KReportItemText::~KReportItemText() { } Qt::Alignment KReportItemText::textFlags() const { Qt::Alignment align; QString t; t = m_horizontalAlignment->value().toString(); if (t == QLatin1String("center")) align = Qt::AlignHCenter; else if (t == QLatin1String("right")) align = Qt::AlignRight; else align = Qt::AlignLeft; t = m_verticalAlignment->value().toString(); if (t == QLatin1String("center")) align |= Qt::AlignVCenter; else if (t == QLatin1String("bottom")) align |= Qt::AlignBottom; else align |= Qt::AlignTop; return align; } void KReportItemText::createProperties() { createDataSourceProperty(); m_itemValue = new KProperty("value", QString(), tr("Value"), tr("Value used if not bound to a field")); KPropertyListData *listData = new KPropertyListData( { QLatin1String("left"), QLatin1String("center"), QLatin1String("right") }, QVariantList{ tr("Left"), tr("Center"), tr("Right") }); m_horizontalAlignment = new KProperty("horizontal-align", listData, QLatin1String("left"), tr("Horizontal Alignment")); listData = new KPropertyListData( { QLatin1String("top"), QLatin1String("center"), QLatin1String("bottom") }, QVariantList{ tr("Top"), tr("Center"), tr("Bottom") }); m_verticalAlignment = new KProperty("vertical-align", listData, QLatin1String("center"), tr("Vertical Alignment")); m_font = new KProperty("font", QApplication::font(), tr("Font")); m_backgroundColor = new KProperty("background-color", QColor(Qt::white), tr("Background Color")); m_foregroundColor = new KProperty("foreground-color", QColor(Qt::black), tr("Foreground Color")); m_lineWeight = new KProperty("line-weight", 1.0, tr("Line Weight")); m_lineWeight->setOption("step", 1.0); m_lineColor = new KProperty("line-color", QColor(Qt::black), tr("Line Color")); m_lineStyle = new KProperty("line-style", static_cast(Qt::NoPen), tr("Line Style"), QString(), KProperty::LineStyle); m_backgroundOpacity = new KProperty("background-opacity", QVariant(0), tr("Background Opacity")); m_backgroundOpacity->setOption("max", 100); m_backgroundOpacity->setOption("min", 0); m_backgroundOpacity->setOption("suffix", QLatin1String("%")); propertySet()->addProperty(m_itemValue); propertySet()->addProperty(m_horizontalAlignment); propertySet()->addProperty(m_verticalAlignment); propertySet()->addProperty(m_font); propertySet()->addProperty(m_backgroundColor); propertySet()->addProperty(m_foregroundColor); propertySet()->addProperty(m_backgroundOpacity); propertySet()->addProperty(m_lineWeight); propertySet()->addProperty(m_lineColor); propertySet()->addProperty(m_lineStyle); } qreal KReportItemText::bottomPadding() const { return m_bottomPadding; } void KReportItemText::setBottomPadding(qreal bp) { if (m_bottomPadding != bp) { m_bottomPadding = bp; } } KReportTextStyleData KReportItemText::textStyle() const { KReportTextStyleData d; d.backgroundColor = m_backgroundColor->value().value(); d.foregroundColor = m_foregroundColor->value().value(); d.font = m_font->value().value(); d.backgroundOpacity = m_backgroundOpacity->value().toInt(); return d; } KReportLineStyle KReportItemText::lineStyle() const { KReportLineStyle ls; ls.setWeight(m_lineWeight->value().toReal()); ls.setColor(m_lineColor->value().value()); ls.setPenStyle((Qt::PenStyle)m_lineStyle->value().toInt()); return ls; } // RTTI QString KReportItemText::typeName() const { return QLatin1String("text"); } int KReportItemText::renderSimpleData(OROPage *page, OROSection *section, const QPointF &offset, const QVariant &data, KReportScriptHandler *script) { Q_UNUSED(script); QString qstrValue; QString cs = itemDataSource(); if (!cs.isEmpty()) { qstrValue = data.toString(); } else { qstrValue = m_itemValue->value().toString(); } QPointF pos = scenePosition(position()); QSizeF siz = sceneSize(size()); pos += offset; QRectF trf(pos, siz); qreal intStretch = trf.top() - offset.y(); if (!qstrValue.isEmpty()) { QRectF rect = trf; int pos = 0; QChar separator; QRegularExpression re(QLatin1String("\\s")); - QPrinter prnt(QPrinter::HighResolution); - QFontMetricsF fm(font(), &prnt); + const QFontMetricsF fm(font(), KReportPrivate::highResolutionPrinter()); - // int intRectWidth = (int)(trf.width() * prnt.resolution()) - 10; - int intRectWidth = (int)((size().width() / 72) * prnt.resolution()); + const int intRectWidth + = (int)((size().width() / 72) * KReportPrivate::highResolutionPrinter()->resolution()); int intLineCounter = 0; qreal intBaseTop = trf.top(); qreal intRectHeight = trf.height(); while (!qstrValue.isEmpty()) { QRegularExpressionMatch match = re.match(qstrValue); int idx = match.capturedStart(pos); if (idx == -1) { idx = qstrValue.length(); separator = QLatin1Char('\n'); } else separator = qstrValue.at(idx); if (fm.boundingRect(qstrValue.left(idx)).width() < intRectWidth || pos == 0) { pos = idx + 1; if (separator == QLatin1Char('\n')) { QString line = qstrValue.left(idx); qstrValue.remove(0, idx + 1); pos = 0; rect.setTop(intBaseTop + (intLineCounter * intRectHeight)); rect.setBottom(rect.top() + intRectHeight); OROTextBox * tb = new OROTextBox(); tb->setPosition(rect.topLeft()); tb->setSize(rect.size()); tb->setFont(font()); tb->setText(line); tb->setFlags(textFlags()); tb->setTextStyle(textStyle()); tb->setLineStyle(lineStyle()); if (page) { page->insertPrimitive(tb); } if (section) { OROTextBox *tb2 = dynamic_cast(tb->clone()); if (tb2) { tb2->setPosition(scenePosition(position())); section->addPrimitive(tb2); } } if (!page) { delete tb; } intStretch += intRectHeight; intLineCounter++; } } else { QString line = qstrValue.left(pos - 1); qstrValue.remove(0, pos); pos = 0; rect.setTop(intBaseTop + (intLineCounter * intRectHeight)); rect.setBottom(rect.top() + intRectHeight); OROTextBox * tb = new OROTextBox(); tb->setPosition(rect.topLeft()); tb->setSize(rect.size()); tb->setFont(font()); tb->setText(line); tb->setFlags(textFlags()); tb->setTextStyle(textStyle()); tb->setLineStyle(lineStyle()); if (page) { page->insertPrimitive(tb); } else { delete tb; } intStretch += intRectHeight; intLineCounter++; } } intStretch += (m_bottomPadding / 100.0); } return intStretch; //Item returns its required section height } diff --git a/src/renderer/KReportView.cpp b/src/renderer/KReportView.cpp index 6825df8b..cf218668 100644 --- a/src/renderer/KReportView.cpp +++ b/src/renderer/KReportView.cpp @@ -1,169 +1,167 @@ /* This file is part of the KDE project Copyright (C) 2015 by Adam Pigg (adam@piggz.co.uk) Copyright (C) 2017 Jarosław Staniek This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "KReportView.h" #include "KReportPage.h" #include "KReportRenderObjects.h" #include "KReportPreRenderer.h" #include "KReportRendererBase.h" #include "kreport_debug.h" #include #include #include #include #include #include -#include -#include #include #include #include //! @internal class Q_DECL_HIDDEN KReportView::Private { public: explicit Private() : reportPage(nullptr) , currentPage(1) , pageCount(0) {} ~Private() {} //! Move to page @a page (counted from 1) void moveToPage(int page) { if (page != currentPage && page >= 1 && page <= pageCount) { currentPage = page; reportPage->renderPage(currentPage); } } QPointer reportDocument; QGraphicsView *reportView; QGraphicsScene *reportScene; KReportPage *reportPage; int currentPage; int pageCount; KReportRendererFactory factory; }; KReportView::KReportView(QWidget *parent) : QWidget(parent), d(new Private()) { setObjectName(QLatin1String("KReportView")); d->reportView = new QGraphicsView(this); // page selector should be always visible: d->reportView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn); QVBoxLayout *l = new QVBoxLayout; l->setMargin(0); setLayout(l); layout()->addWidget(d->reportView); d->reportScene = new QGraphicsScene(this); d->reportScene->setSceneRect(0,0,1000,2000); d->reportView->setScene(d->reportScene); d->reportScene->setBackgroundBrush(palette().brush(QPalette::Dark)); } KReportView::~KReportView() { //kreportDebug(); delete d; } void KReportView::moveToFirstPage() { d->moveToPage(1); } void KReportView::moveToLastPage() { d->moveToPage(d->pageCount); } void KReportView::moveToNextPage() { d->moveToPage(d->currentPage + 1); } void KReportView::moveToPreviousPage() { d->moveToPage(d->currentPage - 1); } void KReportView::moveToPage(int page) { d->moveToPage(page); } int KReportView::currentPage() const { return d->currentPage; } int KReportView::pageCount() const { return d->pageCount; } void KReportView::setDocument(ORODocument* doc) { d->reportDocument = doc; if (d->reportPage) { delete d->reportPage; } d->pageCount = doc->pageCount(); d->reportPage = new KReportPage(this, d->reportDocument); d->reportPage->setObjectName(QLatin1String("KReportPage")); d->reportScene->setSceneRect(0,0,d->reportPage->rect().width() + 40, d->reportPage->rect().height() + 40); d->reportScene->addItem(d->reportPage); d->reportPage->setPos(20,20); d->reportView->centerOn(0,0); } QAbstractScrollArea* KReportView::scrollArea() { return d->reportView; } void KReportView::refreshCurrentPage() { //kreportDebug() << "Refreshing current page" << d->currentPage; if (d->reportPage) { d->reportPage->renderPage(d->currentPage); } }