File indexing completed on 2024-12-15 04:54:41

0001 /******************************************************************************
0002  *
0003  *  SPDX-FileCopyrightText: 2008 Szymon Tomasz Stefanek <pragma@kvirc.net>
0004  *
0005  *  SPDX-License-Identifier: GPL-2.0-or-later
0006  *
0007  *******************************************************************************/
0008 
0009 #pragma once
0010 
0011 #include <QColor>
0012 #include <QList>
0013 #include <QPair>
0014 #include <QString>
0015 
0016 #include "core/optionset.h"
0017 #include "core/sortorder.h"
0018 
0019 class QPixmap;
0020 
0021 namespace MessageList
0022 {
0023 namespace Core
0024 {
0025 /**
0026  * The Theme class defines the visual appearance of the MessageList.
0027  *
0028  * The core structure of the theme is made up of Column objects which
0029  * are mapped to View (QTreeView) columns. Each theme must provide at least one column.
0030  *
0031  * Each column contains a set of Row objects dedicated to message items
0032  * and a set of Row objects dedicated to group header items. There must be at least
0033  * one message row and one group header row in each column. Rows are visually
0034  * ordered from top to bottom.
0035  *
0036  * Each Row contains a set of left aligned and a set of right aligned ContentItem objects.
0037  * The right aligned items are painted from right to left while the left aligned
0038  * ones are painted from left to right. In Right-To-Left mode the ThemeDelegate
0039  * follows the exact opposite convention.
0040  *
0041  * Each ContentItem object specifies a visual element to be displayed in a View
0042  * row. The visual elements may be pieces of text (Subject, Date) or icons.
0043  *
0044  * The Theme is designed to strictly interoperate with the ThemeDelegate class
0045  * which takes care of rendering the contents when attached to an QAbstractItemView.
0046  */
0047 class Theme : public OptionSet
0048 {
0049 public:
0050     /**
0051      * The ContentItem class defines a content item inside a Row.
0052      * Content items are data items extracted from a message or a group header:
0053      * they can be text, spacers, separators or icons.
0054      */
0055     class ContentItem
0056     {
0057     private:
0058         /**
0059          * Bits for composing the Type enumeration members.
0060          * We'll be able to test these bits to quickly figure out item properties.
0061          */
0062         enum TypePropertyBits {
0063             /**
0064              * Item can use the custom color property
0065              */
0066             CanUseCustomColor = (1 << 16),
0067             /**
0068              * Item can be in a disabled state (for example the attachment icon when there is no attachment)
0069              */
0070             CanBeDisabled = (1 << 17),
0071             /**
0072              * Item displays some sort of text
0073              */
0074             DisplaysText = (1 << 18),
0075             /**
0076              * Item makes sense (and can be applied) for messages
0077              */
0078             ApplicableToMessageItems = (1 << 19),
0079             /**
0080              * Item makes sense (and can be applied) for group headers
0081              */
0082             ApplicableToGroupHeaderItems = (1 << 20),
0083             /**
0084              * The item takes more horizontal space than the other text items (at the time of writing it's only the subject)
0085              */
0086             LongText = (1 << 21),
0087             /**
0088              * The item displays an icon
0089              */
0090             IsIcon = (1 << 22),
0091             /**
0092              * The item is a small spacer
0093              */
0094             IsSpacer = (1 << 23),
0095             /**
0096              * The item is clickable
0097              */
0098             IsClickable = (1 << 24)
0099         };
0100 
0101     public:
0102         /**
0103          * The available ContentItem types.
0104          * Note that the values in this enum are unique values or'ed with the TypePropertyBits above.
0105          */
0106         enum Type {
0107             /**
0108              * Display the subject of the message item. This is a long text.
0109              */
0110             Subject = 1 | DisplaysText | CanUseCustomColor | ApplicableToMessageItems | LongText,
0111             /**
0112              * Formatted date time of the message/group
0113              */
0114             Date = 2 | DisplaysText | CanUseCustomColor | ApplicableToMessageItems | ApplicableToGroupHeaderItems,
0115             /**
0116              * From: or To: strip, depending on the folder settings
0117              */
0118             SenderOrReceiver = 3 | DisplaysText | CanUseCustomColor | ApplicableToMessageItems,
0119             /**
0120              * From: strip, always
0121              */
0122             Sender = 4 | DisplaysText | CanUseCustomColor | ApplicableToMessageItems,
0123             /**
0124              * To: strip, always
0125              */
0126             Receiver = 5 | DisplaysText | CanUseCustomColor | ApplicableToMessageItems,
0127             /**
0128              * Formatted size of the message
0129              */
0130             Size = 6 | DisplaysText | CanUseCustomColor | ApplicableToMessageItems,
0131             /**
0132              * The icon that displays the unread/read state (never disabled)
0133              */
0134             ReadStateIcon = 7 | ApplicableToMessageItems | IsIcon,
0135             /**
0136              * The icon that displays the attachment state (may be disabled)
0137              */
0138             AttachmentStateIcon = 8 | CanBeDisabled | ApplicableToMessageItems | IsIcon,
0139             /**
0140              * The icon that displays the replied/forwarded state (may be disabled)
0141              */
0142             RepliedStateIcon = 9 | CanBeDisabled | ApplicableToMessageItems | IsIcon,
0143             /**
0144              * The group header label
0145              */
0146             GroupHeaderLabel = 10 | DisplaysText | CanUseCustomColor | ApplicableToGroupHeaderItems,
0147             /**
0148              * The ActionItem state icon. May be disabled. Clickable (cycles todo->nothing)
0149              */
0150             ActionItemStateIcon = 11 | CanBeDisabled | ApplicableToMessageItems | IsIcon | IsClickable,
0151             /**
0152              * The Important tag icon. May be disabled. Clickable (cycles important->nothing)
0153              */
0154             ImportantStateIcon = 12 | CanBeDisabled | ApplicableToMessageItems | IsIcon | IsClickable,
0155             /**
0156              * The Spam/Ham state icon. May be disabled. Clickable (cycles spam->ham->nothing)
0157              */
0158             SpamHamStateIcon = 13 | CanBeDisabled | ApplicableToMessageItems | IsIcon | IsClickable,
0159             /**
0160              * The Watched/Ignored state icon. May be disabled. Clickable (cycles watched->ignored->nothing)
0161              */
0162             WatchedIgnoredStateIcon = 14 | CanBeDisabled | ApplicableToMessageItems | IsIcon | IsClickable,
0163             /**
0164              * The Expanded state icon for group headers. May be disabled. Clickable (expands/collapses the group)
0165              */
0166             ExpandedStateIcon = 15 | CanBeDisabled | ApplicableToGroupHeaderItems | IsIcon | IsClickable,
0167             /**
0168              * The Encryption state icon for messages. May be disabled (no encryption).
0169              */
0170             EncryptionStateIcon = 16 | CanBeDisabled | ApplicableToMessageItems | IsIcon,
0171             /**
0172              * The Signature state icon for messages. May be disabled (no signature)
0173              */
0174             SignatureStateIcon = 17 | CanBeDisabled | ApplicableToMessageItems | IsIcon,
0175             /**
0176              * A vertical separation line.
0177              */
0178             VerticalLine = 18 | CanUseCustomColor | ApplicableToMessageItems | ApplicableToGroupHeaderItems | IsSpacer,
0179             /**
0180              * A small empty spacer usable as separator.
0181              */
0182             HorizontalSpacer = 19 | ApplicableToMessageItems | ApplicableToGroupHeaderItems | IsSpacer,
0183             /**
0184              * The date of the most recent message in subtree
0185              */
0186             MostRecentDate = 20 | DisplaysText | CanUseCustomColor | ApplicableToMessageItems | ApplicableToGroupHeaderItems,
0187             /**
0188              * The combined icon that displays the unread/read/replied/forwarded state (never disabled)
0189              */
0190             CombinedReadRepliedStateIcon = 21 | ApplicableToMessageItems | IsIcon,
0191             /**
0192              * The list of MessageItem::Tag entries
0193              */
0194             TagList = 22 | ApplicableToMessageItems | IsIcon,
0195             /**
0196              * Whether the message has a annotation/note
0197              */
0198             AnnotationIcon = 23 | ApplicableToMessageItems | IsIcon | CanBeDisabled | IsClickable,
0199 
0200             /**
0201              * Whether the message is an invitation
0202              */
0203             InvitationIcon = 24 | ApplicableToMessageItems | IsIcon,
0204             /**
0205              * Folder of the message
0206              */
0207             Folder = 25 | DisplaysText | CanUseCustomColor | ApplicableToMessageItems
0208 #if 0
0209                      TotalMessageCount
0210                      UnreadMessageCount
0211                      NewMessageCount
0212 #endif
0213         };
0214 
0215         enum Flags {
0216             HideWhenDisabled = 1, ///< In disabled state the icon should take no space (overrides SoftenByBlendingWhenDisabled)
0217             SoftenByBlendingWhenDisabled = (1 << 1), ///< In disabled state the icon should be still shown, but made very soft by alpha blending
0218             UseCustomColor = (1 << 2), ///< For text and vertical line. If set then always use a custom color, otherwise use default text color
0219             IsBold = (1 << 3), ///< For text items. If set then always show as bold, otherwise use the default font weight
0220             IsItalic = (1 << 4), ///< Fot text items. If set then always show as italic, otherwise use the default font style
0221             SoftenByBlending = (1 << 5) ///< For text items: use 60% opacity.
0222         };
0223 
0224     private:
0225         Type mType; ///< The type of item
0226         unsigned int mFlags; ///< The flags of the item
0227 
0228         QColor mCustomColor; ///< The color to use with this content item, meaningful only if canUseCustomColor() return true.
0229 
0230     public:
0231         /**
0232          * Creates a ContentItem with the specified type.
0233          * A content item must be added to a theme Row.
0234          */
0235         explicit ContentItem(Type type);
0236         /**
0237          * Creates a ContentItem that is a copy of the content item src.
0238          * A content item must be added to a theme Row.
0239          */
0240         explicit ContentItem(const ContentItem &src);
0241 
0242     public:
0243         /**
0244          * Returns the type of this content item
0245          */
0246         [[nodiscard]] Type type() const;
0247 
0248         /**
0249          * Returns true if this ContentItem can be in a "disabled" state.
0250          * The attachment state icon, for example, can be disabled when the related
0251          * message has no attachments. For such items the HideWhenDisabled
0252          * and SoftenByBlendingWhenDisabled flags are meaningful.
0253          */
0254         [[nodiscard]] bool canBeDisabled() const;
0255 
0256         /**
0257          * Returns true if this ContentItem can make use of a custom color.
0258          */
0259         [[nodiscard]] bool canUseCustomColor() const;
0260 
0261         /**
0262          * Returns true if this item displays some kind of text.
0263          * Items that display text make use of the customFont() setting.
0264          */
0265         [[nodiscard]] bool displaysText() const;
0266 
0267         /**
0268          * Returns true if this item displays a long text.
0269          * The returned value makes sense only if displaysText() returned true.
0270          */
0271         [[nodiscard]] bool displaysLongText() const;
0272 
0273         /**
0274          * Returns true if this item displays an icon.
0275          */
0276         [[nodiscard]] bool isIcon() const;
0277         /**
0278          * Returns true if clicking on this kind of item can perform an action
0279          */
0280         [[nodiscard]] bool isClickable() const;
0281 
0282         /**
0283          * Returns true if this item is a small spacer
0284          */
0285         [[nodiscard]] bool isSpacer() const;
0286 
0287         /**
0288          * Static test that returns true if an instance of ContentItem with the
0289          * specified type makes sense in a Row for message items.
0290          */
0291         static bool applicableToMessageItems(Type type);
0292 
0293         /**
0294          * Static test that returns true if an instance of ContentItem with the
0295          * specified type makes sense in a Row for group header items.
0296          */
0297         static bool applicableToGroupHeaderItems(Type type);
0298 
0299         /**
0300          * Returns a descriptive name for the specified content item type
0301          */
0302         static QString description(Type type);
0303 
0304         /**
0305          * Returns true if this item uses a custom color.
0306          * The return value of this function is valid only if canUseCustomColor() returns true.
0307          */
0308         bool useCustomColor() const;
0309 
0310         /**
0311          * Makes this item use the custom color that can be set by setCustomColor().
0312          * The custom color is meaningful only if canUseCustomColor() returns true.
0313          */
0314         void setUseCustomColor(bool useCustomColor);
0315 
0316         /**
0317          * Returns true if this item uses a bold text.
0318          * The return value of this function is valid only if displaysText() returns true.
0319          */
0320         bool isBold() const;
0321 
0322         /**
0323          * Makes this item use a bold font.
0324          */
0325         void setBold(bool isBold);
0326 
0327         /**
0328          * Returns true if this item uses an italic text.
0329          * The return value of this function is valid only if displaysText() returns true.
0330          */
0331         bool isItalic() const;
0332 
0333         /**
0334          * Makes this item use italic font.
0335          */
0336         void setItalic(bool isItalic);
0337 
0338         /**
0339          * Returns true if this item should be hidden when in disabled state.
0340          * Hidden content items simply aren't painted and take no space.
0341          * This flag has meaning only on items for that canBeDisabled() returns true.
0342          */
0343         bool hideWhenDisabled() const;
0344 
0345         /**
0346          * Sets the flag that causes this item to be hidden when disabled.
0347          * Hidden content items simply aren't painted and take no space.
0348          * This flag overrides the setSoftenByBlendingWhenDisabled() setting.
0349          * This flag has meaning only on items for that canBeDisabled() returns true.
0350          */
0351         void setHideWhenDisabled(bool hideWhenDisabled);
0352 
0353         /**
0354          * Returns true if this item should be painted in a "soft" fashion when
0355          * in disabled state. Soft icons are painted with very low opacity.
0356          * This flag has meaning only on items for that canBeDisabled() returns true.
0357          */
0358         bool softenByBlendingWhenDisabled() const;
0359 
0360         /**
0361          * Sets the flag that causes this item to be painted "softly" when disabled.
0362          * Soft icons are painted with very low opacity.
0363          * This flag may be overridden by the setHideWhenDisabled() setting.
0364          * This flag has meaning only on items for that canBeDisabled() returns true.
0365          */
0366         void setSoftenByBlendingWhenDisabled(bool softenByBlendingWhenDisabled);
0367 
0368         /**
0369          * Returns true if this item should be always painted in a "soft" fashion.
0370          * Meaningful only for text items.
0371          */
0372         bool softenByBlending() const;
0373 
0374         /**
0375          * Sets the flag that causes this item to be painted "softly".
0376          * Meaningful only for text items.
0377          */
0378         void setSoftenByBlending(bool softenByBlending);
0379 
0380         /**
0381          * Returns the custom color set for this item.
0382          * The return value is meaningful only if canUseCustomColor() returns true
0383          * returns true and setUseCustomColor( true ) has been called.
0384          */
0385         const QColor &customColor() const;
0386 
0387         /**
0388          * Sets the custom color for this item. Meaningful only if canUseCustomColor()
0389          * returns true and you call setUseCustomColor( true )
0390          */
0391         void setCustomColor(const QColor &clr);
0392 
0393         // Stuff used by ThemeDelegate. This section should be protected but some gcc
0394         // versions seem to get confused with nested class and friend declarations
0395         // so for portability we're using a public interface also here.
0396 
0397         /**
0398          * Handles content item saving (used by Theme::Row::save())
0399          */
0400         void save(QDataStream &stream) const;
0401 
0402         /**
0403          * Handles content item loading (used by Theme::Row::load())
0404          */
0405         bool load(QDataStream &stream, int themeVersion);
0406     };
0407 
0408     /**
0409      * The Row class defines a row of items inside a Column.
0410      * The Row has a list of left aligned and a list of right aligned ContentItems.
0411      */
0412     class Row
0413     {
0414     public:
0415         explicit Row();
0416         explicit Row(const Row &src);
0417         ~Row();
0418 
0419     private:
0420         QList<ContentItem *> mLeftItems; ///< The list of left aligned items
0421         QList<ContentItem *> mRightItems; ///< The list of right aligned items
0422 
0423         bool LoadContentItem(int val, QDataStream &stream, int themeVersion, bool leftItem);
0424 
0425     public:
0426         /**
0427          * Returns the list of left aligned items for this row
0428          */
0429         const QList<ContentItem *> &leftItems() const;
0430 
0431         /**
0432          * Removes all the left items from this row: the items are deleted.
0433          */
0434         void removeAllLeftItems();
0435 
0436         /**
0437          * Adds a left aligned item to this row. The row takes the ownership
0438          * of the ContentItem pointer.
0439          */
0440         void addLeftItem(ContentItem *item);
0441 
0442         /**
0443          * Adds a left aligned item at the specified position in this row. The row takes the ownership
0444          * of the ContentItem pointer.
0445          */
0446         void insertLeftItem(int idx, ContentItem *item);
0447 
0448         /**
0449          * Removes the specified left aligned content item from this row.
0450          * The item is NOT deleted.
0451          */
0452         void removeLeftItem(ContentItem *item);
0453 
0454         /**
0455          * Returns the list of right aligned items for this row
0456          */
0457         const QList<ContentItem *> &rightItems() const;
0458 
0459         /**
0460          * Removes all the right items from this row. The items are deleted.
0461          */
0462         void removeAllRightItems();
0463 
0464         /**
0465          * Adds a right aligned item to this row. The row takes the ownership
0466          * of the ContentItem pointer. Please note that the first right aligned item
0467          * will start at the right edge, the second right aligned item will come after it etc...
0468          */
0469         void addRightItem(ContentItem *item);
0470 
0471         /**
0472          * Adds a right aligned item at the specified position in this row. The row takes the ownership
0473          * of the ContentItem pointer. Remember that right item positions go from right to left.
0474          */
0475         void insertRightItem(int idx, ContentItem *item);
0476 
0477         /**
0478          * Removes the specified right aligned content item from this row.
0479          * The item is NOT deleted.
0480          */
0481         void removeRightItem(ContentItem *item);
0482 
0483         /**
0484          * Returns true if this row contains text items.
0485          * This is useful if you want to know if the column should just get
0486          * its minimum allowable space or it should get more.
0487          */
0488         bool containsTextItems() const;
0489 
0490         /**
0491          * Handles row saving (used by Theme::Column::save())
0492          */
0493         void save(QDataStream &stream) const;
0494 
0495         /**
0496          * Handles row loading (used by Theme::Column::load())
0497          */
0498         bool load(QDataStream &stream, int themeVersion);
0499     };
0500 
0501     /**
0502      * The Column class defines a view column available inside this theme.
0503      * Each Column has a list of Row items that define the visible rows.
0504      */
0505     class Column
0506     {
0507     public:
0508         /**
0509          * A set of shared runtime data. This is used to store a set of "override" settings
0510          * at runtime. For instance, the width of the visible columns of a skin are stored here.
0511          */
0512         class SharedRuntimeData
0513         {
0514         private:
0515             int mReferences; ///< The number of external references to this shared data object
0516 
0517             int mCurrentlyVisible; ///< Is this column currently visible ? always valid (eventually set from default)
0518             double mCurrentWidth; ///< The current width of this column, -1 if not valid (never set)
0519         public:
0520             /**
0521              * Create a shared runtime data object
0522              */
0523             explicit SharedRuntimeData(bool currentlyVisible, double currentWidth);
0524 
0525             /**
0526              * Destroy a shared runtime data object
0527              */
0528             ~SharedRuntimeData();
0529 
0530         public:
0531             /**
0532              * Increments the reference count for this shared runtime data object.
0533              */
0534             void addReference();
0535 
0536             /**
0537              * Decrements the reference count for this shared runtime data object.
0538              * Returns true if there are other references and false otherwise (so the data can be safely deleted)
0539              */
0540             bool deleteReference();
0541 
0542             /**
0543              * Returns the current number of reference counts, that is, the number of
0544              * Theme::Column objects that use this SharedRuntimeData instance.
0545              */
0546             int referenceCount() const;
0547 
0548             /**
0549              * Returns the current visibility state
0550              */
0551             bool currentlyVisible() const;
0552 
0553             /**
0554              * Sets the current visibility state
0555              */
0556             void setCurrentlyVisible(bool visible);
0557 
0558             /**
0559              * Returns the current width or -1 if the width is unspecified/invalid
0560              */
0561             double currentWidth() const;
0562 
0563             /**
0564              * Sets the current width of the column
0565              */
0566             void setCurrentWidth(double currentWidth);
0567 
0568             /**
0569              * Saves this runtime data to the specified stream
0570              */
0571             void save(QDataStream &stream) const;
0572 
0573             /**
0574              * Loads the shared runtime data from the specified stream
0575              * assuming that it uses the specified theme version.
0576              * Returns true on success and false if the data can't be loaded.
0577              */
0578             bool load(QDataStream &stream, int themeVersion);
0579         };
0580 
0581     public:
0582         /**
0583          * Create an empty column with default settings
0584          */
0585         explicit Column();
0586         /**
0587          * Create an exact copy of the column src.
0588          * The shared runtime data is not copied (only a reference is added).
0589          * If you need to create an independent clone then please use detach()
0590          * after the construction.
0591          */
0592         explicit Column(const Column &src);
0593         /**
0594          * Kill a column object
0595          */
0596         ~Column();
0597 
0598     private:
0599         QString mLabel; ///< The label visible in the column header
0600         QString mPixmapName; ///< The icon's name visible in the column header if it was set
0601         bool mVisibleByDefault; ///< Is this column visible by default ?
0602         bool mIsSenderOrReceiver; ///< If this column displays the sender/receiver field then we will update its label on the fly
0603         SortOrder::MessageSorting mMessageSorting; ///< The message sort order we switch to when clicking on this column
0604         QList<Row *> mGroupHeaderRows; ///< The list of rows we display in this column for a GroupHeaderItem
0605         QList<Row *> mMessageRows; ///< The list of rows we display in this column for a MessageItem
0606 
0607         SharedRuntimeData *mSharedRuntimeData = nullptr; ///< A pointer to the shared runtime data: shared between all instances of a theme with the same id
0608     public:
0609         /**
0610          * Returns the label set for this column
0611          */
0612         const QString &label() const;
0613 
0614         /**
0615          * Sets the label for this column
0616          */
0617         void setLabel(const QString &label);
0618 
0619         /**
0620          * Returns the icon's name (used in SmallIcon) set for this column
0621          */
0622         const QString &pixmapName() const;
0623 
0624         /**
0625          * Sets the icon's name (used in SmallIcon) for this column
0626          */
0627         void setPixmapName(const QString &pixmapName);
0628 
0629         /**
0630          * Returns true if this column is marked as "sender/receiver" and we should
0631          * update its label on-the-fly.
0632          */
0633         bool isSenderOrReceiver() const;
0634 
0635         /**
0636          * Marks this column as containing the "sender/receiver" field.
0637          * Such columns will have the label automatically updated.
0638          */
0639         void setIsSenderOrReceiver(bool sor);
0640 
0641         /**
0642          * Returns true if this column has to be shown by default
0643          */
0644         bool visibleByDefault() const;
0645 
0646         /**
0647          * Sets the "visible by default" tag for this column.
0648          */
0649         void setVisibleByDefault(bool vbd);
0650 
0651         /**
0652          * Detaches the shared runtime data object and makes this object
0653          * totally independent. The shared runtime data is initialized to default values.
0654          */
0655         void detach();
0656 
0657         /**
0658          * Returns the sort order for messages that we should switch to
0659          * when clicking on this column's header (if visible at all).
0660          */
0661         SortOrder::MessageSorting messageSorting() const;
0662 
0663         /**
0664          * Sets the sort order for messages that we should switch to
0665          * when clicking on this column's header (if visible at all).
0666          */
0667         void setMessageSorting(SortOrder::MessageSorting ms);
0668 
0669         /**
0670          * Returns the current shared visibility state for this column.
0671          * This state is shared between all the instances of this theme.
0672          */
0673         bool currentlyVisible() const;
0674 
0675         /**
0676          * Sets the current shared visibility state for this column.
0677          * This state is shared between all the instances of this theme.
0678          */
0679         void setCurrentlyVisible(bool currentlyVisible);
0680 
0681         /**
0682          * Returns the current shared width setting for this column
0683          * or -1 if the width is not specified and should be auto-determined.
0684          * This state is shared between all the instances of this theme.
0685          */
0686         double currentWidth() const;
0687 
0688         /**
0689          * Sets the current shared width setting for this column.
0690          * This state is shared between all the instances of this theme.
0691          */
0692         void setCurrentWidth(double currentWidth);
0693 
0694         /**
0695          * Returns the list of rows visible in this column for a MessageItem
0696          */
0697         const QList<Row *> &messageRows() const;
0698 
0699         /**
0700          * Removes all the message rows from this column.
0701          */
0702         void removeAllMessageRows();
0703 
0704         /**
0705          * Appends a message row to this theme column. The Theme takes
0706          * the ownership of the Row pointer.
0707          */
0708         void addMessageRow(Row *row);
0709 
0710         /**
0711          * Inserts a message row to this theme column in the specified position. The Theme takes
0712          * the ownership of the Row pointer.
0713          */
0714         void insertMessageRow(int idx, Row *row);
0715 
0716         /**
0717          * Removes the specified message row. The row is NOT deleted.
0718          */
0719         void removeMessageRow(Row *row);
0720 
0721         /**
0722          * Returns the list of rows visible in this column for a GroupHeaderItem
0723          */
0724         const QList<Row *> &groupHeaderRows() const;
0725 
0726         /**
0727          * Removes all the group header rows from this column.
0728          */
0729         void removeAllGroupHeaderRows();
0730 
0731         /**
0732          * Appends a group header row to this theme. The Theme takes
0733          * the ownership of the Row pointer.
0734          */
0735         void addGroupHeaderRow(Row *row);
0736 
0737         /**
0738          * Inserts a group header row to this theme column in the specified position. The Theme takes
0739          * the ownership of the Row pointer.
0740          */
0741         void insertGroupHeaderRow(int idx, Row *row);
0742 
0743         /**
0744          * Removes the specified group header row. The row is NOT deleted.
0745          */
0746         void removeGroupHeaderRow(Row *row);
0747 
0748         /**
0749          * Returns true if this column contains text items.
0750          * This is useful if you want to know if the column should just get
0751          * its minimum allowable space or it should get more.
0752          */
0753         bool containsTextItems() const;
0754 
0755         /**
0756          * Handles column saving (used by Theme::save())
0757          */
0758         void save(QDataStream &stream) const;
0759 
0760         /**
0761          * Handles column loading (used by Theme::load())
0762          */
0763         bool load(QDataStream &stream, int themeVersion);
0764     };
0765 
0766 public:
0767     /**
0768      * Creates a totally uninitialized theme object.
0769      */
0770     explicit Theme();
0771 
0772     /**
0773      * Creates a theme object with the specified name and description.
0774      */
0775     explicit Theme(const QString &name, const QString &description, bool readOnly = false);
0776 
0777     /**
0778      * Creates an exact copy of the theme sharing the same runtime data.
0779      * If you need an exact clone please use detach() and generateUniqueId() just
0780      * after creation.
0781      */
0782     explicit Theme(const Theme &src);
0783 
0784     /**
0785      * Destroys this theme object.
0786      */
0787     ~Theme() override;
0788 
0789     static bool compareName(Theme *theme1, Theme *theme2)
0790     {
0791         return theme1->name() < theme2->name();
0792     }
0793 
0794 public:
0795     /**
0796      * Which color do we use to paint group header background ?
0797      */
0798     enum GroupHeaderBackgroundMode {
0799         Transparent, ///< No background at all: use style default
0800         AutoColor, ///< Automatically determine the color (somewhere in the middle between background and text)
0801         CustomColor, ///< Use a custom color
0802     };
0803 
0804     /**
0805      * How do we paint group header background ?
0806      */
0807     enum GroupHeaderBackgroundStyle {
0808         PlainRect, ///< One plain rect per column
0809         PlainJoinedRect, ///< One big plain rect for all the columns
0810         RoundedRect, ///< One rounded rect per column
0811         RoundedJoinedRect, ///< One big rounded rect for all the columns
0812         GradientRect, ///< One rounded gradient filled rect per column
0813         GradientJoinedRect, ///< One big rounded gradient rect for all the columns
0814         StyledRect, ///< One styled rect per column
0815         StyledJoinedRect, ///< One big styled rect per column
0816     };
0817 
0818     /**
0819      * How do we manage the QHeaderView attached to our View ?
0820      */
0821     enum ViewHeaderPolicy {
0822         ShowHeaderAlways,
0823         NeverShowHeader,
0824         // ShowWhenMoreThanOneColumn,  ///< This doesn't work at the moment (since without header we don't have means for showing columns back)
0825     };
0826 
0827     enum ThemeIcon {
0828         IconNew,
0829         IconUnread,
0830         IconRead,
0831         IconDeleted,
0832         IconReplied,
0833         IconRepliedAndForwarded,
0834         IconQueued,
0835         IconActionItem,
0836         IconSent,
0837         IconForwarded,
0838         IconImportant,
0839         IconWatched,
0840         IconIgnored,
0841         IconSpam,
0842         IconHam,
0843         IconFullySigned,
0844         IconPartiallySigned,
0845         IconUndefinedSigned,
0846         IconNotSigned,
0847         IconFullyEncrypted,
0848         IconPartiallyEncrypted,
0849         IconUndefinedEncrypted,
0850         IconNotEncrypted,
0851         IconAttachment,
0852         IconAnnotation,
0853         IconInvitation,
0854         IconShowMore,
0855         IconShowLess,
0856         IconVerticalLine,
0857         IconHorizontalSpacer,
0858 
0859         _IconCount
0860     };
0861 
0862 private:
0863     QList<Column *> mColumns; ///< The list of columns available in this theme
0864 
0865     // pixmaps cache. Mutable, so it can be lazily populated from const methods
0866     mutable QList<QPixmap *> mPixmaps;
0867 
0868     GroupHeaderBackgroundMode mGroupHeaderBackgroundMode; ///< How do we paint group header background ?
0869     QColor mGroupHeaderBackgroundColor; ///< The background color of the message group, used only if CustomColor
0870     GroupHeaderBackgroundStyle mGroupHeaderBackgroundStyle; ///< How do we paint group header background ?
0871     ViewHeaderPolicy mViewHeaderPolicy; ///< Do we show the header or not ?
0872     int mIconSize; ///< The icon size for this theme, 16 is the default
0873 public:
0874     /**
0875      * Detaches this object from the shared runtime data for columns.
0876      */
0877     void detach();
0878 
0879     /**
0880      * Resets the column state (visibility and width) to their default values (the "visible by default" ones).
0881      */
0882     void resetColumnState();
0883 
0884     /**
0885      * Resets the column sizes to "default" (subset of resetColumnState() above).
0886      */
0887     void resetColumnSizes();
0888 
0889     /**
0890      * Returns the list of columns available in this theme
0891      */
0892     const QList<Column *> &columns() const;
0893 
0894     /**
0895      * Returns a pointer to the column at the specified index or 0 if there is no such column
0896      */
0897     Column *column(int idx) const;
0898 
0899     void moveColumn(int idx, int newPosition);
0900 
0901     /**
0902      * Removes all columns from this theme
0903      */
0904     void removeAllColumns();
0905 
0906     /**
0907      * Appends a column to this theme
0908      */
0909     void addColumn(Column *column);
0910 
0911     /**
0912      * Inserts a column to this theme at the specified position.
0913      */
0914     void insertColumn(int idx, Column *column);
0915 
0916     /**
0917      * Removes the specified message row. The row is NOT deleted.
0918      */
0919     void removeColumn(Column *col);
0920 
0921     /**
0922      * Returns the group header background mode for this theme.
0923      */
0924     GroupHeaderBackgroundMode groupHeaderBackgroundMode() const;
0925 
0926     /**
0927      * Sets the group header background mode for this theme.
0928      * If you set it to CustomColor then please also setGroupHeaderBackgroundColor()
0929      */
0930     void setGroupHeaderBackgroundMode(GroupHeaderBackgroundMode bm);
0931 
0932     /**
0933      * Returns the group header background color for this theme.
0934      * This color is used only if groupHeaderBackgroundMode() is set to CustomColor.
0935      */
0936     const QColor &groupHeaderBackgroundColor() const;
0937 
0938     /**
0939      * Sets the group header background color for this theme.
0940      * This color is used only if groupHeaderBackgroundMode() is set to CustomColor.
0941      */
0942     void setGroupHeaderBackgroundColor(const QColor &clr);
0943 
0944     /**
0945      * Returns the group header background style for this theme.
0946      * The group header background style makes sense only if groupHeaderBackgroundMode() is
0947      * set to something different than Transparent.
0948      */
0949     GroupHeaderBackgroundStyle groupHeaderBackgroundStyle() const;
0950 
0951     /**
0952      * Sets the group header background style for this theme.
0953      * The group header background style makes sense only if groupHeaderBackgroundMode() is
0954      * set to something different than Transparent.
0955      */
0956     void setGroupHeaderBackgroundStyle(GroupHeaderBackgroundStyle groupHeaderBackgroundStyle);
0957 
0958     /**
0959      * Enumerates the available group header background styles.
0960      * The returned descriptors are pairs in that the first item is the localized description
0961      * of the option value and the second item is the integer option value itself.
0962      */
0963     static QList<QPair<QString, int>> enumerateGroupHeaderBackgroundStyles();
0964 
0965     /**
0966      * Returns the currently set ViewHeaderPolicy
0967      */
0968     ViewHeaderPolicy viewHeaderPolicy() const;
0969 
0970     /**
0971      * Sets the ViewHeaderPolicy for this theme
0972      */
0973     void setViewHeaderPolicy(ViewHeaderPolicy vhp);
0974 
0975     /**
0976      * Returns the currently set icon size
0977      */
0978     int iconSize() const;
0979 
0980     /**
0981      * Sets the icon size for this theme.
0982      * Please note that the function will not let you set insane values.
0983      * The allowable range is [8,64]
0984      */
0985     void setIconSize(int iconSize);
0986 
0987     /**
0988      * Enumerates the available view header policy options.
0989      * The returned descriptors are pairs in that the first item is the localized description
0990      * of the option value and the second item is the integer option value itself.
0991      */
0992     static QList<QPair<QString, int>> enumerateViewHeaderPolicyOptions();
0993 
0994     inline const QPixmap *pixmap(ThemeIcon icon) const
0995     {
0996         if (Q_UNLIKELY(mPixmaps.isEmpty())) {
0997             populatePixmapCache();
0998         }
0999         return mPixmaps[icon];
1000     }
1001 
1002 protected:
1003     /**
1004      * Pure virtual reimplemented from OptionSet.
1005      */
1006     void save(QDataStream &stream) const override;
1007 
1008     /**
1009      * Pure virtual reimplemented from OptionSet.
1010      */
1011     bool load(QDataStream &stream) override;
1012 
1013     void clearPixmapCache() const;
1014     void populatePixmapCache() const;
1015 };
1016 } // namespace Core
1017 } // namespace MessageList