1 /****************************************************************************** 2 * 3 * SPDX-FileCopyrightText: 2008 Szymon Tomasz Stefanek <pragma@kvirc.net> 4 * 5 * SPDX-License-Identifier: GPL-2.0-or-later 6 * 7 *******************************************************************************/ 8 9 #pragma once 10 11 #include <QColor> 12 #include <QList> 13 #include <QPair> 14 #include <QString> 15 #include <QVector> 16 17 #include <core/optionset.h> 18 #include <core/sortorder.h> 19 20 class QPixmap; 21 22 namespace MessageList 23 { 24 namespace Core 25 { 26 /** 27 * The Theme class defines the visual appearance of the MessageList. 28 * 29 * The core structure of the theme is made up of Column objects which 30 * are mapped to View (QTreeView) columns. Each theme must provide at least one column. 31 * 32 * Each column contains a set of Row objects dedicated to message items 33 * and a set of Row objects dedicated to group header items. There must be at least 34 * one message row and one group header row in each column. Rows are visually 35 * ordered from top to bottom. 36 * 37 * Each Row contains a set of left aligned and a set of right aligned ContentItem objects. 38 * The right aligned items are painted from right to left while the left aligned 39 * ones are painted from left to right. In Right-To-Left mode the ThemeDelegate 40 * follows the exact opposite convention. 41 * 42 * Each ContentItem object specifies a visual element to be displayed in a View 43 * row. The visual elements may be pieces of text (Subject, Date) or icons. 44 * 45 * The Theme is designed to strictly interoperate with the ThemeDelegate class 46 * which takes care of rendering the contents when attached to an QAbstractItemView. 47 */ 48 class Theme : public OptionSet 49 { 50 public: 51 /** 52 * The ContentItem class defines a content item inside a Row. 53 * Content items are data items extracted from a message or a group header: 54 * they can be text, spacers, separators or icons. 55 */ 56 class ContentItem 57 { 58 private: 59 /** 60 * Bits for composing the Type enumeration members. 61 * We'll be able to test these bits to quickly figure out item properties. 62 */ 63 enum TypePropertyBits { 64 /** 65 * Item can use the custom color property 66 */ 67 CanUseCustomColor = (1 << 16), 68 /** 69 * Item can be in a disabled state (for example the attachment icon when there is no attachment) 70 */ 71 CanBeDisabled = (1 << 17), 72 /** 73 * Item displays some sort of text 74 */ 75 DisplaysText = (1 << 18), 76 /** 77 * Item makes sense (and can be applied) for messages 78 */ 79 ApplicableToMessageItems = (1 << 19), 80 /** 81 * Item makes sense (and can be applied) for group headers 82 */ 83 ApplicableToGroupHeaderItems = (1 << 20), 84 /** 85 * The item takes more horizontal space than the other text items (at the time of writing it's only the subject) 86 */ 87 LongText = (1 << 21), 88 /** 89 * The item displays an icon 90 */ 91 IsIcon = (1 << 22), 92 /** 93 * The item is a small spacer 94 */ 95 IsSpacer = (1 << 23), 96 /** 97 * The item is clickable 98 */ 99 IsClickable = (1 << 24) 100 }; 101 102 public: 103 /** 104 * The available ContentItem types. 105 * Note that the values in this enum are unique values or'ed with the TypePropertyBits above. 106 */ 107 enum Type { 108 /** 109 * Display the subject of the message item. This is a long text. 110 */ 111 Subject = 1 | DisplaysText | CanUseCustomColor | ApplicableToMessageItems | LongText, 112 /** 113 * Formatted date time of the message/group 114 */ 115 Date = 2 | DisplaysText | CanUseCustomColor | ApplicableToMessageItems | ApplicableToGroupHeaderItems, 116 /** 117 * From: or To: strip, depending on the folder settings 118 */ 119 SenderOrReceiver = 3 | DisplaysText | CanUseCustomColor | ApplicableToMessageItems, 120 /** 121 * From: strip, always 122 */ 123 Sender = 4 | DisplaysText | CanUseCustomColor | ApplicableToMessageItems, 124 /** 125 * To: strip, always 126 */ 127 Receiver = 5 | DisplaysText | CanUseCustomColor | ApplicableToMessageItems, 128 /** 129 * Formatted size of the message 130 */ 131 Size = 6 | DisplaysText | CanUseCustomColor | ApplicableToMessageItems, 132 /** 133 * The icon that displays the unread/read state (never disabled) 134 */ 135 ReadStateIcon = 7 | ApplicableToMessageItems | IsIcon, 136 /** 137 * The icon that displays the attachment state (may be disabled) 138 */ 139 AttachmentStateIcon = 8 | CanBeDisabled | ApplicableToMessageItems | IsIcon, 140 /** 141 * The icon that displays the replied/forwarded state (may be disabled) 142 */ 143 RepliedStateIcon = 9 | CanBeDisabled | ApplicableToMessageItems | IsIcon, 144 /** 145 * The group header label 146 */ 147 GroupHeaderLabel = 10 | DisplaysText | CanUseCustomColor | ApplicableToGroupHeaderItems, 148 /** 149 * The ActionItem state icon. May be disabled. Clickable (cycles todo->nothing) 150 */ 151 ActionItemStateIcon = 11 | CanBeDisabled | ApplicableToMessageItems | IsIcon | IsClickable, 152 /** 153 * The Important tag icon. May be disabled. Clickable (cycles important->nothing) 154 */ 155 ImportantStateIcon = 12 | CanBeDisabled | ApplicableToMessageItems | IsIcon | IsClickable, 156 /** 157 * The Spam/Ham state icon. May be disabled. Clickable (cycles spam->ham->nothing) 158 */ 159 SpamHamStateIcon = 13 | CanBeDisabled | ApplicableToMessageItems | IsIcon | IsClickable, 160 /** 161 * The Watched/Ignored state icon. May be disabled. Clickable (cycles watched->ignored->nothing) 162 */ 163 WatchedIgnoredStateIcon = 14 | CanBeDisabled | ApplicableToMessageItems | IsIcon | IsClickable, 164 /** 165 * The Expanded state icon for group headers. May be disabled. Clickable (expands/collapses the group) 166 */ 167 ExpandedStateIcon = 15 | CanBeDisabled | ApplicableToGroupHeaderItems | IsIcon | IsClickable, 168 /** 169 * The Encryption state icon for messages. May be disabled (no encryption). 170 */ 171 EncryptionStateIcon = 16 | CanBeDisabled | ApplicableToMessageItems | IsIcon, 172 /** 173 * The Signature state icon for messages. May be disabled (no signature) 174 */ 175 SignatureStateIcon = 17 | CanBeDisabled | ApplicableToMessageItems | IsIcon, 176 /** 177 * A vertical separation line. 178 */ 179 VerticalLine = 18 | CanUseCustomColor | ApplicableToMessageItems | ApplicableToGroupHeaderItems | IsSpacer, 180 /** 181 * A small empty spacer usable as separator. 182 */ 183 HorizontalSpacer = 19 | ApplicableToMessageItems | ApplicableToGroupHeaderItems | IsSpacer, 184 /** 185 * The date of the most recent message in subtree 186 */ 187 MostRecentDate = 20 | DisplaysText | CanUseCustomColor | ApplicableToMessageItems | ApplicableToGroupHeaderItems, 188 /** 189 * The combined icon that displays the unread/read/replied/forwarded state (never disabled) 190 */ 191 CombinedReadRepliedStateIcon = 21 | ApplicableToMessageItems | IsIcon, 192 /** 193 * The list of MessageItem::Tag entries 194 */ 195 TagList = 22 | ApplicableToMessageItems | IsIcon, 196 /** 197 * Whether the message has a annotation/note 198 */ 199 AnnotationIcon = 23 | ApplicableToMessageItems | IsIcon | CanBeDisabled | IsClickable, 200 201 /** 202 * Whether the message is an invitation 203 */ 204 InvitationIcon = 24 | ApplicableToMessageItems | IsIcon, 205 /** 206 * Folder of the message 207 */ 208 Folder = 25 | DisplaysText | CanUseCustomColor | ApplicableToMessageItems 209 #if 0 210 TotalMessageCount 211 UnreadMessageCount 212 NewMessageCount 213 #endif 214 }; 215 216 enum Flags { 217 HideWhenDisabled = 1, ///< In disabled state the icon should take no space (overrides SoftenByBlendingWhenDisabled) 218 SoftenByBlendingWhenDisabled = (1 << 1), ///< In disabled state the icon should be still shown, but made very soft by alpha blending 219 UseCustomColor = (1 << 2), ///< For text and vertical line. If set then always use a custom color, otherwise use default text color 220 IsBold = (1 << 3), ///< For text items. If set then always show as bold, otherwise use the default font weight 221 IsItalic = (1 << 4), ///< Fot text items. If set then always show as italic, otherwise use the default font style 222 SoftenByBlending = (1 << 5) ///< For text items: use 60% opacity. 223 }; 224 225 private: 226 Type mType; ///< The type of item 227 unsigned int mFlags; ///< The flags of the item 228 229 QColor mCustomColor; ///< The color to use with this content item, meaningful only if canUseCustomColor() return true. 230 231 public: 232 /** 233 * Creates a ContentItem with the specified type. 234 * A content item must be added to a theme Row. 235 */ 236 explicit ContentItem(Type type); 237 /** 238 * Creates a ContentItem that is a copy of the content item src. 239 * A content item must be added to a theme Row. 240 */ 241 explicit ContentItem(const ContentItem &src); 242 243 public: 244 /** 245 * Returns the type of this content item 246 */ 247 Type type() const; 248 249 /** 250 * Returns true if this ContentItem can be in a "disabled" state. 251 * The attachment state icon, for example, can be disabled when the related 252 * message has no attachments. For such items the HideWhenDisabled 253 * and SoftenByBlendingWhenDisabled flags are meaningful. 254 */ 255 bool canBeDisabled() const; 256 257 /** 258 * Returns true if this ContentItem can make use of a custom color. 259 */ 260 bool canUseCustomColor() const; 261 262 /** 263 * Returns true if this item displays some kind of text. 264 * Items that display text make use of the customFont() setting. 265 */ 266 bool displaysText() const; 267 268 /** 269 * Returns true if this item displays a long text. 270 * The returned value makes sense only if displaysText() returned true. 271 */ 272 bool displaysLongText() const; 273 274 /** 275 * Returns true if this item displays an icon. 276 */ 277 bool isIcon() const; 278 /** 279 * Returns true if clicking on this kind of item can perform an action 280 */ 281 bool isClickable() const; 282 283 /** 284 * Returns true if this item is a small spacer 285 */ 286 bool isSpacer() const; 287 288 /** 289 * Static test that returns true if an instance of ContentItem with the 290 * specified type makes sense in a Row for message items. 291 */ 292 static bool applicableToMessageItems(Type type); 293 294 /** 295 * Static test that returns true if an instance of ContentItem with the 296 * specified type makes sense in a Row for group header items. 297 */ 298 static bool applicableToGroupHeaderItems(Type type); 299 300 /** 301 * Returns a descriptive name for the specified content item type 302 */ 303 static QString description(Type type); 304 305 /** 306 * Returns true if this item uses a custom color. 307 * The return value of this function is valid only if canUseCustomColor() returns true. 308 */ 309 bool useCustomColor() const; 310 311 /** 312 * Makes this item use the custom color that can be set by setCustomColor(). 313 * The custom color is meaningful only if canUseCustomColor() returns true. 314 */ 315 void setUseCustomColor(bool useCustomColor); 316 317 /** 318 * Returns true if this item uses a bold text. 319 * The return value of this function is valid only if displaysText() returns true. 320 */ 321 bool isBold() const; 322 323 /** 324 * Makes this item use a bold font. 325 */ 326 void setBold(bool isBold); 327 328 /** 329 * Returns true if this item uses an italic text. 330 * The return value of this function is valid only if displaysText() returns true. 331 */ 332 bool isItalic() const; 333 334 /** 335 * Makes this item use italic font. 336 */ 337 void setItalic(bool isItalic); 338 339 /** 340 * Returns true if this item should be hidden when in disabled state. 341 * Hidden content items simply aren't painted and take no space. 342 * This flag has meaning only on items for that canBeDisabled() returns true. 343 */ 344 bool hideWhenDisabled() const; 345 346 /** 347 * Sets the flag that causes this item to be hidden when disabled. 348 * Hidden content items simply aren't painted and take no space. 349 * This flag overrides the setSoftenByBlendingWhenDisabled() setting. 350 * This flag has meaning only on items for that canBeDisabled() returns true. 351 */ 352 void setHideWhenDisabled(bool hideWhenDisabled); 353 354 /** 355 * Returns true if this item should be painted in a "soft" fashion when 356 * in disabled state. Soft icons are painted with very low opacity. 357 * This flag has meaning only on items for that canBeDisabled() returns true. 358 */ 359 bool softenByBlendingWhenDisabled() const; 360 361 /** 362 * Sets the flag that causes this item to be painted "softly" when disabled. 363 * Soft icons are painted with very low opacity. 364 * This flag may be overridden by the setHideWhenDisabled() setting. 365 * This flag has meaning only on items for that canBeDisabled() returns true. 366 */ 367 void setSoftenByBlendingWhenDisabled(bool softenByBlendingWhenDisabled); 368 369 /** 370 * Returns true if this item should be always painted in a "soft" fashion. 371 * Meaningful only for text items. 372 */ 373 bool softenByBlending() const; 374 375 /** 376 * Sets the flag that causes this item to be painted "softly". 377 * Meaningful only for text items. 378 */ 379 void setSoftenByBlending(bool softenByBlending); 380 381 /** 382 * Returns the custom color set for this item. 383 * The return value is meaningful only if canUseCustomColor() returns true 384 * returns true and setUseCustomColor( true ) has been called. 385 */ 386 const QColor &customColor() const; 387 388 /** 389 * Sets the custom color for this item. Meaningful only if canUseCustomColor() 390 * returns true and you call setUseCustomColor( true ) 391 */ 392 void setCustomColor(const QColor &clr); 393 394 // Stuff used by ThemeDelegate. This section should be protected but some gcc 395 // versions seem to get confused with nested class and friend declarations 396 // so for portability we're using a public interface also here. 397 398 /** 399 * Handles content item saving (used by Theme::Row::save()) 400 */ 401 void save(QDataStream &stream) const; 402 403 /** 404 * Handles content item loading (used by Theme::Row::load()) 405 */ 406 bool load(QDataStream &stream, int themeVersion); 407 }; 408 409 /** 410 * The Row class defines a row of items inside a Column. 411 * The Row has a list of left aligned and a list of right aligned ContentItems. 412 */ 413 class Row 414 { 415 public: 416 explicit Row(); 417 explicit Row(const Row &src); 418 ~Row(); 419 420 private: 421 QList<ContentItem *> mLeftItems; ///< The list of left aligned items 422 QList<ContentItem *> mRightItems; ///< The list of right aligned items 423 424 bool LoadContentItem(int val, QDataStream &stream, int themeVersion, bool leftItem); 425 426 public: 427 /** 428 * Returns the list of left aligned items for this row 429 */ 430 const QList<ContentItem *> &leftItems() const; 431 432 /** 433 * Removes all the left items from this row: the items are deleted. 434 */ 435 void removeAllLeftItems(); 436 437 /** 438 * Adds a left aligned item to this row. The row takes the ownership 439 * of the ContentItem pointer. 440 */ 441 void addLeftItem(ContentItem *item); 442 443 /** 444 * Adds a left aligned item at the specified position in this row. The row takes the ownership 445 * of the ContentItem pointer. 446 */ 447 void insertLeftItem(int idx, ContentItem *item); 448 449 /** 450 * Removes the specified left aligned content item from this row. 451 * The item is NOT deleted. 452 */ 453 void removeLeftItem(ContentItem *item); 454 455 /** 456 * Returns the list of right aligned items for this row 457 */ 458 const QList<ContentItem *> &rightItems() const; 459 460 /** 461 * Removes all the right items from this row. The items are deleted. 462 */ 463 void removeAllRightItems(); 464 465 /** 466 * Adds a right aligned item to this row. The row takes the ownership 467 * of the ContentItem pointer. Please note that the first right aligned item 468 * will start at the right edge, the second right aligned item will come after it etc... 469 */ 470 void addRightItem(ContentItem *item); 471 472 /** 473 * Adds a right aligned item at the specified position in this row. The row takes the ownership 474 * of the ContentItem pointer. Remember that right item positions go from right to left. 475 */ 476 void insertRightItem(int idx, ContentItem *item); 477 478 /** 479 * Removes the specified right aligned content item from this row. 480 * The item is NOT deleted. 481 */ 482 void removeRightItem(ContentItem *item); 483 484 /** 485 * Returns true if this row contains text items. 486 * This is useful if you want to know if the column should just get 487 * its minimum allowable space or it should get more. 488 */ 489 bool containsTextItems() const; 490 491 /** 492 * Handles row saving (used by Theme::Column::save()) 493 */ 494 void save(QDataStream &stream) const; 495 496 /** 497 * Handles row loading (used by Theme::Column::load()) 498 */ 499 bool load(QDataStream &stream, int themeVersion); 500 }; 501 502 /** 503 * The Column class defines a view column available inside this theme. 504 * Each Column has a list of Row items that define the visible rows. 505 */ 506 class Column 507 { 508 public: 509 /** 510 * A set of shared runtime data. This is used to store a set of "override" settings 511 * at runtime. For instance, the width of the visible columns of a skin are stored here. 512 */ 513 class SharedRuntimeData 514 { 515 private: 516 int mReferences; ///< The number of external references to this shared data object 517 518 int mCurrentlyVisible; ///< Is this column currently visible ? always valid (eventually set from default) 519 double mCurrentWidth; ///< The current width of this column, -1 if not valid (never set) 520 public: 521 /** 522 * Create a shared runtime data object 523 */ 524 explicit SharedRuntimeData(bool currentlyVisible, double currentWidth); 525 526 /** 527 * Destroy a shared runtime data object 528 */ 529 ~SharedRuntimeData(); 530 531 public: 532 /** 533 * Increments the reference count for this shared runtime data object. 534 */ 535 void addReference(); 536 537 /** 538 * Decrements the reference count for this shared runtime data object. 539 * Returns true if there are other references and false otherwise (so the data can be safely deleted) 540 */ 541 bool deleteReference(); 542 543 /** 544 * Returns the current number of reference counts, that is, the number of 545 * Theme::Column objects that use this SharedRuntimeData instance. 546 */ 547 int referenceCount() const; 548 549 /** 550 * Returns the current visibility state 551 */ 552 bool currentlyVisible() const; 553 554 /** 555 * Sets the current visibility state 556 */ 557 void setCurrentlyVisible(bool visible); 558 559 /** 560 * Returns the current width or -1 if the width is unspecified/invalid 561 */ 562 double currentWidth() const; 563 564 /** 565 * Sets the current width of the column 566 */ 567 void setCurrentWidth(double currentWidth); 568 569 /** 570 * Saves this runtime data to the specified stream 571 */ 572 void save(QDataStream &stream) const; 573 574 /** 575 * Loads the shared runtime data from the specified stream 576 * assuming that it uses the specified theme version. 577 * Returns true on success and false if the data can't be loaded. 578 */ 579 bool load(QDataStream &stream, int themeVersion); 580 }; 581 582 public: 583 /** 584 * Create an empty column with default settings 585 */ 586 explicit Column(); 587 /** 588 * Create an exact copy of the column src. 589 * The shared runtime data is not copied (only a reference is added). 590 * If you need to create an independent clone then please use detach() 591 * after the construction. 592 */ 593 explicit Column(const Column &src); 594 /** 595 * Kill a column object 596 */ 597 ~Column(); 598 599 private: 600 QString mLabel; ///< The label visible in the column header 601 QString mPixmapName; ///< The icon's name visible in the column header if it was set 602 bool mVisibleByDefault; ///< Is this column visible by default ? 603 bool mIsSenderOrReceiver; ///< If this column displays the sender/receiver field then we will update its label on the fly 604 SortOrder::MessageSorting mMessageSorting; ///< The message sort order we switch to when clicking on this column 605 QList<Row *> mGroupHeaderRows; ///< The list of rows we display in this column for a GroupHeaderItem 606 QList<Row *> mMessageRows; ///< The list of rows we display in this column for a MessageItem 607 608 SharedRuntimeData *mSharedRuntimeData = nullptr; ///< A pointer to the shared runtime data: shared between all instances of a theme with the same id 609 public: 610 /** 611 * Returns the label set for this column 612 */ 613 const QString &label() const; 614 615 /** 616 * Sets the label for this column 617 */ 618 void setLabel(const QString &label); 619 620 /** 621 * Returns the icon's name (used in SmallIcon) set for this column 622 */ 623 const QString &pixmapName() const; 624 625 /** 626 * Sets the icon's name (used in SmallIcon) for this column 627 */ 628 void setPixmapName(const QString &pixmapName); 629 630 /** 631 * Returns true if this column is marked as "sender/receiver" and we should 632 * update its label on-the-fly. 633 */ 634 bool isSenderOrReceiver() const; 635 636 /** 637 * Marks this column as containing the "sender/receiver" field. 638 * Such columns will have the label automatically updated. 639 */ 640 void setIsSenderOrReceiver(bool sor); 641 642 /** 643 * Returns true if this column has to be shown by default 644 */ 645 bool visibleByDefault() const; 646 647 /** 648 * Sets the "visible by default" tag for this column. 649 */ 650 void setVisibleByDefault(bool vbd); 651 652 /** 653 * Detaches the shared runtime data object and makes this object 654 * totally independent. The shared runtime data is initialized to default values. 655 */ 656 void detach(); 657 658 /** 659 * Returns the sort order for messages that we should switch to 660 * when clicking on this column's header (if visible at all). 661 */ 662 SortOrder::MessageSorting messageSorting() const; 663 664 /** 665 * Sets the sort order for messages that we should switch to 666 * when clicking on this column's header (if visible at all). 667 */ 668 void setMessageSorting(SortOrder::MessageSorting ms); 669 670 /** 671 * Returns the current shared visibility state for this column. 672 * This state is shared between all the instances of this theme. 673 */ 674 bool currentlyVisible() const; 675 676 /** 677 * Sets the current shared visibility state for this column. 678 * This state is shared between all the instances of this theme. 679 */ 680 void setCurrentlyVisible(bool currentlyVisible); 681 682 /** 683 * Returns the current shared width setting for this column 684 * or -1 if the width is not specified and should be auto-determined. 685 * This state is shared between all the instances of this theme. 686 */ 687 double currentWidth() const; 688 689 /** 690 * Sets the current shared width setting for this column. 691 * This state is shared between all the instances of this theme. 692 */ 693 void setCurrentWidth(double currentWidth); 694 695 /** 696 * Returns the list of rows visible in this column for a MessageItem 697 */ 698 const QList<Row *> &messageRows() const; 699 700 /** 701 * Removes all the message rows from this column. 702 */ 703 void removeAllMessageRows(); 704 705 /** 706 * Appends a message row to this theme column. The Theme takes 707 * the ownership of the Row pointer. 708 */ 709 void addMessageRow(Row *row); 710 711 /** 712 * Inserts a message row to this theme column in the specified position. The Theme takes 713 * the ownership of the Row pointer. 714 */ 715 void insertMessageRow(int idx, Row *row); 716 717 /** 718 * Removes the specified message row. The row is NOT deleted. 719 */ 720 void removeMessageRow(Row *row); 721 722 /** 723 * Returns the list of rows visible in this column for a GroupHeaderItem 724 */ 725 const QList<Row *> &groupHeaderRows() const; 726 727 /** 728 * Removes all the group header rows from this column. 729 */ 730 void removeAllGroupHeaderRows(); 731 732 /** 733 * Appends a group header row to this theme. The Theme takes 734 * the ownership of the Row pointer. 735 */ 736 void addGroupHeaderRow(Row *row); 737 738 /** 739 * Inserts a group header row to this theme column in the specified position. The Theme takes 740 * the ownership of the Row pointer. 741 */ 742 void insertGroupHeaderRow(int idx, Row *row); 743 744 /** 745 * Removes the specified group header row. The row is NOT deleted. 746 */ 747 void removeGroupHeaderRow(Row *row); 748 749 /** 750 * Returns true if this column contains text items. 751 * This is useful if you want to know if the column should just get 752 * its minimum allowable space or it should get more. 753 */ 754 bool containsTextItems() const; 755 756 /** 757 * Handles column saving (used by Theme::save()) 758 */ 759 void save(QDataStream &stream) const; 760 761 /** 762 * Handles column loading (used by Theme::load()) 763 */ 764 bool load(QDataStream &stream, int themeVersion); 765 }; 766 767 public: 768 /** 769 * Creates a totally uninitialized theme object. 770 */ 771 explicit Theme(); 772 773 /** 774 * Creates a theme object with the specified name and description. 775 */ 776 explicit Theme(const QString &name, const QString &description, bool readOnly = false); 777 778 /** 779 * Creates an exact copy of the theme sharing the same runtime data. 780 * If you need an exact clone please use detach() and generateUniqueId() just 781 * after creation. 782 */ 783 explicit Theme(const Theme &src); 784 785 /** 786 * Destroys this theme object. 787 */ 788 ~Theme() override; 789 compareName(Theme * theme1,Theme * theme2)790 static bool compareName(Theme *theme1, Theme *theme2) 791 { 792 return theme1->name() < theme2->name(); 793 } 794 795 public: 796 /** 797 * Which color do we use to paint group header background ? 798 */ 799 enum GroupHeaderBackgroundMode { 800 Transparent, ///< No background at all: use style default 801 AutoColor, ///< Automatically determine the color (somewhere in the middle between background and text) 802 CustomColor ///< Use a custom color 803 }; 804 805 /** 806 * How do we paint group header background ? 807 */ 808 enum GroupHeaderBackgroundStyle { 809 PlainRect, ///< One plain rect per column 810 PlainJoinedRect, ///< One big plain rect for all the columns 811 RoundedRect, ///< One rounded rect per column 812 RoundedJoinedRect, ///< One big rounded rect for all the columns 813 GradientRect, ///< One rounded gradient filled rect per column 814 GradientJoinedRect, ///< One big rounded gradient rect for all the columns 815 StyledRect, ///< One styled rect per column 816 StyledJoinedRect ///< One big styled rect per column 817 }; 818 819 /** 820 * How do we manage the QHeaderView attached to our View ? 821 */ 822 enum ViewHeaderPolicy { 823 ShowHeaderAlways, 824 NeverShowHeader 825 // ShowWhenMoreThanOneColumn, ///< This doesn't work at the moment (since without header we don't have means for showing columns back) 826 }; 827 828 enum ThemeIcon { 829 IconNew, 830 IconUnread, 831 IconRead, 832 IconDeleted, 833 IconReplied, 834 IconRepliedAndForwarded, 835 IconQueued, 836 IconActionItem, 837 IconSent, 838 IconForwarded, 839 IconImportant, 840 IconWatched, 841 IconIgnored, 842 IconSpam, 843 IconHam, 844 IconFullySigned, 845 IconPartiallySigned, 846 IconUndefinedSigned, 847 IconNotSigned, 848 IconFullyEncrypted, 849 IconPartiallyEncrypted, 850 IconUndefinedEncrypted, 851 IconNotEncrypted, 852 IconAttachment, 853 IconAnnotation, 854 IconInvitation, 855 IconShowMore, 856 IconShowLess, 857 IconVerticalLine, 858 IconHorizontalSpacer, 859 860 _IconCount 861 }; 862 863 private: 864 QList<Column *> mColumns; ///< The list of columns available in this theme 865 866 // pixmaps cache. Mutable, so it can be lazily populated from const methods 867 mutable QVector<QPixmap *> mPixmaps; 868 869 GroupHeaderBackgroundMode mGroupHeaderBackgroundMode; ///< How do we paint group header background ? 870 QColor mGroupHeaderBackgroundColor; ///< The background color of the message group, used only if CustomColor 871 GroupHeaderBackgroundStyle mGroupHeaderBackgroundStyle; ///< How do we paint group header background ? 872 ViewHeaderPolicy mViewHeaderPolicy; ///< Do we show the header or not ? 873 int mIconSize; ///< The icon size for this theme, 16 is the default 874 public: 875 /** 876 * Detaches this object from the shared runtime data for columns. 877 */ 878 void detach(); 879 880 /** 881 * Resets the column state (visibility and width) to their default values (the "visible by default" ones). 882 */ 883 void resetColumnState(); 884 885 /** 886 * Resets the column sizes to "default" (subset of resetColumnState() above). 887 */ 888 void resetColumnSizes(); 889 890 /** 891 * Returns the list of columns available in this theme 892 */ 893 const QList<Column *> &columns() const; 894 895 /** 896 * Returns a pointer to the column at the specified index or 0 if there is no such column 897 */ 898 Column *column(int idx) const; 899 900 void moveColumn(int idx, int newPosition); 901 902 /** 903 * Removes all columns from this theme 904 */ 905 void removeAllColumns(); 906 907 /** 908 * Appends a column to this theme 909 */ 910 void addColumn(Column *column); 911 912 /** 913 * Inserts a column to this theme at the specified position. 914 */ 915 void insertColumn(int idx, Column *column); 916 917 /** 918 * Removes the specified message row. The row is NOT deleted. 919 */ 920 void removeColumn(Column *col); 921 922 /** 923 * Returns the group header background mode for this theme. 924 */ 925 GroupHeaderBackgroundMode groupHeaderBackgroundMode() const; 926 927 /** 928 * Sets the group header background mode for this theme. 929 * If you set it to CustomColor then please also setGroupHeaderBackgroundColor() 930 */ 931 void setGroupHeaderBackgroundMode(GroupHeaderBackgroundMode bm); 932 933 /** 934 * Returns the group header background color for this theme. 935 * This color is used only if groupHeaderBackgroundMode() is set to CustomColor. 936 */ 937 const QColor &groupHeaderBackgroundColor() const; 938 939 /** 940 * Sets the group header background color for this theme. 941 * This color is used only if groupHeaderBackgroundMode() is set to CustomColor. 942 */ 943 void setGroupHeaderBackgroundColor(const QColor &clr); 944 945 /** 946 * Returns the group header background style for this theme. 947 * The group header background style makes sense only if groupHeaderBackgroundMode() is 948 * set to something different than Transparent. 949 */ 950 GroupHeaderBackgroundStyle groupHeaderBackgroundStyle() const; 951 952 /** 953 * Sets the group header background style for this theme. 954 * The group header background style makes sense only if groupHeaderBackgroundMode() is 955 * set to something different than Transparent. 956 */ 957 void setGroupHeaderBackgroundStyle(GroupHeaderBackgroundStyle groupHeaderBackgroundStyle); 958 959 /** 960 * Enumerates the available group header background styles. 961 * The returned descriptors are pairs in that the first item is the localized description 962 * of the option value and the second item is the integer option value itself. 963 */ 964 static QVector<QPair<QString, int>> enumerateGroupHeaderBackgroundStyles(); 965 966 /** 967 * Returns the currently set ViewHeaderPolicy 968 */ 969 ViewHeaderPolicy viewHeaderPolicy() const; 970 971 /** 972 * Sets the ViewHeaderPolicy for this theme 973 */ 974 void setViewHeaderPolicy(ViewHeaderPolicy vhp); 975 976 /** 977 * Returns the currently set icon size 978 */ 979 int iconSize() const; 980 981 /** 982 * Sets the icon size for this theme. 983 * Please note that the function will not let you set insane values. 984 * The allowable range is [8,64] 985 */ 986 void setIconSize(int iconSize); 987 988 /** 989 * Enumerates the available view header policy options. 990 * The returned descriptors are pairs in that the first item is the localized description 991 * of the option value and the second item is the integer option value itself. 992 */ 993 static QVector<QPair<QString, int>> enumerateViewHeaderPolicyOptions(); 994 pixmap(ThemeIcon icon)995 inline const QPixmap *pixmap(ThemeIcon icon) const 996 { 997 if (Q_UNLIKELY(mPixmaps.isEmpty())) { 998 populatePixmapCache(); 999 } 1000 return mPixmaps[icon]; 1001 } 1002 1003 protected: 1004 /** 1005 * Pure virtual reimplemented from OptionSet. 1006 */ 1007 void save(QDataStream &stream) const override; 1008 1009 /** 1010 * Pure virtual reimplemented from OptionSet. 1011 */ 1012 bool load(QDataStream &stream) override; 1013 1014 void clearPixmapCache() const; 1015 void populatePixmapCache() const; 1016 }; 1017 } // namespace Core 1018 } // namespace MessageList 1019 1020