origami 2.0.4 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,84 +0,0 @@
1
- =begin
2
-
3
- This file is part of PDF Walker, a graphical PDF file browser
4
- Copyright (C) 2016 Guillaume Delugré.
5
-
6
- PDF Walker is free software: you can redistribute it and/or modify
7
- it under the terms of the GNU General Public License as published by
8
- the Free Software Foundation, either version 3 of the License, or
9
- (at your option) any later version.
10
-
11
- PDF Walker is distributed in the hope that it will be useful,
12
- but WITHOUT ANY WARRANTY; without even the implied warranty of
13
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
- GNU General Public License for more details.
15
-
16
- You should have received a copy of the GNU General Public License
17
- along with PDF Walker. If not, see <http://www.gnu.org/licenses/>.
18
-
19
- =end
20
-
21
- require 'gui/gtkhex'
22
-
23
- module PDFWalker
24
-
25
- class Walker < Window
26
- private
27
-
28
- def create_hexview
29
- @hexview = DumpView.new(self)
30
- end
31
-
32
- class DumpView < ScrolledWindow
33
-
34
- def initialize(parent)
35
- @parent = parent
36
- super()
37
-
38
- set_policy(POLICY_AUTOMATIC, POLICY_AUTOMATIC)
39
-
40
- @current_obj = nil
41
-
42
- @view = HexEditor.new
43
- @view.show_offsets(true)
44
-
45
- add_with_viewport @view
46
- end
47
-
48
- def clear
49
- @view.set_data ''
50
- end
51
-
52
- def load(object)
53
- return if @current_obj.equal?(object)
54
-
55
- self.clear
56
-
57
- case object
58
- when Origami::Stream
59
- load_stream(object)
60
- when Origami::String
61
- load_string(object)
62
- end
63
-
64
- @current_obj = object
65
- end
66
-
67
- private
68
-
69
- def load_stream(object)
70
- begin
71
- @view.set_data(object.data)
72
- rescue Origami::Filter::Error
73
- @view.set_data($!.input_data) if $!.input_data
74
-
75
- @parent.error("#{$!.class}: #{$!.message}") unless object.filters == [ :DCTDecode ]
76
- end
77
- end
78
-
79
- def load_string(object)
80
- @view.set_data(object.value)
81
- end
82
- end
83
- end
84
- end
@@ -1,69 +0,0 @@
1
- =begin
2
-
3
- This file is part of PDF Walker, a graphical PDF file browser
4
- Copyright (C) 2016 Guillaume Delugré.
5
-
6
- PDF Walker is free software: you can redistribute it and/or modify
7
- it under the terms of the GNU General Public License as published by
8
- the Free Software Foundation, either version 3 of the License, or
9
- (at your option) any later version.
10
-
11
- PDF Walker is distributed in the hope that it will be useful,
12
- but WITHOUT ANY WARRANTY; without even the implied warranty of
13
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
- GNU General Public License for more details.
15
-
16
- You should have received a copy of the GNU General Public License
17
- along with PDF Walker. If not, see <http://www.gnu.org/licenses/>.
18
-
19
- =end
20
-
21
- module PDFWalker
22
-
23
- class ImgViewer < Window
24
- attr_reader :image
25
-
26
- def initialize
27
- super()
28
-
29
- set_title "Image view"
30
- set_decorated false
31
- set_resizable false
32
-
33
- add_events(Gdk::Event::KEY_RELEASE_MASK)
34
- signal_connect('key_release_event') { |_, event|
35
- destroy if event.keyval == Gdk::Keyval::GDK_Escape
36
- }
37
- end
38
-
39
- def show_raw_img(data, w, h, bpc, bpr)
40
- set_default_size w,h
41
-
42
- pixbuf = GdkPixbuf::Pixbuf.new data: data,
43
- colorspace: GdkPixbuf::Colorspace::RGB,
44
- has_alpha: false,
45
- bits_per_sample: bpc,
46
- width: w, height: h,
47
- row_stride: bpr
48
-
49
- @image = Gtk::Image.new(pixbuf)
50
- add @image
51
-
52
- show_all
53
- end
54
-
55
- def show_compressed_img(data)
56
- loader = Gdk::PixbufLoader.new
57
- loader.last_write data
58
-
59
- pixbuf = loader.pixbuf
60
- set_default_size pixbuf.width, pixbuf.height
61
-
62
- @image = Gtk::Image.new(pixbuf)
63
- add @image
64
-
65
- show_all
66
- end
67
- end
68
-
69
- end
@@ -1,382 +0,0 @@
1
- =begin
2
-
3
- This file is part of PDF Walker, a graphical PDF file browser
4
- Copyright (C) 2016 Guillaume Delugré.
5
-
6
- PDF Walker is free software: you can redistribute it and/or modify
7
- it under the terms of the GNU General Public License as published by
8
- the Free Software Foundation, either version 3 of the License, or
9
- (at your option) any later version.
10
-
11
- PDF Walker is distributed in the hope that it will be useful,
12
- but WITHOUT ANY WARRANTY; without even the implied warranty of
13
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
- GNU General Public License for more details.
15
-
16
- You should have received a copy of the GNU General Public License
17
- along with PDF Walker. If not, see <http://www.gnu.org/licenses/>.
18
-
19
- =end
20
-
21
- module PDFWalker
22
-
23
- module PopupMenu
24
-
25
- @@menus = Hash.new([])
26
- @@menus['PDF'] =
27
- [
28
- {
29
- Name: Stock::SAVE_AS,
30
- Sensitive: true,
31
- Callback: lambda { |_widget, viewer, _path|
32
- viewer.parent.save
33
- }
34
- },
35
- {
36
- Name: :"---"
37
- },
38
- {
39
- Name: Stock::PROPERTIES,
40
- Sensitive: true,
41
- Callback: lambda { |_widget, viewer, _path|
42
- viewer.parent.display_file_properties
43
- }
44
- },
45
- {
46
- Name: :"---"
47
- },
48
- {
49
- Name: Stock::CLOSE,
50
- Sensitive: true,
51
- Callback: lambda { |_widget, viewer, _path|
52
- viewer.parent.close
53
- }
54
- }
55
- ]
56
-
57
- @@menus['Reference'] =
58
- [
59
- {
60
- Name: Stock::JUMP_TO,
61
- Sensitive: true,
62
- Callback: lambda { |_widget, viewer, path|
63
- viewer.row_activated(path, viewer.get_column(viewer.class::TEXTCOL))
64
- }
65
- }
66
- ]
67
-
68
- @@menus['Revision'] =
69
- [
70
- {
71
- Name: "Save to this revision",
72
- Sensitive: true,
73
- Callback: lambda { |_widget, viewer, path|
74
- revstr = viewer.model.get_value(viewer.model.get_iter(path), viewer.class::TEXTCOL)
75
- revstr.slice!(0, "Revision ".size)
76
-
77
- revnum = revstr.to_i
78
-
79
- dialog = Gtk::FileChooserDialog.new("Save PDF File",
80
- viewer.parent,
81
- Gtk::FileChooser::ACTION_SAVE,
82
- nil,
83
- [Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL],
84
- [Gtk::Stock::SAVE, Gtk::Dialog::RESPONSE_ACCEPT]
85
- )
86
-
87
- dialog.filter = FileFilter.new.add_pattern("*.pdf")
88
-
89
- if dialog.run == Gtk::Dialog::RESPONSE_ACCEPT
90
- viewer.parent.opened.save_upto(revnum, dialog.filename)
91
- end
92
-
93
- dialog.destroy
94
- }
95
- }
96
- ]
97
-
98
- @@menus['Stream'] =
99
- [
100
- {
101
- Name: "Dump encoded stream",
102
- Sensitive: true,
103
- Callback: lambda { |_widget, viewer, path|
104
- stream = viewer.object_by_path(path)
105
-
106
- viewer.parent.save_data("Save encoded stream to file", stream.encoded_data)
107
- }
108
- },
109
- {
110
- Name: "Dump decoded stream",
111
- Sensitive: true,
112
- Callback: lambda { |_widget, viewer, path|
113
- stream = viewer.object_by_path(path)
114
-
115
- viewer.parent.save_data("Save decoded stream to file", stream.data)
116
- }
117
- }
118
- ]
119
-
120
- @@menus['String'] =
121
- [
122
- {
123
- Name: "Dump string",
124
- Sensitive: true,
125
- Callback: lambda { |_widget, viewer, path|
126
- string = viewer.object_by_path(path)
127
-
128
- viewer.parent.save_data("Save string to file", string.value)
129
- }
130
- }
131
- ]
132
-
133
- @@menus['Image'] = @@menus['Stream'] +
134
- [
135
- {
136
- Name: :"---"
137
- },
138
- {
139
- Name: "View image",
140
- Sensitive: true,
141
- Callback: lambda { |_widget, viewer, path|
142
- stm = viewer.object_by_path(path)
143
- w,h = stm.Width, stm.Height
144
-
145
- if stm.ColorSpace.nil?
146
- colors = 1
147
- else
148
- colors =
149
- case stm.ColorSpace.value
150
- when :DeviceGray then 1
151
- when :DeviceRGB then 3
152
- when :DeviceCMYK then 4
153
- else
154
- 1
155
- end
156
- end
157
-
158
- bpc = stm.BitsPerComponent || 8
159
- bpr = (w * colors * bpc + 7) >> 3
160
- data = stm.data
161
-
162
- begin
163
- imgview = ImgViewer.new
164
- if stm.Filter == :DCTDecode or (stm.Filter.is_a?(Array) and stm.Filter[0] == :DCTDecode)
165
- imgview.show_compressed_img data
166
- else
167
- imgview.show_raw_img data, w, h, bpc, bpr
168
- end
169
- rescue
170
- viewer.parent.error("#{$!.class}: #{$!.message}")
171
- end
172
- }
173
- }
174
- ]
175
-
176
- def popup_menu(obj, event, path)
177
- menu = Menu.new
178
-
179
- type = popup_menu_key(obj)
180
-
181
- # Create menu title.
182
- title = obj.is_a?(Origami::Object) ? "Object : " : ""
183
- title << type.to_s
184
- menu.append(MenuItem.new(title).set_sensitive(false).modify_text(Gtk::STATE_INSENSITIVE, Gdk::Color.new(255,0,255)))
185
-
186
- # Object information.
187
- create_object_menu(menu, obj) if obj.is_a?(Origami::Object)
188
-
189
- # Type-specific menu.
190
- create_type_menu(menu, type, path)
191
-
192
- menu.show_all
193
- menu.popup(nil, nil, event.button, event.time)
194
- end
195
-
196
- private
197
-
198
- def create_object_menu(menu, object)
199
- if object.indirect?
200
- menu.append(MenuItem.new("Number : #{object.no}; Generation : #{object.generation}").set_sensitive(false))
201
- menu.append(MenuItem.new("File offset : #{object.file_offset}").set_sensitive(false))
202
-
203
- getxrefs = MenuItem.new("Search references to this object").set_sensitive(true)
204
- getxrefs.signal_connect("activate") do
205
- self.parent.show_xrefs(object)
206
- end
207
- menu.append(getxrefs)
208
-
209
- elsif not object.parent.nil?
210
- gotoparent = MenuItem.new("Goto Parent Object").set_sensitive(true)
211
- gotoparent.signal_connect("activate") do
212
- self.goto(object.parent)
213
- end
214
- menu.append(gotoparent)
215
- end
216
- end
217
-
218
- def create_type_menu(menu, type, path)
219
- items = @@menus[type]
220
- menu.append(SeparatorMenuItem.new) if not items.empty?
221
-
222
- items.each do |item|
223
- if item[:Name] == :"---"
224
- entry = SeparatorMenuItem.new
225
- else
226
- if item[:Name].is_a?(String)
227
- entry = MenuItem.new(item[:Name])
228
- else
229
- entry = ImageMenuItem.new(item[:Name])
230
- end
231
-
232
- entry.set_sensitive(item[:Sensitive])
233
- entry.signal_connect("activate", self, path, &item[:Callback])
234
- end
235
-
236
- menu.append(entry)
237
- end
238
- end
239
-
240
- def popup_menu_key(object)
241
- if object.is_a?(Origami::Object)
242
- popup_menu_object_key(object)
243
- else
244
- popup_menu_struct_key(object)
245
- end
246
- end
247
-
248
- def popup_menu_object_key(object)
249
- if object.is_a?(Origami::Graphics::ImageXObject)
250
- 'Image'
251
- else
252
- object.native_type.to_s.split("::").last
253
- end
254
- end
255
-
256
- def popup_menu_struct_key(struct)
257
- case struct
258
- when ::Array
259
- 'Body'
260
- when Origami::XRef, Origami::XRefToCompressedObject
261
- 'XRef'
262
- else
263
- struct.class.name.split('::').last
264
- end
265
- end
266
- end
267
-
268
- class Walker < Window
269
-
270
- private
271
-
272
- def create_menus
273
- AccelMap.add_entry("<PDF Walker>/File/Open", Gdk::Keyval::GDK_O, Gdk::Window::CONTROL_MASK)
274
- AccelMap.add_entry("<PDF Walker>/File/Refresh", Gdk::Keyval::GDK_R, Gdk::Window::CONTROL_MASK)
275
- AccelMap.add_entry("<PDF Walker>/File/Close", Gdk::Keyval::GDK_W, Gdk::Window::CONTROL_MASK)
276
- AccelMap.add_entry("<PDF Walker>/File/Save", Gdk::Keyval::GDK_S, Gdk::Window::CONTROL_MASK)
277
- AccelMap.add_entry("<PDF Walker>/File/Quit", Gdk::Keyval::GDK_Q, Gdk::Window::CONTROL_MASK)
278
- AccelMap.add_entry("<PDF Walker>/Document/Search", Gdk::Keyval::GDK_F, Gdk::Window::CONTROL_MASK)
279
-
280
- @menu = MenuBar.new
281
-
282
- create_file_menu
283
- create_document_menu
284
- create_help_menu
285
- end
286
-
287
- def create_file_menu
288
- file_ag = Gtk::AccelGroup.new
289
- @file_menu = Menu.new.set_accel_group(file_ag).set_accel_path("<PDF Walker>/File")
290
- add_accel_group(file_ag)
291
-
292
- entries = [
293
- @file_menu_open = ImageMenuItem.new(Stock::OPEN).set_accel_path("<PDF Walker>/File/Open"),
294
- @file_menu_recent = MenuItem.new("Last opened"),
295
- @file_menu_refresh = ImageMenuItem.new(Stock::REFRESH).set_sensitive(false).set_accel_path("<PDF Walker>/File/Refresh"),
296
- @file_menu_close = ImageMenuItem.new(Stock::CLOSE).set_sensitive(false).set_accel_path("<PDF Walker>/File/Close"),
297
- @file_menu_saveas = ImageMenuItem.new(Stock::SAVE_AS).set_sensitive(false).set_accel_path("<PDF Walker>/File/Save"),
298
- @file_menu_exit = ImageMenuItem.new(Stock::QUIT).set_accel_path("<PDF Walker>/File/Quit"),
299
- ]
300
-
301
- @file_menu_open.signal_connect('activate') { open }
302
- @file_menu_refresh.signal_connect('activate') { open(@filename) }
303
- @file_menu_close.signal_connect('activate') { close }
304
- @file_menu_saveas.signal_connect('activate') { save }
305
- @file_menu_exit.signal_connect('activate') { self.destroy }
306
-
307
- update_recent_menu
308
-
309
- entries.each do |entry|
310
- @file_menu.append(entry)
311
- end
312
-
313
- @menu.append(MenuItem.new('_File').set_submenu(@file_menu))
314
- end
315
-
316
- def create_document_menu
317
- doc_ag = Gtk::AccelGroup.new
318
- @document_menu = Menu.new.set_accel_group(doc_ag)
319
- add_accel_group(doc_ag)
320
-
321
- entries = [
322
- @document_menu_search = ImageMenuItem.new(Stock::FIND).set_sensitive(false).set_accel_path("<PDF Walker>/Document/Search"),
323
- MenuItem.new,
324
- @document_menu_gotocatalog = MenuItem.new("Jump to Catalog").set_sensitive(false),
325
- @document_menu_gotodocinfo = MenuItem.new("Jump to Document Info").set_sensitive(false),
326
- @document_menu_gotometadata = MenuItem.new("Jump to Metadata").set_sensitive(false),
327
- @document_menu_gotorev = MenuItem.new("Jump to Revision...").set_sensitive(false),
328
- @document_menu_gotopage = MenuItem.new("Jump to Page...").set_sensitive(false),
329
- @document_menu_gotofield = MenuItem.new("Jump to Field...").set_sensitive(false),
330
- @document_menu_gotoobj = MenuItem.new("Jump to Object...").set_sensitive(false),
331
- MenuItem.new,
332
- @document_menu_sign = MenuItem.new("Sign the document").set_sensitive(false),
333
- @document_menu_ur = MenuItem.new("Enable Usage Rights").set_sensitive(false),
334
- @document_menu_properties = ImageMenuItem.new(Stock::PROPERTIES).set_sensitive(false),
335
- ]
336
-
337
- @document_menu_search.signal_connect('activate') { search }
338
- @document_menu_gotocatalog.signal_connect('activate') { goto_catalog }
339
- @document_menu_gotodocinfo.signal_connect('activate') { goto_docinfo }
340
- @document_menu_gotometadata.signal_connect('activate') { goto_metadata }
341
- @document_menu_gotoobj.signal_connect('activate') { goto_object }
342
- @document_menu_properties.signal_connect('activate') { display_file_properties }
343
- @document_menu_sign.signal_connect('activate') { display_signing_wizard }
344
- @document_menu_ur.signal_connect('activate') { display_usage_rights_wizard }
345
-
346
- entries.each do |entry|
347
- @document_menu.append(entry)
348
- end
349
-
350
- @menu.append(MenuItem.new('_Document').set_submenu(@document_menu))
351
- end
352
-
353
- def create_help_menu
354
- @help_menu = Menu.new
355
-
356
- @help_menu_profile = CheckMenuItem.new("Profiling (Debug purposes only)").set_active(@config.profile?)
357
- @help_menu_about = ImageMenuItem.new(Stock::ABOUT)
358
-
359
- @help_menu_profile.signal_connect('toggled') do @config.set_profiling(@help_menu_profile.active?) end
360
- @help_menu_about.signal_connect('activate') { about }
361
-
362
- @help_menu.append(@help_menu_profile)
363
- @help_menu.append(@help_menu_about)
364
-
365
- @menu.append(MenuItem.new('_Help').set_submenu(@help_menu))
366
- end
367
-
368
- def update_recent_menu
369
- @recent_menu = Menu.new
370
- @config.recent_files.each { |file|
371
- menu = MenuItem.new(file)
372
- menu.signal_connect('activate') do open(file) end
373
-
374
- @recent_menu.append(menu)
375
- }
376
-
377
- @file_menu_recent.set_submenu(@recent_menu)
378
- @file_menu_recent.show_all
379
- end
380
- end
381
-
382
- end