Merge lp:~artem-anufrij/scratch/Bugfix-1222075 into lp:~elementary-apps/scratch/scratch

Proposed by Artem Anufrij
Status: Superseded
Proposed branch: lp:~artem-anufrij/scratch/Bugfix-1222075
Merge into: lp:~elementary-apps/scratch/scratch
Diff against target: 330 lines (+277/-4)
5 files modified
plugins/CMakeLists.txt (+2/-1)
plugins/clipboard-history/CMakeLists.txt (+28/-0)
plugins/clipboard-history/ClipboardHistory.vala (+230/-0)
plugins/clipboard-history/clipboard-history.plugin (+10/-0)
src/Widgets/SourceView.vala (+7/-3)
To merge this branch: bzr merge lp:~artem-anufrij/scratch/Bugfix-1222075
Reviewer Review Type Date Requested Status
Robert Roth Pending
Review via email: mp+241634@code.launchpad.net

This proposal supersedes a proposal from 2014-11-07.

This proposal has been superseded by a proposal from 2014-12-02.

Description of the change

"Clipboard History" was implemented into Scratch.

"Clipboard History" stores all COPY and CUT actions. System-wide.

Please test it and give me your feedback!

To post a comment you must log in.
Revision history for this message
Robert Roth (evfool) wrote : Posted in a previous version of this proposal

On clicking Paste on one of the items from the clipboard history, I get the following in the console :
[_LOG_LEVEL_FATAL 18:44:12.349959] [GLib] g_string_erase: assertion 'pos >= 0' failed
[_LOG_LEVEL_FATAL 18:44:12.350001] Scratch will not function properly.
Other than that, the plugin could be more useful if it would listen for Gtk clipboard changes [1] (currently only text cut/copied from scratch is added)

[1] https://developer.gnome.org/gtk3/stable/gtk3-Clipboards.html

review: Needs Fixing
Revision history for this message
Artem Anufrij (artem-anufrij) wrote : Posted in a previous version of this proposal

Hey Robert,

always when you add a new tab, scratch throws this exeption. It's not a plugin Error.

"[_LOG_LEVEL_FATAL 18:44:12.349959] [GLib] g_string_erase: assertion 'pos >= 0' failed"

> Other than that, the plugin could be more useful if it would listen for Gtk clipboard changes [1] (currently only text cut/copied from scratch is added)

Thanks for the tip! I will implement it!!!

Revision history for this message
Artem Anufrij (artem-anufrij) wrote :

What is still missing in this case?

Revision history for this message
Artem Anufrij (artem-anufrij) wrote :

