diff --git a/build/module.cmake b/build/module.cmake
index 7d39360..5bd299f 100644
--- a/build/module.cmake
+++ b/build/module.cmake
@@ -20,6 +20,8 @@ set(QML_IMPORT_PATH "${QML_IMPORT_PATH};${CMAKE_CURRENT_LIST_DIR}"
)
target_link_libraries(${MODULE} PRIVATE ${QT_LIBS})
+target_include_directories(${MODULE} PRIVATE ${PROJECT_SOURCE_DIR}/src)
+target_include_directories(${MODULE} PRIVATE ${PROJECT_SOURCE_DIR}/src/global)
list(APPEND QML_IMPORT_PATH ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
list(REMOVE_DUPLICATES QML_IMPORT_PATH)
diff --git a/res/icons/CMakeLists.txt b/res/icons/CMakeLists.txt
index 48add58..b9e1f5a 100644
--- a/res/icons/CMakeLists.txt
+++ b/res/icons/CMakeLists.txt
@@ -10,5 +10,6 @@ qt_add_resources(
PREFIX "/icons/scratchcpp/32x32"
FILES
green_flag.svg
- stop.svg
+ stop.svg
+ turbo.svg
)
diff --git a/res/icons/turbo.svg b/res/icons/turbo.svg
new file mode 100644
index 0000000..64fd166
--- /dev/null
+++ b/res/icons/turbo.svg
@@ -0,0 +1,12 @@
+
+
\ No newline at end of file
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index e952081..35484ce 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -2,3 +2,4 @@ add_subdirectory(app)
add_subdirectory(global)
add_subdirectory(uicomponents)
+add_subdirectory(keyboard)
diff --git a/src/app/appmenubar.cpp b/src/app/appmenubar.cpp
index 9cedf46..b92b543 100644
--- a/src/app/appmenubar.cpp
+++ b/src/app/appmenubar.cpp
@@ -21,7 +21,7 @@ AppMenuBar::AppMenuBar(QObject *parent) :
// File menu
m_fileMenu = new MenuModel(m_model);
- m_fileMenu->setTitle(tr("File"));
+ m_fileMenu->setTitle(tr("&File"));
m_model->addMenu(m_fileMenu);
// File -> Open
@@ -33,6 +33,19 @@ AppMenuBar::AppMenuBar(QObject *parent) :
#ifdef Q_OS_WASM
connect(m_openFileDialog, &FileDialog::fileContentReady, this, &AppMenuBar::loadOpenedFile);
#endif
+
+ // Edit menu
+ m_editMenu = new MenuModel(m_model);
+ m_editMenu->setTitle(tr("&Edit"));
+ m_model->addMenu(m_editMenu);
+
+ // Edit -> Turbo mode
+ m_turboModeItem = new MenuItemModel(m_editMenu);
+ m_turboModeItem->setText(tr("Turbo Mode"));
+ m_turboModeItem->setCheckable(true);
+ m_turboModeItem->setChecked(false);
+ m_editMenu->addItem(m_turboModeItem);
+ connect(m_turboModeItem, &MenuItemModel::checkedChanged, this, &AppMenuBar::turboModeChanged);
}
MenuBarModel *AppMenuBar::model() const
@@ -68,3 +81,16 @@ void AppMenuBar::loadOpenedFile(const QByteArray &content)
qWarning("Failed to create temporary file.");
}
#endif
+
+bool AppMenuBar::turboMode() const
+{
+ return m_turboModeItem->checked();
+}
+
+void AppMenuBar::setTurboMode(bool newTurboMode)
+{
+ if (m_turboModeItem->checked() == newTurboMode)
+ return;
+
+ m_turboModeItem->setChecked(newTurboMode);
+}
diff --git a/src/app/appmenubar.h b/src/app/appmenubar.h
index 0936081..0933543 100644
--- a/src/app/appmenubar.h
+++ b/src/app/appmenubar.h
@@ -27,15 +27,20 @@ class AppMenuBar : public QObject
QML_ELEMENT
QML_SINGLETON
Q_PROPERTY(uicomponents::MenuBarModel *model READ model NOTIFY modelChanged)
+ Q_PROPERTY(bool turboMode READ turboMode WRITE setTurboMode NOTIFY turboModeChanged)
public:
explicit AppMenuBar(QObject *parent = nullptr);
uicomponents::MenuBarModel *model() const;
+ bool turboMode() const;
+ void setTurboMode(bool newTurboMode);
+
signals:
void modelChanged();
void fileOpened(const QString &fileName);
+ void turboModeChanged();
private:
void openFile();
@@ -44,10 +49,14 @@ class AppMenuBar : public QObject
#endif
uicomponents::MenuBarModel *m_model = nullptr;
+
uicomponents::MenuModel *m_fileMenu = nullptr;
uicomponents::MenuItemModel *m_openFileItem = nullptr;
uicomponents::FileDialog *m_openFileDialog = nullptr;
QTemporaryFile *m_tmpFile = nullptr;
+
+ uicomponents::MenuModel *m_editMenu = nullptr;
+ uicomponents::MenuItemModel *m_turboModeItem = nullptr;
};
} // namespace scratchcpp
diff --git a/src/app/main.cpp b/src/app/main.cpp
index 0f2df14..b1a3f30 100644
--- a/src/app/main.cpp
+++ b/src/app/main.cpp
@@ -1,12 +1,16 @@
// SPDX-License-Identifier: GPL-3.0-or-later
#include "app.h"
+#include "globalmodule.h"
+#include "keyboard/keyboardmodule.h"
using namespace scratchcpp;
int main(int argc, char *argv[])
{
App app;
+ app.addModule(new GlobalModule);
+ app.addModule(new keyboard::KeyboardModule);
return app.run(argc, argv);
}
diff --git a/src/app/main.qml b/src/app/main.qml
index c260dc6..27b9642 100644
--- a/src/app/main.qml
+++ b/src/app/main.qml
@@ -6,6 +6,7 @@ import QtQuick.Layouts
import ScratchCPP
import ScratchCPP.UiComponents
import ScratchCPP.Render
+import ScratchCPP.Keyboard
ApplicationWindow {
id: root
@@ -40,12 +41,17 @@ ApplicationWindow {
Layout.fillWidth: true
CustomToolButton {
+ id: greenFlagButton
icon.name: "green_flag"
icon.color: "transparent"
onClicked: {
- player.stop()
- player.start()
- player.forceActiveFocus(Qt.TabFocusReason);
+ if (KeyboardInfo.keyboardModifiers() === Qt.ShiftModifier)
+ AppMenuBar.turboMode = !AppMenuBar.turboMode
+ else {
+ player.stop()
+ player.start()
+ player.forceActiveFocus(Qt.TabFocusReason);
+ }
}
}
@@ -57,6 +63,22 @@ ApplicationWindow {
}
}
+ IconLabel {
+ icon.name: "turbo"
+ icon.color: "transparent"
+ text: qsTr("Turbo Mode")
+ color: Qt.rgba(1, 0.67, 0.1, 1)
+ visible: AppMenuBar.turboMode
+
+ font {
+ // Reuse the font from the green flag button
+ family: greenFlagButton.font.family
+ capitalization: Font.MixedCase
+ pointSize: 8
+ bold: true
+ }
+ }
+
TextField {
id: urlField
Layout.fillWidth: true
@@ -78,6 +100,7 @@ ApplicationWindow {
activeFocusOnTab: true
focus: true
spriteFencing: false
+ turboMode: AppMenuBar.turboMode
stageRect.border.color: Material.theme == Material.Dark ? Qt.rgba(1, 1, 1, 0.15) : Qt.rgba(0, 0, 0, 0.15)
stageRect.border.width: 5
}
diff --git a/src/keyboard/CMakeLists.txt b/src/keyboard/CMakeLists.txt
new file mode 100644
index 0000000..1986bb9
--- /dev/null
+++ b/src/keyboard/CMakeLists.txt
@@ -0,0 +1,11 @@
+set(MODULE keyboard)
+set(MODULE_URI Keyboard)
+set(MODULE_SRC
+ keyboardmodule.cpp
+ keyboardmodule.h
+ ikeyboardinfo.h
+ internal/keyboardinfo.cpp
+ internal/keyboardinfo.h
+)
+
+include(${PROJECT_SOURCE_DIR}/build/module.cmake)
diff --git a/src/keyboard/ikeyboardinfo.h b/src/keyboard/ikeyboardinfo.h
new file mode 100644
index 0000000..df93b49
--- /dev/null
+++ b/src/keyboard/ikeyboardinfo.h
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#pragma once
+
+#include
+#include
+
+namespace scratchcpp::keyboard
+{
+
+class IKeyboardInfo : MODULE_EXPORT_INTERFACE
+{
+ public:
+ virtual ~IKeyboardInfo() { }
+
+ virtual Qt::KeyboardModifiers keyboardModifiers() const = 0;
+};
+
+} // namespace scratchcpp::keyboard
diff --git a/src/keyboard/internal/keyboardinfo.cpp b/src/keyboard/internal/keyboardinfo.cpp
new file mode 100644
index 0000000..2432ace
--- /dev/null
+++ b/src/keyboard/internal/keyboardinfo.cpp
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include
+
+#include "keyboardinfo.h"
+
+using namespace scratchcpp::keyboard;
+
+KeyboardInfo::KeyboardInfo(QObject *parent) :
+ QObject(parent)
+{
+}
+
+Qt::KeyboardModifiers KeyboardInfo::keyboardModifiers() const
+{
+ return QGuiApplication::keyboardModifiers();
+}
diff --git a/src/keyboard/internal/keyboardinfo.h b/src/keyboard/internal/keyboardinfo.h
new file mode 100644
index 0000000..1338d43
--- /dev/null
+++ b/src/keyboard/internal/keyboardinfo.h
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#pragma once
+
+#include
+
+#include "ikeyboardinfo.h"
+
+namespace scratchcpp::keyboard
+{
+
+class KeyboardInfo
+ : public QObject
+ , public IKeyboardInfo
+{
+ Q_OBJECT
+
+ public:
+ explicit KeyboardInfo(QObject *parent = nullptr);
+
+ Q_INVOKABLE Qt::KeyboardModifiers keyboardModifiers() const override;
+};
+
+} // namespace scratchcpp::keyboard
diff --git a/src/keyboard/keyboardmodule.cpp b/src/keyboard/keyboardmodule.cpp
new file mode 100644
index 0000000..a43b071
--- /dev/null
+++ b/src/keyboard/keyboardmodule.cpp
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include
+
+#include "modularity/ioc.h"
+#include "keyboardmodule.h"
+#include "internal/keyboardinfo.h"
+
+using namespace scratchcpp::keyboard;
+
+std::string KeyboardModule::moduleName() const
+{
+ return "keyboard";
+}
+
+void KeyboardModule::registerExports()
+{
+ m_keyboardInfo = std::make_shared();
+
+ QQmlEngine::setObjectOwnership(m_keyboardInfo.get(), QQmlEngine::CppOwnership);
+ qmlRegisterSingletonInstance("ScratchCPP.Keyboard", 1, 0, "KeyboardInfo", m_keyboardInfo.get());
+ modularity::ioc()->registerExport(m_keyboardInfo);
+}
diff --git a/src/keyboard/keyboardmodule.h b/src/keyboard/keyboardmodule.h
new file mode 100644
index 0000000..f36ca30
--- /dev/null
+++ b/src/keyboard/keyboardmodule.h
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#pragma once
+
+#include
+
+#include "modularity/imodulesetup.h"
+
+namespace scratchcpp::keyboard
+{
+
+class KeyboardInfo;
+
+class KeyboardModule : public modularity::IModuleSetup
+{
+ public:
+ std::string moduleName() const override;
+
+ void registerExports() override;
+
+ private:
+ std::shared_ptr m_keyboardInfo;
+};
+
+} // namespace scratchcpp::keyboard