Prechádzať zdrojové kódy

Properly adapt the userstatusselectormodel, eliminate hacks, make code more declarative

Signed-off-by: Claudio Cambra <claudio.cambra@gmail.com>
Claudio Cambra 3 rokov pred
rodič
commit
cf372b43ac

+ 1 - 1
src/gui/BasicComboBox.qml

@@ -86,7 +86,7 @@ ComboBox {
         id: clearStatusDelegate
         width: clearComboBox.width
         contentItem: Label {
-            text: modelData
+            text: modelData.display
             color: Style.ncTextColor
             elide: Text.ElideRight
             verticalAlignment: Text.AlignVCenter

+ 18 - 16
src/gui/UserStatusSelector.qml

@@ -53,12 +53,12 @@ ColumnLayout {
         }
 
         UserStatusSelectorButton {
-            checked: NC.UserStatus.Online == userStatusSelectorModel.onlineStatus
+            checked: NC.UserStatus.Online === userStatusSelectorModel.onlineStatus
             checkable: true
             icon.source: userStatusSelectorModel.onlineIcon
             icon.color: "transparent"
             text: qsTr("Online")
-            onClicked: userStatusSelectorModel.setOnlineStatus(NC.UserStatus.Online)
+            onClicked: userStatusSelectorModel.onlineStatus = NC.UserStatus.Online
 
             Layout.fillWidth: true
             implicitWidth: 200 // Pretty much a hack to ensure all the buttons are equal in width
@@ -67,12 +67,12 @@ ColumnLayout {
             Component.onCompleted: topButtonsLayout.updateMaxButtonHeight(implicitHeight)
         }
         UserStatusSelectorButton {
-            checked: NC.UserStatus.Away == userStatusSelectorModel.onlineStatus
+            checked: NC.UserStatus.Away === userStatusSelectorModel.onlineStatus
             checkable: true
             icon.source: userStatusSelectorModel.awayIcon
             icon.color: "transparent"
             text: qsTr("Away")
-            onClicked: userStatusSelectorModel.setOnlineStatus(NC.UserStatus.Away)
+            onClicked: userStatusSelectorModel.onlineStatus = NC.UserStatus.Away
 
             Layout.fillWidth: true
             implicitWidth: 200 // Pretty much a hack to ensure all the buttons are equal in width
@@ -82,13 +82,13 @@ ColumnLayout {
             
         }
         UserStatusSelectorButton {
-            checked: NC.UserStatus.DoNotDisturb == userStatusSelectorModel.onlineStatus
+            checked: NC.UserStatus.DoNotDisturb === userStatusSelectorModel.onlineStatus
             checkable: true
             icon.source: userStatusSelectorModel.dndIcon
             icon.color: "transparent"
             text: qsTr("Do not disturb")
             secondaryText: qsTr("Mute all notifications")
-            onClicked: userStatusSelectorModel.setOnlineStatus(NC.UserStatus.DoNotDisturb)
+            onClicked: userStatusSelectorModel.onlineStatus = NC.UserStatus.DoNotDisturb
 
             Layout.fillWidth: true
             implicitWidth: 200 // Pretty much a hack to ensure all the buttons are equal in width
@@ -97,13 +97,13 @@ ColumnLayout {
             Component.onCompleted: topButtonsLayout.updateMaxButtonHeight(implicitHeight)
         }
         UserStatusSelectorButton {
-            checked: NC.UserStatus.Invisible == userStatusSelectorModel.onlineStatus
+            checked: NC.UserStatus.Invisible === userStatusSelectorModel.onlineStatus
             checkable: true
             icon.source: userStatusSelectorModel.invisibleIcon
             icon.color: "transparent"
             text: qsTr("Invisible")
             secondaryText: qsTr("Appear offline")
-            onClicked: userStatusSelectorModel.setOnlineStatus(NC.UserStatus.Invisible)
+            onClicked: userStatusSelectorModel.onlineStatus = NC.UserStatus.Invisible
 
             Layout.fillWidth: true
             implicitWidth: 200 // Pretty much a hack to ensure all the buttons are equal in width
@@ -214,7 +214,7 @@ ColumnLayout {
             text: userStatusSelectorModel.userStatusMessage
             color: Style.ncTextColor
             selectByMouse: true
-            onEditingFinished: userStatusSelectorModel.setUserStatusMessage(text)
+            onEditingFinished: userStatusSelectorModel.userStatusMessage = text
 
             property color borderColor: activeFocus ? Style.ncBlue : Style.menuBorder
 
@@ -247,7 +247,7 @@ ColumnLayout {
     }
 
     Repeater {
-        model: userStatusSelectorModel.predefinedStatusesCount
+        model: userStatusSelectorModel.predefinedStatuses
 
         PredefinedStatusButton {
             id: control
@@ -256,9 +256,9 @@ ColumnLayout {
             Layout.rightMargin: Style.standardSpacing
             internalSpacing: Style.standardSpacing + fieldButton.padding + userStatusMessageTextField.padding
 
-            emoji: userStatusSelectorModel.predefinedStatus(index).icon
-            text: "<b>" + userStatusSelectorModel.predefinedStatus(index).message + "</b> – " + userStatusSelectorModel.predefinedStatusClearAt(index)
-            onClicked: userStatusSelectorModel.setPredefinedStatus(index)
+            emoji: modelData.icon
+            text: "<b>%1</b> – %2".arg(modelData.message).arg(userStatusSelectorModel.clearAtReadable(modelData))
+            onClicked: userStatusSelectorModel.setPredefinedStatus(modelData)
         }
     }
 
@@ -279,9 +279,11 @@ ColumnLayout {
            id: clearComboBox
 
            Layout.fillWidth: true
-           model: userStatusSelectorModel.clearAtValues
-           displayText: userStatusSelectorModel.clearAt
-           onActivated: userStatusSelectorModel.setClearAt(index)
+           model: userStatusSelectorModel.clearStageTypes
+           textRole: "display"
+           valueRole: "clearStageType"
+           displayText: userStatusSelectorModel.clearAtDisplayString
+           onActivated: userStatusSelectorModel.setClearAt(currentValue)
        }
    }
 

+ 27 - 33
src/gui/userstatusselectormodel.cpp

@@ -15,9 +15,7 @@
 #include "userstatusselectormodel.h"
 #include "tray/usermodel.h"
 
-#include <ocsuserstatusconnector.h>
 #include <qnamespace.h>
-#include <userstatusconnector.h>
 #include <theme.h>
 
 #include <QDateTime>
@@ -250,7 +248,7 @@ void UserStatusSelectorModel::onUserStatusFetched(const UserStatus &userStatus)
 
     emit userStatusChanged();
     emit onlineStatusChanged();
-    emit clearAtChanged();
+    emit clearAtDisplayStringChanged();
 }
 
 Optional<ClearAt> UserStatusSelectorModel::clearStageTypeToDateTime(ClearStageType type) const
@@ -319,36 +317,27 @@ void UserStatusSelectorModel::clearUserStatus()
     _userStatusConnector->clearMessage();
 }
 
-void UserStatusSelectorModel::onPredefinedStatusesFetched(const std::vector<UserStatus> &statuses)
+void UserStatusSelectorModel::onPredefinedStatusesFetched(const QVector<UserStatus> &statuses)
 {
     _predefinedStatuses = statuses;
     emit predefinedStatusesChanged();
 }
 
-UserStatus UserStatusSelectorModel::predefinedStatus(int index) const
+QVector<UserStatus> UserStatusSelectorModel::predefinedStatuses() const
 {
-    Q_ASSERT(0 <= index && index < static_cast<int>(_predefinedStatuses.size()));
-    return _predefinedStatuses[index];
+    return _predefinedStatuses;
 }
 
-int UserStatusSelectorModel::predefinedStatusesCount() const
+void UserStatusSelectorModel::setPredefinedStatus(const UserStatus &predefinedStatus)
 {
-    return static_cast<int>(_predefinedStatuses.size());
-}
-
-void UserStatusSelectorModel::setPredefinedStatus(int index)
-{
-    Q_ASSERT(0 <= index && index < static_cast<int>(_predefinedStatuses.size()));
-
     _userStatus.setMessagePredefined(true);
-    const auto predefinedStatus = _predefinedStatuses[index];
     _userStatus.setId(predefinedStatus.id());
     _userStatus.setMessage(predefinedStatus.message());
     _userStatus.setIcon(predefinedStatus.icon());
     _userStatus.setClearAt(predefinedStatus.clearAt());
 
     emit userStatusChanged();
-    emit clearAtChanged();
+    emit clearAtDisplayStringChanged();
 }
 
 QString UserStatusSelectorModel::clearAtStageToString(ClearStageType stage) const
@@ -377,21 +366,24 @@ QString UserStatusSelectorModel::clearAtStageToString(ClearStageType stage) cons
     }
 }
 
-QStringList UserStatusSelectorModel::clearAtValues() const
+QVariantList UserStatusSelectorModel::clearStageTypes() const
 {
-    QStringList clearAtStages;
-    std::transform(_clearStages.begin(), _clearStages.end(),
-        std::back_inserter(clearAtStages),
-        [this](const ClearStageType &stage) { return clearAtStageToString(stage); });
+    QVariantList clearStageTypes;
 
-    return clearAtStages;
+    for(const auto clearStageType : _clearStages) {
+        QVariantMap clearStageToAdd;
+        clearStageToAdd.insert(QStringLiteral("display"), clearAtStageToString(clearStageType));
+        clearStageToAdd.insert(QStringLiteral("clearStageType"), QVariant::fromValue(clearStageType));
+        clearStageTypes.append(clearStageToAdd);
+    }
+
+    return clearStageTypes;
 }
 
-void UserStatusSelectorModel::setClearAt(int index)
+void UserStatusSelectorModel::setClearAt(const ClearStageType clearStageType)
 {
-    Q_ASSERT(0 <= index && index < static_cast<int>(_clearStages.size()));
-    _userStatus.setClearAt(clearStageTypeToDateTime(_clearStages[index]));
-    emit clearAtChanged();
+    _userStatus.setClearAt(clearStageTypeToDateTime(clearStageType));
+    emit clearAtDisplayStringChanged();
 }
 
 QString UserStatusSelectorModel::errorMessage() const
@@ -427,6 +419,12 @@ QString UserStatusSelectorModel::timeDifferenceToString(int differenceSecs) cons
     }
 }
 
+QString UserStatusSelectorModel::clearAtReadable(const UserStatus &status) const
+{
+    const auto clearAt = status.clearAt();
+    return clearAtReadable(clearAt);
+}
+
 QString UserStatusSelectorModel::clearAtReadable(const Optional<ClearAt> &clearAt) const
 {
     if (clearAt) {
@@ -456,13 +454,9 @@ QString UserStatusSelectorModel::clearAtReadable(const Optional<ClearAt> &clearA
     return tr("Don't clear");
 }
 
-QString UserStatusSelectorModel::predefinedStatusClearAt(int index) const
-{
-    return clearAtReadable(predefinedStatus(index).clearAt());
-}
-
-QString UserStatusSelectorModel::clearAt() const
+QString UserStatusSelectorModel::clearAtDisplayString() const
 {
     return clearAtReadable(_userStatus.clearAt());
 }
+
 }

+ 33 - 32
src/gui/userstatusselectormodel.h

@@ -17,6 +17,7 @@
 #include "common/result.h"
 
 #include <userstatusconnector.h>
+#include <ocsuserstatusconnector.h>
 #include <datetimeprovider.h>
 
 #include <QObject>
@@ -33,12 +34,12 @@ class UserStatusSelectorModel : public QObject
 {
     Q_OBJECT
 
-    Q_PROPERTY(QString userStatusMessage READ userStatusMessage NOTIFY userStatusChanged)
+    Q_PROPERTY(QString userStatusMessage READ userStatusMessage WRITE setUserStatusMessage NOTIFY userStatusChanged)
     Q_PROPERTY(QString userStatusEmoji READ userStatusEmoji WRITE setUserStatusEmoji NOTIFY userStatusChanged)
     Q_PROPERTY(OCC::UserStatus::OnlineStatus onlineStatus READ onlineStatus WRITE setOnlineStatus NOTIFY onlineStatusChanged)
-    Q_PROPERTY(int predefinedStatusesCount READ predefinedStatusesCount NOTIFY predefinedStatusesChanged)
-    Q_PROPERTY(QStringList clearAtValues READ clearAtValues CONSTANT)
-    Q_PROPERTY(QString clearAt READ clearAt NOTIFY clearAtChanged)
+    Q_PROPERTY(QVector<OCC::UserStatus> predefinedStatuses READ predefinedStatuses NOTIFY predefinedStatusesChanged)
+    Q_PROPERTY(QVariantList clearStageTypes READ clearStageTypes CONSTANT)
+    Q_PROPERTY(QString clearAtDisplayString READ clearAtDisplayString NOTIFY clearAtDisplayStringChanged)
     Q_PROPERTY(QString errorMessage READ errorMessage NOTIFY errorMessageChanged)
     Q_PROPERTY(QUrl onlineIcon READ onlineIcon CONSTANT)
     Q_PROPERTY(QUrl awayIcon READ awayIcon CONSTANT)
@@ -46,6 +47,16 @@ class UserStatusSelectorModel : public QObject
     Q_PROPERTY(QUrl invisibleIcon READ invisibleIcon CONSTANT)
 
 public:
+    enum class ClearStageType {
+        DontClear,
+        HalfHour,
+        OneHour,
+        FourHour,
+        Today,
+        Week,
+    };
+    Q_ENUM(ClearStageType);
+
     explicit UserStatusSelectorModel(QObject *parent = nullptr);
 
     explicit UserStatusSelectorModel(std::shared_ptr<UserStatusConnector> userStatusConnector,
@@ -62,10 +73,8 @@ public:
     explicit UserStatusSelectorModel(const UserStatus &userStatus,
         QObject *parent = nullptr);
 
-    Q_INVOKABLE void load(int id);
-
     Q_REQUIRED_RESULT UserStatus::OnlineStatus onlineStatus() const;
-    Q_INVOKABLE void setOnlineStatus(OCC::UserStatus::OnlineStatus status);
+    void setOnlineStatus(UserStatus::OnlineStatus status);
 
     Q_REQUIRED_RESULT QUrl onlineIcon() const;
     Q_REQUIRED_RESULT QUrl awayIcon() const;
@@ -73,59 +82,51 @@ public:
     Q_REQUIRED_RESULT QUrl invisibleIcon() const;
 
     Q_REQUIRED_RESULT QString userStatusMessage() const;
-    Q_INVOKABLE void setUserStatusMessage(const QString &message);
-    void setUserStatusEmoji(const QString &emoji);
+    void setUserStatusMessage(const QString &message);
     Q_REQUIRED_RESULT QString userStatusEmoji() const;
+    void setUserStatusEmoji(const QString &emoji);
 
-    Q_INVOKABLE void setUserStatus();
-    Q_INVOKABLE void clearUserStatus();
-
-    Q_REQUIRED_RESULT int predefinedStatusesCount() const;
-    Q_INVOKABLE UserStatus predefinedStatus(int index) const;
-    Q_INVOKABLE QString predefinedStatusClearAt(int index) const;
-    Q_INVOKABLE void setPredefinedStatus(int index);
+    QVector<UserStatus> predefinedStatuses() const;
 
-    Q_REQUIRED_RESULT QStringList clearAtValues() const;
-    Q_REQUIRED_RESULT QString clearAt() const;
-    Q_INVOKABLE void setClearAt(int index);
+    Q_REQUIRED_RESULT QVariantList clearStageTypes() const;
+    Q_REQUIRED_RESULT QString clearAtDisplayString() const;
+    Q_INVOKABLE QString clearAtReadable(const UserStatus &status) const;
 
     Q_REQUIRED_RESULT QString errorMessage() const;
 
+public slots:
+    void load(int id);
+    void setUserStatus();
+    void clearUserStatus();
+    void setClearAt(const ClearStageType clearStageType);
+    void setPredefinedStatus(const UserStatus &predefinedStatus);
+
 signals:
     void errorMessageChanged();
     void userStatusChanged();
     void onlineStatusChanged();
-    void clearAtChanged();
+    void clearAtDisplayStringChanged();
     void predefinedStatusesChanged();
     void finished();
 
 private:
-    enum class ClearStageType {
-        DontClear,
-        HalfHour,
-        OneHour,
-        FourHour,
-        Today,
-        Week
-    };
-
     void init();
     void reset();
     void onUserStatusFetched(const UserStatus &userStatus);
-    void onPredefinedStatusesFetched(const std::vector<UserStatus> &statuses);
+    void onPredefinedStatusesFetched(const QVector<UserStatus> &statuses);
     void onUserStatusSet();
     void onMessageCleared();
     void onError(UserStatusConnector::Error error);
 
-    Q_REQUIRED_RESULT QString clearAtStageToString(ClearStageType stage) const;
     Q_REQUIRED_RESULT QString clearAtReadable(const Optional<ClearAt> &clearAt) const;
+    Q_REQUIRED_RESULT QString clearAtStageToString(ClearStageType stage) const;
     Q_REQUIRED_RESULT QString timeDifferenceToString(int differenceSecs) const;
     Q_REQUIRED_RESULT Optional<ClearAt> clearStageTypeToDateTime(ClearStageType type) const;
     void setError(const QString &reason);
     void clearError();
 
     std::shared_ptr<UserStatusConnector> _userStatusConnector {};
-    std::vector<UserStatus> _predefinedStatuses;
+    QVector<UserStatus> _predefinedStatuses;
     UserStatus _userStatus;
     std::unique_ptr<DateTimeProvider> _dateTimeProvider;
 

+ 3 - 3
src/libsync/ocsuserstatusconnector.cpp

@@ -191,15 +191,15 @@ OCC::UserStatus jsonToUserStatus(QJsonObject jsonObject)
     return userStatus;
 }
 
-std::vector<OCC::UserStatus> jsonToPredefinedStatuses(QJsonArray jsonDataArray)
+QVector<OCC::UserStatus> jsonToPredefinedStatuses(QJsonArray jsonDataArray)
 {
-    std::vector<OCC::UserStatus> statuses;
+    QVector<OCC::UserStatus> statuses;
     for (const auto &jsonEntry : jsonDataArray) {
         Q_ASSERT(jsonEntry.isObject());
         if (!jsonEntry.isObject()) {
             continue;
         }
-        statuses.push_back(jsonToUserStatus(jsonEntry.toObject()));
+        statuses.append(jsonToUserStatus(jsonEntry.toObject()));
     }
 
     return statuses;

+ 3 - 1
src/libsync/userstatusconnector.h

@@ -76,6 +76,8 @@ public:
     Q_REQUIRED_RESULT OnlineStatus state() const;
     Q_REQUIRED_RESULT Optional<ClearAt> clearAt() const;
 
+    QString clearAtDisplayString() const;
+
     void setId(const QString &id);
     void setMessage(const QString &message);
     void setState(OnlineStatus state);
@@ -127,7 +129,7 @@ public:
 
 signals:
     void userStatusFetched(const UserStatus &userStatus);
-    void predefinedStatusesFetched(const std::vector<UserStatus> &statuses);
+    void predefinedStatusesFetched(const QVector<UserStatus> &statuses);
     void userStatusSet();
     void serverUserStatusChanged();
     void messageCleared();

+ 77 - 77
test/testsetuserstatusdialog.cpp

@@ -80,7 +80,7 @@ public:
     }
 
     void setFakePredefinedStatuses(
-        const std::vector<OCC::UserStatus> &statuses)
+        const QVector<OCC::UserStatus> &statuses)
     {
         _predefinedStatuses = statuses;
     }
@@ -122,7 +122,7 @@ public:
 private:
     OCC::UserStatus _userStatusSetByCallerOfSetUserStatus;
     OCC::UserStatus _userStatus;
-    std::vector<OCC::UserStatus> _predefinedStatuses;
+    QVector<OCC::UserStatus> _predefinedStatuses;
     bool _isMessageCleared = false;
     bool _couldNotFetchPredefinedUserStatuses = false;
     bool _couldNotFetchUserStatus = false;
@@ -145,10 +145,10 @@ private:
     QDateTime _dateTime;
 };
 
-static std::vector<OCC::UserStatus>
+static QVector<OCC::UserStatus>
 createFakePredefinedStatuses(const QDateTime &currentTime)
 {
-    std::vector<OCC::UserStatus> statuses;
+    QVector<OCC::UserStatus> statuses;
 
     const QString userStatusId("fake-id");
     const QString userStatusMessage("Predefined status");
@@ -161,8 +161,8 @@ createFakePredefinedStatuses(const QDateTime &currentTime)
     clearAt._timestamp = currentTime.addSecs(60 * 60).toSecsSinceEpoch();
     userStatusClearAt = clearAt;
 
-    statuses.emplace_back(userStatusId, userStatusMessage, userStatusIcon,
-        userStatusState, userStatusMessagePredefined, userStatusClearAt);
+    statuses.append({userStatusId, userStatusMessage, userStatusIcon,
+        userStatusState, userStatusMessagePredefined, userStatusClearAt});
 
     return statuses;
 }
@@ -218,13 +218,13 @@ private slots:
         QCOMPARE(model.userStatusMessage(), userStatusMessage);
         QCOMPARE(model.userStatusEmoji(), userStatusIcon);
         QCOMPARE(model.onlineStatus(), userStatusState);
-        QCOMPARE(model.clearAt(), tr("1 day"));
+        QCOMPARE(model.clearAtDisplayString(), tr("1 day"));
 
         // Were predefined statuses fetched correctly?
-        const auto predefinedStatusesCount = model.predefinedStatusesCount();
+        const auto predefinedStatusesCount = model.predefinedStatuses().count();
         QCOMPARE(predefinedStatusesCount, fakePredefinedStatuses.size());
         for (int i = 0; i < predefinedStatusesCount; ++i) {
-            const auto predefinedStatus = model.predefinedStatus(i);
+            const auto predefinedStatus = model.predefinedStatuses()[i];
             QCOMPARE(predefinedStatus.id(),
                 fakePredefinedStatuses[i].id());
             QCOMPARE(predefinedStatus.message(),
@@ -242,7 +242,7 @@ private slots:
 
         QCOMPARE(model.userStatusMessage(), "");
         QCOMPARE(model.userStatusEmoji(), "😀");
-        QCOMPARE(model.clearAt(), tr("Don't clear"));
+        QCOMPARE(model.clearAtDisplayString(), tr("Don't clear"));
     }
 
     void testCtor_fetchStatusButNoStatusSet_showSensibleDefaults()
@@ -255,7 +255,7 @@ private slots:
         QCOMPARE(model.onlineStatus(), OCC::UserStatus::OnlineStatus::Online);
         QCOMPARE(model.userStatusMessage(), "");
         QCOMPARE(model.userStatusEmoji(), "😀");
-        QCOMPARE(model.clearAt(), tr("Don't clear"));
+        QCOMPARE(model.clearAtDisplayString(), tr("Don't clear"));
     }
 
     void testSetOnlineStatus_emitOnlineStatusChanged()
@@ -284,7 +284,7 @@ private slots:
         model.setOnlineStatus(userStatusState);
         model.setUserStatusMessage(userStatusMessage);
         model.setUserStatusEmoji(userStatusIcon);
-        model.setClearAt(1);
+        model.setClearAt(OCC::UserStatusSelectorModel::ClearStageType::HalfHour);
 
         model.setUserStatus();
         QCOMPARE(finishedSpy.count(), 1);
@@ -305,7 +305,7 @@ private slots:
         auto fakeUserStatusJob = std::make_shared<FakeUserStatusConnector>();
         fakeUserStatusJob->setFakePredefinedStatuses(createFakePredefinedStatuses(createDateTime()));
         OCC::UserStatusSelectorModel model(fakeUserStatusJob);
-        model.setPredefinedStatus(0);
+        model.setPredefinedStatus(model.predefinedStatuses()[0]);
         QSignalSpy finishedSpy(&model, &OCC::UserStatusSelectorModel::finished);
 
         const QString userStatusMessage("Some status");
@@ -313,7 +313,7 @@ private slots:
 
         model.setOnlineStatus(userStatusState);
         model.setUserStatusMessage(userStatusMessage);
-        model.setClearAt(1);
+        model.setClearAt(OCC::UserStatusSelectorModel::ClearStageType::HalfHour);
 
         model.setUserStatus();
         QCOMPARE(finishedSpy.count(), 1);
@@ -333,7 +333,7 @@ private slots:
         auto fakeUserStatusJob = std::make_shared<FakeUserStatusConnector>();
         fakeUserStatusJob->setFakePredefinedStatuses(createFakePredefinedStatuses(createDateTime()));
         OCC::UserStatusSelectorModel model(fakeUserStatusJob);
-        model.setPredefinedStatus(0);
+        model.setPredefinedStatus(model.predefinedStatuses()[0]);
         QSignalSpy finishedSpy(&model, &OCC::UserStatusSelectorModel::finished);
 
         const QString userStatusIcon("❤");
@@ -341,7 +341,7 @@ private slots:
 
         model.setOnlineStatus(userStatusState);
         model.setUserStatusEmoji(userStatusIcon);
-        model.setClearAt(1);
+        model.setClearAt(OCC::UserStatusSelectorModel::ClearStageType::HalfHour);
 
         model.setUserStatus();
         QCOMPARE(finishedSpy.count(), 1);
@@ -369,99 +369,99 @@ private slots:
 
         QSignalSpy userStatusChangedSpy(&model,
             &OCC::UserStatusSelectorModel::userStatusChanged);
-        QSignalSpy clearAtChangedSpy(&model,
-            &OCC::UserStatusSelectorModel::clearAtChanged);
+        QSignalSpy clearAtDisplayStringChangedSpy(&model,
+            &OCC::UserStatusSelectorModel::clearAtDisplayStringChanged);
 
         const auto fakePredefinedUserStatusIndex = 0;
-        model.setPredefinedStatus(fakePredefinedUserStatusIndex);
+        model.setPredefinedStatus(model.predefinedStatuses()[fakePredefinedUserStatusIndex]);
 
         QCOMPARE(userStatusChangedSpy.count(), 1);
-        QCOMPARE(clearAtChangedSpy.count(), 1);
+        QCOMPARE(clearAtDisplayStringChangedSpy.count(), 1);
 
         // Was user status set correctly?
         const auto fakePredefinedUserStatus = fakePredefinedStatuses[fakePredefinedUserStatusIndex];
         QCOMPARE(model.userStatusMessage(), fakePredefinedUserStatus.message());
         QCOMPARE(model.userStatusEmoji(), fakePredefinedUserStatus.icon());
         QCOMPARE(model.onlineStatus(), fakePredefinedUserStatus.state());
-        QCOMPARE(model.clearAt(), tr("1 hour"));
+        QCOMPARE(model.clearAtDisplayString(), tr("1 hour"));
     }
 
