From 864a2050af673374135a26b515cfff21028a646a Mon Sep 17 00:00:00 2001 From: Edric Milaret <edric.ladent-milaret@savoirfairelinux.com> Date: Thu, 14 Jan 2016 15:45:03 -0500 Subject: [PATCH] ui: add quality button - Add the slider and the auto quality checkbox - This a an adaptation of Stepan code Change-Id: I04bd33dbc6b9f7042617443ce42f9c6162971282 Tuleap: #215 --- RingWinClient.pro | 9 +- images/video-conf/ic_high_quality_white.svg | 4 + qualitydialog.cpp | 116 ++++++++++++++ qualitydialog.h | 45 ++++++ qualitydialog.ui | 93 +++++++++++ ressources.qrc | 1 + stylesheet.css | 6 + videooverlay.cpp | 20 ++- videooverlay.h | 3 + videooverlay.ui | 163 +++++++++++--------- 10 files changed, 384 insertions(+), 76 deletions(-) create mode 100644 images/video-conf/ic_high_quality_white.svg create mode 100644 qualitydialog.cpp create mode 100644 qualitydialog.h create mode 100644 qualitydialog.ui diff --git a/RingWinClient.pro b/RingWinClient.pro index c67fdac..693af7b 100644 --- a/RingWinClient.pro +++ b/RingWinClient.pro @@ -67,7 +67,8 @@ SOURCES += main.cpp\ mainwindowtoolbar.cpp \ ringcontactlineedit.cpp \ smartlistscrollbar.cpp \ - pixbufmanipulator.cpp + pixbufmanipulator.cpp \ + qualitydialog.cpp HEADERS += mainwindow.h \ callwidget.h \ @@ -102,7 +103,8 @@ HEADERS += mainwindow.h \ mainwindowtoolbar.h \ ringcontactlineedit.h \ smartlistscrollbar.h \ - pixbufmanipulator.h + pixbufmanipulator.h \ + qualitydialog.h FORMS += mainwindow.ui \ callwidget.ui \ @@ -117,7 +119,8 @@ FORMS += mainwindow.ui \ contactpicker.ui \ contactmethodpicker.ui \ callutilsdialog.ui \ - combar.ui + combar.ui \ + qualitydialog.ui win32: LIBS += -lole32 -luuid -lshlwapi diff --git a/images/video-conf/ic_high_quality_white.svg b/images/video-conf/ic_high_quality_white.svg new file mode 100644 index 0000000..ad4091c --- /dev/null +++ b/images/video-conf/ic_high_quality_white.svg @@ -0,0 +1,4 @@ +<svg fill="#FFFFFF" height="48" viewBox="0 0 24 24" width="48" xmlns="http://www.w3.org/2000/svg"> + <path d="M0 0h24v24H0z" fill="none"/> + <path d="M19 4H5c-1.11 0-2 .9-2 2v12c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm-8 11H9.5v-2h-2v2H6V9h1.5v2.5h2V9H11v6zm7-1c0 .55-.45 1-1 1h-.75v1.5h-1.5V15H14c-.55 0-1-.45-1-1v-4c0-.55.45-1 1-1h3c.55 0 1 .45 1 1v4zm-3.5-.5h2v-3h-2v3z"/> +</svg> \ No newline at end of file diff --git a/qualitydialog.cpp b/qualitydialog.cpp new file mode 100644 index 0000000..589e5be --- /dev/null +++ b/qualitydialog.cpp @@ -0,0 +1,116 @@ +/*************************************************************************** + * Copyright (C) 2016 by Savoir-faire Linux * + * Author: Edric Ladent Milaret <edric.ladent-milaret@savoirfairelinux.com>* + * Author: Stepan Salenikovich <stepan.salenikovich@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 "qualitydialog.h" +#include "ui_qualitydialog.h" + +#include "callmodel.h" +#include "account.h" +#include "audio/codecmodel.h" + +#include <QSortFilterProxyModel> + +QualityDialog::QualityDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::QualityDialog) +{ + ui->setupUi(this); + + this->setWindowFlags(Qt::CustomizeWindowHint); + this->setWindowFlags(Qt::FramelessWindowHint | Qt::Popup); +} + +QualityDialog::~QualityDialog() +{ + delete ui; +} + +void +QualityDialog::on_autoCheckBox_toggled(bool checked) +{ + setQuality(); + ui->qualitySlider->setEnabled(not checked); +} + + +void +QualityDialog::on_qualitySlider_sliderReleased() +{ + setQuality(); +} + +void QualityDialog::showEvent(QShowEvent* event) { + QWidget::showEvent(event); + ui->autoCheckBox->blockSignals(true); + const auto& call = CallModel::instance().selectedCall(); + if (const auto& codecModel = call->account()->codecModel()) { + const auto& videoCodecs = codecModel->videoCodecs(); + if (videoCodecs->rowCount() > 0) { + /* we only need to check the first codec since by default it is ON for all, and the + * client sets its ON or OFF for all codecs as well */ + const auto& idx = videoCodecs->index(0,0); + auto auto_quality_enabled = idx.data(static_cast<int>(CodecModel::Role::AUTO_QUALITY_ENABLED)).toString() == "true"; + ui->autoCheckBox->setChecked(auto_quality_enabled); + ui->qualitySlider->setEnabled(not auto_quality_enabled); + + // TODO: save the manual quality setting in the client and set the slider to that value here; + // the daemon resets the bitrate/quality between each call, and the default may be + // different for each codec, so there is no reason to check it here + } + } + ui->autoCheckBox->blockSignals(false); +} + +void +QualityDialog::setQuality() +{ + /* set auto quality true or false, also set the bitrate and quality values; + * the slider is from 0 to 100, use the min and max vals to scale each value accordingly */ + const auto& call = CallModel::instance().selectedCall(); + if (const auto& codecModel = call->account()->codecModel()) { + const auto& videoCodecs = codecModel->videoCodecs(); + + for (int i=0; i < videoCodecs->rowCount();i++) { + const auto& idx = videoCodecs->index(i,0); + + if (ui->autoCheckBox->isChecked()) { + videoCodecs->setData(idx, "true", CodecModel::Role::AUTO_QUALITY_ENABLED); + } else { + auto min_bitrate = idx.data(static_cast<int>(CodecModel::Role::MIN_BITRATE)).toInt(); + auto max_bitrate = idx.data(static_cast<int>(CodecModel::Role::MAX_BITRATE)).toInt(); + auto min_quality = idx.data(static_cast<int>(CodecModel::Role::MIN_QUALITY)).toInt(); + auto max_quality = idx.data(static_cast<int>(CodecModel::Role::MAX_QUALITY)).toInt(); + + double bitrate; + bitrate = min_bitrate + (double)(max_bitrate - min_bitrate)*(ui->qualitySlider->value()/100.0); + if (bitrate < 0) bitrate = 0; + + double quality; + // note: a lower value means higher quality + quality = (double)min_quality - (min_quality - max_quality)*(ui->qualitySlider->value()/100.0); + if (quality < 0) quality = 0; + + videoCodecs->setData(idx, "false", CodecModel::Role::AUTO_QUALITY_ENABLED); + videoCodecs->setData(idx, QString::number((int)bitrate), CodecModel::Role::BITRATE); + videoCodecs->setData(idx, QString::number((int)quality), CodecModel::Role::QUALITY); + } + } + codecModel << CodecModel::EditAction::SAVE; + } +} diff --git a/qualitydialog.h b/qualitydialog.h new file mode 100644 index 0000000..17c4428 --- /dev/null +++ b/qualitydialog.h @@ -0,0 +1,45 @@ +/*************************************************************************** + * Copyright (C) 2016 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/>. * + **************************************************************************/ + +#pragma once + +#include <QDialog> + +namespace Ui { +class QualityDialog; +} + +class QualityDialog : public QDialog +{ + Q_OBJECT + +public: + explicit QualityDialog(QWidget *parent = 0); + ~QualityDialog(); + +protected: + void showEvent(QShowEvent* event); + +private slots: + void on_autoCheckBox_toggled(bool checked); + void on_qualitySlider_sliderReleased(); + +private: + Ui::QualityDialog *ui; + void setQuality(); +}; diff --git a/qualitydialog.ui b/qualitydialog.ui new file mode 100644 index 0000000..3c051e6 --- /dev/null +++ b/qualitydialog.ui @@ -0,0 +1,93 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>QualityDialog</class> + <widget class="QDialog" name="QualityDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>73</width> + <height>194</height> + </rect> + </property> + <property name="windowTitle"> + <string>Dialog</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>5</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QSlider" name="qualitySlider"> + <property name="maximum"> + <number>100</number> + </property> + <property name="value"> + <number>50</number> + </property> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <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> + <widget class="QCheckBox" name="autoCheckBox"> + <property name="text"> + <string>Auto</string> + </property> + </widget> + </item> + <item> + <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> + </property> + </spacer> + </item> + </layout> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/ressources.qrc b/ressources.qrc index 964548e..f3010b8 100644 --- a/ressources.qrc +++ b/ressources.qrc @@ -41,5 +41,6 @@ <file>images/video-conf/btn-transfer.svg</file> <file>images/btn-info.svg</file> <file>images/ic_arrow_back_white.svg</file> + <file>images/video-conf/ic_high_quality_white.svg</file> </qresource> </RCC> diff --git a/stylesheet.css b/stylesheet.css index a588c52..da4912b 100644 --- a/stylesheet.css +++ b/stylesheet.css @@ -119,3 +119,9 @@ QPushButton#imBackButton { border-radius: 15px; border:solid 1px; } + +QPushButton#qualityButton { + background-color: rgba(0, 0, 0, 140); + border-radius: 18px; + border:solid 1px; +} diff --git a/videooverlay.cpp b/videooverlay.cpp index 369f435..5d02898 100644 --- a/videooverlay.cpp +++ b/videooverlay.cpp @@ -24,7 +24,8 @@ VideoOverlay::VideoOverlay(QWidget* parent) : QWidget(parent), ui(new Ui::VideoOverlay), - transferDialog_(new CallUtilsDialog()) + transferDialog_(new CallUtilsDialog()), + qualityDialog_(new QualityDialog()) { ui->setupUi(this); @@ -35,6 +36,11 @@ VideoOverlay::VideoOverlay(QWidget* parent) : ui->noMicButton->setCheckable(true); + QPixmap pixmap(":/images/video-conf/ic_high_quality_white.svg"); + QIcon qualityIcon(pixmap); + ui->qualityButton->setIcon(qualityIcon); + ui->qualityButton->setIconSize(pixmap.rect().size()); + connect(actionModel_,&UserActionModel::dataChanged, [=](const QModelIndex& tl, const QModelIndex& br) { const int first(tl.row()),last(br.row()); for(int i = first; i <= last;i++) { @@ -85,6 +91,7 @@ VideoOverlay::~VideoOverlay() { delete ui; delete transferDialog_; + delete qualityDialog_; } void @@ -159,3 +166,14 @@ void VideoOverlay::on_joinButton_clicked() { CallModel::instance().selectedCall()->joinToParent(); } + +void +VideoOverlay::on_qualityButton_clicked() +{ + auto pos = this->mapToGlobal(ui->qualityButton->pos()); + qualityDialog_->move(pos.x() + - qualityDialog_->size().width()/2 + + ui->qualityButton->size().width()/2, + pos.y() - (qualityDialog_->height())); + qualityDialog_->show(); +} diff --git a/videooverlay.h b/videooverlay.h index 68d4980..322ad62 100644 --- a/videooverlay.h +++ b/videooverlay.h @@ -24,6 +24,7 @@ #include "useractionmodel.h" #include "callutilsdialog.h" +#include "qualitydialog.h" namespace Ui { class VideoOverlay; @@ -51,11 +52,13 @@ private slots: void on_joinButton_clicked(); void on_noMicButton_clicked(); void on_noVideoButton_clicked(); + void on_qualityButton_clicked(); private: Ui::VideoOverlay* ui; UserActionModel* actionModel_; CallUtilsDialog* transferDialog_; + QualityDialog* qualityDialog_; signals: void setChatVisibility(bool visible); diff --git a/videooverlay.ui b/videooverlay.ui index 81b97b1..9301b00 100644 --- a/videooverlay.ui +++ b/videooverlay.ui @@ -23,8 +23,27 @@ <string/> </property> <layout class="QGridLayout" name="gridLayout"> - <item row="0" column="10" alignment="Qt::AlignRight|Qt::AlignTop"> - <widget class="QLabel" name="timerLabel"> + <item row="1" column="1"> + <widget class="QPushButton" name="hangupButton"> + <property name="minimumSize"> + <size> + <width>36</width> + <height>36</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>36</width> + <height>36</height> + </size> + </property> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item row="0" column="0" alignment="Qt::AlignTop"> + <widget class="QLabel" name="nameLabel"> <property name="palette"> <palette> <active> @@ -63,12 +82,12 @@ </palette> </property> <property name="text"> - <string>00:00</string> + <string/> </property> </widget> </item> - <item row="1" column="5"> - <widget class="QPushButton" name="addPersonButton"> + <item row="1" column="6"> + <widget class="QPushButton" name="joinButton"> <property name="minimumSize"> <size> <width>36</width> @@ -86,14 +105,8 @@ </property> </widget> </item> - <item row="1" column="9"> - <widget class="QPushButton" name="noVideoButton"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> + <item row="1" column="2"> + <widget class="QPushButton" name="holdButton"> <property name="minimumSize"> <size> <width>36</width> @@ -114,27 +127,14 @@ </property> </widget> </item> - <item row="1" column="7"> - <widget class="QPushButton" name="transferButton"> - <property name="minimumSize"> - <size> - <width>36</width> - <height>36</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>36</width> - <height>36</height> - </size> - </property> - <property name="text"> - <string/> + <item row="1" column="8"> + <widget class="QPushButton" name="noMicButton"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> </property> - </widget> - </item> - <item row="1" column="2"> - <widget class="QPushButton" name="holdButton"> <property name="minimumSize"> <size> <width>36</width> @@ -174,8 +174,8 @@ </property> </widget> </item> - <item row="1" column="0"> - <spacer name="horizontalSpacer"> + <item row="1" column="11"> + <spacer name="horizontalSpacer_2"> <property name="orientation"> <enum>Qt::Horizontal</enum> </property> @@ -187,36 +187,8 @@ </property> </spacer> </item> - <item row="1" column="8"> - <widget class="QPushButton" name="noMicButton"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>36</width> - <height>36</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>36</width> - <height>36</height> - </size> - </property> - <property name="text"> - <string/> - </property> - <property name="checkable"> - <bool>true</bool> - </property> - </widget> - </item> - <item row="0" column="0" alignment="Qt::AlignTop"> - <widget class="QLabel" name="nameLabel"> + <item row="0" column="11" alignment="Qt::AlignRight|Qt::AlignTop"> + <widget class="QLabel" name="timerLabel"> <property name="palette"> <palette> <active> @@ -255,12 +227,18 @@ </palette> </property> <property name="text"> - <string/> + <string>00:00</string> </property> </widget> </item> - <item row="1" column="6"> - <widget class="QPushButton" name="joinButton"> + <item row="1" column="9"> + <widget class="QPushButton" name="noVideoButton"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> <property name="minimumSize"> <size> <width>36</width> @@ -276,10 +254,13 @@ <property name="text"> <string/> </property> + <property name="checkable"> + <bool>true</bool> + </property> </widget> </item> - <item row="1" column="10"> - <spacer name="horizontalSpacer_2"> + <item row="1" column="0"> + <spacer name="horizontalSpacer"> <property name="orientation"> <enum>Qt::Horizontal</enum> </property> @@ -291,8 +272,46 @@ </property> </spacer> </item> - <item row="1" column="1"> - <widget class="QPushButton" name="hangupButton"> + <item row="1" column="5"> + <widget class="QPushButton" name="addPersonButton"> + <property name="minimumSize"> + <size> + <width>36</width> + <height>36</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>36</width> + <height>36</height> + </size> + </property> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item row="1" column="7"> + <widget class="QPushButton" name="transferButton"> + <property name="minimumSize"> + <size> + <width>36</width> + <height>36</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>36</width> + <height>36</height> + </size> + </property> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item row="1" column="10"> + <widget class="QPushButton" name="qualityButton"> <property name="minimumSize"> <size> <width>36</width> -- GitLab