From cea62ebc0ab1e062e058aac783b8566c800d5643 Mon Sep 17 00:00:00 2001
From: tobiglaser <76131623+tobiglaser@users.noreply.github.com>
Date: Thu, 17 Apr 2025 18:00:04 +0200
Subject: [PATCH] initial commit
---
.clang-format | 287 ++++++++++++++++++++++++++++++++++
.gitignore | 58 +++++++
.vscode/extensions.json | 11 ++
.vscode/launch.json | 16 ++
CMakeLists.txt | 112 +++++++++++++
docs/newAPI-Function.md | 49 ++++++
examples/bubblesort.cpp | 70 +++++++++
examples/dynamicLoadDummy.cpp | 90 +++++++++++
examples/studiMain.cpp | 155 ++++++++++++++++++
include/cute.h | 90 +++++++++++
include/dllDefines.h | 29 ++++
src/algoThread.h | 29 ++++
src/chartMenu.cpp | 54 +++++++
src/chartMenu.h | 35 +++++
src/configPanel.cpp | 92 +++++++++++
src/configPanel.h | 37 +++++
src/control.cpp | 193 +++++++++++++++++++++++
src/control.h | 66 ++++++++
src/cute.cpp | 127 +++++++++++++++
src/cute.def | 17 ++
src/cuteControl.cpp | 3 +
src/cuteControl.h | 148 ++++++++++++++++++
src/cuteImporter.cpp | 149 ++++++++++++++++++
src/graphNames.cpp | 13 ++
src/graphNames.h | 9 ++
src/main.cpp | 12 ++
src/mainWindow.cpp | 243 ++++++++++++++++++++++++++++
src/mainWindow.h | 51 ++++++
28 files changed, 2245 insertions(+)
create mode 100644 .clang-format
create mode 100644 .gitignore
create mode 100644 .vscode/extensions.json
create mode 100644 .vscode/launch.json
create mode 100644 CMakeLists.txt
create mode 100644 docs/newAPI-Function.md
create mode 100644 examples/bubblesort.cpp
create mode 100644 examples/dynamicLoadDummy.cpp
create mode 100644 examples/studiMain.cpp
create mode 100644 include/cute.h
create mode 100644 include/dllDefines.h
create mode 100644 src/algoThread.h
create mode 100644 src/chartMenu.cpp
create mode 100644 src/chartMenu.h
create mode 100644 src/configPanel.cpp
create mode 100644 src/configPanel.h
create mode 100644 src/control.cpp
create mode 100644 src/control.h
create mode 100644 src/cute.cpp
create mode 100644 src/cute.def
create mode 100644 src/cuteControl.cpp
create mode 100644 src/cuteControl.h
create mode 100644 src/cuteImporter.cpp
create mode 100644 src/graphNames.cpp
create mode 100644 src/graphNames.h
create mode 100644 src/main.cpp
create mode 100644 src/mainWindow.cpp
create mode 100644 src/mainWindow.h
diff --git a/.clang-format b/.clang-format
new file mode 100644
index 0000000..293140a
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,287 @@
+Language: Cpp
+AccessModifierOffset: -4
+AlignAfterOpenBracket: Align
+AlignArrayOfStructures: Right
+AlignConsecutiveAssignments:
+ Enabled: true
+ AcrossEmptyLines: false
+ AcrossComments: false
+ AlignCompound: true
+ AlignFunctionDeclarations: true
+ AlignFunctionPointers: false
+ PadOperators: true
+AlignConsecutiveBitFields:
+ Enabled: true
+ AcrossEmptyLines: false
+ AcrossComments: false
+ AlignCompound: true
+ AlignFunctionDeclarations: true
+ AlignFunctionPointers: false
+ PadOperators: true
+AlignConsecutiveDeclarations:
+ Enabled: true
+ AcrossEmptyLines: false
+ AcrossComments: false
+ AlignCompound: true
+ AlignFunctionDeclarations: true
+ AlignFunctionPointers: false
+ PadOperators: true
+AlignConsecutiveMacros:
+ Enabled: true
+ AcrossEmptyLines: false
+ AcrossComments: false
+ AlignCompound: true
+ AlignFunctionDeclarations: true
+ AlignFunctionPointers: false
+ PadOperators: true
+AlignConsecutiveShortCaseStatements:
+ Enabled: true
+ AcrossEmptyLines: true
+ AcrossComments: true
+ AlignCaseArrows: true
+ AlignCaseColons: true
+AlignConsecutiveTableGenBreakingDAGArgColons:
+ Enabled: true
+ AcrossEmptyLines: false
+ AcrossComments: false
+ AlignCompound: false
+ AlignFunctionDeclarations: false
+ AlignFunctionPointers: false
+ PadOperators: false
+AlignConsecutiveTableGenCondOperatorColons:
+ Enabled: true
+ AcrossEmptyLines: false
+ AcrossComments: false
+ AlignCompound: false
+ AlignFunctionDeclarations: false
+ AlignFunctionPointers: false
+ PadOperators: false
+AlignConsecutiveTableGenDefinitionColons:
+ Enabled: true
+ AcrossEmptyLines: false
+ AcrossComments: false
+ AlignCompound: false
+ AlignFunctionDeclarations: false
+ AlignFunctionPointers: false
+ PadOperators: false
+AlignEscapedNewlines: LeftWithLastLine
+AlignOperands: AlignAfterOperator
+AlignTrailingComments:
+ Kind: Always
+ OverEmptyLines: 0
+AllowAllArgumentsOnNextLine: true
+AllowAllParametersOfDeclarationOnNextLine: true
+AllowBreakBeforeNoexceptSpecifier: Never
+AllowShortBlocksOnASingleLine: Empty
+AllowShortCaseExpressionOnASingleLine: true
+AllowShortCaseLabelsOnASingleLine: true
+AllowShortCompoundRequirementOnASingleLine: true
+AllowShortEnumsOnASingleLine: false
+AllowShortFunctionsOnASingleLine: Inline
+AllowShortIfStatementsOnASingleLine: Never
+AllowShortLambdasOnASingleLine: All
+AllowShortLoopsOnASingleLine: false
+AllowShortNamespacesOnASingleLine: false
+AlwaysBreakAfterDefinitionReturnType: None
+AlwaysBreakBeforeMultilineStrings: false
+AttributeMacros:
+ - __capability
+BinPackArguments: false
+BinPackParameters: OnePerLine
+BitFieldColonSpacing: Both
+BraceWrapping:
+ AfterCaseLabel: false
+ AfterClass: true
+ AfterControlStatement: Always
+ AfterEnum: true
+ AfterExternBlock: true
+ AfterFunction: true
+ AfterNamespace: true
+ AfterObjCDeclaration: true
+ AfterStruct: true
+ AfterUnion: true
+ BeforeCatch: true
+ BeforeElse: true
+ BeforeLambdaBody: false
+ BeforeWhile: false
+ IndentBraces: false
+ SplitEmptyFunction: true
+ SplitEmptyRecord: true
+ SplitEmptyNamespace: true
+BreakAdjacentStringLiterals: true
+BreakAfterAttributes: Leave
+BreakAfterJavaFieldAnnotations: false
+BreakAfterReturnType: Automatic
+BreakArrays: true
+BreakBeforeBinaryOperators: All
+BreakBeforeConceptDeclarations: Always
+BreakBeforeBraces: Custom
+BreakBeforeInlineASMColon: OnlyMultiline
+BreakBeforeTernaryOperators: true
+BreakBinaryOperations: OnePerLine
+BreakConstructorInitializers: BeforeColon
+BreakFunctionDefinitionParameters: false
+BreakInheritanceList: BeforeColon
+BreakStringLiterals: true
+BreakTemplateDeclarations: MultiLine
+ColumnLimit: 120
+CommentPragmas: '^ IWYU pragma:'
+CompactNamespaces: false
+ConstructorInitializerIndentWidth: 4
+ContinuationIndentWidth: 4
+Cpp11BracedListStyle: true
+DerivePointerAlignment: false
+DisableFormat: false
+EmptyLineAfterAccessModifier: Never
+EmptyLineBeforeAccessModifier: LogicalBlock
+FixNamespaceComments: true
+ForEachMacros:
+ - foreach
+ - Q_FOREACH
+ - BOOST_FOREACH
+IfMacros:
+ - KJ_IF_MAYBE
+IncludeBlocks: Regroup
+IncludeCategories:
+ - Regex: '^"(llvm|llvm-c|clang|clang-c)/'
+ Priority: 2
+ SortPriority: 0
+ CaseSensitive: false
+ - Regex: '^(<|"(gtest|gmock|isl|json)/)'
+ Priority: 3
+ SortPriority: 0
+ CaseSensitive: false
+ - Regex: '.*'
+ Priority: 1
+ SortPriority: 0
+ CaseSensitive: false
+IncludeIsMainRegex: '(Test)?$'
+IncludeIsMainSourceRegex: ''
+IndentAccessModifiers: false
+IndentCaseBlocks: false
+IndentCaseLabels: true
+IndentExportBlock: true
+IndentExternBlock: AfterExternBlock
+IndentGotoLabels: true
+IndentPPDirectives: BeforeHash
+IndentRequiresClause: true
+IndentWidth: 4
+IndentWrappedFunctionNames: false
+InsertBraces: false
+InsertNewlineAtEOF: true
+InsertTrailingCommas: None
+IntegerLiteralSeparator:
+ Binary: 4
+ BinaryMinDigits: 8
+ Decimal: 3
+ DecimalMinDigits: 5
+ Hex: 4
+ HexMinDigits: 8
+JavaScriptQuotes: Leave
+JavaScriptWrapImports: true
+KeepEmptyLines:
+ AtEndOfFile: false
+ AtStartOfBlock: true
+ AtStartOfFile: true
+KeepFormFeed: false
+LambdaBodyIndentation: Signature
+LineEnding: DeriveLF
+MacroBlockBegin: ''
+MacroBlockEnd: ''
+MainIncludeChar: Quote
+MaxEmptyLinesToKeep: 2
+NamespaceIndentation: All
+ObjCBinPackProtocolList: Auto
+ObjCBlockIndentWidth: 2
+ObjCBreakBeforeNestedBlockParam: true
+ObjCSpaceAfterProperty: false
+ObjCSpaceBeforeProtocolList: true
+PackConstructorInitializers: CurrentLine
+PenaltyBreakAssignment: 2
+PenaltyBreakBeforeFirstCallParameter: 19
+PenaltyBreakBeforeMemberAccess: 150
+PenaltyBreakComment: 300
+PenaltyBreakFirstLessLess: 120
+PenaltyBreakOpenParenthesis: 0
+PenaltyBreakScopeResolution: 500
+PenaltyBreakString: 1000
+PenaltyBreakTemplateDeclaration: 10
+PenaltyExcessCharacter: 1000000
+PenaltyIndentedWhitespace: 0
+PenaltyReturnTypeOnItsOwnLine: 1000
+PointerAlignment: Left
+PPIndentWidth: -1
+QualifierAlignment: Left
+ReferenceAlignment: Pointer
+ReflowComments: Always
+RemoveBracesLLVM: false
+RemoveEmptyLinesInUnwrappedLines: true
+RemoveParentheses: Leave
+RemoveSemicolon: false
+RequiresClausePosition: OwnLine
+RequiresExpressionIndentation: OuterScope
+SeparateDefinitionBlocks: Leave
+ShortNamespaceLines: 1
+SkipMacroDefinitionBody: false
+SortIncludes: CaseSensitive
+SortJavaStaticImport: Before
+SortUsingDeclarations: LexicographicNumeric
+SpaceAfterCStyleCast: false
+SpaceAfterLogicalNot: false
+SpaceAfterTemplateKeyword: false
+SpaceAroundPointerQualifiers: Default
+SpaceBeforeAssignmentOperators: true
+SpaceBeforeCaseColon: false
+SpaceBeforeCpp11BracedList: false
+SpaceBeforeCtorInitializerColon: true
+SpaceBeforeInheritanceColon: true
+SpaceBeforeJsonColon: false
+SpaceBeforeParens: ControlStatementsExceptControlMacros
+SpaceBeforeParensOptions:
+ AfterControlStatements: true
+ AfterForeachMacros: true
+ AfterFunctionDefinitionName: false
+ AfterFunctionDeclarationName: false
+ AfterIfMacros: true
+ AfterOverloadedOperator: false
+ AfterPlacementOperator: true
+ AfterRequiresInClause: false
+ AfterRequiresInExpression: false
+ BeforeNonEmptyParentheses: false
+SpaceBeforeRangeBasedForLoopColon: true
+SpaceBeforeSquareBrackets: false
+SpaceInEmptyBlock: false
+SpacesBeforeTrailingComments: 1
+SpacesInAngles: Never
+SpacesInContainerLiterals: true
+SpacesInLineCommentPrefix:
+ Minimum: 0
+ Maximum: -1
+SpacesInParens: Never
+SpacesInParensOptions:
+ ExceptDoubleParentheses: false
+ InCStyleCasts: false
+ InConditionalStatements: false
+ InEmptyParentheses: false
+ Other: false
+SpacesInSquareBrackets: false
+Standard: Latest
+StatementAttributeLikeMacros:
+ - Q_EMIT
+ - emit
+StatementMacros:
+ - Q_UNUSED
+ - QT_REQUIRE_VERSION
+TableGenBreakInsideDAGArg: DontBreak
+TabWidth: 4
+UseTab: Never
+VerilogBreakBetweenInstancePorts: true
+WhitespaceSensitiveMacros:
+ - BOOST_PP_STRINGIZE
+ - CF_SWIFT_NAME
+ - NS_SWIFT_NAME
+ - PP_STRINGIZE
+ - STRINGIZE
+WrapNamespaceBodyWithEmptyLines: Leave
+...
+
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..6e700b4
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,58 @@
+*~
+*.autosave
+*.a
+*.core
+*.moc
+*.o
+*.obj
+*.orig
+*.rej
+*.so
+*.so.*
+*_pch.h.cpp
+*_resource.rc
+*.qm
+.#*
+*.*#
+core
+!core/
+tags
+.DS_Store
+.directory
+*.debug
+Makefile*
+*.prl
+*.app
+moc_*.cpp
+ui_*.h
+qrc_*.cpp
+Thumbs.db
+*.res
+*.rc
+/.qmake.cache
+/.qmake.stash
+*.pro.user*
+CMakeLists.txt.user*
+*.flc
+.*.swp
+*.ib_pdb_index
+*.idb
+*.ilk
+*.pdb
+*.sln
+*.suo
+*.vcproj
+*vcproj.*.*.user
+*.ncb
+*.sdf
+*.opensdf
+*.vcxproj
+*vcxproj.*
+*.Debug
+*.Release
+*.pyc
+*.dll
+*.exe
+build/
+.cache/
+settings.json
\ No newline at end of file
diff --git a/.vscode/extensions.json b/.vscode/extensions.json
new file mode 100644
index 0000000..a0ae39d
--- /dev/null
+++ b/.vscode/extensions.json
@@ -0,0 +1,11 @@
+{
+ "recommendations": [
+ "aaron-bond.better-comments",
+ "ms-vscode.cpptools-extension-pack",
+ "vadimcn.vscode-lldb",
+ "mhutchie.git-graph",
+ "cschlosser.doxdocgen",
+ "oderwat.indent-rainbow",
+ "llvm-vs-code-extensions.vscode-clangd"
+ ]
+}
\ No newline at end of file
diff --git a/.vscode/launch.json b/.vscode/launch.json
new file mode 100644
index 0000000..f90d82b
--- /dev/null
+++ b/.vscode/launch.json
@@ -0,0 +1,16 @@
+// Use IntelliSense to learn about possible attributes.
+// Hover to view descriptions of existing attributes.
+// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
+{
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "name": "(lldb) Launch",
+ "type": "lldb",
+ "request": "launch",
+ "program": "${command:cmake.launchTargetPath}",
+ "args": [],
+ "cwd": "${workspaceFolder}/build"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..94ffedd
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,112 @@
+cmake_minimum_required(VERSION 3.18)
+
+project(SimpleTest VERSION 0.1 LANGUAGES CXX)
+
+set(CMAKE_AUTOUIC ON)
+set(CMAKE_AUTOMOC ON)
+set(CMAKE_AUTORCC ON)
+
+set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+
+
+if(WIN32)
+ set(CMAKE_FIND_LIBRARY_SUFFIXES ".a" ${CMAKE_FIND_LIBRARY_SUFFIXES})
+ set(Qt5_DIR "C:/msys64/clang64/qt5-static/lib/cmake/Qt5")#ucrt64
+endif()
+
+set(CMAKE_CXX_STANDARD_LIBRARIES "-stdlib=libc++")
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra")
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fuse-ld=lld -static")# -static-libstdc++")# -static-libgcc")# -stdlib=libc++ -lc++ -lc++abi
+set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -s")
+
+
+find_package(Qt5 REQUIRED COMPONENTS Widgets Charts)
+#find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets Charts)
+#find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets Charts)
+
+set(PROJECT_SOURCES
+ src/mainWindow.cpp
+ src/configPanel.cpp
+ src/chartMenu.cpp
+ src/graphNames.cpp
+ src/cute.cpp
+ src/control.cpp
+ src/cuteControl.cpp
+)
+
+#target_include_directories(SimpleTest PRIVATE
+# /usr/include/x86_64-linux-gnu/qt6/QtWidgets
+# /usr/include/x86_64-linux-gnu/qt6/QtCharts
+#)
+
+add_library(cute SHARED
+ ${PROJECT_SOURCES}
+ src/cute.def
+)
+
+target_link_libraries(cute PRIVATE #"-Wl,--no-whole-archive"
+ Qt${QT_VERSION_MAJOR}::Widgets
+ Qt${QT_VERSION_MAJOR}::Charts
+)
+
+target_include_directories(cute PRIVATE
+ include
+)
+
+target_compile_definitions(cute PRIVATE
+ EXPORT_CUTE
+ QT_NO_VERSION_TAGGING
+)
+
+if (WIN32)
+ set_target_properties(cute PROPERTIES PREFIX "")
+endif()
+set_target_properties(cute PROPERTIES LINK_FLAGS "-Wl,--output-def,cute.def")
+
+
+add_executable(DynamicDemo
+ src/main.cpp
+ examples/studiMain.cpp
+)
+
+target_link_libraries(DynamicDemo PRIVATE
+ cute
+)
+
+target_include_directories(DynamicDemo PRIVATE
+ include
+)
+
+# Set the WIN32_EXECUTABLE property conditionally for Release, MinSizeRel, and RelWithDebInfo builds.
+# This lets the exe run without a terminal, making stdout inaccessible for now.
+if(WIN32)
+ set_target_properties(DynamicDemo PROPERTIES WIN32_EXECUTABLE $<OR:$<CONFIG:Release>,$<CONFIG:MinSizeRel>,$<CONFIG:RelWithDebInfo>>)
+endif(WIN32)
+
+
+add_executable(LoaderDemo
+ src/main.cpp
+ src/cuteImporter.cpp
+ examples/dynamicLoadDummy.cpp
+)
+
+target_include_directories(LoaderDemo PRIVATE
+ include
+)
+
+target_compile_definitions(LoaderDemo PRIVATE
+ RUNTIME_LOAD
+)
+
+# Set the WIN32_EXECUTABLE property conditionally for Release, MinSizeRel, and RelWithDebInfo builds.
+# This lets the exe run without a terminal, making stdout inaccessible for now.
+if(WIN32)
+ set_target_properties(LoaderDemo PROPERTIES WIN32_EXECUTABLE $<OR:$<CONFIG:Release>,$<CONFIG:MinSizeRel>,$<CONFIG:RelWithDebInfo>>)
+endif(WIN32)
+
+# Use this command to copy the .dll from the lib folder next to the freshly built .exe. Which is the most simple way to get it working.
+#add_custom_command(TARGET LoaderDemo POST_BUILD # Adds a post-build event to DynamicDemo
+# COMMAND ${CMAKE_COMMAND} -E copy_if_different # which executes "cmake - E copy_if_different..."
+# "${PROJECT_SOURCE_DIR}/lib/cute.dll" # <--this is in-file
+# $<TARGET_FILE_DIR:LoaderDemo>) # <--this is out-file path
diff --git a/docs/newAPI-Function.md b/docs/newAPI-Function.md
new file mode 100644
index 0000000..9b9f83b
--- /dev/null
+++ b/docs/newAPI-Function.md
@@ -0,0 +1,49 @@
+To add a new function to the cute Interface, follow these steps:
+
+1. Declare the function in cute.h with `DYNAMIC`.
+```
+void DYNAMIC setPlotTheme(int themeNumber);
+```
+2. Define the function in cute.cpp. Most likely you just funnel the call and it's parameters into the `CuteControl`-Singleton, to then be able to use Qt's signals and slots.
+```
+void cute::setPlotTheme(int themeNumber)
+{
+CuteControl::get().setPlotTheme(themeNumber);
+}
+```
+3. Define a `signal` in CuteControl, corresponding to your function. To avoid naming conflicts, I used the prefix `s_` in CuteControl. `signals` are always void functions, they are defined by the Qt Meta Object Compiler during the compilation. Think of them as part of the Observer-Pattern, they send a `signal` to all connected `slots`.
+```
+void s_setPlotTheme(int);
+```
+
+4. Declare and define the member function publically in CuteControl. Since Qt's built in types, like `QString` don't require extra steps to be able use them in `signals`, it is advisable to any conversions here. Then `emit` a your `signal`, which will carry the necessary information over the thread boundary. `emit` may be thought of as `fireX()` in the Observer-Pattern.
+```
+void setChartTheme(int themeNumber)
+{
+ emit s_setPlotTheme(themeNumber);
+}
+```
+5. Now define the fitting `slot` in `control.h`, which will be used to receive your `signal`. In the Observer-Pattern, this is the listener function. Technically it only needs to be `public`, if you want to connect to or call it from another class.
+```
+public slots:
+ void setPlotTheme(int themeNumber);
+```
+6. Now define the `slot` like a regular function in `control.cpp`. Here is *finally*, where you implementation should be placed. The View lives in the `MainWindow` member `_w`. In this case, I call a member function of the View.
+```
+void Control::setPlotTheme(int themeNumber)
+{
+ _w->changeChartTheme(themeNumber);
+}
+```
+7. Lastly, connect `signal` and `slot` in `makeConnections()` of the `Control`. This completes the Observer-Pattern, by subscribing `Control` to `CuteControl`.
+Connections are pretty resilient. They check if the listener still exists, as well as in which thread they are. If the listener is in another thread, the `signal` will be queued in the threads corresponding event queue.
+With clang, this command has to be quite verbose, the basic pattern is: `Sender, &signal, Receiver, &slot`
+```
+connect(cc, &CuteControl::s_setPlotTheme, this, &Control::setPlotTheme);
+```
+8. Almost forgot: Of course add some Doxygen. At least in `cute.h`.
+
+
+# TODO
+## without importlib
+setPlotTheme=_ZN4cute12setPlotThemeEi
diff --git a/examples/bubblesort.cpp b/examples/bubblesort.cpp
new file mode 100644
index 0000000..a02bc43
--- /dev/null
+++ b/examples/bubblesort.cpp
@@ -0,0 +1,70 @@
+#include "cute.h"
+
+#include <string>
+
+
+using std::vector;
+using std::string, std::to_string;
+
+void algorithm();
+
+
+
+void setup()
+{
+ using namespace cute;
+ registerAlgorithm(algorithm, "Bubblesort");
+
+ setPlotVisible(result, false);
+ setPlotTitle(plot, "Bubblesort");
+ setPlotTitle(runtime, "Laufzeit");
+ setPlotScale(runtime, linear, linear);
+
+ setProblemSize(12); // oder setProblemFile("~/my_data.csv");
+ enableAutorun();
+}
+
+
+void algorithm()
+{
+ cute::Timer timer = cute::Timer();
+ vector<float> data = cute::getProblemData1D();
+ int swaps = 0;
+ bool did_change = true;
+ timer.start();
+ while (did_change)
+ {
+ did_change = false;
+ for (size_t i = 0; i < data.size() - 1; ++i)
+ {
+ if (data[i] > data[i+1])
+ {
+ float temp = data[i];
+ data[i] = data[i + 1];
+ data[i + 1] = temp;
+ did_change = true;
+ ++swaps;
+ timer.pause();
+ cute::resetPlot();
+ cute::plotValues(data);
+ cute::statusMessage(std::to_string(swaps));
+ cute::delay(200);
+ timer.resume();
+ }
+ }
+ }
+ timer.stop();
+ cute::statusMessage("Finished!");
+ string s = "Result: " + to_string(data.size()) + " Values sorted in " + to_string(timer.result()) + "ms.\n";
+ cute::logMessage(s);
+ cute::addRuntime(data.size(), timer.result());
+ return;
+}
+
+
+
+//#include "bubblesort.h"
+int example_main()
+{
+ cute::run(setup);
+}
\ No newline at end of file
diff --git a/examples/dynamicLoadDummy.cpp b/examples/dynamicLoadDummy.cpp
new file mode 100644
index 0000000..133db94
--- /dev/null
+++ b/examples/dynamicLoadDummy.cpp
@@ -0,0 +1,90 @@
+#include "cute.h"
+
+
+void superDummy();
+void advancedDummy();
+void bubblesort();
+
+// Is run once at startup.
+void setup()
+{
+ //cute::setPlotTitle(cute::plot, "Hallo");
+ //cute::setPlotTitle(cute::result, "Hochschule");
+ //cute::setPlotTitle(cute::runtime, "Reutlingen");
+ cute::logMessage("Hello CuteLib! :D");
+ cute::setProgress(69);
+ //cute::setPlotVisible(cute::result);
+ //!cute::statusMessage("Hallo TEC");
+ cute::registerAlgorithm(superDummy, "DummyAlgo");
+ cute::registerAlgorithm(advancedDummy, "Problem");
+ cute::setProblemFile("example.csv");
+ cute::setProblemSize(4);
+ cute::enableAutorun();
+}
+
+void superDummy()
+{
+ int prog = 0;
+ while (cute::ok())
+ {
+ cute::setProgress(prog);
+ //!cute::statusMessage(std::to_string(prog));
+ ++prog;
+ if (prog > 100)
+ prog = 0;
+
+ cute::delay(200);
+ }
+ //std::string s = "Ended cleanly \\(^-^)/";
+ cute::logMessage("Ended cleanly \\(^-^)/");
+ cute::setProgress(0);
+}
+
+
+std::string fvec2str(std::vector<float> v)
+{
+ std::string s;
+ for (size_t i = 0; i < v.size() -1; i++)
+ {
+ s += std::to_string(v[i]);
+ while (s.back() == '0')
+ {
+ s.pop_back();
+ }
+ s += ", ";
+ }
+ s += std::to_string(v.back());
+ while (s.back() == '0')
+ {
+ s.pop_back();
+ }
+ return s;
+}
+
+std::string point2str(cute::Point p)
+{
+ std::string s = "( ";
+ s += std::to_string(p.x);
+ while (s.back() == '0')
+ s.pop_back();
+ s += " , ";
+ s += std::to_string(p.y);
+ while (s.back() == '0')
+ s.pop_back();
+ s += " )";
+ return s;
+}
+
+void advancedDummy()
+{
+ std::vector<float> problem1D = cute::getProblemData1D();
+ cute::logMessage(fvec2str(problem1D));
+ std::vector<cute::Point> problem2D = cute::getProblemData2D();
+ for (auto &&p : problem2D)
+ {
+ cute::logMessage(point2str(p));
+ }
+
+
+ //!cute::statusMessage("Done already!");
+}
diff --git a/examples/studiMain.cpp b/examples/studiMain.cpp
new file mode 100644
index 0000000..1a41b13
--- /dev/null
+++ b/examples/studiMain.cpp
@@ -0,0 +1,155 @@
+#include "cute.h"
+
+
+void superDummy();
+void advancedDummy();
+void bubblesort();
+
+// Is run once at startup.
+void setup()
+{
+ cute::setPlotTitle(cute::plot, "Hallo");
+ cute::setPlotTitle(cute::result, "Hochschule");
+ cute::setPlotTitle(cute::runtime, "Reutlingen");
+ cute::logMessage("Hello CuteLib! :D");
+ cute::setProgress(69);
+ cute::setPlotVisible(cute::result);
+ cute::statusMessage("Hallo TEC");
+ cute::registerAlgorithm(superDummy, "DummyAlgo");
+ cute::registerAlgorithm(advancedDummy, "Problem");
+ cute::registerAlgorithm(bubblesort, "Bubblesort");
+ cute::setProblemFile("example.csv");
+ cute::setProblemSize(4);
+ cute::enableAutorun();
+}
+
+void superDummy()
+{
+ int prog = 0;
+ while (cute::ok())
+ {
+ cute::setProgress(prog);
+ cute::statusMessage(std::to_string(prog));
+ if (prog % 10 == 0)
+ cute::setPlotTheme(prog / 10);
+ ++prog;
+ if (prog > 100)
+ prog = 0;
+
+ cute::delay(200);
+ }
+ //std::string s = "Ended cleanly \\(^-^)/";
+ cute::logMessage("Ended cleanly \\(^-^)/");
+ cute::setProgress(0);
+}
+
+
+std::string fvec2str(std::vector<float> v)
+{
+ std::string s;
+ for (size_t i = 0; i < v.size() -1; i++)
+ {
+ s += std::to_string(v[i]);
+ while (s.back() == '0')
+ {
+ s.pop_back();
+ }
+ s += ", ";
+ }
+ s += std::to_string(v.back());
+ while (s.back() == '0')
+ {
+ s.pop_back();
+ }
+ return s;
+}
+
+std::string point2str(cute::Point p)
+{
+ std::string s = "( ";
+ s += std::to_string(p.x);
+ while (s.back() == '0')
+ s.pop_back();
+ s += " , ";
+ s += std::to_string(p.y);
+ while (s.back() == '0')
+ s.pop_back();
+ s += " )";
+ return s;
+}
+
+void advancedDummy()
+{
+ std::vector<float> problem1D = cute::getProblemData1D();
+ cute::logMessage(fvec2str(problem1D));
+ std::vector<cute::Point> problem2D = cute::getProblemData2D();
+ for (auto &&p : problem2D)
+ {
+ cute::logMessage(point2str(p));
+ }
+
+
+ cute::statusMessage("Done already!");
+}
+
+
+
+/*
+void setup()
+{
+ using namespace cute;
+ registerAlgorithm(algorithm, "Bubblesort");
+
+ setPlotVisible(result, false);
+ setPlotTitle(plot, "Bubblesort");
+ setPlotTitle(runtime, "Laufzeit");
+ setPlotScale(runtime, linear, linear);
+
+ setProblemSize(12); // oder setProblemFile("~/my_data.csv");
+ enableAutorun();
+}
+*/
+
+void bubblesort()
+{
+ using std::vector;
+ using std::string, std::to_string;
+ //cute::Timer timer = cute::Timer();
+ vector<float> data = cute::getProblemData1D();
+ int swaps = 0;
+ bool did_change = true;
+ //timer.start();
+ while (did_change && cute::ok())
+ {
+ did_change = false;
+ for (size_t i = 0; i < data.size() - 1; ++i)
+ {
+ if (data[i] > data[i+1])
+ {
+ float temp = data[i];
+ data[i] = data[i + 1];
+ data[i + 1] = temp;
+ did_change = true;
+ ++swaps;
+ //timer.pause();
+ //cute::resetPlot();
+ //cute::plotValues(data);
+ cute::logMessage(fvec2str(data)); //
+ cute::statusMessage(std::to_string(swaps));
+ cute::delay(200);
+ //timer.resume();
+ }
+ }
+ }
+ //timer.stop();
+ if (cute::ok())
+ {
+ cute::statusMessage("Finished!");
+ string s = "Result: " + to_string(data.size()) + " Values sorted with " + to_string(swaps) + " swaps in "/* + to_string(timer.result())*/ + "ms.\n";
+ cute::logMessage(s);
+ //cute::addRuntime(data.size(), timer.result());
+ }
+ else
+ cute::logMessage(":'(");
+ return;
+}
diff --git a/include/cute.h b/include/cute.h
new file mode 100644
index 0000000..09aad77
--- /dev/null
+++ b/include/cute.h
@@ -0,0 +1,90 @@
+#ifndef CUTE_H
+#define CUTE_H
+
+#include "dllDefines.h"
+#include <vector>
+#include <string>
+#include <chrono>
+
+namespace cute
+{
+ struct Point
+ {
+ float x;
+ float y;
+ };
+ enum Plot
+ {
+ plot,
+ result,
+ runtime
+ };
+ enum Scale
+ {
+ linear,
+ logarithmic
+ };
+
+ void DYNAMIC setPlotVisible(Plot plot, bool visible = true);
+ void DYNAMIC setPlotTitle(Plot plot, const std::string &title);
+ void DYNAMIC setPlotScale(Plot plot, Scale x, Scale y);
+ void DYNAMIC setPlotTheme(int themeNumber);
+
+ void DYNAMIC registerAlgorithm(void (*func)(), const std::string &name);
+
+ void DYNAMIC plotPoints(std::vector<Point>& points);
+ void DYNAMIC plotValues(std::vector<float> &values);
+ void DYNAMIC plotLines(std::vector<Point> &points);
+ void DYNAMIC plotLine(Point &a, Point &b);
+ void DYNAMIC resetPlot();
+
+ void DYNAMIC addResult(float result);
+ void DYNAMIC resetResultPlot();
+
+ void DYNAMIC addRuntime(int problem_size, std::chrono::duration<float, std::milli> duration);
+ void DYNAMIC addRuntime(int problem_size, float milliseconds);
+ void DYNAMIC resetRuntimePlot();
+
+ void DYNAMIC logMessage(const std::string &message);
+ void DYNAMIC statusMessage(const std::string &message);
+ void DYNAMIC setProgress(int percentage);
+
+ const std::vector<float> DYNAMIC &getProblemData1D();
+ const std::vector<Point> DYNAMIC &getProblemData2D();
+
+ void DYNAMIC setProblemFile(const std::string &path);
+ void DYNAMIC setProblemSize(int n);
+ void DYNAMIC enableAutorun(bool run = true);
+
+ void DYNAMIC delay(int milliseconds);
+
+ int DYNAMIC run(void (*setup)());
+ bool DYNAMIC ok();
+
+ class Timer
+ {
+ public:
+ void start();
+ void pause();
+ void resume();
+ void stop();
+ float result();
+ private:
+ std::chrono::duration<float, std::milli> duration;
+ };
+
+ namespace core
+ {
+ // These are for loading and unloading libcute.dll at runtime
+ #if !defined(RUNTIME_LOAD) and !defined(EXPORT_CUTE)
+ inline int initialize() { return 0; }
+ inline void shutdown() {}
+ #else
+ int initialize();
+ void shutdown();
+ #endif
+ }
+}
+
+
+#endif //CUTE_H
diff --git a/include/dllDefines.h b/include/dllDefines.h
new file mode 100644
index 0000000..2479871
--- /dev/null
+++ b/include/dllDefines.h
@@ -0,0 +1,29 @@
+
+#ifdef RUNTIME_LOAD
+ #define DYNAMIC
+#else
+ #ifndef DYNAMIC
+ #ifdef EXPORT_CUTE
+ // Building the library
+ #ifdef _WIN32
+ // Use the Windows-specific export attribute
+ #define DYNAMIC __declspec(dllexport)
+ #elif __GNUC__ >= 4
+ // Use the GCC-specific export attribute
+ #define DYNAMIC __attribute__((visibility("default")))
+ #else
+ // Assume that no export attributes are needed
+ #define DYNAMIC
+ #endif
+ #else
+ // Using (including) the library
+ #ifdef _WIN32
+ // Use the Windows-specific import attribute
+ #define DYNAMIC __declspec(dllimport)
+ #else
+ // Assume that no import attributes are needed
+ #define DYNAMIC
+ #endif
+ #endif
+ #endif
+#endif
diff --git a/src/algoThread.h b/src/algoThread.h
new file mode 100644
index 0000000..665a4fc
--- /dev/null
+++ b/src/algoThread.h
@@ -0,0 +1,29 @@
+#ifndef ALGOTHREAD_H
+#define ALGOTHREAD_H
+
+#include "cuteControl.h"
+#include <QThread>
+
+class AlgoThread : public QThread
+{
+private:
+ void (*func)();
+
+public:
+ void setAlgorithm(void (*algorithm)())
+ {
+ func = algorithm;
+ }
+ void run() override
+ {
+ func();
+ CuteControl::get().moveToMainThread();
+ }
+};
+
+
+
+
+
+
+#endif // ALGOTHREAD_H
\ No newline at end of file
diff --git a/src/chartMenu.cpp b/src/chartMenu.cpp
new file mode 100644
index 0000000..a15b1c9
--- /dev/null
+++ b/src/chartMenu.cpp
@@ -0,0 +1,54 @@
+#include "chartMenu.h"
+#include <QCheckBox>
+#include <qaction.h>
+#include <string>
+#include "graphNames.h"
+
+ChartMenu::ChartMenu(std::vector<QWidget *>& graphingWidgets, QWidget *parent)
+ : QMenu(parent)
+{
+ cv = graphingWidgets;
+
+ for (size_t i = 0; i < cv.size(); ++i)
+ {
+ QString name = getGraphName(i);
+ QAction *checkboxAction = new QAction(name, this);
+ vis.push_back(checkboxAction);
+ checkboxAction->setCheckable(true); // Make it checkable
+ checkboxAction->setChecked(!cv[i]->isHidden());
+ addAction(checkboxAction);
+ connect(checkboxAction, &QAction::triggered, this, &ChartMenu::onOptionSelected);
+ }
+ connect(this, &QMenu::aboutToShow, this, &ChartMenu::onShow);
+ themeAction = new QAction("Theme", this);
+ addAction(themeAction);
+}
+
+void ChartMenu::onShow()
+{
+ for (size_t i = 0; i < cv.size(); ++i)
+ {
+ vis[i]->setChecked(!cv[i]->isHidden());
+ }
+}
+
+void ChartMenu::onOptionSelected()
+{
+ QAction *senderAction = qobject_cast<QAction *>(sender());
+ if (senderAction) {
+ for (size_t i = 0; i < vis.size(); ++i)
+ {
+ if (senderAction == vis[i])
+ {
+ cv[i]->setHidden(!senderAction->isChecked());
+ }
+ }
+ }
+}
+
+void ChartMenu::chartThemeChanged(int themeNumber)
+{
+ QString s = "Theme: ";
+ s += std::to_string(themeNumber).c_str();
+ themeAction->setText(s);
+}
diff --git a/src/chartMenu.h b/src/chartMenu.h
new file mode 100644
index 0000000..11f1882
--- /dev/null
+++ b/src/chartMenu.h
@@ -0,0 +1,35 @@
+#ifndef CHARTMENU_H
+#define CHARTMENU_H
+
+#include <QMenu>
+#include <QWidget>
+#include <vector>
+
+
+class ChartMenu : public QMenu
+{
+ Q_OBJECT
+private:
+ std::vector<QWidget *> cv;
+ std::vector<QAction *> vis;
+ int chartTheme;
+
+ public:
+ ChartMenu(std::vector<QWidget *>& graphingWidgets, QWidget *parent = nullptr);
+ QAction *themeAction;
+
+private slots:
+ void onShow();
+
+public slots:
+ void onOptionSelected();
+ void chartThemeChanged(int themeNumber);
+};
+
+
+
+
+
+
+
+#endif // CHARTVIEW_H
\ No newline at end of file
diff --git a/src/configPanel.cpp b/src/configPanel.cpp
new file mode 100644
index 0000000..7b30ff8
--- /dev/null
+++ b/src/configPanel.cpp
@@ -0,0 +1,92 @@
+#include "configPanel.h"
+#include <QHBoxLayout>
+#include <QStackedWidget>
+#include <QLineEdit>
+#include <QHBoxLayout>
+
+ConfigPanel::ConfigPanel(QWidget *parent)
+ : QDockWidget{parent}
+{
+ setFeatures(QDockWidget::DockWidgetFeature::DockWidgetMovable);
+ setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
+ setTitleBarWidget(new QWidget());
+
+ QFrame *f = new QFrame();
+ setWidget(f);
+ QHBoxLayout *frameLayout = new QHBoxLayout();
+ f->setLayout(frameLayout);
+ stackedWidget = new QStackedWidget();
+ f->layout()->addWidget(stackedWidget);
+ f->setFrameStyle(QFrame::Panel | QFrame::Raised);
+
+ frameLayout->addStretch();
+
+ algoBox = new QComboBox();
+ f->layout()->addWidget(algoBox);
+ debugBox = new QComboBox();
+ f->layout()->addWidget(debugBox);
+ debugBox->addItem("All");
+ debugBox->addItem("Result");
+ debugBox->addItem("None");
+ runButton = new QPushButton("Start");
+ f->layout()->addWidget(runButton);
+
+
+ fileWidget = new QWidget();
+ stackedWidget->addWidget(fileWidget);
+ QHBoxLayout *fileLayout = new QHBoxLayout();
+ fileWidget->setLayout(fileLayout);
+ openButton = new QPushButton("Open...");
+ fileWidget->layout()->addWidget(openButton);
+ fileLine = new QLineEdit("YourFile");
+ fileWidget->layout()->addWidget(fileLine);
+ fileGenerateButton = new QPushButton("Generate");
+ fileLayout->addWidget(fileGenerateButton);
+ fileLayout->addStretch();
+
+ randomWidget = new QWidget();
+ stackedWidget->addWidget(randomWidget);
+
+ QHBoxLayout *randomLayout = new QHBoxLayout();
+ randomWidget->setLayout(randomLayout);
+ problemSizeBox = new QSpinBox();
+ randomLayout->addWidget(problemSizeBox);
+ randomGenerateButton = new QPushButton("Generate");
+ randomLayout->addWidget(randomGenerateButton);
+ randomLayout->addStretch();
+
+ problemSizeBox->setMinimum(1);
+ problemSizeBox->setMaximum(INT_MAX);
+
+ stackedWidget->setCurrentWidget(randomWidget);
+}
+
+void ConfigPanel::setRunning(bool running)
+{
+ if (running)
+ {
+ runButton->setText("Stop");
+ //TODO setIcon
+ }
+ else
+ {
+ runButton->setText("Start");
+ //TODO setIcon
+ }
+}
+
+void ConfigPanel::setGenLocked()
+{
+ randomGenerateButton->setEnabled(false);
+ randomGenerateButton->setText("Generated");
+ fileGenerateButton->setEnabled(false);
+ fileGenerateButton->setText("Generated");
+}
+
+void ConfigPanel::setGenUnlocked()
+{
+ randomGenerateButton->setEnabled(true);
+ randomGenerateButton->setText("Generate");
+ fileGenerateButton->setEnabled(true);
+ fileGenerateButton->setText("Generate");
+}
diff --git a/src/configPanel.h b/src/configPanel.h
new file mode 100644
index 0000000..43f2e8e
--- /dev/null
+++ b/src/configPanel.h
@@ -0,0 +1,37 @@
+#ifndef CONFIGPANEL_H
+#define CONFIGPANEL_H
+
+#include <QDockWidget>
+#include <QPushButton>
+#include <QSpinBox>
+#include <QCheckBox>
+#include <QComboBox>
+#include <QStackedWidget>
+
+class ConfigPanel : public QDockWidget
+{
+ Q_OBJECT
+
+public:
+ QPushButton *runButton;
+ QPushButton *openButton;
+ QPushButton *randomGenerateButton;
+ QPushButton *fileGenerateButton;
+ QLineEdit *fileLine;
+ QComboBox *algoBox;
+ QSpinBox *problemSizeBox;
+ QComboBox *debugBox;
+ QStackedWidget *stackedWidget;
+ QWidget *fileWidget;
+ QWidget *randomWidget;
+
+public:
+ explicit ConfigPanel(QWidget *parent = nullptr);
+
+public slots:
+ void setRunning(bool running);
+ void setGenLocked();
+ void setGenUnlocked();
+};
+
+#endif // CONFIGPANEL_H
diff --git a/src/control.cpp b/src/control.cpp
new file mode 100644
index 0000000..69f339c
--- /dev/null
+++ b/src/control.cpp
@@ -0,0 +1,193 @@
+#include "control.h"
+#include "cuteControl.h"
+#include "algoThread.h"
+#include "mainWindow.h"
+
+#include <QString>
+#include <QChartView>
+#include <QComboBox>
+#include <QLineEdit>
+#include <random>
+
+void Control::makeConnections()
+{
+ CuteControl *cc = &CuteControl::get();
+ connect(cc, &CuteControl::s_setProgress, this, &Control::setProgress);
+ connect(cc, &CuteControl::s_logMessage, this, &Control::logMessage);
+ connect(cc, &CuteControl::s_statusMessage, this, &Control::statusMessage);
+ connect(cc, &CuteControl::s_setPlotVisible, this, &Control::setPlotVisible);
+ connect(cc, &CuteControl::s_setPlotTitle, this, &Control::setPlotTitle);
+ connect(cc, &CuteControl::s_setPlotTheme, this, &Control::setPlotTheme);
+ connect(cc, &CuteControl::s_enableAutorun, this, &Control::enableAutorun);
+ connect(cc, &CuteControl::s_setProblemSize, this, &Control::setProblemSize);
+ connect(cc, &CuteControl::s_setProblemFile, this, &Control::setProblemFile);
+ connect(this, &Control::endThread, cc, &CuteControl::end);
+ connect(w->configPanel->runButton, &QPushButton::clicked, this, &Control::onRunButton);
+ connect(w->configPanel->fileGenerateButton, &QPushButton::clicked, this, &Control::onGenerateButton);
+ connect(w->configPanel->randomGenerateButton, &QPushButton::clicked, this, &Control::onGenerateButton);
+ connect(w->configPanel->fileLine, &QLineEdit::textChanged, this, &Control::onProblemSettingChanged);
+ connect(w->configPanel->problemSizeBox, &QSpinBox::textChanged, this, &Control::onProblemSettingChanged);
+}
+
+int Control::run(void (*userSetup)())
+{
+ static bool running = false;
+ if (!running)
+ {
+ running = true;
+ int argc = 1;
+ char* argv[] = { (char*)"AppName" };
+ QApplication a(argc, argv);
+ auto Mw = MainWindow();
+ w = &Mw;
+
+ makeConnections();
+
+ userSetup();
+ w->show();
+ if (autorun)
+ startThread(algorithms.front().first);
+ int result = a.exec();
+ running = false;
+ return result;
+ }
+ else
+ return -1;
+}
+
+void Control::logMessage(const QString message)
+{
+ w->textEdit->append(message);
+}
+
+void Control::setProgress(int percentage)
+{
+ w->progressBar->setValue(percentage);
+}
+
+void Control::statusMessage(const QString message)
+{
+ w->statusBar->showMessage(message, 5000);
+}
+
+void Control::setPlotVisible(int plot, bool visible)
+{
+ w->graphingWidgets[plot]->setHidden(!visible);
+}
+
+void Control::setPlotTitle(int plot, const QString title)
+{
+ w->charts[plot]->setTitle(title);
+}
+
+void Control::setPlotTheme(int themeNumber)
+{
+ w->changeChartTheme(themeNumber);
+}
+
+
+void Control::registerAlgorithm(void (*func)(), const QString name)
+{
+ algorithms.emplace_back(func, name);
+ w->addAlgorithm(name);
+}
+
+void Control::stopThread()
+{
+ if (thread)
+ {
+ emit endThread();
+ }
+}
+
+void Control::threadEnded()
+{
+ threadRunning = false;
+ w->configPanel->setRunning(false);
+ thread = nullptr;
+}
+
+void Control::startThread(void (*func)())
+{
+ if (!thread)
+ {
+ thread = new AlgoThread();
+ thread->setAlgorithm(func);
+
+ connect(thread, &AlgoThread::finished, thread, &QObject::deleteLater);
+ connect(thread, &AlgoThread::finished, this, &Control::threadEnded);
+ CuteControl::get().setProblem(getProblem());
+ CuteControl::get().moveToWorkerThread(thread);
+ w->configPanel->setRunning(true);
+ threadRunning = true;
+ thread->start();
+ logMessage("Running...");
+ }
+}
+
+void Control::onRunButton()
+{
+ if (!thread)
+ {
+ int index = w->configPanel->algoBox->currentIndex();
+ auto func = algorithms[index].first;
+ startThread(func);
+ }
+ else
+ {
+ stopThread();
+ }
+}
+
+void Control::setProblemSize(int n)
+{
+ w->configPanel->stackedWidget->setCurrentWidget(w->configPanel->randomWidget);
+ w->configPanel->problemSizeBox->setValue(n);
+}
+
+void Control::setProblemFile(QString path)
+{
+ w->configPanel->stackedWidget->setCurrentWidget(w->configPanel->fileWidget);
+ w->configPanel->fileLine->setText(path);
+}
+
+std::vector<cute::Point> Control::getProblem()
+{
+ if (!problemRetained)
+ {
+ generateProblem();
+ }
+ return problem;
+}
+
+void Control::generateProblem()
+{
+ problem.clear();
+ if (w->configPanel->stackedWidget->currentWidget() == w->configPanel->randomWidget)
+ {
+ int problemSize = w->configPanel->problemSizeBox->value();
+ problem.reserve(problemSize);
+ for (int i = 0; i < problemSize; ++i)
+ {
+ std::random_device rd = std::random_device();
+ problem.emplace_back(cute::Point{(float)(rd() % 100), (float)(rd() % 100)});
+ }
+ }
+ else if (w->configPanel->stackedWidget->currentWidget() == w->configPanel->fileWidget)
+ {
+ //TODO file.csv
+ }
+}
+
+void Control::onGenerateButton()
+{
+ generateProblem();
+ problemRetained = true;
+ w->configPanel->setGenLocked();
+}
+
+void Control::onProblemSettingChanged([[maybe_unused]] const QString &text)
+{
+ problemRetained = false;
+ w->configPanel->setGenUnlocked();
+}
diff --git a/src/control.h b/src/control.h
new file mode 100644
index 0000000..382486f
--- /dev/null
+++ b/src/control.h
@@ -0,0 +1,66 @@
+#ifndef CONTROL_H
+#define CONTROL_H
+
+#include "mainWindow.h"
+#include "algoThread.h"
+#include <QApplication>
+#include <QObject>
+
+
+
+
+class Control : public QObject
+{
+ Q_OBJECT
+private:
+ Control() {}
+ virtual ~Control() { stopThread(); }
+ MainWindow *w;
+ std::vector<std::pair<void(*)(), QString>> algorithms;
+ bool threadRunning;
+ bool autorun;
+ AlgoThread *thread;
+ void startThread(void (*func)());
+ void makeConnections();
+ bool problemRetained;
+ std::vector<cute::Point> problem;
+ void generateProblem();
+ std::vector<cute::Point> getProblem();
+
+public:
+ static Control &getInstance()
+ {
+ static Control instance;
+ return instance;
+ }
+ static Control &get() { return getInstance(); }
+ int run(void (*setup)());
+ void registerAlgorithm(void (*func)(), const QString name);
+public slots:
+ void enableAutorun(bool run) { autorun = run; }
+ void stopThread();
+ void threadEnded();
+ void setProgress(int percentage);
+ void statusMessage(const QString message);
+ void logMessage(const QString message);
+ void setPlotVisible(int plot, bool visible);
+ void setPlotTitle(int plot, const QString title);
+ void setPlotTheme(int themeNumber);
+ void onRunButton();
+ void onGenerateButton();
+ void setProblemSize(int n);
+ void setProblemFile(QString path);
+ void onProblemSettingChanged(const QString &text);
+
+signals:
+ void endThread();
+};
+
+
+
+
+
+
+
+
+#endif //CONTROL_H
diff --git a/src/cute.cpp b/src/cute.cpp
new file mode 100644
index 0000000..2ee83f7
--- /dev/null
+++ b/src/cute.cpp
@@ -0,0 +1,127 @@
+#include "cute.h"
+#include "cuteControl.h"
+#include "control.h"
+
+void cute::setPlotVisible(Plot plot, bool visible)
+{
+ CuteControl::get().setPlotVisible((int)plot, visible);
+}
+
+void cute::setPlotTitle(Plot plot, const std::string &title)
+{
+ CuteControl::get().setPlotTitle((int)plot, title);
+}
+
+/*
+void cute::setPlotScale(Plot plot, Scale x, Scale y);
+*/
+void cute::setPlotTheme(int themeNumber)
+{
+ CuteControl::get().setPlotTheme(themeNumber);
+}
+
+
+void cute::registerAlgorithm(void (*func)(), const std::string &name)
+{
+ Control::get().registerAlgorithm(func, name.c_str());
+}
+
+
+/*
+void cute::plotPoints(std::vector<Point>& points);
+
+void cute::plotValues(std::vector<float> &values);
+
+void cute::plotLines(std::vector<Point> &points);
+
+void cute::plotLine(Point &a, Point &b);
+
+void cute::resetPlot();
+
+
+void cute::addResult(float result);
+
+void cute::resetResultPlot();
+
+
+void cute::addRuntime(std::chrono::duration<float, std::milli> duration, int problem_size);
+
+void cute::addRuntime(float milliseconds, int problem_size);
+
+void cute::resetRuntimePlot();
+*/
+
+
+void cute::logMessage(const std::string &message)
+{
+ CuteControl::get().logMessage(message);
+}
+
+void cute::statusMessage(const std::string &message)
+{
+ CuteControl::get().statusMessage(message);
+}
+
+void cute::setProgress(int percentage)
+{
+ CuteControl::get().setProgress(percentage);
+}
+
+
+const std::vector<float> &cute::getProblemData1D()
+{
+ return CuteControl::get().getData1D();
+}
+
+const std::vector<cute::Point> &cute::getProblemData2D()
+{
+ return CuteControl::get().getData2D();
+}
+
+
+void cute::setProblemFile(const std::string &path)
+{
+ CuteControl::get().setProblemFile(path);
+}
+
+void cute::setProblemSize(int n)
+{
+ CuteControl::get().setProblemSize(n);
+}
+
+void cute::enableAutorun(bool run)
+{
+ CuteControl::get().enableAutorun(run);
+}
+
+
+void cute::delay(int milliseconds)
+{
+ QThread::msleep(milliseconds);
+}
+
+
+int cute::run(void (*setup)())
+{
+ return Control::get().run(setup);
+}
+
+bool cute::ok()
+{
+ return !CuteControl::get().endRequested();
+}
+
+/*
+class Timer
+{
+ public:
+ void start();
+ void pause();
+ void resume();
+ void stop();
+ float result();
+ private:
+ std::chrono::duration<float, std::milli> duration;
+};
+*/
+
diff --git a/src/cute.def b/src/cute.def
new file mode 100644
index 0000000..a1129b1
--- /dev/null
+++ b/src/cute.def
@@ -0,0 +1,17 @@
+LIBRARY cute
+EXPORTS
+ logMessage=_ZN4cute10logMessageERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE
+ setProgress=_ZN4cute11setProgressEi
+ _ZN4cute12setPlotTitleENS_4PlotERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE
+ setPlotTheme=_ZN4cute12setPlotThemeEi
+ enableAutorun=_ZN4cute13enableAutorunEb
+ _ZN4cute13statusMessageERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE
+ _ZN4cute14setPlotVisibleENS_4PlotEb
+ setProblemFile=_ZN4cute14setProblemFileERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE
+ setProblemSize=_ZN4cute14setProblemSizeEi
+ getProblemData1D=_ZN4cute16getProblemData1DEv
+ getProblemData2D=_ZN4cute16getProblemData2DEv
+ registerAlgorithm=_ZN4cute17registerAlgorithmEPFvvERKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE
+ ok=_ZN4cute2okEv
+ run=_ZN4cute3runEPFvvE
+ delay=_ZN4cute5delayEi
diff --git a/src/cuteControl.cpp b/src/cuteControl.cpp
new file mode 100644
index 0000000..1d30049
--- /dev/null
+++ b/src/cuteControl.cpp
@@ -0,0 +1,3 @@
+#include "cuteControl.h"
+
+
diff --git a/src/cuteControl.h b/src/cuteControl.h
new file mode 100644
index 0000000..5df716f
--- /dev/null
+++ b/src/cuteControl.h
@@ -0,0 +1,148 @@
+#ifndef CUTECONTROL_H
+#define CUTECONTROL_H
+
+#include "cute.h"
+#include <QObject>
+#include <QString>
+#include <QApplication>
+
+
+class CuteControl : public QObject
+{
+ Q_OBJECT
+private:
+ CuteControl() {}
+ bool endThread;
+ bool runningInThread;
+ std::vector<cute::Point> problem2D;
+ std::vector<float> problem1D;
+
+signals:
+ void s_setProgress(int n);
+ void s_logMessage(QString message);
+ void s_statusMessage(QString message);
+ void s_setPlotTitle(int plot, QString title);
+ void s_setPlotVisible(int plot, bool visible);
+ void s_enableAutorun(bool run);
+ void s_setProblemSize(int n);
+ void s_setProblemFile(QString path);
+ void s_setPlotTheme(int themeNumber);
+
+public:
+ static CuteControl &getInstance()
+ {
+ static CuteControl instance;
+ return instance;
+ }
+ static CuteControl &get() { return getInstance(); }
+
+ void moveToMainThread()
+ {
+ moveToThread(QApplication::instance()->thread());
+ runningInThread = false;
+ endThread = false;
+ }
+ void moveToWorkerThread(QThread *thread)
+ {
+ moveToThread(thread);
+ runningInThread = true;
+ }
+public:
+ void setProgress(int percentage)
+ {
+ emit s_setProgress(percentage);
+ }
+ bool endRequested()
+ {
+ QApplication::processEvents();
+ return endThread;
+ }
+ void logMessage(const std::string &message)
+ {
+ emit s_logMessage(message.c_str());
+ }
+ void statusMessage(const std::string &message)
+ {
+ emit s_statusMessage(message.c_str());
+ }
+ void setPlotTheme(int themeNumber)
+ {
+ emit s_setPlotTheme(themeNumber);
+ }
+
+ void setPlotTitle(int plot, const std::string &title)
+ {
+ emit s_setPlotTitle(plot, title.c_str());
+ }
+
+ void setPlotVisible(int plot, bool visible)
+ {
+ emit s_setPlotVisible(plot, visible);
+
+ }
+ void enableAutorun(bool run)
+ {
+ emit s_enableAutorun(run);
+ }
+ void setProblemSize(int n)
+ {
+ emit s_setProblemSize(n);
+ }
+ void setProblemFile(const std::string &path)
+ {
+ emit s_setProblemFile(path.c_str());
+ }
+ const std::vector<float> &getData1D()
+ {
+ return problem1D;
+ }
+ const std::vector<cute::Point> &getData2D()
+ {
+ return problem2D;
+ }
+ void setProblem(const std::vector<cute::Point> &problemVector)
+ {
+ if(!runningInThread)
+ {
+ problem2D = problemVector;
+ problem1D.clear();
+ problem1D.reserve(problemVector.size());
+ for (auto &&point : problemVector)
+ {
+ problem1D.push_back(point.x);
+ }
+ }
+ }
+
+public slots:
+ void end()
+ {
+ endThread = true;
+ }
+
+public:
+
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#endif // CUTECONTROL_H
\ No newline at end of file
diff --git a/src/cuteImporter.cpp b/src/cuteImporter.cpp
new file mode 100644
index 0000000..bf0b6c8
--- /dev/null
+++ b/src/cuteImporter.cpp
@@ -0,0 +1,149 @@
+#include "cute.h"
+#include <windows.h>
+
+namespace {
+ // Private variables to hold the DLL handle and function pointers
+ // Anonymous namespace will not be visible outside of this translation unit
+ HINSTANCE hDll = nullptr;
+
+ typedef void (*t_setProgress)(int);
+ typedef void (*t_logMessage)(const std::string&);
+ typedef void (*t_enableAutorun)(bool);
+ typedef void (*t_setProblemFile)(const std::string&);
+ typedef void (*t_setProblemSize)(int);
+ typedef void (*t_registerAlgorithm)(void (*)(), const std::string&);
+ typedef void (*t_delay)(int);
+ typedef int (*t_run)(void (*)());
+ typedef bool (*t_ok)();
+ typedef const std::vector<float> &(*t_getProblemData1D)();
+ typedef const std::vector<cute::Point> &(*t_getProblemData2D)();
+
+ t_setProgress setProgressImpl = nullptr;
+ t_logMessage logMessageImpl = nullptr;
+ t_enableAutorun enableAutorunImpl = nullptr;
+ t_setProblemFile setProblemFileImpl = nullptr;
+ t_setProblemSize setProblemSizeImpl = nullptr;
+ t_registerAlgorithm registerAlgorithmImpl = nullptr;
+ t_delay delayImpl = nullptr;
+ t_run runImpl = nullptr;
+ t_ok okImpl = nullptr;
+ t_getProblemData1D getProblemData1DImpl = nullptr;
+ t_getProblemData2D getProblemData2DImpl = nullptr;
+}
+
+// Function implementations hidden from the user
+namespace cute {
+ int core::initialize() {
+ hDll = LoadLibrary("cute.dll");
+ if (!hDll) {
+ return -2;
+ }
+ #pragma clang diagnostic push
+ #pragma clang diagnostic ignored "-Wcast-function-type"
+ //#pragma GCC diagnostic ignored "-Wcast-function-type"
+ // your code for which the warning gets suppressed
+ setProgressImpl = reinterpret_cast<t_setProgress>(GetProcAddress(hDll, "setProgress"));
+ logMessageImpl = reinterpret_cast<t_logMessage>(GetProcAddress(hDll, "logMessage"));
+ enableAutorunImpl = reinterpret_cast<t_enableAutorun>(GetProcAddress(hDll, "enableAutorun"));
+ setProblemFileImpl = reinterpret_cast<t_setProblemFile>(GetProcAddress(hDll, "setProblemFile"));
+ setProblemSizeImpl = reinterpret_cast<t_setProblemSize>(GetProcAddress(hDll, "setProblemSize"));
+ registerAlgorithmImpl = reinterpret_cast<t_registerAlgorithm>(GetProcAddress(hDll, "registerAlgorithm"));
+ delayImpl = reinterpret_cast<t_delay>(GetProcAddress(hDll, "delay"));
+ runImpl = reinterpret_cast<t_run>(GetProcAddress(hDll, "run"));
+ okImpl = reinterpret_cast<t_ok>(GetProcAddress(hDll, "ok"));
+ getProblemData1DImpl = reinterpret_cast<t_getProblemData1D>(GetProcAddress(hDll, "getProblemData1D"));
+ getProblemData2DImpl = reinterpret_cast<t_getProblemData2D>(GetProcAddress(hDll, "getProblemData2D"));
+ #pragma clang diagnostic pop
+ //#pragma GCC diagnostic pop
+
+ // By checking here, we can spare any future checks and if we exit main() on any errors, we can spare us any exception handling.
+ if (
+ setProgressImpl &&
+ logMessageImpl &&
+ enableAutorunImpl &&
+ setProblemFileImpl &&
+ setProblemSizeImpl &&
+ registerAlgorithmImpl &&
+ delayImpl &&
+ runImpl &&
+ okImpl &&
+ getProblemData1DImpl &&
+ getProblemData2DImpl
+ )
+ {
+ return 0;
+ }
+ else
+ {
+ FreeLibrary(hDll);
+ hDll = nullptr;
+ return -3;
+ }
+ }
+
+ void setProgress(int percentage)
+ {
+ return setProgressImpl(percentage);
+ }
+ void logMessage(const std::string &message)
+ {
+ return logMessageImpl(message);
+ }
+ void enableAutorun(bool run)
+ {
+ return enableAutorunImpl(run);
+ }
+ void setProblemFile(const std::string &path)
+ {
+ return setProblemFileImpl(path);
+ }
+ void setProblemSize(int n)
+ {
+ return setProblemSizeImpl(n);
+ }
+ void registerAlgorithm(void (*func)(), const std::string &name)
+ {
+ return registerAlgorithmImpl(func, name);
+ }
+ void delay(int milliseconds)
+ {
+ return delayImpl(milliseconds);
+ }
+ int run(void (*setup)())
+ {
+ return runImpl(setup);
+ }
+ bool ok()
+ {
+ return okImpl();
+ }
+ const std::vector<float> &getProblemData1D()
+ {
+ return getProblemData1DImpl();
+ }
+ const std::vector<cute::Point> &getProblemData2D()
+ {
+ return getProblemData2DImpl();
+ }
+
+ void core::shutdown()
+ {
+ if (hDll)
+ {
+ FreeLibrary(hDll);
+ hDll = nullptr;
+ setProgressImpl = nullptr;
+ logMessageImpl = nullptr;
+ enableAutorunImpl = nullptr;
+ setProblemFileImpl = nullptr;
+ setProblemSizeImpl = nullptr;
+ registerAlgorithmImpl = nullptr;
+ delayImpl = nullptr;
+ runImpl = nullptr;
+ okImpl = nullptr;
+ getProblemData1DImpl = nullptr;
+ getProblemData2DImpl = nullptr;
+ }
+ }
+}
+
diff --git a/src/graphNames.cpp b/src/graphNames.cpp
new file mode 100644
index 0000000..aa21e04
--- /dev/null
+++ b/src/graphNames.cpp
@@ -0,0 +1,13 @@
+#include "graphNames.h"
+
+#include <array>
+
+QString getGraphName(int index)
+{
+ constexpr std::array<const char *, 3> names =
+ {
+ "MainPlot",
+ "Result",
+ "Runtime"};
+ return names[index];
+}
diff --git a/src/graphNames.h b/src/graphNames.h
new file mode 100644
index 0000000..a0ab438
--- /dev/null
+++ b/src/graphNames.h
@@ -0,0 +1,9 @@
+#ifndef GRAPHNAMES_H
+#define GRAPHNAMES_H
+
+#include <QString>
+
+QString getGraphName(int index);
+
+
+#endif // GRAPHNAMES_H
\ No newline at end of file
diff --git a/src/main.cpp b/src/main.cpp
new file mode 100644
index 0000000..afd8e81
--- /dev/null
+++ b/src/main.cpp
@@ -0,0 +1,12 @@
+#include "cute.h"
+
+extern void setup();
+
+int main()
+{
+ if (cute::core::initialize() != 0)
+ return 1;
+ int r = cute::run(setup);
+ cute::core::shutdown();
+ return r;
+}
diff --git a/src/mainWindow.cpp b/src/mainWindow.cpp
new file mode 100644
index 0000000..71c975b
--- /dev/null
+++ b/src/mainWindow.cpp
@@ -0,0 +1,243 @@
+#include "mainWindow.h"
+#include "configPanel.h"
+#include "chartMenu.h"
+#include "graphNames.h"
+#include <QMenuBar>
+#include <QMenu>
+#include <QBoxLayout>
+#include <QSplitter>
+#include <QFontDatabase>
+#include <QTableView>
+#include <QTableWidget>
+#include <QLabel>
+#include <QToolbar>
+#include <QSpinBox>
+#include <QLineEdit>
+#include <QDockWidget>
+#include <QStackedWidget>
+#include <QSizePolicy>
+#include <QChartView.h>
+#include <QProxyStyle>
+#include <QChart>
+
+MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
+{
+ configPanel = new ConfigPanel();
+ addDockWidget(Qt::DockWidgetArea::TopDockWidgetArea, configPanel);
+ setDockOptions(DockOption::AnimatedDocks);
+ setDockNestingEnabled(false);
+
+
+
+
+
+ /*QTableWidget *T = new QTableWidget(400, 400);
+ grL->addWidget(T);
+ T->setLineWidth(0);
+ T->resizeColumnsToContents();
+ T->resizeRowsToContents();
+ for (size_t i = 0; i < 400; i++)
+ {
+ T->setRowHeight(i, 1);
+ T->setColumnWidth(i, 1);
+ }*/
+
+ setupMenuBar();
+ setupStatusBar();
+ setupCharts();
+
+ /*QToolBar *rtb = new QToolBar("random");
+ // tb->setFloatable();
+ QToolBar *ftb = new QToolBar("file");
+ addToolBar(Qt::ToolBarArea::TopToolBarArea, rtb);
+ addToolBar(Qt::ToolBarArea::TopToolBarArea, ftb);
+
+ rtb->addWidget(new QDoubleSpinBox());
+ rtb->addWidget(new QPushButton("Generate"));
+ ftb->addWidget(new QLineEdit("YourFile"));
+ ftb->addWidget(new QPushButton("Generate"));
+ ftb->setLayoutDirection(Qt::LayoutDirection::LeftToRight);
+ QWidget *sprW1 = new QWidget();
+ sprW1->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+ ftb->addWidget(sprW1);
+ ftb->addWidget(new QPushButton("Go"));
+ QWidget *sprW2 = new QWidget();
+ sprW2->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+ rtb->addWidget(sprW2);
+ rtb->addWidget(new QPushButton("Go"));
+
+ QToolBar *ssb = new QToolBar("ssb");
+ ssb->setLayoutDirection(Qt::LayoutDirection::LeftToRight);
+ ssb->addWidget(new QPushButton("[ ] Start"));
+ addToolBar(Qt::ToolBarArea::TopToolBarArea, ssb);
+ ssb->addSeparator();
+ rtb->setFloatable(false);
+ //rtb->setMovable(false);
+ //ftb->setFloatable(false);
+ //ftb->setMovable(false);
+ ssb->setFloatable(false);
+ //ssb->setMovable(false);
+ //rtb->hide();
+ rtb->addSeparator();*/
+
+ QDockWidget *tdw = new QDockWidget("Output");
+ textEdit = new QTextEdit();
+ tdw->setWidget(textEdit);
+ addDockWidget(Qt::DockWidgetArea::BottomDockWidgetArea, tdw);
+ tdw->setAllowedAreas(Qt::DockWidgetArea::BottomDockWidgetArea | Qt::DockWidgetArea::RightDockWidgetArea | Qt::DockWidgetArea::LeftDockWidgetArea);
+
+ textEdit->setReadOnly(true);
+ QFont fixedFont = QFontDatabase::systemFont(QFontDatabase::FixedFont);
+ textEdit->setCurrentFont(fixedFont);
+ textEdit->setFontPointSize(12);
+}
+
+void MainWindow::setupMenuBar()
+{
+ QMenuBar* menubar = new QMenuBar();
+ setMenuBar(menubar);
+ QMenu* probM = new QMenu("Problem");
+ menubar->addMenu(probM);
+
+ probMenuRandom = new QAction("Random", this);
+ probMenuRandom->setCheckable(true);
+ probMenuRandom->setChecked(true);
+ probMenuRandom->setDisabled(true);
+ probM->addAction(probMenuRandom);
+ connect(probMenuRandom, &QAction::triggered, this, &MainWindow::switchToRandom);
+
+ probMenuFile = new QAction("File", this);
+ probMenuFile->setCheckable(true);
+ probMenuFile->setChecked(false);
+ probM->addAction(probMenuFile);
+ connect(probMenuFile, &QAction::triggered, this, &MainWindow::switchToFile);
+
+ QAction *probSave = new QAction("Save...", this);
+ probM->addAction(probSave);
+ connect(probSave, &QAction::triggered, this, &MainWindow::saveProblem);
+
+ cm = new ChartMenu(graphingWidgets);
+ cm->setTitle("Charts");
+ menubar->addMenu(cm);
+ connect(cm->themeAction, &QAction::triggered, this, &MainWindow::incrementChartTheme);
+}
+
+void MainWindow::switchToFile()
+{
+ probMenuFile->setChecked(true);
+ probMenuRandom->setChecked(false);
+ probMenuFile->setDisabled(true);
+ probMenuRandom->setDisabled(false);
+ configPanel->stackedWidget->setCurrentWidget(configPanel->fileWidget);
+}
+
+void MainWindow::switchToRandom()
+{
+ probMenuFile->setChecked(false);
+ probMenuRandom->setChecked(true);
+ probMenuFile->setDisabled(false);
+ probMenuRandom->setDisabled(true);
+ configPanel->stackedWidget->setCurrentWidget(configPanel->randomWidget);
+}
+
+
+
+void MainWindow::setupCharts()
+{
+ QWidget* grW = new QWidget();
+ setCentralWidget(grW);
+ QHBoxLayout *layout = new QHBoxLayout();
+ grW->setLayout(layout);
+
+ for (size_t i = 0; i < 3; i++)
+ {
+ QtCharts::QChartView *v = new QtCharts::QChartView();
+ graphingWidgets.push_back(v);
+ layout->addWidget(v, 1);
+
+ QtCharts::QChart *c = new QtCharts::QChart();
+ charts.push_back(c);
+ v->setChart(c);
+ c->setTitle(getGraphName(i));
+ c->legend()->setVisible(true);
+ c->setMinimumSize(300, 300);
+ }
+ changeChartTheme((int)QtCharts::QChart::ChartTheme::ChartThemeBlueCerulean);
+}
+
+void MainWindow::addAlgorithm(const QString &name)
+{
+ configPanel->algoBox->addItem(name);
+}
+
+
+void MainWindow::setupStatusBar()
+{
+ statusBar = new QStatusBar();
+ setStatusBar(statusBar);
+ progressBar = new QProgressBar();
+ statusBar->addPermanentWidget(progressBar);
+ statusBar->showMessage("Ready...");
+ progressBar->setMinimum(0);
+ progressBar->setMaximum(100);
+ progressBar->setValue(0);
+}
+
+void MainWindow::changeChartTheme(int themeNumber) {
+ if (themeNumber > 7 || themeNumber < 0) {
+ return;
+ }
+ cm->chartThemeChanged(themeNumber);
+ for (QtCharts::QChart* chart : charts) {
+ chart->setTheme((QtCharts::QChart::ChartTheme)themeNumber);
+ }
+}
+
+void MainWindow::incrementChartTheme() {
+ int n = (int)charts.front()->theme();
+ ++n;
+ if (n > 7) {
+ n = 0;
+ }
+ changeChartTheme(n);
+}
+
+
+
+
+
+/*
+#include <QApplication>
+#include <QGraphicsView>
+#include <QGraphicsScene>
+#include <QGraphicsRectItem>
+#include <QPen>
+
+class GridView : public QGraphicsView {
+public:
+ GridView(QWidget *parent = nullptr) : QGraphicsView(parent) {
+ scene = new QGraphicsScene(this);
+ setScene(scene);
+ initGrid();
+ }
+
+private:
+ QGraphicsScene *scene;
+
+ void initGrid() {
+ int gridSize = 400;
+ int cellSize = 1; // Adjust for visibility
+ QPen pen(Qt::darkGreen); // Grid line color
+
+ for (int row = 0; row < gridSize; ++row) {
+ for (int col = 0; col < gridSize; ++col) {
+ QGraphicsRectItem *rect = new QGraphicsRectItem(col * cellSize, row * cellSize, cellSize, cellSize);
+ rect->setPen(pen);
+ scene->addItem(rect);
+ }
+ }
+
+ //setFixedSize(gridSize * cellSize, gridSize * cellSize);
+ }
+};
+}*/
diff --git a/src/mainWindow.h b/src/mainWindow.h
new file mode 100644
index 0000000..86ebb25
--- /dev/null
+++ b/src/mainWindow.h
@@ -0,0 +1,51 @@
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
+
+#include <QMainWindow>
+#include <QTextEdit>
+#include <QStatusBar>
+#include <QProgressBar>
+#include <QChartView>
+#include <QChart>
+#include "chartMenu.h"
+#include "configPanel.h"
+
+class MainWindow : public QMainWindow
+{
+ Q_OBJECT
+
+private:
+ QAction *probMenuFile;
+ QAction *probMenuRandom;
+ ChartMenu *cm;
+ void incrementChartTheme();
+
+public:
+ MainWindow(QWidget *parent = nullptr);
+
+ QStatusBar* statusBar;
+ QProgressBar *progressBar;
+ QTextEdit *textEdit;
+ ConfigPanel *configPanel;
+
+ std::vector<QWidget *> graphingWidgets;
+ std::vector<QtCharts::QChart *> charts;
+
+ void addAlgorithm(const QString &name);
+
+private:
+ void setupStatusBar();
+ void setupMenuBar();
+ void setupCharts();
+
+public slots:
+ void switchToFile();
+ void switchToRandom();
+ void changeChartTheme(int themeNumber);
+
+signals:
+ void saveProblem();
+
+};
+
+#endif // MAINWINDOW_H
--
GitLab