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)
This commit is contained in:
parent
078f56a39b
commit
22b4cf4da7
6 changed files with 93 additions and 22 deletions
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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",
|
||||||
|
|
|
||||||
|
|
@ -108,7 +108,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 +342,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 +1019,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]):
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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 don’t treat
|
# Guard flag used when repopulating the table so we don’t 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()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue