From 45525371215830ace8fffb0243d671b5009be7a3 Mon Sep 17 00:00:00 2001 From: Miguel Jacq Date: Fri, 14 Nov 2025 13:31:55 +1100 Subject: [PATCH] Various bug fixes. * Prevent being able to left-click a date and have it load in current tab if it is already open in another tab * Avoid second checkbox/bullet on second newline after first newline * Avoid Home/left arrow jumping to the left side of a list symbol --- CHANGELOG.md | 3 +++ bouquin/main_window.py | 29 ++++++++++++++++++++++--- bouquin/markdown_editor.py | 44 +++++++++++++++++++++++++++++++++++++- 3 files changed, 72 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b62cb6e..b02f50b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,9 @@ * Add version information in the navigation * Increase line spacing between lines (except for code blocks) * Add Italian translations (thanks @mdaleo404) + * Prevent being able to left-click a date and have it load in current tab if it is already open in another tab + * Avoid second checkbox/bullet on second newline after first newline + * Avoid Home/left arrow jumping to the left side of a list symbol # 0.2.1.8 diff --git a/bouquin/main_window.py b/bouquin/main_window.py index 578852f..6814f8a 100644 --- a/bouquin/main_window.py +++ b/bouquin/main_window.py @@ -613,6 +613,20 @@ class MainWindow(QMainWindow): date_iso = self._current_date_iso() qd = QDate.fromString(date_iso, "yyyy-MM-dd") + current_index = self.tab_widget.currentIndex() + + # Check if this date is already open in a *different* tab + existing_idx = self._tab_index_for_date(qd) + if existing_idx != -1 and existing_idx != current_index: + # Date is already open in another tab - just switch to that tab + self.tab_widget.setCurrentIndex(existing_idx) + # Keep calendar in sync + with QSignalBlocker(self.calendar): + self.calendar.setSelectedDate(qd) + QTimer.singleShot(0, self._focus_editor_now) + return + + # Date not open in any other tab - load it into current tab # Keep calendar in sync with QSignalBlocker(self.calendar): self.calendar.setSelectedDate(qd) @@ -621,7 +635,6 @@ class MainWindow(QMainWindow): self.editor.current_date = qd # Update tab title - current_index = self.tab_widget.currentIndex() if current_index >= 0: self.tab_widget.setTabText(current_index, date_iso) @@ -765,13 +778,23 @@ class MainWindow(QMainWindow): prev_date_iso = self.editor.current_date.toString("yyyy-MM-dd") self._save_date(prev_date_iso, explicit=False) - # Now load the newly selected date into the current tab + # Now load the newly selected date new_date = self.calendar.selectedDate() + current_index = self.tab_widget.currentIndex() + + # Check if this date is already open in a *different* tab + existing_idx = self._tab_index_for_date(new_date) + if existing_idx != -1 and existing_idx != current_index: + # Date is already open in another tab - just switch to that tab + self.tab_widget.setCurrentIndex(existing_idx) + QTimer.singleShot(0, self._focus_editor_now) + return + + # Date not open in any other tab - load it into current tab self._load_date_into_editor(new_date) self.editor.current_date = new_date # Update tab title - current_index = self.tab_widget.currentIndex() if current_index >= 0: self.tab_widget.setTabText(current_index, new_date.toString("yyyy-MM-dd")) diff --git a/bouquin/markdown_editor.py b/bouquin/markdown_editor.py index bd2bb98..aaddb42 100644 --- a/bouquin/markdown_editor.py +++ b/bouquin/markdown_editor.py @@ -478,6 +478,46 @@ class MarkdownEditor(QTextEdit): self._update_code_block_row_backgrounds() return + # Handle Home and Left arrow keys to prevent going left of list markers + if event.key() in (Qt.Key.Key_Home, Qt.Key.Key_Left): + cursor = self.textCursor() + block = cursor.block() + line = block.text() + pos_in_block = cursor.position() - block.position() + + # Detect list prefix length + prefix_len = 0 + stripped = line.lstrip() + leading_spaces = len(line) - len(stripped) + + # Check for checkbox (Unicode display format) + if stripped.startswith( + f"{self._CHECK_UNCHECKED_DISPLAY} " + ) or stripped.startswith(f"{self._CHECK_CHECKED_DISPLAY} "): + prefix_len = leading_spaces + 2 # icon + space + # Check for bullet list + elif re.match(r"^[-*+]\s", stripped): + prefix_len = leading_spaces + 2 # marker + space + # Check for numbered list + elif re.match(r"^\d+\.\s", stripped): + match = re.match(r"^(\d+\.\s)", stripped) + if match: + prefix_len = leading_spaces + len(match.group(1)) + + if prefix_len > 0: + if event.key() == Qt.Key.Key_Home: + # Move to after the list marker + cursor.setPosition(block.position() + prefix_len) + self.setTextCursor(cursor) + return + elif event.key() == Qt.Key.Key_Left and pos_in_block <= prefix_len: + # Prevent moving left of the list marker + if pos_in_block > prefix_len: + # Allow normal left movement if we're past the prefix + super().keyPressEvent(event) + # Otherwise block the movement + return + # Handle Enter key for smart list continuation AND code blocks if event.key() == Qt.Key.Key_Return or event.key() == Qt.Key.Key_Enter: cursor = self.textCursor() @@ -559,8 +599,10 @@ class MarkdownEditor(QTextEdit): self._last_enter_was_empty = False return elif is_empty: - # First enter on empty list item - remember this + # First enter on empty list item - just insert newline without prefix + super().keyPressEvent(event) self._last_enter_was_empty = True + return else: # Not empty - continue the list self._last_enter_was_empty = False