X-Git-Url: https://git.quassel-irc.org/?p=quassel.git;a=blobdiff_plain;f=src%2Fuisupport%2Fuistyle.h;h=7d1a8bcd285414d4b2565e12b431f943aa233749;hp=769222793d53afe64464ca325dac8dd7a9cecede;hb=ac7a58dd970833da2336f6ce035ec55515bac0f1;hpb=1566f62849f9011656d9111b99f023d694bb8805 diff --git a/src/uisupport/uistyle.h b/src/uisupport/uistyle.h index 76922279..7d1a8bcd 100644 --- a/src/uisupport/uistyle.h +++ b/src/uisupport/uistyle.h @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2005-09 by the Quassel Project * + * Copyright (C) 2005-2016 by the Quassel Project * * devel@quassel-irc.org * * * * This program is free software; you can redistribute it and/or modify * @@ -15,166 +15,392 @@ * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ -#ifndef UISTYLE_H -#define UISTYLE_H +#pragma once + +#include +#include #include #include +#include +#include #include #include -#include +#include +#include +#include "bufferinfo.h" #include "message.h" +#include "networkmodel.h" #include "settings.h" -class UiStyle { - Q_DECLARE_TR_FUNCTIONS(UiStyle) +class UiStyle : public QObject +{ + Q_OBJECT public: - UiStyle(const QString &settingsKey); - virtual ~UiStyle(); - - typedef QList > FormatList; - - //! This enumerates the possible formats a text element may have. */ - /** These formats are ordered on increasing importance, in cases where a given property is specified - * by multiple active formats. - * \NOTE: Do not change/add values here without also adapting the relevant - * methods in this class (in particular mergedFormat())! - * Also, we _do_ rely on certain properties of these values in styleString() and friends! - */ - enum FormatType { - None = 0x00000000, - Invalid = 0x11111111, - // Message Formats (mutually exclusive!) - PlainMsg = 0x00000001, - NoticeMsg = 0x00000002, - ServerMsg = 0x00000003, - ErrorMsg = 0x00000004, - JoinMsg = 0x00000005, - PartMsg = 0x00000006, - QuitMsg = 0x00000007, - KickMsg = 0x00000008, - RenameMsg = 0x00000009, - ModeMsg = 0x0000000a, - ActionMsg = 0x0000000b, - // Standard Formats - Bold = 0x00000010, - Italic = 0x00000020, - Underline = 0x00000040, - Reverse = 0x00000080, - // Individual parts of a message - Timestamp = 0x00000100, - Sender = 0x00000200, - Nick = 0x00000400, - Hostmask = 0x00000800, - ChannelName = 0x00001000, - ModeFlags = 0x00002000, - // URL is special, we want that to take precedence over the rest... - Url = 0x00100000, - // Colors - FgCol00 = 0x00400000, - FgCol01 = 0x01400000, - FgCol02 = 0x02400000, - FgCol03 = 0x03400000, - FgCol04 = 0x04400000, - FgCol05 = 0x05400000, - FgCol06 = 0x06400000, - FgCol07 = 0x07400000, - FgCol08 = 0x08400000, - FgCol09 = 0x09400000, - FgCol10 = 0x0a400000, - FgCol11 = 0x0b400000, - FgCol12 = 0x0c400000, - FgCol13 = 0x0d400000, - FgCol14 = 0x0e400000, - FgCol15 = 0x0f400000, - - BgCol00 = 0x00800000, - BgCol01 = 0x10800000, - BgCol02 = 0x20800000, - BgCol03 = 0x30800000, - BgCol04 = 0x40800000, - BgCol05 = 0x50800000, - BgCol06 = 0x60800000, - BgCol07 = 0x70800000, - BgCol08 = 0x80800000, - BgCol09 = 0x90800000, - BgCol10 = 0xa0800000, - BgCol11 = 0xb0800000, - BgCol12 = 0xc0800000, - BgCol13 = 0xd0800000, - BgCol14 = 0xe0800000, - BgCol15 = 0xf0800000 - - }; - - struct UrlInfo { - int start, end; - QUrl url; - }; - - struct StyledString { - QString plainText; - FormatList formatList; // starting pos, ftypes - }; - - class StyledMessage; - - StyledString styleString(const QString &); - QString mircToInternal(const QString &) const; - - void setFormat(FormatType, QTextCharFormat, Settings::Mode mode/* = Settings::Custom*/); - QTextCharFormat format(FormatType, Settings::Mode mode = Settings::Custom) const; - QTextCharFormat mergedFormat(quint32 formatType); - QFontMetricsF *fontMetrics(quint32 formatType); - - FormatType formatType(const QString &code) const; - QString formatCode(FormatType) const; - - inline QFont defaultFont() const { return _defaultFont; } - - QList toTextLayoutList(const FormatList &, int textLength); + UiStyle(QObject *parent = 0); + virtual ~UiStyle(); + + //! This enumerates the possible formats a text element may have. */ + /** These formats are ordered on increasing importance, in cases where a given property is specified + * by multiple active formats. + * \NOTE: Do not change/add values here without also adapting the relevant + * methods in this class (in particular mergedFormat())! + * Also, we _do_ rely on certain properties of these values in styleString() and friends! + */ + enum class FormatType : quint32 { + Base = 0x00000000, + Invalid = 0xffffffff, + + // Message Formats (mutually exclusive!) + PlainMsg = 0x00000001, + NoticeMsg = 0x00000002, + ActionMsg = 0x00000003, + NickMsg = 0x00000004, + ModeMsg = 0x00000005, + JoinMsg = 0x00000006, + PartMsg = 0x00000007, + QuitMsg = 0x00000008, + KickMsg = 0x00000009, + KillMsg = 0x0000000a, + ServerMsg = 0x0000000b, + InfoMsg = 0x0000000c, + ErrorMsg = 0x0000000d, + DayChangeMsg = 0x0000000e, + TopicMsg = 0x0000000f, + NetsplitJoinMsg = 0x00000010, + NetsplitQuitMsg = 0x00000020, + InviteMsg = 0x00000030, + + // Standard Formats + Bold = 0x00000100, + Italic = 0x00000200, + Underline = 0x00000400, + Reverse = 0x00000800, + + // Individual parts of a message + Timestamp = 0x00001000, + Sender = 0x00002000, + Contents = 0x00004000, + Nick = 0x00008000, + Hostmask = 0x00010000, + ChannelName = 0x00020000, + ModeFlags = 0x00040000, + + // URL is special, we want that to take precedence over the rest... + Url = 0x00080000 + + // mIRC Colors - we assume those to be present only in plain contents + // foreground: 0x0.400000 + // background: 0x.0800000 + }; + + enum class MessageLabel : quint32 { + None = 0x00000000, + OwnMsg = 0x00000001, + Highlight = 0x00000002, + Selected = 0x00000004 // must be last! + }; + + enum class ItemFormatType : quint32 { + None = 0x00000000, + + BufferViewItem = 0x00000001, + NickViewItem = 0x00000002, + + NetworkItem = 0x00000010, + ChannelBufferItem = 0x00000020, + QueryBufferItem = 0x00000040, + IrcUserItem = 0x00000080, + UserCategoryItem = 0x00000100, + + InactiveBuffer = 0x00001000, + ActiveBuffer = 0x00002000, + UnreadBuffer = 0x00004000, + HighlightedBuffer = 0x00008000, + UserAway = 0x00010000, + + Invalid = 0xffffffff + }; + + enum class ColorRole { + MarkerLine, + // Sender colors (16 + self) + // These aren't used directly to avoid having storing all of the sender color options in the + // rendering routine of each item. Also, I couldn't figure out how to do that. + // It would be nice to have the UseSenderColors preference also toggle sender colors set by + // themes, so hopefully this can be extended in the future. + // Furthermore, using this palette directly would mean separate sets of colors couldn't be + // used for different message types. + SenderColorSelf, + SenderColor00, + SenderColor01, + SenderColor02, + SenderColor03, + SenderColor04, + SenderColor05, + SenderColor06, + SenderColor07, + SenderColor08, + SenderColor09, + SenderColor0a, + SenderColor0b, + SenderColor0c, + SenderColor0d, + SenderColor0e, + SenderColor0f, + NumRoles // must be last! + }; + + struct Format { + FormatType type; + }; + + using FormatList = std::vector>; + + struct StyledString { + QString plainText; + FormatList formatList; // starting pos, ftypes + }; + + class StyledMessage; + + /** + * List of default sender colors + * + * In order from 1 - 16, matching the Sender## format in the settings file. + * Don't change the length or values of the colors without updating the UI and color roles, too. + * + * @see ../qtui/settingspages/chatviewsettingspage.ui + * @see UiStyle::ColorRole + */ + const QList defaultSenderColors = QList { + QColor(204, 0, 0), /// Sender00 + QColor( 0, 108, 173), /// Sender01 + QColor( 77, 153, 0), /// Sender02 + QColor(102, 0, 204), /// Sender03 + QColor(166, 125, 0), /// Sender04 + QColor( 0, 153, 39), /// Sender05 + QColor( 0, 48, 192), /// Sender06 + QColor(204, 0, 154), /// Sender07 + QColor(185, 70, 0), /// Sender08 + QColor(134, 153, 0), /// Sender09 + QColor( 20, 153, 0), /// Sender10 + QColor( 0, 153, 96), /// Sender11 + QColor( 0, 108, 173), /// Sender12 + QColor( 0, 153, 204), /// Sender13 + QColor(179, 0, 204), /// Sender14 + QColor(204, 0, 77), /// Sender15 + }; + // Explicitly declare QList type for defaultSenderColors, otherwise error C2797 + // "list initialization inside member initializer list" will occur in Windows builds with Visual + // Studio's compiler. + // + // See https://blogs.msdn.microsoft.com/vcblog/2014/08/19/the-future-of-non-static-data-member-initialization/ + // Note: Qt Creator flags this as invalid unless you set Clang in + // Settings -> C++ -> Code Model -> Code Completion and Semantic Highlighting -> C + // + // See https://bugreports.qt.io/browse/QTCREATORBUG-1902 + + /** + * Default sender color for sent messages + */ + const QColor defaultSenderColorSelf = QColor(0, 0, 0); + + static FormatType formatType(Message::Type msgType); + static StyledString styleString(const QString &string, FormatType baseFormat = FormatType::Base); + static QString mircToInternal(const QString &); + + /** + * Gets if a custom timestamp format is used. + * + * @return True if custom timestamp format used, otherwise false + */ + static inline bool useCustomTimestampFormat() { return _useCustomTimestampFormat; } + + /** + * Gets the format string for chat log timestamps according to the system locale. + * + * This will return " hh:mm:ss" for system locales with 24-hour time or " h:mm:ss AP" for + * systems with 12-hour time. + * + * @return String representing timestamp format according to system locale, e.g. " hh:mm:ss" + */ + static QString systemTimestampFormatString(); + + /** + * Gets the format string for chat log timestamps, either system locale or custom. + * + * Depending on useCustomTimestampFormat(), this will return either the system locale based + * time format, or the custom user-specified string. + * + * @return String representing timestamp format, e.g. "[hh:mm:ss]" or " hh:mm:ss" + */ + static QString timestampFormatString(); + + QTextCharFormat format(FormatType formatType, MessageLabel messageLabel) const; + QFontMetricsF *fontMetrics(FormatType formatType, MessageLabel messageLabel) const; + + QList toTextLayoutList(const FormatList &, int textLength, MessageLabel messageLabel) const; + + inline const QBrush &brush(ColorRole role) const { return _uiStylePalette.at((int)role); } + inline void setBrush(ColorRole role, const QBrush &brush) { _uiStylePalette[(int)role] = brush; } + + QVariant bufferViewItemData(const QModelIndex &networkModelIndex, int role) const; + QVariant nickViewItemData(const QModelIndex &networkModelIndex, int role) const; + +public slots: + void reload(); + +signals: + void changed(); protected: + void loadStyleSheet(); + QString loadStyleSheet(const QString &name, bool shouldExist = false); + + QTextCharFormat format(quint64 key) const; + QTextCharFormat cachedFormat(FormatType formatType, MessageLabel messageLabel) const; + void setCachedFormat(const QTextCharFormat &format, FormatType formatType, MessageLabel messageLabel) const; + void mergeFormat(QTextCharFormat &format, FormatType formatType, MessageLabel messageLabel) const; + void mergeSubElementFormat(QTextCharFormat &format, FormatType formatType, MessageLabel messageLabel) const; + + static FormatType formatType(const QString &code); + static QString formatCode(FormatType); + + /** + * Cache the system locale timestamp format string + * + * Based on whether or not AM/PM designators are used in the QLocale::system().timeFormat(), + * this extends the system locale timestamp format string to include seconds. + * + * @see UiStyle::systemTimestampFormatString() + */ + static void updateSystemTimestampFormat(); + + /** + * Updates the local setting cache of whether or not to use the custom timestamp format + * + * @param[in] enabled If true, custom timestamp format used, otherwise false + */ + static void setUseCustomTimestampFormat(bool enabled); + + /** + * Updates the local setting cache of the timestamp format string + * + * @param[in] format Timestamp format string + */ + static void setTimestampFormatString(const QString &format); + /** + * Updates the local setting cache of whether or not to show sender prefixmodes + * + * @param[in] enabled If true, sender prefixmodes are enabled, otherwise false. + */ + static void enableSenderPrefixes(bool enabled); + + /** + * Updates the local setting cache of whether or not to show sender brackets + * + * @param[in] enabled If true, sender brackets are enabled, otherwise false. + */ + static void enableSenderBrackets(bool enabled); + + QVariant itemData(int role, const QTextCharFormat &format) const; + +private slots: + void allowMircColorsChanged(const QVariant &); + void showItemViewIconsChanged(const QVariant &); + private: - QFont _defaultFont; - QTextCharFormat _defaultPlainFormat; - QHash _defaultFormats; - QHash _customFormats; - QHash _cachedFormats; - QHash _cachedFontMetrics; - QHash _formatCodes; - - QString _settingsKey; + QVector _uiStylePalette; + QBrush _markerLineBrush; + QHash _formats; + mutable QHash _formatCache; + mutable QHash _metricsCache; + QHash _listItemFormats; + static QHash _formatCodes; + static bool _useCustomTimestampFormat; /// If true, use the custom timestamp format + static QString _systemTimestampFormatString; /// Cached copy of system locale timestamp format + static QString _timestampFormatString; /// Timestamp format string + static bool _showSenderPrefixes; /// If true, show prefixmodes before sender names + static bool _showSenderBrackets; /// If true, show brackets around sender names + + QIcon _channelJoinedIcon; + QIcon _channelPartedIcon; + QIcon _userOfflineIcon; + QIcon _userOnlineIcon; + QIcon _userAwayIcon; + QIcon _categoryOpIcon; + QIcon _categoryVoiceIcon; + int _opIconLimit; + int _voiceIconLimit; + bool _showNickViewIcons; + bool _showBufferViewIcons; + bool _allowMircColors; }; -class UiStyle::StyledMessage : public Message { + +class UiStyle::StyledMessage : public Message +{ + Q_DECLARE_TR_FUNCTIONS(UiStyle::StyledMessage) + public: - explicit StyledMessage(const Message &message); + explicit StyledMessage(const Message &message); + + QString decoratedTimestamp() const; + QString plainSender() const; //!< Nickname (no decorations) for Plain and Notice, empty else + QString decoratedSender() const; + const QString &plainContents() const; - bool inline needsStyling() const { return _contents.plainText.isNull(); } - void style(UiStyle *style); + const FormatList &contentsFormatList() const; - QString decoratedTimestamp() const; - QString plainSender() const; //!< Nickname (no decorations) for Plain and Notice, empty else - QString decoratedSender() const; - const QString &plainContents() const { return _contents.plainText; } + quint8 senderHash() const; - inline FormatType timestampFormat() const { return UiStyle::Timestamp; } - FormatType senderFormat() const; - inline const FormatList &contentsFormatList() const { return _contents.formatList; } +protected: + void style() const; private: - StyledString _contents; + mutable StyledString _contents; + mutable quint8 _senderHash; }; +#if QT_VERSION < 0x050000 +uint qHash(UiStyle::ItemFormatType key); +#else +uint qHash(UiStyle::ItemFormatType key, uint seed); +#endif + +// ---- Operators for dealing with enums ---------------------------------------------------------- + +UiStyle::FormatType operator|(UiStyle::FormatType lhs, UiStyle::FormatType rhs); +UiStyle::FormatType& operator|=(UiStyle::FormatType &lhs, UiStyle::FormatType rhs); +UiStyle::FormatType operator|(UiStyle::FormatType lhs, quint32 rhs); +UiStyle::FormatType& operator|=(UiStyle::FormatType &lhs, quint32 rhs); +UiStyle::FormatType operator&(UiStyle::FormatType lhs, UiStyle::FormatType rhs); +UiStyle::FormatType& operator&=(UiStyle::FormatType &lhs, UiStyle::FormatType rhs); +UiStyle::FormatType operator&(UiStyle::FormatType lhs, quint32 rhs); +UiStyle::FormatType& operator&=(UiStyle::FormatType &lhs, quint32 rhs); +UiStyle::FormatType& operator^=(UiStyle::FormatType &lhs, UiStyle::FormatType rhs); + +UiStyle::MessageLabel operator|(UiStyle::MessageLabel lhs, UiStyle::MessageLabel rhs); +UiStyle::MessageLabel& operator|=(UiStyle::MessageLabel &lhs, UiStyle::MessageLabel rhs); +UiStyle::MessageLabel operator&(UiStyle::MessageLabel lhs, quint32 rhs); +UiStyle::MessageLabel& operator&=(UiStyle::MessageLabel &lhs, UiStyle::MessageLabel rhs); + +// Shifts the label into the upper half of the return value +quint64 operator|(UiStyle::FormatType lhs, UiStyle::MessageLabel rhs); + +UiStyle::ItemFormatType operator|(UiStyle::ItemFormatType lhs, UiStyle::ItemFormatType rhs); +UiStyle::ItemFormatType& operator|=(UiStyle::ItemFormatType &lhs, UiStyle::ItemFormatType rhs); + +// ---- Allow for FormatList in QVariant ---------------------------------------------------------- + QDataStream &operator<<(QDataStream &out, const UiStyle::FormatList &formatList); QDataStream &operator>>(QDataStream &in, UiStyle::FormatList &formatList); Q_DECLARE_METATYPE(UiStyle::FormatList) - -#endif +Q_DECLARE_METATYPE(UiStyle::MessageLabel)