diff --git a/CMakeLists.txt b/CMakeLists.txt index ed23e8d..33c6a4b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,87 +1,87 @@ ### # Copyright 2013-2016 Andreas Cord-Landwehr # # 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. ### project(artikulate) -cmake_minimum_required(VERSION 3.0.0) +cmake_minimum_required(VERSION 3.5.0) find_package(ECM 5.15.0 REQUIRED NO_MODULE) find_package(KF5DocTools) set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR}) include(KDEInstallDirs) include(ECMAddTests) include(KDECMakeSettings) include(KDECompilerSettings NO_POLICY_SCOPE) include(ECMInstallIcons) include(ECMOptionalAddSubdirectory) include(ECMSetupVersion) include(ECMEnableSanitizers) include(FeatureSummary) include(GenerateExportHeader) find_package(Qt5 5.10 REQUIRED COMPONENTS Widgets Sql XmlPatterns Qml Quick QuickWidgets Test ) find_package(KF5 5.57 REQUIRED COMPONENTS Archive Config Crash I18n NewStuff XmlGui Kirigami2 ) # options option(BUILD_QTMULTIMEDIA_PLUGIN "Build QtMultimedia sound backend" ON) option(BUILD_GSTREAMER_PLUGIN "Build GStreamer sound backend" OFF) add_definitions( -DQT_NO_URL_CAST_FROM_STRING ) # subdirectories to build ecm_optional_add_subdirectory(data) ecm_optional_add_subdirectory(doc) ecm_optional_add_subdirectory(src) ecm_optional_add_subdirectory(sounds) ecm_optional_add_subdirectory(images) ecm_optional_add_subdirectory(icons) ecm_optional_add_subdirectory(libsound) ecm_optional_add_subdirectory(liblearnerprofile) ecm_optional_add_subdirectory(autotests) # files to install in the artikulate project root directory install(PROGRAMS org.kde.artikulate.desktop DESTINATION ${XDG_APPS_INSTALL_DIR}) install(FILES org.kde.artikulate.appdata.xml DESTINATION ${KDE_INSTALL_METAINFODIR}) feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES) diff --git a/autotests/CMakeLists.txt b/autotests/CMakeLists.txt index 8bb6f37..9d2fafb 100644 --- a/autotests/CMakeLists.txt +++ b/autotests/CMakeLists.txt @@ -1,142 +1,142 @@ ### # Copyright 2013-2019 Andreas Cord-Landwehr # # 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. ### include_directories( ../src/ ../ ${CMAKE_CURRENT_BINARY_DIR} ) # copy test data 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 file(COPY testdata/contributorrepository/ DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/data/contributorrepository/) # copy test files set(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}) # repository tests 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_resourcerepository test_resourcerepository) +add_test(NAME test_resourcerepository COMMAND test_resourcerepository) ecm_mark_as_test(test_resourcerepository) # integration tests for iresource repository interface derived classes set(TestIResourceRepository_SRCS iresourcerepository_integration/test_iresourcerepository.cpp) qt5_add_resources(TestIResourceRepository_SRCS ../data/languages.qrc) add_executable(test_iresourcerepository_integration ${TestIResourceRepository_SRCS}) target_link_libraries(test_iresourcerepository_integration artikulatecore Qt5::Test ) -add_test(test_iresourcerepository_integration test_iresourcerepository_integration) +add_test(NAME test_iresourcerepository_integration COMMAND test_iresourcerepository_integration) ecm_mark_as_test(test_iresourcerepository_integration) # training session tests set(TestTrainingSession_SRCS trainingsession/test_trainingsession.cpp) add_executable(test_trainingsession ${TestTrainingSession_SRCS}) target_link_libraries(test_trainingsession artikulatecore Qt5::Test ) -add_test(test_trainingsession test_trainingsession) +add_test(NAME test_trainingsession COMMAND test_trainingsession) ecm_mark_as_test(test_trainingsession) # editor session tests set(TestEditorSession_SRCS editorsession/test_editorsession.cpp editorsession/editablerepositorystub.cpp ) add_executable(test_editorsession ${TestEditorSession_SRCS}) target_link_libraries(test_editorsession artikulatecore Qt5::Test ) -add_test(test_editorsession test_editorsession) +add_test(NAME test_editorsession COMMAND test_editorsession) ecm_mark_as_test(test_editorsession) # test course resource class set(TestCourseResource_SRCS courseresource/test_courseresource.cpp courseresource/resourcerepositorystub.cpp ) qt5_add_resources(TestCourseResource_SRCS ../data/languages.qrc) add_executable(test_courseresource ${TestCourseResource_SRCS} ) target_link_libraries(test_courseresource artikulatecore Qt5::Test ) -add_test(test_courseresource test_courseresource) +add_test(NAME test_courseresource COMMAND test_courseresource) ecm_mark_as_test(test_courseresource) # test skeleton resource class set(TestSkeletonResource_SRCS skeletonresource/test_skeletonresource.cpp skeletonresource/resourcerepositorystub.cpp ) qt5_add_resources(TestSkeletonResource_SRCS ../data/languages.qrc) add_executable(test_skeletonresource ${TestSkeletonResource_SRCS} ) target_link_libraries(test_skeletonresource artikulatecore Qt5::Test ) -add_test(test_skeletonresource test_skeletonresource) +add_test(NAME test_skeletonresource COMMAND test_skeletonresource) ecm_mark_as_test(test_skeletonresource) # test editable course resource class set(TestEditableCourseResource_SRCS editablecourseresource/test_editablecourseresource.cpp editablecourseresource/resourcerepositorystub.cpp ) qt5_add_resources(TestEditableCourseResource_SRCS ../data/languages.qrc) qt5_add_resources(TestEditableCourseResource_SRCS testdata/testdata.qrc) add_executable(test_editablecourseresource ${TestEditableCourseResource_SRCS} ) target_link_libraries(test_editablecourseresource artikulatecore Qt5::Test ) -add_test(test_editablecourseresource test_editablecourseresource) +add_test(NAME test_editablecourseresource COMMAND test_editablecourseresource) ecm_mark_as_test(test_editablecourseresource) # basic tests language files (input/output) set(TestLanguageFiles_SRCS testlanguagefiles.cpp) add_executable(TestLanguageFiles ${TestLanguageFiles_SRCS} ) target_link_libraries(TestLanguageFiles artikulatecore Qt5::Test ) -add_test(TestLanguageFiles TestLanguageFiles) +add_test(NAME TestLanguageFiles COMMAND TestLanguageFiles) ecm_mark_as_test(TestLanguageFiles) diff --git a/liblearnerprofile/autotests/CMakeLists.txt b/liblearnerprofile/autotests/CMakeLists.txt index 50519ea..e1ee2c8 100644 --- a/liblearnerprofile/autotests/CMakeLists.txt +++ b/liblearnerprofile/autotests/CMakeLists.txt @@ -1,44 +1,44 @@ ### # Copyright 2016 Andreas Cord-Landwehr # # 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. ### include_directories( ../src/ ../ ${CMAKE_CURRENT_BINARY_DIR} ) set(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}) set(TestLearnerStorage_SRCS testlearnerstorage.cpp ../src/storage.cpp ../src/liblearner_debug.cpp ) add_executable(TestLearnerStorage ${TestLearnerStorage_SRCS} ) target_link_libraries(TestLearnerStorage artikulatelearnerprofile Qt5::Test ) -add_test(TestLearnerStorage TestLearnerStorage) +add_test(NAME TestLearnerStorage COMMAND TestLearnerStorage) ecm_mark_as_test(TestLearnerStorage) diff --git a/liblearnerprofile/src/storage.cpp b/liblearnerprofile/src/storage.cpp index 3995f05..2170ebc 100644 --- a/liblearnerprofile/src/storage.cpp +++ b/liblearnerprofile/src/storage.cpp @@ -1,679 +1,679 @@ /* * Copyright 2013-2016 Andreas Cord-Landwehr * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 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 6 of version 3 of the license. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . */ #include "storage.h" #include "learner.h" #include "liblearner_debug.h" #include #include #include #include #include #include #include using namespace LearnerProfile; Storage::Storage(QObject* parent) : QObject(parent) , m_databasePath(QStandardPaths::writableLocation( QStandardPaths::DataLocation) + QLatin1Char('/') + "learnerdata.db") , m_errorMessage(QString()) { } -Storage::Storage(const QString databasePath, QObject* parent) +Storage::Storage(const QString &databasePath, QObject* parent) : QObject(parent) , m_databasePath(databasePath) , m_errorMessage(QString()) { qCDebug(LIBLEARNER_LOG) << "Initialize with custom DB path:" << m_databasePath; } QString Storage::errorMessage() const { return m_errorMessage; } void Storage::raiseError(const QSqlError &error) { m_errorMessage = QStringLiteral("%1 : %2").arg(error.driverText(), error.databaseText()); emit errorMessageChanged(); } bool Storage::storeProfile(Learner *learner) { QSqlDatabase db = database(); // test whether ID is present QSqlQuery idExistsQuery(db); idExistsQuery.prepare(QStringLiteral("SELECT COUNT(*) FROM profiles WHERE id = :id")); idExistsQuery.bindValue(QStringLiteral(":id"), learner->identifier()); idExistsQuery.exec(); if (db.lastError().isValid()) { qCritical() << "ExistsQuery: " << db.lastError().text(); raiseError(db.lastError()); return false; } // go to first result row that contains the count idExistsQuery.next(); if (idExistsQuery.value(0).toInt() < 1) { // in case learner ID is not found in database QSqlQuery insertProfileQuery(db); insertProfileQuery.prepare(QStringLiteral("INSERT INTO profiles (id, name) VALUES (?, ?)")); insertProfileQuery.bindValue(0, learner->identifier()); insertProfileQuery.bindValue(1, learner->name()); insertProfileQuery.exec(); if (insertProfileQuery.lastError().isValid()) { raiseError(insertProfileQuery.lastError()); db.rollback(); return false; } } else { // update name otherwise QSqlQuery updateProfileQuery(db); updateProfileQuery.prepare(QStringLiteral("UPDATE profiles SET name = :name WHERE id = :id")); updateProfileQuery.bindValue(QStringLiteral(":id"), learner->identifier()); updateProfileQuery.bindValue(QStringLiteral(":name"), learner->name()); updateProfileQuery.exec(); if (updateProfileQuery.lastError().isValid()) { qCritical() << updateProfileQuery.lastError().text(); raiseError(updateProfileQuery.lastError()); db.rollback(); return false; } } // store existing learning goal relations foreach (LearningGoal *goal, learner->goals()) { QSqlQuery relationExistsQuery(db); relationExistsQuery.prepare("SELECT COUNT(*) FROM learner_goals " "WHERE goal_category = :goalCategory " "AND goal_identifier = :goalIdentifier " "AND profile_id = :profileId " ); relationExistsQuery.bindValue(QStringLiteral(":goalCategory"), goal->category()); relationExistsQuery.bindValue(QStringLiteral(":goalIdentifier"), goal->identifier()); relationExistsQuery.bindValue(QStringLiteral(":profileId"), learner->identifier()); relationExistsQuery.exec(); if (db.lastError().isValid()) { qCritical() << "ExistsQuery: " << db.lastError().text(); raiseError(db.lastError()); return false; } // go to first result row that contains the count relationExistsQuery.next(); if (relationExistsQuery.value(0).toInt() < 1) { QSqlQuery insertProfileQuery(db); insertProfileQuery.prepare(QStringLiteral("INSERT INTO learner_goals (goal_category, goal_identifier, profile_id) VALUES (?, ?, ?)")); insertProfileQuery.bindValue(0, goal->category()); insertProfileQuery.bindValue(1, goal->identifier()); insertProfileQuery.bindValue(2, learner->identifier()); insertProfileQuery.exec(); } } // remove deleted relations QSqlQuery cleanupRelations(db); cleanupRelations.prepare(QStringLiteral("DELETE FROM learner_goals WHERE ")); //TODO change creation of relations to same way as remove-relations: explicit connections return true; } bool Storage::removeProfile(Learner *learner) { QSqlDatabase db = database(); QSqlQuery removeProfileQuery(db); // delete learner removeProfileQuery.prepare(QStringLiteral("DELETE FROM profiles WHERE id = ?")); removeProfileQuery.bindValue(0, learner->identifier()); removeProfileQuery.exec(); if (removeProfileQuery.lastError().isValid()) { qCritical() << removeProfileQuery.lastError().text(); raiseError(removeProfileQuery.lastError()); db.rollback(); return false; } // delete learning goal relations QSqlQuery removeGoalRelationQuery(db); removeGoalRelationQuery.prepare(QStringLiteral("DELETE FROM learner_goals WHERE profile_id = ?")); removeGoalRelationQuery.bindValue(0, learner->identifier()); removeGoalRelationQuery.exec(); if (removeGoalRelationQuery.lastError().isValid()) { qCritical() << removeGoalRelationQuery.lastError().text(); raiseError(removeGoalRelationQuery.lastError()); db.rollback(); return false; } return true; } bool Storage::removeRelation(Learner *learner, LearningGoal *goal) { QSqlDatabase db = database(); QSqlQuery removeGoalRelationQuery(db); removeGoalRelationQuery.prepare( "DELETE FROM learner_goals " "WHERE goal_category = :goalCategory " "AND goal_identifier = :goalIdentifier " "AND profile_id = :profileId " ); removeGoalRelationQuery.bindValue(QStringLiteral(":goalCategory"), goal->category()); removeGoalRelationQuery.bindValue(QStringLiteral(":goalIdentifier"), goal->identifier()); removeGoalRelationQuery.bindValue(QStringLiteral(":profileId"), learner->identifier()); removeGoalRelationQuery.exec(); if (db.lastError().isValid()) { qCritical() << "ExistsQuery: " << db.lastError().text(); raiseError(db.lastError()); return false; } return true; } QList< Learner* > Storage::loadProfiles(QList goals) { QSqlDatabase db = database(); QSqlQuery profileQuery(db); profileQuery.prepare(QStringLiteral("SELECT id, name FROM profiles")); profileQuery.exec(); if (profileQuery.lastError().isValid()) { qCritical() << profileQuery.lastError().text(); raiseError(profileQuery.lastError()); return QList(); } QList profiles; while (profileQuery.next()) { Learner* profile = new Learner(); profile->setIdentifier(profileQuery.value(0).toInt()); profile->setName(profileQuery.value(1).toString()); profiles.append(profile); } // associate to goals QSqlQuery goalRelationQuery(db); goalRelationQuery.prepare(QStringLiteral("SELECT goal_category, goal_identifier, profile_id FROM learner_goals")); goalRelationQuery.exec(); if (goalRelationQuery.lastError().isValid()) { qCritical() << goalRelationQuery.lastError().text(); raiseError(goalRelationQuery.lastError()); return QList(); } while (goalRelationQuery.next()) { Learner *learner = nullptr; LearningGoal *goal = nullptr; foreach (Learner *cmpProfile, profiles) { if (cmpProfile->identifier() == goalRelationQuery.value(2).toInt()) { learner = cmpProfile; break; } } if (!learner) { qCCritical(LIBLEARNER_LOG) << "Could not retrieve learner from database."; return QList(); } foreach (LearningGoal *cmpGoal, goals) { if (cmpGoal->category() == goalRelationQuery.value(0).toInt() && cmpGoal->identifier() == goalRelationQuery.value(1).toString()) { goal = cmpGoal; break; } } if (learner->goals().contains(goal)) { continue; } if (goal) { learner->addGoal(goal); } } return profiles; } bool Storage::storeGoal(LearningGoal *goal) { QSqlDatabase db = database(); // test whether ID is present QSqlQuery goalExistsQuery(db); goalExistsQuery.prepare(QStringLiteral("SELECT COUNT(*) FROM goals WHERE category = :category AND identifier = :identifier")); goalExistsQuery.bindValue(QStringLiteral(":identifier"), goal->identifier()); goalExistsQuery.bindValue(QStringLiteral(":category"), static_cast(goal->category())); goalExistsQuery.exec(); if (db.lastError().isValid()) { qCritical() << "ExistsQuery: " << db.lastError().text(); raiseError(db.lastError()); return false; } // go to first result row that contains the count goalExistsQuery.next(); if (goalExistsQuery.value(0).toInt() < 1) { // in case learner ID is not found in database QSqlQuery insertGoalQuery(db); insertGoalQuery.prepare(QStringLiteral("INSERT INTO goals (category, identifier, name) VALUES (?, ?, ?)")); insertGoalQuery.bindValue(0, static_cast(goal->category())); insertGoalQuery.bindValue(1, goal->identifier()); insertGoalQuery.bindValue(2, goal->name()); insertGoalQuery.exec(); if (insertGoalQuery.lastError().isValid()) { raiseError(insertGoalQuery.lastError()); db.rollback(); return false; } return true; } else { // update name otherwise QSqlQuery updateGoalQuery(db); updateGoalQuery.prepare(QStringLiteral("UPDATE goals SET name = :name WHERE category = :category AND identifier = :identifier")); updateGoalQuery.bindValue(QStringLiteral(":category"), static_cast(goal->category())); updateGoalQuery.bindValue(QStringLiteral(":identifier"), goal->identifier()); updateGoalQuery.bindValue(QStringLiteral(":name"), goal->name()); updateGoalQuery.exec(); if (updateGoalQuery.lastError().isValid()) { qCritical() << updateGoalQuery.lastError().text(); raiseError(updateGoalQuery.lastError()); db.rollback(); return false; } return true; } } QList< LearningGoal* > Storage::loadGoals() { QSqlDatabase db = database(); QSqlQuery goalQuery(db); goalQuery.prepare(QStringLiteral("SELECT category, identifier, name FROM goals")); goalQuery.exec(); if (goalQuery.lastError().isValid()) { qCritical() << goalQuery.lastError().text(); raiseError(goalQuery.lastError()); return QList(); } QList goals; while (goalQuery.next()) { LearningGoal::Category category = static_cast(goalQuery.value(0).toInt()); QString identifier = goalQuery.value(1).toString(); QString name = goalQuery.value(2).toString(); LearningGoal* goal = new LearningGoal(category, identifier); goal->setName(name); goals.append(goal); } return goals; } bool Storage::storeProgressLog(Learner *learner, LearningGoal *goal, const QString &container, const QString &item, int payload, const QDateTime &time) { QSqlDatabase db = database(); QSqlQuery insertQuery(db); insertQuery.prepare("INSERT INTO learner_progress_log " "(goal_category, goal_identifier, profile_id, item_container, item, payload, date) " "VALUES (:gcategory, :gidentifier, :pid, :container, :item, :payload, :date)"); insertQuery.bindValue(QStringLiteral(":gcategory"), static_cast(goal->category())); insertQuery.bindValue(QStringLiteral(":gidentifier"), goal->identifier()); insertQuery.bindValue(QStringLiteral(":pid"), learner->identifier()); insertQuery.bindValue(QStringLiteral(":container"), container); insertQuery.bindValue(QStringLiteral(":item"), item); insertQuery.bindValue(QStringLiteral(":payload"), payload); insertQuery.bindValue(QStringLiteral(":date"), time.toString(Qt::ISODate)); insertQuery.exec(); if (insertQuery.lastError().isValid()) { raiseError(insertQuery.lastError()); qCCritical(LIBLEARNER_LOG) << "DB Error:" << m_errorMessage; db.rollback(); return false; } return true; } QList> Storage::readProgressLog(Learner *learner, LearningGoal *goal, const QString &container, const QString &item) { QSqlDatabase db = database(); QSqlQuery logQuery(db); logQuery.prepare("SELECT date, payload FROM learner_progress_log " "WHERE goal_category = :goalcategory " "AND goal_identifier = :goalid " "AND profile_id = :profileid " "AND item_container = :container " "AND item = :item"); logQuery.bindValue(QStringLiteral(":goalcategory"), static_cast(goal->category())); logQuery.bindValue(QStringLiteral(":goalid"), goal->identifier()); logQuery.bindValue(QStringLiteral(":profileid"), learner->identifier()); logQuery.bindValue(QStringLiteral(":container"), container); logQuery.bindValue(QStringLiteral(":item"), item); logQuery.exec(); if (logQuery.lastError().isValid()) { qCritical() << logQuery.lastError().text(); raiseError(logQuery.lastError()); return QList>(); } QList> log; while (logQuery.next()) { const QDateTime date{logQuery.value(0).toDateTime()}; int payload{logQuery.value(1).toInt()}; log.append(qMakePair(date, payload)); } return log; } bool Storage::storeProgressValue(Learner *learner, LearningGoal *goal, const QString &container, const QString &item, int payload) { QSqlDatabase db = database(); QSqlQuery query(db); // test if already payload stored query.prepare("SELECT payload FROM learner_progress_value " "WHERE goal_category = :gcategory " "AND goal_identifier = :gidentifier " "AND profile_id = :pid " "AND item_container = :container " "AND item = :item"); query.bindValue(QStringLiteral(":gcategory"), static_cast(goal->category())); query.bindValue(QStringLiteral(":gidentifier"), goal->identifier()); query.bindValue(QStringLiteral(":pid"), learner->identifier()); query.bindValue(QStringLiteral(":container"), container); query.bindValue(QStringLiteral(":item"), item); query.exec(); if (query.lastError().isValid()) { qCritical() << query.lastError().text(); raiseError(query.lastError()); return false; } // if query contains values, perform update query if (query.next()) { query.finish(); // release resources from previous query query.prepare("UPDATE learner_progress_value " "SET payload = :payload " "WHERE goal_category = :gcategory " "AND goal_identifier = :gidentifier " "AND profile_id = :pid " "AND item_container = :container " "AND item = :item"); query.bindValue(QStringLiteral(":payload"), static_cast(payload)); query.bindValue(QStringLiteral(":gcategory"), static_cast(goal->category())); query.bindValue(QStringLiteral(":gidentifier"), goal->identifier()); query.bindValue(QStringLiteral(":pid"), learner->identifier()); query.bindValue(QStringLiteral(":container"), container); query.bindValue(QStringLiteral(":item"), item); query.exec(); if (query.lastError().isValid()) { qCritical() << query.lastError().text(); raiseError(query.lastError()); db.rollback(); return false; } return true; } // else insert new row else { query.finish(); // release resources from previous query query.prepare("INSERT INTO learner_progress_value " "(goal_category, goal_identifier, profile_id, item_container, item, payload) " "VALUES (:gcategory, :gidentifier, :pid, :container, :item, :payload)"); query.bindValue(QStringLiteral(":gcategory"), static_cast(goal->category())); query.bindValue(QStringLiteral(":gidentifier"), goal->identifier()); query.bindValue(QStringLiteral(":pid"), learner->identifier()); query.bindValue(QStringLiteral(":container"), container); query.bindValue(QStringLiteral(":item"), item); query.bindValue(QStringLiteral(":payload"), static_cast(payload)); query.exec(); if (query.lastError().isValid()) { qCritical() << query.lastError().text(); raiseError(query.lastError()); db.rollback(); return false; } return true; } Q_UNREACHABLE(); return false; } QHash Storage::readProgressValues(Learner *learner, LearningGoal *goal, const QString &container) { QSqlDatabase db = database(); QSqlQuery query(db); query.prepare("SELECT item, payload FROM learner_progress_value " "WHERE goal_category = :goalcategory " "AND goal_identifier = :goalid " "AND profile_id = :profileid " "AND item_container = :container"); query.bindValue(QStringLiteral(":goalcategory"), static_cast(goal->category())); query.bindValue(QStringLiteral(":goalid"), goal->identifier()); query.bindValue(QStringLiteral(":profileid"), learner->identifier()); query.bindValue(QStringLiteral(":container"), container); query.exec(); if (query.lastError().isValid()) { qCritical() << query.lastError().text(); raiseError(query.lastError()); return QHash(); } QHash values; while (query.next()) { const QString item{query.value(0).toString()}; const int payload{query.value(1).toInt()}; values.insert(item, payload); } return values; } int Storage::readProgressValue(Learner *learner, LearningGoal *goal, const QString &container, const QString &item) { QSqlDatabase db = database(); QSqlQuery query(db); query.prepare("SELECT payload FROM learner_progress_value " "WHERE goal_category = :goalcategory " "AND goal_identifier = :goalid " "AND profile_id = :profileid " "AND item_container = :container " "AND item = :item"); query.bindValue(QStringLiteral(":goalcategory"), static_cast(goal->category())); query.bindValue(QStringLiteral(":goalid"), goal->identifier()); query.bindValue(QStringLiteral(":profileid"), learner->identifier()); query.bindValue(QStringLiteral(":container"), container); query.bindValue(QStringLiteral(":item"), item); query.exec(); if (query.lastError().isValid()) { qCritical() << query.lastError().text(); raiseError(query.lastError()); return -1; } if (query.next()) { return query.value(0).toInt(); } return -1; } QSqlDatabase Storage::database() { if (QSqlDatabase::contains(QSqlDatabase::defaultConnection)) { return QSqlDatabase::database(QSqlDatabase::defaultConnection); } // create data directory if it does not exist QDir dir = QDir(QStandardPaths::writableLocation(QStandardPaths::DataLocation)); if (!dir.exists()) { dir.mkpath(QStandardPaths::writableLocation(QStandardPaths::DataLocation)); } qCDebug(LIBLEARNER_LOG) << "Database path: " << m_databasePath; QSqlDatabase db = QSqlDatabase::addDatabase(QStringLiteral("QSQLITE")); db.setDatabaseName(m_databasePath); if (!db.open()) { qCritical() << "Could not open database: " << db.lastError().text(); raiseError(db.lastError()); return db; } if (!updateSchema()) { qCritical() << "Database scheme not correct."; return db; } // return correctly set up database return db; } bool Storage::updateSchema() { QSqlDatabase db = database(); // check database version format db.exec("CREATE TABLE IF NOT EXISTS metadata (" "key TEXT PRIMARY KEY, " "value TEXT" ")"); if (db.lastError().isValid()) { qCritical() << db.lastError().text(); raiseError(db.lastError()); return false; } QSqlQuery versionQuery = db.exec(QStringLiteral("SELECT value FROM metadata WHERE key = 'version'")); if (db.lastError().isValid()) { qCritical() << db.lastError().text(); raiseError(db.lastError()); return false; } if (versionQuery.next()) { QString version = versionQuery.value(0).toString(); if (version != QLatin1String("1")) { m_errorMessage = i18n("Invalid database version '%1'.", version); emit errorMessageChanged(); return false; } } else { if (!db.transaction()) { qCWarning(LIBLEARNER_LOG) << db.lastError().text(); raiseError(db.lastError()); return false; } db.exec(QStringLiteral("INSERT INTO metadata (key, value) VALUES ('version', '1')")); if (db.lastError().isValid()) { qCritical() << db.lastError().text(); raiseError(db.lastError()); return false; } if (!db.commit()) { qCritical() << db.lastError().text(); raiseError(db.lastError()); return false; } } // table for learner profiles db.exec("CREATE TABLE IF NOT EXISTS profiles (" "id INTEGER PRIMARY KEY AUTOINCREMENT, " "name TEXT" ")"); if (db.lastError().isValid()) { qCritical() << db.lastError().text(); raiseError(db.lastError()); return false; } // table for registered learning goals db.exec("CREATE TABLE IF NOT EXISTS goals (" "category INTEGER, " // LearningGoal::Category "identifier TEXT, " // identifier, unique per Category "name TEXT, " // name "PRIMARY KEY ( category, identifier )" ")"); if (db.lastError().isValid()) { qCritical() << db.lastError().text(); raiseError(db.lastError()); return false; } // table for learner - learningGoal relations db.exec("CREATE TABLE IF NOT EXISTS learner_goals (" "id INTEGER PRIMARY KEY AUTOINCREMENT, " "goal_category INTEGER, " // LearningGoal::Category "goal_identifier TEXT, " // LearningGoal::Identifier "profile_id INTEGER " // Learner::Identifier ")"); if (db.lastError().isValid()) { qCritical() << db.lastError().text(); raiseError(db.lastError()); return false; } // table for full progress data log db.exec("CREATE TABLE IF NOT EXISTS learner_progress_log (" "id INTEGER PRIMARY KEY AUTOINCREMENT, " "goal_category INTEGER, " // LearningGoal::Category "goal_identifier TEXT, " // LearningGoal::Identifier "profile_id INTEGER, " // Learner::Identifier "item_container TEXT, " "item TEXT, " "payload INTEGER, " "date TEXT" ")"); if (db.lastError().isValid()) { qCritical() << db.lastError().text(); raiseError(db.lastError()); return false; } // table for progress data quick access db.exec("CREATE TABLE IF NOT EXISTS learner_progress_value (" "id INTEGER PRIMARY KEY AUTOINCREMENT, " "goal_category INTEGER, " // LearningGoal::Category "goal_identifier TEXT, " // LearningGoal::Identifier "profile_id INTEGER, " // Learner::Identifier "item_container TEXT, " "item TEXT, " "payload INTEGER" ")"); if (db.lastError().isValid()) { qCritical() << db.lastError().text(); raiseError(db.lastError()); return false; } return true; } diff --git a/liblearnerprofile/src/storage.h b/liblearnerprofile/src/storage.h index 80cf255..67af00a 100644 --- a/liblearnerprofile/src/storage.h +++ b/liblearnerprofile/src/storage.h @@ -1,103 +1,103 @@ /* * Copyright 2013-2016 Andreas Cord-Landwehr * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 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 6 of version 3 of the license. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . */ #ifndef STORAGE_H #define STORAGE_H #include class QSqlError; class QSqlDatabase; namespace LearnerProfile { class Learner; class LearningGoal; /** * \class Storage * Database storage for learner information database. */ class Storage : public QObject { Q_OBJECT Q_PROPERTY(QString errorMessage READ errorMessage NOTIFY errorMessageChanged) public: /** * Default constructor, which sets a default database path at * DataLocation + learnerdata.db */ explicit Storage(QObject* parent = nullptr); /** * \note this constructor is tailored for unit tests */ - explicit Storage(const QString databasePath, QObject* parent = nullptr); + explicit Storage(const QString &databasePath, QObject* parent = nullptr); QString errorMessage() const; /** * Store profile in database. This can either be a new or an existing profile. * If it is an existing profile, the corresponding values are updated. */ bool storeProfile(Learner *learner); bool removeProfile(Learner *learner); bool removeRelation(Learner *learner, LearningGoal *goal); QList loadProfiles(QList< LearnerProfile::LearningGoal* > goals); bool storeGoal(LearningGoal *goal); QList loadGoals(); bool storeProgressLog(Learner *learner, LearningGoal *goal, const QString &container, const QString &item, int payload, const QDateTime &time); /** * Load list of progress values for specified item * \return list of date/payload values for this item */ QList> readProgressLog(Learner *learner, LearningGoal *goal, const QString &container, const QString &item); bool storeProgressValue(Learner *learner, LearningGoal *goal, const QString &container, const QString &item, int payload); /** * Load list of progress values for specified container * \return list of item/payload values for all items in container */ QHash readProgressValues(Learner *learner, LearningGoal *goal, const QString &container); /** * Load payload value of specified item. If no value is found, \return -1 */ int readProgressValue(Learner *learner, LearningGoal *goal, const QString &container, const QString &item); Q_SIGNALS: void errorMessageChanged(); protected: QSqlDatabase database(); void raiseError(const QSqlError &error); private: bool updateSchema(); const QString m_databasePath; QString m_errorMessage; }; } #endif // STORAGE_H diff --git a/libsound/src/capturedevicecontroller.h b/libsound/src/capturedevicecontroller.h index ba70662..e2fb639 100644 --- a/libsound/src/capturedevicecontroller.h +++ b/libsound/src/capturedevicecontroller.h @@ -1,86 +1,85 @@ /* * Copyright 2013 Andreas Cord-Landwehr * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #ifndef CAPTUREDEVICECONTROLLER_H #define CAPTUREDEVICECONTROLLER_H #include "libsound_export.h" #include class CaptureDeviceControllerPrivate; -class QUrl; /** * \class CaptureDeviceController * * This singleton class provides a controller for the sound capture device. */ class LIBSOUND_EXPORT CaptureDeviceController : public QObject { Q_OBJECT public: enum State { StoppedState, RecordingState, PausedState }; /** * Returns self reference to the controller. First call of this method initializes * capture device controller. * * \return self reference */ static CaptureDeviceController & self(); void startCapture(const QString &filePath); CaptureDeviceController::State state() const; void stopCapture(); void setDevice(const QString &deviceIdentifier); /** * \return list of available capture devices */ QList devices() const; public Q_SLOTS: Q_SIGNALS: void captureStarted(); void captureStopped(); private: Q_DISABLE_COPY(CaptureDeviceController) /** * \internal * Private constructor, \ref self(). */ CaptureDeviceController(); /** * Private destructor. */ ~CaptureDeviceController(); const QScopedPointer d; }; #endif diff --git a/libsound/src/qtmultimediabackend/qtmultimediacapturebackend.h b/libsound/src/qtmultimediabackend/qtmultimediacapturebackend.h index d6f7281..b9e85c9 100644 --- a/libsound/src/qtmultimediabackend/qtmultimediacapturebackend.h +++ b/libsound/src/qtmultimediabackend/qtmultimediacapturebackend.h @@ -1,51 +1,53 @@ /* * Copyright 2016 Andreas Cord-Landwehr * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #ifndef QTMULTIMEDIACAPTUREBACKEND_H #define QTMULTIMEDIACAPTUREBACKEND_H #include "capturedevicecontroller.h" #include "capturebackendinterface.h" #include #include #include +class QAudioRecorder; +class QMediaRecorder; class QMediaObject; class QtMultimediaCaptureBackend : public CaptureBackendInterface { Q_OBJECT public: explicit QtMultimediaCaptureBackend(QObject *parent); ~QtMultimediaCaptureBackend() override = default; void startCapture(const QString &filePath) override; void stopCapture() override; CaptureDeviceController::State captureState() const override; QStringList devices() const override; void setDevice(const QString &deviceIdentifier) override; private: QAudioRecorder m_recorder; QString m_device; }; #endif diff --git a/org.kde.artikulate.appdata.xml b/org.kde.artikulate.appdata.xml index 5a9e559..710fa51 100644 --- a/org.kde.artikulate.appdata.xml +++ b/org.kde.artikulate.appdata.xml @@ -1,129 +1,130 @@ org.kde.artikulate.desktop CC0-1.0 GPL-2.0+ Artikulate Artikulate Artikulate Artikulate Artikulate Artikulate Artikulate Artikulate Artikulate Artikulate Artikulate Artikulate Artikulate Artikulate Artikulate Artikulate Artikulate Artikulate Artikulate Artikulate Artikulate Artikulate Artikulate Artikulate Artikulate Artikulate Artikulate Artikulate Artikulate xxArtikulatexx Artikulate Artikulate Artikulate Pronunciation Trainer Artikulate vježba izgovora Entrenador de la pronunciació Artikulate Entrenador de la pronunciació Artikulate Artikulate - učitel výslovnosti Artikulate udtaletræning Artikulate-Aussprachetrainer Artikulate Pronunciation Trainer Artikulate Prononciada Trejnilo Entrenador de pronunciación Artikulate Häälduse harjutaja Artikulate Artikulate ääntämisen harjoitteluohjelma Artikulate, entraînement à la prononciation Adestrador de pronuncia Artikulate Artikulate kiejtés oktató Pelatih Pengucapan Artikulasi Artikulate 발음 타이머 Utspraak-Lehrer Artikulate Artikulate Trainingsprogramma voor uitspraak Artikulate uttaleøvar Trener artykułowanej wymowy Treino de Pronúncia Artikulate Treinador de Pronúncia Artikulate Тренажёр произношения Artikulate Tréner výslovnosti Artikulate Učenje izgovorjave Artikulate Artikulate uttalsövning Artikulate Telaffuz Eğitici Програма для навчання вимові Artikulate xxArtikulate Pronunciation Trainerxx Artikulate 读音训练器 Artikulate 發音訓練器

