From 3bd74d1ca65ef44c0230d81fda87d1875ea54b71 Mon Sep 17 00:00:00 2001 From: Chris Cochrun Date: Thu, 10 Feb 2022 08:44:51 -0600 Subject: [PATCH] Laying out main page and adding songlistmodel --- CMakeLists.txt.user | 420 ++++---------------------- build/CMakeCache.txt | 4 +- build/CMakeFiles/Makefile.cmake | 17 +- build/CMakeFiles/Makefile2 | 6 +- build/CMakeFiles/progress.marks | 2 +- build/src/CMakeFiles/progress.marks | 2 +- build/src/Makefile | 27 ++ src/CMakeLists.txt | 1 + src/main.cpp | 8 +- src/qml/main.qml | 11 +- src/qml/presenter/Actions.qml | 12 + src/qml/presenter/Header.qml | 54 ++++ src/qml/presenter/LeftDock.qml | 74 +++-- src/qml/presenter/Library.qml | 47 +++ src/qml/presenter/LibraryDelegate.qml | 11 + src/qml/presenter/LibraryModel.qml | 76 +++++ src/qml/presenter/MainWindow.qml | 69 ++--- src/qml/presenter/PanelItem.qml | 70 +++++ src/qml/presenter/Slide.qml | 164 ++++++++++ src/resources.qrc | 6 + src/serviceitem.cpp | 57 ++++ src/serviceitem.h | 33 ++ src/songlistmodel.cpp | 55 ++++ src/songlistmodel.h | 44 +++ 24 files changed, 816 insertions(+), 454 deletions(-) create mode 100644 src/qml/presenter/Actions.qml create mode 100644 src/qml/presenter/Header.qml create mode 100644 src/qml/presenter/Library.qml create mode 100644 src/qml/presenter/LibraryDelegate.qml create mode 100644 src/qml/presenter/LibraryModel.qml create mode 100644 src/qml/presenter/PanelItem.qml create mode 100644 src/qml/presenter/Slide.qml create mode 100644 src/serviceitem.cpp create mode 100644 src/serviceitem.h create mode 100644 src/songlistmodel.cpp create mode 100644 src/songlistmodel.h diff --git a/CMakeLists.txt.user b/CMakeLists.txt.user index 1e8d64e..4497f57 100644 --- a/CMakeLists.txt.user +++ b/CMakeLists.txt.user @@ -1,14 +1,14 @@ - + EnvironmentId - {96b0233c-0ac3-4a64-9b08-eb9c58898997} + {d6595ca1-5c4f-4487-b405-470a7201d856} ProjectExplorer.Project.ActiveTarget - 0 + 0 ProjectExplorer.Project.EditorSettings @@ -28,7 +28,7 @@ QmlJSGlobal - 2 + 2 UTF-8 false 4 @@ -37,6 +37,7 @@ true true 1 + false true false 0 @@ -45,438 +46,139 @@ 0 8 true + false 1 true true true + *.md, *.MD, Makefile false + true ProjectExplorer.Project.PluginSettings + + true + false + true + true + true + true + + + 0 + true true + Builtin.BuildSystem + + true + true + Builtin.DefaultTidyAndClazy + 4 + + + + true + ProjectExplorer.Project.Target.0 - Felgo Desktop (Qt 5.15.2 GCC) - Felgo Desktop (Qt 5.15.2 GCC) - vplayengine.2.qt.gcc_64_kit - 0 - 0 - 0 + Desktop + Qt 5.15.2 in PATH (System) + Qt 5.15.2 in PATH (System) + {055b3c2c-94ff-418e-b088-9847da1e7c71} + 0 + 0 + 0 - - CMAKE_BUILD_TYPE:STRING=Debug - CMAKE_CXX_COMPILER:STRING=%{Compiler:Executable:Cxx} - CMAKE_C_COMPILER:STRING=%{Compiler:Executable:C} - CMAKE_PREFIX_PATH:STRING=%{Qt:QT_INSTALL_PREFIX} - QT_QMAKE_EXECUTABLE:STRING=%{Qt:qmakeExecutable} - - /home/chris/dev/build-church-presenter-Felgo_Desktop_Qt_5_15_2_GCC-Debug - - - - - all - - true - CMakeProjectManager.MakeStep - - 1 - Build - Build - ProjectExplorer.BuildSteps.Build - - - - - - clean - - true - CMakeProjectManager.MakeStep - - 1 - Clean - Clean - ProjectExplorer.BuildSteps.Clean - - 2 - false - - Debug - CMakeProjectManager.CMakeBuildConfiguration - - - - CMAKE_BUILD_TYPE:STRING=Release - CMAKE_CXX_COMPILER:STRING=%{Compiler:Executable:Cxx} - CMAKE_C_COMPILER:STRING=%{Compiler:Executable:C} - CMAKE_PREFIX_PATH:STRING=%{Qt:QT_INSTALL_PREFIX} - QT_QMAKE_EXECUTABLE:STRING=%{Qt:qmakeExecutable} - - /home/chris/dev/build-church-presenter-Felgo_Desktop_Qt_5_15_2_GCC-Release - - - - - all - - true - CMakeProjectManager.MakeStep - - 1 - Build - Build - ProjectExplorer.BuildSteps.Build - - - - - - clean - - true - CMakeProjectManager.MakeStep - - 1 - Clean - Clean - ProjectExplorer.BuildSteps.Clean - - 2 - false - - Release - CMakeProjectManager.CMakeBuildConfiguration - - - - CMAKE_BUILD_TYPE:STRING=RelWithDebInfo - CMAKE_CXX_COMPILER:STRING=%{Compiler:Executable:Cxx} - CMAKE_C_COMPILER:STRING=%{Compiler:Executable:C} - CMAKE_PREFIX_PATH:STRING=%{Qt:QT_INSTALL_PREFIX} - QT_QMAKE_EXECUTABLE:STRING=%{Qt:qmakeExecutable} - - /home/chris/dev/build-church-presenter-Felgo_Desktop_Qt_5_15_2_GCC-RelWithDebInfo - - - - - all - - true - CMakeProjectManager.MakeStep - - 1 - Build - Build - ProjectExplorer.BuildSteps.Build - - - - - - clean - - true - CMakeProjectManager.MakeStep - - 1 - Clean - Clean - ProjectExplorer.BuildSteps.Clean - - 2 - false - - Release with Debug Information - CMakeProjectManager.CMakeBuildConfiguration - - - - CMAKE_BUILD_TYPE:STRING=MinSizeRel - CMAKE_CXX_COMPILER:STRING=%{Compiler:Executable:Cxx} - CMAKE_C_COMPILER:STRING=%{Compiler:Executable:C} - CMAKE_PREFIX_PATH:STRING=%{Qt:QT_INSTALL_PREFIX} - QT_QMAKE_EXECUTABLE:STRING=%{Qt:qmakeExecutable} - - /home/chris/dev/build-church-presenter-Felgo_Desktop_Qt_5_15_2_GCC-MinSizeRel - - - - - all - - true - CMakeProjectManager.MakeStep - - 1 - Build - Build - ProjectExplorer.BuildSteps.Build - - - - - - clean - - true - CMakeProjectManager.MakeStep - - 1 - Clean - Clean - ProjectExplorer.BuildSteps.Clean - - 2 - false - - Minimum Size Release - CMakeProjectManager.CMakeBuildConfiguration - - 4 - - - 0 - Deploy - Deploy - ProjectExplorer.BuildSteps.Deploy - - 1 - ProjectExplorer.DefaultDeployConfiguration - - 1 - - - dwarf - - cpu-cycles - - - 250 - - -e - cpu-cycles - --call-graph - dwarf,4096 - -F - 250 - - -F - true - 4096 - false - false - 1000 - - true - - false - false - false - false - true - 0.01 - 10 - true - kcachegrind - 1 - 25 - - 1 - true - false - true - valgrind - - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10 - 11 - 12 - 13 - 14 - - 2 - - presenter - CMakeProjectManager.CMakeRunConfiguration.presenter - presenter - - false - - false - true - true - false - false - true - - /tmp/QtCreator-gODvDS/qtc-cmake-kvNxkPei/bin - - 1 - - - - ProjectExplorer.Project.Target.1 - - Unnamed - Unnamed - {c5efa8e0-6c0b-48cb-bf1d-8d48448dab74} - 0 - 0 - 0 - - - CMAKE_BUILD_TYPE:STRING=Debug - CMAKE_CXX_COMPILER:FILEPATH=/usr/bin/c++ - CMAKE_C_COMPILER:FILEPATH=/usr/bin/cc - CMAKE_PREFIX_PATH:STRING=%{Qt:QT_INSTALL_PREFIX} - QT_QMAKE_EXECUTABLE:STRING=%{Qt:qmakeExecutable} - + Debug + -GUnix Makefiles +-DCMAKE_BUILD_TYPE:STRING=Debug +-DCMAKE_PROJECT_INCLUDE_BEFORE:PATH=%{IDE:ResourcePath}/package-manager/auto-setup.cmake +-DQT_QMAKE_EXECUTABLE:STRING=%{Qt:qmakeExecutable} +-DCMAKE_PREFIX_PATH:STRING=%{Qt:QT_INSTALL_PREFIX} +-DCMAKE_C_COMPILER:STRING=%{Compiler:Executable:C} +-DCMAKE_CXX_COMPILER:STRING=%{Compiler:Executable:Cxx} + /home/chris/dev/church-presenter /home/chris/dev/church-presenter/build - all true + Build CMakeProjectManager.MakeStep - 1 + 1 Build Build ProjectExplorer.BuildSteps.Build - clean true + Build CMakeProjectManager.MakeStep - 1 + 1 Clean Clean ProjectExplorer.BuildSteps.Clean 2 false + + false Debug CMakeProjectManager.CMakeBuildConfiguration - 1 + 1 - 0 + 0 Deploy Deploy ProjectExplorer.BuildSteps.Deploy 1 + + false ProjectExplorer.DefaultDeployConfiguration - 1 - + 1 - dwarf - - cpu-cycles - - - 250 - - -e - cpu-cycles - --call-graph - dwarf,4096 - -F - 250 - - -F true - 4096 - false - false - 1000 - true - - false - false - false - false - true - 0.01 - 10 - true - kcachegrind - 1 - 25 - - 1 true - false - true - valgrind - - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10 - 11 - 12 - 13 - 14 - + 2 presenter CMakeProjectManager.CMakeRunConfiguration.presenter presenter - - false - false true true - false false true - - + /home/chris/dev/church-presenter/build/bin - 1 + 1 ProjectExplorer.Project.TargetCount - 2 + 1 ProjectExplorer.Project.Updater.FileVersion diff --git a/build/CMakeCache.txt b/build/CMakeCache.txt index 98c6816..9cc341d 100644 --- a/build/CMakeCache.txt +++ b/build/CMakeCache.txt @@ -615,11 +615,11 @@ CMAKE_VERBOSE_MAKEFILE-ADVANCED:INTERNAL=1 //Details about finding Gettext FIND_PACKAGE_MESSAGE_DETAILS_Gettext:INTERNAL=[/usr/bin/msgmerge][/usr/bin/msgfmt][v0.21()] //Details about finding KF5 -FIND_PACKAGE_MESSAGE_DETAILS_KF5:INTERNAL=[success][cfound components: Kirigami2 I18n CoreAddons ][v5.90.0(5.68.0)] +FIND_PACKAGE_MESSAGE_DETAILS_KF5:INTERNAL=[success][cfound components: Kirigami2 I18n CoreAddons ][v5.87.0(5.68.0)] //Details about finding KF5CoreAddons FIND_PACKAGE_MESSAGE_DETAILS_KF5CoreAddons:INTERNAL=[/usr/lib64/cmake/KF5CoreAddons/KF5CoreAddonsConfig.cmake][v5.90.0()] //Details about finding KF5I18n -FIND_PACKAGE_MESSAGE_DETAILS_KF5I18n:INTERNAL=[/usr/lib64/cmake/KF5I18n/KF5I18nConfig.cmake][v5.90.0()] +FIND_PACKAGE_MESSAGE_DETAILS_KF5I18n:INTERNAL=[/usr/lib64/cmake/KF5I18n/KF5I18nConfig.cmake][v5.87.0()] //Details about finding KF5Kirigami2 FIND_PACKAGE_MESSAGE_DETAILS_KF5Kirigami2:INTERNAL=[/usr/lib64/cmake/KF5Kirigami2/KF5Kirigami2Config.cmake][v5.90.0()] //Test HAVE_DATE_TIME diff --git a/build/CMakeFiles/Makefile.cmake b/build/CMakeFiles/Makefile.cmake index 2ff999d..cac60cb 100644 --- a/build/CMakeFiles/Makefile.cmake +++ b/build/CMakeFiles/Makefile.cmake @@ -25,7 +25,7 @@ set(CMAKE_MAKEFILE_DEPENDS "/usr/lib64/cmake/KF5I18n/KF5I18nConfigVersion.cmake" "/usr/lib64/cmake/KF5I18n/KF5I18nMacros.cmake" "/usr/lib64/cmake/KF5I18n/KF5I18nQchTargets.cmake" - "/usr/lib64/cmake/KF5I18n/KF5I18nTargets-noconfig.cmake" + "/usr/lib64/cmake/KF5I18n/KF5I18nTargets-debug.cmake" "/usr/lib64/cmake/KF5I18n/KF5I18nTargets.cmake" "/usr/lib64/cmake/KF5Kirigami2/KF5Kirigami2Config.cmake" "/usr/lib64/cmake/KF5Kirigami2/KF5Kirigami2ConfigVersion.cmake" @@ -54,35 +54,25 @@ set(CMAKE_MAKEFILE_DEPENDS "/usr/lib64/cmake/Qt5Gui/Qt5Gui_QEvdevTabletPlugin.cmake" "/usr/lib64/cmake/Qt5Gui/Qt5Gui_QEvdevTouchScreenPlugin.cmake" "/usr/lib64/cmake/Qt5Gui/Qt5Gui_QGifPlugin.cmake" - "/usr/lib64/cmake/Qt5Gui/Qt5Gui_QGtk2ThemePlugin.cmake" "/usr/lib64/cmake/Qt5Gui/Qt5Gui_QGtk3ThemePlugin.cmake" - "/usr/lib64/cmake/Qt5Gui/Qt5Gui_QICNSPlugin.cmake" "/usr/lib64/cmake/Qt5Gui/Qt5Gui_QICOPlugin.cmake" "/usr/lib64/cmake/Qt5Gui/Qt5Gui_QIbusPlatformInputContextPlugin.cmake" - "/usr/lib64/cmake/Qt5Gui/Qt5Gui_QJp2Plugin.cmake" "/usr/lib64/cmake/Qt5Gui/Qt5Gui_QJpegPlugin.cmake" "/usr/lib64/cmake/Qt5Gui/Qt5Gui_QLibInputPlugin.cmake" "/usr/lib64/cmake/Qt5Gui/Qt5Gui_QLinuxFbIntegrationPlugin.cmake" "/usr/lib64/cmake/Qt5Gui/Qt5Gui_QMinimalEglIntegrationPlugin.cmake" "/usr/lib64/cmake/Qt5Gui/Qt5Gui_QMinimalIntegrationPlugin.cmake" - "/usr/lib64/cmake/Qt5Gui/Qt5Gui_QMngPlugin.cmake" "/usr/lib64/cmake/Qt5Gui/Qt5Gui_QOffscreenIntegrationPlugin.cmake" "/usr/lib64/cmake/Qt5Gui/Qt5Gui_QPdfPlugin.cmake" "/usr/lib64/cmake/Qt5Gui/Qt5Gui_QSvgIconPlugin.cmake" "/usr/lib64/cmake/Qt5Gui/Qt5Gui_QSvgPlugin.cmake" - "/usr/lib64/cmake/Qt5Gui/Qt5Gui_QTgaPlugin.cmake" - "/usr/lib64/cmake/Qt5Gui/Qt5Gui_QTiffPlugin.cmake" "/usr/lib64/cmake/Qt5Gui/Qt5Gui_QTsLibPlugin.cmake" "/usr/lib64/cmake/Qt5Gui/Qt5Gui_QTuioTouchPlugin.cmake" - "/usr/lib64/cmake/Qt5Gui/Qt5Gui_QVirtualKeyboardPlugin.cmake" "/usr/lib64/cmake/Qt5Gui/Qt5Gui_QVncIntegrationPlugin.cmake" "/usr/lib64/cmake/Qt5Gui/Qt5Gui_QWaylandEglPlatformIntegrationPlugin.cmake" "/usr/lib64/cmake/Qt5Gui/Qt5Gui_QWaylandIntegrationPlugin.cmake" "/usr/lib64/cmake/Qt5Gui/Qt5Gui_QWaylandXCompositeEglPlatformIntegrationPlugin.cmake" "/usr/lib64/cmake/Qt5Gui/Qt5Gui_QWaylandXCompositeGlxPlatformIntegrationPlugin.cmake" - "/usr/lib64/cmake/Qt5Gui/Qt5Gui_QWbmpPlugin.cmake" - "/usr/lib64/cmake/Qt5Gui/Qt5Gui_QWebGLIntegrationPlugin.cmake" - "/usr/lib64/cmake/Qt5Gui/Qt5Gui_QWebpPlugin.cmake" "/usr/lib64/cmake/Qt5Gui/Qt5Gui_QXcbEglIntegrationPlugin.cmake" "/usr/lib64/cmake/Qt5Gui/Qt5Gui_QXcbGlxIntegrationPlugin.cmake" "/usr/lib64/cmake/Qt5Gui/Qt5Gui_QXcbIntegrationPlugin.cmake" @@ -119,11 +109,6 @@ set(CMAKE_MAKEFILE_DEPENDS "/usr/lib64/cmake/Qt5Widgets/Qt5WidgetsConfigExtras.cmake" "/usr/lib64/cmake/Qt5Widgets/Qt5WidgetsConfigVersion.cmake" "/usr/lib64/cmake/Qt5Widgets/Qt5WidgetsMacros.cmake" - "/usr/lib64/cmake/Qt5Widgets/Qt5Widgets_QBB10StylePlugin.cmake" - "/usr/lib64/cmake/Qt5Widgets/Qt5Widgets_QCleanlooksStylePlugin.cmake" - "/usr/lib64/cmake/Qt5Widgets/Qt5Widgets_QGtk2StylePlugin.cmake" - "/usr/lib64/cmake/Qt5Widgets/Qt5Widgets_QMotifStylePlugin.cmake" - "/usr/lib64/cmake/Qt5Widgets/Qt5Widgets_QPlastiqueStylePlugin.cmake" "/usr/share/ECM/cmake/ECMConfig.cmake" "/usr/share/ECM/cmake/ECMConfigVersion.cmake" "/usr/share/ECM/find-modules/ECMFindModuleHelpersStub.cmake" diff --git a/build/CMakeFiles/Makefile2 b/build/CMakeFiles/Makefile2 index dbd3d31..c1a87f1 100644 --- a/build/CMakeFiles/Makefile2 +++ b/build/CMakeFiles/Makefile2 @@ -205,12 +205,12 @@ CMakeFiles/KF5CoreAddons_QCH.dir/clean: src/CMakeFiles/presenter.dir/all: src/CMakeFiles/presenter_autogen.dir/all $(MAKE) $(MAKESILENT) -f src/CMakeFiles/presenter.dir/build.make src/CMakeFiles/presenter.dir/depend $(MAKE) $(MAKESILENT) -f src/CMakeFiles/presenter.dir/build.make src/CMakeFiles/presenter.dir/build - @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --progress-dir=/home/chris/dev/church-presenter/build/CMakeFiles --progress-num=3,4,5,6,7 "Built target presenter" + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --progress-dir=/home/chris/dev/church-presenter/build/CMakeFiles --progress-num=3,4,5,6,7,8 "Built target presenter" .PHONY : src/CMakeFiles/presenter.dir/all # Build rule for subdir invocation for target. src/CMakeFiles/presenter.dir/rule: cmake_check_build_system - $(CMAKE_COMMAND) -E cmake_progress_start /home/chris/dev/church-presenter/build/CMakeFiles 6 + $(CMAKE_COMMAND) -E cmake_progress_start /home/chris/dev/church-presenter/build/CMakeFiles 7 $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 src/CMakeFiles/presenter.dir/all $(CMAKE_COMMAND) -E cmake_progress_start /home/chris/dev/church-presenter/build/CMakeFiles 0 .PHONY : src/CMakeFiles/presenter.dir/rule @@ -231,7 +231,7 @@ src/CMakeFiles/presenter.dir/clean: src/CMakeFiles/presenter_autogen.dir/all: $(MAKE) $(MAKESILENT) -f src/CMakeFiles/presenter_autogen.dir/build.make src/CMakeFiles/presenter_autogen.dir/depend $(MAKE) $(MAKESILENT) -f src/CMakeFiles/presenter_autogen.dir/build.make src/CMakeFiles/presenter_autogen.dir/build - @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --progress-dir=/home/chris/dev/church-presenter/build/CMakeFiles --progress-num=8 "Built target presenter_autogen" + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --progress-dir=/home/chris/dev/church-presenter/build/CMakeFiles --progress-num=9 "Built target presenter_autogen" .PHONY : src/CMakeFiles/presenter_autogen.dir/all # Build rule for subdir invocation for target. diff --git a/build/CMakeFiles/progress.marks b/build/CMakeFiles/progress.marks index 1e8b314..7f8f011 100644 --- a/build/CMakeFiles/progress.marks +++ b/build/CMakeFiles/progress.marks @@ -1 +1 @@ -6 +7 diff --git a/build/src/CMakeFiles/progress.marks b/build/src/CMakeFiles/progress.marks index 1e8b314..7f8f011 100644 --- a/build/src/CMakeFiles/progress.marks +++ b/build/src/CMakeFiles/progress.marks @@ -1 +1 @@ -6 +7 diff --git a/build/src/Makefile b/build/src/Makefile index 0f482de..4b4b302 100644 --- a/build/src/Makefile +++ b/build/src/Makefile @@ -226,6 +226,30 @@ presenter_autogen/mocs_compilation.cpp.s: cd /home/chris/dev/church-presenter/build && $(MAKE) $(MAKESILENT) -f src/CMakeFiles/presenter.dir/build.make src/CMakeFiles/presenter.dir/presenter_autogen/mocs_compilation.cpp.s .PHONY : presenter_autogen/mocs_compilation.cpp.s +songlistmodel.o: songlistmodel.cpp.o +.PHONY : songlistmodel.o + +# target to build an object file +songlistmodel.cpp.o: + cd /home/chris/dev/church-presenter/build && $(MAKE) $(MAKESILENT) -f src/CMakeFiles/presenter.dir/build.make src/CMakeFiles/presenter.dir/songlistmodel.cpp.o +.PHONY : songlistmodel.cpp.o + +songlistmodel.i: songlistmodel.cpp.i +.PHONY : songlistmodel.i + +# target to preprocess a source file +songlistmodel.cpp.i: + cd /home/chris/dev/church-presenter/build && $(MAKE) $(MAKESILENT) -f src/CMakeFiles/presenter.dir/build.make src/CMakeFiles/presenter.dir/songlistmodel.cpp.i +.PHONY : songlistmodel.cpp.i + +songlistmodel.s: songlistmodel.cpp.s +.PHONY : songlistmodel.s + +# target to generate assembly for a file +songlistmodel.cpp.s: + cd /home/chris/dev/church-presenter/build && $(MAKE) $(MAKESILENT) -f src/CMakeFiles/presenter.dir/build.make src/CMakeFiles/presenter.dir/songlistmodel.cpp.s +.PHONY : songlistmodel.cpp.s + # Help Target help: @echo "The following are some of the valid targets for this Makefile:" @@ -246,6 +270,9 @@ help: @echo "... presenter_autogen/mocs_compilation.o" @echo "... presenter_autogen/mocs_compilation.i" @echo "... presenter_autogen/mocs_compilation.s" + @echo "... songlistmodel.o" + @echo "... songlistmodel.i" + @echo "... songlistmodel.s" .PHONY : help diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f0e282a..ca28ab9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,6 +3,7 @@ add_executable(presenter) target_sources(presenter PRIVATE main.cpp resources.qrc + songlistmodel.cpp songlistmodel.h ) target_link_libraries(presenter diff --git a/src/main.cpp b/src/main.cpp index 608cb11..68452a3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2,11 +2,13 @@ #include #include #include +#include #include #include #include #include +#include "songlistmodel.h" // #include "mpvobject.h" int main(int argc, char *argv[]) @@ -18,15 +20,19 @@ int main(int argc, char *argv[]) QCoreApplication::setOrganizationDomain(QStringLiteral("tfcconnection.org")); QCoreApplication::setApplicationName(QStringLiteral("Church Presenter")); + SongListModel songListModel; + // path = QQmlEngine::importPathList() - std::cout << "Hello World!"; + qDebug() << "Hello World!"; QQmlApplicationEngine engine; engine.rootContext()->setContextObject(new KLocalizedContext(&engine)); + engine.rootContext()->setContextProperty("_songListModel", &songListModel); engine.load(QUrl(QStringLiteral("qrc:qml/main.qml"))); + #ifdef STATIC_KIRIGAMI KirigamiPlugin::getInstance().registerTypes(); #endif diff --git a/src/qml/main.qml b/src/qml/main.qml index afea969..3747066 100644 --- a/src/qml/main.qml +++ b/src/qml/main.qml @@ -10,11 +10,18 @@ import "./presenter" as Presenter Kirigami.ApplicationWindow { id: root + + property bool libraryOpen: true + pageStack.initialPage: mainPage + header: Presenter.Header {} + width: 1280 Presenter.MainWindow { id: mainPage } + + function toggleLibrary() { + libraryOpen = !libraryOpen + } } - - diff --git a/src/qml/presenter/Actions.qml b/src/qml/presenter/Actions.qml new file mode 100644 index 0000000..2552ade --- /dev/null +++ b/src/qml/presenter/Actions.qml @@ -0,0 +1,12 @@ +import QtQuick 2.13 +import QtQuick.Dialogs 1.0 +import QtQuick.Controls 2.15 as Controls +import QtQuick.Window 2.13 +import QtQuick.Layouts 1.2 +import QtMultimedia 5.15 +import QtAudioEngine 1.15 +import org.kde.kirigami 2.13 as Kirigami +import "./" as Presenter + +QtObject { +} diff --git a/src/qml/presenter/Header.qml b/src/qml/presenter/Header.qml new file mode 100644 index 0000000..deb31fb --- /dev/null +++ b/src/qml/presenter/Header.qml @@ -0,0 +1,54 @@ +import QtQuick 2.13 +import QtQuick.Dialogs 1.0 +import QtQuick.Controls 2.15 as Controls +import QtQuick.Window 2.13 +import QtQuick.Layouts 1.2 +import org.kde.kirigami 2.13 as Kirigami + +Kirigami.ActionToolBar { + id: root + alignment: Qt.AlignRight + + Kirigami.Heading { + text: "Presenter" + anchors.verticalCenter: parent.verticalCenter + anchors.left: parent.left + anchors.leftMargin: 20 + } + + actions: [ + + Kirigami.Action { + displayComponent: Component { + Kirigami.SearchField { + id: searchField + onAccepted: showPassiveNotification(searchField.text, 3000) + } + } + }, + + Kirigami.Action { + icon.name: "fileopen" + text: "VideoBG" + onTriggered: { + print("Action button in buttons page clicked"); + fileDialog.open() + } + }, + Kirigami.Action { + icon.name: "view-presentation" + text: "Go Live" + onTriggered: { + print("Window is loading") + presentLoader.active = true + } + }, + + Kirigami.Action { + icon.name: "sidebar-collapse-right" + text: "Close Library" + onTriggered: toggleLibrary() + } + + ] +} diff --git a/src/qml/presenter/LeftDock.qml b/src/qml/presenter/LeftDock.qml index 0e141cf..161b69b 100644 --- a/src/qml/presenter/LeftDock.qml +++ b/src/qml/presenter/LeftDock.qml @@ -7,11 +7,49 @@ import QtMultimedia 5.15 import QtAudioEngine 1.15 import org.kde.kirigami 2.13 as Kirigami -ListView { - id: serviceItemList - model: listModel - delegate: itemDelegate - /* flickDeceleration: 2000 */ +ColumnLayout { + id: root + Layout.fillHeight: true + + Kirigami.Heading { + id: serviceTitle + text: "Service List" + level: 1 + Layout.alignment: Qt.AlignHCenter + } + + ListView { + id: serviceItemList + model: listModel + delegate: itemDelegate + /* flickDeceleration: 2000 */ + + Component { + id: itemDelegate + Kirigami.BasicListItem { + width: serviceItemList.width + height:50 + label: itemName + subtitle: type + hoverEnabled: true + onClicked: serviceItemList.currentIndex = index + + } + } + + Kirigami.WheelHandler { + id: wheelHandler + target: serviceItemList + filterMouseEvents: true + keyNavigationEnabled: true + } + + Controls.ScrollBar.vertical: Controls.ScrollBar { + anchors.right: serviceItemList.right + anchors.leftMargin: 10 + active: hovered || pressed + } + } ListModel { id: listModel @@ -88,30 +126,4 @@ ListView { type: "video" } } - - Component { - id: itemDelegate - Kirigami.BasicListItem { - width: serviceItemList.width - height:50 - label: itemName - subtitle: type - hoverEnabled: true - onClicked: serviceItemList.currentIndex = index - - } - } - - Kirigami.WheelHandler { - id: wheelHandler - target: serviceItemList - filterMouseEvents: true - keyNavigationEnabled: true - } - - Controls.ScrollBar.vertical: Controls.ScrollBar { - anchors.right: serviceItemList.right - anchors.leftMargin: 10 - active: hovered || pressed - } } diff --git a/src/qml/presenter/Library.qml b/src/qml/presenter/Library.qml new file mode 100644 index 0000000..1a26c1d --- /dev/null +++ b/src/qml/presenter/Library.qml @@ -0,0 +1,47 @@ +import QtQuick 2.13 +import QtQuick.Dialogs 1.0 +import QtQuick.Controls 2.0 as Controls +import QtQuick.Layouts 1.2 +import org.kde.kirigami 2.13 as Kirigami +import "./" as Presenter + +Item { + id: root + Presenter.PanelItem { + anchors.fill: parent + title: "Songs" + + ListView { + anchors.fill: parent + id: libraryListView + model: _songListModel + delegate: itemDelegate + + Component { + id: itemDelegate + Kirigami.BasicListItem { + width: ListView.view.width + height:40 + label: title + subtitle: author + hoverEnabled: true + onClicked: ListView.view.currentIndex = index + + } + } + + Kirigami.WheelHandler { + id: wheelHandler + target: libraryListView + filterMouseEvents: true + keyNavigationEnabled: true + } + + Controls.ScrollBar.vertical: Controls.ScrollBar { + anchors.right: libraryListView.right + anchors.leftMargin: 10 + active: hovered || pressed + } + } + } +} diff --git a/src/qml/presenter/LibraryDelegate.qml b/src/qml/presenter/LibraryDelegate.qml new file mode 100644 index 0000000..3d3f3cb --- /dev/null +++ b/src/qml/presenter/LibraryDelegate.qml @@ -0,0 +1,11 @@ +import QtQuick 2.13 +import org.kde.kirigami 2.13 as Kirigami + +Kirigami.BasicListItem { + width: ListView.view.width + height:20 + label: model.itemName + subtitle: model.type + hoverEnabled: true + onClicked: ListView.view.currentIndex = index +} diff --git a/src/qml/presenter/LibraryModel.qml b/src/qml/presenter/LibraryModel.qml new file mode 100644 index 0000000..2f748ca --- /dev/null +++ b/src/qml/presenter/LibraryModel.qml @@ -0,0 +1,76 @@ +import QtQuick 2.13 + +ListModel { + ListElement { + itemName: "10,000 Reason" + type: "song" + } + ListElement { + itemName: "Marvelous Light" + type: "song" + } + ListElement { + itemName: "10 reason to use church presenter" + type: "video" + } + ListElement { + itemName: "killer.jpg" + type: "image" + } + ListElement { + itemName: "Marvelous Light" + type: "song" + } + ListElement { + itemName: "Cool runnings" + type: "video" + } + ListElement { + itemName: "10,000 Reason" + type: "song" + } + ListElement { + itemName: "Slides1.odp" + type: "presentation" + } + ListElement { + itemName: "IntroSlide" + type: "custom-slide" + } + ListElement { + itemName: "10,000 Reason" + type: "song" + } + ListElement { + itemName: "Marvelous Light" + type: "song" + } + ListElement { + itemName: "other slide" + type: "custom-slide" + } + ListElement { + itemName: "10,000 Reason" + type: "song" + } + ListElement { + itemName: "Marvelous Light" + type: "song" + } + ListElement { + itemName: "10 reason to use church presenter" + type: "video" + } + ListElement { + itemName: "10,000 Reason" + type: "song" + } + ListElement { + itemName: "Marvelous Light" + type: "song" + } + ListElement { + itemName: "10 reason to use church presenter" + type: "video" + } +} diff --git a/src/qml/presenter/MainWindow.qml b/src/qml/presenter/MainWindow.qml index b88e14d..eb75b84 100644 --- a/src/qml/presenter/MainWindow.qml +++ b/src/qml/presenter/MainWindow.qml @@ -1,6 +1,6 @@ import QtQuick 2.13 import QtQuick.Dialogs 1.0 -import QtQuick.Controls 2.0 as Controls +import QtQuick.Controls 2.15 as Controls import QtQuick.Window 2.13 import QtQuick.Layouts 1.2 import QtMultimedia 5.15 @@ -8,61 +8,54 @@ import QtAudioEngine 1.15 import org.kde.kirigami 2.13 as Kirigami import "./" as Presenter -Kirigami.Page { +Controls.Page { id: mainPage - title: "Presenter" padding: 0 property var video: null - actions { - main: Kirigami.Action { - icon.name: "fileopen" - text: "VideoBG" - onTriggered: { - print("Action button in buttons page clicked"); - fileDialog.open() - } - } - right: Kirigami.Action { - icon.name: "view-presentation" - text: "Go Live" - onTriggered: { - print("Window is loading") - presentLoader.active = true - } - } - } - Item { id: mainItem anchors.fill: parent height: parent.height - GridLayout { - id: gridLayout + Controls.SplitView { + id: splitMainView anchors.fill: parent - height: parent.height - columns: 3 - rows: 2 - Presenter.LeftDock { - id: leftDock - Layout.fillHeight: true - implicitWidth: 200 + handle: Item{ + implicitWidth: 6 + + Rectangle { + height: parent.height + anchors.horizontalCenter: parent.horizontalCenter + implicitWidth: 2 + color: Controls.SplitHandle.hovered ? Kirigami.Theme.hoverColor : Kirigami.Theme.backgroundColor + //Controls.SplitHandle.pressed ? Kirigami.Theme.focusColor + //: (Controls.Splithandle.hovered ? Kirigami.Theme.highlightColor : Kirigami.Theme.backgroundColor) + } } - Rectangle { - id: leftDockBorder - color: "lightblue" - Layout.fillHeight: true - width: 2 + Presenter.LeftDock { + id: leftDock + Controls.SplitView.fillHeight: true + Controls.SplitView.preferredWidth: 200 } Rectangle { id: rightMainArea color: "red" - Layout.fillHeight: true - Layout.fillWidth: true + Controls.SplitView.fillHeight: true + Controls.SplitView.fillWidth: true + Controls.SplitView.preferredWidth: 700 + Controls.SplitView.minimumWidth: 500 } + + Presenter.Library { + id: library + Controls.SplitView.fillHeight: true + Controls.SplitView.preferredWidth: libraryOpen ? 200 : 0 + Controls.SplitView.maximumWidth: 350 + } + } } diff --git a/src/qml/presenter/PanelItem.qml b/src/qml/presenter/PanelItem.qml new file mode 100644 index 0000000..1134457 --- /dev/null +++ b/src/qml/presenter/PanelItem.qml @@ -0,0 +1,70 @@ +import QtQuick 2.7 +import QtQuick.Controls 2.0 as Controls +import QtQuick.Layouts 1.2 +import org.kde.kirigami 2.13 as Kirigami + +Item { + default property var contentItem: null + property string title: "panel" + id: root + Layout.fillWidth: true + height: 30 + Layout.fillHeight: current + property bool current: false + ColumnLayout { + anchors.fill: parent + spacing: 0 + Rectangle { + id: bar + Layout.fillWidth: true + height: 30 + color: root.current ? Kirigami.Theme.highlightColor : Kirigami.Theme.backgroundColor + Controls.Label { + anchors.fill: parent + anchors.margins: 10 + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + text: root.title + } + Controls.Label { + anchors{ + right: parent.right + top: parent.top + bottom: parent.bottom + margins: 10 + } + horizontalAlignment: Text.AlignRight + verticalAlignment: Text.AlignVCenter + text: "^" + rotation: root.current ? "180" : 0 + } + MouseArea { + anchors.fill: parent + cursorShape: Qt.PointingHandCursor + onClicked: { + root.current = !root.current; + if(root.parent.currentItem !== null) + root.parent.currentItem.current = false; + + root.parent.currentItem = root; + } + } + } + Rectangle { + id: container + Layout.fillWidth: true + Layout.alignment: Qt.AlignTop + Layout.topMargin: bar.height / 4 + implicitHeight: root.height - bar.height + color: Kirigami.Theme.backgroundColor + clip: true + Behavior on implicitHeight { + PropertyAnimation { duration: 100 } + } + } + Component.onCompleted: { + if(root.contentItem !== null) + root.contentItem.parent = container; + } + } +} diff --git a/src/qml/presenter/Slide.qml b/src/qml/presenter/Slide.qml new file mode 100644 index 0000000..2fd0eee --- /dev/null +++ b/src/qml/presenter/Slide.qml @@ -0,0 +1,164 @@ +import QtQuick 2.13 +import QtQuick.Controls 2.15 as Controls +import QtQuick.Layouts 1.2 +import QtMultimedia 5.15 +import QtAudioEngine 1.15 +import org.kde.kirigami 2.13 as Kirigami +import "./" as Presenter + +Item { + /* + Slides can only be instantiated as a direct child of a Presentation {} as they rely on + several properties there. + */ + + id: slide + + property bool isSlide: true; + + property bool delayPoints: false; + property int _pointCounter: 0; + function _advance() { + if (!parent.allowDelay) + return false; + + _pointCounter = _pointCounter + 1; + if (_pointCounter < content.length) + return true; + _pointCounter = 0; + return false; + } + + property string title; + property variant content: [] + property string centeredText + property string writeInText; + property string notes; + + property real fontSize: parent.height * 0.05 + property real fontScale: 1 + + property real baseFontSize: fontSize * fontScale + property real titleFontSize: fontSize * 1.2 * fontScale + property real bulletSpacing: 1 + + property real contentWidth: width + + // Define the slide to be the "content area" + x: parent.width * 0.05 + y: parent.height * 0.2 + width: parent.width * 0.9 + height: parent.height * 0.7 + + property real masterWidth: parent.width + property real masterHeight: parent.height + + property color titleColor: parent.titleColor; + property color textColor: parent.textColor; + property string fontFamily: parent.fontFamily; + property int textFormat: Text.PlainText + + visible: false + + Controls.Label { + id: titleText + font.pixelSize: titleFontSize + text: title; + anchors.horizontalCenter: parent.horizontalCenter + anchors.bottom: parent.top + anchors.bottomMargin: parent.fontSize * 1.5 + font.bold: true; + font.family: slide.fontFamily + color: slide.titleColor + horizontalAlignment: Text.Center + z: 1 + } + + Controls.Label { + id: centeredId + width: parent.width + anchors.centerIn: parent + anchors.verticalCenterOffset: - parent.y / 3 + text: centeredText + horizontalAlignment: Text.Center + font.pixelSize: baseFontSize + font.family: slide.fontFamily + color: slide.textColor + wrapMode: Text.Wrap + } + + Controls.Label { + id: writeInTextId + property int length; + font.family: slide.fontFamily + font.pixelSize: baseFontSize + color: slide.textColor + + anchors.fill: parent; + wrapMode: Text.Wrap + + text: slide.writeInText.substring(0, length); + + NumberAnimation on length { + from: 0; + to: slide.writeInText.length; + duration: slide.writeInText.length * 30; + running: slide.visible && parent.visible && slide.writeInText.length > 0 + } + + visible: slide.writeInText != undefined; + } + + + Column { + id: contentId + anchors.fill: parent + + Repeater { + model: content.length + + Row { + id: row + + function decideIndentLevel(s) { return s.charAt(0) == " " ? 1 + decideIndentLevel(s.substring(1)) : 0 } + property int indentLevel: decideIndentLevel(content[index]) + property int nextIndentLevel: index < content.length - 1 ? decideIndentLevel(content[index+1]) : 0 + property real indentFactor: (10 - row.indentLevel * 2) / 10; + + height: text.height + (nextIndentLevel == 0 ? 1 : 0.3) * slide.baseFontSize * slide.bulletSpacing + x: slide.baseFontSize * indentLevel + visible: (!slide.parent.allowDelay || !delayPoints) || index <= _pointCounter + + Rectangle { + id: dot + anchors.baseline: text.baseline + anchors.baselineOffset: -text.font.pixelSize / 2 + width: text.font.pixelSize / 3 + height: text.font.pixelSize / 3 + color: slide.textColor + radius: width / 2 + opacity: text.text.length == 0 ? 0 : 1 + } + + Item { + id: space + width: dot.width * 1.5 + height: 1 + } + + Controls.Label { + id: text + width: slide.contentWidth - parent.x - dot.width - space.width + font.pixelSize: baseFontSize * row.indentFactor + text: content[index] + textFormat: slide.textFormat + wrapMode: Text.WordWrap + color: slide.textColor + horizontalAlignment: Text.AlignLeft + font.family: slide.fontFamily + } + } + } + } + +} diff --git a/src/resources.qrc b/src/resources.qrc index 8f87b9c..c7d82e3 100644 --- a/src/resources.qrc +++ b/src/resources.qrc @@ -4,5 +4,11 @@ qml/presenter/qmldir qml/presenter/LeftDock.qml qml/presenter/MainWindow.qml + qml/presenter/Library.qml + qml/presenter/LibraryModel.qml + qml/presenter/LibraryDelegate.qml + qml/presenter/Header.qml + qml/presenter/Actions.qml + qml/presenter/PanelItem.qml diff --git a/src/serviceitem.cpp b/src/serviceitem.cpp new file mode 100644 index 0000000..22855bf --- /dev/null +++ b/src/serviceitem.cpp @@ -0,0 +1,57 @@ +#include "serviceitem.h" + +ServiceItem::ServiceItem(QObject *parent) + : QAbstractListModel(parent) +{ +} + +int ServiceItem::rowCount(const QModelIndex &parent) const +{ + // For list models only the root node (an invalid parent) should return the list's size. For all + // other (valid) parents, rowCount() should return 0 so that it does not become a tree model. + if (parent.isValid()) + return 0; + + // FIXME: Implement me! +} + +QVariant ServiceItem::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + return QVariant(); + + // FIXME: Implement me! + return QVariant(); +} + +bool ServiceItem::setData(const QModelIndex &index, const QVariant &value, int role) +{ + if (data(index, role) != value) { + // FIXME: Implement me! + emit dataChanged(index, index, QVector() << role); + return true; + } + return false; +} + +Qt::ItemFlags ServiceItem::flags(const QModelIndex &index) const +{ + if (!index.isValid()) + return Qt::NoItemFlags; + + return Qt::ItemIsEditable; // FIXME: Implement me! +} + +bool ServiceItem::insertRows(int row, int count, const QModelIndex &parent) +{ + beginInsertRows(parent, row, row + count - 1); + // FIXME: Implement me! + endInsertRows(); +} + +bool ServiceItem::removeRows(int row, int count, const QModelIndex &parent) +{ + beginRemoveRows(parent, row, row + count - 1); + // FIXME: Implement me! + endRemoveRows(); +} diff --git a/src/serviceitem.h b/src/serviceitem.h new file mode 100644 index 0000000..71d76c0 --- /dev/null +++ b/src/serviceitem.h @@ -0,0 +1,33 @@ +#ifndef SERVICEITEM_H +#define SERVICEITEM_H + +#include + +class ServiceItem : public QAbstractListModel +{ + Q_OBJECT + +public: + explicit ServiceItem(QObject *parent = nullptr); + + // Basic functionality: + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + + // Editable: + bool setData(const QModelIndex &index, const QVariant &value, + int role = Qt::EditRole) override; + + Qt::ItemFlags flags(const QModelIndex& index) const override; + + // Add data: + bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()) override; + + // Remove data: + bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override; + +private: +}; + +#endif // SERVICEITEM_H diff --git a/src/songlistmodel.cpp b/src/songlistmodel.cpp new file mode 100644 index 0000000..90b156c --- /dev/null +++ b/src/songlistmodel.cpp @@ -0,0 +1,55 @@ +#include "songlistmodel.h" + +SongListModel::SongListModel(QObject *parent) + : QAbstractListModel(parent) +{ + m_data + << Data("10,000 Reasons", "10,000 reasons for my heart to sing", "Matt Redman", "13470183", "") + << Data("Marvelous Light", "Into marvelous light I'm running", "Chris Tomlin", "13470183", ""); +} + +int SongListModel::rowCount(const QModelIndex &parent) const +{ + // For list models only the root node (an invalid parent) should return the list's size. For all + // other (valid) parents, rowCount() should return 0 so that it does not become a tree model. + if (parent.isValid()) + return 0; + + // FIXME: Implement me! + return m_data.count(); + +} + +QVariant SongListModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + return QVariant(); + + // FIXME: Implement me! + const Data &data = m_data.at(index.row()); + if ( role == TitleRole ) + return data.title; + else if (role == LyricsRole) + return data.lyrics; + else if (role == AuthorRole) + return data.author; + else if (role == CCLINumRole) + return data.ccli; + else if (role == AudioRole) + return data.audio; + else + return QVariant(); +} + +QHash SongListModel::roleNames() const +{ + static QHash mapping { + {TitleRole, "title"}, + {LyricsRole, "lyrics"}, + {AuthorRole, "author"}, + {CCLINumRole, "ccli"}, + {AudioRole, "audio"} + }; + + return mapping; +} diff --git a/src/songlistmodel.h b/src/songlistmodel.h new file mode 100644 index 0000000..ea2fb3d --- /dev/null +++ b/src/songlistmodel.h @@ -0,0 +1,44 @@ +#ifndef SONGLISTMODEL_H +#define SONGLISTMODEL_H + +#include + +struct Data { + Data () {} + Data ( const QString& title, const QString& lyrics, const QString& author, + const QString& ccli, const QString& audio) + : title(title), lyrics(lyrics), author(author), ccli(ccli), audio(audio) {} + QString title; + QString lyrics; + QString author; + QString ccli; + QString audio; +}; + +class SongListModel : public QAbstractListModel +{ + Q_OBJECT + +public: + enum Roles { + TitleRole = Qt::UserRole, + LyricsRole, + AuthorRole, + CCLINumRole, + AudioRole, + }; + explicit SongListModel(QObject *parent = nullptr); + + // Basic functionality: + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + + QHash roleNames() const override; + +private: + QVector< Data > m_data; + +}; + +#endif // SONGLISTMODEL_H