diff --git a/RingWinClient.pro b/RingWinClient.pro index 356a53c7bc106dad1ded7cd533bb7920da869c06..99d2580eb6d24fa26735291fb888d6c06f19924b 100644 --- a/RingWinClient.pro +++ b/RingWinClient.pro @@ -67,7 +67,8 @@ SOURCES += main.cpp\ pixbufmanipulator.cpp \ qualitydialog.cpp \ ringbutton.cpp \ - pathpassworddialog.cpp + pathpassworddialog.cpp \ + photoboothdialog.cpp HEADERS += mainwindow.h \ callwidget.h \ @@ -103,7 +104,8 @@ HEADERS += mainwindow.h \ qualitydialog.h \ ringthemeutils.h \ ringbutton.h \ - pathpassworddialog.h + pathpassworddialog.h \ + photoboothdialog.h contains(DEFINES, URI_PROTOCOL) { HEADERS += shmclient.h @@ -125,9 +127,11 @@ FORMS += mainwindow.ui \ combar.ui \ qualitydialog.ui \ ringbutton.ui \ - pathpassworddialog.ui + pathpassworddialog.ui \ + photoboothdialog.ui -win32: LIBS += -lole32 -luuid -lshlwapi -lqrencode +win32: LIBS += -lole32 -luuid -lshlwapi +LIBS += -lqrencode INCLUDEPATH += $${RING}/include/libringclient INCLUDEPATH += $${RING}/include diff --git a/accountdetails.cpp b/accountdetails.cpp index d21f67374f8c28a55969e1799163c03741880af7..b67da7bdeacf9f523ace54e46698301f37a23868 100644 --- a/accountdetails.cpp +++ b/accountdetails.cpp @@ -23,7 +23,6 @@ #include <QFileDialog> #include <QPushButton> -#include "accountdetails.h" #include "codecmodel.h" #include "protocolmodel.h" #include "certificate.h" @@ -112,6 +111,7 @@ AccountDetails::setAccount(Account* currentAccount) { codecModel_ = currentAccount->codecModel(); ui->audioCodecView->setModel(codecModel_->audioCodecs()); ui->videoCodecView->setModel(codecModel_->videoCodecs()); + connect(ui->audioCodecView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this, SLOT(audioCodecSelectionChanged(QItemSelection,QItemSelection))); connect(ui->videoCodecView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), @@ -298,4 +298,3 @@ AccountDetails::getDeleteAccountButton() { return ui->deleteAccountButton; } - diff --git a/accountdetails.ui b/accountdetails.ui index 1c7bbd356a1857f2b9fb1c18e9aa4172805c4adf..dba333fc47d83094487005c350c7e3bac2af1245 100644 --- a/accountdetails.ui +++ b/accountdetails.ui @@ -190,7 +190,7 @@ <property name="verticalSpacing"> <number>10</number> </property> - <item row="0" column="0"> + <item row="1" column="0"> <widget class="QLabel" name="aliasLabel"> <property name="font"> <font> @@ -208,7 +208,7 @@ </property> </widget> </item> - <item row="0" column="1"> + <item row="1" column="1"> <widget class="QLineEdit" name="lrcfg_alias"> <property name="sizePolicy"> <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> @@ -224,7 +224,7 @@ </property> </widget> </item> - <item row="1" column="0"> + <item row="2" column="0"> <widget class="QLabel" name="typeLabel"> <property name="font"> <font> @@ -239,7 +239,7 @@ </property> </widget> </item> - <item row="1" column="1"> + <item row="2" column="1"> <widget class="QLabel" name="typeValueLabel"> <property name="sizePolicy"> <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred"> @@ -2394,7 +2394,7 @@ <customwidget> <class>RingButton</class> <extends>QPushButton</extends> - <header>ringbutton.h</header> + <header location="global">ringbutton.h</header> </customwidget> </customwidgets> <resources> @@ -2547,7 +2547,7 @@ </connection> </connections> <buttongroups> - <buttongroup name="dtmfGroup"/> <buttongroup name="publishGroup"/> + <buttongroup name="dtmfGroup"/> </buttongroups> </ui> diff --git a/callwidget.cpp b/callwidget.cpp index 194e86f9c7b8dbacce5cbd0d3afc390ed835620b..78225acacfde63bf129643b86f63e9f685277dac 100644 --- a/callwidget.cpp +++ b/callwidget.cpp @@ -54,6 +54,10 @@ #include "imdelegate.h" #include "pixbufmanipulator.h" +#include "profilemodel.h" +#include "peerprofilecollection.h" +#include "localprofilecollection.h" + CallWidget::CallWidget(QWidget* parent) : NavWidget(parent), ui(new Ui::CallWidget), @@ -100,6 +104,9 @@ CallWidget::CallWidget(QWidget* parent) : smartListDelegate_ = new SmartListDelegate(); ui->smartList->setSmartListItemDelegate(smartListDelegate_); + PersonModel::instance().addCollection<PeerProfileCollection>(LoadOptions::FORCE_ENABLED); + ProfileModel::instance().addCollection<LocalProfileCollection>(LoadOptions::FORCE_ENABLED); + PersonModel::instance(). addCollection<WindowsContactBackend>(LoadOptions::FORCE_ENABLED); @@ -416,6 +423,7 @@ CallWidget::callIncoming(Call* call) QApplication::alert(this, 5000); } + //FIXME: This should update accordingly with profile changes ui->callerIdLabel->setText(QString(tr("%1", "%1 is the name of the caller")) .arg(call->formattedName())); ui->callerPhoto->setPixmap( @@ -584,8 +592,10 @@ CallWidget::smartListSelectionChanged(const QItemSelection& newSel, const QItemS Q_UNUSED(oldSel) - if (newSel.indexes().empty()) + if (newSel.indexes().empty()) { + setActualCall(nullptr); return ui->stackedWidget->setCurrentWidget(ui->welcomePage); + } auto newIdx = newSel.indexes().first(); if (not newIdx.isValid()) diff --git a/configurationwidget.cpp b/configurationwidget.cpp index 80d863c075e3bb937d5004fe60ac5e7fc02945c4..2fc7ae907d6570f711b98e380930cb6171aab80a 100644 --- a/configurationwidget.cpp +++ b/configurationwidget.cpp @@ -43,6 +43,7 @@ #include "settingskey.h" #include "utils.h" #include "pathpassworddialog.h" +#include "photoboothdialog.h" #include "accountmodel.h" #include "protocolmodel.h" @@ -50,6 +51,9 @@ #include "callmodel.h" #include "ringtonemodel.h" #include "categorizedhistorymodel.h" +#include "profilemodel.h" +#include "profile.h" +#include "person.h" #ifdef ENABLE_AUTOUPDATE #include "winsparkle.h" @@ -176,6 +180,10 @@ ConfigurationWidget::ConfigurationWidget(QWidget *parent) : ui->updateDayLabel->hide(); ui->autoUpdateCheckBox->hide(); #endif + + auto profile = ProfileModel::instance().selectedProfile(); + ui->avatarButton->setIcon(QPixmap::fromImage(Utils::getCirclePhoto(profile->person()->photo().value<QImage>(), ui->avatarButton->width()))); + ui->profileNameEdit->setText(profile->person()->formattedName()); } void ConfigurationWidget::showPreview() @@ -390,3 +398,24 @@ ConfigurationWidget::on_exportButton_clicked() QtConcurrent::run(func, dlg.path_, dlg.password_); } } + +void +ConfigurationWidget::on_avatarButton_clicked() +{ + PhotoBoothDialog dlg; + dlg.exec(); + if (dlg.result() == QDialog::Accepted) { + auto image = QImage(dlg.fileName_); + auto avatar = image.scaled(100, 100, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation); + ProfileModel::instance().selectedProfile()->person()->setPhoto(avatar); + ProfileModel::instance().selectedProfile()->save(); + ui->avatarButton->setIcon(QPixmap::fromImage(Utils::getCirclePhoto(avatar, ui->avatarButton->width()))); + } +} + +void +ConfigurationWidget::on_profileNameEdit_textEdited(const QString& name) +{ + ProfileModel::instance().selectedProfile()->person()->setFormattedName(name); + ProfileModel::instance().selectedProfile()->save(); +} diff --git a/configurationwidget.h b/configurationwidget.h index 97c6b4d18c9b1b96c59ed76970d240960fa696ab..b82061fda955723da9053085fa333818b59c3c6b 100644 --- a/configurationwidget.h +++ b/configurationwidget.h @@ -62,6 +62,8 @@ private slots: void on_recordPath_clicked(); void on_importButton_clicked(); void on_exportButton_clicked(); + void on_avatarButton_clicked(); + void on_profileNameEdit_textEdited(const QString& name); private slots: void accountSelected(QItemSelection itemSel); diff --git a/configurationwidget.ui b/configurationwidget.ui index b6765fd02b26bae688344596bbd47704d8f8a6d3..dfa5fd9bd6ca8ba9ea2726c798e4703b5d4a0410 100644 --- a/configurationwidget.ui +++ b/configurationwidget.ui @@ -237,6 +237,84 @@ <property name="spacing"> <number>10</number> </property> + <item> + <widget class="QLabel" name="label_9"> + <property name="font"> + <font> + <weight>75</weight> + <bold>true</bold> + </font> + </property> + <property name="text"> + <string>Profile</string> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_10"> + <property name="topMargin"> + <number>0</number> + </property> + <item> + <widget class="QPushButton" name="avatarButton"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>74</width> + <height>74</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>74</width> + <height>74</height> + </size> + </property> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset resource="ressources.qrc"> + <normaloff>:/images/user/btn-default-userpic.svg</normaloff>:/images/user/btn-default-userpic.svg</iconset> + </property> + <property name="iconSize"> + <size> + <width>74</width> + <height>74</height> + </size> + </property> + <property name="flat"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QLineEdit" name="profileNameEdit"> + <property name="placeholderText"> + <string>Name</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_10"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>30</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> <item> <widget class="QLabel" name="label"> <property name="font"> @@ -407,7 +485,7 @@ <property name="sizeHint" stdset="0"> <size> <width>20</width> - <height>40</height> + <height>20</height> </size> </property> </spacer> diff --git a/images/icons/ic_photo_camera_white_24dp_2x.png b/images/icons/ic_photo_camera_white_24dp_2x.png new file mode 100644 index 0000000000000000000000000000000000000000..be9fb226a53ce5ee4008cfafa0754f42284d51b3 Binary files /dev/null and b/images/icons/ic_photo_camera_white_24dp_2x.png differ diff --git a/photoboothdialog.cpp b/photoboothdialog.cpp new file mode 100644 index 0000000000000000000000000000000000000000..156af537aec8697dd63861ed88a3f4beba306e97 --- /dev/null +++ b/photoboothdialog.cpp @@ -0,0 +1,75 @@ +/*************************************************************************** + * Copyright (C) 2016 by Savoir-faire Linux * + * Author: Edric Ladent Milaret <edric.ladent-milaret@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 "photoboothdialog.h" +#include "ui_photoboothdialog.h" + +#include <QFileDialog> + +#include "video/previewmanager.h" + +PhotoBoothDialog::PhotoBoothDialog(QWidget* parent) : + QDialog(parent), + fileName_("profile.png"), + ui(new Ui::PhotoBoothDialog) +{ + ui->setupUi(this); + + Qt::WindowFlags flags = windowFlags(); + flags = flags & (~Qt::WindowContextHelpButtonHint); + setWindowFlags(flags); + + ui->videoFeed->setIsFullPreview(true); + ui->videoFeed->setPhotoMode(true); + Video::PreviewManager::instance().startPreview(); +} + +PhotoBoothDialog::~PhotoBoothDialog() +{ + delete ui; +} + +void +PhotoBoothDialog::closeEvent(QCloseEvent* event) +{ + Q_UNUSED(event) + Video::PreviewManager::instance().stopPreview(); +} + +void +PhotoBoothDialog::on_importButton_clicked() +{ + fileName_ = QFileDialog::getOpenFileName(this, tr("Choose File"), + "", + tr("Files (*)")); + if (fileName_.isEmpty()) + fileName_ = QStringLiteral("profile.png"); + else { + Video::PreviewManager::instance().stopPreview(); + accept(); + } +} + +void +PhotoBoothDialog::on_takePhotoButton_clicked() +{ + auto photo = ui->videoFeed->takePhoto(); + Video::PreviewManager::instance().stopPreview(); + photo.save(fileName_); + accept(); +} diff --git a/photoboothdialog.h b/photoboothdialog.h new file mode 100644 index 0000000000000000000000000000000000000000..3c194929b422016ee9b8ac18ffb1f26122cd3701 --- /dev/null +++ b/photoboothdialog.h @@ -0,0 +1,47 @@ +/*************************************************************************** + * Copyright (C) 2016 by Savoir-faire Linux * + * Author: Edric Ladent Milaret <edric.ladent-milaret@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 <QDialog> + +namespace Ui { +class PhotoBoothDialog; +} + +class PhotoBoothDialog : public QDialog +{ + Q_OBJECT + +public: + explicit PhotoBoothDialog(QWidget* parent = 0); + ~PhotoBoothDialog(); +public: + QString fileName_; + +protected: + void closeEvent(QCloseEvent* event); + +//UI SLOTS +private slots: + void on_importButton_clicked(); + void on_takePhotoButton_clicked(); + +private: + Ui::PhotoBoothDialog* ui; +}; diff --git a/photoboothdialog.ui b/photoboothdialog.ui new file mode 100644 index 0000000000000000000000000000000000000000..8c98b5577499a717d963568e53593f537ed4b032 --- /dev/null +++ b/photoboothdialog.ui @@ -0,0 +1,89 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>PhotoBoothDialog</class> + <widget class="QDialog" name="PhotoBoothDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>791</width> + <height>456</height> + </rect> + </property> + <property name="windowTitle"> + <string>Photobooth</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout" stretch="1,0,0,0"> + <item> + <widget class="VideoWidget" name="videoFeed" native="true"/> + </item> + <item alignment="Qt::AlignHCenter"> + <widget class="QPushButton" name="takePhotoButton"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>40</width> + <height>40</height> + </size> + </property> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset resource="ressources.qrc"> + <normaloff>:/images/icons/ic_photo_camera_white_24dp_2x.png</normaloff>:/images/icons/ic_photo_camera_white_24dp_2x.png</iconset> + </property> + <property name="iconSize"> + <size> + <width>36</width> + <height>36</height> + </size> + </property> + </widget> + </item> + <item alignment="Qt::AlignHCenter|Qt::AlignVCenter"> + <widget class="QLabel" name="label"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>or</string> + </property> + </widget> + </item> + <item alignment="Qt::AlignHCenter"> + <widget class="QPushButton" name="importButton"> + <property name="minimumSize"> + <size> + <width>90</width> + <height>30</height> + </size> + </property> + <property name="text"> + <string>Import</string> + </property> + </widget> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>VideoWidget</class> + <extends>QWidget</extends> + <header>videowidget.h</header> + <container>1</container> + </customwidget> + </customwidgets> + <resources> + <include location="ressources.qrc"/> + </resources> + <connections/> +</ui> diff --git a/pixbufmanipulator.cpp b/pixbufmanipulator.cpp index a9872c70f6809c720811c7412bd895d3f7d1d93f..6bda006438ffa514b10fd250f47ad4ee2203be2b 100644 --- a/pixbufmanipulator.cpp +++ b/pixbufmanipulator.cpp @@ -18,12 +18,32 @@ #include "pixbufmanipulator.h" -#include <QtCore/QSize> -#include <QtCore/QMetaType> +#include <QSize> +#include <QMetaType> +#include <QImage> +#include <QIODevice> +#include <QByteArray> +#include <QBuffer> -#include <person.h> -#include <call.h> -#include <contactmethod.h> +#include "person.h" +#include "call.h" +#include "contactmethod.h" +#include "profilemodel.h" +#include "profile.h" + +#include "utils.h" + +#undef interface + +/*Namespace Interfaces collide with QBuffer*/ +QByteArray QImageToByteArray(QImage image) +{ + QByteArray ba; + QBuffer buffer(&ba); + buffer.open(QIODevice::WriteOnly); + image.save(&buffer, "PNG"); + return ba; +} namespace Interfaces { @@ -77,9 +97,12 @@ PixbufManipulator::contactPhoto(Person* c, const QSize& size, bool displayPresen QVariant PixbufManipulator::personPhoto(const QByteArray& data, const QString& type) { - Q_UNUSED(type); - Q_UNUSED(data); - return QVariant(); + QImage avatar; + QByteArray ba = type.toLatin1(); + const char* c_str2 = ba.data(); + if (avatar.loadFromData(data.fromBase64(data), c_str2)) + return Utils::getCirclePhoto(avatar, avatar.size().width()); + return fallbackAvatar_; } QVariant @@ -99,11 +122,14 @@ PixbufManipulator::securityIssueIcon(const QModelIndex& index) return QVariant(); } + + QByteArray PixbufManipulator::toByteArray(const QVariant& pxm) { - Q_UNUSED(pxm); - return QByteArray(); + auto image = pxm.value<QImage>(); + QByteArray ba = QImageToByteArray(image); + return ba; } QVariant @@ -180,7 +206,9 @@ QVariant PixbufManipulator::decorationRole(const Person* p) QVariant PixbufManipulator::decorationRole(const Account* acc) { Q_UNUSED(acc) - return QVariant(); + return Utils::getCirclePhoto(ProfileModel::instance(). + selectedProfile()->person()->photo().value<QImage>(), + imgSize_.width()); } } // namespace Interfaces diff --git a/pixbufmanipulator.h b/pixbufmanipulator.h index fc81cd6eabb37912748ecf09f00ca9c31cfb4222..d42237e7fc750ff640323025c1ca417ec170f019 100644 --- a/pixbufmanipulator.h +++ b/pixbufmanipulator.h @@ -27,6 +27,8 @@ Q_DECLARE_METATYPE(QImage); class Person; +QByteArray QImageToByteArray(QImage image); + namespace Interfaces { class PixbufManipulator : public PixmapManipulatorI { diff --git a/ressources.qrc b/ressources.qrc index 23b356d9e90da373cc2c3727babeabaca081b24e..1450be38c253dc436406ce28395a637bb428e220 100644 --- a/ressources.qrc +++ b/ressources.qrc @@ -37,5 +37,6 @@ <file>images/icons/ic_arrow_tab_next_black_9dp_2x.png</file> <file>images/icons/ic_arrow_tab_previous_black_9dp_2x.png</file> <file>images/spikeMask.png</file> + <file>images/icons/ic_photo_camera_white_24dp_2x.png</file> </qresource> </RCC> diff --git a/stylesheet.css b/stylesheet.css index 76ccc2a425f1cdf02fae3cb4f89cdde9e1bea856..49e085afa01429bf4f1607dc2fb1dfa00b03b202 100644 --- a/stylesheet.css +++ b/stylesheet.css @@ -268,7 +268,7 @@ QWidget#messagingPage{ } QPushButton#wizardButton, QPushButton#playButton, QPushButton#clearHistoryButton, QPushButton#doTransferButton, -QPushButton#checkUpdateButton{ +QPushButton#checkUpdateButton, QPushButton#photoButton, QPushButton#takePhotoButton, QPushButton#importButton{ background-color: #3AC0D2; border: 0px; color: white; @@ -276,12 +276,14 @@ QPushButton#checkUpdateButton{ } QPushButton#wizardButton:hover, QPushButton#playButton:hover, QPushButton#clearHistoryButton:hover, -QPushButton#doTransferButton:hover{ +QPushButton#doTransferButton:hover, QPushButton#photoButton:hover, +QPushButton#takePhotoButton:hover, QPushButton#importButton:hover{ background-color: #4dc6d6; } QPushButton#wizardButton:pressed, QPushButton#playButton:pressed, QPushButton#clearHistoryButton:pressed, -QPushButton#doTransferButton:pressed{ +QPushButton#doTransferButton:pressed, QPushButton#photoButton:pressed, +QPushButton#takePhotoButton:pressed, QPushButton#importButton:pressed{ background-color: #34acbd; } @@ -508,6 +510,11 @@ QPushButton#upAudioButton, QPushButton#downAudioButton, QPushButton#upVideoButto background: transparent; } +QPushButton#avatarButton:hover { + border: 2px solid rgb(77, 77, 77); + border-radius: 37px; +} + QWidget#leftPannel{ background: white; } diff --git a/utils.cpp b/utils.cpp index 49bbd7bda5aa03b266b53330d8122f115d077c04..2f133b7bbb25c94551bf89c11da5d23257437342 100644 --- a/utils.cpp +++ b/utils.cpp @@ -31,6 +31,7 @@ //Qt #include <QObject> #include <QErrorMessage> +#include <QPainter> bool Utils::CreateStartupLink() @@ -161,7 +162,7 @@ Utils::GetCurrentUserName() { wchar_t username[UNLEN+1]; DWORD username_len = UNLEN+1; GetUserName(username, &username_len); - return QString::fromWCharArray(username, username_len); + return QString::fromWCharArray(username, username_len-1); #else return QString(); #endif @@ -185,3 +186,25 @@ Utils::InvokeMailto(const QString& subject, } #endif } + +QImage +Utils::getCirclePhoto(const QImage original, int sizePhoto) +{ + QImage target(sizePhoto, sizePhoto, QImage::Format_ARGB32_Premultiplied); + target.fill(Qt::transparent); + + QPainter painter(&target); + painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform); + painter.setBrush(QBrush(Qt::white)); + auto scaledPhoto = original + .scaled(sizePhoto, sizePhoto, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation) + .convertToFormat(QImage::Format_ARGB32_Premultiplied); + int margin = 0; + if (scaledPhoto.width() > sizePhoto) { + margin = (scaledPhoto.width() - sizePhoto) / 2; + } + painter.drawEllipse(0, 0, sizePhoto, sizePhoto); + painter.setCompositionMode(QPainter::CompositionMode_SourceIn); + painter.drawImage(0, 0, scaledPhoto, margin, 0); + return target; +} diff --git a/utils.h b/utils.h index 36489149783bb4cf350fe71ac5e54d642b4c5f01..1ac3dfdcbe54c286164802b2d6a3abb4ecf15fab 100644 --- a/utils.h +++ b/utils.h @@ -29,6 +29,7 @@ #include <string> #include <QString> +#include <QImage> class Utils { @@ -42,5 +43,6 @@ public: static QString GetISODate(); static QString GetCurrentUserName(); static void InvokeMailto(const QString& subject, const QString& body, const QString& attachement = QString()); + static QImage getCirclePhoto(const QImage original, int sizePhoto); }; diff --git a/videowidget.cpp b/videowidget.cpp index 70a44671bd30a4c14c0275faa7e4f49aec9adc93..b7ab005c4c05b40f8317c0583b4f9831b0f450e3 100644 --- a/videowidget.cpp +++ b/videowidget.cpp @@ -18,6 +18,8 @@ #include "videowidget.h" +#include "utils.h" + VideoWidget::VideoWidget(QWidget* parent) : QWidget(parent) , previewRenderer_(nullptr) @@ -121,7 +123,11 @@ VideoWidget::paintEvent(QPaintEvent* evt) { if(resetPreview_) { auto previewHeight = fullPreview_ ? height() : height() / 4; auto previewWidth = fullPreview_ ? width() : width() / 4; - auto scaledPreview = previewImage_->scaled(previewWidth, previewHeight, Qt::KeepAspectRatio); + QImage scaledPreview; + if (photoMode_) + scaledPreview = Utils::getCirclePhoto(*previewImage_, previewHeight); + else + scaledPreview = previewImage_->scaled(previewWidth, previewHeight, Qt::KeepAspectRatio); auto xDiff = (previewWidth - scaledPreview.width()) / 2; auto yDiff = (previewHeight - scaledPreview.height()) / 2; auto yPos = fullPreview_ ? yDiff : height() - previewHeight - previewMargin_; @@ -131,11 +137,16 @@ VideoWidget::paintEvent(QPaintEvent* evt) { resetPreview_ = false; } - auto scaledPreview = previewImage_->scaled(previewGeometry_.width(), - previewGeometry_.height(), - Qt::KeepAspectRatio); + QImage scaledPreview; + if (photoMode_) + scaledPreview = Utils::getCirclePhoto(*previewImage_, previewGeometry_.height()); + else + scaledPreview = previewImage_->scaled(previewGeometry_.width(), + previewGeometry_.height(), + Qt::KeepAspectRatio); previewGeometry_.setWidth(scaledPreview.width()); previewGeometry_.setHeight(scaledPreview.height()); + painter.drawImage(previewGeometry_, scaledPreview); } } @@ -186,3 +197,22 @@ void VideoWidget::setIsFullPreview(bool full) { fullPreview_ = full; } + +QImage +VideoWidget::takePhoto() { + if (previewImage_) + return previewImage_.get()->copy(); + return QImage(); +} + +void +VideoWidget::setPhotoMode(bool isPhotoMode) { + + photoMode_ = isPhotoMode; + auto color = isPhotoMode ? Qt::transparent : Qt::black; + + QPalette pal(palette()); + pal.setColor(QPalette::Background, color); + setAutoFillBackground(true); + setPalette(pal); +} diff --git a/videowidget.h b/videowidget.h index 7b2dec206071257a936e2b00e643cc1c3b4d5b83..662d11ca022399f8f03192087b6653fc1c35039e 100644 --- a/videowidget.h +++ b/videowidget.h @@ -37,7 +37,9 @@ public: void setPreviewDisplay(bool display); void setDistantRenderer(Video::Renderer* renderer); void setIsFullPreview(bool full); - inline void setResetPreview(bool reset){ resetPreview_ = reset; }; + inline void setResetPreview(bool reset){ resetPreview_ = reset; } + void setPhotoMode(bool isPhotoMode); + QImage takePhoto(); public slots: void previewStarted(Video::Renderer* renderer); @@ -45,7 +47,7 @@ public slots: void frameFromPreview(); void frameFromDistant(); void renderingStopped(); - inline QRect& getPreviewRect(){ return previewGeometry_; }; + inline QRect& getPreviewRect(){ return previewGeometry_; } private: Video::Renderer* previewRenderer_; @@ -61,6 +63,7 @@ private: bool fullPreview_; QRect previewGeometry_; bool resetPreview_ = false; + bool photoMode_ = false; constexpr static int previewMargin_ = 15; }; diff --git a/windowscontactbackend.cpp b/windowscontactbackend.cpp index 60ca74495bc22eff241e959fd5ccf26ea3cefa8d..31ebe3029a126cb3c3a5acaf1ebcf0ff6828770b 100644 --- a/windowscontactbackend.cpp +++ b/windowscontactbackend.cpp @@ -290,7 +290,7 @@ WindowsContactBackend::getPersonFromContactFile(const QDir& contactDir, QImage photo; photo.load(photoValue); if (not photo.isNull()) - p->setPhoto(getCirclePhoto(photo)); + p->setPhoto(Utils::getCirclePhoto(photo, sizePhoto_)); } } else if (name == "EmailAddress") { @@ -345,23 +345,6 @@ WindowsContactBackend::getPersonFromContactFile(const QDir& contactDir, } } -QImage WindowsContactBackend::getCirclePhoto(const QImage original) -{ - QImage target(sizePhoto_, sizePhoto_, QImage::Format_ARGB32_Premultiplied); - target.fill(Qt::transparent); - - QPainter painter(&target); - painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform); - painter.setBrush(QBrush(Qt::white)); - painter.drawEllipse(0, 0, sizePhoto_, sizePhoto_); - painter.setCompositionMode(QPainter::CompositionMode_SourceIn); - painter.drawImage(0, 0, - original - .scaled(60, 60, Qt::KeepAspectRatio, Qt::SmoothTransformation) - .convertToFormat(QImage::Format_ARGB32_Premultiplied)); - return target; -} - bool WindowsContactBackend::reload() { diff --git a/windowscontactbackend.h b/windowscontactbackend.h index da80eca87a6b85dd461ead615d21f5fa1fa44db2..4d0f7c3dd4ba7d3e55ff21d088bdc3e765e4cb81 100644 --- a/windowscontactbackend.h +++ b/windowscontactbackend.h @@ -55,7 +55,6 @@ private: private: bool getPersonFromContactFile(const QDir &contactDir, const QString& contactFileName); - QImage getCirclePhoto(const QImage original); }; class WindowsContactEditor : public CollectionEditor<Person> diff --git a/wizarddialog.cpp b/wizarddialog.cpp index c1f82eba76aa177498aa83f447846a6cddbd831f..be953c97c3a7d81daae7092dc99a0ffa07053384 100644 --- a/wizarddialog.cpp +++ b/wizarddialog.cpp @@ -23,10 +23,13 @@ #include "accountmodel.h" #include "account.h" +#include "profilemodel.h" +#include "profile.h" #include "utils.h" +#include "photoboothdialog.h" -WizardDialog::WizardDialog(QWidget *parent) : +WizardDialog::WizardDialog(QWidget* parent) : QDialog(parent), ui(new Ui::WizardDialog) { @@ -56,21 +59,29 @@ WizardDialog::accept() ui->wizardButton->setEnabled(false); ui->usernameEdit->setEnabled(false); + auto profile = ProfileModel::instance().selectedProfile(); + repaint(); Utils::CreateStartupLink(); auto account = AccountModel::instance().add(ui->usernameEdit->text(), Account::Protocol::RING); - if (not ui->usernameEdit->text().isEmpty()) + if (not ui->usernameEdit->text().isEmpty()) { account->setDisplayName(ui->usernameEdit->text()); - else - account->setDisplayName(tr("Unknown")); + profile->person()->setFormattedName(ui->usernameEdit->text()); + } + else { + profile->person()->setFormattedName(tr("Unknown")); + } account->setRingtonePath(Utils::GetRingtonePath()); account->setUpnpEnabled(true); connect(account, SIGNAL(changed(Account*)), this, SLOT(endSetup(Account*))); account->performAction(Account::EditAction::SAVE); + + profile->setAccounts({account}); + profile->save(); } void @@ -81,9 +92,22 @@ WizardDialog::endSetup(Account* a) } void -WizardDialog::closeEvent(QCloseEvent *event) +WizardDialog::closeEvent(QCloseEvent* event) { Q_UNUSED(event) exit(0); } + +void +WizardDialog::on_avatarButton_clicked() +{ + PhotoBoothDialog dlg; + dlg.exec(); + if (dlg.result() == QDialog::Accepted) { + auto image = QImage(dlg.fileName_); + auto avatar = image.scaled(100, 100, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation); + ProfileModel::instance().selectedProfile()->person()->setPhoto(avatar); + ui->avatarButton->setIcon(QPixmap::fromImage(Utils::getCirclePhoto(avatar, ui->avatarButton->width()))); + } +} diff --git a/wizarddialog.h b/wizarddialog.h index 87a4cb658bf1fb73dc50d58862ad39607ec91cc6..ba1865d94a8f5384638566eb60c3e53e632c1f3a 100644 --- a/wizarddialog.h +++ b/wizarddialog.h @@ -22,6 +22,7 @@ #include <QtConcurrent/QtConcurrent> #include "account.h" +#include "person.h" namespace Ui { class WizardDialog; @@ -32,21 +33,24 @@ class WizardDialog : public QDialog Q_OBJECT public: - explicit WizardDialog(QWidget *parent = 0); + explicit WizardDialog(QWidget* parent = 0); ~WizardDialog(); +// Overrided function protected slots: - void closeEvent(QCloseEvent *event); -private slots: void accept(); + void closeEvent(QCloseEvent* event); -private: - Ui::WizardDialog *ui; - -private: - void setup(); +//UI Slots +private slots: + void on_avatarButton_clicked(); private slots: void endSetup(Account* a); + +private: + Ui::WizardDialog* ui; + + void setup(); }; diff --git a/wizarddialog.ui b/wizarddialog.ui index 7caf3a9cadc26ecab95f42470170df7c94b7c1e6..1198ec373593cde2578c0ecba4c036e3943deac0 100644 --- a/wizarddialog.ui +++ b/wizarddialog.ui @@ -7,7 +7,7 @@ <x>0</x> <y>0</y> <width>500</width> - <height>246</height> + <height>370</height> </rect> </property> <property name="sizePolicy"> @@ -19,7 +19,7 @@ <property name="minimumSize"> <size> <width>500</width> - <height>246</height> + <height>370</height> </size> </property> <property name="windowTitle"> @@ -75,6 +75,44 @@ </property> </spacer> </item> + <item alignment="Qt::AlignHCenter"> + <widget class="QPushButton" name="avatarButton"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>74</width> + <height>74</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>74</width> + <height>74</height> + </size> + </property> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset resource="ressources.qrc"> + <normaloff>:/images/user/btn-default-userpic.svg</normaloff>:/images/user/btn-default-userpic.svg</iconset> + </property> + <property name="iconSize"> + <size> + <width>74</width> + <height>74</height> + </size> + </property> + <property name="flat"> + <bool>true</bool> + </property> + </widget> + </item> <item alignment="Qt::AlignHCenter"> <widget class="QLabel" name="label"> <property name="font">