1
# This file is part of the Frescobaldi project, http://www.frescobaldi.org/
3
# Copyright (c) 2008 - 2011 by Wilbert Berendsen
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.
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.
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.
21
Import and export of snippets.
24
from __future__ import unicode_literals
29
import xml.etree.cElementTree as ET
31
import xml.etree.ElementTree as ET
33
from PyQt4.QtCore import *
34
from PyQt4.QtGui import *
42
from . import snippets
46
def save(names, filename):
47
"""Saves the named snippets to a file."""
48
root = ET.Element('snippets')
51
d = ET.ElementTree(root)
53
comment = ET.Comment(_comment.format(info=info))
58
snippet = ET.Element('snippet')
59
snippet.set('id', name)
63
title = ET.Element('title')
64
title.text = snippets.title(name, False)
67
shortcuts = ET.Element('shortcuts')
68
ss = model.shortcuts(name)
72
shortcut = ET.Element('shortcut')
73
shortcut.text = s.toString()
75
shortcuts.append(shortcut)
78
body = ET.Element('body')
79
body.text = snippets.text(name)
83
snippet.append(shortcuts)
86
d.write(filename, "UTF-8")
89
def load(filename, widget):
90
"""Loads snippets from a file, displaying them in a list.
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.
99
d = ET.parse(filename)
100
elements = list(d.findall('snippet'))
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))
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)
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)
119
new = QTreeWidgetItem(tree, [_("New Snippets")])
120
updated = QTreeWidgetItem(tree, [_("Updated Snippets")])
121
unchanged = QTreeWidgetItem(tree, [_("Unchanged Snippets")])
123
new.setFlags(Qt.ItemIsEnabled)
124
updated.setFlags(Qt.ItemIsEnabled)
125
unchanged.setFlags(Qt.ItemIsEnabled)
127
new.setExpanded(True)
128
updated.setExpanded(True)
131
for snip in elements:
132
item = QTreeWidgetItem()
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'))
138
title = item.title or snippets.maketitle(snippets.parse(item.body).text)
139
item.setText(0, title)
141
name = snip.get('id')
142
name = name if name in builtins else None
145
# determine if new, updated or unchanged
147
name = titles.get(title)
150
if not name or name not in allnames:
153
item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsUserCheckable)
154
item.setCheckState(0, Qt.Checked)
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)
162
item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsUserCheckable)
163
item.setCheckState(0, Qt.Checked)
165
unchanged.addChild(item)
166
item.setFlags(Qt.ItemIsEnabled)
168
for i in new, updated, unchanged:
169
i.setText(0, i.text(0) + " ({0})".format(i.childCount()))
170
for i in new, updated:
172
i.setFlags(Qt.ItemIsEnabled | Qt.ItemIsUserCheckable)
173
i.setCheckState(0, Qt.Checked)
176
if item in (new, updated):
177
for i in range(item.childCount()):
179
c.setCheckState(0, item.checkState(0))
181
tree.itemChanged.connect(changed)
183
importShortcuts = QTreeWidgetItem([_("Import Keyboard Shortcuts")])
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:"))
190
dlg.setMessage(_("There are no new or updated snippets in the file."))
191
unchanged.setExpanded(True)
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)))
201
util.saveDialogSize(dlg, "snippettool/import/size", QSize(400, 300))
202
if not dlg.exec_() or not items:
204
ac = model.collection()
206
with util.busyCursor():
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()
217
Created by {info.appname} {info.version}.
219
Every snippet is represented by:
221
shortcuts: list of shortcut elements, every shortcut is a key sequence
222
body: the snippet text
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.