mirror of
https://git.jami.net/savoirfairelinux/jami-client-qt.git
synced 2025-08-04 06:45:45 +02:00
settings: add support for default and local moderators
- add configurable list of default moderators - add option for enabling local moderators - indicate when participant is locally muted on moderation overlay - small typo fixes Change-Id: I1669c903be3c3a3f2344f1d95d8b618e62b9d412
This commit is contained in:
parent
4a7c859197
commit
7450350348
27 changed files with 424 additions and 231 deletions
|
@ -138,6 +138,7 @@ unix {
|
|||
# Input
|
||||
HEADERS += \
|
||||
src/avatarimageprovider.h \
|
||||
src/moderatorlistmodel.h \
|
||||
src/networkmanager.h \
|
||||
src/smartlistmodel.h \
|
||||
src/updatemanager.h \
|
||||
|
@ -187,6 +188,7 @@ HEADERS += \
|
|||
SOURCES += \
|
||||
src/bannedlistmodel.cpp \
|
||||
src/accountlistmodel.cpp \
|
||||
src/moderatorlistmodel.cpp \
|
||||
src/networkmanager.cpp \
|
||||
src/runguard.cpp \
|
||||
src/updatemanager.cpp \
|
||||
|
|
3
qml.qrc
3
qml.qrc
|
@ -47,7 +47,7 @@
|
|||
<file>src/settingsview/components/PluginItemDelegate.qml</file>
|
||||
<file>src/mainview/components/MediaHandlerItemDelegate.qml</file>
|
||||
<file>src/commoncomponents/PreferenceItemDelegate.qml</file>
|
||||
<file>src/settingsview/components/BannedItemDelegate.qml</file>
|
||||
<file>src/settingsview/components/ContactItemDelegate.qml</file>
|
||||
<file>src/settingsview/components/MediaCodecDelegate.qml</file>
|
||||
<file>src/settingsview/components/NameRegistrationDialog.qml</file>
|
||||
<file>src/settingsview/components/LinkDeviceDialog.qml</file>
|
||||
|
@ -92,7 +92,6 @@
|
|||
<file>src/mainview/js/incomingcallpagecreation.js</file>
|
||||
<file>src/mainview/components/ContactSearchBar.qml</file>
|
||||
<file>src/mainview/components/VideoCallPage.qml</file>
|
||||
<file>src/mainview/components/CallAdvancedOptions.qml</file>
|
||||
<file>src/mainview/components/ParticipantOverlay.qml</file>
|
||||
<file>src/mainview/components/ProjectCreditsScrollView.qml</file>
|
||||
<file>src/mainview/components/AccountComboBoxPopup.qml</file>
|
||||
|
|
|
@ -356,18 +356,9 @@ AccountAdapter::connectAccount(const QString& accountId)
|
|||
|
||||
QObject::disconnect(accountStatusChangedConnection_);
|
||||
QObject::disconnect(contactAddedConnection_);
|
||||
QObject::disconnect(accountProfileChangedConnection_);
|
||||
QObject::disconnect(addedToConferenceConnection_);
|
||||
QObject::disconnect(contactUnbannedConnection_);
|
||||
|
||||
accountProfileChangedConnection_
|
||||
= QObject::connect(&LRCInstance::accountModel(),
|
||||
&lrc::api::NewAccountModel::profileUpdated,
|
||||
[this](const QString& accountId) {
|
||||
if (LRCInstance::getCurrAccId() == accountId)
|
||||
emit accountStatusChanged(accountId);
|
||||
});
|
||||
|
||||
accountStatusChangedConnection_
|
||||
= QObject::connect(accInfo.accountModel,
|
||||
&lrc::api::NewAccountModel::accountStatusChanged,
|
||||
|
|
|
@ -108,6 +108,7 @@ signals:
|
|||
* Trigger other components to reconnect account related signals.
|
||||
*/
|
||||
void accountStatusChanged(QString accountId = {});
|
||||
|
||||
void updateConversationForAddedContact();
|
||||
/*
|
||||
* send report failure to QML to make it show the right UI state .
|
||||
|
@ -144,7 +145,6 @@ private:
|
|||
QMetaObject::Connection accountStatusChangedConnection_;
|
||||
QMetaObject::Connection contactAddedConnection_;
|
||||
QMetaObject::Connection addedToConferenceConnection_;
|
||||
QMetaObject::Connection accountProfileChangedConnection_;
|
||||
QMetaObject::Connection contactUnbannedConnection_;
|
||||
QMetaObject::Connection registeredNameSavedConnection_;
|
||||
};
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
class AudioOutputDeviceModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
public:
|
||||
enum Role { Device_ID = Qt::UserRole + 1, ID_UTF8 };
|
||||
Q_ENUM(Role)
|
||||
|
|
|
@ -24,8 +24,6 @@
|
|||
class BannedListModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
BannedListModel(const BannedListModel& cpy);
|
||||
|
||||
public:
|
||||
enum Role { ContactName = Qt::UserRole + 1, ContactID };
|
||||
Q_ENUM(Role)
|
||||
|
|
|
@ -413,6 +413,14 @@ Item {
|
|||
property string maximizeParticipant: qsTr("Maximize")
|
||||
property string minimizeParticipant: qsTr("Minimize")
|
||||
property string hangupParticipant: qsTr("Hangup")
|
||||
property string localMuted: qsTr("local muted")
|
||||
|
||||
// Settings moderation
|
||||
property string conferenceModeration: qsTr("Conference moderation")
|
||||
property string defaultModerators: qsTr("Default moderators")
|
||||
property string enableLocalModerators: qsTr("Enable local moderators")
|
||||
property string addDefaultModerator: qsTr("Add default moderator")
|
||||
property string removeDefaultModerator: qsTr("Remove default moderator")
|
||||
|
||||
// Daemon reconnection
|
||||
property string reconnectDaemon: qsTr("Trying to reconnect to the Jami daemon (dring)…")
|
||||
|
|
|
@ -35,15 +35,31 @@ ContactAdapter::getContactSelectableModel(int type)
|
|||
* Called from qml every time contact picker refreshes.
|
||||
*/
|
||||
listModeltype_ = static_cast<SmartListModel::Type>(type);
|
||||
smartListModel_.reset(new SmartListModel(this, listModeltype_));
|
||||
|
||||
|
||||
if (listModeltype_ == SmartListModel::Type::CONVERSATION) {
|
||||
defaultModerators_ =
|
||||
LRCInstance::accountModel().getDefaultModerators(LRCInstance::getCurrAccId());
|
||||
smartListModel_.reset(new SmartListModel(this, listModeltype_));
|
||||
smartListModel_->fillConversationsList();
|
||||
} else {
|
||||
smartListModel_.reset(new SmartListModel(this, listModeltype_));
|
||||
}
|
||||
selectableProxyModel_->setSourceModel(smartListModel_.get());
|
||||
|
||||
/*
|
||||
* Adjust filter.
|
||||
*/
|
||||
switch (listModeltype_) {
|
||||
case SmartListModel::Type::CONVERSATION:
|
||||
selectableProxyModel_->setPredicate([this]
|
||||
(const QModelIndex& index, const QRegExp&) {
|
||||
return !defaultModerators_.contains(index.data(SmartListModel::URI).toString());
|
||||
});
|
||||
break;
|
||||
|
||||
case SmartListModel::Type::CONFERENCE:
|
||||
selectableProxyModel_->setPredicate([this](const QModelIndex& index, const QRegExp&) {
|
||||
selectableProxyModel_->setPredicate([](const QModelIndex& index, const QRegExp&) {
|
||||
return index.data(SmartListModel::Presence).toBool();
|
||||
});
|
||||
break;
|
||||
|
@ -77,9 +93,16 @@ ContactAdapter::setSearchFilter(const QString& filter)
|
|||
{
|
||||
if (listModeltype_ == SmartListModel::Type::CONFERENCE) {
|
||||
smartListModel_->setConferenceableFilter(filter);
|
||||
} else if (listModeltype_ == SmartListModel::Type::CONVERSATION) {
|
||||
selectableProxyModel_->setPredicate([this, filter](
|
||||
const QModelIndex& index,
|
||||
const QRegExp&) {
|
||||
return (!defaultModerators_.contains(index.data(SmartListModel::URI).toString())
|
||||
&& index.data(SmartListModel::DisplayName).toString().contains(filter));
|
||||
});
|
||||
}
|
||||
selectableProxyModel_->setFilterRegExp(
|
||||
QRegExp(filter, Qt::CaseInsensitive, QRegExp::FixedString));
|
||||
QRegExp(filter, Qt::CaseInsensitive, QRegExp::FixedString));
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -157,6 +180,17 @@ ContactAdapter::contactSelected(int index)
|
|||
callModel->hangUp(destCallId);
|
||||
}
|
||||
} break;
|
||||
case SmartListModel::Type::CONVERSATION: {
|
||||
const auto contactUri = contactIndex.data(SmartListModel::Role::URI).value<QString>();
|
||||
if (contactUri.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
LRCInstance::accountModel().setDefaultModerator(
|
||||
LRCInstance::getCurrAccId(), contactUri, true);
|
||||
emit defaultModeratorsUpdated();
|
||||
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -95,4 +95,10 @@ private:
|
|||
*/
|
||||
std::unique_ptr<SmartListModel> smartListModel_;
|
||||
std::unique_ptr<SelectableProxyModel> selectableProxyModel_;
|
||||
|
||||
QStringList defaultModerators_;
|
||||
|
||||
signals:
|
||||
void defaultModeratorsUpdated();
|
||||
|
||||
};
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
import QtQuick 2.14
|
||||
import QtQuick.Controls 2.14
|
||||
import QtQuick.Layouts 1.14
|
||||
import net.jami.Models 1.0 //Albert
|
||||
import net.jami.Models 1.0
|
||||
import net.jami.Adapters 1.0
|
||||
import net.jami.Constants 1.0
|
||||
|
||||
|
|
|
@ -1,141 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2020 by Savoir-faire Linux
|
||||
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
|
||||
* Author: Mingrui Zhang <mingrui.zhang@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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import QtQuick 2.14
|
||||
import QtQuick.Controls 2.14
|
||||
import QtQuick.Layouts 1.14
|
||||
import QtQuick.Controls.Universal 2.14
|
||||
import net.jami.Models 1.0
|
||||
import net.jami.Constants 1.0
|
||||
|
||||
import "../../commoncomponents"
|
||||
|
||||
Popup {
|
||||
id: contactPickerPopup
|
||||
|
||||
property int type: ContactPicker.ContactPickerType.JAMICONFERENCE
|
||||
|
||||
|
||||
// Important to keep it one, since enum in c++ starts at one for conferences.
|
||||
enum ContactPickerType {
|
||||
JAMICONFERENCE = 1,
|
||||
SIPTRANSFER
|
||||
}
|
||||
|
||||
contentWidth: 250
|
||||
contentHeight: contactPickerPopupRectColumnLayout.height + 50
|
||||
|
||||
padding: 0
|
||||
|
||||
modal: true
|
||||
|
||||
contentItem: Rectangle {
|
||||
id: contactPickerPopupRect
|
||||
|
||||
width: 250
|
||||
|
||||
PushButton {
|
||||
id: closeButton
|
||||
|
||||
anchors.top: contactPickerPopupRect.top
|
||||
anchors.topMargin: 5
|
||||
anchors.right: contactPickerPopupRect.right
|
||||
anchors.rightMargin: 5
|
||||
|
||||
source: "qrc:/images/icons/ic_close_black_24dp.png"
|
||||
|
||||
onClicked: {
|
||||
contactPickerPopup.close()
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: contactPickerPopupRectColumnLayout
|
||||
|
||||
anchors.top: contactPickerPopupRect.top
|
||||
anchors.topMargin: 15
|
||||
|
||||
Text {
|
||||
id: contactPickerTitle
|
||||
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
Layout.preferredWidth: contactPickerPopupRect.width
|
||||
Layout.preferredHeight: 30
|
||||
|
||||
font.pointSize: JamiTheme.textFontSize
|
||||
font.bold: true
|
||||
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
|
||||
text: type === ContactPicker.ContactPickerType.JAMICONFERENCE ? qsTr("Add to conference") : qsTr("Transfer this call")
|
||||
}
|
||||
|
||||
ContactSearchBar {
|
||||
id: contactPickerContactSearchBar
|
||||
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
Layout.topMargin: 5
|
||||
Layout.bottomMargin: 5
|
||||
Layout.preferredWidth: contactPickerPopupRect.width - 10
|
||||
Layout.preferredHeight: 35
|
||||
|
||||
onContactSearchBarTextChanged: {
|
||||
ContactAdapter.setSearchFilter(text)
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
contactPickerContactSearchBar.setPlaceholderString(
|
||||
qsTr("Search contacts"))
|
||||
}
|
||||
}
|
||||
|
||||
ListView {
|
||||
id: contactPickerListView
|
||||
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
Layout.preferredWidth: contactPickerPopupRect.width
|
||||
Layout.preferredHeight: 200
|
||||
|
||||
model: ContactAdapter.getContactSelectableModel(type)
|
||||
|
||||
clip: true
|
||||
|
||||
delegate: ContactPickerItemDelegate {
|
||||
id: contactPickerItemDelegate
|
||||
}
|
||||
|
||||
ScrollIndicator.vertical: ScrollIndicator {}
|
||||
}
|
||||
}
|
||||
|
||||
radius: 10
|
||||
color: "white"
|
||||
}
|
||||
|
||||
onAboutToShow: {
|
||||
// Reset the model on each show.
|
||||
contactPickerListView.model = ContactAdapter.getContactSelectableModel(
|
||||
type)
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
color: "transparent"
|
||||
}
|
||||
}
|
|
@ -440,8 +440,6 @@ Rectangle {
|
|||
ContactPickerCreation.createContactPickerObjects(
|
||||
ContactPicker.ContactPickerType.JAMICONFERENCE,
|
||||
callOverlayRect)
|
||||
ContactPickerCreation.calculateCurrentGeo(
|
||||
callOverlayRect.width / 2, callOverlayRect.height / 2)
|
||||
ContactPickerCreation.openContactPicker()
|
||||
}
|
||||
|
||||
|
@ -551,20 +549,6 @@ Rectangle {
|
|||
|
||||
color: "transparent"
|
||||
|
||||
onWidthChanged: {
|
||||
ContactPickerCreation.calculateCurrentGeo(callOverlayRect.width / 2,
|
||||
callOverlayRect.height / 2)
|
||||
MediaHandlerPickerCreation.calculateCurrentGeo(callOverlayRect.width / 2,
|
||||
callOverlayRect.height / 2)
|
||||
}
|
||||
|
||||
onHeightChanged: {
|
||||
ContactPickerCreation.calculateCurrentGeo(callOverlayRect.width / 2,
|
||||
callOverlayRect.height / 2)
|
||||
MediaHandlerPickerCreation.calculateCurrentGeo(callOverlayRect.width / 2,
|
||||
callOverlayRect.height / 2)
|
||||
}
|
||||
|
||||
CallViewContextMenu {
|
||||
id: callViewContextMenu
|
||||
|
||||
|
@ -573,16 +557,12 @@ Rectangle {
|
|||
ContactPickerCreation.createContactPickerObjects(
|
||||
ContactPicker.ContactPickerType.SIPTRANSFER,
|
||||
callOverlayRect)
|
||||
ContactPickerCreation.calculateCurrentGeo(
|
||||
callOverlayRect.width / 2, callOverlayRect.height / 2)
|
||||
ContactPickerCreation.openContactPicker()
|
||||
}
|
||||
|
||||
onPluginItemClicked: {
|
||||
// Create media handler picker - PLUGINS
|
||||
MediaHandlerPickerCreation.createMediaHandlerPickerObjects(callOverlayRect)
|
||||
MediaHandlerPickerCreation.calculateCurrentGeo(
|
||||
callOverlayRect.width / 2, callOverlayRect.height / 2)
|
||||
MediaHandlerPickerCreation.openMediaHandlerPicker()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,7 +33,8 @@ Popup {
|
|||
|
||||
// Important to keep it one, since enum in c++ starts at one for conferences.
|
||||
enum ContactPickerType {
|
||||
JAMICONFERENCE = 1,
|
||||
CONVERSATION = 0,
|
||||
JAMICONFERENCE,
|
||||
SIPTRANSFER
|
||||
}
|
||||
|
||||
|
@ -84,7 +85,16 @@ Popup {
|
|||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
|
||||
text: type === ContactPicker.ContactPickerType.JAMICONFERENCE ? qsTr("Add to conference") : qsTr("Transfer this call")
|
||||
text: {
|
||||
switch(type) {
|
||||
case ContactPicker.ContactPickerType.JAMICONFERENCE:
|
||||
return qsTr("Add to conference")
|
||||
case ContactPicker.ContactPickerType.SIPTRANSFER:
|
||||
return qsTr("Transfer this call")
|
||||
default:
|
||||
return qsTr("Add default moderator")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ContactSearchBar {
|
||||
|
@ -127,9 +137,8 @@ Popup {
|
|||
}
|
||||
|
||||
onAboutToShow: {
|
||||
// Reset the model on each show.
|
||||
contactPickerListView.model = ContactAdapter.getContactSelectableModel(
|
||||
type)
|
||||
contactPickerListView.model =
|
||||
ContactAdapter.getContactSelectableModel(type)
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
|
|
|
@ -70,12 +70,12 @@ Rectangle {
|
|||
overlayMenu.showUnsetModerator = isHost && !isLocal && participantIsModerator
|
||||
|
||||
var muteState = CallAdapter.getMuteState(overlayMenu.uri)
|
||||
var isLocalMuted = muteState === CallAdapter.LOCAL_MUTED
|
||||
overlayMenu.isLocalMuted = muteState === CallAdapter.LOCAL_MUTED
|
||||
|| muteState === CallAdapter.BOTH_MUTED
|
||||
var isModeratorMuted = muteState === CallAdapter.MODERATOR_MUTED
|
||||
|| muteState === CallAdapter.BOTH_MUTED
|
||||
|
||||
participantIsMuted = isLocalMuted || isModeratorMuted
|
||||
participantIsMuted = overlayMenu.isLocalMuted || isModeratorMuted
|
||||
|
||||
overlayMenu.showModeratorMute = isModerator && !isModeratorMuted
|
||||
overlayMenu.showModeratorUnmute = isModerator && isModeratorMuted
|
||||
|
|
|
@ -41,6 +41,7 @@ Rectangle {
|
|||
|
||||
property string uri: ""
|
||||
property string bestName: ""
|
||||
property bool isLocalMuted: false
|
||||
property bool showSetModerator: false
|
||||
property bool showUnsetModerator: false
|
||||
property bool showModeratorMute: false
|
||||
|
@ -150,7 +151,10 @@ Rectangle {
|
|||
: JamiTheme.whiteColor
|
||||
|
||||
onClicked: CallAdapter.muteParticipant(uri, showModeratorMute)
|
||||
onHoveredChanged: toggleParticipantToolTip.visible = hovered
|
||||
onHoveredChanged: {
|
||||
toggleParticipantToolTip.visible = hovered
|
||||
localMutedText.visible = hovered && isLocalMuted
|
||||
}
|
||||
|
||||
Text {
|
||||
id: toggleParticipantToolTip
|
||||
|
@ -167,6 +171,22 @@ Rectangle {
|
|||
color: JamiTheme.whiteColor
|
||||
font.pointSize: JamiTheme.tinyFontSize
|
||||
}
|
||||
|
||||
Text {
|
||||
id: localMutedText
|
||||
|
||||
visible: false
|
||||
width: parent.width
|
||||
text: "(" + JamiStrings.localMuted + ")"
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignTop
|
||||
|
||||
anchors.top: parent.bottom
|
||||
anchors.topMargin: 16
|
||||
color: JamiTheme.whiteColor
|
||||
font.pointSize: JamiTheme.tinyFontSize
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
PushButton {
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
/*
|
||||
* Copyright (C) 2020 by Savoir-faire Linux
|
||||
* Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com>
|
||||
|
@ -27,7 +26,6 @@ var contactPickerObject
|
|||
function createContactPickerObjects(type, parent) {
|
||||
if (contactPickerObject) {
|
||||
|
||||
|
||||
/*
|
||||
* If already created, reset parameters, since object cannot be destroyed.
|
||||
*/
|
||||
|
@ -49,23 +47,15 @@ function finishCreation(type, parent) {
|
|||
"type": type
|
||||
})
|
||||
if (contactPickerObject === null) {
|
||||
|
||||
|
||||
/*
|
||||
* Error Handling.
|
||||
*/
|
||||
console.log("Error creating object for contact picker")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Put contact picker in the middle of container.
|
||||
*/
|
||||
function calculateCurrentGeo(containerX, containerY) {
|
||||
if (contactPickerObject) {
|
||||
contactPickerObject.x = containerX - contactPickerObject.width / 2
|
||||
contactPickerObject.y = containerY - contactPickerObject.height / 2
|
||||
} else {
|
||||
contactPickerObject.x = Qt.binding(function(){
|
||||
return parent.width/2 - contactPickerObject.width / 2})
|
||||
contactPickerObject.y = Qt.binding(function(){
|
||||
return parent.height/2 - contactPickerObject.height / 2})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -47,17 +47,11 @@ function finishCreation(parent) {
|
|||
* Error Handling.
|
||||
*/
|
||||
console.log("Error creating object for mediahandler picker")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Put mediahandler picker in the middle of container.
|
||||
*/
|
||||
function calculateCurrentGeo(containerX, containerY) {
|
||||
if (mediahandlerPickerObject) {
|
||||
mediahandlerPickerObject.x = containerX - mediahandlerPickerObject.width / 2
|
||||
mediahandlerPickerObject.y = containerY - mediahandlerPickerObject.height / 2
|
||||
} else {
|
||||
mediahandlerPickerObject.x = Qt.binding(function(){
|
||||
return parent.width/2 - mediahandlerPickerObject.width / 2})
|
||||
mediahandlerPickerObject.y = Qt.binding(function(){
|
||||
return parent.height/2 - mediahandlerPickerObject.height / 2})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
116
src/moderatorlistmodel.cpp
Normal file
116
src/moderatorlistmodel.cpp
Normal file
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* Copyright (C) 2019-2020 by Savoir-faire Linux
|
||||
* Author: Albert Babí Oller <albert.babi@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 "moderatorlistmodel.h"
|
||||
#include "lrcinstance.h"
|
||||
|
||||
ModeratorListModel::ModeratorListModel(QObject* parent)
|
||||
: QAbstractListModel(parent)
|
||||
{}
|
||||
|
||||
ModeratorListModel::~ModeratorListModel() {}
|
||||
|
||||
int
|
||||
ModeratorListModel::rowCount(const QModelIndex& parent) const
|
||||
{
|
||||
if (!parent.isValid()) {
|
||||
return LRCInstance::accountModel().getDefaultModerators(
|
||||
LRCInstance::getCurrentAccountInfo().id).size();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ModeratorListModel::columnCount(const QModelIndex& parent) const
|
||||
{
|
||||
Q_UNUSED(parent);
|
||||
/*
|
||||
* Only need one column.
|
||||
*/
|
||||
return 1;
|
||||
}
|
||||
|
||||
QVariant
|
||||
ModeratorListModel::data(const QModelIndex& index, int role) const
|
||||
{
|
||||
QStringList list = LRCInstance::accountModel().getDefaultModerators(
|
||||
LRCInstance::getCurrAccId());
|
||||
if (!index.isValid() || list.size() <= index.row()) {
|
||||
return QVariant();
|
||||
}
|
||||
auto contactInfo = LRCInstance::getCurrentAccountInfo().contactModel->getContact(
|
||||
list.at(index.row()));
|
||||
|
||||
switch (role) {
|
||||
case Role::ContactName: {
|
||||
QString str = LRCInstance::getCurrentAccountInfo().contactModel->
|
||||
bestNameForContact(list.at(index.row()));
|
||||
return QVariant(str);
|
||||
}
|
||||
case Role::ContactID:
|
||||
return QVariant(contactInfo.profileInfo.uri);
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QHash<int, QByteArray>
|
||||
ModeratorListModel::roleNames() const
|
||||
{
|
||||
QHash<int, QByteArray> roles;
|
||||
roles[ContactName] = "ContactName";
|
||||
roles[ContactID] = "ContactID";
|
||||
return roles;
|
||||
}
|
||||
|
||||
QModelIndex
|
||||
ModeratorListModel::index(int row, int column, const QModelIndex& parent) const
|
||||
{
|
||||
Q_UNUSED(parent);
|
||||
if (column != 0) {
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
if (row >= 0 && row < rowCount()) {
|
||||
return createIndex(row, column);
|
||||
}
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
QModelIndex
|
||||
ModeratorListModel::parent(const QModelIndex& child) const
|
||||
{
|
||||
Q_UNUSED(child);
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
Qt::ItemFlags
|
||||
ModeratorListModel::flags(const QModelIndex& index) const
|
||||
{
|
||||
auto flags = QAbstractItemModel::flags(index) | Qt::ItemNeverHasChildren | Qt::ItemIsSelectable;
|
||||
if (!index.isValid()) {
|
||||
return QAbstractItemModel::flags(index);
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
void
|
||||
ModeratorListModel::reset()
|
||||
{
|
||||
beginResetModel();
|
||||
endResetModel();
|
||||
}
|
51
src/moderatorlistmodel.h
Normal file
51
src/moderatorlistmodel.h
Normal file
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright (C) 2019-2020 by Savoir-faire Linux
|
||||
* Author: Albert Babí Oller <albert.babi@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 <QAbstractListModel>
|
||||
|
||||
class ModeratorListModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum Role { ContactName = Qt::UserRole + 1, ContactID };
|
||||
Q_ENUM(Role)
|
||||
|
||||
explicit ModeratorListModel(QObject* parent = nullptr);
|
||||
~ModeratorListModel();
|
||||
|
||||
/*
|
||||
* QAbstractListModel override.
|
||||
*/
|
||||
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||
int columnCount(const QModelIndex& parent) const override;
|
||||
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
|
||||
/*
|
||||
* Override role name as access point in qml.
|
||||
*/
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
QModelIndex index(int row, int column = 0, const QModelIndex& parent = QModelIndex()) const;
|
||||
QModelIndex parent(const QModelIndex& child) const;
|
||||
Qt::ItemFlags flags(const QModelIndex& index) const;
|
||||
|
||||
/*
|
||||
* This function is to reset the model when there's new account added.
|
||||
*/
|
||||
Q_INVOKABLE void reset();
|
||||
};
|
|
@ -26,6 +26,7 @@
|
|||
#include "audiooutputdevicemodel.h"
|
||||
#include "avadapter.h"
|
||||
#include "bannedlistmodel.h"
|
||||
#include "moderatorlistmodel.h"
|
||||
#include "calladapter.h"
|
||||
#include "contactadapter.h"
|
||||
#include "conversationsadapter.h"
|
||||
|
@ -103,6 +104,7 @@ registerTypes()
|
|||
QML_REGISTERTYPE("net.jami.Models", MediaHandlerItemListModel, 1, 0);
|
||||
QML_REGISTERTYPE("net.jami.Models", PreferenceItemListModel, 1, 0);
|
||||
QML_REGISTERTYPE("net.jami.Models", BannedListModel, 1, 0);
|
||||
QML_REGISTERTYPE("net.jami.Models", ModeratorListModel, 1, 0);
|
||||
QML_REGISTERTYPE("net.jami.Models", MediaCodecListModel, 1, 0);
|
||||
QML_REGISTERTYPE("net.jami.Models", AccountsToMigrateListModel, 1, 0);
|
||||
QML_REGISTERTYPE("net.jami.Models", AudioInputDeviceModel, 1, 0);
|
||||
|
|
|
@ -1016,3 +1016,30 @@ SettingsAdapter::set_FilePrivateKey(QString text)
|
|||
confProps.TLS.privateKeyFile = text;
|
||||
LRCInstance::accountModel().setAccountConfig(LRCInstance::getCurrAccId(), confProps);
|
||||
}
|
||||
|
||||
void
|
||||
SettingsAdapter::setDefaultModerator(const QString& accountId,
|
||||
const QString& peerURI,
|
||||
const bool& state)
|
||||
{
|
||||
return LRCInstance::accountModel().setDefaultModerator(accountId, peerURI, state);
|
||||
}
|
||||
|
||||
QStringList
|
||||
SettingsAdapter::getDefaultModerators(const QString& accountId)
|
||||
{
|
||||
return LRCInstance::accountModel().getDefaultModerators(accountId);
|
||||
}
|
||||
|
||||
void
|
||||
SettingsAdapter::enableLocalModerators(const QString& accountId,
|
||||
const bool& isModEnabled)
|
||||
{
|
||||
return LRCInstance::accountModel().enableLocalModerators(accountId, isModEnabled);
|
||||
}
|
||||
|
||||
bool
|
||||
SettingsAdapter::isLocalModeratorsEnabled(const QString& accountId)
|
||||
{
|
||||
return LRCInstance::accountModel().isLocalModeratorsEnabled(accountId);
|
||||
}
|
||||
|
|
|
@ -227,5 +227,14 @@ public:
|
|||
Q_INVOKABLE void set_FileCACert(QString text);
|
||||
Q_INVOKABLE void set_FileUserCert(QString text);
|
||||
Q_INVOKABLE void set_FilePrivateKey(QString text);
|
||||
|
||||
Q_INVOKABLE void setDefaultModerator(const QString& accountID,
|
||||
const QString& peerURI,
|
||||
const bool& state);
|
||||
Q_INVOKABLE QStringList getDefaultModerators(const QString& accId);
|
||||
Q_INVOKABLE void enableLocalModerators(const QString& accountID,
|
||||
const bool& isModEnabled);
|
||||
Q_INVOKABLE bool isLocalModeratorsEnabled(const QString& accountId);
|
||||
|
||||
};
|
||||
Q_DECLARE_METATYPE(SettingsAdapter*)
|
||||
|
|
|
@ -27,6 +27,8 @@ import net.jami.Adapters 1.0
|
|||
import net.jami.Constants 1.0
|
||||
|
||||
import "components"
|
||||
import "../mainview/js/contactpickercreation.js" as ContactPickerCreation
|
||||
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/*
|
||||
* Copyright (C) 2020 by Savoir-faire Linux
|
||||
* Author: Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com>
|
||||
* Author: Albert Babí Oller <albert.babi@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
|
||||
|
@ -28,6 +29,8 @@ import net.jami.Adapters 1.0
|
|||
import net.jami.Constants 1.0
|
||||
|
||||
import "../../commoncomponents"
|
||||
import "../../mainview/components"
|
||||
import "../../mainview/js/contactpickercreation.js" as ContactPickerCreation
|
||||
|
||||
ColumnLayout {
|
||||
id: root
|
||||
|
@ -43,6 +46,7 @@ ColumnLayout {
|
|||
|
||||
btnRingtone.setEnabled(SettingsAdapter.getAccountConfig_Ringtone_RingtoneEnabled())
|
||||
btnRingtone.setText(UtilsAdapter.toFileInfoName(SettingsAdapter.getAccountConfig_Ringtone_RingtonePath()))
|
||||
updateAndShowModeratorsSlot()
|
||||
}
|
||||
|
||||
function changeRingtonePath(url) {
|
||||
|
@ -54,6 +58,21 @@ ColumnLayout {
|
|||
}
|
||||
}
|
||||
|
||||
function updateAndShowModeratorsSlot() {
|
||||
toggleLocalModerators.checked = SettingsAdapter.isLocalModeratorsEnabled(
|
||||
AccountAdapter.currentAccountId)
|
||||
moderatorListWidget.model.reset()
|
||||
moderatorListWidget.visible = (moderatorListWidget.model.rowCount() > 0)
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: ContactAdapter
|
||||
|
||||
function onDefaultModeratorsUpdated() {
|
||||
updateAndShowModeratorsSlot()
|
||||
}
|
||||
}
|
||||
|
||||
JamiFileDialog {
|
||||
id: ringtonePath_Dialog
|
||||
|
||||
|
@ -142,5 +161,78 @@ ColumnLayout {
|
|||
SettingsAdapter.setIsRendezVous(checked)
|
||||
}
|
||||
}
|
||||
|
||||
ToggleSwitch {
|
||||
id: toggleLocalModerators
|
||||
|
||||
labelText: JamiStrings.enableLocalModerators
|
||||
fontPointSize: JamiTheme.settingsFontSize
|
||||
|
||||
onSwitchToggled: SettingsAdapter.enableLocalModerators(
|
||||
AccountAdapter.currentAccountId, checked)
|
||||
}
|
||||
|
||||
ElidedTextLabel {
|
||||
Layout.fillWidth: true
|
||||
|
||||
eText: JamiStrings.defaultModerators
|
||||
fontSize: JamiTheme.settingsFontSize
|
||||
maxWidth: root.width - JamiTheme.preferredFieldHeight
|
||||
- JamiTheme.preferredMarginSize * 4
|
||||
}
|
||||
|
||||
ListViewJami {
|
||||
id: moderatorListWidget
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 160
|
||||
|
||||
model: ModeratorListModel {}
|
||||
|
||||
delegate: ContactItemDelegate {
|
||||
id: moderatorListDelegate
|
||||
|
||||
width: moderatorListWidget.width
|
||||
height: 74
|
||||
|
||||
contactName: ContactName
|
||||
contactID: ContactID
|
||||
|
||||
btnImgSource: "qrc:/images/icons/round-remove_circle-24px.svg"
|
||||
btnToolTip: JamiStrings.removeDefaultModerator
|
||||
|
||||
onClicked: moderatorListWidget.currentIndex = index
|
||||
onBtnContactClicked: {
|
||||
SettingsAdapter.setDefaultModerator(
|
||||
AccountAdapter.currentAccountId, contactID, false)
|
||||
updateAndShowModeratorsSlot()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MaterialButton {
|
||||
id: addDefaultModeratorPushButton
|
||||
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
Layout.preferredWidth: JamiTheme.preferredFieldWidth
|
||||
Layout.preferredHeight: JamiTheme.preferredFieldHeight
|
||||
|
||||
color: JamiTheme.buttonTintedBlack
|
||||
hoveredColor: JamiTheme.buttonTintedBlackHovered
|
||||
pressedColor: JamiTheme.buttonTintedBlackPressed
|
||||
outlined: true
|
||||
toolTipText: JamiStrings.addDefaultModerator
|
||||
|
||||
source: "qrc:/images/icons/round-add-24px.svg"
|
||||
|
||||
text: JamiStrings.addDefaultModerator
|
||||
|
||||
onClicked: {
|
||||
ContactPickerCreation.createContactPickerObjects(
|
||||
ContactPicker.ContactPickerType.CONVERSATION,
|
||||
mainView)
|
||||
ContactPickerCreation.openContactPicker()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ import net.jami.Constants 1.0
|
|||
import "../../commoncomponents"
|
||||
|
||||
ColumnLayout {
|
||||
id:root
|
||||
id: root
|
||||
|
||||
property bool isSIP
|
||||
|
||||
|
@ -120,18 +120,20 @@ ColumnLayout {
|
|||
|
||||
model: BannedListModel {}
|
||||
|
||||
delegate: BannedItemDelegate {
|
||||
delegate: ContactItemDelegate {
|
||||
id: bannedListDelegate
|
||||
|
||||
width: bannedListWidget.width
|
||||
height: 74
|
||||
|
||||
contactName : ContactName
|
||||
contactName: ContactName
|
||||
contactID: ContactID
|
||||
|
||||
onClicked: bannedListWidget.currentIndex = index
|
||||
btnImgSource: "qrc:/images/icons/round-remove_circle-24px.svg"
|
||||
btnToolTip: JamiStrings.reinstateContact
|
||||
|
||||
onBtnReAddContactClicked: unban(index)
|
||||
onClicked: bannedListWidget.currentIndex = index
|
||||
onBtnContactClicked: unban(index)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/*
|
||||
* Copyright (C) 2019-2020 by Savoir-faire Linux
|
||||
* Author: Yang Wang <yang.wang@savoirfairelinux.com>
|
||||
* Author: Yang Wang <yang.wang@savoirfairelinux.com>
|
||||
* Author: Albert Babí Oller <albert.babi@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
|
||||
|
@ -32,8 +33,10 @@ ItemDelegate {
|
|||
|
||||
property string contactName : ""
|
||||
property string contactID: ""
|
||||
property string btnImgSource: ""
|
||||
property string btnToolTip: ""
|
||||
|
||||
signal btnReAddContactClicked
|
||||
signal btnContactClicked
|
||||
|
||||
highlighted: ListView.isCurrentItem
|
||||
background: Rectangle {
|
||||
|
@ -74,7 +77,7 @@ ItemDelegate {
|
|||
radius: {
|
||||
var size = ((avatarImg.width <= avatarImg.height) ?
|
||||
avatarImg.width:avatarImg.height)
|
||||
return size /2
|
||||
return size / 2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -82,12 +85,12 @@ ItemDelegate {
|
|||
}
|
||||
}
|
||||
|
||||
ColumnLayout{
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
|
||||
Label{
|
||||
Label {
|
||||
id: labelContactName
|
||||
|
||||
Layout.fillWidth: true
|
||||
|
@ -104,7 +107,7 @@ ItemDelegate {
|
|||
color: JamiTheme.textColor
|
||||
}
|
||||
|
||||
Label{
|
||||
Label {
|
||||
id: labelContactId
|
||||
|
||||
Layout.fillWidth: true
|
||||
|
@ -124,21 +127,21 @@ ItemDelegate {
|
|||
}
|
||||
}
|
||||
|
||||
PushButton{
|
||||
id: btnReAddContact
|
||||
PushButton {
|
||||
id: btnContact
|
||||
|
||||
Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
|
||||
Layout.rightMargin: 16
|
||||
Layout.preferredWidth: JamiTheme.preferredFieldHeight
|
||||
Layout.preferredHeight: JamiTheme.preferredFieldHeight
|
||||
|
||||
source: "qrc:/images/icons/person_add-24px.svg"
|
||||
source: btnImgSource
|
||||
imageColor: JamiTheme.textColor
|
||||
normalColor: highlighted? JamiTheme.selectedColor : JamiTheme.editBackgroundColor
|
||||
|
||||
toolTipText: JamiStrings.reinstateContact
|
||||
toolTipText: btnToolTip
|
||||
|
||||
onClicked: btnReAddContactClicked()
|
||||
onClicked: btnContactClicked()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Copyright (C) 2020 by Savoir-faire Linux
|
||||
* Author: Yang Wang <yang.wang@savoirfairelinux.com>
|
||||
* Author: Albert Babí <yang.wang@savoirfairelinux.com>
|
||||
* Author: Albert Babí <albert.babi@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
|
||||
|
|
Loading…
Add table
Reference in a new issue