This commit is contained in:
Julien Wadel 2021-08-05 17:29:35 +02:00
parent 768ee18942
commit c1855d07a4
19 changed files with 131 additions and 61 deletions

View file

@ -26,6 +26,7 @@ on run argv
set the bounds to { 300, 100, 1000, 520 }
set position of item "@APPLICATION_NAME@.app" to { 200, 280 }
set position of item "Applications" to { 500, 280 }
set position of item "include" to { 200, 1000 }
end tell
update without registering applications
delay 1

View file

@ -62,7 +62,8 @@
<file>assets/images/cancel_pressed.svg</file>
<file>assets/images/chat_amount.svg</file>
<file>assets/images/chat_count.svg</file>
<file>assets/images/chat_delivered.svg</file>
<file>assets/images/chat_disabled.svg</file>
<file>assets/images/chat_delivered.svg</file>
<file>assets/images/chat_error.svg</file>
<file>assets/images/chat_hovered.svg</file>
<file>assets/images/chat_is_composing_0.svg</file>

View file

@ -316,7 +316,7 @@ QVariantMap CallsListModel::createChatRoom(const QString& subject, const int& se
params->setEncryptionBackend(linphone::ChatRoomEncryptionBackend::Lime);
}else
params->setBackend(linphone::ChatRoomBackend::Basic);
params->enableGroup(subject != "");
params->enableGroup(chatRoomParticipants.size() > 1);
if(chatRoomParticipants.size() > 0) {

View file

@ -57,8 +57,16 @@ protected:
QModelIndex index = sourceModel()->index(sourceRow, 0, QModelIndex());
const QVariantMap data = index.data().toMap();
return (data["type"].toInt() & mEntryTypeFilter) > 0;
auto eventModel = sourceModel()->data(index);
if( mEntryTypeFilter == ChatRoomModel::EntryType::CallEntry && eventModel.value<ChatCallModel*>() != nullptr)
return true;
if( mEntryTypeFilter == ChatRoomModel::EntryType::MessageEntry && eventModel.value<ChatMessageModel*>() != nullptr)
return true;
if( mEntryTypeFilter == ChatRoomModel::EntryType::NoticeEntry && eventModel.value<ChatNoticeModel*>() != nullptr)
return true;
return false;
}
private:

View file

@ -47,7 +47,7 @@ ParticipantListModel::ParticipantListModel (ChatRoomModel * chatRoomModel, QObje
connect(mChatRoomModel, &ChatRoomModel::participantAdminStatusChanged, this, &ParticipantListModel::onParticipantAdminStatusChanged);
connect(mChatRoomModel, &ChatRoomModel::participantRegistrationSubscriptionRequested, this, &ParticipantListModel::onParticipantRegistrationSubscriptionRequested);
connect(mChatRoomModel, &ChatRoomModel::participantRegistrationUnsubscriptionRequested, this, &ParticipantListModel::onParticipantRegistrationUnsubscriptionRequested);
updateParticipants();
}
}
@ -66,6 +66,10 @@ ChatRoomModel *ParticipantListModel::getChatRoomModel() const{
return mChatRoomModel;
}
int ParticipantListModel::getCount() const{
return mParticipants.size();
}
QString ParticipantListModel::addressesToString()const{
QStringList txt;
for(auto participant : mParticipants){
@ -112,25 +116,25 @@ bool ParticipantListModel::contains(const QString& address) const{
//----------------------------------------------------------------------------
int ParticipantListModel::rowCount (const QModelIndex &) const {
return mParticipants.count();
return mParticipants.count();
}
QHash<int, QByteArray> ParticipantListModel::roleNames () const {
QHash<int, QByteArray> roles;
roles[Qt::DisplayRole] = "$participant";
return roles;
QHash<int, QByteArray> roles;
roles[Qt::DisplayRole] = "$participant";
return roles;
}
QVariant ParticipantListModel::data (const QModelIndex &index, int role) const {
int row = index.row();
if (!index.isValid() || row < 0 || row >= mParticipants.count())
return QVariant();
if (role == Qt::DisplayRole)
return QVariant::fromValue(mParticipants[row].get());
return QVariant();
int row = index.row();
if (!index.isValid() || row < 0 || row >= mParticipants.count())
return QVariant();
if (role == Qt::DisplayRole)
return QVariant::fromValue(mParticipants[row].get());
return QVariant();
}
// -----------------------------------------------------------------------------
@ -140,24 +144,24 @@ QVariant ParticipantListModel::data (const QModelIndex &index, int role) const {
// -----------------------------------------------------------------------------
bool ParticipantListModel::removeRow (int row, const QModelIndex &parent) {
return removeRows(row, 1, parent);
return removeRows(row, 1, parent);
}
bool ParticipantListModel::removeRows (int row, int count, const QModelIndex &parent) {
int limit = row + count - 1;
if (row < 0 || count < 0 || limit >= mParticipants.count())
return false;
beginRemoveRows(parent, row, limit);
for (int i = 0; i < count; ++i){
mParticipants.takeAt(row);
}
endRemoveRows();
return true;
int limit = row + count - 1;
if (row < 0 || count < 0 || limit >= mParticipants.count())
return false;
beginRemoveRows(parent, row, limit);
for (int i = 0; i < count; ++i){
mParticipants.takeAt(row);
}
endRemoveRows();
emit countChanged();
return true;
}
@ -165,21 +169,21 @@ bool ParticipantListModel::removeRows (int row, int count, const QModelIndex &pa
void ParticipantListModel::updateParticipants () {
if( mChatRoomModel) {
bool changed = false;
bool changed = false;
CoreManager *coreManager = CoreManager::getInstance();
auto dbParticipants = mChatRoomModel->getChatRoom()->getParticipants();
auto me = mChatRoomModel->getChatRoom()->getMe();
dbParticipants.push_front(me);
//Remove left participants
//Remove left participants
//for(auto participant : mParticipants){
auto itParticipant = mParticipants.begin();
while(itParticipant != mParticipants.end()) {
auto itDbParticipant = dbParticipants.begin();
while(itDbParticipant != dbParticipants.end()
&& ((*itParticipant)->getParticipant() && !(*itDbParticipant)->getAddress()->weakEqual((*itParticipant)->getParticipant()->getAddress())
|| !(*itParticipant)->getParticipant() && !(*itDbParticipant)->getAddress()->weakEqual(Utils::interpretUrl((*itParticipant)->getSipAddress()))
)
|| !(*itParticipant)->getParticipant() && !(*itDbParticipant)->getAddress()->weakEqual(Utils::interpretUrl((*itParticipant)->getSipAddress()))
)
){
++itDbParticipant;
}
@ -192,14 +196,14 @@ void ParticipantListModel::updateParticipants () {
}else
++itParticipant;
}
// Add new
// Add new
for(auto dbParticipant : dbParticipants){
auto itParticipant = mParticipants.begin();
while(itParticipant != mParticipants.end() && ( (*itParticipant)->getParticipant() && !dbParticipant->getAddress()->weakEqual((*itParticipant)->getParticipant()->getAddress())
|| (!(*itParticipant)->getParticipant() && !dbParticipant->getAddress()->weakEqual(Utils::interpretUrl((*itParticipant)->getSipAddress())))
)
){
|| (!(*itParticipant)->getParticipant() && !dbParticipant->getAddress()->weakEqual(Utils::interpretUrl((*itParticipant)->getSipAddress())))
)
){
++itParticipant;
}
if( itParticipant == mParticipants.end()){
@ -216,8 +220,10 @@ void ParticipantListModel::updateParticipants () {
(*itParticipant)->setParticipant(dbParticipant);
}
}
if( changed)
if( changed){
emit participantsChanged();
emit countChanged();
}
}
}
@ -228,6 +234,7 @@ void ParticipantListModel::add (std::shared_ptr<ParticipantModel> participant){
endInsertRows();
resetInternalData();
emit participantsChanged();
emit countChanged();
}
void ParticipantListModel::remove (ParticipantModel *model) {
@ -248,6 +255,7 @@ void ParticipantListModel::remove (ParticipantModel *model) {
mParticipants.erase(itParticipant);
endRemoveRows();
emit participantsChanged();
emit countChanged();
}
}
@ -280,7 +288,7 @@ void ParticipantListModel::onSecurityEvent(const std::shared_ptr<linphone::ChatR
}
}else{
address = eventLog->getDeviceAddress();
// Looping on all participant ensure to get all devices. Can be optimized if Device address is unique : Gain 2n operations.
// Looping on all participant ensure to get all devices. Can be optimized if Device address is unique : Gain 2n operations.
if(address)
emit deviceSecurityLevelChanged(address);
}

View file

@ -34,6 +34,7 @@ public:
virtual ~ParticipantListModel();
Q_PROPERTY(ChatRoomModel* chatRoomModel READ getChatRoomModel CONSTANT)
Q_PROPERTY(int count READ getCount NOTIFY countChanged)
void reset();
void update();
@ -51,6 +52,7 @@ public:
// Remove a chatroom
Q_INVOKABLE void remove (ParticipantModel *importer);
Q_INVOKABLE ChatRoomModel* getChatRoomModel() const;
int getCount() const;
Q_INVOKABLE QString addressesToString()const;
Q_INVOKABLE QString displayNamesToString()const;
@ -77,6 +79,7 @@ signals:
void securityLevelChanged();
void deviceSecurityLevelChanged(std::shared_ptr<const linphone::Address> device);
void participantsChanged();
void countChanged();
private:
bool removeRow (int row, const QModelIndex &parent = QModelIndex());

View file

@ -61,7 +61,7 @@ QVariantList ParticipantProxyModel::getParticipants() const{
return participants;
}
int ParticipantProxyModel::count(){
int ParticipantProxyModel::getCount() const{
return dynamic_cast<ParticipantListModel*>(sourceModel())->rowCount();
}
@ -88,6 +88,7 @@ void ParticipantProxyModel::add(const QString& address){
participantsModel->add(participant);
if(mChatRoomModel && mChatRoomModel->getChatRoom())// Invite and wait for its creation
mChatRoomModel->getChatRoom()->addParticipant(Utils::interpretUrl(address));
emit countChanged();
}
}
@ -99,6 +100,7 @@ void ParticipantProxyModel::remove(ParticipantModel * participant){
}else if(mChatRoomModel->getChatRoom() && participant->getParticipant() )
mChatRoomModel->getChatRoom()->removeParticipant(participant->getParticipant());
//dynamic_cast<ParticipantListModel*>(sourceModel())->remove(participant);
emit countChanged();
}
}

View file

@ -40,6 +40,7 @@ public:
ParticipantProxyModel ( QObject *parent = Q_NULLPTR);
Q_PROPERTY(ChatRoomModel* chatRoomModel READ getChatRoomModel WRITE setChatRoomModel NOTIFY chatRoomModelChanged)
Q_PROPERTY(int count READ getCount NOTIFY countChanged)
bool filterAcceptsRow (int sourceRow, const QModelIndex &sourceParent) const override;
bool lessThan (const QModelIndex &left, const QModelIndex &right) const override;
@ -47,7 +48,7 @@ public:
ChatRoomModel *getChatRoomModel() const;
Q_INVOKABLE QStringList getSipAddresses() const;
Q_INVOKABLE QVariantList getParticipants() const;
Q_INVOKABLE int count();
Q_INVOKABLE int getCount() const;
void setChatRoomModel(ChatRoomModel * chatRoomModel);
@ -58,6 +59,7 @@ public:
signals:
void chatRoomModelChanged();
void countChanged();
private:
/*

View file

@ -169,6 +169,12 @@ QVariantMap AccountSettingsModel::getProxyConfigDescription (const shared_ptr<li
return map;
}
QString AccountSettingsModel::getConferenceURI() const{
shared_ptr<linphone::Core> core = CoreManager::getInstance()->getCore();
shared_ptr<linphone::ProxyConfig> proxyConfig = core->getDefaultProxyConfig();
return proxyConfig ? Utils::coreStringToAppString(proxyConfig->getConferenceFactoryUri()) : "";
}
void AccountSettingsModel::setDefaultProxyConfig (const shared_ptr<linphone::ProxyConfig> &proxyConfig) {
shared_ptr<linphone::Core> core = CoreManager::getInstance()->getCore();
if (core->getDefaultProxyConfig() != proxyConfig) {

View file

@ -37,6 +37,8 @@ class AccountSettingsModel : public QObject {
Q_PROPERTY(QString sipAddress READ getUsedSipAddressAsStringUriOnly NOTIFY accountSettingsUpdated);
Q_PROPERTY(QString fullSipAddress READ getUsedSipAddressAsString);
Q_PROPERTY(RegistrationState registrationState READ getRegistrationState NOTIFY accountSettingsUpdated);
Q_PROPERTY(QString conferenceURI READ getConferenceURI NOTIFY accountSettingsUpdated)
// Default info.
Q_PROPERTY(QString primaryDisplayName READ getPrimaryDisplayName WRITE setPrimaryDisplayName NOTIFY accountSettingsUpdated);
@ -65,6 +67,7 @@ public:
bool addOrUpdateProxyConfig (const std::shared_ptr<linphone::ProxyConfig> &proxyConfig);
Q_INVOKABLE QVariantMap getProxyConfigDescription (const std::shared_ptr<linphone::ProxyConfig> &proxyConfig);
QString getConferenceURI() const;
Q_INVOKABLE void setDefaultProxyConfig (const std::shared_ptr<linphone::ProxyConfig> &proxyConfig = nullptr);
Q_INVOKABLE void setDefaultProxyConfigFromSipAddress (const QString &sipAddress);

View file

@ -19,6 +19,7 @@
*/
#include "components/core/CoreManager.hpp"
#include "components/participant/ParticipantListModel.hpp"
#include "components/settings/AccountSettingsModel.hpp"
#include "components/sip-addresses/SipAddressesModel.hpp"
#include "utils/Utils.hpp"
@ -104,15 +105,15 @@ bool TimelineProxyModel::filterAcceptsRow (int sourceRow, const QModelIndex &sou
auto timeline = sourceModel()->data(index).value<TimelineModel*>();
bool show = (mFilterFlags==0);// Show all at 0 (no hide all)
auto currentAddress = Utils::interpretUrl(CoreManager::getInstance()->getAccountSettingsModel()->getUsedSipAddressAsStringUriOnly());
bool isGroup = timeline->getChatRoomModel()->isGroupEnabled() && timeline->getChatRoomModel()->getParticipants()->getCount() > 2;
if( !show && ( (mFilterFlags & TimelineFilter::SimpleChatRoom) == TimelineFilter::SimpleChatRoom))
show = !timeline->getChatRoomModel()->isGroupEnabled() && !timeline->getChatRoomModel()->haveEncryption();
show = !isGroup && !timeline->getChatRoomModel()->haveEncryption();
if( !show && ( (mFilterFlags & TimelineFilter::SecureChatRoom) == TimelineFilter::SecureChatRoom))
show = !timeline->getChatRoomModel()->isGroupEnabled() && timeline->getChatRoomModel()->haveEncryption();
show = !isGroup && timeline->getChatRoomModel()->haveEncryption();
if( !show && ( (mFilterFlags & TimelineFilter::GroupChatRoom) == TimelineFilter::GroupChatRoom))
show = timeline->getChatRoomModel()->isGroupEnabled() && !timeline->getChatRoomModel()->haveEncryption();
show = isGroup && !timeline->getChatRoomModel()->haveEncryption();
if( !show && ( (mFilterFlags & TimelineFilter::SecureGroupChatRoom) == TimelineFilter::SecureGroupChatRoom))
show = timeline->getChatRoomModel()->isGroupEnabled() && timeline->getChatRoomModel()->haveEncryption();
show = isGroup && timeline->getChatRoomModel()->haveEncryption();
if( !show && ( (mFilterFlags & TimelineFilter::EphemeralChatRoom) == TimelineFilter::EphemeralChatRoom))
show = timeline->getChatRoomModel()->isEphemeralEnabled();
if(show && mFilterText != ""){

View file

@ -12,6 +12,7 @@ MouseArea {
property int delay: TooltipStyle.delay
property bool force: false
property var tooltipParent: parent
property int maxWidth : tooltipParent.width
property bool _visible: false
property int hoveringCursor : Qt.PointingHandCursor
@ -36,7 +37,7 @@ MouseArea {
delay: tooltipArea.delay
parent: tooltipParent
visible: _visible || force
width: Math.min(tooltip.implicitWidth, Math.max(tooltipParent.width, TooltipStyle.minWidth))
width: Math.min(tooltip.implicitWidth, Math.max(tooltipArea.maxWidth, TooltipStyle.minWidth))
//tooltipParent.width>TooltipStyle.minWidth?tooltipParent.width:TooltipStyle.minWidth

View file

@ -98,7 +98,7 @@ Rectangle {
icon:'chat_room'
iconSize: ContactStyle.contentHeight
visible: entry!=undefined && entry.groupEnabled != undefined && entry.groupEnabled
visible: entry!=undefined && entry.groupEnabled != undefined && entry.groupEnabled && entry.participants.count > 2
Icon{
anchors.right: parent.right

View file

@ -85,7 +85,7 @@ SearchBox {
}, {
icon: SettingsModel.chatEnabled && SettingsModel.getShowStartChatButton() ? 'chat' : 'history',
secure:1,
visible:SettingsModel.chatEnabled && SettingsModel.getShowStartChatButton(),
visible:SettingsModel.chatEnabled && SettingsModel.getShowStartChatButton() && AccountSettingsModel.conferenceURI != '',
handler: function (entry) {
searchBox.closeMenu()
searchBox.launchSecureChat(entry.sipAddress)

View file

@ -54,8 +54,8 @@ function openCallSipAddress () {
window.attachVirtualWindow(Qt.resolvedUrl('Dialogs/CallSipAddress.qml'))
}
function openConferenceManager (params) {
window.attachVirtualWindow(Qt.resolvedUrl('Dialogs/ConferenceManager.qml'), params)
function openConferenceManager (params, exitHandler) {
window.attachVirtualWindow(Qt.resolvedUrl('Dialogs/ConferenceManager.qml'), params, exitHandler)
}
// -----------------------------------------------------------------------------

View file

@ -43,8 +43,14 @@ Window {
rightPaned.close()
}
function conferenceManagerResult(exitValue){
if(exitValue == 0 && calls.count == 0)
close();
}
function openConferenceManager (params) {
Logic.openConferenceManager(params)
Logic.openConferenceManager(params, conferenceManagerResult)
}
function setHeight (height) {
@ -122,7 +128,9 @@ Window {
icon: 'new_conference'
visible: SettingsModel.conferenceEnabled
onClicked: Logic.openConferenceManager()
onClicked: {
Logic.openConferenceManager()
}
}
}
}

View file

@ -125,6 +125,7 @@ ColumnLayout {
Item {
ActionBar {
id:actionBar
anchors {
left: parent.left
verticalCenter: parent.verticalCenter
@ -152,7 +153,8 @@ ColumnLayout {
ActionButton {
icon: 'chat'
visible:SettingsModel.chatEnabled && SettingsModel.getShowStartChatButton() && $contact.hasCapability(LinphoneEnums.FriendCapabilityLimeX3Dh)
visible: SettingsModel.chatEnabled && SettingsModel.getShowStartChatButton() && $contact.hasCapability(LinphoneEnums.FriendCapabilityLimeX3Dh)
enabled: AccountSettingsModel.conferenceURI != ''
Icon{
icon:'secure_level_1'
iconSize:15
@ -161,6 +163,13 @@ ColumnLayout {
anchors.topMargin: -3
}
onClicked: {actions.itemAt(3).open()}
TooltipArea{
maxWidth: actionBar.width
visible: AccountSettingsModel.conferenceURI == ''
//: 'You need to set the conference URI in your account settings to create a conference based chat room.' : Tooltip to warn the user that a setting is missing in its configuration.
text: '- ' + qsTr('missingConferenceURI') + '\n'
}
}
}

View file

@ -81,7 +81,7 @@ ColumnLayout {
icon:'chat_room'
iconSize: ConversationStyle.bar.groupChatSize
visible: chatRoomModel.groupEnabled
visible: chatRoomModel.groupEnabled && chatRoomModel.participants.count > 2
}
Item{
Layout.fillHeight: true

View file

@ -29,7 +29,7 @@ DialogPlus {
onClicked: exit(0)
},
TextButtonB {
//enabled: toAddView.count >= conferenceManager.minParticipants
enabled: selectedParticipants.count >= conferenceManager.minParticipants && subject.text != '' && AccountSettingsModel.conferenceURI != ''
//: 'Launch' : Start button
text: qsTr('startButton')
capitalization: Font.AllUppercase
@ -38,6 +38,23 @@ DialogPlus {
if(CallsListModel.createChatRoom(subject.text, secureSwitch.checked, selectedParticipants.getParticipants() ))
exit(1)
}
TooltipArea{
visible: AccountSettingsModel.conferenceURI == '' || subject.text == '' || selectedParticipants.count < conferenceManager.minParticipants
maxWidth: participantView.width
text: {
var txt = '\n';
if( subject.text == '')
//: 'You need to fill a subject.' : Tooltip to warn a user on missing field.
txt ='- ' + qsTr('missingSubject') + '\n'
if( selectedParticipants.count < conferenceManager.minParticipants)
//: 'You need at least %1 participant.' : Tooltip to warn a user that there are not enough participants for the chat creation.
txt += '- ' + qsTr('missingParticipants', '', conferenceManager.minParticipants) + '\n'
if( AccountSettingsModel.conferenceURI == '')
//: 'You need to set the conference URI in your account settings to create a conference based chat room.' : Tooltip to warn the user that a setting is missong in its configuration.
txt += '- ' + qsTr('missingConferenceURI') + '\n'
return txt;
}
}
}
]