diff --git a/CMakeLists.txt b/CMakeLists.txt index f3e93852..d60ca37d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,336 +1,347 @@ project(calligraplan) cmake_minimum_required(VERSION 3.0) if (POLICY CMP0002) cmake_policy(SET CMP0002 NEW) endif () if (POLICY CMP0017) cmake_policy(SET CMP0017 NEW) endif () if (POLICY CMP0022) cmake_policy(SET CMP0022 NEW) endif () if (POLICY CMP0026) cmake_policy(SET CMP0026 NEW) endif() if (POLICY CMP0046) cmake_policy(SET CMP0046 NEW) endif () if (POLICY CMP0059) cmake_policy(SET CMP0059 NEW) endif() if (POLICY CMP0063) cmake_policy(SET CMP0063 NEW) endif() if (POLICY CMP0071) cmake_policy(SET CMP0071 NEW) endif() list(APPEND CMAKE_AUTOMOC_MACRO_NAMES "PLAN_SCHEDULERPLUGIN_EXPORT") # define the version of Plan # update these version for every release: set(PLAN_YEAR 2018) # update every year set(PLAN_VERSION_STRING "3.1.89") set(PLAN_STABLE_VERSION_MAJOR 3) # 3 for 3.x, 4 for 4.x, etc. set(PLAN_STABLE_VERSION_MINOR 1) # 0 for 3.0, 1 for 3.1, etc. set(PLAN_VERSION_RELEASE 89) # 89 for Alpha, increase for next test releases, set 0 for first Stable, etc. set(PLAN_ALPHA 1) # uncomment only for Alpha #set(PLAN_BETA 2) # uncomment only for Beta #set(PLAN_RC 1) # uncomment only for RC # Define the generic version of the Calligra Plan libraries here # This makes it easy to advance it when the next release comes. # 14 was the last GENERIC_CALLIGRA_LIB_VERSION_MAJOR of the previous Calligra series # (2.x) so we're starting with 15 in 3.x series. if(PLAN_STABLE_VERSION_MAJOR EQUAL 3) math(EXPR GENERIC_PLAN_LIB_VERSION_MAJOR "${PLAN_STABLE_VERSION_MINOR} + 15") else() # let's make sure we won't forget to update the "15" message(FATAL_ERROR "Reminder: please update offset == 15 used to compute GENERIC_PLAN_LIB_VERSION_MAJOR to something bigger") endif() set(GENERIC_PLAN_LIB_VERSION "${GENERIC_PLAN_LIB_VERSION_MAJOR}.0.0") set(GENERIC_PLAN_LIB_SOVERSION "${GENERIC_PLAN_LIB_VERSION_MAJOR}") message(STATUS "") message(STATUS "Build Calligra Plan ${PLAN_VERSION_STRING} with cmake version: ${CMAKE_VERSION}, required version: ${CMAKE_MINIMUM_REQUIRED_VERSION}") message(STATUS "") # ensure out-of-source build string(COMPARE EQUAL "${CMAKE_SOURCE_DIR}" "${CMAKE_BINARY_DIR}" isBuildInSource) if(isBuildInSource) message(FATAL_ERROR "Compiling Plan inside the source folder is not possible.\nPlease refer to the build instruction: https://community.kde.org/Calligra/Building/3\nYou need to clean up the source folder from all build artifacts just created, otherwise further building attempts will fail again: With a git repo, you can use \"git clean -df\" in the toplevel source folder (attention! will remove also uncommited changes to the source code). With sources from a file bundle (like a zip file), delete the source folder and unbundle the sources again.") endif() ############ ############# ## Options ## ############# ############ option(PACKAGERS_BUILD "Build support of multiple CPU architectures in one binary. Should be used by packagers only." ON) ########################## ########################### ## Look for ECM, Qt, KF5 ## ########################### ########################## find_package(ECM 5.19 REQUIRED NO_MODULE) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${ECM_MODULE_PATH}) # ECM KDE macros (include first, to have their policies and settings effect all other macros) include(KDEInstallDirs) include(KDECMakeSettings NO_POLICY_SCOPE) include(KDECompilerSettings NO_POLICY_SCOPE) # CMake macros include(CMakePackageConfigHelpers) include(WriteBasicConfigVersionFile) include(CheckFunctionExists) include(CheckTypeSize) include(CheckIncludeFile) include(GenerateExportHeader) include(FeatureSummary) # ECM macros include(ECMOptionalAddSubdirectory) include(ECMInstallIcons) include(ECMAddAppIcon) include(ECMSetupVersion) include(ECMAddTests) include(ECMMarkAsTest) include(ECMMarkNonGuiExecutable) include(ECMGenerateHeaders) # Own macros # This macro is a copy from calligra so only needs to be included when plan is build stand alone set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules) include(MacroOptionalFindPackage) set(REQUIRED_KF5_VERSION "5.45.0") find_package(KF5 ${REQUIRED_KF5_VERSION} REQUIRED COMPONENTS Init Archive # Codecs # Completion Config ConfigWidgets CoreAddons DBusAddons # DocTools GuiAddons I18n IconThemes ItemViews JobWidgets KIO Notifications # NotifyConfig Parts # Sonnet TextWidgets WidgetsAddons WindowSystem XmlGui # Kross ) find_package(KF5Activities) set_package_properties(KF5Activities PROPERTIES DESCRIPTION "Library for Activities" PURPOSE "Required for activities support (optional)" TYPE OPTIONAL ) if(KF5Activities_FOUND) set(HAVE_KACTIVITIES TRUE) endif() find_package(KF5KHtml) set_package_properties(KF5KHtml PROPERTIES PURPOSE "Required for rich text support" TYPE REQUIRED ) find_package(KF5Holidays) set_package_properties(KF5Holidays PROPERTIES DESCRIPTION "Library for generation of public holidays" PURPOSE "Required for holidays support (optional)" TYPE RECOMMENDED ) set(REQUIRED_QT_VERSION "5.9.0") find_package(Qt5 ${REQUIRED_QT_VERSION} REQUIRED COMPONENTS Core Gui PrintSupport Test Widgets Xml ) find_package(Qt5DBus ${REQUIRED_QT_VERSION} QUIET) set_package_properties(Qt5DBus PROPERTIES DESCRIPTION "Library for dbus access" PURPOSE "Required for dbus support (optional)" TYPE OPTIONAL ) find_package(X11) if(X11_FOUND) find_package(Qt5 ${REQUIRED_QT_VERSION} REQUIRED COMPONENTS X11Extras ) set(HAVE_X11 TRUE) add_definitions(-DHAVE_X11) else() set(HAVE_X11 FALSE) endif() # use sane compile flags add_definitions( -DQT_USE_QSTRINGBUILDER -DQT_STRICT_ITERATORS -DQT_NO_SIGNALS_SLOTS_KEYWORDS -DQT_NO_URL_CAST_FROM_STRING -DQT_NO_CAST_TO_ASCII ) # only with this definition will all the FOO_TEST_EXPORT macro do something # TODO: check if this can be moved to only those places which make use of it, # to reduce global compiler definitions that would trigger a recompile of # everything on a change (like adding/removing tests to/from the build) if(BUILD_TESTING) add_definitions(-DCOMPILING_TESTS) endif() # overcome some platform incompatibilities if(WIN32) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/winquirks) add_definitions(-D_USE_MATH_DEFINES) add_definitions(-DNOMINMAX) set(WIN32_PLATFORM_NET_LIBS ws2_32.lib netapi32.lib) endif() ########################### ############################ ## Required dependencies ## ############################ ########################### ## ## Test for KGantt ## macro_optional_find_package(KGantt 2.6.0 QUIET) set_package_properties(KGantt PROPERTIES DESCRIPTION "Library for creating Gantt diagrams (part of KDiagram)" URL "https://www.kde.org/" TYPE REQUIRED ) if(KGantt_FOUND) set(KGANTT_VERSION_MAJOR "${KGantt_VERSION_MAJOR}") set(KGANTT_VERSION_MINOR "${KGantt_VERSION_MINOR}") set(KGANTT_VERSION_PATCH "${KGantt_VERSION_PATCH}") endif() ## ## Test for KChart ## macro_optional_find_package(KChart 2.6.0 QUIET) set_package_properties(KChart PROPERTIES DESCRIPTION "Library for creating business charts (part of KDiagram)" URL "https://www.kde.org/" TYPE REQUIRED ) ## ## Test for QCA2 ## macro_optional_find_package(Qca-qt5 2.1.0 QUIET) set_package_properties(Qca-qt5 PROPERTIES DESCRIPTION "Qt Cryptographic Architecture" URL "https:/download.kde.org/stable/qca-qt5" PURPOSE "Required for encrypted OpenDocument files and encrypted xls files support" TYPE OPTIONAL ) find_package(KF5Wallet ${REQUIRED_KF5_VERSION}) if(Qca-qt5_FOUND AND KF5Wallet_FOUND) add_definitions( -DQCA2 ) endif() find_package(Perl REQUIRED) find_package(ZLIB REQUIRED) ########################### ############################ ## Optional dependencies ## ############################ ########################### ### Remove dependency on KF5AkonadiContact ### Review how to get at contacts in more portable way ## ## Test for KF5AkonadiContact ## # find_package(KF5AkonadiContact CONFIG QUIET) # set_package_properties(KF5AkonadiContact PROPERTIES # DESCRIPTION "Library for Accessing Contacts stored in Akonadi" # URL "https://www.kde.org/" # PURPOSE "Required for address book support" # TYPE OPTIONAL # ) +## +## Test for KF5CalendarCore +## +# find_package(KF5CalendarCore CONFIG QUIET) +# set_package_properties(KF5CalendarCore PROPERTIES +# DESCRIPTION "KDE Calendar Library" +# URL "https://www.kde.org/" +# PURPOSE "Optionally used by semantic item Event" +# TYPE OPTIONAL +# ) + if(WIN32) set(LIB_INSTALL_DIR ${LIB_INSTALL_DIR} RUNTIME DESTINATION ${BIN_INSTALL_DIR} LIBRARY ${INSTALL_TARGETS_DEFAULT_ARGS} ARCHIVE ${INSTALL_TARGETS_DEFAULT_ARGS} ) endif() #### Disable kreport for now, reconsider when it is stable #### if (TEST_FOR_KREPORT) # # Test for KReport # macro_optional_find_package(KReport 3.1 QUIET) set_package_properties(KReport PROPERTIES PURPOSE "Required for KReport support in Plan" TYPE OPTIONAL ) ## ## Test for KPropertyWidgets ## macro_optional_find_package(KPropertyWidgets 3.1 QUIET) set_package_properties(KPropertyWidgets PROPERTIES PURPOSE "Required for KReports support in Plan" TYPE OPTIONAL ) if (KReport_FOUND AND KPropertyWidgets_FOUND) set(PLAN_USE_KREPORT TRUE) endif() endif (TEST_FOR_KREPORT) add_subdirectory(src) add_subdirectory(devtools) if (BUILD_TESTING) add_subdirectory(tests) endif() #add_custom_target(apidox doc/api/gendocs.pl WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) ### Summarize findings #### feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES) diff --git a/src/kptmaindocument.h b/src/kptmaindocument.h index 8647c2e5..93b490f8 100644 --- a/src/kptmaindocument.h +++ b/src/kptmaindocument.h @@ -1,267 +1,268 @@ /* This file is part of the KDE project * Copyright (C) 1998, 1999, 2000 Torben Weis * Copyright (C) 2004 - 2010 Dag Andersen * Copyright (C) 2006 Raphael Langerhorst * Copyright (C) 2007 Thorsten Zachmann * Copyright (C) 2019 Dag Andersen * * 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 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 KPTMAINDOCUMENT_H #define KPTMAINDOCUMENT_H #include "plan_export.h" #include "kptpackage.h" #include "kpttask.h" #include "kptconfig.h" #include "kptwbsdefinition.h" #include "kptxmlloaderobject.h" #include "about/aboutpage.h" #include "KoDocument.h" #include #include #define PLAN_MIME_TYPE "application/x-vnd.kde.plan" /// The main namespace. namespace KPlato { class DocumentChild; class Project; class Context; class SchedulerPlugin; class ViewListItem; class View; class Package; class PLAN_EXPORT MainDocument : public KoDocument { Q_OBJECT public: explicit MainDocument(KoPart *part); ~MainDocument(); /// reimplemented from KoDocument virtual QByteArray nativeFormatMimeType() const { return PLAN_MIME_TYPE; } /// reimplemented from KoDocument virtual QByteArray nativeOasisMimeType() const { return ""; } /// reimplemented from KoDocument virtual QStringList extraNativeMimeTypes() const { return QStringList() << PLAN_MIME_TYPE; } void setReadWrite( bool rw ); void configChanged(); virtual void paintContent( QPainter& painter, const QRect& rect); void setProject( Project *project ); + Project *project() const { return m_project; } Project &getProject() { return *m_project; } const Project &getProject() const { return * m_project; } /** * Return the set of SupportedSpecialFormats that the kplato wants to * offer in the "Save" file dialog. * Note: SaveEncrypted is not supported. */ virtual int supportedSpecialFormats() const { return SaveAsDirectoryStore; } // The load and save functions. Look in the file kplato.dtd for info virtual bool loadXML( const KoXmlDocument &document, KoStore *store ); virtual QDomDocument saveXML(); /// Save a workpackage file containing @p node with schedule identity @p id, owned by @p resource QDomDocument saveWorkPackageXML( const Node *node, long id, Resource *resource = 0 ); bool saveOdf( SavingContext &/*documentContext */) { return false; } bool loadOdf( KoOdfReadStore & odfStore ); Config &config() { return m_config; } Context *context() const { return m_context; } WBSDefinition &wbsDefinition() { return m_project->wbsDefinition(); } const XMLLoaderObject &xmlLoader() const { return m_xmlLoader; } DocumentChild *createChild( KoDocument *doc, const QRect &geometry = QRect() ); bool saveWorkPackageToStream( QIODevice * dev, const Node *node, long id, Resource *resource = 0 ); bool saveWorkPackageFormat( const QString &file, const Node *node, long id, Resource *resource = 0 ); bool saveWorkPackageUrl( const QUrl & _url, const Node *node, long id, Resource *resource = 0 ); /// Load the workpackage from @p url into @p project. Return true if successful, else false. bool loadWorkPackage( Project &project, const QUrl &url ); Package *loadWorkPackageXML( Project& project, QIODevice*, const KoXmlDocument& document, const QUrl& url ); QMap workPackages() const { return m_workpackages; } void clearWorkPackages() { qDeleteAll(m_workpackages); m_workpackages.clear(); m_checkingForWorkPackages = false; } void insertFile( const QUrl &url, Node *parent, Node *after = 0 ); bool insertProject( Project &project, Node *parent, Node *after ); bool mergeResources(Project &project); KPlatoAboutPage &aboutPage() { return m_aboutPage; } bool extractFiles( KoStore *store, Package *package ); bool extractFile( KoStore *store, Package *package, const Document *doc ); void registerView( View *view ); /// Create a new project from this project /// Generates new project id and task ids /// Keeps resource- and calendar ids void createNewProject(); bool isTaskModule() const; using KoDocument::setModified; public Q_SLOTS: void setModified( bool mod ); /// Inserts an item into all other views than @p view void insertViewListItem(KPlato::View *view, const KPlato::ViewListItem *item, const KPlato::ViewListItem *parent, int index); /// Removes the view list item from all other views than @p view void removeViewListItem(KPlato::View *view, const KPlato::ViewListItem *item); /// View selector has been modified void slotViewlistModified(); /// Check for workpackages /// If @p keep is true, packages that has been refused will not be checked for again void checkForWorkPackages(bool keep); /// Remove @p package void terminateWorkPackage( const KPlato::Package *package ); void setLoadingTemplate( bool ); void setLoadingSharedResourcesTemplate( bool ); void insertResourcesFile(const QUrl &url, const QUrl &projects = QUrl()); void slotProjectCreated(); /// Prepare for insertion of resource assignments of shared resources from the project(s) in @p urls void insertSharedProjects(const QList &urls); /// Prepare for insertion of resource assignments of shared resources from the project(s) in @p url void insertSharedProjects(const QUrl &url); /// Clear resource assignments of shared resources void clearResourceAssignments(); /// Load resource assignments of shared resources from the project(s) in @p url void loadResourceAssignments(QUrl url); void setIsTaskModule(bool value); void autoCheckForWorkPackages(); Q_SIGNALS: void changed(); void workPackageLoaded(); void viewlistModified( bool ); void viewListItemAdded(const KPlato::ViewListItem *item, const KPlato::ViewListItem *parent, int index); void viewListItemRemoved(const KPlato::ViewListItem *item); void insertSharedProject(); protected: /// Load kplato specific files virtual bool completeLoading( KoStore* store ); /// Save kplato specific files virtual bool completeSaving( KoStore* store ); // used by insert file struct InsertFileInfo { QUrl url; Node *parent; Node *after; } m_insertFileInfo; protected Q_SLOTS: void slotViewDestroyed(); void addSchedulerPlugin(const QString&, KPlato::SchedulerPlugin *plugin); void checkForWorkPackage(); void insertFileCompleted(); void insertResourcesFileCompleted(); void insertFileCancelled( const QString& ); void slotInsertSharedProject(); void insertSharedProjectCompleted(); void insertSharedProjectCancelled( const QString& ); void slotNodeChanged(KPlato::Node*, int); void slotScheduleManagerChanged(KPlato::ScheduleManager *sm, int property); void setCalculationNeeded(); void slotCalculationFinished(KPlato::Project *project, KPlato::ScheduleManager *sm); void slotStartCalculation(); private: bool loadAndParse(KoStore* store, const QString& filename, KoXmlDocument& doc); void loadSchedulerPlugins(); private: Project *m_project; QWidget* m_parentWidget; Config m_config; Context *m_context; XMLLoaderObject m_xmlLoader; bool m_loadingTemplate; bool m_loadingSharedResourcesTemplate; QMap m_schedulerPlugins; QMap m_workpackages; QFileInfoList m_infoList; QList m_skipUrls; QMap m_mergedPackages; KPlatoAboutPage m_aboutPage; QDomDocument m_reports; bool m_viewlistModified; bool m_checkingForWorkPackages; QList > m_views; bool m_loadingSharedProject; QList m_sharedProjectsFiles; bool m_skipSharedProjects; bool m_isTaskModule; KUndo2Command* m_calculationCommand; ScheduleManager* m_currentCalculationManager; ScheduleManager* m_nextCalculationManager; }; } //KPlato namespace #endif diff --git a/src/libs/main/KoDocument.h b/src/libs/main/KoDocument.h index 082f0d8c..bfca7b7a 100644 --- a/src/libs/main/KoDocument.h +++ b/src/libs/main/KoDocument.h @@ -1,814 +1,819 @@ /* This file is part of the KDE project Copyright (C) 1998, 1999 Torben Weis Copyright (C) 2000-2005 David Faure Copyright (C) 2007 Thorsten Zachmann Copyright (C) 2010 Boudewijn Rempt 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 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 KODOCUMENT_H #define KODOCUMENT_H #include #include #include "komain_export.h" #include #include #include class KUndo2Command; class KoPart; class KoStore; class KoDocumentInfo; //class KoDocumentRdf; //class KoDocumentRdfBase; class KoProgressUpdater; class KoProgressProxy; class KoDocumentInfoDlg; class KoUnit; //class KoGridData; //class KoGuidesData; class KoXmlWriter; class QDomDocument; // MSVC seems to need to know the declaration of the classes // we pass references of in, when used by external modules // e.g. // when building chartshapecore.lib, the forward-declaration // approach lead to unresolved externals warnings when it used // the pagelayout functions. // Also when building calligra_shape_formular.dll - FormulaDocument // referenced the same two pagelayout functions incorrectly. #if defined(_WIN32) || defined(_WIN64) #include #else struct KoPageLayout; #endif +namespace KPlato { + class Project; +} + class KoVersionInfo { public: QDateTime date; QString saved_by; QString comment; QString title; QByteArray data; //the content of the compressed version }; /** * The %Calligra document class * * This class provides some functionality each %Calligra document should have. * * @short The %Calligra document class */ class KOMAIN_EXPORT KoDocument : public QObject, public KoDocumentBase { Q_OBJECT Q_PROPERTY(bool backupFile READ backupFile WRITE setBackupFile NOTIFY backupFileChanged) Q_PROPERTY(int pageCount READ pageCount) // clazy:exclude=qproperty-without-notify public: /** * Constructor. * * @param parent The KoPart that owns the document. XXX: should be removed! * @param undoStack accepts the stack for the document. You can create any type of stack if you need. * The stack objects will become owned by the document. This is used by Krita's KisDoc2. The default value for this * parameter is a usual Qt's stack. */ explicit KoDocument(KoPart *parent, KUndo2Stack *undoStack = new KUndo2Stack()); + virtual KPlato::Project *project() const { return nullptr; } /** * Destructor. * * The destructor does not delete any attached KoView objects and it does not * delete the attached widget as returned by widget(). */ virtual ~KoDocument(); /// XXX: Temporary! KoPart *documentPart() const; /** * Reimplemented from KoParts::ReadWritePart for internal reasons * (for the autosave functionality) */ virtual bool openUrl(const QUrl &url); /** * Opens the document given by @p url, without storing the URL * in the KoDocument. * Call this instead of openUrl() to implement KoMainWindow's * File --> Import feature. * * @note This will call openUrl(). To differentiate this from an ordinary * Open operation (in any reimplementation of openUrl() or openFile()) * call isImporting(). */ bool importDocument(const QUrl &url); /** * Saves the document as @p url without changing the state of the * KoDocument (URL, modified flag etc.). Call this instead of * KoParts::ReadWritePart::saveAs() to implement KoMainWindow's * File --> Export feature. * * @note This will call KoDocument::saveAs(). To differentiate this * from an ordinary Save operation (in any reimplementation of * saveFile()) call isExporting(). */ bool exportDocument(const QUrl &url); /** * @brief Sets whether the document can be edited or is read only. * * This recursively applied to all child documents and * KoView::updateReadWrite is called for every attached * view. */ virtual void setReadWrite(bool readwrite = true); /** * To be preferred when a document exists. It is fast when calling * it multiple times since it caches the result that readNativeFormatMimeType() * delivers. * This comes from the X-KDE-NativeMimeType key in the .desktop file. */ virtual QByteArray nativeFormatMimeType() const = 0; /** * Returns the OASIS OpenDocument mimetype of the document, if supported * This comes from the X-KDE-NativeOasisMimeType key in the * desktop file * * @return the oasis mimetype or, if it hasn't one, the nativeformatmimetype. */ virtual QByteArray nativeOasisMimeType() const = 0; /// Checks whether a given mimetype can be handled natively. bool isNativeFormat(const QByteArray& mimetype) const; /// Returns a list of the mimetypes considered "native", i.e. which can /// be saved by KoDocument without a filter, in *addition* to the main one virtual QStringList extraNativeMimeTypes() const = 0; /** * Return the set of SupportedSpecialFormats that the application wants to * offer in the "Save" file dialog. */ virtual int supportedSpecialFormats() const; /** * Returns the actual mimetype of the document */ QByteArray mimeType() const; /** * @brief Sets the mime type for the document. * * When choosing "save as" this is also the mime type * selected by default. */ void setMimeType(const QByteArray & mimeType); /** * @brief Set the format in which the document should be saved. * * This is called on loading, and in "save as", so you shouldn't * have to call it. * * @param mimeType the mime type (format) to use. * @param specialOutputFlag is for "save as older version" etc. */ void setOutputMimeType(const QByteArray & mimeType, int specialOutputFlag = 0); QByteArray outputMimeType() const; int specialOutputFlag() const; /** * Returns true if this document was the result of opening a foreign * file format and if the user hasn't yet saved the document (in any * format). * * Used by KoMainWindow to warn the user when s/he lazily presses * CTRL+S to save in the same foreign format, putting all his/her * formatting at risk (normally an export confirmation only comes up * with Save As). * * @param exporting specifies whether this is the setting for a * File --> Export or File --> Save/Save As operation. */ bool confirmNonNativeSave(const bool exporting) const; void setConfirmNonNativeSave(const bool exporting, const bool on); /** * @return true if saving/exporting should inhibit the option dialog */ bool saveInBatchMode() const; /** * @param batchMode if true, do not show the option dialog when saving or exporting. */ void setSaveInBatchMode(const bool batchMode); /** * Sets the error message to be shown to the user (use i18n()!) * when loading or saving fails. * If you asked the user about something and they chose "Cancel", * set the message to the magic string "USER_CANCELED", to skip the error dialog. */ void setErrorMessage(const QString& errMsg); /** * Return the last error message. Usually KoDocument takes care of * showing it; this method is mostly provided for non-interactive use. */ QString errorMessage() const; /** * Show the last error message in a message box. * The dialog box will mention a loading problem. * openUrl/openFile takes care of doing it, but not loadNativeFormat itself, * so this is often called after loadNativeFormat returned false. */ void showLoadingErrorDialog(); /** * @brief Generates a preview picture of the document * @note The preview is used in the File Dialog and also to create the Thumbnail */ virtual QPixmap generatePreview(const QSize& size); /** * Paints the data itself. * It's this method that %Calligra Parts have to implement. * * @param painter The painter object onto which will be drawn. * @param rect The rect that should be used in the painter object. */ virtual void paintContent(QPainter &painter, const QRect &rect) = 0; /** * Tells the document that its title has been modified, either because * the modified status changes (this is done by setModified() ) or * because the URL or the document-info's title changed. */ void setTitleModified(); /** * @return true if the document is empty. */ virtual bool isEmpty() const; /** * @brief Sets the document to empty. * * Used after loading a template * (which is not empty, but not the user's input). * * @see isEmpty() */ virtual void setEmpty(); /** * @brief Loads a document from a store. * * You should never have to reimplement. * * @param store The store to load from * @param url An internal url, like tar:/1/2 */ virtual bool loadFromStore(KoStore *store, const QString& url); /** * @brief Loads an OASIS document from a store. * This is used for both the main document and embedded objects. */ virtual bool loadOasisFromStore(KoStore *store); /** * @brief Saves a sub-document to a store. * * You should not have to reimplement this. */ virtual bool saveToStore(KoStore *store, const QString& path); /** * Reimplement this method to load the contents of your Calligra document, * from the XML document. This is for the pre-Oasis file format (maindoc.xml). */ virtual bool loadXML(const KoXmlDocument & doc, KoStore *store) = 0; /** * Reimplement this to save the contents of the %Calligra document into * a QDomDocument. The framework takes care of saving it to the store. */ virtual QDomDocument saveXML(); /** * Return a correctly created QDomDocument for this KoDocument, * including processing instruction, complete DOCTYPE tag (with systemId and publicId), and root element. * @param tagName the name of the tag for the root element * @param version the DTD version (usually the application's version). */ QDomDocument createDomDocument(const QString& tagName, const QString& version) const; /** * Return a correctly created QDomDocument for an old (1.3-style) %Calligra document, * including processing instruction, complete DOCTYPE tag (with systemId and publicId), and root element. * This static method can be used e.g. by filters. * @param appName the app's instance name, e.g. words, kspread, kpresenter etc. * @param tagName the name of the tag for the root element, e.g. DOC for words/kpresenter. * @param version the DTD version (usually the application's version). */ static QDomDocument createDomDocument(const QString& appName, const QString& tagName, const QString& version); /** * The first thing to do in loadOasis is get hold of the office:body tag, then its child. * If the child isn't the expected one, the error message can indicate what it is instead. * This method returns a translated name for the type of document, * e.g. i18n("Word Processing") for office:text. */ static QString tagNameToDocumentType(const QString& localName); /** * Loads a document in the native format from a given URL. * Reimplement if your native format isn't XML. * * @param file the file to load - usually KReadOnlyPart::m_file or the result of a filter */ virtual bool loadNativeFormat(const QString & file); /** * Saves the document in native format, to a given file * You should never have to reimplement. * Made public for writing templates. */ virtual bool saveNativeFormat(const QString & file); /** * Saves the document in native ODF format to the given store. */ bool saveNativeFormatODF(KoStore *store, const QByteArray &mimeType); /** * Saves the document in the native format to the given store. */ bool saveNativeFormatCalligra(KoStore *store); /** * Activate/deactivate/configure the autosave feature. * @param delay in seconds, 0 to disable */ void setAutoSave(int delay); /** * Checks whether the document is currently in the process of autosaving */ bool isAutosaving() const; /** * Set whether the next openUrl call should check for an auto-saved file * and offer to open it. This is usually true, but can be turned off * (e.g. for the preview module). This only checks for names auto-saved * files, unnamed auto-saved files are only checked on KoApplication startup. */ void setCheckAutoSaveFile(bool b); /** * Set whether the next openUrl call should show error message boxes in case * of errors. This is usually the case, but e.g. not when generating thumbnail * previews. */ void setAutoErrorHandlingEnabled(bool b); /** * Checks whether error message boxes should be shown. */ bool isAutoErrorHandlingEnabled() const; /** * Retrieve the default value for autosave in seconds. * Called by the applications to use the correct default in their config */ static int defaultAutoSave(); /** * @return the information concerning this document. * @see KoDocumentInfo */ KoDocumentInfo *documentInfo() const; /** * @return the Rdf metadata for this document. * This method should only be used by code that links to * the RDF system and needs full access to the KoDocumentRdf object. * @see KoDocumentRdf */ // KoDocumentRdfBase *documentRdf() const; /** * Replace the current rdf document with the given rdf document. The existing RDF document * will be deleted, and if RDF support is compiled out, KoDocument does not take ownership. * Otherwise, KoDocument will own the rdf document. */ //void setDocumentRdf(KoDocumentRdfBase *rdfDocument); /** * @return the object to report progress to. * One can add more KoUpdaters to it to make the progress reporting more * accurate. If no active progress reporter is present, 0 is returned. **/ KoProgressUpdater *progressUpdater() const; /** * Set a custom progress proxy to use to report loading * progress to. */ void setProgressProxy(KoProgressProxy *progressProxy); KoProgressProxy* progressProxy() const; /** * Return true if url() is a real filename, false if url() is * an internal url in the store, like "tar:/..." */ virtual bool isStoredExtern() const; /** * @return the page layout associated with this document (margins, pageSize, etc). * Override this if you want to provide different sized pages. * * @see KoPageLayout */ virtual KoPageLayout pageLayout(int pageNumber = 0) const; virtual void setPageLayout(const KoPageLayout &pageLayout); /** * Performs a cleanup of unneeded backup files */ void removeAutoSaveFiles(); void setBackupFile(bool _b); bool backupFile()const; /** * Returns true if this document or any of its internal child documents are modified. */ Q_INVOKABLE bool isModified() const; /** * Returns true during loading (openUrl can be asynchronous) */ bool isLoading() const; int queryCloseDia(); /** * Sets the backup path of the document */ void setBackupPath(const QString & _path); /** * @return path to the backup document */ QString backupPath()const; /** * @return caption of the document * * Caption is of the form "[title] - [url]", * built out of the document info (title) and pretty-printed * document URL. * If the title is not present, only the URL it returned. */ QString caption() const; /** * Sets the document URL to empty URL * KParts doesn't allow this, but %Calligra apps have e.g. templates * After using loadNativeFormat on a template, one wants * to set the url to QUrl() */ void resetURL(); /** * Set when you want an external embedded document to be stored internally */ void setStoreInternal(bool i); /** * @return true when external embedded documents are stored internally */ bool storeInternal() const; bool hasExternURL() const; /** * @internal (public for KoMainWindow) */ void setMimeTypeAfterLoading(const QString& mimeType); /** * @return returns the number of pages in the document. */ virtual int pageCount() const; /** * Returns the unit used to display all measures/distances. */ KoUnit unit() const; /** * Sets the unit used to display all measures/distances. */ void setUnit(const KoUnit &unit); /** * Save the unit to the settings writer * * @param settingsWriter */ void saveUnitOdf(KoXmlWriter *settingsWriter) const; QList &versionList(); bool loadNativeFormatFromStore(QByteArray &data); /** * Adds a new version and then saves the whole document. * @param comment the comment for the version * @return true on success, otherwise false */ bool addVersion(const QString& comment); /// return the grid data for this document. // KoGridData &gridData(); /// returns the guides data for this document. // KoGuidesData &guidesData(); void clearUndoHistory(); /** * Sets the modified flag on the document. This means that it has * to be saved or not before deleting it. */ Q_INVOKABLE virtual void setModified(bool _mod); /** * Initialize an empty document using default values */ virtual void initEmpty(); /** * Returns the global undo stack */ KUndo2Stack *undoStack(); /** * Set the output stream to report profile information to. */ void setProfileStream(QTextStream *profilestream); /** * Set the output stream to report profile information to. */ void setProfileReferenceTime(const QTime& referenceTime); /// If set, the document shall be saved even if it is not marked as modified. /// @see setAlwaysAllowSaving() bool alwaysAllowSaving() const; /// Set alwaysAllowSaving to @p allow. /// Enables applications to always allow saving even when document is not modified. /// This makes it possible to save settings/context info without marking /// the document as modified. /// @see alwaysAllowSaving() void setAlwaysAllowSaving(bool allow); public Q_SLOTS: /** * Adds a command to the undo stack and executes it by calling the redo() function. * @param command command to add to the undo stack */ virtual void addCommand(KUndo2Command *command); /** * Begins recording of a macro command. At the end endMacro needs to be called. * @param text command description */ virtual void beginMacro(const KUndo2MagicString &text); /** * Ends the recording of a macro command. */ virtual void endMacro(); Q_SIGNALS: /** * This signal is emitted when the unit is changed by setUnit(). * It is common to connect views to it, in order to change the displayed units * (e.g. in the rulers) */ void unitChanged(const KoUnit &unit); /** * Progress info while loading or saving. The value is in percents (i.e. a number between 0 and 100) * Your KoDocument-derived class should emit the signal now and then during load/save. * KoMainWindow will take care of displaying a progress bar automatically. */ void sigProgress(int value); /** * Emitted e.g. at the beginning of a save operation * This is emitted by KoDocument and used by KoView to display a statusbar message */ void statusBarMessage(const QString& text); /** * Emitted e.g. at the end of a save operation * This is emitted by KoDocument and used by KoView to clear the statusbar message */ void clearStatusBarMessage(); /** * Emitted when the document is modified */ void modified(bool); void titleModified(const QString &caption, bool isModified); void backupFileChanged(bool); protected: friend class KoPart; /** * Generate a name for the document. */ QString newObjectName(); QString autoSaveFile(const QString & path) const; void setDisregardAutosaveFailure(bool disregardFailure); /** * Loads a document from KReadOnlyPart::m_file (KParts takes care of downloading * remote documents). * Applies a filter if necessary, and calls loadNativeFormat in any case * You should not have to reimplement, except for very special cases. * * NOTE: this method also creates a new KoView instance! * * This method is called from the KReadOnlyPart::openUrl method. */ virtual bool openFile(); /** * This method is called by @a openFile() to allow applications to setup there * own KoProgressUpdater-subTasks which are then taken into account for the * displayed progressbar during loading. */ virtual void setupOpenFileSubProgress(); /** * Saves a document to KReadOnlyPart::m_file (KParts takes care of uploading * remote documents) * Applies a filter if necessary, and calls saveNativeFormat in any case * You should not have to reimplement, except for very special cases. */ virtual bool saveFile(); /** * Overload this function if you have to load additional files * from a store. This function is called after loadXML() * and after loadChildren() have been called. */ virtual bool completeLoading(KoStore *store); /** * If you want to write additional files to a store, * then you must do it here. * In the implementation, you should prepend the document * url (using url().url()) before the filename, so that everything is kept relative * to this document. For instance it will produce urls such as * tar:/1/pictures/picture0.png, if the doc url is tar:/1 * But do this ONLY if the document is not stored extern (see isStoredExtern() ). * If it is, then the pictures should be saved to tar:/pictures. */ virtual bool completeSaving(KoStore *store); /** @internal */ virtual void setModified(); /** * Returns whether or not the current openUrl() or openFile() call is * actually an import operation (like File --> Import). * This is for informational purposes only. */ bool isImporting() const; /** * Returns whether or not the current saveFile() call is actually an export * operation (like File --> Export). * If this function returns true during saveFile() and you are changing * some sort of state, you _must_ restore it before the end of saveFile(); * otherwise, File --> Export will not work properly. */ bool isExporting() const; public: QString localFilePath() const; void setLocalFilePath( const QString &localFilePath ); virtual KoDocumentInfoDlg* createDocumentInfoDialog(QWidget *parent, KoDocumentInfo *docInfo) const; bool isReadWrite() const; QUrl url() const; void setUrl(const QUrl &url); virtual bool closeUrl(bool promptToSave = true); virtual bool saveAs( const QUrl &url ); public Q_SLOTS: virtual bool save(); bool waitSaveComplete(); Q_SIGNALS: void completed(); void canceled(const QString &); private Q_SLOTS: void slotAutoSave(); /// Called by the undo stack when undo or redo is called void slotUndoStackIndexChanged(int idx); protected: bool oldLoadAndParse(KoStore *store, const QString& filename, KoXmlDocument& doc); private: bool saveToStream(QIODevice *dev); QString checkImageMimeTypes(const QString &mimeType, const QUrl &url) const; bool loadNativeFormatFromStore(const QString& file); bool loadNativeFormatFromStoreInternal(KoStore *store); bool savePreview(KoStore *store); bool saveOasisPreview(KoStore *store, KoXmlWriter *manifestWriter); QString prettyPathOrUrl() const; bool queryClose(); bool saveToUrl(); bool openUrlInternal(const QUrl &url); void abortLoad(); class Private; Private *const d; Q_PRIVATE_SLOT(d, void _k_slotJobFinished( KJob * job )) Q_PRIVATE_SLOT(d, void _k_slotStatJobFinished(KJob*)) Q_PRIVATE_SLOT(d, void _k_slotGotMimeType(KIO::Job *job, const QString &mime)) Q_PRIVATE_SLOT(d, void _k_slotUploadFinished( KJob * job )) }; Q_DECLARE_METATYPE(KoDocument*) #endif diff --git a/src/plugins/filters/icalendar/export/CMakeLists.txt b/src/plugins/filters/icalendar/export/CMakeLists.txt index 6232e786..4dc4b52e 100644 --- a/src/plugins/filters/icalendar/export/CMakeLists.txt +++ b/src/plugins/filters/icalendar/export/CMakeLists.txt @@ -1,31 +1,35 @@ include_directories( ${CMAKE_CURRENT_BINARY_DIR} ${PLAN_SOURCE_DIR} ${PLANKERNEL_INCLUDES} ${PLANUI_INCLUDES} ${PLANMAIN_INCLUDES} ) set(icalendarexport_SRCS icalendarexport.cpp ICalExportDialog.cpp ) ki18n_wrap_ui(icalendarexport_SRCS ICalExportDialog.ui ) add_library(planicalexport MODULE ${icalendarexport_SRCS}) #calligraplan_filter_desktop_to_json(planicalexport plan_icalendar_export.desktop) if(${KF5_VERSION} VERSION_LESS "5.16.0") kcoreaddons_desktop_to_json(planicalexport plan_icalendar_export.desktop) else() kcoreaddons_desktop_to_json(planicalexport plan_icalendar_export.desktop SERVICE_TYPES ${PLAN_SOURCE_DIR}/servicetypes/calligraplan_filter.desktop ) endif() target_link_libraries(planicalexport planprivate plankernel planmain) +if (KF5CalendarCore_FOUND) + target_link_libraries(planicalexport KF5::CalendarCore) +endif() + install(TARGETS planicalexport DESTINATION ${PLUGIN_INSTALL_DIR}/calligraplan/formatfilters) diff --git a/src/plugins/filters/icalendar/export/icalendarexport.cpp b/src/plugins/filters/icalendar/export/icalendarexport.cpp index bb6b097d..8f6f09ef 100644 --- a/src/plugins/filters/icalendar/export/icalendarexport.cpp +++ b/src/plugins/filters/icalendar/export/icalendarexport.cpp @@ -1,426 +1,427 @@ /* This file is part of the KDE project * Copyright (C) 2009, 2011, 2012 Dag Andersen * Copyright (C) 2019 Dag Andersen * * 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 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. */ // clazy:excludeall=qstring-arg #include "icalendarexport.h" #include "ICalExportDialog.h" #include "config.h" #include #include #include #include #include #include "kptdebug.h" #if 0 #include #include #include #include #include #endif #include #include #include #include #include #include #include #include #include using namespace KPlato; K_PLUGIN_FACTORY_WITH_JSON(ICalendarExportFactory, "plan_icalendar_export.json", registerPlugin();) #ifdef HAVE_QDATETIME_KCALCORE #define KQDT QDateTime #else #define KQDT KDateTime #endif const QLoggingCategory &PLAN_ICAL_EXPORT_LOG() { static const QLoggingCategory category("calligra.plan.ical.export"); return category; } #define debugPlanICalExport qCDebug(PLAN_ICAL_EXPORT_LOG)<manager() ) { batch = m_chain->manager()->getBatchMode(); } if ( batch ) { //TODO debugPlanICalExport<<"batch"; return KoFilter::UsageError; } debugPlanICalExport<<"online:"<inputDocument(); - MainDocument *doc = dynamic_cast( m_chain->inputDocument() ); - if (doc == 0) { + KoDocument *doc = m_chain->inputDocument(); + if (!doc || !doc->project()) { errorPlan << "Cannot open Plan document"; return KoFilter::InternalError; } if (m_chain->outputFile().isEmpty()) { errorPlan << "Output filename is empty"; return KoFilter::InternalError; } QFile file(m_chain->outputFile()); if (! file.open(QIODevice::WriteOnly)) { errorPlan << "Failed to open output file:" << file.fileName(); return KoFilter::StorageCreationError; } QApplication::restoreOverrideCursor(); - ICalExportDialog dlg(doc->getProject()); + ICalExportDialog dlg(*doc->project()); if (dlg.exec() != QDialog::Accepted) { QApplication::setOverrideCursor(Qt::WaitCursor); return KoFilter::UserCancelled; } QApplication::setOverrideCursor( Qt::WaitCursor ); m_scheduleId = dlg.scheduleId(); m_includeProject = dlg.includeProject(); m_includeSummarytasks = dlg.includeSummarytasks(); - KoFilter::ConversionStatus status = convert(doc->getProject(), file); + KoFilter::ConversionStatus status = convert(*doc->project(), file); file.close(); debugPlanICalExport<<"Finished with status:"<resources()) { if (r->type() == Resource::Type_Work) { s += QString("ATTENDEE;CN=") + r->name() + "\r\n\t"; s += QString(";RSVP=FALSE;PARTSTAT=NEEDS-ACTION;ROLE=REQ-PARTICIPANT;") + "\r\n\t"; s += QString("CUTYPE=INDIVIDUAL;") + "\r\n\t"; s += QString("X-UID=") + r->id(); s += ":MAILTO:" + r->email() + "\r\n"; } } } else { const QList lst = static_cast(node).requestedResources(); foreach(const Resource *r, lst) { if (r->type() == Resource::Type_Work) { s += QString("ATTENDEE;CN=") + r->name() + "\r\n\t"; s += QString(";RSVP=FALSE;PARTSTAT=NEEDS-ACTION;ROLE=REQ-PARTICIPANT;") + "\r\n\t"; s += QString("CUTYPE=INDIVIDUAL;") + "\r\n\t"; s += QString("X-UID=") + r->id(); s += ":MAILTO:" + r->email() + "\r\n"; } } } return s; } QString doAttachment(const Documents &docs) { QString s; foreach(const Document *doc, docs.documents()) { s += QString("ATTACH:") + doc->url().url() + "\r\n"; } return s; } void escape(QString &txt) { txt.replace('\\', "\\\\"); txt.replace('\n', "\\n"); txt.replace(',', "\\,"); txt.replace(':', "\\:"); txt.replace(';', "\\;"); } QString ICalendarExport::doDescription(const QString &description) { QTextEdit te; te.setHtml(description); QString txt = te.toPlainText().trimmed(); QString s; if (!txt.isEmpty()) { s = QString("DESCRIPTION") + QString::number(m_descriptions.count()) + ':' + "\r\n"; escape(txt); m_descriptions << txt; txt = description; txt.remove('\n'); txt.remove('\r'); // in case... escape(txt); s += QString("X-ALT-DESC;FMTTYPE=text/html:") + txt + "\r\n"; } return s; } QString ICalendarExport::createTodo(const Node &node, long sid) { QString s; s += QString("BEGIN:VTODO") + "\r\n"; QString txt = node.name(); escape(txt); s += QString("SUMMARY:") + txt + "\r\n"; s += doDescription(node.description()); s += QString("UID:") + node.id() + "\r\n"; s += QString("DTSTAMP:") + dtToString(QDateTime::currentDateTime()) + "\r\n"; s += QString("CREATED:") + dtToString(QDateTime::currentDateTime()) + "\r\n"; s += QString("LAST-MODIFIED:") + dtToString(QDateTime::currentDateTime()) + "\r\n"; s += QString("CATEGORIES:Plan") + "\r\n"; DateTime dt = node.startTime(sid); if (dt.isValid()) { s += QString("DTSTART:") + dtToString(dt) + "\r\n"; } dt = node.endTime(sid); if (dt.isValid()) { s += QString("DUE:") + dtToString(dt) + "\r\n"; } if (node.parentNode()) { if (m_includeSummarytasks && node.parentNode()->type() == Node::Type_Summarytask) { s += QString("RELATED-TO:") + node.parentNode()->id() + "\r\n"; } else if (m_includeProject) { s += QString("RELATED-TO:") + node.projectNode()->id() + "\r\n"; } } if (node.type() == Node::Type_Task) { s += QString("PERCENT-COMPLETE:") + QString::number(static_cast(node).completion().percentFinished()) + "\r\n"; s += doAttendees(node, sid); } else if (node.type() == Node::Type_Milestone) { s += QString("PERCENT-COMPLETE:") + QString::number(static_cast(node).completion().percentFinished()) + "\r\n"; } else if (node.type() == Node::Type_Project) { if (!node.leader().isEmpty()) { s += QString("ORGANIZER:") + node.leader() + "\r\n"; } } s += doAttachment(node.documents()); s += QString("END:VTODO") + "\r\n"; return s; } QString ICalendarExport::doNode(const Node *node, long sid) { QString s; bool create = true; if (node->type() == Node::Type_Project) { create = m_includeProject; } else if (node->type() == Node::Type_Summarytask) { create = m_includeSummarytasks; } debugPlanICalExport<numChildren(); ++i) { s += doNode(node->childNode(i), sid); } return s; } void foldData(QString &data) { int count = 0; // bytecount for (int i = 0; i < data.length() - 6; ++i) { if (data.at(i) == '\r' && data.at(i+1) == '\n') { count = 0; ++i; // skip past LF continue; } if (count >= 70) { data.insert(i, "\r\n\t"); count = 0; i += 2; // skip past CRLFTAB continue; } // we count bytes, so need to know bytesize of character count += QByteArray::fromStdString(QString(data.at(i)).toStdString()).size(); } // remove any empty lines (not allowed) while (data.contains("\r\n\r\n")) { data.replace("\r\n\r\n", "\r\n"); } } KoFilter::ConversionStatus ICalendarExport::convert(const Project &project, QFile &file) { long sid = m_scheduleId; QString data = beginCalendar(); data += doNode(&project, sid); data += endCalendar(); foldData(data); for (int i = 0; i < m_descriptions.count(); ++i) { QString rs = QString("DESCRIPTION") + QString::number(i) + ':'; QString s = QString("DESCRIPTION:") + m_descriptions.at(i); foldData(s); data.replace(rs, s); } qint64 n = file.write(data.toUtf8()); if (n < 0) { return KoFilter::InternalError; } return KoFilter::OK; } -#if 0 +#else KoFilter::ConversionStatus ICalendarExport::convert(const Project &project, QFile &file) { KCalCore::Calendar::Ptr cal(new KCalCore::MemoryCalendar("UTC")); //TODO: schedule selection dialog long id = ANYSCHEDULED; bool baselined = project.isBaselined(id); QList lst = project.allScheduleManagers(); foreach(const ScheduleManager *m, lst) { if (! baselined) { id = lst.last()->scheduleId(); //debugPlanICalExport<<"last:"<isBaselined()) { id = m->scheduleId(); //debugPlanICalExport<<"baselined:"<setUid( node->id() ); todo->setSummary(node->name()); todo->setDescription(node->description()); todo->setCategories(QLatin1String("Plan")); if (! node->projectNode()->leader().isEmpty()) { todo->setOrganizer(node->projectNode()->leader()); } if ( node->type() != Node::Type_Project && ! node->leader().isEmpty()) { #if KCALCORE_VERSION >= QT_VERSION_CHECK(5, 11, 80) KCalCore::Person p = KCalCore::Person::fromFullName(node->leader()); KCalCore::Attendee a(p.name(), p.email()); a.setRole(KCalCore::Attendee::NonParticipant); #else KCalCore::Person::Ptr p = KCalCore::Person::fromFullName(node->leader()); KCalCore::Attendee::Ptr a(new KCalCore::Attendee(p->name(), p->email())); a->setRole(KCalCore::Attendee::NonParticipant); #endif todo->addAttendee(a); } DateTime st = node->startTime(id); DateTime et = node->endTime(id); if (st.isValid()) { todo->setDtStart( KQDT( st ) ); } if (et.isValid()) { todo->setDtDue( KQDT( et ) ); } if (node->type() == Node::Type_Task) { const Task *task = qobject_cast(const_cast(node)); Schedule *s = task->schedule(id); if (id < 0 || s == 0) { // Not scheduled, use requests const QList lst = task->requestedResources(); foreach(const Resource *r, lst) { if (r->type() == Resource::Type_Work) { #if KCALCORE_VERSION >= QT_VERSION_CHECK(5, 11, 80) todo->addAttendee(KCalCore::Attendee(r->name(), r->email())); #else todo->addAttendee(KCalCore::Attendee::Ptr(new KCalCore::Attendee(r->name(), r->email()))); #endif } } } else { foreach(const Resource *r, s->resources()) { if (r->type() == Resource::Type_Work) { #if KCALCORE_VERSION >= QT_VERSION_CHECK(5, 11, 80) todo->addAttendee(KCalCore::Attendee(r->name(), r->email())); #else todo->addAttendee(KCalCore::Attendee::Ptr(new KCalCore::Attendee(r->name(), r->email()))); #endif } } } } else if (node->type() == Node::Type_Milestone) { const Task *task = qobject_cast(const_cast(node)); todo->setDtStart(KQDT()); todo->setPercentComplete(task->completion().percentFinished()); } foreach(const Document *doc, node->documents().documents()) { #if KCALCORE_VERSION >= QT_VERSION_CHECK(5, 11, 80) todo->addAttachment(KCalCore::Attachment(doc->url().url())); #else todo->addAttachment(KCalCore::Attachment::Ptr(new KCalCore::Attachment(doc->url().url()))); #endif } if (! parent.isNull()) { todo->setRelatedTo(parent->uid(), KCalCore::Incidence::RelTypeParent); } cal->addTodo(todo); foreach(const Node *n, node->childNodeIterator()) { createTodos(cal, n, id, todo); } } #endif #include "icalendarexport.moc" diff --git a/src/plugins/filters/icalendar/export/icalendarexport.h b/src/plugins/filters/icalendar/export/icalendarexport.h index c3f27e35..36c03eac 100644 --- a/src/plugins/filters/icalendar/export/icalendarexport.h +++ b/src/plugins/filters/icalendar/export/icalendarexport.h @@ -1,72 +1,75 @@ /* This file is part of the KDE project * Copyright (C) 2009 Dag Andersen * Copyright (C) 2019 Dag Andersen * * 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 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 ICALENDAREXPORT_H #define ICALENDAREXPORT_H #include -#if 0 +//#define USE_KCALCORE + +#ifdef USE_KCALCORE #include #endif #include #include class QFile; class QByteArray; + namespace KPlato { class Project; class Node; } class ICalendarExport : public KoFilter { Q_OBJECT public: ICalendarExport(QObject* parent, const QVariantList &); virtual ~ICalendarExport() {} virtual KoFilter::ConversionStatus convert(const QByteArray& from, const QByteArray& to); protected: KoFilter::ConversionStatus convert(const KPlato::Project &project, QFile &file); -#if 0 +#ifdef USE_KCALCORE void createTodos(KCalCore::Calendar::Ptr cal, const KPlato::Node *node, long id, KCalCore::Todo::Ptr parent = KCalCore::Todo::Ptr()); #endif private: QString doNode(const KPlato::Node *node, long sid); QString createTodo(const KPlato::Node &node, long sid); QString doDescription(const QString &description); private: long m_scheduleId; bool m_includeProject; bool m_includeSummarytasks; QList m_descriptions; }; #endif // ICALENDAREXPORT_H