Commit c377254b authored by Nicolas Fella's avatar Nicolas Fella Committed by Bhushan Shah

Use a proper model for the call history

parent d15262b3
......@@ -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
......
/*
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);
}
/*
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
}
......
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