~ubuntu-branches/ubuntu/vivid/frescobaldi/vivid

« back to all changes in this revision

Viewing changes to frescobaldi_app/snippet/model.py

  • Committer: Package Import Robot
  • Author(s): Ryan Kavanagh
  • Date: 2012-01-03 16:20:11 UTC
  • mfrom: (1.4.1)
  • Revision ID: package-import@ubuntu.com-20120103162011-tsjkwl4sntwmprea
Tags: 2.0.0-1
* New upstream release 
* Drop the following uneeded patches:
  + 01_checkmodules_no_python-kde4_build-dep.diff
  + 02_no_pyc.diff
  + 04_no_binary_lilypond_upgrades.diff
* Needs new dependency python-poppler-qt4
* Update debian/watch for new download path
* Update copyright file with new holders and years

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# This file is part of the Frescobaldi project, http://www.frescobaldi.org/
 
2
#
 
3
# Copyright (c) 2008 - 2011 by Wilbert Berendsen
 
4
#
 
5
# This program is free software; you can redistribute it and/or
 
6
# modify it under the terms of the GNU General Public License
 
7
# as published by the Free Software Foundation; either version 2
 
8
# of the License, or (at your option) any later version.
 
9
#
 
10
# This program is distributed in the hope that it will be useful,
 
11
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
# GNU General Public License for more details.
 
14
#
 
15
# You should have received a copy of the GNU General Public License
 
16
# along with this program; if not, write to the Free Software
 
17
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
18
# See http://www.gnu.org/licenses/ for more information.
 
19
 
 
20
"""
 
21
The model containing the snippets data.
 
22
"""
 
23
 
 
24
 
 
25
from __future__ import unicode_literals
 
26
 
 
27
import bisect
 
28
 
 
29
from PyQt4.QtCore import QAbstractItemModel, QModelIndex, Qt
 
30
from PyQt4.QtGui import QKeySequence
 
31
 
 
32
import app
 
33
import actioncollection
 
34
 
 
35
from . import snippets
 
36
 
 
37
 
 
38
def model():
 
39
    """Returns the global model containing snippets."""
 
40
    m = SnippetModel(app.qApp)
 
41
    global model
 
42
    model = lambda: m
 
43
    return m
 
44
 
 
45
 
 
46
class SnippetModel(QAbstractItemModel):
 
47
    """Presents the snippets as a Qt Model."""
 
48
    def __init__(self, parent = None):
 
49
        super(SnippetModel, self).__init__(parent)
 
50
        self._names = []
 
51
        self.load()
 
52
        app.settingsChanged.connect(self.slotSettingsChanged)
 
53
        app.languageChanged.connect(self.slotLanguageChanged)
 
54
        
 
55
    # methods needed to be a well-behaved model
 
56
    def headerData(self, section, orientation, role=Qt.DisplayRole):
 
57
        if role == Qt.DisplayRole and orientation == Qt.Horizontal:
 
58
            if section == 0:
 
59
                return _("Name")
 
60
            elif section == 1:
 
61
                return _("Description")
 
62
            else:
 
63
                return _("Shortcut")
 
64
    
 
65
    def index(self, row, column, parent=None):
 
66
        return self.createIndex(row, column)
 
67
    
 
68
    def parent(self, index):
 
69
        return QModelIndex()
 
70
    
 
71
    def columnCount(self, parent=QModelIndex()):
 
72
        return 3 if not parent.isValid() else 0
 
73
    
 
74
    def rowCount(self, parent=QModelIndex()):
 
75
        return len(self._names) if not parent.isValid() else 0
 
76
    
 
77
    def data(self, index, role=Qt.DisplayRole):
 
78
        name = self.name(index)
 
79
        if role == Qt.DisplayRole:
 
80
            if index.column() == 0:
 
81
                return snippets.get(name).variables.get('name')
 
82
            elif index.column() == 1:
 
83
                return snippets.title(name)
 
84
            else:
 
85
                return shortcut(name)
 
86
        elif role == Qt.DecorationRole and index.column() == 1:
 
87
            return snippets.icon(name)
 
88
    
 
89
    # slots
 
90
    def slotSettingsChanged(self):
 
91
        """Called when settings change, e.g. when keyboard shortcuts are altered."""
 
