qgsabstractreportsection.h 11.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388
/***************************************************************************
                             qgsabstractreportsection.h
                             ---------------------------
    begin                : December 2017
    copyright            : (C) 2017 by Nyall Dawson
    email                : nyall dot dawson at gmail dot com
 ***************************************************************************/
/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/
#ifndef QGSABSTRACTREPORTSECTION_H
#define QGSABSTRACTREPORTSECTION_H

#include "qgis_core.h"
#include "qgsabstractlayoutiterator.h"
#include "qgslayoutreportcontext.h"
#include "qgsvectorlayerref.h"


///@cond NOT_STABLE

// This is not considered stable API - it is exposed to python bindings only for unit testing!

/**
 * \ingroup core
 * \class QgsReportSectionContext
 * \brief Current context for a report section.
 * \warning This is not considered stable API, and may change in future QGIS releases. It is
 * exposed to the Python bindings for unit testing purposes only.
 * \since QGIS 3.0
 */
class CORE_EXPORT QgsReportSectionContext
{
  public:

    //! Current feature
    QgsFeature feature;

    //! Current coverage layer
    QgsVectorLayer *currentLayer = nullptr;

    //! Current field filters
    QVariantMap fieldFilters;
};

/**
 * \ingroup core
 * \class QgsAbstractReportSection
 * \brief An abstract base class for QgsReport subsections.
 * \warning This is not considered stable API, and may change in future QGIS releases. It is
 * exposed to the Python bindings for unit testing purposes only.
 * \since QGIS 3.0
 */
class CORE_EXPORT QgsAbstractReportSection : public QgsAbstractLayoutIterator
{

#ifdef SIP_RUN
    SIP_CONVERT_TO_SUBCLASS_CODE
    if ( dynamic_cast< QgsReportSectionFieldGroup * >( sipCpp ) )
      sipType = sipType_QgsReportSectionFieldGroup;
    else if ( dynamic_cast< QgsReportSectionLayout * >( sipCpp ) )
      sipType = sipType_QgsReportSectionLayout;
    else
      sipType = NULL;
    SIP_END
#endif

  public:

    /**
     * Constructor for QgsAbstractReportSection, attached to the specified \a parent section.
     * Note that ownership is not transferred to \a parent.
     */
    QgsAbstractReportSection( QgsAbstractReportSection *parentSection = nullptr );

    ~QgsAbstractReportSection() override;

    //! QgsAbstractReportSection cannot be copied
    QgsAbstractReportSection( const QgsAbstractReportSection &other ) = delete;

    //! QgsAbstractReportSection cannot be copied
    QgsAbstractReportSection &operator=( const QgsAbstractReportSection &other ) = delete;

    /**
     * Returns the section subclass type.
     */
    virtual QString type() const = 0;

    /**
     * Returns a user-visible, translated description of the section.
     */
    virtual QString description() const = 0;

    /**
     * Returns an icon representing the section.
     */
    virtual QIcon icon() const = 0;

    /**
     * Clones the report section. Ownership of the returned section is
     * transferred to the caller.
     *
     * Subclasses should call copyCommonProperties() in their clone()
     * implementations.
     */
    virtual QgsAbstractReportSection *clone() const = 0 SIP_FACTORY;

    /**
     * Returns the parent report section.
     */
    QgsAbstractReportSection *parentSection() { return mParent; }

    /**
     * Returns the associated project.
     */
    QgsProject *project();

    // TODO - how to handle this?
    int count() const override { return -1; }

    QString filePath( const QString &baseFilePath, const QString &extension ) override;
    QgsLayout *layout() override;
    bool beginRender() override;
    bool next() override;
    bool endRender() override;

    /**
     * Resets the section, ready for a new iteration.
     */
    virtual void reset();

    /**
     * Called just before rendering the section's header. Should return TRUE if the header
     * is to be included for this section, or FALSE to skip the header for the current
     * section.
     * \see prepareFooter()
     */
    virtual bool prepareHeader();

    /**
     * Called just before rendering the section's footer. Should return TRUE if the footer
     * is to be included for this section, or FALSE to skip the footerfor the current
     * section.
     * \see prepareHeader()
     */
    virtual bool prepareFooter();

    /**
     * Returns the next body layout to export, or NULLPTR if
     * no body layout is required this iteration.
     *
     * \a ok will be set to FALSE if no bodies remain for this section.
     */
    virtual QgsLayout *nextBody( bool &ok SIP_OUT ) { ok = false; return nullptr; }

    /**
     * Returns TRUE if the header for the section is enabled.
     * \see setHeaderEnabled()
     * \see header()
     * \see setHeader()
     */
    bool headerEnabled() const { return mHeaderEnabled; }

    /**
     * Sets whether the header for the section is \a enabled.
     * \see headerEnabled()
     * \see header()
     * \see setHeader()
     */
    void setHeaderEnabled( bool enabled ) { mHeaderEnabled = enabled; }

    /**
     * Returns the header for the section. Note that the header is only
     * included if headerEnabled() is TRUE.
     * \see setHeaderEnabled()
     * \see headerEnabled()
     * \see setHeader()
     */
    QgsLayout *header() { return mHeader.get(); }

    /**
     * Sets the \a header for the section. Note that the header is only
     * included if headerEnabled() is TRUE. Ownership of \a header
     * is transferred to the report section.
     * \see setHeaderEnabled()
     * \see headerEnabled()
     * \see header()
     */
    void setHeader( QgsLayout *header SIP_TRANSFER );

