+void UiStyle::updateSystemTimestampFormat()
+{
+ // Does the system locale use AM/PM designators? For example:
+ // AM/PM: h:mm AP
+ // AM/PM: hh:mm a
+ // 24-hour: h:mm
+ // 24-hour: hh:mm ADD things
+ // For timestamp format, see https://doc.qt.io/qt-5/qdatetime.html#toString
+ // This won't update if the system locale is changed while Quassel is running. If need be,
+ // Quassel could hook into notifications of changing system locale to update this.
+ //
+ // Match any AP or A designation if on a word boundary, including underscores.
+ // .*(\b|_)(A|AP)(\b|_).*
+ // .* Match any number of characters
+ // \b Match a word boundary, i.e. "AAA.BBB", "." is matched
+ // _ Match the literal character '_' (not considered a word boundary)
+ // (X|Y) Match either X or Y, exactly
+ //
+ // Note that '\' must be escaped as '\\'
+ // QRegExp does not support (?> ...), so it's replaced with standard matching, (...)
+ // Helpful interactive website for debugging and explaining: https://regex101.com/
+ const QRegExp regExpMatchAMPM(".*(\\b|_)(A|AP)(\\b|_).*", Qt::CaseInsensitive);
+
+ if (regExpMatchAMPM.exactMatch(QLocale().timeFormat(QLocale::ShortFormat))) {
+ // AM/PM style used
+ _systemTimestampFormatString = " h:mm:ss ap";
+ }
+ else {
+ // 24-hour style used
+ _systemTimestampFormatString = " hh:mm:ss";
+ }
+ // Include a space to give the timestamp a small bit of padding between the border of the chat
+ // buffer window and the numbers. Helps with readability.
+ // If you change this to include brackets, e.g. "[hh:mm:ss]", also update
+ // ChatScene::updateTimestampHasBrackets() to true or false as needed!
+}
+
+// FIXME The following should trigger a reload/refresh of the chat view.
+void UiStyle::setUseCustomTimestampFormat(bool enabled)
+{
+ if (_useCustomTimestampFormat != enabled) {
+ _useCustomTimestampFormat = enabled;
+ }
+}
+
+void UiStyle::setTimestampFormatString(const QString& format)
+{
+ if (_timestampFormatString != format) {
+ _timestampFormatString = format;
+ }
+}
+
+void UiStyle::setSenderPrefixDisplay(UiStyle::SenderPrefixMode mode)
+{
+ if (_senderPrefixDisplay != mode) {
+ _senderPrefixDisplay = mode;
+ }
+}
+
+void UiStyle::enableSenderBrackets(bool enabled)
+{
+ if (_showSenderBrackets != enabled) {
+ _showSenderBrackets = enabled;
+ }
+}
+
+void UiStyle::allowMircColorsChanged(const QVariant& v)
+{
+ _allowMircColors = v.toBool();
+ emit changed();
+}
+
+/******** ItemView Styling *******/
+
+void UiStyle::showItemViewIconsChanged(const QVariant& v)
+{
+ _showBufferViewIcons = _showNickViewIcons = v.toBool();
+}
+
+QVariant UiStyle::bufferViewItemData(const QModelIndex& index, int role) const
+{
+ BufferInfo::Type type = (BufferInfo::Type)index.data(NetworkModel::BufferTypeRole).toInt();
+ bool isActive = index.data(NetworkModel::ItemActiveRole).toBool();
+
+ if (role == Qt::DecorationRole) {
+ if (!_showBufferViewIcons)
+ return QVariant();
+
+ switch (type) {
+ case BufferInfo::ChannelBuffer:
+ if (isActive)
+ return _channelJoinedIcon;
+ else
+ return _channelPartedIcon;
+ case BufferInfo::QueryBuffer:
+ if (!isActive)
+ return _userOfflineIcon;
+ if (index.data(NetworkModel::UserAwayRole).toBool())
+ return _userAwayIcon;
+ else
+ return _userOnlineIcon;
+ default:
+ return QVariant();
+ }
+ }
+
+ ItemFormatType fmtType = ItemFormatType::BufferViewItem;
+ switch (type) {
+ case BufferInfo::StatusBuffer:
+ fmtType |= ItemFormatType::NetworkItem;
+ break;
+ case BufferInfo::ChannelBuffer:
+ fmtType |= ItemFormatType::ChannelBufferItem;
+ break;
+ case BufferInfo::QueryBuffer:
+ fmtType |= ItemFormatType::QueryBufferItem;
+ break;
+ default:
+ return QVariant();
+ }
+
+ QTextCharFormat fmt = _listItemFormats.value(ItemFormatType::BufferViewItem);
+ fmt.merge(_listItemFormats.value(fmtType));
+
+ BufferInfo::ActivityLevel activity = (BufferInfo::ActivityLevel)index.data(NetworkModel::BufferActivityRole).toInt();
+ if (activity & BufferInfo::Highlight) {
+ fmt.merge(_listItemFormats.value(ItemFormatType::BufferViewItem | ItemFormatType::HighlightedBuffer));
+ fmt.merge(_listItemFormats.value(fmtType | ItemFormatType::HighlightedBuffer));
+ }
+ else if (activity & BufferInfo::NewMessage) {
+ fmt.merge(_listItemFormats.value(ItemFormatType::BufferViewItem | ItemFormatType::UnreadBuffer));
+ fmt.merge(_listItemFormats.value(fmtType | ItemFormatType::UnreadBuffer));
+ }
+ else if (activity & BufferInfo::OtherActivity) {
+ fmt.merge(_listItemFormats.value(ItemFormatType::BufferViewItem | ItemFormatType::ActiveBuffer));
+ fmt.merge(_listItemFormats.value(fmtType | ItemFormatType::ActiveBuffer));
+ }
+ else if (!isActive) {
+ fmt.merge(_listItemFormats.value(ItemFormatType::BufferViewItem | ItemFormatType::InactiveBuffer));
+ fmt.merge(_listItemFormats.value(fmtType | ItemFormatType::InactiveBuffer));
+ }
+ else if (index.data(NetworkModel::UserAwayRole).toBool()) {
+ fmt.merge(_listItemFormats.value(ItemFormatType::BufferViewItem | ItemFormatType::UserAway));
+ fmt.merge(_listItemFormats.value(fmtType | ItemFormatType::UserAway));
+ }
+
+ return itemData(role, fmt);
+}
+
+QVariant UiStyle::nickViewItemData(const QModelIndex& index, int role) const
+{
+ NetworkModel::ItemType type = (NetworkModel::ItemType)index.data(NetworkModel::ItemTypeRole).toInt();
+
+ if (role == Qt::DecorationRole) {
+ if (!_showNickViewIcons)
+ return QVariant();
+
+ switch (type) {
+ case NetworkModel::UserCategoryItemType: {
+ int categoryId = index.data(TreeModel::SortRole).toInt();
+ if (categoryId <= _opIconLimit)
+ return _categoryOpIcon;
+ if (categoryId <= _voiceIconLimit)
+ return _categoryVoiceIcon;
+ return _userOnlineIcon;
+ }
+ case NetworkModel::IrcUserItemType:
+ if (index.data(NetworkModel::ItemActiveRole).toBool())
+ return _userOnlineIcon;
+ else
+ return _userAwayIcon;
+ default:
+ return QVariant();
+ }
+ }
+
+ QTextCharFormat fmt = _listItemFormats.value(ItemFormatType::NickViewItem);
+
+ switch (type) {
+ case NetworkModel::IrcUserItemType:
+ fmt.merge(_listItemFormats.value(ItemFormatType::NickViewItem | ItemFormatType::IrcUserItem));
+ if (!index.data(NetworkModel::ItemActiveRole).toBool()) {
+ fmt.merge(_listItemFormats.value(ItemFormatType::NickViewItem | ItemFormatType::UserAway));
+ fmt.merge(_listItemFormats.value(ItemFormatType::NickViewItem | ItemFormatType::IrcUserItem | ItemFormatType::UserAway));
+ }
+ break;
+ case NetworkModel::UserCategoryItemType:
+ fmt.merge(_listItemFormats.value(ItemFormatType::NickViewItem | ItemFormatType::UserCategoryItem));
+ break;
+ default:
+ return QVariant();
+ }
+
+ return itemData(role, fmt);
+}
+
+QVariant UiStyle::itemData(int role, const QTextCharFormat& format) const
+{
+ switch (role) {
+ case Qt::FontRole:
+ return format.font();
+ case Qt::ForegroundRole:
+ return format.property(QTextFormat::ForegroundBrush);
+ case Qt::BackgroundRole:
+ return format.property(QTextFormat::BackgroundBrush);
+ default:
+ return QVariant();
+ }