Artikulate is a pronunciation trainer that helps improving and perfecting a learner's pronunciation skills for a foreign language. It provides courses with native speaker recordings for several training languages. The learner downloads those courses, selects a category of phrases to train, then starts with recording her/his own voice when speaking the phrases and comparing the results to the native speaker's recordings by listening to both. By adjusting and repeating the own pronunciation, the learner can improve his/her skill.

Artikulate je trener izgovora koji poboljšava i usavršava izgovorne vještine za učenike stranih jezik. Ona pruža kurseve sa snimcima na maternjem jeziku za nekoliko jezika obuke. Učenik preuzima ove kurseve, bira kategoriju fraza za obuku, a zatim počinje sa snimanjem njegovog/njenog glasa pri izgovoru fraze.i Porede se rezultati snimaka na maternji i slušaju oba. Podešavanjem i ponavljanja sopstvenog izgovora, učenik može da poboljša njegovu / njenu vještinu.

L'Artikulate és un entrenador de pronunciació que ajuda a millor i perfeccionar les habilitats de pronunciació d'un alumne d'un idioma estranger. Proporciona cursos amb enregistraments d'un parlant natiu. L'alumne baixa aquests cursos, selecciona una categoria de frases per entrenar, després comença enregistrant la seva pròpia veu en pronunciar les frases i compara els resultats amb els enregistraments del parlant natiu escoltant els dos. Ajustant i repetint la pronunciació pròpia, l'alumne pot millorar la seva habilitat.