    /**
     * Returns TRUE if the footer for the section is enabled.
     * \see setFooterEnabled()
     * \see footer()
     * \see setFooter()
     */
    bool footerEnabled() const { return mFooterEnabled; }

    /**
     * Sets whether the footer for the section is \a enabled.
     * \see footerEnabled()
     * \see footer()
     * \see setFooter()
     */
    void setFooterEnabled( bool enabled ) { mFooterEnabled = enabled; }

    /**
     * Returns the footer for the section. Note that the footer is only
     * included if footerEnabled() is TRUE.
     * \see setFooterEnabled()
     * \see footerEnabled()
     * \see setFooter()
     */
    QgsLayout *footer() { return mFooter.get(); }

    /**
     * Sets the \a footer for the section. Note that the footer is only
     * included if footerEnabled() is TRUE. Ownership of \a footer
     * is transferred to the report section.
     * \see setFooterEnabled()
     * \see footerEnabled()
     * \see footer()
     */
    void setFooter( QgsLayout *footer SIP_TRANSFER );

    /**
     * Returns the number of child sections for this report section. The child
     * sections form the body of the report section.
     * \see children()
     */
    int childCount() const { return mChildren.count(); }

    /**
     * Returns the row number of the section within it's parent section.
     */
    int row() const;

    /**
     * Returns all child sections for this report section. The child
     * sections form the body of the report section.
     * \see childCount()
     * \see child()
     * \see appendChild()
     * \see insertChild()
     * \see removeChild()
     */
    QList< QgsAbstractReportSection * > childSections() const { return mChildren; }

    /**
     * Returns the child section at the specified \a index.
     * \see children()
     */
    QgsAbstractReportSection *childSection( int index );

    /**
     * Adds a child \a section, transferring ownership of the section to this section.
     * \see children()
     * \see insertChild()
     */
    void appendChild( QgsAbstractReportSection *section SIP_TRANSFER );

    /**
     * Inserts a child \a section at the specified \a index, transferring ownership of the section to this section.
     * \see children()
     * \see appendChild()
     */
    void insertChild( int index, QgsAbstractReportSection *section SIP_TRANSFER );

    /**
     * Removes a child \a section, deleting it.
     * \see children()
     */
    void removeChild( QgsAbstractReportSection *section );

    /**
     * Removes the child section at the specified \a index, deleting it.
     * \see children()
     */
    void removeChildAt( int index );

    /**
     * Sets the current \a context for this section.
     * \see context()
     */
    void setContext( const QgsReportSectionContext &context );

    /**
     * Returns the current context for this section.
     * \see setContext()
     */
    const QgsReportSectionContext &context() const { return mContext; }

    /**
     * Stores the section state in a DOM element.
     * \see readXml()
     */
    bool writeXml( QDomElement &parentElement, QDomDocument &document, const QgsReadWriteContext &context ) const;

    /**
     * Sets the item state from a DOM element.
     * \see writeXml()
     */
    bool readXml( const QDomElement &sectionElement, const QDomDocument &document, const QgsReadWriteContext &context );

    /**
     * Refreshes the section when global layout related options change.
     */
    virtual void reloadSettings();

    /**
     * Accepts the specified style entity \a visitor, causing it to visit all style entities associated
     * with the report.
     *
     * Returns TRUE if the visitor should continue visiting other objects, or FALSE if visiting
     * should be canceled.
     *
     * \since QGIS 3.10
     */
    bool accept( QgsStyleEntityVisitorInterface *visitor ) const;

  protected:

    //! Report sub-sections
    enum SubSection
    {
      Header, //!< Header for section
      Body, //!< Body of section
      Children, //!< Child sections
      Footer, //!< Footer for section
      End, //!< End of section (i.e. past all available content)
    };

    /**
     * Copies the common properties of a report section to a \a destination section.
     * This method should be called from clone() implementations.
     */
    void copyCommonProperties( QgsAbstractReportSection *destination ) const;

    /**
     * Sets the \a parent report section.
     */
    virtual void setParentSection( QgsAbstractReportSection *parent ) { mParent = parent; }

    /**
     * Stores section state within an XML DOM element.
     * \see writeXml()
     * \see readPropertiesFromElement()
     */
    virtual bool writePropertiesToElement( QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context ) const;

    /**
     * Sets section state from a DOM element.
     * \see writePropertiesToElement()
     * \see readXml()
     */
    virtual bool readPropertiesFromElement( const QDomElement &element, const QDomDocument &document, const QgsReadWriteContext &context );

  private:

    QgsAbstractReportSection *mParent = nullptr;

    int mSectionNumber = 0;
    SubSection mNextSection = Header;
    int mNextChild = 0;
    QgsLayout *mCurrentLayout = nullptr;

    bool mHeaderEnabled = false;
    bool mFooterEnabled = false;
    std::unique_ptr< QgsLayout > mHeader;
    std::unique_ptr< QgsLayout > mFooter;

    QList< QgsAbstractReportSection * > mChildren;

    QgsReportSectionContext mContext;

#ifdef SIP_RUN
    QgsAbstractReportSection( const QgsAbstractReportSection &other );
#endif
};

///@endcond

#endif //QGSABSTRACTREPORTSECTION_H