Line data Source code
1 : /*
2 : * SPDX-License-Identifier: GPL-3.0-only
3 : * MuseScore-Studio-CLA-applies
4 : *
5 : * MuseScore Studio
6 : * Music Composition & Notation
7 : *
8 : * Copyright (C) 2025 MuseScore Limited and others
9 : *
10 : * This program is free software: you can redistribute it and/or modify
11 : * it under the terms of the GNU General Public License version 3 as
12 : * published by the Free Software Foundation.
13 : *
14 : * This program is distributed in the hope that it will be useful,
15 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : * GNU General Public License for more details.
18 : *
19 : * You should have received a copy of the GNU General Public License
20 : * along with this program. If not, see <https://www.gnu.org/licenses/>.
21 : */
22 :
23 : #include "welcomedialogmodel.h"
24 :
25 : #include "translation.h"
26 : #include "log.h"
27 :
28 : using namespace mu::appshell;
29 :
30 0 : static std::vector<QVariantMap> welcomeDialogData()
31 : {
32 0 : QVariantMap museSoundsPro;
33 0 : museSoundsPro.insert("title", muse::qtrc("appshell/welcome", "Unlock Premium Playback"));
34 0 : museSoundsPro.insert("imageUrl", "qrc:/resources/welcomedialog/MuseSoundsPro.png");
35 0 : museSoundsPro.insert("description", muse::qtrc("appshell/welcome",
36 : "Hear your scores come to life with professionally recorded instrument libraries for expressive, realistic playback in MuseScore Studio."));
37 0 : museSoundsPro.insert("buttonText", muse::qtrc("appshell/welcome", "Get MuseSounds Pro"));
38 0 : museSoundsPro.insert("destinationUrl",
39 : "https://www.musehub.com/muse-sounds/musesounds-pro?utm_medium=Referral&utm_source=MSS&utm_campaign=MH_WW_REF_MSS_APP_ALL_040826_crosslink&utm_content=welcome_screen");
40 :
41 0 : QVariantMap whatsNew;
42 0 : whatsNew.insert("title", muse::qtrc("appshell/welcome", "What’s new in MuseScore Studio"));
43 0 : whatsNew.insert("imageUrl", "qrc:/resources/welcomedialog/WhatsNew.png");
44 0 : whatsNew.insert("description", muse::qtrc("appshell/welcome",
45 : "Includes essential new engraving tools, major improvements to playback, video export, dive notation for guitar, and features to speed up your workflow."));
46 0 : whatsNew.insert("buttonText", muse::qtrc("appshell/welcome", "Watch video"));
47 0 : whatsNew.insert("destinationUrl", "https://youtu.be/grKX-cBEEmM");
48 :
49 0 : QVariantMap cloudStorage;
50 0 : cloudStorage.insert("title", muse::qtrc("appshell/welcome", "Enjoy free cloud storage"));
51 0 : cloudStorage.insert("imageUrl", "qrc:/resources/welcomedialog/MuseScoreCom.png");
52 0 : cloudStorage.insert("description", muse::qtrc("appshell/welcome",
53 : "Save your scores privately on MuseScore.com to revisit past versions and invite others to view and comment – and when you’re ready, share your music with the world."));
54 0 : cloudStorage.insert("buttonText", muse::qtrc("appshell/welcome", "View my scores online"));
55 0 : cloudStorage.insert("destinationUrl",
56 : "https://musescore.com/my-scores?utm_source=mss-app-welcome-musescore-com&utm_medium=mss-app-welcome-musescore-com&utm_campaign=mss-app-welcome-musescore-com");
57 :
58 0 : QVariantMap freeMuseSounds;
59 0 : freeMuseSounds.insert("title", muse::qtrc("appshell/welcome", "Install our free MuseSounds libraries"));
60 0 : freeMuseSounds.insert("imageUrl", "qrc:/resources/welcomedialog/MuseSounds.png");
61 0 : freeMuseSounds.insert("description", muse::qtrc("appshell/welcome",
62 : "Explore our collection of realistic sample libraries, including solo instruments, marching percussion, and full orchestra - available for free on MuseHub."));
63 0 : freeMuseSounds.insert("buttonText", muse::qtrc("appshell/welcome", "Get it on MuseHub"));
64 0 : freeMuseSounds.insert("destinationUrl",
65 : "https://www.musehub.com/free-musesounds?utm_source=mss-app-welcome-free-musesounds&utm_medium=mss-app-welcome-free-musesounds&utm_campaign=mss-app-welcome-free-musesounds&utm_id=mss-app-welcome-free-musesounds");
66 :
67 0 : QVariantMap exploreTutorials;
68 0 : exploreTutorials.insert("title", muse::qtrc("appshell/welcome", "Explore our tutorials"));
69 0 : exploreTutorials.insert("imageUrl", "qrc:/resources/welcomedialog/ExploreTutorials.png");
70 0 : exploreTutorials.insert("description", muse::qtrc("appshell/welcome",
71 : "We’ve put together a playlist of tutorials to help both beginners and experienced users get the most out of MuseScore Studio."));
72 0 : exploreTutorials.insert("buttonText", muse::qtrc("appshell/welcome", "View tutorials"));
73 0 : exploreTutorials.insert("destinationUrl",
74 : "https://www.youtube.com/playlist?list=PLTYuWi2LmaPECOZrC6bkPHBkYY9_WEexT&utm_source=mss-app-welcome-tutorials&utm_medium=mss-app-welcome-tutorials&utm_campaign=mss-app-welcome-tutorials&utm_id=mss-app-welcome-tutorials");
75 :
76 : //! NOTE: This is the order the above items will appear in the carousel
77 0 : return { museSoundsPro, whatsNew, cloudStorage, freeMuseSounds, exploreTutorials };
78 0 : }
79 :
80 0 : WelcomeDialogModel::WelcomeDialogModel()
81 0 : : muse::Contextable(muse::iocCtxForQmlObject(this))
82 : {
83 0 : }
84 :
85 0 : void WelcomeDialogModel::init()
86 : {
87 0 : IF_ASSERT_FAILED(configuration()) {
88 0 : return;
89 : }
90 :
91 0 : m_items = welcomeDialogData();
92 :
93 0 : m_currentIndex = configuration()->welcomeDialogLastShownIndex();
94 0 : nextItem();
95 :
96 0 : IF_ASSERT_FAILED(m_currentIndex != muse::nidx) {
97 0 : m_currentIndex = 0;
98 : }
99 0 : configuration()->setWelcomeDialogLastShownIndex(static_cast<int>(m_currentIndex));
100 :
101 0 : emit itemsChanged();
102 0 : emit currentItemChanged();
103 : }
104 :
105 0 : QVariantMap WelcomeDialogModel::currentItem() const
106 : {
107 0 : if (m_items.empty()) {
108 0 : return QVariantMap();
109 : }
110 0 : return m_items.at(m_currentIndex);
111 : }
112 :
113 0 : void WelcomeDialogModel::nextItem()
114 : {
115 0 : IF_ASSERT_FAILED(!m_items.empty()) {
116 0 : return;
117 : }
118 :
119 0 : if (hasNext()) {
120 0 : ++m_currentIndex;
121 : } else {
122 : // Cycle to first...
123 0 : m_currentIndex = 0;
124 : }
125 0 : configuration()->setWelcomeDialogLastShownIndex(static_cast<int>(m_currentIndex));
126 :
127 0 : emit currentItemChanged();
128 : }
129 :
130 0 : void WelcomeDialogModel::prevItem()
131 : {
132 0 : IF_ASSERT_FAILED(!m_items.empty()) {
133 0 : return;
134 : }
135 :
136 0 : if (hasPrev()) {
137 0 : --m_currentIndex;
138 : } else {
139 : // Cycle to last....
140 0 : m_currentIndex = count() - 1;
141 : }
142 0 : configuration()->setWelcomeDialogLastShownIndex(static_cast<int>(m_currentIndex));
143 :
144 0 : emit currentItemChanged();
145 : }
146 :
147 0 : bool WelcomeDialogModel::showOnStartup() const
148 : {
149 0 : return configuration()->welcomeDialogShowOnStartup();
150 : }
151 :
152 0 : void WelcomeDialogModel::setShowOnStartup(bool show)
153 : {
154 0 : if (show == showOnStartup()) {
155 0 : return;
156 : }
157 :
158 0 : configuration()->setWelcomeDialogShowOnStartup(show);
159 0 : emit showOnStartupChanged();
160 : }
|