From cf8970ac63aae2665c9fba335ac0c6bc17dd354b Mon Sep 17 00:00:00 2001
From: Emmanuel Lepage Vallee <elv1313@gmail.com>
Date: Mon, 23 May 2016 22:49:03 -0400
Subject: [PATCH] profile: Partially fix multiple profiles

This commit implements some logic necessary to assign a profile per account
rather than a global one. This will require more work to add both a global
profile mode and a per account one.

A profile is now assigned to an account at all times to avoid any account
belonging to multiple profiles at once. This should make sense in itself
as it avoids a potential logical cardinality issue.

Again, it is not intended to break the Gnome/OS X/Windows clients way of
handling profiles, but make other models possible to implement.

Change-Id: Ibd675210dc2939244454cee338cf9cda263aa2ae
---
 src/account.cpp         | 45 +++++++++++++++++++++++++++++++++++++++++
 src/account.h           |  4 ++++
 src/private/account_p.h |  2 ++
 src/profile.cpp         |  4 ++++
 4 files changed, 55 insertions(+)

diff --git a/src/account.cpp b/src/account.cpp
index 876bda1b..c1990fd0 100644
--- a/src/account.cpp
+++ b/src/account.cpp
@@ -48,6 +48,8 @@
 #include "bootstrapmodel.h"
 #include "trustrequest.h"
 #include "person.h"
+#include "profile.h"
+#include "profilemodel.h"
 #include "pendingtrustrequestmodel.h"
 #include "private/pendingtrustrequestmodel_p.h"
 #include "accountstatusmodel.h"
@@ -1875,6 +1877,49 @@ void Account::setDTMFType(DtmfType type)
    d_ptr->setAccountProperty(DRing::Account::ConfProperties::DTMF_TYPE,(type==OverRtp)?"overrtp":"oversip");
 }
 
+void Account::setProfile(Profile* p)
+{
+    if (!p) {
+        qWarning() << "Cannot set profile to null as all accounts must belong to a profile";
+        return;
+    }
+
+    if (p == d_ptr->m_pProfile)
+        return; // nothing to do
+
+    if (d_ptr->m_pProfile)
+        d_ptr->m_pProfile->removeAccount(this);
+
+    if (p->addAccount(this))
+        p->save();
+
+    d_ptr->m_pProfile = p;
+
+    emit changed(this);
+}
+
+Profile* Account::profile() const
+{
+   // Make sure all accounts belong to a profile
+   if (!d_ptr->m_pProfile) {
+      Profile* p = ProfileModel::instance().selectedProfile();
+
+      if (!p) // for now default to the first profile
+         p = ProfileModel::instance().getProfile(ProfileModel::instance().index(0,0));
+
+      if (!p)
+         return nullptr;
+
+      // Use a const cast rather than a mutable to make sure the logic is the
+      // same between "automatic" default profile" and the setProfile
+      // implementation.
+      const_cast<Account*>(this)->setProfile(p);
+   }
+
+   return d_ptr->m_pProfile;
+}
+
+
 #define CAST(item) static_cast<int>(item)
 ///Proxy for AccountModel::setData
 void Account::setRoleData(int role, const QVariant& value)
diff --git a/src/account.h b/src/account.h
index bcd0560b..41b6c64b 100644
--- a/src/account.h
+++ b/src/account.h
@@ -43,6 +43,7 @@ class BootstrapModel          ;
 class NetworkInterfaceModel   ;
 class KeyExchangeModelPrivate ;
 class PendingTrustRequestModel;
+class Profile;
 
 //Private
 class AccountPrivate;
@@ -143,6 +144,7 @@ class LIB_EXPORT Account : public ItemBase {
    Q_PROPERTY(int            audioPortMin                 READ audioPortMin                  WRITE setAudioPortMin                )
    Q_PROPERTY(bool           upnpEnabled                  READ isUpnpEnabled                 WRITE setUpnpEnabled                 )
    Q_PROPERTY(bool           hasCustomUserAgent           READ hasCustomUserAgent            WRITE setHasCustomUserAgent          )
+   Q_PROPERTY(Profile*       profile                      READ profile                       WRITE setProfile                     )
 
    Q_PROPERTY(QString        userAgent                    READ userAgent                     WRITE setUserAgent                   )
    Q_PROPERTY(bool           useDefaultPort               READ useDefaultPort                WRITE setUseDefaultPort              )
@@ -431,6 +433,7 @@ class LIB_EXPORT Account : public ItemBase {
       RegistrationState  registrationState () const;
       Protocol           protocol          () const;
       ContactMethod*     contactMethod     () const;
+      Profile*           profile           () const;
       bool    allowIncomingFromUnknown     () const;
       bool    allowIncomingFromHistory     () const;
       bool    allowIncomingFromContact     () const;
@@ -510,6 +513,7 @@ class LIB_EXPORT Account : public ItemBase {
       void setAllowIncomingFromContact      (bool value );
       void setAllowIncomingFromUnknown      (bool value );
       void setHasActiveCallLimit            (bool value );
+      void setProfile                       (Profile* p );
 
       void setRoleData(int role, const QVariant& value);
 
diff --git a/src/private/account_p.h b/src/private/account_p.h
index afc27837..95a3a169 100644
--- a/src/private/account_p.h
+++ b/src/private/account_p.h
@@ -35,6 +35,7 @@ class NetworkInterfaceModel;
 class BootstrapModel;
 class DaemonCertificateCollection;
 class PendingTrustRequestModel;
+class Profile;
 
 typedef void (AccountPrivate::*account_function)();
 
@@ -139,6 +140,7 @@ public:
    Account::EditState           m_CurrentState            ;
    QMetaObject::Connection      m_cTlsCert                ;
    QMetaObject::Connection      m_cTlsCaCert              ;
+   Profile*                     m_pProfile {nullptr}      ;
    PendingTrustRequestModel*    m_pPendingTrustRequestModel;
 
    QHash<int, Account::RoleStatus> m_hRoleStatus;
diff --git a/src/profile.cpp b/src/profile.cpp
index 0ea18909..212c8bbc 100644
--- a/src/profile.cpp
+++ b/src/profile.cpp
@@ -77,6 +77,10 @@ bool Profile::addAccount(Account* acc)
     if (d_ptr->m_Accounts.indexOf(acc) == -1) {
        d_ptr->m_Accounts << acc;
 
+       // The Account::setProfile logic should take care of removing the old
+       // profile.
+       acc->setProfile(this);
+
        return true;
     }
 
-- 
GitLab