Commit 67007d13 authored by Edric Milaret's avatar Edric Milaret Committed by Guillaume Roguez

windows: add partial contact backend

Refs #72110

Change-Id: Ib6177477a92e0a03e7eefd0de7c723abea2b0e40
parent 34eb9202
......@@ -38,7 +38,8 @@ SOURCES += main.cpp\
pivotcontrol.cpp \
videowidget.cpp \
utils.cpp \
wizarddialog.cpp
wizarddialog.cpp \
windowscontactbackend.cpp
HEADERS += mainwindow.h \
callwidget.h \
......@@ -54,7 +55,8 @@ HEADERS += mainwindow.h \
pivotcontrol.h \
videowidget.h \
utils.h \
wizarddialog.h
wizarddialog.h \
windowscontactbackend.h
FORMS += mainwindow.ui \
callwidget.ui \
......
......@@ -26,6 +26,8 @@
#include "personmodel.h"
#include "fallbackpersoncollection.h"
#include "accountmodel.h"
#include "categorizedcontactmodel.h"
#include "windowscontactbackend.h"
#include "wizarddialog.h"
......@@ -53,12 +55,26 @@ CallWidget::CallWidget(QWidget *parent) :
connect(callModel_, SIGNAL(callStateChanged(Call*, Call::State)),
this, SLOT(callStateChanged(Call*, Call::State)));
connect(AccountModel::instance()
, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector<int>))
, this
, SLOT(findRingAccount(QModelIndex, QModelIndex, QVector<int>)));
ui->callList->setModel(callModel_);
CategorizedHistoryModel::instance()->
addCollection<MinimalHistoryBackend>(LoadOptions::FORCE_ENABLED);
PersonModel::instance()->
addCollection<FallbackPersonCollection>(LoadOptions::FORCE_ENABLED);
PersonModel::instance()->
addCollection<WindowsContactBackend>(LoadOptions::FORCE_ENABLED);
ui->historyList->setModel(CategorizedHistoryModel::instance());
CategorizedContactModel::instance()->setSortAlphabetical(false);
ui->contactView->setModel(CategorizedContactModel::instance());
ui->contactView->setHeaderHidden(true);
ui->speakerSlider->setValue(Audio::Settings::instance()->playbackVolume());
ui->micSlider->setValue(Audio::Settings::instance()->captureVolume());
......@@ -75,7 +91,33 @@ CallWidget::~CallWidget()
}
void
CallWidget::findRingAccount() {
CallWidget::findRingAccount(QModelIndex idx1, QModelIndex idx2, QVector<int> vec)
{
Q_UNUSED(idx1)
Q_UNUSED(idx2)
Q_UNUSED(vec)
auto a_count = AccountModel::instance()->rowCount();
auto found = false;
for (int i = 0; i < a_count; ++i) {
auto idx = AccountModel::instance()->index(i, 0);
auto protocol = idx.data(static_cast<int>(Account::Role::Proto));
if ((Account::Protocol)protocol.toUInt() == Account::Protocol::RING) {
auto username = idx.data(static_cast<int>(Account::Role::Username));
ui->ringIdLabel->setText(
"Your Ring ID: " + username.toString());
found = true;
return;
}
}
if (not found){
ui->ringIdLabel->setText("NO RING ACCOUNT FOUND");
}
}
void
CallWidget::findRingAccount()
{
auto a_count = AccountModel::instance()->rowCount();
auto found = false;
......@@ -94,7 +136,6 @@ CallWidget::findRingAccount() {
WizardDialog *wizardDialog = new WizardDialog();
wizardDialog->exec();
delete wizardDialog;
findRingAccount();
}
}
......@@ -150,19 +191,21 @@ CallWidget::addedCall(Call* call, Call* parent) {
}
void
CallWidget::callStateChanged(Call* call, Call::State previousState) {
CallWidget::callStateChanged(Call* call, Call::State previousState)
{
Q_UNUSED(previousState)
ui->callList->setCurrentIndex(callModel_->getIndex(actualCall_));
if (call->state() == Call::State::OVER) {
actualCall_ = nullptr;
ui->videoWidget->hide();
} else if (call->state() == Call::State::HOLD) {
ui->videoWidget->hide();
} else {
ui->videoWidget->show();
connect(actualCall_, SIGNAL(isOver(Call*)),
this, SLOT(callStateChanged(Call*,Call::State::OVER)));
ui->messageOutput->setModel(
IMConversationManager::instance()->getModel(actualCall_));
}
ui->callStateLabel->setText("Call State : " + state.at((int)call->state()));
}
void
......@@ -220,3 +263,27 @@ void
CallWidget::atExit() {
}
void
CallWidget::on_contactView_doubleClicked(const QModelIndex &index)
{
auto contact = index.data((int)ContactMethod::Role::Uri);
QString uri;
if (contact.isValid()) {
uri = contact.toString();
} else {
auto var = index.data((int)Person::Role::Object);
if (var.isValid()) {
Person* person = var.value<Person*>();
if (person->phoneNumbers().size() > 0) {
uri = person->phoneNumbers().at(0)->uri();
}
}
}
if (not uri.isEmpty()) {
auto outCall = CallModel::instance()->dialingCall(uri);
outCall->setDialNumber(uri);
outCall->performAction(Call::Action::ACCEPT);
}
}
......@@ -20,6 +20,8 @@
#define CALLWIDGET_H
#include <QWidget>
#include <QVector>
#include <QString>
#include "navwidget.h"
......@@ -38,6 +40,12 @@ class CallWidget : public NavWidget
{
Q_OBJECT
const QVector<QString> state = {"New", "Incoming", "Ringing", "Current",
"Dialing", "Hold", "Failure", "Busy",
"Transferred", "Transfer hold", "Over",
"Error", "Conference",
"Conference Hold", "Initialization",
"Aborted", "Connected"};
public:
explicit CallWidget(QWidget *parent = 0);
~CallWidget();
......@@ -56,11 +64,13 @@ private slots:
void on_speakerSlider_sliderReleased();
void on_micSlider_sliderMoved(int position);
void on_micSlider_sliderReleased();
void on_contactView_doubleClicked(const QModelIndex &index);
private slots:
void callIncoming(Call *call);
void addedCall(Call *call, Call *parent);
void callStateChanged(Call *call, Call::State previousState);
void findRingAccount(QModelIndex idx1, QModelIndex idx2, QVector<int> vec);
private:
Ui::CallWidget *ui;
......
......@@ -49,32 +49,86 @@
</property>
<property name="maximumSize">
<size>
<width>200</width>
<width>220</width>
<height>16777215</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QTreeView" name="historyList">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<widget class="QTabWidget" name="tabWidget">
<property name="maximumSize">
<size>
<width>200</width>
<width>220</width>
<height>16777215</height>
</size>
</property>
<property name="currentIndex">
<number>1</number>
</property>
<widget class="QWidget" name="historyTab">
<attribute name="title">
<string>History</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_6">
<property name="leftMargin">
<number>4</number>
</property>
<property name="topMargin">
<number>4</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>4</number>
</property>
<item>
<widget class="QTreeView" name="historyList">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>200</width>
<height>16777215</height>
</size>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="contactTab">
<attribute name="title">
<string>Contact</string>
</attribute>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="leftMargin">
<number>4</number>
</property>
<property name="topMargin">
<number>4</number>
</property>
<property name="rightMargin">
<number>4</number>
</property>
<property name="bottomMargin">
<number>4</number>
</property>
<item>
<widget class="QTreeView" name="contactView"/>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
......@@ -184,6 +238,13 @@
</layout>
</widget>
</item>
<item alignment="Qt::AlignHCenter">
<widget class="QLabel" name="callStateLabel">
<property name="text">
<string>Call State :</string>
</property>
</widget>
</item>
<item>
<widget class="QWidget" name="horizontalWidget" native="true">
<property name="sizePolicy">
......
......@@ -29,7 +29,7 @@
<attribute name="title">
<string>Video</string>
</attribute>
<layout class="QGridLayout" name="gridLayout" rowstretch="0,0" columnstretch="0,0">
<layout class="QGridLayout" name="gridLayout" rowstretch="0,1" columnstretch="0,0">
<item row="0" column="0">
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="spacing">
......@@ -224,14 +224,24 @@
</widget>
</item>
<item>
<widget class="QCheckBox" name="startupBox">
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="topMargin">
<number>0</number>
</property>
<property name="text">
<string>Launch Ring on Startup</string>
<property name="rightMargin">
<number>10</number>
</property>
</widget>
<item alignment="Qt::AlignRight">
<widget class="QCheckBox" name="startupBox">
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
</property>
<property name="text">
<string>Launch Ring on Startup</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
......
/***************************************************************************
* Copyright (C) 2015 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 "windowscontactbackend.h"
WindowsContactEditor::WindowsContactEditor(CollectionMediator<Person> *m
, WindowsContactBackend *parent)
: CollectionEditor<Person>(m),collection_(parent)
{
}
WindowsContactEditor::~WindowsContactEditor()
{
}
bool
WindowsContactEditor::save(const Person *item)
{
Q_UNUSED(item)
return false;
}
bool
WindowsContactEditor::remove(const Person *item)
{
Q_UNUSED(item)
return false;
}
bool
WindowsContactEditor::edit(Person *item)
{
Q_UNUSED(item)
return false;
}
bool
WindowsContactEditor::addNew(const Person *item)
{
Q_UNUSED(item)
return false;
}
bool
WindowsContactEditor::addExisting(const Person *item)
{
items_ << const_cast<Person*>(item);
mediator()->addItem(item);
return true;
}
QVector<Person*>
WindowsContactEditor::items() const
{
return items_;
}
WindowsContactBackend::WindowsContactBackend(CollectionMediator<Person>* mediator,
CollectionInterface* parent)
: CollectionInterface(new WindowsContactEditor(mediator,this), parent)
, mediator_(mediator)
{
}
WindowsContactBackend::~WindowsContactBackend()
{
}
bool
WindowsContactBackend::load()
{
QtConcurrent::run(this, &WindowsContactBackend::loadRun);
return true;
}
bool
WindowsContactBackend::loadRun()
{
QDir contactDir(QStandardPaths::writableLocation
(QStandardPaths::HomeLocation) + "/Contacts");
QStringList filesList = contactDir.entryList(QStringList("*.contact"));
for(auto contactFileName : filesList) {
QString contactFilePath
(contactDir.absolutePath() + "/" + contactFileName);
QFile contactFile(contactFilePath);
if (contactFile.open(QIODevice::ReadOnly)) {
QXmlStreamReader reader;
Person *p = new Person();
QVector<ContactMethod*> contactMethod;
reader.setDevice(&contactFile);
while (!reader.atEnd()) {
reader.readNext();
if (reader.isStartElement()) {
QString name = reader.name().toString();
if (name == "FormattedName")
p->setFormattedName(reader.readElementText());
else if (name == "NickName")
p->setNickName(reader.readElementText());
else if (name == "GivenName")
p->setFirstName(reader.readElementText());
else if (name == "FamilyName")
p->setFamilyName(reader.readElementText());
else if (name == "Company")
p->setOrganization(reader.readElementText());
else if (name == "Department")
p->setDepartment(reader.readElementText());
else if (name == "Number") {
QString number = reader.readElementText();
if (not number.isEmpty()) {
ContactMethod *contact = PhoneDirectoryModel::instance()->getNumber(number);
contactMethod.append(contact);
}
}
else if (name == "Photo") {
//FIXME: It seems to be possible to have multiple photo...
reader.readNext();
if (reader.name().toString() == "Value") {
QString photoValue = reader.readElementText();
QByteArray byteArray;
byteArray.append(photoValue);
p->setPhoto(byteArray);
}
}
else if (name == "EmailAddress") {
QString address;
bool isPreferred = false;
reader.readNext();
while (reader.name().toString() != "EmailAddress"
&& !reader.atEnd()) {
if (reader.isStartElement()) {
QString tag = reader.name().toString();
if (tag == "Address")
address = reader.readElementText();
else if (tag == "Label")
if (reader.readElementText() == "Preferred")
isPreferred = true;
}
reader.readNext();
}
if (isPreferred)
p->setPreferredEmail(address);
}
}
}
if (reader.hasError()) {
qDebug() << reader.errorString();
} else {
if (contactMethod.size() > 0)
p->setContactMethods(contactMethod);
editor<Person>()->addExisting(p);
}
} else {
qDebug() << "Error Opening contact file : " << contactFileName;
}
}
return false;
}
bool
WindowsContactBackend::reload()
{
return false;
}
bool
WindowsContactBackend::clear()
{
return false;
}
QString
WindowsContactBackend::name() const
{
return "Windows Contact Backend";
}
QString
WindowsContactBackend::category() const
{
return "Contacts";
}
bool
WindowsContactBackend::isEnabled() const
{
return true;
}
QByteArray
WindowsContactBackend::id() const
{
return "wincb";
}
FlagPack<CollectionInterface::SupportedFeatures> WindowsContactBackend::supportedFeatures() const
{
return (
CollectionInterface::SupportedFeatures::NONE |
CollectionInterface::SupportedFeatures::LOAD);
}
/***************************************************************************
* Copyright (C) 2015 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/>. *
**************************************************************************/
#ifndef WINDOWSCONTACTBACKEND_H
#define WINDOWSCONTACTBACKEND_H
#include <QObject>
#include <QStandardPaths>
#include <QDir>
#include <QXmlStreamReader>
#include <QtConcurrent/QtConcurrent>
#include "person.h"
#include "collectioninterface.h"
#include "contactmethod.h"
#include "phonedirectorymodel.h"
class WindowsContactBackend : public CollectionInterface
{
public:
explicit WindowsContactBackend(CollectionMediator<Person>* mediator, CollectionInterface* parent = nullptr);
virtual ~WindowsContactBackend();
virtual bool load() override;
virtual bool reload() override;
virtual bool clear() override;
virtual QString name () const override;
virtual QString category () const override;
virtual bool isEnabled() const override;
virtual QByteArray id () const override;
virtual FlagPack<CollectionInterface::SupportedFeatures> supportedFeatures() const override;
private:
bool loadRun();
private:
CollectionMediator<Person>* mediator_;
};
class WindowsContactEditor : public CollectionEditor<Person>
{
public:
WindowsContactEditor(CollectionMediator<Person>* m, WindowsContactBackend* parent);
~WindowsContactEditor();
virtual bool save ( const Person* item ) override;
virtual bool remove ( const Person* item ) override;
virtual bool edit ( Person* item ) override;
virtual bool addNew ( const Person* item ) override;
virtual bool addExisting( const Person* item ) override;
private:
virtual QVector<Person*> items() const override;
QVector<Person*> items_;
WindowsContactBackend* collection_;
};
#endif // WINDOWSCONTACTBACKEND_H
/***************************************************************************
* Copyright (C) 2015 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 "wizarddialog.h"
#include "ui_wizarddialog.h"
......@@ -23,12 +41,30 @@ WizardDialog::~WizardDialog()
}
void
WizardDialog::on_buttonBox_accepted()
WizardDialog::accept()
{
ui->label->setText("Working...");
ui->buttonBox->setEnabled(false);
ui->usernameEdit->setEnabled(false);
QtConcurrent::run(this, &WizardDialog::setup).waitForFinished();
}
void
WizardDialog::endSetup()
{
QDialog::accept();
}
void
WizardDialog::setup()
{
auto account = AccountModel::instance()->add(ui->usernameEdit->text(), Account::Protocol::RING);
AccountModel::instance()->ip2ip()->setRingtonePath(Utils::GetRingtonePath());
account->setRingtonePath(Utils::GetRingtonePath());
AccountModel::instance()->save();
Utils::CreateStartupLink();
endSetup();
}
void
......
/***************************************************************************
* Copyright (C) 2015 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/>. *
**************************************************************************/
#ifndef WIZARDDIALOG_H
#define WIZARDDIALOG_H
#include <QDialog>
#include <QtConcurrent/QtConcurrent>
namespace Ui {
class WizardDialog;
......@@ -16,12 +35,16 @@ public:
~WizardDialog();
private slots:
void on_buttonBox_accepted();
void on_usernameEdit_textChanged(const QString &arg1);
void accept();
void endSetup();
private:
Ui::WizardDialog *ui;
private:
void setup();
};
#endif // WIZARDDIALOG_H
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