mirror of
https://invent.kde.org/marcoa/shift-shell.git
synced 2026-04-26 14:23:09 +00:00
Use a proper model for the call history
This commit is contained in:
parent
d15262b394
commit
c377254bd1
8 changed files with 241 additions and 90 deletions
|
|
@ -25,7 +25,7 @@ include(ECMGenerateHeaders)
|
|||
include(GenerateExportHeader)
|
||||
include(FeatureSummary)
|
||||
|
||||
find_package(Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED Core Gui Widgets Qml Quick Test)
|
||||
find_package(Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED Core Gui Widgets Qml Quick Test Sql)
|
||||
|
||||
find_package(KF5 ${KF5_MIN_VERSION} REQUIRED COMPONENTS Plasma Service Declarative I18n KIO People)
|
||||
find_package(KF5 REQUIRED COMPONENTS PlasmaQuick DBusAddons Notifications)
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ set(plasmaphonedialer_SRCS
|
|||
main.cpp
|
||||
dialerutils.cpp
|
||||
call-handler.cpp
|
||||
callhistorymodel.cpp
|
||||
call-manager.cpp
|
||||
resources.qrc
|
||||
)
|
||||
|
|
@ -15,6 +16,7 @@ target_link_libraries(plasmaphonedialer
|
|||
Qt5::Gui
|
||||
Qt5::Quick
|
||||
Qt5::Widgets
|
||||
Qt5::Sql
|
||||
KF5::Declarative
|
||||
KF5::I18n
|
||||
KF5::QuickAddons
|
||||
|
|
|
|||
149
dialer/src/callhistorymodel.cpp
Normal file
149
dialer/src/callhistorymodel.cpp
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
Copyright (C) 2019 Nicolas Fella <nicolas.fella@gmx.de>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "callhistorymodel.h"
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QStandardPaths>
|
||||
#include <QSqlQuery>
|
||||
#include <QSqlError>
|
||||
#include <QDebug>
|
||||
|
||||
CallHistoryModel::CallHistoryModel(QObject *parent)
|
||||
: QAbstractListModel(parent)
|
||||
, m_db(QSqlDatabase::addDatabase(QStringLiteral("QSQLITE"), QStringLiteral("calldb")))
|
||||
{
|
||||
m_db.setDatabaseName(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "plasmaphonedialerdb.sqlite");
|
||||
bool open = m_db.open();
|
||||
|
||||
if (!open) {
|
||||
qWarning() << "Could not open call database" << m_db.lastError();
|
||||
}
|
||||
|
||||
QSqlQuery createTable(m_db);
|
||||
createTable.exec(QStringLiteral("CREATE TABLE IF NOT EXISTS History(id INTEGER PRIMARY KEY AUTOINCREMENT, number TEXT, time DATETIME, duration INTEGER, callType INTEGER)"));
|
||||
|
||||
QSqlQuery fetchCalls(m_db);
|
||||
fetchCalls.exec(QStringLiteral("SELECT id, number, time, duration, callType FROM History"));
|
||||
|
||||
beginResetModel();
|
||||
while (fetchCalls.next()) {
|
||||
CallData call;
|
||||
call.id = fetchCalls.value(0).toString();
|
||||
call.number = fetchCalls.value(1).toString();
|
||||
call.time = QDateTime::fromMSecsSinceEpoch(fetchCalls.value(2).toInt());
|
||||
call.duration = fetchCalls.value(3).toInt();
|
||||
call.callType = fetchCalls.value(4).toInt();
|
||||
|
||||
m_calls.append(call);
|
||||
}
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
void CallHistoryModel::addCall(QString number, int duration, int type)
|
||||
{
|
||||
beginInsertRows(QModelIndex(), m_calls.size(), m_calls.size());
|
||||
QSqlQuery putCall(m_db);
|
||||
putCall.prepare(QStringLiteral("INSERT INTO History (number, time, duration, callType) VALUES (:number, :time, :duration, :callType)"));
|
||||
putCall.bindValue(":number", number);
|
||||
putCall.bindValue(":time", QDateTime::currentDateTime().toMSecsSinceEpoch());
|
||||
putCall.bindValue(":duration", duration);
|
||||
putCall.bindValue(":callType", type);
|
||||
putCall.exec();
|
||||
|
||||
CallData data;
|
||||
data.id = putCall.lastInsertId().toString();
|
||||
data.number = number;
|
||||
data.duration = duration;
|
||||
data.time = QDateTime::currentDateTime();
|
||||
data.callType = type;
|
||||
|
||||
m_calls.append(data);
|
||||
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
void CallHistoryModel::clear()
|
||||
{
|
||||
beginResetModel();
|
||||
|
||||
QSqlQuery clearCalls(m_db);
|
||||
clearCalls.exec(QStringLiteral("DELETE FROM History"));
|
||||
m_calls.clear();
|
||||
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
QVariant CallHistoryModel::data(const QModelIndex& index, int role) const
|
||||
{
|
||||
int row = index.row();
|
||||
|
||||
switch (role) {
|
||||
case Roles::PhoneNumberRole:
|
||||
return m_calls[row].number;
|
||||
case Roles::CallTypeRole:
|
||||
return m_calls[row].callType;
|
||||
case Roles::DurationRole:
|
||||
return m_calls[row].duration;
|
||||
case Roles::TimeRole:
|
||||
return m_calls[row].time;
|
||||
case Roles::IdRole:
|
||||
return m_calls[row].id;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
int CallHistoryModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent)
|
||||
return m_calls.size();
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> CallHistoryModel::roleNames() const
|
||||
{
|
||||
QHash<int, QByteArray> roleNames;
|
||||
roleNames[PhoneNumberRole] = "number";
|
||||
roleNames[CallTypeRole] = "time";
|
||||
roleNames[DurationRole] = "duration";
|
||||
roleNames[TimeRole] = "callType";
|
||||
roleNames[IdRole] = "dbid";
|
||||
|
||||
return roleNames;
|
||||
}
|
||||
|
||||
bool CallHistoryModel::removeRows(int row, int count, const QModelIndex &parent)
|
||||
{
|
||||
Q_UNUSED(count)
|
||||
|
||||
beginRemoveRows(parent, row, row);
|
||||
QSqlQuery remove(m_db);
|
||||
remove.prepare(QStringLiteral("DELETE FROM History WHERE id=:id"));
|
||||
remove.bindValue(":id", m_calls[row].id);
|
||||
remove.exec();
|
||||
|
||||
endRemoveRows();
|
||||
return true;
|
||||
}
|
||||
|
||||
void CallHistorySortFilterModel::remove(int index)
|
||||
{
|
||||
QSortFilterProxyModel::removeRow(index);
|
||||
}
|
||||
|
||||
void CallHistorySortFilterModel::sort(int column, Qt::SortOrder order)
|
||||
{
|
||||
QSortFilterProxyModel::sort(column, order);
|
||||
}
|
||||
69
dialer/src/callhistorymodel.h
Normal file
69
dialer/src/callhistorymodel.h
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
Copyright (C) 2019 Nicolas Fella <nicolas.fella@gmx.de>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <QAbstractListModel>
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <QSqlDatabase>
|
||||
#include <QDateTime>
|
||||
#include <QVector>
|
||||
|
||||
struct CallData {
|
||||
QString id;
|
||||
QString number;
|
||||
QDateTime time;
|
||||
int duration;
|
||||
int callType;
|
||||
};
|
||||
|
||||
class CallHistoryModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
CallHistoryModel(QObject *parent = nullptr);
|
||||
|
||||
enum Roles {
|
||||
PhoneNumberRole = Qt::UserRole + 1,
|
||||
DurationRole,
|
||||
TimeRole,
|
||||
CallTypeRole,
|
||||
IdRole
|
||||
};
|
||||
Q_ENUM(Roles)
|
||||
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
Q_INVOKABLE void addCall(QString number, int duration, int type);
|
||||
Q_INVOKABLE void clear();
|
||||
|
||||
bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
|
||||
|
||||
private:
|
||||
QSqlDatabase m_db;
|
||||
QVector<CallData> m_calls;
|
||||
};
|
||||
|
||||
class CallHistorySortFilterModel : public QSortFilterProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
Q_INVOKABLE void remove(int index);
|
||||
Q_INVOKABLE void sort(int column, Qt::SortOrder order = Qt::AscendingOrder) override;
|
||||
};
|
||||
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include "dialerutils.h"
|
||||
#include "call-handler.h"
|
||||
#include "callhistorymodel.h"
|
||||
|
||||
#include <TelepathyQt/Types>
|
||||
#include <TelepathyQt/Debug>
|
||||
|
|
@ -109,6 +110,9 @@ int main(int argc, char **argv)
|
|||
|
||||
parser.process(app);
|
||||
|
||||
qmlRegisterType<CallHistoryModel>("org.kde.plasma.dialer", 1, 0, "CallHistoryModel");
|
||||
qmlRegisterType<CallHistorySortFilterModel>("org.kde.plasma.dialer", 1, 0, "CallHistorySortFilterModel");
|
||||
|
||||
Tp::registerTypes();
|
||||
|
||||
Tp::AccountFactoryPtr accountFactory = Tp::AccountFactory::create(QDBusConnection::sessionBus(),
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@ import org.kde.plasma.core 2.0 as PlasmaCore
|
|||
import org.kde.plasma.components 2.0 as PlasmaComponents
|
||||
import org.kde.plasma.extras 2.0 as PlasmaExtras
|
||||
|
||||
import org.kde.plasma.dialer 1.0
|
||||
|
||||
Item {
|
||||
|
||||
function secondsToTimeString(seconds) {
|
||||
|
|
@ -38,12 +40,12 @@ Item {
|
|||
PlasmaComponents.Label {
|
||||
anchors.centerIn: parent
|
||||
text: i18n("No recent calls")
|
||||
visible: historyModel.count == 0
|
||||
visible: view.count == 0
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
visible: historyModel.count > 0
|
||||
visible: view.count > 0
|
||||
PlasmaComponents.ToolBar {
|
||||
Layout.fillWidth: true
|
||||
tools: RowLayout {
|
||||
|
|
@ -55,7 +57,7 @@ Item {
|
|||
text: i18n("All")
|
||||
onCheckedChanged: {
|
||||
if (checked) {
|
||||
filterModel.filterString = "";
|
||||
filterModel.setFilterFixedString("")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -64,7 +66,7 @@ Item {
|
|||
text: i18n("Missed")
|
||||
onCheckedChanged: {
|
||||
if (checked) {
|
||||
filterModel.filterString = "0";
|
||||
filterModel.setFilterFixedString("0")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -74,7 +76,7 @@ Item {
|
|||
}
|
||||
PlasmaComponents.Button {
|
||||
text: i18n("Clear")
|
||||
onClicked: clearHistory();
|
||||
onClicked: historyModel.clear()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -83,12 +85,12 @@ Item {
|
|||
Layout.fillHeight: true
|
||||
ListView {
|
||||
id: view
|
||||
model: PlasmaCore.SortFilterModel {
|
||||
model: CallHistorySortFilterModel {
|
||||
id: filterModel
|
||||
sourceModel: historyModel
|
||||
filterRole: "callType"
|
||||
sortRole: "time"
|
||||
sortOrder: Qt.DescendingOrder
|
||||
filterRole: CallHistoryModel.CallTypeRole
|
||||
sortRole: CallHistoryModel.TimeRole
|
||||
Component.onCompleted: sort(0, Qt.DescendingOrder)
|
||||
}
|
||||
section {
|
||||
property: "date"
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@ import QtQuick.Controls 2.2 as Controls
|
|||
import org.kde.kirigami 2.2 as Kirigami
|
||||
import org.kde.plasma.components 2.0 as PlasmaComponents
|
||||
|
||||
|
||||
Item {
|
||||
id: delegateParent
|
||||
width: view.width
|
||||
|
|
@ -50,7 +49,7 @@ Item {
|
|||
easing.type: Easing.InOutQuad
|
||||
}
|
||||
ScriptAction {
|
||||
script: removeCallFromHistory(model.originalIndex);
|
||||
script: filterModel.remove(model.index)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@ import QtQuick.LocalStorage 2.0
|
|||
import org.kde.plasma.extras 2.0 as PlasmaExtras
|
||||
import org.kde.kirigami 2.0 as Kirigami
|
||||
|
||||
import org.kde.plasma.dialer 1.0
|
||||
|
||||
ApplicationWindow {
|
||||
id: root
|
||||
|
||||
|
|
@ -57,7 +59,7 @@ ApplicationWindow {
|
|||
} else {
|
||||
callType = 2;
|
||||
}
|
||||
insertCallInHistory(callContactNumber, callDuration, callType);
|
||||
historyModel.addCall(callContactNumber, callDuration, callType)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -71,86 +73,10 @@ ApplicationWindow {
|
|||
function call(number) {
|
||||
dialerUtils.dial(number);
|
||||
}
|
||||
|
||||
function insertCallInHistory(number, duration, callType) {
|
||||
//DATABSE
|
||||
var db = LocalStorage.openDatabaseSync("PlasmaPhoneDialer", "1.0", "Call history of the Plasma Phone dialer", 1000000);
|
||||
|
||||
db.transaction(
|
||||
function(tx) {
|
||||
var rs = tx.executeSql("INSERT INTO History VALUES(NULL, ?, datetime('now'), ?, ? )", [number, duration, callType]);
|
||||
|
||||
var rs = tx.executeSql('SELECT * FROM History where id=?', [rs.insertId]);
|
||||
|
||||
for(var i = 0; i < rs.rows.length; i++) {
|
||||
var row = rs.rows.item(i);
|
||||
row.date = Qt.formatDate(row.time, "yyyy-MM-dd");
|
||||
row.originalIndex = historyModel.count;
|
||||
historyModel.append(row);
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
//index is historyModel row number, not db id and not sortmodel row number
|
||||
function removeCallFromHistory(index) {
|
||||
var item = historyModel.get(index);
|
||||
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
|
||||
var db = LocalStorage.openDatabaseSync("PlasmaPhoneDialer", "1.0", "Call history of the Plasma Phone dialer", 1000000);
|
||||
|
||||
db.transaction(
|
||||
function(tx) {
|
||||
tx.executeSql("DELETE from History WHERE id=?", [item.id]);
|
||||
}
|
||||
)
|
||||
|
||||
historyModel.remove(index);
|
||||
}
|
||||
|
||||
function clearHistory() {
|
||||
var db = LocalStorage.openDatabaseSync("PlasmaPhoneDialer", "1.0", "Call history of the Plasma Phone dialer", 1000000);
|
||||
|
||||
db.transaction(
|
||||
function(tx) {
|
||||
tx.executeSql("DELETE from History");
|
||||
}
|
||||
)
|
||||
|
||||
historyModel.clear();
|
||||
}
|
||||
|
||||
//END FUNCTIONS
|
||||
|
||||
//BEGIN DATABASE
|
||||
Component.onCompleted: {
|
||||
//DATABSE
|
||||
var db = LocalStorage.openDatabaseSync("PlasmaPhoneDialer", "1.0", "Call history of the Plasma Phone dialer", 1000000);
|
||||
|
||||
db.transaction(
|
||||
function(tx) {
|
||||
// Create the database if it doesn't already exist
|
||||
//callType: whether is incoming, outgoing, unanswered
|
||||
tx.executeSql('CREATE TABLE IF NOT EXISTS History(id INTEGER PRIMARY KEY AUTOINCREMENT, number TEXT, time DATETIME, duration INTEGER, callType INTEGER)');
|
||||
|
||||
var rs = tx.executeSql('SELECT * FROM History');
|
||||
|
||||
for(var i = 0; i < rs.rows.length; i++) {
|
||||
var row = rs.rows.item(i);
|
||||
row.date = Qt.formatDate(row.time, "yyyy-MM-dd");
|
||||
row.originalIndex = historyModel.count;
|
||||
historyModel.append(row);
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
//END DATABASE
|
||||
|
||||
//BEGIN MODELS
|
||||
ListModel {
|
||||
CallHistoryModel {
|
||||
id: historyModel
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue