Commit 4e5b50fb authored by Andreas Cord-Landwehr's avatar Andreas Cord-Landwehr
Browse files

Introduce Interface for Repository

This major refactoring introduces an interface for the resource
repository. The interface is a first step towards a much looser coupling
between the internal classes. Specifically, I will be used to allow
an easier exchange between a training repository and a contributor
repository.

For now, the old resourcemanager will stay until it is fully replaced
by an implementation that is compatible with the IResourceRepository
interface.
parent e0bab5b1
......@@ -70,7 +70,6 @@ add_definitions(
# subdirectories to build
ecm_optional_add_subdirectory(data)
ecm_optional_add_subdirectory(schemes)
ecm_optional_add_subdirectory(doc)
ecm_optional_add_subdirectory(src)
ecm_optional_add_subdirectory(sounds)
......
......@@ -30,32 +30,31 @@ include_directories(
)
# copy test data
file(COPY ../schemes/ DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/schemes) # copy test files
file(COPY ../data/languages DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/data) # copy test files
file(COPY testcourses/de.xml DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/data/courses) # copy test files
file(COPY testcourses/fr.xml DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/data/courses) # copy test files
file(COPY testdata/courses/de.xml DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/data/courses/de/) # copy test files
file(COPY testdata/courses/fr.xml DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/data/courses/fr/) # copy test files
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR})
# repository tests
set(TestRepository_SRCS repository/test_repository.cpp)
add_executable(test_repository ${TestRepository_SRCS} )
target_link_libraries(test_repository
set(TestResourceRepository_SRCS resourcerepository/test_resourcerepository.cpp)
qt5_add_resources(TestResourceRepository_SRCS ../data/languages.qrc)
add_executable(test_resourcerepository ${TestResourceRepository_SRCS})
target_link_libraries(test_resourcerepository
artikulatecore
Qt5::Test
)
add_test(test_repository test_repository)
ecm_mark_as_test(test_repository)
add_test(test_resourcerepository test_resourcerepository)
ecm_mark_as_test(test_resourcerepository)
# training session tests
set(TestTrainingSession_SRCS trainingsession/test_trainingsession.cpp)
add_executable(test_trainingsession ${TestTrainingSession_SRCS} )
add_executable(test_trainingsession ${TestTrainingSession_SRCS})
target_link_libraries(test_trainingsession
artikulatecore
Qt5::Test
)
add_test(test_repository test_repository)
ecm_mark_as_test(test_repository)
add_test(test_trainingsession test_trainingsession)
ecm_mark_as_test(test_trainingsession)
set(TestCourseFiles_SRCS testcoursefiles.cpp)
kconfig_add_kcfg_files(TestCourseFiles_SRCS ../src/settings.kcfgc)
......
/*
* Copyright 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
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* 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 "test_course.h"
#include "src/core/icourse.h"
#include "src/core/course.h"
#include "src/core/resources/courseresource.h"
#include "src/core/language.h"
#include "src/core/unit.h"
#include <QTest>
#include <QSignalSpy>
/*
class CourseStub : public ICourse
{
public:
CourseStub(Language *language, QVector<Unit *> units)
: m_language(language)
, m_units(units)
{
}
QString id() const override
{
return "courseid";
}
QString title() const override
{
return "title";
}
QString i18nTitle() const override
{
return "i18n title";
}
QString description() const override
{
return "description of the course";
}
Language * language() const override
{
return m_language;
}
QList<Unit *> unitList() const override
{
return m_units.toList();
}
QUrl file() const override
{
return QUrl();
}
private:
Language *m_language{nullptr};
QVector<Unit *> m_units;
};*/
void TestCourse::init()
{
// TODO initialization of test case
}
void TestCourse::cleanup()
{
// TODO cleanup after test run
}
void TestCourse::createCourseWithoutUnits()
{
// CourseResource resource(nullptr);
Course course();
//TODO
// virtual ~ICourse() = default;
// virtual QString id() const = 0;
// virtual QString title() const = 0;
// virtual QString i18nTitle() const = 0;
// virtual QString description() const = 0;
// virtual Language * language() const = 0;
// virtual QList<Unit *> unitList() const = 0;
// virtual QUrl file() const = 0;
// Language language;
// CourseStub course(&language, QVector<Unit *>());
// LearnerProfile::ProfileManager manager;
// TrainingSession session(&manager);
// session.setCourse(&course);
// QVERIFY(&course == session.course());
}
void TestCourse::createCourseWithoutPhrases()
{
// Language language;
// Unit unitA;
// Unit unitB;
// Phrase phraseA1;
// Phrase phraseA2;
// Phrase phraseB1;
// Phrase phraseB2;
// // note: phrases without soundfiles are skipped in session generation
// phraseA1.setId("A1");
// phraseA2.setId("A2");
// phraseB1.setId("B1");
// phraseB2.setId("B2");
// phraseA1.setSound(QUrl::fromLocalFile("/tmp/a1.ogg"));
// unitA.addPhrase(&phraseA1);
// unitA.addPhrase(&phraseA2);
// unitB.addPhrase(&phraseB1);
// unitB.addPhrase(&phraseB2);
// CourseStub course(&language, QVector<Unit *>({&unitA, &unitB}));
// LearnerProfile::ProfileManager manager;
// TrainingSession session(&manager);
// session.setCourse(&course);
// // test number of actions
// auto actions = session.trainingActions();
// QCOMPARE(actions.count(), 1);
// QCOMPARE(actions.at(0)->actions().count(), 1);
}
QTEST_GUILESS_MAIN(TestCourse)
......@@ -18,17 +18,17 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TEST_REPOSITORY_H
#define TEST_REPOSITORY_H
#ifndef TEST_COURSE_H
#define TEST_COURSE_H
#include <QObject>
class TestRepository : public QObject
class TestCourse : public QObject
{
Q_OBJECT
public:
TestRepository() = default;
TestCourse() = default;
private Q_SLOTS:
/**
......@@ -41,7 +41,15 @@ private Q_SLOTS:
*/
void cleanup();
void createRepository();
/**
* @brief Construct and destruct course without units
*/
void createCourseWithoutUnits();
/**
* @brief Construct training session and check that phrases without sound file paths are skipped
*/
void createCourseWithoutPhrases();
};
#endif
/*
* Copyright 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
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* 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 "test_resourcerepository.h"
#include <QTest>
#include <QSignalSpy>
#include <QObject>
#include "src/core/resourcerepository.h"
#include "src/core/language.h"
void TestResourceRepository::init()
{
// check that test data is deployed at the expected location
QVERIFY(QFile::exists("data/courses/de/de.xml"));
QVERIFY(QFile::exists("data/courses/fr/fr.xml"));
}
void TestResourceRepository::cleanup()
{
// TODO cleanup after test run
}
void TestResourceRepository::createRepository()
{
ResourceRepository repository(QUrl::fromLocalFile("data/courses/"));
QCOMPARE(repository.storageLocation(), "data/courses/");
repository.reloadCourses();
QCOMPARE(repository.courses().count(), 2);
}
void TestResourceRepository::iResourceRepositoryCompatability()
{
ResourceRepository repository(QUrl::fromLocalFile("data/courses/"));
IResourceRepository *interface = &repository;
QCOMPARE(interface->storageLocation(), "data/courses/");
QVERIFY(interface->languages().count() > 0);
QCOMPARE(interface->courses().count(), 0);
// test adding
QSignalSpy spyAboutToBeAdded(dynamic_cast<QObject *>(interface), SIGNAL(courseAboutToBeAdded(ICourse*, int)));
QSignalSpy spyAdded(dynamic_cast<QObject *>(interface), SIGNAL(courseAdded()));
QCOMPARE(spyAboutToBeAdded.count(), 0);
QCOMPARE(spyAdded.count(), 0);
repository.reloadCourses();
QCOMPARE(interface->courses().count(), 2);
QCOMPARE(spyAboutToBeAdded.count(), 2);
QCOMPARE(spyAdded.count(), 2);
// test removal
// note: repository does not provide removal of courses, yet
// test access of courses grouped by language
auto languages = interface->languages();
Language *german = nullptr;
for (auto language : interface->languages()) {
if (language->id() == "de") {
german = language;
break;
}
}
QVERIFY(german != nullptr); // ensure that German language was found
QCOMPARE(interface->courses(german).count(), 1); // there is exactly one German course
QCOMPARE(interface->courses(nullptr).count(), 2); // all courses in total are 2
}
QTEST_GUILESS_MAIN(TestResourceRepository)
......@@ -18,24 +18,39 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "test_repository.h"
#include <QTest>
#ifndef TEST_RESOURCEREPOSITORY_H
#define TEST_RESOURCEREPOSITORY_H
#include "src/core/resourcemanager.h"
#include <QObject>
void TestRepository::init()
class TestResourceRepository : public QObject
{
// TODO initialization of test case
}
Q_OBJECT
void TestRepository::cleanup()
{
// TODO cleanup after test run
}
public:
TestResourceRepository() = default;
void TestRepository::createRepository()
{
private Q_SLOTS:
/**
* Called before every test case.
*/
void init();
/**
* Called after every test case.
*/
void cleanup();
/**
* Create and load repository with simple testdata
*/
void createRepository();
}
/**
* @brief integration test for IResourceRepository interface
* Test expectations of the IResourceRepository interface.
*/
void iResourceRepositoryCompatability();
};
QTEST_GUILESS_MAIN(TestRepository)
#endif
......@@ -59,7 +59,7 @@ public:
{
return m_language;
}
QList<Unit *> unitList() const override
QList<Unit *> unitList() override
{
return m_units.toList();
}
......
###
# Copyright 2013 Andreas Cord-Landwehr <cordlandwehr@kde.org>
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
###
ecm_optional_add_subdirectory(languages)
<RCC>
<qresource prefix="/artikulate/">
<file>languages/ba.xml</file>
<file>languages/ca.xml</file>
<file>languages/de.xml</file>
<file>languages/du.xml</file>
<file>languages/en_BE.xml</file>
<file>languages/en_US.xml</file>
<file>languages/fr.xml</file>
<file>languages/gr.xml</file>
<file>languages/hi.xml</file>
<file>languages/it.xml</file>
<file>languages/mr.xml</file>
<file>languages/sp.xml</file>
<file>languages/pl.xml</file>
<file>schemes/course.xsd</file>
<file>schemes/language.xsd</file>
<file>schemes/skeleton.xsd</file>
</qresource>
</RCC>
###
# Copyright 2013 Andreas Cord-Landwehr <cordlandwehr@kde.org>
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
###
set(languages
ba.xml
ca.xml
de.xml
du.xml
en_BE.xml
en_US.xml
fr.xml
gr.xml
hi.xml
it.xml
mr.xml
sp.xml
pl.xml
)
install(FILES ${languages} DESTINATION ${DATA_INSTALL_DIR}/artikulate/languages)
###
# Copyright 2013 Andreas Cord-Landwehr <cordlandwehr@kde.org>
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
###
FILE(GLOB schemes *.xsd)
install(FILES ${schemes} DESTINATION ${DATA_INSTALL_DIR}/artikulate/schemes)
......@@ -44,6 +44,8 @@ set(artikulateCore_SRCS
core/drawertrainingactions.cpp
core/course.cpp
core/resourcemanager.cpp
core/iresourcerepository.h
core/resourcerepository.cpp
core/language.cpp
core/phrase.cpp
core/phoneme.cpp
......@@ -127,6 +129,7 @@ ki18n_wrap_ui (artikulate_SRCS
ui/appearencedialogpage.ui
)
qt5_add_resources(artikulate_SRCS resources.qrc)
qt5_add_resources(artikulate_SRCS ../data/languages.qrc)
kconfig_add_kcfg_files (artikulate_SRCS settings.kcfgc)
set(artikulate_editor_SRCS
......
......@@ -21,6 +21,7 @@
#include "application.h"
#include "core/course.h"
#include "core/iresourcerepository.h"
#include "core/drawertrainingactions.h"
#include "core/trainingaction.h"
#include "core/editorsession.h"
......@@ -67,6 +68,16 @@ Application::Application(int& argc, char** argv)
registerQmlTypes();
}
IResourceRepository * Application::resourceRepository() const
{
return m_resourceRepository;
}
void Application::installResourceRepository(IResourceRepository *resourceRepository)
{
m_resourceRepository = resourceRepository;
}
void Application::registerQmlTypes()
{
qmlRegisterUncreatableType<TrainingSession>(
......@@ -85,8 +96,12 @@ void Application::registerQmlTypes()
"artikulate", 1, 0,
"ProfileManager",
QStringLiteral("ProfileManager is unique object provided by the backend"));
qmlRegisterUncreatableType<ICourse>("artikulate", 1, 0, "ICourse", "Courses are managed by repository");
// interfaces
qmlRegisterInterface<IResourceRepository>("IResourceRepository");
qmlRegisterInterface<ICourse>("ICourse");
// concrete instantiable types
qmlRegisterType<LearnerProfile::Learner>("artikulate", 1, 0, "Learner");
qmlRegisterType<LearnerProfile::LearningGoal>("artikulate", 1, 0, "LearningGoal");
qmlRegisterType<Unit>("artikulate", 1, 0, "Unit");
......@@ -103,6 +118,7 @@ void Application::registerQmlTypes()
qmlRegisterType<DrawerTrainingActions>("artikulate", 1, 0, "DrawerTrainingActions");
qmlRegisterType<TrainingAction>("artikulate", 1, 0, "TrainingAction");
// models
qmlRegisterType<CourseModel>("artikulate", 1, 0, "CourseModel");
qmlRegisterType<CourseFilterModel>("artikulate", 1, 0, "CourseFilterModel");
qmlRegisterType<LanguageModel>("artikulate", 1, 0, "LanguageModel");
......
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