├── .gitignore ├── CPP ├── CPPCD │ ├── CMakeLists.txt │ ├── YunaPlayer.qmlproject │ ├── YunaPlayer.qmlproject.qtds │ ├── YunaPlayer.qrc │ ├── asset_imports │ │ ├── CMakeLists.txt │ │ └── asset_imports.txt │ ├── content │ │ ├── App.qml │ │ ├── BppTable │ │ │ └── assets │ │ │ │ ├── arrows-alt-h-solid.svg │ │ │ │ ├── cog-solid.svg │ │ │ │ ├── copy-solid.svg │ │ │ │ ├── icon-delete.svg │ │ │ │ ├── sort-down.svg │ │ │ │ ├── sort-up-and-down.svg │ │ │ │ └── sort-up.svg │ │ ├── CMakeLists.txt │ │ ├── Screen01.qml │ │ ├── Screen01.ui.qml │ │ ├── Screen02.qml │ │ ├── Screen02.ui.qml │ │ ├── Screen02.ui.qml.autosave │ │ ├── fonts │ │ │ ├── fa-brands-400.ttf │ │ │ ├── fa-regular-400.ttf │ │ │ ├── fa-solid-900.ttf │ │ │ └── fonts.txt │ │ └── images │ │ │ ├── school_logo.jpg │ │ │ └── test1.jpg │ ├── imports │ │ ├── CMakeLists.txt │ │ ├── YunaPlayer │ │ │ ├── CMakeLists.txt │ │ │ ├── Constants.qml │ │ │ ├── DirectoryFontLoader.qml │ │ │ ├── EventListModel.qml │ │ │ ├── EventListSimulator.qml │ │ │ ├── Theme.qml │ │ │ ├── designer │ │ │ │ └── plugin.metainfo │ │ │ └── qmldir │ │ └── bpptable │ │ │ ├── CMakeLists.txt │ │ │ ├── CellButton.qml │ │ │ ├── CellClicker.qml │ │ │ ├── CellFa.qml │ │ │ ├── CellText.qml │ │ │ ├── CompGrid.qml │ │ │ ├── GridStatusButton.qml │ │ │ └── qmldir │ ├── main.qml │ ├── qmlcomponents │ ├── qmlmodules │ ├── qtquickcontrols2.conf │ └── src │ │ ├── Manage.cpp │ │ ├── Manage.h │ │ ├── MediaPlayer.cpp │ │ ├── MediaPlayer.h │ │ ├── SList.h │ │ ├── app_environment.h │ │ ├── bpbtable │ │ ├── bpptablecolumn.cpp │ │ ├── bpptablecolumn.h │ │ ├── bpptablecolumnlist.cpp │ │ ├── bpptablecolumnlist.h │ │ ├── bpptabledatabase.cpp │ │ ├── bpptabledatabase.h │ │ ├── bpptableheading.cpp │ │ ├── bpptableheading.h │ │ ├── bpptablemodel.cpp │ │ └── bpptablemodel.h │ │ ├── import_qml_components_plugins.h │ │ ├── import_qml_plugins.h │ │ └── main.cpp ├── CPPTP │ ├── .gitignore │ ├── CMakeLists.txt │ ├── CXXTP_zh_CN.ts │ ├── MainUI.cpp │ ├── MainUI.h │ ├── SList.h │ ├── SSet.h │ ├── SSetting.cpp │ ├── SSetting.h │ ├── SStack.h │ ├── classcard.cpp │ ├── classcard.h │ ├── classcard.ui │ ├── loginwindow.cpp │ ├── loginwindow.h │ ├── loginwindow.ui │ ├── main.cpp │ ├── mainwindow.ui │ ├── studentwindow.cpp │ ├── studentwindow.h │ ├── studentwindow.ui │ └── test │ │ ├── SListTest.cpp │ │ ├── SSetTest.cpp │ │ └── SStackTest.cpp └── README.md ├── CProgramLanguage ├── README.md ├── ThirdProject.c └── 燕山大学课程三级项目报告.pdf ├── LICENSE ├── README.md └── SQL ├── README.md └── hw01 └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Object files 5 | *.o 6 | *.ko 7 | *.obj 8 | *.elf 9 | 10 | # Linker output 11 | *.ilk 12 | *.map 13 | *.exp 14 | 15 | # Precompiled Headers 16 | *.gch 17 | *.pch 18 | 19 | # Libraries 20 | *.lib 21 | *.a 22 | *.la 23 | *.lo 24 | 25 | # Shared objects (inc. Windows DLLs) 26 | *.dll 27 | *.so 28 | *.so.* 29 | *.dylib 30 | 31 | # Executables 32 | *.exe 33 | *.out 34 | *.app 35 | *.i*86 36 | *.x86_64 37 | *.hex 38 | 39 | # Debug files 40 | *.dSYM/ 41 | *.su 42 | *.idb 43 | *.pdb 44 | 45 | # Kernel Module Compile Results 46 | *.mod* 47 | *.cmd 48 | .tmp_versions/ 49 | modules.order 50 | Module.symvers 51 | Mkfile.old 52 | dkms.conf 53 | -------------------------------------------------------------------------------- /CPP/CPPCD/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.21.1) 2 | 3 | set(BUILD_QDS_COMPONENTS ON CACHE BOOL "Build design studio components") 4 | 5 | project(YunaPlayerApp LANGUAGES CXX) 6 | 7 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 8 | set(CMAKE_AUTOMOC ON) 9 | set(CMAKE_CXX_STANDARD 17) 10 | 11 | find_package(QT NAMES Qt6 COMPONENTS Gui Qml Quick Multimedia Sql) 12 | find_package(Qt6 REQUIRED COMPONENTS Core Qml Quick Multimedia Sql) 13 | qt_policy(SET QTP0001 NEW) 14 | 15 | 16 | qt_add_executable(${CMAKE_PROJECT_NAME} src/main.cpp src/MediaPlayer.cpp src/MediaPlayer.h 17 | src/bpbtable/bpptablecolumn.cpp 18 | src/bpbtable/bpptablecolumn.h 19 | src/bpbtable/bpptablecolumnlist.cpp 20 | src/bpbtable/bpptablecolumnlist.h 21 | src/bpbtable/bpptabledatabase.cpp 22 | src/bpbtable/bpptabledatabase.h 23 | src/bpbtable/bpptableheading.cpp 24 | src/bpbtable/bpptableheading.h 25 | src/bpbtable/bpptablemodel.cpp 26 | src/bpbtable/bpptablemodel.h 27 | src/SList.h src/Manage.cpp src/Manage.h src/Manage.h src/Manage.cpp) 28 | 29 | 30 | # qt_standard_project_setup() requires Qt 6.3 or higher. See https://doc.qt.io/qt-6/qt-standard-project-setup.html for details. 31 | qt6_standard_project_setup() 32 | 33 | 34 | qt_add_resources(${CMAKE_PROJECT_NAME} "configuration" 35 | PREFIX "/" 36 | FILES 37 | qtquickcontrols2.conf 38 | ) 39 | 40 | target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE 41 | Qt${QT_VERSION_MAJOR}::Core 42 | Qt${QT_VERSION_MAJOR}::Gui 43 | Qt${QT_VERSION_MAJOR}::Quick 44 | Qt${QT_VERSION_MAJOR}::Qml 45 | Qt${QT_VERSION_MAJOR}::Multimedia 46 | Qt${QT_VERSION_MAJOR}::Sql 47 | ) 48 | 49 | if (${BUILD_QDS_COMPONENTS}) 50 | include(${CMAKE_CURRENT_SOURCE_DIR}/qmlcomponents) 51 | endif () 52 | 53 | include(${CMAKE_CURRENT_SOURCE_DIR}/qmlmodules) 54 | -------------------------------------------------------------------------------- /CPP/CPPCD/YunaPlayer.qmlproject: -------------------------------------------------------------------------------- 1 | import QmlProject 2 | 3 | Project { 4 | mainFile: "content/App.qml" 5 | 6 | /* Include .qml, .js, and image files from current directory and subdirectories */ 7 | QmlFiles { 8 | directory: "content" 9 | } 10 | 11 | QmlFiles { 12 | directory: "imports" 13 | } 14 | 15 | JavaScriptFiles { 16 | directory: "content" 17 | } 18 | 19 | JavaScriptFiles { 20 | directory: "imports" 21 | } 22 | 23 | ImageFiles { 24 | directory: "content" 25 | } 26 | 27 | ImageFiles { 28 | directory: "asset_imports" 29 | } 30 | 31 | Files { 32 | filter: "*.conf" 33 | files: ["qtquickcontrols2.conf"] 34 | } 35 | 36 | Files { 37 | filter: "qmldir" 38 | directory: "." 39 | } 40 | 41 | Files { 42 | filter: "*.ttf;*.otf" 43 | } 44 | 45 | Files { 46 | filter: "*.wav;*.mp3" 47 | } 48 | 49 | Files { 50 | filter: "*.mp4" 51 | } 52 | 53 | Files { 54 | filter: "*.glsl;*.glslv;*.glslf;*.vsh;*.fsh;*.vert;*.frag" 55 | } 56 | 57 | Files { 58 | filter: "*.mesh" 59 | directory: "asset_imports" 60 | } 61 | 62 | Files { 63 | filter: "*.qml" 64 | directory: "asset_imports" 65 | } 66 | 67 | Environment { 68 | QT_QUICK_CONTROLS_CONF: "qtquickcontrols2.conf" 69 | QT_AUTO_SCREEN_SCALE_FACTOR: "1" 70 | QML_COMPAT_RESOLVE_URLS_ON_ASSIGNMENT: "1" 71 | QT_LOGGING_RULES: "qt.qml.connections=false" 72 | QT_ENABLE_HIGHDPI_SCALING: "0" 73 | /* Useful for debugging 74 | QSG_VISUALIZE=batches 75 | QSG_VISUALIZE=clip 76 | QSG_VISUALIZE=changes 77 | QSG_VISUALIZE=overdraw 78 | */ 79 | } 80 | 81 | qt6Project: true 82 | 83 | /* List of plugin directories passed to QML runtime */ 84 | importPaths: [ "imports", "asset_imports" ] 85 | 86 | /* Required for deployment */ 87 | targetDirectory: "/opt/YunaPlayer" 88 | 89 | qdsVersion: "3.9" 90 | 91 | quickVersion: "6.2" 92 | 93 | /* If any modules the project imports require widgets (e.g. QtCharts), widgetApp must be true */ 94 | widgetApp: true 95 | 96 | /* args: Specifies command line arguments for qsb tool to generate shaders. 97 | files: Specifies target files for qsb tool. If path is included, it must be relative to this file. 98 | Wildcard '*' can be used in the file name part of the path. 99 | e.g. files: [ "content/shaders/*.vert", "*.frag" ] */ 100 | ShaderTool { 101 | args: "-s --glsl \"100 es,120,150\" --hlsl 50 --msl 12" 102 | files: [ "content/shaders/*" ] 103 | } 104 | 105 | multilanguageSupport: true 106 | supportedLanguages: ["en"] 107 | primaryLanguage: "en" 108 | 109 | } 110 | -------------------------------------------------------------------------------- /CPP/CPPCD/YunaPlayer.qmlproject.qtds: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | EnvironmentId 7 | {8183bc8a-d18f-4b68-baa7-f51a207e5e3f} 8 | 9 | 10 | ProjectExplorer.Project.ActiveTarget 11 | 0 12 | 13 | 14 | ProjectExplorer.Project.EditorSettings 15 | 16 | true 17 | false 18 | true 19 | 20 | Cpp 21 | 22 | CppGlobal 23 | 24 | 25 | 26 | QmlJS 27 | 28 | QmlJSGlobal 29 | 30 | 31 | 2 32 | UTF-8 33 | false 34 | 4 35 | false 36 | 80 37 | true 38 | true 39 | 1 40 | false 41 | true 42 | false 43 | 0 44 | true 45 | true 46 | 0 47 | 8 48 | true 49 | false 50 | 1 51 | true 52 | true 53 | true 54 | *.md, *.MD, Makefile 55 | false 56 | true 57 | true 58 | 59 | 60 | 61 | ProjectExplorer.Project.Target.0 62 | 63 | Desktop 64 | Desktop Qt 6.4.1 65 | Desktop Qt 6.4.1 66 | {63f87550-2541-4163-9631-08b7fea781da} 67 | -1 68 | 0 69 | 0 70 | 0 71 | 72 | 73 | 0 74 | Deploy 75 | Deploy 76 | ProjectExplorer.BuildSteps.Deploy 77 | 78 | 1 79 | 80 | false 81 | ProjectExplorer.DefaultDeployConfiguration 82 | 83 | 1 84 | 85 | true 86 | 87 | 0 88 | 89 | QML Runtime 90 | QmlProjectManager.QmlRunConfiguration.Qml 91 | 92 | en 93 | CurrentFile 94 | true 95 | false 96 | true 97 | false 98 | true 99 | 100 | 1 101 | 102 | 103 | 104 | ProjectExplorer.Project.TargetCount 105 | 1 106 | 107 | 108 | ProjectExplorer.Project.Updater.FileVersion 109 | 22 110 | 111 | 112 | Version 113 | 22 114 | 115 | 116 | -------------------------------------------------------------------------------- /CPP/CPPCD/YunaPlayer.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /CPP/CPPCD/asset_imports/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ### This file is automatically generated by Qt Design Studio. 2 | ### Do not change 3 | 4 | -------------------------------------------------------------------------------- /CPP/CPPCD/asset_imports/asset_imports.txt: -------------------------------------------------------------------------------- 1 | Imported 3D assets and components imported from bundles will be created in this folder. 2 | -------------------------------------------------------------------------------- /CPP/CPPCD/content/App.qml: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0 3 | 4 | import QtQuick 6.2 5 | import QtQuick.Controls 6.2 6 | import QtQuick.Layouts 6.2 7 | import Qt5Compat.GraphicalEffects 8 | import YunaPlayer 9 | 10 | ApplicationWindow { 11 | id: root 12 | 13 | height: Constants.height 14 | title: "YunaPlayer" 15 | visible: true 16 | width: Constants.width 17 | 18 | header: ToolBar { 19 | id: header 20 | 21 | RowLayout { 22 | anchors.fill: parent 23 | 24 | ToolButton { 25 | text: stack.depth > 1 ? qsTr("<") : qsTr("X") 26 | 27 | onClicked: function () { 28 | if (stack.depth > 1) { 29 | frameTitle.text = "YunaPlayer" 30 | stack.pop(); 31 | } 32 | } 33 | } 34 | Label { 35 | id: frameTitle 36 | 37 | Layout.fillWidth: true 38 | elide: Label.ElideRight 39 | font.pixelSize: Theme.labelTextSize 40 | horizontalAlignment: Qt.AlignHCenter 41 | text: "YunaPlayer" 42 | verticalAlignment: Qt.AlignVCenter 43 | } 44 | ToolButton { 45 | enabled: stack.depth < 2 46 | text: qsTr(":") 47 | 48 | onClicked: function () { 49 | frameTitle.text = "Playlist"; 50 | stack.push(songList); 51 | } 52 | } 53 | } 54 | } 55 | 56 | StackView { 57 | id: stack 58 | 59 | property alias mainScreen: mainScreen 60 | 61 | anchors.fill: parent 62 | initialItem: mainScreen 63 | opacity: 0.7 64 | 65 | Screen01 { 66 | id: mainScreen 67 | 68 | height: root.height - header.height 69 | objectName: "mainScreen" 70 | width: root.width 71 | } 72 | } 73 | Component { 74 | id: songList 75 | 76 | Screen02 { 77 | height: root.height - root.header.height 78 | objectName: "songList" 79 | width: root.width 80 | } 81 | } 82 | Item { 83 | height: parent.height 84 | layer.enabled: true 85 | width: parent.width 86 | z: -1 87 | 88 | layer.effect: GaussianBlur { 89 | radius: 30 90 | source: stack.mainScreen.songImage 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /CPP/CPPCD/content/BppTable/assets/arrows-alt-h-solid.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /CPP/CPPCD/content/BppTable/assets/cog-solid.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /CPP/CPPCD/content/BppTable/assets/copy-solid.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /CPP/CPPCD/content/BppTable/assets/icon-delete.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /CPP/CPPCD/content/BppTable/assets/sort-down.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /CPP/CPPCD/content/BppTable/assets/sort-up-and-down.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | 12 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /CPP/CPPCD/content/BppTable/assets/sort-up.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /CPP/CPPCD/content/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ### This file is automatically generated by Qt Design Studio. 2 | ### Do not change 3 | 4 | 5 | 6 | qt_add_library(content STATIC) 7 | qt6_add_qml_module(content 8 | URI "content" 9 | VERSION 1.0 10 | QML_FILES 11 | Screen01.ui.qml 12 | Screen01.qml 13 | Screen02.qml 14 | Screen02.ui.qml 15 | App.qml 16 | RESOURCES 17 | images/school_logo.jpg 18 | images/test1.jpg 19 | BppTable/assets/arrows-alt-h-solid.svg 20 | BppTable/assets/cog-solid.svg 21 | BppTable/assets/copy-solid.svg 22 | BppTable/assets/icon-delete.svg 23 | BppTable/assets/sort-down.svg 24 | BppTable/assets/sort-up.svg 25 | BppTable/assets/sort-up-and-down.svg 26 | ) -------------------------------------------------------------------------------- /CPP/CPPCD/content/Screen01.qml: -------------------------------------------------------------------------------- 1 | // This file include the logical part of Screen01.ui.qml 2 | 3 | import QtQuick 6.2 4 | import QtQuick.Controls 6.2 5 | import YunaPlayer 6 | 7 | Screen01 { 8 | currentPlayingTime: 0 9 | currentSongIndex: 1 10 | currentVolume: 50 11 | playing: false 12 | songType: "MP3" 13 | songChannel: "Dual Channel" 14 | songBitrate: "192kbps" 15 | 16 | onPlayingChanged: { 17 | songImageAnim.running = true; 18 | !playing ? songImageAnim.pause() : songImageAnim.resume(); 19 | // if(playing){ 20 | // if(!songImageAnim.running){ 21 | // songImageAnim.running = true; 22 | // songImageAnim.pause(); 23 | // } 24 | // }else songImageAnim.resume 25 | } 26 | 27 | playControlStop { 28 | onClicked: { 29 | playing = !playing; 30 | player.onPlayButtonClick(playing); 31 | } 32 | } 33 | playingSlider { 34 | onMoved: { 35 | currentPlayingTime = playingSlider.value; 36 | player.onPlaySlideChanged(currentPlayingTime); 37 | } 38 | } 39 | volumeSlider { 40 | onMoved: { 41 | currentVolume = volumeSlider.value; 42 | player.onVolumeChanged(currentVolume); 43 | } 44 | } 45 | SequentialAnimation { 46 | id: sequentialAnimation 47 | 48 | running: false 49 | 50 | NumberAnimation { 51 | id: numberAnimationStart 52 | 53 | duration: 5000 54 | easing.type: Easing.Linear 55 | target: playingSongName 56 | } 57 | NumberAnimation { 58 | id: numberAnimationEnd 59 | 60 | duration: 0 61 | easing.type: Easing.Linear 62 | target: playingSongName 63 | to: 0 64 | } 65 | } 66 | Timer { 67 | id: numberAnimationTimer 68 | 69 | interval: 15000 70 | repeat: true 71 | running: true 72 | triggeredOnStart: true 73 | 74 | onTriggered: { 75 | if (playingSongName.x + playingSongName.width > playingSongName.parent.width) { 76 | numberAnimationStart.to = 0 - playingSongName.width + playingSongName.parent.width * 3 / 4; 77 | numberAnimationEnd.to = 0; 78 | sequentialAnimation.running = true; 79 | } else { 80 | sequentialAnimation.running = false; 81 | } 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /CPP/CPPCD/content/Screen01.ui.qml: -------------------------------------------------------------------------------- 1 | /* 2 | This is a UI file (.ui.qml) that is intended to be edited in Qt Design Studio only. 3 | It is supposed to be strictly declarative and only uses a subset of QML. If you edit 4 | this file manually, you might introduce QML code that is not supported by Qt Design Studio. 5 | Check out https://doc.qt.io/qtcreator/creator-quick-ui-forms.html for details on .ui.qml files. 6 | */ 7 | import QtQuick 6.2 8 | import QtQuick.Controls 6.2 9 | import Qt5Compat.GraphicalEffects 10 | import YunaPlayer 11 | 12 | Rectangle { 13 | id: screen01Rect 14 | 15 | property int currentPlayingTime 16 | property int currentVolume 17 | property int currentSongIndex 18 | property int playPolicy // 0: Stop 1: Next 2: Single 19 | property string songType 20 | property string songName 21 | property string songChannel 22 | property string songBitrate 23 | property alias playControlStop: playControlStop 24 | property bool playing 25 | property alias playingSlider: playingSlider 26 | property alias playingSongName: playingSongName 27 | property alias songImage: songImage 28 | property alias songImageAnim: songImageAnim 29 | property int totalPlayingTime 30 | property alias volumeSlider: volumeSlider 31 | 32 | antialiasing: true 33 | color: Theme.backgroundColor 34 | height: Constants.height 35 | width: Constants.width 36 | 37 | Text { 38 | id: songNumberLabel 39 | 40 | color: Theme.outlineColor 41 | font.pixelSize: 20 42 | text: (currentSongIndex+1+'').padStart(3, '0') 43 | 44 | anchors { 45 | left: parent.left 46 | leftMargin: 10 47 | top: parent.top 48 | topMargin: 10 49 | } 50 | } 51 | Text { 52 | id: playingSongName 53 | 54 | font.pixelSize: Theme.labelTextSize 55 | text: songName 56 | 57 | anchors { 58 | left: songNumberLabel.right 59 | leftMargin: 10 60 | top: songNumberLabel.top 61 | } 62 | // TODO Make it marquee 63 | } 64 | Text { 65 | id: playingSongInfoFormat 66 | 67 | font.pixelSize: Theme.labelTextSize 68 | text: songType 69 | 70 | anchors { 71 | left: songNumberLabel.left 72 | top: songNumberLabel.bottom 73 | topMargin: 5 74 | } 75 | } 76 | Text { 77 | id: playingSongInfoBitrate 78 | 79 | font.pixelSize: Theme.labelTextSize 80 | text: songBitrate 81 | 82 | anchors { 83 | left: playingSongInfoFormat.right 84 | leftMargin: 5 85 | top: playingSongInfoFormat.top 86 | } 87 | } 88 | Text { 89 | id: playingSongInfoChannelType 90 | 91 | font.pixelSize: Theme.labelTextSize 92 | text: songChannel 93 | 94 | anchors { 95 | left: playingSongInfoBitrate.right 96 | leftMargin: 5 97 | top: playingSongInfoFormat.top 98 | } 99 | } 100 | 101 | // Bottom 102 | Button { 103 | id: playControlStop 104 | 105 | background: null 106 | flat: true 107 | text: playing ? "⏸" : "▶" 108 | width: playControlStop.height 109 | 110 | anchors { 111 | bottom: parent.bottom 112 | bottomMargin: 5 113 | horizontalCenter: parent.horizontalCenter 114 | } 115 | } 116 | 117 | Button { 118 | id: playPolicyControl 119 | 120 | background: null 121 | flat: true 122 | text: function () { 123 | switch (playPolicy) { 124 | case 0: 125 | return 'PAUSE' 126 | case 1: 127 | return 'CONTINUE' 128 | case 2: 129 | return 'LOOP' 130 | } 131 | return 'ERR' 132 | }() 133 | 134 | anchors { 135 | left: parent.left 136 | leftMargin: 10 137 | top: playControlStop.top 138 | } 139 | 140 | onClicked: { 141 | playPolicy += 1; 142 | playPolicy %= 3; 143 | } 144 | } 145 | Button { 146 | id: playControlPrev 147 | 148 | background: null 149 | flat: true 150 | text: "<" 151 | width: playControlStop.height 152 | 153 | anchors { 154 | bottom: playControlStop.bottom 155 | right: playControlStop.left 156 | rightMargin: 10 157 | } 158 | 159 | onClicked: { 160 | player.playMusic(currentSongIndex-1); 161 | } 162 | } 163 | Button { 164 | id: playControlNext 165 | 166 | background: null 167 | flat: true 168 | text: ">" 169 | width: playControlStop.height 170 | 171 | anchors { 172 | bottom: playControlStop.bottom 173 | left: playControlStop.right 174 | leftMargin: 10 175 | } 176 | 177 | onClicked: { 178 | player.playMusic(currentSongIndex+1); 179 | } 180 | } 181 | Text { 182 | id: playTimeInfo 183 | 184 | font.pixelSize: Theme.labelTextSize 185 | text: ((Math.floor(currentPlayingTime / 60) + '') + ':' + ('' + currentPlayingTime % 60).padStart(2, '0')) 186 | 187 | anchors { 188 | bottom: playControlStop.top 189 | bottomMargin: 5 190 | left: parent.left 191 | leftMargin: 5 192 | } 193 | } 194 | Text { 195 | id: playTotalTimeInfo 196 | 197 | font.pixelSize: Theme.labelTextSize 198 | text: ((Math.floor(totalPlayingTime / 60) + '') + ':' + ('' + totalPlayingTime % 60).padStart(2, '0')) 199 | 200 | anchors { 201 | bottom: playControlStop.top 202 | bottomMargin: 5 203 | right: parent.right 204 | rightMargin: 5 205 | } 206 | } 207 | Slider { 208 | id: playingSlider 209 | 210 | height: playTimeInfo.height 211 | orientation: Qt.Horizontal 212 | stepSize: 1 213 | to: totalPlayingTime 214 | value: currentPlayingTime 215 | 216 | anchors { 217 | left: playTimeInfo.right 218 | leftMargin: 5 219 | right: playTotalTimeInfo.left 220 | rightMargin: 5 221 | top: playTimeInfo.top 222 | } 223 | } 224 | Rectangle { 225 | id: songClip 226 | 227 | anchors.centerIn: parent 228 | clip: true 229 | color: Qt.rgba(255, 255, 255, 0) 230 | //visible: false 231 | height: (root.width + root.height) / 6 232 | width: (root.width + root.height) / 6 233 | 234 | Image { 235 | id: songImage 236 | 237 | antialiasing: true 238 | fillMode: Image.PreserveAspectFit 239 | source: "images/school_logo.jpg" 240 | transformOrigin: Item.Center 241 | visible: false 242 | 243 | anchors { 244 | fill: parent 245 | } 246 | RotationAnimation { 247 | id: songImageAnim 248 | 249 | duration: 8000 250 | loops: Animation.Infinite 251 | running: false // See Screen01.qml. There is a listener to pause/resume this animation 252 | target: songClip 253 | to: 360 254 | } 255 | } 256 | OpacityMask { 257 | anchors.fill: songImage 258 | invert: false 259 | source: songImage 260 | opacity: 1 261 | 262 | maskSource: Rectangle { 263 | color: Qt.rgba(255, 255, 255, 1) 264 | height: songImage.height 265 | radius: songImage.width / 2 266 | width: songImage.width 267 | opacity: 1 268 | } 269 | } 270 | } 271 | Slider { 272 | id: volumeSlider 273 | 274 | height: playTimeInfo.height 275 | orientation: Qt.Horizontal 276 | stepSize: 1 277 | to: 100 278 | value: currentVolume 279 | width: root.width / 4 280 | 281 | anchors { 282 | right: parent.right 283 | rightMargin: 5 284 | top: playControlStop.top 285 | } 286 | } 287 | Text { 288 | id: volumeLabel 289 | 290 | text: currentVolume + " %" 291 | 292 | anchors { 293 | right: volumeSlider.left 294 | rightMargin: 10 295 | top: volumeSlider.top 296 | } 297 | } 298 | } 299 | -------------------------------------------------------------------------------- /CPP/CPPCD/content/Screen02.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 6.2 2 | import QtQuick.Controls 6.2 3 | import YunaPlayer 4 | 5 | Screen02 { 6 | fruitList: {} 7 | } -------------------------------------------------------------------------------- /CPP/CPPCD/content/Screen02.ui.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 6.2 2 | import QtQuick.Controls 6.2 3 | import Qt.labs.qmlmodels 1.0 4 | import YunaPlayer 5 | import BppTable 0.1 6 | import QtQuick.Dialogs 7 | 8 | Rectangle { 9 | property var fruitList: [] 10 | 11 | function fillData() { 12 | var j = []; 13 | for (var i = 0; i < player.getDataSize(); i++) { 14 | j.push(player.fillData(i)); 15 | console.log(j); 16 | } 17 | fruitList = j; 18 | console.log(fruitList); 19 | bGrid.fillFromJson(fruitList); 20 | } 21 | 22 | //property alias songList: songList 23 | 24 | color: Theme.backgroundColor 25 | 26 | Component.onCompleted: { 27 | fillData(); 28 | } 29 | 30 | Button { 31 | id: buttonAdd 32 | 33 | text: "Add" 34 | 35 | anchors { 36 | left: parent.left 37 | leftMargin: 10 38 | top: parent.top 39 | } 40 | 41 | onClicked: { 42 | addDialog.open(); 43 | } 44 | } 45 | Button { 46 | id: buttonDelete 47 | 48 | text: "Delete" 49 | 50 | anchors { 51 | left: buttonAdd.right 52 | leftMargin: 10 53 | top: buttonAdd.top 54 | } 55 | 56 | onClicked: { 57 | player.deleteFile(bGrid.cellValue(bGrid.selectedRow, 0) - 1) 58 | player.refreshList(); 59 | fillData(); 60 | } 61 | } 62 | Rectangle { 63 | border.color: "gray" 64 | border.width: 1 65 | color: "lightgray" 66 | height: buttonDelete.height * 0.8 67 | radius: 5 68 | width: parent.width / 3 69 | 70 | anchors { 71 | left: buttonDelete.right 72 | leftMargin: 20 73 | right: buttonSearch.left 74 | rightMargin: 20 75 | verticalCenter: buttonDelete.verticalCenter 76 | } 77 | TextInput { 78 | id: searchInput 79 | 80 | font.pixelSize: parent.height * 0.8 81 | 82 | anchors { 83 | fill: parent 84 | verticalCenter: parent.verticalCenter 85 | } 86 | } 87 | } 88 | Button { 89 | id: buttonSearch 90 | 91 | text: "Search" 92 | 93 | onClicked: { 94 | player.searchFor(searchInput.text); 95 | console.log("Fill data"); 96 | fillData(); 97 | } 98 | 99 | anchors { 100 | leftMargin: 10 101 | right: parent.right 102 | top: buttonAdd.top 103 | } 104 | } 105 | CompGrid { 106 | id: bGrid 107 | 108 | cellDelegate: cellItem 109 | dataHeight: 30 110 | fromArray: [// {sid: 1, name: "A", artist: "Abc", ci: "Mr.a", qu: "Mr.b", time: "2022-03-01"} 111 | { 112 | "role": "sid", 113 | "title": "ID", 114 | "dataType": BTColumn.Int 115 | }, { 116 | "role": "name", 117 | "title": "Name", 118 | "minWidth": 70 119 | }, { 120 | "role": "artist", 121 | "title": "Artist", 122 | "dataType": BTColumn.Str 123 | }, { 124 | "role": "ci", 125 | "title": "Lyricist", 126 | "dataType": BTColumn.Str 127 | }, { 128 | "role": "qu", 129 | "title": "Composer", 130 | "dataType": BTColumn.Str 131 | }, { 132 | "role": "time", 133 | "title": "Release Date", 134 | "dataType": BTColumn.Date 135 | }, { 136 | "role": "duration", 137 | "title": "Duration", 138 | "dataType": BTColumn.Int 139 | }] 140 | showOptionsButton: true 141 | 142 | anchors { 143 | bottom: parent.bottom 144 | left: parent.left 145 | right: parent.right 146 | top: buttonAdd.bottom 147 | } 148 | Component { 149 | id: cellItem 150 | 151 | Rectangle { 152 | color: bGrid.getCellBk(row, highlight) 153 | implicitHeight: bGrid.dataHeight 154 | 155 | CellText { 156 | horizontalAlignment: bGrid.getAlign(dataType) 157 | text: bGrid.formatDisplay(display, dataType, 2) 158 | } 159 | CellClicker { 160 | grid: bGrid 161 | linkEnabled: true 162 | 163 | onDoCommand: { 164 | player.playMusic(bGrid.cellValue(bGrid.selectedRow, 0) - 1); 165 | } 166 | } 167 | } 168 | } 169 | } 170 | FileDialog { 171 | id: addDialog 172 | 173 | nameFilters: ["Music Files (*.mp3 *.flac *.wav *.aac)"] 174 | title: qsTr("Please choose music file") 175 | 176 | onAccepted: { 177 | console.log("Add", selectedFile); 178 | player.addFile(selectedFile); 179 | player.refreshList(); 180 | fillData(); 181 | } 182 | } 183 | } 184 | -------------------------------------------------------------------------------- /CPP/CPPCD/content/Screen02.ui.qml.autosave: -------------------------------------------------------------------------------- 1 | import QtQuick 6.2 2 | import QtQuick.Controls 6.2 3 | import Qt.labs.qmlmodels 1.0 4 | import YunaPlayer 5 | 6 | Rectangle { 7 | //property alias songList: songList 8 | 9 | width: 900 10 | height: 680 11 | color: Theme.backgroundColor 12 | 13 | ListModel { 14 | id: songItemList 15 | 16 | ListElement { 17 | name: "Lion" 18 | place: "Africa" 19 | } 20 | ListElement { 21 | name: "Puma" 22 | place: "Americas" 23 | } 24 | } 25 | ListModel { 26 | id: libraryModel 27 | 28 | ListElement { 29 | author: "Gabriel" 30 | title: "A Masterpiece" 31 | } 32 | ListElement { 33 | author: "Jens" 34 | title: "Brilliance" 35 | } 36 | ListElement { 37 | author: "Frederik" 38 | title: "Outstanding" 39 | } 40 | } 41 | 42 | // ListView { 43 | // id: songList 44 | // anchors.fill: parent 45 | // model: songItemList 46 | // spacing: 0 47 | // 48 | // delegate: Button { 49 | // height: 50 50 | // font.pixelSize: 30 51 | // text: name 52 | // anchors { 53 | // left: parent.left 54 | // right: parent.right 55 | // leftMargin: 10 56 | // rightMargin: 10 57 | // } 58 | // 59 | // background: Rectangle { 60 | // radius: 0 61 | // color: index%2 === 0 ? Theme.backgroundColor : "grey" 62 | // } 63 | // } 64 | // } 65 | } 66 | -------------------------------------------------------------------------------- /CPP/CPPCD/content/fonts/fa-brands-400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KamijoToma/YSUProject/1a960ba55ac9789537dfce7f955ee955b8ea99e6/CPP/CPPCD/content/fonts/fa-brands-400.ttf -------------------------------------------------------------------------------- /CPP/CPPCD/content/fonts/fa-regular-400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KamijoToma/YSUProject/1a960ba55ac9789537dfce7f955ee955b8ea99e6/CPP/CPPCD/content/fonts/fa-regular-400.ttf -------------------------------------------------------------------------------- /CPP/CPPCD/content/fonts/fa-solid-900.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KamijoToma/YSUProject/1a960ba55ac9789537dfce7f955ee955b8ea99e6/CPP/CPPCD/content/fonts/fa-solid-900.ttf -------------------------------------------------------------------------------- /CPP/CPPCD/content/fonts/fonts.txt: -------------------------------------------------------------------------------- 1 | Fonts in this folder are loaded automatically. 2 | -------------------------------------------------------------------------------- /CPP/CPPCD/content/images/school_logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KamijoToma/YSUProject/1a960ba55ac9789537dfce7f955ee955b8ea99e6/CPP/CPPCD/content/images/school_logo.jpg -------------------------------------------------------------------------------- /CPP/CPPCD/content/images/test1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KamijoToma/YSUProject/1a960ba55ac9789537dfce7f955ee955b8ea99e6/CPP/CPPCD/content/images/test1.jpg -------------------------------------------------------------------------------- /CPP/CPPCD/imports/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ### This file is automatically generated by Qt Design Studio. 2 | ### Do not change 3 | 4 | add_subdirectory(YunaPlayer) 5 | add_subdirectory(bpptable) -------------------------------------------------------------------------------- /CPP/CPPCD/imports/YunaPlayer/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ### This file is automatically generated by Qt Design Studio. 2 | ### Do not change 3 | 4 | set_source_files_properties(Constants.qml 5 | PROPERTIES 6 | QT_QML_SINGLETON_TYPE true 7 | ) 8 | set_source_files_properties(Theme.qml 9 | PROPERTIES 10 | QT_QML_SINGLETON_TYPE true 11 | ) 12 | 13 | 14 | 15 | qt_add_library(YunaPlayer STATIC) 16 | qt6_add_qml_module(YunaPlayer 17 | URI "YunaPlayer" 18 | VERSION 1.0 19 | QML_FILES 20 | EventListSimulator.qml 21 | EventListModel.qml 22 | DirectoryFontLoader.qml 23 | Constants.qml 24 | Theme.qml 25 | RESOURCES 26 | qmldir 27 | ) 28 | 29 | -------------------------------------------------------------------------------- /CPP/CPPCD/imports/YunaPlayer/Constants.qml: -------------------------------------------------------------------------------- 1 | pragma Singleton 2 | import QtQuick 6.2 3 | import QtQuick.Studio.Application 4 | import QtQuick.Controls.Material 2.3 5 | 6 | QtObject { 7 | readonly property int width: 900 8 | readonly property int height: 680 9 | 10 | property string relativeFontDirectory: "fonts" 11 | 12 | /* Edit this comment to add your custom font */ 13 | readonly property font font: Qt.font({ 14 | family: Qt.application.font.family, 15 | pixelSize: Qt.application.font.pixelSize 16 | }) 17 | readonly property font largeFont: Qt.font({ 18 | family: Qt.application.font.family, 19 | pixelSize: Qt.application.font.pixelSize * 1.6 20 | }) 21 | 22 | 23 | 24 | property StudioApplication application: StudioApplication { 25 | fontPath: Qt.resolvedUrl("../../content/" + relativeFontDirectory) 26 | } 27 | 28 | 29 | } 30 | -------------------------------------------------------------------------------- /CPP/CPPCD/imports/YunaPlayer/DirectoryFontLoader.qml: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0 3 | 4 | import QtQuick 6.2 5 | import Qt.labs.folderlistmodel 6.2 6 | 7 | QtObject { 8 | id: loader 9 | 10 | property url fontDirectory: Qt.resolvedUrl("../../content/" + relativeFontDirectory) 11 | property string relativeFontDirectory: "fonts" 12 | 13 | function loadFont(url) { 14 | var fontLoader = Qt.createQmlObject('import QtQuick 2.15; FontLoader { source: "' + url + '"; }', 15 | loader, 16 | "dynamicFontLoader"); 17 | } 18 | 19 | property FolderListModel folderModel: FolderListModel { 20 | id: folderModel 21 | folder: loader.fontDirectory 22 | nameFilters: [ "*.ttf", "*.otf" ] 23 | showDirs: false 24 | 25 | onStatusChanged: { 26 | if (folderModel.status == FolderListModel.Ready) { 27 | var i 28 | for (i = 0; i < count; i++) { 29 | loadFont(folderModel.get(i, "fileURL")) 30 | } 31 | } 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /CPP/CPPCD/imports/YunaPlayer/EventListModel.qml: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0 3 | 4 | import QtQuick 6.2 5 | 6 | ListModel { 7 | id: eventListModel 8 | 9 | ListElement { 10 | eventId: "enterPressed" 11 | eventDescription: "Emitted when pressing the enter button" 12 | shortcut: "Return" 13 | parameters: "Enter" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /CPP/CPPCD/imports/YunaPlayer/EventListSimulator.qml: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2018 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0 3 | 4 | import QtQuick 6.2 5 | import QtQuick.Studio.EventSimulator 1.0 6 | import QtQuick.Studio.EventSystem 1.0 7 | 8 | QtObject { 9 | id: simulator 10 | property bool active: true 11 | 12 | property Timer __timer: Timer { 13 | id: timer 14 | interval: 100 15 | onTriggered: { 16 | EventSimulator.show() 17 | } 18 | } 19 | 20 | Component.onCompleted: { 21 | EventSystem.init(Qt.resolvedUrl("EventListModel.qml")) 22 | if (simulator.active) 23 | timer.start() 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /CPP/CPPCD/imports/YunaPlayer/Theme.qml: -------------------------------------------------------------------------------- 1 | pragma Singleton 2 | import QtQuick 3 | 4 | QtObject { 5 | property color name: "#ffffff" 6 | property color backgroundColor: Qt.rgba(255, 255, 255, 128) 7 | property color outlineColor: "#79757f" 8 | property int labelTextSize: 20 9 | } 10 | -------------------------------------------------------------------------------- /CPP/CPPCD/imports/YunaPlayer/designer/plugin.metainfo: -------------------------------------------------------------------------------- 1 | MetaInfo { 2 | Type { 3 | name: "YunaPlayer.EventListSimulator" 4 | icon: ":/qtquickplugin/images/item-icon16.png" 5 | 6 | Hints { 7 | visibleInNavigator: true 8 | canBeDroppedInNavigator: true 9 | canBeDroppedInFormEditor: false 10 | canBeDroppedInView3D: false 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /CPP/CPPCD/imports/YunaPlayer/qmldir: -------------------------------------------------------------------------------- 1 | Module YunaPlayer 2 | singleton Constants 1.0 Constants.qml 3 | EventListSimulator 1.0 EventListSimulator.qml 4 | EventListModel 1.0 EventListModel.qml 5 | DirectoryFontLoader 1.0 DirectoryFontLoader.qml 6 | singleton Theme 1.0 Theme.qml 7 | -------------------------------------------------------------------------------- /CPP/CPPCD/imports/bpptable/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ### This file is automatically generated by Qt Design Studio. 2 | ### Do not change 3 | 4 | 5 | 6 | qt_add_library(BppTable STATIC) 7 | qt6_add_qml_module(BppTable 8 | URI "BppTable" 9 | VERSION 1.0 10 | QML_FILES 11 | CellButton.qml 12 | CellClicker.qml 13 | CellFa.qml 14 | CellText.qml 15 | GridStatusButton.qml 16 | CompGrid.qml 17 | RESOURCES 18 | qmldir 19 | ) 20 | 21 | -------------------------------------------------------------------------------- /CPP/CPPCD/imports/bpptable/CellButton.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | import QtQuick.Controls 2.12 3 | 4 | Text { 5 | id: theTxt 6 | 7 | property alias text: theTxt.text 8 | property alias horizontalAlignment: theTxt.horizontalAlignment 9 | 10 | verticalAlignment: Text.AlignVCenter 11 | anchors.fill: parent 12 | anchors.leftMargin: 5 13 | anchors.rightMargin: 5 14 | font.pointSize: 11 15 | font.underline: true 16 | color: "blue" 17 | elide: Qt.ElideRight 18 | } 19 | -------------------------------------------------------------------------------- /CPP/CPPCD/imports/bpptable/CellClicker.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | //import BppTableModel 0.1 3 | import BppTable 4 | 5 | MouseArea { 6 | property CompGrid grid: null 7 | property bool linkEnabled: false 8 | 9 | signal doCommand(); 10 | 11 | cursorShape: linkEnabled ? Qt.PointingHandCursor : Qt.ArrowCursor 12 | 13 | anchors.fill: parent 14 | onClicked: function(mouse){ 15 | if(grid){ 16 | grid.setSelectedRow(row, mouse.modifiers); 17 | } 18 | } 19 | 20 | onDoubleClicked: function(mouse){ 21 | if(linkEnabled) { 22 | if(grid.selectedRow !== row) grid.setSelectedRow(row, mouse.modifiers); 23 | doCommand() 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /CPP/CPPCD/imports/bpptable/CellFa.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | 3 | Text { 4 | id: theTxt 5 | 6 | property alias horizontalAlignment: theTxt.horizontalAlignment 7 | property alias fa_family: theTxt.font.family 8 | property alias fa_ico: theTxt.text 9 | property alias pointSize: theTxt.font.pointSize 10 | 11 | verticalAlignment: Text.AlignVCenter 12 | horizontalAlignment: Text.AlignHCenter; 13 | anchors.fill: parent 14 | anchors.leftMargin: 5 15 | anchors.rightMargin: 5 16 | 17 | font.pointSize: 14 18 | font.family: Fa.solid 19 | } 20 | -------------------------------------------------------------------------------- /CPP/CPPCD/imports/bpptable/CellText.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | 3 | Text { 4 | //id: theTxt 5 | 6 | //property alias text: theTxt.text 7 | //property alias horizontalAlignment: theTxt.horizontalAlignment 8 | 9 | verticalAlignment: Text.AlignVCenter 10 | anchors.fill: parent 11 | anchors.leftMargin: 5 12 | anchors.rightMargin: 5 13 | font.pointSize: 11 14 | elide: Qt.ElideRight 15 | } 16 | -------------------------------------------------------------------------------- /CPP/CPPCD/imports/bpptable/GridStatusButton.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | 3 | Rectangle { 4 | id: container 5 | property int fontSizePt: 11 6 | property color textColor: "black" 7 | property color textColorDisabled: "gray" 8 | property alias buttonText: txt.text 9 | property alias buttonFontFamily: txt.font.family 10 | 11 | signal pressed(); 12 | 13 | Text { 14 | id: txt 15 | anchors.fill: parent 16 | font.pointSize: fontSizePt 17 | verticalAlignment: Text.AlignVCenter 18 | horizontalAlignment: Text.AlignHCenter 19 | color: container.enabled ? textColor : textColorDisabled 20 | } 21 | MouseArea { 22 | anchors.fill: parent 23 | hoverEnabled: true 24 | cursorShape: containsMouse ? Qt.PointingHandCursor : Qt.ArrowCursor 25 | onClicked: container.pressed(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /CPP/CPPCD/imports/bpptable/qmldir: -------------------------------------------------------------------------------- 1 | module BppTable 2 | CellButton 0.1 CellButton.qml 3 | CellClicker 0.1 CellClicker.qml 4 | CellText 0.1 CellText.qml 5 | CellFa 0.1 CellFa.qml 6 | GridStatusButton 0.1 GridStatusButton.qml 7 | CompGrid 0.1 CompGrid.qml 8 | -------------------------------------------------------------------------------- /CPP/CPPCD/main.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2 | import content 3 | 4 | App { 5 | } 6 | 7 | -------------------------------------------------------------------------------- /CPP/CPPCD/qmlcomponents: -------------------------------------------------------------------------------- 1 | ### This file is automatically generated by Qt Design Studio. 2 | ### Do not change 3 | 4 | message("Building designer components.") 5 | 6 | set(QT_QML_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/qml") 7 | 8 | include(FetchContent) 9 | FetchContent_Declare( 10 | ds 11 | GIT_TAG qds-3.9 12 | GIT_REPOSITORY https://code.qt.io/qt-labs/qtquickdesigner-components.git 13 | ) 14 | 15 | FetchContent_GetProperties(ds) 16 | FetchContent_Populate(ds) 17 | 18 | target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE 19 | QuickStudioComponentsplugin 20 | QuickStudioEffectsplugin 21 | QuickStudioApplicationplugin 22 | FlowViewplugin 23 | QuickStudioLogicHelperplugin 24 | QuickStudioMultiTextplugin 25 | QuickStudioEventSimulatorplugin 26 | QuickStudioEventSystemplugin 27 | ) 28 | 29 | add_subdirectory(${ds_SOURCE_DIR} ${ds_BINARY_DIR}) 30 | 31 | target_compile_definitions(${CMAKE_PROJECT_NAME} PRIVATE 32 | BULD_QDS_COMPONENTS=true 33 | ) 34 | -------------------------------------------------------------------------------- /CPP/CPPCD/qmlmodules: -------------------------------------------------------------------------------- 1 | ### This file is automatically generated by Qt Design Studio. 2 | ### Do not change 3 | 4 | qt6_add_qml_module(YunaPlayerApp 5 | URI "Main" 6 | VERSION 1.0 7 | NO_PLUGIN 8 | QML_FILES main.qml 9 | ) 10 | 11 | add_subdirectory(content) 12 | add_subdirectory(imports) 13 | add_subdirectory(asset_imports) 14 | 15 | 16 | target_link_libraries(YunaPlayerApp PRIVATE 17 | contentplugin 18 | YunaPlayerplugin 19 | BppTableplugin 20 | ) 21 | -------------------------------------------------------------------------------- /CPP/CPPCD/qtquickcontrols2.conf: -------------------------------------------------------------------------------- 1 | [Controls] 2 | Style=Material 3 | 4 | [Material] 5 | Theme=Light 6 | -------------------------------------------------------------------------------- /CPP/CPPCD/src/Manage.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by SkyRain on 2023/06/09. 3 | // 4 | 5 | #include "Manage.h" 6 | -------------------------------------------------------------------------------- /CPP/CPPCD/src/Manage.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by SkyRain on 2023/06/09. 3 | // 4 | 5 | #ifndef YUNAPLAYERAPP_MANAGE_H 6 | #define YUNAPLAYERAPP_MANAGE_H 7 | 8 | class Manage { 9 | 10 | }; 11 | 12 | #endif // YUNAPLAYERAPP_MANAGE_H 13 | -------------------------------------------------------------------------------- /CPP/CPPCD/src/MediaPlayer.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by SkyRain on 2023/06/08. 3 | // 4 | 5 | #include "MediaPlayer.h" 6 | -------------------------------------------------------------------------------- /CPP/CPPCD/src/MediaPlayer.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by SkyRain on 2023/06/08. 3 | // 4 | 5 | #ifndef YUNAPLAYERAPP_MEDIAPLAYER_H 6 | #define YUNAPLAYERAPP_MEDIAPLAYER_H 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #include "SList.h" 23 | #include "bpbtable/bpptablemodel.h" 24 | 25 | class MediaPlayer : public QObject { 26 | Q_OBJECT 27 | private: 28 | QQmlApplicationEngine* engine; 29 | QObject* mainScreen, *songList; 30 | QMediaPlayer player; 31 | QAudioOutput audioOutput; 32 | SList *sList, *filteredList; 33 | bool isReady = false; 34 | 35 | 36 | 37 | public: 38 | explicit MediaPlayer(QQmlApplicationEngine* engine): QObject(engine), engine(engine){ 39 | // Find mainScreen 40 | sList = new SList(); 41 | mainScreen = engine->rootObjects().first()->findChild("mainScreen"); 42 | songList = engine->rootObjects().first()->findChild("songList"); 43 | assert(mainScreen != nullptr && mainScreen != nullptr); 44 | // Load player 45 | player.setAudioOutput(&audioOutput); 46 | connect(&player, SIGNAL(positionChanged(qint64)), this, SLOT(positionChanged(qint64))); 47 | connect(&player, SIGNAL(durationChanged(qint64)), this, SLOT(durationChanged(qint64))); 48 | connect(&player, SIGNAL(metaDataChanged()), this, SLOT(onMetaInfoChanged())); 49 | connect(&player, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)), this, SLOT(playStateChanged(QMediaPlayer::MediaStatus))); 50 | audioOutput.setVolume(50); 51 | refreshList(); 52 | } 53 | 54 | ~MediaPlayer(){ 55 | delete sList; 56 | } 57 | public: 58 | Q_INVOKABLE void onPlayButtonClick(bool play){ 59 | // This function is called from QML Runtime 60 | if(play){ 61 | qDebug() << "Playing"; 62 | player.play(); 63 | }else player.pause(); 64 | }; 65 | 66 | Q_INVOKABLE void addFile(QString filePath){ 67 | // Add filepath 68 | qDebug() << "From " << QUrl(filePath).toLocalFile() << " To" << QCoreApplication::applicationDirPath()+"/song/" + QUrl(filePath).fileName(); 69 | QFile::copy(QUrl(filePath).toLocalFile(), QCoreApplication::applicationDirPath()+"/song/" + QUrl(filePath).fileName()); 70 | qDebug() << "Copy OK"; 71 | } 72 | 73 | Q_INVOKABLE void deleteFile(int index){ 74 | auto name = (*(*filteredList)[index])["file"]; 75 | qDebug() << name.toString(); 76 | QFile file(name.toString()); 77 | file.remove(); 78 | } 79 | 80 | Q_INVOKABLE void refreshList(){ 81 | player.setSource(QUrl("")); 82 | int i=0; 83 | sList->clear(); 84 | for(const auto& file : std::filesystem::directory_iterator((QCoreApplication::applicationDirPath()+ "/song/").toStdString())){ 85 | isReady = false; 86 | player.setSource(QUrl::fromLocalFile(QString::fromStdString(file.path().generic_u8string()))); 87 | auto *map = new QVariantMap(); 88 | (*map)["sid"] = ++i; 89 | (*map)["file"] = QString::fromStdString(file.path().generic_u8string()); 90 | while(!isReady); 91 | auto metaInfo = player.metaData(); 92 | if(metaInfo.value(QMediaMetaData::Title).isValid()) 93 | (*map)["name"] = metaInfo.stringValue(QMediaMetaData::Title); 94 | else (*map)["name"] = QString::fromStdString(file.path().filename().generic_u8string()); 95 | if(metaInfo.value(QMediaMetaData::AlbumArtist).isValid()){ 96 | (*map)["artist"] = metaInfo.stringValue(QMediaMetaData::AlbumArtist); 97 | (*map)["ci"] = metaInfo.stringValue(QMediaMetaData::AlbumArtist); 98 | }else{ 99 | (*map)["artist"] = metaInfo.stringValue(QMediaMetaData::ContributingArtist); 100 | (*map)["ci"] = metaInfo.stringValue(QMediaMetaData::ContributingArtist); 101 | } 102 | (*map)["qu"] = metaInfo.stringValue(QMediaMetaData::AlbumTitle); 103 | (*map)["time"] = metaInfo.stringValue(QMediaMetaData::Date); 104 | (*map)["duration"] = static_cast(metaInfo.value(QMediaMetaData::Duration).value()/1000); 105 | for(auto& key : metaInfo.keys()){ 106 | qDebug() << key << " " << metaInfo.value(key); 107 | } 108 | sList->push_back(map); 109 | } 110 | filteredList = sList; 111 | QQmlProperty::write(mainScreen, "currentSongIndex", filteredList->getSize()-1); 112 | 113 | } 114 | 115 | Q_INVOKABLE void onVolumeChanged(float volume){ 116 | qDebug() << "Volume changed to " << volume << "%"; 117 | audioOutput.setVolume(volume/100); 118 | }; 119 | 120 | Q_INVOKABLE void onPlaySlideChanged(float seek){ 121 | qDebug() << "Play time seeked to " << seek << "s"; 122 | if(abs(player.position()/1000-seek) >= 1){ 123 | // Seeked by human 124 | if(seek >= 0 && seek <= player.duration()/1000+1){ 125 | player.setPosition(seek*1000); 126 | }else{ 127 | qDebug() << "Invalid seek position: " << seek << "(0 to " << player.duration()/1000+1 << ")"; 128 | } 129 | } 130 | }; 131 | 132 | Q_INVOKABLE QVariantMap fillData(int i){ 133 | if(filteredList->getSize() == 1) { 134 | auto k= (*filteredList)[0]; 135 | qDebug() << k; 136 | return *(*filteredList)[0]; 137 | }else{ 138 | qDebug() << "Get" << *(*filteredList)[i]; 139 | return *(*filteredList)[i]; 140 | } 141 | } 142 | 143 | Q_INVOKABLE int getDataSize(){ 144 | qDebug() << "Get " << filteredList->getSize(); 145 | return filteredList->getSize(); 146 | } 147 | 148 | Q_INVOKABLE void searchFor(const QString s){ 149 | qDebug() << s ; 150 | if(s != ""){ 151 | auto list = new SList; 152 | for(int i=0; igetSize(); i++){ 153 | auto* v = (*sList)[i]; 154 | if((*v)["name"].value().contains(s)){ 155 | list->push_back(v); 156 | qDebug() << "Searched " << (*v)["name"]; 157 | } 158 | } 159 | filteredList = list; 160 | for(int i=0; igetSize(); i++){ 161 | qDebug() << "Test: " << *(*filteredList)[i]; 162 | } 163 | } else{ 164 | filteredList = sList; 165 | } 166 | }; 167 | 168 | Q_INVOKABLE void playMusic(int index){ 169 | index += filteredList->getSize(); 170 | index %= filteredList->getSize(); 171 | auto url = (*filteredList)[index]->value("file").value(); 172 | qDebug() << "PlayMusic: " << url; 173 | isReady = false; 174 | player.setSource(QUrl::fromLocalFile(url)); 175 | while(!isReady); 176 | player.play(); 177 | QQmlProperty::write(mainScreen, "currentSongIndex", index); 178 | QQmlProperty::write(mainScreen, "playing", true); 179 | } 180 | public slots: 181 | void positionChanged(qint64 milisecond){ 182 | // this function is called when playing. 183 | QQmlProperty::write(mainScreen, "currentPlayingTime", (int)(milisecond/1000)); 184 | }; 185 | 186 | void playStateChanged(const QMediaPlayer::MediaStatus status){ 187 | switch (status) { 188 | case QMediaPlayer::EndOfMedia:{ 189 | QQmlProperty::write(mainScreen, "playing", false); 190 | auto policy = QQmlProperty::read(mainScreen, "playPolicy").toInt(); 191 | switch (policy){ 192 | case 0: 193 | break; 194 | case 1:{ 195 | auto index = QQmlProperty::read(mainScreen, "currentSongIndex").toInt(); 196 | playMusic(index+1); 197 | player.play(); 198 | break; 199 | } 200 | case 2:{ 201 | auto index = QQmlProperty::read(mainScreen, "currentSongIndex").toInt(); 202 | player.setPosition(0); 203 | QQmlProperty::write(mainScreen, "playing", true); 204 | player.play(); 205 | } 206 | } 207 | break; 208 | } 209 | case QMediaPlayer::LoadedMedia:{ 210 | //isReady = true; 211 | break; 212 | } 213 | } 214 | } 215 | 216 | void durationChanged(qint64 milisecond){ 217 | qDebug() << "Duration has changed to " << milisecond << " ms"; 218 | QQmlProperty::write(mainScreen, "totalPlayingTime", (int)(milisecond/1000)); 219 | }; 220 | 221 | void onMetaInfoChanged(){ 222 | isReady = true; 223 | auto metaInfo = player.metaData(); 224 | qDebug() << metaInfo.value(QMediaMetaData::AudioCodec).toString() << " " << metaInfo.value(QMediaMetaData::AudioBitRate).value() << " " << 225 | metaInfo.value(QMediaMetaData::ThumbnailImage) << " " << metaInfo.value(QMediaMetaData::FileFormat) << " " << metaInfo.value(QMediaMetaData::Composer); 226 | QQmlProperty::write(mainScreen, "songType", metaInfo.value(QMediaMetaData::AudioCodec).toString()); 227 | QQmlProperty::write(mainScreen, "songBitrate", QString::number(metaInfo.value(QMediaMetaData::AudioBitRate).value()/1000) + "kbps"); 228 | QQmlProperty::write(mainScreen, "songChannel", metaInfo.value(QMediaMetaData::TrackNumber).toString()); 229 | QQmlProperty::write(mainScreen, "songName", player.source().toString().split('/').last()); 230 | } 231 | }; 232 | 233 | #endif // YUNAPLAYERAPP_MEDIAPLAYER_H 234 | -------------------------------------------------------------------------------- /CPP/CPPCD/src/SList.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by SkyRain on 2023/05/03. 3 | // 4 | 5 | #ifndef SLIST_H 6 | #define SLIST_H 7 | #include 8 | #include 9 | 10 | template 11 | class SList { 12 | 13 | private: 14 | /** 15 | * List node presentation. 16 | */ 17 | struct Node { 18 | /** 19 | * Inner data 20 | */ 21 | T data; 22 | /** 23 | * Next node pointer. Default nulptr 24 | */ 25 | Node* next; 26 | /** 27 | * Previous node pointer. Default nulptr 28 | */ 29 | Node* prev; 30 | explicit Node(const T& d = T(), Node* n = nullptr, Node* p = nullptr) : data(d), next(n), prev(p) {} 31 | }; 32 | 33 | /** 34 | * First node 35 | */ 36 | Node* head; 37 | /** 38 | * Last node 39 | */ 40 | Node* tail; 41 | /** 42 | * List size 43 | */ 44 | std::size_t size; 45 | 46 | public: 47 | /** 48 | * Default constructor 49 | */ 50 | SList() : head(nullptr), tail(nullptr), size(0) {} 51 | /** 52 | * Copy constructor 53 | * @param other other list 54 | */ 55 | SList(const SList & other); 56 | /** 57 | * Equal constructor 58 | * @param other Other list 59 | * @return list reference 60 | */ 61 | SList & operator=(const SList & other); 62 | /** 63 | * Destructor 64 | */ 65 | ~SList(); 66 | 67 | /** 68 | * Add a value to its head 69 | * @param val value 70 | */ 71 | void push_front(const T& val); 72 | /** 73 | * Add a value to its tail 74 | * @param val value 75 | */ 76 | void push_back(const T& val); 77 | /** 78 | * Remove its front value. 79 | * If it does not have, do nothing. 80 | */ 81 | void pop_front(); 82 | /** 83 | * Remove its tail value. 84 | * If it does not have, do nothing. 85 | */ 86 | void pop_back(); 87 | /** 88 | * Clear list. Destruct all node pointer 89 | */ 90 | void clear(); 91 | /** 92 | * Indicate if the list is empty 93 | * @return bool value 94 | */ 95 | [[nodiscard]] bool empty() const; 96 | /** 97 | * Return its size 98 | * @return size 99 | */ 100 | [[nodiscard]] std::size_t getSize() const; 101 | /** 102 | * Get its front value 103 | * @return front value reference 104 | */ 105 | T& front(); 106 | /** 107 | * Get its front value constantly 108 | * @return constant front value reference 109 | */ 110 | const T& front() const; 111 | /** 112 | * Get its tail value 113 | * @return tail value reference 114 | */ 115 | T& back(); 116 | /** 117 | * Get its tail value constantly 118 | * @return constant tail value reference 119 | */ 120 | const T& back() const; 121 | /** 122 | * Insert a value 123 | * @param val value 124 | * @param pos position 125 | */ 126 | void insert(const T& val, std::size_t pos); 127 | /** 128 | * Delete a value 129 | * @param pos position 130 | */ 131 | void erase(std::size_t pos); 132 | /** 133 | * Index operator 134 | * @param i position 135 | * @return value 136 | */ 137 | T& operator[](const size_t i) const; 138 | }; 139 | 140 | template T &SList::operator[](const size_t i) const { 141 | if(i >= size){ 142 | throw std::out_of_range("List out of range"); 143 | } 144 | auto curr = head; 145 | for(int j=0; jnext; 147 | } 148 | return curr->data; 149 | } 150 | 151 | template SList::SList(const SList& other) { 152 | head = tail = nullptr; 153 | size = 0; 154 | for (Node* it = other.head; it != nullptr; it = it->next) { 155 | push_back(it->data); 156 | } 157 | } 158 | 159 | template SList&SList::operator=(const SList& other) { 160 | if (this != &other) { 161 | clear(); 162 | for (Node* it = other.head; it != nullptr; it = it->next) { 163 | push_back(it->data); 164 | } 165 | } 166 | return *this; 167 | } 168 | 169 | template SList::~SList() { 170 | clear(); 171 | } 172 | 173 | template 174 | void SList::push_front(const T& val) { 175 | Node* newNode = new Node(val, head, nullptr); 176 | if (head != nullptr) { 177 | head->prev = newNode; 178 | } else { 179 | tail = newNode; 180 | } 181 | head = newNode; 182 | ++size; 183 | } 184 | 185 | template 186 | void SList::push_back(const T& val) { 187 | Node* newNode = new Node(val, nullptr, tail); 188 | if (tail != nullptr) { 189 | tail->next = newNode; 190 | } else { 191 | head = newNode; 192 | } 193 | tail = newNode; 194 | ++size; 195 | } 196 | 197 | template 198 | void SList::pop_front() { 199 | if (head != nullptr) { 200 | Node* tmp = head; 201 | head = head->next; 202 | if (head != nullptr) { 203 | head->prev = nullptr; 204 | } else { 205 | tail = nullptr; 206 | } 207 | delete tmp; 208 | --size; 209 | } 210 | } 211 | 212 | template 213 | void SList::pop_back() { 214 | if (tail != nullptr) { 215 | Node* tmp = tail; 216 | tail = tail->prev; 217 | if (tail != nullptr) { 218 | tail->next = nullptr; 219 | } else { 220 | head = nullptr; 221 | } 222 | delete tmp; 223 | --size; 224 | } 225 | } 226 | 227 | template 228 | void SList::clear() { 229 | while (head != nullptr) { 230 | Node* tmp = head; 231 | head = head->next; 232 | delete tmp; 233 | } 234 | tail = nullptr; 235 | size = 0; 236 | } 237 | 238 | template 239 | bool SList::empty() const{ 240 | return size == 0; 241 | } 242 | 243 | template 244 | std::size_t SList::getSize() const { 245 | return size; 246 | } 247 | 248 | template 249 | T&SList::front() { 250 | return head->data; 251 | } 252 | 253 | template 254 | const T&SList::front() const { 255 | return head->data; 256 | } 257 | 258 | template 259 | T&SList::back() { 260 | return tail->data; 261 | } 262 | 263 | template 264 | const T&SList::back() const { 265 | return tail->data; 266 | } 267 | 268 | template 269 | void SList::insert(const T& val, std::size_t pos) { 270 | if (pos > size) { 271 | return; 272 | } 273 | if (pos == 0) { 274 | push_front(val); 275 | } else if (pos == size) { 276 | push_back(val); 277 | } else { 278 | Node* it = head; 279 | for (std::size_t i = 0; i < pos; ++i) { 280 | it = it->next; 281 | } 282 | Node* newNode = new Node(val, it, it->prev); 283 | it->prev->next = newNode; 284 | it->prev = newNode; 285 | ++size; 286 | } 287 | } 288 | 289 | template 290 | void SList::erase(std::size_t pos) { 291 | if (pos >= size) { 292 | return; 293 | } 294 | if (pos == 0) { 295 | pop_front(); 296 | } else if (pos == size - 1) { 297 | pop_back(); 298 | } else { 299 | Node* it = head; 300 | for (std::size_t i = 0; i < pos; ++i) { 301 | it = it->next; 302 | } 303 | it->prev->next = it->next; 304 | it->next->prev = it->prev; 305 | delete it; 306 | --size; 307 | } 308 | } 309 | #endif 310 | -------------------------------------------------------------------------------- /CPP/CPPCD/src/app_environment.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is automatically generated by Qt Design Studio. 3 | * Do not change. 4 | */ 5 | 6 | #include 7 | 8 | void set_qt_environment() 9 | { 10 | qputenv("QT_QUICK_CONTROLS_CONF", ":/qtquickcontrols2.conf"); 11 | qputenv("QT_ENABLE_HIGHDPI_SCALING", "0"); 12 | qputenv("QT_AUTO_SCREEN_SCALE_FACTOR", "1"); 13 | qputenv("QML_COMPAT_RESOLVE_URLS_ON_ASSIGNMENT", "1"); 14 | qputenv("QT_LOGGING_RULES", "qt.qml.connections=false"); 15 | 16 | } 17 | -------------------------------------------------------------------------------- /CPP/CPPCD/src/bpbtable/bpptablecolumn.cpp: -------------------------------------------------------------------------------- 1 | #include "bpptablecolumn.h" 2 | #include 3 | 4 | namespace bpp { 5 | 6 | TableColumn::TableColumn(QObject *parent) : 7 | QObject(parent), 8 | type(Str), 9 | view(0), 10 | sortFlag(0), 11 | action(0), 12 | command(0), 13 | width(0), 14 | minWidth(0), 15 | visible(true), 16 | reference1(-1) 17 | { 18 | 19 | } 20 | 21 | void TableColumn::registerQml() 22 | { 23 | //qmlRegisterType("BppTableModel", 0, 1, "BTColumn"); 24 | qmlRegisterType("BppTable", 0, 1, "BTColumn"); 25 | } 26 | 27 | void TableColumn::modify(const QVariantMap &colDef, bool withDefaults) 28 | { 29 | if(!colDef.contains("width")){ 30 | if(withDefaults) width = 100; 31 | } 32 | else 33 | { 34 | width = colDef["width"].toInt(); 35 | } 36 | if(width == 0) width = 100; 37 | 38 | if(!colDef.contains("minWidth")){ 39 | if(withDefaults) minWidth = 0; 40 | } 41 | else 42 | minWidth = colDef["minWidth"].toInt(); 43 | 44 | if(!colDef.contains("title")){ 45 | if(withDefaults) title = ""; 46 | } 47 | else 48 | title = colDef["title"].toString(); 49 | 50 | if(!colDef.contains("sort")){ 51 | if(withDefaults) sortFlag = 0; 52 | } 53 | else 54 | sortFlag = colDef["sort"].toInt(); 55 | 56 | if(!colDef.contains("dataType")){ 57 | if(withDefaults) type = Str; 58 | } 59 | else 60 | type = ColumnType( colDef["dataType"].toInt() ); 61 | 62 | if(!colDef.contains("view")){ 63 | if(withDefaults) view = 0; 64 | } 65 | else 66 | view = colDef["view"].toInt(); 67 | 68 | if(!colDef.contains("command")){ 69 | if(withDefaults) command = 0; 70 | } 71 | else 72 | command = colDef["command"].toInt(); 73 | 74 | if(!colDef.contains("role")){ 75 | if(withDefaults) role = ""; 76 | } 77 | else 78 | role = colDef["role"].toString(); 79 | 80 | if(!colDef.contains("visible")){ 81 | if(withDefaults) visible = true; 82 | } 83 | else 84 | visible = colDef["visible"].toBool(); 85 | 86 | if(!colDef.contains("dataRef1")){ 87 | if(withDefaults) dataRef1.clear(); 88 | } 89 | else 90 | dataRef1 = colDef["dataRef1"].toString(); 91 | } 92 | 93 | } 94 | -------------------------------------------------------------------------------- /CPP/CPPCD/src/bpbtable/bpptablecolumn.h: -------------------------------------------------------------------------------- 1 | #ifndef TABLECOLUMN_H 2 | #define TABLECOLUMN_H 3 | 4 | #include 5 | 6 | namespace bpp { 7 | 8 | class TableColumn : public QObject 9 | { 10 | Q_OBJECT 11 | public: 12 | explicit TableColumn(QObject *parent = nullptr); 13 | static void registerQml(); 14 | void modify(const QVariantMap& colDef, bool withDefaults); 15 | 16 | enum ColumnType{ 17 | Str = 0, 18 | Dbl, 19 | Int, 20 | Date, 21 | DateTime 22 | }; 23 | 24 | Q_ENUM(ColumnType) 25 | 26 | QString title; 27 | ColumnType type; 28 | int view; 29 | int sortFlag; 30 | int action; 31 | int command; 32 | int width; 33 | int minWidth; 34 | bool visible; 35 | QString role; 36 | QString dataRef1; 37 | 38 | int reference1; 39 | 40 | signals: 41 | 42 | public slots: 43 | }; 44 | 45 | } 46 | #endif // TABLECOLUMN_H 47 | -------------------------------------------------------------------------------- /CPP/CPPCD/src/bpbtable/bpptablecolumnlist.cpp: -------------------------------------------------------------------------------- 1 | #include "bpptablecolumnlist.h" 2 | #include 3 | #include 4 | 5 | namespace bpp { 6 | 7 | TableColumnList::TableColumnList(QObject *parent) : QObject(parent) 8 | { 9 | 10 | } 11 | 12 | TableColumnList::~TableColumnList() 13 | { 14 | clear(); 15 | } 16 | 17 | void TableColumnList::registerQml() 18 | { 19 | qmlRegisterType("BppTableModel", 0, 1, "BTColList"); 20 | } 21 | 22 | const QVector TableColumnList::getSortColumns() const 23 | { 24 | QVector sortColumns; 25 | 26 | int iCol(1); 27 | for(auto curColumn: def){ 28 | int sortVal = curColumn->sortFlag; 29 | if(sortVal == 1) 30 | sortColumns.push_back(iCol); 31 | if(sortVal == 2) 32 | sortColumns.push_back(-iCol); 33 | iCol++; 34 | } 35 | 36 | return sortColumns; 37 | } 38 | 39 | void TableColumnList::clear() 40 | { 41 | for(auto col: def){ 42 | delete col; 43 | } 44 | def.clear(); 45 | } 46 | 47 | int TableColumnList::add() 48 | { 49 | int newCol(def.size()); 50 | def.push_back( new TableColumn() ); 51 | return newCol; 52 | } 53 | 54 | void TableColumnList::modifyColumn(int columnId, bool withDefaults, const QVariantMap &colDef) 55 | { 56 | def[columnId]->modify(colDef, withDefaults); 57 | } 58 | 59 | const TableColumn &TableColumnList::operator[](int columnId) const 60 | { 61 | return *def[columnId]; 62 | } 63 | 64 | const TableColumn &TableColumnList::at(int columnId) const 65 | { 66 | return *def[columnId]; 67 | } 68 | 69 | QVariantList TableColumnList::getColumnMap() 70 | { 71 | QVariantList records; 72 | QVariantMap currentRecord; 73 | 74 | for(auto col: def){ 75 | currentRecord.clear(); 76 | currentRecord.insert("title", col->title); 77 | currentRecord.insert("dataType", col->type); 78 | currentRecord.insert("sort", col->sortFlag); 79 | currentRecord.insert("action", col->action); 80 | currentRecord.insert("command", col->command); 81 | currentRecord.insert("width", col->width); 82 | currentRecord.insert("minWidth", col->minWidth); 83 | currentRecord.insert("role", col->role); 84 | records.append(currentRecord); 85 | } 86 | 87 | return records; 88 | } 89 | 90 | bool TableColumnList::resizeColumns(int theWidth) 91 | { 92 | if(def.size() == 0) return false; 93 | if(theWidth <= 0) return false; 94 | 95 | int minWidth = 0; 96 | QSet toResize; 97 | 98 | for(int i=0; i < def.size(); i++){ 99 | if(def[i]->minWidth) { 100 | toResize.insert(i); 101 | minWidth += def[i]->minWidth; 102 | } 103 | } 104 | 105 | if(toResize.isEmpty()) return false; 106 | 107 | int usedWidth = 0; 108 | for(int i=0; i < def.size(); i++){ 109 | if(!toResize.contains(i)) { 110 | if(def[i]->width) 111 | usedWidth += def[i]->width; 112 | else 113 | usedWidth += 100; 114 | } 115 | } 116 | 117 | int newWidth = theWidth - usedWidth; 118 | if( newWidth < minWidth ) { 119 | //mantain min 120 | for(auto iCol: toResize) 121 | def[iCol]->width = def[iCol]->minWidth ; 122 | } 123 | else { 124 | double factor = double(newWidth) / double(minWidth); 125 | for(auto iCol: toResize) 126 | def[iCol]->width = int(floor(double(def[iCol]->minWidth) * factor)) ; 127 | } 128 | 129 | return true; 130 | } 131 | 132 | int TableColumnList::size() const 133 | { 134 | return def.size(); 135 | } 136 | 137 | void TableColumnList::swapSort(int columnId) 138 | { 139 | int sortVal = def[columnId]->sortFlag; 140 | 141 | sortVal++; 142 | if(sortVal > 2) sortVal = 0; 143 | 144 | def[columnId]->sortFlag = sortVal; 145 | } 146 | 147 | } 148 | -------------------------------------------------------------------------------- /CPP/CPPCD/src/bpbtable/bpptablecolumnlist.h: -------------------------------------------------------------------------------- 1 | #ifndef TABLECOLUMNLIST_H 2 | #define TABLECOLUMNLIST_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include "bpptablecolumn.h" 8 | 9 | namespace bpp { 10 | 11 | class TableColumnList : public QObject 12 | { 13 | Q_OBJECT 14 | public: 15 | explicit TableColumnList(QObject *parent = nullptr); 16 | virtual ~TableColumnList(); 17 | static void registerQml(); 18 | 19 | const QVector getSortColumns() const; 20 | 21 | Q_INVOKABLE void clear(); 22 | Q_INVOKABLE int add(); 23 | Q_INVOKABLE void modifyColumn(int columnId, bool withDefaults, const QVariantMap& colDef); 24 | Q_INVOKABLE int size() const; 25 | void swapSort(int columnId); 26 | const TableColumn& operator[] (int columnId) const; 27 | const TableColumn& at(int columnId) const; 28 | 29 | Q_INVOKABLE QVariantList getColumnMap(); 30 | Q_INVOKABLE bool resizeColumns(int theWidth); 31 | 32 | signals: 33 | 34 | public slots: 35 | 36 | protected: 37 | QVector def; 38 | }; 39 | 40 | } 41 | #endif // TABLECOLUMNLIST_H 42 | -------------------------------------------------------------------------------- /CPP/CPPCD/src/bpbtable/bpptabledatabase.cpp: -------------------------------------------------------------------------------- 1 | #include "bpptabledatabase.h" 2 | #include 3 | 4 | namespace bpp { 5 | 6 | TableDatabase::TableDatabase(QObject *parent) : QObject(parent) 7 | { 8 | 9 | } 10 | 11 | QSqlDatabase *TableDatabase::getDb() 12 | { 13 | return nullptr; 14 | } 15 | 16 | void TableDatabase::registerQml() 17 | { 18 | //qmlRegisterType("BppTableModel", 0, 1, "BTDb"); 19 | qmlRegisterType("BppTable", 0, 1, "BTDb"); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /CPP/CPPCD/src/bpbtable/bpptabledatabase.h: -------------------------------------------------------------------------------- 1 | #ifndef TABLEDATABASE_H 2 | #define TABLEDATABASE_H 3 | 4 | #include 5 | #include 6 | 7 | namespace bpp { 8 | 9 | class TableDatabase : public QObject 10 | { 11 | Q_OBJECT 12 | public: 13 | explicit TableDatabase(QObject *parent = nullptr); 14 | virtual ~TableDatabase() {} 15 | 16 | virtual QSqlDatabase* getDb(); 17 | 18 | static void registerQml(); 19 | signals: 20 | 21 | public slots: 22 | }; 23 | 24 | } 25 | #endif // TABLEDATABASE_H 26 | -------------------------------------------------------------------------------- /CPP/CPPCD/src/bpbtable/bpptableheading.cpp: -------------------------------------------------------------------------------- 1 | #include "bpptableheading.h" 2 | #include 3 | #include 4 | 5 | namespace bpp { 6 | 7 | TableHeading::TableHeading(QObject *parent) : 8 | QObject(parent) 9 | { 10 | 11 | } 12 | 13 | TableHeading::~TableHeading() 14 | { 15 | clearColumnsDef(); 16 | } 17 | 18 | int TableHeading::getColWidth(int columnId) const 19 | { 20 | if(columnId<0) 21 | return 100; 22 | 23 | if(!columnsDef[columnId]->visible) 24 | return 0; 25 | 26 | return columnsDef[columnId]->width; 27 | } 28 | 29 | void TableHeading::clearColumnsDef() 30 | { 31 | for(auto col: columnsDef){ 32 | delete col; 33 | } 34 | columnsDef.clear(); 35 | } 36 | 37 | int TableHeading::addColumnDef() 38 | { 39 | int newCol(columnsDef.size()); 40 | columnsDef.push_back( new TableColumn() ); 41 | return newCol; 42 | } 43 | 44 | void TableHeading::setColumnDef(int columnId, bool withDefaults, const QVariantMap &colDef) 45 | { 46 | columnsDef[columnId]->modify(colDef, withDefaults); 47 | } 48 | 49 | const TableColumn &TableHeading::getColumnDef(int columnId) const 50 | { 51 | return *columnsDef[columnId]; 52 | } 53 | 54 | int TableHeading::sizeColumnsDef() const 55 | { 56 | return columnsDef.size(); 57 | } 58 | 59 | void TableHeading::registerQml() 60 | { 61 | qmlRegisterType("BppTableModel", 0, 1, "BTHeading"); 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /CPP/CPPCD/src/bpbtable/bpptableheading.h: -------------------------------------------------------------------------------- 1 | #ifndef TABLEHEADING_H 2 | #define TABLEHEADING_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include "bpptablecolumn.h" 8 | 9 | namespace bpp { 10 | 11 | class TableHeading : public QObject 12 | { 13 | Q_OBJECT 14 | public: 15 | explicit TableHeading(QObject *parent = nullptr); 16 | virtual ~TableHeading(); 17 | 18 | Q_INVOKABLE int getColWidth(int columnId) const; 19 | Q_INVOKABLE void clearColumnsDef(); 20 | Q_INVOKABLE int addColumnDef(); 21 | Q_INVOKABLE void setColumnDef(int columnId, bool withDefaults, const QVariantMap& colDef); 22 | Q_INVOKABLE int sizeColumnsDef() const; 23 | const TableColumn& getColumnDef(int columnId) const; 24 | 25 | static void registerQml(); 26 | 27 | signals: 28 | 29 | public slots: 30 | 31 | private: 32 | QVector columnsDef; 33 | }; 34 | 35 | } 36 | 37 | #endif // TABLEHEADING_H 38 | -------------------------------------------------------------------------------- /CPP/CPPCD/src/bpbtable/bpptablemodel.h: -------------------------------------------------------------------------------- 1 | #ifndef TABLEMODEL1_H 2 | #define TABLEMODEL1_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include "bpptabledatabase.h" 8 | #include "bpptablecolumn.h" 9 | 10 | namespace bpp { 11 | 12 | class TableModel : public QAbstractTableModel 13 | { 14 | Q_OBJECT 15 | Q_PROPERTY(int highlightRow READ getHighlightRow NOTIFY highlightRowChanged) 16 | Q_PROPERTY(bool hasMultiselection READ getHasMultiselection WRITE setHasMultiselection NOTIFY hasMultiselectionChanged) 17 | Q_PROPERTY(bool multiselectionMobileMode READ getMultiselectionMobileMode WRITE setMultiselectionMobileMode NOTIFY multiselectionMobileModeChanged) 18 | public: 19 | 20 | enum CustomRoles{ 21 | roleDataType = Qt::UserRole, 22 | roleView, 23 | roleCommand, 24 | roleHighlight, 25 | roleVisible, 26 | roleRef1 27 | }; 28 | 29 | enum DataDialect{ 30 | Sqlite = 0, 31 | JsonISO 32 | }; 33 | 34 | TableModel(); 35 | virtual ~TableModel() override; 36 | 37 | int rowCount(const QModelIndex & = QModelIndex()) const override; 38 | int columnCount(const QModelIndex & = QModelIndex()) const override; 39 | QVariant data(const QModelIndex &cellIndex, int role) const override; 40 | 41 | //https://doc.qt.io/qt-5/qt.html#ItemDataRole-enum 42 | QHash roleNames() const override; 43 | 44 | Q_INVOKABLE void sortData(); 45 | 46 | Q_INVOKABLE void beginReset(bool appendMode); 47 | Q_INVOKABLE void endReset(); 48 | 49 | Q_INVOKABLE void addRecord(const QList& theData); 50 | Q_INVOKABLE bool addFromQuery(const QString& theSqlQuery, const QList& parameters); 51 | Q_INVOKABLE bool addFromList(const QVariantList& values, bool resetList = true); 52 | Q_INVOKABLE void setFrontRecords(const QVariantList& values); 53 | 54 | Q_INVOKABLE int countFromQuery(const QString& theSqlQuery, const QList& parameters); 55 | 56 | Q_INVOKABLE void setHighlightRow(int rowNum, int modifiers); 57 | Q_INVOKABLE void setHighlightRows(bool emptySel, const QVector& rowsIdx); 58 | Q_INVOKABLE int getHighlightRow() const; 59 | Q_INVOKABLE bool isHighlightRow(int rowNum) const; 60 | Q_INVOKABLE int countHighlightRows() const; 61 | Q_INVOKABLE QVector getHighlightRows() const; 62 | 63 | Q_INVOKABLE void dataNeedSort(); 64 | Q_INVOKABLE void updateLayout(); 65 | 66 | static void registerQml(); 67 | Q_INVOKABLE void setDbRef(bpp::TableDatabase *value); 68 | 69 | Q_INVOKABLE int getColWidth(int columnId) const; 70 | Q_INVOKABLE void clearColumnsDef(); 71 | const TableColumn& getColumnDef(int columnId) const; 72 | Q_INVOKABLE int getColumnId(const QString& columnRole); 73 | 74 | Q_INVOKABLE int addColumnDef(); 75 | Q_INVOKABLE void setColumnDef(int columnId, bool withDefaults, const QVariantMap& colDef); 76 | Q_INVOKABLE void endUpdateColumns(); 77 | 78 | Q_INVOKABLE bool canHideColumns(); 79 | 80 | Q_INVOKABLE bool copyRowToClipboard(int row) const; 81 | Q_INVOKABLE QString getRowString(int row) const; 82 | Q_INVOKABLE QVariantMap getRowObject(int row) const; 83 | 84 | Q_INVOKABLE bool setCellValue(int rowNum, int columnNum, const QVariant& data); 85 | 86 | bool getHasMultiselection() const; 87 | void setHasMultiselection(bool value); 88 | 89 | bool getMultiselectionMobileMode() const; 90 | void setMultiselectionMobileMode(bool value); 91 | 92 | signals: 93 | void highlightRowChanged(); 94 | void hasMultiselectionChanged(); 95 | void multiselectionMobileModeChanged(); 96 | 97 | protected: 98 | void appendDataVariant(QVector& record, const QVariant& theValue, TableColumn::ColumnType columnType, DataDialect dia); 99 | void calcSortColumns(); 100 | void calcReferenceColumns(); 101 | 102 | QVariant getDataDisplayRole(const QModelIndex &index) const; 103 | 104 | TableDatabase emptyDbRef; 105 | TableDatabase* dbRef; 106 | 107 | bool dataChangedALS; //new rows added or removed, After Last Sort 108 | bool columnsChangedALS; //new columns added or removed, After Last Sort 109 | bool sortedChangedALS; //to sort colmumn list changed, After Last Sort 110 | 111 | QVector sortColumns; //column ordinal, starting from 1 (not 0!) 112 | QVector columnsDef; 113 | 114 | int highlightRow; 115 | int lastHighlightRow; 116 | std::set highlightRows; 117 | bool hasMultiselection; 118 | bool multiselectionMobileMode; 119 | QVector< QVector > dataVal; 120 | QVector dataIndex; 121 | 122 | QVariantList addFrontRecords; 123 | 124 | QVariant emptyVString = QVariant(QVariant::String); 125 | QVariant emptyVDouble = QVariant(QVariant::Double); 126 | QVariant emptyVInt = QVariant(QVariant::Int); 127 | QVariant emptyVDate = QVariant(QVariant::Date); 128 | QVariant emptyVDateTime = QVariant(QVariant::DateTime); 129 | 130 | QVector onlyHighlightRole; 131 | }; 132 | 133 | } 134 | 135 | #endif // TABLEMODEL1_H 136 | -------------------------------------------------------------------------------- /CPP/CPPCD/src/import_qml_components_plugins.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is automatically generated by Qt Design Studio. 3 | * Do not change. 4 | */ 5 | 6 | #include "qqmlextensionplugin.h" 7 | 8 | #ifdef BULD_QDS_COMPONENTS 9 | 10 | Q_IMPORT_QML_PLUGIN(QtQuick_Studio_ComponentsPlugin) 11 | Q_IMPORT_QML_PLUGIN(QtQuick_Studio_EffectsPlugin) 12 | Q_IMPORT_QML_PLUGIN(QtQuick_Studio_ApplicationPlugin) 13 | Q_IMPORT_QML_PLUGIN(FlowViewPlugin) 14 | Q_IMPORT_QML_PLUGIN(QtQuick_Studio_LogicHelperPlugin) 15 | Q_IMPORT_QML_PLUGIN(QtQuick_Studio_MultiTextPlugin) 16 | Q_IMPORT_QML_PLUGIN(QtQuick_Studio_EventSimulatorPlugin) 17 | Q_IMPORT_QML_PLUGIN(QtQuick_Studio_EventSystemPlugin) 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /CPP/CPPCD/src/import_qml_plugins.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is automatically generated by Qt Design Studio. 3 | * Do not change. 4 | */ 5 | 6 | #include 7 | 8 | Q_IMPORT_QML_PLUGIN(contentPlugin) 9 | Q_IMPORT_QML_PLUGIN(YunaPlayerPlugin) 10 | 11 | -------------------------------------------------------------------------------- /CPP/CPPCD/src/main.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "app_environment.h" 9 | #include "import_qml_plugins.h" 10 | #include "MediaPlayer.h" 11 | 12 | #include "bpbtable/bpptablemodel.h" 13 | 14 | 15 | int main(int argc, char *argv[]) 16 | { 17 | set_qt_environment(); 18 | QGuiApplication app(argc, argv); 19 | 20 | QQmlApplicationEngine engine; 21 | const QUrl url(u"qml/Main/main.qml"_qs); 22 | QObject::connect( 23 | &engine, &QQmlApplicationEngine::objectCreated, &app, 24 | [url](QObject *obj, const QUrl &objUrl) { 25 | if (!obj && url == objUrl) 26 | QCoreApplication::exit(-1); 27 | }, 28 | Qt::QueuedConnection); 29 | 30 | engine.addImportPath(QCoreApplication::applicationDirPath() + "/qml"); 31 | engine.addImportPath(":/"); 32 | bpp::TableModel::registerQml(); 33 | engine.load(url); 34 | 35 | if (engine.rootObjects().isEmpty()) { 36 | return -1; 37 | } 38 | 39 | 40 | // Register QObject 41 | MediaPlayer player(&engine); 42 | engine.rootContext()->setContextProperty("player", &player); 43 | 44 | return app.exec(); 45 | } 46 | -------------------------------------------------------------------------------- /CPP/CPPTP/.gitignore: -------------------------------------------------------------------------------- 1 | # This file is used to ignore files which are generated 2 | # ---------------------------------------------------------------------------- 3 | 4 | *~ 5 | *.autosave 6 | *.a 7 | *.core 8 | *.moc 9 | *.o 10 | *.obj 11 | *.orig 12 | *.rej 13 | *.so 14 | *.so.* 15 | *_pch.h.cpp 16 | *_resource.rc 17 | *.qm 18 | .#* 19 | *.*# 20 | core 21 | !core/ 22 | tags 23 | .DS_Store 24 | .directory 25 | *.debug 26 | Makefile* 27 | *.prl 28 | *.app 29 | moc_*.cpp 30 | ui_*.h 31 | qrc_*.cpp 32 | Thumbs.db 33 | *.res 34 | *.rc 35 | /.qmake.cache 36 | /.qmake.stash 37 | 38 | # qtcreator generated files 39 | *.pro.user* 40 | CMakeLists.txt.user* 41 | 42 | # xemacs temporary files 43 | *.flc 44 | 45 | # Vim temporary files 46 | .*.swp 47 | 48 | # Visual Studio generated files 49 | *.ib_pdb_index 50 | *.idb 51 | *.ilk 52 | *.pdb 53 | *.sln 54 | *.suo 55 | *.vcproj 56 | *vcproj.*.*.user 57 | *.ncb 58 | *.sdf 59 | *.opensdf 60 | *.vcxproj 61 | *vcxproj.* 62 | 63 | # MinGW generated files 64 | *.Debug 65 | *.Release 66 | 67 | # Python byte code 68 | *.pyc 69 | 70 | # Binaries 71 | # -------- 72 | *.dll 73 | *.exe 74 | 75 | -------------------------------------------------------------------------------- /CPP/CPPTP/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5) 2 | 3 | project(CXXTP VERSION 0.1 LANGUAGES CXX) 4 | 5 | set(CMAKE_AUTOUIC ON) 6 | set(CMAKE_AUTOMOC ON) 7 | set(CMAKE_AUTORCC ON) 8 | 9 | set(CMAKE_CXX_STANDARD 17) 10 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 11 | 12 | find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets LinguistTools) 13 | find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets LinguistTools) 14 | 15 | # Google test 16 | include(FetchContent) 17 | FetchContent_Declare( 18 | googletest 19 | URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip 20 | ) 21 | # For Windows: Prevent overriding the parent project's compiler/linker settings 22 | set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) 23 | FetchContent_MakeAvailable(googletest) 24 | enable_testing() 25 | add_executable( 26 | SListTest 27 | test/SListTest.cpp 28 | test/SSetTest.cpp) 29 | target_link_libraries( 30 | SListTest 31 | GTest::gtest_main 32 | ) 33 | add_executable( 34 | SStackTest 35 | test/SStackTest.cpp 36 | 37 | SStack.h 38 | ) 39 | target_link_libraries( 40 | SStackTest 41 | GTest::gtest_main 42 | ) 43 | include(GoogleTest) 44 | gtest_discover_tests(SListTest) 45 | gtest_discover_tests(SStackTest) 46 | 47 | set(TS_FILES CXXTP_zh_CN.ts) 48 | 49 | set(PROJECT_SOURCES 50 | mainwindow.ui 51 | main.cpp 52 | ${TS_FILES} 53 | MainUI.h MainUI.cpp loginwindow.cpp loginwindow.h loginwindow.ui studentwindow.cpp studentwindow.h studentwindow.ui classcard.cpp classcard.h classcard.ui SList.h SStack.h SSet.h SSetting.cpp SSetting.h) 54 | 55 | if(${QT_VERSION_MAJOR} GREATER_EQUAL 6) 56 | qt_add_executable(CXXTP 57 | MANUAL_FINALIZATION 58 | ${PROJECT_SOURCES} 59 | ) 60 | # Define target properties for Android with Qt 6 as: 61 | # set_property(TARGET CXXTP APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR 62 | # ${CMAKE_CURRENT_SOURCE_DIR}/android) 63 | # For more information, see https://doc.qt.io/qt-6/qt-add-executable.html#target-creation 64 | 65 | qt_create_translation(QM_FILES ${CMAKE_SOURCE_DIR} ${TS_FILES}) 66 | else() 67 | if(ANDROID) 68 | add_library(CXXTP SHARED 69 | ${PROJECT_SOURCES} 70 | ) 71 | # Define properties for Android with Qt 5 after find_package() calls as: 72 | # set(ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android") 73 | else() 74 | add_executable(CXXTP 75 | ${PROJECT_SOURCES} 76 | ) 77 | endif() 78 | 79 | qt5_create_translation(QM_FILES ${CMAKE_SOURCE_DIR} ${TS_FILES}) 80 | endif() 81 | 82 | target_link_libraries(CXXTP PRIVATE Qt${QT_VERSION_MAJOR}::Widgets) 83 | 84 | set_target_properties(CXXTP PROPERTIES 85 | MACOSX_BUNDLE_GUI_IDENTIFIER my.example.com 86 | MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION} 87 | MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR} 88 | MACOSX_BUNDLE TRUE 89 | WIN32_EXECUTABLE TRUE 90 | ) 91 | 92 | install(TARGETS CXXTP 93 | BUNDLE DESTINATION . 94 | LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) 95 | 96 | if(QT_VERSION_MAJOR EQUAL 6) 97 | qt_finalize_executable(CXXTP) 98 | endif() 99 | -------------------------------------------------------------------------------- /CPP/CPPTP/CXXTP_zh_CN.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /CPP/CPPTP/MainUI.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by SkyRain on 2023/4/5. 3 | // 4 | #include "MainUI.h" 5 | #include 6 | 7 | CXXTP::MyMainWindow::MyMainWindow(QWidget* parent): QMainWindow(parent), w(), editStatus(false), index(0){ 8 | w.setupUi(this); 9 | w.tabWidget->setCurrentIndex(0); 10 | lessonList = SSetting::getLessonList(); 11 | refresh(); 12 | } 13 | [[maybe_unused]] void CXXTP::MyMainWindow::addData() { 14 | if(!editStatus){ 15 | auto item = new Lesson{ 16 | w.ClassNameLineEdit->text(), 17 | w.nameLineEdit->text(), 18 | w.classroomComboBox->currentText(), 19 | static_cast(w.ClassLimitSpinBox->value()), 20 | w.ClassWeekCombo->currentText(), 21 | w.ClassTimeCombo->currentText(), 22 | w.ClassDescEdit->toPlainText() 23 | }; 24 | lessonList->push_back(item); 25 | }else{ 26 | // Recover 27 | editStatus = false; 28 | delete (*lessonList)[index]; 29 | (*lessonList)[index] = new Lesson{ 30 | w.ClassNameLineEdit->text(), 31 | w.nameLineEdit->text(), 32 | w.classroomComboBox->currentText(), 33 | static_cast(w.ClassLimitSpinBox->value()), 34 | w.ClassWeekCombo->currentText(), 35 | w.ClassTimeCombo->currentText(), 36 | w.ClassDescEdit->toPlainText() 37 | }; 38 | w.saveButton->setText("保存"); 39 | w.clearButton->setText("清空"); 40 | } 41 | refresh(); 42 | } 43 | void CXXTP::MyMainWindow::clearInput() { 44 | editStatus = false; 45 | w.saveButton->setText("保存"); 46 | w.clearButton->setText("清空"); 47 | w.ClassNameLineEdit->clear(); 48 | w.nameLineEdit->clear(); 49 | w.classroomComboBox->setCurrentIndex(0); 50 | w.ClassLimitSpinBox->setValue(0); 51 | w.ClassWeekCombo->setCurrentIndex(0); 52 | w.ClassTimeCombo->setCurrentIndex(0); 53 | w.ClassDescEdit->clear(); 54 | } 55 | 56 | 57 | void CXXTP::MyMainWindow::clearData() { 58 | } 59 | 60 | void CXXTP::MyMainWindow::refresh() { 61 | auto table = w.treeWidget; 62 | table->clear(); 63 | for(int i=0; igetSize(); i++){ 64 | auto lesson = (*lessonList)[i]; 65 | auto item = new QTreeWidgetItem( 66 | QStringList() 67 | << QString::number(i+1) 68 | << lesson->name 69 | << lesson->teacherName 70 | << lesson->classroomName 71 | << QString::number(lesson->classCapacity) 72 | << lesson->week 73 | << lesson->time 74 | << lesson->description 75 | ); 76 | table->addTopLevelItem(item); 77 | } 78 | SSetting::save(); 79 | } 80 | [[maybe_unused]] void CXXTP::MyMainWindow::saveData() { 81 | CXXTP::SSetting::save(); 82 | } 83 | void CXXTP::MyMainWindow::contextMenu(const QPoint & pos) { 84 | auto item = w.treeWidget->itemAt(pos); 85 | if(item != nullptr){ 86 | auto menu = new QMenu(this); 87 | auto deleteAction = new QAction("删除"); 88 | connect(deleteAction, SIGNAL(triggered(bool)), this, SLOT(deleteData())); 89 | auto changeAction = new QAction("修改"); 90 | connect(changeAction, SIGNAL(triggered(bool)), this, SLOT(edit())); 91 | menu->addAction(deleteAction); 92 | menu->addAction(changeAction); 93 | menu->move(mapToGlobal(pos)); 94 | menu->show(); 95 | } 96 | } 97 | void CXXTP::MyMainWindow::deleteData() { 98 | auto item = w.treeWidget->currentItem(); 99 | if(item != nullptr){ 100 | bool ok = false; 101 | auto index = item->text(0).toInt(&ok)-1; 102 | if(ok){ 103 | lessonList->erase(index); 104 | refresh(); 105 | } 106 | } 107 | } 108 | void CXXTP::MyMainWindow::edit() { 109 | bool ok = false; 110 | this->index = w.treeWidget->currentItem()->text(0).toInt(&ok)-1; 111 | if(!ok) return; 112 | w.tabWidget->setCurrentIndex(0); 113 | editStatus = true; 114 | w.saveButton->setText("确认"); 115 | w.clearButton->setText("取消"); 116 | 117 | // Set texts 118 | auto item = (*lessonList)[index]; 119 | w.ClassNameLineEdit->setText(item->name); 120 | w.nameLineEdit->setText(item->teacherName); 121 | w.classroomComboBox->setEditText(item->classroomName); 122 | w.ClassLimitSpinBox->setValue(static_cast(item->classCapacity)); 123 | w.ClassWeekCombo->setCurrentText(item->week); 124 | w.ClassTimeCombo->setCurrentText(item->time); 125 | w.ClassDescEdit->setText(item->description); 126 | } 127 | 128 | void CXXTP::MyMainWindow::searchClear() { 129 | refresh(); 130 | } 131 | 132 | void CXXTP::MyMainWindow::search() { 133 | _search(); 134 | _search(); 135 | _search(); 136 | _search(); 137 | } 138 | void CXXTP::MyMainWindow::_search() { 139 | QTreeWidgetItemIterator it(w.treeWidget); 140 | while(*it){ 141 | auto item = *it; 142 | if(w.classnamecheckBox->isChecked() && 143 | !item->text(1).contains(w.classnamelineEdit->text(), Qt::CaseSensitive)){ 144 | delete item; 145 | it++; 146 | continue ; 147 | } 148 | if(w.teachernamecheckBox->isChecked() && 149 | !item->text(2).contains(w.teachernameEdit->text(), Qt::CaseSensitive)){ 150 | delete item; 151 | it++; 152 | continue; 153 | } 154 | if(w.timeCheckBox->isChecked()){ 155 | if(w.weekComboBox->currentText() != "任意" && item->text(5) !=w.weekComboBox->currentText()){ 156 | delete item; 157 | it++; 158 | continue ; 159 | } 160 | if(w.weekComboBox_2->currentText() != "任意" && item->text(6).contains(w.weekComboBox_2->currentText())){ 161 | delete item; 162 | it++; 163 | continue ; 164 | } 165 | } 166 | if(w.classroomCheckBox->isChecked() && 167 | item->text(3) !=w.classroomComboBox->currentText()){ 168 | delete item; 169 | it++; 170 | continue ; 171 | } 172 | it++; 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /CPP/CPPTP/MainUI.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by SkyRain on 2023/3/22. 3 | // 4 | 5 | #ifndef CXXTP_MAINUI_H 6 | #define CXXTP_MAINUI_H 7 | #include "SList.h" 8 | #include "SSetting.h" 9 | #include "ui_mainwindow.h" 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | namespace CXXTP { 18 | 19 | class MyMainWindow : public QMainWindow{ 20 | Q_OBJECT 21 | public: 22 | MyMainWindow(QWidget* parent= nullptr); 23 | ::Ui::MainWindow w{}; 24 | 25 | private: 26 | QStandardItemModel dataModel; 27 | QList*> dataList; 28 | CXXTP::SList* lessonList; 29 | bool editStatus; 30 | int index; 31 | void refresh(); 32 | public slots: 33 | void slotCatch(){ 34 | QMessageBox box(this); 35 | box.setWindowTitle("Click"); 36 | box.setDetailedText("You clicked this button!"); 37 | box.setText("You clicked the button!"); 38 | box.exec(); 39 | } 40 | 41 | void aboutSlot(){ 42 | QMessageBox box(this); 43 | box.setWindowTitle("About"); 44 | box.setDetailedText("Demo Program about QT6.0"); 45 | box.setText("Demo Program about QT6.0\nBuild with CMake Qt6 MSVC."); 46 | box.exec(); 47 | } 48 | 49 | [[maybe_unused]] void addData(); 50 | void clearData(); 51 | void clearInput(); 52 | [[maybe_unused]] void saveData(); 53 | void contextMenu(const QPoint&); 54 | void deleteData(); 55 | void edit(); 56 | void search(); 57 | void _search(); 58 | void searchClear(); 59 | }; 60 | } 61 | #endif // CXXTP_MAINUI_H 62 | -------------------------------------------------------------------------------- /CPP/CPPTP/SList.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by SkyRain on 2023/05/03. 3 | // 4 | 5 | #ifndef SLIST_H 6 | #define SLIST_H 7 | #include 8 | #include 9 | namespace CXXTP { 10 | 11 | template 12 | class SList { 13 | 14 | private: 15 | /** 16 | * List node presentation. 17 | */ 18 | struct Node { 19 | /** 20 | * Inner data 21 | */ 22 | T data; 23 | /** 24 | * Next node pointer. Default nulptr 25 | */ 26 | Node* next; 27 | /** 28 | * Previous node pointer. Default nulptr 29 | */ 30 | Node* prev; 31 | explicit Node(const T& d = T(), Node* n = nullptr, Node* p = nullptr) : data(d), next(n), prev(p) {} 32 | }; 33 | 34 | /** 35 | * First node 36 | */ 37 | Node* head; 38 | /** 39 | * Last node 40 | */ 41 | Node* tail; 42 | /** 43 | * List size 44 | */ 45 | std::size_t size; 46 | 47 | public: 48 | /** 49 | * Default constructor 50 | */ 51 | SList() : head(nullptr), tail(nullptr), size(0) {} 52 | /** 53 | * Copy constructor 54 | * @param other other list 55 | */ 56 | SList(const SList & other); 57 | /** 58 | * Equal constructor 59 | * @param other Other list 60 | * @return list reference 61 | */ 62 | SList & operator=(const SList & other); 63 | /** 64 | * Destructor 65 | */ 66 | ~SList(); 67 | 68 | /** 69 | * Add a value to its head 70 | * @param val value 71 | */ 72 | void push_front(const T& val); 73 | /** 74 | * Add a value to its tail 75 | * @param val value 76 | */ 77 | void push_back(const T& val); 78 | /** 79 | * Remove its front value. 80 | * If it does not have, do nothing. 81 | */ 82 | void pop_front(); 83 | /** 84 | * Remove its tail value. 85 | * If it does not have, do nothing. 86 | */ 87 | void pop_back(); 88 | /** 89 | * Clear list. Destruct all node pointer 90 | */ 91 | void clear(); 92 | /** 93 | * Indicate if the list is empty 94 | * @return bool value 95 | */ 96 | [[nodiscard]] bool empty() const; 97 | /** 98 | * Return its size 99 | * @return size 100 | */ 101 | [[nodiscard]] std::size_t getSize() const; 102 | /** 103 | * Get its front value 104 | * @return front value reference 105 | */ 106 | T& front(); 107 | /** 108 | * Get its front value constantly 109 | * @return constant front value reference 110 | */ 111 | const T& front() const; 112 | /** 113 | * Get its tail value 114 | * @return tail value reference 115 | */ 116 | T& back(); 117 | /** 118 | * Get its tail value constantly 119 | * @return constant tail value reference 120 | */ 121 | const T& back() const; 122 | /** 123 | * Insert a value 124 | * @param val value 125 | * @param pos position 126 | */ 127 | void insert(const T& val, std::size_t pos); 128 | /** 129 | * Delete a value 130 | * @param pos position 131 | */ 132 | void erase(std::size_t pos); 133 | /** 134 | * Index operator 135 | * @param i position 136 | * @return value 137 | */ 138 | T& operator[](const size_t i) const; 139 | }; 140 | 141 | template T &SList::operator[](const size_t i) const { 142 | if(i >= size){ 143 | throw std::out_of_range("List out of range"); 144 | } 145 | auto curr = head; 146 | for(int j=0; jnext; 148 | } 149 | return curr->data; 150 | } 151 | 152 | template SList::SList(const SList& other) { 153 | head = tail = nullptr; 154 | size = 0; 155 | for (Node* it = other.head; it != nullptr; it = it->next) { 156 | push_back(it->data); 157 | } 158 | } 159 | 160 | template SList&SList::operator=(const SList& other) { 161 | if (this != &other) { 162 | clear(); 163 | for (Node* it = other.head; it != nullptr; it = it->next) { 164 | push_back(it->data); 165 | } 166 | } 167 | return *this; 168 | } 169 | 170 | template SList::~SList() { 171 | clear(); 172 | } 173 | 174 | template 175 | void SList::push_front(const T& val) { 176 | Node* newNode = new Node(val, head, nullptr); 177 | if (head != nullptr) { 178 | head->prev = newNode; 179 | } else { 180 | tail = newNode; 181 | } 182 | head = newNode; 183 | ++size; 184 | } 185 | 186 | template 187 | void SList::push_back(const T& val) { 188 | Node* newNode = new Node(val, nullptr, tail); 189 | if (tail != nullptr) { 190 | tail->next = newNode; 191 | } else { 192 | head = newNode; 193 | } 194 | tail = newNode; 195 | ++size; 196 | } 197 | 198 | template 199 | void SList::pop_front() { 200 | if (head != nullptr) { 201 | Node* tmp = head; 202 | head = head->next; 203 | if (head != nullptr) { 204 | head->prev = nullptr; 205 | } else { 206 | tail = nullptr; 207 | } 208 | delete tmp; 209 | --size; 210 | } 211 | } 212 | 213 | template 214 | void SList::pop_back() { 215 | if (tail != nullptr) { 216 | Node* tmp = tail; 217 | tail = tail->prev; 218 | if (tail != nullptr) { 219 | tail->next = nullptr; 220 | } else { 221 | head = nullptr; 222 | } 223 | delete tmp; 224 | --size; 225 | } 226 | } 227 | 228 | template 229 | void SList::clear() { 230 | while (head != nullptr) { 231 | Node* tmp = head; 232 | head = head->next; 233 | delete tmp; 234 | } 235 | tail = nullptr; 236 | size = 0; 237 | } 238 | 239 | template 240 | bool SList::empty() const{ 241 | return size == 0; 242 | } 243 | 244 | template 245 | std::size_t SList::getSize() const { 246 | return size; 247 | } 248 | 249 | template 250 | T&SList::front() { 251 | return head->data; 252 | } 253 | 254 | template 255 | const T&SList::front() const { 256 | return head->data; 257 | } 258 | 259 | template 260 | T&SList::back() { 261 | return tail->data; 262 | } 263 | 264 | template 265 | const T&SList::back() const { 266 | return tail->data; 267 | } 268 | 269 | template 270 | void SList::insert(const T& val, std::size_t pos) { 271 | if (pos > size) { 272 | return; 273 | } 274 | if (pos == 0) { 275 | push_front(val); 276 | } else if (pos == size) { 277 | push_back(val); 278 | } else { 279 | Node* it = head; 280 | for (std::size_t i = 0; i < pos; ++i) { 281 | it = it->next; 282 | } 283 | Node* newNode = new Node(val, it, it->prev); 284 | it->prev->next = newNode; 285 | it->prev = newNode; 286 | ++size; 287 | } 288 | } 289 | 290 | template 291 | void SList::erase(std::size_t pos) { 292 | if (pos >= size) { 293 | return; 294 | } 295 | if (pos == 0) { 296 | pop_front(); 297 | } else if (pos == size - 1) { 298 | pop_back(); 299 | } else { 300 | Node* it = head; 301 | for (std::size_t i = 0; i < pos; ++i) { 302 | it = it->next; 303 | } 304 | it->prev->next = it->next; 305 | it->next->prev = it->prev; 306 | delete it; 307 | --size; 308 | } 309 | } 310 | 311 | } // namespace CXXTP 312 | #endif 313 | -------------------------------------------------------------------------------- /CPP/CPPTP/SSet.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by SkyRain on 2023/05/03. 3 | // 4 | 5 | #ifndef CXXTP_SSET_H 6 | #define CXXTP_SSET_H 7 | #include "SList.h" 8 | namespace CXXTP { 9 | template 10 | class SSet : public SList { 11 | public: 12 | SSet() = default; 13 | 14 | // 求集合差 15 | SSet operator- (const SSet& rhs) const { 16 | SSet result; 17 | for(int i=0; ioperator[](i))){ 19 | result.push_back(this->operator[](i)); 20 | } 21 | } 22 | return result; 23 | } 24 | 25 | // 求集合并 26 | SSet operator+ (const SSet& rhs) const { 27 | SSet result = *this; 28 | for(int i=0; i and_(const SSet& rhs) const { 38 | SSet result; 39 | for(int i=0; ioperator[](i))){ 41 | result.push_back(this->operator[](i)); 42 | } 43 | } 44 | return result; 45 | } 46 | 47 | // 判断元素是否在集合中 48 | bool contains(const T& item) const { 49 | for(int i=0; ioperator[](i)){ 51 | return true; 52 | } 53 | } 54 | return false; 55 | } 56 | }; 57 | 58 | } 59 | #endif // CXXTP_SSET_H 60 | -------------------------------------------------------------------------------- /CPP/CPPTP/SSetting.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by SkyRain on 2023/05/03. 3 | // 4 | 5 | 6 | #include "SSetting.h" 7 | #include 8 | using namespace std; 9 | static QSettings* settings; 10 | static CXXTP::SList* userList; 11 | static CXXTP::SList* lessonList; 12 | 13 | void CXXTP::SSetting::init() { 14 | settings = new QSettings("settings.ini", QSettings::IniFormat); 15 | userList = new SList; 16 | lessonList = new SList; 17 | settings->beginGroup("User"); 18 | auto result = settings->value("user", "").toStringList(); 19 | settings->endGroup(); 20 | auto lessonSize = settings->beginReadArray("Lesson"); 21 | for(int i=0; isetArrayIndex(i); 23 | auto item = new Lesson{ 24 | settings->value("name", "Default").toString(), 25 | settings->value("teacherName", "LiMing").toString(), 26 | settings->value("classroomName", "Classroom1").toString(), 27 | settings->value("classCapacity", 0).toUInt(), 28 | settings->value("week", "星期一").toString(), 29 | settings->value("time", "第一节课").toString(), 30 | settings->value("description", "Default").toString() 31 | }; 32 | lessonList->push_back(item); 33 | } 34 | settings->endArray(); 35 | if(!result.empty()){ 36 | for(const auto& item:result){ 37 | auto k = item.split("@"); 38 | if(k.size() != 2) 39 | continue ; 40 | auto i = new User{ 41 | k[0], 42 | k[1] 43 | }; 44 | qDebug() << k[0] << k[1]; 45 | userList->push_back(i); 46 | } 47 | } 48 | } 49 | CXXTP::AuthResult CXXTP::SSetting::authUser(const QString &username, 50 | const QString &password) { 51 | if(username == "admin" && password == "admin@YSU"){ 52 | return ADMIN; 53 | } 54 | for(int i=0; igetSize(); i++){ 55 | auto item = (*userList)[i]; 56 | if(username == item->username && password == item->password){ 57 | return STUDENT; 58 | } 59 | } 60 | return CXXTP::ERROR; 61 | } 62 | void CXXTP::SSetting::addUser(const QString &username, 63 | const QString &password) { 64 | for(int i=0; igetSize(); i++){ 65 | auto item = (*userList)[i]; 66 | if(item->username == username){ 67 | item->password = password; 68 | return; 69 | } 70 | } 71 | userList->push_back(new User{username, password}); 72 | save(); 73 | } 74 | void CXXTP::SSetting::save() { 75 | QStringList userSaveList; 76 | for(int i=0; igetSize(); i++){ 77 | auto item = (*userList)[i]; 78 | userSaveList.push_back(item->username+"@"+item->password); 79 | } 80 | settings->beginGroup("User"); 81 | settings->setValue("user", userSaveList); 82 | settings->endGroup(); 83 | settings->beginWriteArray("Lesson"); 84 | for(int i=0; igetSize(); i++){ 85 | settings->setArrayIndex(i); 86 | auto item = (*lessonList)[i]; 87 | settings->setValue("name", item->name); 88 | settings->setValue("teacherName", item->teacherName); 89 | settings->setValue("classroomName", item->classroomName); 90 | settings->setValue("classCapacity", item->classCapacity); 91 | settings->setValue("week", item->week); 92 | settings->setValue("time", item->time); 93 | settings->setValue("description", item->description); 94 | } 95 | settings->endArray(); 96 | } 97 | CXXTP::SList *CXXTP::SSetting::getLessonList() { 98 | return lessonList; 99 | } 100 | 101 | QSettings *CXXTP::SSetting::getGlobalSettings() { 102 | return settings; 103 | } 104 | 105 | bool CXXTP::User::operator==(const CXXTP::User & rhs) const { 106 | return username == rhs.username && password == rhs.password; 107 | } 108 | -------------------------------------------------------------------------------- /CPP/CPPTP/SSetting.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by SkyRain on 2023/05/03. 3 | // 4 | 5 | #ifndef CXXTP_SSETTING_H 6 | #define CXXTP_SSETTING_H 7 | #include "QString" 8 | #include "QSettings" 9 | #include "SList.h" 10 | namespace CXXTP { 11 | enum AuthResult{ 12 | ADMIN, 13 | STUDENT, 14 | ERROR 15 | }; 16 | struct User{ 17 | QString username; 18 | QString password; 19 | bool operator==(const User&) const; 20 | }; 21 | struct Lesson{ 22 | QString name; 23 | QString teacherName; 24 | QString classroomName; 25 | unsigned int classCapacity; 26 | QString week; 27 | QString time; 28 | QString description; 29 | }; 30 | 31 | class SSetting { 32 | public: 33 | /** 34 | * Auth user with username and password 35 | * @param username Username 36 | * @param password Password 37 | * @return One enum in AuthResult indicating auth result. 38 | */ 39 | static AuthResult authUser(const QString& username, const QString& password); 40 | /** 41 | * Add user to database 42 | * @param username Username 43 | * @param password Password 44 | */ 45 | static void addUser(const QString& username, const QString& password); 46 | /** 47 | * Explicitly save data to file 48 | */ 49 | static void save(); 50 | /** 51 | * Get lession list pointer 52 | * @return Lession list 53 | */ 54 | static CXXTP::SList* getLessonList(); 55 | /** 56 | * Init settings. It should be call only on application init. 57 | */ 58 | static void init(); 59 | /** 60 | * Get QSettings pointer. It is used in studentwindow for user data reading. 61 | * @return 62 | */ 63 | static QSettings* getGlobalSettings(); 64 | /** 65 | * Default constructor 66 | */ 67 | SSetting() = default; 68 | }; 69 | } 70 | #endif // CXXTP_SSETTING_H 71 | -------------------------------------------------------------------------------- /CPP/CPPTP/SStack.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by SkyRain on 2023/05/03. 3 | // 4 | 5 | #ifndef CXXTP_SSTACK_H 6 | #define CXXTP_SSTACK_H 7 | #include "SList.h" 8 | namespace CXXTP { 9 | template 10 | class SStack : private SList { 11 | public: 12 | /** 13 | * If it is empty 14 | * @return is empty 15 | */ 16 | bool empty() const { return SList::empty(); } 17 | /** 18 | * Return size 19 | * @return size 20 | */ 21 | size_t size() const { return SList::getSize(); } 22 | /** 23 | * Return top value 24 | * @return top value 25 | */ 26 | T& top() { return SList::back(); } 27 | /** 28 | * Return top value constantly 29 | * @return constant top value 30 | */ 31 | const T& top() const { return SList::back(); } 32 | /** 33 | * Push in top value 34 | * @param value value 35 | */ 36 | void push(const T &value) { SList::push_back(value); } 37 | /** 38 | * Pop out value 39 | */ 40 | void pop() { SList::pop_back(); } 41 | }; 42 | 43 | } 44 | #endif // CXXTP_SSTACK_H 45 | -------------------------------------------------------------------------------- /CPP/CPPTP/classcard.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by SkyRain on 2023/04/25. 3 | // 4 | 5 | // You may need to build the project (run Qt uic code generator) to get 6 | // "ui_ClassCard.h" resolved 7 | 8 | #include "classcard.h" 9 | #include "ui_ClassCard.h" 10 | #include "studentwindow.h" 11 | namespace CXXTP { 12 | ClassCard::ClassCard(const Lesson& lesson, const int id, QWidget *parent) : QWidget(parent), id(id), p(parent),ui(new Ui::ClassCard){ 13 | ui->setupUi(this); 14 | ui->classname->setText(lesson.name); 15 | ui->teachername->setText(lesson.teacherName); 16 | ui->classtime->setText(lesson.week + " " + lesson.time); 17 | ui->description->setText(lesson.description); 18 | ui->electStatus->setText("容量 "+QString::number(lesson.classCapacity)+" 人"); 19 | } 20 | 21 | ClassCard::~ClassCard() { delete ui; } 22 | void ClassCard::elect() { 23 | auto w = dynamic_cast(p); 24 | w->electClass(id, this); 25 | } 26 | ClassCard::ClassCard() : id(0) { 27 | ui->setupUi(this); 28 | } 29 | } // namespace CXXTP 30 | -------------------------------------------------------------------------------- /CPP/CPPTP/classcard.h: -------------------------------------------------------------------------------- 1 | #ifndef CXXTP_CLASSCARD_H 2 | #define CXXTP_CLASSCARD_H 3 | 4 | #include 5 | #include "SSetting.h" 6 | 7 | namespace CXXTP { 8 | QT_BEGIN_NAMESPACE 9 | namespace Ui { 10 | class ClassCard; 11 | } 12 | QT_END_NAMESPACE 13 | 14 | /* 15 | * class ClassCard: Single card display module. 16 | */ 17 | class ClassCard : public QWidget { 18 | Q_OBJECT 19 | 20 | public: 21 | ClassCard(const Lesson&, int id, QWidget *parent = nullptr); 22 | ClassCard(); 23 | ~ClassCard() override; 24 | Ui::ClassCard *ui{}; 25 | 26 | private: 27 | const int id; 28 | QWidget* p; 29 | private slots: 30 | void elect(); 31 | }; 32 | } // namespace CXXTP 33 | 34 | #endif // CXXTP_CLASSCARD_H 35 | -------------------------------------------------------------------------------- /CPP/CPPTP/classcard.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | CXXTP::ClassCard 4 | 5 | 6 | 7 | 0 8 | 0 9 | 218 10 | 149 11 | 12 | 13 | 14 | 15 | 218 16 | 149 17 | 18 | 19 | 20 | ClassCard 21 | 22 | 23 | background-color: #cfe9d9; 24 | 25 | 26 | 27 | 28 | 0 29 | 30 | 31 | 0 32 | 33 | 34 | 0 35 | 36 | 37 | 0 38 | 39 | 40 | 0 41 | 42 | 43 | 44 | 45 | 0 46 | 47 | 48 | QLayout::SetDefaultConstraint 49 | 50 | 51 | 52 | 53 | 54 | 0 55 | 0 56 | 57 | 58 | 59 | font: bold; 60 | font-size: 20px; 61 | 62 | 63 | 李大海的课 64 | 65 | 66 | Qt::AlignCenter 67 | 68 | 69 | 70 | 71 | 72 | 73 | 李大海 74 | 75 | 76 | Qt::AlignCenter 77 | 78 | 79 | 80 | 81 | 82 | 83 | 0 84 | 85 | 86 | 0 87 | 88 | 89 | 0 90 | 91 | 92 | 93 | 94 | padding-left: 0.2em; 95 | 96 | 97 | 周一 第一节 98 | 99 | 100 | 101 | 102 | 103 | 104 | padding-right: 0.2em; 105 | 106 | 107 | 教室1 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 0 117 | 118 | 119 | 0 120 | 121 | 122 | 0 123 | 124 | 125 | 126 | 127 | padding-left: 0.2em; 128 | padding-right: 0.2em; 129 | 130 | 131 | 这是李大海的水课,讲点没什么用的东西 132 | 这是第二行 133 | 134 | 135 | true 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 0 145 | 146 | 147 | 0 148 | 149 | 150 | 151 | 152 | padding-left: 0.2em; 153 | 154 | 155 | 1/100人已选 156 | 157 | 158 | 159 | 160 | 161 | 162 | true 163 | 164 | 165 | QPushButton{ 166 | border-radius: 0.2em; 167 | width: 7em; 168 | background-color: rgb(49, 122, 121); 169 | color: rgb(255, 255, 255); 170 | outline: none; 171 | height: 1.5em; 172 | } 173 | QPushButton:disabled{ 174 | background-color: rgb(181, 181, 181); 175 | } 176 | 177 | 178 | 选课 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | electButton 192 | clicked() 193 | CXXTP::ClassCard 194 | elect() 195 | 196 | 197 | 162 198 | 132 199 | 200 | 201 | 168 202 | 196 203 | 204 | 205 | 206 | 207 | 208 | elect() 209 | 210 | 211 | -------------------------------------------------------------------------------- /CPP/CPPTP/loginwindow.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by SkyRain on 2023/04/17. 3 | // 4 | 5 | // You may need to build the project (run Qt uic code generator) to get 6 | // "ui_LoginWindow.h" resolved 7 | 8 | #include "loginwindow.h" 9 | #include "ui_LoginWindow.h" 10 | #include "MainUI.h" 11 | #include "studentwindow.h" 12 | #include "SSetting.h" 13 | 14 | namespace CXXTP { 15 | LoginWindow::LoginWindow(QWidget *parent) 16 | : QWidget(parent), ui(new Ui::LoginWindow) { 17 | ui->setupUi(this); 18 | } 19 | 20 | LoginWindow::~LoginWindow() { delete ui; } 21 | void LoginWindow::login() { 22 | auto username = ui->usernameField->text(); 23 | auto password = ui->passwordField->text(); 24 | switch(CXXTP::SSetting::authUser(username, password)){ 25 | case ADMIN: 26 | this->close(); 27 | (new MyMainWindow)->show(); 28 | break; 29 | case STUDENT: 30 | this->close(); 31 | (new studentwindow(username))->show(); 32 | break; 33 | case ERROR: 34 | ui->infoLabel->setText("用户名或密码错误"); 35 | break; 36 | } 37 | } 38 | void LoginWindow::reg() { 39 | auto username = ui->usernameField->text(); 40 | auto password = ui->passwordField->text(); 41 | CXXTP::SSetting::addUser(username, password); 42 | ui->infoLabel->setText("注册成功"); 43 | } 44 | } // namespace CXXTP 45 | -------------------------------------------------------------------------------- /CPP/CPPTP/loginwindow.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by SkyRain on 2023/04/17. 3 | // 4 | 5 | #ifndef CXXTP_LOGINWINDOW_H 6 | #define CXXTP_LOGINWINDOW_H 7 | 8 | #include 9 | 10 | namespace CXXTP { 11 | QT_BEGIN_NAMESPACE 12 | namespace Ui { 13 | class LoginWindow; 14 | } 15 | QT_END_NAMESPACE 16 | 17 | class LoginWindow : public QWidget { 18 | Q_OBJECT 19 | 20 | public: 21 | explicit LoginWindow(QWidget *parent = nullptr); 22 | ~LoginWindow() override; 23 | private: 24 | Ui::LoginWindow *ui; 25 | private slots: 26 | void login(); 27 | void reg(); 28 | }; 29 | } // namespace CXXTP 30 | 31 | #endif // CXXTP_LOGINWINDOW_H 32 | -------------------------------------------------------------------------------- /CPP/CPPTP/loginwindow.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | CXXTP::LoginWindow 4 | 5 | 6 | 7 | 0 8 | 0 9 | 700 10 | 400 11 | 12 | 13 | 14 | 15 | 0 16 | 0 17 | 18 | 19 | 20 | 21 | 700 22 | 400 23 | 24 | 25 | 26 | 27 | 700 28 | 400 29 | 30 | 31 | 32 | 选课管理系统 33 | 34 | 35 | background: rgb(255, 255, 255) 36 | 37 | 38 | 39 | 0 40 | 41 | 42 | 0 43 | 44 | 45 | 0 46 | 47 | 48 | 0 49 | 50 | 51 | 0 52 | 53 | 54 | 55 | 56 | false 57 | 58 | 59 | background: #dbe5dd 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | Qt::Horizontal 74 | 75 | 76 | QSizePolicy::Minimum 77 | 78 | 79 | 80 | 40 81 | 20 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 10 90 | 91 | 92 | 93 | 94 | Qt::Vertical 95 | 96 | 97 | QSizePolicy::MinimumExpanding 98 | 99 | 100 | 101 | 20 102 | 10 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 0 112 | 0 113 | 114 | 115 | 116 | 117 | 18 118 | 119 | 120 | 121 | 选课管理系统 122 | 123 | 124 | Qt::AlignCenter 125 | 126 | 127 | 128 | 129 | 130 | 131 | 10 132 | 133 | 134 | 135 | 136 | 137 | 0 138 | 0 139 | 140 | 141 | 142 | 143 | 0 144 | 30 145 | 146 | 147 | 148 | QLineEdit { 149 | background-color: rgb(245, 245, 245); 150 | border-radius: 1em; 151 | } 152 | QLineEdit:focus { 153 | background-color: rgb(235, 235, 235); 154 | } 155 | 156 | 157 | 20 158 | 159 | 160 | Qt::AlignCenter 161 | 162 | 163 | false 164 | 165 | 166 | 用户名 167 | 168 | 169 | Qt::LogicalMoveStyle 170 | 171 | 172 | false 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 0 181 | 0 182 | 183 | 184 | 185 | 186 | 0 187 | 30 188 | 189 | 190 | 191 | QLineEdit { 192 | background-color: rgb(245, 245, 245); 193 | border-radius: 1em; 194 | } 195 | QLineEdit:focus { 196 | background-color: rgb(235, 235, 235); 197 | } 198 | 199 | 200 | 20 201 | 202 | 203 | QLineEdit::Password 204 | 205 | 206 | Qt::AlignCenter 207 | 208 | 209 | 密码 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 20 219 | 220 | 221 | 20 222 | 223 | 224 | 5 225 | 226 | 227 | 20 228 | 229 | 230 | 231 | 232 | 233 | 0 234 | 30 235 | 236 | 237 | 238 | border-radius: 0.3em; 239 | width: 7em; 240 | background-color: rgb(49, 122, 121); 241 | color: rgb(255, 255, 255); 242 | outline: none; 243 | 244 | 245 | 登录 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 0 254 | 30 255 | 256 | 257 | 258 | border-radius: 0.3em; 259 | width: 7em; 260 | border-color: rgb(49, 122, 121); 261 | background-color: rgb(255, 255, 255); 262 | border-width: 0.05em; 263 | border-style:solid; 264 | outline: none; 265 | 266 | 267 | 注册 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 8 278 | 279 | 280 | 281 | color: rgb(255, 0, 0); 282 | 283 | 284 | 285 | 286 | 287 | Qt::AlignCenter 288 | 289 | 290 | 291 | 292 | 293 | 294 | Qt::Vertical 295 | 296 | 297 | 298 | 20 299 | 40 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | Qt::Horizontal 310 | 311 | 312 | QSizePolicy::Minimum 313 | 314 | 315 | 316 | 40 317 | 20 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | imgLabel 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | registerButton 336 | clicked() 337 | CXXTP::LoginWindow 338 | reg() 339 | 340 | 341 | 630 342 | 266 343 | 344 | 345 | 254 346 | 376 347 | 348 | 349 | 350 | 351 | loginButton 352 | clicked() 353 | CXXTP::LoginWindow 354 | login() 355 | 356 | 357 | 503 358 | 266 359 | 360 | 361 | 139 362 | 404 363 | 364 | 365 | 366 | 367 | usernameField 368 | returnPressed() 369 | loginButton 370 | click() 371 | 372 | 373 | 492 374 | 166 375 | 376 | 377 | 470 378 | 256 379 | 380 | 381 | 382 | 383 | passwordField 384 | returnPressed() 385 | loginButton 386 | click() 387 | 388 | 389 | 502 390 | 203 391 | 392 | 393 | 448 394 | 259 395 | 396 | 397 | 398 | 399 | 400 | login() 401 | reg() 402 | 403 | 404 | -------------------------------------------------------------------------------- /CPP/CPPTP/main.cpp: -------------------------------------------------------------------------------- 1 | #include "ui_mainwindow.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "SSetting.h" 8 | #include "loginwindow.h" 9 | 10 | int main(int argc, char *argv[]) 11 | { 12 | QApplication a(argc, argv); 13 | 14 | QTranslator translator; 15 | const QStringList uiLanguages = QLocale::system().uiLanguages(); 16 | for (const QString &locale : uiLanguages) { 17 | const QString baseName = "CXXTP_" + QLocale(locale).name(); 18 | if (translator.load(":/i18n/" + baseName)) { 19 | a.installTranslator(&translator); 20 | break; 21 | } 22 | } 23 | 24 | // CXXTP::MyMainWindow mainWindow; 25 | // mainWindow.show(); 26 | 27 | CXXTP::SSetting::init(); 28 | CXXTP::LoginWindow w; 29 | w.show(); 30 | auto r = a.exec(); 31 | CXXTP::SSetting::save(); 32 | return r; 33 | } 34 | -------------------------------------------------------------------------------- /CPP/CPPTP/mainwindow.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | MainWindow 4 | 5 | 6 | 7 | 0 8 | 0 9 | 775 10 | 359 11 | 12 | 13 | 14 | MainWindow 15 | 16 | 17 | 18 | 19 | 20 | 21 | Qt::CustomContextMenu 22 | 23 | 24 | true 25 | 26 | 27 | true 28 | 29 | 30 | 20 31 | 32 | 33 | 100 34 | 35 | 36 | true 37 | 38 | 39 | true 40 | 41 | 42 | 43 | ID 44 | 45 | 46 | 47 | 48 | 课程名称 49 | 50 | 51 | 52 | 53 | 任课教师 54 | 55 | 56 | 57 | 58 | 教室 59 | 60 | 61 | 62 | 63 | 课程容量 64 | 65 | 66 | 67 | 68 | 开课周 69 | 70 | 71 | 72 | 73 | 开课节 74 | 75 | 76 | 77 | 78 | 课程描述 79 | 80 | 81 | 82 | 83 | 1 84 | 85 | 86 | 李大海的课 87 | 88 | 89 | 李大海 90 | 91 | 92 | 教室1 93 | 94 | 95 | 100 96 | 97 | 98 | 星期二第四节课 99 | 100 | 101 | 102 | 103 | 104 | 这是李大海的水课 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 0 113 | 114 | 115 | 116 | Edit 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 课程名称 125 | 126 | 127 | 128 | 129 | 130 | 131 | Qt::NoContextMenu 132 | 133 | 134 | 135 | 136 | 137 | 138 | 任课教师 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 教室 149 | 150 | 151 | 152 | 153 | 154 | 155 | true 156 | 157 | 158 | 159 | 教室1 160 | 161 | 162 | 163 | 164 | 教室2 165 | 166 | 167 | 168 | 169 | 教室3 170 | 171 | 172 | 173 | 174 | 教室4 175 | 176 | 177 | 178 | 179 | 教室5 180 | 181 | 182 | 183 | 184 | 教室6 185 | 186 | 187 | 188 | 189 | 教室7 190 | 191 | 192 | 193 | 194 | 教室8 195 | 196 | 197 | 198 | 199 | 教室9 200 | 201 | 202 | 203 | 204 | 教室10 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 课程容量 213 | 214 | 215 | 216 | 217 | 218 | 219 | 1000 220 | 221 | 222 | 223 | 224 | 225 | 226 | 开课时间 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 星期一 237 | 238 | 239 | 240 | 241 | 星期二 242 | 243 | 244 | 245 | 246 | 星期三 247 | 248 | 249 | 250 | 251 | 星期四 252 | 253 | 254 | 255 | 256 | 星期五 257 | 258 | 259 | 260 | 261 | 星期六 262 | 263 | 264 | 265 | 266 | 星期日 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 第一节课 276 | 277 | 278 | 279 | 280 | 第二节课 281 | 282 | 283 | 284 | 285 | 第三节课 286 | 287 | 288 | 289 | 290 | 第四节课 291 | 292 | 293 | 294 | 295 | 第五节课 296 | 297 | 298 | 299 | 300 | 第六节课 301 | 302 | 303 | 304 | 305 | 第七节课 306 | 307 | 308 | 309 | 310 | 第八节课 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 课程描述 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | QLayout::SetMinimumSize 333 | 334 | 335 | 336 | 337 | border-radius: 0.1em; 338 | width: 7em; 339 | height: 1.5em; 340 | color: #FFFFFF; 341 | background-color: rgb(49, 122, 121); 342 | border-width: 0.05em; 343 | border-style:solid; 344 | 345 | 346 | 保存 347 | 348 | 349 | 350 | 351 | 352 | 353 | border-radius: 0.1em; 354 | height: 1.45em; 355 | border-color: rgb(49, 122, 121); 356 | background-color: rgb(255, 255, 255); 357 | border-width: 0.05em; 358 | border-style:solid; 359 | outline: none; 360 | 361 | 362 | 清空 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | Search 373 | 374 | 375 | 376 | QLayout::SetMaximumSize 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 课程名称 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 开课教师 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 开课时间 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 任意 424 | 425 | 426 | 427 | 428 | 星期一 429 | 430 | 431 | 432 | 433 | 星期二 434 | 435 | 436 | 437 | 438 | 星期三 439 | 440 | 441 | 442 | 443 | 星期四 444 | 445 | 446 | 447 | 448 | 星期五 449 | 450 | 451 | 452 | 453 | 星期六 454 | 455 | 456 | 457 | 458 | 星期日 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 任意 468 | 469 | 470 | 471 | 472 | 第一节 473 | 474 | 475 | 476 | 477 | 第二节 478 | 479 | 480 | 481 | 482 | 第三节 483 | 484 | 485 | 486 | 487 | 第四节 488 | 489 | 490 | 491 | 492 | 第五节 493 | 494 | 495 | 496 | 497 | 第六节 498 | 499 | 500 | 501 | 502 | 第七节 503 | 504 | 505 | 506 | 507 | 第八节 508 | 509 | 510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 | 518 | 519 | 520 | 521 | 教室 522 | 523 | 524 | 525 | 526 | 527 | 528 | true 529 | 530 | 531 | 532 | 教室1 533 | 534 | 535 | 536 | 537 | 教室2 538 | 539 | 540 | 541 | 542 | 教室3 543 | 544 | 545 | 546 | 547 | 教室4 548 | 549 | 550 | 551 | 552 | 教室5 553 | 554 | 555 | 556 | 557 | 教室6 558 | 559 | 560 | 561 | 562 | 教室7 563 | 564 | 565 | 566 | 567 | 教室8 568 | 569 | 570 | 571 | 572 | 教室9 573 | 574 | 575 | 576 | 577 | 教室10 578 | 579 | 580 | 581 | 582 | 583 | 584 | 585 | 586 | 587 | Qt::Vertical 588 | 589 | 590 | 591 | 20 592 | 40 593 | 594 | 595 | 596 | 597 | 598 | 599 | 600 | border-radius: 0.1em; 601 | width: 7em; 602 | height: 1.5em; 603 | color: #FFFFFF; 604 | background-color: rgb(49, 122, 121); 605 | border-width: 0.05em; 606 | border-style:solid; 607 | 608 | 609 | 搜索 610 | 611 | 612 | 613 | 614 | 615 | 616 | border-radius: 0.1em; 617 | height: 1.45em; 618 | border-color: rgb(49, 122, 121); 619 | background-color: rgb(255, 255, 255); 620 | border-width: 0.05em; 621 | border-style:solid; 622 | outline: none; 623 | 624 | 625 | 清空 626 | 627 | 628 | 629 | 630 | 631 | 632 | 633 | 634 | 635 | 636 | 637 | 638 | 639 | 640 | 0 641 | 0 642 | 775 643 | 22 644 | 645 | 646 | 647 | 648 | File 649 | 650 | 651 | 652 | 653 | 654 | 655 | 656 | 657 | About 658 | 659 | 660 | 661 | 662 | 663 | 664 | Edit 665 | 666 | 667 | 668 | 669 | 670 | 671 | 672 | 673 | 674 | 675 | 676 | 677 | Open 678 | 679 | 680 | 681 | 682 | Recent 683 | 684 | 685 | 686 | 687 | Close 688 | 689 | 690 | 691 | 692 | Help 693 | 694 | 695 | 696 | 697 | About 698 | 699 | 700 | 701 | 702 | Save 703 | 704 | 705 | 706 | 707 | Undo 708 | 709 | 710 | 711 | 712 | Redo 713 | 714 | 715 | 716 | 717 | 718 | 719 | actionAbout 720 | triggered() 721 | MainWindow 722 | aboutSlot() 723 | 724 | 725 | -1 726 | -1 727 | 728 | 729 | 289 730 | 206 731 | 732 | 733 | 734 | 735 | actionSave 736 | triggered() 737 | MainWindow 738 | saveData() 739 | 740 | 741 | -1 742 | -1 743 | 744 | 745 | 387 746 | 179 747 | 748 | 749 | 750 | 751 | treeWidget 752 | customContextMenuRequested(QPoint) 753 | MainWindow 754 | contextMenu(QPoint) 755 | 756 | 757 | 146 758 | 158 759 | 760 | 761 | 146 762 | 407 763 | 764 | 765 | 766 | 767 | treeWidget 768 | doubleClicked(QModelIndex) 769 | MainWindow 770 | edit() 771 | 772 | 773 | 150 774 | 64 775 | 776 | 777 | 268 778 | 414 779 | 780 | 781 | 782 | 783 | saveButton 784 | clicked() 785 | MainWindow 786 | addData() 787 | 788 | 789 | 596 790 | 300 791 | 792 | 793 | 596 794 | 399 795 | 796 | 797 | 798 | 799 | clearButton 800 | clicked() 801 | MainWindow 802 | clearInput() 803 | 804 | 805 | 685 806 | 302 807 | 808 | 809 | 693 810 | 408 811 | 812 | 813 | 814 | 815 | searchButton 816 | clicked() 817 | MainWindow 818 | search() 819 | 820 | 821 | 561 822 | 278 823 | 824 | 825 | 570 826 | 390 827 | 828 | 829 | 830 | 831 | searchClearButton 832 | clicked() 833 | MainWindow 834 | searchClear() 835 | 836 | 837 | 628 838 | 304 839 | 840 | 841 | 644 842 | 407 843 | 844 | 845 | 846 | 847 | ClassNameLineEdit 848 | returnPressed() 849 | saveButton 850 | click() 851 | 852 | 853 | 571 854 | 77 855 | 856 | 857 | 547 858 | 307 859 | 860 | 861 | 862 | 863 | nameLineEdit 864 | returnPressed() 865 | saveButton 866 | click() 867 | 868 | 869 | 576 870 | 96 871 | 872 | 873 | 527 874 | 298 875 | 876 | 877 | 878 | 879 | 880 | slotCatch() 881 | aboutSlot() 882 | fillExampleData() 883 | addData() 884 | clearData() 885 | testA() 886 | clearInput() 887 | saveData() 888 | contextMenu(QPoint) 889 | edit() 890 | search() 891 | searchClear() 892 | 893 | 894 | -------------------------------------------------------------------------------- /CPP/CPPTP/studentwindow.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by SkyRain on 2023/04/24. 3 | // 4 | 5 | // You may need to build the project (run Qt uic code generator) to get 6 | // "ui_studentwindow.h" resolved 7 | 8 | #include "studentwindow.h" 9 | #include "ui_studentwindow.h" 10 | #include "ui_ClassCard.h" 11 | #include "classcard.h" 12 | #include 13 | #include 14 | 15 | int convertWeek(const QString& week){ 16 | if(week == "星期一") 17 | return 0; 18 | if(week == "星期二") 19 | return 1; 20 | if(week == "星期三") 21 | return 2; 22 | if(week == "星期四") 23 | return 3; 24 | if(week == "星期五") 25 | return 4; 26 | if(week == "星期六") 27 | return 5; 28 | if(week == "星期日") 29 | return 6; 30 | return 0; 31 | } 32 | 33 | int convertTime(const QString& time){ 34 | if(time == "第一节课") 35 | return 0; 36 | if(time == "第二节课") 37 | return 1; 38 | if(time == "第三节课") 39 | return 2; 40 | if(time == "第四节课") 41 | return 3; 42 | if(time == "第五节课") 43 | return 4; 44 | if(time == "第六节课") 45 | return 5; 46 | if(time == "第七节课") 47 | return 6; 48 | if(time == "第八节课") 49 | return 7; 50 | return 0; 51 | } 52 | 53 | studentwindow::studentwindow(const QString& username, QWidget *parent) 54 | : QWidget(parent), ui(new Ui::studentwindow), selectedList(new CXXTP::SList), 55 | username(username), settings(CXXTP::SSetting::getGlobalSettings()){ 56 | ui->setupUi(this); 57 | ui->usernameLabel->setText(username); 58 | ui->tableWidget->clearContents(); 59 | const auto size = settings->beginReadArray("Stu"+username); 60 | for(int i=0; isetArrayIndex(i); 62 | auto item = new CXXTP::Lesson{ 63 | settings->value("name", "Default").toString(), 64 | settings->value("teacherName", "LiMing").toString(), 65 | settings->value("classroomName", "Classroom1").toString(), 66 | settings->value("classCapacity", 0).toUInt(), 67 | settings->value("week", "星期一").toString(), 68 | settings->value("time", "第一节课").toString(), 69 | settings->value("description", "Default").toString() 70 | }; 71 | auto week = convertWeek(item->week); 72 | auto time = convertTime(item->time); 73 | auto tableItem = ui->tableWidget->item(time, week); 74 | if(tableItem == nullptr){ 75 | auto tItem = new QTableWidgetItem(item->name); 76 | selectedList->push_back(item); 77 | ui->tableWidget->setItem(time, week, tItem); 78 | } 79 | selectedList->push_back(item); 80 | } 81 | settings->endArray(); 82 | for(int i=0; igetSize(); i++){ 83 | auto item = new CXXTP::ClassCard(*(*CXXTP::SSetting::getLessonList())[i], i, this); 84 | ui->gridLayout_2->addWidget(item, i/3, i%3); 85 | } 86 | } 87 | 88 | void studentwindow::save(){ 89 | settings->beginWriteArray("Stu"+username); 90 | for(int i=0; igetSize(); i++){ 91 | settings->setArrayIndex(i); 92 | auto item = (*selectedList)[i]; 93 | settings->setValue("name", item->name); 94 | settings->setValue("teacherName", item->teacherName); 95 | settings->setValue("classroomName", item->classroomName); 96 | settings->setValue("classCapacity", item->classCapacity); 97 | settings->setValue("week", item->week); 98 | settings->setValue("time", item->time); 99 | settings->setValue("description", item->description); 100 | } 101 | settings->endArray(); 102 | } 103 | 104 | studentwindow::~studentwindow() { 105 | delete ui; 106 | save(); 107 | } 108 | 109 | void studentwindow::electClass(const int id, CXXTP::ClassCard* card) { 110 | auto lessonList = CXXTP::SSetting::getLessonList(); 111 | auto item = (*lessonList)[id]; 112 | auto week = convertWeek(item->week); 113 | auto time = convertTime(item->time); 114 | auto tableItem = ui->tableWidget->item(time, week); 115 | if(tableItem == nullptr){ 116 | auto tItem = new QTableWidgetItem(item->name); 117 | selectedList->push_back(item); 118 | ui->tableWidget->setItem(time, week, tItem); 119 | card->ui->electButton->setDisabled(true); 120 | } 121 | } 122 | void studentwindow::saveData() { 123 | save(); 124 | } 125 | void studentwindow::exit() { 126 | QApplication* app; 127 | save(); 128 | app->exit(); 129 | } 130 | void studentwindow::clear() { 131 | ui->tableWidget->clearContents(); 132 | selectedList->clear(); 133 | for(int i=0; igridLayout_2->count(); i++){ 134 | auto widget = ui->gridLayout_2->itemAt(i)->widget(); 135 | auto card = dynamic_cast(widget); 136 | card->ui->electButton->setEnabled(true); 137 | } 138 | } 139 | 140 | void studentwindow::showMenu(const QPoint &point) { 141 | QMenu menu(this); 142 | auto deleteAction = new QAction("删除", this); 143 | menu.addAction(deleteAction); 144 | menu.move(mapToGlobal(point)); 145 | menu.show(); 146 | } 147 | -------------------------------------------------------------------------------- /CPP/CPPTP/studentwindow.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by SkyRain on 2023/04/24. 3 | // 4 | 5 | #ifndef CXXTP_STUDENTWINDOW_H 6 | #define CXXTP_STUDENTWINDOW_H 7 | 8 | #include 9 | #include "SList.h" 10 | #include "classcard.h" 11 | 12 | QT_BEGIN_NAMESPACE 13 | namespace Ui { 14 | class studentwindow; 15 | } 16 | QT_END_NAMESPACE 17 | 18 | class studentwindow : public QWidget { 19 | Q_OBJECT 20 | 21 | public: 22 | explicit studentwindow(const QString&, QWidget *parent = nullptr); 23 | ~studentwindow() override; 24 | 25 | private: 26 | Ui::studentwindow *ui; 27 | QString username; 28 | QSettings* settings; 29 | CXXTP::SList list; 30 | friend CXXTP::ClassCard; 31 | void electClass(int id, CXXTP::ClassCard*); 32 | CXXTP::SList* selectedList; 33 | void save(); 34 | void refresh(); 35 | private slots: 36 | void saveData(); 37 | void exit(); 38 | void clear(); 39 | void showMenu(const QPoint& point); 40 | }; 41 | 42 | #endif // CXXTP_STUDENTWINDOW_H 43 | -------------------------------------------------------------------------------- /CPP/CPPTP/studentwindow.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | studentwindow 4 | 5 | 6 | 7 | 0 8 | 0 9 | 974 10 | 443 11 | 12 | 13 | 14 | studentwindow 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | Qt::CustomContextMenu 25 | 26 | 27 | Qt::LeftToRight 28 | 29 | 30 | QTableWidget::item { 31 | background-color: rgba(138, 248, 198, 128); 32 | color: black; 33 | border-radius: 0.5em; 34 | outline: none; 35 | text-align:center; 36 | } 37 | 38 | QTableWidget{ 39 | text-align: right; 40 | outline: none; 41 | } 42 | 43 | QTableWidget::item:alternate { 44 | background-color: #c5e8fb; 45 | } 46 | 47 | 48 | QAbstractItemView::NoEditTriggers 49 | 50 | 51 | true 52 | 53 | 54 | Qt::ElideLeft 55 | 56 | 57 | QAbstractItemView::ScrollPerItem 58 | 59 | 60 | Qt::NoPen 61 | 62 | 63 | false 64 | 65 | 66 | false 67 | 68 | 69 | true 70 | 71 | 72 | 40 73 | 74 | 75 | 50 76 | 77 | 78 | 79 | 第一节 80 | 81 | 82 | 83 | 84 | 第二节 85 | 86 | 87 | 88 | 89 | 第三节 90 | 91 | 92 | 93 | 94 | 第四节 95 | 96 | 97 | 98 | 99 | 第五节 100 | 101 | 102 | 103 | 104 | 第六节 105 | 106 | 107 | 108 | 109 | 第七节 110 | 111 | 112 | 113 | 114 | 第八节 115 | 116 | 117 | 118 | 119 | 星期一 120 | 121 | 122 | 123 | 124 | 星期二 125 | 126 | 127 | 128 | 129 | 星期三 130 | 131 | 132 | 133 | 134 | 星期四 135 | 136 | 137 | 138 | 139 | 星期五 140 | 141 | 142 | 143 | 144 | 星期六 145 | 146 | 147 | 148 | 149 | 星期日 150 | 151 | 152 | 153 | 154 | 形势与政策 155 | 156 | 157 | 158 | 5 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | Qt::Vertical 175 | 176 | 177 | 178 | 20 179 | 20 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 15 189 | 190 | 191 | 192 | 学生选课系统 193 | 194 | 195 | Qt::AlignCenter 196 | 197 | 198 | 199 | 200 | 201 | 202 | Qt::Vertical 203 | 204 | 205 | 206 | 20 207 | 10 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 0 216 | 217 | 218 | 219 | 220 | 221 | 222 | 用户 223 | 224 | 225 | 226 | 227 | 228 | 229 | 李大海 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 2 239 | 240 | 241 | 242 | 243 | border-radius: 0.1em; 244 | height: 1.5em; 245 | color: #FFFFFF; 246 | background-color: rgb(49, 122, 121); 247 | border-width: 0.05em; 248 | border-style:solid; 249 | 250 | 251 | 保存 252 | 253 | 254 | 255 | 256 | 257 | 258 | border-radius: 0.1em; 259 | height: 1.45em; 260 | border-color: rgb(49, 122, 121); 261 | background-color: rgb(255, 255, 255); 262 | border-width: 0.05em; 263 | border-style:solid; 264 | outline: none; 265 | 266 | 267 | 清空 268 | 269 | 270 | 271 | 272 | 273 | 274 | border-radius: 0.1em; 275 | height: 1.45em; 276 | border-color: rgb(49, 122, 121); 277 | background-color: rgb(255, 255, 255); 278 | border-width: 0.05em; 279 | border-style:solid; 280 | outline: none; 281 | 282 | 283 | 退出 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | true 299 | 300 | 301 | 302 | 303 | 0 304 | 0 305 | 540 306 | 421 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | pushButton 321 | clicked() 322 | studentwindow 323 | clear() 324 | 325 | 326 | 303 327 | 417 328 | 329 | 330 | 311 331 | 537 332 | 333 | 334 | 335 | 336 | saveButton 337 | clicked() 338 | studentwindow 339 | saveData() 340 | 341 | 342 | 225 343 | 416 344 | 345 | 346 | 234 347 | 471 348 | 349 | 350 | 351 | 352 | exitButton 353 | clicked() 354 | studentwindow 355 | exit() 356 | 357 | 358 | 396 359 | 414 360 | 361 | 362 | 396 363 | 485 364 | 365 | 366 | 367 | 368 | tableWidget 369 | customContextMenuRequested(QPoint) 370 | studentwindow 371 | showMenu(QPoint) 372 | 373 | 374 | 157 375 | 189 376 | 377 | 378 | 145 379 | 535 380 | 381 | 382 | 383 | 384 | 385 | clear() 386 | saveData() 387 | exit() 388 | showMenu(QPoint) 389 | 390 | 391 | -------------------------------------------------------------------------------- /CPP/CPPTP/test/SListTest.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by SkyRain on 2023/05/03. 3 | // 4 | #include "../SList.h" 5 | #include 6 | using namespace CXXTP; 7 | TEST(SListTest, TestPushBack) { 8 | SList list; 9 | list.push_back(1); 10 | list.push_back(2); 11 | list.push_back(3); 12 | EXPECT_EQ(list.getSize(), 3); 13 | EXPECT_EQ(list.front(), 1); 14 | EXPECT_EQ(list.back(), 3); 15 | } 16 | 17 | TEST(SListTest, TestPopFront) { 18 | SList list; 19 | list.push_back(1); 20 | list.push_back(2); 21 | list.push_back(3); 22 | list.pop_front(); 23 | EXPECT_EQ(list.getSize(), 2); 24 | EXPECT_EQ(list.front(), 2); 25 | EXPECT_EQ(list.back(), 3); 26 | } 27 | 28 | TEST(SListTest, TestCopyConstructor) { 29 | SList list1; 30 | list1.push_back(1); 31 | list1.push_back(2); 32 | list1.push_back(3); 33 | SList list2(list1); 34 | EXPECT_EQ(list2.getSize(), 3); 35 | EXPECT_EQ(list2.front(), 1); 36 | EXPECT_EQ(list2.back(), 3); 37 | } 38 | 39 | TEST(SListTest, TestAssignmentOperator) { 40 | SList list1; 41 | list1.push_back(1); 42 | list1.push_back(2); 43 | list1.push_back(3); 44 | SList list2; 45 | list2.push_back(4); 46 | list2.push_back(5); 47 | list2 = list1; 48 | EXPECT_EQ(list2.getSize(), 3); 49 | EXPECT_EQ(list2.front(), 1); 50 | EXPECT_EQ(list2.back(), 3); 51 | } 52 | 53 | TEST(SListTest, TestClear) { 54 | SList list; 55 | list.push_back(1); 56 | list.push_back(2); 57 | list.push_back(3); 58 | list.clear(); 59 | EXPECT_EQ(list.getSize(), 0); 60 | EXPECT_TRUE(list.empty()); 61 | } 62 | 63 | TEST(SListTest, TestIndexOperator){ 64 | SList list; 65 | list.push_back(1); 66 | list.push_back(2); 67 | list.push_back(3); 68 | EXPECT_EQ(list[0], 1); 69 | EXPECT_EQ(list[1], 2); 70 | EXPECT_EQ(list[2], 3); 71 | EXPECT_THROW(list[3], std::out_of_range); 72 | } -------------------------------------------------------------------------------- /CPP/CPPTP/test/SSetTest.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by SkyRain on 2023/05/03. 3 | // 4 | #include "../SSet.h" 5 | #include 6 | using namespace CXXTP; 7 | TEST(SSetTest, SetDifference) { 8 | SSet set1, set2; 9 | set1.push_back(1); 10 | set1.push_back(2); 11 | set1.push_back(3); 12 | set2.push_back(3); 13 | set2.push_back(4); 14 | set2.push_back(5); 15 | 16 | auto set3 = set1 - set2; 17 | 18 | ASSERT_EQ(set3.getSize(), 2); 19 | EXPECT_EQ(set3[0], 1); 20 | EXPECT_EQ(set3[1], 2); 21 | } 22 | 23 | TEST(SSetTest, SetUnion) { 24 | SSet set1, set2; 25 | set1.push_back(1); 26 | set1.push_back(2); 27 | set1.push_back(3); 28 | set2.push_back(3); 29 | set2.push_back(4); 30 | set2.push_back(5); 31 | 32 | auto set4 = set1 + set2; 33 | 34 | ASSERT_EQ(set4.getSize(), 5); 35 | EXPECT_EQ(set4[0], 1); 36 | EXPECT_EQ(set4[1], 2); 37 | EXPECT_EQ(set4[2], 3); 38 | EXPECT_EQ(set4[3], 4); 39 | EXPECT_EQ(set4[4], 5); 40 | } 41 | 42 | TEST(SSetTest, SetIntersection) { 43 | SSet set1, set2; 44 | set1.push_back(1); 45 | set1.push_back(2); 46 | set1.push_back(3); 47 | set2.push_back(3); 48 | set2.push_back(4); 49 | set2.push_back(5); 50 | 51 | auto set5 = set1.and_(set2); 52 | 53 | ASSERT_EQ(set5.getSize(), 1); 54 | EXPECT_EQ(set5[0], 3); 55 | } 56 | -------------------------------------------------------------------------------- /CPP/CPPTP/test/SStackTest.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by SkyRain on 2023/05/03. 3 | // 4 | #include "../SStack.h" 5 | #include 6 | using namespace CXXTP; 7 | TEST(SStackTest, EmptyStack) { 8 | SStack stack; 9 | EXPECT_TRUE(stack.empty()); 10 | } 11 | 12 | TEST(SStackTest, PushAndPop) { 13 | SStack stack; 14 | stack.push(1); 15 | stack.push(2); 16 | stack.push(3); 17 | EXPECT_EQ(stack.size(), 3U); 18 | EXPECT_EQ(stack.top(), 3); 19 | stack.pop(); 20 | EXPECT_EQ(stack.top(), 2); 21 | stack.pop(); 22 | EXPECT_EQ(stack.top(), 1); 23 | stack.pop(); 24 | EXPECT_TRUE(stack.empty()); 25 | } 26 | -------------------------------------------------------------------------------- /CPP/README.md: -------------------------------------------------------------------------------- 1 | # README for this project 2 | 3 | *** 课程成绩: A+(C++程序设计) A+(C++课设)*** 4 | 5 | 这是计科专业大一下的C++程序设计课程,整体课程包含两个项目:三级项目和课设。 6 | 7 | 三级项目设计了一款图形界面的选课系统,参考了YSU实际投入使用的 [燕山大学学生选课系统](https://xsxk.ysu.edu.cn) 来制作。 8 | 使用了传统Qt(编辑器拖拽)的方法来编写。 9 | 10 | 课设设计了一款音乐播放器,包含增改删查等功能。此项目使用了新版QML系统来编写界面,和三级项目所用技术不同。 11 | 12 | ## 三级项目设计指导书节选 13 | 14 | > 本课程的三级项目是要求学生设计实现一个人员信息管理系统(不限于该系统)。引导学生积极思考、主动学习,锻炼和提高学生的交流、沟通和表达能力以及团队合作能力,培养学生的责任感和职业道德。 15 | > 1、问题描述 16 | > 开发一个人员信息管理系统,用于管理学生及教师的相关信息,具备查询、统计、添加、删除等功能。 17 | > 2、功能需求 18 | > 用链表实现,需要满足如下要求。 19 | > 1) 链表元素中要有指针指向动态分配的内存空间,练习析构函数的操作规则; 20 | > 2) 链表应该至少有两个类,Node类和List类, Node类的构造和析构函数负责结点本身的初始化和空间回收,List类负责整个链表的管理工作,其构造和析构函数负责整个链表的初始化和回收; 21 | > 3) 从List类派生出Stack和Queue,并使其具有自身的操作特性,练习派生类的概念; 22 | > 4) 从List类派生出Set类,负责集合操作的实现; 23 | > 5) 具有集合差“-”,并“+”,交“and”三种操作,其中前两个是运算符的重载,第三个并非运算符的重载。 24 | 25 | 其中3 4 5是可选做的项目,本项目仅实现了3和4的代码,在实际程序中并未使用 26 | 27 | ## 课程设计指导书节选 28 | 29 | > 题目十二:歌曲播放器 30 | > 设计开发歌曲播放器。实现功能: 31 | > 1、添加多首歌曲到播放列表(添加、删除)。 32 | > 2、在播放列表中搜索想听的歌曲。 33 | > 3、播放和暂停选中的歌曲。 34 | > 4、对播放列表中的歌曲按不同的项排序。 35 | > 5、调节音量大小。 36 | > 6、快进、切换到上一首或下一首歌曲。 37 | > 7、界面及其中菜单、按钮等设计美观大方。 38 | > 备注:每首歌曲至少应该有以下数据项:歌曲名称,演唱者,作词,作曲,发行时间。 39 | 40 | -------------------------------------------------------------------------------- /CProgramLanguage/README.md: -------------------------------------------------------------------------------- 1 | # README of this project 2 | 3 | *** 课程成绩: A+ *** 4 | 5 | 这是燕山大学大一上C语言结课项目的源代码。 6 | 7 | 该代码完全体具有以下特性 8 | 9 | * 以链表存储图书信息 10 | * 从数据文件加载图书馆 11 | * 保存图书馆到数据文件 12 | * 从宏定义不同的程序生成的数据文件中正确的读取图书馆 13 | * 实现有限范围内的增改删查 14 | * 部分跨平台 15 | 16 | ### 什么叫“宏定义不同的程序生成的数据文件”? 17 | 18 | 程序首部有4个`define`语句,它们管理着下面所述的四个字符串长度限制 19 | 20 | 更改这些`define`语句后,编译出来的程序可以兼容之前的程序生成的数据文件。 21 | 22 | 不过,依`define`语句修改情况,可能会出现字符串的截断,导致数据丢失。 23 | 24 | ## 数据文件结构 25 | 26 | 从首部开始: 27 | 28 | 1. 4个int大小的数据,分别是 图书名称字段长度B 图书作者字段长度A 图书ISBN字段长度I 图书馆名称字段长度L 29 | 2. 一个长度为L的以\0结尾的字符串,为图书馆名称 30 | 3. 一个int大小的数据,为书籍数量n 31 | 4. n个大小为(B+A+I+2*long long)的结构体 32 | 33 | 图书结构体的定义如下: 34 | 35 | ```c 36 | typedef struct { 37 | char name[B]; 38 | char author[A]; 39 | char isbn[I]; 40 | long long addAt; 41 | long long updatedAt; 42 | } Book; 43 | ``` 44 | 45 | 数据文件的结构体定义如下: 46 | 47 | ```c 48 | #pragma pack(1) 49 | 50 | typedef struct { 51 | int B; 52 | int A; 53 | int I; 54 | int L; 55 | char library_name[L]; 56 | int n; 57 | Book bookList[n]; 58 | } DataFile; 59 | ``` 60 | 61 | ## Bugs 62 | 63 | * Linux系统下的原生编译的程序会出现输入缓冲区清空失败的问题 64 | 65 | ## 提醒 66 | 67 | 报告PDF仅供参考,请勿抄袭 68 | 69 | 上传的源代码与报告中附录B中的源代码并不一致,请仔细甄别。 70 | -------------------------------------------------------------------------------- /CProgramLanguage/ThirdProject.c: -------------------------------------------------------------------------------- 1 | /* 2 | * The EndOfCourse project for C Program Language in the YSU 3 | * 4 | * Date: 2022/11/22 5 | * Author: SkyRain PYH NXC 6 | * Instruction Teacher: NJC 7 | * 8 | * Name: Book Management System 9 | */ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | 18 | #define BOOK_NAME_LENGTH 21 19 | #define BOOK_ISBN_LENGTH 18 20 | #define BOOK_AUTHOR_LENGTH 21 21 | #define LIBRARY_NAME_LENGTH 20 22 | 23 | // Book Item 24 | typedef struct { 25 | char name[BOOK_NAME_LENGTH]; // Book name 26 | char isbn[BOOK_ISBN_LENGTH]; // Book ISBN number 27 | char author[BOOK_AUTHOR_LENGTH]; // Book Author 28 | long long addAt; // When the book was added to the library 29 | long long updatedAt; // When the book was last updated 30 | } Book; 31 | 32 | // BookNode in BookList 33 | typedef struct _BookNode { 34 | Book item; // The book in this node 35 | struct _BookNode* next; 36 | } BookNode; 37 | 38 | // BookList (a List) 39 | typedef struct { 40 | BookNode* head; // Head pointer of this List 41 | } BookList; 42 | 43 | typedef struct { 44 | char name[LIBRARY_NAME_LENGTH]; 45 | BookList bookList; 46 | } Library; 47 | 48 | 49 | /* 50 | * Library* createLibrary(char*) 51 | * - create a Library object in the given name 52 | * This function will check the length of the name 53 | * - Return allocated Library* 54 | */ 55 | Library* createLibrary(char* name){ 56 | Library* library; // Define the pointer that is to be returnd 57 | library = (Library*) malloc(sizeof(Library)); // Dynamicly allocate memory for Library 58 | memcpy(library->name, name, sizeof(char) * (strlen(name) > LIBRARY_NAME_LENGTH ? LIBRARY_NAME_LENGTH : strlen(name) )); // String length limit for the name property 59 | library->bookList.head = NULL; // Initalize the head property with NULL. That ensures no error will occurred when looping the list. 60 | return library; 61 | } 62 | 63 | /* 64 | * void freeLibrary(Library*) 65 | * - free library 66 | */ 67 | void freeLibrary(Library* library){ 68 | BookNode *node = library->bookList.head, *n; 69 | while(node!=NULL){ 70 | n = node->next; 71 | free(node); 72 | node = n; 73 | } 74 | free(library); 75 | } 76 | 77 | /* 78 | * void addBook(Library*, Book*) 79 | * - Add book into Library 80 | */ 81 | void addBook(Library* library, Book* book){ 82 | BookNode* node = library->bookList.head; 83 | if(library->bookList.head == NULL){ // When the head is NULL, add book as head. 84 | library->bookList.head = (BookNode*) malloc(sizeof(BookNode)); // Allocate memory for BookNode 85 | library->bookList.head->item = *book; 86 | library->bookList.head->next = NULL; // Initalize the next property with NULL. That ensures no error will occurred when looping the list 87 | }else{ 88 | BookNode* p; 89 | for(; node!=NULL; p=node, node=node->next); // Go to the last node of the list 90 | node = (BookNode*) malloc(sizeof(BookNode)); // Allocate memory for BookNode 91 | node->next = NULL; // Initalize the next property with NULL. That ensures no error will occurred when looping the list 92 | p->next = node; // Append the BookNode in the end of the list 93 | node->item = *book; 94 | } 95 | } 96 | 97 | /* 98 | * void saveToFile(Library*, char*) 99 | * - save Library* data to given destination 100 | * 101 | * FILE STRUCTURE 102 | * + BOOK_NAME_LENGTH BOOK_AUTHOR_LENGTH BOOK_ISBN_LENGTH LIBRARY_NAME_LENGTH (4*sizeof(int))Byte 103 | * + Library Name (20Byte) 104 | * + Book numbers (sizeof(int)Byte) 105 | * + n*Book (n*sizeof(Book)Byte) 106 | */ 107 | int saveToFile(Library* library, char* dest){ 108 | FILE* f = fopen(dest, "wb+"); // Open file handler 109 | if(f == NULL) return 0; // Error process 110 | BookNode* node = library->bookList.head; 111 | int sum = 0; 112 | // Get book number 113 | while(node != NULL){ 114 | sum++; 115 | node = node->next; 116 | } 117 | if(sum == 0){ // Book number == 0 118 | int head[] = {BOOK_NAME_LENGTH, BOOK_AUTHOR_LENGTH, BOOK_ISBN_LENGTH, LIBRARY_NAME_LENGTH}; 119 | fwrite(head, sizeof(int), 4, f); // Write Meta 120 | fwrite(library->name, sizeof(char), LIBRARY_NAME_LENGTH, f); // Write Library name 121 | fwrite(&sum, sizeof(int), 1, f); // Write Book number 122 | fclose(f);// Close handler 123 | return 1; // Return 124 | } 125 | node = library->bookList.head; 126 | Book* bookList = (Book*) calloc(sum, sizeof(Book)); // Alloc memory 127 | for(int i=0; iitem; 129 | node = node->next; 130 | } 131 | 132 | int head[] = {BOOK_NAME_LENGTH, BOOK_AUTHOR_LENGTH, BOOK_ISBN_LENGTH, LIBRARY_NAME_LENGTH}; 133 | fwrite(head, sizeof(int), 4, f); 134 | fwrite(library->name, sizeof(library->name), 1, f); 135 | fwrite(&sum, sizeof(int), 1, f); 136 | //fwrite(bookList, sizeof(Book), sum, f); 137 | for(int i=0; i= '0' && isbnCode[i] <= '9'){ 161 | if(j%2==1){ 162 | sum+=isbnCode[i]-'0'; 163 | }else{ 164 | sum+=3*(isbnCode[i]-'0'); 165 | } 166 | j++; 167 | } 168 | } 169 | c = isbnCode[len-1]; 170 | sum=10-(sum%10); 171 | if(sum == 10) return c == 'X' || c == 'x'; 172 | else return sum == c-'0'; 173 | } 174 | 175 | // Deprecated 176 | Library* loadFromFilev1(char* dest){ 177 | FILE* f = fopen(dest, "r"); 178 | if(f == NULL) return NULL; 179 | Library* library = malloc(sizeof(Library)); 180 | library->bookList.head = NULL; 181 | int head[4]; 182 | fread(head, sizeof(head), 1, f); 183 | fread(library->name, sizeof(char), LIBRARY_NAME_LENGTH, f); 184 | int sum; 185 | fread(&sum, sizeof(int), 1, f); 186 | if(sum == 0) return library; 187 | Book* bookList = (Book*) malloc(sizeof(Book)*sum); 188 | fread(bookList, sizeof(Book), sum, f); 189 | fclose(f); 190 | library->bookList.head = (BookNode*) malloc(sizeof(BookNode)); 191 | library->bookList.head->next = NULL; 192 | library->bookList.head->item = bookList[0]; 193 | BookNode *p=library->bookList.head; 194 | for(int i=1; inext){ 195 | p->next = (BookNode*) malloc(sizeof(BookNode)); 196 | p->next->item = bookList[i]; 197 | p->next->next = NULL; 198 | } 199 | free(bookList); 200 | return library; 201 | } 202 | 203 | void strfit(char* d, char* s, int size){ 204 | // Fit string to given size 205 | if(strlen(s)+1 <= size){ 206 | memcpy(d, s, sizeof(char)*strlen(s)+1); 207 | }else{ 208 | memcpy(d, s, size); 209 | d[size-1] = '\0'; 210 | } 211 | } 212 | 213 | /* 214 | * Library* loadFromFile(char*) 215 | * - load Library from given path. 216 | * return NULL if errors occurred 217 | */ 218 | Library* loadFromFile(char* dest){ 219 | FILE* f = fopen(dest, "r"); 220 | if(f == NULL) return NULL; 221 | Library* library = (Library*) malloc(sizeof(Library)); 222 | library->bookList.head = NULL; 223 | int head[4]; 224 | fread(head, sizeof(head), 1, f); 225 | char* libraryString = (char*) malloc(sizeof(char)*head[3]); 226 | fread(libraryString, sizeof(char), head[3], f); 227 | strfit(library->name, libraryString, LIBRARY_NAME_LENGTH); 228 | free(libraryString); 229 | int sum; 230 | fread(&sum, sizeof(int), 1, f); 231 | if(sum == 0) return library; 232 | Book* bookList = (Book*) malloc(sizeof(Book)*sum); 233 | for(int i=0; ibookList.head = (BookNode*) malloc(sizeof(BookNode)); 252 | library->bookList.head->next = NULL; 253 | library->bookList.head->item = bookList[0]; 254 | BookNode *p=library->bookList.head; 255 | for(int i=1; inext){ 256 | p->next = (BookNode*) malloc(sizeof(BookNode)); 257 | p->next->item = bookList[i]; 258 | p->next->next = NULL; 259 | } 260 | free(bookList); 261 | return library; 262 | } 263 | 264 | 265 | /* int deleteBook(Library*, int) 266 | * - Delete a book from the library 267 | * Return the id of the deleted book 268 | * Return -1 if the book isnot found 269 | */ 270 | int deleteBook(Library* library, unsigned int index){ 271 | BookNode* node = library->bookList.head, *p=node; 272 | if(node == NULL) return -1; 273 | if(index == 1){ 274 | p = library->bookList.head; 275 | library->bookList.head = library->bookList.head->next; 276 | free(p); 277 | return index; 278 | } 279 | int now = 1; 280 | while(now != index){ 281 | p = node; 282 | node = node->next; 283 | if(node == NULL) return -1; 284 | now++; 285 | } 286 | p->next = node->next; 287 | free(node); 288 | return index; 289 | } 290 | 291 | /* 292 | * long long get_timestamp() 293 | * - Get the timestamp now 294 | */ 295 | long long get_timestamp() 296 | { 297 | time_t seconds = time(NULL); //The function time(NULL) returns the time since the Epoch (00:00:00 UTC, January 1, 1970), measured in seconds. 298 | return (long long)seconds; 299 | } 300 | 301 | /* 302 | * void timestampToTime(long long, char*, char*, int) 303 | * - Convert timestamp to date string in the given format 304 | */ 305 | void timeStampToTime(long long timestamp, char* dest, char* format, int sizeofDest){ 306 | struct tm tm; 307 | time_t tick = (time_t) timestamp; 308 | tm = *localtime(&tick); 309 | strftime(dest, sizeofDest, format, &tm); 310 | } 311 | 312 | /* 313 | * void printBook(Book*) 314 | * - print book on stdout 315 | */ 316 | void printBook(Book* book){ 317 | char addTime[20], updatedTime[20]; 318 | timeStampToTime(book->addAt, addTime, "%Y-%m-%d %H:%M:%S", sizeof(addTime)); 319 | timeStampToTime(book->updatedAt, updatedTime, "%Y-%m-%d %H:%M:%S", sizeof(updatedTime)); 320 | printf("%-*s|%-*s|%-*s|%-20s|%-20s\n", BOOK_NAME_LENGTH-1, book->name, BOOK_AUTHOR_LENGTH-1, book->author, BOOK_ISBN_LENGTH-1, book->isbn, addTime, updatedTime); 321 | } 322 | 323 | #define PRINT_HEAD printf("========================================================================================================\n");\ 324 | printf("%-3s %-*s %-*s %-*s %-20s %-20s\n","ID", BOOK_NAME_LENGTH - 1, "BOOK NAME", BOOK_AUTHOR_LENGTH - 1, "AUTHOR", BOOK_ISBN_LENGTH - 1, "ISBN", "ADD TIME", "UPDATE TIME");\ 325 | printf("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n"); 326 | #define PRINT_TAIL printf("========================================================================================================\n"); 327 | /* 328 | * void printBookList(Library*) 329 | * - Print a table of books 330 | */ 331 | void printBookList(Library* library){ 332 | int sum=1; 333 | BookNode* node = library->bookList.head; 334 | PRINT_HEAD 335 | while(node != NULL){ 336 | printf("%-3d ", sum); 337 | printBook(&node->item); 338 | node = node->next; 339 | sum++; 340 | } 341 | PRINT_TAIL 342 | } 343 | 344 | /* 345 | * int getIDByBook(Library*, Book*) 346 | * - return the id 347 | */ 348 | int getIDByBook(Library* library, Book* book){ 349 | int id = 1; 350 | BookNode* node = library->bookList.head; 351 | while(&node->item != book){ 352 | node = node->next; 353 | if(node == NULL) return -1; 354 | id++; 355 | } 356 | return id; 357 | } 358 | 359 | /* 360 | * int existsBook(Library*, int) 361 | * - Return the id of the book. If not found, return -1 362 | */ 363 | int existsBook(Library* library, int id){ 364 | if(id < 1) return -1; 365 | BookNode* node = library->bookList.head; 366 | int sum = 1; 367 | while(sum != id){ 368 | if(node == NULL) return -1; 369 | node = node->next; 370 | sum++; 371 | } 372 | return sum; 373 | } 374 | 375 | /* 376 | * int changeBook(Library*, Book*, int) 377 | * - change the book by id 378 | * return the id of the changed book 379 | * return -1 if the id is invaild 380 | */ 381 | int changeBook(Library* library, Book* book, int id){ 382 | if(existsBook(library, id) == -1) return -1; 383 | int sum = 1; 384 | BookNode* node = library->bookList.head; 385 | while(sum!=id){ 386 | node = node->next; 387 | sum++; 388 | } 389 | long long addTimestamp = node->item.addAt; 390 | node->item = *book; 391 | node->item.updatedAt = get_timestamp(); 392 | node->item.addAt = addTimestamp; 393 | return id; 394 | } 395 | 396 | /* 397 | * int stdinRead(char*, int); 398 | * - Read the stdin with given length 399 | */ 400 | void stdinRead(char* data, int size){ 401 | fgets(data, size, stdin); 402 | char* p; 403 | while(p=strchr(data, '\n'), p!=NULL) *p = '\0'; 404 | fflush(stdin); 405 | } 406 | 407 | /* 408 | * int inputBook(Book*) 409 | * input the book data 410 | */ 411 | int inputBook(Book* b){ 412 | printf(" - Please input book name (in %d characters): ", BOOK_NAME_LENGTH-1); 413 | stdinRead(b->name, BOOK_NAME_LENGTH); 414 | printf(" - Please input the author of this book: "); 415 | stdinRead(b->author, BOOK_AUTHOR_LENGTH); 416 | printf(" - Please input the ISBN code of this book: "); 417 | stdinRead(b->isbn, BOOK_ISBN_LENGTH); 418 | #ifndef TP_FORCE_RIGHT_ISBN 419 | if(!checkISBN(b->isbn)) printf("Warning: ISBN invalid!\n"); 420 | #else 421 | if(!checkISBN(b->isbn)){ 422 | printf("Error: ISBN invalid!\n"); 423 | return 0; 424 | } 425 | #endif 426 | b->addAt = get_timestamp(); 427 | b->updatedAt = get_timestamp(); 428 | return 1; 429 | } 430 | 431 | /* 432 | * Book* getBookByISBN(Library*, char*) 433 | * - Get book by given ISBN code 434 | */ 435 | Book* getBookByISBN(Library* library, char* isbn){ 436 | BookNode* node = library->bookList.head; 437 | if(node == NULL) return NULL; 438 | Book* book = NULL; 439 | while(node != NULL){ 440 | if(strcmp(node->item.isbn, isbn) == 0){ 441 | book = &(node->item); 442 | break; 443 | } 444 | node = node->next; 445 | } 446 | return book; 447 | } 448 | 449 | /* 450 | * Book* getBookByName(Library* char*) 451 | * - Get book by given book name 452 | */ 453 | Book* getBookByName(Library* library, char* name){ 454 | BookNode* node = library->bookList.head; 455 | if(node == NULL) return NULL; 456 | Book* book = NULL; 457 | PRINT_HEAD 458 | while(node != NULL){ 459 | if(strstr(node->item.name, name) != NULL){ 460 | book = &node->item; 461 | printf("%-3d ", getIDByBook(library, book)); 462 | printBook(book); 463 | } 464 | node = node->next; 465 | } 466 | PRINT_TAIL 467 | return book; 468 | } 469 | 470 | /* 471 | * void pressEnterToContinue() 472 | * - Generate a message 473 | */ 474 | void pressEnterToContinue(){ 475 | printf("Press ENTER to continue."); 476 | char a[10]; 477 | stdinRead(a, 10); 478 | } 479 | 480 | /* 481 | * The enterance of this program 482 | */ 483 | int main(){ 484 | Library* library = createLibrary("YSULib"); 485 | char command; 486 | 487 | int shouldExit = 0; 488 | while(shouldExit == 0){ 489 | #ifdef __WIN32__ 490 | system("cls"); 491 | #endif 492 | fflush(stdin); 493 | printf("========== Book Management System ==========\n"); 494 | printf(" - [l] Show books in current library\n"); 495 | printf(" - [a] Add a new book\n"); 496 | printf(" - [d] Delete a book from the library.\n"); 497 | printf(" - [c] Change book data by id\n"); 498 | printf(" - [q] Query book by its name\n"); 499 | printf(" - [i] Query book by its ISBN\n"); 500 | printf(" - [s] Save book data to disk\n"); 501 | printf(" - [L] Load book data from disk\n"); 502 | printf("============================================\n"); 503 | printf(" - [v] Show version information\n"); 504 | printf(" - [x] Exit this system\n"); 505 | printf("============================================\n"); 506 | printf(" + Current Library: %s\nPress C to change the name.\n\n", library->name); 507 | 508 | while(scanf("%c", &command), command=='\n' || command==' '); // Get rid of `pause` 509 | fflush(stdin); 510 | switch(command){ 511 | case 'l':{ 512 | printBookList(library); 513 | break; 514 | } 515 | case 'a':{ 516 | Book b; 517 | printf("\n"); 518 | if(inputBook(&b)){ 519 | addBook(library, &b); 520 | }else{ 521 | printf("Input invalid!\n"); 522 | } 523 | break; 524 | } 525 | 526 | case 'v':{ 527 | printf("TP. The Final Version\n"); 528 | #ifdef __DEBUG 529 | printf("关注永雏塔菲喵,关注永雏塔菲谢谢喵\n"); 530 | #endif 531 | break; 532 | } 533 | case 'x':{ 534 | printf("Bye.\n"); 535 | shouldExit = 1; 536 | break; 537 | } 538 | case 'L':{ 539 | printf("Please input the path of the data file: "); 540 | char path[50]; 541 | stdinRead(path, 50); 542 | Library* l = loadFromFile(path); 543 | if(l == NULL){ 544 | printf("Path or file is invalid.\n"); 545 | }else{ 546 | freeLibrary(library); 547 | library = l; 548 | printf("Successfully loaded.\n"); 549 | printBookList(library); 550 | } 551 | break; 552 | } 553 | case 'i':{ 554 | printf("Please input book ISBN:"); 555 | char isbn[BOOK_ISBN_LENGTH]; 556 | stdinRead(isbn, BOOK_ISBN_LENGTH); 557 | Book* b = getBookByISBN(library, isbn); 558 | if(b == NULL) printf("Book does not exist!\n"); 559 | else{ 560 | PRINT_HEAD 561 | printf("%-3d ", getIDByBook(library, b)); 562 | printBook(b); 563 | PRINT_TAIL 564 | } 565 | break; 566 | } 567 | case 'q':{ 568 | printf("Please input book name:"); 569 | char name[BOOK_NAME_LENGTH]; 570 | stdinRead(name, BOOK_NAME_LENGTH); 571 | if(getBookByName(library, name) == NULL) printf("Book does not exist!\n"); 572 | break; 573 | } 574 | case 'd':{ 575 | printBookList(library); 576 | printf("\n\nPlease input the book id you want to delete: "); 577 | int index; 578 | scanf("%d", &index); 579 | fflush(stdin); 580 | if(deleteBook(library, index) == -1){ 581 | printf("Invalid index is given!\n"); 582 | }else{ 583 | printf("Successfully deleted.\n"); 584 | } 585 | break; 586 | } 587 | case 'c':{ 588 | printBookList(library); 589 | printf("Please input the book id that you want to change: "); 590 | int id; 591 | scanf("%d", &id); 592 | fflush(stdin); 593 | if(existsBook(library, id) == -1){ 594 | printf("Book id is invalid! \n"); 595 | //pressEnterToContinue(); 596 | break; 597 | } 598 | Book book; 599 | printf("\n"); 600 | if(inputBook(&book)){ 601 | changeBook(library, &book, id); 602 | }else{ 603 | printf("Input invalid!\n"); 604 | } 605 | break; 606 | } 607 | 608 | case 's':{ 609 | printf("Please input the path of the data file: "); 610 | char path[50]; 611 | stdinRead(path, 50); 612 | if(saveToFile(library, path) == 0){ 613 | printf("Failed to open file: Errno[%d] %s\n", errno, strerror(errno)); 614 | }else{ 615 | printf("Save success!\n"); 616 | } 617 | break; 618 | } 619 | case 'C':{ 620 | printf("Please input the name you like: "); 621 | stdinRead(library->name, LIBRARY_NAME_LENGTH); 622 | break; 623 | } 624 | 625 | default:{ 626 | printf("Please input correct command!\n"); 627 | } 628 | } 629 | if(shouldExit == 0) pressEnterToContinue(); 630 | } 631 | return 0; 632 | } 633 | -------------------------------------------------------------------------------- /CProgramLanguage/燕山大学课程三级项目报告.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KamijoToma/YSUProject/1a960ba55ac9789537dfce7f955ee955b8ea99e6/CProgramLanguage/燕山大学课程三级项目报告.pdf -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Rainight 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # YSUProject 2 | 3 | ## 前言 4 | 5 | 是这样的,🐦🧱虽然不是本科,但你要是努力的话,也不比一些二本三本的垃圾专业混的差,关键是要靠个人努力,不能因为考不上本科而自暴自弃。 是这样的,🐦🧱虽然不是本科,但你要是努力的话,也不比一些二本三本的垃圾专业混的差,关键是要靠个人努力,不能因为考不上本科而自暴自弃。 是这样的,🐦🧱虽然不是本科,但你要是努力的话,也不比一些二本三本的垃圾专业混的差,关键是要靠个人努力,不能因为考不上本科而自暴自弃。 是这样的,🐦🧱虽然不是本科,但你要是努力的话,也不比一些二本三本的垃圾专业混的差,关键是要靠个人努力,不能因为考不上本科而自暴自弃。 是这样的,🐦🧱虽然不是本科,但你要是努力的话,也不比一些二本三本的垃圾专业混的差,关键是要靠个人努力,不能因为考不上本科而自暴自弃。 是这样的,🐦🧱虽然不是本科,但你要是努力的话,也不比一些二本三本的垃圾专业混的差,关键是要靠个人努力,不能因为考不上本科而自暴自弃。 是这样的,🐦🧱虽然不是本科,但你要是努力的话,也不比一些二本三本的垃圾专业混的差,关键是要靠个人努力,不能因为考不上本科而自暴自弃。 是这样的,🐦🧱虽然不是本科,但你要是努力的话,也不比一些二本三本的垃圾专业混的差,关键是要靠个人努力,不能因为考不上本科而自暴自弃。 是这样的,🐦🧱虽然不是本科,但你要是努力的话,也不比一些二本三本的垃圾专业混的差,关键是要靠个人努力,不能因为考不上本科而自暴自弃。 6 | 7 | ## 正文 8 | 9 | 这个项目包含了各种专业课的三级项目。目前包含: 10 | 11 | * C语言 12 | * 面向对象程序设计(C++) 13 | 14 | 本项目内所有源代码的作者为源代码注释内的`Author`字段的值。 15 | 16 | 除了在源文件首个多行注释内明确注明开源协议外,其他源代码均采用`MIT License` 17 | -------------------------------------------------------------------------------- /SQL/README.md: -------------------------------------------------------------------------------- 1 | # SQL 2 | 3 | I don't like cows because they always have bad moooooooooooooods. 4 | 5 | 课程作业和三级项目将在课程结课后公布。 6 | -------------------------------------------------------------------------------- /SQL/hw01/README.md: -------------------------------------------------------------------------------- 1 | # HW01 2 | 3 | 把 C语言的三级项目中的数据用数据库存储。 4 | 5 | Knock knock! 6 | 7 | 本项目源码将在课程结束后公布。 8 | 9 | sha256sum: 10 | 11 | ``` 12 | c69f360a1b46e0b7d630e4812538a5a54c62c2bfc57373412589403f6266b755 main.db 13 | 3f413a0b8937bbf681fc2e59444fa18fb28ce2888bc2af1bbb49559fdf7fc5d1 main.py 14 | ``` 15 | --------------------------------------------------------------------------------