mirror of
https://gitlab.linphone.org/BC/public/linphone-desktop.git
synced 2026-01-17 11:28:07 +00:00
call history
new item: popup button
This commit is contained in:
parent
4ed07c9104
commit
97c01e66f8
28 changed files with 1379 additions and 234 deletions
|
|
@ -34,6 +34,7 @@
|
|||
|
||||
#include "core/account/AccountCore.hpp"
|
||||
#include "core/account/AccountProxy.hpp"
|
||||
#include "core/call-history/CallHistoryProxy.hpp"
|
||||
#include "core/call/CallCore.hpp"
|
||||
#include "core/call/CallGui.hpp"
|
||||
#include "core/call/CallList.hpp"
|
||||
|
|
@ -157,6 +158,7 @@ void App::initCppInterfaces() {
|
|||
qmlRegisterUncreatableType<AccountCore>(Constants::MainQmlUri, 1, 0, "AccountCore", QLatin1String("Uncreatable"));
|
||||
qmlRegisterUncreatableType<CallCore>(Constants::MainQmlUri, 1, 0, "CallCore", QLatin1String("Uncreatable"));
|
||||
qmlRegisterType<CallProxy>(Constants::MainQmlUri, 1, 0, "CallProxy");
|
||||
qmlRegisterType<CallHistoryProxy>(Constants::MainQmlUri, 1, 0, "CallHistoryProxy");
|
||||
qmlRegisterType<CallGui>(Constants::MainQmlUri, 1, 0, "CallGui");
|
||||
qmlRegisterType<FriendGui>(Constants::MainQmlUri, 1, 0, "FriendGui");
|
||||
qmlRegisterUncreatableType<FriendCore>(Constants::MainQmlUri, 1, 0, "FriendCore", QLatin1String("Uncreatable"));
|
||||
|
|
|
|||
|
|
@ -8,6 +8,10 @@ list(APPEND _LINPHONEAPP_SOURCES
|
|||
core/call/CallGui.cpp
|
||||
core/call/CallList.cpp
|
||||
core/call/CallProxy.cpp
|
||||
core/call-history/CallHistoryCore.cpp
|
||||
core/call-history/CallHistoryGui.cpp
|
||||
core/call-history/CallHistoryList.cpp
|
||||
core/call-history/CallHistoryProxy.cpp
|
||||
core/camera/CameraGui.cpp
|
||||
core/camera/CameraDummy.cpp
|
||||
core/friend/FriendCore.cpp
|
||||
|
|
|
|||
|
|
@ -23,11 +23,11 @@
|
|||
#include "AccountList.hpp"
|
||||
|
||||
AccountProxy::AccountProxy(QObject *parent) : SortFilterProxy(parent) {
|
||||
mList = AccountList::create();
|
||||
connect(mList.get(), &AccountList::countChanged, this, &AccountProxy::resetDefaultAccount);
|
||||
connect(mList.get(), &AccountList::defaultAccountChanged, this, &AccountProxy::resetDefaultAccount);
|
||||
connect(mList.get(), &AccountList::haveAccountChanged, this, &AccountProxy::haveAccountChanged);
|
||||
setSourceModel(mList.get());
|
||||
mAccountList = AccountList::create();
|
||||
connect(mAccountList.get(), &AccountList::countChanged, this, &AccountProxy::resetDefaultAccount);
|
||||
connect(mAccountList.get(), &AccountList::defaultAccountChanged, this, &AccountProxy::resetDefaultAccount);
|
||||
connect(mAccountList.get(), &AccountList::haveAccountChanged, this, &AccountProxy::haveAccountChanged);
|
||||
setSourceModel(mAccountList.get());
|
||||
sort(0);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ protected:
|
|||
|
||||
QString mFilterText;
|
||||
AccountGui *mDefaultAccount = nullptr; // When null, a new UI object is build from List
|
||||
QSharedPointer<AccountList> mList;
|
||||
QSharedPointer<AccountList> mAccountList;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
81
Linphone/core/call-history/CallHistoryCore.cpp
Normal file
81
Linphone/core/call-history/CallHistoryCore.cpp
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of linphone-desktop
|
||||
* (see https://www.linphone.org).
|
||||
*
|
||||
* 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 "CallHistoryCore.hpp"
|
||||
#include "core/App.hpp"
|
||||
#include "model/call-history/CallHistoryModel.hpp"
|
||||
#include "model/object/VariantObject.hpp"
|
||||
#include "model/tool/ToolModel.hpp"
|
||||
#include "tool/Utils.hpp"
|
||||
#include "tool/thread/SafeConnection.hpp"
|
||||
|
||||
#include <QDateTime>
|
||||
|
||||
DEFINE_ABSTRACT_OBJECT(CallHistoryCore)
|
||||
|
||||
QSharedPointer<CallHistoryCore> CallHistoryCore::create(const std::shared_ptr<linphone::CallLog> &callLog) {
|
||||
auto sharedPointer = QSharedPointer<CallHistoryCore>(new CallHistoryCore(callLog), &QObject::deleteLater);
|
||||
sharedPointer->setSelf(sharedPointer);
|
||||
sharedPointer->moveToThread(App::getInstance()->thread());
|
||||
return sharedPointer;
|
||||
}
|
||||
|
||||
CallHistoryCore::CallHistoryCore(const std::shared_ptr<linphone::CallLog> &callLog) : QObject(nullptr) {
|
||||
// qDebug() << "[CallHistoryCore] new" << this;
|
||||
App::getInstance()->mEngine->setObjectOwnership(this, QQmlEngine::CppOwnership);
|
||||
// Should be call from model Thread
|
||||
mustBeInLinphoneThread(getClassName());
|
||||
|
||||
auto addr = callLog->getRemoteAddress()->clone();
|
||||
addr->clean();
|
||||
mRemoteAddress = Utils::coreStringToAppString(addr->asStringUriOnly());
|
||||
// mRemoteAddress->clean();
|
||||
mStatus = LinphoneEnums::fromLinphone(callLog->getStatus());
|
||||
mDate = QDateTime::fromMSecsSinceEpoch(callLog->getStartDate() * 1000);
|
||||
mCallHistoryModel = std::make_shared<CallHistoryModel>(callLog);
|
||||
mIsOutgoing = callLog->getDir() == linphone::Call::Dir::Outgoing;
|
||||
mDuration = QString::number(callLog->getDuration());
|
||||
}
|
||||
|
||||
CallHistoryCore::~CallHistoryCore() {
|
||||
qDebug() << "[CallHistoryCore] delete" << this;
|
||||
mustBeInMainThread("~" + getClassName());
|
||||
}
|
||||
|
||||
void CallHistoryCore::setSelf(QSharedPointer<CallHistoryCore> me) {
|
||||
mHistoryModelConnection = QSharedPointer<SafeConnection<CallHistoryCore, CallHistoryModel>>(
|
||||
new SafeConnection<CallHistoryCore, CallHistoryModel>(me, mCallHistoryModel), &QObject::deleteLater);
|
||||
}
|
||||
|
||||
QString CallHistoryCore::getDuration() const {
|
||||
return mDuration;
|
||||
}
|
||||
|
||||
void CallHistoryCore::setDuration(const QString &duration) {
|
||||
mustBeInMainThread(log().arg(Q_FUNC_INFO));
|
||||
if (mDuration != duration) {
|
||||
mDuration = duration;
|
||||
emit durationChanged(mDuration);
|
||||
}
|
||||
}
|
||||
|
||||
void CallHistoryCore::remove() {
|
||||
mHistoryModelConnection->invokeToModel([this]() { mCallHistoryModel->removeCallHistory(); });
|
||||
}
|
||||
71
Linphone/core/call-history/CallHistoryCore.hpp
Normal file
71
Linphone/core/call-history/CallHistoryCore.hpp
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of linphone-desktop
|
||||
* (see https://www.linphone.org).
|
||||
*
|
||||
* 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 CALL_HISTORY_CORE_H_
|
||||
#define CALL_HISTORY_CORE_H_
|
||||
|
||||
#include "tool/LinphoneEnums.hpp"
|
||||
#include "tool/thread/SafeConnection.hpp"
|
||||
#include <QDateTime>
|
||||
#include <QObject>
|
||||
#include <QSharedPointer>
|
||||
#include <linphone++/linphone.hh>
|
||||
|
||||
class CallHistoryModel;
|
||||
|
||||
class CallHistoryCore : public QObject, public AbstractObject {
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(QString remoteAddress MEMBER mRemoteAddress CONSTANT)
|
||||
Q_PROPERTY(bool isOutgoing MEMBER mIsOutgoing CONSTANT)
|
||||
Q_PROPERTY(QDateTime date MEMBER mDate CONSTANT)
|
||||
Q_PROPERTY(LinphoneEnums::CallStatus status MEMBER mStatus CONSTANT)
|
||||
Q_PROPERTY(QString duration READ getDuration WRITE setDuration NOTIFY durationChanged)
|
||||
|
||||
public:
|
||||
static QSharedPointer<CallHistoryCore> create(const std::shared_ptr<linphone::CallLog> &callLogs);
|
||||
CallHistoryCore(const std::shared_ptr<linphone::CallLog> &callLog);
|
||||
~CallHistoryCore();
|
||||
|
||||
void setSelf(QSharedPointer<CallHistoryCore> me);
|
||||
|
||||
QString getDuration() const;
|
||||
void setDuration(const QString &duration);
|
||||
|
||||
Q_INVOKABLE void remove();
|
||||
|
||||
QString mRemoteAddress;
|
||||
QDateTime mDate;
|
||||
bool mIsOutgoing;
|
||||
LinphoneEnums::CallStatus mStatus;
|
||||
|
||||
signals:
|
||||
void durationChanged(QString duration);
|
||||
|
||||
private:
|
||||
QString mDuration;
|
||||
|
||||
std::shared_ptr<CallHistoryModel> mCallHistoryModel;
|
||||
QSharedPointer<SafeConnection<CallHistoryCore, CallHistoryModel>> mHistoryModelConnection;
|
||||
|
||||
DECLARE_ABSTRACT_OBJECT
|
||||
};
|
||||
Q_DECLARE_METATYPE(CallHistoryCore *)
|
||||
#endif
|
||||
40
Linphone/core/call-history/CallHistoryGui.cpp
Normal file
40
Linphone/core/call-history/CallHistoryGui.cpp
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of linphone-desktop
|
||||
* (see https://www.linphone.org).
|
||||
*
|
||||
* 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 "CallHistoryGui.hpp"
|
||||
#include "core/App.hpp"
|
||||
|
||||
DEFINE_ABSTRACT_OBJECT(CallHistoryGui)
|
||||
|
||||
CallHistoryGui::CallHistoryGui(QSharedPointer<CallHistoryCore> core) {
|
||||
// qDebug() << "[CallHistoryGui] new" << this;
|
||||
App::getInstance()->mEngine->setObjectOwnership(this, QQmlEngine::JavaScriptOwnership);
|
||||
mCore = core;
|
||||
if (isInLinphoneThread()) moveToThread(App::getInstance()->thread());
|
||||
}
|
||||
|
||||
CallHistoryGui::~CallHistoryGui() {
|
||||
mustBeInMainThread("~" + getClassName());
|
||||
// qDebug() << "[CallHistoryGui] delete" << this;
|
||||
}
|
||||
|
||||
CallHistoryCore *CallHistoryGui::getCore() const {
|
||||
return mCore.get();
|
||||
}
|
||||
41
Linphone/core/call-history/CallHistoryGui.hpp
Normal file
41
Linphone/core/call-history/CallHistoryGui.hpp
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of linphone-desktop
|
||||
* (see https://www.linphone.org).
|
||||
*
|
||||
* 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 CALL_HISTORY_GUI_H_
|
||||
#define CALL_HISTORY_GUI_H_
|
||||
|
||||
#include "CallHistoryCore.hpp"
|
||||
#include <QObject>
|
||||
#include <QSharedPointer>
|
||||
|
||||
class CallHistoryGui : public QObject, public AbstractObject {
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(CallHistoryCore *core READ getCore CONSTANT)
|
||||
|
||||
public:
|
||||
CallHistoryGui(QSharedPointer<CallHistoryCore> core);
|
||||
~CallHistoryGui();
|
||||
CallHistoryCore *getCore() const;
|
||||
QSharedPointer<CallHistoryCore> mCore;
|
||||
DECLARE_ABSTRACT_OBJECT
|
||||
};
|
||||
|
||||
#endif
|
||||
107
Linphone/core/call-history/CallHistoryList.cpp
Normal file
107
Linphone/core/call-history/CallHistoryList.cpp
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of linphone-desktop
|
||||
* (see https://www.linphone.org).
|
||||
*
|
||||
* 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 "CallHistoryList.hpp"
|
||||
#include "CallHistoryGui.hpp"
|
||||
#include "core/App.hpp"
|
||||
#include "model/object/VariantObject.hpp"
|
||||
#include "tool/Utils.hpp"
|
||||
#include <QSharedPointer>
|
||||
#include <linphone++/linphone.hh>
|
||||
|
||||
// =============================================================================
|
||||
|
||||
DEFINE_ABSTRACT_OBJECT(CallHistoryList)
|
||||
|
||||
QSharedPointer<CallHistoryList> CallHistoryList::create() {
|
||||
auto model = QSharedPointer<CallHistoryList>(new CallHistoryList(), &QObject::deleteLater);
|
||||
model->moveToThread(App::getInstance()->thread());
|
||||
model->setSelf(model);
|
||||
return model;
|
||||
}
|
||||
|
||||
QSharedPointer<CallHistoryCore>
|
||||
CallHistoryList::createCallHistoryCore(const std::shared_ptr<linphone::CallLog> &callLog) {
|
||||
auto callHistoryCore = CallHistoryCore::create(callLog);
|
||||
return callHistoryCore;
|
||||
}
|
||||
|
||||
CallHistoryList::CallHistoryList(QObject *parent) : ListProxy(parent) {
|
||||
mustBeInMainThread(getClassName());
|
||||
}
|
||||
|
||||
CallHistoryList::~CallHistoryList() {
|
||||
mustBeInMainThread("~" + getClassName());
|
||||
mModelConnection = nullptr;
|
||||
}
|
||||
|
||||
void CallHistoryList::setSelf(QSharedPointer<CallHistoryList> me) {
|
||||
mModelConnection = QSharedPointer<SafeConnection<CallHistoryList, CoreModel>>(
|
||||
new SafeConnection<CallHistoryList, CoreModel>(me, CoreModel::getInstance()), &QObject::deleteLater);
|
||||
|
||||
mModelConnection->makeConnectToCore(&CallHistoryList::lUpdate, [this]() {
|
||||
mModelConnection->invokeToModel([this]() {
|
||||
// Avoid copy to lambdas
|
||||
QList<QSharedPointer<CallHistoryCore>> *callLogs = new QList<QSharedPointer<CallHistoryCore>>();
|
||||
mustBeInLinphoneThread(getClassName());
|
||||
auto linphoneCallLogs = CoreModel::getInstance()->getCore()->getCallLogs();
|
||||
for (auto it : linphoneCallLogs) {
|
||||
auto model = createCallHistoryCore(it);
|
||||
callLogs->push_back(model);
|
||||
}
|
||||
mModelConnection->invokeToCore([this, callLogs]() {
|
||||
mustBeInMainThread(getClassName());
|
||||
resetData();
|
||||
add(*callLogs);
|
||||
delete callLogs;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
mModelConnection->makeConnectToModel(&CoreModel::callLogUpdated,
|
||||
[this]() { mModelConnection->invokeToCore([this]() { lUpdate(); }); });
|
||||
lUpdate();
|
||||
}
|
||||
|
||||
void CallHistoryList::removeAllEntries() {
|
||||
beginResetModel();
|
||||
for (auto it = mList.rbegin(); it != mList.rend(); ++it) {
|
||||
auto callHistory = it->objectCast<CallHistoryCore>();
|
||||
callHistory->remove();
|
||||
}
|
||||
mList.clear();
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
void CallHistoryList::remove(const int &row) {
|
||||
beginRemoveRows(QModelIndex(), row, row);
|
||||
auto item = mList[row].objectCast<CallHistoryCore>();
|
||||
item->remove();
|
||||
endRemoveRows();
|
||||
}
|
||||
|
||||
QVariant CallHistoryList::data(const QModelIndex &index, int role) const {
|
||||
int row = index.row();
|
||||
if (!index.isValid() || row < 0 || row >= mList.count()) return QVariant();
|
||||
if (role == Qt::DisplayRole) {
|
||||
return QVariant::fromValue(new CallHistoryGui(mList[row].objectCast<CallHistoryCore>()));
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
70
Linphone/core/call-history/CallHistoryList.hpp
Normal file
70
Linphone/core/call-history/CallHistoryList.hpp
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of linphone-desktop
|
||||
* (see https://www.linphone.org).
|
||||
*
|
||||
* 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 CALL_HISTORY_LIST_H_
|
||||
#define CALL_HISTORY_LIST_H_
|
||||
|
||||
#include "../proxy/ListProxy.hpp"
|
||||
#include "tool/AbstractObject.hpp"
|
||||
#include "tool/thread/SafeConnection.hpp"
|
||||
#include <QLocale>
|
||||
|
||||
class CallGui;
|
||||
class CallHistoryCore;
|
||||
class CoreModel;
|
||||
// =============================================================================
|
||||
|
||||
class CallHistoryList : public ListProxy, public AbstractObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
static QSharedPointer<CallHistoryList> create();
|
||||
// Create a CallHistoryCore and make connections to List.
|
||||
QSharedPointer<CallHistoryCore> createCallHistoryCore(const std::shared_ptr<linphone::CallLog> &callLog);
|
||||
CallHistoryList(QObject *parent = Q_NULLPTR);
|
||||
~CallHistoryList();
|
||||
|
||||
void setSelf(QSharedPointer<CallHistoryList> me);
|
||||
|
||||
void removeAllEntries();
|
||||
void remove(const int &row);
|
||||
|
||||
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
|
||||
// virtual QHash<int, QByteArray> roleNames() const override {
|
||||
// QHash<int, QByteArray> roles;
|
||||
// roles[Qt::DisplayRole] = "gui";
|
||||
// roles[Qt::DisplayRole + 1] = "name";
|
||||
// roles[Qt::DisplayRole + 2] = "date";
|
||||
// return roles;
|
||||
// }
|
||||
|
||||
signals:
|
||||
void lUpdate();
|
||||
|
||||
private:
|
||||
// Check the state from CallHistoryCore: sender() must be a CallHistoryCore.
|
||||
void onStatusChanged();
|
||||
|
||||
bool mHaveCallHistory = false;
|
||||
QSharedPointer<SafeConnection<CallHistoryList, CoreModel>> mModelConnection;
|
||||
DECLARE_ABSTRACT_OBJECT
|
||||
};
|
||||
|
||||
#endif
|
||||
88
Linphone/core/call-history/CallHistoryProxy.cpp
Normal file
88
Linphone/core/call-history/CallHistoryProxy.cpp
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of linphone-desktop
|
||||
* (see https://www.linphone.org).
|
||||
*
|
||||
* 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 "CallHistoryProxy.hpp"
|
||||
#include "CallHistoryGui.hpp"
|
||||
#include "CallHistoryList.hpp"
|
||||
#include "tool/Utils.hpp"
|
||||
|
||||
DEFINE_ABSTRACT_OBJECT(CallHistoryProxy)
|
||||
|
||||
CallHistoryProxy::CallHistoryProxy(QObject *parent) : SortFilterProxy(parent) {
|
||||
mHistoryList = CallHistoryList::create();
|
||||
setSourceModel(mHistoryList.get());
|
||||
// sort(0);
|
||||
}
|
||||
|
||||
CallHistoryProxy::~CallHistoryProxy() {
|
||||
setSourceModel(nullptr);
|
||||
}
|
||||
|
||||
QString CallHistoryProxy::getFilterText() const {
|
||||
return mFilterText;
|
||||
}
|
||||
|
||||
void CallHistoryProxy::setFilterText(const QString &filter) {
|
||||
if (mFilterText != filter) {
|
||||
mFilterText = filter;
|
||||
invalidate();
|
||||
emit filterTextChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void CallHistoryProxy::removeAllEntries() {
|
||||
static_cast<CallHistoryList *>(sourceModel())->removeAllEntries();
|
||||
}
|
||||
|
||||
void CallHistoryProxy::removeEntriesWithFilter() {
|
||||
std::list<QSharedPointer<CallHistoryCore>> itemList(rowCount());
|
||||
for (auto i = rowCount() - 1; i >= 0; --i) {
|
||||
auto item = getItemAt<CallHistoryList, CallHistoryCore>(i);
|
||||
itemList.emplace_back(item);
|
||||
}
|
||||
for (auto item : itemList) {
|
||||
mHistoryList->ListProxy::remove(item.get());
|
||||
if (item) item->remove();
|
||||
}
|
||||
}
|
||||
|
||||
void CallHistoryProxy::updateView() {
|
||||
mHistoryList->lUpdate();
|
||||
}
|
||||
|
||||
bool CallHistoryProxy::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const {
|
||||
bool show = (mFilterText.isEmpty() || mFilterText == "*");
|
||||
if (!show) {
|
||||
QRegularExpression search(QRegularExpression::escape(mFilterText),
|
||||
QRegularExpression::CaseInsensitiveOption |
|
||||
QRegularExpression::UseUnicodePropertiesOption);
|
||||
auto callLog = qobject_cast<CallHistoryList *>(sourceModel())->getAt<CallHistoryCore>(sourceRow);
|
||||
show = callLog->mRemoteAddress.contains(search);
|
||||
}
|
||||
|
||||
return show;
|
||||
}
|
||||
|
||||
bool CallHistoryProxy::lessThan(const QModelIndex &left, const QModelIndex &right) const {
|
||||
auto l = getItemAt<CallHistoryList, CallHistoryCore>(left.row());
|
||||
auto r = getItemAt<CallHistoryList, CallHistoryCore>(right.row());
|
||||
|
||||
return l->mDate < r->mDate;
|
||||
}
|
||||
60
Linphone/core/call-history/CallHistoryProxy.hpp
Normal file
60
Linphone/core/call-history/CallHistoryProxy.hpp
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of linphone-desktop
|
||||
* (see https://www.linphone.org).
|
||||
*
|
||||
* 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 CALL_HISTORY_PROXY_H_
|
||||
#define CALL_HISTORY_PROXY_H_
|
||||
|
||||
#include "../proxy/SortFilterProxy.hpp"
|
||||
#include "CallHistoryGui.hpp"
|
||||
#include "CallHistoryList.hpp"
|
||||
#include "tool/AbstractObject.hpp"
|
||||
|
||||
// =============================================================================
|
||||
|
||||
class CallHistoryProxy : public SortFilterProxy, public AbstractObject {
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(QString filterText READ getFilterText WRITE setFilterText NOTIFY filterTextChanged)
|
||||
|
||||
public:
|
||||
CallHistoryProxy(QObject *parent = Q_NULLPTR);
|
||||
~CallHistoryProxy();
|
||||
|
||||
QString getFilterText() const;
|
||||
void setFilterText(const QString &filter);
|
||||
|
||||
Q_INVOKABLE void removeAllEntries();
|
||||
Q_INVOKABLE void removeEntriesWithFilter();
|
||||
Q_INVOKABLE void updateView();
|
||||
|
||||
signals:
|
||||
void filterTextChanged();
|
||||
|
||||
protected:
|
||||
virtual bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override;
|
||||
virtual bool lessThan(const QModelIndex &left, const QModelIndex &right) const override;
|
||||
|
||||
QString mFilterText;
|
||||
QSharedPointer<CallHistoryList> mHistoryList;
|
||||
|
||||
DECLARE_ABSTRACT_OBJECT
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -36,6 +36,11 @@ public:
|
|||
virtual int getCount() const;
|
||||
virtual int getFilterType() const;
|
||||
Q_INVOKABLE QVariant getAt(const int &index) const;
|
||||
template <class A, class B>
|
||||
QSharedPointer<B> getItemAt(const int &atIndex) const {
|
||||
auto modelIndex = index(atIndex, 0);
|
||||
return qobject_cast<A *>(sourceModel())->template getAt<B>(mapToSource(modelIndex).row());
|
||||
}
|
||||
Q_INVOKABLE void setSortOrder(const Qt::SortOrder &order);
|
||||
|
||||
virtual void setFilterType(int filterType);
|
||||
|
|
|
|||
|
|
@ -58,6 +58,9 @@ list(APPEND _LINPHONEAPP_RC_FILES data/assistant/use-app-sip-account.rc
|
|||
"data/image/randomAvatar.png"
|
||||
"data/image/pause.svg"
|
||||
"data/image/smiley.svg"
|
||||
"data/image/trash-simple.svg"
|
||||
"data/image/copy.svg"
|
||||
"data/image/empty.svg"
|
||||
|
||||
data/shaders/roundEffect.vert.qsb
|
||||
data/shaders/roundEffect.frag.qsb
|
||||
|
|
|
|||
3
Linphone/data/image/empty.svg
Normal file
3
Linphone/data/image/empty.svg
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M20.8285 12.6229L17.4503 15.9998L20.8285 19.3768C20.9238 19.472 20.9994 19.5852 21.051 19.7097C21.1026 19.8342 21.1291 19.9676 21.1291 20.1024C21.1291 20.2372 21.1026 20.3706 21.051 20.4951C20.9994 20.6196 20.9238 20.7327 20.8285 20.828C20.7332 20.9233 20.6201 20.9989 20.4956 21.0505C20.3711 21.1021 20.2377 21.1286 20.1029 21.1286C19.9681 21.1286 19.8347 21.1021 19.7102 21.0505C19.5857 20.9989 19.4725 20.9233 19.3773 20.828L16.0003 17.4498L12.6234 20.828C12.5281 20.9233 12.415 20.9989 12.2905 21.0505C12.166 21.1021 12.0325 21.1286 11.8978 21.1286C11.763 21.1286 11.6296 21.1021 11.5051 21.0505C11.3805 20.9989 11.2674 20.9233 11.1721 20.828C11.0768 20.7327 11.0012 20.6196 10.9497 20.4951C10.8981 20.3706 10.8716 20.2372 10.8716 20.1024C10.8716 19.9676 10.8981 19.8342 10.9497 19.7097C11.0012 19.5852 11.0768 19.472 11.1721 19.3768L14.5503 15.9998L11.1721 12.6229C10.9797 12.4305 10.8716 12.1694 10.8716 11.8973C10.8716 11.6251 10.9797 11.3641 11.1721 11.1716C11.3646 10.9792 11.6256 10.8711 11.8978 10.8711C12.1699 10.8711 12.431 10.9792 12.6234 11.1716L16.0003 14.5498L19.3773 11.1716C19.4725 11.0763 19.5857 11.0007 19.7102 10.9492C19.8347 10.8976 19.9681 10.8711 20.1029 10.8711C20.2377 10.8711 20.3711 10.8976 20.4956 10.9492C20.6201 11.0007 20.7332 11.0763 20.8285 11.1716C20.9238 11.2669 20.9994 11.3801 21.051 11.5046C21.1026 11.6291 21.1291 11.7625 21.1291 11.8973C21.1291 12.032 21.1026 12.1655 21.051 12.29C20.9994 12.4145 20.9238 12.5276 20.8285 12.6229ZM29.3337 15.9998C29.3337 18.6369 28.5517 21.2148 27.0866 23.4074C25.6215 25.6001 23.5391 27.3091 21.1028 28.3182C18.6664 29.3274 15.9855 29.5914 13.3991 29.077C10.8127 28.5625 8.43694 27.2926 6.57224 25.4279C4.70754 23.5632 3.43766 21.1875 2.92319 18.601C2.40872 16.0146 2.67277 13.3337 3.68194 10.8974C4.69111 8.46104 6.40007 6.37866 8.59273 4.91358C10.7854 3.44849 13.3632 2.6665 16.0003 2.6665C19.5354 2.67024 22.9246 4.07619 25.4243 6.57587C27.924 9.07554 29.3299 12.4648 29.3337 15.9998ZM27.2824 15.9998C27.2824 13.7685 26.6207 11.5872 25.381 9.73186C24.1413 7.87654 22.3793 6.43049 20.3178 5.57658C18.2563 4.72267 15.9878 4.49925 13.7993 4.93457C11.6108 5.36989 9.60054 6.4444 8.02272 8.02222C6.44489 9.60004 5.37038 11.6103 4.93506 13.7988C4.49974 15.9873 4.72316 18.2558 5.57707 20.3173C6.43099 22.3788 7.87703 24.1408 9.73236 25.3805C11.5877 26.6202 13.769 27.2819 16.0003 27.2819C18.9915 27.2785 21.8591 26.0888 23.9742 23.9737C26.0893 21.8586 27.279 18.991 27.2824 15.9998Z" fill="#6C7A87"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.5 KiB |
|
|
@ -4,6 +4,8 @@ list(APPEND _LINPHONEAPP_SOURCES
|
|||
|
||||
model/call/CallModel.cpp
|
||||
|
||||
model/call-history/CallHistoryModel.cpp
|
||||
|
||||
model/core/CoreModel.cpp
|
||||
|
||||
model/friend/FriendModel.cpp
|
||||
|
|
|
|||
42
Linphone/model/call-history/CallHistoryModel.cpp
Normal file
42
Linphone/model/call-history/CallHistoryModel.cpp
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of linphone-desktop
|
||||
* (see https://www.linphone.org).
|
||||
*
|
||||
* 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 "CallHistoryModel.hpp"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include "model/core/CoreModel.hpp"
|
||||
#include "tool/Utils.hpp"
|
||||
|
||||
DEFINE_ABSTRACT_OBJECT(CallHistoryModel)
|
||||
|
||||
CallHistoryModel::CallHistoryModel(const std::shared_ptr<linphone::CallLog> &callLog, QObject *parent)
|
||||
: callLog(callLog) {
|
||||
mustBeInLinphoneThread(getClassName());
|
||||
}
|
||||
|
||||
CallHistoryModel::~CallHistoryModel() {
|
||||
qDebug() << "[CallHistoryModel] delete" << this;
|
||||
mustBeInLinphoneThread("~" + getClassName());
|
||||
}
|
||||
|
||||
void CallHistoryModel::removeCallHistory() {
|
||||
CoreModel::getInstance()->getCore()->removeCallLog(callLog);
|
||||
}
|
||||
44
Linphone/model/call-history/CallHistoryModel.hpp
Normal file
44
Linphone/model/call-history/CallHistoryModel.hpp
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of linphone-desktop
|
||||
* (see https://www.linphone.org).
|
||||
*
|
||||
* 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 CALL_HISTORY_MODEL_H_
|
||||
#define CALL_HISTORY_MODEL_H_
|
||||
|
||||
#include "model/listener/Listener.hpp"
|
||||
#include "tool/AbstractObject.hpp"
|
||||
|
||||
#include <QObject>
|
||||
#include <QTimer>
|
||||
#include <linphone++/linphone.hh>
|
||||
|
||||
class CallHistoryModel : public QObject, public AbstractObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
CallHistoryModel(const std::shared_ptr<linphone::CallLog> &callLog, QObject *parent = nullptr);
|
||||
~CallHistoryModel();
|
||||
|
||||
void removeCallHistory();
|
||||
|
||||
private:
|
||||
std::shared_ptr<linphone::CallLog> callLog;
|
||||
DECLARE_ABSTRACT_OBJECT
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -89,6 +89,7 @@ VariantObject *Utils::createCall(const QString &sipAddress,
|
|||
auto app = App::getInstance();
|
||||
auto window = app->getCallsWindow(callGui);
|
||||
smartShowWindow(window);
|
||||
// callGui.value<CallGui *>()->getCore()->lSetCameraEnabled(true);
|
||||
});
|
||||
return callGui;
|
||||
} else return QVariant();
|
||||
|
|
@ -174,7 +175,7 @@ QString Utils::createAvatar(const QUrl &fileUrl) {
|
|||
return fileUri;
|
||||
}
|
||||
|
||||
QString Utils::formatElapsedTime(int seconds) {
|
||||
QString Utils::formatElapsedTime(int seconds, bool dotsSeparator) {
|
||||
// s, m, h, d, W, M, Y
|
||||
// 1, 60, 3600, 86400, 604800, 2592000, 31104000
|
||||
auto y = floor(seconds / 31104000);
|
||||
|
|
@ -192,14 +193,50 @@ QString Utils::formatElapsedTime(int seconds) {
|
|||
|
||||
QString hours, min, sec;
|
||||
|
||||
if (h < 10 && h > 0) hours = "0";
|
||||
if (dotsSeparator && h < 10 && h > 0) hours = "0";
|
||||
hours.append(QString::number(h));
|
||||
|
||||
if (m < 10) min = "0";
|
||||
if (dotsSeparator && m < 10) min = "0";
|
||||
min.append(QString::number(m));
|
||||
|
||||
if (s < 10) sec = "0";
|
||||
if (dotsSeparator && s < 10) sec = "0";
|
||||
sec.append(QString::number(s));
|
||||
|
||||
return (h == 0 ? "" : hours + ":") + min + ":" + sec;
|
||||
if (dotsSeparator) return (h == 0 ? "" : hours + ":") + min + ":" + sec;
|
||||
else return (h == 0 ? "" : hours + "h ") + (m == 0 ? "" : min + "min ") + sec + "s";
|
||||
}
|
||||
|
||||
QString Utils::formatDate(const QDateTime &date, bool includeTime) {
|
||||
QString format = date.date().year() == QDateTime::currentDateTime().date().year() ? "dd MMMM" : "dd MMMM yyyy";
|
||||
auto dateDay = tr(date.date().toString(format).toLocal8Bit().data());
|
||||
if (!includeTime) return dateDay;
|
||||
|
||||
auto time = date.time().toString("hh:mm");
|
||||
return dateDay + " | " + time;
|
||||
}
|
||||
|
||||
QString Utils::formatDateElapsedTime(const QDateTime &date) {
|
||||
// auto y = floor(seconds / 31104000);
|
||||
// if (y > 0) return QString::number(y) + " years";
|
||||
// auto M = floor(seconds / 2592000);
|
||||
// if (M > 0) return QString::number(M) + " months";
|
||||
// auto w = floor(seconds / 604800);
|
||||
// if (w > 0) return QString::number(w) + " week";
|
||||
auto dateSec = date.secsTo(QDateTime::currentDateTime());
|
||||
|
||||
auto d = floor(dateSec / 86400);
|
||||
if (d > 7) {
|
||||
return formatDate(date, false);
|
||||
} else if (d > 0) {
|
||||
return tr(date.date().toString("dddd").toLocal8Bit().data());
|
||||
}
|
||||
|
||||
auto h = floor(dateSec / 3600);
|
||||
if (h > 0) return QString::number(h) + " h";
|
||||
|
||||
auto m = floor((dateSec - h * 3600) / 60);
|
||||
if (m > 0) return QString::number(m) + " m";
|
||||
|
||||
auto s = dateSec - h * 3600 - m * 60;
|
||||
return QString::number(s) + " s";
|
||||
}
|
||||
|
|
@ -64,7 +64,10 @@ public:
|
|||
Q_INVOKABLE static VariantObject *haveAccount();
|
||||
Q_INVOKABLE static void smartShowWindow(QQuickWindow *window);
|
||||
Q_INVOKABLE static QString createAvatar(const QUrl &fileUrl); // Return the avatar path
|
||||
Q_INVOKABLE static QString formatElapsedTime(int seconds); // Return the elapsed time formated
|
||||
Q_INVOKABLE static QString formatElapsedTime(int seconds,
|
||||
bool dotsSeparator = true); // Return the elapsed time formated
|
||||
Q_INVOKABLE static QString formatDate(const QDateTime &date, bool includeTime = true); // Return the date formated
|
||||
Q_INVOKABLE static QString formatDateElapsedTime(const QDateTime &date); // Return the date formated
|
||||
|
||||
static inline QString coreStringToAppString(const std::string &str) {
|
||||
if (Constants::LinphoneLocaleEncoding == QString("UTF-8")) return QString::fromStdString(str);
|
||||
|
|
|
|||
|
|
@ -121,9 +121,9 @@ Window {
|
|||
|
||||
|
||||
component BottomButton : Button {
|
||||
id: bottomButton
|
||||
required property string enabledIcon
|
||||
property string disabledIcon
|
||||
id: bottomButton
|
||||
enabled: call != undefined
|
||||
padding: 18 * DefaultStyle.dp
|
||||
checkable: true
|
||||
|
|
@ -367,7 +367,8 @@ Window {
|
|||
Avatar {
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
// TODO : remove username when friend list ready
|
||||
address: mainWindow.peerNameText
|
||||
call: mainWindow.call
|
||||
// address: mainWindow.peerNameText
|
||||
Layout.preferredWidth: 120 * DefaultStyle.dp
|
||||
Layout.preferredHeight: 120 * DefaultStyle.dp
|
||||
}
|
||||
|
|
@ -414,6 +415,7 @@ Window {
|
|||
}
|
||||
Text {
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.leftMargin: 10 * DefaultStyle.dp
|
||||
anchors.bottomMargin: 10 * DefaultStyle.dp
|
||||
|
|
@ -528,15 +530,13 @@ Window {
|
|||
id: callList
|
||||
model: callsModel
|
||||
height: contentHeight
|
||||
onHeightChanged: console.log("height changzed lustviexw", height, contentHeight)
|
||||
spacing: 15 * DefaultStyle.dp
|
||||
|
||||
onCountChanged: forceLayout()
|
||||
|
||||
delegate: Item {
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
id: callDelegate
|
||||
width: callList.width
|
||||
height: 45 * DefaultStyle.dp
|
||||
|
||||
RowLayout {
|
||||
|
|
@ -567,118 +567,62 @@ Window {
|
|||
|| modelData.core.state === LinphoneEnums.CallState.PausedByRemote
|
||||
? qsTr("Appel en pause") : qsTr("Appel en cours")
|
||||
}
|
||||
Button {
|
||||
PopupButton {
|
||||
id: listCallOptionsButton
|
||||
checked: listCallOptionsMenu.visible
|
||||
Layout.preferredWidth: 24 * DefaultStyle.dp
|
||||
Layout.preferredHeight: 24 * DefaultStyle.dp
|
||||
Layout.alignment: Qt.AlignRight
|
||||
leftPadding: 0
|
||||
rightPadding: 0
|
||||
topPadding: 0
|
||||
bottomPadding: 0
|
||||
background: Rectangle {
|
||||
anchors.fill: listCallOptionsButton
|
||||
opacity: listCallOptionsButton.checked ? 1 : 0
|
||||
color: DefaultStyle.main2_300
|
||||
radius: 40 * DefaultStyle.dp
|
||||
}
|
||||
contentItem: Image {
|
||||
source: AppIcons.verticalDots
|
||||
sourceSize.width: 24 * DefaultStyle.dp
|
||||
sourceSize.height: 24 * DefaultStyle.dp
|
||||
width: 24 * DefaultStyle.dp
|
||||
height: 24 * DefaultStyle.dp
|
||||
}
|
||||
onPressed: {
|
||||
console.log("listCallOptionsMenu visible", listCallOptionsMenu.visible, "opened", listCallOptionsMenu.opened)
|
||||
if (listCallOptionsMenu.visible){
|
||||
console.log("close popup")
|
||||
listCallOptionsMenu.close()
|
||||
}
|
||||
else {
|
||||
console.log("open popup")
|
||||
listCallOptionsMenu.open()
|
||||
}
|
||||
}
|
||||
Control.Popup {
|
||||
id: listCallOptionsMenu
|
||||
x: - width
|
||||
y: listCallOptionsButton.height
|
||||
onVisibleChanged: console.log("popup visible", visible)
|
||||
closePolicy: Popup.CloseOnPressOutsideParent | Popup.CloseOnEscape
|
||||
|
||||
padding: 20 * DefaultStyle.dp
|
||||
|
||||
background: Item {
|
||||
anchors.fill: parent
|
||||
Rectangle {
|
||||
id: callOptionsMenuPopup
|
||||
anchors.fill: parent
|
||||
color: DefaultStyle.grey_0
|
||||
radius: 16 * DefaultStyle.dp
|
||||
}
|
||||
MultiEffect {
|
||||
source: callOptionsMenuPopup
|
||||
anchors.fill: callOptionsMenuPopup
|
||||
shadowEnabled: true
|
||||
shadowBlur: 1
|
||||
shadowColor: DefaultStyle.grey_900
|
||||
shadowOpacity: 0.4
|
||||
}
|
||||
}
|
||||
|
||||
contentItem: ColumnLayout {
|
||||
spacing: 0
|
||||
Control.Button {
|
||||
background: Item {}
|
||||
contentItem: RowLayout {
|
||||
Image {
|
||||
source: modelData.core.state === LinphoneEnums.CallState.Paused
|
||||
|| modelData.core.state === LinphoneEnums.CallState.PausedByRemote
|
||||
? AppIcons.phone : AppIcons.pause
|
||||
sourceSize.width: 32 * DefaultStyle.dp
|
||||
sourceSize.height: 32 * DefaultStyle.dp
|
||||
Layout.preferredWidth: 32 * DefaultStyle.dp
|
||||
Layout.preferredHeight: 32 * DefaultStyle.dp
|
||||
fillMode: Image.PreserveAspectFit
|
||||
}
|
||||
Text {
|
||||
text: modelData.core.state === LinphoneEnums.CallState.Paused
|
||||
|| modelData.core.state === LinphoneEnums.CallState.PausedByRemote
|
||||
? qsTr("Reprendre l'appel") : qsTr("Mettre en pause")
|
||||
color: DefaultStyle.main2_500main
|
||||
Layout.preferredWidth: metrics.width
|
||||
}
|
||||
TextMetrics {
|
||||
id: metrics
|
||||
text: qsTr("Reprendre l'appel")
|
||||
}
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
popup.contentItem: ColumnLayout {
|
||||
spacing: 0
|
||||
Control.Button {
|
||||
background: Item {}
|
||||
contentItem: RowLayout {
|
||||
Image {
|
||||
source: modelData.core.state === LinphoneEnums.CallState.Paused
|
||||
|| modelData.core.state === LinphoneEnums.CallState.PausedByRemote
|
||||
? AppIcons.phone : AppIcons.pause
|
||||
sourceSize.width: 32 * DefaultStyle.dp
|
||||
sourceSize.height: 32 * DefaultStyle.dp
|
||||
Layout.preferredWidth: 32 * DefaultStyle.dp
|
||||
Layout.preferredHeight: 32 * DefaultStyle.dp
|
||||
fillMode: Image.PreserveAspectFit
|
||||
}
|
||||
onClicked: modelData.core.lSetPaused(!modelData.core.paused)
|
||||
}
|
||||
Control.Button {
|
||||
background: Item {}
|
||||
contentItem: RowLayout {
|
||||
EffectImage {
|
||||
image.source: AppIcons.endCall
|
||||
colorizationColor: DefaultStyle.danger_500main
|
||||
width: 32 * DefaultStyle.dp
|
||||
height: 32 * DefaultStyle.dp
|
||||
}
|
||||
Text {
|
||||
color: DefaultStyle.danger_500main
|
||||
text: qsTr("Terminer l'appel")
|
||||
}
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
Text {
|
||||
text: modelData.core.state === LinphoneEnums.CallState.Paused
|
||||
|| modelData.core.state === LinphoneEnums.CallState.PausedByRemote
|
||||
? qsTr("Reprendre l'appel") : qsTr("Mettre en pause")
|
||||
color: DefaultStyle.main2_500main
|
||||
Layout.preferredWidth: metrics.width
|
||||
}
|
||||
TextMetrics {
|
||||
id: metrics
|
||||
text: qsTr("Reprendre l'appel")
|
||||
}
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
onClicked: mainWindow.endCall(modelData)
|
||||
}
|
||||
onClicked: modelData.core.lSetPaused(!modelData.core.paused)
|
||||
}
|
||||
Control.Button {
|
||||
background: Item {}
|
||||
contentItem: RowLayout {
|
||||
EffectImage {
|
||||
image.source: AppIcons.endCall
|
||||
colorizationColor: DefaultStyle.danger_500main
|
||||
width: 32 * DefaultStyle.dp
|
||||
height: 32 * DefaultStyle.dp
|
||||
}
|
||||
Text {
|
||||
color: DefaultStyle.danger_500main
|
||||
text: qsTr("Terminer l'appel")
|
||||
}
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
}
|
||||
onClicked: mainWindow.endCall(modelData)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,18 +15,16 @@ list(APPEND _LINPHONEAPP_QML_FILES
|
|||
|
||||
view/Item/Prototype/CanvasCircle.qml
|
||||
|
||||
view/Item/BusyIndicator.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/Contact/Sticker.qml
|
||||
|
||||
view/Item/BusyIndicator.qml
|
||||
view/Item/Button.qml
|
||||
view/Item/Carousel.qml
|
||||
view/Item/CheckBox.qml
|
||||
view/Item/ComboBox.qml
|
||||
view/Item/DesktopPopup.qml
|
||||
view/Item/DigitInput.qml
|
||||
view/Item/EffectImage.qml
|
||||
|
|
@ -35,6 +33,7 @@ list(APPEND _LINPHONEAPP_QML_FILES
|
|||
view/Item/PhoneNumberComboBox.qml
|
||||
view/Item/PhoneNumberInput.qml
|
||||
view/Item/Popup.qml
|
||||
view/Item/PopupButton.qml
|
||||
view/Item/RadioButton.qml
|
||||
view/Item/RectangleTest.qml
|
||||
view/Item/SearchBar.qml
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ Rectangle{
|
|||
width: 22 * DefaultStyle.dp
|
||||
height: 22 * DefaultStyle.dp
|
||||
radius: width/2
|
||||
color: DefaultStyle.danger_500
|
||||
color: DefaultStyle.danger_500main
|
||||
border.color: DefaultStyle.grey_0
|
||||
border.width: 2 * DefaultStyle.dp
|
||||
Text{
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ Notification {
|
|||
readonly property var call: notificationData && notificationData.call
|
||||
property var state: call.core.state
|
||||
onStateChanged:{
|
||||
console.log("state notif", state)
|
||||
if(state != LinphoneEnums.CallState.IncomingReceived){
|
||||
close()
|
||||
}
|
||||
|
|
|
|||
62
Linphone/view/Item/PopupButton.qml
Normal file
62
Linphone/view/Item/PopupButton.qml
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
import QtQuick 2.7
|
||||
import QtQuick.Controls 2.2 as Control
|
||||
import QtQuick.Effects
|
||||
import Linphone
|
||||
|
||||
Button {
|
||||
id: mainItem
|
||||
property alias popup: popup
|
||||
checked: popup.visible
|
||||
implicitWidth: 24 * DefaultStyle.dp
|
||||
implicitHeight: 24 * DefaultStyle.dp
|
||||
leftPadding: 0
|
||||
rightPadding: 0
|
||||
topPadding: 0
|
||||
bottomPadding: 0
|
||||
function closePopup() {
|
||||
popup.close()
|
||||
}
|
||||
background: Rectangle {
|
||||
anchors.fill: mainItem
|
||||
visible: mainItem.checked
|
||||
color: DefaultStyle.main2_300
|
||||
radius: 40 * DefaultStyle.dp
|
||||
}
|
||||
contentItem: Image {
|
||||
source: AppIcons.verticalDots
|
||||
sourceSize.width: 24 * DefaultStyle.dp
|
||||
sourceSize.height: 24 * DefaultStyle.dp
|
||||
width: 24 * DefaultStyle.dp
|
||||
height: 24 * DefaultStyle.dp
|
||||
}
|
||||
onPressed: {
|
||||
if (popup.visible) popup.close()
|
||||
else popup.open()
|
||||
}
|
||||
Control.Popup {
|
||||
id: popup
|
||||
x: - width
|
||||
y: mainItem.height
|
||||
closePolicy: Popup.CloseOnPressOutsideParent | Popup.CloseOnEscape
|
||||
|
||||
padding: 20 * DefaultStyle.dp
|
||||
|
||||
background: Item {
|
||||
anchors.fill: parent
|
||||
Rectangle {
|
||||
id: callOptionsMenuPopup
|
||||
anchors.fill: parent
|
||||
color: DefaultStyle.grey_0
|
||||
radius: 16 * DefaultStyle.dp
|
||||
}
|
||||
MultiEffect {
|
||||
source: callOptionsMenuPopup
|
||||
anchors.fill: callOptionsMenuPopup
|
||||
shadowEnabled: true
|
||||
shadowBlur: 1
|
||||
shadowColor: DefaultStyle.grey_900
|
||||
shadowOpacity: 0.4
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -15,9 +15,8 @@ Item {
|
|||
property string newItemIconSource
|
||||
property string emptyListText
|
||||
property alias leftPanelContent: leftPanel.children
|
||||
property var rightPanelContent: rightPanelItem.children
|
||||
property alias rightPanelContent: rightPanelItem.children
|
||||
property bool showDefaultItem: true
|
||||
// onShowDefaultItemChanged: stackView.replace(showDefaultItem ? defaultItem : rightPanelItem)
|
||||
signal noItemButtonPressed()
|
||||
|
||||
Control.SplitView {
|
||||
|
|
@ -31,7 +30,7 @@ Item {
|
|||
|
||||
ColumnLayout {
|
||||
id: leftPanel
|
||||
Control.SplitView.preferredWidth: 280 * DefaultStyle.dp
|
||||
Control.SplitView.preferredWidth: 350 * DefaultStyle.dp
|
||||
}
|
||||
Rectangle {
|
||||
id: rightPanel
|
||||
|
|
@ -44,6 +43,7 @@ Item {
|
|||
id: defaultItem
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
RowLayout {
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
|
|
@ -105,7 +105,7 @@ Item {
|
|||
}
|
||||
|
||||
}
|
||||
Item {
|
||||
ColumnLayout {
|
||||
id: rightPanelItem
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
|
@ -114,4 +114,3 @@ Item {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Effects
|
||||
import QtQuick.Layouts
|
||||
import QtQuick.Controls as Control
|
||||
import Linphone
|
||||
|
|
@ -10,26 +11,33 @@ AbstractMainPage {
|
|||
emptyListText: qsTr("Historique d'appel vide")
|
||||
newItemIconSource: AppIcons.newCall
|
||||
|
||||
property var selectedRowHistoryGui
|
||||
|
||||
signal listViewUpdated()
|
||||
|
||||
onNoItemButtonPressed: goToNewCall()
|
||||
|
||||
|
||||
showDefaultItem: listStackView.currentItem.listView ? listStackView.currentItem.listView.count === 0 : true
|
||||
|
||||
function goToNewCall() {
|
||||
listStackView.push(newCallItem)
|
||||
}
|
||||
|
||||
leftPanelContent: Item {
|
||||
id: leftPanel
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
Control.StackView {
|
||||
id: listStackView
|
||||
clip: true
|
||||
initialItem: listItem
|
||||
initialItem: historyListItem
|
||||
anchors.fill: parent
|
||||
property int sideMargin: 25 * DefaultStyle.dp
|
||||
// anchors.leftMargin: 25
|
||||
// anchors.rightMargin: 25
|
||||
}
|
||||
Component {
|
||||
id: listItem
|
||||
id: historyListItem
|
||||
|
||||
ColumnLayout {
|
||||
RowLayout {
|
||||
|
|
@ -45,12 +53,35 @@ AbstractMainPage {
|
|||
Item {
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
Control.Button {
|
||||
enabled: false
|
||||
background: Item {
|
||||
}
|
||||
contentItem: Image {
|
||||
source: AppIcons.verticalDots
|
||||
PopupButton {
|
||||
id: removeHistory
|
||||
popup.x: 0
|
||||
popup.padding: 10 * DefaultStyle.dp
|
||||
popup.contentItem: Button {
|
||||
background: Item{}
|
||||
contentItem: RowLayout {
|
||||
EffectImage {
|
||||
image.source: AppIcons.trashCan
|
||||
width: 24 * DefaultStyle.dp
|
||||
height: 24 * DefaultStyle.dp
|
||||
Layout.preferredWidth: 24 * DefaultStyle.dp
|
||||
Layout.preferredHeight: 24 * DefaultStyle.dp
|
||||
image.fillMode: Image.PreserveAspectFit
|
||||
colorizationColor: DefaultStyle.danger_500main
|
||||
}
|
||||
Text {
|
||||
text: qsTr("Supprimmer l’historique")
|
||||
color: DefaultStyle.danger_500main
|
||||
font {
|
||||
pixelSize: 14 * DefaultStyle.dp
|
||||
weight: 400 * DefaultStyle.dp
|
||||
}
|
||||
}
|
||||
}
|
||||
onClicked: {
|
||||
historyListView.model.removeAllEntries()
|
||||
removeHistory.closePopup()
|
||||
}
|
||||
}
|
||||
}
|
||||
Control.Button {
|
||||
|
|
@ -65,112 +96,200 @@ AbstractMainPage {
|
|||
fillMode: Image.PreserveAspectFit
|
||||
}
|
||||
onClicked: {
|
||||
console.log("[CallPage]User: create new call")
|
||||
console.debug("[CallPage]User: create new call")
|
||||
listStackView.push(newCallItem)
|
||||
}
|
||||
}
|
||||
}
|
||||
Control.Control {
|
||||
id: listLayout
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
Layout.leftMargin: listStackView.sideMargin
|
||||
Layout.rightMargin: listStackView.sideMargin
|
||||
RowLayout {
|
||||
Control.Control {
|
||||
id: listLayout
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
Layout.leftMargin: listStackView.sideMargin
|
||||
Layout.rightMargin: listStackView.sideMargin
|
||||
|
||||
background: Rectangle {
|
||||
anchors.fill: parent
|
||||
}
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
SearchBar {
|
||||
id: searchBar
|
||||
Layout.alignment: Qt.AlignTop
|
||||
Layout.fillWidth: true
|
||||
placeholderText: qsTr("Rechercher un appel")
|
||||
background: Rectangle {
|
||||
anchors.fill: parent
|
||||
}
|
||||
ColumnLayout {
|
||||
Text {
|
||||
text: qsTr("Aucun appel")
|
||||
font {
|
||||
pixelSize: 16 * DefaultStyle.dp
|
||||
weight: 800 * DefaultStyle.dp
|
||||
}
|
||||
visible: listView.count === 0
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.topMargin: 30 * DefaultStyle.dp
|
||||
}
|
||||
ListView {
|
||||
id: listView
|
||||
clip: true
|
||||
anchors.fill: parent
|
||||
SearchBar {
|
||||
id: searchBar
|
||||
Layout.alignment: Qt.AlignTop
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
model: 0
|
||||
currentIndex: 0
|
||||
|
||||
delegate: Item {
|
||||
required property int index
|
||||
width:listView.width
|
||||
height: 30 * DefaultStyle.dp
|
||||
// RectangleTest{}
|
||||
RowLayout {
|
||||
anchors.fill: parent
|
||||
Image {
|
||||
source: AppIcons.info
|
||||
}
|
||||
ColumnLayout {
|
||||
Text {
|
||||
text: "John Doe"
|
||||
}
|
||||
// RowLayout {
|
||||
// Image {
|
||||
// source: AppIcons.incomingCall
|
||||
// }
|
||||
// Text {
|
||||
// text: "info sur l'appel"
|
||||
// }
|
||||
// }
|
||||
}
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
Control.Button {
|
||||
implicitWidth: 30 * DefaultStyle.dp
|
||||
implicitHeight: 30 * DefaultStyle.dp
|
||||
background: Item {
|
||||
visible: false
|
||||
}
|
||||
contentItem: Image {
|
||||
source: AppIcons.phone
|
||||
width: 20 * DefaultStyle.dp
|
||||
sourceSize.width: 20 * DefaultStyle.dp
|
||||
fillMode: Image.PreserveAspectFit
|
||||
}
|
||||
}
|
||||
placeholderText: qsTr("Rechercher un appel")
|
||||
}
|
||||
ColumnLayout {
|
||||
Text {
|
||||
text: qsTr("Aucun appel")
|
||||
font {
|
||||
pixelSize: 16 * DefaultStyle.dp
|
||||
weight: 800 * DefaultStyle.dp
|
||||
}
|
||||
MouseArea {
|
||||
hoverEnabled: true
|
||||
Rectangle {
|
||||
visible: historyListView.count === 0
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.topMargin: 30 * DefaultStyle.dp
|
||||
}
|
||||
ListView {
|
||||
id: historyListView
|
||||
clip: true
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
Layout.topMargin: 30 * DefaultStyle.dp
|
||||
model: CallHistoryProxy{
|
||||
filterText: searchBar.text
|
||||
}
|
||||
currentIndex: -1
|
||||
onCurrentIndexChanged: {
|
||||
mainItem.selectedRowHistoryGui = model.getAt(currentIndex)
|
||||
}
|
||||
spacing: 10 * DefaultStyle.dp
|
||||
highlightMoveDuration: 10
|
||||
highlightMoveVelocity: -1
|
||||
// highlightFollowsCurrentItem: true
|
||||
highlight: Rectangle {
|
||||
x: historyListView.x
|
||||
width: historyListView.width
|
||||
height: historyListView.height
|
||||
color: DefaultStyle.main2_100
|
||||
y: historyListView.currentItem? historyListView.currentItem.y : 0
|
||||
}
|
||||
|
||||
delegate: Item {
|
||||
width:historyListView.width
|
||||
height: 56 * DefaultStyle.dp
|
||||
anchors.topMargin: 5 * DefaultStyle.dp
|
||||
anchors.bottomMargin: 5 * DefaultStyle.dp
|
||||
RowLayout {
|
||||
z: 1
|
||||
anchors.fill: parent
|
||||
opacity: 0.1
|
||||
radius: 15 * DefaultStyle.dp
|
||||
color: DefaultStyle.main2_500main
|
||||
visible: parent.containsMouse
|
||||
Item {
|
||||
Layout.preferredWidth: historyAvatar.width
|
||||
Layout.preferredHeight: historyAvatar.height
|
||||
Layout.leftMargin: 5 * DefaultStyle.dp
|
||||
MultiEffect {
|
||||
source: historyAvatar
|
||||
anchors.fill: historyAvatar
|
||||
shadowEnabled: true
|
||||
shadowBlur: 1
|
||||
shadowColor: DefaultStyle.grey_900
|
||||
shadowOpacity: 0.1
|
||||
}
|
||||
Avatar {
|
||||
id: historyAvatar
|
||||
address: modelData.core.remoteAddress
|
||||
width: 45 * DefaultStyle.dp
|
||||
height: 45 * DefaultStyle.dp
|
||||
}
|
||||
}
|
||||
ColumnLayout {
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
Text {
|
||||
property var remoteAddress: modelData ? UtilsCpp.getDisplayName(modelData.core.remoteAddress) : undefined
|
||||
text: remoteAddress ? remoteAddress.value : ""
|
||||
font {
|
||||
pixelSize: 14 * DefaultStyle.dp
|
||||
weight: 400 * DefaultStyle.dp
|
||||
}
|
||||
}
|
||||
RowLayout {
|
||||
Image {
|
||||
source: modelData.core.status === LinphoneEnums.CallStatus.Declined
|
||||
|| modelData.core.status === LinphoneEnums.CallStatus.DeclinedElsewhere
|
||||
|| modelData.core.status === LinphoneEnums.CallStatus.Aborted
|
||||
|| modelData.core.status === LinphoneEnums.CallStatus.EarlyAborted
|
||||
? modelData.core.isOutgoing
|
||||
? AppIcons.outgoingCallRejected
|
||||
: AppIcons.incomingCallRejected
|
||||
: modelData.core.status === LinphoneEnums.CallStatus.Missed
|
||||
? modelData.core.isOutgoing
|
||||
? AppIcons.outgoingCallMissed
|
||||
: AppIcons.incomingCallMissed
|
||||
: modelData.core.isOutgoing
|
||||
? AppIcons.outgoingCall
|
||||
: AppIcons.incomingCall
|
||||
Layout.preferredWidth: 5 * DefaultStyle.dp
|
||||
Layout.preferredHeight: 5 * DefaultStyle.dp
|
||||
sourceSize.width: 5 * DefaultStyle.dp
|
||||
sourceSize.height: 5 * DefaultStyle.dp
|
||||
}
|
||||
Text {
|
||||
// text: modelData.core.date
|
||||
text: UtilsCpp.formatDateElapsedTime(modelData.core.date)
|
||||
font {
|
||||
pixelSize: 12 * DefaultStyle.dp
|
||||
weight: 300 * DefaultStyle.dp
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
Control.Button {
|
||||
implicitWidth: 24 * DefaultStyle.dp
|
||||
implicitHeight: 24 * DefaultStyle.dp
|
||||
Layout.rightMargin: 5 * DefaultStyle.dp
|
||||
padding: 0
|
||||
background: Item {
|
||||
visible: false
|
||||
}
|
||||
contentItem: Image {
|
||||
source: AppIcons.phone
|
||||
width: 24 * DefaultStyle.dp
|
||||
sourceSize.width: 24 * DefaultStyle.dp
|
||||
fillMode: Image.PreserveAspectFit
|
||||
}
|
||||
onClicked: {
|
||||
var addr = modelData.core.remoteAddress
|
||||
var addressEnd = "@sip.linphone.org"
|
||||
if (!addr.endsWith(addressEnd)) addr += addressEnd
|
||||
var callVarObject = UtilsCpp.createCall(addr)
|
||||
}
|
||||
}
|
||||
}
|
||||
MouseArea {
|
||||
hoverEnabled: true
|
||||
anchors.fill: parent
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
opacity: 0.1
|
||||
color: DefaultStyle.main2_500main
|
||||
visible: parent.containsMouse
|
||||
}
|
||||
onPressed: {
|
||||
historyListView.currentIndex = model.index
|
||||
}
|
||||
}
|
||||
onPressed: listView.currentIndex = parent.index
|
||||
}
|
||||
|
||||
onCountChanged: {
|
||||
mainItem.showDefaultItem = historyListView.count === 0 && historyListView.visible
|
||||
}
|
||||
|
||||
onVisibleChanged: {
|
||||
mainItem.showDefaultItem = historyListView.count === 0 && historyListView.visible
|
||||
if (!visible) currentIndex = -1
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: mainItem
|
||||
onShowDefaultItemChanged: mainItem.showDefaultItem = mainItem.showDefaultItem && historyListView.count === 0 && historyListView.visible
|
||||
onListViewUpdated: {
|
||||
historyListView.model.updateView()
|
||||
}
|
||||
}
|
||||
Control.ScrollBar.vertical: scrollbar
|
||||
}
|
||||
|
||||
onCountChanged: mainItem.showDefaultItem = listView.count === 0
|
||||
|
||||
Connections {
|
||||
target: mainItem
|
||||
onShowDefaultItemChanged: mainItem.showDefaultItem = mainItem.showDefaultItem && listView.count === 0
|
||||
}
|
||||
|
||||
Control.ScrollIndicator.vertical: Control.ScrollIndicator { }
|
||||
}
|
||||
}
|
||||
}
|
||||
Control.ScrollBar {
|
||||
id: scrollbar
|
||||
active: true
|
||||
Layout.fillHeight: true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -223,7 +342,321 @@ AbstractMainPage {
|
|||
}
|
||||
}
|
||||
|
||||
rightPanelContent: ColumnLayout {
|
||||
rightPanelContent: RowLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
visible: mainItem.selectedRowHistoryGui != undefined
|
||||
Layout.topMargin: 45 * DefaultStyle.dp
|
||||
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
}
|
||||
ColumnLayout {
|
||||
spacing: 30 * DefaultStyle.dp
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
Item {
|
||||
Layout.preferredHeight: detailAvatar.height
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Avatar {
|
||||
id: detailAvatar
|
||||
anchors.centerIn: parent
|
||||
width: 100 * DefaultStyle.dp
|
||||
height: 100 * DefaultStyle.dp
|
||||
address: mainItem.selectedRowHistoryGui ? mainItem.selectedRowHistoryGui.core.remoteAddress : ""
|
||||
}
|
||||
PopupButton {
|
||||
id: detailOptions
|
||||
anchors.left: detailAvatar.right
|
||||
anchors.leftMargin: 30 * DefaultStyle.dp
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
popup.x: width
|
||||
popup.contentItem: ColumnLayout {
|
||||
Button {
|
||||
background: Item {}
|
||||
contentItem: IconLabel {
|
||||
text: qsTr("Ajouter aux contacts")
|
||||
iconSource: AppIcons.plusCircle
|
||||
}
|
||||
onClicked: console.debug("[CallPage.qml] TODO : add to contact")
|
||||
}
|
||||
Button {
|
||||
background: Item {}
|
||||
contentItem: IconLabel {
|
||||
text: qsTr("Copier l'adresse SIP")
|
||||
iconSource: AppIcons.copy
|
||||
}
|
||||
onClicked: console.debug("[CallPage.qml] TODO : copy SIP address")
|
||||
}
|
||||
Button {
|
||||
background: Item {}
|
||||
contentItem: IconLabel {
|
||||
text: qsTr("Bloquer")
|
||||
iconSource: AppIcons.empty
|
||||
}
|
||||
onClicked: console.debug("[CallPage.qml] TODO : block user")
|
||||
}
|
||||
Rectangle {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 2 * DefaultStyle.dp
|
||||
color: DefaultStyle.main2_400
|
||||
}
|
||||
Button {
|
||||
background: Item {}
|
||||
contentItem: IconLabel {
|
||||
text: qsTr("Supprimer l'historique")
|
||||
iconSource: AppIcons.trashCan
|
||||
colorizationColor: DefaultStyle.danger_500main
|
||||
}
|
||||
onClicked: {
|
||||
detailListView.model.removeEntriesWithFilter()
|
||||
detailListView.currentIndex = -1 // reset index for ui
|
||||
detailOptions.closePopup()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ColumnLayout {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.fillWidth: true
|
||||
Text {
|
||||
property var remoteAddress: mainItem.selectedRowHistoryGui ? UtilsCpp.getDisplayName(mainItem.selectedRowHistoryGui.core.remoteAddress) : undefined
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
text: remoteAddress ? remoteAddress.value : ""
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
font {
|
||||
pixelSize: 14 * DefaultStyle.dp
|
||||
weight: 400 * DefaultStyle.dp
|
||||
}
|
||||
}
|
||||
Text {
|
||||
text: mainItem.selectedRowHistoryGui ? mainItem.selectedRowHistoryGui.core.remoteAddress : ""
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
font {
|
||||
pixelSize: 12 * DefaultStyle.dp
|
||||
weight: 300 * DefaultStyle.dp
|
||||
}
|
||||
}
|
||||
Text {
|
||||
// connection status
|
||||
}
|
||||
}
|
||||
RowLayout {
|
||||
spacing: 40 * DefaultStyle.dp
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.fillWidth: true
|
||||
// Layout.fillHeight: true
|
||||
Item {Layout.fillWidth: true}
|
||||
LabelButton {
|
||||
Layout.preferredWidth: 24 * DefaultStyle.dp//image.width
|
||||
Layout.preferredHeight: image.height
|
||||
image.source: AppIcons.phone
|
||||
label: qsTr("Appel")
|
||||
button.onClicked: {
|
||||
var addr = mainItem.selectedRowHistoryGui.core.remoteAddress
|
||||
var addressEnd = "@sip.linphone.org"
|
||||
if (!addr.endsWith(addressEnd)) addr += addressEnd
|
||||
UtilsCpp.createCall(addr)
|
||||
}
|
||||
}
|
||||
LabelButton {
|
||||
Layout.preferredWidth: image.width
|
||||
Layout.preferredHeight: image.height
|
||||
image.source: AppIcons.chatTeardropText
|
||||
label: qsTr("Message")
|
||||
button.onClicked: console.debug("[CallPage.qml] TODO : open conversation")
|
||||
}
|
||||
LabelButton {
|
||||
Layout.preferredWidth: image.width
|
||||
Layout.preferredHeight: image.height
|
||||
image.source: AppIcons.videoCamera
|
||||
label: qsTr("Appel Video")
|
||||
button.onClicked: {
|
||||
var addr = mainItem.selectedRowHistoryGui.core.remoteAddress
|
||||
var addressEnd = "@sip.linphone.org"
|
||||
if(!addr.endsWith(addressEnd)) addr += addressEnd
|
||||
UtilsCpp.createCall(addr)
|
||||
console.log("[CallPage.qml] TODO : enable video")
|
||||
}
|
||||
}
|
||||
Item {Layout.fillWidth: true}
|
||||
|
||||
}
|
||||
|
||||
Control.Control {
|
||||
id: detailControl
|
||||
Layout.preferredWidth: detailListView.width + leftPadding + rightPadding
|
||||
implicitHeight: 430 * DefaultStyle.dp + topPadding + bottomPadding
|
||||
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.topMargin: 30 * DefaultStyle.dp
|
||||
|
||||
topPadding: 16 * DefaultStyle.dp
|
||||
bottomPadding: 21 * DefaultStyle.dp
|
||||
leftPadding: 17 * DefaultStyle.dp
|
||||
rightPadding: 17 * DefaultStyle.dp
|
||||
|
||||
background: Rectangle {
|
||||
id: detailListBackground
|
||||
width: parent.width
|
||||
height: detailListView.height
|
||||
color: DefaultStyle.grey_0
|
||||
radius: 15 * DefaultStyle.dp
|
||||
}
|
||||
ListView {
|
||||
id: detailListView
|
||||
width: 360 * DefaultStyle.dp
|
||||
height: Math.min(detailControl.implicitHeight, contentHeight)
|
||||
anchors.centerIn: detailListBackground
|
||||
anchors.bottomMargin: 21 * DefaultStyle.dp
|
||||
spacing: 10 * DefaultStyle.dp
|
||||
clip: true
|
||||
|
||||
onCountChanged: {
|
||||
mainItem.listViewUpdated()
|
||||
}
|
||||
|
||||
model: CallHistoryProxy {
|
||||
filterText: mainItem.selectedRowHistoryGui ? mainItem.selectedRowHistoryGui.core.remoteAddress : ""
|
||||
}
|
||||
delegate: Item {
|
||||
width:detailListView.width
|
||||
height: 56 * DefaultStyle.dp
|
||||
// anchors.topMargin: 5 * DefaultStyle.dp
|
||||
// anchors.bottomMargin: 5 * DefaultStyle.dp
|
||||
RowLayout {
|
||||
anchors.fill: parent
|
||||
ColumnLayout {
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
RowLayout {
|
||||
Image {
|
||||
source: modelData.core.status === LinphoneEnums.CallStatus.Declined
|
||||
|| modelData.core.status === LinphoneEnums.CallStatus.DeclinedElsewhere
|
||||
|| modelData.core.status === LinphoneEnums.CallStatus.Aborted
|
||||
|| modelData.core.status === LinphoneEnums.CallStatus.EarlyAborted
|
||||
? modelData.core.isOutgoing
|
||||
? AppIcons.outgoingCallRejected
|
||||
: AppIcons.incomingCallRejected
|
||||
: modelData.core.status === LinphoneEnums.CallStatus.Missed
|
||||
? modelData.core.isOutgoing
|
||||
? AppIcons.outgoingCallMissed
|
||||
: AppIcons.incomingCallMissed
|
||||
: modelData.core.isOutgoing
|
||||
? AppIcons.outgoingCall
|
||||
: AppIcons.incomingCall
|
||||
Layout.preferredWidth: 6.67 * DefaultStyle.dp
|
||||
Layout.preferredHeight: 6.67 * DefaultStyle.dp
|
||||
sourceSize.width: 6.67 * DefaultStyle.dp
|
||||
sourceSize.height: 6.67 * DefaultStyle.dp
|
||||
}
|
||||
Text {
|
||||
Component.onCompleted: console.log("status", modelData.core.status)
|
||||
text: modelData.core.status === LinphoneEnums.CallStatus.Missed
|
||||
? qsTr("Appel manqué")
|
||||
: modelData.core.isOutgoing
|
||||
? qsTr("Appel sortant")
|
||||
: qsTr("Appel entrant")
|
||||
font {
|
||||
pixelSize: 14 * DefaultStyle.dp
|
||||
weight: 400 * DefaultStyle.dp
|
||||
}
|
||||
}
|
||||
}
|
||||
Text {
|
||||
text: UtilsCpp.formatDate(modelData.core.date)
|
||||
color: modelData.core.status === LinphoneEnums.CallStatus.Missed? DefaultStyle.danger_500main : DefaultStyle.main2_500main
|
||||
font {
|
||||
pixelSize: 12 * DefaultStyle.dp
|
||||
weight: 300 * DefaultStyle.dp
|
||||
}
|
||||
}
|
||||
}
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
Text {
|
||||
text: UtilsCpp.formatElapsedTime(modelData.core.duration, false)
|
||||
font {
|
||||
pixelSize: 12 * DefaultStyle.dp
|
||||
weight: 300 * DefaultStyle.dp
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
}
|
||||
}
|
||||
|
||||
component LabelButton: ColumnLayout {
|
||||
id: labelButton
|
||||
property alias image: buttonImg
|
||||
property alias button: button
|
||||
property string label
|
||||
spacing: 8 * DefaultStyle.dp
|
||||
Button {
|
||||
id: button
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.preferredWidth: 56 * DefaultStyle.dp
|
||||
Layout.preferredHeight: 56 * DefaultStyle.dp
|
||||
topPadding: 16 * DefaultStyle.dp
|
||||
bottomPadding: 16 * DefaultStyle.dp
|
||||
leftPadding: 16 * DefaultStyle.dp
|
||||
rightPadding: 16 * DefaultStyle.dp
|
||||
background: Rectangle {
|
||||
anchors.fill: parent
|
||||
radius: 40 * DefaultStyle.dp
|
||||
color: DefaultStyle.main2_200
|
||||
}
|
||||
contentItem: Image {
|
||||
id: buttonImg
|
||||
source: labelButton.source
|
||||
width: 24 * DefaultStyle.dp
|
||||
height: 24 * DefaultStyle.dp
|
||||
fillMode: Image.PreserveAspectFit
|
||||
sourceSize.width: 24 * DefaultStyle.dp
|
||||
sourceSize.height: 24 * DefaultStyle.dp
|
||||
}
|
||||
}
|
||||
Text {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
text: labelButton.label
|
||||
font {
|
||||
pixelSize: 14 * DefaultStyle.dp
|
||||
weight: 400 * DefaultStyle.dp
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
component IconLabel: RowLayout {
|
||||
id: iconLabel
|
||||
property string text
|
||||
property string iconSource
|
||||
property color colorizationColor: DefaultStyle.main2_500main
|
||||
EffectImage {
|
||||
image.source: iconLabel.iconSource
|
||||
width: 24 * DefaultStyle.dp
|
||||
height: 24 * DefaultStyle.dp
|
||||
Layout.preferredWidth: 24 * DefaultStyle.dp
|
||||
Layout.preferredHeight: 24 * DefaultStyle.dp
|
||||
image.fillMode: Image.PreserveAspectFit
|
||||
colorizationColor: iconLabel.colorizationColor
|
||||
}
|
||||
Text {
|
||||
text: iconLabel.text
|
||||
color: iconLabel.colorizationColor
|
||||
font {
|
||||
pixelSize: 14 * DefaultStyle.dp
|
||||
weight: 400 * DefaultStyle.dp
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ QtObject {
|
|||
property string incomingCallRejected: "image://internal/incoming_call_rejected.svg"
|
||||
property string outgoingCall: "image://internal/outgoing_call.svg"
|
||||
property string outgoingCallMissed: "image://internal/outgoing_call_missed.svg"
|
||||
property string outgoingCallRejected: "image://internal/outgoing_call_rejected.svg"
|
||||
property string microphone: "image://internal/microphone.svg"
|
||||
property string microphoneSlash: "image://internal/microphone-slash.svg"
|
||||
property string videoCamera: "image://internal/video-camera.svg"
|
||||
|
|
@ -57,4 +58,7 @@ QtObject {
|
|||
property string pause: "image://internal/pause.svg"
|
||||
property string play: "image://internal/play.svg"
|
||||
property string smiley: "image://internal/smiley.svg"
|
||||
property string trashCan: "image://internal/trash-simple.svg"
|
||||
property string copy: "image://internal/copy.svg"
|
||||
property string empty: "image://internal/empty.svg"
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue