Source code for entryline
# -*- coding: utf-8 -*-
# Copyright Martin Manns
# Distributed under the terms of the GNU General Public License
# --------------------------------------------------------------------
# pyspread is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# pyspread is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with pyspread. If not, see <http://www.gnu.org/licenses/>.
# --------------------------------------------------------------------
"""
**Provides**
* :class:`Entryline`
"""
from contextlib import contextmanager
from PyQt6.QtCore import Qt, QEvent
from PyQt6.QtGui import QTextOption, QKeyEvent
from PyQt6.QtWidgets import QWidget, QMainWindow
try:
import pyspread.commands as commands
from pyspread.lib.spelltextedit import SpellTextEdit
from pyspread.lib.string_helpers import quote
except ImportError:
import commands
from lib.spelltextedit import SpellTextEdit
from lib.string_helpers import quote
[docs]
class Entryline(SpellTextEdit):
"""The entry line for pyspread"""
def __init__(self, main_window: QMainWindow):
"""
:param main_window: Application main window
"""
font_family = main_window.settings.entry_line_font_family
super().__init__(line_numbers=False, font_family=font_family)
self.main_window = main_window
min_height = self.cursorRect().y() + self.cursorRect().height() + 20
self.setMinimumHeight(min_height)
self.setWordWrapMode(QTextOption.WrapMode.WrapAnywhere)
self.installEventFilter(self)
self.last_key = None
# self.highlighter.setDocument(self.document())
# Overrides
[docs]
def eventFilter(self, source: QWidget, event: QEvent):
"""Quotes editor content for <Ctrl>+<Enter> and <Ctrl>+<Return>
Overrides SpellTextEdit default shortcut. Counts as undoable action.
:param source: Source widget of event
:param event: Event to be filtered
"""
if event.type() == QEvent.Type.ShortcutOverride \
and event.modifiers() == Qt.KeyboardModifier.ControlModifier \
and source == self \
and event.key() in (Qt.Key.Key_Return, Qt.Key.Key_Enter):
focused_grid = self.main_window.focused_grid
code = quote(source.toPlainText())
index = focused_grid.currentIndex()
description = "Quote code for cell {}".format(index)
cmd = commands.SetCellCode(code, focused_grid.model, index,
description)
self.main_window.undo_stack.push(cmd)
focused_grid.setFocus()
focused_grid.selectionModel().clearSelection()
focused_grid.current = (focused_grid.row + 1, focused_grid.column,
focused_grid.table)
return False
return QWidget.eventFilter(self, source, event)
[docs]
@contextmanager
def disable_updates(self):
"""Disables updates and highlighter"""
doc = self.highlighter.document()
self.highlighter.setDocument(None)
self.main_window.entry_line.setUpdatesEnabled(False)
yield
self.main_window.entry_line.setUpdatesEnabled(True)
self.highlighter.setDocument(doc)
[docs]
def keyPressEvent(self, event: QKeyEvent):
"""Key press event filter
:param event: Key event
"""
grid = self.main_window.focused_grid
self.last_key = event.key()
if self.last_key in (Qt.Key.Key_Enter, Qt.Key.Key_Return):
if event.modifiers() == Qt.KeyboardModifier.ShiftModifier:
self.insertPlainText('\n')
else:
if grid.selection_mode:
grid.set_selection_mode(False)
else:
self.store_data()
grid.row += 1
elif self.last_key == Qt.Key.Key_Tab:
self.store_data()
grid.column += 1
elif self.last_key == Qt.Key.Key_Escape:
grid.on_current_changed()
grid.setFocus()
elif self.last_key == Qt.Key.Key_Insert:
grid.set_selection_mode(not grid.selection_mode)
else:
super().keyPressEvent(event)
[docs]
def store_data(self):
"""Stores current entry line data in grid model"""
grid = self.main_window.focused_grid
index = grid.currentIndex()
model = grid.model
description = "Set code for cell {}".format(index)
command = commands.SetCellCode(self.toPlainText(), model, index,
description)
self.main_window.undo_stack.push(command)
[docs]
def on_toggle_spell_check(self, signal: bool):
"""Spell check toggle event handler
:param signal: Spell check is enabled if True
"""
self.highlighter.enable_enchant = bool(signal)
[docs]
def setPlainText(self, text: str):
"""Overides setPlainText
Additionally shows busy cursor and disables highlighter on long texts,
and omits identical replace.
:param text: Text to be set
"""
is_long = (text is not None
and len(text) > self.main_window.settings.highlighter_limit)
if text == self.toPlainText():
return
if is_long:
with self.main_window.workflows.busy_cursor():
self.highlighter.setDocument(None)
super().setPlainText(text)
else:
super().setPlainText(text)