diff --git a/MinimalHistoryBackend.mm b/MinimalHistoryBackend.mm index 064533f92882a3cd259fea4abb9e9ba22f85f2c6..77377f441fabdb081239d88c5049a92cf34d59f9 100644 --- a/MinimalHistoryBackend.mm +++ b/MinimalHistoryBackend.mm @@ -20,223 +20,231 @@ //Qt #include <QtCore/QFile> +#include <QtCore/QDir> #include <QtCore/QHash> -#include <QtCore/qcoreapplication.h> +#include <QtWidgets/QApplication> +#include <QtCore/QStandardPaths> //Ring -#include "call.h" -#include "account.h" -#include "phonenumber.h" -#include "historymodel.h" +#include <call.h> +#include <account.h> +#include <person.h> +#include <contactmethod.h> +#include <historymodel.h> +class MinimalHistoryEditor : public CollectionEditor<Call> +{ +public: + MinimalHistoryEditor(CollectionMediator<Call>* m, MinimalHistoryBackend* parent); + virtual bool save ( const Call* item ) override; + virtual bool remove ( const Call* item ) override; + virtual bool edit ( Call* item ) override; + virtual bool addNew ( const Call* item ) override; + virtual bool addExisting( const Call* item ) override; + +private: + virtual QVector<Call*> items() const override; + + //Helpers + void saveCall(QTextStream& stream, const Call* call); + bool regenFile(const Call* toIgnore); + + //Attributes + QVector<Call*> m_lItems; + MinimalHistoryBackend* m_pCollection; +}; + +MinimalHistoryEditor::MinimalHistoryEditor(CollectionMediator<Call>* m, MinimalHistoryBackend* parent) : +CollectionEditor<Call>(m),m_pCollection(parent) +{ + +} + +MinimalHistoryBackend::MinimalHistoryBackend(CollectionMediator<Call>* mediator) : +CollectionInterface(new MinimalHistoryEditor(mediator,this)),m_pMediator(mediator) +{ +} MinimalHistoryBackend::~MinimalHistoryBackend() { } -bool MinimalHistoryEditor::save(const Call* item) +void MinimalHistoryEditor::saveCall(QTextStream& stream, const Call* call) +{ + const QString direction = (call->direction()==Call::Direction::INCOMING)? + Call::HistoryStateName::INCOMING : Call::HistoryStateName::OUTGOING; + + const Account* a = call->account(); + stream << QString("%1=%2\n").arg(Call::HistoryMapFields::CALLID ).arg(call->historyId() ); + stream << QString("%1=%2\n").arg(Call::HistoryMapFields::TIMESTAMP_START ).arg(call->startTimeStamp() ); + stream << QString("%1=%2\n").arg(Call::HistoryMapFields::TIMESTAMP_STOP ).arg(call->stopTimeStamp() ); + stream << QString("%1=%2\n").arg(Call::HistoryMapFields::ACCOUNT_ID ).arg(a?QString(a->id()):"" ); + stream << QString("%1=%2\n").arg(Call::HistoryMapFields::DISPLAY_NAME ).arg(call->peerName() ); + stream << QString("%1=%2\n").arg(Call::HistoryMapFields::PEER_NUMBER ).arg(call->peerContactMethod()->uri() ); + stream << QString("%1=%2\n").arg(Call::HistoryMapFields::DIRECTION ).arg(direction ); + stream << QString("%1=%2\n").arg(Call::HistoryMapFields::MISSED ).arg(call->isMissed() ); + stream << QString("%1=%2\n").arg(Call::HistoryMapFields::RECORDING_PATH ).arg(call->recordingPath() ); + stream << QString("%1=%2\n").arg(Call::HistoryMapFields::CONTACT_USED ).arg(false );//TODO + if (call->peerContactMethod()->contact()) { + stream << QString("%1=%2\n").arg(Call::HistoryMapFields::CONTACT_UID ).arg( + QString(call->peerContactMethod()->contact()->uid()) + ); + } + stream << "\n"; + stream.flush(); +} + +bool MinimalHistoryEditor::regenFile(const Call* toIgnore) { - Q_UNUSED(item) - return false; + QDir dir(QString('/')); + dir.mkpath(QStandardPaths::writableLocation(QStandardPaths::DataLocation) + QLatin1Char('/') + QString()); + + QFile file(QStandardPaths::writableLocation(QStandardPaths::DataLocation) + QLatin1Char('/') +"history.ini"); + if ( file.open(QIODevice::WriteOnly | QIODevice::Text) ) { + QTextStream stream(&file); + for (const Call* c : HistoryModel::instance()->getHistoryCalls()) { + if (c != toIgnore) + saveCall(stream, c); + } + file.close(); + return true; + } + return false; } -bool MinimalHistoryEditor::append(const Call* item) +bool MinimalHistoryEditor::save(const Call* call) { - Q_UNUSED(item) - return false; + if (call->collection()->editor<Call>() != this) + return addNew(call); + + return regenFile(nullptr); } -bool MinimalHistoryEditor::remove(Call* item) +bool MinimalHistoryEditor::remove(const Call* item) { - Q_UNUSED(item) - return false; + return regenFile(item); } bool MinimalHistoryEditor::edit( Call* item) { - Q_UNUSED(item) - return false; + Q_UNUSED(item) + return false; +} + +bool MinimalHistoryEditor::addNew(const Call* call) +{ + QDir dir(QString('/')); + dir.mkpath(QStandardPaths::writableLocation(QStandardPaths::DataLocation) + QLatin1Char('/') + QString()); + + if ((call->collection() && call->collection()->editor<Call>() == this) || call->historyId().isEmpty()) return false; + //TODO support \r and \n\r end of line + QFile file(QStandardPaths::writableLocation(QStandardPaths::DataLocation) + QLatin1Char('/')+"history.ini"); + + if ( file.open(QIODevice::Append | QIODevice::Text) ) { + QTextStream streamFileOut(&file); + saveCall(streamFileOut, call); + file.close(); + + const_cast<Call*>(call)->setCollection(m_pCollection); + addExisting(call); + return true; + } + else + qWarning() << "Unable to save history"; + return false; } -bool MinimalHistoryEditor::addNew( Call* item) +bool MinimalHistoryEditor::addExisting(const Call* item) { - Q_UNUSED(item) - return false; + m_lItems << const_cast<Call*>(item); + mediator()->addItem(item); + return true; } QVector<Call*> MinimalHistoryEditor::items() const { - return QVector<Call*>(); + return m_lItems; } QString MinimalHistoryBackend::name () const { - return QObject::tr("Minimal history backend"); + return QObject::tr("Minimal history backend"); } QString MinimalHistoryBackend::category () const { - return QObject::tr("History"); + return QObject::tr("History"); } QVariant MinimalHistoryBackend::icon() const { - return QVariant(); + return QVariant(); } bool MinimalHistoryBackend::isEnabled() const { - return true; + return true; } bool MinimalHistoryBackend::load() { - QFile file(QCoreApplication::applicationDirPath() +"/history.ini"); - if ( file.open(QIODevice::ReadOnly | QIODevice::Text) ) { - QMap<QString,QString> hc; - while (!file.atEnd()) { - QByteArray line = file.readLine().trimmed(); - - //The item is complete - if ((line.isEmpty() || !line.size()) && hc.size()) { - Call* pastCall = Call::buildHistoryCall(hc); - if (pastCall->peerName().isEmpty()) { - pastCall->setPeerName(QObject::tr("Unknown")); + QFile file(QStandardPaths::writableLocation(QStandardPaths::DataLocation) + QLatin1Char('/') +"history.ini"); + if ( file.open(QIODevice::ReadOnly | QIODevice::Text) ) { + QMap<QString,QString> hc; + while (!file.atEnd()) { + QByteArray line = file.readLine().trimmed(); + + //The item is complete + if ((line.isEmpty() || !line.size()) && hc.size()) { + Call* pastCall = Call::buildHistoryCall(hc); + if (pastCall->peerName().isEmpty()) { + pastCall->setPeerName(QObject::tr("Unknown")); + } + pastCall->setRecordingPath(hc[ Call::HistoryMapFields::RECORDING_PATH ]); + pastCall->setCollection(this); + + editor<Call>()->addExisting(pastCall); + hc.clear(); } - pastCall->setRecordingPath(hc[ Call::HistoryMapFields::RECORDING_PATH ]); - pastCall->setBackend(this); - m_pMediator->addItem(pastCall); - hc.clear(); - } - // Add to the current set - else { - const int idx = line.indexOf("="); - if (idx >= 0) - hc[line.left(idx)] = line.right(line.size()-idx-1); - } - } - return true; - } - else - qWarning() << "History doesn't exist or is not readable"; - return false; + // Add to the current set + else { + const int idx = line.indexOf("="); + if (idx >= 0) + hc[line.left(idx)] = line.right(line.size()-idx-1); + } + } + return true; + } + else + qWarning() << "History doesn't exist or is not readable"; + return false; } bool MinimalHistoryBackend::reload() { - return false; -} - - -// bool MinimalHistoryBackend::append(const Call* call) -// { -// if (call->backend() == this || call->id().isEmpty()) return false; -// //TODO support \r and \n\r end of line -// QFile file(KStandardDirs::locateLocal("appdata","")+"history.ini"); -// if ( file.open(QIODevice::Append | QIODevice::Text) ) { -// const QString direction = (call->direction()==Call::Direction::INCOMING)? -// Call::HistoryStateName::INCOMING : Call::HistoryStateName::OUTGOING; -// QTextStream streamFileOut(&file); -// const Account* a = call->account(); -// streamFileOut << QString("%1=%2\n").arg(Call::HistoryMapFields::CALLID ).arg(call->id() ); -// streamFileOut << QString("%1=%2\n").arg(Call::HistoryMapFields::TIMESTAMP_START ).arg(call->startTimeStamp() ); -// streamFileOut << QString("%1=%2\n").arg(Call::HistoryMapFields::TIMESTAMP_STOP ).arg(call->stopTimeStamp() ); -// streamFileOut << QString("%1=%2\n").arg(Call::HistoryMapFields::ACCOUNT_ID ).arg(a?QString(a->id()):"" ); -// streamFileOut << QString("%1=%2\n").arg(Call::HistoryMapFields::DISPLAY_NAME ).arg(call->peerName() ); -// streamFileOut << QString("%1=%2\n").arg(Call::HistoryMapFields::PEER_NUMBER ).arg(call->peerPhoneNumber()->uri() ); -// streamFileOut << QString("%1=%2\n").arg(Call::HistoryMapFields::DIRECTION ).arg(direction ); -// streamFileOut << QString("%1=%2\n").arg(Call::HistoryMapFields::MISSED ).arg(call->isMissed() ); -// streamFileOut << QString("%1=%2\n").arg(Call::HistoryMapFields::RECORDING_PATH ).arg(call->recordingPath() ); -// streamFileOut << QString("%1=%2\n").arg(Call::HistoryMapFields::CONTACT_USED ).arg(false );//TODO -// if (call->peerPhoneNumber()->contact()) { -// streamFileOut << QString("%1=%2\n").arg(Call::HistoryMapFields::CONTACT_UID ).arg( -// QString(call->peerPhoneNumber()->contact()->uid()) -// ); -// } -// streamFileOut << "\n"; -// streamFileOut.flush(); -// file.close(); -// return true; -// } -// else -// qWarning() << "Unable to save history"; -// return false; -// } - -/** Rewrite the file from scratch - * @todo Eventually check if it is necessary, it will be faster - */ -// bool MinimalHistoryBackend::save(const Call* call) -// { -// Q_UNUSED(call) -// if (call->backend() != this) -// append(call); -// -// //TODO, need to regenerate everything -// /*QFile file(KStandardDirs::locateLocal("appdata","")+"history.ini"); -// if ( file.open(QIODevice::WriteOnly | QIODevice::Text) ) { -// foreach(const Call* call, HistoryModel::instance()->getHistoryCalls()) { -// qDebug() << "HERE" << call->id(); -// } -// return true; -// }*/ -// return false; -// } + return false; +} CollectionInterface::SupportedFeatures MinimalHistoryBackend::supportedFeatures() const { - return (CollectionInterface::SupportedFeatures) ( - CollectionInterface::SupportedFeatures::NONE | - CollectionInterface::SupportedFeatures::LOAD | - CollectionInterface::SupportedFeatures::CLEAR | -// CollectionInterface::SupportedFeatures::REMOVE| - CollectionInterface::SupportedFeatures::ADD ); -} - -///Edit 'item', the implementation may be a GUI or somehting else -// bool MinimalHistoryBackend::edit( Call* call) -// { -// Q_UNUSED(call) -// return false; -// } - - -// bool MinimalHistoryBackend::remove ( Call* c ) -// { -// Q_UNUSED(c) -// qDebug() << "Removing item is not yet supported"; -// return true; -// } - -///Add a new item to the backend -// bool MinimalHistoryBackend::addNew( Call* call) -// { -// Q_UNUSED(call) -// return true; -// } - -///Add a new phone number to an existing item -// bool MinimalHistoryBackend::addPhoneNumber( Call* call , PhoneNumber* number ) -// { -// Q_UNUSED(call) -// Q_UNUSED(number) -// return false; -// } + return (CollectionInterface::SupportedFeatures) ( + CollectionInterface::SupportedFeatures::NONE | + CollectionInterface::SupportedFeatures::LOAD | + CollectionInterface::SupportedFeatures::CLEAR | + CollectionInterface::SupportedFeatures::REMOVE| + CollectionInterface::SupportedFeatures::ADD ); +} bool MinimalHistoryBackend::clear() { - QFile::remove(QCoreApplication::applicationDirPath()+"/history.ini"); + /* TODO: insert confirm dialog? */ + QFile::remove(QStandardPaths::writableLocation(QStandardPaths::DataLocation) + QLatin1Char('/') + "history.ini"); + return true; } QByteArray MinimalHistoryBackend::id() const { - return "mhb"; + return "mhb"; } - -// QList<Call*> MinimalHistoryBackend::items() const -// { -// return QList<Call*>(); //TODO -// } - diff --git a/minimalhistorybackend.h b/minimalhistorybackend.h index 9ec028245d82de5c7b6b226f77aad59f348c7e13..152bf7f446194a756bc9961687f5d5f4b1239a20 100644 --- a/minimalhistorybackend.h +++ b/minimalhistorybackend.h @@ -19,8 +19,8 @@ #ifndef MINIMALHISTORYBACKEND_H #define MINIMALHISTORYBACKEND_H -#include "collectioninterface.h" -#include "collectioneditor.h" +#include <collectioninterface.h> +#include <collectioneditor.h> class Call; @@ -29,58 +29,21 @@ template<typename T> class CollectionMediator; class LIB_EXPORT MinimalHistoryBackend : public CollectionInterface { public: - template<typename T> - explicit MinimalHistoryBackend(CollectionMediator<T>* mediator); - virtual ~MinimalHistoryBackend(); - - virtual bool load() override; - virtual bool reload() override; - virtual bool clear() override; -// virtual bool save(const Call* call) override; -// virtual bool append(const Call* item) override; - - virtual QString name () const override; - virtual QString category () const override; - virtual QVariant icon () const override; - virtual bool isEnabled() const override; - virtual QByteArray id () const override; -// virtual bool remove ( Call* c ) override; - - virtual SupportedFeatures supportedFeatures() const override; - -// virtual QList<Call*> items() const override; - - ///Edit 'item', the implementation may be a GUI or somehting else -// virtual bool edit( Call* call) override; - ///Add a new item to the backend -// virtual bool addNew( Call* call) override; - - ///Add a new phone number to an existing item -// virtual bool addPhoneNumber( Call* call , PhoneNumber* number ) override; -private: - CollectionMediator<Call>* m_pMediator; -}; - -class MinimalHistoryEditor : public CollectionEditor<Call> -{ -public: - MinimalHistoryEditor(CollectionMediator<Call>* m) : CollectionEditor<Call>(m) {} - virtual bool save ( const Call* item ) override; - virtual bool append ( const Call* item ) override; - virtual bool remove ( Call* item ) override; - virtual bool edit ( Call* item ) override; - virtual bool addNew ( Call* item ) override; + explicit MinimalHistoryBackend(CollectionMediator<Call>* mediator); + virtual ~MinimalHistoryBackend(); + + virtual bool load() override; + virtual bool reload() override; + virtual bool clear() override; + virtual QString name () const override; + virtual QString category () const override; + virtual QVariant icon () const override; + virtual bool isEnabled() const override; + virtual QByteArray id () const override; + virtual SupportedFeatures supportedFeatures() const override; private: - virtual QVector<Call*> items() const override; + CollectionMediator<Call>* m_pMediator; }; - -template<typename T> -MinimalHistoryBackend::MinimalHistoryBackend(CollectionMediator<T>* mediator) : -CollectionInterface(new MinimalHistoryEditor(mediator)),m_pMediator(mediator) -{ -// setObjectName("MinimalHistoryBackend"); -} - #endif