-    void testSetClear_setClearAtStage0_emitClearAtChangedAndClearAtSet()
+    void testSetClear_setClearAtStage0_emitclearAtDisplayStringChangedAndClearAtSet()
     {
         auto fakeUserStatusJob = std::make_shared<FakeUserStatusConnector>();
         OCC::UserStatusSelectorModel model(fakeUserStatusJob);
-        QSignalSpy clearAtChangedSpy(&model, &OCC::UserStatusSelectorModel::clearAtChanged);
+        QSignalSpy clearAtDisplayStringChangedSpy(&model, &OCC::UserStatusSelectorModel::clearAtDisplayStringChanged);
 
-        const auto clearAtIndex = 0;
-        model.setClearAt(clearAtIndex);
+        const auto clearAtToSet = OCC::UserStatusSelectorModel::ClearStageType::DontClear;
+        model.setClearAt(clearAtToSet);
 
-        QCOMPARE(clearAtChangedSpy.count(), 1);
-        QCOMPARE(model.clearAt(), tr("Don't clear"));
+        QCOMPARE(clearAtDisplayStringChangedSpy.count(), 1);
+        QCOMPARE(model.clearAtDisplayString(), tr("Don't clear"));
     }
 
-    void testSetClear_setClearAtStage1_emitClearAtChangedAndClearAtSet()
+    void testSetClear_setClearAtStage1_emitclearAtDisplayStringChangedAndClearAtSet()
     {
         auto fakeUserStatusJob = std::make_shared<FakeUserStatusConnector>();
         OCC::UserStatusSelectorModel model(fakeUserStatusJob);
-        QSignalSpy clearAtChangedSpy(&model, &OCC::UserStatusSelectorModel::clearAtChanged);
+        QSignalSpy clearAtDisplayStringChangedSpy(&model, &OCC::UserStatusSelectorModel::clearAtDisplayStringChanged);
 
-        const auto clearAtIndex = 1;
-        model.setClearAt(clearAtIndex);
+        const auto clearAtToSet = OCC::UserStatusSelectorModel::ClearStageType::HalfHour;
+        model.setClearAt(clearAtToSet);
 
-        QCOMPARE(clearAtChangedSpy.count(), 1);
-        QCOMPARE(model.clearAt(), tr("30 minutes"));
+        QCOMPARE(clearAtDisplayStringChangedSpy.count(), 1);
+        QCOMPARE(model.clearAtDisplayString(), tr("30 minutes"));
     }
 
