Compare commits

...

2 commits

Author SHA1 Message Date
0862ce7fd6
Say just 'once' (not 'once (today)') in reminders, now that we can set the specific date
All checks were successful
CI / test (push) Successful in 9m23s
Lint / test (push) Successful in 37s
Trivy / test (push) Successful in 20s
2025-12-10 18:27:15 +11:00
61b3e5b45a
Code comments 2025-12-09 12:48:59 +11:00
13 changed files with 32 additions and 32 deletions

View file

@ -1301,7 +1301,7 @@ class DBManager:
cur = self.conn.cursor() cur = self.conn.cursor()
if granularity == "none": if granularity == "none":
# No grouping one row per time_log record # No grouping - one row per time_log record
rows = cur.execute( rows = cur.execute(
""" """
SELECT SELECT

View file

@ -112,7 +112,7 @@ class TodaysDocumentsWidget(QFrame):
if project_name: if project_name:
extra_parts.append(project_name) extra_parts.append(project_name)
if extra_parts: if extra_parts:
label = f"{file_name} " + " · ".join(extra_parts) label = f"{file_name} - " + " · ".join(extra_parts)
item = QListWidgetItem(label) item = QListWidgetItem(label)
item.setData( item.setData(

View file

@ -418,7 +418,7 @@ class InvoiceDialog(QDialog):
hours = minutes / 60.0 hours = minutes / 60.0
# Hours editable via spin box (override allowed) # Hours - editable via spin box (override allowed)
hours_spin = QDoubleSpinBox() hours_spin = QDoubleSpinBox()
hours_spin.setRange(0, 24) hours_spin.setRange(0, 24)
hours_spin.setDecimals(2) hours_spin.setDecimals(2)
@ -457,7 +457,7 @@ class InvoiceDialog(QDialog):
descr_parts = [date_str, activity] descr_parts = [date_str, activity]
if note: if note:
descr_parts.append(note) descr_parts.append(note)
descr = " ".join(descr_parts) descr = " - ".join(descr_parts)
hours_widget = self.table.cellWidget(r, self.COL_HOURS) hours_widget = self.table.cellWidget(r, self.COL_HOURS)
hours = ( hours = (
@ -567,10 +567,10 @@ class InvoiceDialog(QDialog):
details = self._db.get_client_by_company(text) details = self._db.get_client_by_company(text)
if not details: if not details:
# New client leave other fields as-is # New client - leave other fields as-is
return return
# We don't touch the company combo text user already chose/typed it. # We don't touch the company combo text - user already chose/typed it.
client_name, client_company, client_address, client_email = details client_name, client_company, client_address, client_email = details
if client_name: if client_name:
self.client_name_edit.setText(client_name) self.client_name_edit.setText(client_name)
@ -609,7 +609,7 @@ class InvoiceDialog(QDialog):
else InvoiceDetailMode.SUMMARY else InvoiceDetailMode.SUMMARY
) )
# Build line items + collect time_log_ids # Build line items & collect time_log_ids
if detail_mode == InvoiceDetailMode.DETAILED: if detail_mode == InvoiceDetailMode.DETAILED:
items = self._detail_line_items() items = self._detail_line_items()
time_log_ids: list[int] = [] time_log_ids: list[int] = []
@ -631,7 +631,7 @@ class InvoiceDialog(QDialog):
) )
return return
# Rate + tax info # Rate & tax info
rate_cents = int(round(self.rate_spin.value() * 100)) rate_cents = int(round(self.rate_spin.value() * 100))
currency = self.currency_edit.text().strip() currency = self.currency_edit.text().strip()
tax_label = self.tax_label_edit.text().strip() or None tax_label = self.tax_label_edit.text().strip() or None
@ -715,7 +715,7 @@ class InvoiceDialog(QDialog):
doc = QTextDocument() doc = QTextDocument()
# 🔹 Load company profile *before* building HTML # Load company profile before building HTML
profile = self._db.get_company_profile() profile = self._db.get_company_profile()
self._company_profile = None self._company_profile = None
if profile: if profile:
@ -1178,7 +1178,7 @@ class InvoicesDialog(QDialog):
row_idx, self.COL_TAX_RATE, QTableWidgetItem(tax_rate_text) row_idx, self.COL_TAX_RATE, QTableWidgetItem(tax_rate_text)
) )
# Column 79: amounts (cents → dollars) # Column 7-9: amounts (cents → dollars)
self.table.setItem( self.table.setItem(
row_idx, row_idx,
self.COL_SUBTOTAL, self.COL_SUBTOTAL,
@ -1441,7 +1441,7 @@ class InvoicesDialog(QDialog):
self._db.set_invoice_field_by_id(inv_id, field, cents) self._db.set_invoice_field_by_id(inv_id, field, cents)
# Normalize formatting in the table # Normalise formatting in the table
self._reloading_invoices = True self._reloading_invoices = True
try: try:
item.setText(f"{cents / 100.0:.2f}") item.setText(f"{cents / 100.0:.2f}")

View file

@ -306,7 +306,7 @@
"reminder": "Reminder", "reminder": "Reminder",
"reminders": "Reminders", "reminders": "Reminders",
"time": "Time", "time": "Time",
"once_today": "Once (today)", "once": "Once",
"every_day": "Every day", "every_day": "Every day",
"every_weekday": "Every weekday (Mon-Fri)", "every_weekday": "Every weekday (Mon-Fri)",
"every_week": "Every week", "every_week": "Every week",

View file

@ -274,7 +274,7 @@
"weekly": "hebdomadaire", "weekly": "hebdomadaire",
"edit_reminder": "Modifier le rappel", "edit_reminder": "Modifier le rappel",
"time": "Heure", "time": "Heure",
"once_today": "Une fois (aujourd'hui)", "once": "Une fois (aujourd'hui)",
"every_day": "Tous les jours", "every_day": "Tous les jours",
"every_weekday": "Tous les jours de semaine (lun-ven)", "every_weekday": "Tous les jours de semaine (lun-ven)",
"every_week": "Toutes les semaines", "every_week": "Toutes les semaines",

View file

@ -496,7 +496,7 @@ class MainWindow(QMainWindow):
idx = self._tab_index_for_date(date) idx = self._tab_index_for_date(date)
if idx != -1: if idx != -1:
self.tab_widget.setCurrentIndex(idx) self.tab_widget.setCurrentIndex(idx)
# keep calendar selection in sync (dont trigger load) # keep calendar selection in sync (don't trigger load)
from PySide6.QtCore import QSignalBlocker from PySide6.QtCore import QSignalBlocker
with QSignalBlocker(self.calendar): with QSignalBlocker(self.calendar):
@ -519,7 +519,7 @@ class MainWindow(QMainWindow):
editor = MarkdownEditor(self.themes) editor = MarkdownEditor(self.themes)
# Apply users preferred font size # Apply user's preferred font size
self._apply_font_size(editor) self._apply_font_size(editor)
# Set up the editor's event connections # Set up the editor's event connections

View file

@ -382,7 +382,7 @@ class MarkdownEditor(QTextEdit):
cursor.removeSelectedText() cursor.removeSelectedText()
cursor.insertText("\n" + new_text + "\n") cursor.insertText("\n" + new_text + "\n")
else: else:
# Empty block keep one blank line inside the fences # Empty block - keep one blank line inside the fences
cursor.removeSelectedText() cursor.removeSelectedText()
cursor.insertText("\n\n") cursor.insertText("\n\n")
cursor.endEditBlock() cursor.endEditBlock()
@ -789,7 +789,7 @@ class MarkdownEditor(QTextEdit):
""" """
# When the user is actively dragging with the mouse, we *do* want the # When the user is actively dragging with the mouse, we *do* want the
# checkbox/bullet to be part of the selection (for deleting whole rows). # checkbox/bullet to be part of the selection (for deleting whole rows).
# So dont rewrite the selection in that case. # So don't rewrite the selection in that case.
if getattr(self, "_mouse_drag_selecting", False): if getattr(self, "_mouse_drag_selecting", False):
return return
@ -863,7 +863,7 @@ class MarkdownEditor(QTextEdit):
): ):
return ("checkbox", f"{self._CHECK_UNCHECKED_DISPLAY} ") return ("checkbox", f"{self._CHECK_UNCHECKED_DISPLAY} ")
# Bullet list Unicode bullet # Bullet list - Unicode bullet
if line.startswith(f"{self._BULLET_DISPLAY} "): if line.startswith(f"{self._BULLET_DISPLAY} "):
return ("bullet", f"{self._BULLET_DISPLAY} ") return ("bullet", f"{self._BULLET_DISPLAY} ")
@ -1055,7 +1055,7 @@ class MarkdownEditor(QTextEdit):
# of list prefixes (checkboxes / bullets / numbers). # of list prefixes (checkboxes / bullets / numbers).
if event.key() in (Qt.Key.Key_Home, Qt.Key.Key_Left): if event.key() in (Qt.Key.Key_Home, Qt.Key.Key_Left):
# Let Ctrl+Home / Ctrl+Left keep their usual meaning (start of # Let Ctrl+Home / Ctrl+Left keep their usual meaning (start of
# document / word-left) we don't interfere with those. # document / word-left) - we don't interfere with those.
if event.modifiers() & Qt.ControlModifier: if event.modifiers() & Qt.ControlModifier:
pass pass
else: else:
@ -1367,7 +1367,7 @@ class MarkdownEditor(QTextEdit):
cursor = self.cursorForPosition(event.pos()) cursor = self.cursorForPosition(event.pos())
block = cursor.block() block = cursor.block()
# If were on or inside a code block, open the editor instead # If we're on or inside a code block, open the editor instead
if self._is_inside_code_block(block) or block.text().strip().startswith("```"): if self._is_inside_code_block(block) or block.text().strip().startswith("```"):
# Only swallow the double-click if we actually opened a dialog. # Only swallow the double-click if we actually opened a dialog.
if not self._edit_code_block(block): if not self._edit_code_block(block):

View file

@ -133,7 +133,7 @@ class PomodoroManager:
if hasattr(time_log_widget, "show_pomodoro_widget"): if hasattr(time_log_widget, "show_pomodoro_widget"):
time_log_widget.show_pomodoro_widget(self._active_timer) time_log_widget.show_pomodoro_widget(self._active_timer)
else: else:
# Fallback just attach it as a child widget # Fallback - just attach it as a child widget
self._active_timer.setParent(time_log_widget) self._active_timer.setParent(time_log_widget)
self._active_timer.show() self._active_timer.show()

View file

@ -107,7 +107,7 @@ class ReminderDialog(QDialog):
# Recurrence type # Recurrence type
self.type_combo = QComboBox() self.type_combo = QComboBox()
self.type_combo.addItem(strings._("once_today"), ReminderType.ONCE) self.type_combo.addItem(strings._("once"), ReminderType.ONCE)
self.type_combo.addItem(strings._("every_day"), ReminderType.DAILY) self.type_combo.addItem(strings._("every_day"), ReminderType.DAILY)
self.type_combo.addItem(strings._("every_weekday"), ReminderType.WEEKDAYS) self.type_combo.addItem(strings._("every_weekday"), ReminderType.WEEKDAYS)
self.type_combo.addItem(strings._("every_week"), ReminderType.WEEKLY) self.type_combo.addItem(strings._("every_week"), ReminderType.WEEKLY)
@ -484,7 +484,7 @@ class UpcomingRemindersWidget(QFrame):
offset = (target_dow - first.dayOfWeek() + 7) % 7 offset = (target_dow - first.dayOfWeek() + 7) % 7
candidate = first.addDays(offset + anchor_n * 7) candidate = first.addDays(offset + anchor_n * 7)
# If that nth weekday doesnt exist this month (e.g. 5th Monday), skip # If that nth weekday doesn't exist this month (e.g. 5th Monday), skip
if candidate.month() != date.month(): if candidate.month() != date.month():
return False return False

