2026 Renovation (#3)
Rebuilt using raylib immediate mode gui. Simple window mode with text input and progress graph, and overlay mode. Reviewed-on: #3 Co-authored-by: talksik <[email protected]>
This commit was merged in pull request #3.
This commit is contained in:
+5
-1
@@ -1,2 +1,6 @@
|
|||||||
build/
|
build/
|
||||||
build-universal/
|
*~
|
||||||
|
*.o
|
||||||
|
*#*
|
||||||
|
adhd
|
||||||
|
*.sqlite3
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
cmake_minimum_required(VERSION 3.16)
|
|
||||||
|
|
||||||
project(adhd VERSION 1.0.0 LANGUAGES CXX)
|
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
||||||
|
|
||||||
# Set minimum macOS version
|
|
||||||
# Qt 6.8.6 requires macOS 11.0 (Big Sur) minimum
|
|
||||||
if(APPLE)
|
|
||||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "11.0" CACHE STRING "Minimum macOS version")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
find_package(Qt6 REQUIRED COMPONENTS
|
|
||||||
Core
|
|
||||||
Gui
|
|
||||||
Widgets
|
|
||||||
)
|
|
||||||
|
|
||||||
qt_standard_project_setup()
|
|
||||||
|
|
||||||
qt_add_executable(adhd
|
|
||||||
main.cpp
|
|
||||||
mainwindow.cpp
|
|
||||||
mainwindow.h
|
|
||||||
service.cpp
|
|
||||||
service.h
|
|
||||||
mainwindow.ui
|
|
||||||
sessionslistmodel.h
|
|
||||||
sessionslistmodel.cpp
|
|
||||||
sessionitemdelegate.h
|
|
||||||
sessionitemdelegate.cpp
|
|
||||||
createsessiondialog.h
|
|
||||||
createsessiondialog.cpp
|
|
||||||
createsessiondialog.ui
|
|
||||||
focusoverlay.h
|
|
||||||
focusoverlay.cpp
|
|
||||||
focusoverlay.ui
|
|
||||||
endsessiondialog.h
|
|
||||||
endsessiondialog.cpp
|
|
||||||
endsessiondialog.ui
|
|
||||||
namegenerator.h
|
|
||||||
namegenerator.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
# Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1.
|
|
||||||
# If you are developing for iOS or macOS you should consider setting an
|
|
||||||
# explicit, fixed bundle identifier manually though.
|
|
||||||
set_target_properties(adhd PROPERTIES
|
|
||||||
# MACOSX_BUNDLE_GUI_IDENTIFIER com.example.adhd
|
|
||||||
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
|
|
||||||
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
|
|
||||||
MACOSX_BUNDLE TRUE
|
|
||||||
WIN32_EXECUTABLE $<NOT:$<CONFIG:Debug>>
|
|
||||||
)
|
|
||||||
|
|
||||||
target_link_libraries(adhd
|
|
||||||
PRIVATE
|
|
||||||
Qt6::Core
|
|
||||||
Qt6::Gui
|
|
||||||
Qt6::Widgets
|
|
||||||
)
|
|
||||||
|
|
||||||
include(GNUInstallDirs)
|
|
||||||
install(TARGETS adhd
|
|
||||||
BUNDLE DESTINATION .
|
|
||||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
|
||||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
|
||||||
)
|
|
||||||
|
|
||||||
qt_generate_deploy_app_script(
|
|
||||||
TARGET adhd
|
|
||||||
OUTPUT_SCRIPT deploy_script
|
|
||||||
NO_UNSUPPORTED_PLATFORM_ERROR
|
|
||||||
)
|
|
||||||
install(SCRIPT ${deploy_script})
|
|
||||||
@@ -1,462 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE QtCreatorProject>
|
|
||||||
<!-- Written by QtCreator 16.0.2, 2026-02-01T13:41:28. -->
|
|
||||||
<qtcreator>
|
|
||||||
<data>
|
|
||||||
<variable>EnvironmentId</variable>
|
|
||||||
<value type="QByteArray">{1354daad-1138-41d2-985c-27357b7ee48a}</value>
|
|
||||||
</data>
|
|
||||||
<data>
|
|
||||||
<variable>ProjectExplorer.Project.ActiveTarget</variable>
|
|
||||||
<value type="qlonglong">0</value>
|
|
||||||
</data>
|
|
||||||
<data>
|
|
||||||
<variable>ProjectExplorer.Project.EditorSettings</variable>
|
|
||||||
<valuemap type="QVariantMap">
|
|
||||||
<value type="bool" key="EditorConfiguration.AutoDetect">true</value>
|
|
||||||
<value type="bool" key="EditorConfiguration.AutoIndent">true</value>
|
|
||||||
<value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value>
|
|
||||||
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0">
|
|
||||||
<value type="QString" key="language">Cpp</value>
|
|
||||||
<valuemap type="QVariantMap" key="value">
|
|
||||||
<value type="QByteArray" key="CurrentPreferences">CppGlobal</value>
|
|
||||||
</valuemap>
|
|
||||||
</valuemap>
|
|
||||||
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1">
|
|
||||||
<value type="QString" key="language">QmlJS</value>
|
|
||||||
<valuemap type="QVariantMap" key="value">
|
|
||||||
<value type="QByteArray" key="CurrentPreferences">QmlJSGlobal</value>
|
|
||||||
</valuemap>
|
|
||||||
</valuemap>
|
|
||||||
<value type="qlonglong" key="EditorConfiguration.CodeStyle.Count">2</value>
|
|
||||||
<value type="QByteArray" key="EditorConfiguration.Codec">UTF-8</value>
|
|
||||||
<value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value>
|
|
||||||
<value type="int" key="EditorConfiguration.IndentSize">4</value>
|
|
||||||
<value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value>
|
|
||||||
<value type="int" key="EditorConfiguration.LineEndingBehavior">0</value>
|
|
||||||
<value type="int" key="EditorConfiguration.MarginColumn">80</value>
|
|
||||||
<value type="bool" key="EditorConfiguration.MouseHiding">true</value>
|
|
||||||
<value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
|
|
||||||
<value type="int" key="EditorConfiguration.PaddingMode">1</value>
|
|
||||||
<value type="int" key="EditorConfiguration.PreferAfterWhitespaceComments">0</value>
|
|
||||||
<value type="bool" key="EditorConfiguration.PreferSingleLineComments">false</value>
|
|
||||||
<value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
|
|
||||||
<value type="bool" key="EditorConfiguration.ShowMargin">false</value>
|
|
||||||
<value type="int" key="EditorConfiguration.SmartBackspaceBehavior">2</value>
|
|
||||||
<value type="bool" key="EditorConfiguration.SmartSelectionChanging">true</value>
|
|
||||||
<value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
|
|
||||||
<value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
|
|
||||||
<value type="int" key="EditorConfiguration.TabSize">8</value>
|
|
||||||
<value type="bool" key="EditorConfiguration.UseGlobal">true</value>
|
|
||||||
<value type="bool" key="EditorConfiguration.UseIndenter">false</value>
|
|
||||||
<value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value>
|
|
||||||
<value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
|
|
||||||
<value type="bool" key="EditorConfiguration.cleanIndentation">true</value>
|
|
||||||
<value type="bool" key="EditorConfiguration.cleanWhitespace">true</value>
|
|
||||||
<value type="QString" key="EditorConfiguration.ignoreFileTypes">*.md, *.MD, Makefile</value>
|
|
||||||
<value type="bool" key="EditorConfiguration.inEntireDocument">false</value>
|
|
||||||
<value type="bool" key="EditorConfiguration.skipTrailingWhitespace">true</value>
|
|
||||||
<value type="bool" key="EditorConfiguration.tintMarginArea">true</value>
|
|
||||||
</valuemap>
|
|
||||||
</data>
|
|
||||||
<data>
|
|
||||||
<variable>ProjectExplorer.Project.PluginSettings</variable>
|
|
||||||
<valuemap type="QVariantMap">
|
|
||||||
<valuemap type="QVariantMap" key="AutoTest.ActiveFrameworks">
|
|
||||||
<value type="bool" key="AutoTest.Framework.Boost">true</value>
|
|
||||||
<value type="bool" key="AutoTest.Framework.CTest">false</value>
|
|
||||||
<value type="bool" key="AutoTest.Framework.Catch">true</value>
|
|
||||||
<value type="bool" key="AutoTest.Framework.GTest">true</value>
|
|
||||||
<value type="bool" key="AutoTest.Framework.QtQuickTest">true</value>
|
|
||||||
<value type="bool" key="AutoTest.Framework.QtTest">true</value>
|
|
||||||
</valuemap>
|
|
||||||
<value type="bool" key="AutoTest.ApplyFilter">false</value>
|
|
||||||
<valuemap type="QVariantMap" key="AutoTest.CheckStates"/>
|
|
||||||
<valuelist type="QVariantList" key="AutoTest.PathFilters"/>
|
|
||||||
<value type="int" key="AutoTest.RunAfterBuild">0</value>
|
|
||||||
<value type="bool" key="AutoTest.UseGlobal">true</value>
|
|
||||||
<valuemap type="QVariantMap" key="ClangTools">
|
|
||||||
<value type="bool" key="ClangTools.AnalyzeOpenFiles">true</value>
|
|
||||||
<value type="bool" key="ClangTools.BuildBeforeAnalysis">true</value>
|
|
||||||
<value type="QString" key="ClangTools.DiagnosticConfig">Builtin.DefaultTidyAndClazy</value>
|
|
||||||
<value type="int" key="ClangTools.ParallelJobs">5</value>
|
|
||||||
<value type="bool" key="ClangTools.PreferConfigFile">true</value>
|
|
||||||
<valuelist type="QVariantList" key="ClangTools.SelectedDirs"/>
|
|
||||||
<valuelist type="QVariantList" key="ClangTools.SelectedFiles"/>
|
|
||||||
<valuelist type="QVariantList" key="ClangTools.SuppressedDiagnostics"/>
|
|
||||||
<value type="bool" key="ClangTools.UseGlobalSettings">true</value>
|
|
||||||
</valuemap>
|
|
||||||
</valuemap>
|
|
||||||
</data>
|
|
||||||
<data>
|
|
||||||
<variable>ProjectExplorer.Project.Target.0</variable>
|
|
||||||
<valuemap type="QVariantMap">
|
|
||||||
<value type="QString" key="DeviceType">Desktop</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Qt 6.8.6 for macOS</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Qt 6.8.6 for macOS</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">qt.qt6.686.clang_64_kit</value>
|
|
||||||
<value type="qlonglong" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
|
|
||||||
<value type="qlonglong" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
|
|
||||||
<value type="qlonglong" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
|
|
||||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
|
|
||||||
<value type="QString" key="CMake.Build.Type">Debug</value>
|
|
||||||
<value type="int" key="CMake.Configure.BaseEnvironment">2</value>
|
|
||||||
<value type="bool" key="CMake.Configure.ClearSystemEnvironment">false</value>
|
|
||||||
<valuelist type="QVariantList" key="CMake.Configure.UserEnvironmentChanges"/>
|
|
||||||
<value type="QString" key="CMake.Initial.Parameters">-DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}
|
|
||||||
-DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
|
|
||||||
-DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG}
|
|
||||||
-DCMAKE_COLOR_DIAGNOSTICS:BOOL=ON
|
|
||||||
-DCMAKE_BUILD_TYPE:STRING=Debug
|
|
||||||
-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
|
|
||||||
-DCMAKE_GENERATOR:STRING=Ninja
|
|
||||||
-DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx}
|
|
||||||
-DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}</value>
|
|
||||||
<value type="int" key="EnableQmlDebugging">0</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/Users/talksik/Documents/code/adhd/build/Qt_6_8_6_for_macOS-Debug</value>
|
|
||||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
|
||||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
|
||||||
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
|
|
||||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
|
|
||||||
<value type="QString">all</value>
|
|
||||||
</valuelist>
|
|
||||||
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
|
|
||||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
|
|
||||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
|
|
||||||
</valuemap>
|
|
||||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
|
||||||
</valuemap>
|
|
||||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
|
||||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
|
||||||
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
|
|
||||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
|
|
||||||
<value type="QString">clean</value>
|
|
||||||
</valuelist>
|
|
||||||
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
|
|
||||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
|
|
||||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
|
|
||||||
</valuemap>
|
|
||||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
|
||||||
</valuemap>
|
|
||||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
|
||||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
|
||||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
|
|
||||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ParseStandardOutput">false</value>
|
|
||||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Debug</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeBuildConfiguration</value>
|
|
||||||
</valuemap>
|
|
||||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.1">
|
|
||||||
<value type="QString" key="CMake.Build.Type">Release</value>
|
|
||||||
<value type="int" key="CMake.Configure.BaseEnvironment">2</value>
|
|
||||||
<value type="bool" key="CMake.Configure.ClearSystemEnvironment">false</value>
|
|
||||||
<valuelist type="QVariantList" key="CMake.Configure.UserEnvironmentChanges"/>
|
|
||||||
<value type="QString" key="CMake.Initial.Parameters">-DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}
|
|
||||||
-DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
|
|
||||||
-DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG}
|
|
||||||
-DCMAKE_COLOR_DIAGNOSTICS:BOOL=ON
|
|
||||||
-DCMAKE_BUILD_TYPE:STRING=Release
|
|
||||||
-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
|
|
||||||
-DCMAKE_GENERATOR:STRING=Ninja
|
|
||||||
-DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx}
|
|
||||||
-DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/Users/talksik/Documents/code/adhd/build/Qt_6_8_6_for_macOS-Release</value>
|
|
||||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
|
||||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
|
||||||
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
|
|
||||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
|
|
||||||
<value type="QString">all</value>
|
|
||||||
</valuelist>
|
|
||||||
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
|
|
||||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
|
|
||||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
|
|
||||||
</valuemap>
|
|
||||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
|
||||||
</valuemap>
|
|
||||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
|
||||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
|
||||||
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
|
|
||||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
|
|
||||||
<value type="QString">clean</value>
|
|
||||||
</valuelist>
|
|
||||||
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
|
|
||||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
|
|
||||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
|
|
||||||
</valuemap>
|
|
||||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
|
||||||
</valuemap>
|
|
||||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
|
||||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
|
||||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
|
|
||||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ParseStandardOutput">false</value>
|
|
||||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Release</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeBuildConfiguration</value>
|
|
||||||
</valuemap>
|
|
||||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.2">
|
|
||||||
<value type="QString" key="CMake.Build.Type">RelWithDebInfo</value>
|
|
||||||
<value type="int" key="CMake.Configure.BaseEnvironment">2</value>
|
|
||||||
<value type="bool" key="CMake.Configure.ClearSystemEnvironment">false</value>
|
|
||||||
<valuelist type="QVariantList" key="CMake.Configure.UserEnvironmentChanges"/>
|
|
||||||
<value type="QString" key="CMake.Initial.Parameters">-DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}
|
|
||||||
-DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
|
|
||||||
-DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG}
|
|
||||||
-DCMAKE_COLOR_DIAGNOSTICS:BOOL=ON
|
|
||||||
-DCMAKE_BUILD_TYPE:STRING=RelWithDebInfo
|
|
||||||
-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
|
|
||||||
-DCMAKE_GENERATOR:STRING=Ninja
|
|
||||||
-DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx}
|
|
||||||
-DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/Users/talksik/Documents/code/adhd/build/Qt_6_8_6_for_macOS-RelWithDebInfo</value>
|
|
||||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
|
||||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
|
||||||
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
|
|
||||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
|
|
||||||
<value type="QString">all</value>
|
|
||||||
</valuelist>
|
|
||||||
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
|
|
||||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
|
|
||||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
|
|
||||||
</valuemap>
|
|
||||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
|
||||||
</valuemap>
|
|
||||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
|
||||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
|
||||||
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
|
|
||||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
|
|
||||||
<value type="QString">clean</value>
|
|
||||||
</valuelist>
|
|
||||||
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
|
|
||||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
|
|
||||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
|
|
||||||
</valuemap>
|
|
||||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
|
||||||
</valuemap>
|
|
||||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
|
||||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
|
||||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
|
|
||||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ParseStandardOutput">false</value>
|
|
||||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Release with Debug Information</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeBuildConfiguration</value>
|
|
||||||
</valuemap>
|
|
||||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.3">
|
|
||||||
<value type="QString" key="CMake.Build.Type">RelWithDebInfo</value>
|
|
||||||
<value type="int" key="CMake.Configure.BaseEnvironment">2</value>
|
|
||||||
<value type="bool" key="CMake.Configure.ClearSystemEnvironment">false</value>
|
|
||||||
<valuelist type="QVariantList" key="CMake.Configure.UserEnvironmentChanges"/>
|
|
||||||
<value type="QString" key="CMake.Initial.Parameters">-DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}
|
|
||||||
-DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
|
|
||||||
-DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG}
|
|
||||||
-DCMAKE_COLOR_DIAGNOSTICS:BOOL=ON
|
|
||||||
-DCMAKE_BUILD_TYPE:STRING=RelWithDebInfo
|
|
||||||
-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
|
|
||||||
-DCMAKE_GENERATOR:STRING=Ninja
|
|
||||||
-DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx}
|
|
||||||
-DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}</value>
|
|
||||||
<value type="int" key="EnableQmlDebugging">0</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/Users/talksik/Documents/code/adhd/build/Qt_6_8_6_for_macOS-Profile</value>
|
|
||||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
|
||||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
|
||||||
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
|
|
||||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
|
|
||||||
<value type="QString">all</value>
|
|
||||||
</valuelist>
|
|
||||||
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
|
|
||||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
|
|
||||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
|
|
||||||
</valuemap>
|
|
||||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
|
||||||
</valuemap>
|
|
||||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
|
||||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
|
||||||
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
|
|
||||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
|
|
||||||
<value type="QString">clean</value>
|
|
||||||
</valuelist>
|
|
||||||
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
|
|
||||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
|
|
||||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
|
|
||||||
</valuemap>
|
|
||||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
|
||||||
</valuemap>
|
|
||||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
|
||||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
|
||||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
|
|
||||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ParseStandardOutput">false</value>
|
|
||||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Profile</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeBuildConfiguration</value>
|
|
||||||
</valuemap>
|
|
||||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.4">
|
|
||||||
<value type="QString" key="CMake.Build.Type">MinSizeRel</value>
|
|
||||||
<value type="int" key="CMake.Configure.BaseEnvironment">2</value>
|
|
||||||
<value type="bool" key="CMake.Configure.ClearSystemEnvironment">false</value>
|
|
||||||
<valuelist type="QVariantList" key="CMake.Configure.UserEnvironmentChanges"/>
|
|
||||||
<value type="QString" key="CMake.Initial.Parameters">-DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}
|
|
||||||
-DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
|
|
||||||
-DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG}
|
|
||||||
-DCMAKE_COLOR_DIAGNOSTICS:BOOL=ON
|
|
||||||
-DCMAKE_BUILD_TYPE:STRING=MinSizeRel
|
|
||||||
-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
|
|
||||||
-DCMAKE_GENERATOR:STRING=Ninja
|
|
||||||
-DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx}
|
|
||||||
-DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/Users/talksik/Documents/code/adhd/build/Qt_6_8_6_for_macOS-MinSizeRel</value>
|
|
||||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
|
||||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
|
||||||
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
|
|
||||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
|
|
||||||
<value type="QString">all</value>
|
|
||||||
</valuelist>
|
|
||||||
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
|
|
||||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
|
|
||||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
|
|
||||||
</valuemap>
|
|
||||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
|
||||||
</valuemap>
|
|
||||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
|
||||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
|
||||||
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
|
|
||||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
|
|
||||||
<value type="QString">clean</value>
|
|
||||||
</valuelist>
|
|
||||||
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
|
|
||||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
|
|
||||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
|
|
||||||
</valuemap>
|
|
||||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
|
||||||
</valuemap>
|
|
||||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
|
||||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
|
||||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
|
|
||||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ParseStandardOutput">false</value>
|
|
||||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Minimum Size Release</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeBuildConfiguration</value>
|
|
||||||
</valuemap>
|
|
||||||
<value type="qlonglong" key="ProjectExplorer.Target.BuildConfigurationCount">5</value>
|
|
||||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
|
|
||||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
|
||||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Deploy</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
|
|
||||||
</valuemap>
|
|
||||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
|
|
||||||
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
|
|
||||||
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
|
|
||||||
</valuemap>
|
|
||||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.1">
|
|
||||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
|
||||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
|
||||||
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
|
|
||||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
|
|
||||||
<value type="QString"></value>
|
|
||||||
</valuelist>
|
|
||||||
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
|
|
||||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
|
|
||||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ApplicationManagerPlugin.Deploy.CMakePackageStep</value>
|
|
||||||
</valuemap>
|
|
||||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
|
|
||||||
<value type="QString" key="ApplicationManagerPlugin.Deploy.InstallPackageStep.Arguments">install-package --acknowledge</value>
|
|
||||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Install Application Manager package</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ApplicationManagerPlugin.Deploy.InstallPackageStep</value>
|
|
||||||
<valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedFiles"/>
|
|
||||||
<valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedHosts"/>
|
|
||||||
<valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedRemotePaths"/>
|
|
||||||
<valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedSysroots"/>
|
|
||||||
<valuelist type="QVariantList" key="RemoteLinux.LastDeployedLocalTimes"/>
|
|
||||||
<valuelist type="QVariantList" key="RemoteLinux.LastDeployedRemoteTimes"/>
|
|
||||||
</valuemap>
|
|
||||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Deploy</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
|
|
||||||
</valuemap>
|
|
||||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
|
|
||||||
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
|
|
||||||
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ApplicationManagerPlugin.Deploy.Configuration</value>
|
|
||||||
</valuemap>
|
|
||||||
<value type="qlonglong" key="ProjectExplorer.Target.DeployConfigurationCount">2</value>
|
|
||||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
|
|
||||||
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
|
|
||||||
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
|
|
||||||
<value type="int" key="Analyzer.Valgrind.Callgrind.CostFormat">0</value>
|
|
||||||
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
|
|
||||||
<valuelist type="QVariantList" key="CustomOutputParsers"/>
|
|
||||||
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
|
||||||
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
|
||||||
<value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
|
|
||||||
<value type="QString" key="PerfRecordArgsId">-e cpu-cycles --call-graph dwarf,4096 -F 250</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">adhd</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeRunConfiguration.</value>
|
|
||||||
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">adhd</value>
|
|
||||||
<value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
|
|
||||||
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
|
||||||
<value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
|
|
||||||
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
|
||||||
<value type="QString" key="RunConfiguration.WorkingDirectory.default">/Users/talksik/Documents/code/adhd/build/Qt_6_8_6_for_macOS-Debug/adhd.app/Contents/MacOS</value>
|
|
||||||
</valuemap>
|
|
||||||
<value type="qlonglong" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
|
|
||||||
</valuemap>
|
|
||||||
</data>
|
|
||||||
<data>
|
|
||||||
<variable>ProjectExplorer.Project.TargetCount</variable>
|
|
||||||
<value type="qlonglong">1</value>
|
|
||||||
</data>
|
|
||||||
<data>
|
|
||||||
<variable>ProjectExplorer.Project.Updater.FileVersion</variable>
|
|
||||||
<value type="int">22</value>
|
|
||||||
</data>
|
|
||||||
<data>
|
|
||||||
<variable>Version</variable>
|
|
||||||
<value type="int">22</value>
|
|
||||||
</data>
|
|
||||||
</qtcreator>
|
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
CC = cc
|
||||||
|
CFLAGS = -g -Wall -Iinclude
|
||||||
|
SOURCES = src/main.c src/window_state.c
|
||||||
|
OBJECTS = src/main.o src/window_state.o
|
||||||
|
LDFLAGS = -lraylib -lm -lsqlite3
|
||||||
|
HEADERS = \
|
||||||
|
include/raygui.h include/common.h include/window_state.h
|
||||||
|
|
||||||
|
PREFIX ?= /usr/local
|
||||||
|
BINDIR := $(PREFIX)/bin
|
||||||
|
|
||||||
|
# adhd: $(OBJECTS)
|
||||||
|
# $(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS)
|
||||||
|
|
||||||
|
# %.o: %.c $(HEADERS)
|
||||||
|
# $(CC) $(CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
adhd: src/main.o src/window_state.o
|
||||||
|
$(CC) $(CFLAGS) src/main.o src/window_state.o -o $@ $(LDFLAGS)
|
||||||
|
|
||||||
|
src/main.o: src/main.c $(HEADERS)
|
||||||
|
$(CC) -c $(CFLAGS) src/main.c -o $@
|
||||||
|
|
||||||
|
src/window_state.o: src/window_state.c $(HEADERS)
|
||||||
|
$(CC) -c $(CFLAGS) src/window_state.c -o $@
|
||||||
|
clean:
|
||||||
|
rm -rf $(OBJECTS) adhd
|
||||||
|
|
||||||
|
.PHONY: install
|
||||||
|
install: adhd
|
||||||
|
install -D adhd $(BINDIR)/adhd
|
||||||
|
|
||||||
@@ -1,33 +1,29 @@
|
|||||||
# Flowy.adhd
|
# Flowy.adhd
|
||||||
|
|
||||||
A macOS focus app that helps you stay on track by setting one intention per session.
|
We live in a noisy digital world. Unless you turn off your WiFi, millions of companies bid for your attention as you try to perform even the simplest of tasks.
|
||||||
|
|
||||||
|
This tool is a free, open-source application to help you stay on track. You set an intention before you work, and an overlay will remind you of your intention every x minutes.
|
||||||
|
|
||||||