-    void testSetClear_setClearAtStage2_emitClearAtChangedAndClearAtSet()
+    void testSetClear_setClearAtStage2_emitclearAtDisplayStringChangedAndClearAtSet()
     {
         auto fakeUserStatusJob = std::make_shared<FakeUserStatusConnector>();
         OCC::UserStatusSelectorModel model(fakeUserStatusJob);
-        QSignalSpy clearAtChangedSpy(&model, &OCC::UserStatusSelectorModel::clearAtChanged);
+        QSignalSpy clearAtDisplayStringChangedSpy(&model, &OCC::UserStatusSelectorModel::clearAtDisplayStringChanged);
 
-        const auto clearAtIndex = 2;
-        model.setClearAt(clearAtIndex);
+        const auto clearAtToSet = OCC::UserStatusSelectorModel::ClearStageType::OneHour;
+        model.setClearAt(clearAtToSet);
 
-        QCOMPARE(clearAtChangedSpy.count(), 1);
-        QCOMPARE(model.clearAt(), tr("1 hour"));
+        QCOMPARE(clearAtDisplayStringChangedSpy.count(), 1);
+        QCOMPARE(model.clearAtDisplayString(), tr("1 hour"));
     }
 
-    void testSetClear_setClearAtStage3_emitClearAtChangedAndClearAtSet()
+    void testSetClear_setClearAtStage3_emitclearAtDisplayStringChangedAndClearAtSet()
     {
         auto fakeUserStatusJob = std::make_shared<FakeUserStatusConnector>();
         OCC::UserStatusSelectorModel model(fakeUserStatusJob);
-        QSignalSpy clearAtChangedSpy(&model, &OCC::UserStatusSelectorModel::clearAtChanged);
+        QSignalSpy clearAtDisplayStringChangedSpy(&model, &OCC::UserStatusSelectorModel::clearAtDisplayStringChanged);
 
-        const auto clearAtIndex = 3;
-        model.setClearAt(clearAtIndex);
+        const auto clearAtToSet = OCC::UserStatusSelectorModel::ClearStageType::FourHour;
+        model.setClearAt(clearAtToSet);
 
-        QCOMPARE(clearAtChangedSpy.count(), 1);
-        QCOMPARE(model.clearAt(), tr("4 hours"));
+        QCOMPARE(clearAtDisplayStringChangedSpy.count(), 1);
+        QCOMPARE(model.clearAtDisplayString(), tr("4 hours"));
     }
 