L'Artikulate és un entrenador de pronunciació que ajuda a millor i perfeccionar les habilitats de pronunciació d'un alumne d'un idioma estranger. Proporciona cursos amb enregistraments d'un parlant natiu. L'alumne baixa aquests cursos, selecciona una categoria de frases per entrenar, després comença enregistrant la seua pròpia veu en pronunciar les frases i compara els resultats amb els enregistraments del parlant natiu escoltant els dos. Ajustant i repetint la pronunciació pròpia, l'alumne pot millorar la seua habilitat.

Artikulate er udtaletræning som hjælper med at forbedre og perfektionere din udtale af et fremmedsprog. Det leverer kurser med modersmåloptagelser for flere øvelsessprog. Eleven downloader disse kurser, vælger en kategori af fraser der skal øves, og begynder så at optage sin egen stemme når fraserne udtales og sammenligner resultaterne med modersmåloptagelserne ved at lytte til begge. Ved at justere og gentage den egen udtale, kan eleven forbedre sine evner.

Artikulate ist eine Anwendung zum Üben der Aussprache und hilft beim Verbessern und Perfektionieren Ihrer Aussprachefähigkeiten für eine fremde Sprache. Dazu können Übungen mit Aufnahmen von Muttersprachlern für mehrere Zielsprachen heruntergeladen werden. Dann wird eine Gruppe von Redewendungen ausgewählt, die eigene Stimme beim Aussprechen der Redewendungen aufgenommen und mit den Aufnahmen von Muttersprachlern verglichen. Durch Anpassen und Wiederholen kann die eigene Aussprache verbessert werden.

