From 83f25405db09648518f0abf16c5206b2a1e645da Mon Sep 17 00:00:00 2001 From: Miguel Jacq Date: Tue, 18 Nov 2025 20:38:39 +1100 Subject: [PATCH] Add ability to set alarm reminders --- CHANGELOG.md | 1 + README.md | 7 + bouquin/locales/en.json | 9 +- bouquin/main_window.py | 191 +++++++++++++++++- bouquin/markdown_editor.py | 29 +++ bouquin/tag_graph_dialog.py | 2 +- bouquin/toolbar.py | 9 + .../bouquin_tag_relationship_graph.png | Bin 0 -> 30181 bytes 8 files changed, 241 insertions(+), 7 deletions(-) create mode 100644 screenshots/bouquin_tag_relationship_graph.png diff --git a/CHANGELOG.md b/CHANGELOG.md index f668299..5109618 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ * Add Tag relationship visualisation tool * Improve size of checkboxes * Convert bullet - to actual unicode bullets + * Add alarm option to set reminders # 0.3.2 diff --git a/README.md b/README.md index 2df84cf..b241452 100644 --- a/README.md +++ b/README.md @@ -16,10 +16,16 @@ report from within the app. ## Screenshots +### General view ![Screenshot of Bouquin](https://git.mig5.net/mig5/bouquin/raw/branch/main/screenshots/screenshot.png) + +### History panes ![Screenshot of Bouquin History Preview pane](https://git.mig5.net/mig5/bouquin/raw/branch/main/screenshots/history_preview.png) ![Screenshot of Bouquin History Diff pane](https://git.mig5.net/mig5/bouquin/raw/branch/main/screenshots/history_diff.png) +### Tag relationship visualiser +![Screenshot of Tag Relationship Visualiser](https://git.mig5.net/mig5/bouquin/raw/branch/main/screenshots/bouquin_tag_relationship_graph.png) + ## Features * Data is encrypted at rest @@ -41,6 +47,7 @@ report from within the app. * Automatically generate checkboxes when typing 'TODO' * It is possible to automatically move unchecked checkboxes from yesterday to today, on startup * English, French and Italian locales provided + * Ability to set reminder alarms in the app against the current line of text on today's date ## How to install diff --git a/bouquin/locales/en.json b/bouquin/locales/en.json index 19cf85d..69bb0b4 100644 --- a/bouquin/locales/en.json +++ b/bouquin/locales/en.json @@ -155,5 +155,12 @@ "bug_report_empty": "Please enter some details about the bug before sending.", "bug_report_send_failed": "Could not send bug report.", "bug_report_sent_ok": "Bug report sent. Thank you!", - "send": "Send" + "send": "Send", + "set_reminder": "Set reminder prompt", + "set_reminder_prompt": "Enter a time", + "reminder_no_text_fallback": "You scheduled a reminder to alert you now!", + "invalid_time_title": "Invalid time", + "invalid_time_message": "Please enter a time in the format HH:MM", + "dismiss": "Dismiss", + "toolbar_alarm": "Set reminder alarm" } diff --git a/bouquin/main_window.py b/bouquin/main_window.py index 59581fb..0763f29 100644 --- a/bouquin/main_window.py +++ b/bouquin/main_window.py @@ -16,6 +16,8 @@ from PySide6.QtCore import ( QUrl, QEvent, QSignalBlocker, + QDateTime, + QTime, ) from PySide6.QtGui import ( QAction, @@ -43,6 +45,10 @@ from PySide6.QtWidgets import ( QTabWidget, QVBoxLayout, QWidget, + QInputDialog, + QLabel, + QPushButton, + QApplication, ) from .db import DBManager @@ -164,8 +170,6 @@ class MainWindow(QMainWindow): self._locked = False # reset idle timer on any key press anywhere in the app - from PySide6.QtWidgets import QApplication - QApplication.instance().installEventFilter(self) # Focus on the editor @@ -292,7 +296,9 @@ class MainWindow(QMainWindow): self._save_timer = QTimer(self) self._save_timer.setSingleShot(True) self._save_timer.timeout.connect(self._save_current) - # Note: textChanged will be connected per-editor in _create_new_tab + + # Reminders / alarms + self._reminder_timers: list[QTimer] = [] # First load + mark dates in calendar with content if not self._load_yesterday_todos(): @@ -310,6 +316,9 @@ class MainWindow(QMainWindow): # apply once on startup so links / calendar colors are set immediately self._retheme_overrides() + # Build any alarms for *today* from stored markdown + self._rebuild_reminders_for_today() + @property def editor(self) -> MarkdownEditor | None: """Get the currently active editor.""" @@ -966,6 +975,7 @@ class MainWindow(QMainWindow): self._tb_bullets = lambda: self._call_editor("toggle_bullets") self._tb_numbers = lambda: self._call_editor("toggle_numbers") self._tb_checkboxes = lambda: self._call_editor("toggle_checkboxes") + self._tb_alarm = self._on_alarm_requested tb.boldRequested.connect(self._tb_bold) tb.italicRequested.connect(self._tb_italic) @@ -975,9 +985,9 @@ class MainWindow(QMainWindow): tb.bulletsRequested.connect(self._tb_bullets) tb.numbersRequested.connect(self._tb_numbers) tb.checkboxesRequested.connect(self._tb_checkboxes) - - tb.historyRequested.connect(self._open_history) + tb.alarmRequested.connect(self._tb_alarm) tb.insertImageRequested.connect(self._on_insert_image) + tb.historyRequested.connect(self._open_history) self._toolbar_bound = True @@ -1023,6 +1033,177 @@ class MainWindow(QMainWindow): self.toolBar.actBullets.setChecked(bool(bullets_on)) self.toolBar.actNumbers.setChecked(bool(numbers_on)) + # ----------- Alarms handler ------------# + def _on_alarm_requested(self): + """Create a one-shot reminder based on the current line in the editor.""" + editor = getattr(self, "editor", None) + if editor is None: + return + + # Use the current line in the markdown editor as the reminder text + try: + line_text = editor.get_current_line_text().strip() + except AttributeError: + c = editor.textCursor() + line_text = c.block().text().strip() + + # Ask user for a time today in HH:MM format + time_str, ok = QInputDialog.getText( + self, + strings._("set_reminder"), + strings._("set_reminder_prompt") + " (HH:MM)", + ) + if not ok or not time_str.strip(): + return + + try: + hour, minute = map(int, time_str.strip().split(":", 1)) + except ValueError: + QMessageBox.warning( + self, + strings._("invalid_time_title"), + strings._("invalid_time_message"), + ) + return + + now = QDateTime.currentDateTime() + target = QDateTime(now.date(), QTime(hour, minute)) + + t = QTime(hour, minute) + if not t.isValid(): + QMessageBox.warning( + self, + strings._("invalid_time_title"), + strings._("invalid_time_message"), + ) + return + + # Normalise to HH:MM + time_str = f"{t.hour():02d}:{t.minute():02d}" + + # Insert / update ⏰ in the editor text + if hasattr(editor, "insert_alarm_marker"): + editor.insert_alarm_marker(time_str) + + # Rebuild timers, but only if this page is for "today" + self._rebuild_reminders_for_today() + + def _show_flashing_reminder(self, text: str): + """ + Show a small flashing dialog and request attention from the OS. + Called by reminder timers. + """ + # Ask OS to flash / bounce our app in the dock/taskbar + QApplication.alert(self, 0) + + # Try to bring the window to the front + self.showNormal() + self.raise_() + self.activateWindow() + + # Simple dialog with a flashing background to reinforce the alert + dlg = QDialog(self) + dlg.setWindowTitle(strings._("reminder")) + dlg.setModal(True) + + layout = QVBoxLayout(dlg) + label = QLabel(text) + label.setWordWrap(True) + layout.addWidget(label) + + btn = QPushButton(strings._("dismiss")) + btn.clicked.connect(dlg.accept) + layout.addWidget(btn) + + flash_timer = QTimer(dlg) + flash_state = {"on": False} + + def toggle(): + flash_state["on"] = not flash_state["on"] + if flash_state["on"]: + dlg.setStyleSheet("background-color: #3B3B3B;") + else: + dlg.setStyleSheet("") + + flash_timer.timeout.connect(toggle) + flash_timer.start(500) # ms + + dlg.exec() + + flash_timer.stop() + + def _clear_reminder_timers(self): + """Stop and delete any existing reminder timers.""" + for t in self._reminder_timers: + try: + t.stop() + t.deleteLater() + except Exception: + pass + self._reminder_timers = [] + + def _rebuild_reminders_for_today(self): + """ + Scan the markdown for today's date and create QTimers + only for alarms on the *current day* (system date). + """ + # We only ever set timers for the real current date + today = QDate.currentDate() + today_iso = today.toString("yyyy-MM-dd") + + # Clear any previously scheduled "today" reminders + self._clear_reminder_timers() + + # Prefer live editor content if it is showing today's page + text = "" + if ( + hasattr(self, "editor") + and hasattr(self.editor, "current_date") + and self.editor.current_date == today + ): + text = self.editor.to_markdown() + else: + # Fallback to DB: still only today's date + text = self.db.get_entry(today_iso) if hasattr(self, "db") else "" + + if not text: + return + + now = QDateTime.currentDateTime() + + for line in text.splitlines(): + # Look for "⏰ HH:MM" anywhere in the line + m = re.search(r"⏰\s*(\d{1,2}):(\d{2})", line) + if not m: + continue + + hour = int(m.group(1)) + minute = int(m.group(2)) + + t = QTime(hour, minute) + if not t.isValid(): + continue + + target = QDateTime(today, t) + + # Skip alarms that are already in the past + if target <= now: + continue + + # The reminder text is the part before the symbol + reminder_text = line.split("⏰", 1)[0].strip() + if not reminder_text: + reminder_text = strings._("reminder_no_text_fallback") + + msecs = now.msecsTo(target) + timer = QTimer(self) + timer.setSingleShot(True) + timer.timeout.connect( + lambda txt=reminder_text: self._show_flashing_reminder(txt) + ) + timer.start(msecs) + self._reminder_timers.append(timer) + # ----------- History handler ------------# def _open_history(self): if hasattr(self.editor, "current_date"): diff --git a/bouquin/markdown_editor.py b/bouquin/markdown_editor.py index 9212229..5cd357c 100644 --- a/bouquin/markdown_editor.py +++ b/bouquin/markdown_editor.py @@ -391,12 +391,41 @@ class MarkdownEditor(QTextEdit): cursor.setPosition(match.end(), QTextCursor.MoveMode.KeepAnchor) cursor.insertImage(img_format) + def insert_alarm_marker(self, time_str: str) -> None: + """ + Append or replace an ⏰ HH:MM marker on the current line. + time_str is expected to be 'HH:MM'. + """ + cursor = self.textCursor() + block = cursor.block() + line = block.text() + + # Strip any existing ⏰ HH:MM at the end of the line + new_line = re.sub(r"\s*⏰\s*\d{1,2}:\d{2}\s*$", "", line).rstrip() + + # Append the new marker + new_line = f"{new_line} ⏰ {time_str}" + + bc = QTextCursor(block) + bc.beginEditBlock() + bc.select(QTextCursor.SelectionType.BlockUnderCursor) + bc.insertText(new_line) + bc.endEditBlock() + + # Move cursor to end of the edited line + cursor.setPosition(block.position() + len(new_line)) + self.setTextCursor(cursor) + def _get_current_line(self) -> str: """Get the text of the current line.""" cursor = self.textCursor() cursor.select(QTextCursor.SelectionType.LineUnderCursor) return cursor.selectedText() + def get_current_line_text(self) -> str: + """Public wrapper used by MainWindow for reminders.""" + return self._get_current_line() + def _detect_list_type(self, line: str) -> tuple[str | None, str]: """ Detect if line is a list item. Returns (list_type, prefix). diff --git a/bouquin/tag_graph_dialog.py b/bouquin/tag_graph_dialog.py index ef2d0cc..a4065cb 100644 --- a/bouquin/tag_graph_dialog.py +++ b/bouquin/tag_graph_dialog.py @@ -281,7 +281,7 @@ class TagGraphDialog(QDialog): # Update labels for i, label in enumerate(self._label_items): - label.setPos(float(pos[i, 0]), float(pos[i, 1]) + 0.30) + label.setPos(float(pos[i, 0]), float(pos[i, 1]) + 0.15) # Update halo positions to match nodes if self._halo_sizes and self._halo_brushes: diff --git a/bouquin/toolbar.py b/bouquin/toolbar.py index 89999b8..9764246 100644 --- a/bouquin/toolbar.py +++ b/bouquin/toolbar.py @@ -18,6 +18,7 @@ class ToolBar(QToolBar): checkboxesRequested = Signal() historyRequested = Signal() insertImageRequested = Signal() + alarmRequested = Signal() def __init__(self, parent=None): super().__init__(strings._("toolbar_format"), parent) @@ -85,6 +86,11 @@ class ToolBar(QToolBar): self.actCheckboxes.setToolTip(strings._("toolbar_toggle_checkboxes")) self.actCheckboxes.triggered.connect(self.checkboxesRequested) + # Alarm / reminder + self.actAlarm = QAction("⏰", self) + self.actAlarm.setToolTip(strings._("toolbar_alarm")) + self.actAlarm.triggered.connect(self.alarmRequested) + # Images self.actInsertImg = QAction(strings._("images"), self) self.actInsertImg.setToolTip(strings._("insert_images")) @@ -129,6 +135,7 @@ class ToolBar(QToolBar): self.actBullets, self.actNumbers, self.actCheckboxes, + self.actAlarm, self.actInsertImg, self.actHistory, ] @@ -151,6 +158,8 @@ class ToolBar(QToolBar): # Lists self._style_letter_button(self.actBullets, "•") self._style_letter_button(self.actNumbers, "1.") + self._style_letter_button(self.actCheckboxes, "☐") + self._style_letter_button(self.actAlarm, "⏰") # History self._style_letter_button(self.actHistory, strings._("view_history")) diff --git a/screenshots/bouquin_tag_relationship_graph.png b/screenshots/bouquin_tag_relationship_graph.png new file mode 100644 index 0000000000000000000000000000000000000000..083bf6afa9e72e178435a38e69f90e110fb8b7b6 GIT binary patch literal 30181 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 literal 0 HcmV?d00001