-    void testSetClear_setClearAtStage4_emitClearAtChangedAndClearAtSet()
+    void testSetClear_setClearAtStage4_emitclearAtDisplayStringChangedAndClearAtSet()
     {
         auto fakeUserStatusJob = std::make_shared<FakeUserStatusConnector>();
         OCC::UserStatusSelectorModel model(fakeUserStatusJob);
-        QSignalSpy clearAtChangedSpy(&model, &OCC::UserStatusSelectorModel::clearAtChanged);
+        QSignalSpy clearAtDisplayStringChangedSpy(&model, &OCC::UserStatusSelectorModel::clearAtDisplayStringChanged);
 
-        const auto clearAtIndex = 4;
-        model.setClearAt(clearAtIndex);
+        const auto clearAtToSet = OCC::UserStatusSelectorModel::ClearStageType::Today;
+        model.setClearAt(clearAtToSet);
 
-        QCOMPARE(clearAtChangedSpy.count(), 1);
-        QCOMPARE(model.clearAt(), tr("Today"));
+        QCOMPARE(clearAtDisplayStringChangedSpy.count(), 1);
+        QCOMPARE(model.clearAtDisplayString(), tr("Today"));
     }
 
-    void testSetClear_setClearAtStage5_emitClearAtChangedAndClearAtSet()
+    void testSetClear_setClearAtStage5_emitclearAtDisplayStringChangedAndClearAtSet()
     {
         auto fakeUserStatusJob = std::make_shared<FakeUserStatusConnector>();
         OCC::UserStatusSelectorModel model(fakeUserStatusJob);
-        QSignalSpy clearAtChangedSpy(&model, &OCC::UserStatusSelectorModel::clearAtChanged);
+        QSignalSpy clearAtDisplayStringChangedSpy(&model, &OCC::UserStatusSelectorModel::clearAtDisplayStringChanged);
 
-        const auto clearAtIndex = 5;
-        model.setClearAt(clearAtIndex);
+        const auto clearAtToSet = OCC::UserStatusSelectorModel::ClearStageType::Week;
+        model.setClearAt(clearAtToSet);
 
-        QCOMPARE(clearAtChangedSpy.count(), 1);
-        QCOMPARE(model.clearAt(), tr("This week"));
+        QCOMPARE(clearAtDisplayStringChangedSpy.count(), 1);
+        QCOMPARE(model.clearAtDisplayString(), tr("This week"));
     }
 
     void testClearAtStages()
