Commit 7f593153 authored by Andreas Cord-Landwehr's avatar Andreas Cord-Landwehr
Browse files

Replace ResourceManager with ContributorRepository

Many cleanups for unclean usage of the old manager and introduction
of the new contribution specific repository.
parent 7e53c68a
......@@ -19,7 +19,6 @@
*/
#include "testlanguagefiles.h"
#include "core/resourcemanager.h"
#include "core/language.h"
#include "core/unit.h"
#include "core/phrase.h"
......@@ -38,10 +37,6 @@
TestLanguageFiles::TestLanguageFiles()
{
//FIXME port this
// KGlobal::dirs()->addResourceDir("appdata" , "./autotests/data");
// KGlobal::dirs()->addResourceDir("appdata" , "./autotests");
// KGlobal::dirs()->addResourceDir("appdata" , "./");
}
void TestLanguageFiles::init()
......@@ -97,7 +92,6 @@ void TestLanguageFiles::languageSchemeValidationTest()
void TestLanguageFiles::checkIdUniqueness()
{
ResourceManager manager;
QStringList languageFiles = QStandardPaths::locateAll(QStandardPaths::DataLocation, QStringLiteral("data/languages/*.xml"));
foreach (const QString &file, languageFiles) {
qDebug() << "File being parsed: " << file;
......
......@@ -41,9 +41,9 @@ include_directories(
set(artikulateCore_SRCS
core/icourse.h
core/drawertrainingactions.cpp
core/resourcemanager.cpp
core/iresourcerepository.h
core/resourcerepository.cpp
core/contributorrepository.cpp
core/language.cpp
core/phrase.cpp
core/phoneme.cpp
......@@ -166,6 +166,7 @@ ki18n_wrap_ui(artikulate_editor_SRCS
ui/sounddevicedialogpage.ui
)
qt5_add_resources(artikulate_editor_SRCS resources.qrc)
qt5_add_resources(artikulate_editor_SRCS ../data/languages.qrc)
kconfig_add_kcfg_files (artikulate_editor_SRCS settings.kcfgc)
# executables
......
......@@ -21,6 +21,7 @@
#include "application.h"
#include "core/iresourcerepository.h"
#include "core/contributorrepository.h"
#include "core/drawertrainingactions.h"
#include "core/trainingaction.h"
#include "core/editorsession.h"
......@@ -30,10 +31,10 @@
#include "core/phrase.h"
#include "core/player.h"
#include "core/recorder.h"
#include "core/resourcemanager.h"
#include "core/skeleton.h"
#include "core/trainingsession.h"
#include "core/unit.h"
#include "core/resources/editablecourseresource.h"
#include "models/coursefiltermodel.h"
#include "models/coursemodel.h"
#include "models/languagemodel.h"
......@@ -88,14 +89,18 @@ void Application::registerQmlTypes()
"artikulate", 1, 0,
"EditorSession",
QStringLiteral("EditorSession is unique object provided by the backend"));
qmlRegisterUncreatableType<ResourceManager>(
qmlRegisterUncreatableType<ContributorRepository>(
"artikulate", 1, 0,
"ResourceManager",
QStringLiteral("ResourceManager is unique object provided by the backend"));
"ContributorRepository",
QStringLiteral("ContributorRepository is unique object provided by the backend"));
qmlRegisterUncreatableType<LearnerProfile::ProfileManager>(
"artikulate", 1, 0,
"ProfileManager",
QStringLiteral("ProfileManager is unique object provided by the backend"));
qmlRegisterUncreatableType<EditableCourseResource>(
"artikulate", 1, 0,
"EditableCourseResource",
QStringLiteral("EditableCourseResource objects are backend objects"));
// interfaces
qmlRegisterInterface<IResourceRepository>("IResourceRepository");
......@@ -107,7 +112,6 @@ void Application::registerQmlTypes()
qmlRegisterType<Unit>("artikulate", 1, 0, "Unit");
qmlRegisterType<Skeleton>("artikulate", 1, 0, "Skeleton");
qmlRegisterType<Language>("artikulate", 1, 0, "Language");
qmlRegisterType<ResourceManager>("artikulate", 1, 0, "ResourceManager");
qmlRegisterType<Phrase>("artikulate", 1, 0, "Phrase");
qmlRegisterType<Phoneme>("artikulate", 1, 0, "Phoneme");
qmlRegisterType<PhonemeGroup>("artikulate", 1, 0, "PhonemeGroup");
......
/*
* Copyright 2013-2015 Andreas Cord-Landwehr <cordlandwehr@kde.org>
* Copyright 2013-2019 Andreas Cord-Landwehr <cordlandwehr@kde.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
......@@ -18,7 +18,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "resourcemanager.h"
#include "contributorrepository.h"
#include "language.h"
#include "skeleton.h"
#include "unit.h"
......@@ -45,12 +45,12 @@
#include <QUrl>
#include <QStandardPaths>
ResourceManager::ResourceManager(QObject *parent)
: QObject(parent)
ContributorRepository::ContributorRepository(QObject *parent)
: IResourceRepository()
{
}
void ResourceManager::loadCourseResources()
void ContributorRepository::loadCourseResources()
{
//TODO fix this method such that it may be called many times of e.g. updating
......@@ -127,26 +127,23 @@ void ResourceManager::loadCourseResources()
emit repositoryChanged();
}
void ResourceManager::loadLanguageResources()
void ContributorRepository::loadLanguageResources()
{
// load language resources
// all other resources are only loaded on demand
QStringList dirs = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation);
foreach (const QString &testdir, dirs) {
QDir dir(testdir + "/artikulate/languages/");
dir.setFilter(QDir::Files | QDir::NoSymLinks);
QFileInfoList list = dir.entryInfoList();
for (int i = 0; i < list.size(); ++i) {
QFileInfo fileInfo = list.at(i);
if (fileInfo.completeSuffix() != QLatin1String("xml")) {
continue;
}
addLanguage(QUrl::fromLocalFile(fileInfo.absoluteFilePath()));
QDir dir(":/artikulate/languages/");
dir.setFilter(QDir::Files | QDir::NoSymLinks);
QFileInfoList list = dir.entryInfoList();
for (int i = 0; i < list.size(); ++i) {
QFileInfo fileInfo = list.at(i);
if (fileInfo.completeSuffix() != QLatin1String("xml")) {
continue;
}
addLanguage(QUrl::fromLocalFile(fileInfo.absoluteFilePath()));
}
}
void ResourceManager::sync()
void ContributorRepository::sync()
{
// QMap< QString, QList< CourseResource* > >::iterator iter;
// for (iter = m_courseResources.begin(); iter != m_courseResources.end(); ++iter) {
......@@ -159,7 +156,7 @@ void ResourceManager::sync()
// }
}
bool ResourceManager::modified() const
bool ContributorRepository::modified() const
{
for (auto iter = m_courses.constBegin(); iter != m_courses.constEnd(); ++iter) {
for (auto *course : iter.value()) {
......@@ -176,13 +173,13 @@ bool ResourceManager::modified() const
return false;
}
void ResourceManager::addLanguage(const QUrl &languageFile)
void ContributorRepository::addLanguage(const QUrl &languageFile)
{
if (m_loadedResources.contains(languageFile.toLocalFile())) {
return;
}
LanguageResource *resource = new LanguageResource(this, languageFile);
LanguageResource *resource = new LanguageResource(languageFile);
emit languageResourceAboutToBeAdded(resource, m_languageResources.count());
m_languageResources.append(resource);
......@@ -191,28 +188,37 @@ void ResourceManager::addLanguage(const QUrl &languageFile)
emit languageResourceAdded();
}
bool ResourceManager::isRepositoryManager() const
bool ContributorRepository::isRepositoryManager() const
{
return !Settings::courseRepositoryPath().isEmpty();
}
QString ResourceManager::repositoryUrl() const
QString ContributorRepository::storageLocation() const
{
return Settings::courseRepositoryPath();
}
QList< LanguageResource* > ResourceManager::languageResources() const
QList< LanguageResource* > ContributorRepository::languageResources() const
{
return m_languageResources;
}
Language * ResourceManager::language(int index) const
QVector<Language *> ContributorRepository::languages() const
{
QVector<Language *> languages;
for (auto resourse : m_languageResources) {
languages.append(resourse->language());
}
return languages;
}
Language * ContributorRepository::language(int index) const
{
Q_ASSERT(index >= 0 && index < m_languageResources.count());
return m_languageResources.at(index)->language();
}
Language * ResourceManager::language(LearnerProfile::LearningGoal *learningGoal) const
Language * ContributorRepository::language(LearnerProfile::LearningGoal *learningGoal) const
{
if (!learningGoal) {
return nullptr;
......@@ -230,7 +236,7 @@ Language * ResourceManager::language(LearnerProfile::LearningGoal *learningGoal)
return nullptr;
}
QList<EditableCourseResource *> ResourceManager::courseResources(Language *language)
QList<EditableCourseResource *> ContributorRepository::courseResources(Language *language)
{
if (!language) {
QList<EditableCourseResource *> courses;
......@@ -246,7 +252,17 @@ QList<EditableCourseResource *> ResourceManager::courseResources(Language *langu
return m_courses[language->id()];
}
EditableCourseResource * ResourceManager::course(Language *language, int index) const
QVector<ICourse *> ContributorRepository::courses() const
{
return QVector<ICourse *>(); //TODO and check if overload for editable is needed
}
QVector<ICourse *> ContributorRepository::courses(Language *language) const
{
return QVector<ICourse *>(); //TODO and check if overload for editable is needed
}
EditableCourseResource * ContributorRepository::course(Language *language, int index) const
{
Q_ASSERT(m_courses.contains(language->id()));
Q_ASSERT(index >= 0 && index < m_courses[language->id()].count());
......@@ -254,7 +270,7 @@ EditableCourseResource * ResourceManager::course(Language *language, int index)
return m_courses[language->id()].at(index);
}
void ResourceManager::reloadCourseOrSkeleton(ICourse *courseOrSkeleton)
void ContributorRepository::reloadCourseOrSkeleton(ICourse *courseOrSkeleton)
{
if (!courseOrSkeleton) {
qCritical() << "Cannot reload non-existing course";
......@@ -283,7 +299,7 @@ void ResourceManager::reloadCourseOrSkeleton(ICourse *courseOrSkeleton)
}
}
void ResourceManager::updateCourseFromSkeleton(EditableCourseResource *course)
void ContributorRepository::updateCourseFromSkeleton(EditableCourseResource *course)
{
//TODO implement status information that are shown at mainwindow
if (course->foreignId().isEmpty()) {
......@@ -357,9 +373,9 @@ void ResourceManager::updateCourseFromSkeleton(EditableCourseResource *course)
qCDebug(ARTIKULATE_LOG) << "Update performed!";
}
EditableCourseResource * ResourceManager::addCourse(const QUrl &courseFile)
EditableCourseResource * ContributorRepository::addCourse(const QUrl &courseFile)
{
EditableCourseResource *resource = new EditableCourseResource(courseFile, nullptr); //FIXME second parameter must be interface!
EditableCourseResource *resource = new EditableCourseResource(courseFile, this);
if (resource->language() == nullptr) {
delete resource;
qCritical() << "Could not load course, language unknown:" << courseFile.toLocalFile();
......@@ -377,7 +393,7 @@ EditableCourseResource * ResourceManager::addCourse(const QUrl &courseFile)
return resource;
}
void ResourceManager::addCourseResource(EditableCourseResource *resource)
void ContributorRepository::addCourseResource(EditableCourseResource *resource)
{
Q_ASSERT(m_courses.contains(resource->language()->id()));
......@@ -385,26 +401,27 @@ void ResourceManager::addCourseResource(EditableCourseResource *resource)
// emit courseResourceAboutToBeAdded(resource, m_courses[resource->language()].count()); //FIXME
}
else {
emit courseResourceAboutToBeAdded(resource, 0);
emit courseAboutToBeAdded(resource, 0);
m_courses.insert(resource->language()->id(), QList<EditableCourseResource*>());
}
m_courses[resource->language()->id()].append(resource);
emit courseResourceAdded();
emit courseAdded();
}
void ResourceManager::removeCourse(ICourse *course)
void ContributorRepository::removeCourse(ICourse *course)
{
for (int index = 0; index < m_courses[course->language()->id()].length(); ++index) {
if (m_courses[course->language()->id()].at(index) == course) {
emit courseResourceAboutToBeRemoved(index);
emit courseAboutToBeRemoved(index);
m_courses[course->language()->id()].removeAt(index);
emit courseRemoved();
course->deleteLater();
return;
}
}
}
EditableCourseResource * ResourceManager::createCourse(Language *language, Skeleton *skeleton)
EditableCourseResource * ContributorRepository::createCourse(Language *language, Skeleton *skeleton)
{
// set path
QString path = QStringLiteral("%1/%2/%3/%4/%4.xml")
......@@ -413,7 +430,7 @@ EditableCourseResource * ResourceManager::createCourse(Language *language, Skele
skeleton->id(),
language->id());
EditableCourseResource * course = new EditableCourseResource(QUrl::fromLocalFile(path), nullptr); //FIXME
EditableCourseResource * course = new EditableCourseResource(QUrl::fromLocalFile(path), this);
Q_ASSERT(course);
course->setId(QUuid::createUuid().toString());
......@@ -430,13 +447,13 @@ EditableCourseResource * ResourceManager::createCourse(Language *language, Skele
return course;
}
void ResourceManager::addSkeleton(const QUrl &skeletonFile)
void ContributorRepository::addSkeleton(const QUrl &skeletonFile)
{
SkeletonResource *resource = new SkeletonResource(this, skeletonFile);
SkeletonResource *resource = new SkeletonResource(skeletonFile);
addSkeletonResource(resource);
}
void ResourceManager::addSkeletonResource(SkeletonResource *resource)
void ContributorRepository::addSkeletonResource(SkeletonResource *resource)
{
// skip already loaded resources
if (m_loadedResources.contains(resource->path().toLocalFile())) {
......@@ -448,7 +465,7 @@ void ResourceManager::addSkeletonResource(SkeletonResource *resource)
emit skeletonAdded();
}
void ResourceManager::removeSkeleton(Skeleton *skeleton)
void ContributorRepository::removeSkeleton(Skeleton *skeleton)
{
for (int index = 0; index < m_skeletonResources.length(); ++index) {
if (m_skeletonResources.at(index)->identifier() == skeleton->id()) {
......@@ -461,7 +478,7 @@ void ResourceManager::removeSkeleton(Skeleton *skeleton)
}
}
QList< SkeletonResource* > ResourceManager::skeletonResources()
QList< SkeletonResource* > ContributorRepository::skeletonResources()
{
return m_skeletonResources;
}
/*
* Copyright 2013-2015 Andreas Cord-Landwehr <cordlandwehr@kde.org>
* Copyright 2013-2019 Andreas Cord-Landwehr <cordlandwehr@kde.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
......@@ -18,10 +18,11 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef RESOURCEMANAGER_H
#define RESOURCEMANAGER_H
#ifndef CONTRIBUTORREPOSITORY_H
#define CONTRIBUTORREPOSITORY_H
#include "artikulatecore_export.h"
#include "iresourcerepository.h"
#include <QObject>
#include <QMap>
#include <QHash>
......@@ -43,17 +44,18 @@ namespace LearnerProfile {
}
/**
* \class ResourceManager
* This class loads and stores all data files of the application.
* @class ContributorRepository
* This class handles the resources of a contributor.
*/
class ARTIKULATECORE_EXPORT ResourceManager : public QObject
class ARTIKULATECORE_EXPORT ContributorRepository : public IResourceRepository
{
Q_OBJECT
Q_PROPERTY(bool isRepositoryManager READ isRepositoryManager NOTIFY repositoryChanged)
Q_PROPERTY(QString repositoryUrl READ repositoryUrl NOTIFY repositoryChanged)
Q_INTERFACES(IResourceRepository)
Q_PROPERTY(QString repositoryUrl READ storageLocation NOTIFY repositoryChanged)
public:
explicit ResourceManager(QObject *parent = nullptr);
explicit ContributorRepository(QObject *parent = nullptr);
/**
* Load all course resources.
......@@ -88,12 +90,17 @@ public:
/**
* \return path to working repository, if one is set
*/
QString repositoryUrl() const;
QString storageLocation() const override;
/**
* \return list of all available language specifications
*/
QList<LanguageResource *> languageResources() const;
Q_DECL_DEPRECATED QList<LanguageResource *> languageResources() const;
/**
* \return list of all available language specifications
*/
QVector<Language *> languages() const;
/**
* \return language by \p index
......@@ -105,6 +112,9 @@ public:
*/
Q_INVOKABLE Language * language(LearnerProfile::LearningGoal* learningGoal) const;
QVector<ICourse *> courses() const override;
QVector<ICourse *> courses(Language *language) const override;
/**
* \return list of all loaded courses for language \p language
*/
......@@ -119,6 +129,9 @@ public:
*/
Q_INVOKABLE void reloadCourseOrSkeleton(ICourse *course);
//TODO implement some logic
void reloadCourses() override {}
/**
* Imports units and phrases from skeleton, deassociates removed ones.
*
......@@ -197,9 +210,10 @@ Q_SIGNALS:
void languageResourceRemoved();
void languageResourceAboutToBeRemoved(int);
void repositoryChanged();
void courseResourceAdded();
void courseResourceAboutToBeAdded(ICourse*,int);
void courseResourceAboutToBeRemoved(int);
void courseAdded() override;
void courseAboutToBeAdded(ICourse*,int) override;
void courseAboutToBeRemoved(int) override;
void courseRemoved() override;
void skeletonAdded();
void skeletonAboutToBeAdded(ICourse*,int);
void skeletonRemoved();
......@@ -213,4 +227,4 @@ private:
QStringList m_loadedResources;
};
#endif // RESOURCEMANAGER_H
#endif
......@@ -25,12 +25,12 @@
#include "core/resources/languageresource.h"
#include "core/unit.h"
#include "core/phrase.h"
#include "core/resourcemanager.h"
#include "core/contributorrepository.h"
#include "artikulate_debug.h"
EditorSession::EditorSession(QObject *parent)
: QObject(parent)
, m_resourceManager(nullptr)
, m_repository(nullptr)
, m_skeletonMode(true)
, m_editSkeleton(false)
, m_skeleton(nullptr)
......@@ -43,9 +43,9 @@ EditorSession::EditorSession(QObject *parent)
}
void EditorSession::setResourceManager(ResourceManager *manager)
void EditorSession::setContributorRepository(ContributorRepository *repository)
{
m_resourceManager = manager;
m_repository = repository;
}
void EditorSession::setSkeletonMode(bool enabled)
......@@ -97,14 +97,14 @@ void EditorSession::setSkeleton(Skeleton *skeleton)
Language *language = m_language;
if (!m_language) {
language = m_resourceManager->languageResources().constFirst()->language();
language = m_repository->languages().constFirst();
}
if (m_skeleton) {
bool found = false;
int resources = m_resourceManager->courseResources(language).count();
int resources = m_repository->courseResources(language).count();
for (int i=0; i < resources; ++i) {
EditableCourseResource * course = m_resourceManager->course(language, i);
EditableCourseResource * course = m_repository->course(language, i);
if (course->foreignId() == m_skeleton->id()) {
setCourse(course);
found = true;
......@@ -133,9 +133,9 @@ void EditorSession::setLanguage(Language *language)
if (m_skeletonMode) {
bool found = false;
if (m_skeleton) {
int resources = m_resourceManager->courseResources(m_language).count();
int resources = m_repository->courseResources(m_language).count();
for (int i=0; i < resources; ++i) {
EditableCourseResource * course = m_resourceManager->course(m_language, i);
EditableCourseResource * course = m_repository->course(m_language, i);
if (course->foreignId() == m_skeleton->id()) {
setCourse(course);
found = true;
......@@ -148,8 +148,8 @@ void EditorSession::setLanguage(Language *language)
}
}
else { // not skeleton mode
if (m_resourceManager->courseResources(m_language).count() > 0) {
setCourse(m_resourceManager->course(m_language, 0));
if (m_repository->courseResources(m_language).count() > 0) {
setCourse(m_repository->course(m_language, 0));
}
}
emit languageChanged();
......
......@@ -29,7 +29,7 @@ class Skeleton;
class Language;
class EditableCourseResource;
class Unit;
class ResourceManager;
class ContributorRepository;
/**
* \class EditorSession
......@@ -68,7 +68,7 @@ class ARTIKULATECORE_EXPORT EditorSession : public QObject
public:
explicit EditorSession(QObject *parent = nullptr);
void setResourceManager(ResourceManager *manager);
void setContributorRepository(ContributorRepository *manager);
void setSkeletonMode(bool enabled=true);
bool skeletonMode() const;
void setEditSkeleton(bool enabled=true);
......@@ -106,7 +106,7 @@ Q_SIGNALS:
private:
Q_DISABLE_COPY(EditorSession)
ResourceManager * m_resourceManager;
ContributorRepository * m_repository;
bool m_skeletonMode;
bool m_editSkeleton;
Skeleton *m_skeleton;
......
......@@ -144,7 +144,7 @@ bool ResourceRepository::loadCourse(const QString &resourceFile)
bool ResourceRepository::loadLanguage(const QString &resourceFile)
{
LanguageResource *resource = new LanguageResource(nullptr, QUrl::fromLocalFile(resourceFile)); //TODO hacky adapter code
LanguageResource *resource = new LanguageResource(QUrl::fromLocalFile(resourceFile));
if (!resource) {
qCWarning(ARTIKULATE_CORE()) << "Could not load language" << resourceFile;
resource->deleteLater();
......
......@@ -19,7 +19,7 @@
*/
#include "languageresource.h"
#include "core/resourcemanager.h"
#include "courseparser.h"
#include "core/language.h"
#include "core/phoneme.h"
#include "core/phonemegroup.h"
......@@ -35,10 +35,8 @@
class LanguageResourcePrivate
{
public:
LanguageResourcePrivate(ResourceManager *resourceManager)
: m_resourceManager(resourceManager)
, m_languageResource(nullptr)
, m_type(ResourceInterface::LanguageResourceType)
LanguageResourcePrivate()
: m_languageResource(nullptr)
{
}
......@@ -46,18 +44,15 @@ public:
{
}
ResourceManager *m_resourceManager;
Language *m_languageResource;
QString m_identifier;
QUrl m_path;
QString m_title;
QString m_i18nTitle;
ResourceInterface::Type m_type;
};
LanguageResource::LanguageResource(ResourceManager *resourceManager, const QUrl &path)
: ResourceInterface(resourceManager)
, d(new LanguageResourcePrivate(resourceManager))
LanguageResource::LanguageResource(const QUrl &path)
: d(new LanguageResourcePrivate)
{
d->m_path = path;
......@@ -141,12 +136,12 @@ QObject * LanguageResource::resource()
return nullptr;
}
QXmlSchema schema = loadXmlSchema(QStringLiteral("language"));
QXmlSchema schema = CourseParser::loadXmlSchema(QStringLiteral("language"));