origami 2.0.4 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,308 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- =begin
4
-
5
- This file is part of PDF Walker, a graphical PDF file browser
6
- Copyright (C) 2016 Guillaume Delugré.
7
-
8
- PDF Walker is free software: you can redistribute it and/or modify
9
- it under the terms of the GNU General Public License as published by
10
- the Free Software Foundation, either version 3 of the License, or
11
- (at your option) any later version.
12
-
13
- PDF Walker is distributed in the hope that it will be useful,
14
- but WITHOUT ANY WARRANTY; without even the implied warranty of
15
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
- GNU General Public License for more details.
17
-
18
- You should have received a copy of the GNU General Public License
19
- along with PDF Walker. If not, see <http://www.gnu.org/licenses/>.
20
-
21
- =end
22
-
23
- begin
24
- require 'gtk2'
25
- rescue LoadError
26
- abort('Error: you need to install ruby-gtk2 to run this application')
27
- end
28
- include Gtk
29
-
30
- begin
31
- require 'origami'
32
- rescue LoadError
33
- $: << File.join(__dir__, '../../lib')
34
- require 'origami'
35
- end
36
-
37
- require 'gui/menu'
38
- require 'gui/about'
39
- require 'gui/file'
40
- require 'gui/hexview'
41
- require 'gui/treeview'
42
- require 'gui/textview'
43
- require 'gui/imgview'
44
- require 'gui/config'
45
- require 'gui/properties'
46
- require 'gui/xrefs'
47
- require 'gui/signing'
48
-
49
- module PDFWalker #:nodoc:all
50
-
51
- class Walker < Window
52
- attr_reader :treeview, :hexview, :objectview
53
- attr_reader :explorer_history
54
- attr_reader :config
55
- attr_reader :filename
56
-
57
- def self.start(file = nil)
58
- Gtk.init
59
- Walker.new(file)
60
- Gtk.main
61
- end
62
-
63
- def initialize(target_file = nil)
64
- super("PDF Walker")
65
-
66
- @config = Walker::Config.new
67
- @opened = nil
68
-
69
- @last_search_result = []
70
- @last_search =
71
- {
72
- :expr => "",
73
- :regexp => false,
74
- :type => :body
75
- }
76
-
77
- @explorer_history = []
78
-
79
- init_interface
80
-
81
- open(target_file)
82
- end
83
-
84
- def error(msg)
85
- dialog = Gtk::MessageDialog.new(self,
86
- Gtk::Dialog::DESTROY_WITH_PARENT,
87
- Gtk::MessageDialog::ERROR,
88
- Gtk::MessageDialog::BUTTONS_CLOSE,
89
- msg
90
- )
91
-
92
- dialog.run
93
- dialog.destroy
94
- end
95
-
96
- def reload
97
- @treeview.load(@opened) if @opened
98
- end
99
-
100
- def search
101
- dialog = Gtk::Dialog.new("Search...",
102
- self,
103
- Gtk::Dialog::MODAL | Gtk::Dialog::DESTROY_WITH_PARENT,
104
- [Gtk::Stock::FIND, Gtk::Dialog::RESPONSE_OK],
105
- [Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL]
106
- )
107
-
108
- entry = Gtk::Entry.new
109
- entry.signal_connect('activate') { dialog.response(Gtk::Dialog::RESPONSE_OK) }
110
- entry.text = @last_search[:expr]
111
-
112
- button_bydata = Gtk::RadioButton.new("In object body")
113
- button_byname = Gtk::RadioButton.new(button_bydata, "In object name")
114
- button_regexp = Gtk::CheckButton.new("Regular expression")
115
-
116
- button_bydata.set_active(true) if @last_search[:type] == :body
117
- button_byname.set_active(true) if @last_search[:type] == :name
118
- button_regexp.set_active(@last_search[:regexp])
119
-
120
- hbox = HBox.new
121
- hbox.pack_start Gtk::Label.new("Search for expression ")
122
- hbox.pack_start entry
123
-
124
- dialog.vbox.pack_start(hbox)
125
- dialog.vbox.pack_start(button_bydata)
126
- dialog.vbox.pack_start(button_byname)
127
- dialog.vbox.pack_end(button_regexp)
128
-
129
- dialog.signal_connect('response') do |_, response|
130
- if response != Gtk::Dialog::RESPONSE_OK
131
- dialog.destroy
132
- next
133
- end
134
-
135
- search_document(entry.text, regexp: button_regexp.active?, type: (button_bydata.active? ? 'body' : 'name'))
136
- end
137
-
138
- dialog.show_all
139
- end
140
-
141
- def goto_catalog
142
- @treeview.goto(@opened.Catalog.reference)
143
- end
144
-
145
- def goto_docinfo
146
- @treeview.goto(@opened.document_info.reference) if @opened.document_info?
147
- end
148
-
149
- def goto_metadata
150
- @treeview.goto(@opened.Catalog.Metadata.reference) if @opened.metadata?
151
- end
152
-
153
- def goto_object
154
- dialog = Gtk::Dialog.new("Jump to object...",
155
- self,
156
- Gtk::Dialog::MODAL | Gtk::Dialog::DESTROY_WITH_PARENT,
157
- [Gtk::Stock::OK, Gtk::Dialog::RESPONSE_OK],
158
- [Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL]
159
- )
160
-
161
- entry = Gtk::Entry.new
162
- entry.signal_connect('activate') { dialog.response(Gtk::Dialog::RESPONSE_OK) }
163
-
164
- dialog.vbox.pack_start Gtk::Label.new("Object number: ")
165
- dialog.vbox.pack_start entry
166
- dialog.show_all
167
-
168
- no = 0
169
- dialog.run do |response|
170
- no = entry.text.to_i if response == Gtk::Dialog::RESPONSE_OK
171
-
172
- dialog.destroy
173
- end
174
-
175
- return unless no > 0
176
-
177
- obj = @opened[no]
178
- if obj.nil?
179
- error("Object #{no} not found.")
180
- else
181
- @treeview.goto(obj)
182
- end
183
- end
184
-
185
- private
186
-
187
- def init_interface
188
- signal_connect('destroy') {
189
- @config.save
190
- Gtk.main_quit
191
- }
192
-
193
- add_events(Gdk::Event::KEY_RELEASE_MASK)
194
- signal_connect('key_release_event') { |_w, event|
195
- if event.keyval == Gdk::Keyval::GDK_F1 then about
196
- elsif event.keyval == Gdk::Keyval::GDK_Escape and @opened and not @explorer_history.empty?
197
- @treeview.goto(@explorer_history.pop)
198
- end
199
- }
200
-
201
- create_menus
202
- create_treeview
203
- create_hexview
204
- create_objectview
205
- create_panels
206
- create_statusbar
207
-
208
- @vbox = VBox.new
209
- @vbox.pack_start(@menu, false, false)
210
- @vbox.pack_start(@hpaned)
211
- @vbox.pack_end(@statusbar, false, false)
212
-
213
- add @vbox
214
-
215
- set_default_size(self.screen.width * 0.5, self.screen.height * 0.5)
216
- show_all
217
- end
218
-
219
- def search_document(expr, regexp: false, type: 'body')
220
- search =
221
- {
222
- expr: expr,
223
- regexp: regexp,
224
- type: type,
225
- }
226
-
227
- if search == @last_search
228
- @last_search_result.push @last_search_result.shift
229
- results = @last_search_result
230
- else
231
- expr = Regexp.new(expr) if search[:regexp]
232
-
233
- results =
234
- if search[:type] == 'body'
235
- @opened.grep(expr)
236
- else
237
- @opened.ls(expr, follow_references: false)
238
- end
239
-
240
- @last_search = search
241
- end
242
-
243
- goto_next_search_result(results)
244
- end
245
-
246
- def goto_next_search_result(results)
247
- if results.empty?
248
- error("No result found.")
249
- else
250
- if results != @last_search_result
251
- # Reset the previous search highlighting.
252
- @last_search_result.each do |obj| @treeview.highlight(obj, nil) end
253
-
254
- # Highlight the new results.
255
- results.each do |obj| @treeview.highlight(obj, "lightpink") end
256
-
257
- @last_search_result = results
258
- end
259
-
260
- @treeview.goto(results.first, follow_references: false)
261
- end
262
- end
263
-
264
- def create_panels
265
- @hpaned = HPaned.new
266
-
267
- @treepanel = ScrolledWindow.new.set_policy(POLICY_AUTOMATIC, POLICY_AUTOMATIC)
268
- @treepanel.add @treeview
269
-
270
- @vpaned = VPaned.new
271
- @vpaned.pack1(@objectview, true, false)
272
- @vpaned.pack2(@hexview, true, false)
273
-
274
- @hpaned.pack1(@treepanel, true, false)
275
- @hpaned.pack2(@vpaned, true, false)
276
- end
277
-
278
- def create_statusbar
279
- @statusbar = Statusbar.new
280
-
281
- @main_context = @statusbar.get_context_id 'Main'
282
- @statusbar.push(@main_context, 'No file selected')
283
- end
284
-
285
- def start_profiling
286
- if @help_menu_profile.active?
287
- require 'ruby-prof'
288
- RubyProf.start
289
- end
290
-
291
- result = yield
292
-
293
- if @help_menu_profile.active?
294
- result = RubyProf.stop
295
- multiprinter = RubyProf::MultiPrinter.new(result)
296
-
297
- Dir.mkdir(@config.profile_output_dir) unless Dir.exist?(@config.profile_output_dir)
298
-
299
- multiprinter.print(path: @config.profile_output_dir, profile: File.basename(filename))
300
- end
301
-
302
- result
303
- end
304
- end
305
-
306
- end
307
-
308
- PDFWalker::Walker.start if __FILE__ == $0
@@ -1,75 +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 Walker < Window
24
- def show_xrefs(target)
25
- XrefsDialog.new(self, target)
26
- end
27
- end
28
-
29
- class XrefsDialog < Dialog
30
- OBJCOL = 0
31
- REFCOL = 1
32
- NAMECOL = 2
33
-
34
- def initialize(parent, target)
35
- super("Xrefs to #{target.reference}", parent, Dialog::MODAL, [Stock::CLOSE, Dialog::RESPONSE_NONE])
36
- @parent = parent
37
-
38
- @list = ListStore.new(Object, String, String)
39
- @view = TreeView.new(@list)
40
-
41
- column = Gtk::TreeViewColumn.new("Origin", Gtk::CellRendererText.new, text: REFCOL)
42
- @view.append_column(column)
43
-
44
- column = Gtk::TreeViewColumn.new("Objects", Gtk::CellRendererText.new, text: NAMECOL)
45
- @view.append_column(column)
46
-
47
- target.xrefs.each { |obj|
48
- str = obj.type.to_s
49
- iter = @list.append
50
- @list.set_value(iter, OBJCOL, obj)
51
-
52
- obj = obj.parent until obj.indirect?
53
- @list.set_value(iter, REFCOL, obj.reference.to_s)
54
-
55
- @list.set_value(iter, NAMECOL, str)
56
- }
57
-
58
- @view.signal_connect("row_activated") { |_tree, _path, _column|
59
- if @view.selection.selected
60
- from = @list.get_value(@view.selection.selected, OBJCOL)
61
- @parent.treeview.goto(from)
62
- end
63
- }
64
-
65
- scroll = ScrolledWindow.new.set_policy(POLICY_NEVER, POLICY_AUTOMATIC)
66
- scroll.add(@view)
67
- vbox.add(scroll)
68
-
69
- set_default_size(200, 200)
70
-
71
- signal_connect('response') { destroy }
72
- show_all
73
- end
74
- end
75
- end
@@ -1,6 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- $:.unshift(__dir__)
4
- require 'gui/walker'
5
-
6
- PDFWalker::Walker.start(ARGV[0])