im: add off call instant messaging

- Add a non-designed page for out of call messaging
accesible by a button on smartlist.
- Use a combobox to select the contact method in case
there is more than one.
- Connect to message inserted signal to scroll to bottom
the message view.

Change-Id: I84c99403054fb8a64aecb93b87c7c68c1e34f4ac
Tuleap: #153
diff --git a/callwidget.cpp b/callwidget.cpp
index 53b988c..aa51bd7 100644
--- a/callwidget.cpp
+++ b/callwidget.cpp
@@ -37,6 +37,7 @@
 #include "media/recording.h"
 #include "media/textrecording.h"
 #include "recentmodel.h"
+#include "contactmethod.h"
 
 #include "wizarddialog.h"
 #include "windowscontactbackend.h"
@@ -46,11 +47,13 @@
 #include "historydelegate.h"
 #include "contactdelegate.h"
 #include "smartlistdelegate.h"
+#include "imdelegate.h"
 
 CallWidget::CallWidget(QWidget* parent) :
     NavWidget(END ,parent),
     ui(new Ui::CallWidget),
-    menu_(new QMenu())
+    menu_(new QMenu()),
+    imDelegate_(new ImDelegate())
 {
     setMouseTracking(true);
 
@@ -166,6 +169,7 @@
         });
 
         findRingAccount();
+        ui->listMessageView->setItemDelegate(imDelegate_);
 
     } catch (const std::exception& e) {
         qDebug() << "INIT ERROR" << e.what();
@@ -177,6 +181,7 @@
     delete ui;
     delete menu_;
     delete contactDelegate_;
+    delete imDelegate_;
 }
 
 void
@@ -397,11 +402,17 @@
 
     Q_UNUSED(oldSel)
 
+    if (newSel.indexes().empty())
+    {
+        ui->stackedWidget->setCurrentWidget(ui->welcomePage);
+        return;
+    }
     auto newIdx = newSel.indexes().first();
     if (not newIdx.isValid())
         return;
 
-    auto newIdxCall = RecentModel::instance().getActiveCall(RecentModel::instance().peopleProxy()->mapToSource(newIdx));
+    auto nodeIdx = RecentModel::instance().peopleProxy()->mapToSource(newIdx);
+    auto newIdxCall = RecentModel::instance().getActiveCall(nodeIdx);
 
     if (newIdxCall == actualCall_)
         return;
@@ -462,3 +473,73 @@
 
     on_smartList_doubleClicked(highLightedIndex_);
 }
+
+void
+CallWidget::on_btnchat_clicked()
+{
+    if (not highLightedIndex_.isValid())
+        return;
+
+    ui->smartList->selectionModel()->select(highLightedIndex_, QItemSelectionModel::ClearAndSelect);
+
+    ui->contactMethodComboBox->clear();
+
+    auto nodeIdx = RecentModel::instance().peopleProxy()->mapToSource(highLightedIndex_);
+    auto cmVector = RecentModel::instance().getContactMethods(nodeIdx);
+    foreach (const ContactMethod* cm, cmVector) {
+       ui->contactMethodComboBox->addItem(cm->uri());
+    }
+
+    ui->stackedWidget->currentWidget() == ui->messagingPage ?
+                ui->stackedWidget->setCurrentWidget(ui->welcomePage) :
+                ui->stackedWidget->setCurrentWidget(ui->messagingPage);
+}
+
+void
+CallWidget::on_sendButton_clicked()
+{
+    if (ui->messageEdit->text().isEmpty())
+        return;
+    auto number = ui->contactMethodComboBox->currentText();
+    if (auto cm = PhoneDirectoryModel::instance().getNumber(number)) {
+        QMap<QString, QString> msg;
+        msg["text/plain"] = ui->messageEdit->text();
+        cm->sendOfflineTextMessage(msg);
+        ui->messageEdit->clear();
+    } else {
+        qWarning() << "Contact Method not found for " << number;
+    }
+}
+
+void
+CallWidget::on_messageEdit_returnPressed()
+{
+    on_sendButton_clicked();
+}
+
+void
+CallWidget::on_contactMethodComboBox_currentIndexChanged(const QString& number)
+{
+    auto cm = PhoneDirectoryModel::instance().getNumber(number);
+    if (auto txtRecording = cm->textRecording()) {
+        ui->listMessageView->setModel(txtRecording->instantMessagingModel());
+        disconnect(imConnection_);
+        imConnection_ = connect(txtRecording,
+                SIGNAL(messageInserted(QMap<QString,QString>,ContactMethod*,Media::Media::Direction)),
+                this,
+                SLOT(slotAccountMessageReceived(QMap<QString,QString>,ContactMethod*,Media::Media::Direction)));
+        ui->listMessageView->scrollToBottom();
+    }
+}
+
+void
+CallWidget::slotAccountMessageReceived(const QMap<QString,QString> message,
+                                       ContactMethod* cm,
+                                       Media::Media::Direction dir)
+{
+    Q_UNUSED(message)
+    Q_UNUSED(cm)
+    Q_UNUSED(dir)
+
+    ui->listMessageView->scrollToBottom();
+}
diff --git a/callwidget.h b/callwidget.h
index 30541fb..b39d7c8 100644
--- a/callwidget.h
+++ b/callwidget.h
@@ -37,6 +37,7 @@
 class ContactDelegate;
 class HistoryDelegate;
 class SmartListDelegate;
