mirror of
https://git.jami.net/savoirfairelinux/jami-client-qt.git
synced 2025-09-10 12:03:18 +02:00
calloverlay: keep the recording action visible while recording
Gitlab: #411 Change-Id: Id987ad1b3c0c583425a53b85735ab7eb3f434036
This commit is contained in:
parent
2267c046d8
commit
378ab7cb93
4 changed files with 126 additions and 103 deletions
|
@ -1,6 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2021 by Savoir-faire Linux
|
* Copyright (C) 2021 by Savoir-faire Linux
|
||||||
* Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
|
* Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
|
||||||
|
* Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -22,70 +23,6 @@
|
||||||
#include <QMouseEvent>
|
#include <QMouseEvent>
|
||||||
#include <QQuickWindow>
|
#include <QQuickWindow>
|
||||||
|
|
||||||
CallControlListModel::CallControlListModel(QObject* parent)
|
|
||||||
: QAbstractListModel(parent)
|
|
||||||
{}
|
|
||||||
|
|
||||||
int
|
|
||||||
CallControlListModel::rowCount(const QModelIndex& parent) const
|
|
||||||
{
|
|
||||||
if (parent.isValid())
|
|
||||||
return 0;
|
|
||||||
return data_.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariant
|
|
||||||
CallControlListModel::data(const QModelIndex& index, int role) const
|
|
||||||
{
|
|
||||||
if (!index.isValid())
|
|
||||||
return QVariant();
|
|
||||||
|
|
||||||
using namespace CallControl;
|
|
||||||
auto item = data_.at(index.row());
|
|
||||||
|
|
||||||
switch (role) {
|
|
||||||
case Role::ItemAction:
|
|
||||||
return QVariant::fromValue(item.itemAction);
|
|
||||||
case Role::BadgeCount:
|
|
||||||
return QVariant::fromValue(item.badgeCount);
|
|
||||||
}
|
|
||||||
return QVariant();
|
|
||||||
}
|
|
||||||
|
|
||||||
QHash<int, QByteArray>
|
|
||||||
CallControlListModel::roleNames() const
|
|
||||||
{
|
|
||||||
using namespace CallControl;
|
|
||||||
QHash<int, QByteArray> roles;
|
|
||||||
roles[ItemAction] = "ItemAction";
|
|
||||||
roles[BadgeCount] = "BadgeCount";
|
|
||||||
return roles;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CallControlListModel::setBadgeCount(int row, int count)
|
|
||||||
{
|
|
||||||
if (row >= rowCount())
|
|
||||||
return;
|
|
||||||
data_[row].badgeCount = count;
|
|
||||||
auto idx = index(row, 0);
|
|
||||||
Q_EMIT dataChanged(idx, idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CallControlListModel::addItem(const CallControl::Item& item)
|
|
||||||
{
|
|
||||||
beginResetModel();
|
|
||||||
data_.append(item);
|
|
||||||
endResetModel();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CallControlListModel::clearData()
|
|
||||||
{
|
|
||||||
data_.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
IndexRangeFilterProxyModel::IndexRangeFilterProxyModel(QAbstractListModel* parent)
|
IndexRangeFilterProxyModel::IndexRangeFilterProxyModel(QAbstractListModel* parent)
|
||||||
: QSortFilterProxyModel(parent)
|
: QSortFilterProxyModel(parent)
|
||||||
{
|
{
|
||||||
|
@ -188,13 +125,13 @@ PendingConferenceesListModel::connectSignals()
|
||||||
disconnect(beginRemovePendingConferencesRows_);
|
disconnect(beginRemovePendingConferencesRows_);
|
||||||
disconnect(endRemovePendingConferencesRows_);
|
disconnect(endRemovePendingConferencesRows_);
|
||||||
|
|
||||||
|
using namespace PendingConferences;
|
||||||
callsStatusChanged_ = connect(lrcInstance_->getCurrentCallModel(),
|
callsStatusChanged_ = connect(lrcInstance_->getCurrentCallModel(),
|
||||||
&NewCallModel::callStatusChanged,
|
&NewCallModel::callStatusChanged,
|
||||||
this,
|
[this](const QString&, int) {
|
||||||
[this]() {
|
Q_EMIT dataChanged(index(0, 0),
|
||||||
dataChanged(index(0, 0),
|
index(rowCount() - 1),
|
||||||
index(rowCount() - 1),
|
{Role::CallStatus});
|
||||||
{PendingConferences::Role::CallStatus});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
beginInsertPendingConferencesRows_ = connect(
|
beginInsertPendingConferencesRows_ = connect(
|
||||||
|
@ -233,6 +170,77 @@ PendingConferenceesListModel::connectSignals()
|
||||||
endResetModel();
|
endResetModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CallControlListModel::CallControlListModel(QObject* parent)
|
||||||
|
: QAbstractListModel(parent)
|
||||||
|
{}
|
||||||
|
|
||||||
|
int
|
||||||
|
CallControlListModel::rowCount(const QModelIndex& parent) const
|
||||||
|
{
|
||||||
|
if (parent.isValid())
|
||||||
|
return 0;
|
||||||
|
return data_.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant
|
||||||
|
CallControlListModel::data(const QModelIndex& index, int role) const
|
||||||
|
{
|
||||||
|
if (!index.isValid())
|
||||||
|
return QVariant();
|
||||||
|
|
||||||
|
using namespace CallControl;
|
||||||
|
auto item = data_.at(index.row());
|
||||||
|
|
||||||
|
switch (role) {
|
||||||
|
case Role::ItemAction:
|
||||||
|
return QVariant::fromValue(item.itemAction);
|
||||||
|
case Role::UrgentCount:
|
||||||
|
return QVariant::fromValue(item.urgentCount);
|
||||||
|
}
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
QHash<int, QByteArray>
|
||||||
|
CallControlListModel::roleNames() const
|
||||||
|
{
|
||||||
|
using namespace CallControl;
|
||||||
|
QHash<int, QByteArray> roles;
|
||||||
|
roles[ItemAction] = "ItemAction";
|
||||||
|
roles[UrgentCount] = "UrgentCount";
|
||||||
|
return roles;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CallControlListModel::setUrgentCount(QVariant item, int count)
|
||||||
|
{
|
||||||
|
const auto* obj = item.value<QObject*>();
|
||||||
|
auto it = std::find_if(data_.cbegin(), data_.cend(), [obj](const auto& item) {
|
||||||
|
return item.itemAction == obj;
|
||||||
|
});
|
||||||
|
if (it != data_.cend()) {
|
||||||
|
auto row = std::distance(data_.cbegin(), it);
|
||||||
|
if (row >= rowCount())
|
||||||
|
return;
|
||||||
|
data_[row].urgentCount = count;
|
||||||
|
auto idx = index(row, 0);
|
||||||
|
Q_EMIT dataChanged(idx, idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CallControlListModel::addItem(const CallControl::Item& item)
|
||||||
|
{
|
||||||
|
beginResetModel();
|
||||||
|
data_.append(item);
|
||||||
|
endResetModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CallControlListModel::clearData()
|
||||||
|
{
|
||||||
|
data_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
CallOverlayModel::CallOverlayModel(LRCInstance* instance, QObject* parent)
|
CallOverlayModel::CallOverlayModel(LRCInstance* instance, QObject* parent)
|
||||||
: QObject(parent)
|
: QObject(parent)
|
||||||
, lrcInstance_(instance)
|
, lrcInstance_(instance)
|
||||||
|
@ -247,7 +255,7 @@ CallOverlayModel::CallOverlayModel(LRCInstance* instance, QObject* parent)
|
||||||
&CallOverlayModel::overflowIndexChanged,
|
&CallOverlayModel::overflowIndexChanged,
|
||||||
this,
|
this,
|
||||||
&CallOverlayModel::setControlRanges);
|
&CallOverlayModel::setControlRanges);
|
||||||
overflowVisibleModel_->setFilterRole(CallControl::Role::BadgeCount);
|
overflowVisibleModel_->setFilterRole(CallControl::Role::UrgentCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -264,9 +272,9 @@ CallOverlayModel::addSecondaryControl(const QVariant& action)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CallOverlayModel::setBadgeCount(int row, int count)
|
CallOverlayModel::setUrgentCount(QVariant row, int count)
|
||||||
{
|
{
|
||||||
secondaryModel_->setBadgeCount(row, count);
|
secondaryModel_->setUrgentCount(row, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant
|
QVariant
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2021 by Savoir-faire Linux
|
* Copyright (C) 2021 by Savoir-faire Linux
|
||||||
* Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
|
* Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
|
||||||
|
* Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -35,13 +36,13 @@
|
||||||
|
|
||||||
namespace CallControl {
|
namespace CallControl {
|
||||||
Q_NAMESPACE
|
Q_NAMESPACE
|
||||||
enum Role { ItemAction = Qt::UserRole + 1, BadgeCount };
|
enum Role { ItemAction = Qt::UserRole + 1, UrgentCount };
|
||||||
Q_ENUM_NS(Role)
|
Q_ENUM_NS(Role)
|
||||||
|
|
||||||
struct Item
|
struct Item
|
||||||
{
|
{
|
||||||
QObject* itemAction;
|
QObject* itemAction;
|
||||||
int badgeCount {0};
|
int urgentCount {0};
|
||||||
};
|
};
|
||||||
} // namespace CallControl
|
} // namespace CallControl
|
||||||
|
|
||||||
|
@ -56,24 +57,6 @@ enum Role {
|
||||||
Q_ENUM_NS(Role)
|
Q_ENUM_NS(Role)
|
||||||
} // namespace PendingConferences
|
} // namespace PendingConferences
|
||||||
|
|
||||||
class CallControlListModel : public QAbstractListModel
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
CallControlListModel(QObject* parent = nullptr);
|
|
||||||
|
|
||||||
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
|
|
||||||
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
|
|
||||||
QHash<int, QByteArray> roleNames() const override;
|
|
||||||
|
|
||||||
void setBadgeCount(int row, int count);
|
|
||||||
void addItem(const CallControl::Item& item);
|
|
||||||
void clearData();
|
|
||||||
|
|
||||||
private:
|
|
||||||
QList<CallControl::Item> data_;
|
|
||||||
};
|
|
||||||
|
|
||||||
class IndexRangeFilterProxyModel : public QSortFilterProxyModel
|
class IndexRangeFilterProxyModel : public QSortFilterProxyModel
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -112,6 +95,24 @@ private:
|
||||||
QMetaObject::Connection endRemovePendingConferencesRows_;
|
QMetaObject::Connection endRemovePendingConferencesRows_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class CallControlListModel : public QAbstractListModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
CallControlListModel(QObject* parent = nullptr);
|
||||||
|
|
||||||
|
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||||
|
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
|
||||||
|
QHash<int, QByteArray> roleNames() const override;
|
||||||
|
|
||||||
|
void setUrgentCount(QVariant item, int count);
|
||||||
|
void addItem(const CallControl::Item& item);
|
||||||
|
void clearData();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QList<CallControl::Item> data_;
|
||||||
|
};
|
||||||
|
|
||||||
class CallOverlayModel : public QObject
|
class CallOverlayModel : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -122,7 +123,7 @@ public:
|
||||||
|
|
||||||
Q_INVOKABLE void addPrimaryControl(const QVariant& action);
|
Q_INVOKABLE void addPrimaryControl(const QVariant& action);
|
||||||
Q_INVOKABLE void addSecondaryControl(const QVariant& action);
|
Q_INVOKABLE void addSecondaryControl(const QVariant& action);
|
||||||
Q_INVOKABLE void setBadgeCount(int row, int count);
|
Q_INVOKABLE void setUrgentCount(QVariant item, int count);
|
||||||
Q_INVOKABLE void clearControls();
|
Q_INVOKABLE void clearControls();
|
||||||
|
|
||||||
Q_INVOKABLE QVariant primaryModel();
|
Q_INVOKABLE QVariant primaryModel();
|
||||||
|
|
|
@ -210,6 +210,10 @@ Control {
|
||||||
text: !checked ? JamiStrings.startRec : JamiStrings.stopRec
|
text: !checked ? JamiStrings.startRec : JamiStrings.stopRec
|
||||||
property bool blinksWhenChecked: true
|
property bool blinksWhenChecked: true
|
||||||
property real size: 28
|
property real size: 28
|
||||||
|
onCheckedChanged: {
|
||||||
|
CallOverlayModel.setUrgentCount(recordAction,
|
||||||
|
checked ? -1 : 0)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
Action {
|
Action {
|
||||||
id: pluginsAction
|
id: pluginsAction
|
||||||
|
@ -345,9 +349,10 @@ Control {
|
||||||
"#80777777" :
|
"#80777777" :
|
||||||
"#80444444"
|
"#80444444"
|
||||||
type: {
|
type: {
|
||||||
if ((overflowItemListView.count &&
|
if (overflowItemListView.count ||
|
||||||
!urgentOverflowListView.count) ||
|
urgentOverflowListView.count ||
|
||||||
overflowHiddenListView.count) {
|
(overflowHiddenListView.count &&
|
||||||
|
overflowButton.popup.visible)) {
|
||||||
return HalfPill.None
|
return HalfPill.None
|
||||||
} else {
|
} else {
|
||||||
return HalfPill.Left
|
return HalfPill.Left
|
||||||
|
@ -370,7 +375,10 @@ Control {
|
||||||
|
|
||||||
spacing: itemSpacing
|
spacing: itemSpacing
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
model: CallOverlayModel.overflowVisibleModel()
|
model: !overflowButton.popup.visible ?
|
||||||
|
CallOverlayModel.overflowVisibleModel() :
|
||||||
|
null
|
||||||
|
|
||||||
delegate: buttonDelegate
|
delegate: buttonDelegate
|
||||||
ScrollIndicator.vertical: ScrollIndicator {}
|
ScrollIndicator.vertical: ScrollIndicator {}
|
||||||
|
|
||||||
|
|
|
@ -115,13 +115,15 @@ ItemDelegate {
|
||||||
|
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
horizontalAlignment: Text.AlignHCenter
|
horizontalAlignment: Text.AlignHCenter
|
||||||
source: ItemAction.icon.source
|
source: ItemAction ? ItemAction.icon.source : ""
|
||||||
color: ItemAction.icon.color
|
color: ItemAction ? ItemAction.icon.color : null
|
||||||
|
|
||||||
SequentialAnimation on opacity {
|
SequentialAnimation on opacity {
|
||||||
loops: Animation.Infinite
|
loops: Animation.Infinite
|
||||||
running: ItemAction.blinksWhenChecked !== undefined &&
|
running: ItemAction !== undefined &&
|
||||||
|
ItemAction.blinksWhenChecked !== undefined &&
|
||||||
ItemAction.blinksWhenChecked && checked
|
ItemAction.blinksWhenChecked && checked
|
||||||
|
onStopped: icon.opacity = 1
|
||||||
NumberAnimation { from: 1; to: 0; duration: JamiTheme.recordBlinkDuration }
|
NumberAnimation { from: 1; to: 0; duration: JamiTheme.recordBlinkDuration }
|
||||||
NumberAnimation { from: 0; to: 1; duration: JamiTheme.recordBlinkDuration }
|
NumberAnimation { from: 0; to: 1; duration: JamiTheme.recordBlinkDuration }
|
||||||
}
|
}
|
||||||
|
@ -142,7 +144,9 @@ ItemDelegate {
|
||||||
id: toolTip
|
id: toolTip
|
||||||
parent: parent
|
parent: parent
|
||||||
visible: text.length > 0 && (wrapper.hovered || menu.hovered)
|
visible: text.length > 0 && (wrapper.hovered || menu.hovered)
|
||||||
text: menu.hovered ? menuAction.text : ItemAction.text
|
text: menu.hovered ?
|
||||||
|
menuAction.text :
|
||||||
|
(ItemAction !== undefined ? ItemAction.text : null)
|
||||||
verticalPadding: 1
|
verticalPadding: 1
|
||||||
font.pointSize: 9
|
font.pointSize: 9
|
||||||
}
|
}
|
||||||
|
@ -155,7 +159,7 @@ ItemDelegate {
|
||||||
|
|
||||||
indicator: null
|
indicator: null
|
||||||
|
|
||||||
visible: menuAction !== undefined && !BadgeCount
|
visible: menuAction !== undefined && !UrgentCount
|
||||||
|
|
||||||
y: isVertical ? 0 : -4
|
y: isVertical ? 0 : -4
|
||||||
x: isVertical ? -4 : 0
|
x: isVertical ? -4 : 0
|
||||||
|
@ -256,6 +260,7 @@ ItemDelegate {
|
||||||
property real menuItemWidth: 0
|
property real menuItemWidth: 0
|
||||||
property real menuItemHeight: 39
|
property real menuItemHeight: 39
|
||||||
|
|
||||||
|
pixelAligned: true
|
||||||
orientation: ListView.Vertical
|
orientation: ListView.Vertical
|
||||||
implicitWidth: menuItemWidth
|
implicitWidth: menuItemWidth
|
||||||
implicitHeight: Math.min(contentHeight,
|
implicitHeight: Math.min(contentHeight,
|
||||||
|
@ -306,7 +311,8 @@ ItemDelegate {
|
||||||
BadgeNotifier {
|
BadgeNotifier {
|
||||||
id: badge
|
id: badge
|
||||||
|
|
||||||
count: BadgeCount
|
visible: count > 0
|
||||||
|
count: UrgentCount
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
width: 18
|
width: 18
|
||||||
height: width
|
height: width
|
||||||
|
|
Loading…
Add table
Reference in a new issue