Clipboard history stores all COPY and CUT actions. System-wide.

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'plugins/CMakeLists.txt'
--- plugins/CMakeLists.txt 2014-06-16 22:28:26 +0000
+++ plugins/CMakeLists.txt 2014-11-12 23:59:09 +0000
@@ -12,4 +12,5 @@
12add_subdirectory (source-tree)12add_subdirectory (source-tree)
13add_subdirectory (outline)13add_subdirectory (outline)
14add_subdirectory (vim-emulation)14add_subdirectory (vim-emulation)
15add_subdirectory (highlight-word-selection)
16\ No newline at end of file15\ No newline at end of file
16add_subdirectory (highlight-word-selection)
17add_subdirectory (clipboard-history)
17\ No newline at end of file18\ No newline at end of file
1819
=== added directory 'plugins/clipboard-history'
=== added file 'plugins/clipboard-history/CMakeLists.txt'
--- plugins/clipboard-history/CMakeLists.txt 1970-01-01 00:00:00 +0000
+++ plugins/clipboard-history/CMakeLists.txt 2014-11-12 23:59:09 +0000
@@ -0,0 +1,28 @@
1add_definitions(${NORMAL_CFLAGS})
2include_directories(${CMAKE_BINARY_DIR} ${CMAKE_BINARY_DIR}/scratchcore/)
3link_directories(${NORMAL_LINK_DIRS})
4
5vala_precompile(VALA_C
6 ClipboardHistory.vala
7PACKAGES
8 granite
9 gtksourceview-3.0
10 scratchcore
11 gee-0.8
12 libpeas-1.0
13 ${ZEITGEIST_DEPS}
14OPTIONS
15 --thread
16 --vapidir=${CMAKE_BINARY_DIR}
17 --vapidir=${CMAKE_BINARY_DIR}/src/
18 --vapidir=${CMAKE_SOURCE_DIR}/vapi/
19 --vapidir=${CMAKE_BINARY_DIR}/scratchcore/
20)
21
22add_library(clipboard-history MODULE ${VALA_C})
23add_dependencies(clipboard-history scratchcore scratch)
24
25install(TARGETS clipboard-history DESTINATION lib/scratch/plugins/clipboard-history/)
26install(FILES clipboard-history.plugin DESTINATION lib/scratch/plugins/clipboard-history/)
27
28message("-- Clipboard History plugin will be compiled")
0\ No newline at end of file29\ No newline at end of file
130
=== added file 'plugins/clipboard-history/ClipboardHistory.vala'
--- plugins/clipboard-history/ClipboardHistory.vala 1970-01-01 00:00:00 +0000
+++ plugins/clipboard-history/ClipboardHistory.vala 2014-11-12 23:59:09 +0000
@@ -0,0 +1,230 @@
1// -*- Mode: vala; indent-tabs-mode: nil; tab-width: 4 -*-
2/***
3 BEGIN LICENSE
4
5 Copyright (C) 2014 Artem Anufrij <artem.anufrij@live.de>
6 This program is free software: you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License version 3, as published
8 by the Free Software Foundation.
9
10 This program is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranties of
12 MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
13 PURPOSE. See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License along
16 with this program. If not, see <http://www.gnu.org/licenses/>
17
18 END LICENSE
19***/
20
21public const string NAME = N_("Clipboard History");
22public const string DESCRIPTION = N_("Clipboard to view history");
23
24public class Scratch.Plugins.ClipboardHistory : Peas.ExtensionBase, Peas.Activatable {
25
26 const int MAX_SIZE = 32;
27 const int MAX_LINE_LENGTH = 24;
28 const string DOTS = _("...");
29 MainWindow window = null;
30 Gtk.Notebook? contextbar = null;
31
32 Gtk.ScrolledWindow scrolled;
33 Gtk.ListStore list_store;
34 Gtk.TreeIter iter;
35 Gtk.TreeView view;
36
37 Gtk.Menu menu;
38 Gtk.MenuItem menu_paste;
39 Gtk.MenuItem menu_delete;
40
41 Scratch.Services.Interface plugins;
42 public Object object { owned get; construct; }
43
44 public void update_state () {
45 }
46
47 public void activate () {
48 debug ("-- %s avtivate", NAME);
49
50 plugins = (Scratch.Services.Interface) object;
51
52 plugins.hook_window.connect ((w) => {
53 if(window != null)
54 return;
55
56 window = w;
57 window.clipboard.owner_change.connect (clipboard_action);
58 });
59
60 plugins.hook_notebook_context.connect ((n) => {
61 if (contextbar == null) {
62 this.contextbar = n;
63
64 build_plugin_ui ();
65 }
66 });
67 }
68
69 public void deactivate () {
70 debug ("-- %s deavtivate", NAME);
71
72 contextbar.remove_page (contextbar.page_num (scrolled));
73
74 window.clipboard.owner_change.disconnect (clipboard_action);
75 }
76
77 void clipboard_action(Gdk.Event event) {
78 string? clipboard_content = window.clipboard.wait_for_text ();
79 if (clipboard_content != null)
80 add_clipboard_item (clipboard_content);
81 }
82
83 void add_clipboard_item (string clipboard_content) {
84 if(clipboard_content == "")
85 return;
86
87 // Set the plugin visible
88 if (contextbar.page_num (scrolled) == -1)
89 contextbar.append_page (scrolled, new Gtk.Label (_("Clipboard History")));
90
91 // Delete last item, if the size of the list store > MAX_SIZE
92 if (list_store.get_iter_from_string (out iter, (MAX_SIZE - 1).to_string ()))
93 list_store.remove (iter);
94
95 // Delete dupplicates from list store, if exists
96 delete_dupplicates (clipboard_content);
97
98 // Create a short title
99 string title = create_clipboard_item_title (clipboard_content);
100
101 if (title == "")
102 return;
103
104 // Add a new item
105 list_store.insert (out iter, 0);
106 list_store.set (iter, 0, "edit-paste", 1, title, 2, clipboard_content);
107 }
108
109 string create_clipboard_item_title (string clipboard_content) {
110
111 string [] lines = clipboard_content.split ("\n");
112
113 string title = "";
114
115 for (int i = 0; i < lines.length; i++ ){
116 if (lines [i].strip () != "") {
117 title = lines [i];
118 if (i > 0)
119 title = DOTS + title; // ...Code
120 if (title.length > MAX_LINE_LENGTH)
121 title = title.substring (0, MAX_LINE_LENGTH) + DOTS; // Code...
122 else if (i + 1 < lines.length)
123 title += DOTS; // Code...
124 break;
125 }
126 }
127
128 return title;
129 }
130
131 void delete_dupplicates (string new_clipboard_string) {
132 Gtk.TreeIter? to_delete = null;
133 list_store.foreach ((model, path, it) => {
134 Value content;
135 list_store.get_value (it, 2, out content);
136 string clipboard_string = content.get_string ();
137 if (clipboard_string == new_clipboard_string) {
138 to_delete = it;
139 return true;
140 }
141
142 return false;
143 });
144
145 if (to_delete != null)
146 list_store.remove (to_delete);
147 }
148
149 void build_plugin_ui () {
150 scrolled = new Gtk.ScrolledWindow (null, null);
151 list_store = new Gtk.ListStore (3, typeof (string), typeof (string), typeof (string));
152
153 // Context Menu
154 menu = new Gtk.Menu ();
155
156 menu_delete = new Gtk.MenuItem.with_label (_("Delete"));
157 menu_delete.activate.connect (delete_selected);
158
159 menu_paste = new Gtk.MenuItem.with_label (_("Paste"));
160 menu_paste.activate.connect (paste_selected);
161
162 menu.append (menu_paste);
163 menu.append (menu_delete);
164
165 menu.show_all ();
166
167 // The View
168 view = new Gtk.TreeView.with_model (list_store);
169 view.headers_visible = false;
170 view.set_tooltip_column (2);
171
172 view.insert_column_with_attributes (-1, "icon-name", new Gtk.CellRendererPixbuf (), "icon_name", 0);
173 view.insert_column_with_attributes (-1, "clipboard", new Gtk.CellRendererText (), "text", 1);
174 view.button_press_event.connect (show_context_menu);
175
176 scrolled.add (view);
177 scrolled.show_all ();
178 }
179
180 public bool show_context_menu (Gtk.Widget sender, Gdk.EventButton evt) {
181 if (evt.type == Gdk.EventType.BUTTON_PRESS && evt.button == 3)
182 menu.popup (null, null, null, evt.button, evt.time);
183
184 return false;
185 }
186
187 public void paste_selected () {
188 var selection = view.get_selection();
189 selection.set_mode(Gtk.SelectionMode.SINGLE);
190 Gtk.TreeModel model;
191 Gtk.TreeIter iter;
192 if (!selection.get_selected(out model, out iter)) {
193 return;
194 }
195 Value content;
196 model.get_value(iter, 2, out content);
197 string clipboard_string = content.get_string ();
198
199 Scratch.Services.Document? current_document = window.get_current_document ();
200
201 if (current_document == null)
202 return;
203 // Set focus on active document, delete selected text and paste the value from selected item.
204 current_document.focus();
205 current_document.source_view.delete_from_cursor (Gtk.DeleteType.CHARS, current_document.source_view.get_selected_text ().length);
206 current_document.source_view.insert_at_cursor (clipboard_string);
207 }
208
209 public void delete_selected () {
210 var selection = view.get_selection();
211 selection.set_mode(Gtk.SelectionMode.SINGLE);
212 Gtk.TreeModel model;
213 Gtk.TreeIter iter;
214 if (!selection.get_selected(out model, out iter)) {
215 return;
216 }
217 list_store.remove (iter);
218
219 // Hiding PlugIn, if no more items exist in the list store.
220 if (!list_store.get_iter_first (out iter))
221 contextbar.remove_page (contextbar.page_num (scrolled));
222 }
223}
224
225[ModuleInit]
226public void peas_register_types (GLib.TypeModule module) {
227 var objmodule = module as Peas.ObjectModule;
228 objmodule.register_extension_type (typeof (Peas.Activatable),
229 typeof (Scratch.Plugins.ClipboardHistory));
230}
0\ No newline at end of file231\ No newline at end of file
1232
=== added file 'plugins/clipboard-history/clipboard-history.plugin'
--- plugins/clipboard-history/clipboard-history.plugin 1970-01-01 00:00:00 +0000
+++ plugins/clipboard-history/clipboard-history.plugin 2014-11-12 23:59:09 +0000
@@ -0,0 +1,10 @@
1[Plugin]
2Module=clipboard-history
3Loader=C
4IAge=2
5Name=Clipboard History
6Description=Clipboard History
7Icon=edit-paste
8Authors=Artem Anufrij <artem.anufrij@live.de>
9Copyright=Copyright © 2014 Scratch and Artem Anufrij
10Website=http://launchpad.net/scratch
0\ No newline at end of file11\ No newline at end of file
112
=== modified file 'src/Widgets/SourceView.vala'
--- src/Widgets/SourceView.vala 2014-10-29 19:28:47 +0000
+++ src/Widgets/SourceView.vala 2014-11-12 23:59:09 +0000
@@ -260,11 +260,12 @@
260 }260 }
261261
262 // Get selected text262 // Get selected text
263 public string get_selected_text () {263 public string get_selected_text (bool replace_new_line = true) {
264 TextIter start, end;264 TextIter start, end;
265 this.buffer.get_selection_bounds (out start, out end);265 this.buffer.get_selection_bounds (out start, out end);
266 string selected = this.buffer.get_text (start, end, true);266 string selected = this.buffer.get_text (start, end, true);
267 selected = selected.chomp ().replace ("\n", " ");267 if (replace_new_line)
268 selected = selected.chomp ().replace ("\n", " ");
268 return selected;269 return selected;
269 }270 }
270271
@@ -306,7 +307,10 @@
306 buffer.place_cursor (start);307 buffer.place_cursor (start);
307 }308 }
308309
309 public void set_language (SourceLanguage lang) {310 public void set_language (SourceLanguage? lang) {
311 if (lang == null)
312 return;
313
310 this.buffer.set_language (lang);314 this.buffer.set_language (lang);
311 this.language_changed (lang);315 this.language_changed (lang);
312 }316 }

Subscribers

People subscribed via source and target branches