Optionally use system locale for chat timestamp
[quassel.git] / src / uisupport / uistyle.cpp
index cba2eda..fd2bee5 100644 (file)
 #include "util.h"
 
 QHash<QString, UiStyle::FormatType> UiStyle::_formatCodes;
-QString UiStyle::_timestampFormatString; /// Timestamp format
-bool UiStyle::_showSenderBrackets;       /// If true, show brackets around sender names
+bool UiStyle::_useCustomTimestampFormat;       /// If true, use the custom timestamp format
+QString UiStyle::_timestampFormatString;       /// Timestamp format
+QString UiStyle::_systemTimestampFormatString; /// Cached copy of system locale timestamp format
+bool UiStyle::_showSenderBrackets;             /// If true, show brackets around sender names
 
 UiStyle::UiStyle(QObject *parent)
     : QObject(parent),
@@ -70,6 +72,7 @@ UiStyle::UiStyle(QObject *parent)
     // Initialize fallback defaults
     // NOTE: If you change this, update qtui/chatviewsettings.h, too.  More explanations available
     // in there.
+    setUseCustomTimestampFormat(false);
     setTimestampFormatString(" hh:mm:ss");
     enableSenderBrackets(true);
 
@@ -168,7 +171,52 @@ QString UiStyle::loadStyleSheet(const QString &styleSheet, bool shouldExist)
     return ss;
 }
 
+
+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::system().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) {
@@ -663,14 +711,35 @@ QString UiStyle::mircToInternal(const QString &mirc_)
 }
 
 
+QString UiStyle::systemTimestampFormatString()
+{
+    if (_systemTimestampFormatString.isEmpty()) {
+        // Calculate and cache the system timestamp format string
+        updateSystemTimestampFormat();
+    }
+    return _systemTimestampFormatString;
+}
+
+
+QString UiStyle::timestampFormatString()
+{
+    if (useCustomTimestampFormat()) {
+        return _timestampFormatString;
+    } else {
+        return systemTimestampFormatString();
+    }
+}
+
+
 /***********************************************************************************/
 UiStyle::StyledMessage::StyledMessage(const Message &msg)
     : Message(msg)
 {
-    if (type() == Message::Plain)
+    if (type() == Message::Plain || type() == Message::Action)
         _senderHash = 0xff;
     else
-        _senderHash = 0x00;  // this means we never compute the hash for msgs that aren't plain
+        _senderHash = 0x00;
+    // This means we never compute the hash for msgs that aren't Plain or Action
 }