@@ -469,16 +469,16 @@ private slots:
         auto fakeUserStatusJob = std::make_shared<FakeUserStatusConnector>();
         OCC::UserStatusSelectorModel model(fakeUserStatusJob);
 
-        QCOMPARE(model.clearAt(), tr("Don't clear"));
-        const auto clearAtValues = model.clearAtValues();
-        QCOMPARE(clearAtValues.count(), 6);
+        QCOMPARE(model.clearAtDisplayString(), tr("Don't clear"));
+        const auto clearStageTypes = model.clearStageTypes();
+        QCOMPARE(clearStageTypes.count(), 6);
 
-        QCOMPARE(clearAtValues[0], tr("Don't clear"));
-        QCOMPARE(clearAtValues[1], tr("30 minutes"));
-        QCOMPARE(clearAtValues[2], tr("1 hour"));
-        QCOMPARE(clearAtValues[3], tr("4 hours"));
-        QCOMPARE(clearAtValues[4], tr("Today"));
-        QCOMPARE(clearAtValues[5], tr("This week"));
+        QCOMPARE(clearStageTypes[0].value<QVariantMap>()[QStringLiteral("display")], tr("Don't clear"));
+        QCOMPARE(clearStageTypes[1].value<QVariantMap>()[QStringLiteral("display")], tr("30 minutes"));
+        QCOMPARE(clearStageTypes[2].value<QVariantMap>()[QStringLiteral("display")], tr("1 hour"));
+        QCOMPARE(clearStageTypes[3].value<QVariantMap>()[QStringLiteral("display")], tr("4 hours"));
+        QCOMPARE(clearStageTypes[4].value<QVariantMap>()[QStringLiteral("display")], tr("Today"));
+        QCOMPARE(clearStageTypes[5].value<QVariantMap>()[QStringLiteral("display")], tr("This week"));
     }
 
     void testClearAt_clearAtTimestamp()
