Compare commits

...

2 commits

Author SHA1 Message Date
7d58acfc7d
remove unneeded import since calendar theming now fully moved to theme.py
Some checks failed
CI / test (push) Failing after 5m9s
Lint / test (push) Successful in 32s
Trivy / test (push) Successful in 22s
2025-12-01 10:20:20 +11:00
22b4cf4da7
Allow changing the date when logging time (rather than having to go to that date before clicking on adding time log/opening time log manager) 2025-12-01 10:19:41 +11:00
6 changed files with 93 additions and 23 deletions

View file

@ -2,6 +2,7 @@
* Add + button to time log widget in side bar to have a simplified log entry dialog (without summary or report option) * Add + button to time log widget in side bar to have a simplified log entry dialog (without summary or report option)
* Allow click-and-drag mouse select on lines with checkbox, to capture the checkbox as well as the text. * Allow click-and-drag mouse select on lines with checkbox, to capture the checkbox as well as the text.
* Allow changing the date when logging time (rather than having to go to that date before clicking on adding time log/opening time log manager)
# 0.5.4 # 0.5.4

View file

@ -236,6 +236,8 @@
"time_log": "Time log", "time_log": "Time log",
"time_log_collapsed_hint": "Time log", "time_log_collapsed_hint": "Time log",
"time_log_date_label": "Time log date: {date}", "time_log_date_label": "Time log date: {date}",
"time_log_change_date": "Change date",
"time_log_select_date_title": "Select time log date",
"time_log_for": "Time log for {date}", "time_log_for": "Time log for {date}",
"time_log_no_date": "Time log", "time_log_no_date": "Time log",
"time_log_no_entries": "No time entries yet", "time_log_no_entries": "No time entries yet",

View file

@ -27,7 +27,6 @@ from PySide6.QtGui import (
QFont, QFont,
QGuiApplication, QGuiApplication,
QKeySequence, QKeySequence,
QTextCharFormat,
QTextCursor, QTextCursor,
QTextListFormat, QTextListFormat,
) )
@ -108,7 +107,7 @@ class MainWindow(QMainWindow):
self.search.resultDatesChanged.connect(self._on_search_dates_changed) self.search.resultDatesChanged.connect(self._on_search_dates_changed)
# Features # Features
self.time_log = TimeLogWidget(self.db) self.time_log = TimeLogWidget(self.db, themes=self.themes)
self.tags = PageTagsWidget(self.db) self.tags = PageTagsWidget(self.db)
self.tags.tagActivated.connect(self._on_tag_activated) self.tags.tagActivated.connect(self._on_tag_activated)
@ -342,7 +341,6 @@ class MainWindow(QMainWindow):
# re-apply all runtime color tweaks when theme changes # re-apply all runtime color tweaks when theme changes
self.themes.themeChanged.connect(lambda _t: self._retheme_overrides()) self.themes.themeChanged.connect(lambda _t: self._retheme_overrides())
self._apply_calendar_text_colors()
# apply once on startup so links / calendar colors are set immediately # apply once on startup so links / calendar colors are set immediately
self._retheme_overrides() self._retheme_overrides()
@ -1020,22 +1018,10 @@ class MainWindow(QMainWindow):
save_db_config(cfg) save_db_config(cfg)
def _retheme_overrides(self): def _retheme_overrides(self):
self._apply_calendar_text_colors()
self._apply_search_highlights(getattr(self, "_search_highlighted_dates", set())) self._apply_search_highlights(getattr(self, "_search_highlighted_dates", set()))
self.calendar.update() self.calendar.update()
self.editor.viewport().update() self.editor.viewport().update()
def _apply_calendar_text_colors(self):
pal = QApplication.instance().palette()
txt = pal.windowText().color()
fmt = QTextCharFormat()
fmt.setForeground(txt)
# Use normal text color for weekends
self.calendar.setWeekdayTextFormat(Qt.Saturday, fmt)
self.calendar.setWeekdayTextFormat(Qt.Sunday, fmt)
# --------------- Search sidebar/results helpers ---------------- # # --------------- Search sidebar/results helpers ---------------- #
def _on_search_dates_changed(self, date_strs: list[str]): def _on_search_dates_changed(self, date_strs: list[str]):

View file

@ -137,7 +137,9 @@ class PomodoroManager:
hours = 0.25 hours = 0.25
# Open time log dialog # Open time log dialog
dlg = TimeLogDialog(self._db, date_iso, self._parent, True) dlg = TimeLogDialog(
self._db, date_iso, self._parent, True, themes=self._parent.themes
)
# Pre-fill the hours # Pre-fill the hours
dlg.hours_spin.setValue(hours) dlg.hours_spin.setValue(hours)

View file

@ -1,9 +1,9 @@
from __future__ import annotations from __future__ import annotations
from dataclasses import dataclass from dataclasses import dataclass
from enum import Enum from enum import Enum
from PySide6.QtGui import QPalette, QColor, QGuiApplication from PySide6.QtGui import QPalette, QColor, QGuiApplication, QTextCharFormat
from PySide6.QtWidgets import QApplication, QCalendarWidget, QWidget from PySide6.QtWidgets import QApplication, QCalendarWidget, QWidget
from PySide6.QtCore import QObject, Signal from PySide6.QtCore import QObject, Signal, Qt
from weakref import WeakSet from weakref import WeakSet
@ -174,6 +174,14 @@ class ThemeManager(QObject):
cal.setPalette(app_pal) cal.setPalette(app_pal)
cal.setStyleSheet("") cal.setStyleSheet("")
# --- Normalise weekend colours on *all* themed calendars -------------
# Qt's default is red for weekends; we want them to match normal text.
weekday_color = app_pal.windowText().color()
weekend_fmt = QTextCharFormat()
weekend_fmt.setForeground(weekday_color)
cal.setWeekdayTextFormat(Qt.Saturday, weekend_fmt)
cal.setWeekdayTextFormat(Qt.Sunday, weekend_fmt)
cal.update() cal.update()
def _calendar_qss(self, highlight_css: str) -> str: def _calendar_qss(self, highlight_css: str) -> str:

View file

@ -11,7 +11,9 @@ from PySide6.QtCore import Qt, QDate, QUrl
from PySide6.QtGui import QPainter, QColor, QImage, QTextDocument, QPageLayout from PySide6.QtGui import QPainter, QColor, QImage, QTextDocument, QPageLayout
from PySide6.QtPrintSupport import QPrinter from PySide6.QtPrintSupport import QPrinter
from PySide6.QtWidgets import ( from PySide6.QtWidgets import (
QCalendarWidget,
QDialog, QDialog,
QDialogButtonBox,
QFrame, QFrame,
QVBoxLayout, QVBoxLayout,
QHBoxLayout, QHBoxLayout,
@ -40,6 +42,7 @@ from PySide6.QtWidgets import (
) )
from .db import DBManager from .db import DBManager
from .theme import ThemeManager
from . import strings from . import strings
@ -49,9 +52,15 @@ class TimeLogWidget(QFrame):
Shown in the left sidebar above the Tags widget. Shown in the left sidebar above the Tags widget.
""" """
def __init__(self, db: DBManager, parent: QWidget | None = None): def __init__(
self,
db: DBManager,
themes: ThemeManager | None = None,
parent: QWidget | None = None,
):
super().__init__(parent) super().__init__(parent)
self._db = db self._db = db
self._themes = themes
self._current_date: Optional[str] = None self._current_date: Optional[str] = None
self.setFrameShape(QFrame.StyledPanel) self.setFrameShape(QFrame.StyledPanel)
@ -162,7 +171,7 @@ class TimeLogWidget(QFrame):
if not self._current_date: if not self._current_date:
return return
dlg = TimeLogDialog(self._db, self._current_date, self) dlg = TimeLogDialog(self._db, self._current_date, self, themes=self._themes)
dlg.exec() dlg.exec()
# Always refresh summary + header totals # Always refresh summary + header totals
@ -175,7 +184,9 @@ class TimeLogWidget(QFrame):
if not self._current_date: if not self._current_date:
return return
dlg = TimeLogDialog(self._db, self._current_date, self, True) dlg = TimeLogDialog(
self._db, self._current_date, self, True, themes=self._themes
)
dlg.exec() dlg.exec()
# Always refresh summary + header totals # Always refresh summary + header totals
@ -202,9 +213,11 @@ class TimeLogDialog(QDialog):
date_iso: str, date_iso: str,
parent=None, parent=None,
log_entry_only: bool | None = False, log_entry_only: bool | None = False,
themes: ThemeManager | None = None,
): ):
super().__init__(parent) super().__init__(parent)
self._db = db self._db = db
self._themes = themes
self._date_iso = date_iso self._date_iso = date_iso
self._current_entry_id: Optional[int] = None self._current_entry_id: Optional[int] = None
# Guard flag used when repopulating the table so we dont treat # Guard flag used when repopulating the table so we dont treat
@ -216,8 +229,20 @@ class TimeLogDialog(QDialog):
root = QVBoxLayout(self) root = QVBoxLayout(self)
# --- Top: date label # --- Top: date label + change-date button
root.addWidget(QLabel(strings._("time_log_date_label").format(date=date_iso))) date_row = QHBoxLayout()
self.date_label = QLabel(strings._("time_log_date_label").format(date=date_iso))
date_row.addWidget(self.date_label)
date_row.addStretch(1)
# You can i18n this later if you like
self.change_date_btn = QPushButton(strings._("time_log_change_date"))
self.change_date_btn.clicked.connect(self._on_change_date_clicked)
date_row.addWidget(self.change_date_btn)
root.addLayout(date_row)
# --- Project / activity / hours row # --- Project / activity / hours row
form = QFormLayout() form = QFormLayout()
@ -370,6 +395,52 @@ class TimeLogDialog(QDialog):
# ----- Actions ----------------------------------------------------- # ----- Actions -----------------------------------------------------
def _on_change_date_clicked(self) -> None:
"""Let the user choose a different date and reload entries."""
# Start from current dialog date; fall back to today if invalid
current_qdate = QDate.fromString(self._date_iso, Qt.ISODate)
if not current_qdate.isValid():
current_qdate = QDate.currentDate()
dlg = QDialog(self)
dlg.setWindowTitle(strings._("time_log_select_date_title"))
layout = QVBoxLayout(dlg)
calendar = QCalendarWidget(dlg)
calendar.setSelectedDate(current_qdate)
layout.addWidget(calendar)
# Apply the same theming as the main sidebar calendar
if self._themes is not None:
self._themes.register_calendar(calendar)
buttons = QDialogButtonBox(
QDialogButtonBox.Ok | QDialogButtonBox.Cancel, parent=dlg
)
buttons.accepted.connect(dlg.accept)
buttons.rejected.connect(dlg.reject)
layout.addWidget(buttons)
if dlg.exec() != QDialog.Accepted:
return
new_qdate = calendar.selectedDate()
new_iso = new_qdate.toString(Qt.ISODate)
if new_iso == self._date_iso:
# No change
return
# Update state
self._date_iso = new_iso
# Update window title and header label
self.setWindowTitle(strings._("time_log_for").format(date=new_iso))
self.date_label.setText(strings._("time_log_date_label").format(date=new_iso))
# Reload entries for the newly selected date
self._reload_entries()
def _ensure_project_id(self) -> Optional[int]: def _ensure_project_id(self) -> Optional[int]:
"""Get selected project_id from combo.""" """Get selected project_id from combo."""
idx = self.project_combo.currentIndex() idx = self.project_combo.currentIndex()