File: tagedit.py

package info (click to toggle)
anki 2.1.8%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 5,976 kB
  • sloc: python: 26,992; xml: 67; sh: 49; makefile: 45
file content (115 lines) | stat: -rw-r--r-- 4,010 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# Copyright: Damien Elmes <anki@ichi2.net>
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html

from aqt.qt import *
import re

class TagEdit(QLineEdit):

    lostFocus = pyqtSignal()

    # 0 = tags, 1 = decks
    def __init__(self, parent, type=0):
        QLineEdit.__init__(self, parent)
        self.col = None
        self.model = QStringListModel()
        self.type = type
        if type == 0:
            self.completer = TagCompleter(self.model, parent, self)
        else:
            self.completer = QCompleter(self.model, parent)
        self.completer.setCompletionMode(QCompleter.PopupCompletion)
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        self.setCompleter(self.completer)

    def setCol(self, col):
        "Set the current col, updating list of available tags."
        self.col = col
        if self.type == 0:
            l = sorted(self.col.tags.all())
        else:
            l = sorted(self.col.decks.allNames())
        self.model.setStringList(l)

    def focusInEvent(self, evt):
        QLineEdit.focusInEvent(self, evt)

    def keyPressEvent(self, evt):
        if evt.key() in (Qt.Key_Up, Qt.Key_Down):
            # show completer on arrow key up/down
            if not self.completer.popup().isVisible():
                self.showCompleter()
            return
        if (evt.key() == Qt.Key_Tab and evt.modifiers() & Qt.ControlModifier):
            # select next completion
            if not self.completer.popup().isVisible():
                self.showCompleter()
            index = self.completer.currentIndex()
            self.completer.popup().setCurrentIndex(index)
            cur_row = index.row()
            if not self.completer.setCurrentRow(cur_row + 1):
                self.completer.setCurrentRow(0)
            return
        if evt.key() in (Qt.Key_Enter, Qt.Key_Return):
            # apply first completion if no suggestion selected
            selected_row = self.completer.popup().currentIndex().row()
            if selected_row == -1:
                self.completer.setCurrentRow(0)
                index = self.completer.currentIndex()
                self.completer.popup().setCurrentIndex(index)
            self.hideCompleter()
            QWidget.keyPressEvent(self, evt)
            return
        QLineEdit.keyPressEvent(self, evt)
        if not evt.text():
            # if it's a modifier, don't show
            return
        if evt.key() not in (
            Qt.Key_Enter, Qt.Key_Return, Qt.Key_Escape, Qt.Key_Space,
            Qt.Key_Tab, Qt.Key_Backspace, Qt.Key_Delete):
            self.showCompleter()

    def showCompleter(self):
        self.completer.setCompletionPrefix(self.text())
        self.completer.complete()

    def focusOutEvent(self, evt):
        QLineEdit.focusOutEvent(self, evt)
        self.lostFocus.emit()
        self.completer.popup().hide()

    def hideCompleter(self):
        if sip.isdeleted(self.completer):
            return
        self.completer.popup().hide()

class TagCompleter(QCompleter):

    def __init__(self, model, parent, edit, *args):
        QCompleter.__init__(self, model, parent)
        self.tags = []
        self.edit = edit
        self.cursor = None

    def splitPath(self, tags):
        stripped_tags = tags.strip()
        stripped_tags = re.sub("  +", " ", stripped_tags)
        self.tags = self.edit.col.tags.split(stripped_tags)
        self.tags.append("")
        p = self.edit.cursorPosition()
        if tags.endswith("  "):
            self.cursor = len(self.tags) - 1
        else:
            self.cursor = stripped_tags.count(" ", 0, p)
        return [self.tags[self.cursor]]

    def pathFromIndex(self, idx):
        if self.cursor is None:
            return self.edit.text()
        ret = QCompleter.pathFromIndex(self, idx)
        self.tags[self.cursor] = ret
        try:
            self.tags.remove("")
        except ValueError:
            pass
        return " ".join(self.tags) + " "