diff --git a/sflphone-client-kde/data/sflphone-client-kdeui.rc b/sflphone-client-kde/data/sflphone-client-kdeui.rc index 08c501092907c656132600c40881a845ad89fc08..d015a8cac79d547df0247c62b3bb390c041a7da8 100644 --- a/sflphone-client-kde/data/sflphone-client-kdeui.rc +++ b/sflphone-client-kde/data/sflphone-client-kdeui.rc @@ -7,7 +7,6 @@ http://www.kde.org/standards/kxmlgui/1.0/kxmlgui.xsd" > --> <gui name="sflphone-client-kde" version="1"> - <MenuBar> <Menu name="Actions" > <text>Actions</text> @@ -37,18 +36,13 @@ </Menu> </MenuBar> - <ToolBar name="mainToolBar" iconText="icononly" position="Top" noMerge="1" fullWidth="true" newline="true" > + <ToolBar name="mainToolBar" position="Top" noMerge="1" fullWidth="true" newline="true" > <Action name="action_accept" /> <Action name="action_mailBox" /> - </ToolBar> - <ToolBar name="callsToolBar" iconText="icononly" position="Top" noMerge="1" fullWidth="true" newline="true" > <Action name="action_refuse" /> <Action name="action_hold" /> <Action name="action_transfer" /> <Action name="action_record" /> - </ToolBar> - - <ToolBar name="screenToolBar" iconText="icononly" position="Top" noMerge="1" fullWidth="true" newline="true" > <Action name="action_main" /> <Action name="action_history" /> <Action name="action_addressBook" /> diff --git a/sflphone-client-kde/src/Call.cpp b/sflphone-client-kde/src/Call.cpp index 8942159b8ae21face7107cca4ef9a6ee9b7efb08..6469669453dd51eb4398432f2f5a1ba67247aecb 100644 --- a/sflphone-client-kde/src/Call.cpp +++ b/sflphone-client-kde/src/Call.cpp @@ -139,6 +139,7 @@ const char * Call::historyIcons[3] = {ICON_HISTORY_INCOMING, ICON_HISTORY_OUTGOI Call::Call(call_state startState, QString callId, QString peerName, QString peerNumber, QString account) + : conference(false) { this->callId = callId; this->peerPhoneNumber = peerNumber; @@ -152,7 +153,14 @@ Call::Call(call_state startState, QString callId, QString peerName, QString peer // this->initCallItemWidget(); emit changed(); } -#include <unistd.h> + +Call::Call(QString confId, QString account) + : conference(true) +{ + this->confId = confId; + this->account = account; +} + Call * Call::buildExistingCall(QString callId) { CallManagerInterface & callManager = CallManagerInterfaceSingleton::getInstance(); @@ -687,4 +695,20 @@ void Call::changeCurrentState(call_state newState) if (currentState == CALL_STATE_OVER) emit isOver(this); +} + +bool Call::isConference() const { + return conference; +} + +void Call::setConference(bool value) { + conference = value; +} + +QString Call::getConfId() const { + return confId; +} + +void Call::setConfId(QString value) { + confId = value; } \ No newline at end of file diff --git a/sflphone-client-kde/src/Call.h b/sflphone-client-kde/src/Call.h index 2eb1b8798ad2204bf28f6956ac45e43ea6dae389..ecebd61eccb5407d4f5df3e625c07abe9f6e2364 100644 --- a/sflphone-client-kde/src/Call.h +++ b/sflphone-client-kde/src/Call.h @@ -146,6 +146,7 @@ private: QString account; QString callId; + QString confId; QString peerPhoneNumber; QString peerName; history_state historyState; @@ -163,6 +164,8 @@ private: QString transferNumber; QString callNumber; + bool conference; + //Automate attributes /** * actionPerformedStateMap[orig_state][action] @@ -228,7 +231,7 @@ private: void warning(); public: - + Call(QString confId, QString account); //Constructors & Destructors ~Call(); // void initCallItemWidget(); @@ -255,6 +258,12 @@ public: bool isHistory() const; QString getStopTimeStamp() const; QString getStartTimeStamp() const; + bool isConference() const; + + void setConference(bool value); + + QString getConfId() const; + void setConfId(QString value); QString getTransferNumber() const; void setTransferNumber(QString number); diff --git a/sflphone-client-kde/src/CallModel.cpp b/sflphone-client-kde/src/CallModel.cpp index 9d11984f50fb9a96a0c22302a824167da7669e69..ff7339174632dc2ed05ad08200815b9181490a97 100644 --- a/sflphone-client-kde/src/CallModel.cpp +++ b/sflphone-client-kde/src/CallModel.cpp @@ -28,14 +28,18 @@ CallModel::CallModel(ModelType type, QWidget* parent) : QTreeWidget(parent) { CallManagerInterface & callManager = CallManagerInterfaceSingleton::getInstance(); ConfigurationManagerInterface & configurationManager = ConfigurationManagerInterfaceSingleton::getInstance(); QStringList callList = callManager.getCallList(); - qDebug() << "Call List = " << callList; - for(int i = 0 ; i < callList.size() ; i++) { - Call* tmpCall = Call::buildExistingCall(callList[i]); + foreach (QString callId, callList) { + Call* tmpCall = Call::buildExistingCall(callId); activeCalls[tmpCall->getCallId()] = tmpCall; if (type == ActiveCall) addCall(tmpCall); } + QStringList confList = callManager.getConferenceList(); + foreach (QString confId, confList) { + addConference(confId); + } + //Add older calls MapStringString historyMap = configurationManager.getHistory().value(); qDebug() << "Call History = " << historyMap; @@ -50,7 +54,7 @@ CallModel::CallModel(ModelType type, QWidget* parent) : QTreeWidget(parent) { uint stopTimeStamp = param[3].toUInt(); QString account = param[4]; historyCalls[QString::number(startTimeStamp)] = Call::buildHistoryCall(generateCallId(), startTimeStamp, stopTimeStamp, account, name, number, type); - //if (type == ActiveCall) //TODO undelete + //if (type == ActiveCall) //TODO uncomment //addCall(historyCalls[QString::number(startTimeStamp)]); } @@ -71,6 +75,7 @@ Call* CallModel::addCall(Call* call, Call* parent) { QTreeWidgetItem* callItem = new QTreeWidgetItem(); aNewStruct->currentItem = callItem; + aNewStruct->conference = false; privateCallList_item[callItem] = aNewStruct; privateCallList_call[call] = aNewStruct; @@ -90,6 +95,7 @@ MapStringString CallModel::getHistoryMap() { foreach(Call* call, historyCalls) { toReturn[historyCalls.key(call)] = Call::getTypeFromHistoryState(call->getHistoryState()) + "|" + call->getPeerPhoneNumber() + "|" + call->getPeerName() + "|" + call->getStopTimeStamp() + "|" + call->getAccountId(); } + return toReturn; } Call* CallModel::addDialingCall(const QString & peerName, QString account) @@ -122,20 +128,85 @@ Call* CallModel::addRingingCall(const QString & callId) Call* CallModel::addConference(const QString & confID) { qDebug() << "Notified of a new conference " << confID; CallManagerInterface& callManager = CallManagerInterfaceSingleton::getInstance(); - sleep(2); QStringList callList = callManager.getParticipantList(confID); qDebug() << "Paticiapants are:" << callList; + + if (!callList.size()) { + qDebug() << "This conference (" + confID + ") contain no call"; + return 0; + } + + if (!privateCallList_callId[callList[0]]) { + qDebug() << "Invalid call"; + return 0; + } + Call* newConf = new Call(confID, privateCallList_callId[callList[0]]->call_real->getAccountId()); + + InternalCallModelStruct* aNewStruct = new InternalCallModelStruct; + aNewStruct->call_real = newConf; + aNewStruct->conference = true; + + QTreeWidgetItem* confItem = new QTreeWidgetItem(); + aNewStruct->currentItem = confItem; + + privateCallList_item[confItem] = aNewStruct; + privateCallList_call[newConf] = aNewStruct; + privateCallList_callId[newConf->getConfId()] = aNewStruct; //WARNING It may break something is it is done wrong + + aNewStruct->call = insertItem(confItem,(QTreeWidgetItem*)0); + privateCallList_widget[aNewStruct->call] = aNewStruct; + + setCurrentItem(confItem); + + foreach (QString callId, callList) { + insertItem(extractItem(privateCallList_callId[callId]->currentItem),confItem); + } + return newConf; } -Call* CallModel::createConferenceFromCall(Call* call1, Call* call2) { - qDebug() << "Need to join call: " << call1->getCallId() << " and " << call2->getCallId(); +bool CallModel::createConferenceFromCall(Call* call1, Call* call2) { + qDebug() << "Joining call: " << call1->getCallId() << " and " << call2->getCallId(); CallManagerInterface & callManager = CallManagerInterfaceSingleton::getInstance(); - //callManager.joinConference(call1->getCallId(),call2->getCallId()); callManager.joinParticipant(call1->getCallId(),call2->getCallId()); + return true; } -Call* CallModel::addParticipant(Call* call2, Call* conference) { - +bool CallModel::addParticipant(Call* call2, Call* conference) { + if (conference->isConference()) { + CallManagerInterface & callManager = CallManagerInterfaceSingleton::getInstance(); + callManager.addParticipant(call2->getCallId(), conference->getConfId()); + return true; + } + else { + qDebug() << "This is not a conference"; + return false; + } +} + +bool CallModel::detachParticipant(Call* call) { + CallManagerInterface & callManager = CallManagerInterfaceSingleton::getInstance(); + callManager.detachParticipant(call->getCallId()); + //insertItem(extractItem(privateCallList_call[call]->currentItem)); + return true; +} + +bool CallModel::mergeConferences(Call* conf1, Call* conf2) { + CallManagerInterface & callManager = CallManagerInterfaceSingleton::getInstance(); + callManager.joinConference(conf1->getConfId(),conf2->getConfId()); + return true; +} + +void CallModel::conferenceChanged(const QString &confId, const QString &state) { + CallManagerInterface& callManager = CallManagerInterfaceSingleton::getInstance(); + QStringList callList = callManager.getParticipantList(confId); + qDebug() << "New " + confId + " participant list: " << callList; + foreach (QString callId, callList) { + qDebug() << "Item: " << privateCallList_callId[callId]->currentItem; + if (privateCallList_callId[callId]) + insertItem(extractItem(privateCallList_callId[callId]->currentItem), privateCallList_callId[confId]->currentItem); + else + qDebug() << "Call " << callId << " does not exist"; + } } int CallModel::size() { @@ -154,30 +225,6 @@ QList<Call*> CallModel::getCallList() { return callList; } -void CallModel::mergeCall(Call* call1, Call* call2) { - -} - -uint CallModel::countChild(Call* call) { - -} - -bool CallModel::isConference(Call* call) { - -} - -QList<Call*> CallModel::children(Call* call) { - -} - -bool CallModel::endCall(Call* call, Call* endConference) { - -} - -InternalCallModelStruct CallModel::find(const CallTreeItem* call) { - -} - bool CallModel::selectItem(Call* item) { if (privateCallList_call[item]->currentItem) { setCurrentItem(privateCallList_call[item]->currentItem); @@ -195,8 +242,12 @@ Call* CallModel::getCurrentItem() { } bool CallModel::removeItem(Call* item) { - if (indexOfTopLevelItem(privateCallList_call[item]->currentItem) != -1) //TODO To remove once safe - removeItemWidget(privateCallList_call[item]->currentItem,0); + if (indexOfTopLevelItem(privateCallList_call[item]->currentItem) != -1) {//TODO To remove once safe + removeItemWidget(privateCallList_call[item]->currentItem,0);\ + return true; + } + else + return false; } QWidget* CallModel::getWidget() { @@ -239,6 +290,11 @@ CallTreeItem* CallModel::insertItem(QTreeWidgetItem* item, Call* parent) { } CallTreeItem* CallModel::insertItem(QTreeWidgetItem* item, QTreeWidgetItem* parent) { + if (!item) { + qDebug() << "This is not a valid call"; + return 0; + } + if (!parent) insertTopLevelItem(0,item); else @@ -248,9 +304,10 @@ CallTreeItem* CallModel::insertItem(QTreeWidgetItem* item, QTreeWidgetItem* pare privateCallList_item[item]->call = new CallTreeItem(); privateCallList_item[item]->call->setCall(privateCallList_item[item]->call_real); privateCallList_widget[privateCallList_item[item]->call] = privateCallList_item[item]; + + qDebug() << "DEBUG item: " << item << " widget : " << privateCallList_item[item]->call; setItemWidget(item,0,privateCallList_item[item]->call); - //TODO check to destroy 1 participant conferences expandAll(); return privateCallList_item[item]->call; } @@ -261,46 +318,53 @@ void CallModel::clearArtefact(QTreeWidgetItem* item) { bool CallModel::dropMimeData(QTreeWidgetItem *parent, int index, const QMimeData *data, Qt::DropAction action) { QByteArray encodedData = data->data("text/sflphone.call.id"); - + clearArtefact(privateCallList_callId[encodedData]->currentItem); if (!parent) { qDebug() << "Call dropped on empty space"; - insertItem(extractItem(encodedData)); - return true; //TODO this call may be (or not) in a conversation, if yes, split it + if (privateCallList_callId[encodedData]->currentItem->parent()) + detachParticipant(privateCallList_callId[encodedData]->call_real); + return true; } - + if (privateCallList_item[parent]->call_real->getCallId() == QString(encodedData)) { - qDebug() << "Call dropped on itself"; + qDebug() << "Call dropped on itself (doing nothing)"; return true; //Item dropped on itself } - + if ((parent->parent()) || (parent->childCount())) { qDebug() << "Call dropped on a conference"; - if (privateCallList_callId[encodedData]->currentItem->parent()) - if (privateCallList_callId[encodedData]->currentItem->parent() == parent->parent()) { - qDebug() << "Call dropped on it's own conversation"; + + if ((privateCallList_callId[encodedData]->currentItem->childCount()) && (!parent->childCount())) { + qDebug() << "Conference dropped on a call (doing nothing)"; + return true; + } + + QTreeWidgetItem* call1 = privateCallList_callId[encodedData]->currentItem; + QTreeWidgetItem* call2 = (parent->parent())?parent->parent():parent; + + if (privateCallList_callId[encodedData]->currentItem->parent()) { + if (privateCallList_callId[encodedData]->currentItem->parent() == call2->parent()) { + qDebug() << "Call dropped on it's own conversation (doing nothing)"; return true; } - - QTreeWidgetItem* call1 = extractItem(encodedData); - QTreeWidgetItem* call2 = (parent->parent())?parent->parent():parent; - insertItem(call1,call2); - createConferenceFromCall(privateCallList_item[call1]->call_real,privateCallList_item[call2]->call_real); - - return true; //TODO this is a conference call, need to check if the call is in the conversation, if not, add it + else if (privateCallList_item[call1]->currentItem->childCount()) { + qDebug() << "Merging two conferences"; + mergeConferences(privateCallList_item[call1]->call_real,privateCallList_item[call2]->call_real); + } + else if (call1->parent()) { + qDebug() << "Moving call from a conference to an other"; + detachParticipant(privateCallList_callId[encodedData]->call_real); + } + } + + addParticipant(privateCallList_item[call1]->call_real,privateCallList_item[call2]->call_real); + return true; } - //Create a conference - QTreeWidgetItem* newConference = new QTreeWidgetItem(this); - newConference->setText(0,"Conference"); qDebug() << "Call dropped on another call"; - - QTreeWidgetItem* call1 = extractItem(encodedData); - insertItem(call1,newConference); - insertItem(extractItem(parent),newConference); - - createConferenceFromCall(privateCallList_item[call1]->call_real,privateCallList_item[parent]->call_real); + createConferenceFromCall(privateCallList_callId[encodedData]->call_real,privateCallList_item[parent]->call_real); return true; } @@ -310,7 +374,10 @@ QMimeData* CallModel::mimeData(const QList<QTreeWidgetItem *> items) const { QMimeData *mimeData = new QMimeData(); //Call ID for internal call merging and spliting - mimeData->setData("text/sflphone.call.id", privateCallList_item[items[0]]->call_real->getCallId().toAscii()); + if (privateCallList_item[items[0]]->call_real->isConference()) + mimeData->setData("text/sflphone.call.id", privateCallList_item[items[0]]->call_real->getConfId().toAscii()); + else + mimeData->setData("text/sflphone.call.id", privateCallList_item[items[0]]->call_real->getCallId().toAscii()); //Plain text for other applications mimeData->setData("text/plain", QString(privateCallList_item[items[0]]->call_real->getPeerName()+"\n"+privateCallList_item[items[0]]->call_real->getPeerPhoneNumber()).toAscii()); diff --git a/sflphone-client-kde/src/CallModel.h b/sflphone-client-kde/src/CallModel.h index 4335a143e9ff851fb7a6ce8d118496d8aa95963d..0bcba6332fc78beb9df3f2c2c2f992678095fe6c 100644 --- a/sflphone-client-kde/src/CallModel.h +++ b/sflphone-client-kde/src/CallModel.h @@ -46,6 +46,7 @@ struct InternalCallModelStruct { Call* call_real; QTreeWidgetItem* currentItem; QList<InternalCallModelStruct*> children; + bool conference; }; struct InternalCallModelStruct; @@ -72,12 +73,7 @@ class CallModel : private QTreeWidget { Call* addCall(Call* call, Call* parent =0); int size(); Call* findCallByCallId(QString callId); - void mergeCall(Call* call1, Call* call2); - uint countChild(Call* call); - bool isConference(Call* call); - QList<Call*> children(Call* call); QList<Call*> getCallList(); - bool endCall(Call* call, Call* endConference = false); bool selectItem(Call* item); Call* getCurrentItem(); bool removeItem(Call* item); @@ -89,9 +85,12 @@ class CallModel : private QTreeWidget { Call* addDialingCall(const QString & peerName = "", QString account = ""); Call* addIncomingCall(const QString & callId/*, const QString & from, const QString & account*/); Call* addRingingCall(const QString & callId); - Call* createConferenceFromCall(Call* call1, Call* call2); + bool createConferenceFromCall(Call* call1, Call* call2); Call* addConference(const QString &confID); - Call* addParticipant(Call* call2, Call* conference); + bool mergeConferences(Call* conf1, Call* conf2); + bool addParticipant(Call* call2, Call* conference); + bool detachParticipant(Call* call); + void conferenceChanged(const QString &confId, const QString &state); MapStringString getHistoryMap(); diff --git a/sflphone-client-kde/src/CallTreeItem.cpp b/sflphone-client-kde/src/CallTreeItem.cpp index 2e195cbb986aa0801cd55ad3ec53e9bf12786a49..415aa84df6817d5437cc8484f249383fe7636f0d 100644 --- a/sflphone-client-kde/src/CallTreeItem.cpp +++ b/sflphone-client-kde/src/CallTreeItem.cpp @@ -92,6 +92,9 @@ void CallTreeItem::setCall(Call *call) void CallTreeItem::updated() { + if (itemCall->isConference()) + return; + call_state state = itemCall->getState(); bool recording = itemCall->getRecording(); if(state != CALL_STATE_OVER) { diff --git a/sflphone-client-kde/src/SFLPhone.cpp b/sflphone-client-kde/src/SFLPhone.cpp index df60ebc66bfcffbef5e620704786b3b467bfe6db..fabc7d15ab29bdbecd1bc9a896d2f58d1ae62879 100644 --- a/sflphone-client-kde/src/SFLPhone.cpp +++ b/sflphone-client-kde/src/SFLPhone.cpp @@ -270,12 +270,12 @@ void SFLPhone::on_view_windowTitleChangeAsked(const QString & message) void SFLPhone::on_view_enabledActionsChangeAsked(const bool * enabledActions) { qDebug() << "on_view_enabledActionsChangeAsked"; - action_accept->setEnabled(enabledActions[SFLPhone::Accept]); - action_refuse->setEnabled(enabledActions[SFLPhone::Refuse]); - action_hold->setEnabled(enabledActions[SFLPhone::Hold]); - action_transfer->setEnabled(enabledActions[SFLPhone::Transfer]); - action_record->setEnabled(enabledActions[SFLPhone::Record]); - action_mailBox->setEnabled(enabledActions[SFLPhone::Mailbox]); + action_accept->setVisible(enabledActions[SFLPhone::Accept]); + action_refuse->setVisible(enabledActions[SFLPhone::Refuse]); + action_hold->setVisible(enabledActions[SFLPhone::Hold]); + action_transfer->setVisible(enabledActions[SFLPhone::Transfer]); + action_record->setVisible(enabledActions[SFLPhone::Record]); + action_mailBox->setVisible(enabledActions[SFLPhone::Mailbox]); } void SFLPhone::on_view_actionIconsChangeAsked(const QString * actionIcons) diff --git a/sflphone-client-kde/src/SFLPhoneView.cpp b/sflphone-client-kde/src/SFLPhoneView.cpp index 8d0e503e9eb97ea61fc6764e77d8da8e4c259cde..0c2516f30bd0e8070e488c3fb383c4e7afa4ad8a 100644 --- a/sflphone-client-kde/src/SFLPhoneView.cpp +++ b/sflphone-client-kde/src/SFLPhoneView.cpp @@ -116,7 +116,9 @@ SFLPhoneView::SFLPhoneView(QWidget *parent) connect(&callManager, SIGNAL(incomingCall(const QString &, const QString &, const QString &)), this, SLOT(on1_incomingCall(const QString &, const QString &))); connect(&callManager, SIGNAL(conferenceCreated(const QString &)), - this, SLOT(on1_incommingConference(const QString &))); + this, SLOT(on1_incomingConference(const QString &))); + connect(&callManager, SIGNAL(conferenceChanged(const QString &, const QString &)), + this, SLOT(on1_changingConference(const QString &, const QString &))); connect(&callManager, SIGNAL(incomingMessage(const QString &, const QString &)), this, SLOT(on1_incomingMessage(const QString &, const QString &))); connect(&callManager, SIGNAL(voiceMailNotify(const QString &, int)), @@ -789,6 +791,11 @@ void SFLPhoneView::updateVolumeControls() toolButton_sndVol->setVisible(display); slider_recVol->setVisible(display); slider_sndVol->setVisible(display); + + slider_sndVol_2->setVisible(display); + slider_recVol_2->setVisible(display); + toolButton_recVol_2->setVisible(display); + toolButton_sndVol_2->setVisible(display); } void SFLPhoneView::updateDialpad() @@ -1279,10 +1286,14 @@ void SFLPhoneView::on1_incomingCall(const QString & /*accountID*/, const QString emit incomingCall(call); } -void SFLPhoneView::on1_incommingConference(const QString &confID) { +void SFLPhoneView::on1_incomingConference(const QString &confID) { callTreeModel.addConference(confID); } +void SFLPhoneView::on1_changingConference(const QString &confID, const QString &state) { + callTreeModel.conferenceChanged(confID, state); +} + void SFLPhoneView::on1_incomingMessage(const QString &accountID, const QString &message) { qDebug() << "Signal : Incoming Message for account " << accountID << " ! \nMessage : " << message; diff --git a/sflphone-client-kde/src/SFLPhoneView.h b/sflphone-client-kde/src/SFLPhoneView.h index 54071266beb7c1b34b19db24b6a71e92fd8f3ac5..075f191c021bf6629fa0ef097db86761b4ed09c3 100644 --- a/sflphone-client-kde/src/SFLPhoneView.h +++ b/sflphone-client-kde/src/SFLPhoneView.h @@ -350,7 +350,8 @@ public slots: void on1_voiceMailNotify(const QString &accountID, int count); void on1_volumeChanged(const QString &device, double value); void on1_audioManagerChanged(); - void on1_incommingConference(const QString &confID); + void on1_incomingConference(const QString &confID); + void on1_changingConference(const QString &confID, const QString &state); void changeScreen(int screen); signals: