Merge lp:~gero-bare/scratch/add-linter-support into lp:~elementary-apps/scratch/scratch
- add-linter-support
- Merge into scratch
Status: | Needs review | ||||
---|---|---|---|---|---|
Proposed branch: | lp:~gero-bare/scratch/add-linter-support | ||||
Merge into: | lp:~elementary-apps/scratch/scratch | ||||
Diff against target: |
1764 lines (+1684/-1) 11 files modified
plugins/CMakeLists.txt (+1/-0) plugins/linter-manager/CMakeLists.txt (+35/-0) plugins/linter-manager/ConfigurationDialog.vala (+330/-0) plugins/linter-manager/LinterManagerPlugin.vala (+481/-0) plugins/linter-manager/Settings.vala (+32/-0) plugins/linter-manager/icons/check_file.svg (+775/-0) plugins/linter-manager/icons/linter-manager.gresource.xml (+6/-0) plugins/linter-manager/linter-manager.plugin (+9/-0) schemas/CMakeLists.txt (+1/-0) schemas/org.pantheon.scratch.plugins.linter-manager.gschema.xml (+10/-0) src/Scratch.vala (+4/-1) |
||||
To merge this branch: | bzr merge lp:~gero-bare/scratch/add-linter-support | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Jeremy Wootten | ui/ux | Needs Fixing | |
Zisu Andrei (community) | Needs Fixing | ||
Review via email: mp+273938@code.launchpad.net |
Commit message
Description of the change
This add linter support, in a generic form.
You need a cli program to do processing and a regex to handle virtually any linter.
The command is simply any command you like plus
The regex uses "named" sub patterns: "line", "column", "type" of warning and the "message".
At the moment this linter manager support out of the box:
*python3 pep8
*npm jshint
*npm csslint
*html tidy
Additional features:
It has an icon. Yay.
Online help documentation (in github) https:/
Idk really...
deleted the "%u" none-sense
Missing features.
* No shortcut.
* No color/error markings in sourceview.
Things to check.
* Accepts files with spaces in the path.
* Doesn't crash messing with the configuration /deleting, resetting profiles.
* The documentation is good enough. (my engrish is not that good)
* Doesn't mess the bottom notebook with the terminal
* Click in the error resume brings up the correct file.
* Closing files close the resume
* Any gui design input ?
* Changing the Syntax highlight brings up the correct linter.
I think is "robust" enough by now.
Zisu Andrei (matzipan) wrote : | # |
Ok so I installed it. First of all, I think it should use another icon. Secondly, if I don't have any tabs open, if I click on the icon, I get:
[DEBUG 22:11:33.500717] LinterManagerPl
[FATAL 22:11:35.684459] scratch_
Segmentation fault (core dumped)
Also the configuration window could use a bit of visual improvement. Would it be possible to add it to Scratch's preferences dialog?
Also, maybe there should be an option to run lint on save?
Zisu Andrei (matzipan) wrote : | # |
Lots and lots of comments inline. It's not bad at all, just needs some grooming.
I haven't tested the functionality yet.
Jeremy Wootten (jeremywootten) wrote : | # |
On trying out the html linter I get two error messages, both for Line 0, Column 0:
1) Regex failure
2) Failed to execute child process "tidy" ....
until I installed the application "tidy". It would be better if an informative message or dialog was used to inform the user how to fix the problem.
Some work needs doing on the appearance of the configuration dialog in my opinion - needs UX team input.
Unmerged revisions
- 1567. By Gero.Bare
-
* Several code improvements due previus review.
- 1566. By Gero.Bare
-
Added online documentation
(for now linked to my github repo, later it should be maintained in the elementary side) - 1565. By Gero.Bare
-
* merge with the current branch to fix some conflicts
- 1564. By Gero.Bare
-
* Modified the command input, it no longer uses the %u wildcard
* Modified the regex format.
* Added new tooltips
* Fixed some minor bugs. - 1563. By Gero.Bare
-
Re-designed the linter output view in the editor.
- 1562. By Gero.Bare
-
Re done the design of the configuration dialog.
Addes some tooltips. - 1561. By Gero.Bare
-
Some minor changes.
- 1560. By Gero.Bare
-
* Added Icon for the plugin.
* Added the ability to copy linter messages to the clipboard.
* Fixed a crash. - 1559. By Gero.Bare
-
Add support for html tidy.
Now concatenating stderr and stdout just in case (i.e. html tidy). - 1558. By Gero.Bare
-
Minor changes.
Preview Diff
1 | === modified file 'plugins/CMakeLists.txt' |
2 | --- plugins/CMakeLists.txt 2016-09-03 10:30:53 +0000 |
3 | +++ plugins/CMakeLists.txt 2016-10-27 12:57:14 +0000 |
4 | @@ -23,3 +23,4 @@ |
5 | add_subdirectory (clipboard-history) |
6 | add_subdirectory (detect-indent) |
7 | add_subdirectory (preserve-indent) |
8 | +add_subdirectory (linter-manager) |
9 | |
10 | === added directory 'plugins/linter-manager' |
11 | === added file 'plugins/linter-manager/CMakeLists.txt' |
12 | --- plugins/linter-manager/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
13 | +++ plugins/linter-manager/CMakeLists.txt 2016-10-27 12:57:14 +0000 |
14 | @@ -0,0 +1,35 @@ |
15 | +add_definitions(${NORMAL_CFLAGS}) |
16 | +include_directories(${CMAKE_BINARY_DIR} ${CMAKE_BINARY_DIR}/scratchcore/) |
17 | +link_directories(${NORMAL_LINK_DIRS}) |
18 | + |
19 | +set (PLUGIN_NAME "linter-manager") |
20 | + |
21 | + |
22 | +vala_precompile(VALA_C ${PLUGIN_NAME} |
23 | + LinterManagerPlugin.vala |
24 | + ConfigurationDialog.vala |
25 | + Settings.vala |
26 | +PACKAGES |
27 | + granite |
28 | + gtksourceview-3.0 |
29 | + scratchcore |
30 | + gee-0.8 |
31 | + libpeas-1.0 |
32 | +OPTIONS |
33 | + --thread |
34 | + --vapidir=${CMAKE_BINARY_DIR} |
35 | + --vapidir=${CMAKE_BINARY_DIR}/src/ |
36 | + --vapidir=${CMAKE_SOURCE_DIR}/vapi/ |
37 | + --vapidir=${CMAKE_BINARY_DIR}/scratchcore/ |
38 | +) |
39 | + |
40 | +include (GResource) |
41 | +glib_compile_resources (GLIB_RESOURCES_LINTER_MANAGER SOURCE icons/linter-manager.gresource.xml) |
42 | + |
43 | +add_library(${PLUGIN_NAME} MODULE ${VALA_C} ${GLIB_RESOURCES_LINTER_MANAGER}) |
44 | +add_dependencies(${PLUGIN_NAME} ${LIBNAME} scratch) |
45 | +target_link_libraries(${PLUGIN_NAME} ${NORMAL_LIBRARIES}) |
46 | + |
47 | +install(TARGETS ${PLUGIN_NAME} DESTINATION ${PLUGINDIR}/${PLUGIN_NAME}) |
48 | +install(FILES ${PLUGIN_NAME}.plugin DESTINATION ${PLUGINDIR}/${PLUGIN_NAME}) |
49 | +message("-- Linter-manager plugin will be compiled") |
50 | |
51 | === added file 'plugins/linter-manager/ConfigurationDialog.vala' |
52 | --- plugins/linter-manager/ConfigurationDialog.vala 1970-01-01 00:00:00 +0000 |
53 | +++ plugins/linter-manager/ConfigurationDialog.vala 2016-10-27 12:57:14 +0000 |
54 | @@ -0,0 +1,330 @@ |
55 | +// -*- Mode: vala; indent-tabs-mode: nil; tab-width: 4 -*- |
56 | +/*** |
57 | + BEGIN LICENSE |
58 | + |
59 | + Copyright (C) 2016 Geronimo Bareiro <gero[dot]bare[at]gmail[dot]com> |
60 | + This program is free software: you can redistribute it and/or modify it |
61 | + under the terms of the GNU Lesser General Public License version 3, as published |
62 | + by the Free Software Foundation. |
63 | + |
64 | + This program is distributed in the hope that it will be useful, but |
65 | + WITHOUT ANY WARRANTY; without even the implied warranties of |
66 | + MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
67 | + PURPOSE. See the GNU General Public License for more details. |
68 | + |
69 | + You should have received a copy of the GNU General Public License along |
70 | + with this program. If not, see <http://www.gnu.org/licenses/> |
71 | + |
72 | + END LICENSE |
73 | +***/ |
74 | + |
75 | +namespace Scratch.Plugins.LinterManager { |
76 | + |
77 | + public class ListPopover : Gtk.Popover { |
78 | + private Gtk.TreeView tree; |
79 | + private unowned Gtk.Button button; |
80 | + |
81 | + public ListPopover (Gtk.Button button) { |
82 | + |
83 | + this.button = button; |
84 | + set_relative_to (button); |
85 | + |
86 | + tree = new Gtk.TreeView (); |
87 | + tree.headers_visible = false; |
88 | + |
89 | + var store = new Gtk.ListStore (1, typeof (string)); |
90 | + var cell = new Gtk.CellRendererText (); |
91 | + |
92 | + tree.insert_column_with_attributes (0, null, cell, "text", 0); |
93 | + tree.set_model (store); |
94 | + tree.hexpand = true; |
95 | + tree.get_selection ().mode = Gtk.SelectionMode.SINGLE; |
96 | + tree.unselect_all (); |
97 | + |
98 | + Gtk.TreeIter iter; |
99 | + var manager = Gtk.SourceLanguageManager.get_default (); |
100 | + foreach (var ids in manager.get_language_ids ()) { |
101 | + store.append (out iter); |
102 | + store.set (iter, 0, ids); |
103 | + } |
104 | + |
105 | + var scrolled_window = new Gtk.ScrolledWindow (null, null); |
106 | + scrolled_window.set_policy (Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC); |
107 | + scrolled_window.add (tree); |
108 | + scrolled_window.set_min_content_height (150); |
109 | + scrolled_window.hexpand = true; |
110 | + |
111 | + tree.row_activated.connect ((path, column) => { |
112 | + Gtk.TreeIter iter_val; |
113 | + store.get_iter (out iter_val, path); |
114 | + Value val; |
115 | + store.get_value (iter_val, 0, out val); |
116 | + button.label = (string) val; |
117 | + hide (); |
118 | + }); |
119 | + |
120 | + add (scrolled_window); |
121 | + show_all (); |
122 | + } |
123 | + } |
124 | + |
125 | + public class LinterRow : Gtk.ListBoxRow { |
126 | + private Gtk.Button lang_button; |
127 | + private Gtk.Entry cmd_entry; |
128 | + private Gtk.Entry regex_entry; |
129 | + private Gtk.Grid main_grid; |
130 | + private Gtk.Grid left_grid; |
131 | + private Gtk.Grid right_grid; |
132 | + |
133 | + public string language { |
134 | + get { return lang_button.label; } |
135 | + set { lang_button.label = value; } |
136 | + } |
137 | + |
138 | + public string command { |
139 | + get { return cmd_entry.text; } |
140 | + set { cmd_entry.text = value; } |
141 | + } |
142 | + |
143 | + public string regex { |
144 | + get { return regex_entry.text; } |
145 | + set { regex_entry.text = value; } |
146 | + } |
147 | + |
148 | + public LinterRow (string lan, string com, string re) { |
149 | + |
150 | + var delete_button = new Gtk.Button.from_icon_name ("edit-delete"); |
151 | + delete_button.relief = Gtk.ReliefStyle.NONE; |
152 | + delete_button.tooltip_text = _("Delete this linter profile"); |
153 | + |
154 | + right_grid = new Gtk.Grid (); |
155 | + right_grid.orientation = Gtk.Orientation.VERTICAL; |
156 | + right_grid.add (delete_button); |
157 | + |
158 | + var lang_label = new Gtk.Label ("<b>%s</b>".printf(_("Language:"))); |
159 | + lang_label.set_use_markup (true); |
160 | + lang_label.get_style_context ().add_class ("h4"); |
161 | + lang_button = new Gtk.Button.with_label (lan); |
162 | + lang_button.tooltip_text = _("Click to select the language"); |
163 | + lang_button.relief = Gtk.ReliefStyle.NONE; |
164 | + |
165 | + var cmd_label = new Gtk.Label ("<b>%s</b>".printf(_("Command:"))); |
166 | + cmd_label.set_use_markup (true); |
167 | + cmd_entry = new Gtk.Entry (); |
168 | + cmd_entry.text = com; |
169 | + cmd_entry.width_request = 480; |
170 | + cmd_entry.tooltip_text = _("This is the command to call the cli executable used to analize the file"); |
171 | + |
172 | + var regex_label = new Gtk.Label ("<b>%s</b>".printf(_("Regex:"))); |
173 | + regex_label.set_use_markup (true); |
174 | + regex_entry = new Gtk.Entry (); |
175 | + regex_entry.text = re; |
176 | + regex_entry.width_request = 480; |
177 | + regex_entry.tooltip_text = _("This is the regex used to evaluate the command output"); |
178 | + |
179 | + left_grid = new Gtk.Grid (); |
180 | + left_grid.width_request = 580; |
181 | + left_grid.attach (lang_label, 0, 0, 1, 1); |
182 | + left_grid.attach (lang_button, 1, 0, 3, 1); |
183 | + left_grid.attach (cmd_label, 0, 1, 1, 1); |
184 | + left_grid.attach (cmd_entry, 1, 1, 3, 1); |
185 | + |
186 | + left_grid.attach (regex_label, 0, 2, 1, 1); |
187 | + left_grid.attach (regex_entry, 1, 2, 3, 1); |
188 | + |
189 | + main_grid = new Gtk.Grid (); |
190 | + main_grid.orientation = Gtk.Orientation.HORIZONTAL; |
191 | + main_grid.add (left_grid); |
192 | + main_grid.add (right_grid); |
193 | + main_grid.show_all (); |
194 | + add (main_grid); |
195 | + |
196 | + lang_button.clicked.connect (()=> { |
197 | + var popover = new ListPopover (lang_button); |
198 | + popover.show (); |
199 | + }); |
200 | + |
201 | + delete_button.clicked.connect (() => { |
202 | + parent.remove (this); // Remove itself from the list |
203 | + }); |
204 | + } |
205 | + |
206 | + } |
207 | + |
208 | + public class LinterConfigurationDialog : Gtk.Dialog { |
209 | + |
210 | + unowned LinterManagerPlugin linter_manager; |
211 | + unowned GLib.HashTable<string, Linter> linter_list; |
212 | + Gtk.Button button_add; |
213 | + Gtk.Button button_reset; |
214 | + Gtk.ListBox linter_box = null; |
215 | + |
216 | + public LinterConfigurationDialog (LinterManagerPlugin linter_manager_plugin) { |
217 | + linter_manager = linter_manager_plugin; |
218 | + linter_list = linter_manager.linter_list; |
219 | + |
220 | + title ="Configuration Dialog"; |
221 | + set_default_size (600, 400); |
222 | + |
223 | + add_button (_("Apply"), Gtk.ResponseType.ACCEPT); |
224 | + add_button (_("Close"), Gtk.ResponseType.CLOSE); |
225 | + add_button (_("Help"), Gtk.ResponseType.HELP); |
226 | + |
227 | + create_widgets(); |
228 | + populate_linterbox (); |
229 | + connect_signals(); |
230 | + } |
231 | + |
232 | + void create_widgets () { |
233 | + if (linter_box != null) { |
234 | + return; |
235 | + } |
236 | + |
237 | + linter_box = new Gtk.ListBox (); |
238 | + linter_box. selection_mode = Gtk.SelectionMode.NONE; |
239 | + linter_box.vexpand = true; |
240 | + linter_box.hexpand = true; |
241 | + |
242 | + var scrolled_window = new Gtk.ScrolledWindow (null, null); |
243 | + scrolled_window.set_policy (Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC); |
244 | + scrolled_window.add (linter_box); |
245 | + scrolled_window.set_min_content_height (150); |
246 | + |
247 | + var botom_grid = new Gtk.Grid (); |
248 | + button_add = new Gtk.Button.with_label (_("Add")); |
249 | + button_add.hexpand = false; |
250 | + button_add.tooltip_text = _("Add a new Linter to the list"); |
251 | + |
252 | + button_reset = new Gtk.Button.with_label (_("Reset Defaults")); |
253 | + button_reset.hexpand = false; |
254 | + button_reset.tooltip_text = _("Reset all Linter Manager options to the Default Configuration"); |
255 | + |
256 | + botom_grid.attach (button_add, 0, 0, 1, 1); |
257 | + botom_grid.attach (button_reset, 2, 0, 1, 1); |
258 | + |
259 | + var label = new Gtk.Label (_("Profiles")); |
260 | + var main_grid = new Gtk.Grid (); |
261 | + main_grid.orientation = Gtk.Orientation.VERTICAL; |
262 | + main_grid.add (label); |
263 | + main_grid.add (scrolled_window); |
264 | + main_grid.add (botom_grid); |
265 | + |
266 | + Gtk.Box content = get_content_area () as Gtk.Box; |
267 | + content.pack_start (main_grid, false, true, 0); |
268 | + main_grid.show_all (); |
269 | + } |
270 | + |
271 | + private void populate_linterbox () { |
272 | + foreach (var language in linter_list.get_keys()) { |
273 | + var linter_row = new LinterRow (language, |
274 | + linter_list[language].command, linter_list[language].regex); |
275 | + linter_box.add (linter_row); |
276 | + } |
277 | + |
278 | + linter_box.show_all (); |
279 | + } |
280 | + |
281 | + void connect_signals () { |
282 | + response.connect (on_response); |
283 | + button_add.clicked.connect (on_add); |
284 | + button_reset.clicked.connect (on_reset_linter_conf); |
285 | + |
286 | + } |
287 | + |
288 | + private void on_add () { |
289 | + var linter_row = new LinterRow ("", "", ""); |
290 | + linter_box.add (linter_row); |
291 | + linter_box.show_all (); |
292 | + debug ("Added new LinterRow"); |
293 | + } |
294 | + |
295 | + private void on_reset_linter_conf () { |
296 | + linter_manager.default_conf (); |
297 | + linter_manager.save_conf (); |
298 | + |
299 | + linter_box.@foreach ((widget) => { |
300 | + linter_box.remove (widget); |
301 | + }); |
302 | + |
303 | + populate_linterbox (); |
304 | + } |
305 | + |
306 | + private bool configuration_is_valid () { |
307 | + //Check we have a sane configuration |
308 | + var lang_table = new GenericSet<string> (str_hash, str_equal); |
309 | + |
310 | + foreach (var child in linter_box.get_children ()) { |
311 | + var child_linter_row = (LinterRow) child; |
312 | + if (child_linter_row.language.length == 0) { |
313 | + var msg = new Gtk.MessageDialog (null, |
314 | + Gtk.DialogFlags.DESTROY_WITH_PARENT, Gtk.MessageType.WARNING, |
315 | + Gtk.ButtonsType.OK, _("One or more entries contain the language's field empty.\nPlease select a proper Language.").printf (child_linter_row.language)); |
316 | + msg.response.connect ((response_id) => { |
317 | + msg.destroy (); |
318 | + }); |
319 | + msg.run (); |
320 | + return false; |
321 | + |
322 | + } else if (lang_table.contains (child_linter_row.language)) { |
323 | + var msg = new Gtk.MessageDialog (null, |
324 | + Gtk.DialogFlags.DESTROY_WITH_PARENT, Gtk.MessageType.WARNING, |
325 | + Gtk.ButtonsType.OK, _("The %s lanugage has multiple definitions.\nPlease make sure there is only one entry for each language.").printf (child_linter_row.language)); |
326 | + msg.response.connect ((response_id) => { |
327 | + msg.destroy (); |
328 | + }); |
329 | + msg.run (); |
330 | + return false; |
331 | + } else if (child_linter_row.command.length == 0 || child_linter_row.regex.length == 0) { |
332 | + var msg = new Gtk.MessageDialog (null, |
333 | + Gtk.DialogFlags.DESTROY_WITH_PARENT, Gtk.MessageType.WARNING, |
334 | + Gtk.ButtonsType.OK, _("The %s language has empty fields.\nPlease check your configuration.").printf (child_linter_row.language)); |
335 | + msg.response.connect ((response_id) => { |
336 | + msg.destroy (); |
337 | + }); |
338 | + msg.run (); |
339 | + return false; |
340 | + } |
341 | + |
342 | + lang_table.add (child_linter_row.language.dup ()); |
343 | + } |
344 | + |
345 | + return true; |
346 | + } |
347 | + |
348 | + private void update_configuration () { |
349 | + |
350 | + if (!configuration_is_valid ()) { |
351 | + return; |
352 | + } |
353 | + |
354 | + // If we are clear, we commit |
355 | + linter_list.remove_all (); |
356 | + foreach (var child in linter_box.get_children ()) { |
357 | + var child_linter_row = (LinterRow) child; |
358 | + linter_list[child_linter_row.language.dup ()] = new Linter (child_linter_row.command, child_linter_row.regex); |
359 | + } |
360 | + |
361 | + linter_manager.save_conf (); |
362 | + } |
363 | + |
364 | + private void on_response (Gtk.Dialog source, int response_id) { |
365 | + switch (response_id) { |
366 | + case Gtk.ResponseType.ACCEPT: |
367 | + debug ("Update Configuration"); |
368 | + update_configuration (); |
369 | + break; |
370 | + case Gtk.ResponseType.CLOSE: |
371 | + destroy (); |
372 | + break; |
373 | + case Gtk.ResponseType.HELP: |
374 | + try { |
375 | + Gtk.show_uri (null, ONLINE_DOCUMENTATION_URL, Gtk.get_current_event_time()); |
376 | + } catch (Error e) { |
377 | + warning (e.message); |
378 | + } |
379 | + |
380 | + break; |
381 | + } |
382 | + } |
383 | + } |
384 | +} |
385 | |
386 | === added file 'plugins/linter-manager/LinterManagerPlugin.vala' |
387 | --- plugins/linter-manager/LinterManagerPlugin.vala 1970-01-01 00:00:00 +0000 |
388 | +++ plugins/linter-manager/LinterManagerPlugin.vala 2016-10-27 12:57:14 +0000 |
389 | @@ -0,0 +1,481 @@ |
390 | +// -*- Mode: vala; indent-tabs-mode: nil; tab-width: 4 -*- |
391 | +/*** |
392 | + BEGIN LICENSE |
393 | + |
394 | + Copyright (C) 2016 Geronimo Bareiro <gero[dot]bare[at]gmail[dot]com> |
395 | + This program is free software: you can redistribute it and/or modify it |
396 | + under the terms of the GNU Lesser General Public License version 3, as published |
397 | + by the Free Software Foundation. |
398 | + |
399 | + This program is distributed in the hope that it will be useful, but |
400 | + WITHOUT ANY WARRANTY; without even the implied warranties of |
401 | + MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
402 | + PURPOSE. See the GNU General Public License for more details. |
403 | + |
404 | + You should have received a copy of the GNU General Public License along |
405 | + with this program. If not, see <http://www.gnu.org/licenses/> |
406 | + |
407 | + END LICENSE |
408 | +***/ |
409 | + |
410 | +public const string NAME = _("Linter Manager"); |
411 | +public const string DESCRIPTION = _("Linter support for scratch"); |
412 | + |
413 | +namespace Scratch.Plugins.LinterManager { |
414 | + |
415 | + public class Linter : Object { |
416 | + public string command { get; construct; } |
417 | + public string regex { get; construct; } |
418 | + |
419 | + public Linter (string com, string reg) { |
420 | + Object (command: com, regex: reg); |
421 | + } |
422 | + |
423 | + construct {} |
424 | + } |
425 | + |
426 | + enum RESULTS { |
427 | + LINE, |
428 | + COLUMN, |
429 | + MESSAGE |
430 | + } |
431 | + |
432 | + public const string ONLINE_DOCUMENTATION_URL = "https://github.com/gerito1/misc-docs/blob/master/scratch-plugin-linter-manager/help.md"; |
433 | + public const string LINTER_RESOURCE_PATH = "/org/pantheon/scratch/plugin/linter-manager/"; |
434 | + private string text_to_copy; |
435 | + |
436 | + public class LinterManagerPlugin : Peas.ExtensionBase, Peas.Activatable { |
437 | + |
438 | + public Object object { owned get; construct; } |
439 | + private Scratch.Services.Interface plugins { owned get { return (Scratch.Services.Interface) object; } } |
440 | + |
441 | + Settings settings; |
442 | + |
443 | + MainWindow? window = null; |
444 | + Gtk.Notebook? bottombar = null; |
445 | + Gtk.Grid? container = null; |
446 | + Gtk.TreeView tree_view; |
447 | + Gtk.ListStore list_store; |
448 | + Scratch.Widgets.Toolbar? toolbar = null; |
449 | + Gtk.MenuToolButton? menu_tool_button = null; |
450 | + Gtk.Menu? context_menu = null; |
451 | + |
452 | + Scratch.Services.Document document = null; |
453 | + Scratch.Services.Document current_document = null; |
454 | + |
455 | + public GLib.HashTable<string, Linter> linter_list; |
456 | + |
457 | + LinterConfigurationDialog dialog; |
458 | + GLib.KeyFile keyfile; |
459 | + const string CONF_FILENAME = "linter.conf"; |
460 | + string file; |
461 | + |
462 | + public void update_state () { |
463 | + } |
464 | + |
465 | + public void activate () { |
466 | + create_widgets (); |
467 | + |
468 | + settings = new Settings (); |
469 | + |
470 | + plugins.hook_document.connect (on_hook_document); |
471 | + plugins.hook_notebook_bottom.connect (on_hook_notebook_bottom); |
472 | + plugins.hook_toolbar.connect (on_hook_on_toolbar); |
473 | + |
474 | + plugins.hook_window.connect ((w) => { |
475 | + if (window != null) { |
476 | + return; |
477 | + } |
478 | + |
479 | + window = w; |
480 | + }); |
481 | + |
482 | + linter_list = new GLib.HashTable<string,Linter> (GLib.str_hash, GLib.str_equal); |
483 | + load_conf(); |
484 | + } |
485 | + |
486 | + public void deactivate () { |
487 | + remove_container (); |
488 | + toolbar.remove (menu_tool_button); |
489 | + |
490 | + if (menu_tool_button != null) { |
491 | + menu_tool_button.destroy (); |
492 | + } |
493 | + |
494 | + if (container != null) { |
495 | + container.destroy (); |
496 | + } |
497 | + |
498 | + } |
499 | + |
500 | + void create_widgets () { |
501 | + var icon = new Gtk.Image.from_resource ("%scheck_file.svg".printf (LINTER_RESOURCE_PATH)); |
502 | + var run_button = new Gtk.ToolButton (icon, null); |
503 | + run_button.clicked.connect (run_linter); |
504 | + run_button.tooltip_text = _("Run Linter"); |
505 | + |
506 | + var conf_icon = new Gtk.Image.from_icon_name ("applications-system", Gtk.IconSize.SMALL_TOOLBAR); |
507 | + var configure_button = new Gtk.ToolButton (conf_icon, null); |
508 | + configure_button.clicked.connect (on_configure_clicked); |
509 | + configure_button.tooltip_text = _("Open Linter Manager Configuration"); |
510 | + |
511 | + var close_icon = new Gtk.Image.from_icon_name ("window-close", Gtk.IconSize.SMALL_TOOLBAR); |
512 | + var close_button = new Gtk.ToolButton (close_icon, null); |
513 | + close_button.clicked.connect (on_hide_clicked); |
514 | + close_button.tooltip_text = _("Hide Linter output view"); |
515 | + |
516 | + var toolbar = new Gtk.Toolbar (); |
517 | + toolbar.orientation = Gtk.Orientation.VERTICAL; |
518 | + toolbar.add (run_button); |
519 | + toolbar.add (configure_button); |
520 | + toolbar.add (close_button); |
521 | + |
522 | + list_store = new Gtk.ListStore (3, typeof (int), typeof (int), typeof (string)); |
523 | + tree_view = new Gtk.TreeView.with_model (list_store); |
524 | + |
525 | + var cell = new Gtk.CellRendererText (); |
526 | + tree_view.insert_column_with_attributes (-1, _("Line"), cell, "text", RESULTS.LINE); |
527 | + tree_view.insert_column_with_attributes (-1, _("Column"), cell, "text", RESULTS.COLUMN); |
528 | + tree_view.insert_column_with_attributes (-1, _("Message"), cell, "text", RESULTS.MESSAGE); |
529 | + |
530 | + var scrolled_window = new Gtk.ScrolledWindow (null, null); |
531 | + scrolled_window.set_policy (Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC); |
532 | + scrolled_window.add (tree_view); |
533 | + scrolled_window.vexpand = true; |
534 | + scrolled_window.hexpand = true; |
535 | + |
536 | + container = new Gtk.Grid (); |
537 | + container.attach (toolbar, 0, 0, 1, 1); |
538 | + container.attach (scrolled_window, 1, 0, 1, 1); |
539 | + |
540 | + var item_copy = new Gtk.MenuItem.with_label (_("Copy to Clipboard")); |
541 | + |
542 | + context_menu = new Gtk.Menu (); |
543 | + context_menu.append (item_copy); |
544 | + |
545 | + item_copy.activate.connect (() => { |
546 | + var display = window.get_display (); |
547 | + var clipboard = Gtk.Clipboard.get_for_display (display, Gdk.SELECTION_CLIPBOARD); |
548 | + clipboard.set_text (text_to_copy, text_to_copy.length); |
549 | + }); |
550 | + |
551 | + tree_view.button_press_event.connect ((event) => { |
552 | + if (event.type == Gdk.EventType.BUTTON_PRESS && event.button == 3) { |
553 | + var path = new Gtk.TreePath (); |
554 | + int x, y; |
555 | + tree_view.get_path_at_pos ((int) event.x, (int) event.y, out path, null, out x, out y); |
556 | + |
557 | + if (path == null) { |
558 | + return false; |
559 | + } |
560 | + |
561 | + Gtk.TreeIter iter; |
562 | + list_store.get_iter_from_string (out iter, path.to_string ()); |
563 | + list_store.get (iter, RESULTS.MESSAGE, out text_to_copy); |
564 | + |
565 | + //We manually select the row to give feedback to te user |
566 | + tree_view.get_selection ().select_path (path); |
567 | + context_menu.show_all (); |
568 | + context_menu.popup (null, null, null, event.button, event.time); |
569 | + return true; |
570 | + } |
571 | + return false; |
572 | + }); |
573 | + } |
574 | + |
575 | + public void save_conf () { |
576 | + keyfile = new GLib.KeyFile (); |
577 | + |
578 | + foreach (string language in linter_list.get_keys ()) { |
579 | + keyfile.set_string (language, "command", linter_list[language].command); |
580 | + keyfile.set_string (language, "regex", linter_list[language].regex); |
581 | + } |
582 | + |
583 | + try { |
584 | + debug ("Saving linter configuration"); |
585 | + GLib.FileUtils.set_contents (file, keyfile.to_data ()); |
586 | + } catch (FileError e) { |
587 | + warning ("FileError: %s", e.message); |
588 | + } |
589 | + } |
590 | + |
591 | + public void default_conf () { |
592 | + message ("Setting default configuration"); |
593 | + linter_list.remove_all (); |
594 | + |
595 | + linter_list["js"] = new Linter ("jshint", |
596 | + ".+:\\s*(line (?<line>\\d+), col (?<col>\\d+), )(?<message>.*)"); |
597 | + linter_list["css"] = new Linter ("csslint --format=compact", |
598 | + ".+:\\s*(line (?<line>\\d+), col (?<col>\\d+), )?(?:(?<err>Error)|(?<war>Warning)) - (?<message>.*)"); |
599 | + linter_list["python"] = new Linter ("pep8", |
600 | + ".+:(?<line>\\d+):(?<col>\\d+): (?:(?<err>E)|(?<war>W))\\d+ (?<message>.+)"); |
601 | + linter_list["html"] = new Linter ("tidy -errors -quiet -utf8", |
602 | + "line (?<line>\\d+) column (?<col>\\d+) - (?:(?<err>Error)|(?<war>Warning)|(?<inf>Info)): (?<message>.+)"); |
603 | + } |
604 | + |
605 | + public void load_conf () { |
606 | + keyfile = new GLib.KeyFile (); |
607 | + debug ("Loading linter configuration"); |
608 | + file = Path.build_filename (Scratch.ScratchApp.instance.data_home_folder, CONF_FILENAME); |
609 | + try { |
610 | + keyfile.load_from_file (file, KeyFileFlags.NONE); |
611 | + var languages = keyfile.get_groups (); |
612 | + |
613 | + //Recovering Groups and configuration keys |
614 | + if (languages.length > 0) { |
615 | + foreach (var language in languages ) { |
616 | + debug ("Loading language %s", language); |
617 | + var command = keyfile.get_string (language, "command"); |
618 | + var regex = keyfile.get_string (language, "regex"); |
619 | + linter_list[language] = new Linter (command, regex); |
620 | + } |
621 | + } else { //In case of empty file. |
622 | + default_conf (); |
623 | + save_conf (); |
624 | + } |
625 | + } catch (Error e) { |
626 | + warning ("Failed to load config: %s", e.message); |
627 | + default_conf (); |
628 | + save_conf (); |
629 | + } |
630 | + } |
631 | + |
632 | + void on_hook_document (Scratch.Services.Document doc) { |
633 | + document = doc; |
634 | + debug ("Linter Hook on document"); |
635 | + } |
636 | + |
637 | + void on_hook_notebook_bottom (Gtk.Notebook notebook) { |
638 | + debug ("Linter Hook on notebook bottom"); |
639 | + |
640 | + if (bottombar == null) { |
641 | + bottombar = notebook; |
642 | + } |
643 | + |
644 | + } |
645 | + |
646 | + void on_hook_on_toolbar (Scratch.Widgets.Toolbar scratch_toolbar) { |
647 | + if (toolbar != null) { |
648 | + return; |
649 | + } |
650 | + |
651 | + toolbar = scratch_toolbar; |
652 | + |
653 | + var icon = new Gtk.Image.from_resource ("%scheck_file.svg".printf(LINTER_RESOURCE_PATH)); |
654 | + icon.icon_size = Gtk.IconSize.LARGE_TOOLBAR; |
655 | + |
656 | + menu_tool_button = new Gtk.MenuToolButton (icon, null); |
657 | + menu_tool_button.tooltip_text = _("Run Linter"); |
658 | + |
659 | + var item_configure = new Gtk.MenuItem.with_label (_("Configure")); |
660 | + item_configure.tooltip_text = _("Open Linter Manager Configuration"); |
661 | + item_configure.activate.connect (on_configure_clicked); |
662 | + |
663 | + var item_hide = new Gtk.MenuItem.with_label (_("Hide Linter")); |
664 | + item_hide.tooltip_text = _("Hide Linter output view"); |
665 | + item_hide.activate.connect (on_hide_clicked); |
666 | + |
667 | + var menu = new Gtk.Menu (); |
668 | + menu.append (item_configure); |
669 | + menu.append (item_hide); |
670 | + menu.show_all (); |
671 | + menu_tool_button.set_menu (menu); |
672 | + menu_tool_button.show_all (); |
673 | + |
674 | + toolbar.pack_end (menu_tool_button); |
675 | + |
676 | + menu_tool_button.clicked.connect (()=> { |
677 | + add_container (); |
678 | + run_linter (); |
679 | + }); |
680 | + } |
681 | + |
682 | + void add_container () { |
683 | + if (bottombar.page_num (container) == -1) { |
684 | + var new_page = bottombar.append_page (container, new Gtk.Label (_("Linter"))); |
685 | + bottombar.set_current_page (new_page); |
686 | + container.show_all (); |
687 | + } |
688 | + } |
689 | + |
690 | + void remove_container () { |
691 | + if (bottombar.page_num (container) != -1) { |
692 | + bottombar.remove (container); |
693 | + } |
694 | + |
695 | + if (window.get_current_document () != null) { |
696 | + window.get_current_document ().focus (); |
697 | + } |
698 | + |
699 | + tree_view.row_activated.disconnect (go_to_line); |
700 | + |
701 | + if (current_document != null) { |
702 | + current_document.doc_closed.disconnect (doc_closed); |
703 | + } |
704 | + |
705 | + } |
706 | + |
707 | + void go_to_line (Gtk.TreePath path, Gtk.TreeViewColumn column) { |
708 | + Gtk.TreeIter iter_val; |
709 | + list_store.get_iter (out iter_val, path); |
710 | + Value val; |
711 | + list_store.get_value (iter_val, RESULTS.LINE, out val); |
712 | + int line = (int) val; |
713 | + |
714 | + if (line <= 0) { //The line count should start at 1 |
715 | + debug ("Trying to go a line <= 0 : %d", line); |
716 | + return; |
717 | + } |
718 | + |
719 | + plugins.open_file (current_document.file); |
720 | + current_document.source_view.go_to_line (line); |
721 | + } |
722 | + |
723 | + void run_linter () { |
724 | + if (document == null) { |
725 | + return; |
726 | + } |
727 | + |
728 | + current_document = document; |
729 | + |
730 | + //No Tempfiles I want a pathfile and a type extension |
731 | + if (current_document.is_file_temporary) { |
732 | + var msg = new Gtk.MessageDialog (null, Gtk.DialogFlags.DESTROY_WITH_PARENT, Gtk.MessageType.WARNING, Gtk.ButtonsType.OK, _("You must save the document first.")); |
733 | + msg.response.connect ((response_id) => { |
734 | + msg.destroy (); |
735 | + }); |
736 | + msg.run (); |
737 | + return; |
738 | + } |
739 | + |
740 | + var language = current_document.source_view.buffer.language; |
741 | + |
742 | + current_document.doc_closed.connect (doc_closed); |
743 | + |
744 | + //First we make sure we reset behavior |
745 | + list_store.clear (); |
746 | + tree_view.row_activated.disconnect (go_to_line); |
747 | + |
748 | + if (language != null && linter_list[language.id] != null) { |
749 | + current_document.save.begin (); |
750 | + |
751 | + debug ("Language selected: %s", language.id); |
752 | + run_regex.begin (language); |
753 | + } else { |
754 | + Gtk.TreeIter iter; |
755 | + list_store.append (out iter); |
756 | + list_store.set (iter, RESULTS.LINE, 0, RESULTS.COLUMN, 0, RESULTS.MESSAGE, _("There's no valid linter for the file.")); |
757 | + } |
758 | + } |
759 | + |
760 | + async void run_regex (Gtk.SourceLanguage language) { |
761 | + Idle.add(()=> { |
762 | + try { |
763 | + var re = new Regex(linter_list[language.id].regex); |
764 | + string stdout; |
765 | + string stderr; |
766 | + int retcode; |
767 | + string command = "%s \"%s\"".printf (linter_list[language.id].command, current_document.file.get_path ()); |
768 | + GLib.Process.spawn_command_line_sync (command, out stdout, out stderr, out retcode); |
769 | + |
770 | + MatchInfo match; |
771 | + |
772 | + //We are concatenating stderr and stdout to analyze, some linters use stderr |
773 | + //instead of stdout. For example html-tidy. Analyze both is a safe assumption. |
774 | + //The spaces are necesary because there is a bug in the regex library |
775 | + //check https://bugzilla.gnome.org/show_bug.cgi?id=773285 |
776 | + //For most cases of the spaces won't affect the program. |
777 | + var input = " \n%s \n%s".printf (stdout, stderr); |
778 | + bool match_exist = re.match (input, 0, out match); |
779 | + |
780 | + Gtk.TreeIter iter; |
781 | + |
782 | + if (!match_exist) { |
783 | + if (retcode == 0) { |
784 | + list_store.append (out iter); |
785 | + list_store.set (iter, RESULTS.LINE, 0, |
786 | + RESULTS.COLUMN, 0, RESULTS.MESSAGE, _("No errors found.")); |
787 | + } else { |
788 | + //There was a problem, either command or regex had failed |
789 | + |
790 | + list_store.append (out iter); |
791 | + list_store.set (iter, RESULTS.LINE, 0, |
792 | + RESULTS.COLUMN, 0, RESULTS.MESSAGE, _("Unexpected result.")); |
793 | + warning ("Current Language: %s", language.id); |
794 | + warning ("Command used %s", command); |
795 | + warning ("Regex used %s", linter_list[language.id].regex); |
796 | + warning ("Return code recieved %d", retcode); |
797 | + warning ("Return stderr recieved:\n%s", stderr); |
798 | + warning ("Return stdout recieved:\n%s", stdout); |
799 | + } |
800 | + return false; |
801 | + } |
802 | + |
803 | + tree_view.row_activated.connect (go_to_line); |
804 | + while (match_exist) { |
805 | + |
806 | + list_store.append (out iter); |
807 | + string type; |
808 | + if (match.fetch_named ("err") != null && match.fetch_named ("err").length > 0 ) { |
809 | + type = match.fetch_named ("err"); |
810 | + } else if (match.fetch_named ("war") != null && match.fetch_named ("war").length > 0 ) { |
811 | + type = match.fetch_named ("war"); |
812 | + }else if (match.fetch_named ("inf") != null && match.fetch_named ("inf").length > 0 ) { |
813 | + type = match.fetch_named ("inf"); |
814 | + }else { |
815 | + type = ""; |
816 | + } |
817 | + |
818 | + var message = "%s%s".printf (type.length > 0 ? type + ": " : "", match.fetch_named ("message") ?? ""); |
819 | + list_store.set (iter, RESULTS.LINE, int.parse(match.fetch_named ("line") ?? "-1"), |
820 | + RESULTS.COLUMN, int.parse (match.fetch_named ("col") ?? "-1"), |
821 | + RESULTS.MESSAGE, message); |
822 | + match_exist = match.next (); |
823 | + } |
824 | + } catch (Error e) { |
825 | + Gtk.TreeIter iter; |
826 | + list_store.append (out iter); |
827 | + list_store.set (iter, RESULTS.LINE, 0, RESULTS.COLUMN, 0, RESULTS.MESSAGE, _("Regex failure.")); |
828 | + |
829 | + //Use the treeview to comunicate error to the user. |
830 | + list_store.append (out iter); |
831 | + list_store.set (iter, RESULTS.LINE, 0, RESULTS.COLUMN, 0, RESULTS.MESSAGE, e.message); |
832 | + |
833 | + warning ("Regex failure.\n%s", e.message); |
834 | + return false; |
835 | + } |
836 | + return false; |
837 | + }, GLib.Priority.DEFAULT_IDLE); |
838 | + yield; |
839 | + } |
840 | + |
841 | + void on_configure_clicked () { |
842 | + dialog = new LinterConfigurationDialog (this); |
843 | + dialog.show_all (); |
844 | + dialog.run (); |
845 | + } |
846 | + |
847 | + void on_hide_clicked () { |
848 | + remove_container (); |
849 | + window.get_current_document ().focus (); |
850 | + } |
851 | + |
852 | + void doc_closed (Scratch.Services.Document doc) { |
853 | + |
854 | + if (doc == current_document) { |
855 | + list_store.clear (); |
856 | + tree_view.row_activated.disconnect (go_to_line); |
857 | + current_document = null; |
858 | + } |
859 | + |
860 | + doc.doc_closed.disconnect (doc_closed); |
861 | + } |
862 | + } |
863 | +} |
864 | + |
865 | +[ModuleInit] |
866 | +public void peas_register_types (GLib.TypeModule module) { |
867 | + var objmodule = module as Peas.ObjectModule; |
868 | + objmodule.register_extension_type (typeof (Peas.Activatable), |
869 | + typeof (Scratch.Plugins.LinterManager.LinterManagerPlugin)); |
870 | +} |
871 | |
872 | === added file 'plugins/linter-manager/Settings.vala' |
873 | --- plugins/linter-manager/Settings.vala 1970-01-01 00:00:00 +0000 |
874 | +++ plugins/linter-manager/Settings.vala 2016-10-27 12:57:14 +0000 |
875 | @@ -0,0 +1,32 @@ |
876 | +// -*- Mode: vala; indent-tabs-mode: nil; tab-width: 4 -*- |
877 | +/*** |
878 | + BEGIN LICENSE |
879 | + |
880 | + Copyright (C) 2016 Geronimo Bareiro <gero[dot]bare[at]gmail[dot]com> |
881 | + This program is free software: you can redistribute it and/or modify it |
882 | + under the terms of the GNU Lesser General Public License version 3, as published |
883 | + by the Free Software Foundation. |
884 | + |
885 | + This program is distributed in the hope that it will be useful, but |
886 | + WITHOUT ANY WARRANTY; without even the implied warranties of |
887 | + MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
888 | + PURPOSE. See the GNU General Public License for more details. |
889 | + |
890 | + You should have received a copy of the GNU General Public License along |
891 | + with this program. If not, see <http://www.gnu.org/licenses/> |
892 | + |
893 | + END LICENSE |
894 | +***/ |
895 | + |
896 | +namespace Scratch.Plugins.LinterManager { |
897 | + internal class Settings : Granite.Services.Settings { |
898 | + |
899 | + private const string SCHEMA = "org.pantheon.scratch.plugins.linter-manager"; |
900 | + |
901 | + public bool auto_run { get; set; } |
902 | + |
903 | + public Settings () { |
904 | + base (SCHEMA); |
905 | + } |
906 | + } |
907 | +} |
908 | |
909 | === added directory 'plugins/linter-manager/icons' |
910 | === added file 'plugins/linter-manager/icons/check_file.svg' |
911 | --- plugins/linter-manager/icons/check_file.svg 1970-01-01 00:00:00 +0000 |
912 | +++ plugins/linter-manager/icons/check_file.svg 2016-10-27 12:57:14 +0000 |
913 | @@ -0,0 +1,775 @@ |
914 | +<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
915 | +<svg |
916 | + xmlns:dc="http://purl.org/dc/elements/1.1/" |
917 | + xmlns:cc="http://creativecommons.org/ns#" |
918 | + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" |
919 | + xmlns:svg="http://www.w3.org/2000/svg" |
920 | + xmlns="http://www.w3.org/2000/svg" |
921 | + xmlns:xlink="http://www.w3.org/1999/xlink" |
922 | + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" |
923 | + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" |
924 | + version="1.0" |
925 | + width="24" |
926 | + height="24" |
927 | + id="svg2" |
928 | + inkscape:version="0.91 r13725" |
929 | + sodipodi:docname="check_file.svg"> |
930 | + <sodipodi:namedview |
931 | + pagecolor="#ffffff" |
932 | + bordercolor="#666666" |
933 | + borderopacity="1" |
934 | + objecttolerance="10" |
935 | + gridtolerance="10" |
936 | + guidetolerance="10" |
937 | + inkscape:pageopacity="0" |
938 | + inkscape:pageshadow="2" |
939 | + inkscape:window-width="881" |
940 | + inkscape:window-height="480" |
941 | + id="namedview153" |
942 | + showgrid="true" |
943 | + showguides="true" |
944 | + inkscape:zoom="4.9166667" |
945 | + inkscape:cx="8.9489574" |
946 | + inkscape:cy="0.46632093" |
947 | + inkscape:window-x="0" |
948 | + inkscape:window-y="2" |
949 | + inkscape:window-maximized="0" |
950 | + inkscape:current-layer="svg2"> |
951 | + <inkscape:grid |
952 | + type="xygrid" |
953 | + id="grid4388" /> |
954 | + </sodipodi:namedview> |
955 | + <defs |
956 | + id="defs4"> |
957 | + <radialGradient |
958 | + cx="605.71429" |
959 | + cy="486.64789" |
960 | + r="117.14286" |
961 | + fx="605.71429" |
962 | + fy="486.64789" |
963 | + id="radialGradient4536" |
964 | + xlink:href="#linearGradient5060" |
965 | + gradientUnits="userSpaceOnUse" |
966 | + gradientTransform="matrix(-2.774389,0,0,1.969706,112.7623,-872.8854)" /> |
967 | + <linearGradient |
968 | + id="linearGradient5060"> |
969 | + <stop |
970 | + id="stop5062" |
971 | + style="stop-color:#000000;stop-opacity:1" |
972 | + offset="0" /> |
973 | + <stop |
974 | + id="stop5064" |
975 | + style="stop-color:#000000;stop-opacity:0" |
976 | + offset="1" /> |
977 | + </linearGradient> |
978 | + <radialGradient |
979 | + cx="605.71429" |
980 | + cy="486.64789" |
981 | + r="117.14286" |
982 | + fx="605.71429" |
983 | + fy="486.64789" |
984 | + id="radialGradient4534" |
985 | + xlink:href="#linearGradient5060" |
986 | + gradientUnits="userSpaceOnUse" |
987 | + gradientTransform="matrix(2.774389,0,0,1.969706,-1891.633,-872.8854)" /> |
988 | + <linearGradient |
989 | + id="linearGradient5048"> |
990 | + <stop |
991 | + id="stop5050" |
992 | + style="stop-color:#000000;stop-opacity:0" |
993 | + offset="0" /> |
994 | + <stop |
995 | + id="stop5056" |
996 | + style="stop-color:#000000;stop-opacity:1" |
997 | + offset="0.5" /> |
998 | + <stop |
999 | + id="stop5052" |
1000 | + style="stop-color:#000000;stop-opacity:0" |
1001 | + offset="1" /> |
1002 | + </linearGradient> |
1003 | + <linearGradient |
1004 | + x1="302.85715" |
1005 | + y1="366.64789" |
1006 | + x2="302.85715" |
1007 | + y2="609.50507" |
1008 | + id="linearGradient4532" |
1009 | + xlink:href="#linearGradient5048" |
1010 | + gradientUnits="userSpaceOnUse" |
1011 | + gradientTransform="matrix(2.774389,0,0,1.969706,-1892.179,-872.8854)" /> |
1012 | + <linearGradient |
1013 | + id="linearGradient3104"> |
1014 | + <stop |
1015 | + id="stop3106" |
1016 | + style="stop-color:#969696;stop-opacity:1" |
1017 | + offset="0" /> |
1018 | + <stop |
1019 | + id="stop3108" |
1020 | + style="stop-color:#bebebe;stop-opacity:1" |
1021 | + offset="1" /> |
1022 | + </linearGradient> |
1023 | + <linearGradient |
1024 | + x1="11.536495" |
1025 | + y1="44.952385" |
1026 | + x2="11.536495" |
1027 | + y2="-1.0040783" |
1028 | + id="linearGradient4196" |
1029 | + xlink:href="#linearGradient3104" |
1030 | + gradientUnits="userSpaceOnUse" |
1031 | + gradientTransform="matrix(0.4857163,0,0,0.489929,0.34281,0.7216336)" /> |
1032 | + <linearGradient |
1033 | + id="linearGradient3600"> |
1034 | + <stop |
1035 | + id="stop3602" |
1036 | + style="stop-color:#f4f4f4;stop-opacity:1" |
1037 | + offset="0" /> |
1038 | + <stop |
1039 | + id="stop3604" |
1040 | + style="stop-color:#dbdbdb;stop-opacity:1" |
1041 | + offset="1" /> |
1042 | + </linearGradient> |
1043 | + <linearGradient |
1044 | + x1="-60.969666" |
1045 | + y1="13.668072" |
1046 | + x2="-60.908253" |
1047 | + y2="114.5354" |
1048 | + id="linearGradient4194" |
1049 | + xlink:href="#linearGradient3600" |
1050 | + gradientUnits="userSpaceOnUse" |
1051 | + gradientTransform="matrix(0.2187514,1.3312651e-4,-1.3318587e-4,0.2186539,23.078109,-2.7267432)" /> |
1052 | + <linearGradient |
1053 | + id="linearGradient3191-577"> |
1054 | + <stop |
1055 | + id="stop2613" |
1056 | + style="stop-color:#dbce48;stop-opacity:1" |
1057 | + offset="0" /> |
1058 | + <stop |
1059 | + id="stop2615" |
1060 | + style="stop-color:#c5b625;stop-opacity:1" |
1061 | + offset="1" /> |
1062 | + </linearGradient> |
1063 | + <linearGradient |
1064 | + x1="5.5178981" |
1065 | + y1="37.371799" |
1066 | + x2="9.5220556" |
1067 | + y2="41.391716" |
1068 | + id="linearGradient3857" |
1069 | + xlink:href="#linearGradient3191-577" |
1070 | + gradientUnits="userSpaceOnUse" |
1071 | + gradientTransform="matrix(0.3763801,0.03615261,0.03669995,0.374874,-2.2182805,-1.1331002)" /> |
1072 | + <linearGradient |
1073 | + id="linearGradient3290-678"> |
1074 | + <stop |
1075 | + id="stop2607" |
1076 | + style="stop-color:#ece5a5;stop-opacity:1" |
1077 | + offset="0" /> |
1078 | + <stop |
1079 | + id="stop2609" |
1080 | + style="stop-color:#fcfbf2;stop-opacity:1" |
1081 | + offset="1" /> |
1082 | + </linearGradient> |
1083 | + <linearGradient |
1084 | + x1="9" |
1085 | + y1="29.056757" |
1086 | + x2="9" |
1087 | + y2="26.02973" |
1088 | + id="linearGradient3855" |
1089 | + xlink:href="#linearGradient3290-678" |
1090 | + gradientUnits="userSpaceOnUse" |
1091 | + gradientTransform="matrix(0.4040235,-0.4056919,0.6073752,0.602268,-17.636692,0.462492)" /> |
1092 | + <linearGradient |
1093 | + id="linearGradient3223-699"> |
1094 | + <stop |
1095 | + id="stop2599" |
1096 | + style="stop-color:#b1b1b1;stop-opacity:1" |
1097 | + offset="0" /> |
1098 | + <stop |
1099 | + id="stop2601" |
1100 | + style="stop-color:#ffffff;stop-opacity:1" |
1101 | + offset="0.5" /> |
1102 | + <stop |
1103 | + id="stop2603" |
1104 | + style="stop-color:#8f8f8f;stop-opacity:1" |
1105 | + offset="1" /> |
1106 | + </linearGradient> |
1107 | + <linearGradient |
1108 | + x1="30.037716" |
1109 | + y1="24.989594" |
1110 | + x2="30.037716" |
1111 | + y2="30.000141" |
1112 | + id="linearGradient3853" |
1113 | + xlink:href="#linearGradient3223-699" |
1114 | + gradientUnits="userSpaceOnUse" |
1115 | + gradientTransform="matrix(0.4040235,-0.4056919,0.6073752,0.6022679,-17.177369,-2.1969969e-4)" /> |
1116 | + <linearGradient |
1117 | + id="linearGradient3240-907"> |
1118 | + <stop |
1119 | + id="stop2591" |
1120 | + style="stop-color:#565656;stop-opacity:1" |
1121 | + offset="0" /> |
1122 | + <stop |
1123 | + id="stop2593" |
1124 | + style="stop-color:#9a9a9a;stop-opacity:1" |
1125 | + offset="0.5" /> |
1126 | + <stop |
1127 | + id="stop2595" |
1128 | + style="stop-color:#545454;stop-opacity:1" |
1129 | + offset="1" /> |
1130 | + </linearGradient> |
1131 | + <linearGradient |
1132 | + x1="30.037716" |
1133 | + y1="24.989594" |
1134 | + x2="30.037716" |
1135 | + y2="30.000141" |
1136 | + id="linearGradient3851" |
1137 | + xlink:href="#linearGradient3240-907" |
1138 | + gradientUnits="userSpaceOnUse" |
1139 | + gradientTransform="matrix(0.4040235,-0.4056919,0.6073752,0.6022679,-17.061661,-0.1164056)" /> |
1140 | + <linearGradient |
1141 | + id="linearGradient3223-768"> |
1142 | + <stop |
1143 | + id="stop2583" |
1144 | + style="stop-color:#b1b1b1;stop-opacity:1" |
1145 | + offset="0" /> |
1146 | + <stop |
1147 | + id="stop2585" |
1148 | + style="stop-color:#ffffff;stop-opacity:1" |
1149 | + offset="0.5" /> |
1150 | + <stop |
1151 | + id="stop2587" |
1152 | + style="stop-color:#8f8f8f;stop-opacity:1" |
1153 | + offset="1" /> |
1154 | + </linearGradient> |
1155 | + <linearGradient |
1156 | + x1="30.037716" |
1157 | + y1="24.989594" |
1158 | + x2="30.037716" |
1159 | + y2="30.000141" |
1160 | + id="linearGradient3849" |
1161 | + xlink:href="#linearGradient3223-768" |
1162 | + gradientUnits="userSpaceOnUse" |
1163 | + gradientTransform="matrix(0.4040235,-0.4056919,0.6073752,0.6022679,-17.581392,0.4054707)" /> |
1164 | + <linearGradient |
1165 | + id="linearGradient3240-686"> |
1166 | + <stop |
1167 | + id="stop2575" |
1168 | + style="stop-color:#565656;stop-opacity:1" |
1169 | + offset="0" /> |
1170 | + <stop |
1171 | + id="stop2577" |
1172 | + style="stop-color:#9a9a9a;stop-opacity:1" |
1173 | + offset="0.5" /> |
1174 | + <stop |
1175 | + id="stop2579" |
1176 | + style="stop-color:#545454;stop-opacity:1" |
1177 | + offset="1" /> |
1178 | + </linearGradient> |
1179 | + <linearGradient |
1180 | + x1="30.037716" |
1181 | + y1="24.989594" |
1182 | + x2="30.037716" |
1183 | + y2="30.000141" |
1184 | + id="linearGradient3847" |
1185 | + xlink:href="#linearGradient3240-686" |
1186 | + gradientUnits="userSpaceOnUse" |
1187 | + gradientTransform="matrix(0.4040235,-0.4056919,0.6073752,0.6022679,-17.465684,0.2892868)" /> |
1188 | + <linearGradient |
1189 | + id="linearGradient3223-789"> |
1190 | + <stop |
1191 | + id="stop2567" |
1192 | + style="stop-color:#b1b1b1;stop-opacity:1" |
1193 | + offset="0" /> |
1194 | + <stop |
1195 | + id="stop2569" |
1196 | + style="stop-color:#ffffff;stop-opacity:1" |
1197 | + offset="0.5" /> |
1198 | + <stop |
1199 | + id="stop2571" |
1200 | + style="stop-color:#8f8f8f;stop-opacity:1" |
1201 | + offset="1" /> |
1202 | + </linearGradient> |
1203 | + <linearGradient |
1204 | + x1="30.037716" |
1205 | + y1="24.989594" |
1206 | + x2="30.037716" |
1207 | + y2="30.000141" |
1208 | + id="linearGradient3845" |
1209 | + xlink:href="#linearGradient3223-789" |
1210 | + gradientUnits="userSpaceOnUse" |
1211 | + gradientTransform="matrix(0.4040235,-0.4056919,0.6073752,0.6022679,-17.983472,0.8092126)" /> |
1212 | + <linearGradient |
1213 | + id="linearGradient3240-279"> |
1214 | + <stop |
1215 | + id="stop2559" |
1216 | + style="stop-color:#565656;stop-opacity:1" |
1217 | + offset="0" /> |
1218 | + <stop |
1219 | + id="stop2561" |
1220 | + style="stop-color:#9a9a9a;stop-opacity:1" |
1221 | + offset="0.5" /> |
1222 | + <stop |
1223 | + id="stop2563" |
1224 | + style="stop-color:#545454;stop-opacity:1" |
1225 | + offset="1" /> |
1226 | + </linearGradient> |
1227 | + <linearGradient |
1228 | + x1="30.037716" |
1229 | + y1="24.989594" |
1230 | + x2="30.037716" |
1231 | + y2="30.000141" |
1232 | + id="linearGradient3843" |
1233 | + xlink:href="#linearGradient3240-279" |
1234 | + gradientUnits="userSpaceOnUse" |
1235 | + gradientTransform="matrix(0.4040235,-0.4056919,0.6073752,0.6022679,-17.867764,0.6930272)" /> |
1236 | + <linearGradient |
1237 | + id="linearGradient3155-40"> |
1238 | + <stop |
1239 | + id="stop2541" |
1240 | + style="stop-color:#181818;stop-opacity:1" |
1241 | + offset="0" /> |
1242 | + <stop |
1243 | + id="stop2543" |
1244 | + style="stop-color:#dbdbdb;stop-opacity:1" |
1245 | + offset="0.13482948" /> |
1246 | + <stop |
1247 | + id="stop2545" |
1248 | + style="stop-color:#a4a4a4;stop-opacity:1" |
1249 | + offset="0.20224422" /> |
1250 | + <stop |
1251 | + id="stop2547" |
1252 | + style="stop-color:#ffffff;stop-opacity:1" |
1253 | + offset="0.26965895" /> |
1254 | + <stop |
1255 | + id="stop2549" |
1256 | + style="stop-color:#8d8d8d;stop-opacity:1" |
1257 | + offset="0.44650277" /> |
1258 | + <stop |
1259 | + id="stop2551" |
1260 | + style="stop-color:#959595;stop-opacity:1" |
1261 | + offset="0.57114136" /> |
1262 | + <stop |
1263 | + id="stop2553" |
1264 | + style="stop-color:#cecece;stop-opacity:1" |
1265 | + offset="0.72038066" /> |
1266 | + <stop |
1267 | + id="stop2555" |
1268 | + style="stop-color:#181818;stop-opacity:1" |
1269 | + offset="1" /> |
1270 | + </linearGradient> |
1271 | + <linearGradient |
1272 | + x1="23.575972" |
1273 | + y1="25.356892" |
1274 | + x2="23.575972" |
1275 | + y2="31.210939" |
1276 | + id="linearGradient3841" |
1277 | + xlink:href="#linearGradient3155-40" |
1278 | + gradientUnits="userSpaceOnUse" |
1279 | + gradientTransform="matrix(0.415777,-0.4174938,0.518983,0.5146192,-15.747227,2.6503673)" |
1280 | + spreadMethod="pad" /> |
1281 | + <linearGradient |
1282 | + x1="71.204407" |
1283 | + y1="6.2375584" |
1284 | + x2="71.204407" |
1285 | + y2="44.340794" |
1286 | + id="linearGradient3316" |
1287 | + xlink:href="#linearGradient4011-5" |
1288 | + gradientUnits="userSpaceOnUse" |
1289 | + gradientTransform="matrix(0.35135136,0,0,0.35135136,-16.20367,0.0907)" /> |
1290 | + <linearGradient |
1291 | + id="linearGradient4011-5"> |
1292 | + <stop |
1293 | + id="stop4013-6" |
1294 | + style="stop-color:#ffffff;stop-opacity:1" |
1295 | + offset="0" /> |
1296 | + <stop |
1297 | + id="stop4015-1" |
1298 | + style="stop-color:#ffffff;stop-opacity:0.23529412" |
1299 | + offset="0.507761" /> |
1300 | + <stop |
1301 | + id="stop4017-4" |
1302 | + style="stop-color:#ffffff;stop-opacity:0.15686275" |
1303 | + offset="0.83456558" /> |
1304 | + <stop |
1305 | + id="stop4019-3" |
1306 | + style="stop-color:#ffffff;stop-opacity:0.39215687" |
1307 | + offset="1" /> |
1308 | + </linearGradient> |
1309 | + </defs> |
1310 | + <metadata |
1311 | + id="metadata7"> |
1312 | + <rdf:RDF> |
1313 | + <cc:Work |
1314 | + rdf:about=""> |
1315 | + <dc:format>image/svg+xml</dc:format> |
1316 | + <dc:type |
1317 | + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> |
1318 | + <dc:title></dc:title> |
1319 | + </cc:Work> |
1320 | + </rdf:RDF> |
1321 | + </metadata> |
1322 | + <g |
1323 | + style="display:inline;stroke-width:1.88256383;stroke-miterlimit:4;stroke-dasharray:none" |
1324 | + id="g3490" |
1325 | + transform="matrix(0.5004324,0,0,0.5168524,0.1147464,-0.5781821)"> |
1326 | + <g |
1327 | + style="display:inline;stroke-width:104.96237946;stroke-miterlimit:4;stroke-dasharray:none" |
1328 | + id="g5022" |
1329 | + transform="matrix(0.02165152,0,0,0.01485743,43.0076,42.68539)"> |
1330 | + <rect |
1331 | + style="display:inline;overflow:visible;visibility:visible;opacity:0.40206185;fill:url(#linearGradient4532);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:104.96237946;marker:none" |
1332 | + id="rect4173" |
1333 | + y="-150.69685" |
1334 | + x="-1559.2523" |
1335 | + height="478.35718" |
1336 | + width="1339.6335" /> |
1337 | + <path |
1338 | + inkscape:connector-curvature="0" |
1339 | + style="display:inline;overflow:visible;visibility:visible;opacity:0.40206185;fill:url(#radialGradient4534);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:104.96237946;marker:none" |
1340 | + id="path5058" |
1341 | + d="m -219.61876,-150.68038 c 0,0 0,478.33079 0,478.33079 142.874166,0.90045 345.40022,-107.16966 345.40014,-239.196175 0,-132.026537 -159.436816,-239.134595 -345.40014,-239.134615 z" /> |
1342 | + <path |
1343 | + inkscape:connector-curvature="0" |
1344 | + style="display:inline;overflow:visible;visibility:visible;opacity:0.40206185;fill:url(#radialGradient4536);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:104.96237946;marker:none" |
1345 | + id="path5018" |
1346 | + d="m -1559.2523,-150.68038 c 0,0 0,478.33079 0,478.33079 -142.8742,0.90045 -345.4002,-107.16966 -345.4002,-239.196175 0,-132.026537 159.4368,-239.134595 345.4002,-239.134615 z" /> |
1347 | + </g> |
1348 | + </g> |
1349 | + <path |
1350 | + inkscape:connector-curvature="0" |
1351 | + style="display:inline;fill:url(#linearGradient4194);fill-opacity:1;stroke:url(#linearGradient4196);stroke-width:1.00000012;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" |
1352 | + id="path2855" |
1353 | + d="m 3.5133625,0.49999968 c 4.1393458,0.002518 12.8294425,0.007809 16.9687885,0.010328 -0.0037,6.04861402 0.02118,15.96248032 0.01751,21.98982332 -5.666565,-0.0034 -11.3331314,-0.0069 -16.9996976,-0.01035 0.00447,-7.329933 0.00893,-14.659869 0.013397,-21.98980333 z" /> |
1354 | + <g |
1355 | + style="fill:#999999" |
1356 | + id="g4198" |
1357 | + transform="matrix(1.0195441,0,0,1,32.167123,7.773339)"> |
1358 | + <path |
1359 | + inkscape:connector-curvature="0" |
1360 | + style="display:inline;opacity:0.7;fill:#999999;fill-opacity:1;stroke:none" |
1361 | + id="path6035" |
1362 | + d="m -25.665515,-2.7733386 1.124072,0 0,1 -1.124072,0 0,-1 z" /> |
1363 | + <path |
1364 | + inkscape:connector-curvature="0" |
1365 | + style="display:inline;opacity:0.7;fill:#999999;fill-opacity:1;stroke:none" |
1366 | + id="path6033" |
1367 | + d="m -24.388326,-2.7733386 1.060612,0 0,1 -1.060612,0 0,-1 z" /> |
1368 | + <path |
1369 | + inkscape:connector-curvature="0" |
1370 | + style="display:inline;opacity:0.7;fill:#999999;fill-opacity:1;stroke:none" |
1371 | + id="path6031" |
1372 | + d="m -23.174597,-2.7733386 0.933684,0 0,1 -0.933684,0 0,-1 z" /> |
1373 | + <path |
1374 | + inkscape:connector-curvature="0" |
1375 | + style="display:inline;opacity:0.7;fill:#999999;fill-opacity:1;stroke:none" |
1376 | + id="path6029" |
1377 | + d="m -22.087797,-2.7733386 0.410114,0 0,1 -0.410114,0 0,-1 z" /> |
1378 | + <path |
1379 | + inkscape:connector-curvature="0" |
1380 | + style="display:inline;opacity:0.7;fill:#999999;fill-opacity:1;stroke:none" |
1381 | + id="path6027" |
1382 | + d="m -21.524561,-2.7733386 0.917815,0 0,1 -0.917815,0 0,-1 z" /> |
1383 | + <path |
1384 | + inkscape:connector-curvature="0" |
1385 | + style="display:inline;opacity:0.7;fill:#999999;fill-opacity:1;stroke:none" |
1386 | + id="path6025" |
1387 | + d="m -20.453624,-2.7733386 2.377462,0 0,1 -2.377462,0 0,-1 z" /> |
1388 | + <path |
1389 | + inkscape:connector-curvature="0" |
1390 | + style="display:inline;opacity:0.7;fill:#999999;fill-opacity:1;stroke:none" |
1391 | + id="path6023" |
1392 | + d="m -17.923045,-2.7733386 1.806297,0 0,1 -1.806297,0 0,-1 z" /> |
1393 | + <path |
1394 | + inkscape:connector-curvature="0" |
1395 | + style="display:inline;opacity:0.7;fill:#999999;fill-opacity:1;stroke:none" |
1396 | + id="path6017" |
1397 | + d="m -25.665515,3.2266614 1.124072,0 0,1 -1.124072,0 0,-1 z" /> |
1398 | + <path |
1399 | + inkscape:connector-curvature="0" |
1400 | + style="display:inline;opacity:0.7;fill:#999999;fill-opacity:1;stroke:none" |
1401 | + id="path6015" |
1402 | + d="m -24.388327,3.2266614 1.060612,0 0,1 -1.060612,0 0,-1 z" /> |
1403 | + <path |
1404 | + inkscape:connector-curvature="0" |
1405 | + style="display:inline;opacity:0.7;fill:#999999;fill-opacity:1;stroke:none" |
1406 | + id="path6013" |
1407 | + d="m -23.174598,3.2266614 0.933683,0 0,1 -0.933683,0 0,-1 z" /> |
1408 | + <path |
1409 | + inkscape:connector-curvature="0" |
1410 | + style="display:inline;opacity:0.7;fill:#999999;fill-opacity:1;stroke:none" |
1411 | + id="path6011" |
1412 | + d="m -22.087799,3.2266614 0.410114,0 0,1 -0.410114,0 0,-1 z" /> |
1413 | + <path |
1414 | + inkscape:connector-curvature="0" |
1415 | + style="display:inline;opacity:0.7;fill:#999999;fill-opacity:1;stroke:none" |
1416 | + id="path6009" |
1417 | + d="m -21.524563,3.2266614 0.917814,0 0,1 -0.917814,0 0,-1 z" /> |
1418 | + <path |
1419 | + inkscape:connector-curvature="0" |
1420 | + style="display:inline;opacity:0.7;fill:#999999;fill-opacity:1;stroke:none" |
1421 | + id="path6007" |
1422 | + d="m -20.453627,3.2266614 2.377461,0 0,1 -2.377461,0 0,-1 z" /> |
1423 | + <path |
1424 | + inkscape:connector-curvature="0" |
1425 | + style="display:inline;opacity:0.7;fill:#999999;fill-opacity:1;stroke:none" |
1426 | + id="path6005" |
1427 | + d="m -17.923049,3.2266614 1.806296,0 0,1 -1.806296,0 0,-1 z" /> |
1428 | + <path |
1429 | + inkscape:connector-curvature="0" |
1430 | + style="display:inline;opacity:0.7;fill:#999999;fill-opacity:1;stroke:none" |
1431 | + id="path6003" |
1432 | + d="m -15.963631,3.2266614 0.552901,0 0,1 -0.552901,0 0,-1 z" /> |
1433 | + <path |
1434 | + inkscape:connector-curvature="0" |
1435 | + style="display:inline;opacity:0.7;fill:#999999;fill-opacity:1;stroke:none" |
1436 | + id="path6001" |
1437 | + d="m -15.257608,3.2266614 1.092339,0 0,1 -1.092339,0 0,-1 z" /> |
1438 | + <path |
1439 | + inkscape:connector-curvature="0" |
1440 | + style="display:inline;opacity:0.7;fill:#999999;fill-opacity:1;stroke:none" |
1441 | + id="path5999" |
1442 | + d="m -25.665515,-0.77333856 1.742834,0 0,1 -1.742834,0 0,-1 z" /> |
1443 | + <path |
1444 | + inkscape:connector-curvature="0" |
1445 | + style="display:inline;opacity:0.7;fill:#999999;fill-opacity:1;stroke:none" |
1446 | + id="path5997" |
1447 | + d="m -23.76361,-0.77333856 0.838487,0 0,1 -0.838487,0 0,-1 z" /> |
1448 | + <path |
1449 | + inkscape:connector-curvature="0" |
1450 | + style="display:inline;opacity:0.7;fill:#999999;fill-opacity:1;stroke:none" |
1451 | + id="path5995" |
1452 | + d="m -22.766052,-0.77333856 0.394245,0 0,1 -0.394245,0 0,-1 z" /> |
1453 | + <path |
1454 | + inkscape:connector-curvature="0" |
1455 | + style="display:inline;opacity:0.7;fill:#999999;fill-opacity:1;stroke:none" |
1456 | + id="path5993" |
1457 | + d="m -22.212735,-0.77333856 0.759159,0 0,1 -0.759159,0 0,-1 z" /> |
1458 | + <path |
1459 | + inkscape:connector-curvature="0" |
1460 | + style="display:inline;opacity:0.7;fill:#999999;fill-opacity:1;stroke:none" |
1461 | + id="path5991" |
1462 | + d="m -21.29451,-0.77333856 0.759159,0 0,1 -0.759159,0 0,-1 z" /> |
1463 | + <path |
1464 | + inkscape:connector-curvature="0" |
1465 | + style="display:inline;opacity:0.7;fill:#999999;fill-opacity:1;stroke:none" |
1466 | + id="path5989" |
1467 | + d="m -20.376281,-0.77333856 1.219264,0 0,1 -1.219264,0 0,-1 z" /> |
1468 | + <path |
1469 | + inkscape:connector-curvature="0" |
1470 | + style="display:inline;opacity:0.7;fill:#999999;fill-opacity:1;stroke:none" |
1471 | + id="path5987" |
1472 | + d="m -18.99795,-0.77333856 1.600045,0 0,1 -1.600045,0 0,-1 z" /> |
1473 | + <path |
1474 | + inkscape:connector-curvature="0" |
1475 | + style="display:inline;opacity:0.7;fill:#999999;fill-opacity:1;stroke:none" |
1476 | + id="path5985" |
1477 | + d="m -17.238834,-0.77333856 1.076471,0 0,1 -1.076471,0 0,-1 z" /> |
1478 | + <path |
1479 | + inkscape:connector-curvature="0" |
1480 | + style="display:inline;opacity:0.7;fill:#999999;fill-opacity:1;stroke:none" |
1481 | + id="path5983" |
1482 | + d="m -16.003291,-0.77333856 0.251453,0 0,1 -0.251453,0 0,-1 z" /> |
1483 | + <path |
1484 | + inkscape:connector-curvature="0" |
1485 | + style="display:inline;opacity:0.7;fill:#999999;fill-opacity:1;stroke:none" |
1486 | + id="path5981" |
1487 | + d="m -25.665515,1.2266614 1.996685,0 0,1 -1.996685,0 0,-1 z" /> |
1488 | + <path |
1489 | + inkscape:connector-curvature="0" |
1490 | + style="display:inline;opacity:0.7;fill:#999999;fill-opacity:1;stroke:none" |
1491 | + id="path5979" |
1492 | + d="m -23.512309,1.2266614 2.139471,0 0,1 -2.139471,0 0,-1 z" /> |
1493 | + <path |
1494 | + inkscape:connector-curvature="0" |
1495 | + style="display:inline;opacity:0.7;fill:#999999;fill-opacity:1;stroke:none" |
1496 | + id="path5977" |
1497 | + d="m -21.216317,1.2266614 0.854355,0 0,1 -0.854355,0 0,-1 z" /> |
1498 | + <path |
1499 | + inkscape:connector-curvature="0" |
1500 | + style="display:inline;opacity:0.7;fill:#999999;fill-opacity:1;stroke:none" |
1501 | + id="path5975" |
1502 | + d="m -20.205441,1.2266614 2.012548,0 0,1 -2.012548,0 0,-1 z" /> |
1503 | + <path |
1504 | + inkscape:connector-curvature="0" |
1505 | + style="display:inline;opacity:0.7;fill:#999999;fill-opacity:1;stroke:none" |
1506 | + id="path5973" |
1507 | + d="m -16.501932,1.2266614 0.537037,0 0,1 -0.537037,0 0,-1 z" /> |
1508 | + <path |
1509 | + inkscape:connector-curvature="0" |
1510 | + style="display:inline;opacity:0.7;fill:#999999;fill-opacity:1;stroke:none" |
1511 | + id="path5971" |
1512 | + d="m -18.036372,1.2266614 1.377919,0 0,1 -1.377919,0 0,-1 z" /> |
1513 | + <path |
1514 | + inkscape:connector-curvature="0" |
1515 | + style="display:inline;opacity:0.7;fill:#999999;fill-opacity:1;stroke:none" |
1516 | + id="path5969" |
1517 | + d="m -15.808375,1.2266614 0.314918,0 0,1 -0.314918,0 0,-1 z" /> |
1518 | + <path |
1519 | + inkscape:connector-curvature="0" |
1520 | + style="display:inline;opacity:0.7;fill:#999999;fill-opacity:1;stroke:none" |
1521 | + id="path5967" |
1522 | + d="m -15.336936,1.2266614 0.854355,0 0,1 -0.854355,0 0,-1 z" /> |
1523 | + <path |
1524 | + inkscape:connector-curvature="0" |
1525 | + style="display:inline;opacity:0.7;fill:#999999;fill-opacity:1;stroke:none" |
1526 | + id="path5965" |
1527 | + d="m -25.665515,9.2266614 1.996686,0 0,0.9999996 -1.996686,0 0,-0.9999996 z" /> |
1528 | + <path |
1529 | + inkscape:connector-curvature="0" |
1530 | + style="display:inline;opacity:0.7;fill:#999999;fill-opacity:1;stroke:none" |
1531 | + id="path5963" |
1532 | + d="m -23.512309,9.2266614 2.139473,0 0,0.9999996 -2.139473,0 0,-0.9999996 z" /> |
1533 | + <path |
1534 | + inkscape:connector-curvature="0" |
1535 | + style="display:inline;opacity:0.7;fill:#999999;fill-opacity:1;stroke:none" |
1536 | + id="path5961" |
1537 | + d="m -21.216315,9.2266614 0.854355,0 0,0.9999996 -0.854355,0 0,-0.9999996 z" /> |
1538 | + <path |
1539 | + inkscape:connector-curvature="0" |
1540 | + style="display:inline;opacity:0.7;fill:#999999;fill-opacity:1;stroke:none" |
1541 | + id="path5959" |
1542 | + d="m -20.205439,9.2266614 2.012549,0 0,0.9999996 -2.012549,0 0,-0.9999996 z" /> |
1543 | + <path |
1544 | + inkscape:connector-curvature="0" |
1545 | + style="display:inline;opacity:0.7;fill:#999999;fill-opacity:1;stroke:none" |
1546 | + id="path5957" |
1547 | + d="m -16.501929,9.2266614 0.537037,0 0,0.9999996 -0.537037,0 0,-0.9999996 z" /> |
1548 | + <path |
1549 | + inkscape:connector-curvature="0" |
1550 | + style="display:inline;opacity:0.7;fill:#999999;fill-opacity:1;stroke:none" |
1551 | + id="path5955" |
1552 | + d="m -18.036369,9.2266614 1.377919,0 0,0.9999996 -1.377919,0 0,-0.9999996 z" /> |
1553 | + <path |
1554 | + inkscape:connector-curvature="0" |
1555 | + style="display:inline;opacity:0.7;fill:#999999;fill-opacity:1;stroke:none" |
1556 | + id="path5953" |
1557 | + d="m -15.808371,9.2266614 0.314918,0 0,0.9999996 -0.314918,0 0,-0.9999996 z" /> |
1558 | + <path |
1559 | + inkscape:connector-curvature="0" |
1560 | + style="display:inline;opacity:0.7;fill:#999999;fill-opacity:1;stroke:none" |
1561 | + id="path5951" |
1562 | + d="m -15.336932,9.2266614 0.854355,0 0,0.9999996 -0.854355,0 0,-0.9999996 z" /> |
1563 | + <path |
1564 | + inkscape:connector-curvature="0" |
1565 | + style="display:inline;opacity:0.7;fill:#999999;fill-opacity:1;stroke:none" |
1566 | + id="path5949" |
1567 | + d="m -25.665515,5.2266614 1.441384,0 0,1 -1.441384,0 0,-1 z" /> |
1568 | + <path |
1569 | + inkscape:connector-curvature="0" |
1570 | + style="display:inline;opacity:0.7;fill:#999999;fill-opacity:1;stroke:none" |
1571 | + id="path5947" |
1572 | + d="m -24.071009,5.2266614 2.393326,0 0,1 -2.393326,0 0,-1 z" /> |
1573 | + <path |
1574 | + inkscape:connector-curvature="0" |
1575 | + style="display:inline;opacity:0.7;fill:#999999;fill-opacity:1;stroke:none" |
1576 | + id="path5945" |
1577 | + d="m -21.524561,5.2266614 1.155799,0 0,1 -1.155799,0 0,-1 z" /> |
1578 | + <path |
1579 | + inkscape:connector-curvature="0" |
1580 | + style="display:inline;opacity:0.7;fill:#999999;fill-opacity:1;stroke:none" |
1581 | + id="path5943" |
1582 | + d="m -18.986049,5.2266614 0.917816,0 0,1 -0.917816,0 0,-1 z" /> |
1583 | + <path |
1584 | + inkscape:connector-curvature="0" |
1585 | + style="display:inline;opacity:0.7;fill:#999999;fill-opacity:1;stroke:none" |
1586 | + id="path5941" |
1587 | + d="m -17.915112,5.2266614 1.473117,0 0,1 -1.473117,0 0,-1 z" /> |
1588 | + <path |
1589 | + inkscape:connector-curvature="0" |
1590 | + style="display:inline;opacity:0.7;fill:#999999;fill-opacity:1;stroke:none" |
1591 | + id="path5939" |
1592 | + d="m -16.288879,5.2266614 2.393331,0 0,1 -2.393331,0 0,-1 z" /> |
1593 | + <path |
1594 | + inkscape:connector-curvature="0" |
1595 | + style="display:inline;opacity:0.7;fill:#999999;fill-opacity:1;stroke:none" |
1596 | + id="path5937" |
1597 | + d="m -20.215641,5.2266614 1.076476,0 0,1 -1.076476,0 0,-1 z" /> |
1598 | + <path |
1599 | + inkscape:connector-curvature="0" |
1600 | + style="display:inline;opacity:0.7;fill:#999999;fill-opacity:1;stroke:none" |
1601 | + id="path5935" |
1602 | + d="m -25.665515,7.2266614 1.806297,0 0,1 -1.806297,0 0,-1 z" /> |
1603 | + <path |
1604 | + inkscape:connector-curvature="0" |
1605 | + style="display:inline;opacity:0.7;fill:#999999;fill-opacity:1;stroke:none" |
1606 | + id="path5933" |
1607 | + d="m -23.710065,7.2266614 0.56877,0 0,1 -0.56877,0 0,-1 z" /> |
1608 | + <path |
1609 | + inkscape:connector-curvature="0" |
1610 | + style="display:inline;opacity:0.7;fill:#999999;fill-opacity:1;stroke:none" |
1611 | + id="path5931" |
1612 | + d="m -22.992143,7.2266614 1.298596,0 0,1 -1.298596,0 0,-1 z" /> |
1613 | + <path |
1614 | + inkscape:connector-curvature="0" |
1615 | + style="display:inline;opacity:0.7;fill:#999999;fill-opacity:1;stroke:none" |
1616 | + id="path5929" |
1617 | + d="m -21.544395,7.2266614 0.886087,0 0,1 -0.886087,0 0,-1 z" /> |
1618 | + <path |
1619 | + inkscape:connector-curvature="0" |
1620 | + style="display:inline;opacity:0.7;fill:#999999;fill-opacity:1;stroke:none" |
1621 | + id="path5927" |
1622 | + d="m -20.509155,7.2266614 0.886082,0 0,1 -0.886082,0 0,-1 z" /> |
1623 | + <path |
1624 | + inkscape:connector-curvature="0" |
1625 | + style="display:inline;opacity:0.7;fill:#999999;fill-opacity:1;stroke:none" |
1626 | + id="path5925" |
1627 | + d="m -19.473916,7.2266614 1.282728,0 0,1 -1.282728,0 0,-1 z" /> |
1628 | + <path |
1629 | + inkscape:connector-curvature="0" |
1630 | + style="display:inline;opacity:0.7;fill:#999999;fill-opacity:1;stroke:none" |
1631 | + id="path5923" |
1632 | + d="m -18.042041,7.2266614 0.267326,0 0,1 -0.267326,0 0,-1 z" /> |
1633 | + <path |
1634 | + inkscape:connector-curvature="0" |
1635 | + style="display:inline;opacity:0.7;fill:#999999;fill-opacity:1;stroke:none" |
1636 | + id="path5921" |
1637 | + d="m -17.625563,7.2266614 1.663505,0 0,1 -1.663505,0 0,-1 z" /> |
1638 | + <path |
1639 | + inkscape:connector-curvature="0" |
1640 | + style="display:inline;opacity:0.7;fill:#999999;fill-opacity:1;stroke:none" |
1641 | + id="path5919" |
1642 | + d="m -15.812906,7.2266614 0.886087,0 0,1 -0.886087,0 0,-1 z" /> |
1643 | + <path |
1644 | + inkscape:connector-curvature="0" |
1645 | + style="display:inline;opacity:0.7;fill:#999999;fill-opacity:1;stroke:none" |
1646 | + id="path5917" |
1647 | + d="m -25.665515,11.226661 0.727427,0 0,1 -0.727427,0 0,-1 z" /> |
1648 | + <path |
1649 | + inkscape:connector-curvature="0" |
1650 | + style="display:inline;opacity:0.7;fill:#999999;fill-opacity:1;stroke:none" |
1651 | + id="path5915" |
1652 | + d="m -24.749835,11.226661 2.647178,0 0,1 -2.647178,0 0,-1 z" /> |
1653 | + <path |
1654 | + inkscape:connector-curvature="0" |
1655 | + style="display:inline;opacity:0.7;fill:#999999;fill-opacity:1;stroke:none" |
1656 | + id="path6838" |
1657 | + d="m -18.374424,11.226661 -0.727427,0 0,1 0.727427,0 0,-1 z" /> |
1658 | + <path |
1659 | + inkscape:connector-curvature="0" |
1660 | + style="display:inline;opacity:0.7;fill:#999999;fill-opacity:1;stroke:none" |
1661 | + id="path6840" |
1662 | + d="m -19.290104,11.226661 -2.647178,0 0,1 2.647178,0 0,-1 z" /> |
1663 | + </g> |
1664 | + <g |
1665 | + transform="matrix(0.81408898,0,0,0.81408898,10.177436,10.177436)" |
1666 | + id="g4236"> |
1667 | + <path |
1668 | + d="M 9,1.5 C 4.86176,1.5 1.5,4.86176 1.5,9 c 0,4.13824 3.36176,7.5 7.5,7.5 4.13824,0 7.5,-3.36176 7.5,-7.5 C 16.5,4.86176 13.13824,1.5 9,1.5 Z" |
1669 | + id="path2555-7" |
1670 | + style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#008000;fill-opacity:1;fill-rule:nonzero;stroke:#008000;stroke-width:0.99999994;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" |
1671 | + inkscape:connector-curvature="0" /> |
1672 | + <path |
1673 | + d="M 15.5,8.99977 C 15.5,12.58974 12.58964,15.5 9.00008,15.5 5.4102,15.5 2.5,12.5897 2.5,8.99977 2.5,5.40997 5.4102,2.5 9.00008,2.5 12.58964,2.5 15.5,5.40997 15.5,8.99977 l 0,0 z" |
1674 | + id="path8655-6" |
1675 | + style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.5;fill:none;stroke:url(#linearGradient3316);stroke-width:0.99999994;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" |
1676 | + inkscape:connector-curvature="0" /> |
1677 | + <path |
1678 | + d="m 14.03125,4.15625 a 0.94895148,0.94895148 0 0 0 -0.09375,0.0625 l -4.96875,5.4375 -2.3125,-2.3125 a 0.94895148,0.94895148 0 0 0 -1.3125,0 l -2,2 A 0.94895148,0.94895148 0 0 0 3.40625,10.75 l 5,4 A 0.94895148,0.94895148 0 0 0 9.6875,14.65625 l 6.21875,-6.6875 c -0.218501,-1.473701 -0.888095,-2.7885095 -1.875,-3.8125 z" |
1679 | + id="path4318" |
1680 | + style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.25;fill:#115710;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.84323651;marker:none;enable-background:accumulate" |
1681 | + inkscape:connector-curvature="0" /> |
1682 | + <path |
1683 | + d="M 14.625,4.875 9,11 6,8 4,10 9,14 15.65625,6.84375 Z" |
1684 | + id="path2922-6-6-0" |
1685 | + style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.84323651;marker:none;enable-background:accumulate" |
1686 | + inkscape:connector-curvature="0" /> |
1687 | + </g> |
1688 | +</svg> |
1689 | |
1690 | === added file 'plugins/linter-manager/icons/linter-manager.gresource.xml' |
1691 | --- plugins/linter-manager/icons/linter-manager.gresource.xml 1970-01-01 00:00:00 +0000 |
1692 | +++ plugins/linter-manager/icons/linter-manager.gresource.xml 2016-10-27 12:57:14 +0000 |
1693 | @@ -0,0 +1,6 @@ |
1694 | +<?xml version="1.0" encoding="UTF-8"?> |
1695 | +<gresources> |
1696 | + <gresource prefix="/org/pantheon/scratch/plugin/linter-manager"> |
1697 | + <file compressed="true" preprocess="xml-stripblanks">check_file.svg</file> |
1698 | + </gresource> |
1699 | +</gresources> |
1700 | |
1701 | === added file 'plugins/linter-manager/linter-manager.plugin' |
1702 | --- plugins/linter-manager/linter-manager.plugin 1970-01-01 00:00:00 +0000 |
1703 | +++ plugins/linter-manager/linter-manager.plugin 2016-10-27 12:57:14 +0000 |
1704 | @@ -0,0 +1,9 @@ |
1705 | +[Plugin] |
1706 | +Module=linter-manager |
1707 | +Loader=C |
1708 | +IAge=2 |
1709 | +Name=Linter Manager |
1710 | +Description=Some linter support for scratch |
1711 | +Authors=gero-bare <gero[dot]bare[at]gmail[dot]com> |
1712 | +Copyright=Copyright © 2016 Scratch Developers |
1713 | +Website=http://launchpad.net/scratch |
1714 | |
1715 | === modified file 'schemas/CMakeLists.txt' |
1716 | --- schemas/CMakeLists.txt 2015-09-10 00:54:45 +0000 |
1717 | +++ schemas/CMakeLists.txt 2016-10-27 12:57:14 +0000 |
1718 | @@ -3,4 +3,5 @@ |
1719 | add_schema("org.pantheon.scratch.plugins.folder-manager.gschema.xml") |
1720 | add_schema("org.pantheon.scratch.plugins.file-manager.gschema.xml") |
1721 | add_schema("org.pantheon.scratch.plugins.terminal.gschema.xml") |
1722 | +add_schema("org.pantheon.scratch.plugins.linter-manager.gschema.xml") |
1723 | add_schema("org.pantheon.scratch.plugins.spell.gschema.xml") |
1724 | |
1725 | === added file 'schemas/org.pantheon.scratch.plugins.linter-manager.gschema.xml' |
1726 | --- schemas/org.pantheon.scratch.plugins.linter-manager.gschema.xml 1970-01-01 00:00:00 +0000 |
1727 | +++ schemas/org.pantheon.scratch.plugins.linter-manager.gschema.xml 2016-10-27 12:57:14 +0000 |
1728 | @@ -0,0 +1,10 @@ |
1729 | +<?xml version="1.0" encoding="UTF-8"?> |
1730 | +<schemalist> |
1731 | + <schema path="/org/pantheon/scratch/plugins/linter-manager/" id="org.pantheon.scratch.plugins.linter-manager" gettext-domain="scratch"> |
1732 | + <key name="auto-run" type="b"> |
1733 | + <default>false</default> |
1734 | + <summary>Run the linter after every save.</summary> |
1735 | + <description>true to run the linter every time the file is saved.</description> |
1736 | + </key> |
1737 | + </schema> |
1738 | +</schemalist> |
1739 | |
1740 | === modified file 'src/Scratch.vala' |
1741 | --- src/Scratch.vala 2016-09-01 04:13:38 +0000 |
1742 | +++ src/Scratch.vala 2016-10-27 12:57:14 +0000 |
1743 | @@ -27,9 +27,11 @@ |
1744 | |
1745 | public class ScratchApp : Granite.Application { |
1746 | public string app_cmd_name { get { return _app_cmd_name; } } |
1747 | + public string data_home_folder { get { return _data_home_folder; } } |
1748 | public string data_home_folder_unsaved { get { return _data_home_folder_unsaved; } } |
1749 | public string default_font { get; set; } |
1750 | private static string _app_cmd_name; |
1751 | + private static string _data_home_folder; |
1752 | private static string _data_home_folder_unsaved; |
1753 | private static string _cwd; |
1754 | private static bool print_version = false; |
1755 | @@ -87,7 +89,8 @@ |
1756 | services = new ServicesSettings (); |
1757 | |
1758 | // Init data home folder for unsaved text files |
1759 | - _data_home_folder_unsaved = Environment.get_user_data_dir () + "/" + exec_name + "/unsaved/"; |
1760 | + _data_home_folder = "%s/%s/".printf (Environment.get_user_data_dir (), exec_name); |
1761 | + _data_home_folder_unsaved ="%s/%s/%s/".printf (Environment.get_user_data_dir (), exec_name, "unsaved"); |
1762 | } |
1763 | |
1764 | public static ScratchApp _instance = null; |
My comments on the code are inlined.