92
        self.load()
 
93
        
 
94
    def slotLanguageChanged(self):
 
95
        """Called when the user changes the language."""
 
96
        self.headerDataChanged.emit(Qt.Horizontal, 0, 2)
 
97
        
 
98
    def load(self):
 
99
        self.beginResetModel()
 
100
        self._names = sorted(snippets.names(), key=snippets.title)
 
101
        self.endResetModel()
 
102
    
 
103
    # interface for getting/altering snippets
 
104
    def names(self):
 
105
        """Returns the internal list of snippet names in title order. Do not alter!"""
 
106
        return self._names
 
107
        
 
108
    def name(self, index):
 
109
        """The internal snippet id for the given QModelIndex."""
 
110
        return self._names[index.row()]
 
111
 
 
112
    def removeRows(self, row, count, parent=QModelIndex()):
 
113
        end = row + count
 
114
        self.beginRemoveRows(parent, row, end)
 
115
        try:
 
116
            for name in self._names[row:end]:
 
117
                snippets.delete(name)
 
118
            del self._names[row:end]
 
119
        finally:
 
120
            self.endRemoveRows()
 
121
            return True
 
122
        
 
123
    def saveSnippet(self, name, text, title):
 
124
        """Store a snippet.
 
125
        
 
126
        If name is None or does not exist in names(), a new snippet is created.
 
127
        Returns the QModelIndex the snippet was stored at.
 
128
        
 
129
        Title may be None.
 
130
        
 
131
        """
 
132
        # first, get the old titles list
 
133
        titles = list(snippets.title(n) for n in self._names)
 
134
        
 
135
        oldrow = None
 
136
        if name is None:
 
137
            name = snippets.name(self._names)
 
138
        else:
 
139
            try:
 
140
                oldrow = self._names.index(name)
 
141
            except ValueError:
 
142
                pass
 
143
        snippets.save(name, text, title)
 
144
        # sort the new snippet in
 
145
        # if oldrow is not None, it is the row to be removed.
 
146
        title = snippets.title(name)
 
147
        i = bisect.bisect_right(titles, title)
 
148
        
 
149
        if oldrow is None:
 
150
            # just insert new snippet
 
151
            self.beginInsertRows(QModelIndex(), i, i )
 
152
            self._names.insert(i, name)
 
153
            self.endInsertRows()
 
154
            return self.createIndex(i, 0)
 
155
        elif i in (oldrow, oldrow+1):
 
156
            # just replace
 
157
            self._names[oldrow] = name
 
158
            self.dataChanged.emit(self.createIndex(oldrow, 0), self.createIndex(oldrow, 2))
 
159
            return self.createIndex(oldrow, 0)
 
160
        else:
 
161
            # move the old row to the new place
 
162
            if self.beginMoveRows(QModelIndex(), oldrow, oldrow, QModelIndex(), i):
 
163
                del self._names[oldrow]
 
164
                if i > oldrow:
 
165
                    i -= 1
 
166
                self._names.insert(i, name)
 
167
                self.endMoveRows()
 
168
                self.dataChanged.emit(self.createIndex(i, 0), self.createIndex(i, 2))
 
169
                return self.createIndex(i, 0)
 
170
            raise RuntimeError("wrong row move offset")
 
171
 
 
172
 
 
173
def shortcut(name):
 
174
    """Returns a shortcut text for the named snippets, if any, else None."""
 
175
    s = shortcuts(name)
 
176
    if s:
 
177
        text = s[0].toString(QKeySequence.NativeText)
 
178
        if len(s) > 1:
 
179
            text += "..."
 
180
        return text
 
181
 
 
182
 
 
183
def shortcuts(name):
 
184
    """Returns a (maybe empty) list of QKeySequences for the named snippet."""
 
185
    ac = collection()
 
186
    return ac and ac.shortcuts(name) or []
 
187
 
 
188
 
 
189
def collection():
 
190
    """Returns an instance of the 'snippets' ShortcutCollection, if existing."""
 
191
    try:
 
192
        # HACK alert :-) access an instance of the ShortcutCollection named 'snippets'
 
193
        ref = actioncollection.ShortcutCollection.others['snippets'][0]
 
194
    except (KeyError, IndexError):
 
195
        return
 
196
    return ref()
 
197
 
 
198