Commit 01da004a authored by Ming Rui Zhang's avatar Ming Rui Zhang Committed by Andreas Traczyk

transferCall: add blind/attended transfer call support

Change-Id: I7a159ac51cb7527ce8fc1010c2c6caebd7251c0e
parent 60a3e631
......@@ -642,11 +642,13 @@ void CallWidget::slotShowCallView(const std::string& accountId,
const lrc::api::conversation::Info& convInfo)
{
Q_UNUSED(accountId);
Q_UNUSED(convInfo);
qDebug() << "slotShowCallView";
setCallPanelVisibility(true);
// find out the best name for current callee, remove the search result from smart list
auto callModel = LRCInstance::getCurrentCallModel();
auto convModel = LRCInstance::getCurrentConversationModel();
auto bestName = QString::fromStdString(Utils::bestNameForConversation(convInfo, *convModel));
ui->videoWidget->setCurrentCalleeName(bestName);
setCallPanelVisibility(true);
if (callModel->hasCall(convInfo.callId)) {
auto call = callModel->getCall(convInfo.callId);
......@@ -659,7 +661,7 @@ void CallWidget::slotShowCallView(const std::string& accountId,
}
ui->callStackWidget->setCurrentWidget(ui->videoPage);
hideMiniSpinner();
ui->videoWidget->pushRenderer(convInfo.callId);
ui->videoWidget->pushRenderer(convInfo.callId, LRCInstance::accountModel().getAccountInfo(accountId).profileInfo.type == lrc::api::profile::Type::SIP);
}
void CallWidget::slotShowIncomingCallView(const std::string& accountId,
......@@ -683,6 +685,7 @@ void CallWidget::slotShowIncomingCallView(const std::string& accountId,
auto call = callModel->getCall(convInfo.callId);
auto isCallSelected = LRCInstance::getSelectedConvUid() == convInfo.uid;
ui->callingStatusLabel->setText(QString::fromStdString(lrc::api::call::to_string(call.status)));
ui->videoWidget->setCurrentCalleeName(bestName);
connect(callModel, &lrc::api::NewCallModel::callStatusChanged, ui->incomingCallPage,
[this, accountId](const std::string& callId) {
......@@ -726,7 +729,7 @@ void CallWidget::slotShowIncomingCallView(const std::string& accountId,
ui->messagesWidget->show();
}
ui->videoWidget->pushRenderer(convInfo.callId);
ui->videoWidget->pushRenderer(convInfo.callId, LRCInstance::accountModel().getAccountInfo(accountId).profileInfo.type == lrc::api::profile::Type::SIP);
QFontMetrics primaryCallLabelFontMetrics(ui->callingBestNameLabel->font());
QFontMetrics sencondaryCallLabelFontMetrics(ui->callingBestIdLabel->font());
......
......@@ -73,9 +73,8 @@ ContactPicker::accept()
case Type::CONFERENCE:
emit contactWillJoinConference(thisCallId, contactUri);
break;
case Type::BLIND_TRANSFER:
case Type::ATTENDED_TRANSFER:
emit contactWillDoBlindTransfer(thisCallId, contactUri);
case Type::TRANSFER:
emit contactWillDoTransfer(thisCallId, contactUri);
break;
default:
break;
......@@ -96,7 +95,6 @@ ContactPicker::mousePressEvent(QMouseEvent *event)
{
auto contactPickerWidgetRect = ui->contactPickerWidget->rect();
if (!contactPickerWidgetRect.contains(event->pos())) {
//close();
emit willClose(event);
}
}
......@@ -131,11 +129,17 @@ ContactPicker::setType(const Type& type)
!index.parent().isValid();
});
break;
case Type::BLIND_TRANSFER:
case Type::ATTENDED_TRANSFER:
case Type::TRANSFER:
selectableProxyModel_->setPredicate(
[this](const QModelIndex& index, const QRegExp& regexp) {
return true;
// Regex to remove current callee
QRegExp matchExcept= QRegExp(QString("\\b(?!" + CalleeDisplayName_ + "\\b)\\w+"));
bool match = false;
bool match_non_self = matchExcept.indexIn(index.data(Qt::DisplayRole).toString()) != -1;
if (match_non_self) {
match = regexp.indexIn(index.data(Qt::DisplayRole).toString()) != -1;
}
return match && !index.parent().isValid();
});
break;
default:
......@@ -143,3 +147,9 @@ ContactPicker::setType(const Type& type)
}
selectableProxyModel_->invalidate();
}
void
ContactPicker::setCurrentCalleeDisplayName(const QString& CalleeDisplayName)
{
CalleeDisplayName_ = CalleeDisplayName;
}
......@@ -63,8 +63,7 @@ class ContactPicker : public QDialog
public:
enum class Type {
CONFERENCE,
BLIND_TRANSFER,
ATTENDED_TRANSFER,
TRANSFER,
COUNT__
};
......@@ -72,13 +71,14 @@ public:
~ContactPicker();
void setTitle(const std::string& title);
void setType(const Type& type);
void setCurrentCalleeDisplayName(const QString& CalleeDisplayName);
protected:
void mousePressEvent(QMouseEvent *event);
signals:
void contactWillJoinConference(const std::string& callId, const std::string& contactUri);
void contactWillDoBlindTransfer(const std::string& callId, const std::string& contactUri);
void contactWillDoTransfer(const std::string& callId, const std::string& contactUri);
void willClose(QMouseEvent *event);
protected slots:
......@@ -94,5 +94,6 @@ private:
std::unique_ptr<SmartListModel> smartListModel_;
SelectableProxyModel* selectableProxyModel_;
Type type_;
QString CalleeDisplayName_;
};
......@@ -190,7 +190,7 @@
<cursorShape>IBeamCursor</cursorShape>
</property>
<property name="toolTip">
<string>Search contact text input</string>
<string>Search contact</string>
</property>
<property name="maxLength">
<number>100</number>
......@@ -251,10 +251,10 @@
<attribute name="headerVisible">
<bool>false</bool>
</attribute>
<attribute name="headerDefaultSectionSize">
<attribute name="headerMinimumSectionSize">
<number>0</number>
</attribute>
<attribute name="headerMinimumSectionSize">
<attribute name="headerDefaultSectionSize">
<number>0</number>
</attribute>
</widget>
......@@ -294,7 +294,7 @@
<string/>
</property>
<property name="pixmap">
<pixmap resource="ressources.qrc">:/images/spike.png</pixmap>
<pixmap>:/images/spike.png</pixmap>
</property>
</widget>
</item>
......@@ -312,8 +312,6 @@
<header>smartlistview.h</header>
</customwidget>
</customwidgets>
<resources>
<include location="ressources.qrc"/>
</resources>
<resources/>
<connections/>
</ui>
......@@ -104,6 +104,7 @@ ContactPickerItemDelegate::paint(QPainter* painter
paintRingContactItem(painter, option, rect, index);
break;
case profile::Type::SIP:
paintSIPContactItem(painter, option, rect, index);
break;
default:
paintRingContactItem(painter, option, rect, index);
......@@ -183,9 +184,68 @@ ContactPickerItemDelegate::paintRingContactItem(QPainter* painter,
void
ContactPickerItemDelegate::paintSIPContactItem(QPainter* painter,
const QStyleOptionViewItem& option,
const QRect& rect,
const QModelIndex& index) const
{
Q_UNUSED(painter);
Q_UNUSED(option);
Q_UNUSED(index);
QRect rectName1;
QRect rectName2;
QFont font(painter->font());
QPen pen(painter->pen());
painter->setPen(pen);
auto scalingRatio = MainWindow::instance().getCurrentScalingRatio();
if (scalingRatio > 1.0) {
font.setPointSize(fontSize_ - 2);
} else {
font.setPointSize(fontSize_);
}
auto leftMargin = dx_ + sizeImage_ + dx_;
auto rightMargin = dx_;
auto topMargin = 4;
auto bottomMargin = 8;
if (!rect.isEmpty()) {
rectName1 = QRect(rect.left() + leftMargin,
rect.top() + topMargin,
rect.width() - leftMargin * 2,
rect.height() / 2 - 2);
rectName2 = QRect(rectName1.left(),
rectName1.top() + rectName1.height(),
rectName1.width(),
rectName1.height() - bottomMargin);
}
QFontMetrics fontMetrics(font);
// The name is displayed at the avatar's right
QString nameStr = index.data(static_cast<int>(SmartListModel::Role::DisplayName)).value<QString>();
if (!nameStr.isNull()) {
font.setItalic(false);
font.setBold(false);
pen.setColor(RingTheme::lightBlack_);
painter->setPen(pen);
painter->setFont(font);
if (!rectName1.isEmpty()) {
QString elidedNameStr = fontMetrics.elidedText(nameStr, Qt::ElideRight, rectName1.width());
painter->drawText(rectName1, Qt::AlignVCenter | Qt::AlignLeft, elidedNameStr);
}
}
// Display the ID under the name
QString idStr = index.data(static_cast<int>(SmartListModel::Role::DisplayID)).value<QString>();
if (idStr != nameStr && !idStr.isNull()) {
font.setItalic(false);
font.setBold(false);
pen.setColor(RingTheme::grey_);
painter->setPen(pen);
painter->setFont(font);
if (!rectName2.isEmpty()) {
idStr = fontMetrics.elidedText(idStr, Qt::ElideRight, rectName2.width());
painter->drawText(rectName2, Qt::AlignVCenter | Qt::AlignLeft, idStr);
}
}
}
......@@ -35,7 +35,7 @@ protected:
private:
void paintRingContactItem(QPainter* painter, const QStyleOptionViewItem& option, const QRect& rect, const QModelIndex& index) const;
void paintSIPContactItem(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const;
void paintSIPContactItem(QPainter* painter, const QStyleOptionViewItem& option, const QRect& rect, const QModelIndex& index) const;
constexpr static int sizeImage_ = 48;
constexpr static int cellHeight_ = 60;
......
......@@ -177,7 +177,7 @@ QWidget#messageViewLayoutWidget, QWidget#welcomePage {
QPushButton#holdButton, QPushButton#chatButton, QPushButton#noMicButton, QPushButton#noVideoButton,
QPushButton#transferButton, QPushButton#addPersonButton, QPushButton#joinButton,
QPushButton#qualityButton, QPushButton#recButton {
QPushButton#qualityButton, QPushButton#recButton, QPushButton#transferCallButton {
background-color: rgba(0, 0, 0, 140);
border-radius: 18px;
border: solid 1px;
......@@ -186,7 +186,7 @@ QPushButton#qualityButton, QPushButton#recButton {
QPushButton#holdButton:hover, QPushButton#chatButton:hover, QPushButton#noMicButton:hover,
QPushButton#noVideoButton:hover, QPushButton#transferButton:hover, QPushButton#addPersonButton:hover,
QPushButton#joinButton:hover, QPushButton#qualityButton:hover, QPushButton#addToContactButton:hover,
QPushButton#recButton:hover {
QPushButton#recButton:hover, QPushButton#transferCallButton:hover {
background-color: rgba(0, 192, 213, 0.6);
}
......@@ -199,7 +199,7 @@ QPushButton#recButton:pressed {
QPushButton#holdButton:checked, QPushButton#noMicButton:checked,
QPushButton#noVideoButton:checked, QPushButton#recButton:checked,
QPushButton#chatButton:checked{
QPushButton#chatButton:checked, QPushButton#transferCallButton:checked {
background-color: rgba(0, 192, 213, 0.8);
}
......
......@@ -44,6 +44,15 @@ VideoOverlay::VideoOverlay(QWidget* parent) :
ui->onHoldLabel->setVisible(false);
ui->recButton->setVisible(false);
ui->transferCallButton->setVisible(false);
ui->transferCallButton->setCheckable(true);
contactPicker_->setVisible(false);
contactPicker_->setTitle("Select Peer to Tranfer");
connect(ui->transferCallButton, &QPushButton::toggled, this, &VideoOverlay::on_transferButton_toggled);
connect(contactPicker_, &ContactPicker::contactWillDoTransfer, this, &VideoOverlay::on_transferCall_requested);
}
VideoOverlay::~VideoOverlay()
......@@ -176,6 +185,79 @@ VideoOverlay::on_recButton_clicked()
}
}
void
VideoOverlay::setTransferCallAvailability(bool visible)
{
ui->transferCallButton->setVisible(visible);
}
void
VideoOverlay::on_transferButton_toggled(bool checked)
{
if (callId_.empty() || !checked) {
return;
}
contactPicker_->setType(ContactPicker::Type::TRANSFER);
QPoint globalPos_button = mapToGlobal(ui->transferCallButton->pos());
QPoint globalPos_bottomButtons = mapToGlobal(ui->bottomButtons->pos());
contactPicker_->move(globalPos_button.x(), globalPos_bottomButtons.y() - contactPicker_->height());
// receive the signal that ensure the button checked status is correct and contactpicker
// is properly hidden
Utils::oneShotConnect(contactPicker_, &ContactPicker::willClose, [this](QMouseEvent *event) {
contactPicker_->hide();
// check if current mouse position is on button
auto relativeCursorPos = ui->transferCallButton->mapFromGlobal(event->pos());
if (!ui->transferCallButton->rect().contains(relativeCursorPos)) {
ui->transferCallButton->setChecked(false);
}
});
// for esc key, receive reject signal
Utils::oneShotConnect(contactPicker_, &QDialog::rejected,
[this] {
ui->transferCallButton->setChecked(false);
});
contactPicker_->show();
}
void
VideoOverlay::on_transferCall_requested(const std::string& callId, const std::string& contactUri)
{
auto callModel = LRCInstance::getCurrentCallModel();
contactPicker_->hide();
ui->transferCallButton->setChecked(false);
std::string destCallId;
try {
//check if the call exist - (check non-finished calls)
auto callInfo = callModel->getCallFromURI(contactUri, true);
destCallId = callInfo.id;
} catch(std::exception& e) {
qDebug().noquote() << e.what();
destCallId = "";
}
// if no second call -> blind transfer
// if there is a second call -> attended transfer
if (destCallId.size() == 0) {
callModel->transfer(callId, "sip:" + contactUri);
callModel->hangUp(callId);
}else{
callModel->transferToCall(callId, destCallId);
callModel->hangUp(callId);
callModel->hangUp(destCallId);
}
}
void
VideoOverlay::setCurrentSelectedCalleeDisplayName(const QString& CalleeDisplayName)
{
contactPicker_->setCurrentCalleeDisplayName(CalleeDisplayName);
}
void
VideoOverlay::resetOverlay(bool isAudioMuted, bool isVideoMuted, bool isRecording, bool isHolding)
{
......
......@@ -45,6 +45,8 @@ public:
bool shouldShowOverlay();
void simulateShowChatview(bool checked);
bool getShowChatView();
void setTransferCallAvailability(bool visible);
void setCurrentSelectedCalleeDisplayName(const QString& CalleeDisplayName);
void resetOverlay(bool isAudioMuted, bool isVideoMuted, bool isRecording, bool isHolding);
//UI SLOTS
......@@ -56,6 +58,8 @@ private slots:
void on_noMicButton_toggled(bool checked);
void on_noVideoButton_toggled(bool checked);
void on_recButton_clicked();
void on_transferButton_toggled(bool checked);
void on_transferCall_requested(const std::string& callId, const std::string& contactUri);
private:
Ui::VideoOverlay* ui;
......
......@@ -333,7 +333,7 @@ VideoView::showContextMenu(const QPoint& pos)
}
void
VideoView::pushRenderer(const std::string& callId) {
VideoView::pushRenderer(const std::string& callId, bool isSIP) {
auto callModel = LRCInstance::getCurrentCallModel();
QObject::disconnect(ui->videoWidget);
......@@ -349,6 +349,8 @@ VideoView::pushRenderer(const std::string& callId) {
return;
}
// transfer call will only happen in SIP calls
this->overlay_->setTransferCallAvailability(isSIP);
this->overlay_->callStarted(callId);
this->overlay_->setVideoMuteVisibility(!LRCInstance::getCurrentCallModel()->getCall(callId).isAudioOnly);
......@@ -426,6 +428,13 @@ VideoView::mouseMoveEvent(QMouseEvent* event)
and geometry().contains(event->pos()))
previewRect.setBottomRight(event->pos());
}
void
VideoView::setCurrentCalleeName(const QString& CalleeDisplayName)
{
overlay_->setCurrentSelectedCalleeDisplayName(CalleeDisplayName);
}
void
VideoView::resetVideoOverlay(bool isAudioMuted, bool isVideoMuted, bool isRecording, bool isHolding)
{
......
......@@ -36,8 +36,10 @@ class VideoView : public QWidget
public:
explicit VideoView(QWidget* parent = 0);
~VideoView();
void pushRenderer(const std::string& callUid);
void pushRenderer(const std::string& callUid, bool isSIP);
void showChatviewIfToggled();
void simulateShowChatview(bool checked);
void setCurrentCalleeName(const QString& CalleeDisplayName);
void resetVideoOverlay(bool isAudioMuted, bool isVideoMuted, bool isRecording, bool isHolding);
protected:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment