Commit 30c92d55 authored by Ronan Abhamon's avatar Ronan Abhamon

feat(ui/views/App/MainWindow/ContactEdit): view in progress

parent ac0f224e
......@@ -46,6 +46,7 @@ foreach (package ${QT5_PACKAGES})
endforeach ()
list(APPEND LIBS "${CMAKE_SOURCE_DIR}/../OUTPUT/desktop/lib64/liblinphone++.so")
list(APPEND LIBS "${CMAKE_SOURCE_DIR}/../OUTPUT/desktop/lib64/libbelcard.so")
set(SOURCES
src/app/App.cpp
......
<?xml version="1.0" encoding="UTF-8"?>
<svg width="60px" height="60px" viewBox="0 0 60 60" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 41.2 (35397) - http://www.bohemiancoding.com/sketch -->
<title>contact_card_photo_over</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Symbols" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="contact_card_photo_over">
<g id="Group-7">
<path d="M0,30 C0,46.568 13.4315,60 30,60 C46.568,60 60,46.568 60,30 C60,13.431 46.568,0 30,0 C13.4315,0 0,13.431 0,30 Z" id="AVATAR" fill="#6B7A86"></path>
<path d="M42.7031449,40.8140504 L18.234171,40.8140504 C17.0106603,40.8140504 16,39.8196379 16,38.615797 L16,23.2282265 C16,22.0243856 17.0106603,21.0300409 18.234171,21.0300409 L21.7980713,21.0300409 C22.3833064,21.0300409 23.074829,20.5589962 23.2343634,19.9831696 L23.5535012,18.9363661 C23.925886,17.837375 25.0961496,17 26.2663444,17 L34.7242185,17 C35.8944133,17 37.064677,17.837375 37.4370618,18.9363661 L37.7561995,19.9831696 C37.915734,20.5589962 38.6072565,21.0300409 39.1924917,21.0300409 L42.7564608,21.0300409 C43.9799026,21.0300409 44.9905629,22.0243856 44.9905629,23.2282265 L44.9905629,38.615797 C44.9905629,39.8196379 43.9799026,40.8140504 42.7031449,40.8140504 L42.7031449,40.8140504 Z M18.234171,22.3383927 C17.7021829,22.3383927 17.2767577,22.7572496 17.2767577,23.2806853 L17.2767577,38.6679846 C17.2767577,39.1913525 17.7021829,39.6102094 18.234171,39.6102094 L42.7031449,39.6102094 C43.235133,39.6102094 43.6608337,39.1913525 43.6608337,38.6679846 L43.6608337,23.2806853 C43.6608337,22.7572496 43.235133,22.3383927 42.7031449,22.3383927 L39.1392447,22.3383927 C37.9690499,22.3383927 36.7987862,21.5010177 36.4264014,20.4020266 L36.1072637,19.3552231 C35.9477292,18.7795998 35.2562067,18.3083518 34.6709715,18.3083518 L26.2130974,18.3083518 C25.6280689,18.3083518 24.9365463,18.7795998 24.7767363,19.3552231 L24.4575986,20.4020266 C24.0852138,21.5010177 22.915019,22.3383927 21.7447553,22.3383927 L18.234171,22.3383927 Z" id="Fill-1" fill="#FFFFFF"></path>
<path d="M30.1811164,37.1313385 C26.2447625,37.1313385 23,33.9911314 23,30.0656693 C23,26.1926659 26.191791,23 30.1811164,23 C34.1707173,23 37.3625083,26.1402071 37.3625083,30.0656693 C37.3625083,33.9911314 34.117677,37.1313385 30.1811164,37.1313385 L30.1811164,37.1313385 Z M30.1811164,24.3608106 C26.9363539,24.3608106 24.3300736,26.9254622 24.3300736,30.118128 C24.3300736,33.3107261 26.9363539,35.8753777 30.1811164,35.8753777 C33.4261544,35.8753777 36.0324347,33.3107261 36.0324347,30.118128 C36.0324347,26.9254622 33.4261544,24.3608106 30.1811164,24.3608106 L30.1811164,24.3608106 Z" id="Fill-2" fill="#FFFFFF"></path>
</g>
</g>
</g>
</svg>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<svg width="60px" height="60px" viewBox="0 0 60 60" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 41.2 (35397) - http://www.bohemiancoding.com/sketch -->
<title>contact_card_photo_default</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Symbols" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="contact_card_photo_default">
<g id="Group-7">
<path d="M0,30 C0,46.568 13.4315,60 30,60 C46.568,60 60,46.568 60,30 C60,13.431 46.568,0 30,0 C13.4315,0 0,13.431 0,30 Z" id="AVATAR" fill="#D0D8DE"></path>
<path d="M42.7031449,40.8140504 L18.234171,40.8140504 C17.0106603,40.8140504 16,39.8196379 16,38.615797 L16,23.2282265 C16,22.0243856 17.0106603,21.0300409 18.234171,21.0300409 L21.7980713,21.0300409 C22.3833064,21.0300409 23.074829,20.5589962 23.2343634,19.9831696 L23.5535012,18.9363661 C23.925886,17.837375 25.0961496,17 26.2663444,17 L34.7242185,17 C35.8944133,17 37.064677,17.837375 37.4370618,18.9363661 L37.7561995,19.9831696 C37.915734,20.5589962 38.6072565,21.0300409 39.1924917,21.0300409 L42.7564608,21.0300409 C43.9799026,21.0300409 44.9905629,22.0243856 44.9905629,23.2282265 L44.9905629,38.615797 C44.9905629,39.8196379 43.9799026,40.8140504 42.7031449,40.8140504 L42.7031449,40.8140504 Z M18.234171,22.3383927 C17.7021829,22.3383927 17.2767577,22.7572496 17.2767577,23.2806853 L17.2767577,38.6679846 C17.2767577,39.1913525 17.7021829,39.6102094 18.234171,39.6102094 L42.7031449,39.6102094 C43.235133,39.6102094 43.6608337,39.1913525 43.6608337,38.6679846 L43.6608337,23.2806853 C43.6608337,22.7572496 43.235133,22.3383927 42.7031449,22.3383927 L39.1392447,22.3383927 C37.9690499,22.3383927 36.7987862,21.5010177 36.4264014,20.4020266 L36.1072637,19.3552231 C35.9477292,18.7795998 35.2562067,18.3083518 34.6709715,18.3083518 L26.2130974,18.3083518 C25.6280689,18.3083518 24.9365463,18.7795998 24.7767363,19.3552231 L24.4575986,20.4020266 C24.0852138,21.5010177 22.915019,22.3383927 21.7447553,22.3383927 L18.234171,22.3383927 Z" id="Fill-1" fill="#FFFFFF"></path>
<path d="M30.1811164,37.1313385 C26.2447625,37.1313385 23,33.9911314 23,30.0656693 C23,26.1926659 26.191791,23 30.1811164,23 C34.1707173,23 37.3625083,26.1402071 37.3625083,30.0656693 C37.3625083,33.9911314 34.117677,37.1313385 30.1811164,37.1313385 L30.1811164,37.1313385 Z M30.1811164,24.3608106 C26.9363539,24.3608106 24.3300736,26.9254622 24.3300736,30.118128 C24.3300736,33.3107261 26.9363539,35.8753777 30.1811164,35.8753777 C33.4261544,35.8753777 36.0324347,33.3107261 36.0324347,30.118128 C36.0324347,26.9254622 33.4261544,24.3608106 30.1811164,24.3608106 L30.1811164,24.3608106 Z" id="Fill-2" fill="#FFFFFF"></path>
</g>
</g>
</g>
</svg>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<svg width="60px" height="60px" viewBox="0 0 60 60" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 41.2 (35397) - http://www.bohemiancoding.com/sketch -->
<title>contact_card_photo_over</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Symbols" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="contact_card_photo_over">
<g id="Group-7">
<path d="M0,30 C0,46.568 13.4315,60 30,60 C46.568,60 60,46.568 60,30 C60,13.431 46.568,0 30,0 C13.4315,0 0,13.431 0,30 Z" id="AVATAR" fill="#FF5E00"></path>
<path d="M42.7031449,40.8140504 L18.234171,40.8140504 C17.0106603,40.8140504 16,39.8196379 16,38.615797 L16,23.2282265 C16,22.0243856 17.0106603,21.0300409 18.234171,21.0300409 L21.7980713,21.0300409 C22.3833064,21.0300409 23.074829,20.5589962 23.2343634,19.9831696 L23.5535012,18.9363661 C23.925886,17.837375 25.0961496,17 26.2663444,17 L34.7242185,17 C35.8944133,17 37.064677,17.837375 37.4370618,18.9363661 L37.7561995,19.9831696 C37.915734,20.5589962 38.6072565,21.0300409 39.1924917,21.0300409 L42.7564608,21.0300409 C43.9799026,21.0300409 44.9905629,22.0243856 44.9905629,23.2282265 L44.9905629,38.615797 C44.9905629,39.8196379 43.9799026,40.8140504 42.7031449,40.8140504 L42.7031449,40.8140504 Z M18.234171,22.3383927 C17.7021829,22.3383927 17.2767577,22.7572496 17.2767577,23.2806853 L17.2767577,38.6679846 C17.2767577,39.1913525 17.7021829,39.6102094 18.234171,39.6102094 L42.7031449,39.6102094 C43.235133,39.6102094 43.6608337,39.1913525 43.6608337,38.6679846 L43.6608337,23.2806853 C43.6608337,22.7572496 43.235133,22.3383927 42.7031449,22.3383927 L39.1392447,22.3383927 C37.9690499,22.3383927 36.7987862,21.5010177 36.4264014,20.4020266 L36.1072637,19.3552231 C35.9477292,18.7795998 35.2562067,18.3083518 34.6709715,18.3083518 L26.2130974,18.3083518 C25.6280689,18.3083518 24.9365463,18.7795998 24.7767363,19.3552231 L24.4575986,20.4020266 C24.0852138,21.5010177 22.915019,22.3383927 21.7447553,22.3383927 L18.234171,22.3383927 Z" id="Fill-1" fill="#FFFFFF"></path>
<path d="M30.1811164,37.1313385 C26.2447625,37.1313385 23,33.9911314 23,30.0656693 C23,26.1926659 26.191791,23 30.1811164,23 C34.1707173,23 37.3625083,26.1402071 37.3625083,30.0656693 C37.3625083,33.9911314 34.117677,37.1313385 30.1811164,37.1313385 L30.1811164,37.1313385 Z M30.1811164,24.3608106 C26.9363539,24.3608106 24.3300736,26.9254622 24.3300736,30.118128 C24.3300736,33.3107261 26.9363539,35.8753777 30.1811164,35.8753777 C33.4261544,35.8753777 36.0324347,33.3107261 36.0324347,30.118128 C36.0324347,26.9254622 33.4261544,24.3608106 30.1811164,24.3608106 L30.1811164,24.3608106 Z" id="Fill-2" fill="#FFFFFF"></path>
</g>
</g>
</g>
</svg>
......@@ -138,6 +138,10 @@
<source>webSitesInput</source>
<translation type="unfinished">URL</translation>
</message>
<message>
<source>avatarChooserTitle</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>Contacts</name>
......
......@@ -130,6 +130,10 @@
<source>webSitesInput</source>
<translation type="unfinished">URL</translation>
</message>
<message>
<source>avatarChooserTitle</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>Contacts</name>
......
......@@ -36,6 +36,9 @@
<file>assets/images/chevron_red.svg</file>
<file>assets/images/chevron_white.svg</file>
<file>assets/images/collapse.svg</file>
<file>assets/images/contact_card_photo_hovered.svg</file>
<file>assets/images/contact_card_photo_normal.svg</file>
<file>assets/images/contact_card_photo_pressed.svg</file>
<file>assets/images/contact_edit_hovered.svg</file>
<file>assets/images/contact_edit_normal.svg</file>
<file>assets/images/contact_edit_pressed.svg</file>
......
......@@ -14,8 +14,9 @@
QStandardPaths::writableLocation(QStandardPaths::HomeLocation)
#endif
#define DATABASE_PATH_FRIENDS_LIST ".linphone-friends.db"
#define DATABASE_PATH_AVATARS ".linphone/avatars/"
#define DATABASE_PATH_CALL_HISTORY_LIST ".linphone-call-history.db"
#define DATABASE_PATH_FRIENDS_LIST ".linphone-friends.db"
#define DATABASE_PATH_MESSAGE_HISTORY_LIST ".linphone-history.db"
using namespace std;
......@@ -33,6 +34,16 @@ inline bool ensureDatabaseFilePathExists (const QString &path) {
return file.exists() || file.open(QIODevice::ReadWrite);
}
string Database::getAvatarsPath () {
QString path(DATABASES_PATH + "/" DATABASE_PATH_AVATARS);
QDir dir(path);
if (!dir.exists() && !dir.mkpath(path))
return "";
return Utils::qStringToLinphoneString(QDir::toNativeSeparators(path));
}
inline string getDatabaseFilePath (const QString &filename) {
QString path(DATABASES_PATH + "/");
path += filename;
......@@ -41,14 +52,14 @@ inline string getDatabaseFilePath (const QString &filename) {
: "";
}
string Database::getFriendsListPath () {
return getDatabaseFilePath(DATABASE_PATH_FRIENDS_LIST);
}
string Database::getCallHistoryPath () {
return getDatabaseFilePath(DATABASE_PATH_CALL_HISTORY_LIST);
}
string Database::getFriendsListPath () {
return getDatabaseFilePath(DATABASE_PATH_FRIENDS_LIST);
}
string Database::getMessageHistoryPath () {
return getDatabaseFilePath(DATABASE_PATH_MESSAGE_HISTORY_LIST);
}
......@@ -9,8 +9,10 @@ namespace Database {
// Returns the databases paths.
// If files cannot be created or are unavailable, a empty string is returned.
// Use the directories separator of used OS.
std::string getFriendsListPath ();
std::string getAvatarsPath ();
std::string getCallHistoryPath ();
std::string getFriendsListPath ();
std::string getMessageHistoryPath ();
};
......
#include <QFileInfo>
#include <QImageReader>
#include <QUuid>
#include <QtDebug>
#include <belcard/belcard.hpp>
#include "../../app/Database.hpp"
#include "../../utils.hpp"
#include "ContactModel.hpp"
using namespace std;
// ===================================================================
inline shared_ptr<belcard::BelCard> getBelCard (
const shared_ptr<linphone::Friend> &linphone_friend
) {
shared_ptr<linphone::Vcard> vcard = linphone_friend->getVcard();
return *reinterpret_cast<shared_ptr<belcard::BelCard> *>(vcard.get());
}
// -------------------------------------------------------------------
Presence::PresenceStatus ContactModel::getPresenceStatus () const {
return m_presence_status;
}
......@@ -18,6 +37,43 @@ QString ContactModel::getUsername () const {
);
}
bool ContactModel::setAvatar (const QString &path) {
// Try to copy photo in avatars folder.
QFile file(path);
if (!file.exists() || QImageReader::imageFormat(path).size() == 0)
return false;
QFileInfo info(file);
QString file_id = QUuid::createUuid().toString() + "." + info.suffix();
QString dest = Utils::linphoneStringToQString(Database::getAvatarsPath()) +
file_id;
if (!file.copy(dest))
return false;
qInfo() << QStringLiteral("Update avatar of `%1`. (path=%2)")
.arg(getUsername()).arg(dest);
// Remove oldest photos.
shared_ptr<belcard::BelCard> belCard = getBelCard(m_linphone_friend);
for (const auto &photo : belCard->getPhotos()) {
qDebug() << Utils::linphoneStringToQString(photo->getValue());
belCard->removePhoto(photo);
}
// Update.
shared_ptr<belcard::BelCardPhoto> photo =
belcard::BelCardGeneric::create<belcard::BelCardPhoto>();
photo->setValue(Utils::qStringToLinphoneString(file_id));
belCard->addPhoto(photo);
emit contactUpdated();
return true;
}
QString ContactModel::getSipAddress () const {
return Utils::linphoneStringToQString(
m_linphone_friend->getAddress()->asString()
......
......@@ -23,19 +23,20 @@ class ContactModel : public QObject {
Q_PROPERTY(
QString avatar
READ getAvatar
WRITE setAvatar
NOTIFY contactUpdated
);
Q_PROPERTY(
Presence::PresenceStatus presenceStatus
READ getPresenceStatus
CONSTANT
NOTIFY contactUpdated
);
Q_PROPERTY(
Presence::PresenceLevel presenceLevel
READ getPresenceLevel
CONSTANT
NOTIFY contactUpdated
);
Q_PROPERTY(
......@@ -60,6 +61,8 @@ private:
return "";
}
bool setAvatar (const QString &path);
Presence::PresenceStatus getPresenceStatus () const;
Presence::PresenceLevel getPresenceLevel () const;
......
......@@ -9,7 +9,7 @@ QtObject {
property color backgroundColor: Colors.g20
property QtObject contentItem: QtObject {
property int implicitHeight: 100
property int implicitHeight: 8
property int implicitWidth: 8
property int radius: 10
}
......
......@@ -20,6 +20,10 @@ Item {
// -----------------------------------------------------------------
function isLoaded () {
return roundedImage.status === Image.Ready
}
function _computeInitials () {
var result = username.match(_initialsRegex)
......
......@@ -388,6 +388,12 @@ function isInteger (integer) {
// -------------------------------------------------------------------
function isObject (object) {
return object !== null && typeof object === 'object'
}
// -------------------------------------------------------------------
function isString (string) {
return typeof string === 'string' || string instanceof String
}
......
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Dialogs 1.2
import QtQuick.Layouts 1.3
import Common 1.0
......@@ -20,10 +21,12 @@ ColumnLayout {
sipAddress
) || sipAddress
property var _info: {}
// -----------------------------------------------------------------
function _removeContact () {
Utils.openConfirmDialog(this, {
Utils.openConfirmDialog(window, {
descriptionText: qsTr('removeContactDescription'),
exitHandler: function (status) {
if (status) {
......@@ -35,10 +38,31 @@ ColumnLayout {
})
}
function _setAvatar (path) {
if (!path) {
return
}
if (Utils.isObject(_contact)) {
_contact.avatar = path.match(/^(?:file:\/\/)?(.*)$/)[1]
}
// TODO: Not registered contact.
}
// -----------------------------------------------------------------
spacing: 0
FileDialog {
id: avatarChooser
folder: shortcuts.home
title: qsTr('avatarChooserTitle')
onAccepted: _setAvatar(fileUrls[0])
}
// -----------------------------------------------------------------
// Info bar.
// -----------------------------------------------------------------
......@@ -64,6 +88,22 @@ ColumnLayout {
width: ContactEditStyle.infoBar.avatarSize
username: LinphoneUtils.getContactUsername(_contact)
visible: isLoaded()
MouseArea {
anchors.fill: parent
onClicked: avatarChooser.open()
}
}
ActionButton {
Layout.preferredHeight: ContactEditStyle.infoBar.avatarSize
Layout.preferredWidth: ContactEditStyle.infoBar.avatarSize
icon: 'contact_card_photo'
visible: !avatar.isLoaded()
onClicked: avatarChooser.open()
}
Text {
......@@ -83,6 +123,7 @@ ColumnLayout {
Layout.alignment: Qt.AlignRight
iconSize: ContactEditStyle.infoBar.buttons.size
spacing: ContactEditStyle.infoBar.buttons.spacing
visible: Utils.isObject(_contact)
ActionButton {
icon: 'history'
......@@ -107,16 +148,17 @@ ColumnLayout {
Layout.fillHeight: true
Layout.fillWidth: true
ScrollBar.vertical: ForceScrollBar {}
boundsBehavior: Flickable.StopAtBounds
clip: true
contentHeight: content.height
contentHeight: infoList.height
flickableDirection: Flickable.VerticalFlick
ColumnLayout {
anchors.left: parent.left
anchors.margins: 20
anchors.margins: 40
anchors.right: parent.right
id: content
id: infoList
ListForm {
title: qsTr('sipAccounts')
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment