[ktp-contact-list] /: Independent account presence support.

James D. Smith null at kde.org
Wed Nov 22 01:07:30 UTC 2017


Git commit f40dc5815e0c8e66781331ede1ffd8716d4b0921 by James D. Smith.
Committed on 22/11/2017 at 01:06.
Pushed by smithjd into branch 'master'.

Independent account presence support.
Bugfixes and improvements.
REVIEW: 130189
BUG: 181748
GUI:

M  +1    -0    CMakeLists.txt
A  +303  -0    dialogs/advanced-presence-dialog.cpp     [License: GPL (v2/3)]
A  +59   -0    dialogs/advanced-presence-dialog.h     [License: GPL (v2/3)]
M  +5    -0    dialogs/custom-presence-dialog.cpp
M  +78   -102  global-presence-chooser.cpp
M  +6    -4    global-presence-chooser.h
M  +7    -27   main-widget.cpp
M  +0    -2    main-widget.h

https://commits.kde.org/ktp-contact-list/f40dc5815e0c8e66781331ede1ffd8716d4b0921

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9d31463..54d96c4 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -51,6 +51,7 @@ set (ktp_contactlist_SRCS
      global-presence-chooser.cpp
      dialogs/remove-contact-dialog.cpp
      dialogs/custom-presence-dialog.cpp
+     dialogs/advanced-presence-dialog.cpp
      tooltips/ktooltip.cpp
      tooltips/tooltipmanager.cpp
      tooltips/ktooltipwindow.cpp
diff --git a/dialogs/advanced-presence-dialog.cpp b/dialogs/advanced-presence-dialog.cpp
new file mode 100644
index 0000000..3bc0fb3
--- /dev/null
+++ b/dialogs/advanced-presence-dialog.cpp
@@ -0,0 +1,303 @@
+/*
+  Copyright © 2017 James D. Smith <smithjd15 at gmail.com>
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of
+  the License or (at your option) version 3 or any later version
+  accepted by the membership of KDE e.V. (or its successor approved
+  by the membership of KDE e.V.), which shall act as a proxy
+  defined in Section 14 of version 3 of the license.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "advanced-presence-dialog.h"
+#include "global-presence-chooser.h"
+
+#include <QHBoxLayout>
+#include <QVBoxLayout>
+#include <QModelIndex>
+#include <QComboBox>
+#include <QDialogButtonBox>
+
+#include <KLocalizedString>
+
+#include <QLabel>
+#include <QCheckBox>
+#include <QLineEdit>
+#include <QKeyEvent>
+
+#include <KTp/presence.h>
+#include <KTp/global-presence.h>
+#include <KTp/Models/presence-model.h>
+#include <KTp/Models/accounts-list-model.h>
+
+//A sneaky class that adds an extra entries to the end of the presence model.
+class AccountPresenceModelExtended : public QAbstractListModel
+{
+    Q_OBJECT
+public:
+    AccountPresenceModelExtended(KTp::PresenceModel *presenceModel, QObject *parent);
+    int rowCount(const QModelIndex &parent = QModelIndex()) const;
+    QVariant data(const QModelIndex &index, int role) const;
+    /** Adds a presence to the model which is to be used when the presence has been set externally and we need to show it, but not save it to the config*/
+    QModelIndex addTemporaryPresence(const KTp::Presence &presence);
+    void removeTemporaryPresence();
+private slots:
+    void sourceRowsInserted(const QModelIndex &index, int start, int end);
+    void sourceRowsRemoved(const QModelIndex &index, int start, int end);
+private:
+    KTp::Presence m_temporaryPresence;
+    KTp::PresenceModel *m_model;
+};
+
+AccountPresenceModelExtended::AccountPresenceModelExtended(KTp::PresenceModel *presenceModel, QObject *parent) :
+    QAbstractListModel(parent),
+    m_model(presenceModel)
+{
+    connect(m_model, &QAbstractItemModel::rowsInserted, this, &AccountPresenceModelExtended::sourceRowsInserted);
+    connect(m_model, &QAbstractItemModel::rowsRemoved, this, &AccountPresenceModelExtended::sourceRowsRemoved);
+}
+
+//return number of rows + the extra items added to end of list
+int AccountPresenceModelExtended::rowCount(const QModelIndex &parent) const
+{
+    if (parent.isValid()) {
+        return 0;
+    }
+    int rowCount = m_model->rowCount(parent);
+    if (m_temporaryPresence.isValid()) {
+        rowCount++;
+    }
+    return rowCount;
+}
+
+QVariant AccountPresenceModelExtended::data(const QModelIndex &index, int role) const
+{
+    if (m_temporaryPresence.isValid() && index.row() == rowCount() - 1) {
+        switch (role) {
+        case Qt::DisplayRole:
+            return m_temporaryPresence.statusMessage();
+        case Qt::DecorationRole:
+            return m_temporaryPresence.icon();
+        case KTp::PresenceModel::PresenceRole:
+            return QVariant::fromValue<KTp::Presence>(m_temporaryPresence);
+        }
+    } else {
+        return m_model->data(m_model->index(index.row()), role);
+    }
+    return QVariant();
+}
+
+void AccountPresenceModelExtended::sourceRowsInserted(const QModelIndex &index, int start, int end)
+{
+    beginInsertRows(createIndex(index.row(), 0), start, end);
+    endInsertRows();
+}
+
+void AccountPresenceModelExtended::sourceRowsRemoved(const QModelIndex &index, int start, int end)
+{
+    beginRemoveRows(createIndex(index.row(), 0), start, end);
+    endRemoveRows();
+}
+
+void AccountPresenceModelExtended::removeTemporaryPresence()
+{
+    if (!m_temporaryPresence.isValid()) {
+        return; //if not already set, do nothing.
+    }
+
+    int row = m_model->rowCount();
+    beginRemoveRows(QModelIndex(), row, row);
+    m_temporaryPresence = KTp::Presence();
+    endRemoveRows();
+}
+
+QModelIndex AccountPresenceModelExtended::addTemporaryPresence(const KTp::Presence &presence)
+{
+    int row = m_model->rowCount();
+
+    //if the temp presence already exists, don't remove and readd it
+    //but simply replace it
+    if (m_temporaryPresence.isValid()) {
+        m_temporaryPresence = presence;
+        emit dataChanged(this->createIndex(row, 0), this->createIndex(row, 0));
+    } else {
+        beginInsertRows(QModelIndex(), row, row);
+        m_temporaryPresence = presence;
+        endInsertRows();
+    }
+
+    return this->createIndex(row, 0);
+}
+
+AdvancedPresenceDialog::AdvancedPresenceDialog(KTp::PresenceModel *presenceModel, KTp::GlobalPresence *globalPresence, QWidget *parent)
+    : QDialog(parent),
+      m_presenceModel(presenceModel),
+      m_accountsModel(new KTp::AccountsListModel()),
+      m_globalPresence(globalPresence)
+{
+    setupDialog();
+}
+
+void AdvancedPresenceDialog::setupDialog()
+{
+    setWindowTitle(i18n("Advanced Presence Setting"));
+
+    QVBoxLayout *vLayout = new QVBoxLayout();
+    QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Close, this);
+    connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
+
+    if (m_globalPresence->enabledAccounts()->accounts().isEmpty()) {
+        QLabel *emptyBox = new QLabel();
+        emptyBox->setText(i18n("It appears that you do not have any accounts configured"));
+        QVBoxLayout *emptyAccountLayout = new QVBoxLayout();
+        emptyAccountLayout->addWidget(emptyBox);
+
+        vLayout->addWidget(emptyBox);
+    } else {
+        m_accountsModel->setAccountSet(m_globalPresence->enabledAccounts());
+        for (int i = 0; i < m_accountsModel->rowCount(); i++) {
+            const QModelIndex &index = m_accountsModel->index(i, 0);
+
+            if (!m_accountsModel->data(index, KTp::AccountsListModel::AccountRole).value<Tp::AccountPtr>()->isValid())
+                continue;
+
+            QVBoxLayout *vAccountLayout = new QVBoxLayout();
+            QHBoxLayout *hAccountLayout = new QHBoxLayout();
+            QHBoxLayout *lHAccountLayout = new QHBoxLayout();
+
+            const QIcon &accountIcon = m_accountsModel->data(index, Qt::DecorationRole).value<QIcon>();
+            QLabel *icoLabel = new QLabel();
+            icoLabel->setPixmap(accountIcon.pixmap(accountIcon.actualSize(QSize(16, 16))));
+            QLabel *label = new QLabel(m_accountsModel->data(index, Qt::DisplayRole).value<QString>());
+
+            auto setComboLineEdit = [=] () {
+                if (m_comboBoxes[i]->currentData(KTp::PresenceModel::PresenceRole).value<KTp::Presence>().statusMessage().isEmpty()) {
+                    m_comboBoxes[i]->lineEdit()->setPlaceholderText(i18n("Set a status message ..."));
+                    m_comboBoxes[i]->lineEdit()->setReadOnly(false);
+                } else {
+                    m_comboBoxes[i]->lineEdit()->setPlaceholderText(m_comboBoxes[i]->currentData(Qt::DisplayRole).value<QString>());
+                    m_comboBoxes[i]->lineEdit()->setReadOnly(true);
+                }
+
+                m_comboBoxes[i]->lineEdit()->setToolTip(m_comboBoxes[i]->currentData(Qt::DisplayRole).value<QString>());
+            };
+
+            QCheckBox *checkBox = new QCheckBox();
+            checkBox->setChecked(true);
+            connect(checkBox, &QCheckBox::clicked, [=] (bool checked) {
+                m_comboBoxes[i]->setEnabled(checked);
+                KTp::Presence presence;
+                if (checked) {
+                    setComboLineEdit();
+                    presence = m_comboBoxes[i]->currentData(KTp::PresenceModel::PresenceRole).value<KTp::Presence>();
+                } else {
+                    m_comboBoxes[i]->lineEdit()->setPlaceholderText(m_comboBoxes[i]->currentData(Qt::DisplayRole).value<QString>());
+                    presence.setStatus(Tp::ConnectionPresenceTypeUnset, QLatin1String("unset"), QString());
+                }
+
+                m_accountsModel->setData(index, QVariant::fromValue<KTp::Presence>(presence), KTp::AccountsListModel::StatusHandlerPresenceRole);
+            });
+
+            KTp::Presence accountPresence = m_accountsModel->data(index, KTp::AccountsListModel::StatusHandlerPresenceRole).value<KTp::Presence>();
+            if (accountPresence.type() == Tp::ConnectionPresenceTypeUnset) {
+                if (m_globalPresence->globalPresence().type() == Tp::ConnectionPresenceTypeUnset) {
+                    accountPresence = m_accountsModel->data(index, KTp::AccountsListModel::RequestedPresenceRole).value<KTp::Presence>();
+                } else {
+                    accountPresence = m_globalPresence->globalPresence();
+                    checkBox->setChecked(false);
+                }
+            }
+
+            m_comboBoxes.insert(i, new QComboBox());
+            m_extendedModels.insert(i, new AccountPresenceModelExtended(m_presenceModel, this));
+            m_comboBoxes[i]->setModel(m_extendedModels[i]);
+            m_comboBoxes[i]->setEnabled(checkBox->isChecked());
+            m_comboBoxes[i]->setEditable(true);
+            m_comboBoxes[i]->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon);
+            m_comboBoxes[i]->setWhatsThis(KDED_STATUS_MESSAGE_PARSER_WHATSTHIS);
+            m_comboBoxes[i]->installEventFilter(this);
+
+            int width = m_comboBoxes[i]->minimumSizeHint().width();
+            m_comboBoxes[i]->setMinimumContentsLength(width);
+
+            connect(m_comboBoxes[i], static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), [=] {
+                setComboLineEdit();
+
+                if (m_comboBoxes[i]->currentIndex() < m_presenceModel->rowCount()) {
+                    m_extendedModels[i]->removeTemporaryPresence();
+                }
+
+                m_accountsModel->setData(index, m_comboBoxes[i]->currentData(KTp::PresenceModel::PresenceRole), KTp::AccountsListModel::StatusHandlerPresenceRole);
+            });
+
+            const QModelIndexList &matchIndexList = m_presenceModel->match(m_presenceModel->index(0, 0), KTp::PresenceModel::PresenceRole, QVariant::fromValue<KTp::Presence>(accountPresence));
+            if (!matchIndexList.isEmpty()) {
+                m_comboBoxes[i]->setCurrentIndex(matchIndexList.at(0).row());
+            } else {
+                const QModelIndex &tempPresenceIndex = m_extendedModels[i]->addTemporaryPresence(accountPresence);
+                m_comboBoxes[i]->setCurrentIndex(tempPresenceIndex.row());
+            }
+
+            setComboLineEdit();
+
+            lHAccountLayout->addWidget(icoLabel);
+            lHAccountLayout->addWidget(label, Qt::AlignLeft);
+            vAccountLayout->addLayout(lHAccountLayout);
+            hAccountLayout->addWidget(checkBox);
+            hAccountLayout->addWidget(m_comboBoxes[i]);
+            vAccountLayout->addLayout(hAccountLayout);
+            vLayout->addLayout(vAccountLayout);
+        }
+    }
+
+    vLayout->addWidget(buttonBox);
+    setLayout(vLayout);
+}
+
+bool AdvancedPresenceDialog::eventFilter(QObject* obj, QEvent* event)
+{
+    QComboBox *comboBox = qobject_cast<QComboBox*>(obj);
+
+    if (event->type() == QEvent::KeyPress) {
+        QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
+        if (keyEvent->modifiers() == Qt::NoModifier && (keyEvent->key() == Qt::Key_Return || keyEvent->key() == Qt::Key_Enter) && m_comboBoxes.values().contains(comboBox)) {
+            const QModelIndex &index = m_accountsModel->index(m_comboBoxes.key(comboBox), 0);
+            KTp::Presence accountPresence = comboBox->currentData(KTp::PresenceModel::PresenceRole).value<KTp::Presence>();
+            accountPresence.setStatusMessage(comboBox->lineEdit()->text());
+
+            const QModelIndexList &matchIndexList = m_presenceModel->match(m_presenceModel->index(0, 0), KTp::PresenceModel::PresenceRole, QVariant::fromValue<KTp::Presence>(accountPresence));
+            if (matchIndexList.isEmpty()) {
+                const QModelIndex &tempPresenceIndex = m_extendedModels[index.row()]->addTemporaryPresence(accountPresence);
+                comboBox->setCurrentIndex(tempPresenceIndex.row());
+            }
+
+            comboBox->lineEdit()->setPlaceholderText(comboBox->currentData(Qt::DisplayRole).value<QString>());
+            comboBox->lineEdit()->setToolTip(comboBox->currentData(Qt::DisplayRole).value<QString>());
+            comboBox->clearFocus();
+
+            m_accountsModel->setData(index, comboBox->currentData(KTp::PresenceModel::PresenceRole), KTp::AccountsListModel::StatusHandlerPresenceRole);
+
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    if (event->type() == QEvent::FocusOut) {
+        comboBox->clearFocus();
+    }
+
+    // standard event processing
+    return QObject::eventFilter(obj, event);
+}
+
+#include "advanced-presence-dialog.moc"
diff --git a/dialogs/advanced-presence-dialog.h b/dialogs/advanced-presence-dialog.h
new file mode 100644
index 0000000..fa8161f
--- /dev/null
+++ b/dialogs/advanced-presence-dialog.h
@@ -0,0 +1,59 @@
+/*
+  Copyright © 2017 James D. Smith <smithjd15 at gmail.com>
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of
+  the License or (at your option) version 3 or any later version
+  accepted by the membership of KDE e.V. (or its successor approved
+  by the membership of KDE e.V.), which shall act as a proxy
+  defined in Section 14 of version 3 of the license.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef ADVANCED_PRESENCE_DIALOG_H
+#define ADVANCED_PRESENCE_DIALOG_H
+
+#include <QDialog>
+#include <QComboBox>
+
+class QPushButton;
+class QListView;
+class QComboBox;
+class AccountPresenceModelExtended;
+
+namespace KTp {
+    class Presence;
+    class GlobalPresence;
+    class PresenceModel;
+    class AccountsListModel;
+}
+
+class AdvancedPresenceDialog : public QDialog
+{
+    Q_OBJECT
+
+public:
+    explicit AdvancedPresenceDialog(KTp::PresenceModel *presenceModel, KTp::GlobalPresence *globalPresence, QWidget *parent = 0);
+    bool eventFilter(QObject* obj, QEvent* event);
+
+private:
+    ///Setup the initial dialog
+    void setupDialog();
+
+    KTp::PresenceModel *m_presenceModel;
+    KTp::AccountsListModel *m_accountsModel;
+    KTp::GlobalPresence *m_globalPresence;
+
+    QHash<int,QComboBox*> m_comboBoxes;
+    QHash<int,AccountPresenceModelExtended*> m_extendedModels;
+};
+
+#endif // ADVANCED_PRESENCE_DIALOG_H
diff --git a/dialogs/custom-presence-dialog.cpp b/dialogs/custom-presence-dialog.cpp
index e85dc46..73588cf 100644
--- a/dialogs/custom-presence-dialog.cpp
+++ b/dialogs/custom-presence-dialog.cpp
@@ -19,6 +19,7 @@
 */
 
 #include "custom-presence-dialog.h"
+#include "global-presence-chooser.h"
 
 #include <QListView>
 #include <QHBoxLayout>
@@ -97,6 +98,7 @@ void CustomPresenceDialog::setupDialog()
     m_statusMessage->show();
 
     m_statusMessage->lineEdit()->setPlaceholderText(m_statusMessage->currentText());
+    m_statusMessage->lineEdit()->setWhatsThis(KDED_STATUS_MESSAGE_PARSER_WHATSTHIS);
 
     connect(m_statusMessage, SIGNAL(editTextChanged(QString)),
             this, SLOT(presenceMessageTextChanged(QString)));
@@ -202,6 +204,9 @@ void CustomPresenceDialog::presenceViewSelectionChanged(const QModelIndex& index
     } else {
         m_removeStatus->setEnabled(false);
     }
+
+    KTp::Presence presence = index.data(KTp::PresenceModel::PresenceRole).value<KTp::Presence>();
+    m_statusMessage->lineEdit()->setText(presence.statusMessage());
 }
 
 #include "custom-presence-dialog.moc"
diff --git a/global-presence-chooser.cpp b/global-presence-chooser.cpp
index 323217c..f9b5a82 100644
--- a/global-presence-chooser.cpp
+++ b/global-presence-chooser.cpp
@@ -20,12 +20,13 @@
 
 #include "global-presence-chooser.h"
 
-#include <KTp/global-presence.h>
+#include "dialogs/custom-presence-dialog.h"
+#include "dialogs/advanced-presence-dialog.h"
+
 #include <KTp/presence.h>
+#include <KTp/global-presence.h>
 #include <KTp/Models/presence-model.h>
 
-#include "dialogs/custom-presence-dialog.h"
-
 #include <KLocalizedString>
 #include <KSharedConfig>
 #include <KLineEdit>
@@ -34,7 +35,6 @@
 #include <KMessageBox>
 #include <KIconLoader>
 
-#include <TelepathyQt/Presence>
 #include <TelepathyQt/Account>
 
 #include <QFontDatabase>
@@ -45,8 +45,27 @@
 #include <QMenu>
 #include <QPointer>
 
-//A sneaky class that adds an extra entries to the end of the presence model,
-//currently "Now listening to" and "Configure Custom Presences"
+extern const QString KDED_STATUS_MESSAGE_PARSER_WHATSTHIS(
+        i18n("<p>Tokens can be used wherever a status message can be set to create a dynamic status message.</p>")
+        + i18n("<p><strong>%tr+<val></strong>: Countdown to 0 from <strong><val></strong> minutes. e.g. %tr+30</p>")
+        + i18n("<p><strong>%time+[<val>]</strong>: The current local time, or if a value is specified, the local time <strong><val></strong> minutes in the future. e.g. %time+10</p>")
+        + i18n("<p><strong>%utc+[<val>]</strong>: The current UTC time, or if a value is specified, the UTC time <strong><val></strong> minutes into the future. e.g. %utc</p>")
+        + i18n("<p><strong>%te+[<val>]</strong>: Time elapsed from message activation. Append an initial elapsed time "<val>&quot in minutes.; e.g. %te+5</p>")
+        + i18n("<p><strong>%title</strong>: Now Playing track title.</p>")
+        + i18n("<p><strong>%artist</strong>: Now Playing track or album artist.</p>")
+        + i18n("<p><strong>%album</strong>: Now Playing album.</p>")
+        + i18n("<p><strong>%track</strong>: Now Playing track number.</p>")
+        + i18n("<p><strong>%um+[<val>]</strong>: When specified globally or in an account presence status message, overrides all automatic presence messages. When specified in an automatic presence status message, is substituted for the global or account presence status message (if specified). When <strong>val = g</strong> in an account presence status message or an automatic presence status message, overrides the account presence status message or automatic presence status message with the global presence status message. e.g. %um, %um+g</p>")
+        + i18n("<p><strong>%tu+<val></strong>: Refresh the status message every <strong><val></strong> minutes. e.g. %tu+2</p>")
+        + i18n("<p><strong>%tx+<val></strong>: Expire the status message after <strong><val></strong> minutes, or when the Now Playing active player stops (<strong>val = np</strong>). e.g. %tx+20, %tx+np</p>")
+        + i18n("<p><strong>%xm+"<val>"</strong>: Specify a message to follow %tr, %time, %utc, and %tx token expiry. e.g. %xm+"Back %time. %tx+3 %xm+"Running late""</p>")
+        + i18n("<p><strong>%tf+"<val>"</strong>: Specify the format for local time using QDateTime::toString() expressions. e.g. %tf+"h:mm AP t"</p>")
+        + i18n("<p><strong>%uf+"<val>"</strong>: Specify the format for UTC time using QDateTime::toString() expressions. e.g. %uf+"hh:mm t"</p>")
+        + i18n("<p><strong>%sp+"<val>"</strong>: Change the separator for empty fields. e.g. %sp+"-"</p>")
+        + i18n("<p>Using tokens requires the Telepathy KDED module to be loaded. Tokens can be escaped by prepending a backslash character, e.g. \%sp</p>")
+        );
+
+//A sneaky class that adds an extra entries to the end of the presence model.
 class PresenceModelExtended : public QAbstractListModel
 {
     Q_OBJECT
@@ -70,8 +89,8 @@ PresenceModelExtended::PresenceModelExtended(KTp::PresenceModel *presenceModel,
     QAbstractListModel(parent),
     m_model(presenceModel)
 {
-    connect(m_model, SIGNAL(rowsInserted(QModelIndex,int,int)), SLOT(sourceRowsInserted(QModelIndex,int,int)));
-    connect(m_model, SIGNAL(rowsRemoved(QModelIndex,int,int)), SLOT(sourceRowsRemoved(QModelIndex,int,int)));
+    connect(m_model, &QAbstractItemModel::rowsInserted, this, &PresenceModelExtended::sourceRowsInserted);
+    connect(m_model, &QAbstractItemModel::rowsRemoved, this, &PresenceModelExtended::sourceRowsRemoved);
 }
 
 //return number of rows + the extra items added to end of list
@@ -103,9 +122,9 @@ QVariant PresenceModelExtended::data(const QModelIndex &index, int role) const
     } else if (index.row() == rowCount() - 2) {
         switch (role) {
         case Qt::DisplayRole:
-            return i18n("Now listening to...");
+            return i18n("Advanced Presence Setting...");
         case Qt::DecorationRole:
-            return QIcon::fromTheme("speaker");
+            return QIcon::fromTheme("configure");
         }
     } else if (m_temporaryPresence.isValid() && index.row() == rowCount() - 3) {
         switch (role) {
@@ -180,8 +199,6 @@ GlobalPresenceChooser::GlobalPresenceChooser(QWidget *parent) :
     m_changePresenceMessageButton(new QPushButton(this))
 {
     this->setModel(m_modelExtended);
-    //needed for mousemove events
-    setMouseTracking(true);
 
     m_busyOverlay->setSequence(KIconLoader::global()->loadPixmapSequence("process-working", KIconLoader::SizeSmallMedium));
     setEditable(false);
@@ -190,37 +207,34 @@ GlobalPresenceChooser::GlobalPresenceChooser(QWidget *parent) :
     m_changePresenceMessageButton->setFlat(true);
     m_changePresenceMessageButton->setToolTip(i18n("Click to change your presence message"));
 
-    connect(this, SIGNAL(currentIndexChanged(int)), SLOT(onAllComboChanges(int)));
-    connect(this, SIGNAL(activated(int)), SLOT(onUserActivatedComboChange(int)));
-    connect(m_globalPresence, SIGNAL(requestedPresenceChanged(KTp::Presence)), SLOT(onPresenceChanged(KTp::Presence)));
-    connect(m_globalPresence, SIGNAL(connectionStatusChanged(Tp::ConnectionStatus)), SLOT(onConnectionStatusChanged(Tp::ConnectionStatus)));
-    connect(m_changePresenceMessageButton, SIGNAL(clicked(bool)), this, SLOT(onChangePresenceMessageClicked()));
+    connect(this, static_cast<void(GlobalPresenceChooser::*)(int)>(&KComboBox::currentIndexChanged), &GlobalPresenceChooser::onAllComboChanges);
+    connect(this, static_cast<void(GlobalPresenceChooser::*)(int)>(&KComboBox::activated), &GlobalPresenceChooser::onUserActivatedComboChange);
+    connect(m_globalPresence, &KTp::GlobalPresence::currentPresenceChanged, this, &GlobalPresenceChooser::onPresenceChanged);
+    connect(m_globalPresence, &KTp::GlobalPresence::connectionStatusChanged, this, &GlobalPresenceChooser::onConnectionStatusChanged);
+    connect(m_changePresenceMessageButton, &QPushButton::clicked, this, &GlobalPresenceChooser::onChangePresenceMessageClicked);
 
-    onPresenceChanged(m_globalPresence->requestedPresence());
+    onPresenceChanged(m_globalPresence->currentPresence());
     //we need to check if there is some account connecting and if so, spin the spinner
     onConnectionStatusChanged(m_globalPresence->connectionStatus());
 }
 
-void GlobalPresenceChooser::setAccountManager(const Tp::AccountManagerPtr &accountManager)
-{
-    m_accountManager = accountManager;
-    m_globalPresence->setAccountManager(accountManager);
-}
-
 bool GlobalPresenceChooser::event(QEvent *e)
 {
     if (e->type() == QEvent::ToolTip) {
-        if (m_accountManager.isNull()) {
-            return false;
-        }
-
         QHelpEvent *helpEvent = static_cast<QHelpEvent *>(e);
 
         QString toolTipText;
-        toolTipText.append("<table>");
 
-        Q_FOREACH(const Tp::AccountPtr &account, m_accountManager->allAccounts()) {
-            if (account->isEnabled()) {
+        if (isEditable()) {
+            toolTipText = KDED_STATUS_MESSAGE_PARSER_WHATSTHIS;
+        } else {
+            if (m_globalPresence->accountManager().isNull()) {
+                return false;
+            }
+
+            toolTipText.append("<table>");
+
+            for (const Tp::AccountPtr &account : m_globalPresence->accountManager()->enabledAccounts()->accounts()) {
                 KTp::Presence accountPresence(account->currentPresence());
                 QString presenceIconPath = KIconLoader::global()->iconPath(accountPresence.icon().name(), 1);
                 QString presenceIconString = QString::fromLatin1("<img src=\"%1\">").arg(presenceIconPath);
@@ -229,14 +243,17 @@ bool GlobalPresenceChooser::event(QEvent *e)
                 QString presenceString;
                 if (account->connectionStatus() == Tp::ConnectionStatusConnecting) {
                     presenceString = i18nc("Presence string when the account is connecting", "Connecting...");
+                } else if (!account->currentPresence().statusMessage().isEmpty()){
+                    presenceString = QString::fromLatin1("(%1) ").arg(accountPresence.displayString()) + accountPresence.statusMessage();
                 } else {
                     presenceString = accountPresence.displayString();
                 }
                 toolTipText.append(QString::fromLatin1("<tr><td>%1 %2</td></tr><tr><td style=\"padding-left: 24px\">%3 %4</td></tr>").arg(accountIconString, account->displayName(), presenceIconString, presenceString));
             }
+
+            toolTipText.append("</table>");
         }
 
-        toolTipText.append("</table>");
         QToolTip::showText(helpEvent->globalPos(), toolTipText, this);
         return true;
     }
@@ -246,10 +263,8 @@ bool GlobalPresenceChooser::event(QEvent *e)
     }
 
     if (e->type() == QEvent::ContextMenu) {
-        QMouseEvent *me = static_cast<QMouseEvent*>(e);
         if (isEditable()) {
-            //we need to correctly position the menu, otherwise it just appears at (0;0)
-            m_lineEditContextMenu.data()->exec(me->globalPos());
+            m_lineEditContextMenu = lineEdit()->createStandardContextMenu();
 
             return true;
         }
@@ -303,7 +318,7 @@ void GlobalPresenceChooser::setEditable(bool editable)
         m_busyOverlay->setWidget(0);
     } else {
         m_busyOverlay->setWidget(this);
-        if (m_globalPresence->connectionStatus() == Tp::ConnectionStatusConnecting) {
+        if (m_globalPresence->connectionStatus() == KTp::GlobalPresence::Connecting) {
             m_busyOverlay->start(); // If telepathy is still connecting, overlay must be spinning again.
         }
     }
@@ -312,57 +327,24 @@ void GlobalPresenceChooser::setEditable(bool editable)
 
 void GlobalPresenceChooser::onUserActivatedComboChange(int index)
 {
-    if (index == -1) {
+    if ((index == -1) || (index == count() - 3)) {
         return;
     }
-    //if they select the "configure item"
-    if (index == count() - 1) {
+
+    if (index == count() - 2) {
+        QPointer<AdvancedPresenceDialog> dialog = new AdvancedPresenceDialog(m_model, m_globalPresence, this);
+        dialog.data()->exec();
+        delete dialog.data();
+    } else if (index == count() - 1) {
         QPointer<CustomPresenceDialog> dialog = new CustomPresenceDialog(m_model, this);
         dialog.data()->exec();
         delete dialog.data();
-        onPresenceChanged(m_globalPresence->requestedPresence());
-    } else if (index == count() - 2) {
-        KSharedConfigPtr config = KSharedConfig::openConfig(QLatin1String("ktelepathyrc"));
-        KConfigGroup kdedConfig = config->group("KDED");
-
-        bool pluginEnabled = kdedConfig.readEntry("nowPlayingEnabled", false);
-
-        if (!pluginEnabled) {
-            if (KMessageBox::questionYesNo(this,
-                                           i18n("This plugin is currently disabled. Do you want to enable it and use as your presence?"),
-                                           i18n("Plugin disabled")) == KMessageBox::Yes) {
-
-                kdedConfig.writeEntry("nowPlayingEnabled", true);
-                kdedConfig.sync();
-
-                QDBusMessage message = QDBusMessage::createSignal(QLatin1String("/Telepathy"),
-                                       QLatin1String("org.kde.Telepathy"),
-                                       QLatin1String("settingsChange"));
-                QDBusConnection::sessionBus().send(message);
-            } else {
-                onPresenceChanged(m_globalPresence->requestedPresence());
-                return;
-            }
-        }
-
-        QDBusMessage message = QDBusMessage::createSignal(QLatin1String("/Telepathy"),
-							  QLatin1String("org.kde.Telepathy"),
-							  QLatin1String("activateNowPlaying"));
-        QDBusConnection::sessionBus().send(message);
-        onPresenceChanged(m_globalPresence->requestedPresence());
-    } else if (m_modelExtended->temporaryPresence().isValid() && index == count() - 3) {
-        //do nothing if the temporary presence is selected. This is only used for externally set presences.
-        //at which point reselecting it does nothing.
     } else {
-        QDBusMessage message = QDBusMessage::createSignal(QLatin1String("/Telepathy"),
-							  QLatin1String("org.kde.Telepathy"),
-							  QLatin1String("deactivateNowPlaying"));
-        QDBusConnection::sessionBus().send(message);
-        onPresenceChanged(m_globalPresence->requestedPresence());
-        // only set global presence on user change
         KTp::Presence presence = itemData(index, KTp::PresenceModel::PresenceRole).value<KTp::Presence>();
         m_globalPresence->setPresence(presence);
     }
+
+    onPresenceChanged(m_globalPresence->currentPresence());
 }
 
 void GlobalPresenceChooser::onAllComboChanges(int index)
@@ -378,35 +360,32 @@ void GlobalPresenceChooser::onAllComboChanges(int index)
         }
     }
 
+    clearFocus();
 }
 
-
 void GlobalPresenceChooser::onPresenceChanged(const KTp::Presence &presence)
 {
-    if (presence.type() == Tp::ConnectionPresenceTypeUnknown) {
+    if (presence.type() == Tp::ConnectionPresenceTypeUnset) {
         setCurrentIndex(-1);
         m_busyOverlay->start();
         return;
     }
-    for (int i = 0; i < count() ; i++) {
-        KTp::Presence itemPresence = itemData(i, KTp::PresenceModel::PresenceRole).value<KTp::Presence>();
-        if (itemPresence.type() == presence.type() && itemPresence.statusMessage() == presence.statusMessage()) {
-            setCurrentIndex(i);
-            if (itemPresence != m_modelExtended->temporaryPresence()) {
-                m_modelExtended->removeTemporaryPresence();
-            }
-            return;
-        }
+
+    const QModelIndexList &matchIndexList = m_model->match(m_model->index(0, 0), KTp::PresenceModel::PresenceRole, QVariant::fromValue<KTp::Presence>(presence));
+    if (!matchIndexList.isEmpty()) {
+        m_modelExtended->removeTemporaryPresence();
+        setCurrentIndex(matchIndexList.at(0).row());
+    } else {
+        const QModelIndex &index = m_modelExtended->addTemporaryPresence(presence);
+        setCurrentIndex(index.row());
     }
 
-    QModelIndex index = m_modelExtended->addTemporaryPresence(presence);
-    setCurrentIndex(index.row());
     m_busyOverlay->stop();
 }
 
-void GlobalPresenceChooser::onConnectionStatusChanged(Tp::ConnectionStatus connectionStatus)
+void GlobalPresenceChooser::onConnectionStatusChanged(KTp::GlobalPresence::ConnectionStatus connectionStatus)
 {
-    if (connectionStatus == Tp::ConnectionStatusConnecting) {
+    if (connectionStatus == KTp::GlobalPresence::Connecting) {
         repositionOverlays();
         m_busyOverlay->start();
     } else {
@@ -443,27 +422,24 @@ void GlobalPresenceChooser::onChangePresenceMessageClicked()
     setEditable(true);
 
     //if current presence has no presence message, delete the text
-    if (m_globalPresence->requestedPresence().statusMessage().isEmpty()) {
+    if (m_globalPresence->globalPresence().statusMessage().isEmpty()) {
         lineEdit()->clear();
+    } else {
+        lineEdit()->setText(m_globalPresence->globalPresence().statusMessage());
     }
 
-    m_lineEditContextMenu = lineEdit()->createStandardContextMenu();
-
     lineEdit()->setFocus();
 }
 
 void GlobalPresenceChooser::onConfirmPresenceMessageClicked()
 {
     m_changePresenceMessageButton->show();
-
     KTp::Presence presence = itemData(currentIndex(), KTp::PresenceModel::PresenceRole).value<KTp::Presence>();
-    presence.setStatus(presence.type(), presence.status(), lineEdit()->text());
-    QModelIndex newPresence = m_model->addPresence(presence); //m_model->addPresence(presence);
+    presence.setStatusMessage(lineEdit()->text());
+
     setEditable(false);
-    setCurrentIndex(newPresence.row());
 
-    onUserActivatedComboChange(newPresence.row());
-    onAllComboChanges(newPresence.row());
+    m_globalPresence->setPresence(presence);
 }
 
 
diff --git a/global-presence-chooser.h b/global-presence-chooser.h
index f07b882..3c6e48d 100644
--- a/global-presence-chooser.h
+++ b/global-presence-chooser.h
@@ -23,7 +23,7 @@
 
 #include <KComboBox>
 
-#include <TelepathyQt/AccountManager>
+#include <KTp/global-presence.h>
 #include <KTp/presence.h>
 
 class QMenu;
@@ -36,15 +36,18 @@ namespace KTp {
     class PresenceModel;
 }
 
+extern const QString KDED_STATUS_MESSAGE_PARSER_WHATSTHIS;
+
 class GlobalPresenceChooser : public KComboBox
 {
     Q_OBJECT
 public:
     explicit GlobalPresenceChooser(QWidget *parent = 0);
-    void setAccountManager(const Tp::AccountManagerPtr &accountManager);
 
     void repositionOverlays();
 
+    KTp::GlobalPresence *globalPresence() {return m_globalPresence;};
+
 protected:
     virtual bool event(QEvent *event);
     virtual void setEditable(bool editable); /** Hides overlay and calls ancestor's method. */
@@ -53,7 +56,7 @@ private Q_SLOTS:
     void onUserActivatedComboChange(int index);
     void onAllComboChanges(int index);
     void onPresenceChanged(const KTp::Presence &presence);
-    void onConnectionStatusChanged(Tp::ConnectionStatus connectionStatus);
+    void onConnectionStatusChanged(KTp::GlobalPresence::ConnectionStatus connectionStatus);
     void onChangePresenceMessageClicked();
     void onConfirmPresenceMessageClicked();
 
@@ -63,7 +66,6 @@ private:
     PresenceModelExtended *m_modelExtended;
 
     KPixmapSequenceOverlayPainter *m_busyOverlay;
-    Tp::AccountManagerPtr m_accountManager;
     QPushButton *m_changePresenceMessageButton;
     QPointer<QMenu> m_lineEditContextMenu;
 };
diff --git a/main-widget.cpp b/main-widget.cpp
index 4b4f700..31622ac 100644
--- a/main-widget.cpp
+++ b/main-widget.cpp
@@ -46,6 +46,7 @@
 #include <KTp/actions.h>
 #include <KTp/contact-factory.h>
 #include <KTp/types.h>
+#include <KTp/global-presence.h>
 #include <KTp/Widgets/add-contact-dialog.h>
 #include <KTp/Widgets/join-chat-room-dialog.h>
 #include <KTp/Widgets/start-chat-dialog.h>
@@ -179,7 +180,7 @@ void MainWidget::onAccountManagerReady(Tp::PendingOperation* op)
         return;
     }
 
-    m_presenceChooser->setAccountManager(m_accountManager);
+    m_presenceChooser->globalPresence()->setAccountManager(m_accountManager);
     m_contactsListView->setAccountManager(m_accountManager);
     m_contextMenu->setAccountManager(m_accountManager);
 }
@@ -291,8 +292,9 @@ void MainWidget::closeEvent(QCloseEvent* e)
     if (qApp->closingDown()) {
         //the standard KMessageBox control saves "true" if you select the checkbox, therefore the reversed var name
         bool dontCheckForPlasmoid = notifyConigGroup.readEntry("dont_check_for_plasmoid", false);
+        bool onlineAccounts = !m_presenceChooser->globalPresence()->onlineAccounts()->accounts().isEmpty();
 
-        if (isAnyAccountOnline() && !dontCheckForPlasmoid) {
+        if (onlineAccounts && !dontCheckForPlasmoid) {
             if (!isPresencePlasmoidPresent()) {
                 switch (KMessageBox::warningYesNoCancel(this,
                         i18n("You do not have any other presence controls active (a Presence widget for example).\n"
@@ -305,17 +307,17 @@ void MainWidget::closeEvent(QCloseEvent* e)
 
                     case KMessageBox::No:
                         generalConfigGroup.writeEntry("go_offline_when_closing", true);
-                        goOffline();
+                        m_presenceChooser->globalPresence()->setPresence(KTp::Presence::offline(), KTp::GlobalPresence::Session);
                         break;
                     case KMessageBox::Cancel:
                         e->ignore();
                         return;
                 }
             }
-        } else if (isAnyAccountOnline() && dontCheckForPlasmoid) {
+        } else if (onlineAccounts && dontCheckForPlasmoid) {
             bool shouldGoOffline = generalConfigGroup.readEntry("go_offline_when_closing", false);
             if (shouldGoOffline) {
-                goOffline();
+                m_presenceChooser->globalPresence()->setPresence(KTp::Presence::offline(), KTp::GlobalPresence::Session);
             }
         }
 
@@ -340,28 +342,6 @@ bool MainWidget::isPresencePlasmoidPresent() const
     }
 }
 
-void MainWidget::goOffline()
-{
-    //FIXME use global presence
-    qCDebug(KTP_CONTACTLIST_MODULE) << "Setting all accounts offline...";
-    foreach (const Tp::AccountPtr &account, m_accountManager->allAccounts()) {
-        if (account->isEnabled() && account->isValid()) {
-            account->setRequestedPresence(Tp::Presence::offline());
-        }
-    }
-}
-
-bool MainWidget::isAnyAccountOnline() const
-{
-    foreach (const Tp::AccountPtr &account, m_accountManager->allAccounts()) {
-        if (account->isEnabled() && account->isValid() && account->isOnline()) {
-            return true;
-        }
-    }
-
-    return false;
-}
-
 void MainWidget::toggleSearchWidget(bool show)
 {
     m_searchContactAction->setChecked(show);
diff --git a/main-widget.h b/main-widget.h
index 43334ef..59063d6 100644
--- a/main-widget.h
+++ b/main-widget.h
@@ -57,7 +57,6 @@ public:
     ~MainWidget();
 
     bool isPresencePlasmoidPresent() const;
-    bool isAnyAccountOnline() const;
 
     enum SystemMessageType {
         /*
@@ -77,7 +76,6 @@ public:
 
 public Q_SLOTS:
     void showMessageToUser(const QString &text, const SystemMessageType type);
-    void goOffline();
     Q_INVOKABLE void toggleWindowVisibility();
 
 private Q_SLOTS:


More information about the kde-doc-english mailing list