+class ImDelegate;
 
 namespace Ui {
 class CallWidget;
@@ -59,6 +60,7 @@
     void on_ringContactLineEdit_returnPressed();
     void on_btnCall_clicked();
     void on_btnvideo_clicked();
+    void on_btnchat_clicked();
     inline void on_entered(const QModelIndex& i){highLightedIndex_ = i;};
 
 //UI SLOTS
@@ -69,6 +71,9 @@
     void on_cancelButton_clicked();
     void on_smartList_doubleClicked(const QModelIndex& index);
     void on_historyList_doubleClicked(const QModelIndex& index);
+    void on_sendButton_clicked();
+    void on_messageEdit_returnPressed();
+    void on_contactMethodComboBox_currentIndexChanged(const QString& number);
 
 private slots:
     void callIncoming(Call* call);
@@ -76,6 +81,7 @@
     void callStateChanged(Call* call, Call::State previousState);
     void findRingAccount(QModelIndex idx1, QModelIndex idx2, QVector<int> vec);
     void smartListSelectionChanged(const QItemSelection& newSel, const QItemSelection& oldSel);
+    void slotAccountMessageReceived(const QMap<QString,QString> message,ContactMethod* cm,Media::Media::Direction dir);
 
 private:
     Ui::CallWidget* ui;
@@ -89,6 +95,8 @@
     HistoryDelegate* historyDelegate_;
     SmartListDelegate* smartListDelegate_;
     QModelIndex highLightedIndex_;
+    ImDelegate* imDelegate_;
+    QMetaObject::Connection imConnection_;
 
 private:
     void findRingAccount();
diff --git a/callwidget.ui b/callwidget.ui
index 0a4d60b..5d49054 100644
--- a/callwidget.ui
+++ b/callwidget.ui
@@ -261,6 +261,46 @@
           </item>
          </layout>
         </widget>
+        <widget class="QWidget" name="messagingPage">
+         <layout class="QVBoxLayout" name="verticalLayout_11">
+          <property name="leftMargin">
+           <number>0</number>
+          </property>
+          <property name="topMargin">
+           <number>0</number>
+          </property>
+          <property name="rightMargin">
+           <number>0</number>
+          </property>
+          <property name="bottomMargin">
+           <number>0</number>
+          </property>
+          <item>
+           <widget class="QListView" name="listMessageView">
+            <property name="selectionMode">
+             <enum>QAbstractItemView::SingleSelection</enum>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QComboBox" name="contactMethodComboBox"/>
+          </item>
+          <item>
+           <layout class="QHBoxLayout" name="horizontalLayout_5">
+            <item>
+             <widget class="QLineEdit" name="messageEdit"/>
+            </item>
+            <item>
+             <widget class="QPushButton" name="sendButton">
+              <property name="text">
+               <string>Send</string>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </item>
+         </layout>
+        </widget>
         <widget class="QWidget" name="callInvitePage">
          <layout class="QVBoxLayout" name="verticalLayout_9">
           <property name="spacing">
diff --git a/combar.cpp b/combar.cpp
index c2a458b..498ef99 100644
--- a/combar.cpp
+++ b/combar.cpp
@@ -26,7 +26,6 @@
     ui->setupUi(this);
 
     // [jn] these buttons are for further uses
-    ui->btnchat->hide();
     ui->btncontactinfo->hide();
 }