Compare commits
2 commits
81878c63d9
...
0862ce7fd6
| Author | SHA1 | Date | |
|---|---|---|---|
| 0862ce7fd6 | |||
| 61b3e5b45a |
13 changed files with 32 additions and 32 deletions
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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(
|
||||||
|
|
|
||||||
|
|
@ -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 7–9: 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}")
|
||||||
|
|
|
||||||
|
|
@ -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",
|
||||||
|
|
|
||||||
|
|
@ -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",
|
||||||
|
|
|
||||||
|
|
@ -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 (don’t 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 user’s 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
|
||||||
|
|
|
||||||
|
|
@ -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 don’t 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 we’re 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):
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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 doesn’t 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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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"))
|
||||||
|
|
|
||||||
|
|
@ -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 (Mon–Sun)
|
# Only 7 rows (Mon-Sun)
|
||||||
if not (0 <= row < 7):
|
if not (0 <= row < 7):
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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 don’t 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 Monday–Sunday 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 = [
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue