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

« back to all changes in this revision

Viewing changes to frescobaldi_app/snippet/import_export.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
Import and export of snippets.
 
22
"""
 
23
 
 
24
from __future__ import unicode_literals
 
25
 
 
26
import os
 
27
 
 
28
try:
 
29
    import xml.etree.cElementTree as ET
 
30
except ImportError:
 
31
    import xml.etree.ElementTree as ET
 
32
 
 
33
from PyQt4.QtCore import *
 
34
from PyQt4.QtGui import *
 
35
 
 
36
import app
 
37
import info
 
38
import util
 
39
import widgets.dialog
 
40
 
 
41
from . import model
 
42
from . import snippets
 
43
from . import builtin
 
44
 
 
45
 
 
46
def save(names, filename):
 
47
    """Saves the named snippets to a file."""
 
48
    root = ET.Element('snippets')
 
49
    root.text = '\n\n'
 
50
    root.tail = '\n'
 
51
    d = ET.ElementTree(root)
 
52
    
 
53
    comment = ET.Comment(_comment.format(info=info))
 
54
    comment.tail = '\n\n'
 
55
    root.append(comment)
 
56
    
 
57
    for name in names:
 
58
        snippet = ET.Element('snippet')
 
59
        snippet.set('id', name)
 
60
        snippet.text = '\n'
 
61
        snippet.tail = '\n\n'
 
62
        
 
63
        title = ET.Element('title')
 
64
        title.text = snippets.title(name, False)
 
65
        title.tail = '\n'
 
66
        
 
67
        shortcuts = ET.Element('shortcuts')
 
68
        ss = model.shortcuts(name)
 
69
        if ss:
 
70
            shortcuts.text = '\n'
 
71
            for s in ss:
 
72
                shortcut = ET.Element('shortcut')
 
73
                shortcut.text = s.toString()
 
74
                shortcut.tail = '\n'
 
75
                shortcuts.append(shortcut)
 
76
        shortcuts.tail = '\n'
 
77
        
 
78
        body = ET.Element('body')
 
79
        body.text = snippets.text(name)
 
80
        body.tail = '\n'
 
81
        
 
82
        snippet.append(title)
 
83
        snippet.append(shortcuts)
 
84
        snippet.append(body)
 
85
        root.append(snippet)
 
86
    d.write(filename, "UTF-8")
 
87
 
 
88
 
 
89
def load(filename, widget):
 
90
    """Loads snippets from a file, displaying them in a list.
 
91
    
 
92
    The user can then choose:
 
93
    - overwrite builtin snippets or not
 
94
    - overwrite own snippets with same title or not
 
95
    - select and view snippets contents.
 
