diff --git a/RingWinClient.pro b/RingWinClient.pro index 8e36a423f0ed850839d30c25eb3a6196e97335a0..d5ba0af6e171e98596f9ddf4cbf67f431bc635ad 100644 --- a/RingWinClient.pro +++ b/RingWinClient.pro @@ -56,8 +56,8 @@ SOURCES += main.cpp\ contactpicker.cpp \ contactmethodpicker.cpp \ globalsystemtray.cpp \ - transferdialog.cpp \ - smartlistdelegate.cpp + smartlistdelegate.cpp \ + callutilsdialog.cpp HEADERS += mainwindow.h \ callwidget.h \ @@ -84,8 +84,8 @@ HEADERS += mainwindow.h \ contactmethodpicker.h \ settingskey.h \ globalsystemtray.h \ - transferdialog.h \ - smartlistdelegate.h + smartlistdelegate.h \ + callutilsdialog.h FORMS += mainwindow.ui \ callwidget.ui \ @@ -99,7 +99,7 @@ FORMS += mainwindow.ui \ videooverlay.ui \ contactpicker.ui \ contactmethodpicker.ui \ - transferdialog.ui + callutilsdialog.ui win32: LIBS += -lole32 -luuid -lshlwapi diff --git a/callutilsdialog.cpp b/callutilsdialog.cpp new file mode 100644 index 0000000000000000000000000000000000000000..86d566b4a4d1f6422eed3144b9054a1305d0aa36 --- /dev/null +++ b/callutilsdialog.cpp @@ -0,0 +1,137 @@ +/*************************************************************************** + * Copyright (C) 2015 by Savoir-faire Linux * + * Author: Edric Ladent Milaret <edric.ladent-milaret@savoirfairelinux.com>* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + **************************************************************************/ + +#include "callutilsdialog.h" +#include "ui_callutilsdialog.h" + +#include "callmodel.h" +#include "phonedirectorymodel.h" +#include "recentmodel.h" +#include "contactmethod.h" +#include "person.h" + +CallUtilsDialog::CallUtilsDialog(QWidget* parent) : + QDialog(parent), + ui(new Ui::CallUtilsDialog), + confMode_(false), + smartListDelegate_(nullptr), + notCurrentProxyModel_(nullptr) +{ + ui->setupUi(this); + + this->setWindowFlags(Qt::CustomizeWindowHint); + this->setWindowFlags(Qt::FramelessWindowHint | Qt::Popup); +} + +CallUtilsDialog::~CallUtilsDialog() +{ + delete smartListDelegate_; + delete notCurrentProxyModel_; + delete ui; +} + +void +CallUtilsDialog::showEvent(QShowEvent* event) +{ + Q_UNUSED(event) + + ui->numberBar->clear(); + if (not notCurrentProxyModel_) { + notCurrentProxyModel_ = new NotCurrentProxyModel(&RecentModel::instance()); + } + ui->contactView->setModel(notCurrentProxyModel_); + if (not smartListDelegate_) { + smartListDelegate_ = new SmartListDelegate(); + } + ui->contactView->setItemDelegate(smartListDelegate_); +} + +void CallUtilsDialog::removeProxyModel() +{ + ui->contactView->setModel(nullptr); +} + +void CallUtilsDialog::closeEvent(QCloseEvent* event) +{ + //This prevent a crash happening in Qt5.5 in QSortFilterProxyModel + Q_UNUSED(event) + removeProxyModel(); +} + +void +CallUtilsDialog::on_transferButton_clicked() +{ + auto callList = CallModel::instance().getActiveCalls(); + for (auto c : callList) { + if (c->state() == Call::State::CURRENT) { + if (not ui->numberBar->text().isEmpty()) { + auto number = PhoneDirectoryModel::instance().getNumber(ui->numberBar->text()); + CallModel::instance().transfer(c, number); + } + removeProxyModel(); + this->close(); + return; + } + } +} + +void +CallUtilsDialog::setConfMode(bool active) +{ + confMode_ = active; + ui->transferButton->setVisible(not active); + ui->numberBar->setVisible(not active); +} + +void +CallUtilsDialog::on_contactView_doubleClicked(const QModelIndex& index) +{ + removeProxyModel(); + if (not index.isValid()) + return; + auto realIdx = notCurrentProxyModel_->mapToSource(index); + if (not RecentModel::instance().hasActiveCall(realIdx)) { + ContactMethod* m = nullptr; + if (auto cm = realIdx.data(static_cast<int>(Call::Role::ContactMethod)).value<ContactMethod*>()) { + m = cm; + } else { + if (auto person = realIdx.data(static_cast<int>(Person::Role::Object)).value<Person*>()) { + m = person->phoneNumbers().first(); + } + } + if (confMode_) { + if (m && !RecentModel::instance().index(0, 0, realIdx).isValid()) { + Call* c = CallModel::instance().dialingCall(m, CallModel::instance().selectedCall()); + c->performAction(Call::Action::ACCEPT); + } + } else { + if (m) { + auto activeCall = CallModel::instance().selectedCall(); + CallModel::instance().transfer(activeCall, m); + } + } + } else { + auto activeCall = CallModel::instance().selectedCall(); + auto call = RecentModel::instance().getActiveCall(realIdx); + if (not confMode_) + CallModel::instance().attendedTransfer(activeCall, call); + else + CallModel::instance().createJoinOrMergeConferenceFromCall(activeCall, call); + } + this->close(); +} diff --git a/transferdialog.h b/callutilsdialog.h similarity index 70% rename from transferdialog.h rename to callutilsdialog.h index a28fce0daa1330dbea41937bfdd008c9a6d7e419..37c9e21befe5f612f9ef6757b2723b6807af0875 100644 --- a/transferdialog.h +++ b/callutilsdialog.h @@ -22,15 +22,18 @@ #include <QSortFilterProxyModel> #include "callmodel.h" +#include "recentmodel.h" + +#include "smartlistdelegate.h" namespace Ui { -class TransferDialog; + class CallUtilsDialog; } -class ActiveCallsProxyModel : public QSortFilterProxyModel +class NotCurrentProxyModel : public QSortFilterProxyModel { public: - ActiveCallsProxyModel(QAbstractItemModel* parent) : QSortFilterProxyModel(parent) + NotCurrentProxyModel(QAbstractItemModel* parent) : QSortFilterProxyModel(parent) { setSourceModel(parent); } @@ -41,32 +44,34 @@ public: auto idx = sourceModel()->index(source_row,0,source_parent); if (not idx.isValid()) return false; - return idx.data(static_cast<int>(Call::Role::State)) - .value<Call::State>() != Call::State::CURRENT; + auto call = RecentModel::instance().getActiveCall(idx); + return not call || not (call->state() == Call::State::CURRENT); } }; - -class TransferDialog : public QDialog +class CallUtilsDialog : public QDialog { Q_OBJECT public: - explicit TransferDialog(QWidget *parent = 0); - ~TransferDialog(); + explicit CallUtilsDialog(QWidget* parent = 0); + ~CallUtilsDialog(); + + void setConfMode(bool active); //UI SLOTS protected slots: - void showEvent(QShowEvent *event); + void showEvent(QShowEvent* event); + void closeEvent(QCloseEvent* event); private slots: void on_transferButton_clicked(); - void on_activeCallsView_doubleClicked(const QModelIndex &index); - void on_activeCallsView_clicked(const QModelIndex &index); + void on_contactView_doubleClicked(const QModelIndex& index); private: - Ui::TransferDialog *ui; - Call *selectedCall_; - ActiveCallsProxyModel *activeProxy_; + Ui::CallUtilsDialog* ui; + bool confMode_; + SmartListDelegate* smartListDelegate_; + NotCurrentProxyModel* notCurrentProxyModel_; void removeProxyModel(); }; diff --git a/transferdialog.ui b/callutilsdialog.ui similarity index 59% rename from transferdialog.ui rename to callutilsdialog.ui index 73165908402000eb4fac8c92b32de46d951a05da..f2cb59a2bb9ec26dbfcd35ede560baa4e3740e46 100644 --- a/transferdialog.ui +++ b/callutilsdialog.ui @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> - <class>TransferDialog</class> - <widget class="QDialog" name="TransferDialog"> + <class>CallUtilsDialog</class> + <widget class="QDialog" name="CallUtilsDialog"> <property name="geometry"> <rect> <x>0</x> @@ -13,18 +13,23 @@ <property name="windowTitle"> <string>Dialog</string> </property> - <layout class="QGridLayout" name="gridLayout" rowstretch="0,0,0,0" columnstretch="0,0"> - <item row="1" column="0"> - <widget class="QListView" name="activeCallsView"/> + <layout class="QVBoxLayout" name="verticalLayout"> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>4</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>1</number> + </property> + <item> + <widget class="QListView" name="contactView"/> </item> - <item row="3" column="0" colspan="2"> - <widget class="QPushButton" name="transferButton"> - <property name="text"> - <string>Transfer</string> - </property> - </widget> - </item> - <item row="2" column="0"> + <item> <widget class="QLineEdit" name="numberBar"> <property name="placeholderText"> <string>or type number...</string> @@ -34,10 +39,10 @@ </property> </widget> </item> - <item row="0" column="0"> - <widget class="QLabel" name="label"> + <item> + <widget class="QPushButton" name="transferButton"> <property name="text"> - <string>Current Calls</string> + <string>Transfer</string> </property> </widget> </item> diff --git a/callwidget.cpp b/callwidget.cpp index 1e3b5f9dd966cdeedca4ecee4aa17b164f8680f0..d018bd7b93a63d29e60f758e83e9201f7b6100bf 100644 --- a/callwidget.cpp +++ b/callwidget.cpp @@ -150,8 +150,8 @@ CallWidget::CallWidget(QWidget *parent) : findRingAccount(); - } catch (...) { - qDebug() << "INIT ERROR"; + } catch (const std::exception& e) { + qDebug() << "INIT ERROR" << e.what(); } } @@ -270,9 +270,6 @@ CallWidget::callStateChanged(Call* call, Call::State previousState) if (call == nullptr) return; - //Force update of smartList - ui->smartList->setFocus(); - if (call->state() == Call::State::OVER || call->state() == Call::State::ERROR || call->state() == Call::State::FAILURE @@ -349,8 +346,8 @@ void CallWidget::setActualCall(Call* value) { actualCall_ = value; - if (value) - CallModel::instance().selectCall(value); + CallModel::instance().selectCall(value); + ui->videoWidget->pushRenderer(value); } void @@ -395,18 +392,14 @@ CallWidget::smartListSelectionChanged(const QItemSelection &newSel, const QItemS Q_UNUSED(oldSel) auto newIdx = newSel.indexes().first(); - if (newIdx.parent().isValid()) + if (not newIdx.isValid()) return; auto newIdxCall = RecentModel::instance().getActiveCall(RecentModel::instance().peopleProxy()->mapToSource(newIdx)); if (newIdxCall == actualCall_) return; - if (actualCall_ != nullptr) { - actualCall_->performAction(Call::Action::HOLD); - } if (newIdxCall) { - newIdxCall->performAction(Call::Action::HOLD); setActualCall(newIdxCall); ui->stackedWidget->setCurrentWidget(ui->videoPage); } else { diff --git a/transferdialog.cpp b/transferdialog.cpp deleted file mode 100644 index 90e204ce775e8698cc184f48d39bbc3fee1b0db2..0000000000000000000000000000000000000000 --- a/transferdialog.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2015 by Savoir-faire Linux * - * Author: Edric Ladent Milaret <edric.ladent-milaret@savoirfairelinux.com>* - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 3 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see <http://www.gnu.org/licenses/>. * - **************************************************************************/ - -#include "transferdialog.h" -#include "ui_transferdialog.h" - -#include "callmodel.h" -#include "phonedirectorymodel.h" - -TransferDialog::TransferDialog(QWidget *parent) : - QDialog(parent), - ui(new Ui::TransferDialog), - activeProxy_(nullptr) -{ - ui->setupUi(this); - - this->setWindowFlags(Qt::CustomizeWindowHint); - this->setWindowFlags(Qt::FramelessWindowHint); -} - -TransferDialog::~TransferDialog() -{ - delete ui; -} - -void -TransferDialog::showEvent(QShowEvent *event) -{ - Q_UNUSED(event) - - ui->numberBar->clear(); - selectedCall_ = nullptr; - if (not activeProxy_) { - activeProxy_ = new ActiveCallsProxyModel(&CallModel::instance()); - activeProxy_->setDynamicSortFilter(false); - } - ui->activeCallsView->setModel(activeProxy_); - ui->activeCallsView->clearSelection(); -} - -void -TransferDialog::on_transferButton_clicked() -{ - removeProxyModel(); - - auto callList = CallModel::instance().getActiveCalls(); - for (auto c : callList) { - if (c->state() == Call::State::CURRENT) { - if (not ui->numberBar->text().isEmpty()) { - auto number = PhoneDirectoryModel::instance().getNumber(ui->numberBar->text()); - CallModel::instance().transfer(c, number); - } else if (selectedCall_) { - CallModel::instance().attendedTransfer(c, selectedCall_); - } - this->close(); - return; - } - } -} - -void -TransferDialog::removeProxyModel() -{ - //This prevent a crash happening in Qt5.5 in QSortFilterProxyModel - ui->activeCallsView->setModel(nullptr); -} - -void -TransferDialog::on_activeCallsView_doubleClicked(const QModelIndex &index) -{ - Q_UNUSED(index) - - removeProxyModel(); - - auto callList = CallModel::instance().getActiveCalls(); - for (auto c : callList) { - if (c->state() == Call::State::CURRENT) { - if (c != selectedCall_) { - CallModel::instance().attendedTransfer(c, selectedCall_); - this->close(); - return; - } - } - } -} - -void -TransferDialog::on_activeCallsView_clicked(const QModelIndex &index) -{ - selectedCall_ = CallModel::instance().getCall(index); -} diff --git a/videooverlay.cpp b/videooverlay.cpp index cbe728cb955c3bfd7a57f3c3016229957f46007d..0028307b2be5a8f5fddadf8c5bfeb7f69534766d 100644 --- a/videooverlay.cpp +++ b/videooverlay.cpp @@ -21,15 +21,14 @@ #include "callmodel.h" -VideoOverlay::VideoOverlay(QWidget *parent) : +VideoOverlay::VideoOverlay(QWidget* parent) : QWidget(parent), ui(new Ui::VideoOverlay), - transferDialog_(new TransferDialog()) + transferDialog_(new CallUtilsDialog()) { ui->setupUi(this); ui->chatButton->setCheckable(true); - ui->transferButton->setCheckable(true); actionModel_ = CallModel::instance().userActionModel(); setAttribute(Qt::WA_NoSystemBackground); @@ -62,6 +61,10 @@ VideoOverlay::VideoOverlay(QWidget *parent) : muteVideo->setChecked(idx.data(Qt::CheckStateRole).value<bool>()); muteVideo->setEnabled(idx.flags() & Qt::ItemIsEnabled); break; + case UserActionModel::Action::HOLD: + ui->holdButton->setChecked(idx.data(Qt::CheckStateRole).value<bool>()); + ui->holdButton->setEnabled(idx.flags() & Qt::ItemIsEnabled); + break; default: break; } @@ -69,6 +72,30 @@ VideoOverlay::VideoOverlay(QWidget *parent) : }); ui->moreButton->setMenu(menu_); + + connect(CallModel::instance().selectionModel(), &QItemSelectionModel::currentChanged, [=](const QModelIndex ¤t, const QModelIndex &previous) { + Q_UNUSED(previous) + Call* c = current.data(static_cast<int>(Call::Role::Object)).value<Call*>(); + if (c) { + if (c->hasParentCall()) { + ui->holdButton->hide(); + ui->moreButton->hide(); + ui->transferButton->hide(); + ui->addPersonButton->hide(); + ui->chatButton->hide(); + + ui->joinButton->show(); + } else { + ui->holdButton->show(); + ui->moreButton->show(); + ui->transferButton->show(); + ui->addPersonButton->show(); + ui->chatButton->show(); + + ui->joinButton->hide(); + } + } + }); } VideoOverlay::~VideoOverlay() @@ -90,13 +117,6 @@ VideoOverlay::setTime(const QString& time) ui->timerLabel->setText(time); } -void -VideoOverlay::on_holdButton_toggled(bool checked) -{ - Q_UNUSED(checked) - actionModel_->execute(UserActionModel::Action::HOLD); -} - void VideoOverlay::on_hangupButton_clicked() { @@ -111,9 +131,36 @@ VideoOverlay::on_chatButton_toggled(bool checked) } void -VideoOverlay::on_transferButton_toggled(bool checked) +VideoOverlay::on_transferButton_clicked() { + transferDialog_->setConfMode(false); auto pos = this->mapToGlobal(ui->transferButton->pos()); - transferDialog_->move(pos.x() + ui->transferButton->width(), pos.y() - (transferDialog_->height()/2)); - checked ? transferDialog_->show() : transferDialog_->hide(); + transferDialog_->move(pos.x() + - transferDialog_->size().width()/2 + + ui->transferButton->size().width()/2, + pos.y() - (transferDialog_->height())); + transferDialog_->show(); +} + +void +VideoOverlay::on_addPersonButton_clicked() +{ + transferDialog_->setConfMode(true); + auto pos = this->mapToGlobal(ui->addPersonButton->pos()); + transferDialog_->move(pos.x() + - transferDialog_->size().width()/2 + + ui->addPersonButton->size().width()/2, + pos.y() - (transferDialog_->height())); + transferDialog_->show(); +} + +void +VideoOverlay::on_holdButton_clicked() +{ + actionModel_->execute(UserActionModel::Action::HOLD); +} + +void VideoOverlay::on_joinButton_clicked() +{ + CallModel::instance().selectedCall()->joinToParent(); } diff --git a/videooverlay.h b/videooverlay.h index 2037876631399cf0999c041562849a83614c8a39..7d821bc58cedd03f844de7174d14543478bb75d5 100644 --- a/videooverlay.h +++ b/videooverlay.h @@ -23,7 +23,7 @@ #include "useractionmodel.h" -#include "transferdialog.h" +#include "callutilsdialog.h" namespace Ui { class VideoOverlay; @@ -34,25 +34,27 @@ class VideoOverlay : public QWidget Q_OBJECT public: - explicit VideoOverlay(QWidget *parent = 0); + explicit VideoOverlay(QWidget* parent = 0); ~VideoOverlay(); public: - void setName(const QString &name); - void setTime(const QString &time); + void setName(const QString& name); + void setTime(const QString& time); //UI SLOTS private slots: - void on_holdButton_toggled(bool checked); void on_hangupButton_clicked(); void on_chatButton_toggled(bool checked); - void on_transferButton_toggled(bool checked); + void on_transferButton_clicked(); + void on_addPersonButton_clicked(); + void on_holdButton_clicked(); + void on_joinButton_clicked(); private: - Ui::VideoOverlay *ui; + Ui::VideoOverlay* ui; UserActionModel* actionModel_; QMenu* menu_; - TransferDialog *transferDialog_; + CallUtilsDialog* transferDialog_; signals: void setChatVisibility(bool visible); diff --git a/videooverlay.ui b/videooverlay.ui index 7d38ac99635f09bd2da8be2405624887b6014c64..27674f5f3cbeb749d193409bd8dc7abbe7526d93 100644 --- a/videooverlay.ui +++ b/videooverlay.ui @@ -23,22 +23,8 @@ <string/> </property> <layout class="QGridLayout" name="gridLayout"> - <item row="1" column="2"> - <widget class="QPushButton" name="hangupButton"> - <property name="text"> - <string>Hangup</string> - </property> - </widget> - </item> - <item row="1" column="5"> - <widget class="QPushButton" name="moreButton"> - <property name="text"> - <string>...</string> - </property> - </widget> - </item> - <item row="1" column="0"> - <spacer name="horizontalSpacer"> + <item row="1" column="8"> + <spacer name="horizontalSpacer_2"> <property name="orientation"> <enum>Qt::Horizontal</enum> </property> @@ -50,21 +36,15 @@ </property> </spacer> </item> - <item row="1" column="6"> - <spacer name="horizontalSpacer_2"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> + <item row="1" column="2"> + <widget class="QPushButton" name="hangupButton"> + <property name="text"> + <string>Hangup</string> </property> - </spacer> + </widget> </item> - <item row="0" column="0" alignment="Qt::AlignTop"> - <widget class="QLabel" name="nameLabel"> + <item row="0" column="8" alignment="Qt::AlignRight|Qt::AlignTop"> + <widget class="QLabel" name="timerLabel"> <property name="palette"> <palette> <active> @@ -103,12 +83,26 @@ </palette> </property> <property name="text"> - <string/> + <string>00:00</string> </property> </widget> </item> - <item row="0" column="6" alignment="Qt::AlignRight|Qt::AlignTop"> - <widget class="QLabel" name="timerLabel"> + <item row="1" column="4"> + <widget class="QPushButton" name="addPersonButton"> + <property name="text"> + <string>Add People</string> + </property> + </widget> + </item> + <item row="1" column="7"> + <widget class="QPushButton" name="moreButton"> + <property name="text"> + <string>...</string> + </property> + </widget> + </item> + <item row="0" column="0" alignment="Qt::AlignTop"> + <widget class="QLabel" name="nameLabel"> <property name="palette"> <palette> <active> @@ -147,10 +141,30 @@ </palette> </property> <property name="text"> - <string>00:00</string> + <string/> + </property> + </widget> + </item> + <item row="1" column="3"> + <widget class="QPushButton" name="chatButton"> + <property name="text"> + <string>Chat</string> </property> </widget> </item> + <item row="1" column="0"> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> <item row="1" column="1"> <widget class="QPushButton" name="holdButton"> <property name="text"> @@ -161,17 +175,17 @@ </property> </widget> </item> - <item row="1" column="3"> - <widget class="QPushButton" name="chatButton"> + <item row="1" column="6"> + <widget class="QPushButton" name="transferButton"> <property name="text"> - <string>Chat</string> + <string>Transfer</string> </property> </widget> </item> - <item row="1" column="4"> - <widget class="QPushButton" name="transferButton"> + <item row="1" column="5"> + <widget class="QPushButton" name="joinButton"> <property name="text"> - <string>Transfer</string> + <string>Join</string> </property> </widget> </item> diff --git a/videoview.cpp b/videoview.cpp index 4157d7ae63de1a157d455f081c91f15b62636826..c0e18165fea8b1706702a6faf9014055e1e78292 100644 --- a/videoview.cpp +++ b/videoview.cpp @@ -35,7 +35,7 @@ #include "videooverlay.h" #include "selectareadialog.h" -VideoView::VideoView(QWidget *parent) : +VideoView::VideoView(QWidget* parent) : QWidget(parent), ui(new Ui::VideoView) { @@ -72,7 +72,7 @@ VideoView::~VideoView() } void -VideoView::resizeEvent(QResizeEvent *event) +VideoView::resizeEvent(QResizeEvent* event) { Q_UNUSED(event) overlay_->resize(this->size()); @@ -99,24 +99,26 @@ void VideoView::callStateChanged(Call* call, Call::State previousState) { Q_UNUSED(previousState) + if (call->state() == Call::State::CURRENT) { ui->videoWidget->show(); timerConnection_ = connect(call, SIGNAL(changed()), this, SLOT(updateCall())); } else { + QObject::disconnect(timerConnection_); emit setChatVisibility(false); if (isFullScreen()) toggleFullScreen(); - QObject::disconnect(timerConnection_); } } void VideoView::updateCall() { - auto call = CallModel::instance().selectedCall(); - overlay_->setName(call->formattedName()); - overlay_->setTime(call->length()); + if (auto call = CallModel::instance().selectedCall()) { + overlay_->setName(call->formattedName()); + overlay_->setTime(call->length()); + } } void @@ -125,13 +127,15 @@ VideoView::mouseDoubleClickEvent(QMouseEvent* e) { toggleFullScreen(); } -void VideoView::dragEnterEvent(QDragEnterEvent *event) +void +VideoView::dragEnterEvent(QDragEnterEvent* event) { if (event->mimeData()->hasUrls()) event->acceptProposedAction(); } -void VideoView::dropEvent(QDropEvent *event) +void +VideoView::dropEvent(QDropEvent* event) { auto urls = event->mimeData()->urls(); Video::SourceModel::instance().setFile(urls.at(0)); @@ -204,3 +208,27 @@ VideoView::showContextMenu(const QPoint& pos) menu.exec(globalPos); } +void +VideoView::pushRenderer(Call* call) { + if (not call) { + disconnect(videoStartedConnection_); + return; + } + if (auto renderer = call->videoRenderer()) { + slotVideoStarted(renderer); + } else { + disconnect(videoStartedConnection_); + videoStartedConnection_ = connect(call, + SIGNAL(videoStarted(Video::Renderer*)), + this, + SLOT(slotVideoStarted(Video::Renderer*))); + } + ui->videoWidget->setPreviewDisplay(call->type() != Call::Type::CONFERENCE); +} + +void +VideoView::slotVideoStarted(Video::Renderer* renderer) { + ui->videoWidget->show(); + ui->videoWidget->setDistantRenderer(renderer); +} + diff --git a/videoview.h b/videoview.h index 4e535ef7904217c209ecb910457865d311c85aae..bcf95c17b4e336ed43cc5e1b4702e7d7fea33c63 100644 --- a/videoview.h +++ b/videoview.h @@ -34,30 +34,33 @@ class VideoView : public QWidget Q_OBJECT public: - explicit VideoView(QWidget *parent = 0); + explicit VideoView(QWidget* parent = 0); ~VideoView(); + void pushRenderer(Call* call); protected: void resizeEvent(QResizeEvent* event); void enterEvent(QEvent* event); void leaveEvent(QEvent* event); - void mouseDoubleClickEvent(QMouseEvent *e); - void dragEnterEvent(QDragEnterEvent *event); - void dropEvent(QDropEvent *event); + void mouseDoubleClickEvent(QMouseEvent* e); + void dragEnterEvent(QDragEnterEvent* event); + void dropEvent(QDropEvent* event); private slots: - void callStateChanged(Call *call, Call::State previousState); + void callStateChanged(Call* call, Call::State previousState); void updateCall(); - void showContextMenu(const QPoint &pos); + void showContextMenu(const QPoint& pos); + void slotVideoStarted(Video::Renderer* renderer); private: - Ui::VideoView *ui; + Ui::VideoView* ui; VideoOverlay* overlay_; constexpr static int fadeOverlayTime_ = 2000; //msec QPropertyAnimation* fadeAnim_; - QWidget *oldParent_; + QWidget* oldParent_; QSize oldSize_; QMetaObject::Connection timerConnection_; + QMetaObject::Connection videoStartedConnection_; private: void toggleFullScreen(); signals: diff --git a/videowidget.cpp b/videowidget.cpp index c12c100d36be3b17ba0775c12274c1e903eeed61..5bc7023b8f77c5027a45a6960e87c8c95d8c8cb4 100644 --- a/videowidget.cpp +++ b/videowidget.cpp @@ -18,18 +18,15 @@ #include "videowidget.h" -VideoWidget::VideoWidget(QWidget *parent) : +VideoWidget::VideoWidget(QWidget* parent) : QWidget(parent) , previewRenderer_(nullptr) , renderer_(nullptr) + , isPreviewDisplayed_(true) { connect(&Video::PreviewManager::instance(), SIGNAL(previewStarted(Video::Renderer*)), this, SLOT(previewStarted(Video::Renderer*))); - connect(&CallModel::instance(), - SIGNAL(rendererAdded(Call*,Video::Renderer*)), - this, SLOT(callInitiated(Call*, Video::Renderer*)), - Qt::ConnectionType::DirectConnection); QPalette pal(palette()); pal.setColor(QPalette::Background, Qt::black); @@ -41,10 +38,12 @@ VideoWidget::~VideoWidget() {} void -VideoWidget::previewStarted(Video::Renderer *renderer) { +VideoWidget::previewStarted(Video::Renderer* renderer) { //Enforce that only one videowidget we'll be used at the same time if (not isVisible()) return; + if (previewRenderer_ == renderer) + return; previewRenderer_ = renderer; connect(previewRenderer_, SIGNAL(frameUpdated()), this, SLOT(frameFromPreview())); @@ -57,7 +56,7 @@ VideoWidget::previewStopped() { disconnect(previewRenderer_, SIGNAL(frameUpdated()), this, SLOT(frameFromPreview())); disconnect(previewRenderer_, SIGNAL(stopped()), - this, SLOT(renderingStopped())); + this, SLOT(previewStopped())); previewRenderer_ = nullptr; } @@ -75,7 +74,7 @@ VideoWidget::frameFromPreview() { } void -VideoWidget::paintEvent(QPaintEvent *evt) { +VideoWidget::paintEvent(QPaintEvent* evt) { Q_UNUSED(evt) QPainter painter(this); @@ -99,7 +98,7 @@ VideoWidget::paintEvent(QPaintEvent *evt) { painter.drawImage(QRect(xDiff,yDiff,scaledDistant.width(),scaledDistant.height()), scaledDistant); } } - if (previewRenderer_) { + if (previewRenderer_ && isPreviewDisplayed_) { { QMutexLocker lock(&mutex_); if (currentPreviewFrame_.storage.size() != 0 @@ -129,15 +128,15 @@ VideoWidget::paintEvent(QPaintEvent *evt) { } void -VideoWidget::callInitiated(Call* call, Video::Renderer *renderer) { - Q_UNUSED(call) - //Enforce that only one videowidget we'll be used at the same time - if (not isVisible()) +VideoWidget::setDistantRenderer(Video::Renderer* renderer) { + if (not renderer) return; - renderer_ = renderer; - connect(renderer_, SIGNAL(frameUpdated()), this, SLOT(frameFromDistant())); - connect(renderer_, SIGNAL(stopped()),this, SLOT(renderingStopped()), - Qt::ConnectionType::DirectConnection); + if (renderer_ != renderer) { + renderingStopped(); + renderer_ = renderer; + connect(renderer_, SIGNAL(frameUpdated()), this, SLOT(frameFromDistant())); + connect(renderer_, SIGNAL(stopped()),this, SLOT(renderingStopped())); + } } void @@ -148,7 +147,6 @@ VideoWidget::frameFromDistant() { auto tmp = renderer_->currentFrame(); if (tmp.storage.size()) currentDistantFrame_ = tmp; - } update(); } @@ -156,7 +154,14 @@ VideoWidget::frameFromDistant() { void VideoWidget::renderingStopped() { + if (not renderer_) + return; disconnect(renderer_, SIGNAL(frameUpdated()), this, SLOT(frameFromDistant())); disconnect(renderer_, SIGNAL(stopped()),this, SLOT(renderingStopped())); renderer_ = nullptr; } + +void +VideoWidget::setPreviewDisplay(bool display) { + isPreviewDisplayed_ = display; +} diff --git a/videowidget.h b/videowidget.h index aa39d4741d6cbbaa023ead5c1fc233ee3f00cdc5..83ac5ac6a438ebca420f9bceb1fa55d7bf6cda7d 100644 --- a/videowidget.h +++ b/videowidget.h @@ -31,15 +31,16 @@ class VideoWidget : public QWidget { Q_OBJECT public: - explicit VideoWidget(QWidget *parent = 0); + explicit VideoWidget(QWidget* parent = 0); ~VideoWidget(); void paintEvent(QPaintEvent* evt); + void setPreviewDisplay(bool display); + void setDistantRenderer(Video::Renderer* renderer); public slots: void previewStarted(Video::Renderer* renderer); void previewStopped(); void frameFromPreview(); - void callInitiated(Call *call, Video::Renderer *renderer); void frameFromDistant(); void renderingStopped(); @@ -53,6 +54,7 @@ private: std::unique_ptr<QImage> previewImage_; std::vector<uint8_t> frameDistant_; std::vector<uint8_t> framePreview_; + bool isPreviewDisplayed_; constexpr static int previewMargin_ = 15; };