Anki/qt/aqt/browser/table/__init__.py
Ben Nguyen 931e1d80f2
Enable strict_optional in aqt/. and aqt/browser (#3486)
* Boolean naming convention

* Rename no_strict_optional -> strict_optional

* Update CONTRIBUTORS

* Enable strict optional for aqt module

* Fix errors

* Enable strict optional for aqt browser

* Fix layout.py errors

* Fix find_duplicates.py errors

* Fix browser.py errors

* Revert a0 a1 names

* Fix tree.py errors

* Fix previewer.py errors

* Fix model.py errors

* Fix find_and_replace.py errors

* Fix item.py errors

* Fix toolbar.py errors

* Fix table/__init__.py errors

* Fix model.py errors

* Fix state.py errors

* Fix table.py errors

* Fix errors in card_info.py

* Fix searchbar.py errors

* Fix name

* Fix assert in browser.py

* Formatting

* Fix assert vh

* assert is not None instead of truthy

* Split _move_current() up to correct type signature (dae)

We want either index or direction, but not both.
2024-10-11 23:12:48 +10:00

139 lines
4.3 KiB
Python

# Copyright: Ankitects Pty Ltd and contributors
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
from __future__ import annotations
import copy
import time
from collections.abc import Generator, Sequence
from dataclasses import dataclass
from typing import TYPE_CHECKING, Union
import aqt
import aqt.browser
from anki.cards import CardId
from anki.collection import BrowserColumns as Columns
from anki.collection import BrowserRow
from anki.notes import NoteId
from aqt import colors
from aqt.qt import QColor
from aqt.utils import tr
Column = Columns.Column
ItemId = Union[CardId, NoteId]
ItemList = Union[Sequence[CardId], Sequence[NoteId]]
@dataclass
class SearchContext:
search: str
browser: aqt.browser.Browser
order: bool | str | Column = True
reverse: bool = False
# if set, provided ids will be used instead of the regular search
ids: Sequence[ItemId] | None = None
class Cell:
def __init__(
self, text: str, is_rtl: bool, elide_mode: BrowserRow.Cell.TextElideMode.V
) -> None:
self.text: str = text
self.is_rtl: bool = is_rtl
self.elide_mode: aqt.Qt.TextElideMode = backend_elide_mode_to_aqt_elide_mode(
elide_mode
)
class CellRow:
is_disabled: bool = False
def __init__(
self,
cells: Generator[tuple[str, bool, BrowserRow.Cell.TextElideMode.V], None, None],
color: BrowserRow.Color.V,
font_name: str,
font_size: int,
) -> None:
self.refreshed_at: float = time.time()
self.cells: tuple[Cell, ...] = tuple(Cell(*cell) for cell in cells)
self.color: dict[str, str] | None = backend_color_to_aqt_color(color)
self.font_name: str = font_name or "arial"
self.font_size: int = font_size if font_size > 0 else 12
def is_stale(self, threshold: float) -> bool:
return self.refreshed_at < threshold
@staticmethod
def generic(length: int, cell_text: str) -> CellRow:
return CellRow(
((cell_text, False, BrowserRow.Cell.ElideRight) for cell in range(length)),
BrowserRow.COLOR_DEFAULT,
"arial",
12,
)
@staticmethod
def placeholder(length: int) -> CellRow:
return CellRow.generic(length, "...")
@staticmethod
def disabled(length: int, cell_text: str) -> CellRow:
row = CellRow.generic(length, cell_text)
row.is_disabled = True
return row
def backend_elide_mode_to_aqt_elide_mode(
elide_mode: BrowserRow.Cell.TextElideMode.V,
) -> aqt.Qt.TextElideMode:
if elide_mode == BrowserRow.Cell.ElideLeft:
return aqt.Qt.TextElideMode.ElideLeft
if elide_mode == BrowserRow.Cell.ElideMiddle:
return aqt.Qt.TextElideMode.ElideMiddle
if elide_mode == BrowserRow.Cell.ElideNone:
return aqt.Qt.TextElideMode.ElideNone
return aqt.Qt.TextElideMode.ElideRight
def backend_color_to_aqt_color(color: BrowserRow.Color.V) -> dict[str, str] | None:
temp_color = None
if color == BrowserRow.COLOR_MARKED:
temp_color = colors.STATE_MARKED
if color == BrowserRow.COLOR_SUSPENDED:
temp_color = colors.STATE_SUSPENDED
if color == BrowserRow.COLOR_BURIED:
temp_color = colors.STATE_BURIED
if color == BrowserRow.COLOR_FLAG_RED:
temp_color = colors.FLAG_1
if color == BrowserRow.COLOR_FLAG_ORANGE:
temp_color = colors.FLAG_2
if color == BrowserRow.COLOR_FLAG_GREEN:
temp_color = colors.FLAG_3
if color == BrowserRow.COLOR_FLAG_BLUE:
temp_color = colors.FLAG_4
if color == BrowserRow.COLOR_FLAG_PINK:
temp_color = colors.FLAG_5
if color == BrowserRow.COLOR_FLAG_TURQUOISE:
temp_color = colors.FLAG_6
if color == BrowserRow.COLOR_FLAG_PURPLE:
temp_color = colors.FLAG_7
return adjusted_bg_color(temp_color)
def adjusted_bg_color(color: dict[str, str] | None) -> dict[str, str] | None:
if color:
adjusted_color = copy.copy(color)
light = QColor(color["light"]).lighter(150)
adjusted_color["light"] = light.name()
dark = QColor(color["dark"]).darker(150)
adjusted_color["dark"] = dark.name()
return adjusted_color
else:
return None
from .model import DataModel
from .state import CardState, ItemState, NoteState
from .table import StatusDelegate, Table