@@ -496,7 +496,7 @@ private slots:
 
             OCC::UserStatusSelectorModel model(userStatus, std::move(fakeDateTimeProvider));
 
-            QCOMPARE(model.clearAt(), tr("Less than a minute"));
+            QCOMPARE(model.clearAtDisplayString(), tr("Less than a minute"));
         }
 
         {
@@ -511,7 +511,7 @@ private slots:
 
             OCC::UserStatusSelectorModel model(userStatus, std::move(fakeDateTimeProvider));
 
-            QCOMPARE(model.clearAt(), tr("1 minute"));
+            QCOMPARE(model.clearAtDisplayString(), tr("1 minute"));
         }
 
         {
@@ -526,7 +526,7 @@ private slots:
 
             OCC::UserStatusSelectorModel model(userStatus, std::move(fakeDateTimeProvider));
 
-            QCOMPARE(model.clearAt(), tr("30 minutes"));
+            QCOMPARE(model.clearAtDisplayString(), tr("30 minutes"));
         }
 
         {
@@ -541,7 +541,7 @@ private slots:
 
             OCC::UserStatusSelectorModel model(userStatus, std::move(fakeDateTimeProvider));
 
-            QCOMPARE(model.clearAt(), tr("1 hour"));
+            QCOMPARE(model.clearAtDisplayString(), tr("1 hour"));
         }
 
         {
@@ -556,7 +556,7 @@ private slots:
 
             OCC::UserStatusSelectorModel model(userStatus, std::move(fakeDateTimeProvider));
 
-            QCOMPARE(model.clearAt(), tr("4 hours"));
+            QCOMPARE(model.clearAtDisplayString(), tr("4 hours"));
         }
 
         {
@@ -571,7 +571,7 @@ private slots:
 
             OCC::UserStatusSelectorModel model(userStatus, std::move(fakeDateTimeProvider));
 
-            QCOMPARE(model.clearAt(), tr("1 day"));
+            QCOMPARE(model.clearAtDisplayString(), tr("1 day"));
         }
 
         {
@@ -586,7 +586,7 @@ private slots:
 
             OCC::UserStatusSelectorModel model(userStatus, std::move(fakeDateTimeProvider));
 
-            QCOMPARE(model.clearAt(), tr("7 days"));
+            QCOMPARE(model.clearAtDisplayString(), tr("7 days"));
         }
     }
 
@@ -601,7 +601,7 @@ private slots:
 
             OCC::UserStatusSelectorModel model(userStatus);
 
-            QCOMPARE(model.clearAt(), tr("Today"));
+            QCOMPARE(model.clearAtDisplayString(), tr("Today"));
         }
 
         {
@@ -613,7 +613,7 @@ private slots:
 
             OCC::UserStatusSelectorModel model(userStatus);
 
-            QCOMPARE(model.clearAt(), tr("This week"));
+            QCOMPARE(model.clearAtDisplayString(), tr("This week"));
         }
     }
 
@@ -628,7 +628,7 @@ private slots:
 
             OCC::UserStatusSelectorModel model(userStatus);
 
-            QCOMPARE(model.clearAt(), tr("30 minutes"));
+            QCOMPARE(model.clearAtDisplayString(), tr("30 minutes"));
         }
 
         {
@@ -640,7 +640,7 @@ private slots:
 
             OCC::UserStatusSelectorModel model(userStatus);
 
-            QCOMPARE(model.clearAt(), tr("1 hour"));
+            QCOMPARE(model.clearAtDisplayString(), tr("1 hour"));
         }
     }