From 9b4fffcdbcc43a368ddcce98e1f935a0161d2138 Mon Sep 17 00:00:00 2001
From: Emmanuel Lepage <emmanuel.lepage@savoirfairelinux.com>
Date: Tue, 20 Sep 2011 17:39:09 -0400
Subject: [PATCH] Add basic history drag and drop support

---
 kde/src/AkonadiBackend.cpp      |  1 +
 kde/src/CallView.cpp            | 30 ++++++++++---------
 kde/src/lib/Contact.cpp         | 10 +++++++
 kde/src/lib/Contact.h           |  4 +++
 kde/src/lib/sflphone_const.h    |  8 +++--
 kde/src/widgets/ContactDock.cpp |  3 ++
 kde/src/widgets/HistoryDock.cpp | 53 +++++++++++++++++++++++++++++++--
 kde/src/widgets/HistoryDock.h   | 12 ++++++--
 8 files changed, 100 insertions(+), 21 deletions(-)

diff --git a/kde/src/AkonadiBackend.cpp b/kde/src/AkonadiBackend.cpp
index ecd95ac5d9..67be33b30d 100644
--- a/kde/src/AkonadiBackend.cpp
+++ b/kde/src/AkonadiBackend.cpp
@@ -76,6 +76,7 @@ ContactList AkonadiBackend::update(Akonadi::Collection collection)
             aContact->setFamilyName     (tmp.familyName()     );
             aContact->setOrganization   (tmp.organization()   );
             aContact->setPreferredEmail (tmp.preferredEmail() );
+            aContact->setUid            (tmp.uid()            );
             aContact->setPhoneNumbers   (newNumbers           );
             
             if (!tmp.photo().data().isNull())
