mirror of
https://gitlab.linphone.org/BC/public/linphone-desktop.git
synced 2026-01-17 11:28:07 +00:00
Feature : display accounts.
- Implement shaders to make round images and use qsb --qt6. - Add picture to Friend. - Display username if displayname is not found. - Compute initials from C++ with emojis. - Add Accounts list in a popup from main window. - Add a hack on account to update avatar on all AcountModel. - Add Avatar item for initials/picture. - Add Contact description item. - Make sizes proportionals to match designs. - Add image colorization.
This commit is contained in:
parent
41ee79c070
commit
a1d72e6382
24 changed files with 537 additions and 30 deletions
|
|
@ -40,6 +40,7 @@ FriendCore::FriendCore(const std::shared_ptr<linphone::Friend> &contact) : QObje
|
|||
mFriendModel->setSelf(mFriendModel);
|
||||
mConsolidatedPresence = LinphoneEnums::fromLinphone(contact->getConsolidatedPresence());
|
||||
mPresenceTimestamp = mFriendModel->getPresenceTimestamp();
|
||||
mPictureUri = Utils::coreStringToAppString(contact->getPhoto());
|
||||
auto address = contact->getAddress();
|
||||
mAddress = address ? Utils::coreStringToAppString(contact->getAddress()->asString()) : "NoAddress";
|
||||
mIsSaved = true;
|
||||
|
|
@ -71,6 +72,14 @@ void FriendCore::setSelf(SafeSharedPointer<QObject> me) {
|
|||
setPresenceTimestamp(presenceTimestamp);
|
||||
});
|
||||
});
|
||||
mFriendModelConnection->makeConnect(mFriendModel.get(), &FriendModel::pictureUriChanged, [this](QString uri) {
|
||||
mFriendModelConnection->invokeToCore([this, uri]() { this->onPictureUriChanged(uri); });
|
||||
});
|
||||
|
||||
// From GUI
|
||||
mFriendModelConnection->makeConnect(this, &FriendCore::lSetPictureUri, [this](QString uri) {
|
||||
mFriendModelConnection->invokeToModel([this, uri]() { mFriendModel->setPictureUri(uri); });
|
||||
});
|
||||
|
||||
} else { // Create
|
||||
mFriendModelConnection = QSharedPointer<SafeConnection>(
|
||||
|
|
@ -133,6 +142,15 @@ void FriendCore::setPresenceTimestamp(QDateTime presenceTimestamp) {
|
|||
}
|
||||
}
|
||||
|
||||
QString FriendCore::getPictureUri() const {
|
||||
return mPictureUri;
|
||||
}
|
||||
|
||||
void FriendCore::onPictureUriChanged(QString uri) {
|
||||
mPictureUri = uri;
|
||||
emit pictureUriChanged();
|
||||
}
|
||||
|
||||
bool FriendCore::getIsSaved() const {
|
||||
return mIsSaved;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ class FriendCore : public QObject, public AbstractObject {
|
|||
Q_PROPERTY(LinphoneEnums::ConsolidatedPresence consolidatedPresence READ getConsolidatedPresence NOTIFY
|
||||
consolidatedPresenceChanged)
|
||||
Q_PROPERTY(bool isSaved READ getIsSaved NOTIFY isSavedChanged)
|
||||
Q_PROPERTY(QString pictureUri READ getPictureUri WRITE lSetPictureUri NOTIFY pictureUriChanged)
|
||||
|
||||
public:
|
||||
// Should be call from model Thread. Will be automatically in App thread after initialization
|
||||
|
|
@ -70,6 +71,9 @@ public:
|
|||
bool getIsSaved() const;
|
||||
void setIsSaved(bool isSaved);
|
||||
|
||||
QString getPictureUri() const;
|
||||
void onPictureUriChanged(QString uri);
|
||||
|
||||
void onPresenceReceived(LinphoneEnums::ConsolidatedPresence consolidatedPresence, QDateTime presenceTimestamp);
|
||||
|
||||
Q_INVOKABLE void remove();
|
||||
|
|
@ -84,10 +88,13 @@ signals:
|
|||
void presenceTimestampChanged(QDateTime presenceTimestamp);
|
||||
void sipAddressAdded(const QString &sipAddress);
|
||||
void sipAddressRemoved(const QString &sipAddress);
|
||||
void pictureUriChanged();
|
||||
void saved();
|
||||
void isSavedChanged(bool isSaved);
|
||||
void removed(FriendCore *contact);
|
||||
|
||||
void lSetPictureUri(QString pictureUri);
|
||||
|
||||
protected:
|
||||
void writeInto(std::shared_ptr<linphone::Friend> contact) const;
|
||||
void writeFrom(const std::shared_ptr<linphone::Friend> &contact);
|
||||
|
|
@ -96,6 +103,7 @@ protected:
|
|||
QDateTime mPresenceTimestamp;
|
||||
QString mName;
|
||||
QString mAddress;
|
||||
QString mPictureUri;
|
||||
bool mIsSaved;
|
||||
std::shared_ptr<FriendModel> mFriendModel;
|
||||
QSharedPointer<SafeConnection> mFriendModelConnection;
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ list(APPEND _LINPHONEAPP_RC_FILES data/assistant/use-app-sip-account.rc
|
|||
"data/image/info.svg"
|
||||
"data/image/belledonne.svg"
|
||||
"data/image/user-circle.svg"
|
||||
"data/image/user-circle-gear.svg"
|
||||
"data/image/logo.svg"
|
||||
"data/image/login_image.svg"
|
||||
"data/image/eye-slash.svg"
|
||||
|
|
@ -45,6 +46,9 @@ list(APPEND _LINPHONEAPP_RC_FILES data/assistant/use-app-sip-account.rc
|
|||
"data/image/outgoing_call_missed.svg"
|
||||
"data/image/outgoing_call_rejected.svg"
|
||||
|
||||
data/shaders/roundEffect.vert.qsb
|
||||
data/shaders/roundEffect.frag.qsb
|
||||
|
||||
)
|
||||
|
||||
set(_LINPHONEAPP_RC_FILES ${_LINPHONEAPP_RC_FILES} PARENT_SCOPE)
|
||||
|
|
|
|||
18
Linphone/data/shaders/roundEffect.frag
Normal file
18
Linphone/data/shaders/roundEffect.frag
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
#version 440
|
||||
layout(location = 0) in vec2 coord;
|
||||
layout(location = 0) out vec4 fragColor;
|
||||
layout(std140, binding = 0) uniform buf {
|
||||
mat4 qt_Matrix;
|
||||
float qt_Opacity;
|
||||
float edge;
|
||||
};
|
||||
layout(binding = 1) uniform sampler2D src;
|
||||
|
||||
void main() {
|
||||
float dist = distance(coord, vec2( 0.5 ));
|
||||
float delta = fwidth(dist);
|
||||
float alpha = smoothstep( mix(clamp(edge, 0.0, 1.0), 0.0, 0.5) - delta, 0.5, dist );
|
||||
|
||||
vec4 tex = texture(src, coord);
|
||||
fragColor = mix( tex, vec4(0.0), alpha) * qt_Opacity;
|
||||
}
|
||||
BIN
Linphone/data/shaders/roundEffect.frag.qsb
Normal file
BIN
Linphone/data/shaders/roundEffect.frag.qsb
Normal file
Binary file not shown.
13
Linphone/data/shaders/roundEffect.vert
Normal file
13
Linphone/data/shaders/roundEffect.vert
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
#version 440
|
||||
layout(location = 0) in vec4 qt_Vertex;
|
||||
layout(location = 1) in vec2 qt_MultiTextCoord0;
|
||||
layout(location = 0) out vec2 coord;
|
||||
layout(std140, binding = 0) uniform buf {
|
||||
mat4 qt_Matrix;
|
||||
float qt_Opacity;
|
||||
};
|
||||
|
||||
void main() {
|
||||
coord = qt_MultiTextCoord0;
|
||||
gl_Position = qt_Matrix * qt_Vertex;
|
||||
}
|
||||
BIN
Linphone/data/shaders/roundEffect.vert.qsb
Normal file
BIN
Linphone/data/shaders/roundEffect.vert.qsb
Normal file
Binary file not shown.
|
|
@ -34,6 +34,10 @@ AccountModel::AccountModel(const std::shared_ptr<linphone::Account> &account, QO
|
|||
mustBeInLinphoneThread(getClassName());
|
||||
connect(CoreModel::getInstance().get(), &CoreModel::defaultAccountChanged, this,
|
||||
&AccountModel::onDefaultAccountChanged);
|
||||
|
||||
// Hack because Account doesn't provide callbacks on updated data
|
||||
connect(this, &AccountModel::defaultAccountChanged, this,
|
||||
[this]() { emit pictureUriChanged(Utils::coreStringToAppString(mMonitor->getParams()->getPictureUri())); });
|
||||
}
|
||||
|
||||
AccountModel::~AccountModel() {
|
||||
|
|
@ -61,7 +65,10 @@ void AccountModel::setPictureUri(QString uri) {
|
|||
}
|
||||
params->setPictureUri(Utils::appStringToCoreString(uri));
|
||||
account->setParams(params);
|
||||
emit pictureUriChanged(uri);
|
||||
// Hack because Account doesn't provide callbacks on updated data
|
||||
// emit pictureUriChanged(uri);
|
||||
emit CoreModel::getInstance()->defaultAccountChanged(CoreModel::getInstance()->getCore(),
|
||||
CoreModel::getInstance()->getCore()->getDefaultAccount());
|
||||
}
|
||||
|
||||
void AccountModel::onDefaultAccountChanged() {
|
||||
|
|
|
|||
|
|
@ -20,7 +20,11 @@
|
|||
|
||||
#include "FriendModel.hpp"
|
||||
|
||||
#include "core/path/Paths.hpp"
|
||||
#include "tool/Utils.hpp"
|
||||
#include "tool/providers/AvatarProvider.hpp"
|
||||
#include <QDebug>
|
||||
#include <QUrl>
|
||||
|
||||
DEFINE_ABSTRACT_OBJECT(FriendModel)
|
||||
|
||||
|
|
@ -48,3 +52,21 @@ QDateTime FriendModel::getPresenceTimestamp() const {
|
|||
void FriendModel::onPresenceReceived(const std::shared_ptr<linphone::Friend> &contact) {
|
||||
emit presenceReceived(LinphoneEnums::fromLinphone(contact->getConsolidatedPresence()), getPresenceTimestamp());
|
||||
}
|
||||
|
||||
void FriendModel::setPictureUri(QString uri) {
|
||||
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
||||
auto account = std::dynamic_pointer_cast<linphone::Account>(mMonitor);
|
||||
auto params = account->getParams()->clone();
|
||||
auto oldPictureUri = Utils::coreStringToAppString(params->getPictureUri());
|
||||
if (!oldPictureUri.isEmpty()) {
|
||||
QString appPrefix = QStringLiteral("image://%1/").arg(AvatarProvider::ProviderId);
|
||||
if (oldPictureUri.startsWith(appPrefix)) {
|
||||
oldPictureUri = Paths::getAvatarsDirPath() + oldPictureUri.mid(appPrefix.length());
|
||||
}
|
||||
QFile oldPicture(oldPictureUri);
|
||||
if (!oldPicture.remove()) qWarning() << log().arg("Cannot delete old avatar file at " + oldPictureUri);
|
||||
}
|
||||
params->setPictureUri(Utils::appStringToCoreString(uri));
|
||||
account->setParams(params);
|
||||
emit pictureUriChanged(uri);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,9 +39,13 @@ public:
|
|||
~FriendModel();
|
||||
|
||||
QDateTime getPresenceTimestamp() const;
|
||||
|
||||
std::shared_ptr<linphone::Friend> getFriend() const;
|
||||
|
||||
void setPictureUri(QString uri);
|
||||
|
||||
signals:
|
||||
void pictureUriChanged(QString uri);
|
||||
|
||||
private:
|
||||
DECLARE_ABSTRACT_OBJECT
|
||||
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ QString ToolModel::getDisplayName(const std::shared_ptr<const linphone::Address>
|
|||
QString displayName;
|
||||
if (address) {
|
||||
displayName = Utils::coreStringToAppString(address->getDisplayName());
|
||||
if (displayName.isEmpty()) displayName = Utils::coreStringToAppString(address->getUsername());
|
||||
// TODO
|
||||
// std::shared_ptr<linphone::Address> cleanAddress = address->clone();
|
||||
// cleanAddress->clean();
|
||||
|
|
|
|||
|
|
@ -53,6 +53,26 @@ VariantObject *Utils::getDisplayName(const QString &address) {
|
|||
return data;
|
||||
}
|
||||
|
||||
QString Utils::getInitials(const QString &username) {
|
||||
if (username.isEmpty()) return "";
|
||||
|
||||
QRegularExpression regex("[\\s\\.]+");
|
||||
QStringList words = username.split(regex); // Qt 5.14: Qt::SkipEmptyParts
|
||||
QStringList initials;
|
||||
auto str32 = words[0].toStdU32String();
|
||||
std::u32string char32;
|
||||
char32 += str32[0];
|
||||
initials << QString::fromStdU32String(char32);
|
||||
for (int i = 1; i < words.size() && initials.size() <= 1; ++i) {
|
||||
if (words[i].size() > 0) {
|
||||
str32 = words[i].toStdU32String();
|
||||
char32[0] = str32[0];
|
||||
initials << QString::fromStdU32String(char32);
|
||||
}
|
||||
}
|
||||
return QLocale().toUpper(initials.join(""));
|
||||
}
|
||||
|
||||
VariantObject *Utils::createCall(const QString &sipAddress,
|
||||
const QString &prepareTransfertAddress,
|
||||
const QHash<QString, QString> &headers) {
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ public:
|
|||
}
|
||||
|
||||
Q_INVOKABLE static VariantObject *getDisplayName(const QString &address);
|
||||
Q_INVOKABLE static QString getInitials(const QString &username); // Support UTF32
|
||||
Q_INVOKABLE static VariantObject *createCall(const QString &sipAddress,
|
||||
const QString &prepareTransfertAddress = "",
|
||||
const QHash<QString, QString> &headers = {});
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import QtCore
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Layouts 1.3
|
||||
import QtQuick.Controls 2.2 as Control
|
||||
import QtQuick.Dialogs
|
||||
import QtQuick.Effects
|
||||
|
||||
import Linphone
|
||||
import UtilsCpp
|
||||
|
|
@ -17,7 +17,7 @@ Item {
|
|||
RowLayout {
|
||||
anchors.fill: parent
|
||||
// spacing: 30
|
||||
anchors.topMargin: 18
|
||||
anchors.topMargin: 18 * DefaultStyle.dp
|
||||
VerticalTabBar {
|
||||
id: tabbar
|
||||
Layout.fillHeight: true
|
||||
|
|
@ -32,7 +32,9 @@ Item {
|
|||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
RowLayout {
|
||||
Layout.leftMargin: 25
|
||||
id: topRow
|
||||
Layout.leftMargin: 25 * DefaultStyle.dp
|
||||
Layout.rightMargin: 41 * DefaultStyle.dp
|
||||
TextInput {
|
||||
fillWidth: true
|
||||
placeholderText: qsTr("Rechercher un contact, appeler ou envoyer un message...")
|
||||
|
|
@ -41,42 +43,44 @@ Item {
|
|||
id: avatarButton
|
||||
AccountProxy{
|
||||
id: accountProxy
|
||||
property bool haveAvatar: defaultAccount && defaultAccount.core.pictureUri || false
|
||||
//property bool haveAvatar: defaultAccount && defaultAccount.core.pictureUri || false
|
||||
}
|
||||
|
||||
Layout.preferredWidth: 30
|
||||
Layout.preferredHeight: 30
|
||||
Layout.preferredWidth: 54 * DefaultStyle.dp
|
||||
Layout.preferredHeight: width
|
||||
background: Item {
|
||||
visible: false
|
||||
}
|
||||
contentItem: Image {
|
||||
contentItem: Avatar {
|
||||
id: avatar
|
||||
source: accountProxy.haveAvatar ? accountProxy.defaultAccount.core.pictureUri : AppIcons.welcomeLinphoneLogo
|
||||
fillMode: Image.PreserveAspectFit
|
||||
height: avatarButton.height
|
||||
width: avatarButton.width
|
||||
account: accountProxy.defaultAccount
|
||||
}
|
||||
onClicked: {
|
||||
fileDialog.open()
|
||||
accountList.open()
|
||||
}
|
||||
FileDialog {
|
||||
id: fileDialog
|
||||
currentFolder: StandardPaths.standardLocations(StandardPaths.PicturesLocation)[0]
|
||||
onAccepted: {
|
||||
var avatarPath = UtilsCpp.createAvatar( selectedFile )
|
||||
if(avatarPath){
|
||||
accountProxy.defaultAccount.core.pictureUri = avatarPath
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Control.Button {
|
||||
id: settingsButton
|
||||
enabled: false
|
||||
Layout.preferredWidth: 30
|
||||
Layout.preferredHeight: 30
|
||||
Layout.preferredWidth: 30 * DefaultStyle.dp
|
||||
Layout.preferredHeight: 30 * DefaultStyle.dp
|
||||
background: Item {
|
||||
}
|
||||
contentItem: Image {
|
||||
source: AppIcons.verticalDots
|
||||
}
|
||||
Popup{
|
||||
id: accountList
|
||||
x: -width + parent.width
|
||||
y: settingsButton.height + (10 * DefaultStyle.dp)
|
||||
contentWidth: accounts.width
|
||||
contentHeight: accounts.height
|
||||
Accounts{
|
||||
id: accounts
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
StackLayout {
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ import Linphone
|
|||
|
||||
Window {
|
||||
id: mainWindow
|
||||
width: 1025
|
||||
height: 641
|
||||
width: 1512 * DefaultStyle.dp
|
||||
height: 930 * DefaultStyle.dp
|
||||
visible: true
|
||||
title: qsTr("Linphone")
|
||||
property bool firstConnection: true
|
||||
|
|
|
|||
|
|
@ -4,10 +4,17 @@ list(APPEND _LINPHONEAPP_QML_FILES
|
|||
view/App/Layout/LoginLayout.qml
|
||||
view/App/Layout/MainLayout.qml
|
||||
|
||||
view/Item/Account/Accounts.qml
|
||||
|
||||
view/Item/Button.qml
|
||||
view/Item/Carousel.qml
|
||||
view/Item/CheckBox.qml
|
||||
view/Item/ComboBox.qml
|
||||
|
||||
view/Item/Contact/Avatar.qml
|
||||
view/Item/Contact/Contact.qml
|
||||
view/Item/Contact/ContactDescription.qml
|
||||
|
||||
view/Item/DesktopPopup.qml
|
||||
view/Item/DigitInput.qml
|
||||
|
||||
|
|
@ -18,6 +25,7 @@ list(APPEND _LINPHONEAPP_QML_FILES
|
|||
view/Item/NumericPad.qml
|
||||
view/Item/PhoneNumberComboBox.qml
|
||||
view/Item/PhoneNumberInput.qml
|
||||
view/Item/Popup.qml
|
||||
view/Item/RadioButton.qml
|
||||
view/Item/RectangleTest.qml
|
||||
view/Item/SearchBar.qml
|
||||
|
|
|
|||
73
Linphone/view/Item/Account/Accounts.qml
Normal file
73
Linphone/view/Item/Account/Accounts.qml
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Layouts 1.3
|
||||
import QtQuick.Controls 2.2 as Control
|
||||
|
||||
import Linphone
|
||||
import UtilsCpp
|
||||
|
||||
Item {
|
||||
id: mainItem
|
||||
width: 517 * DefaultStyle.dp
|
||||
readonly property int topPadding: 23 * DefaultStyle.dp
|
||||
readonly property int bottomPadding: 18 * DefaultStyle.dp
|
||||
readonly property int leftPadding: 32 * DefaultStyle.dp
|
||||
readonly property int rightPadding: 32 * DefaultStyle.dp
|
||||
readonly property int spacing: 16 * DefaultStyle.dp
|
||||
implicitHeight: list.contentHeight + topPadding + bottomPadding + 32 * DefaultStyle.dp + 1 + newAccountArea.height
|
||||
ColumnLayout{
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: mainItem.topPadding
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: mainItem.leftPadding
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: mainItem.rightPadding
|
||||
ListView{
|
||||
id: list
|
||||
Layout.preferredHeight: contentHeight
|
||||
Layout.fillWidth: true
|
||||
spacing: mainItem.spacing
|
||||
model: AccountProxy{}
|
||||
delegate: Contact{
|
||||
width: list.width
|
||||
account: modelData
|
||||
}
|
||||
}
|
||||
Rectangle{
|
||||
id: separator
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: mainItem.spacing
|
||||
Layout.bottomMargin: mainItem.spacing
|
||||
height: 1
|
||||
color: DefaultStyle.main2_300
|
||||
}
|
||||
MouseArea{ // TODO
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 32 * DefaultStyle.dp
|
||||
onClicked: console.log('New!')
|
||||
RowLayout{
|
||||
id: newAccountArea
|
||||
anchors.fill: parent
|
||||
spacing: 5 * DefaultStyle.dp
|
||||
EffectImage {
|
||||
id: newAccount
|
||||
image.source: AppIcons.plusCircle
|
||||
Layout.fillHeight: true
|
||||
Layout.preferredWidth: height
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
image.fillMode: Image.PreserveAspectFit
|
||||
colorizationColor: DefaultStyle.main2_500main
|
||||
}
|
||||
Text{
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
font.weight: 400 * DefaultStyle.dp
|
||||
font.pixelSize: 14 * DefaultStyle.dp
|
||||
color: DefaultStyle.main2_500main
|
||||
text: 'Ajouter un compte'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
77
Linphone/view/Item/Contact/Avatar.qml
Normal file
77
Linphone/view/Item/Contact/Avatar.qml
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
import QtQuick 2.7
|
||||
import QtQuick.Layouts 1.3
|
||||
import QtQuick.Controls 2.2
|
||||
import QtQuick.Effects
|
||||
|
||||
import Linphone
|
||||
import UtilsCpp
|
||||
|
||||
// Avatar using initial of the username in case
|
||||
// they don't have any profile picture
|
||||
|
||||
StackView{
|
||||
id: mainItem
|
||||
property FriendGui contact
|
||||
property AccountGui account
|
||||
onAccountChanged: if(account) replace(avatar, StackView.Immediate)
|
||||
property string address: account ? account.core.identityAddress : ''
|
||||
property var displayNameObj: UtilsCpp.getDisplayName(address)
|
||||
property bool haveAvatar: (account && account.core.pictureUri )
|
||||
|| (contact && contact.core.pictureUri)
|
||||
|
||||
initialItem: haveAvatar ? avatar : initials
|
||||
Component{
|
||||
id: initials
|
||||
Rectangle {
|
||||
id: initialItem
|
||||
property string initials: UtilsCpp.getInitials(mainItem.displayNameObj.value)
|
||||
onInitialsChanged: console.log("newInit:"+initials)
|
||||
radius: width / 2
|
||||
color: DefaultStyle.main2_200
|
||||
height: mainItem.height
|
||||
width: height
|
||||
Component.onCompleted: console.log("init:"+initials)
|
||||
Text {
|
||||
anchors.fill: parent
|
||||
anchors.centerIn: parent
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
text: initialItem.initials
|
||||
font {
|
||||
pixelSize: initialItem.height * 36 / 120
|
||||
weight: 800 * DefaultStyle.dp
|
||||
capitalization: Font.AllUppercase
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Component{
|
||||
id: avatar
|
||||
Item {
|
||||
id: avatarItem
|
||||
height: mainItem.height
|
||||
width: height
|
||||
|
||||
Image {
|
||||
id: image
|
||||
visible: false
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
sourceSize.width: avatarItem.width
|
||||
sourceSize.height: avatarItem.height
|
||||
fillMode: Image.PreserveAspectCrop
|
||||
anchors.centerIn: parent
|
||||
source: mainItem.account ? mainItem.account.core.pictureUri : mainItem.contact.core.pictureUri
|
||||
mipmap: true
|
||||
}
|
||||
ShaderEffect {
|
||||
id: roundEffect
|
||||
property variant src: image
|
||||
property double edge: 0.9
|
||||
anchors.fill: parent
|
||||
vertexShader: 'qrc:/data/shaders/roundEffect.vert.qsb'
|
||||
fragmentShader: 'qrc:/data/shaders/roundEffect.frag.qsb'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
137
Linphone/view/Item/Contact/Contact.qml
Normal file
137
Linphone/view/Item/Contact/Contact.qml
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
import QtCore
|
||||
import QtQuick
|
||||
import QtQuick.Effects
|
||||
import QtQuick.Dialogs
|
||||
import QtQuick.Layouts
|
||||
|
||||
|
||||
import Linphone
|
||||
import UtilsCpp
|
||||
|
||||
Rectangle{
|
||||
id: mainItem
|
||||
property AccountGui account
|
||||
height: 45 * DefaultStyle.dp
|
||||
RowLayout{
|
||||
anchors.fill: parent
|
||||
spacing: 0
|
||||
Avatar{
|
||||
id: avatar
|
||||
Layout.preferredWidth: 45 * DefaultStyle.dp
|
||||
Layout.preferredHeight: 45 * DefaultStyle.dp
|
||||
account: mainItem.account
|
||||
MouseArea{
|
||||
anchors.fill: parent
|
||||
onClicked: fileDialog.open()
|
||||
}
|
||||
FileDialog {
|
||||
id: fileDialog
|
||||
currentFolder: StandardPaths.standardLocations(StandardPaths.PicturesLocation)[0]
|
||||
onAccepted: {
|
||||
var avatarPath = UtilsCpp.createAvatar( selectedFile )
|
||||
if(avatarPath){
|
||||
mainItem.account.core.pictureUri = avatarPath
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ContactDescription{
|
||||
id: description
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
Layout.leftMargin: 10 * DefaultStyle.dp
|
||||
account: mainItem.account
|
||||
}
|
||||
Item{
|
||||
id: registrationStatusItem
|
||||
Layout.preferredWidth: 97 * DefaultStyle.dp
|
||||
Layout.fillHeight: true
|
||||
Rectangle{
|
||||
id: registrationStatus
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: Math.min(text.implicitWidth + (2 * 8 * DefaultStyle.dp), registrationStatusItem.width)
|
||||
height: 24 * DefaultStyle.dp
|
||||
color: DefaultStyle.main2_200
|
||||
radius: 90 * DefaultStyle.dp
|
||||
Text{
|
||||
id: text
|
||||
anchors.fill: parent
|
||||
anchors.leftMargin: 8 * DefaultStyle.dp
|
||||
anchors.rightMargin: 8 * DefaultStyle.dp
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
visible: mainItem.account
|
||||
readonly property int mode : !mainItem.account || mainItem.account.core.registrationState == LinphoneEnums.RegistrationState.Ok
|
||||
? 0
|
||||
: mainItem.account.core.registrationState == LinphoneEnums.RegistrationState.Cleared || mainItem.account.core.registrationState == LinphoneEnums.RegistrationState.None
|
||||
? 1
|
||||
: mainItem.account.core.registrationState == LinphoneEnums.RegistrationState.Progress || mainItem.account.core.registrationState == LinphoneEnums.RegistrationState.Refreshing
|
||||
? 2
|
||||
: 3
|
||||
// Test texts
|
||||
//Timer{
|
||||
// running: true
|
||||
// interval: 1000
|
||||
// repeat: true
|
||||
// onTriggered: text.mode = (++text.mode) % 4
|
||||
//}
|
||||
font.weight: 300 * DefaultStyle.dp
|
||||
font.pixelSize: 12 * DefaultStyle.dp
|
||||
color: mode == 0
|
||||
? DefaultStyle.success_500main
|
||||
: mode == 1
|
||||
? DefaultStyle.warning_600
|
||||
: mode == 2
|
||||
? DefaultStyle.main2_500main
|
||||
: DefaultStyle.danger_500main
|
||||
text: mode == 0
|
||||
? 'Connecté'
|
||||
: mode == 1
|
||||
? 'Désactivé'
|
||||
: mode == 2
|
||||
? 'Connexion...'
|
||||
: 'Erreur'
|
||||
}
|
||||
}
|
||||
}
|
||||
Item{ // TODO
|
||||
Layout.preferredWidth: 100 * DefaultStyle.dp
|
||||
Layout.fillHeight: true
|
||||
Rectangle{
|
||||
id: unreadNotifications
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 10 * DefaultStyle.dp
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: 22 * DefaultStyle.dp
|
||||
height: 22 * DefaultStyle.dp
|
||||
radius: width/2
|
||||
color: DefaultStyle.danger_500main
|
||||
border.color: DefaultStyle.grey_0
|
||||
border.width: 2 * DefaultStyle.dp
|
||||
Text{
|
||||
id: unreadCount
|
||||
anchors.fill: parent
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
color: DefaultStyle.grey_0
|
||||
text: '2'
|
||||
}
|
||||
}
|
||||
}
|
||||
EffectImage {
|
||||
id: manageAccount
|
||||
image.source: AppIcons.manageProfile
|
||||
Layout.preferredWidth: 24 * DefaultStyle.dp
|
||||
Layout.preferredHeight: 24 * DefaultStyle.dp
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
image.sourceSize.width: 24 * DefaultStyle.dp
|
||||
image.fillMode: Image.PreserveAspectFit
|
||||
colorizationColor: DefaultStyle.main2_500main
|
||||
MouseArea{ // TODO
|
||||
anchors.fill: parent
|
||||
onClicked: console.log('Manage!')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
37
Linphone/view/Item/Contact/ContactDescription.qml
Normal file
37
Linphone/view/Item/Contact/ContactDescription.qml
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import QtQuick.Controls
|
||||
|
||||
import Linphone
|
||||
import UtilsCpp
|
||||
|
||||
ColumnLayout{
|
||||
id: mainItem
|
||||
property AccountGui account: null
|
||||
property var displayName: account ? UtilsCpp.getDisplayName(account.core.identityAddress) : ''
|
||||
property string topText: displayName ? displayName.value : ''
|
||||
property string bottomText: account ? account.core.identityAddress : ''
|
||||
spacing: 0
|
||||
Text{
|
||||
id: topTextItem
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
verticalAlignment: (bottomTextItem.visible?Text.AlignBottom:Text.AlignVCenter)
|
||||
visible: text != ''
|
||||
font.weight: 400 * DefaultStyle.dp
|
||||
font.pixelSize: 14 * DefaultStyle.dp
|
||||
color: DefaultStyle.main2_700
|
||||
text: mainItem.topText
|
||||
}
|
||||
Text{
|
||||
id: bottomTextItem
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
verticalAlignment: (topTextItem.visible?Text.AlignTop:Text.AlignVCenter)
|
||||
visible: text != ''
|
||||
font.weight: 300 * DefaultStyle.dp
|
||||
font.pixelSize: 12 * DefaultStyle.dp
|
||||
color: DefaultStyle.main2_400
|
||||
text: mainItem.bottomText
|
||||
}
|
||||
}
|
||||
|
|
@ -9,21 +9,36 @@ Item {
|
|||
id: mainItem
|
||||
property alias image: image
|
||||
property alias effect: effect
|
||||
property alias effect2: effect2
|
||||
property var colorizationColor
|
||||
readonly property bool useColor: colorizationColor != undefined
|
||||
width: image.width
|
||||
height: image.height
|
||||
|
||||
Image {
|
||||
id: image
|
||||
width: 20
|
||||
height: 20
|
||||
sourceSize.width: 20
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
//sourceSize.width: parent.width
|
||||
fillMode: Image.PreserveAspectFit
|
||||
anchors.centerIn: parent
|
||||
visible: !effect2.enabled
|
||||
}
|
||||
MultiEffect {
|
||||
id: effect
|
||||
anchors.fill: image
|
||||
source: image
|
||||
maskSource: image
|
||||
visible: !effect2.enabled
|
||||
brightness: effect2.enabled ? 1.0 : 0.0
|
||||
}
|
||||
}
|
||||
MultiEffect {
|
||||
id: effect2
|
||||
enabled: mainItem.useColor
|
||||
anchors.fill: effect
|
||||
source: effect
|
||||
maskSource: effect
|
||||
colorizationColor: effect2.enabled ? mainItem.colorizationColor : 'black'
|
||||
colorization: effect2.enabled ? 1.0 : 0.0
|
||||
}
|
||||
}
|
||||
|
|
|
|||
27
Linphone/view/Item/Popup.qml
Normal file
27
Linphone/view/Item/Popup.qml
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
import QtQuick
|
||||
import QtQuick.Controls as Control
|
||||
import QtQuick.Effects
|
||||
import Linphone
|
||||
|
||||
Control.Popup{
|
||||
id: mainItem
|
||||
padding: 0
|
||||
background: Item{
|
||||
Rectangle{
|
||||
id: backgroundItem
|
||||
width: mainItem.width
|
||||
height: mainItem.height
|
||||
radius: 16 * DefaultStyle.dp
|
||||
border.color: DefaultStyle.grey_0
|
||||
border.width: 1
|
||||
}
|
||||
MultiEffect {
|
||||
anchors.fill: backgroundItem
|
||||
source: backgroundItem
|
||||
maskSource: backgroundItem
|
||||
shadowEnabled: true
|
||||
shadowBlur: 1.0
|
||||
shadowOpacity: 0.1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -14,6 +14,7 @@ QtObject {
|
|||
property string loginImage: "image://internal/login_image.svg"
|
||||
property string belledonne: "image://internal/belledonne.svg"
|
||||
property string profile: "image://internal/user-circle.svg"
|
||||
property string manageProfile: "image://internal/user-circle-gear.svg"
|
||||
property string verif_page_image: "image://internal/verif_page_image.svg"
|
||||
property string check: "image://internal/check.svg"
|
||||
property string dialer: "image://internal/dialer.svg"
|
||||
|
|
|
|||
|
|
@ -78,4 +78,16 @@ QtObject {
|
|||
|
||||
property color splitViewHandleColor: "#F9F9F9"
|
||||
property color splitViewHoveredHandleColor: "#EDEDED"
|
||||
|
||||
property color danger_500main: "#DD5F5F"
|
||||
property color grey_0: "#FFFFFF"
|
||||
property color success_500main: "#4FAE80"
|
||||
property color warning_600: "#DBB820"
|
||||
property color main2_200: "#DFECF2"
|
||||
property color main2_300: "#C0D1D9"
|
||||
property color main2_400: "#9AABB5"
|
||||
property color main2_700: "#364860"
|
||||
property color main2_500main: "#6C7A87"
|
||||
|
||||
property double dp: 1.0//0.66
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue