diff --git a/.editorconfig b/.editorconfig index 54d8ffe..0388b6f 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,30 +1,30 @@ -root = true - -[*] -charset = utf-8 -end_of_line = lf -insert_final_newline = true -indent_style = space -indent_size = 2 -trim_trailing_whitespace = true - -[*.md] -trim_trailing_whitespace = false - -[*.py] -indent_size = 4 - -[*.rs] -indent_size = 4 - -[*.yml] -indent_size = 2 - -[*.yaml] -indent_size = 2 - -[*.json] -indent_size = 2 - -[*.toml] -indent_size = 2 +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +indent_style = space +indent_size = 2 +trim_trailing_whitespace = true + +[*.md] +trim_trailing_whitespace = false + +[*.py] +indent_size = 4 + +[*.rs] +indent_size = 4 + +[*.yml] +indent_size = 2 + +[*.yaml] +indent_size = 2 + +[*.json] +indent_size = 2 + +[*.toml] +indent_size = 2 diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 30d8ab3..388d8cd 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1 +1 @@ -* @ZFordDev +* @ZFordDev diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index ce4ec41..8a2b69b 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1,2 +1,2 @@ -github: ZFordDev -ko_fi: zforddev +github: ZFordDev +ko_fi: zforddev diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 62998a8..08584e8 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -1,51 +1,51 @@ -name: Bug Report -description: Report a reproducible issue in SchedPlus -labels: [bug] -body: - - type: markdown - attributes: - value: | - Thank you for helping improve SchedPlus! - Please provide as much detail as possible so we can reproduce the issue. - - - type: input - id: version - attributes: - label: SchedPlus Version - placeholder: e.g., 0.1.0, 0.2.0-dev - - - type: input - id: os - attributes: - label: Operating System - placeholder: e.g., Windows 11, Ubuntu 22.04 - - - type: textarea - id: steps - attributes: - label: Steps to Reproduce - description: List each step clearly. - placeholder: | - 1. Open SchedPlus - 2. Add a new task - 3. Save the schedule - 4. Reopen the app and load tasks - 5. Error occurs - - - type: textarea - id: expected - attributes: - label: Expected Behavior - placeholder: Describe what you expected to happen. - - - type: textarea - id: actual - attributes: - label: Actual Behavior - placeholder: Describe what actually happened. - - - type: textarea - id: logs - attributes: - label: Logs / Screenshots (optional) - description: Attach anything helpful. +name: Bug Report +description: Report a reproducible issue in SchedPlus +labels: [bug] +body: + - type: markdown + attributes: + value: | + Thank you for helping improve SchedPlus! + Please provide as much detail as possible so we can reproduce the issue. + + - type: input + id: version + attributes: + label: SchedPlus Version + placeholder: e.g., 0.1.0, 0.2.0-dev + + - type: input + id: os + attributes: + label: Operating System + placeholder: e.g., Windows 11, Ubuntu 22.04 + + - type: textarea + id: steps + attributes: + label: Steps to Reproduce + description: List each step clearly. + placeholder: | + 1. Open SchedPlus + 2. Add a new task + 3. Save the schedule + 4. Reopen the app and load tasks + 5. Error occurs + + - type: textarea + id: expected + attributes: + label: Expected Behavior + placeholder: Describe what you expected to happen. + + - type: textarea + id: actual + attributes: + label: Actual Behavior + placeholder: Describe what actually happened. + + - type: textarea + id: logs + attributes: + label: Logs / Screenshots (optional) + description: Attach anything helpful. diff --git a/.github/ISSUE_TEMPLATE/documentation.yml b/.github/ISSUE_TEMPLATE/documentation.yml index 605d74a..a65563d 100644 --- a/.github/ISSUE_TEMPLATE/documentation.yml +++ b/.github/ISSUE_TEMPLATE/documentation.yml @@ -1,15 +1,15 @@ -name: Documentation Update -description: Suggest improvements to documentation or examples -labels: [documentation] -body: - - type: textarea - id: update - attributes: - label: What needs to be updated? - placeholder: | - Describe the missing, unclear, or incorrect documentation. - Examples: - - A function is undocumented - - A UI mode is unclear - - A screenshot is outdated - - A section needs clarification +name: Documentation Update +description: Suggest improvements to documentation or examples +labels: [documentation] +body: + - type: textarea + id: update + attributes: + label: What needs to be updated? + placeholder: | + Describe the missing, unclear, or incorrect documentation. + Examples: + - A function is undocumented + - A UI mode is unclear + - A screenshot is outdated + - A section needs clarification diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml index b4c66b5..272e948 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.yml +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -1,34 +1,34 @@ -name: Feature Request -description: Suggest an improvement or new feature for SchedPlus -labels: [enhancement] -body: - - type: markdown - attributes: - value: | - Thanks for your idea! - SchedPlus aims to stay simple, predictable, and local‑first. - Please describe the problem your feature solves. - - - type: textarea - id: problem - attributes: - label: Problem / Use Case - placeholder: What problem does this solve? What workflow is blocked or inefficient? - - - type: textarea - id: proposal - attributes: - label: Proposed Solution - placeholder: Describe the feature, interaction, or workflow improvement. - - - type: textarea - id: alternatives - attributes: - label: Alternatives Considered (optional) - placeholder: Any other approaches you thought about? - - - type: textarea - id: notes - attributes: - label: Additional Notes (optional) - placeholder: Screenshots, examples, or extra context. +name: Feature Request +description: Suggest an improvement or new feature for SchedPlus +labels: [enhancement] +body: + - type: markdown + attributes: + value: | + Thanks for your idea! + SchedPlus aims to stay simple, predictable, and local‑first. + Please describe the problem your feature solves. + + - type: textarea + id: problem + attributes: + label: Problem / Use Case + placeholder: What problem does this solve? What workflow is blocked or inefficient? + + - type: textarea + id: proposal + attributes: + label: Proposed Solution + placeholder: Describe the feature, interaction, or workflow improvement. + + - type: textarea + id: alternatives + attributes: + label: Alternatives Considered (optional) + placeholder: Any other approaches you thought about? + + - type: textarea + id: notes + attributes: + label: Additional Notes (optional) + placeholder: Screenshots, examples, or extra context. diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 61373d7..abe3e9d 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,17 +1,17 @@ -# Dependabot configuration for MathPlus -# Updates Cargo dependencies and GitHub Actions workflows. -# See documentation for all configuration options: -# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file - -version: 2 -updates: - - package-ecosystem: "pip" - directory: "/" - schedule: - interval: "weekly" - open-pull-requests-limit: 5 - - - package-ecosystem: "github-actions" - directory: "/" - schedule: - interval: "weekly" +# Dependabot configuration for MathPlus +# Updates Cargo dependencies and GitHub Actions workflows. +# See documentation for all configuration options: +# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file + +version: 2 +updates: + - package-ecosystem: "pip" + directory: "/" + schedule: + interval: "weekly" + open-pull-requests-limit: 5 + + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index b3a0242..17ac6f8 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,56 +1,56 @@ -# Pull Request - -Thank you for contributing to SchedPlus! -Please complete the sections below to help us review your PR. - ---- - -## Summary - -Describe what this PR changes and why. - ---- - -## Type of Change - -- [ ] Bug fix -- [ ] New feature -- [ ] Workflow improvement -- [ ] UI/UX improvement -- [ ] Documentation update -- [ ] Refactor / cleanup - ---- - -## Details - -Explain the implementation, any decisions made, and any side effects. -If the change affects task storage, JSON handling, Tkinter/PyQt UI behaviour, or cross‑platform compatibility, please describe it clearly. - ---- - -## Testing - -Describe how you tested your changes: - -- [ ] Runs successfully -- [ ] Tested on Windows -- [ ] Tested on Linux -- [ ] Tkinter UI behaves as expected -- [ ] PyQt UI behaves as expected (if applicable) -- [ ] JSON save/load works correctly -- [ ] No regressions found - ---- - -## Related Issues - -Link any related issues or discussions: - -`Fixes #123` or `Related to #456` - ---- - -## Additional Notes (optional) - -Anything else reviewers should know. +# Pull Request + +Thank you for contributing to SchedPlus! +Please complete the sections below to help us review your PR. + +--- + +## Summary + +Describe what this PR changes and why. + +--- + +## Type of Change + +- [ ] Bug fix +- [ ] New feature +- [ ] Workflow improvement +- [ ] UI/UX improvement +- [ ] Documentation update +- [ ] Refactor / cleanup + +--- + +## Details + +Explain the implementation, any decisions made, and any side effects. +If the change affects task storage, JSON handling, Tkinter/PyQt UI behaviour, or cross‑platform compatibility, please describe it clearly. + +--- + +## Testing + +Describe how you tested your changes: + +- [ ] Runs successfully +- [ ] Tested on Windows +- [ ] Tested on Linux +- [ ] Tkinter UI behaves as expected +- [ ] PyQt UI behaves as expected (if applicable) +- [ ] JSON save/load works correctly +- [ ] No regressions found + +--- + +## Related Issues + +Link any related issues or discussions: + +`Fixes #123` or `Related to #456` + +--- + +## Additional Notes (optional) + +Anything else reviewers should know. diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5664960..47fc44b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,33 +1,33 @@ -name: SchedPlus CI - -on: - push: - branches: - - main - pull_request: - -jobs: - lint_and_test: - name: Lint & Validate - runs-on: ubuntu-latest - - steps: - - name: Checkout repository - uses: actions/checkout@v6 - - - name: Set up Python - uses: actions/setup-python@v6 - with: - python-version: "3.14" - - - name: Install dependencies - run: | - pip install -r requirements.txt - pip install pyflakes - - - name: Lint (pyflakes) - run: pyflakes src/ - - - name: Validate project structure - run: | - echo "Project structure OK" +name: SchedPlus CI + +on: + push: + branches: + - main + pull_request: + +jobs: + lint_and_test: + name: Lint & Validate + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v6 + + - name: Set up Python + uses: actions/setup-python@v6 + with: + python-version: "3.14" + + - name: Install dependencies + run: | + pip install -r requirements.txt + pip install pyflakes + + - name: Lint (pyflakes) + run: pyflakes src/ + + - name: Validate project structure + run: | + echo "Project structure OK" diff --git a/.gitignore b/.gitignore index effd886..d4a3cf2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,66 +1,66 @@ -# ──────────────────────────────────────────────── -# Python -# ──────────────────────────────────────────────── -__pycache__/ -*.pyc -*.pyo -*.pyd -*.pdb -*.pkl - -# Virtual environments -venv/ -env/ -.venv/ - -# Python tooling caches -.pytest_cache/ -.mypy_cache/ -.ruff_cache/ -.coverage - -# ──────────────────────────────────────────────── -# Editor / IDE -# ──────────────────────────────────────────────── -.vscode/ -.idea/ -*.swp -*.swo - -# ──────────────────────────────────────────────── -# OS Files -# ──────────────────────────────────────────────── -.DS_Store -Thumbs.db -desktop.ini - -# ──────────────────────────────────────────────── -# Packaging (Snap, Debian, PyInstaller) -# ──────────────────────────────────────────────── - -# Snapcraft -snap/.snapcraft/ -parts/ -prime/ -stage/ - -# Debian packaging -packaging/deb/usr/ -packaging/deb/DEBIAN/ - -# PyInstaller / Windows builds -dist/ -build/ -*.spec -*.exe - -# ──────────────────────────────────────────────── -# App Data -# ──────────────────────────────────────────────── -tasks.json -*.log - -# ──────────────────────────────────────────────── -# Ecosystem Standards -# ──────────────────────────────────────────────── -temp_notes.md +# ──────────────────────────────────────────────── +# Python +# ──────────────────────────────────────────────── +__pycache__/ +*.pyc +*.pyo +*.pyd +*.pdb +*.pkl + +# Virtual environments +venv/ +env/ +.venv/ + +# Python tooling caches +.pytest_cache/ +.mypy_cache/ +.ruff_cache/ +.coverage + +# ──────────────────────────────────────────────── +# Editor / IDE +# ──────────────────────────────────────────────── +.vscode/ +.idea/ +*.swp +*.swo + +# ──────────────────────────────────────────────── +# OS Files +# ──────────────────────────────────────────────── +.DS_Store +Thumbs.db +desktop.ini + +# ──────────────────────────────────────────────── +# Packaging (Snap, Debian, PyInstaller) +# ──────────────────────────────────────────────── + +# Snapcraft +snap/.snapcraft/ +parts/ +prime/ +stage/ + +# Debian packaging +packaging/deb/usr/ +packaging/deb/DEBIAN/ + +# PyInstaller / Windows builds +dist/ +build/ +*.spec +*.exe + +# ──────────────────────────────────────────────── +# App Data +# ──────────────────────────────────────────────── +tasks.json +*.log + +# ──────────────────────────────────────────────── +# Ecosystem Standards +# ──────────────────────────────────────────────── +temp_notes.md diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 6045fd5..0b04c69 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -1,103 +1,103 @@ - - - - - - - -
- ZFordDev Standards Approved Badge -
- -# Code of Conduct - -The ZFordDev ecosystem is built on clarity, simplicity, and long‑term maintainability. -To keep our community healthy and welcoming, all contributors are expected to follow the guidelines below. - -This Code of Conduct applies to all project spaces, including GitHub Issues, Discussions, pull requests, and any community interactions related to ZFordDev projects. - ---- - -## Our Principles - -We strive to create an environment where contributors can collaborate respectfully and productively. -We expect all participants to: - -- Be kind, patient, and constructive -- Respect differing viewpoints and experiences -- Give and receive feedback gracefully -- Focus on improving the project, not winning arguments -- Assume good intentions -- Keep discussions technical, not personal - ---- - -## Unacceptable Behavior - -The following behaviors are not allowed in any ZFordDev project: - -- Harassment, insults, or personal attacks -- Discriminatory language or exclusionary behavior -- Trolling, baiting, or intentionally derailing discussions -- Publishing private information without permission -- Aggressive or hostile communication -- Repeatedly ignoring project standards or maintainers’ guidance - ---- - -## Responsibilities of Maintainers - -Project maintainers are responsible for: - -- Clarifying standards and expectations -- Reviewing contributions fairly -- Providing constructive feedback -- Taking action when behavior violates this Code -- Keeping the community safe and welcoming - -Maintainers may remove comments, close issues, or reject contributions that violate these guidelines. - ---- - -## Reporting Issues - -If you experience or witness behavior that violates this Code of Conduct: - -- Open a private issue if appropriate -- Or contact the project maintainer directly through GitHub - -All reports will be reviewed promptly and handled respectfully. - ---- - -## Enforcement - -Consequences for violating this Code may include: - -- A private warning -- Temporary or permanent removal from project spaces -- Rejection of contributions -- Escalation to GitHub moderation if necessary - -Enforcement decisions are made by project maintainers and are final. - ---- - -## SchedPlus‑Specific Notes - -SchedPlus is a tiny, focused scheduler built in Python. -Contributions and discussions should reflect that philosophy: - -- Keep discussions respectful, constructive, and solution‑oriented -- Maintain the lightweight, minimal nature of the app -- Avoid proposing features that introduce unnecessary complexity or bloat -- Preserve the clean, predictable UI and simple interaction patterns -- Keep the codebase approachable — SchedPlus is also a learning reference -- Ensure new ideas align with the “simple, local‑first, predictable” philosophy - ---- - -## Acknowledgment - -This Code of Conduct is inspired by the Contributor Covenant but rewritten to better fit the ZFordDev ecosystem’s tone and values. - + + + + + + + +
+ ZFordDev Standards Approved Badge +
+ +# Code of Conduct + +The ZFordDev ecosystem is built on clarity, simplicity, and long‑term maintainability. +To keep our community healthy and welcoming, all contributors are expected to follow the guidelines below. + +This Code of Conduct applies to all project spaces, including GitHub Issues, Discussions, pull requests, and any community interactions related to ZFordDev projects. + +--- + +## Our Principles + +We strive to create an environment where contributors can collaborate respectfully and productively. +We expect all participants to: + +- Be kind, patient, and constructive +- Respect differing viewpoints and experiences +- Give and receive feedback gracefully +- Focus on improving the project, not winning arguments +- Assume good intentions +- Keep discussions technical, not personal + +--- + +## Unacceptable Behavior + +The following behaviors are not allowed in any ZFordDev project: + +- Harassment, insults, or personal attacks +- Discriminatory language or exclusionary behavior +- Trolling, baiting, or intentionally derailing discussions +- Publishing private information without permission +- Aggressive or hostile communication +- Repeatedly ignoring project standards or maintainers’ guidance + +--- + +## Responsibilities of Maintainers + +Project maintainers are responsible for: + +- Clarifying standards and expectations +- Reviewing contributions fairly +- Providing constructive feedback +- Taking action when behavior violates this Code +- Keeping the community safe and welcoming + +Maintainers may remove comments, close issues, or reject contributions that violate these guidelines. + +--- + +## Reporting Issues + +If you experience or witness behavior that violates this Code of Conduct: + +- Open a private issue if appropriate +- Or contact the project maintainer directly through GitHub + +All reports will be reviewed promptly and handled respectfully. + +--- + +## Enforcement + +Consequences for violating this Code may include: + +- A private warning +- Temporary or permanent removal from project spaces +- Rejection of contributions +- Escalation to GitHub moderation if necessary + +Enforcement decisions are made by project maintainers and are final. + +--- + +## SchedPlus‑Specific Notes + +SchedPlus is a tiny, focused scheduler built in Python. +Contributions and discussions should reflect that philosophy: + +- Keep discussions respectful, constructive, and solution‑oriented +- Maintain the lightweight, minimal nature of the app +- Avoid proposing features that introduce unnecessary complexity or bloat +- Preserve the clean, predictable UI and simple interaction patterns +- Keep the codebase approachable — SchedPlus is also a learning reference +- Ensure new ideas align with the “simple, local‑first, predictable” philosophy + +--- + +## Acknowledgment + +This Code of Conduct is inspired by the Contributor Covenant but rewritten to better fit the ZFordDev ecosystem’s tone and values. + diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 28a90c2..b7d3ed1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,151 +1,151 @@ - - - - - - - -
- ZFordDev Standards Approved Badge -
- -# Contributing to ZFordDev Projects - -Thank you for your interest in contributing! -All ZFordDev projects follow a shared set of standards designed to keep the ecosystem consistent, maintainable, and welcoming. - -This document explains how to contribute code, documentation, bug reports, and feature requests across the ecosystem. - -For ecosystem‑wide expectations, please read: - -👉 [**STANDARDS.md**](https://github.com/ZFordDev/ZFordDev/blob/main/STANDARDS.md) -(Clarity • Simplicity • Maintainability • Long‑term stability) - ---- - -## Ways to Contribute - -You can contribute in many ways: - -- Reporting bugs -- Suggesting new features -- Improving documentation -- Submitting pull requests -- Reviewing existing issues -- Helping refine UX or workflows -- Testing on different platforms - -All contributions are appreciated — even small ones. - ---- - -## Code of Conduct - -By participating in this project, you agree to follow: - -👉 [**CODE_OF_CONDUCT.md**](CODE_OF_CONDUCT.md) - -Respect, clarity, and constructive collaboration are core values of the ecosystem. - ---- - -## Before You Start - -Please check: - -- The **Issues** tab for existing reports -- The **Roadmap** (if present) -- The **Discussions** tab for ongoing ideas -- The **STANDARDS.md** file for ecosystem rules -- The **project‑specific section** below for details unique to this repository - -If you’re unsure whether an idea fits, open a Discussion first — it saves everyone time. - ---- - -## Pull Request Guidelines - -To keep contributions consistent: - -1. **Fork the repository** -2. **Create a feature branch** - - `feature/your-feature-name` - - `fix/your-bug-name` -3. **Keep PRs focused** - - One feature or fix per PR - - Avoid unrelated formatting changes -4. **Follow the coding style of the project** - - Naming conventions - - File structure - - Module layout -5. **Test your changes** - - Ensure the app builds - - Ensure no regressions -6. **Write clear commit messages** - - Present tense - - Short and descriptive -7. **Describe your PR clearly** - - What changed - - Why it changed - - Any side effects or considerations - -Small, focused PRs are easier to review and merge. - ---- - -## Reporting Bugs - -When reporting a bug, please include: - -- OS and version -- App version -- Steps to reproduce -- Expected behavior -- Actual behavior -- Screenshots or logs (if helpful) - -Clear reports help us fix issues faster. - ---- - -## Suggesting Features - -Feature requests should: - -- Explain the problem, not just the solution -- Describe the use case -- Fit the project’s philosophy (see STANDARDS.md) -- Avoid scope creep or IDE‑level complexity - -If unsure, open a Discussion first. - ---- - -## Project‑Specific Guidelines - -Each project may have additional rules, workflows, or architectural notes. - -### SchedPlus‑Specific Notes - -SchedPlus is a small, Python‑based desktop scheduler. -Contributions should reflect its lightweight, minimal, and predictable design: - -- UI changes should follow the existing layout and interaction patterns -- Avoid introducing heavy dependencies — keep the project simple and easy to install -- JSON storage must remain safe, local, and predictable -- Do not add features that turn SchedPlus into a full productivity suite unless scoped and discussed -- PyQt‑related changes should be tested on Windows and Linux when possible -- Keep the codebase beginner‑friendly — SchedPlus is also a learning reference -- Maintain the clean, distraction‑free feel of the interface -- Ensure new features align with the “simple, local‑first, predictable” philosophy -- Avoid complex background services, cloud sync, or account systems -- Follow the existing module layout in `src/` - ---- - -## Thank You - -Your contributions help strengthen the entire ZFordDev ecosystem. -Whether you’re fixing a typo or building a major feature — you’re part of the project’s future. - - + + + + + + + +
+ ZFordDev Standards Approved Badge +
+ +# Contributing to ZFordDev Projects + +Thank you for your interest in contributing! +All ZFordDev projects follow a shared set of standards designed to keep the ecosystem consistent, maintainable, and welcoming. + +This document explains how to contribute code, documentation, bug reports, and feature requests across the ecosystem. + +For ecosystem‑wide expectations, please read: + +👉 [**STANDARDS.md**](https://github.com/ZFordDev/ZFordDev/blob/main/STANDARDS.md) +(Clarity • Simplicity • Maintainability • Long‑term stability) + +--- + +## Ways to Contribute + +You can contribute in many ways: + +- Reporting bugs +- Suggesting new features +- Improving documentation +- Submitting pull requests +- Reviewing existing issues +- Helping refine UX or workflows +- Testing on different platforms + +All contributions are appreciated — even small ones. + +--- + +## Code of Conduct + +By participating in this project, you agree to follow: + +👉 [**CODE_OF_CONDUCT.md**](CODE_OF_CONDUCT.md) + +Respect, clarity, and constructive collaboration are core values of the ecosystem. + +--- + +## Before You Start + +Please check: + +- The **Issues** tab for existing reports +- The **Roadmap** (if present) +- The **Discussions** tab for ongoing ideas +- The **STANDARDS.md** file for ecosystem rules +- The **project‑specific section** below for details unique to this repository + +If you’re unsure whether an idea fits, open a Discussion first — it saves everyone time. + +--- + +## Pull Request Guidelines + +To keep contributions consistent: + +1. **Fork the repository** +2. **Create a feature branch** + - `feature/your-feature-name` + - `fix/your-bug-name` +3. **Keep PRs focused** + - One feature or fix per PR + - Avoid unrelated formatting changes +4. **Follow the coding style of the project** + - Naming conventions + - File structure + - Module layout +5. **Test your changes** + - Ensure the app builds + - Ensure no regressions +6. **Write clear commit messages** + - Present tense + - Short and descriptive +7. **Describe your PR clearly** + - What changed + - Why it changed + - Any side effects or considerations + +Small, focused PRs are easier to review and merge. + +--- + +## Reporting Bugs + +When reporting a bug, please include: + +- OS and version +- App version +- Steps to reproduce +- Expected behavior +- Actual behavior +- Screenshots or logs (if helpful) + +Clear reports help us fix issues faster. + +--- + +## Suggesting Features + +Feature requests should: + +- Explain the problem, not just the solution +- Describe the use case +- Fit the project’s philosophy (see STANDARDS.md) +- Avoid scope creep or IDE‑level complexity + +If unsure, open a Discussion first. + +--- + +## Project‑Specific Guidelines + +Each project may have additional rules, workflows, or architectural notes. + +### SchedPlus‑Specific Notes + +SchedPlus is a small, Python‑based desktop scheduler. +Contributions should reflect its lightweight, minimal, and predictable design: + +- UI changes should follow the existing layout and interaction patterns +- Avoid introducing heavy dependencies — keep the project simple and easy to install +- JSON storage must remain safe, local, and predictable +- Do not add features that turn SchedPlus into a full productivity suite unless scoped and discussed +- PyQt‑related changes should be tested on Windows and Linux when possible +- Keep the codebase beginner‑friendly — SchedPlus is also a learning reference +- Maintain the clean, distraction‑free feel of the interface +- Ensure new features align with the “simple, local‑first, predictable” philosophy +- Avoid complex background services, cloud sync, or account systems +- Follow the existing module layout in `src/` + +--- + +## Thank You + +Your contributions help strengthen the entire ZFordDev ecosystem. +Whether you’re fixing a typo or building a major feature — you’re part of the project’s future. + + diff --git a/LICENSE b/LICENSE index ea0df50..75b8a6b 100644 --- a/LICENSE +++ b/LICENSE @@ -1,21 +1,21 @@ -MIT License - -Copyright (c) 2026 ZFordDev - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +MIT License + +Copyright (c) 2026 ZFordDev + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md index e0364b3..faff5e9 100644 --- a/README.md +++ b/README.md @@ -1,234 +1,234 @@ - - - - - - - - -
- ZFordDev Standards Approved Badge -
- - - - - -[![Docs](https://img.shields.io/badge/DocsHub-docs.zford.dev-4F46E5?style=flat-square)](https://docs.zford.dev) -![Status](https://img.shields.io/badge/Status-ACTIVE-4CAF50?style=flat-square) -![Platforms](https://img.shields.io/badge/Platforms-Windows%20%7C%20Linux-blue?style=flat-square) - - - - - - - -![Python](https://img.shields.io/badge/Built_with-Python-blue?style=flat-square) - -# SchedPlus - -> A lightweight, local‑first desktop scheduler built in Python. -> **Status:** Alpha • Actively Maintained • Accepting Contributions - ---- - -## Why This Exists - -Most scheduling tools try to do everything — calendars, reminders, syncing, accounts, cloud dashboards — and end up feeling heavy, slow, or overly complex. - -SchedPlus was built to be the opposite: - -- **simple** -- **local‑first** -- **lightweight** -- **predictable** -- **no accounts** -- **no cloud** -- **no unnecessary features** - -It focuses on one job: helping you plan your day without getting in your way. - -SchedPlus is also a great **learning reference**, showing how a real desktop app evolves over time — from a quick Tkinter prototype to a structured Python application and eventually a full PyQt desktop experience. - ---- - -## Overview - -SchedPlus is a simple, predictable desktop scheduler built for people who want structure without the noise. - -It focuses on: - -- fast startup -- a clean, minimal interface -- local‑only task storage -- a small, readable Python codebase -- an offline‑first workflow - -It’s intentionally lightweight — ideal for daily planning, learning Python UI development, or experimenting with how real desktop apps evolve over time. - -SchedPlus currently ships with a stable Tkinter UI, while a full PyQt migration is actively underway to bring a more modern, cross‑platform experience. - ---- - -## Features - -* Local task creation and management -* JSON‑based save/load -* Offline‑first workflow -* Tkinter UI (stable) -* PyQt UI (in development) -* Clean logic/storage separation -* Beginner‑friendly codebase - ---- - -## Requirements - -SchedPlus is currently a source‑only project. -To run or develop it, you’ll need: - -> Python 3.14+ -> pip (latest) -> Tkinter (included with most Python installs) -> PyQt6 (optional, for the new UI) - -**Supported environments:** - -> Windows 10+ -> Linux (Ubuntu 22.04+) - ---- - -## Quick Start - -```bash -git clone https://github.com/ZFordDev/schedplus.git -cd schedplus - -pip install -r requirements.txt - -python3 src/main.py -``` - -> *Recommended: use a `.venv`.* - ---- - -## Installation - -SchedPlus currently has no build pipeline yet — please wait for the beta release. - ---- - -## Usage - -Basic usage: - -```bash -python3 src/main.py -``` - -The UI will open and allow you to create, edit, and save tasks locally. - ---- - -## Project Structure - -SchedPlus uses a simple, predictable layout designed to keep UI, logic, and data clearly separated. - -```text -schedplus/ -├── src/ -│ ├── assets/ # Icons and UI assets -│ ├── data/ # Local task storage -│ ├── logic/ # Core scheduling logic -│ ├── startup/ # NEW — startup -│ ├── ui/ # Tkinter + PyQt interfaces -│ └── main.py # Application entry point -│ -└── packaging/ # Future packaging targets - ├── snap/ - ├── deb/ - └── windows/ -``` - ---- - -## Roadmap - -* [ ] Full PyQt migration -* [ ] Cross‑platform packaging -* [ ] Windows installer -* [ ] Improved task management -* [ ] UI backend experimentation -* [ ] Multi‑platform releases - ---- - -## Screenshots - -

- - -

- ---- - -## Known Issues - -* PyQt UI is incomplete -* Packaging is experimental -* macOS support not yet available - ---- - -## Related Projects - -- **MathPlus** — a lightweight desktop calculator - [https://github.com/ZFordDev/MathPlus](https://github.com/ZFordDev/MathPlus) - ---- - -## Support - -You can support SchedPlus by: - -* Leaving a ⭐ on GitHub -* Reporting bugs -* Suggesting new features -* Improving documentation -* Contributing code - ---- - -## Contributing - -Contributions, bug reports, feature requests, and feedback are welcome. - -See `CONTRIBUTING.md` for project‑specific guidelines. -For ecosystem‑wide expectations, see [STANDARDS.md](https://github.com/ZFordDev/ZFordDev/blob/main/STANDARDS.md). - ---- - -## Security - -See `SECURITY.md` for vulnerability reporting guidelines. -If no security policy is present, please report issues responsibly via GitHub Issues. - ---- - -## License - -Released under the MIT License. -See `LICENSE` for details. - ---- - -## About ZFordDev - -This project is part of the ZFordDev ecosystem — a collection of lightweight, practical tools built with clarity, simplicity, and long‑term maintainability in mind. - -For ecosystem‑wide standards, see [STANDARDS.md](https://github.com/ZFordDev/ZFordDev/blob/main/STANDARDS.md). - + + + + + + + + +
+ ZFordDev Standards Approved Badge +
+ + + + + +[![Docs](https://img.shields.io/badge/DocsHub-docs.zford.dev-4F46E5?style=flat-square)](https://docs.zford.dev) +![Status](https://img.shields.io/badge/Status-ACTIVE-4CAF50?style=flat-square) +![Platforms](https://img.shields.io/badge/Platforms-Windows%20%7C%20Linux-blue?style=flat-square) + + + + + + + +![Python](https://img.shields.io/badge/Built_with-Python-blue?style=flat-square) + +# SchedPlus + +> A lightweight, local‑first desktop scheduler built in Python. +> **Status:** Alpha • Actively Maintained • Accepting Contributions + +--- + +## Why This Exists + +Most scheduling tools try to do everything — calendars, reminders, syncing, accounts, cloud dashboards — and end up feeling heavy, slow, or overly complex. + +SchedPlus was built to be the opposite: + +- **simple** +- **local‑first** +- **lightweight** +- **predictable** +- **no accounts** +- **no cloud** +- **no unnecessary features** + +It focuses on one job: helping you plan your day without getting in your way. + +SchedPlus is also a great **learning reference**, showing how a real desktop app evolves over time — from a quick Tkinter prototype to a structured Python application and eventually a full PyQt desktop experience. + +--- + +## Overview + +SchedPlus is a simple, predictable desktop scheduler built for people who want structure without the noise. + +It focuses on: + +- fast startup +- a clean, minimal interface +- local‑only task storage +- a small, readable Python codebase +- an offline‑first workflow + +It’s intentionally lightweight — ideal for daily planning, learning Python UI development, or experimenting with how real desktop apps evolve over time. + +SchedPlus currently ships with a stable Tkinter UI, while a full PyQt migration is actively underway to bring a more modern, cross‑platform experience. + +--- + +## Features + +* Local task creation and management +* JSON‑based save/load +* Offline‑first workflow +* Tkinter UI (stable) +* PyQt UI (in development) +* Clean logic/storage separation +* Beginner‑friendly codebase + +--- + +## Requirements + +SchedPlus is currently a source‑only project. +To run or develop it, you’ll need: + +> Python 3.14+ +> pip (latest) +> Tkinter (included with most Python installs) +> PyQt6 (optional, for the new UI) + +**Supported environments:** + +> Windows 10+ +> Linux (Ubuntu 22.04+) + +--- + +## Quick Start + +```bash +git clone https://github.com/ZFordDev/schedplus.git +cd schedplus + +pip install -r requirements.txt + +python3 src/main.py +``` + +> *Recommended: use a `.venv`.* + +--- + +## Installation + +SchedPlus currently has no build pipeline yet — please wait for the beta release. + +--- + +## Usage + +Basic usage: + +```bash +python3 src/main.py +``` + +The UI will open and allow you to create, edit, and save tasks locally. + +--- + +## Project Structure + +SchedPlus uses a simple, predictable layout designed to keep UI, logic, and data clearly separated. + +```text +schedplus/ +├── src/ +│ ├── assets/ # Icons and UI assets +│ ├── data/ # Local task storage +│ ├── logic/ # Core scheduling logic +│ ├── startup/ # NEW — startup +│ ├── ui/ # Tkinter + PyQt interfaces +│ └── main.py # Application entry point +│ +└── packaging/ # Future packaging targets + ├── snap/ + ├── deb/ + └── windows/ +``` + +--- + +## Roadmap + +* [ ] Full PyQt migration +* [ ] Cross‑platform packaging +* [ ] Windows installer +* [ ] Improved task management +* [ ] UI backend experimentation +* [ ] Multi‑platform releases + +--- + +## Screenshots + +

+ + +

+ +--- + +## Known Issues + +* PyQt UI is incomplete +* Packaging is experimental +* macOS support not yet available + +--- + +## Related Projects + +- **MathPlus** — a lightweight desktop calculator + [https://github.com/ZFordDev/MathPlus](https://github.com/ZFordDev/MathPlus) + +--- + +## Support + +You can support SchedPlus by: + +* Leaving a ⭐ on GitHub +* Reporting bugs +* Suggesting new features +* Improving documentation +* Contributing code + +--- + +## Contributing + +Contributions, bug reports, feature requests, and feedback are welcome. + +See `CONTRIBUTING.md` for project‑specific guidelines. +For ecosystem‑wide expectations, see [STANDARDS.md](https://github.com/ZFordDev/ZFordDev/blob/main/STANDARDS.md). + +--- + +## Security + +See `SECURITY.md` for vulnerability reporting guidelines. +If no security policy is present, please report issues responsibly via GitHub Issues. + +--- + +## License + +Released under the MIT License. +See `LICENSE` for details. + +--- + +## About ZFordDev + +This project is part of the ZFordDev ecosystem — a collection of lightweight, practical tools built with clarity, simplicity, and long‑term maintainability in mind. + +For ecosystem‑wide standards, see [STANDARDS.md](https://github.com/ZFordDev/ZFordDev/blob/main/STANDARDS.md). + --- \ No newline at end of file diff --git a/SECURITY.md b/SECURITY.md index ba1efde..8b9c290 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -1,104 +1,104 @@ - - - - - - - -
- ZFordDev Standards Approved Badge -
- -# Security Policy - -The ZFordDev ecosystem values stability, safety, and long‑term maintainability. -We take security seriously and appreciate responsible disclosure of any vulnerabilities. - -This document explains how to report security issues and what to expect during the process. - ---- - -## Supported Versions - -Security updates are provided for: - -- **Current stable releases** -- **Active development branches** -- **Classic versions**, where applicable - -Older or archived versions may not receive fixes. - ---- - -## Reporting a Vulnerability - -If you discover a security issue, please report it responsibly. - -### **How to report** -- Open a **private GitHub security advisory** (preferred) -- Or contact the project maintainer directly through GitHub - -Please **do not** open a public issue for security vulnerabilities. - -### **Include the following information** -- Description of the issue -- Steps to reproduce -- Impact or potential risk -- Affected versions -- Any relevant logs or screenshots - -Clear reports help us respond quickly. - ---- - -## Response Process - -When a report is received: - -1. The maintainer will acknowledge the report -2. The issue will be investigated -3. A fix or mitigation will be prepared -4. A patched release will be published -5. A security advisory will be issued (if applicable) - -We aim to handle all reports respectfully and promptly. - ---- - -## Scope - -This policy applies to: - -- All ZFordDev repositories -- All official releases -- All ecosystem tools and modules - -It does **not** apply to: - -- Third‑party dependencies -- Forks or modified builds -- Unofficial distributions - ---- - -## SchedPlus‑Specific Notes - -SchedPlus is a lightweight Python application with a local‑only workflow. -When reporting security issues, please consider the following: - -- SchedPlus does not load or execute remote content -- All data is stored locally in simple JSON files (`data/tasks.json`) -- No networking, syncing, or cloud communication is performed -- The Tkinter UI is stable; the PyQt UI is in active development and may behave differently across platforms -- SchedPlus does not collect telemetry or send user data anywhere -- The application does not run background services or scheduled tasks - -If a vulnerability involves JSON handling, UI behaviour, file access, or platform‑specific issues, please include clear reproduction steps for both Windows and Linux (when applicable). - ---- - - -## Thank You - -Responsible disclosure helps keep the entire ZFordDev ecosystem safe. -We appreciate your effort and your commitment to improving the project. + + + + + + + +
+ ZFordDev Standards Approved Badge +
+ +# Security Policy + +The ZFordDev ecosystem values stability, safety, and long‑term maintainability. +We take security seriously and appreciate responsible disclosure of any vulnerabilities. + +This document explains how to report security issues and what to expect during the process. + +--- + +## Supported Versions + +Security updates are provided for: + +- **Current stable releases** +- **Active development branches** +- **Classic versions**, where applicable + +Older or archived versions may not receive fixes. + +--- + +## Reporting a Vulnerability + +If you discover a security issue, please report it responsibly. + +### **How to report** +- Open a **private GitHub security advisory** (preferred) +- Or contact the project maintainer directly through GitHub + +Please **do not** open a public issue for security vulnerabilities. + +### **Include the following information** +- Description of the issue +- Steps to reproduce +- Impact or potential risk +- Affected versions +- Any relevant logs or screenshots + +Clear reports help us respond quickly. + +--- + +## Response Process + +When a report is received: + +1. The maintainer will acknowledge the report +2. The issue will be investigated +3. A fix or mitigation will be prepared +4. A patched release will be published +5. A security advisory will be issued (if applicable) + +We aim to handle all reports respectfully and promptly. + +--- + +## Scope + +This policy applies to: + +- All ZFordDev repositories +- All official releases +- All ecosystem tools and modules + +It does **not** apply to: + +- Third‑party dependencies +- Forks or modified builds +- Unofficial distributions + +--- + +## SchedPlus‑Specific Notes + +SchedPlus is a lightweight Python application with a local‑only workflow. +When reporting security issues, please consider the following: + +- SchedPlus does not load or execute remote content +- All data is stored locally in simple JSON files (`data/tasks.json`) +- No networking, syncing, or cloud communication is performed +- The Tkinter UI is stable; the PyQt UI is in active development and may behave differently across platforms +- SchedPlus does not collect telemetry or send user data anywhere +- The application does not run background services or scheduled tasks + +If a vulnerability involves JSON handling, UI behaviour, file access, or platform‑specific issues, please include clear reproduction steps for both Windows and Linux (when applicable). + +--- + + +## Thank You + +Responsible disclosure helps keep the entire ZFordDev ecosystem safe. +We appreciate your effort and your commitment to improving the project. diff --git a/assets/icon.svg b/assets/icon.svg index a5c45bd..39d9eeb 100644 --- a/assets/icon.svg +++ b/assets/icon.svg @@ -1,44 +1,44 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/config/README.md b/config/README.md index 8da6cfa..f865439 100644 --- a/config/README.md +++ b/config/README.md @@ -1,9 +1,9 @@ -# Config Directory - -This folder stores user‑specific configuration files for SchedPlus. - -- These files are **local to your machine**. -- They are **not tracked by Git** and are safe to modify. -- The contents here act as **templates** for personal settings, saved tasks, and future features like authentication or database configuration. - -As SchedPlus evolves, this directory will remain the home for all user‑level config and state files. +# Config Directory + +This folder stores user‑specific configuration files for SchedPlus. + +- These files are **local to your machine**. +- They are **not tracked by Git** and are safe to modify. +- The contents here act as **templates** for personal settings, saved tasks, and future features like authentication or database configuration. + +As SchedPlus evolves, this directory will remain the home for all user‑level config and state files. diff --git a/config/tasks.json b/config/tasks.json index e09d31f..368ea5e 100644 --- a/config/tasks.json +++ b/config/tasks.json @@ -1,20 +1,20 @@ -[ - { - "id": "task1", - "name": "Task 1", - "description": "This is the first task.", - "status": "pending" - }, - { - "id": "task2", - "name": "Task 2", - "description": "This is the second task.", - "status": "in_progress" - }, - { - "id": "task3", - "name": "Task 3", - "description": "This is the third task.", - "status": "completed" - } +[ + { + "id": "task1", + "name": "Task 1", + "description": "This is the first task.", + "status": "pending" + }, + { + "id": "task2", + "name": "Task 2", + "description": "This is the second task.", + "status": "in_progress" + }, + { + "id": "task3", + "name": "Task 3", + "description": "This is the third task.", + "status": "completed" + } ] \ No newline at end of file diff --git a/docs/schema.md b/docs/schema.md index 8b87297..5a276d0 100644 --- a/docs/schema.md +++ b/docs/schema.md @@ -1,40 +1,40 @@ -# Task JSON Schema - -SchedPlus stores scheduled tasks in JSON using a simple versioned schema. - -## Task Object Structure - -Each task is represented as an object with the following fields: - -- `id` — unique task identifier (string, `uuid4` recommended) -- `date` — ISO date in `YYYY-MM-DD` format -- `time` — 24-hour time in `HH:MM` format -- `text` — task description -- `createdAt` — creation timestamp in epoch milliseconds -- `updatedAt` — last update timestamp in epoch milliseconds - -## Full File Layout - -The top-level file contains a `version` field and a `tasks` array. - -```json -{ - "version": 1, - "tasks": [ - { - "id": "uuid", - "date": "2026-05-04", - "time": "14:30", - "text": "Example task", - "createdAt": 1714820000000, - "updatedAt": 1714820000000 - } - ] -} -``` - -## Notes - -- The `version` field supports future migrations. -- The schema uses ISO date/time formats for clarity. -- The file is intentionally simple and beginner-friendly. +# Task JSON Schema + +SchedPlus stores scheduled tasks in JSON using a simple versioned schema. + +## Task Object Structure + +Each task is represented as an object with the following fields: + +- `id` — unique task identifier (string, `uuid4` recommended) +- `date` — ISO date in `YYYY-MM-DD` format +- `time` — 24-hour time in `HH:MM` format +- `text` — task description +- `createdAt` — creation timestamp in epoch milliseconds +- `updatedAt` — last update timestamp in epoch milliseconds + +## Full File Layout + +The top-level file contains a `version` field and a `tasks` array. + +```json +{ + "version": 1, + "tasks": [ + { + "id": "uuid", + "date": "2026-05-04", + "time": "14:30", + "text": "Example task", + "createdAt": 1714820000000, + "updatedAt": 1714820000000 + } + ] +} +``` + +## Notes + +- The `version` field supports future migrations. +- The schema uses ISO date/time formats for clarity. +- The file is intentionally simple and beginner-friendly. diff --git a/requirements.txt b/requirements.txt index 22779d0..65a6327 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,3 @@ -# SchedPlus dependencies - +# SchedPlus dependencies + PyQt6 \ No newline at end of file diff --git a/src/startup/controller.py b/src/startup/controller.py index 61fbdf3..29ea8a4 100644 --- a/src/startup/controller.py +++ b/src/startup/controller.py @@ -89,7 +89,7 @@ def _launch_mode(mode: StartupMode): if mode == StartupMode.TK: try: - from ui.tkinter_ui import run_ui + from ui.tk import run_ui except Exception: print("Tkinter UI is not available on this system.") return diff --git a/src/ui/tk/__init__.py b/src/ui/tk/__init__.py new file mode 100644 index 0000000..56b9ea1 --- /dev/null +++ b/src/ui/tk/__init__.py @@ -0,0 +1,7 @@ +""" +Tkinter UI package for SchedPlus. + +Exposes the run_ui() entrypoint used by the startup controller. +""" + +from .main_window import run_ui diff --git a/src/ui/tk/add_task_dialog.py b/src/ui/tk/add_task_dialog.py new file mode 100644 index 0000000..f39cd3c --- /dev/null +++ b/src/ui/tk/add_task_dialog.py @@ -0,0 +1,119 @@ +""" +add_task_dialog.py +------------------ +Improved modal dialog for adding a task. + +- Pre-fills date/time with current values +- Adds keyboard shortcuts (Enter/Esc) +- Adds simple validation +- Cleaner layout and spacing +""" + +import tkinter as tk +from tkinter import ttk +from datetime import datetime + + +class AddTaskDialog(tk.Toplevel): + """Modal dialog for entering task details.""" + + def __init__(self, parent): + super().__init__(parent) + self.title("Add Task") + self.resizable(False, False) + + self.result = None + + # --------------------------------------------------------- + # Frame + # --------------------------------------------------------- + frame = ttk.Frame(self, padding=15) + frame.grid(row=0, column=0) + + # --------------------------------------------------------- + # Default values + # --------------------------------------------------------- + now = datetime.now() + default_date = now.strftime("%Y-%m-%d") + default_time = now.strftime("%H:%M") + + # --------------------------------------------------------- + # Date + # --------------------------------------------------------- + ttk.Label(frame, text="Date (YYYY-MM-DD):").grid(row=0, column=0, sticky="w", pady=4) + self.date_entry = ttk.Entry(frame, width=25) + self.date_entry.insert(0, default_date) + self.date_entry.grid(row=0, column=1, pady=4) + + # --------------------------------------------------------- + # Time + # --------------------------------------------------------- + ttk.Label(frame, text="Time (HH:MM):").grid(row=1, column=0, sticky="w", pady=4) + self.time_entry = ttk.Entry(frame, width=25) + self.time_entry.insert(0, default_time) + self.time_entry.grid(row=1, column=1, pady=4) + + # --------------------------------------------------------- + # Task title + # --------------------------------------------------------- + ttk.Label(frame, text="Task:").grid(row=2, column=0, sticky="w", pady=4) + self.text_entry = ttk.Entry(frame, width=25) + self.text_entry.grid(row=2, column=1, pady=4) + + # --------------------------------------------------------- + # Buttons + # --------------------------------------------------------- + btn_frame = ttk.Frame(frame) + btn_frame.grid(row=3, column=0, columnspan=2, pady=(12, 0)) + + ttk.Button(btn_frame, text="Cancel", command=self._cancel).grid(row=0, column=0, padx=6) + ttk.Button(btn_frame, text="Add", command=self._on_add).grid(row=0, column=1, padx=6) + + # --------------------------------------------------------- + # Keyboard shortcuts + # --------------------------------------------------------- + self.bind("", lambda e: self._on_add()) + self.bind("", lambda e: self._cancel()) + + # --------------------------------------------------------- + # Focus + # --------------------------------------------------------- + self.text_entry.focus() + + # Modal behavior + self.grab_set() + self.wait_window() + + # ------------------------------------------------------------- + # Actions + # ------------------------------------------------------------- + def _cancel(self): + self.result = None + self.destroy() + + def _on_add(self): + """Validate, collect values, and close dialog.""" + date = self.date_entry.get().strip() + time = self.time_entry.get().strip() + text = self.text_entry.get().strip() + + # Simple validation + if not (date and time and text): + self._flash_error() + return + + self.result = (date, time, text) + self.destroy() + + # ------------------------------------------------------------- + # UX: Flash red border on invalid input + # ------------------------------------------------------------- + def _flash_error(self): + for widget in (self.date_entry, self.time_entry, self.text_entry): + widget.configure(style="Error.TEntry") + + self.after(150, self._clear_error) + + def _clear_error(self): + for widget in (self.date_entry, self.time_entry, self.text_entry): + widget.configure(style="TEntry") diff --git a/src/ui/tk/connector.py b/src/ui/tk/connector.py new file mode 100644 index 0000000..90e2224 --- /dev/null +++ b/src/ui/tk/connector.py @@ -0,0 +1,54 @@ +""" +connector.py +------------ +Thin wrapper between Tkinter UI and the scheduler. + +Keeps UI code clean and storage-agnostic. +""" + +from .utils import build_due_date + + +class TkConnector: + """ + Provides UI-friendly access to scheduler operations. + + The connector: + - Validates UI input + - Converts UI date/time → ISO format + - Delegates all logic to the scheduler + - Keeps UI code simple and logic-free + """ + + def __init__(self, scheduler): + self.scheduler = scheduler + + # --------------------------------------------------------- + # Read operations + # --------------------------------------------------------- + def list_tasks(self): + """Return all tasks from the scheduler.""" + return self.scheduler.list_tasks() + + # --------------------------------------------------------- + # Write operations + # --------------------------------------------------------- + def add_task(self, date: str, time: str, title: str) -> bool: + """ + Validate and add a new task. + + Returns: + bool: True if task was added, False if validation failed. + """ + if not (date and time and title): + return False + + due_date = build_due_date(date, time) + + self.scheduler.add_task( + title=title, + description=None, + due_date=due_date, + ) + + return True diff --git a/src/ui/tk/main_window.py b/src/ui/tk/main_window.py new file mode 100644 index 0000000..a005bc9 --- /dev/null +++ b/src/ui/tk/main_window.py @@ -0,0 +1,180 @@ +""" +main_window.py +-------------- +Primary Tkinter window for SchedPlus (Basic Mode). + +A modernized task manager UI with modal task entry, a refreshed task table, +and improved keyboard shortcuts for faster task handling. +""" + +import tkinter as tk +from tkinter import ttk + +from .add_task_dialog import AddTaskDialog +from .connector import TkConnector +from .utils import split_due_date + + +def run_ui(scheduler): + """Entry point called by startup controller.""" + connector = TkConnector(scheduler) + + root = tk.Tk() + root.title("SchedPlus") + root.geometry("560x560") + root.minsize(520, 520) + root.configure(bg="#edf2fb") + + style = ttk.Style(root) + style.theme_use("clam") + style.configure("Root.TFrame", background="#edf2fb") + style.configure("Card.TFrame", background="#ffffff", relief="flat") + style.configure("Header.TLabel", background="#edf2fb", font=("Segoe UI", 16, "bold"), foreground="#1f2937") + style.configure("SubHeader.TLabel", background="#edf2fb", font=("Segoe UI", 10), foreground="#4b5563") + style.configure("Accent.TButton", font=("Segoe UI", 10, "bold"), foreground="#ffffff", background="#4f46e5", padding=10) + style.map("Accent.TButton", background=[("active", "#4338ca"), ("pressed", "#3730a3")]) + style.configure("Secondary.TButton", font=("Segoe UI", 10), foreground="#111827", background="#f3f4f6", padding=8) + style.configure("Task.Treeview", background="#ffffff", fieldbackground="#ffffff", highlightthickness=0, bordercolor="#d1d5db", borderwidth=1) + style.configure("Task.Treeview.Heading", font=("Segoe UI", 10, "bold"), foreground="#111827") + style.map("Task.Treeview", background=[("selected", "#e0e7ff")]) + + root.columnconfigure(0, weight=1) + root.rowconfigure(0, weight=1) + + container = ttk.Frame(root, style="Root.TFrame", padding=(18, 18, 18, 12)) + container.grid(row=0, column=0, sticky="nsew") + container.columnconfigure(0, weight=1) + container.rowconfigure(3, weight=1) + + header_frame = ttk.Frame(container, style="Root.TFrame") + header_frame.grid(row=0, column=0, sticky="ew", pady=(0, 14)) + header_frame.columnconfigure(0, weight=1) + + heading = ttk.Label(header_frame, text="SchedPlus", style="Header.TLabel") + heading.grid(row=0, column=0, sticky="w") + + subtitle = ttk.Label( + header_frame, + text="A clean way to add tasks, track due times, and stay organized.", + style="SubHeader.TLabel" + ) + subtitle.grid(row=1, column=0, sticky="w", pady=(6, 0)) + + # Quick action row. + action_frame = ttk.Frame(container, style="Card.TFrame", padding=14) + action_frame.grid(row=1, column=0, sticky="ew", pady=(0, 14)) + action_frame.columnconfigure(0, weight=1) + action_frame.columnconfigure(1, weight=0) + + info_text = ttk.Label( + action_frame, + text="Use the button below to add a task with full date, time, and title.", + style="SubHeader.TLabel", + wraplength=360, + justify="left" + ) + info_text.grid(row=0, column=0, sticky="w") + + add_button = ttk.Button(action_frame, text="Add Task", style="Accent.TButton") + add_button.grid(row=0, column=1, sticky="e") + + control_frame = ttk.Frame(container, style="Root.TFrame") + control_frame.grid(row=2, column=0, sticky="ew", pady=(0, 10)) + control_frame.columnconfigure(0, weight=1) + control_frame.columnconfigure(1, weight=0) + control_frame.columnconfigure(2, weight=0) + + task_count_label = ttk.Label(control_frame, text="0 tasks", style="SubHeader.TLabel") + task_count_label.grid(row=0, column=0, sticky="w") + + refresh_button = ttk.Button(control_frame, text="Refresh", style="Secondary.TButton") + refresh_button.grid(row=0, column=1, sticky="e", padx=(0, 8)) + + help_button = ttk.Button(control_frame, text="Help", style="Secondary.TButton") + help_button.grid(row=0, column=2, sticky="e") + + list_frame = ttk.Frame(container, style="Card.TFrame", padding=12) + list_frame.grid(row=3, column=0, sticky="nsew") + list_frame.columnconfigure(0, weight=1) + list_frame.rowconfigure(0, weight=1) + + task_table = ttk.Treeview( + list_frame, + columns=("date", "time", "task"), + show="headings", + style="Task.Treeview", + selectmode="browse", + height=14, + ) + task_table.heading("date", text="Date") + task_table.heading("time", text="Time") + task_table.heading("task", text="Task") + task_table.column("date", width=100, anchor="center") + task_table.column("time", width=80, anchor="center") + task_table.column("task", anchor="w") + task_table.grid(row=0, column=0, sticky="nsew") + + scrollbar = ttk.Scrollbar(list_frame, orient="vertical", command=task_table.yview) + scrollbar.grid(row=0, column=1, sticky="ns", padx=(8, 0)) + task_table.configure(yscrollcommand=scrollbar.set) + + empty_state = ttk.Label( + list_frame, + text="No tasks yet. Click Add Task to create your first item.", + style="SubHeader.TLabel", + anchor="center" + ) + empty_state.grid(row=0, column=0, sticky="nsew") + + def _update_empty_state(): + has_tasks = len(task_table.get_children()) > 0 + empty_state.lift() if not has_tasks else empty_state.lower() + + def refresh_task_list(): + task_table.delete(*task_table.get_children()) + for index, entry in enumerate(connector.list_tasks()): + date, time = split_due_date(entry.due_date) + tag = "evenrow" if index % 2 == 0 else "oddrow" + task_table.insert("", tk.END, values=(date, time, entry.title), tags=(tag,)) + + task_table.tag_configure("evenrow", background="#ffffff") + task_table.tag_configure("oddrow", background="#f8fafc") + task_count_label.configure(text=f"{len(task_table.get_children())} tasks") + _update_empty_state() + + def open_add_task_dialog(event=None): + dialog = AddTaskDialog(root) + if not dialog.result: + return + + date, time, title = dialog.result + if connector.add_task(date, time, title): + refresh_task_list() + + def show_help(): + help_text = ( + "Enter a date in YYYY-MM-DD format, a time in HH:MM format,\n" + "and a short task title. Use Add Task to save it. \n" + "Refresh updates the task list when changes occur." + ) + help_dialog = tk.Toplevel(root) + help_dialog.title("Help") + help_dialog.resizable(False, False) + help_frame = ttk.Frame(help_dialog, padding=16) + help_frame.grid(row=0, column=0) + ttk.Label(help_frame, text="How to use SchedPlus", font=("Segoe UI", 12, "bold")).grid(row=0, column=0, sticky="w", pady=(0, 10)) + ttk.Label(help_frame, text=help_text, font=("Segoe UI", 10), foreground="#374151", justify="left").grid(row=1, column=0, sticky="w") + ttk.Button(help_frame, text="Close", command=help_dialog.destroy, style="Accent.TButton").grid(row=2, column=0, pady=(14, 0), sticky="e") + help_dialog.grab_set() + help_dialog.transient(root) + help_dialog.wait_window() + + add_button.configure(command=open_add_task_dialog) + refresh_button.configure(command=refresh_task_list) + help_button.configure(command=show_help) + + root.bind("", open_add_task_dialog) + root.bind("", lambda event: refresh_task_list()) + + refresh_task_list() + root.mainloop() diff --git a/src/ui/tk/utils.py b/src/ui/tk/utils.py new file mode 100644 index 0000000..696fd3f --- /dev/null +++ b/src/ui/tk/utils.py @@ -0,0 +1,29 @@ +""" +utils.py +-------- +Small helper functions shared across Tkinter UI files. +""" + +def split_due_date(due_date: str) -> tuple[str, str]: + """ + Convert ISO 'YYYY-MM-DDTHH:MM' → ('YYYY-MM-DD', 'HH:MM'). + + Returns empty strings if the input is missing or malformed. + """ + if not due_date: + return ("", "") + + if "T" not in due_date: + return ("", "") + + date, time = due_date.split("T", 1) + return (date, time) + + +def build_due_date(date: str, time: str) -> str: + """ + Build ISO timestamp from separate date + time fields. + + Does not validate the values — validation happens in the connector/UI. + """ + return f"{date}T{time}" diff --git a/src/ui/tkinter_ui.py b/src/ui/tkinter_ui.py index b642504..05d36e7 100644 --- a/src/ui/tkinter_ui.py +++ b/src/ui/tkinter_ui.py @@ -1,10 +1,9 @@ """ -tkinter_ui.py (v0.5) --------------------- -Improved teaching Tkinter UI for SchedPlus. +tkinter_ui.py (v0.5 - DB compatible MVP) +---------------------------------------- +Minimal compatibility update for the new DB-backed scheduler. -Still intentionally simple, but with cleaner layout, -better spacing, and more readable structure. +Full UI overhaul will happen in a separate issue. """ import tkinter as tk @@ -16,21 +15,17 @@ def run_ui(scheduler): root = tk.Tk() root.title("SchedPlus v0.5 (Tkinter)") - # Center window root.geometry("420x420") - # --- Main container --- container = ttk.Frame(root, padding=15) container.grid(row=0, column=0, sticky="nsew") root.columnconfigure(0, weight=1) root.rowconfigure(0, weight=1) - # --- Heading --- heading = ttk.Label(container, text="Add a Task", font=("Segoe UI", 12, "bold")) heading.grid(row=0, column=0, columnspan=2, pady=(0, 10)) - # --- Input fields --- ttk.Label(container, text="Date (YYYY-MM-DD):").grid(row=1, column=0, sticky="w", pady=3) date_entry = ttk.Entry(container, width=25) date_entry.grid(row=1, column=1, sticky="ew", pady=3) @@ -43,11 +38,9 @@ def run_ui(scheduler): task_entry = ttk.Entry(container, width=25) task_entry.grid(row=3, column=1, sticky="ew", pady=3) - # --- Add Task button --- add_button = ttk.Button(container, text="Add Task") add_button.grid(row=4, column=0, columnspan=2, pady=(10, 15)) - # --- Task list frame --- list_frame = ttk.LabelFrame(container, text="Tasks", padding=10) list_frame.grid(row=5, column=0, columnspan=2, sticky="nsew") @@ -55,30 +48,34 @@ def run_ui(scheduler): list_frame.rowconfigure(0, weight=1) list_frame.columnconfigure(0, weight=1) - # --- Task list --- task_list = tk.Listbox(list_frame, width=50, height=10, borderwidth=1, relief="solid") task_list.grid(row=0, column=0, sticky="nsew") - # Populate existing tasks - for task in scheduler.get_tasks(): - task_list.insert(tk.END, f"{task.date} {task.time} - {task.text}") + # --- Populate tasks from DB --- + for entry in scheduler.list_tasks(): + # entry.due_date is ISO: "YYYY-MM-DDTHH:MM" + date, time = _split_due_date(entry.due_date) + task_list.insert(tk.END, f"{date} {time} - {entry.title}") # --- Add Task logic --- def add_task(): date = date_entry.get().strip() time = time_entry.get().strip() - text = task_entry.get().strip() + title = task_entry.get().strip() - if date and time and text: - scheduler.add_task(date, time, text) - new_task = scheduler.get_tasks()[-1] + if date and time and title: + due_date = f"{date}T{time}" - task_list.insert(tk.END, f"{new_task.date} {new_task.time} - {new_task.text}") + scheduler.add_task( + title=title, + description=None, + due_date=due_date, + ) - try: - scheduler.save_tasks() - except Exception: - pass + new_entry = scheduler.list_tasks()[-1] + new_date, new_time = _split_due_date(new_entry.due_date) + + task_list.insert(tk.END, f"{new_date} {new_time} - {new_entry.title}") task_entry.delete(0, tk.END) @@ -86,3 +83,12 @@ def add_task(): bind_enter_key([date_entry, time_entry, task_entry], add_task) root.mainloop() + + +def _split_due_date(due_date: str): + """ + Helper: Convert ISO "YYYY-MM-DDTHH:MM" → ("YYYY-MM-DD", "HH:MM") + """ + if due_date and "T" in due_date: + return due_date.split("T", 1) + return ("", "") diff --git a/temp_notes.md b/temp_notes.md index 734344d..c72e84a 100644 --- a/temp_notes.md +++ b/temp_notes.md @@ -1,11 +1,11 @@ -> [!NOTE] -> **ZFordDev Standard: Temp Notes** -> -> This file is included in every repository as part of the ZFordDev ecosystem -> standards. It provides a safe local-only space for scratch notes, planning, -> and quick thoughts while working. -> -> This file is ignored by Git (see `.gitignore`) and will never be committed -> or pushed to the repository. - -# ***NOTES*** +> [!NOTE] +> **ZFordDev Standard: Temp Notes** +> +> This file is included in every repository as part of the ZFordDev ecosystem +> standards. It provides a safe local-only space for scratch notes, planning, +> and quick thoughts while working. +> +> This file is ignored by Git (see `.gitignore`) and will never be committed +> or pushed to the repository. + +# ***NOTES***