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

Update learner goals on-the-fly.

The learner just have to learn in the future, all data like learnnig
goals and learning tracking will be set in the background without any
necessary user interaction.
parent b349581e
/*
* Copyright 2013-2014 Andreas Cord-Landwehr <cordlandwehr@kde.org>
* Copyright 2013-2016 Andreas Cord-Landwehr <cordlandwehr@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
......@@ -52,7 +52,7 @@ public:
Language = 1
};
explicit Learner(QObject *parent = 0);
explicit Learner(QObject *parent = nullptr);
~Learner();
QString name() const;
......@@ -66,11 +66,14 @@ public:
void importImage(const QString &path);
int identifier() const;
void setIdentifier(int identifier);
/**
* \return list of all learning goals of learner
*/
QList<LearningGoal *> goals() const;
Q_INVOKABLE void addGoal(LearnerProfile::LearningGoal *goal);
Q_INVOKABLE void removeGoal(LearnerProfile::LearningGoal *goal);
Q_INVOKABLE bool hasGoal(LearnerProfile::LearningGoal *goal) const;
void setActiveGoal(LearningGoal *goal);
void setActiveGoal(LearnerProfile::LearningGoal *goal);
Q_INVOKABLE void setActiveGoal(LearnerProfile::Learner::Category category, const QString &identifier);
Q_INVOKABLE LearnerProfile::LearningGoal * activeGoal(LearnerProfile::Learner::Category category) const;
......
......@@ -52,8 +52,8 @@ public:
LearnerProfile::ProfileManagerPrivate::ProfileManagerPrivate()
: m_profiles(QList<Learner*>())
, m_activeProfile(0)
, m_config(0)
, m_activeProfile(nullptr)
, m_config(nullptr)
{
// load all profiles from storage
m_goals.append(m_storage.loadGoals());
......@@ -81,7 +81,7 @@ LearnerProfile::ProfileManagerPrivate::ProfileManagerPrivate()
break;
}
}
if (m_activeProfile == 0) {
if (m_activeProfile == nullptr) {
qCDebug(LIBLEARNER_LOG) << "No last active profile found, falling back to first found profile";
if (m_profiles.size() > 0) {
m_activeProfile = m_profiles.at(0);
......@@ -204,8 +204,8 @@ void ProfileManager::removeProfile(Learner *learner)
d->m_storage.removeProfile(learner);
if (d->m_activeProfile == learner) {
if (d->m_profiles.count() == 0) {
setActiveProfile(0);
if (d->m_profiles.isEmpty()) {
setActiveProfile(nullptr);
}
else {
setActiveProfile(d->m_profiles.at(0));
......@@ -222,7 +222,7 @@ void ProfileManager::removeLearningGoal(Learner* learner, LearningGoal* goal)
Learner * ProfileManager::profile(int index)
{
if (index < 0 || index >= profiles().count()) {
return 0;
return nullptr;
}
return profiles().at(index);
}
......@@ -232,7 +232,9 @@ QList< LearningGoal* > ProfileManager::goals() const
return d->m_goals;
}
void ProfileManager::registerGoal(LearningGoal::Category category, const QString &identifier, const QString &name)
void ProfileManager::registerGoal(LearningGoal::Category category,
const QString &identifier,
const QString &name)
{
// test whether goal is already registered
foreach (LearningGoal *cmpGoal, d->m_goals) {
......@@ -246,6 +248,23 @@ void ProfileManager::registerGoal(LearningGoal::Category category, const QString
d->m_storage.storeGoal(goal);
}
LearnerProfile::LearningGoal * LearnerProfile::ProfileManager::goal(
LearningGoal::Category category,
const QString& identifier) const
{
foreach (LearningGoal *goal, d->m_goals) {
if (goal->category() != category) {
continue;
}
if (goal->identifier() != identifier) {
continue;
}
return goal;
}
qCWarning(LIBLEARNER_LOG) << "no goal found for:" << category << identifier;
return nullptr;
}
void ProfileManager::sync()
{
d->sync();
......
......@@ -41,7 +41,7 @@ class LIBLEARNERPROFILE_EXPORT ProfileManager : public QObject
Q_PROPERTY (LearnerProfile::Learner * activeProfile READ activeProfile WRITE setActiveProfile NOTIFY activeProfileChanged)
public:
explicit ProfileManager(QObject *parent = 0);
explicit ProfileManager(QObject *parent = nullptr);
~ProfileManager();
QList< Learner* > profiles() const;
......@@ -56,9 +56,13 @@ public:
* internal database.
*/
void registerGoal(LearningGoal::Category category, const QString &identifier, const QString &name);
LearningGoal * goal(LearningGoal::Category category, const QString &identifier) const;
/**
* write all profiles to database
*/
Q_INVOKABLE void sync();
/**
* Writes \p profile to database.
* write specified \p profile to database
*/
Q_INVOKABLE void sync(LearnerProfile::Learner *learner);
void setActiveProfile(LearnerProfile::Learner *learner);
......
/*
* Copyright 2013-2015 Andreas Cord-Landwehr <cordlandwehr@kde.org>
* Copyright 2013-2016 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
......@@ -24,10 +24,13 @@
#include "core/unit.h"
#include "core/phrase.h"
#include "core/phonemegroup.h"
#include "profilemanager.h"
#include "learner.h"
#include "artikulate_debug.h"
TrainingSession::TrainingSession(QObject *parent)
: QObject(parent)
, m_profileManager(nullptr)
, m_language(nullptr)
, m_course(nullptr)
, m_unit(nullptr)
......@@ -36,6 +39,14 @@ TrainingSession::TrainingSession(QObject *parent)
}
void TrainingSession::setProfileManager(LearnerProfile::ProfileManager *manager)
{
if (m_profileManager == manager) {
return;
}
m_profileManager = manager;
}
Language * TrainingSession::language() const
{
return m_language;
......@@ -121,13 +132,15 @@ Phrase * TrainingSession::nextPhrase() const
void TrainingSession::showNextPhrase()
{
updateGoal();
//TODO update learning log
setPhrase(nextPhrase());
}
void TrainingSession::skipPhrase()
{
//FIXME
qCWarning(ARTIKULATE_LOG) << "Learning profile update not implemented";
updateGoal();
//TODO update learning log
showNextPhrase();
}
......@@ -135,3 +148,20 @@ bool TrainingSession::hasNextPhrase() const
{
return nextPhrase() != nullptr;
}
void TrainingSession::updateGoal()
{
if (!m_profileManager) {
qCWarning(ARTIKULATE_LOG) << "No ProfileManager registered, aborting operation";
return;
}
LearnerProfile::Learner *learner = m_profileManager->activeProfile();
if (!learner) {
qCWarning(ARTIKULATE_LOG) << "No active Learner registered, aborting operation";
return;
}
LearnerProfile::LearningGoal * goal = m_profileManager->goal(
LearnerProfile::LearningGoal::Language, m_course->id());
learner->addGoal(goal);
learner->setActiveGoal(goal);
}
......@@ -31,6 +31,10 @@ class Course;
class Unit;
class PhonemeGroup;
namespace LearnerProfile {
class ProfileManager;
}
/**
* \class TrainingSession
*/
......@@ -46,6 +50,7 @@ class ARTIKULATECORE_EXPORT TrainingSession : public QObject
public:
explicit TrainingSession(QObject *parent = nullptr);
void setProfileManager(LearnerProfile::ProfileManager *manager);
Language * language() const;
void setLanguage(Language *language);
Course * course() const;
......@@ -72,6 +77,8 @@ Q_SIGNALS:
private:;
Q_DISABLE_COPY(TrainingSession)
Phrase * nextPhrase() const;
void updateGoal();
LearnerProfile::ProfileManager *m_profileManager;
Language *m_language;
Course *m_course;
Unit *m_unit;
......
......@@ -62,8 +62,8 @@ MainWindow::MainWindow()
: m_actionCollection(new KActionCollection(this, "artikulate"))
, m_helpMenu(new KHelpMenu)
, m_resourceManager(new ResourceManager(this))
, m_trainingSession(new TrainingSession(this))
, m_profileManager(new LearnerProfile::ProfileManager(this))
, m_trainingSession(new TrainingSession(this))
{
// load saved sound settings
OutputDeviceController::self().setVolume(Settings::audioOutputVolume());
......@@ -75,6 +75,7 @@ MainWindow::MainWindow()
}
m_resourceManager->loadCourseResources();
m_resourceManager->registerLearningGoals(m_profileManager);
m_trainingSession->setProfileManager(m_profileManager);
KDeclarative::KDeclarative kdeclarative;
kdeclarative.setDeclarativeEngine(this);
......
......@@ -66,8 +66,8 @@ private:
KActionCollection *m_actionCollection;
KHelpMenu *m_helpMenu;
ResourceManager *m_resourceManager;
TrainingSession *m_trainingSession;
LearnerProfile::ProfileManager *m_profileManager;
TrainingSession *m_trainingSession;
};
#endif
......@@ -72,25 +72,25 @@ Item {
}
}
style: TabViewStyle {
frameOverlap: 1
tab: Rectangle {
id: tabRect
color: styleData.selected ? "#c0e7f9" : "#ffffff"
border.width: 0
implicitWidth: Math.max(text.width + 8, 80)
implicitHeight: 24
Text {
id: text
anchors.centerIn: parent
text: styleData.title
color: "black"
style: TabViewStyle {
frameOverlap: 1
tab: Rectangle {
id: tabRect
color: styleData.selected ? "#c0e7f9" : "#ffffff"
border.width: 0
implicitWidth: Math.max(text.width + 8, 80)
implicitHeight: 24
Text {
id: text
anchors.centerIn: parent
text: styleData.title
color: "black"
}
}
frame: Rectangle {
color: "#c0e7f9"
}
}
frame: Rectangle {
color: "#c0e7f9"
}
}
}
}
}
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