Commit ec858ede authored by Emmanuel Lepage's avatar Emmanuel Lepage

Add drag and drop support, initial context menu and fix 3 bugs in the account dialog

parent 9b4fffcd
......@@ -69,6 +69,7 @@ ContactList AkonadiBackend::update(Akonadi::Collection collection)
newNumbers << new Contact::PhoneNumber(number.number(),number.typeLabel());
m_pContactByPhone[number.number()] = aContact;
}
m_pContactByUid[tmp.uid()] = aContact;
aContact->setNickName (tmp.nickName() );
aContact->setFormattedName (tmp.formattedName() );
......@@ -103,6 +104,11 @@ Contact* AkonadiBackend::getContactByPhone(QString phoneNumber)
return m_pContactByPhone[phoneNumber];
}
Contact* AkonadiBackend::getContactByUid(QString uid)
{
return m_pContactByUid[uid];
}
void AkonadiBackend::collectionsReceived( const Akonadi::Collection::List& list)
{
foreach (Akonadi::Collection coll, list) {
......
......@@ -16,17 +16,17 @@ class AkonadiBackend : public QObject {
public:
static AkonadiBackend* getInstance();
Contact* getContactByPhone(QString phoneNumber);
Contact* getContactByUid(QString uid);
private:
AkonadiBackend(QObject* parent);
virtual ~AkonadiBackend();
//Attributes
static AkonadiBackend* m_pInstance;
Akonadi::Session* m_pSession;
Akonadi::Collection m_pCollection;
QHash<QString,Contact*> m_pContactByPhone;
QHash<QString,Contact*> m_pContactByUid;
public slots:
ContactList update();
ContactList update(Akonadi::Collection collection);
......
#include "CallView.h"
#include "AkonadiBackend.h"
#include "lib/Contact.h"
#include <QtGui/QInputDialog>
///Retrieve current and older calls from the daemon, fill history and the calls TreeView and enable drag n' drop
CallView::CallView(ModelType type, QWidget* parent) : QTreeWidget(parent), CallModel<CallTreeItem*,QTreeWidgetItem*>(type)
CallView::CallView(ModelType type, QWidget* parent) : QTreeWidget(parent), TreeWidgetCallModel(type)
{
if (type == ActiveCall)
initCall();
......@@ -46,21 +50,14 @@ CallView::CallView(ModelType type, QWidget* parent) : QTreeWidget(parent), CallM
* *
****************************************************************************/
///Action performed when an item is dropped on the TreeView
bool CallView::dropMimeData(QTreeWidgetItem *parent, int index, const QMimeData *data, Qt::DropAction action)
bool CallView::callToCall(QTreeWidgetItem *parent, int index, const QMimeData *data, Qt::DropAction action)
{
Q_UNUSED(index)
Q_UNUSED(action)
QByteArray encodedCallId = data->data( MIME_CALLID );
QByteArray encodedPhoneNumber = data->data( MIME_PHONENUMBER );
qDebug() << "In export"<< QString(encodedCallId);
qDebug() << "In export2"<< QString(encodedPhoneNumber);
if (!QString(encodedCallId).isEmpty()) {
clearArtefact(getIndex(encodedCallId));
clearArtefact(getIndex(encodedCallId));
if (!parent) {
qDebug() << "Call dropped on empty space";
if (getIndex(encodedCallId)->parent()) {
......@@ -71,12 +68,12 @@ bool CallView::dropMimeData(QTreeWidgetItem *parent, int index, const QMimeData
qDebug() << "The call is not in a conversation (doing nothing)";
return true;
}
if (getCall(parent)->getCallId() == QString(encodedCallId)) {
qDebug() << "Call dropped on itself (doing nothing)";
return true;
}
if ((parent->childCount()) && (getIndex(encodedCallId)->childCount())) {
qDebug() << "Merging two conferences";
mergeConferences(getCall(parent),getCall(encodedCallId));
......@@ -84,15 +81,15 @@ bool CallView::dropMimeData(QTreeWidgetItem *parent, int index, const QMimeData
}
else if ((parent->parent()) || (parent->childCount())) {
qDebug() << "Call dropped on a conference";
if ((getIndex(encodedCallId)->childCount()) && (!parent->childCount())) {
qDebug() << "Conference dropped on a call (doing nothing)";
return true;
}
QTreeWidgetItem* call1 = getIndex(encodedCallId);
QTreeWidgetItem* call2 = (parent->parent())?parent->parent():parent;
if (call1->parent()) {
qDebug() << "Call 1 is part of a conference";
if (call1->parent() == call2) {
......@@ -109,6 +106,14 @@ bool CallView::dropMimeData(QTreeWidgetItem *parent, int index, const QMimeData
}
}
qDebug() << "Adding participant";
int state = getCall(call1)->getState();
if(state == CALL_STATE_INCOMING || state == CALL_STATE_DIALING || state == CALL_STATE_TRANSFER || state == CALL_STATE_TRANSF_HOLD) {
getCall(call1)->actionPerformed(CALL_ACTION_ACCEPT);
}
state = getCall(call2)->getState();
if(state == CALL_STATE_INCOMING || state == CALL_STATE_DIALING || state == CALL_STATE_TRANSFER || state == CALL_STATE_TRANSF_HOLD) {
getCall(call2)->actionPerformed(CALL_ACTION_ACCEPT);
}
addParticipant(getCall(call1),getCall(call2));
return true;
}
......@@ -116,14 +121,135 @@ bool CallView::dropMimeData(QTreeWidgetItem *parent, int index, const QMimeData
qDebug() << "Call dropped on it's own conference (doing nothing)";
return true;
}
qDebug() << "Call dropped on another call";
createConferenceFromCall(getCall(encodedCallId),getCall(parent));
return true;
}
return false;
}
bool CallView::phoneNumberToCall(QTreeWidgetItem *parent, int index, const QMimeData *data, Qt::DropAction action)
{
Q_UNUSED(index)
Q_UNUSED(action)
QByteArray encodedPhoneNumber = data->data( MIME_PHONENUMBER );
if (!QString(encodedPhoneNumber).isEmpty()) {
Contact* contact = AkonadiBackend::getInstance()->getContactByPhone(encodedPhoneNumber);
QString name;
if (contact)
name = contact->getFormattedName();
else
name = "Unknow";
Call* call2 = TreeWidgetCallModel::addDialingCall(name, TreeWidgetCallModel::getCurrentAccountId());
call2->appendText(QString(encodedPhoneNumber));
if (!parent) {
//Dropped on free space
qDebug() << "Adding new dialing call";
}
else if (parent->childCount() || parent->parent()) {
//Dropped on a conversation
QTreeWidgetItem* call = (parent->parent())?parent->parent():parent;
addParticipant(getCall(call),call2);
}
else {
//Dropped on call
call2->actionPerformed(CALL_ACTION_ACCEPT);
int state = getCall(parent)->getState();
if(state == CALL_STATE_INCOMING || state == CALL_STATE_DIALING || state == CALL_STATE_TRANSFER || state == CALL_STATE_TRANSF_HOLD) {
getCall(parent)->actionPerformed(CALL_ACTION_ACCEPT);
}
createConferenceFromCall(call2,getCall(parent));
}
}
return false;
}
bool CallView::contactToCall(QTreeWidgetItem *parent, int index, const QMimeData *data, Qt::DropAction action)
{
qDebug() << "contactToCall";
Q_UNUSED(index)
Q_UNUSED(action)
QByteArray encodedContact = data->data( MIME_CONTACT );
if (!QString(encodedContact).isEmpty()) {
Contact* contact = AkonadiBackend::getInstance()->getContactByUid(encodedContact);
qDebug() << "Contact:" << contact;
if (contact) {
qDebug() << "In contact";
Call* call2;
if (contact->getPhoneNumbers().count() == 1) {
call2 = TreeWidgetCallModel::addDialingCall(contact->getFormattedName(), TreeWidgetCallModel::getCurrentAccountId());
call2->appendText(contact->getPhoneNumbers()[0]->getNumber());
}
else if (contact->getPhoneNumbers().count() > 1) {
bool ok = false;
QHash<QString,QString> map;
QStringList list;
foreach (Contact::PhoneNumber* number, contact->getPhoneNumbers()) {
map[number->getType()+" ("+number->getNumber()+")"] = number->getNumber();
list << number->getType()+" ("+number->getNumber()+")";
}
QString result = QInputDialog::getItem (this, QString("Select phone number"), QString("This contact have many phone number, please select the one you wish to call"), list, 0, false, &ok);
if (ok) {
call2 = TreeWidgetCallModel::addDialingCall(contact->getFormattedName(), TreeWidgetCallModel::getCurrentAccountId());
call2->appendText(map[result]);
}
else {
qDebug() << "Operation cancelled";
return false;
}
}
else {
qDebug() << "This contact have no valid phone number";
return false;
}
if (!parent) {
//Dropped on free space
qDebug() << "Adding new dialing call";
}
else if (parent->childCount() || parent->parent()) {
//Dropped on a conversation
QTreeWidgetItem* call = (parent->parent())?parent->parent():parent;
addParticipant(getCall(call),call2);
}
else {
//Dropped on call
call2->actionPerformed(CALL_ACTION_ACCEPT);
int state = getCall(parent)->getState();
if(state == CALL_STATE_INCOMING || state == CALL_STATE_DIALING || state == CALL_STATE_TRANSFER || state == CALL_STATE_TRANSF_HOLD) {
getCall(parent)->actionPerformed(CALL_ACTION_ACCEPT);
}
createConferenceFromCall(call2,getCall(parent));
}
}
}
return false;
}
///Action performed when an item is dropped on the TreeView
bool CallView::dropMimeData(QTreeWidgetItem *parent, int index, const QMimeData *data, Qt::DropAction action)
{
Q_UNUSED(index)
Q_UNUSED(action)
QByteArray encodedCallId = data->data( MIME_CALLID );
QByteArray encodedPhoneNumber = data->data( MIME_PHONENUMBER );
QByteArray encodedContact = data->data( MIME_CONTACT );
if (!QString(encodedCallId).isEmpty()) {
qDebug() << "CallId dropped"<< QString(encodedCallId);
callToCall(parent, index, data, action);
}
else if (!QString(encodedPhoneNumber).isEmpty()) {
qDebug() << "PhoneNumber dropped"<< QString(encodedPhoneNumber);
phoneNumberToCall(parent, index, data, action);
}
else if (!QString(encodedContact).isEmpty()) {
qDebug() << "Contact dropped"<< QString(encodedContact);
contactToCall(parent, index, data, action);
}
return false;
}
......@@ -350,7 +476,7 @@ void CallView::itemClicked(QTreeWidgetItem* item, int column) {
Call* CallView::addConference(const QString & confID)
{
qDebug() << "Conference created";
Call* newConf = CallModel<CallTreeItem*,QTreeWidgetItem*>::addConference(confID);
Call* newConf = TreeWidgetCallModel::addConference(confID);
//InternalCallModelStruct<CallTreeItem>* aNewStruct = privateCallList_callId[confID];
......@@ -387,7 +513,7 @@ Call* CallView::addConference(const QString & confID)
bool CallView::conferenceChanged(const QString &confId, const QString &state)
{
qDebug() << "Conference changed";
if (!CallModel<CallTreeItem*,QTreeWidgetItem*>::conferenceChanged(confId, state))
if (!TreeWidgetCallModel::conferenceChanged(confId, state))
return false;
CallManagerInterface& callManager = CallManagerInterfaceSingleton::getInstance();
......@@ -421,7 +547,7 @@ void CallView::conferenceRemoved(const QString &confId)
insertItem(extractItem(getIndex(confId)->child(0)));
}
takeTopLevelItem(indexOfTopLevelItem(getIndex(confId)));
CallModel<CallTreeItem*,QTreeWidgetItem*>::conferenceRemoved(confId);
TreeWidgetCallModel::conferenceRemoved(confId);
qDebug() << "Conference removed";
}
......
......@@ -22,7 +22,9 @@ class CallTreeItemDelegate : public QItemDelegate
}
};
class CallView : private QTreeWidget, public CallModel<CallTreeItem*,QTreeWidgetItem*> {
typedef CallModel<CallTreeItem*,QTreeWidgetItem*> TreeWidgetCallModel;
class CallView : private QTreeWidget, public TreeWidgetCallModel {
Q_OBJECT
public:
CallView(ModelType type, QWidget* parent =0);
......@@ -48,6 +50,9 @@ class CallView : private QTreeWidget, public CallModel<CallTreeItem*,QTreeWidget
protected:
void dragEnterEvent(QDragEnterEvent *e) { e->accept(); }
void dragMoveEvent(QDragMoveEvent *e) { e->accept(); }
bool callToCall(QTreeWidgetItem *parent, int index, const QMimeData *data, Qt::DropAction action);
bool phoneNumberToCall(QTreeWidgetItem *parent, int index, const QMimeData *data, Qt::DropAction action);
bool contactToCall(QTreeWidgetItem *parent, int index, const QMimeData *data, Qt::DropAction action);
public slots:
void destroyCall(Call* toDestroy);
......
......@@ -76,8 +76,8 @@ enum CallAction {
NumberOfCallActions};
private:
// Whether or not the object has been initialized
bool initialized_;
// Whether or not the object has been initialized
bool initialized_;
KAction * action_accept;
KAction * action_refuse;
KAction * action_hold;
......
......@@ -253,14 +253,25 @@ void DlgAccounts::saveAccount(QListWidgetItem * item)
account->setAccountDetail(LOCAL_INTERFACE,comboBox_ni_local_address->currentText());
QStringList _codecList;
qDebug() << keditlistbox_codec->items() << codecList;
foreach (QString aCodec, keditlistbox_codec->items()) {
foreach (StringHash _aCodec, codecList) {
if (_aCodec["alias"] == aCodec) {
qDebug() << "Saving:" << _aCodec["id"];
_codecList << _aCodec["id"];
}
}
// }
// foreach (QString aCodec, keditlistbox_codec->items()) {
// foreach (StringHash aCodec, codecList) {
// if (aCodec["alias"] == keditlistbox_codec->currentText()) {
// label_bandwidth_value->setText(aCodec["bandwidth"]);
// label_bitrate_value->setText(aCodec["bitrate"]);
// label_frequency_value->setText(aCodec["frequency"]);
// }
// }
}
ConfigurationManagerInterface & configurationManager = ConfigurationManagerInterfaceSingleton::getInstance();
configurationManager.setActiveAudioCodecList(_codecList, account->getAccountDetail(ACCOUNT_ID));
qDebug() << "Account codec have been saved" << _codecList << account->getAccountDetail(ACCOUNT_ID);
......@@ -368,10 +379,11 @@ void DlgAccounts::loadAccount(QListWidgetItem * item)
keditlistbox_codec->clear();
ConfigurationManagerInterface & configurationManager = ConfigurationManagerInterfaceSingleton::getInstance();
QStringList activeCodecList = configurationManager.getActiveAudioCodecList(account->getAccountDetail(ACCOUNT_ID));
qDebug() << "Active codecs" << activeCodecList;
foreach (QString aCodec, activeCodecList) {
foreach (StringHash _aCodec, codecList) {
if (_aCodec["id"] == aCodec)
keditlistbox_codec->insertItem(_aCodec["alias"]);
; if (_aCodec["id"] == aCodec)
keditlistbox_codec->insertItem(_aCodec["alias"]);
}
}
......@@ -623,7 +635,7 @@ void DlgAccounts::loadCodecList()
_codec["frequency"] = codec[1];
_codec["bitrate"] = codec[2];
_codec["bandwidth"] = ""; //TODO remove
_codec["id"] = aCodec;
_codec["id"] = QString::number(aCodec);
tmpNameList << _codec["name"];
......
......@@ -456,7 +456,11 @@
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="spinBox_ni_local_port"/>
<widget class="QSpinBox" name="spinBox_ni_local_port">
<property name="maximum">
<number>65535</number>
</property>
</widget>
</item>
<item row="0" column="2">
<spacer name="horizontalSpacer_8">
......@@ -509,7 +513,11 @@
</widget>
</item>
<item row="4" column="1" colspan="2">
<widget class="QSpinBox" name="spinBox_pa_published_port"/>
<widget class="QSpinBox" name="spinBox_pa_published_port">
<property name="maximum">
<number>65535</number>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="lineEdit_pa_published_address"/>
......@@ -777,8 +785,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>536</width>
<height>758</height>
<width>539</width>
<height>660</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout_5">
......@@ -1156,6 +1164,11 @@
</layout>
</widget>
<customwidgets>
<customwidget>
<class>KEditListBox</class>
<extends>QGroupBox</extends>
<header>keditlistbox.h</header>
</customwidget>
<customwidget>
<class>KIntSpinBox</class>
<extends>QSpinBox</extends>
......@@ -1166,11 +1179,6 @@
<extends>QFrame</extends>
<header>kurlrequester.h</header>
</customwidget>
<customwidget>
<class>KEditListBox</class>
<extends>QGroupBox</extends>
<header>keditlistbox.h</header>
</customwidget>
<customwidget>
<class>KLineEdit</class>
<extends>QLineEdit</extends>
......
......@@ -37,6 +37,7 @@ class QNumericTreeWidgetItem : public QTreeWidgetItem {
QNumericTreeWidgetItem(QTreeWidget* parent):QTreeWidgetItem(parent),widget(0),weight(-1){}
QNumericTreeWidgetItem(QTreeWidgetItem* parent):QTreeWidgetItem(parent),widget(0),weight(-1){}
ContactItemWidget* widget;
QString number;
int weight;
private:
bool operator<(const QTreeWidgetItem & other) const {
......@@ -56,7 +57,7 @@ ContactDock::ContactDock(QWidget* parent) : QDockWidget(parent)
m_pFilterLE = new KLineEdit ( );
m_pSplitter = new QSplitter ( Qt::Vertical,this );
m_pSortByCBB = new QComboBox ( this );
m_pContactView = new QTreeWidget ( this );
m_pContactView = new ContactTree ( this );
m_pCallView = new QListWidget ( this );
m_pShowHistoCK = new QCheckBox ( this );
......@@ -121,10 +122,14 @@ void ContactDock::reloadContact()
if (numbers.count() > 1) {
foreach (Contact::PhoneNumber* number, numbers) {
QNumericTreeWidgetItem* item2 = new QNumericTreeWidgetItem(item);
QLabel* numberL = new QLabel("<b>"+number->getType()+":</b>"+number->getNumber());
QLabel* numberL = new QLabel("<b>"+number->getType()+":</b>"+number->getNumber(),this);
item2->number = number->getNumber();
m_pContactView->setItemWidget(item2,0,numberL);
}
}
else if (numbers.count() == 1) {
item->number = numbers[0]->getNumber();
}
m_pContactView->addTopLevelItem(item);
m_pContactView->setItemWidget(item,0,aContact);
......@@ -165,4 +170,42 @@ void ContactDock::filter(QString text)
item->getItem()->setHidden(!visible);
}
m_pContactView->expandAll();
}
QMimeData* ContactTree::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_CONTACT, item->widget->getContact()->getUid().toUtf8());
}
else if (!item->number.isEmpty()) {
mimeData->setData(MIME_PHONENUMBER, item->number.toUtf8());
}
}
else {
qDebug() << "the item is not a call";
}
return mimeData;
}
bool ContactTree::dropMimeData(QTreeWidgetItem *parent, int index, const QMimeData *data, Qt::DropAction action)
{
Q_UNUSED(index)
Q_UNUSED(action)
Q_UNUSED(parent)
QByteArray encodedData = data->data(MIME_CALLID);
qDebug() << "In history import"<< QString(encodedData);
return false;
}
\ No newline at end of file
......@@ -2,6 +2,7 @@
#define CONTACT_DOCK_H
#include <QtGui/QDockWidget>
#include <QtGui/QTreeWidget>
#include <QSplitter>
#include <akonadi/entitytreeview.h>
......@@ -11,12 +12,12 @@
#include <akonadi/contact/contactstreemodel.h>
#include <akonadi/collectioncombobox.h>
class QTreeWidget;
class QListWidget;
class QComboBox;
class QTreeWidgetItem;
class QCheckBox;
class ContactItemWidget;
class ContactTree;
class ContactDock : public QDockWidget {
Q_OBJECT
......@@ -27,7 +28,7 @@ private:
//Attributes
KLineEdit* m_pFilterLE;
QSplitter* m_pSplitter;
QTreeWidget* m_pContactView;
ContactTree* m_pContactView;
QListWidget* m_pCallView;
QComboBox* m_pSortByCBB;
QCheckBox* m_pShowHistoCK;
......@@ -39,4 +40,12 @@ private slots:
void filter(QString text);
};
class ContactTree : public QTreeWidget {
Q_OBJECT
public:
ContactTree(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
......@@ -19,19 +19,50 @@
***************************************************************************/
#include <QtCore/QStringList>
#include <QtCore/QMimeData>
#include <QtGui/QApplication>
#include <QtGui/QClipboard>
#include <QtGui/QGridLayout>
#include <QtGui/QMenu>
#include <klocale.h>
#include <kdebug.h>
#include <unistd.h>
#include <kaction.h>
#include "lib/sflphone_const.h"
#include "ContactItemWidget.h"
ContactItemWidget::ContactItemWidget(QWidget *parent)
: QWidget(parent), init(false)
: QWidget(parent), m_pMenu(0),init(false)
{
setContextMenuPolicy(Qt::CustomContextMenu);
m_pCallAgain = new KAction(this);
m_pCallAgain->setShortcut(Qt::CTRL + Qt::Key_Enter);
m_pCallAgain->setText("Call Again");
m_pCallAgain->setIcon(KIcon(ICON_DIALING));
m_pEditContact = new KAction(this);
m_pEditContact->setShortcut(Qt::CTRL + Qt::Key_E);
m_pEditContact->setText("Edit contact");
m_pEditContact->setIcon(KIcon("contact-new"));
m_pCopy = new KAction(this);
m_pCopy->setShortcut(Qt::CTRL + Qt::Key_C);
m_pCopy->setText("Copy");
m_pCopy->setIcon(KIcon("edit-copy"));
m_pEmail = new KAction(this);
m_pEmail->setShortcut(Qt::CTRL + Qt::Key_M);
m_pEmail->setText("Send Email");
m_pEmail->setIcon(KIcon("mail-message-new"));
m_pAddPhone = new KAction(this);
m_pAddPhone->setShortcut(Qt::CTRL + Qt::Key_N);
m_pAddPhone->setText("Add Phone Number");
m_pAddPhone->setIcon(KIcon("list-resource-add"));
connect(m_pCallAgain ,SIGNAL(triggered()),this,SLOT(callAgain() ));
connect(m_pEditContact ,SIGNAL(triggered()),this,SLOT(editContact() ));
connect(m_pCopy ,SIGNAL(triggered()),this,SLOT(copy() ));
connect(m_pEmail ,SIGNAL(triggered()),this,SLOT(sendEmail() ));
connect(m_pAddPhone ,SIGNAL(triggered()),this,SLOT(addPhone() ));
}
ContactItemWidget::~ContactItemWidget()
......@@ -71,6 +102,7 @@ void ContactItemWidget::setContact(Contact* contact)
setMinimumSize(QSize(50, 30));
updated();
connect(this,SIGNAL(customContextMenuRequested(QPoint)),this,SLOT(showContext(QPoint)));
}