├── .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 |
43 |
--------------------------------------------------------------------------------
/CPP/CPPCD/content/BppTable/assets/sort-up-and-down.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
48 |
--------------------------------------------------------------------------------
/CPP/CPPCD/content/BppTable/assets/sort-up.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
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 |
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 |
--------------------------------------------------------------------------------