|

|
||||||

|

|
||||||
|
|
||||||
|
## Install
|
||||||
|
At the moment, you must build and install the application yourself. There are minimum dependencies, so you essentially just need a C compiler.
|
||||||
|
|
||||||
## How it works
|
## How it works
|
||||||
|
|
||||||
1. Set your intention when you sit down at your computer
|
1. Set your intention when you sit down at your computer
|
||||||
2. A persistent overlay keeps your focus visible while you work
|
2. A persistent overlay reminds you of your intention
|
||||||
3. End the session and mark it as a win or loss
|
3. Set whether today was a win (focused) or loss (distracted), and view your daily activity in a nice graph
|
||||||
4. Build a log of your sessions over time
|
|
||||||
|
|
||||||
## Philosophy
|
## Philosophy
|
||||||
|
|
||||||
Stay aware of your intentions to avoid distractions. No todo manager needed—just focus on winning each session, one thing at a time.
|
In a world of fancy todo managers, for anyone with adhd, doing one thing at a time is the key. Win one intention at a time instead of planning, prioritizing, and juggling 100s of things.
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- **No sign in required** - Start using immediately
|
- **No sign in required**
|
||||||
- **Privacy first** - Sessions stored locally as markdown files
|
- **Slick overlay to show current intention**
|
||||||
|
- **Lightweight** - Written in C with few dependencies, nothing bloated like electron
|
||||||
|
- **Privacy first** - No telemetry, works offline
|
||||||
- **Session history** - Review your past wins and losses
|
- **Session history** - Review your past wins and losses
|
||||||
|
|
||||||
## Download
|
|
||||||
|
|
||||||
Get the latest version from [releases](https://github.com/flowy-live/adhd/releases).
|
|
||||||
|
|
||||||
## Roadmap
|
|
||||||
|
|
||||||
- View past session notes
|
|
||||||
- Win/loss statistics visualizer
|
|
||||||
- Windows and Linux support
|
|
||||||
|
|||||||
@@ -1,45 +1,13 @@
|
|||||||
## Todo
|
|
||||||
- [ ] tab widget: one for settings, one for sessions, one for active session editing
|
|
||||||
- [ ] active session view would show timer, pause, end, and edit session details
|
|
||||||
- [ ] create new session button
|
|
||||||
- [ ] click on a session to set as active
|
|
||||||
|
|
||||||
- [ ] create separate overlay that the main app can listen to and notify of active session changes
|
- [x] model window state with intention and simple overlay, window modes
|
||||||
|
|
||||||
## Ideas
|
- [x] create 2d grid
|
||||||
- Show me all sessions and the current session
|
- [x] usability: show week of the year / day of week, tooltips
|
||||||
- Sum up how many sessions I won/lost
|
- [x] toggle win / loss and persist values
|
||||||
- A session can simply be described by simple paragraph of what you'll do, maybe markdown
|
|
||||||
- Less rigidity in the sense of typing out thoughts and session goals...less due dates. Capture first, do later.
|
|
||||||
- Later: allow notes within a session, jot things down, all live in the same folder
|
|
||||||
- It's like a todo.md
|
|
||||||
- Every session is based on week # - year - session x
|
|
||||||
- Every session is an individual document that lives on disk
|
|
||||||
- See which week of the year that I'm in
|
|
||||||
- See progress bar of how much of the year is done or percentage
|
|
||||||
- Show stats on how many sessions total I've won/lost
|
|
||||||
- Display a separate overlay window that shows me my active working item in center bottom in a pill
|
|
||||||
- Can commit to github for "sync" and even include an input url to auto-upload the data directory to github
|
|
||||||
|
|
||||||
- overlay can show the first line of the session doc (or separate input)
|
- [x] persist results in sqlite3
|
||||||
- review of session can be: `Win`, `Neutral`, or `Loss`
|
|
||||||
|
|
||||||
## Flow
|
- [ ] reminder animation
|
||||||
- select location to save all your session data in markdown files
|
|
||||||
- data in the app parses the markdown file and uses it as the database, including the frontmatter
|
|
||||||
|
|
||||||
1. At the start of the day/session, set an intention by creating a session
|
- [ ] install via homebrew
|
||||||
2. Enter the top things to do this session in plain english (list or paragraph in markdown)
|
- [ ] launch on hackernews "for developers with adhd"
|
||||||
3. Click start session, and clock runs. Can pause, or stop.
|
|
||||||
4. When done for the session, select "Close session"...it will ask you to grade the session
|
|
||||||
5. View previous sessions in a list
|
|
||||||
|
|
||||||
## marketing
|
|
||||||
- local-only
|
|
||||||
- access files and metadata
|
|
||||||
- simple video demo OR flowy research-site page that has simple visuals
|
|
||||||
|
|
||||||
## Launch
|
|
||||||
- [ ] install via brew
|
|
||||||
- [ ] open source github
|
|
||||||
- [ ] hackernews "for developers with adhd"...purist site
|
|
||||||
|
|||||||
@@ -1,141 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Build script for universal macOS bundle (arm64 + x86_64)
|
|
||||||
|
|
||||||
set -e # Exit on error
|
|
||||||
|
|
||||||
echo "========================================="
|
|
||||||
echo "Building Universal macOS Bundle for adhd"
|
|
||||||
echo "========================================="
|
|
||||||
|
|
||||||
# Configuration
|
|
||||||
APP_NAME="adhd"
|
|
||||||
BUILD_DIR="build-universal"
|
|
||||||
BUILD_TYPE="Release"
|
|
||||||
ARCHITECTURES="arm64;x86_64"
|
|
||||||
QT_PATH="$HOME/Qt/6.8.6/macos"
|
|
||||||
APPLE_DEVELOPMENT_IDENTITY="Developer ID Application: Arjun Patel (RK9WWM4Q99)"
|
|
||||||
|
|
||||||
# Clean previous build (optional - comment out to keep incremental builds)
|
|
||||||
# rm -rf "$BUILD_DIR"
|
|
||||||
|
|
||||||
# Configure CMake
|
|
||||||
echo ""
|
|
||||||
echo "Configuring CMake for universal binary..."
|
|
||||||
echo "Minimum macOS version: 11.0 (Big Sur)"
|
|
||||||
cmake -B "$BUILD_DIR" \
|
|
||||||
-DCMAKE_OSX_ARCHITECTURES="$ARCHITECTURES" \
|
|
||||||
-DCMAKE_OSX_DEPLOYMENT_TARGET="11.0" \
|
|
||||||
-DCMAKE_PREFIX_PATH="$QT_PATH" \
|
|
||||||
-DCMAKE_BUILD_TYPE="$BUILD_TYPE"
|
|
||||||
|
|
||||||
# Build
|
|
||||||
echo ""
|
|
||||||
echo "Building..."
|
|
||||||
cmake --build "$BUILD_DIR" --config "$BUILD_TYPE" -j$(sysctl -n hw.ncpu)
|
|
||||||
|
|
||||||
# Verify the binary is universal
|
|
||||||
echo ""
|
|
||||||
echo "Verifying binary architectures..."
|
|
||||||
if [ -f "$BUILD_DIR/$APP_NAME.app/Contents/MacOS/$APP_NAME" ]; then
|
|
||||||
lipo -info "$BUILD_DIR/$APP_NAME.app/Contents/MacOS/$APP_NAME"
|
|
||||||
echo "✓ Binary is universal"
|
|
||||||
else
|
|
||||||
echo "✗ Error: Binary not found at expected location"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Deploy Qt dependencies
|
|
||||||
echo ""
|
|
||||||
echo "Deploying Qt dependencies..."
|
|
||||||
$QT_PATH/bin/macdeployqt "$BUILD_DIR/$APP_NAME.app" -always-overwrite -verbose=1
|
|
||||||
echo "✓ Qt dependencies deployed"
|
|
||||||
|
|
||||||
# Code signing
|
|
||||||
echo ""
|
|
||||||
echo "========================================="
|
|
||||||
echo "Listing identities for code-signing"
|
|
||||||
echo "========================================="
|
|
||||||
security find-identity -v -p codesigning
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "========================================="
|
|
||||||
echo "Code signing .app bundle"
|
|
||||||
echo "========================================="
|
|
||||||
echo "Using: $APPLE_DEVELOPMENT_IDENTITY"
|
|
||||||
|
|
||||||
cd "$BUILD_DIR"
|
|
||||||
|
|
||||||
codesign --deep --force --timestamp --verify --verbose=1 \
|
|
||||||
--sign "$APPLE_DEVELOPMENT_IDENTITY" \
|
|
||||||
--options runtime "$APP_NAME.app"
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "Verifying code signature..."
|
|
||||||
codesign --verify --deep --strict --verbose=1 "./$APP_NAME.app"
|
|
||||||
echo "✓ Code signing complete"
|
|
||||||
|
|
||||||
# Create DMG
|
|
||||||
echo ""
|
|
||||||
echo "========================================="
|
|
||||||
echo "Creating DMG"
|
|
||||||
echo "========================================="
|
|
||||||
echo "NOTE: Install create-dmg if needed: https://github.com/sindresorhus/create-dmg"
|
|
||||||
|
|
||||||
if ! command -v create-dmg &> /dev/null; then
|
|
||||||
echo "⚠ Warning: create-dmg not found. Install with: brew install create-dmg"
|
|
||||||
echo "Skipping DMG creation, notarization, and stapling."
|
|
||||||
cd ..
|
|
||||||
echo ""
|
|
||||||
echo "========================================="
|
|
||||||
echo "Build completed (without DMG/notarization)"
|
|
||||||
echo "App bundle location: $BUILD_DIR/$APP_NAME.app"
|
|
||||||
echo "========================================="
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
create-dmg "$APP_NAME.app" --identity="$APPLE_DEVELOPMENT_IDENTITY" --dmg-title="$APP_NAME"
|
|
||||||
# WORKAROUND: https://github.com/sindresorhus/create-dmg/issues/52
|
|
||||||
mv *.dmg "$APP_NAME.dmg" 2>/dev/null || true
|
|
||||||
|
|
||||||
echo "✓ DMG created: $APP_NAME.dmg"
|
|
||||||
|
|
||||||
# Notarization
|
|
||||||
echo ""
|
|
||||||
echo "========================================="
|
|
||||||
echo "Starting Notarization"
|
|
||||||
echo "========================================="
|
|
||||||
echo "NOTE: Make sure you've run 'xcrun notarytool store-credentials' first"
|
|
||||||
|
|
||||||
xcrun notarytool submit "$APP_NAME.dmg" \
|
|
||||||
--keychain-profile "default" \
|
|
||||||
--wait \
|
|
||||||
--timeout "10m"
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "========================================="
|
|
||||||
echo "Stapling notarization ticket"
|
|
||||||
echo "========================================="
|
|
||||||
xcrun stapler staple -v "$APP_NAME.dmg"
|
|
||||||
echo "✓ Notarization complete"
|
|
||||||
|
|
||||||
# Optional: Create zip
|
|
||||||
echo ""
|
|
||||||
read -p "Create zip file? (y/N): " CREATE_ZIP
|
|
||||||
if [[ "$CREATE_ZIP" == "y" || "$CREATE_ZIP" == "Y" ]]; then
|
|
||||||
ZIP_NAME="$APP_NAME-universal.zip"
|
|
||||||
zip -9 "$ZIP_NAME" "$APP_NAME.dmg"
|
|
||||||
echo "✓ Created: $ZIP_NAME"
|
|
||||||
fi
|
|
||||||
|
|
||||||
cd ..
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "========================================="
|
|
||||||
echo "Build completed successfully!"
|
|
||||||
echo "========================================="
|
|
||||||
echo "App bundle: $BUILD_DIR/$APP_NAME.app"
|
|
||||||
echo "DMG: $BUILD_DIR/$APP_NAME.dmg"
|
|
||||||
echo ""
|
|
||||||
echo "To test: open $BUILD_DIR/$APP_NAME.dmg"
|
|
||||||
echo "========================================="
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
#include "createsessiondialog.h"
|
|
||||||
#include "ui_createsessiondialog.h"
|
|
||||||
#include <QPushButton>
|
|
||||||
|
|
||||||
CreateSessionDialog::CreateSessionDialog(QWidget *parent)
|
|
||||||
: QDialog(parent),
|
|
||||||
ui(new Ui::CreateSessionDialog)
|
|
||||||
{
|
|
||||||
ui->setupUi(this);
|
|
||||||
|
|
||||||
setWindowTitle("Create New Session");
|
|
||||||
|
|
||||||
// Disable OK button initially
|
|
||||||
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
|
|
||||||
|
|
||||||
// Connect oneliner field to validation
|
|
||||||
connect(ui->onelinerEdit, &QLineEdit::textChanged,
|
|
||||||
this, &CreateSessionDialog::onOnelinerChanged);
|
|
||||||
}
|
|
||||||
|
|
||||||
CreateSessionDialog::~CreateSessionDialog()
|
|
||||||
{
|
|
||||||
delete ui;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString CreateSessionDialog::getOneliner() const
|
|
||||||
{
|
|
||||||
return ui->onelinerEdit->text().trimmed();
|
|
||||||
}
|
|
||||||
|
|
||||||
QString CreateSessionDialog::getContent() const
|
|
||||||
{
|
|
||||||
return ui->contentEdit->toPlainText().trimmed();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CreateSessionDialog::onOnelinerChanged(const QString &text)
|
|
||||||
{
|
|
||||||
bool isValid = !text.trimmed().isEmpty();
|
|
||||||
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(isValid);
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
#ifndef CREATESESSIONDIALOG_H
|
|
||||||
#define CREATESESSIONDIALOG_H
|
|
||||||
|
|
||||||
#include <QDialog>
|
|
||||||
|
|
||||||
namespace Ui {
|
|
||||||
class CreateSessionDialog;
|
|
||||||
}
|
|
||||||
|
|
||||||
class CreateSessionDialog : public QDialog
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit CreateSessionDialog(QWidget *parent = nullptr);
|
|
||||||
~CreateSessionDialog();
|
|
||||||
|
|
||||||
QString getOneliner() const;
|
|
||||||
QString getContent() const;
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void onOnelinerChanged(const QString &text);
|
|
||||||
|
|
||||||
private:
|
|
||||||
Ui::CreateSessionDialog *ui;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // CREATESESSIONDIALOG_H
|
|
||||||
@@ -1,96 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<ui version="4.0">
|
|
||||||
<class>CreateSessionDialog</class>
|
|
||||||
<widget class="QDialog" name="CreateSessionDialog">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>0</x>
|
|
||||||
<y>0</y>
|
|
||||||
<width>500</width>
|
|
||||||
<height>300</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="windowTitle">
|
|
||||||
<string>Create Session</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
|
||||||
<item>
|
|
||||||
<layout class="QFormLayout" name="formLayout">
|
|
||||||
<item row="0" column="0">
|
|
||||||
<widget class="QLabel" name="onelinerLabel">
|
|
||||||
<property name="text">
|
|
||||||
<string>Oneliner:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="1">
|
|
||||||
<widget class="QLineEdit" name="onelinerEdit">
|
|
||||||
<property name="placeholderText">
|
|
||||||
<string>What will you focus on?</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QLabel" name="contentLabel">
|
|
||||||
<property name="text">
|
|
||||||
<string>Initial Content:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="1">
|
|
||||||
<widget class="QTextEdit" name="contentEdit">
|
|
||||||
<property name="placeholderText">
|
|
||||||
<string>Optional: Add initial notes or context...</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QDialogButtonBox" name="buttonBox">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="standardButtons">
|
|
||||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<resources/>
|
|
||||||
<connections>
|
|
||||||
<connection>
|
|
||||||
<sender>buttonBox</sender>
|
|
||||||
<signal>accepted()</signal>
|
|
||||||
<receiver>CreateSessionDialog</receiver>
|
|
||||||
<slot>accept()</slot>
|
|
||||||
<hints>
|
|
||||||
<hint type="sourcelabel">
|
|
||||||
<x>248</x>
|
|
||||||
<y>254</y>
|
|
||||||
</hint>
|
|
||||||
<hint type="destinationlabel">
|
|
||||||
<x>157</x>
|
|
||||||
<y>274</y>
|
|
||||||
</hint>
|
|
||||||
</hints>
|
|
||||||
</connection>
|
|
||||||
<connection>
|
|
||||||
<sender>buttonBox</sender>
|
|
||||||
<signal>rejected()</signal>
|
|
||||||
<receiver>CreateSessionDialog</receiver>
|
|
||||||
<slot>reject()</slot>
|
|
||||||
<hints>
|
|
||||||
<hint type="sourcelabel">
|
|
||||||
<x>316</x>
|
|
||||||
<y>260</y>
|
|
||||||
</hint>
|
|
||||||
<hint type="destinationlabel">
|
|
||||||
<x>286</x>
|
|
||||||
<y>274</y>
|
|
||||||
</hint>
|
|
||||||
</hints>
|
|
||||||
</connection>
|
|
||||||
</connections>
|
|
||||||
</ui>
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
#include "endsessiondialog.h"
|
|
||||||
#include "ui_endsessiondialog.h"
|
|
||||||
|
|
||||||
EndSessionDialog::EndSessionDialog(const QString &oneliner, int elapsedMs, QWidget *parent)
|
|
||||||
: QDialog(parent),
|
|
||||||
ui(new Ui::EndSessionDialog),
|
|
||||||
m_selectedResult(Session::UNSPECIFIED)
|
|
||||||
{
|
|
||||||
ui->setupUi(this);
|
|
||||||
|
|
||||||
setWindowTitle("End Session");
|
|
||||||
|
|
||||||
// Set oneliner and elapsed time
|
|
||||||
ui->onelinerLabel->setText(oneliner);
|
|
||||||
|
|
||||||
int seconds = elapsedMs / 1000;
|
|
||||||
int hours = seconds / 3600;
|
|
||||||
int minutes = (seconds % 3600) / 60;
|
|
||||||
int secs = seconds % 60;
|
|
||||||
|
|
||||||
QString timeStr = QString("%1:%2:%3")
|
|
||||||
.arg(hours, 2, 10, QChar('0'))
|
|
||||||
.arg(minutes, 2, 10, QChar('0'))
|
|
||||||
.arg(secs, 2, 10, QChar('0'));
|
|
||||||
|
|
||||||
ui->elapsedLabel->setText("Duration: " + timeStr);
|
|
||||||
|
|
||||||
// Connect buttons
|
|
||||||
connect(ui->winButton, &QPushButton::clicked,
|
|
||||||
this, &EndSessionDialog::onWinClicked);
|
|
||||||
connect(ui->lossButton, &QPushButton::clicked,
|
|
||||||
this, &EndSessionDialog::onLossClicked);
|
|
||||||
connect(ui->neutralButton, &QPushButton::clicked,
|
|
||||||
this, &EndSessionDialog::onNeutralClicked);
|
|
||||||
}
|
|
||||||
|
|
||||||
EndSessionDialog::~EndSessionDialog()
|
|
||||||
{
|
|
||||||
delete ui;
|
|
||||||
}
|
|
||||||
|
|
||||||
Session::Result EndSessionDialog::getResult() const
|
|
||||||
{
|
|
||||||
return m_selectedResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString EndSessionDialog::getAdditionalNotes() const
|
|
||||||
{
|
|
||||||
return ui->notesEdit->toPlainText().trimmed();
|
|
||||||
}
|
|
||||||
|
|
||||||
void EndSessionDialog::onWinClicked()
|
|
||||||
{
|
|
||||||
m_selectedResult = Session::WIN;
|
|
||||||
accept();
|
|
||||||
}
|
|
||||||
|
|
||||||
void EndSessionDialog::onLossClicked()
|
|
||||||
{
|
|
||||||
m_selectedResult = Session::LOSS;
|
|
||||||
accept();
|
|
||||||
}
|
|
||||||
|
|
||||||
void EndSessionDialog::onNeutralClicked()
|
|
||||||
{
|
|
||||||
m_selectedResult = Session::NEUTRAL;
|
|
||||||
accept();
|
|
||||||
}
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
#ifndef ENDSESSIONDIALOG_H
|
|
||||||
#define ENDSESSIONDIALOG_H
|
|
||||||
|
|
||||||
#include <QDialog>
|
|
||||||
#include "service.h"
|
|
||||||
|
|
||||||
namespace Ui {
|
|
||||||
class EndSessionDialog;
|
|
||||||
}
|
|
||||||
|
|
||||||
class EndSessionDialog : public QDialog
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit EndSessionDialog(const QString &oneliner, int elapsedMs, QWidget *parent = nullptr);
|
|
||||||
~EndSessionDialog();
|
|
||||||
|
|
||||||
Session::Result getResult() const;
|
|
||||||
QString getAdditionalNotes() const;
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void onWinClicked();
|
|
||||||
void onLossClicked();
|
|
||||||
void onNeutralClicked();
|
|
||||||
|
|
||||||
private:
|
|
||||||
Ui::EndSessionDialog *ui;
|
|
||||||
Session::Result m_selectedResult;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // ENDSESSIONDIALOG_H
|
|
||||||
@@ -1,221 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<ui version="4.0">
|
|
||||||
<class>EndSessionDialog</class>
|
|
||||||
<widget class="QDialog" name="EndSessionDialog">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>0</x>
|
|
||||||
<y>0</y>
|
|
||||||
<width>500</width>
|
|
||||||
<height>400</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="windowTitle">
|
|
||||||
<string>End Session</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="label">
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<pointsize>16</pointsize>
|
|
||||||
<weight>75</weight>
|
|
||||||
<bold>true</bold>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>How did your session go?</string>
|
|
||||||
</property>
|
|
||||||
<property name="alignment">
|
|
||||||
<set>Qt::AlignCenter</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="onelinerLabel">
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<pointsize>14</pointsize>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Session Oneliner</string>
|
|
||||||
</property>
|
|
||||||
<property name="alignment">
|
|
||||||
<set>Qt::AlignCenter</set>
|
|
||||||
</property>
|
|
||||||
<property name="wordWrap">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="elapsedLabel">
|
|
||||||
<property name="text">
|
|
||||||
<string>Duration: 00:00:00</string>
|
|
||||||
</property>
|
|
||||||
<property name="alignment">
|
|
||||||
<set>Qt::AlignCenter</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<spacer name="verticalSpacer">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Vertical</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeType">
|
|
||||||
<enum>QSizePolicy::Fixed</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>20</width>
|
|
||||||
<height>20</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="winButton">
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>0</width>
|
|
||||||
<height>60</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<pointsize>14</pointsize>
|
|
||||||
<weight>75</weight>
|
|
||||||
<bold>true</bold>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="styleSheet">
|
|
||||||
<string notr="true">QPushButton {
|
|
||||||
background-color: #2ecc71;
|
|
||||||
color: white;
|
|
||||||
border-radius: 5px;
|
|
||||||
}
|
|
||||||
QPushButton:hover {
|
|
||||||
background-color: #27ae60;
|
|
||||||
}
|
|
||||||
QPushButton:pressed {
|
|
||||||
background-color: #229954;
|
|
||||||
}</string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>WIN</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="lossButton">
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>0</width>
|
|
||||||
<height>60</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<pointsize>14</pointsize>
|
|
||||||
<weight>75</weight>
|
|
||||||
<bold>true</bold>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="styleSheet">
|
|
||||||
<string notr="true">QPushButton {
|
|
||||||
background-color: #e74c3c;
|
|
||||||
color: white;
|
|
||||||
border-radius: 5px;
|
|
||||||
}
|
|
||||||
QPushButton:hover {
|
|
||||||
background-color: #c0392b;
|
|
||||||
}
|
|
||||||
QPushButton:pressed {
|
|
||||||
background-color: #a93226;
|
|
||||||
}</string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>LOSS</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="neutralButton">
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>0</width>
|
|
||||||
<height>60</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<pointsize>14</pointsize>
|
|
||||||
<weight>75</weight>
|
|
||||||
<bold>true</bold>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="styleSheet">
|
|
||||||
<string notr="true">QPushButton {
|
|
||||||
background-color: #95a5a6;
|
|
||||||
color: white;
|
|
||||||
border-radius: 5px;
|
|
||||||
}
|
|
||||||
QPushButton:hover {
|
|
||||||
background-color: #7f8c8d;
|
|
||||||
}
|
|
||||||
QPushButton:pressed {
|
|
||||||
background-color: #707b7c;
|
|
||||||
}</string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>NEUTRAL</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<spacer name="verticalSpacer_2">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Vertical</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeType">
|
|
||||||
<enum>QSizePolicy::Fixed</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>20</width>
|
|
||||||
<height>20</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="label_2">
|
|
||||||
<property name="text">
|
|
||||||
<string>Optional: Add final notes</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QTextEdit" name="notesEdit">
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>16777215</width>
|
|
||||||
<height>100</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="placeholderText">
|
|
||||||
<string>Any final thoughts or notes about this session...</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<resources/>
|
|
||||||
<connections/>
|
|
||||||
</ui>
|
|
||||||
@@ -1,100 +0,0 @@
|
|||||||
#include "focusoverlay.h"
|
|
||||||
#include "ui_focusoverlay.h"
|
|
||||||
#include <QScreen>
|
|
||||||
#include <QGuiApplication>
|
|
||||||
#include <QMouseEvent>
|
|
||||||
|
|
||||||
FocusOverlay::FocusOverlay(QWidget *parent)
|
|
||||||
: QWidget(parent),
|
|
||||||
ui(new Ui::FocusOverlay),
|
|
||||||
m_dragging(false)
|
|
||||||
{
|
|
||||||
ui->setupUi(this);
|
|
||||||
|
|
||||||
// Set window flags for always-on-top frameless window
|
|
||||||
// Use Qt::Window instead of Qt::Tool so it stays visible when app loses focus
|
|
||||||
setWindowFlags(Qt::Window | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
|
|
||||||
setAttribute(Qt::WA_TranslucentBackground);
|
|
||||||
setAttribute(Qt::WA_ShowWithoutActivating); // Don't steal focus when showing
|
|
||||||
|
|
||||||
// Connect buttons
|
|
||||||
connect(ui->resetButton, &QPushButton::clicked,
|
|
||||||
this, &FocusOverlay::onResetButtonClicked);
|
|
||||||
connect(ui->endButton, &QPushButton::clicked,
|
|
||||||
this, &FocusOverlay::onEndButtonClicked);
|
|
||||||
|
|
||||||
// Position window
|
|
||||||
positionAtBottomCenter();
|
|
||||||
}
|
|
||||||
|
|
||||||
FocusOverlay::~FocusOverlay()
|
|
||||||
{
|
|
||||||
delete ui;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FocusOverlay::setOneliner(const QString &oneliner)
|
|
||||||
{
|
|
||||||
ui->onelinerLabel->setText(oneliner);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FocusOverlay::setElapsedTime(int elapsedMs)
|
|
||||||
{
|
|
||||||
int seconds = elapsedMs / 1000;
|
|
||||||
int hours = seconds / 3600;
|
|
||||||
int minutes = (seconds % 3600) / 60;
|
|
||||||
int secs = seconds % 60;
|
|
||||||
|
|
||||||
QString timeStr = QString("%1:%2:%3")
|
|
||||||
.arg(hours, 2, 10, QChar('0'))
|
|
||||||
.arg(minutes, 2, 10, QChar('0'))
|
|
||||||
.arg(secs, 2, 10, QChar('0'));
|
|
||||||
|
|
||||||
ui->elapsedLabel->setText("Elapsed: " + timeStr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FocusOverlay::onResetButtonClicked()
|
|
||||||
{
|
|
||||||
emit resetClicked();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FocusOverlay::onEndButtonClicked()
|
|
||||||
{
|
|
||||||
emit endSessionClicked();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FocusOverlay::positionAtBottomCenter()
|
|
||||||
{
|
|
||||||
QScreen *screen = QGuiApplication::primaryScreen();
|
|
||||||
if (!screen) return;
|
|
||||||
|
|
||||||
QRect screenGeometry = screen->geometry();
|
|
||||||
int x = (screenGeometry.width() - width()) / 2;
|
|
||||||
int y = screenGeometry.height() - height();
|
|
||||||
|
|
||||||
move(x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FocusOverlay::mousePressEvent(QMouseEvent *event)
|
|
||||||
{
|
|
||||||
if (event->button() == Qt::LeftButton) {
|
|
||||||
m_dragging = true;
|
|
||||||
m_dragStartPosition = event->globalPosition().toPoint() - frameGeometry().topLeft();
|
|
||||||
event->accept();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FocusOverlay::mouseMoveEvent(QMouseEvent *event)
|
|
||||||
{
|
|
||||||
if (m_dragging && (event->buttons() & Qt::LeftButton)) {
|
|
||||||
move(event->globalPosition().toPoint() - m_dragStartPosition);
|
|
||||||
event->accept();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FocusOverlay::mouseReleaseEvent(QMouseEvent *event)
|
|
||||||
{
|
|
||||||
if (event->button() == Qt::LeftButton) {
|
|
||||||
m_dragging = false;
|
|
||||||
event->accept();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
#ifndef FOCUSOVERLAY_H
|
|
||||||
#define FOCUSOVERLAY_H
|
|
||||||
|
|
||||||
#include <QWidget>
|
|
||||||
|
|
||||||
namespace Ui {
|
|
||||||
class FocusOverlay;
|
|
||||||
}
|
|
||||||
|
|
||||||
class FocusOverlay : public QWidget
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit FocusOverlay(QWidget *parent = nullptr);
|
|
||||||
~FocusOverlay();
|
|
||||||
|
|
||||||
void setOneliner(const QString &oneliner);
|
|
||||||
void setElapsedTime(int elapsedMs);
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void resetClicked();
|
|
||||||
void endSessionClicked();
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void onResetButtonClicked();
|
|
||||||
void onEndButtonClicked();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void mousePressEvent(QMouseEvent *event) override;
|
|
||||||
void mouseMoveEvent(QMouseEvent *event) override;
|
|
||||||
void mouseReleaseEvent(QMouseEvent *event) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
Ui::FocusOverlay *ui;
|
|
||||||
void positionAtBottomCenter();
|
|
||||||
|
|
||||||
// For dragging
|
|
||||||
bool m_dragging;
|
|
||||||
QPoint m_dragStartPosition;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // FOCUSOVERLAY_H
|
|
||||||
-158
@@ -1,158 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<ui version="4.0">
|
|
||||||
<class>FocusOverlay</class>
|
|
||||||
<widget class="QWidget" name="FocusOverlay">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>0</x>
|
|
||||||
<y>0</y>
|
|
||||||
<width>350</width>
|
|
||||||
<height>102</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>350</width>
|
|
||||||
<height>80</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>350</width>
|
|
||||||
<height>102</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="windowTitle">
|
|
||||||
<string>Focus Session</string>
|
|
||||||
</property>
|
|
||||||
<property name="styleSheet">
|
|
||||||
<string notr="true">QWidget#FocusOverlay {
|
|
||||||
background-color: rgba(50, 50, 50, 200);
|
|
||||||
border-radius: 10px;
|
|
||||||
border: 2px solid rgba(100, 100, 100, 255);
|
|
||||||
}
|
|
||||||
|
|
||||||
QLabel {
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
QPushButton {
|
|
||||||
background-color: rgba(80, 80, 80, 255);
|
|
||||||
color: white;
|
|
||||||
border: 1px solid rgba(120, 120, 120, 255);
|
|
||||||
border-radius: 5px;
|
|
||||||
padding: 4px 8px;
|
|
||||||
min-width: 50px;
|
|
||||||
}
|
|
||||||
|
|
||||||
QPushButton:hover {
|
|
||||||
background-color: rgba(100, 100, 100, 255);
|
|
||||||
}
|
|
||||||
|
|
||||||
QPushButton:pressed {
|
|
||||||
background-color: rgba(60, 60, 60, 255);
|
|
||||||
}</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
|
||||||
<property name="spacing">
|
|
||||||
<number>8</number>
|
|
||||||
</property>
|
|
||||||
<property name="leftMargin">
|
|
||||||
<number>10</number>
|
|
||||||
</property>
|
|
||||||
<property name="topMargin">
|
|
||||||
<number>8</number>
|
|
||||||
</property>
|
|
||||||
<property name="rightMargin">
|
|
||||||
<number>10</number>
|
|
||||||
</property>
|
|
||||||
<property name="bottomMargin">
|
|
||||||
<number>8</number>
|
|
||||||
</property>
|
|
||||||
<item>
|
|
||||||
<widget class="QWidget" name="widget" native="true">
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
|
||||||
<property name="spacing">
|
|
||||||
<number>2</number>
|
|
||||||
</property>
|
|
||||||
<property name="leftMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="topMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="rightMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="bottomMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="onelinerLabel">
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<pointsize>12</pointsize>
|
|
||||||
<bold>true</bold>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Session Oneliner</string>
|
|
||||||
</property>
|
|
||||||
<property name="alignment">
|
|
||||||
<set>Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignVCenter</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="elapsedLabel">
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<pointsize>10</pointsize>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Elapsed: 00:00:00</string>
|
|
||||||
</property>
|
|
||||||
<property name="alignment">
|
|
||||||
<set>Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignVCenter</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="resetButton">
|
|
||||||
<property name="text">
|
|
||||||
<string>Reset</string>
|
|
||||||
</property>
|
|
||||||
<property name="default">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="flat">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="endButton">
|
|
||||||
<property name="text">
|
|
||||||
<string>End Session</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<resources/>
|
|
||||||
<connections/>
|
|
||||||
</ui>
|
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
#ifndef COMMON_H
|
||||||
|
#define COMMON_H
|
||||||
|
|
||||||
|
typedef unsigned int U32;
|
||||||
|
|
||||||
|
struct date {
|
||||||
|
U32 day;
|
||||||
|
U32 month;
|
||||||
|
U32 year;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct date to_date(char *);
|
||||||
|
char *to_string(struct date);
|
||||||
|
|
||||||
|
#endif
|
||||||
+6464
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,10 @@
|
|||||||
|
#include <sqlite3.h>
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
/* persist on disk with compact representation
|
||||||
|
date representation -> value
|
||||||
|
*/
|
||||||
|
void store_result(U32 val, struct date d);
|
||||||
|
void retrieve_result(U32 val, struct date d);
|
||||||
|
void retrieve_results_before(int *vals, struct date before);
|
||||||
|
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
#ifndef WINDOWSTATE_H
|
||||||
|
#define WINDOWSTATE_H
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
enum mode_t {
|
||||||
|
WINDOW = 0,
|
||||||
|
OVERLAY
|
||||||
|
};
|
||||||
|
typedef enum mode_t Mode;
|
||||||
|
|
||||||
|
void init_window_state();
|
||||||
|
void cleanup_window_state();
|
||||||
|
|
||||||
|
void set_intention(char *intention);
|
||||||
|
char *get_intention();
|
||||||
|
size_t get_intention_size();
|
||||||
|
|
||||||
|
Mode get_mode();
|
||||||
|
void set_mode(Mode mode);
|
||||||
|
|
||||||
|
// returns 1 for win, 0 for loss
|
||||||
|
U32 get_result(struct tm *time);
|
||||||
|
void set_result(struct tm *time, U32 result);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
#include <iostream>
|
|
||||||
#include <QApplication>
|
|
||||||
#include "mainwindow.h"
|
|
||||||
#include "service.h"
|
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
|
||||||
std::cout << "Starting adhd program" << std::endl;
|
|
||||||
|
|
||||||
QApplication a(argc, argv);
|
|
||||||
a.setStyle("fusion");
|
|
||||||
|
|
||||||
MainWindow w;
|
|
||||||
w.show();
|
|
||||||
|
|
||||||
return a.exec();
|
|
||||||
}
|
|
||||||
-264
@@ -1,264 +0,0 @@
|
|||||||
#include "mainwindow.h"
|
|
||||||
#include "service.h"
|
|
||||||
#include "sessionslistmodel.h"
|
|
||||||
#include "sessionitemdelegate.h"
|
|
||||||
#include "createsessiondialog.h"
|
|
||||||
#include "focusoverlay.h"
|
|
||||||
#include "endsessiondialog.h"
|
|
||||||
#include <QFileDialog>
|
|
||||||
#include <QLabel>
|
|
||||||
#include <QVBoxLayout>
|
|
||||||
#include <QTimer>
|
|
||||||
#include <QMessageBox>
|
|
||||||
#include <QSettings>
|
|
||||||
#include "ui_mainwindow.h"
|
|
||||||
|
|
||||||
MainWindow::MainWindow(QWidget *parent)
|
|
||||||
: QMainWindow(parent),
|
|
||||||
m_service(new Service(this)),
|
|
||||||
m_focusOverlay(nullptr),
|
|
||||||
m_updatingActiveFields(false)
|
|
||||||
{
|
|
||||||
ui = new Ui::MainWindow;
|
|
||||||
ui->setupUi(this);
|
|
||||||
setWindowTitle("flowy.adhd");
|
|
||||||
|
|
||||||
m_listModel = new SessionsListModel(m_service, this);
|
|
||||||
ui->listView->setModel(m_listModel);
|
|
||||||
ui->listView->setItemDelegate(new SessionItemDelegate(this));
|
|
||||||
|
|
||||||
// Connect Service signals
|
|
||||||
connect(m_service, &Service::activeSessionChanged,
|
|
||||||
this, &MainWindow::onActiveSessionChanged);
|
|
||||||
connect(m_service, &Service::sessionTimerTicked,
|
|
||||||
this, &MainWindow::onSessionTimerTicked);
|
|
||||||
|
|
||||||
// Connect Active tab field changes
|
|
||||||
connect(ui->oneLineEdit, &QLineEdit::editingFinished,
|
|
||||||
this, &MainWindow::onActiveOnelinerChanged);
|
|
||||||
|
|
||||||
// Debounce content text changes
|
|
||||||
QTimer *contentDebounce = new QTimer(this);
|
|
||||||
contentDebounce->setSingleShot(true);
|
|
||||||
contentDebounce->setInterval(500);
|
|
||||||
connect(ui->contentTextEdit, &QTextEdit::textChanged,
|
|
||||||
[contentDebounce]() { contentDebounce->start(); });
|
|
||||||
connect(contentDebounce, &QTimer::timeout,
|
|
||||||
this, &MainWindow::onActiveContentChanged);
|
|
||||||
|
|
||||||
// Set initial state: no active session
|
|
||||||
ui->activeStackedWidget->setCurrentIndex(0);
|
|
||||||
|
|
||||||
// Load saved vault directory from settings
|
|
||||||
QSettings settings("flowy", "adhd");
|
|
||||||
QString savedVaultPath = settings.value("vaultDirectory").toString();
|
|
||||||
if (!savedVaultPath.isEmpty() && QDir(savedVaultPath).exists()) {
|
|
||||||
m_service->setVaultDirectory(savedVaultPath);
|
|
||||||
ui->vaultLabel->setText(savedVaultPath);
|
|
||||||
// Switch to Sessions tab if we have a valid vault
|
|
||||||
ui->tabWidget->setCurrentIndex(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MainWindow::~MainWindow() {}
|
|
||||||
|
|
||||||
void MainWindow::on_selectVaultButton_clicked()
|
|
||||||
{
|
|
||||||
QString dir = QFileDialog::getExistingDirectory(this,
|
|
||||||
"Select Directory",
|
|
||||||
QDir::homePath(),
|
|
||||||
QFileDialog::ShowDirsOnly);
|
|
||||||
if (!dir.isEmpty()) {
|
|
||||||
m_service->setVaultDirectory(dir);
|
|
||||||
ui->tabWidget->setCurrentIndex(1);
|
|
||||||
ui->vaultLabel->setText(dir);
|
|
||||||
|
|
||||||
// Save to settings for next launch
|
|
||||||
QSettings settings("flowy", "adhd");
|
|
||||||
settings.setValue("vaultDirectory", dir);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::on_newSessionButton_clicked()
|
|
||||||
{
|
|
||||||
CreateSessionDialog dialog(this);
|
|
||||||
if (dialog.exec() == QDialog::Accepted) {
|
|
||||||
QString oneliner = dialog.getOneliner();
|
|
||||||
QString content = dialog.getContent();
|
|
||||||
|
|
||||||
Session session = m_service->createSession(oneliner, content);
|
|
||||||
m_service->startSession(session);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::on_startSessionButton_clicked()
|
|
||||||
{
|
|
||||||
QModelIndex index = ui->listView->currentIndex();
|
|
||||||
if (!index.isValid()) {
|
|
||||||
QMessageBox::warning(this, "No Selection", "Please select a session to start.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Session session = m_listModel->getSessionByIndex(index);
|
|
||||||
m_service->startSession(session);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::on_endSessionButton_clicked()
|
|
||||||
{
|
|
||||||
auto activeSession = m_service->activeSession();
|
|
||||||
if (!activeSession) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
EndSessionDialog dialog(activeSession->oneliner, m_service->getElapsedMs(), this);
|
|
||||||
if (dialog.exec() == QDialog::Accepted) {
|
|
||||||
Session::Result result = dialog.getResult();
|
|
||||||
QString notes = dialog.getAdditionalNotes();
|
|
||||||
|
|
||||||
// Append notes to content if provided
|
|
||||||
if (!notes.isEmpty()) {
|
|
||||||
Session updated = *activeSession;
|
|
||||||
if (!updated.content.isEmpty()) {
|
|
||||||
updated.content += "\n\n";
|
|
||||||
}
|
|
||||||
updated.content += notes;
|
|
||||||
m_service->updateSession(updated);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_service->endSession(result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::onActiveSessionChanged()
|
|
||||||
{
|
|
||||||
auto activeSession = m_service->activeSession();
|
|
||||||
|
|
||||||
if (activeSession) {
|
|
||||||
// Session started
|
|
||||||
ui->activeStackedWidget->setCurrentIndex(1);
|
|
||||||
updateActiveTab();
|
|
||||||
|
|
||||||
// Create and show overlay
|
|
||||||
if (!m_focusOverlay) {
|
|
||||||
m_focusOverlay = new FocusOverlay();
|
|
||||||
connect(m_focusOverlay, &FocusOverlay::resetClicked,
|
|
||||||
this, &MainWindow::onOverlayResetClicked);
|
|
||||||
connect(m_focusOverlay, &FocusOverlay::endSessionClicked,
|
|
||||||
this, &MainWindow::onOverlayEndSessionClicked);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_focusOverlay->setOneliner(activeSession->oneliner);
|
|
||||||
m_focusOverlay->setElapsedTime(0);
|
|
||||||
m_focusOverlay->show();
|
|
||||||
|
|
||||||
// Switch to Active tab
|
|
||||||
ui->tabWidget->setCurrentIndex(2);
|
|
||||||
} else {
|
|
||||||
// Session ended
|
|
||||||
ui->activeStackedWidget->setCurrentIndex(0);
|
|
||||||
|
|
||||||
// Hide and delete overlay
|
|
||||||
if (m_focusOverlay) {
|
|
||||||
m_focusOverlay->hide();
|
|
||||||
m_focusOverlay->deleteLater();
|
|
||||||
m_focusOverlay = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::onSessionTimerTicked(int elapsedMs)
|
|
||||||
{
|
|
||||||
ui->elapsedLabel->setText(formatDuration(elapsedMs));
|
|
||||||
|
|
||||||
if (m_focusOverlay) {
|
|
||||||
m_focusOverlay->setElapsedTime(elapsedMs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::onActiveOnelinerChanged()
|
|
||||||
{
|
|
||||||
if (m_updatingActiveFields) return;
|
|
||||||
|
|
||||||
auto activeSession = m_service->activeSession();
|
|
||||||
if (!activeSession) return;
|
|
||||||
|
|
||||||
Session updated = *activeSession;
|
|
||||||
updated.oneliner = ui->oneLineEdit->text();
|
|
||||||
updated.lastModifiedAt = QDateTime::currentDateTime();
|
|
||||||
|
|
||||||
m_updatingActiveFields = true;
|
|
||||||
m_service->updateSession(updated);
|
|
||||||
m_service->updateActiveSession(updated);
|
|
||||||
|
|
||||||
// Update overlay
|
|
||||||
if (m_focusOverlay) {
|
|
||||||
m_focusOverlay->setOneliner(updated.oneliner);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_updatingActiveFields = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::onActiveContentChanged()
|
|
||||||
{
|
|
||||||
if (m_updatingActiveFields) return;
|
|
||||||
|
|
||||||
auto activeSession = m_service->activeSession();
|
|
||||||
if (!activeSession) return;
|
|
||||||
|
|
||||||
Session updated = *activeSession;
|
|
||||||
updated.content = ui->contentTextEdit->toPlainText();
|
|
||||||
updated.lastModifiedAt = QDateTime::currentDateTime();
|
|
||||||
|
|
||||||
m_updatingActiveFields = true;
|
|
||||||
m_service->updateSession(updated);
|
|
||||||
m_service->updateActiveSession(updated);
|
|
||||||
m_updatingActiveFields = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::onOverlayResetClicked()
|
|
||||||
{
|
|
||||||
QMessageBox::StandardButton reply = QMessageBox::question(
|
|
||||||
this,
|
|
||||||
"Reset Timer",
|
|
||||||
"Are you sure you want to reset the timer to 00:00:00?",
|
|
||||||
QMessageBox::Yes | QMessageBox::No);
|
|
||||||
|
|
||||||
if (reply == QMessageBox::Yes) {
|
|
||||||
m_service->resetSessionTimer();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::onOverlayEndSessionClicked()
|
|
||||||
{
|
|
||||||
on_endSessionButton_clicked();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::updateActiveTab()
|
|
||||||
{
|
|
||||||
auto activeSession = m_service->activeSession();
|
|
||||||
if (!activeSession) return;
|
|
||||||
|
|
||||||
m_updatingActiveFields = true;
|
|
||||||
|
|
||||||
ui->oneLineEdit->setText(activeSession->oneliner);
|
|
||||||
ui->elapsedLabel->setText(formatDuration(m_service->getElapsedMs()));
|
|
||||||
|
|
||||||
ui->createdLabel->setText(activeSession->createdAt.toString("yyyy-MM-dd hh:mm:ss"));
|
|
||||||
ui->modifiedLabel->setText(activeSession->lastModifiedAt.toString("yyyy-MM-dd hh:mm:ss"));
|
|
||||||
ui->contentTextEdit->setPlainText(activeSession->content);
|
|
||||||
|
|
||||||
m_updatingActiveFields = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString MainWindow::formatDuration(int ms) const
|
|
||||||
{
|
|
||||||
int seconds = ms / 1000;
|
|
||||||
int hours = seconds / 3600;
|
|
||||||
int minutes = (seconds % 3600) / 60;
|
|
||||||
int secs = seconds % 60;
|
|
||||||
|
|
||||||
return QString("%1:%2:%3")
|
|
||||||
.arg(hours, 2, 10, QChar('0'))
|
|
||||||
.arg(minutes, 2, 10, QChar('0'))
|
|
||||||
.arg(secs, 2, 10, QChar('0'));
|
|
||||||
}
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
#ifndef MAINWINDOW_H
|
|
||||||
#define MAINWINDOW_H
|
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
#include <QMainWindow>
|
|
||||||
|
|
||||||
class Service;
|
|
||||||
class SessionsListModel;
|
|
||||||
class FocusOverlay;
|
|
||||||
class QTimer;
|
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
|
||||||
QT_END_NAMESPACE
|
|
||||||
|
|
||||||
namespace Ui {
|
|
||||||
class MainWindow;
|
|
||||||
}
|
|
||||||
|
|
||||||
class MainWindow : public QMainWindow {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
MainWindow(QWidget *parent = nullptr);
|
|
||||||
~MainWindow();
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void on_selectVaultButton_clicked();
|
|
||||||
void on_newSessionButton_clicked();
|
|
||||||
void on_startSessionButton_clicked();
|
|
||||||
void on_endSessionButton_clicked();
|
|
||||||
|
|
||||||
// Service signal handlers
|
|
||||||
void onActiveSessionChanged();
|
|
||||||
void onSessionTimerTicked(int elapsedMs);
|
|
||||||
|
|
||||||
// Active tab field editing
|
|
||||||
void onActiveOnelinerChanged();
|
|
||||||
void onActiveContentChanged();
|
|
||||||
|
|
||||||
// Overlay handlers
|
|
||||||
void onOverlayResetClicked();
|
|
||||||
void onOverlayEndSessionClicked();
|
|
||||||
|
|
||||||
private:
|
|
||||||
Ui::MainWindow *ui;
|
|
||||||
Service *m_service;
|
|
||||||
SessionsListModel *m_listModel;
|
|
||||||
FocusOverlay *m_focusOverlay;
|
|
||||||
|
|
||||||
bool m_updatingActiveFields;
|
|
||||||
|
|
||||||
void updateActiveTab();
|
|
||||||
QString formatDuration(int ms) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // MAINWINDOW_H
|
|
||||||
-289
@@ -1,289 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<ui version="4.0">
|
|
||||||
<class>MainWindow</class>
|
|
||||||
<widget class="QMainWindow" name="MainWindow">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>0</x>
|
|
||||||
<y>0</y>
|
|
||||||
<width>400</width>
|
|
||||||
<height>600</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="windowTitle">
|
|
||||||
<string>MainWindow</string>
|
|
||||||
</property>
|
|
||||||
<widget class="QWidget" name="centralwidget">
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
|
||||||
<item>
|
|
||||||
<widget class="QTabWidget" name="tabWidget">
|
|
||||||
<property name="currentIndex">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<widget class="QWidget" name="tab">
|
|
||||||
<attribute name="title">
|
|
||||||
<string>Settings</string>
|
|
||||||
</attribute>
|
|
||||||
<widget class="QLabel" name="vaultLabel">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>80</x>
|
|
||||||
<y>210</y>
|
|
||||||
<width>221</width>
|
|
||||||
<height>16</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Select a folder</string>
|
|
||||||
</property>
|
|
||||||
<property name="alignment">
|
|
||||||
<set>Qt::AlignmentFlag::AlignCenter</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
<widget class="QPushButton" name="selectVaultButton">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>130</x>
|
|
||||||
<y>240</y>
|
|
||||||
<width>121</width>
|
|
||||||
<height>32</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Select vault</string>
|
|
||||||
</property>
|
|
||||||
<property name="icon">
|
|
||||||
<iconset theme="QIcon::ThemeIcon::DocumentOpen"/>
|
|
||||||
</property>
|
|
||||||
<property name="default">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</widget>
|
|
||||||
<widget class="QWidget" name="tab_2">
|
|
||||||
<attribute name="title">
|
|
||||||
<string>Sessions</string>
|
|
||||||
</attribute>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
|
||||||
<item>
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="newSessionButton">
|
|
||||||
<property name="text">
|
|
||||||
<string>New Session</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="startSessionButton">
|
|
||||||
<property name="text">
|
|
||||||
<string>Start Selected</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<spacer name="horizontalSpacer">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Orientation::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>40</width>
|
|
||||||
<height>20</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QListView" name="listView"/>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<widget class="QWidget" name="tab_3">
|
|
||||||
<attribute name="title">
|
|
||||||
<string>Active</string>
|
|
||||||
</attribute>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
|
||||||
<item>
|
|
||||||
<widget class="QStackedWidget" name="activeStackedWidget">
|
|
||||||
<property name="currentIndex">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<widget class="QWidget" name="noSessionPage">
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
|
||||||
<item>
|
|
||||||
<spacer name="verticalSpacer">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Orientation::Vertical</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>20</width>
|
|
||||||
<height>40</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="noSessionLabel">
|
|
||||||
<property name="text">
|
|
||||||
<string>No session running. Start a session to begin.</string>
|
|
||||||
</property>
|
|
||||||
<property name="alignment">
|
|
||||||
<set>Qt::AlignmentFlag::AlignCenter</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<spacer name="verticalSpacer_2">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Orientation::Vertical</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>20</width>
|
|
||||||
<height>40</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<widget class="QWidget" name="activeSessionPage">
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
|
||||||
<item>
|
|
||||||
<widget class="QScrollArea" name="scrollArea">
|
|
||||||
<property name="widgetResizable">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<widget class="QWidget" name="scrollAreaWidgetContents">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>0</x>
|
|
||||||
<y>0</y>
|
|
||||||
<width>190</width>
|
|
||||||
<height>244</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
|
||||||
<item>
|
|
||||||
<layout class="QFormLayout" name="formLayout">
|
|
||||||
<item row="0" column="0">
|
|
||||||
<widget class="QLabel" name="label">
|
|
||||||
<property name="text">
|
|
||||||
<string>Oneliner:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="1">
|
|
||||||
<widget class="QLineEdit" name="oneLineEdit"/>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QLabel" name="label_2">
|
|
||||||
<property name="text">
|
|
||||||
<string>Elapsed Time:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="1">
|
|
||||||
<widget class="QLabel" name="elapsedLabel">
|
|
||||||
<property name="text">
|
|
||||||
<string>00:00:00</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="0">
|
|
||||||
<widget class="QLabel" name="label_4">
|
|
||||||
<property name="text">
|
|
||||||
<string>Created:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="1">
|
|
||||||
<widget class="QLabel" name="createdLabel">
|
|
||||||
<property name="text">
|
|
||||||
<string>-</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="0">
|
|
||||||
<widget class="QLabel" name="label_5">
|
|
||||||
<property name="text">
|
|
||||||
<string>Modified:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="1">
|
|
||||||
<widget class="QLabel" name="modifiedLabel">
|
|
||||||
<property name="text">
|
|
||||||
<string>-</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="0">
|
|
||||||
<widget class="QLabel" name="label_6">
|
|
||||||
<property name="text">
|
|
||||||
<string>Content:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="1">
|
|
||||||
<widget class="QTextEdit" name="contentTextEdit">
|
|
||||||
<property name="placeholderText">
|
|
||||||
<string>Add notes, context, or anything related to this session...</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<spacer name="verticalSpacer_3">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Orientation::Vertical</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>20</width>
|
|
||||||
<height>40</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="endSessionButton">
|
|
||||||
<property name="text">
|
|
||||||
<string>End Session</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<widget class="QMenuBar" name="menubar">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>0</x>
|
|
||||||
<y>0</y>
|
|
||||||
<width>400</width>
|
|
||||||
<height>30</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
<widget class="QStatusBar" name="statusbar"/>
|
|
||||||
</widget>
|
|
||||||
<resources/>
|
|
||||||
<connections/>
|
|
||||||
</ui>
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
#include "namegenerator.h"
|
|
||||||
|
|
||||||
QString generate() {
|
|
||||||
return QString("generated-name-placeholder");
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
#ifndef NAMEGENERATOR_H
|
|
||||||
#define NAMEGENERATOR_H
|
|
||||||
|
|
||||||
#include <QString>
|
|
||||||
|
|
||||||
QString generate();
|
|
||||||
|
|
||||||
#endif //NAMEGENERATOR_H
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
#!/bin/bash -e
|
|
||||||
|
|
||||||
BUILD_DIR=build
|
|
||||||
|
|
||||||
if [ ! -d "$BUILD_DIR" ]; then
|
|
||||||
cmake -B$BUILD_DIR -S. -GNinja \
|
|
||||||
-DCMAKE_BUILD_TYPE=Debug \
|
|
||||||
-DCMAKE_CXX_FLAGS="-Wall -Wextra" \
|
|
||||||
-DCMAKE_PREFIX_PATH="$HOME/Qt/6.8.6/macos" \
|
|
||||||
-DCMAKE_COLOR_DIAGNOSTICS=ON \
|
|
||||||
-DCMAKE_CXX_FLAGS_INIT="-DQT_QML_DEBUG"
|
|
||||||
fi
|
|
||||||
|
|
||||||
cmake --build $BUILD_DIR --target all
|
|
||||||
|
|
||||||
$BUILD_DIR/adhd.app/Contents/MacOS/adhd
|
|
||||||
-349
@@ -1,349 +0,0 @@
|
|||||||
#include "service.h"
|
|
||||||
#include <QDir>
|
|
||||||
#include <QFileInfoList>
|
|
||||||
#include <QUuid>
|
|
||||||
#include <QFile>
|
|
||||||
|
|
||||||
bool Session::isComplete() const {
|
|
||||||
return result != UNSPECIFIED;
|
|
||||||
}
|
|
||||||
|
|
||||||
Service::Service(QObject *parent)
|
|
||||||
: QObject(parent),
|
|
||||||
m_tickTimer(new QTimer(this))
|
|
||||||
{
|
|
||||||
m_tickTimer->setInterval(1000); // Fire every second
|
|
||||||
connect(m_tickTimer, &QTimer::timeout, this, &Service::onTickTimerFired);
|
|
||||||
}
|
|
||||||
|
|
||||||
Service::~Service() {}
|
|
||||||
|
|
||||||
QString Service::vaultDirectory() const {
|
|
||||||
return m_vaultDirectory;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Service::sessionCount() const {
|
|
||||||
return m_sessions.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
int Service::completedSessionCount() const {
|
|
||||||
int count = 0;
|
|
||||||
for (const Session &session : m_sessions) {
|
|
||||||
if (session.isComplete()) {
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Service::totalWins() const {
|
|
||||||
int count = 0;
|
|
||||||
for (const Session &session : m_sessions) {
|
|
||||||
if (session.result == Session::WIN) {
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Service::totalLosses() const {
|
|
||||||
int count = 0;
|
|
||||||
for (const Session &session : m_sessions) {
|
|
||||||
if (session.result == Session::LOSS) {
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Service::totalNeutrals() const {
|
|
||||||
int count = 0;
|
|
||||||
for (const Session &session : m_sessions) {
|
|
||||||
if (session.result == Session::NEUTRAL) {
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
QList<Session> Service::sessions() const {
|
|
||||||
return m_sessions;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Service::setVaultDirectory(const QString &path) {
|
|
||||||
m_sessions.clear();
|
|
||||||
|
|
||||||
qDebug() << "Setting vault directory to: " << path;
|
|
||||||
|
|
||||||
QDir dir = QDir(path);
|
|
||||||
if (!dir.exists()) {
|
|
||||||
qWarning() << "Vault directory does not exist";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_vaultDirectory = path;
|
|
||||||
|
|
||||||
dir.setFilter(QDir::Files);
|
|
||||||
dir.setSorting(QDir::Time);
|
|
||||||
|
|
||||||
QFileInfoList list = dir.entryInfoList();
|
|
||||||
for (int i = 0; i < list.size(); ++i) {
|
|
||||||
QFileInfo fileInfo = list.at(i);
|
|
||||||
|
|
||||||
if (fileInfo.completeSuffix() != QStringLiteral("md")) {
|
|
||||||
qWarning() << "Skipping invalid file format: " << fileInfo.completeSuffix();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
qDebug() << "Parsing file: " << fileInfo.absoluteFilePath();
|
|
||||||
std::optional<Session> session = parseFile(fileInfo);
|
|
||||||
if (session) {
|
|
||||||
m_sessions.append(*session);
|
|
||||||
} else {
|
|
||||||
qWarning() << "Failed to parse session file: " << fileInfo.absoluteFilePath();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
emit sessionsChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
Session Service::createSession(const QString &oneliner, const QString &content) {
|
|
||||||
assert(!m_vaultDirectory.isEmpty() && "Vault directory must be set before creating sessions");
|
|
||||||
|
|
||||||
QString uuid = QUuid::createUuid().toString(QUuid::WithoutBraces);
|
|
||||||
|
|
||||||
Session session = {};
|
|
||||||
session.id = uuid;
|
|
||||||
session.oneliner = oneliner;
|
|
||||||
session.durationMs = 0;
|
|
||||||
session.content = content;
|
|
||||||
session.result = Session::UNSPECIFIED;
|
|
||||||
session.createdAt = QDateTime::currentDateTime();
|
|
||||||
session.lastModifiedAt = QDateTime::currentDateTime();
|
|
||||||
|
|
||||||
overwriteSessionFile(session);
|
|
||||||
|
|
||||||
m_sessions.prepend(session);
|
|
||||||
emit sessionsChanged();
|
|
||||||
|
|
||||||
return session;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Service::updateSession(const Session &session) {
|
|
||||||
overwriteSessionFile(session);
|
|
||||||
for (int i = 0; i < m_sessions.size(); ++i) {
|
|
||||||
if (m_sessions[i].id == session.id) {
|
|
||||||
m_sessions[i] = session;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
emit sessionsChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Service::deleteSession(const QString &sessionId) {
|
|
||||||
QDir dir = QDir(m_vaultDirectory);
|
|
||||||
QString filePath = dir.filePath(sessionId + ".md");
|
|
||||||
QFile file = QFile(filePath);
|
|
||||||
if (!file.remove()) {
|
|
||||||
qWarning() << "Failed to delete session file: " << filePath;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < m_sessions.size(); ++i) {
|
|
||||||
if (m_sessions[i].id == sessionId) {
|
|
||||||
m_sessions.removeAt(i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
emit sessionsChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<Session> Service::parseFile(const QFileInfo &fileInfo) {
|
|
||||||
QString path = fileInfo.absoluteFilePath();
|
|
||||||
QFile file = QFile(path);
|
|
||||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
Session session = {};
|
|
||||||
session.id = fileInfo.baseName(); // Get filename without extension
|
|
||||||
session.content = "";
|
|
||||||
session.oneliner = "";
|
|
||||||
session.durationMs = 0;
|
|
||||||
session.result = Session::UNSPECIFIED;
|
|
||||||
session.createdAt = fileInfo.birthTime();
|
|
||||||
session.lastModifiedAt = fileInfo.lastModified();
|
|
||||||
|
|
||||||
QTextStream in(&file);
|
|
||||||
int separatorCounts = 0;
|
|
||||||
while (!in.atEnd()) {
|
|
||||||
QString line = in.readLine();
|
|
||||||
// qDebug() << "Reading line: " << line;
|
|
||||||
|
|
||||||
if (separatorCounts >= 2) {
|
|
||||||
session.content += line + '\n';
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (line[0].toLatin1()) {
|
|
||||||
case '-':
|
|
||||||
separatorCounts++;
|
|
||||||
continue;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// parse each key value pair
|
|
||||||
QStringList parts = line.split(':');
|
|
||||||
if (parts.size() != 2) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
QString key = parts[0].trimmed();
|
|
||||||
QString value = parts[1].trimmed();
|
|
||||||
if (key == "Oneliner") {
|
|
||||||
session.oneliner = value;
|
|
||||||
continue;
|
|
||||||
} else if (key == "DurationMs") {
|
|
||||||
session.durationMs = value.toInt();
|
|
||||||
continue;
|
|
||||||
} else if (key == "Result") {
|
|
||||||
session.result = parseResult(value);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
qDebug() << "Parsed oneliner: " << session.oneliner;
|
|
||||||
qDebug() << "Parsed durationMs: " << session.durationMs;
|
|
||||||
qDebug() << "Parsed result: " << static_cast<int>(session.result);
|
|
||||||
qDebug() << "Parsed content: " << session.content;
|
|
||||||
qDebug() << "Created at: " << session.createdAt;
|
|
||||||
qDebug() << "Last modified at: " << session.lastModifiedAt;
|
|
||||||
|
|
||||||
file.close();
|
|
||||||
|
|
||||||
return session;
|
|
||||||
}
|
|
||||||
|
|
||||||
Session::Result Service::parseResult(const QString &resultStr) {
|
|
||||||
if (resultStr == "Win") {
|
|
||||||
return Session::WIN;
|
|
||||||
} else if (resultStr == "Loss") {
|
|
||||||
return Session::LOSS;
|
|
||||||
} else if (resultStr == "Neutral") {
|
|
||||||
return Session::NEUTRAL;
|
|
||||||
} else {
|
|
||||||
return Session::UNSPECIFIED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Service::overwriteSessionFile(const Session &session)
|
|
||||||
{
|
|
||||||
// rewrites the entire file
|
|
||||||
QDir dir = QDir(m_vaultDirectory);
|
|
||||||
QString filePath = dir.filePath(session.id + ".md");
|
|
||||||
QFile file = QFile(filePath);
|
|
||||||
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
|
||||||
qWarning() << "Failed to update session file: " << filePath;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QTextStream out(&file);
|
|
||||||
out << "---\n";
|
|
||||||
out << "Oneliner: " << session.oneliner << "\n";
|
|
||||||
out << "DurationMs: " << session.durationMs << "\n";
|
|
||||||
QString resultStr;
|
|
||||||
switch (session.result) {
|
|
||||||
case Session::WIN:
|
|
||||||
resultStr = "Win";
|
|
||||||
break;
|
|
||||||
case Session::LOSS:
|
|
||||||
resultStr = "Loss";
|
|
||||||
break;
|
|
||||||
case Session::NEUTRAL:
|
|
||||||
resultStr = "Neutral";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
resultStr = "";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!resultStr.isEmpty()) {
|
|
||||||
out << "Result: " << resultStr << "\n";
|
|
||||||
}
|
|
||||||
out << "---\n";
|
|
||||||
out << session.content << "\n";
|
|
||||||
file.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Session lifecycle methods
|
|
||||||
|
|
||||||
void Service::startSession(const Session &session) {
|
|
||||||
if (m_activeSession.has_value()) {
|
|
||||||
qWarning() << "A session is already active. End it before starting a new one.";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_activeSession = session;
|
|
||||||
m_sessionTimer.start();
|
|
||||||
m_tickTimer->start();
|
|
||||||
|
|
||||||
emit activeSessionChanged();
|
|
||||||
emit sessionTimerTicked(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Service::updateActiveSession(const Session &session) {
|
|
||||||
if (!m_activeSession.has_value()) {
|
|
||||||
qWarning() << "No active session to update.";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_activeSession = session;
|
|
||||||
// Don't emit activeSessionChanged - just update the session data
|
|
||||||
// Timer keeps running
|
|
||||||
}
|
|
||||||
|
|
||||||
int Service::getElapsedMs() const {
|
|
||||||
if (!m_activeSession) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return m_sessionTimer.elapsed();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Service::resetSessionTimer() {
|
|
||||||
if (!m_activeSession) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_sessionTimer.restart();
|
|
||||||
emit sessionTimerTicked(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Service::endSession(Session::Result result) {
|
|
||||||
if (!m_activeSession) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update session with final values
|
|
||||||
Session updated = *m_activeSession;
|
|
||||||
updated.durationMs = getElapsedMs();
|
|
||||||
updated.result = result;
|
|
||||||
updated.lastModifiedAt = QDateTime::currentDateTime();
|
|
||||||
|
|
||||||
// Save to file and update in list
|
|
||||||
updateSession(updated);
|
|
||||||
|
|
||||||
// Clear active state
|
|
||||||
m_activeSession.reset();
|
|
||||||
m_tickTimer->stop();
|
|
||||||
|
|
||||||
emit activeSessionChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<Session> Service::activeSession() const {
|
|
||||||
return m_activeSession;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Service::onTickTimerFired() {
|
|
||||||
if (m_activeSession) {
|
|
||||||
emit sessionTimerTicked(getElapsedMs());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,104 +0,0 @@
|
|||||||
#ifndef SERVICE_H
|
|
||||||
#define SERVICE_H
|
|
||||||
|
|
||||||
#include <QList>
|
|
||||||
#include <QObject>
|
|
||||||
#include <QDateTime>
|
|
||||||
#include <QString>
|
|
||||||
#include <QFileInfo>
|
|
||||||
#include <QElapsedTimer>
|
|
||||||
#include <QTimer>
|
|
||||||
#include <optional>
|
|
||||||
|
|
||||||
struct Session
|
|
||||||
{
|
|
||||||
enum Result {
|
|
||||||
UNSPECIFIED = 0,
|
|
||||||
WIN,
|
|
||||||
LOSS,
|
|
||||||
NEUTRAL
|
|
||||||
};
|
|
||||||
// Becomes the file name
|
|
||||||
QString id;
|
|
||||||
// Stored in the frontmatter under 'Oneliner' key
|
|
||||||
QString oneliner;
|
|
||||||
// Stored in the frontmatter
|
|
||||||
int durationMs;
|
|
||||||
// After the --- onwards, serves as general scratchpad
|
|
||||||
QString content;
|
|
||||||
// Stored in the frontmatter under 'Result' key
|
|
||||||
Result result;
|
|
||||||
|
|
||||||
QDateTime lastModifiedAt;
|
|
||||||
QDateTime createdAt;
|
|
||||||
|
|
||||||
bool isComplete() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Service : public QObject {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit Service(QObject *parent = nullptr);
|
|
||||||
~Service();
|
|
||||||
|
|
||||||
QList<Session> sessions() const;
|
|
||||||
QString vaultDirectory() const;
|
|
||||||
|
|
||||||
int sessionCount() const;
|
|
||||||
int completedSessionCount() const;
|
|
||||||
int totalWins() const;
|
|
||||||
int totalLosses() const;
|
|
||||||
int totalNeutrals() const;
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
/// @brief sets the directory from which to read/write sessions
|
|
||||||
/// Fails silently if not a valid path
|
|
||||||
/// Loads sessions from this path
|
|
||||||
void setVaultDirectory(const QString &path);
|
|
||||||
|
|
||||||
/// @brief creates the session and stores in sessions list
|
|
||||||
/// @returns the newly created session
|
|
||||||
Session createSession(const QString &oneliner, const QString &content);
|
|
||||||
|
|
||||||
/// @brief updates the session
|
|
||||||
/// Updates session in the sessions list, and the file associated
|
|
||||||
void updateSession(const Session &session);
|
|
||||||
|
|
||||||
void deleteSession(const QString &sessionId);
|
|
||||||
|
|
||||||
// Session lifecycle methods
|
|
||||||
void startSession(const Session &session);
|
|
||||||
void updateActiveSession(const Session &session); // Update without restarting timer
|
|
||||||
int getElapsedMs() const;
|
|
||||||
void resetSessionTimer();
|
|
||||||
void endSession(Session::Result result);
|
|
||||||
std::optional<Session> activeSession() const;
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void sessionsChanged();
|
|
||||||
void activeSessionChanged();
|
|
||||||
void sessionTimerTicked(int elapsedMs);
|
|
||||||
|
|
||||||
private:
|
|
||||||
QString m_vaultDirectory;
|
|
||||||
QList<Session> m_sessions;
|
|
||||||
|
|
||||||
// Active session tracking
|
|
||||||
std::optional<Session> m_activeSession;
|
|
||||||
QElapsedTimer m_sessionTimer;
|
|
||||||
QTimer *m_tickTimer;
|
|
||||||
|
|
||||||
/// @returns null Session if not a valid session markdown document
|
|
||||||
std::optional<Session> parseFile(const QFileInfo &fileInfo);
|
|
||||||
|
|
||||||
Session::Result parseResult(const QString &resultStr);
|
|
||||||
void overwriteSessionFile(const Session &session);
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void onTickTimerFired();
|
|
||||||
};
|
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(Session)
|
|
||||||
|
|
||||||
#endif //SERVICE_H
|
|
||||||
@@ -1,139 +0,0 @@
|
|||||||
#include "sessionitemdelegate.h"
|
|
||||||
#include "service.h"
|
|
||||||
#include <QPainter>
|
|
||||||
#include <QDateTime>
|
|
||||||
|
|
||||||
SessionItemDelegate::SessionItemDelegate(QObject *parent)
|
|
||||||
: QStyledItemDelegate(parent)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void SessionItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
|
|
||||||
const QModelIndex &index) const
|
|
||||||
{
|
|
||||||
if (!index.isValid()) {
|
|
||||||
QStyledItemDelegate::paint(painter, option, index);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
painter->save();
|
|
||||||
|
|
||||||
// Get session data
|
|
||||||
Session session = index.data(Qt::UserRole).value<Session>();
|
|
||||||
QString oneliner = session.oneliner;
|
|
||||||
|
|
||||||
// Format duration
|
|
||||||
int seconds = session.durationMs / 1000;
|
|
||||||
int hours = seconds / 3600;
|
|
||||||
int minutes = (seconds % 3600) / 60;
|
|
||||||
int secs = seconds % 60;
|
|
||||||
QString durationStr = QString("%1:%2:%3")
|
|
||||||
.arg(hours, 2, 10, QChar('0'))
|
|
||||||
.arg(minutes, 2, 10, QChar('0'))
|
|
||||||
.arg(secs, 2, 10, QChar('0'));
|
|
||||||
|
|
||||||
// Format result
|
|
||||||
QString resultStr;
|
|
||||||
switch (session.result) {
|
|
||||||
case Session::WIN:
|
|
||||||
resultStr = "WIN";
|
|
||||||
break;
|
|
||||||
case Session::LOSS:
|
|
||||||
resultStr = "LOSS";
|
|
||||||
break;
|
|
||||||
case Session::NEUTRAL:
|
|
||||||
resultStr = "NEUTRAL";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
resultStr = "UNSPECIFIED";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Format relative time
|
|
||||||
QDateTime now = QDateTime::currentDateTime();
|
|
||||||
qint64 secsSinceModified = session.lastModifiedAt.secsTo(now);
|
|
||||||
QString relativeTime;
|
|
||||||
if (secsSinceModified < 60) {
|
|
||||||
relativeTime = "just now";
|
|
||||||
} else if (secsSinceModified < 3600) {
|
|
||||||
relativeTime = QString("%1 min ago").arg(secsSinceModified / 60);
|
|
||||||
} else if (secsSinceModified < 86400) {
|
|
||||||
relativeTime = QString("%1 hr ago").arg(secsSinceModified / 3600);
|
|
||||||
} else {
|
|
||||||
relativeTime = QString("%1 days ago").arg(secsSinceModified / 86400);
|
|
||||||
}
|
|
||||||
|
|
||||||
QString metadata = QString("Duration: %1 | Result: %2 | Modified: %3")
|
|
||||||
.arg(durationStr)
|
|
||||||
.arg(resultStr)
|
|
||||||
.arg(relativeTime);
|
|
||||||
|
|
||||||
// Draw background
|
|
||||||
if (option.state & QStyle::State_Selected) {
|
|
||||||
painter->fillRect(option.rect, option.palette.highlight());
|
|
||||||
} else {
|
|
||||||
painter->fillRect(option.rect, option.palette.base());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Draw result indicator bar on the left
|
|
||||||
QColor indicatorColor;
|
|
||||||
switch (session.result) {
|
|
||||||
case Session::WIN:
|
|
||||||
indicatorColor = QColor(46, 204, 113); // Green
|
|
||||||
break;
|
|
||||||
case Session::LOSS:
|
|
||||||
indicatorColor = QColor(231, 76, 60); // Red
|
|
||||||
break;
|
|
||||||
case Session::NEUTRAL:
|
|
||||||
indicatorColor = QColor(149, 165, 166); // Gray
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
indicatorColor = QColor(0, 0, 0, 0); // Transparent
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (session.result != Session::UNSPECIFIED) {
|
|
||||||
QRect indicatorRect(option.rect.left(), option.rect.top(), 4, option.rect.height());
|
|
||||||
painter->fillRect(indicatorRect, indicatorColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set up text drawing
|
|
||||||
QRect textRect = option.rect.adjusted(10, 5, -5, -5);
|
|
||||||
QColor textColor = (option.state & QStyle::State_Selected)
|
|
||||||
? option.palette.highlightedText().color()
|
|
||||||
: option.palette.text().color();
|
|
||||||
|
|
||||||
// Draw oneliner (bold, larger font)
|
|
||||||
painter->setPen(textColor);
|
|
||||||
QFont onelineFont = option.font;
|
|
||||||
onelineFont.setPointSize(14);
|
|
||||||
onelineFont.setBold(true);
|
|
||||||
painter->setFont(onelineFont);
|
|
||||||
|
|
||||||
QRect onelineRect = textRect;
|
|
||||||
onelineRect.setHeight(24);
|
|
||||||
QString elidedOneliner = painter->fontMetrics().elidedText(oneliner, Qt::ElideRight, onelineRect.width());
|
|
||||||
painter->drawText(onelineRect, Qt::AlignLeft | Qt::AlignVCenter, elidedOneliner);
|
|
||||||
|
|
||||||
// Draw metadata (smaller font, lighter color)
|
|
||||||
QFont metadataFont = option.font;
|
|
||||||
metadataFont.setPointSize(11);
|
|
||||||
painter->setFont(metadataFont);
|
|
||||||
|
|
||||||
QColor metadataColor = textColor;
|
|
||||||
metadataColor.setAlpha(180); // Make it slightly transparent
|
|
||||||
painter->setPen(metadataColor);
|
|
||||||
|
|
||||||
QRect metadataRect = textRect;
|
|
||||||
metadataRect.setTop(onelineRect.bottom() + 2);
|
|
||||||
QString elidedMetadata = painter->fontMetrics().elidedText(metadata, Qt::ElideRight, metadataRect.width());
|
|
||||||
painter->drawText(metadataRect, Qt::AlignLeft | Qt::AlignVCenter, elidedMetadata);
|
|
||||||
|
|
||||||
painter->restore();
|
|
||||||
}
|
|
||||||
|
|
||||||
QSize SessionItemDelegate::sizeHint(const QStyleOptionViewItem &option,
|
|
||||||
const QModelIndex &index) const
|
|
||||||
{
|
|
||||||
return QSize(option.rect.width(), 65);
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
#ifndef SESSIONITEMDELEGATE_H
|
|
||||||
#define SESSIONITEMDELEGATE_H
|
|
||||||
|
|
||||||
#include <QStyledItemDelegate>
|
|
||||||
|
|
||||||
class SessionItemDelegate : public QStyledItemDelegate
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit SessionItemDelegate(QObject *parent = nullptr);
|
|
||||||
|
|
||||||
void paint(QPainter *painter, const QStyleOptionViewItem &option,
|
|
||||||
const QModelIndex &index) const override;
|
|
||||||
|
|
||||||
QSize sizeHint(const QStyleOptionViewItem &option,
|
|
||||||
const QModelIndex &index) const override;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // SESSIONITEMDELEGATE_H
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
#include "sessionslistmodel.h"
|
|
||||||
|
|
||||||
SessionsListModel::SessionsListModel(Service *service, QObject *parent)
|
|
||||||
: QAbstractListModel{parent}, m_service(service)
|
|
||||||
{
|
|
||||||
connect(m_service, &Service::sessionsChanged, this, [this]() {
|
|
||||||
beginResetModel();
|
|
||||||
endResetModel();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
int SessionsListModel::rowCount(const QModelIndex &parent) const {
|
|
||||||
return m_service->sessions().size();
|
|
||||||
}
|
|
||||||
|
|
||||||
int SessionsListModel::columnCount(const QModelIndex &parent) const {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariant SessionsListModel::data(const QModelIndex &index, int role) const {
|
|
||||||
if (index.row() < 0 || index.row() >= rowCount()) {
|
|
||||||
return QVariant();
|
|
||||||
} else if (!index.isValid()) {
|
|
||||||
return QVariant();
|
|
||||||
}
|
|
||||||
|
|
||||||
const Session session = m_service->sessions().at(index.row());
|
|
||||||
switch (role) {
|
|
||||||
case Qt::DisplayRole:
|
|
||||||
// Simple display for fallback - delegate will handle rich rendering
|
|
||||||
return session.oneliner;
|
|
||||||
case Qt::UserRole:
|
|
||||||
// Store full session object for delegate access
|
|
||||||
return QVariant::fromValue(session);
|
|
||||||
default:
|
|
||||||
return QVariant();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Session SessionsListModel::getSessionByIndex(const QModelIndex &index) const {
|
|
||||||
if (!index.isValid() || index.row() < 0 || index.row() >= rowCount()) {
|
|
||||||
return Session(); // Return default-constructed session
|
|
||||||
}
|
|
||||||
return m_service->sessions().at(index.row());
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
#ifndef SESSIONSLISTMODEL_H
|
|
||||||
#define SESSIONSLISTMODEL_H
|
|
||||||
|
|
||||||
#include <QAbstractListModel>
|
|
||||||
#include <QObject>
|
|
||||||
#include "service.h"
|
|
||||||
|
|
||||||
class SessionsListModel : public QAbstractListModel
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
explicit SessionsListModel(Service *service, QObject *parent = nullptr);
|
|
||||||
|
|
||||||
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
|
|
||||||
int columnCount(const QModelIndex& parent = QModelIndex()) const override;
|
|
||||||
QVariant data(const QModelIndex &index, int role) const override;
|
|
||||||
|
|
||||||
Session getSessionByIndex(const QModelIndex &index) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
Service *m_service;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // SESSIONSLISTMODEL_H
|
|
||||||
+182
@@ -0,0 +1,182 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#define RAYGUI_IMPLEMENTATION
|
||||||
|
#include <raygui.h>
|
||||||
|
#include <raylib.h>
|
||||||
|
#include "window_state.h"
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
#define WINDOW_HEIGHT 700
|
||||||
|
#define WINDOW_WIDTH 550
|
||||||
|
#define OVERLAY_HEIGHT 400
|
||||||
|
#define OVERLAY_WIDTH 700
|
||||||
|
|
||||||
|
#define NUM_WEEKS 12
|
||||||
|
|
||||||
|
void switch_mode(Mode mode) {
|
||||||
|
set_mode(mode);
|
||||||
|
|
||||||
|
switch (mode) {
|
||||||
|
case WINDOW:
|
||||||
|
SetWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT);
|
||||||
|
break;
|
||||||
|
case OVERLAY:
|
||||||
|
SetWindowSize(OVERLAY_WIDTH, OVERLAY_HEIGHT);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct cell_t {
|
||||||
|
int row;
|
||||||
|
int column;
|
||||||
|
} Cell;
|
||||||
|
|
||||||
|
int cell_number(Cell c) {
|
||||||
|
return c.row + 1 + (c.column * 7);
|
||||||
|
}
|
||||||
|
|
||||||
|
int distance(Cell a, Cell b) {
|
||||||
|
return cell_number(b) - cell_number(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define CELL_SPACING 10
|
||||||
|
#define CELL_SIZE 20
|
||||||
|
time_t now;
|
||||||
|
struct tm local_time;
|
||||||
|
|
||||||
|
// Returns the time info struct which is a static variable within time.h stdlib
|
||||||
|
struct tm *get_date_days_ago(int days_ago, char *buffer, size_t buffer_size) {
|
||||||
|
time_t raw_time;
|
||||||
|
struct tm *time_info;
|
||||||
|
time(&raw_time);
|
||||||
|
time_info = localtime(&raw_time); // caution: localtime() overwrites the static struct internally as opposed to localtime_r
|
||||||
|
time_info->tm_mday -= days_ago;
|
||||||
|
mktime(time_info);
|
||||||
|
|
||||||
|
strftime(buffer, buffer_size, "%B %d", time_info);
|
||||||
|
|
||||||
|
return time_info;
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw_graph(int x, int y) {
|
||||||
|
GuiEnableTooltip();
|
||||||
|
|
||||||
|
int num_columns = NUM_WEEKS;
|
||||||
|
int num_rows = 7; // days in a week
|
||||||
|
|
||||||
|
int cell_number_today = cell_number((Cell) {local_time.tm_wday, num_columns - 1});
|
||||||
|
|
||||||
|
for (int c = 0; c < num_columns; c++) {
|
||||||
|
for (int r = 0; r < num_rows; r++) {
|
||||||
|
Cell cell = { r, c };
|
||||||
|
int curr_cell_number = cell_number(cell);
|
||||||
|
if (curr_cell_number > cell_number_today) break;
|
||||||
|
|
||||||
|
int days_ago = cell_number_today - curr_cell_number;
|
||||||
|
char tooltip_text[128];
|
||||||
|
struct tm *time = get_date_days_ago(days_ago, tooltip_text, sizeof(tooltip_text));
|
||||||
|
|
||||||
|
U32 result = get_result(time);
|
||||||
|
GuiSetTooltip(tooltip_text);
|
||||||
|
|
||||||
|
// full size of a cell is spacing * 2 + size, and then need to go little more
|
||||||
|
int cell_x = CELL_SPACING + (((CELL_SPACING * 2) + CELL_SIZE) * c);
|
||||||
|
int cell_y = CELL_SPACING + (((CELL_SPACING * 2) + CELL_SIZE) * r);
|
||||||
|
|
||||||
|
if (result) {
|
||||||
|
GuiSetStyle(BUTTON, BASE_COLOR_NORMAL, ColorToInt(GREEN));
|
||||||
|
} else {
|
||||||
|
GuiSetStyle(BUTTON, BASE_COLOR_NORMAL, ColorToInt(BLANK));
|
||||||
|
}
|
||||||
|
if (GuiButton((Rectangle) {cell_x + x, cell_y + y, CELL_SIZE, CELL_SIZE}, " ")) {
|
||||||
|
set_result(time, abs(result - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c == 0 && r == 1) {
|
||||||
|
GuiLabel((Rectangle) {x-5, cell_y + y, 20, 20}, "M");
|
||||||
|
} else if (c==0 && r== 3) {
|
||||||
|
GuiLabel((Rectangle) {x-5, cell_y + y, 20, 20}, "W");
|
||||||
|
} else if (c==0 && r == 5) {
|
||||||
|
GuiLabel((Rectangle) {x-5, cell_y + y, 20, 20}, "F");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GuiDisableTooltip();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool edit_mode = false;
|
||||||
|
|
||||||
|
void render_window() {
|
||||||
|
ClearBackground(RAYWHITE);
|
||||||
|
DrawFPS(WINDOW_WIDTH - 50, 10);
|
||||||
|
|
||||||
|
Rectangle text_box_rect = {(WINDOW_WIDTH / 2) - 200, (WINDOW_HEIGHT / 2) - 200, 400, 50};
|
||||||
|
Vector2 mouse_pos = GetMousePosition();
|
||||||
|
if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) {
|
||||||
|
if (CheckCollisionRecs((Rectangle) {mouse_pos.x, mouse_pos.y, 2, 2}, text_box_rect)) {
|
||||||
|
|
||||||
|
edit_mode = true;
|
||||||
|
} else {
|
||||||
|
edit_mode = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (GuiTextBox(text_box_rect, get_intention(), get_intention_size(), edit_mode)) {
|
||||||
|
switch_mode(OVERLAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
char label[2048];
|
||||||
|
sprintf(label, "%d / %d characters | Hit enter to set", (int) strlen(get_intention()), (int) get_intention_size());
|
||||||
|
GuiLabel((Rectangle){ WINDOW_WIDTH / 2 - 100, (WINDOW_HEIGHT / 2) - 150, 300, 50}, label);
|
||||||
|
|
||||||
|
int graph_y_offset = (WINDOW_HEIGHT / 2) + 50;
|
||||||
|
draw_graph(20, graph_y_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void render_overlay() {
|
||||||
|
ClearBackground(BLANK);
|
||||||
|
DrawFPS(OVERLAY_WIDTH - 50, 10);
|
||||||
|
|
||||||
|
const Rectangle button_rect = {OVERLAY_WIDTH - 100, 10, 100, 25};
|
||||||
|
int active = 0;
|
||||||
|
|
||||||
|
if (GuiToggleSlider(button_rect, "Toggle mode", &active)) {
|
||||||
|
switch_mode(WINDOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
GuiSetStyle(DEFAULT, TEXT_SIZE, 75);
|
||||||
|
GuiSetStyle(DEFAULT, TEXT_WRAP_MODE, TEXT_WRAP_CHAR);
|
||||||
|
GuiSetStyle(LABEL, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER);
|
||||||
|
GuiLabel((Rectangle){0, 0, OVERLAY_WIDTH, OVERLAY_HEIGHT}, get_intention());
|
||||||
|
GuiSetStyle(DEFAULT, TEXT_WRAP_MODE, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
time(&now);
|
||||||
|
localtime_r(&now, &local_time);
|
||||||
|
mktime(&local_time);
|
||||||
|
|
||||||
|
init_window_state();
|
||||||
|
|
||||||
|
printf("Welcome to Flowy.adhd\n");
|
||||||
|
|
||||||
|
InitWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "Flowy.adhd");
|
||||||
|
|
||||||
|
while (!WindowShouldClose()) {
|
||||||
|
BeginDrawing();
|
||||||
|
|
||||||
|
GuiSetStyle(DEFAULT, TEXT_SIZE, 15);
|
||||||
|
|
||||||
|
if (get_mode() == WINDOW) render_window();
|
||||||
|
else render_overlay();
|
||||||
|
|
||||||
|
EndDrawing();
|
||||||
|
}
|
||||||
|
|
||||||
|
CloseWindow();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,231 @@
|
|||||||
|
#include "window_state.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <sqlite3.h>
|
||||||
|
|
||||||
|
struct state *s = NULL;
|
||||||
|
|
||||||
|
#define INTENTION_MAX_SIZE 2048
|
||||||
|
|
||||||
|
typedef struct record_t {
|
||||||
|
char *key;
|
||||||
|
U32 value;
|
||||||
|
} Record;
|
||||||
|
|
||||||
|
struct state {
|
||||||
|
Mode mode;
|
||||||
|
char intention[INTENTION_MAX_SIZE];
|
||||||
|
Record **records; // array of records
|
||||||
|
size_t size_records;
|
||||||
|
size_t capacity_records;
|
||||||
|
};
|
||||||
|
|
||||||
|
static sqlite3 *db = NULL;
|
||||||
|
|
||||||
|
static void db_open() {
|
||||||
|
int r = sqlite3_open("local.sqlite3", &db);
|
||||||
|
if (r == SQLITE_OK) {
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Unable to prepare sqlite db\n");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *sql =
|
||||||
|
"CREATE TABLE IF NOT EXISTS records ("
|
||||||
|
"key TEXT PRIMARY KEY,"
|
||||||
|
"value INT"
|
||||||
|
");"
|
||||||
|
;
|
||||||
|
|
||||||
|
char *err;
|
||||||
|
r = sqlite3_exec(db, sql, NULL, NULL, &err);
|
||||||
|
if (r != SQLITE_OK) {
|
||||||
|
fprintf(stderr, "SQL error during setup: %s\n", err);
|
||||||
|
sqlite3_free(err);
|
||||||
|
sqlite3_close(db);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void db_close() {
|
||||||
|
if (db) {
|
||||||
|
sqlite3_close(db);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int db_get_record_callback(void *ctx, int argc, char *argv[], char **argv_col_name) {
|
||||||
|
Record *rec = calloc(1, sizeof(Record));
|
||||||
|
|
||||||
|
for (int i = 0; i < argc; i++) {
|
||||||
|
if (strcmp(argv_col_name[i], "key") == 0) {
|
||||||
|
rec->key = strdup(argv[i]);
|
||||||
|
} else if (strcmp(argv_col_name[i], "value") == 0) {
|
||||||
|
rec->value = (U32) atoi(argv[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s->size_records >= s->capacity_records) {
|
||||||
|
printf("MAX capacity");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
*(s->records + s->size_records) = rec;
|
||||||
|
s->size_records++;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void db_upsert_record(char *key, U32 value) {
|
||||||
|
sqlite3_stmt *stmt;
|
||||||
|
const char *sql = "INSERT INTO records (key, value) VALUES (?, ?) ON CONFLICT (key) DO UPDATE SET value = ?;";
|
||||||
|
int rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
|
||||||
|
assert(rc == SQLITE_OK);
|
||||||
|
sqlite3_bind_text(stmt, 1, key, -1, SQLITE_STATIC);
|
||||||
|
sqlite3_bind_int(stmt, 2, value);
|
||||||
|
sqlite3_bind_int(stmt, 3, value);
|
||||||
|
|
||||||
|
rc = sqlite3_step(stmt);
|
||||||
|
if (rc != SQLITE_DONE) {
|
||||||
|
printf("Failure in insert: %s\n", sqlite3_errmsg(db));
|
||||||
|
}
|
||||||
|
|
||||||
|
sqlite3_finalize(stmt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void db_get_all_records() {
|
||||||
|
const char *sql = "SELECT key, value FROM records;";
|
||||||
|
int rc = sqlite3_exec(db, sql, db_get_record_callback, NULL, NULL);
|
||||||
|
assert(rc == SQLITE_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_window_state() {
|
||||||
|
s = malloc(sizeof(struct state));
|
||||||
|
s->mode = WINDOW;
|
||||||
|
|
||||||
|
memset(s->intention, 0, sizeof(s->intention));
|
||||||
|
|
||||||
|
s->size_records = 0;
|
||||||
|
s->capacity_records = 1000; //TODO: make dynamic
|
||||||
|
s->records = malloc(sizeof(Record *) * s->capacity_records);
|
||||||
|
|
||||||
|
db_open();
|
||||||
|
db_get_all_records();
|
||||||
|
}
|
||||||
|
|
||||||
|
static Record *append_record(char *key, U32 value) {
|
||||||
|
if (s->size_records >= s->capacity_records) {
|
||||||
|
printf("MAX capacity");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *cpy = strdup(key);
|
||||||
|
|
||||||
|
Record *new_record = malloc(sizeof(Record));
|
||||||
|
new_record->key = cpy;
|
||||||
|
new_record->value = value;
|
||||||
|
|
||||||
|
*(s->records + s->size_records) = new_record;
|
||||||
|
s->size_records++;
|
||||||
|
return new_record;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void upsert_record(char *key, U32 value) {
|
||||||
|
bool found = false;
|
||||||
|
for (int i = 0; i < s->size_records; i++) {
|
||||||
|
Record *rec = *(s->records + i);
|
||||||
|
if (strcmp(rec->key, key) == 0) {
|
||||||
|
found = true;
|
||||||
|
rec->value = value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found) {
|
||||||
|
append_record(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Record *get_record(char *key) {
|
||||||
|
for (int i = 0; i < s->size_records; i++) {
|
||||||
|
Record *rec = *(s->records + i);
|
||||||
|
if (strcmp(rec->key, key) == 0) {
|
||||||
|
return rec;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_records() {
|
||||||
|
for (int i = 0; i < s->size_records; i++) {
|
||||||
|
Record *rec = *(s->records + i);
|
||||||
|
printf("record: %s -> %d\n", rec->key, rec->value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void generate_key(struct tm *time, char *buffer, size_t buffer_size) {
|
||||||
|
snprintf(buffer, buffer_size, "%d", time->tm_yday);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cleanup_window_state() {
|
||||||
|
if (!s) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < s->size_records; i++) {
|
||||||
|
Record *rec = *(s->records + s->size_records);
|
||||||
|
free(rec);
|
||||||
|
}
|
||||||
|
free(s->records);
|
||||||
|
|
||||||
|
free(s);
|
||||||
|
s = NULL;
|
||||||
|
|
||||||
|
db_close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_intention(char *intention) {
|
||||||
|
assert(s);
|
||||||
|
|
||||||
|
strncpy(s->intention, intention, sizeof(s->intention));
|
||||||
|
s->intention[sizeof(s->intention) - 1] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
char *get_intention() {
|
||||||
|
assert(s);
|
||||||
|
return s->intention;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t get_intention_size() {
|
||||||
|
assert(s);
|
||||||
|
return sizeof(s->intention);
|
||||||
|
}
|
||||||
|
|
||||||
|
Mode get_mode() {
|
||||||
|
assert(s);
|
||||||
|
return s->mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_mode(Mode new_mode) {
|
||||||
|
s->mode = new_mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
U32 get_result(struct tm *time) {
|
||||||
|
char key[10];
|
||||||
|
generate_key(time, key, sizeof(key));
|
||||||
|
Record *rec = get_record(key);
|
||||||
|
if (!rec) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rec->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_result(struct tm *time, U32 result) {
|
||||||
|
char key[10];
|
||||||
|
generate_key(time, key, sizeof(key));
|
||||||
|
upsert_record(key, result);
|
||||||
|
db_upsert_record(key, result);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user