96
    
 
97
    """
 
98
    try:
 
99
        d = ET.parse(filename)
 
100
        elements = list(d.findall('snippet'))
 
101
        if not elements:
 
102
            raise ValueError(_("No snippets found."))
 
103
    except Exception as e:
 
104
        QMessageBox.critical(widget, app.caption(_("Error")),
 
105
        _("Can't read from source:\n\n{url}\n\n{error}").format(
 
106
            url=filename, error=e))
 
107
        return
 
108
 
 
109
 
 
110
    dlg = widgets.dialog.Dialog(widget)
 
111
    dlg.setWindowTitle(app.caption(_("dialog title", "Import Snippets")))
 
112
    tree = QTreeWidget(headerHidden=True, rootIsDecorated=False)
 
113
    dlg.setMainWidget(tree)
 
114
    
 
115
    allnames = frozenset(snippets.names())
 
116
    builtins = frozenset(builtin.builtin_snippets)
 
117
    titles = dict((snippets.title(n), n) for n in allnames if n not in builtins)
 
118
    
 
119
    new = QTreeWidgetItem(tree, [_("New Snippets")])
 
120
    updated = QTreeWidgetItem(tree, [_("Updated Snippets")])
 
121
    unchanged = QTreeWidgetItem(tree, [_("Unchanged Snippets")])
 
122
    
 
123
    new.setFlags(Qt.ItemIsEnabled)
 
124
    updated.setFlags(Qt.ItemIsEnabled)
 
125
    unchanged.setFlags(Qt.ItemIsEnabled)
 
126
    
 
127
    new.setExpanded(True)
 
128
    updated.setExpanded(True)
 
129
    
 
130
    items = []
 
131
    for snip in elements:
 
132
        item = QTreeWidgetItem()
 
133
        
 
134
        item.body = snip.find('body').text
 
135
        item.title = snip.find('title').text
 
136
        item.shortcuts = list(e.text for e in snip.findall('shortcuts/shortcut'))
 
137
        
 
138
        title = item.title or snippets.maketitle(snippets.parse(item.body).text)
 
139
        item.setText(0, title)
 
140
        
 
141
        name = snip.get('id')
 
142
        name = name if name in builtins else None
 
143
        
 
144
        
 
145
        # determine if new, updated or unchanged
 
146
        if not name:
 
147
            name = titles.get(title)
 
148
        item.name = name
 
149
        
 
150
        if not name or name not in allnames:
 
151
            new.addChild(item)
 
152
            items.append(item)
 
153
            item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsUserCheckable)
 
154
            item.setCheckState(0, Qt.Checked)
 
155
        elif name:
 
156
            if (item.body != snippets.text(name)
 
157
                or title != snippets.title(name)
 
158
                or (item.shortcuts and item.shortcuts != 
 
159
                    [s.toString() for s in model.shortcuts(name) or ()])):
 
160
                updated.addChild(item)
 
161
                items.append(item)
 
162
                item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsUserCheckable)
 
163
                item.setCheckState(0, Qt.Checked)
 
164
            else:
 
165
                unchanged.addChild(item)
 
166
                item.setFlags(Qt.ItemIsEnabled)
 
167
    # count:
 
168
    for i in new, updated, unchanged:
 
169
        i.setText(0, i.text(0) + " ({0})".format(i.childCount()))
 
170
    for i in new, updated:
 
171
        if i.childCount():
 
172
            i.setFlags(Qt.ItemIsEnabled | Qt.ItemIsUserCheckable)
 
173
            i.setCheckState(0, Qt.Checked)
 
174
    
 
175
    def changed(item):
 
176
        if item in (new, updated):
 
177
            for i in range(item.childCount()):
 
178
                c = item.child(i)
 
179
                c.setCheckState(0, item.checkState(0))
 
180
            
 
181
    tree.itemChanged.connect(changed)
 
182
    
 
183
    importShortcuts = QTreeWidgetItem([_("Import Keyboard Shortcuts")])
 
184
    if items:
 
185
        tree.addTopLevelItem(importShortcuts)
 
186
        importShortcuts.setFlags(Qt.ItemIsEnabled | Qt.ItemIsUserCheckable)
 
187
        importShortcuts.setCheckState(0, Qt.Checked)
 
188
        dlg.setMessage(_("Choose which snippets you want to import:"))
 
189
    else:
 
190
        dlg.setMessage(_("There are no new or updated snippets in the file."))
 
191
        unchanged.setExpanded(True)
 
192
    
 
193
    tree.setWhatsThis(_(
 
194
        "<p>Here the snippets from {filename} are displayed.</p>\n"
 
195
        "<p>If there are new or updated snippets, you can select or deselect "
 
196
        "them one by one, or all at once, using the checkbox of the group. "
 
197
        "Then click OK to import all the selected snippets.</p>\n"
 
198
        "<p>Existing, unchanged snippets can't be imported.</p>\n"
 
199
        ).format(filename=os.path.basename(filename)))
 
200
        
 
201
    util.saveDialogSize(dlg, "snippettool/import/size", QSize(400, 300))
 
202
    if not dlg.exec_() or not items:
 
203
        return
 
204
    ac = model.collection()
 
205
    m = model.model()
 
206
    with util.busyCursor():
 
207
        for i in items:
 
208
            if i.checkState(0) == Qt.Checked:
 
209
                index = m.saveSnippet(i.name, i.body, i.title)
 
210
                if i.shortcuts and importShortcuts.checkState(0):
 
211
                    shortcuts = list(map(QKeySequence.fromString, i.shortcuts))
 
212
                    ac.setShortcuts(m.name(index), shortcuts)
 
213
        widget.updateColumnSizes()
 
214
 
 
215
 
 
216
_comment = """
 
217
  Created by {info.appname} {info.version}.
 
218
  
 
219
  Every snippet is represented by:
 
220
    title:      title text
 
221
    shortcuts:  list of shortcut elements, every shortcut is a key sequence
 
222
    body:       the snippet text
 
223
  
 
224
  The snippet id attribute can be the name of a builtin snippet or a random
 
225
  name like 'n123456'. In the latter case, the title is used to determine
 
226
  whether a snippet is new or updated.
 
227
"""
 
228
 
 
229