Artikulate is a pronunciation trainer that helps improving and perfecting a learner's pronunciation skills for a foreign language. It provides courses with native speaker recordings for several training languages. The learner downloads those courses, selects a category of phrases to train, then starts with recording her/his own voice when speaking the phrases and comparing the results to the native speaker's recordings by listening to both. By adjusting and repeating the own pronunciation, the learner can improve his/her skill.

Artikulate estas prononciada trejnilo kiu helpas plibonigi kaj perfektigi prononciadon de lernanta sperto por fremda lingvo. Ĝi provizas kursojn kun denaksulaj registroj por pluraj trejnataj lingvoj. La lernanto elŝutas tiujn kursojn, elektas kategorion da frazoj trejnendaj, registras sian voĉon dirante la frazojn kaj komparas la rezultojn al registroj de denaskuloj aŭskultante ambaŭ. Ĝustigante kaj ripetante sian propran prononciadon, la lernanto povas plibonigi sian kompetenton.

Artikulate es un entrenador de pronunciación que ayuda a mejorar y perfeccionar la pronunciación de un idioma extranjero por parte del estudiante. Para ello, proporciona cursos que se pueden descargar con grabaciones de hablantes nativos de varios idiomas. El estudiante descarga los cursos, selecciona un conjunto de frases, graba su propia voz al repetir las frases y luego al escucharlas, compara los resultados con las grabaciones de hablantes nativos. Estudiante puede mejorar su pronunciación mediante el ajuste y la repetición.

