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 <[email protected]>
+
+  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 <[email protected]>
+
+  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+&lt;val&gt;</strong>: Countdown to 0 from 
<strong>&lt;val&gt;</strong> minutes. e.g. %tr+30</p>")
+        + i18n("<p><strong>%time+[&lt;val&gt;]</strong>: The current local 
time, or if a value is specified, the local time <strong>&lt;val&gt;</strong> 
minutes in the future. e.g. %time+10</p>")
+        + i18n("<p><strong>%utc+[&lt;val&gt;]</strong>: The current UTC time, 
or if a value is specified, the UTC time <strong>&lt;val&gt;</strong> minutes 
into the future. e.g. %utc</p>")
+        + i18n("<p><strong>%te+[&lt;val&gt;]</strong>: Time elapsed from 
message activation. Append an initial elapsed time &quot;&lt;val&gt;&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+[&lt;val&gt;]</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+&lt;val&gt;</strong>: Refresh the status 
message every <strong>&lt;val&gt;</strong> minutes. e.g. %tu+2</p>")
+        + i18n("<p><strong>%tx+&lt;val&gt;</strong>: Expire the status message 
after <strong>&lt;val&gt;</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+&quot;&lt;val&gt;&quot;</strong>: Specify a 
message to follow %tr, %time, %utc, and %tx token expiry. e.g. %xm+&quot;Back 
%time. %tx+3 %xm+&quot;Running late&quot;&quot;</p>")
+        + i18n("<p><strong>%tf+&quot;&lt;val&gt;&quot;</strong>: Specify the 
format for local time using QDateTime::toString() expressions. e.g. 
%tf+&quot;h:mm AP t&quot;</p>")
+        + i18n("<p><strong>%uf+&quot;&lt;val&gt;&quot;</strong>: Specify the 
format for UTC time using QDateTime::toString() expressions. e.g. 
%uf+&quot;hh:mm t&quot;</p>")
+        + i18n("<p><strong>%sp+&quot;&lt;val&gt;&quot;</strong>: Change the 
separator for empty fields. e.g. %sp+&quot;-&quot;</p>")
+        + i18n("<p>Using tokens requires the Telepathy KDED module to be 
loaded. Tokens can be escaped by prepending a backslash character, e.g. 
&#92;%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&nbsp;%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:

Reply via email to