diff --git a/kde/src/CallView.cpp b/kde/src/CallView.cpp
index ef6a81b7ea..b0d2532bed 100644
--- a/kde/src/CallView.cpp
+++ b/kde/src/CallView.cpp
@@ -52,43 +52,45 @@ bool CallView::dropMimeData(QTreeWidgetItem *parent, int index, const QMimeData
    Q_UNUSED(index)
    Q_UNUSED(action)
    
-   QByteArray encodedData = data->data(MIME_CALLID);
+   QByteArray encodedCallId      = data->data( MIME_CALLID      );
+   QByteArray encodedPhoneNumber = data->data( MIME_PHONENUMBER );
    
-   qDebug() << "In export"<< QString(encodedData);
+   qDebug() << "In export"<< QString(encodedCallId);
+   qDebug() << "In export2"<< QString(encodedPhoneNumber);
    
-   if (!QString(encodedData).isEmpty()) {
-   clearArtefact(getIndex(encodedData));
+   if (!QString(encodedCallId).isEmpty()) {
+   clearArtefact(getIndex(encodedCallId));
    
       if (!parent) {
          qDebug() << "Call dropped on empty space";
-         if (getIndex(encodedData)->parent()) {
+         if (getIndex(encodedCallId)->parent()) {
             qDebug() << "Detaching participant";
-            detachParticipant(getCall(encodedData));
+            detachParticipant(getCall(encodedCallId));
          }
          else
             qDebug() << "The call is not in a conversation (doing nothing)";
          return true;
       }
       
-      if (getCall(parent)->getCallId() == QString(encodedData)) {
+      if (getCall(parent)->getCallId() == QString(encodedCallId)) {
          qDebug() << "Call dropped on itself (doing nothing)";
          return true;
       }
       
-      if ((parent->childCount()) && (getIndex(encodedData)->childCount())) {
+      if ((parent->childCount()) && (getIndex(encodedCallId)->childCount())) {
          qDebug() << "Merging two conferences";
-         mergeConferences(getCall(parent),getCall(encodedData));
+         mergeConferences(getCall(parent),getCall(encodedCallId));
          return true;
       }
       else if ((parent->parent()) || (parent->childCount())) {
          qDebug() << "Call dropped on a conference";
          
-         if ((getIndex(encodedData)->childCount()) && (!parent->childCount())) {
+         if ((getIndex(encodedCallId)->childCount()) && (!parent->childCount())) {
             qDebug() << "Conference dropped on a call (doing nothing)";
             return true;
          }
          
-         QTreeWidgetItem* call1 = getIndex(encodedData);
+         QTreeWidgetItem* call1 = getIndex(encodedCallId);
          QTreeWidgetItem* call2 = (parent->parent())?parent->parent():parent;
          
          if (call1->parent()) {
@@ -103,14 +105,14 @@ bool CallView::dropMimeData(QTreeWidgetItem *parent, int index, const QMimeData
             }
             else if (call1->parent()) {
                qDebug() << "Moving call from a conference to an other";
-               detachParticipant(getCall(encodedData));
+               detachParticipant(getCall(encodedCallId));
             }
          }
          qDebug() << "Adding participant";
          addParticipant(getCall(call1),getCall(call2));
          return true;
       }
-      else if ((getIndex(encodedData)->childCount()) && (!parent->childCount())) {
+      else if ((getIndex(encodedCallId)->childCount()) && (!parent->childCount())) {
          qDebug() << "Call dropped on it's own conference (doing nothing)";
          return true;
       }
@@ -118,7 +120,7 @@ bool CallView::dropMimeData(QTreeWidgetItem *parent, int index, const QMimeData
 
       
       qDebug() << "Call dropped on another call";
-      createConferenceFromCall(getCall(encodedData),getCall(parent));
+      createConferenceFromCall(getCall(encodedCallId),getCall(parent));
       return true;
    }
    
diff --git a/kde/src/lib/Contact.cpp b/kde/src/lib/Contact.cpp
index 54731e870f..21d18d14fe 100644
--- a/kde/src/lib/Contact.cpp
+++ b/kde/src/lib/Contact.cpp
@@ -99,6 +99,11 @@ QString Contact::getPreferredEmail()  const
    return m_pPreferredEmail;
 }
 
+QString Contact::getUid() const
+{
+   return m_pUid;
+}
+
 QString Contact::getType() const
 {
    return m_pType;
@@ -143,4 +148,9 @@ void Contact::setOrganization(QString name)
 void Contact::setPreferredEmail(QString name)
 {
    m_pPreferredEmail = name;
+}
+
+void Contact::setUid(QString id)
+{
+   m_pUid = id;
 }
\ No newline at end of file
diff --git a/kde/src/lib/Contact.h b/kde/src/lib/Contact.h
index 33a5955e8a..73d706f0bb 100644
--- a/kde/src/lib/Contact.h
+++ b/kde/src/lib/Contact.h
@@ -34,6 +34,7 @@
 
 /**
    @author Jérémy Quentin <jeremy.quentin@savoirfairelinux.com>
+   @author Jérémy Quentin <emmanuel.lepage@savoirfairelinux.com>
 */
 class LIB_EXPORT Contact : public QObject{
    Q_OBJECT
@@ -63,6 +64,7 @@ private:
    QString      m_pFormattedName  ;
    QString      m_pPreferredEmail ;
    QString      m_pOrganization   ;
+   QString      m_pUid            ;
    bool         displayPhoto      ;
    PhoneNumbers m_pNumbers        ;
 public:
@@ -77,6 +79,7 @@ public:
    virtual QString        getSecondName()      const;
    virtual QString        getFormattedName()   const;
    virtual QString        getOrganization()    const;
+   virtual QString        getUid()             const;
    virtual QString        getPreferredEmail()  const;
    virtual const QPixmap* getPhoto()           const;
    virtual QString        getType()            const;
@@ -89,6 +92,7 @@ public:
    virtual void setFamilyName     (QString name   );
    virtual void setOrganization   (QString name   );
    virtual void setPreferredEmail (QString name   );
+   virtual void setUid            (QString id     );
    virtual void setPhoto          (QPixmap* photo );
    
 protected:
diff --git a/kde/src/lib/sflphone_const.h b/kde/src/lib/sflphone_const.h
index 38ebe1995c..5668b1ea29 100644
--- a/kde/src/lib/sflphone_const.h
+++ b/kde/src/lib/sflphone_const.h
@@ -307,7 +307,11 @@ typedef enum
 } call_state;
 
 /** MIME API */
-#define MIME_CALLID "text/sflphone.call.id"
-#define MIME_PLAIN_TEXT "text/plain"
+#define MIME_CALLID           "text/sflphone.call.id"
+#define MIME_CONTACT          "text/sflphone.contact"
+#define MIME_HISTORYID        "text/sflphone.history.id"
+#define MIME_PHONENUMBER      "text/sflphone.phone.number"
+#define MIME_CONTACT_PHONE    "text/sflphone.contact.phone"
+#define MIME_PLAIN_TEXT       "text/plain"
 #endif
 
diff --git a/kde/src/widgets/ContactDock.cpp b/kde/src/widgets/ContactDock.cpp
index aee22b880e..ee80de641e 100644
--- a/kde/src/widgets/ContactDock.cpp
+++ b/kde/src/widgets/ContactDock.cpp
@@ -60,6 +60,7 @@ ContactDock::ContactDock(QWidget* parent) : QDockWidget(parent)
    m_pCallView     = new QListWidget ( this              );
    m_pShowHistoCK  = new QCheckBox   ( this              );
 
+
    QStringList sortType;
    sortType << "Name" << "Organisation" << "Phone number type" << "Rencently used" << "Group";
    m_pSortByCBB->addItems(sortType);
@@ -70,6 +71,8 @@ ContactDock::ContactDock(QWidget* parent) : QDockWidget(parent)
    m_pContactView->headerItem()->setText(0,"Contacts");
    m_pContactView->header()->setClickable(true);
    m_pContactView->header()->setSortIndicatorShown(true);
+   m_pContactView->setAcceptDrops(true);
+   m_pContactView->setDragEnabled(true);
 
    m_pContactView->setAlternatingRowColors(true);
 
diff --git a/kde/src/widgets/HistoryDock.cpp b/kde/src/widgets/HistoryDock.cpp
index 80925e90f4..c8c648cba1 100644
--- a/kde/src/widgets/HistoryDock.cpp
+++ b/kde/src/widgets/HistoryDock.cpp
@@ -15,10 +15,12 @@
 #include "widgets/HistoryTreeItem.h"
 #include "conf/ConfigurationSkeleton.h"
 #include "AkonadiBackend.h"
+#include "lib/sflphone_const.h"
 
 class QNumericTreeWidgetItem : public QTreeWidgetItem {
    public:
       QNumericTreeWidgetItem(QTreeWidget* parent):QTreeWidgetItem(parent),widget(0),weight(-1){}
+      QNumericTreeWidgetItem(QTreeWidgetItem* parent):QTreeWidgetItem(parent),widget(0),weight(-1){}
       HistoryTreeItem* widget;
       int weight;
    private:
@@ -39,7 +41,7 @@ HistoryDock::HistoryDock(QWidget* parent) : QDockWidget(parent)
    setMinimumSize(250,0);
    setSizePolicy(QSizePolicy::Minimum,QSizePolicy::Minimum);
    m_pFilterLE   = new KLineEdit();
-   m_pItemView   = new QTreeWidget(this);
+   m_pItemView   = new HistoryTree(this);
    m_pSortByCBB  = new QComboBox();
    m_pSortByL    = new QLabel("Sort by:");
    m_pFromL      = new QLabel("From:");
@@ -61,6 +63,8 @@ HistoryDock::HistoryDock(QWidget* parent) : QDockWidget(parent)
    m_pItemView->header    ()->setClickable(true          );
    m_pItemView->header    ()->setSortIndicatorShown(true );
    m_pItemView->setAlternatingRowColors(true             );
+   m_pItemView->setAcceptDrops( true                     );
+   m_pItemView->setDragEnabled( true                     );
 
    m_pFilterLE->setPlaceholderText("Filter");
    m_pFilterLE->setClearButtonShown(true);
@@ -153,8 +157,9 @@ void HistoryDock::reload()
                group[getIdentity(item)]->setText(0,getIdentity(item));
                m_pItemView->addTopLevelItem(group[getIdentity(item)]);
             }
-            QTreeWidgetItem* twItem = new QTreeWidgetItem(group[getIdentity(item)]);
+            QNumericTreeWidgetItem* twItem = new QNumericTreeWidgetItem(group[getIdentity(item)]);
             item->setItem(twItem);
+            twItem->widget = item;
             m_pItemView->setItemWidget(twItem,0,item);
          }
          break;
@@ -169,8 +174,9 @@ void HistoryDock::reload()
             }
             group[getIdentity(item)]->weight++;
             group[getIdentity(item)]->setText(0,getIdentity(item)+" ("+QString::number(group[getIdentity(item)]->weight)+")");
-            QTreeWidgetItem* twItem = new QTreeWidgetItem(group[getIdentity(item)]);
+            QNumericTreeWidgetItem* twItem = new QNumericTreeWidgetItem(group[getIdentity(item)]);
             item->setItem(twItem);
+            twItem->widget = item;
             m_pItemView->setItemWidget(twItem,0,item);
          }
          break;
@@ -242,4 +248,45 @@ void HistoryDock::updateLinkedToDate(QDate date)
    disconnect(m_pFromDW  ,  SIGNAL(changed(QDate)),       this, SLOT(updateLinkedFromDate(QDate)));
    updateLinkedDate(m_pFromDW,m_pCurrentToDate,date);
    connect(m_pFromDW  ,  SIGNAL(changed(QDate)),       this, SLOT(updateLinkedFromDate(QDate)));
+}
+
+QMimeData* HistoryTree::mimeData( const QList<QTreeWidgetItem *> items) const
+{
+   qDebug() << "An history call is being dragged";
+   if (items.size() < 1) {
+      return NULL;
+   }
+
+   QMimeData *mimeData = new QMimeData();
+
+   //Contact
+   if (dynamic_cast<QNumericTreeWidgetItem*>(items[0])) {
+      QNumericTreeWidgetItem* item = dynamic_cast<QNumericTreeWidgetItem*>(items[0]);
+      if (item->widget != 0) {
+         mimeData->setData(MIME_PHONENUMBER, item->widget->call()->getPeerPhoneNumber().toUtf8());
+      }
+   }
+   else {
+      qDebug() << "the item is not a call";
+   }
+
+// 
+//    //Plain text for other applications
+//    mimeData->setData(MIME_PLAIN_TEXT, QString(getCall(items[0])->getPeerName()+"\n"+getCall(items[0])->getPeerPhoneNumber()).toAscii());
+// 
+//    //TODO Comment this line if you don't want to see ugly artefact, but the caller details will not be visible while dragged
+//    items[0]->setText(0, getCall(items[0])->getPeerName() + "\n" + getCall(items[0])->getPeerPhoneNumber());
+   return mimeData;
+}
+
+bool HistoryTree::dropMimeData(QTreeWidgetItem *parent, int index, const QMimeData *data, Qt::DropAction action)
+{
+   Q_UNUSED(index)
+   Q_UNUSED(action)
+
+   QByteArray encodedData = data->data(MIME_CALLID);
+
+   qDebug() << "In history import"<< QString(encodedData);
+
+   return false;
 }
\ No newline at end of file
diff --git a/kde/src/widgets/HistoryDock.h b/kde/src/widgets/HistoryDock.h
index 2180bad2ed..466f798d95 100644
--- a/kde/src/widgets/HistoryDock.h
+++ b/kde/src/widgets/HistoryDock.h
@@ -16,6 +16,7 @@ class QCheckBox;
 class QPushButton;
 class QDate;
 class HistoryTreeItem;
+class HistoryTree;
 
 typedef QList<HistoryTreeItem*> HistoryList;
 
@@ -34,8 +35,7 @@ private:
 
    void updateLinkedDate(KDateWidget* item, QDate& prevDate, QDate& newDate);
    QString getIdentity(HistoryTreeItem* item);
-   
-   QTreeWidget*  m_pItemView;
+   HistoryTree*  m_pItemView;
    KLineEdit*    m_pFilterLE;
    QComboBox*    m_pSortByCBB;
    QLabel*       m_pSortByL;
@@ -58,4 +58,12 @@ private slots:
    void updateContactInfo();
 };
 
+class HistoryTree : public QTreeWidget {
+   Q_OBJECT
+public:
+   HistoryTree(QWidget* parent) : QTreeWidget(parent) {}
+   virtual QMimeData* mimeData( const QList<QTreeWidgetItem *> items) const;
+   bool dropMimeData(QTreeWidgetItem *parent, int index, const QMimeData *data, Qt::DropAction action);
+};
+
 #endif
\ No newline at end of file
-- 
GitLab