Artikulate on häälduse harjutamise abiline, mis aitab õppuril täiendada ja täiustada võõrkeele hääldamisoskust. Rakendus pakub mitme keele kursuseid, millele vastavat keelt emakeelena kõnelejad on loonud salvestisi. Õppur laadib kursused alla, valib väljendite kategooria, mida ta soovib harjutada, ning hakkab siis salvestama enda häält, kui ta lausub etteantud fraase, võrreldes hiljem neid emakeeles kõneleja salvestustega. Oma hääldust kohendades ja väljendeid korrates saab võõrkeeleoskust tublisti edendada.

Artikulate auttaa parantamaan vieraan kielen ääntämistä. Siinä on äidinkielisten puhumia kursseja useille kielille. Harjoittelija lataa kurssit, valitsee harjoitusfraasien luokan ja alkaa äänittää fraaseja itse lausuttuina. Oman ääntämisen äänittämisen jälkeen harjoittelija vertaa tuloksiaan äidinkieliseen puhujaan kuuntelemalla sekä oman että ädiinkielisen puhujan äänitteen. Hiomalla ja toistamalla omaa ääntämystään harjoittelija voi parantaa taitoaan.

Artikulate est un programme d'entraînement à la prononciation pour améliorer et perfectionner les compétences dans une langue étrangère. Il fournit des cours avec les enregistrements d'un locuteur natif pour plusieurs langues d'entraînement. L'élève télécharge ces cours, sélectionne une catégorie ou des phrases à travailler, enregistre sa propre voix en prononçant les phrases, puis se compare aux enregistrement du locuteur natif. En ajustant et en répétant sa propre prononciation, l'élève s'améliore au fur et à mesure.

Artikulate é un adestrador de pronuncia para axudarlo a mellorar e perfeccionar a súa pronuncia de distintos idiomas. Fornece cursos con gravacións de falantes nativos para varios idiomas. O estudante descarga os cursos, selecciona unha categoría de frases para adestrar, e comeza coa gravación da súa propia voz pronunciando as frases, e comparando os resultados coas gravacións do falante nativo, escoitando ambas as dúas gravacións. Axustando e repetindo a súa gravación, o estudante pode mellorar a súa pronuncia.

