diff --git a/src/core/contributorrepository.h b/src/core/contributorrepository.h index 4650f08..bd064d9 100644 --- a/src/core/contributorrepository.h +++ b/src/core/contributorrepository.h @@ -1,215 +1,216 @@ /* * Copyright 2013-2019 Andreas Cord-Landwehr * * 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 . */ #ifndef CONTRIBUTORREPOSITORY_H #define CONTRIBUTORREPOSITORY_H #include "artikulatecore_export.h" #include "ieditablerepository.h" #include #include #include #include #include #include "liblearnerprofile/src/learninggoal.h" class SkeletonResource; class EditableCourseResource; class LanguageResource; class Language; class ICourse; class QUrl; /** * @class ContributorRepository * This class handles the resources of a contributor. */ class ARTIKULATECORE_EXPORT ContributorRepository : public IEditableRepository { Q_OBJECT Q_INTERFACES(IResourceRepository) Q_INTERFACES(IEditableRepository) Q_PROPERTY(QString repositoryUrl READ storageLocation NOTIFY repositoryChanged) public: explicit ContributorRepository(QObject *parent = nullptr); + ~ContributorRepository() override = default; /** * save all changes to course resources */ void sync(); /** * \return \c true if any course or skeleton is modified, otherwise \c false */ bool modified() const; /** * \return path to working repository, if one is set */ QString storageLocation() const override; /** * Set path to central storage location * \param path the path to the storage location directory */ void setStorageLocation(const QString &path); /** * \return list of all available language specifications */ Q_DECL_DEPRECATED QList languageResources() const; QVector languages() const override; /** * \return language by \p index */ Q_INVOKABLE Language * language(int index) const; /** * \return language by \p learningGoal */ Q_INVOKABLE Language * language(LearnerProfile::LearningGoal* learningGoal) const; QVector courses() const override; QVector editableCourses() const override; QVector courses(Language *language) const override; /** * \return list of all loaded courses for language \p language */ QList courseResources(Language *language); Q_INVOKABLE IEditableCourse * editableCourse(Language *language, int index) const override; /** * Reset the file for this course or skeleton. * * \param course the course to be reloaded */ Q_INVOKABLE void reloadCourseOrSkeleton(ICourse *course); /** * @brief Implementation of course resource reloading */ void reloadCourses() override; /** * Imports units and phrases from skeleton, deassociates removed ones. * * \param course the course to be update */ void updateCourseFromSkeleton(EditableCourseResource *course); /** * Add language to resource manager by parsing the given language specification file. * * \param languageFile is the local XML file containing the language */ void addLanguage(const QUrl &languageFile); /** * Adds course to resource manager by parsing the given course specification file. * * \param courseFile is the local XML file containing the course * \return true if loaded successfully, otherwise false */ EditableCourseResource * addCourse(const QUrl &courseFile); /** * Adds course to resource manager. If the course's language is not registered, the language * is registered by this method. * * \param resource the course resource to add to resource manager */ void addCourseResource(EditableCourseResource *resource); /** * Remove course from resource manager. If the course is modified its changes are NOT * written. For writing changes, the Course::sync() method must be called directly. * * \param course is the course to be removed */ void removeCourse(ICourse *course); /** * Create new course for \p language and derived from \p skeleton. * * \return created course */ Q_INVOKABLE EditableCourseResource * createCourse(Language *language, SkeletonResource *skeleton); /** * Adds skeleton resource to resource manager * * \param resource the skeleton resource to add to resource manager */ void addSkeleton(const QUrl &skeletonFile); /** * Adds skeleton resource to resource manager * * \param resource the skeleton resource to add to resource manager */ void addSkeletonResource(SkeletonResource *resource); /** * Remove skeleton from resource manager. If the skeleton is modified its changes are NOT * written. For writing changes, the Skeleton::sync() method must be called directly. * * \param skeleton is the skeleton to be removed */ void removeSkeleton(SkeletonResource *skeleton); QVector skeletons() const override; Q_SIGNALS: void languageResourceAdded(); void languageResourceAboutToBeAdded(LanguageResource*,int); void languageResourceRemoved(); void languageResourceAboutToBeRemoved(int); void repositoryChanged(); void courseAdded() override; void courseAboutToBeAdded(ICourse*,int) override; void courseAboutToBeRemoved(int) override; void courseRemoved() override; void skeletonAdded(); void skeletonAboutToBeAdded(ICourse*,int); void skeletonRemoved(); void skeletonAboutToBeRemoved(int,int); void languageCoursesChanged(); private: /** * This method loads all language files that are provided in the standard directories * for this application. */ void loadLanguageResources(); QString m_storageLocation; QList m_languageResources; QMap > m_courses; //!> (language-id, course-resource) QVector m_skeletonResources; QStringList m_loadedResources; }; #endif diff --git a/src/models/skeletonmodel.cpp b/src/models/skeletonmodel.cpp index b5e706e..c06a6e2 100644 --- a/src/models/skeletonmodel.cpp +++ b/src/models/skeletonmodel.cpp @@ -1,185 +1,185 @@ /* * Copyright 2013 Andreas Cord-Landwehr * * 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 . */ #include "skeletonmodel.h" #include "core/icourse.h" #include "core/contributorrepository.h" #include "core/resources/skeletonresource.h" #include #include #include #include "artikulate_debug.h" SkeletonModel::SkeletonModel(QObject *parent) : QAbstractListModel(parent) , m_repository(nullptr) , m_signalMapper(new QSignalMapper(this)) { connect(m_signalMapper, SIGNAL(mapped(int)), SLOT(emitSkeletonChanged(int))); } QHash< int, QByteArray > SkeletonModel::roleNames() const { QHash roles; roles[TitleRole] = "title"; roles[DescriptionRole] = "description"; roles[IdRole] = "id"; roles[DataRole] = "dataRole"; return roles; } -void SkeletonModel::setResourceRepository(ContributorRepository *repository) +void SkeletonModel::setResourceRepository(IEditableRepository *repository) { if (m_repository == repository) { return; } beginResetModel(); if (m_repository) { m_repository->disconnect(this); } m_repository = repository; if (m_repository) { //FIXME // connect(m_resourceManager, &ResourceManager::skeletonAboutToBeAdded, this, &SkeletonModel::onSkeletonAboutToBeAdded); // connect(m_resourceManager, &ResourceManager::skeletonAdded, this, &SkeletonModel::onSkeletonAdded); // connect(m_resourceManager, &ResourceManager::skeletonAboutToBeRemoved, this, &SkeletonModel::onSkeletonsAboutToBeRemoved); // connect(m_resourceManager, &ResourceManager::skeletonRemoved, this, &SkeletonModel::onSkeletonsRemoved); } endResetModel(); emit resourceRepositoryChanged(); } -ContributorRepository * SkeletonModel::resourceRepository() const +IEditableRepository * SkeletonModel::resourceRepository() const { return m_repository; } QVariant SkeletonModel::data(const QModelIndex& index, int role) const { if (!index.isValid()) { return QVariant(); } if (index.row() >= m_repository->skeletons().count()) { return QVariant(); } ICourse * const skeleton = m_repository->skeletons().at(index.row()); switch(role) { case Qt::DisplayRole: return !skeleton->title().isEmpty() ? QVariant(skeleton->title()): QVariant(i18nc("@item:inlistbox:", "unknown")); case Qt::ToolTipRole: return QVariant(skeleton->title()); case TitleRole: return skeleton->title(); case DescriptionRole: return skeleton->description(); case IdRole: return skeleton->id(); case DataRole: return QVariant::fromValue(skeleton); default: return QVariant(); } } int SkeletonModel::rowCount(const QModelIndex &parent) const { if (!m_repository) { return 0; } if (parent.isValid()) { return 0; } return m_repository->skeletons().count(); } void SkeletonModel::onSkeletonAboutToBeAdded(ICourse *skeleton, int index) { connect(skeleton, SIGNAL(titleChanged()), m_signalMapper, SLOT(map())); //TODO add missing signals beginInsertRows(QModelIndex(), index, index); } void SkeletonModel::onSkeletonAdded() { updateMappings(); endInsertRows(); emit countChanged(); } void SkeletonModel::onSkeletonsAboutToBeRemoved(int first, int last) { beginRemoveRows(QModelIndex(), first, last); } void SkeletonModel::onSkeletonsRemoved() { endRemoveRows(); emit countChanged(); } void SkeletonModel::emitSkeletonChanged(int row) { emit skeletonChanged(row); emit dataChanged(index(row, 0), index(row, 0)); } QVariant SkeletonModel::headerData(int section, Qt::Orientation orientation, int role) const { if (role != Qt::DisplayRole) { return QVariant(); } if (orientation == Qt::Vertical) { return QVariant(section + 1); } return QVariant(i18nc("@title:column", "Skeleton")); } int SkeletonModel::count() const { return m_repository->skeletons().count(); } void SkeletonModel::updateMappings() { int skeletons = m_repository->skeletons().count(); for (int i = 0; i < skeletons; ++i) { m_signalMapper->setMapping(m_repository->skeletons().at(i), i); } } QVariant SkeletonModel::skeleton(int row) const { return data(index(row, 0), SkeletonModel::DataRole); } diff --git a/src/models/skeletonmodel.h b/src/models/skeletonmodel.h index 95bdad7..b96fb29 100644 --- a/src/models/skeletonmodel.h +++ b/src/models/skeletonmodel.h @@ -1,77 +1,77 @@ /* * Copyright 2013-2015 Andreas Cord-Landwehr * * 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 . */ #ifndef SKELETONMODEL_H #define SKELETONMODEL_H #include -class ContributorRepository; +class IEditableRepository; class ICourse; class Skeleton; class Language; class QSignalMapper; class SkeletonModel : public QAbstractListModel { Q_OBJECT - Q_PROPERTY(ContributorRepository *repository READ resourceRepository WRITE setResourceRepository NOTIFY resourceRepositoryChanged) + Q_PROPERTY(IEditableRepository *repository READ resourceRepository WRITE setResourceRepository NOTIFY resourceRepositoryChanged) Q_PROPERTY(int count READ count NOTIFY countChanged) public: enum courseRoles { TitleRole = Qt::UserRole + 1, DescriptionRole, IdRole, DataRole }; explicit SkeletonModel(QObject *parent = nullptr); - void setResourceRepository(ContributorRepository *repository); + void setResourceRepository(IEditableRepository *repository); /** * Reimplemented from QAbstractListModel::roleNames() */ virtual QHash roleNames() const override; - ContributorRepository * resourceRepository() const; + IEditableRepository * resourceRepository() const; virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; virtual int rowCount(const QModelIndex &parent = QModelIndex()) const override; virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; int count() const; Q_INVOKABLE QVariant skeleton(int index) const; Q_SIGNALS: void skeletonChanged(int index); void resourceRepositoryChanged(); void countChanged(); private Q_SLOTS: void onSkeletonAboutToBeAdded(ICourse *skeleton, int index); void onSkeletonAdded(); void onSkeletonsAboutToBeRemoved(int first, int last); void onSkeletonsRemoved(); void emitSkeletonChanged(int row); private: void updateMappings(); - ContributorRepository *m_repository; + IEditableRepository *m_repository; QSignalMapper *m_signalMapper; }; #endif // SKELETONMODEL_H