View file

@ -246,7 +246,7 @@ class SettingsDialog(QDialog):
self.company_payment_details_edit, self.company_payment_details_edit,
) )
# Logo picker store bytes on self._logo_bytes # Logo picker - store bytes on self._logo_bytes
self._logo_bytes = logo_bytes self._logo_bytes = logo_bytes
logo_row = QHBoxLayout() logo_row = QHBoxLayout()
self.logo_label = QLabel(strings._("invoice_company_logo_not_set")) self.logo_label = QLabel(strings._("invoice_company_logo_not_set"))

View file

@ -216,7 +216,7 @@ class DateHeatmap(QWidget):
col = int((x - self._margin_left) // cell_span) # week index col = int((x - self._margin_left) // cell_span) # week index
row = int((y - self._margin_top) // cell_span) # dow (0..6) row = int((y - self._margin_top) // cell_span) # dow (0..6)
# Only 7 rows (MonSun) # Only 7 rows (Mon-Sun)
if not (0 <= row < 7): if not (0 <= row < 7):
return return

View file

@ -270,7 +270,7 @@ class TimeLogDialog(QDialog):
self._date_iso = date_iso self._date_iso = date_iso
self._current_entry_id: Optional[int] = None self._current_entry_id: Optional[int] = None
self.cfg = load_db_config() self.cfg = load_db_config()
# Guard flag used when repopulating the table so we dont treat # Guard flag used when repopulating the table so we don't treat
# programmatic item changes as user edits. # programmatic item changes as user edits.
self._reloading_entries: bool = False self._reloading_entries: bool = False
@ -620,7 +620,7 @@ class TimeLogDialog(QDialog):
hours_item = self.table.item(row, 3) hours_item = self.table.item(row, 3)
if proj_item is None or act_item is None or hours_item is None: if proj_item is None or act_item is None or hours_item is None:
# Incomplete row nothing to do. # Incomplete row - nothing to do.
return return
# Recover the entry id from the hidden UserRole on the project cell # Recover the entry id from the hidden UserRole on the project cell
@ -829,7 +829,7 @@ class TimeCodeManagerDialog(QDialog):
try: try:
self._db.add_project(name) self._db.add_project(name)
except ValueError: except ValueError:
# Empty / invalid name nothing to do, but be defensive # Empty / invalid name - nothing to do, but be defensive
QMessageBox.warning( QMessageBox.warning(
self, self,
strings._("invalid_project_title"), strings._("invalid_project_title"),
@ -1193,7 +1193,7 @@ class TimeReportDialog(QDialog):
end = today end = today
elif preset == "last_week": elif preset == "last_week":
# Compute MondaySunday of the previous week (Monday-based weeks) # Compute Monday-Sunday of the previous week (Monday-based weeks)
# 1. Monday of this week: # 1. Monday of this week:
start_of_this_week = today.addDays(1 - today.dayOfWeek()) start_of_this_week = today.addDays(1 - today.dayOfWeek())
# 2. Last week is 7 days before that: # 2. Last week is 7 days before that:
@ -1208,7 +1208,7 @@ class TimeReportDialog(QDialog):
start = QDate(today.year(), 1, 1) start = QDate(today.year(), 1, 1)
end = today end = today
else: # "custom" leave fields as user-set else: # "custom" - leave fields as user-set
return return
# Update date edits without triggering anything else # Update date edits without triggering anything else
@ -1284,7 +1284,7 @@ class TimeReportDialog(QDialog):
# no note column # no note column
self.table.setItem(i, 3, QTableWidgetItem(f"{hrs:.2f}")) self.table.setItem(i, 3, QTableWidgetItem(f"{hrs:.2f}"))
# Summary label include per-project totals when in "all projects" mode # Summary label - include per-project totals when in "all projects" mode
total_hours = self._last_total_minutes / 60.0 total_hours = self._last_total_minutes / 60.0
if self._last_all_projects: if self._last_all_projects:
per_project_bits = [ per_project_bits = [

View file

@ -3,7 +3,7 @@
set -eo pipefail set -eo pipefail
# Clean caches etc # Clean caches etc
/home/user/venv-guardutils/bin/filedust -y . filedust -y .
# Publish to Pypi # Publish to Pypi
poetry build poetry build