Artikulate adalah pelatih pengucapan yang membantu meningkatkan dan menyempurnakan keterampilan pengucapan pembelajar untuk bahasa asing. Ini memberikan kursus dengan rekaman penutur asli untuk beberapa bahasa pelatihan. Pelajar mengunduh kursus-kursus tersebut, memilih kategori frasa untuk dilatih, kemudian mulai dengan merekam suaranya sendiri ketika mengucapkan frasa dan membandingkan hasilnya dengan rekaman penutur asli dengan mendengarkan keduanya. Dengan menyesuaikan dan mengulangi pengucapannya sendiri, pelajar dapat meningkatkan keterampilannya.

Artikulate is en Utspraak-Lehrprogramm dat dor bi hölpen schall, de Utspraak vun en Schöler to verbetern. Dat höllt Lexen mit Opnahmen vun Moderspraaklers för en Reeg vun Spraken praat. De Schöler laadt de Lexen daal, söcht en Kategorie vun Utdrück ut, de he lehren will, nimmt sien egen Stimm op, wenn he de Utdrück weddergifft un vergliekt dat mit de Opnahmen vun de Moderspraaklers. So kann he sien egen Utspraak verbetern.

Artikulate is een trainingsprogramma voor uitspraak dat helpt om het uitspreken van een vreemde taal van een leerling te verbeteren en te perfectioneren. Het biedt lessen met opnamen van sprekers in de eigen taal voor training in verschillende talen. De leerling downloadt deze lessen, selecteert een categorie van te leren frasen, start daarna met het opnemen van haar/zijn eigen stem bij het uitspreken van de frasen en vergelijkt de resultaten met die van de opnamen van de spreker in de eigen taal door naar beiden te luisteren. Door de eigen uitspraak aan te passen en te herhalen, kan de leerling zijn/haar prestaties verbeteren.

Artikulate jest programem do ćwiczenia wymowy, który pomaga ulepszać umiejętności wymowy uczącego się w obcym języku. Zapewnia lekcje z nagraniami rodowitego mówcy dla kilku języków. Uczący się pobiera te lekcje, wybiera kategorię wyrażeń do przećwiczenia, a następnie zaczyna nagrywać swój własny głos porównując przy tym swoje wyniki z głosem rodowitego mówcy, poprzez słuchanie obu. Poprzez dostrajanie i powtarzanie wymowy, uczący się może polepszyć własne umiejętności.

O Artikulate é um treinador de pronúncia que ajuda a melhorar e a aperfeiçoar os dotes de pronúncia de um aluno para uma dada língua estrangeira. Fornece exercícios com gravações de locutores nativos para diversas línguas de treino. O aluno pode transferir esses exercícios, escolher uma categoria de frases a treinar, começando depois a gravar a sua própria voz a falar as frases e a comparar os resultados com as gravações do locutor nativo, ouvindo-os a ambos. Ao ajustar e ao repetir a sua própria pronúncia, o aluno poderá melhorar as suas aptidões.

Artikulate é um treinador de pronúncia que ajuda a melhorar e aperfeiçoar as habilidades de pronúncia de um aluno para um idioma estrangeiro. Fornece exercícios com gravações de locutores nativos para diversos idiomas de treinamento. O aluno pode baixar esses exercícios, escolher uma categoria de frases para treinar, começando com a gravação da sua própria voz ao falar as frases e comparar os resultados com as gravações do locutor nativo, ouvindo-os a ambos. Ao ajustar e repetir a sua própria pronúncia, o aluno poderá melhorar as suas aptidões.

Artikulate — тренажёр произношения, который может помочь при тренировке произношения иностранных слов. В программе можно выбрать курсы с записью голосов носителей языка. После того, как выбранный курс будет загружен из Интернета, обучающийся может записать своё произношение фраз и сличить с записью голоса диктора. Повторяя за диктором и исправляя несоответствия, можно улучшить свой навык произношения фраз на иностранном языке.

Artikulate je tréner výslovnosti, ktorý pomôže zlepšiť výslovnosť študenta pre cudzí jazyk. Poskytuje kurzy s nahrávkami rodeného hovorcu pre niekoľko výukových jazykov. Študent si stiahne tieto kurzy, vyberie kategóriu a frázy na precvičenie, potom začne nahrávať svoj hlas pri hovorení fráz a porovná výsledky s rodeným hovorcom počúvaním oboch. Úpravou a opakovaním výslovnosti si môže študent zlepšiť schopnosti.

Artikulate je pomočnik za učenje izgovorjave, ki vam pomaga izboljšati in izpopolniti izgovorjavo tujega jezika. Ponuja tečaje s posnetki govorca maternega jezika za številne jezike. Učenec prejme tečaje, izbere kategorijo fraz, ki se bi jih rad naučil in nato začne s snemanjem svojega glasu med izgovorjavo fraz. Te posnetke primerja s posnetki govorca maternega jezika. S prilagajanjem in ponavljanjem izgovorjave, lahko učenec izboljša svoje sposobnosti.

Artikulate är ett uttalsövningsprogram som hjälper till att förbättra och fullkomna en elevs uttalsfärdighet på ett främmande språk. Det tillhandahåller kurser med inspelningar av infödda på ett flertal övningsspråk. Eleven laddar ner kurserna, väljer en kategori meningar att öva på, och börjar därefter med att spela in sin egen röst vid uppläsning av meningarna och jämför därefter resultatet med de inföddas inspelningar genom att lyssna på båda. Genom att justera och upprepa sitt eget uttal, kan eleven förbättra sina färdigheter.

Artikulate yabancı dil öğrenmeye çalışanların telaffuzlarını geliştirmelerine ve mükemmelleştirmelerine yardım eden bir telaffuz eğiticisidir. Birçok eğitim dili için doğal konuşma kayıtlarını içeren dersler sağlar. Öğrenci kursları indirir, çalışacağı kategoriyi seçer ve kendi seslendirdiği ifadeleri kaydederek o dili doğal dil olarak konuşanların kayıtlarıyla karşılaştırmaya başlar. Kendi telaffuzunu ayarlayarak ve tekrarlayarak, öğrenci becerilerini artırabilir.

Artikulate — програма для навчання вимові, яка допомагає у покращенні та удосконаленні навичок учня з вимови слів іноземною мовою. У програмі передбачено курси, записані людьми, для яких мова є рідною, створені декількома мовами. Учень може отримати такий курс, вибрати категорію фраз для навчання і розпочати записування власних спроб вимовити фразу та порівняння з еталонними записами. Коригуючи і повторюючи вимов, учень може покращити власні навички.

xxArtikulate is a pronunciation trainer that helps improving and perfecting a learner's pronunciation skills for a foreign language. It provides courses with native speaker recordings for several training languages. The learner downloads those courses, selects a category of phrases to train, then starts with recording her/his own voice when speaking the phrases and comparing the results to the native speaker's recordings by listening to both. By adjusting and repeating the own pronunciation, the learner can improve his/her skill.xx

Artikulate 可以協助改進學生學習的外國語發音。它提供以該語言為母語的人的發音錄音課程。學生只要下載這些課程,選擇要練習的類別或片語,然後開始錄自己的發音,並跟母語發音做比較。只要不斷重複並調整自己的發音,就可以進步。

http://edu.kde.org/artikulate/ https://bugs.kde.org/enter_bug.cgi?format=guided&product=artikulate http://docs.kde.org/stable/en/kdeedu/artikulate/index.html https://www.kde.org/community/donations/?app=artikulate&source=appdata Training in Artikulate Entrenament a l'Artikulate Entrenament a l'Artikulate Übung in Artikulate Training in Artikulate Entrenando en Artikulate + Séance d'entraînement sur Artikulate Adestrando en Artikulate Berlatih di Artikulate Oefening in Artikulate Ćwiczenie w Artikulate Exercício no Artikulate Treinando no Artikulate Övning i Artikulate Вправляння в Artikulate xxTraining in Artikulatexx 使用 Artikulate 训练 在 Artikulate 中訓練 - http://edu.kde.org/images/screenshots/resized/artikulate.png + https://cdn.kde.org/screenshots/artikulate/artikulate.png KDE artikulate
diff --git a/src/core/editorsession.h b/src/core/editorsession.h index 7e2b72f..f6b7cc2 100644 --- a/src/core/editorsession.h +++ b/src/core/editorsession.h @@ -1,132 +1,131 @@ /* * 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 EDITORSESSION_H #define EDITORSESSION_H #include "artikulatecore_export.h" #include "phrase.h" -class QString; class Language; class IEditableCourse; class Unit; class SkeletonResource; class IEditableRepository; /** * \class EditorSession * * An object of this class is used to set the current state of the editor. By this, we put all logic * how language, skeleton and course fit to each other into this class. The main concept is that * we have to fundamentally different workflows that both are modeled in this class: * * 1. Skeleton based workflow * - a skeleton is selected * - every language is available, since eventually the course should be available in every language * - for every language, there is at most one course (there is none only in case it is not created yet) * - adding new units or phrases is only possible in the skeleton course * - every course can update/sync with the skeleton * * 2. Course based workflow * - there is no skeleton from which the course is derived * - the base is a language that is selected first * - for a language there can be none to arbitrarily many courses * * The main switch is \c EditorSession::setSkeletonMode(bool) */ class ARTIKULATECORE_EXPORT EditorSession : public QObject { Q_OBJECT Q_PROPERTY(bool skeletonMode READ skeletonMode NOTIFY skeletonModeChanged) Q_PROPERTY(bool editSkeleton READ isEditSkeleton WRITE setEditSkeleton NOTIFY editSkeletonChanged) Q_PROPERTY(IEditableCourse *skeleton READ skeleton WRITE setSkeleton NOTIFY skeletonChanged) Q_PROPERTY(IEditableCourse *course READ course WRITE setCourse NOTIFY courseChanged) // editor elements depending on curently selected mode, skeleton and course /** * @brief the displayed course (skeleton or course) depending on the user selection */ Q_PROPERTY(IEditableCourse *displayedCourse READ displayedCourse NOTIFY displayedCourseChanged) Q_PROPERTY(Language *language READ language NOTIFY languageChanged) Q_PROPERTY(Unit *unit READ unit WRITE setUnit NOTIFY unitChanged) Q_PROPERTY(Phrase *phrase READ phrase WRITE setPhrase NOTIFY phraseChanged) Q_PROPERTY(bool hasNextPhrase READ hasNextPhrase NOTIFY phraseChanged) Q_PROPERTY(bool hasPreviousPhrase READ hasPreviousPhrase NOTIFY phraseChanged) public: explicit EditorSession(QObject *parent = nullptr); void setRepository(IEditableRepository *repository); bool skeletonMode() const; void setEditSkeleton(bool enabled=true); bool isEditSkeleton() const; IEditableCourse * skeleton() const; void setSkeleton(IEditableCourse *skeleton); Language * language() const; IEditableCourse * course() const; void setCourse(IEditableCourse *course); /** * @brief Open course resource by specifying the language * @param language the target language */ Q_INVOKABLE void setCourseByLanguage(Language *language); IEditableCourse * displayedCourse() const; Unit * unit() const; void setUnit(Unit *unit); Phrase * phrase() const; void setPhrase(Phrase *phrase); Phrase::Type phraseType() const; void setPhraseType(Phrase::Type type); bool hasPreviousPhrase() const; bool hasNextPhrase() const; Q_INVOKABLE void switchToPreviousPhrase(); Q_INVOKABLE void switchToNextPhrase(); Q_INVOKABLE void updateCourseFromSkeleton(); private Q_SLOTS: void updateDisplayedUnit(); private: Phrase * nextPhrase() const; Phrase * previousPhrase() const; Q_SIGNALS: void editSkeletonChanged(); void skeletonModeChanged(); void skeletonChanged(); void languageChanged(); void courseChanged(); void displayedCourseChanged(); void unitChanged(); void phraseChanged(); private: Q_DISABLE_COPY(EditorSession) IEditableRepository * m_repository{ nullptr }; bool m_editSkeleton{ false }; IEditableCourse *m_skeleton{ nullptr }; Language *m_language{ nullptr }; IEditableCourse *m_course{ nullptr }; Unit *m_unit{ nullptr }; Phrase *m_phrase{ nullptr }; }; #endif diff --git a/src/core/trainingsession.h b/src/core/trainingsession.h index 9f3450a..e457be4 100644 --- a/src/core/trainingsession.h +++ b/src/core/trainingsession.h @@ -1,95 +1,94 @@ /* * 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 TRAININGSESSION_H #define TRAININGSESSION_H #include "artikulatecore_export.h" #include "phrase.h" #include -class QString; class Language; class ICourse; class Unit; class TrainingAction; namespace LearnerProfile { class ProfileManager; } /** * \class TrainingSession */ class ARTIKULATECORE_EXPORT TrainingSession : public QObject { Q_OBJECT Q_PROPERTY(ICourse *course READ course WRITE setCourse NOTIFY courseChanged) Q_PROPERTY(Unit *unit READ activeUnit WRITE setUnit NOTIFY phraseChanged) Q_PROPERTY(Phrase *phrase READ activePhrase WRITE setPhrase NOTIFY phraseChanged) Q_PROPERTY(bool hasNext READ hasNext NOTIFY phraseChanged) public: explicit TrainingSession(LearnerProfile::ProfileManager *manager, QObject *parent = nullptr); ICourse * course() const; void setCourse(ICourse *course); Unit * activeUnit() const; void setUnit(Unit *unit); TrainingAction * activeAction() const; Phrase * activePhrase() const; void setPhrase(Phrase *phrase); bool hasPrevious() const; bool hasNext() const; Q_INVOKABLE void accept(); Q_INVOKABLE void skip(); /** * @brief Return tree of training actions * * The return actions form a 2-level hierarchy: * - the first level are all units * - the unit actions may contain sub-actions, which are the phrases * * @note phrases without sound file paths are skipped when generating actions */ QVector trainingActions() const; Q_SIGNALS: void courseChanged(); void phraseChanged(); /** * @brief Emitted when last phrase of session is skipped or marked as completed. */ void completed(); private: Q_DISABLE_COPY(TrainingSession) void updateTrainingActions(); void selectNextPhrase(); void updateGoal(); LearnerProfile::ProfileManager *m_profileManager; ICourse *m_course; QVector m_actions; int m_indexUnit{-1}; int m_indexPhrase{-1}; }; #endif diff --git a/src/mainwindow_editor.h b/src/mainwindow_editor.h index 1a68186..0f16c5f 100644 --- a/src/mainwindow_editor.h +++ b/src/mainwindow_editor.h @@ -1,72 +1,70 @@ /* * Copyright 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 MAINWINDOW_EDITOR_H #define MAINWINDOW_EDITOR_H #include #include #include "core/contributorrepository.h" #include "core/trainingsession.h" class EditorSession; -class KActionCollection; -class KMenu; class QQuickWidget; class MainWindowEditor : public KXmlGuiWindow { Q_OBJECT public: /** * Default Constructor */ MainWindowEditor(ContributorRepository *repository); /** * Default Destructor */ virtual ~MainWindowEditor(); ContributorRepository * resourceRepository() const; void setupActions(); QSize sizeHint() const override { return QSize(1000, 700); } bool queryClose() override; public Q_SLOTS: void showSettingsDialog(); void save(); void quit(); Q_SIGNALS: void modeChanged(bool); private: ContributorRepository *m_repository; EditorSession *m_editorSession; QQuickWidget *m_widget; }; #endif diff --git a/src/models/coursefiltermodel.h b/src/models/coursefiltermodel.h index 8ec7502..4202e2f 100644 --- a/src/models/coursefiltermodel.h +++ b/src/models/coursefiltermodel.h @@ -1,65 +1,64 @@ /* * Copyright 2014-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 COURSEFILTERMODEL_H #define COURSEFILTERMODEL_H #include class Course; class CourseModel; -class QSignalMapper; class CourseFilterModel : public QSortFilterProxyModel { Q_OBJECT Q_PROPERTY(CourseModel *courseModel READ courseModel WRITE setCourseModel NOTIFY courseModelChanged) Q_PROPERTY(CourseResourceView view READ view WRITE setView NOTIFY viewChanged) Q_PROPERTY(int filteredCount READ filteredCount NOTIFY filteredCountChanged) public: Q_ENUMS(CourseResourceView); enum CourseResourceView { OnlyGetHotNewStuffResources = 1, OnlyContributorResources = 2, AllResources = 3 }; explicit CourseFilterModel(QObject *parent = nullptr); CourseModel * courseModel() const; void setCourseModel(CourseModel* courseModel); int filteredCount() const; virtual bool lessThan(const QModelIndex &left, const QModelIndex &right) const override; virtual bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override; void setView(CourseResourceView view); CourseResourceView view() const; Q_INVOKABLE QVariant course(int row) const; Q_SIGNALS: void courseModelChanged(); void viewChanged(); void sortOptionChanged(); void filteredCountChanged(); private: CourseModel *m_courseModel; CourseResourceView m_view; }; #endif diff --git a/src/models/languagemodel.h b/src/models/languagemodel.h index 6b2c13f..57ed4f9 100644 --- a/src/models/languagemodel.h +++ b/src/models/languagemodel.h @@ -1,62 +1,61 @@ /* * 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 LANGUAGEMODEL_H #define LANGUAGEMODEL_H #include class LanguageResourceModel; class Language; -class QSignalMapper; class LanguageModel : public QSortFilterProxyModel { Q_OBJECT Q_PROPERTY(LanguageResourceModel *resourceModel READ resourceModel WRITE setResourceModel NOTIFY resourceModelChanged) Q_PROPERTY(LanguageResourceView view READ view WRITE setView NOTIFY viewChanged) public: enum LanguageResourceView { NonEmptyContributorOnlyResources, NonEmptyGhnsOnlyLanguages, NonEmptyLanguages, AllLanguages }; Q_ENUM(LanguageResourceView) explicit LanguageModel(QObject *parent = nullptr); LanguageResourceModel * resourceModel() const; void setResourceModel(LanguageResourceModel *resourceModel); bool lessThan(const QModelIndex &left, const QModelIndex &right) const override; void setView(LanguageResourceView view); LanguageResourceView view() const; Q_INVOKABLE QVariant language(int index) const; Q_SIGNALS: void resourceModelChanged(); void viewChanged(); private: LanguageResourceModel *m_resourceModel; LanguageResourceView m_view; }; #endif diff --git a/src/models/phrasefiltermodel.h b/src/models/phrasefiltermodel.h index df73d46..e1eedca 100644 --- a/src/models/phrasefiltermodel.h +++ b/src/models/phrasefiltermodel.h @@ -1,72 +1,71 @@ /* * Copyright 2013-2015 Andreas Cord-Landwehr * Copyright 2013 Samikshan Bairagya * * 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 PHRASEFILTERMODEL_H #define PHRASEFILTERMODEL_H #include class PhraseListModel; -class QSignalMapper; class PhraseFilterModel : public QSortFilterProxyModel { Q_OBJECT Q_PROPERTY(PhraseListModel *phraseModel READ phraseModel WRITE setPhraseModel NOTIFY phraseModelChanged) Q_PROPERTY(bool hideExcluded READ isHideExcluded WRITE setHideExcluded NOTIFY hideExcludedChanged) Q_PROPERTY(bool hideNotRecorded READ isHideNotRecorded WRITE setHideNotRecorded NOTIFY hideNotRecordedChanged) Q_PROPERTY(SortOption sortOption READ sortOption WRITE setSortOption NOTIFY sortOptionChanged) Q_PROPERTY(int filteredCount READ filteredCount NOTIFY filteredCountChanged) public: Q_ENUMS(SortOption) enum SortOption { Id, Type }; explicit PhraseFilterModel(QObject *parent = nullptr); PhraseListModel * phraseModel() const; void setPhraseModel(PhraseListModel* phraseModel); void setSortOption(SortOption option = Id); SortOption sortOption() const; int filteredCount() const; virtual bool lessThan(const QModelIndex &left, const QModelIndex &right) const override; virtual bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override; void setHideExcluded(bool hide=true); bool isHideExcluded() const; void setHideNotRecorded(bool hide=true); bool isHideNotRecorded() const; Q_SIGNALS: void phraseModelChanged(); void hideExcludedChanged(); void hideNotRecordedChanged(); void sortOptionChanged(); void filteredCountChanged(); private: PhraseListModel *m_phraseModel; bool m_hideExcluded; bool m_hideNotRecorded; SortOption m_sortOption; }; #endif diff --git a/src/models/skeletonmodel.h b/src/models/skeletonmodel.h index b96fb29..bd103de 100644 --- a/src/models/skeletonmodel.h +++ b/src/models/skeletonmodel.h @@ -1,77 +1,76 @@ /* * 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 IEditableRepository; class ICourse; class Skeleton; -class Language; class QSignalMapper; class SkeletonModel : public QAbstractListModel { Q_OBJECT 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(IEditableRepository *repository); /** * Reimplemented from QAbstractListModel::roleNames() */ virtual QHash roleNames() const override; 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(); IEditableRepository *m_repository; QSignalMapper *m_signalMapper; }; #endif // SKELETONMODEL_H diff --git a/src/models/unitfiltermodel.h b/src/models/unitfiltermodel.h index 86dc75f..7142640 100644 --- a/src/models/unitfiltermodel.h +++ b/src/models/unitfiltermodel.h @@ -1,53 +1,52 @@ /* * Copyright 2014-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 UNITFILTERMODEL_H #define UNITFILTERMODEL_H #include class UnitModel; -class QSignalMapper; class UnitFilterModel : public QSortFilterProxyModel { Q_OBJECT Q_PROPERTY(UnitModel *unitModel READ unitModel WRITE setUnitModel NOTIFY unitModelChanged) Q_PROPERTY(int filteredCount READ filteredCount NOTIFY filteredCountChanged) public: explicit UnitFilterModel(QObject *parent = nullptr); UnitModel * unitModel() const; void setUnitModel(UnitModel* unitModel); int filteredCount() const; virtual bool lessThan(const QModelIndex &left, const QModelIndex &right) const override; virtual bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override; Q_SIGNALS: void unitModelChanged(); void viewChanged(); void sortOptionChanged(); void filteredCountChanged(); private: UnitModel *m_unitModel; }; #endif diff --git a/src/qmlcontrols/iconitem.cpp b/src/qmlcontrols/iconitem.cpp index 46fb916..739db1e 100644 --- a/src/qmlcontrols/iconitem.cpp +++ b/src/qmlcontrols/iconitem.cpp @@ -1,168 +1,168 @@ /* * Copyright 2011 Marco Martin * Copyright 2014 Aleix Pol Gonzalez * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * 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 Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "iconitem.h" #include -#include +#include #include #include "imagetexturescache.h" #include "managedtexturenode.h" Q_GLOBAL_STATIC(ImageTexturesCache, s_iconImageCache) IconItem::IconItem(QQuickItem *parent) : QQuickItem(parent), m_smooth(false), m_state(DefaultState), m_changed(false) { setFlag(ItemHasContents, true); } IconItem::~IconItem() { } void IconItem::setIcon(const QVariant &icon) { if(icon.canConvert()) { m_icon = icon.value(); } else if(icon.canConvert()) { m_icon = QIcon::fromTheme(icon.toString()); } else { m_icon = QIcon(); } m_changed = true; update(); } QIcon IconItem::icon() const { return m_icon; } IconItem::State IconItem::state() const { return m_state; } void IconItem::setState(IconItem::State state) { if (m_state == state) { return; } m_state = state; m_changed = true; emit stateChanged(state); update(); } bool IconItem::enabled() const { return (m_state == DefaultState); } void IconItem::setEnabled(bool enabled) { if (enabled) { setState(DefaultState); } else { setState(DisabledState); } } int IconItem::implicitWidth() const { return 32; } int IconItem::implicitHeight() const { return 32; } void IconItem::setSmooth(const bool smooth) { if (smooth == m_smooth) { return; } m_smooth = smooth; m_changed = true; update(); } bool IconItem::smooth() const { return m_smooth; } QSGNode* IconItem::updatePaintNode(QSGNode* node, QQuickItem::UpdatePaintNodeData* /*data*/) { if (m_icon.isNull()) { delete node; return nullptr; } if (m_changed || node == nullptr) { m_changed = false; ManagedTextureNode* mNode = dynamic_cast(node); if(!mNode) { delete node; mNode = new ManagedTextureNode; } QIcon::Mode mode; switch(m_state) { case DefaultState: mode = QIcon::Normal; break; case ActiveState: mode = QIcon::Active; break; case DisabledState: mode = QIcon::Disabled; break; } QImage img; const QSize size(static_cast(width()), static_cast(height())); if (!size.isEmpty()) { img = m_icon.pixmap(size, mode, QIcon::On).toImage(); } mNode->setTexture(s_iconImageCache->loadTexture(window(), img)); mNode->setRect(QRect(QPoint(0,0), size)); node = mNode; } return node; } void IconItem::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) { if (newGeometry.size() != oldGeometry.size()) { m_changed = true; update(); } QQuickItem::geometryChanged(newGeometry, oldGeometry); } diff --git a/src/ui/sounddevicedialogpage.h b/src/ui/sounddevicedialogpage.h index 7a52714..e2f86bb 100644 --- a/src/ui/sounddevicedialogpage.h +++ b/src/ui/sounddevicedialogpage.h @@ -1,57 +1,56 @@ /* * 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 . */ #ifndef SOUNDDEVICEDIALOGPAGE_H #define SOUNDDEVICEDIALOGPAGE_H #include "ui_sounddevicedialogpage.h" #include #include -class QMediaPlayer; class SoundDeviceDialogPage : public QWidget { Q_OBJECT public: SoundDeviceDialogPage(); ~SoundDeviceDialogPage(); public slots: void saveSettings(); void loadSettings(); void playTestSound(); void playRecordedSound(); void recordSound(); void updatePlayButtonIcons(); void stopPlaying(); void stopRecord(); void setVolume(int volume); private: Ui::SoundDeviceDialogPage *ui; QList m_audioInputs; QList m_audioOutputs; QTemporaryFile m_recordTestFile; }; #endif