rcv 0.0.1

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.
@@ -0,0 +1,4 @@
1
+ == 0.0.1 2008-04-24
2
+
3
+ * 1 major enhancement:
4
+ * Initial release
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008 Kazuki Uchida
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,29 @@
1
+ History.txt
2
+ License.txt
3
+ Manifest.txt
4
+ PostInstall.txt
5
+ README.txt
6
+ Rakefile
7
+ bin/rcv
8
+ config/hoe.rb
9
+ config/requirements.rb
10
+ lib/rcv.rb
11
+ lib/rcv/config.rb
12
+ lib/rcv/reader.rb
13
+ lib/rcv/version.rb
14
+ script/console
15
+ script/destroy
16
+ script/generate
17
+ script/manifest.rb
18
+ script/txt2html
19
+ setup.rb
20
+ tasks/deployment.rake
21
+ tasks/environment.rake
22
+ tasks/website.rake
23
+ test/test_helper.rb
24
+ test/test_rcv.rb
25
+ website/index.html
26
+ website/index.txt
27
+ website/javascripts/rounded_corners_lite.inc.js
28
+ website/stylesheets/screen.css
29
+ website/template.html.erb
@@ -0,0 +1,7 @@
1
+
2
+ For more information on rcv, see http://rcv.rubyforge.org
3
+
4
+ NOTE: Change this information in PostInstall.txt
5
+ You can also delete it if you don't want it.
6
+
7
+
@@ -0,0 +1,45 @@
1
+ == DESCRIPTION:
2
+
3
+ RCV is simple comic viewer
4
+
5
+ == INSTALL:
6
+
7
+ gem install rcv
8
+
9
+ == LICENSE:
10
+
11
+ Ruby's
12
+
13
+ == Usage:
14
+
15
+ rcv zipfile
16
+ rcv
17
+
18
+ == Shortcut key:
19
+
20
+ o : Open file
21
+ right : Next Image
22
+ left : Prev Image
23
+ s : save bookmark
24
+ b : load bookmark
25
+
26
+ Copyright (c) 2008 Kazuki Uchida <gioext at gmail.com>
27
+
28
+ Permission is hereby granted, free of charge, to any person obtaining
29
+ a copy of this software and associated documentation files (the
30
+ 'Software'), to deal in the Software without restriction, including
31
+ without limitation the rights to use, copy, modify, merge, publish,
32
+ distribute, sublicense, and/or sell copies of the Software, and to
33
+ permit persons to whom the Software is furnished to do so, subject to
34
+ the following conditions:
35
+
36
+ The above copyright notice and this permission notice shall be
37
+ included in all copies or substantial portions of the Software.
38
+
39
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
40
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
41
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
42
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
43
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
44
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
45
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,4 @@
1
+ require 'config/requirements'
2
+ require 'config/hoe' # setup Hoe + all gem configuration
3
+
4
+ Dir['tasks/**/*.rake'].each { |rake| load rake }
data/bin/rcv ADDED
@@ -0,0 +1,157 @@
1
+ #!/usr/bin/ruby
2
+
3
+ require "rubygems"
4
+ require "gtk2"
5
+ require "rcv"
6
+ require "optparse"
7
+
8
+ module RCV
9
+ class GtkWindow < Gtk::Window
10
+ def initialize
11
+ super()
12
+ set_title("RCV")
13
+ signal_connect("destroy") do
14
+ Gtk.main_quit
15
+ false
16
+ end
17
+ signal_connect("key_press_event") do |w, e|
18
+ on_key_press_event(w, e)
19
+ true
20
+ end
21
+ maximize
22
+
23
+ @drawing_area = Gtk::DrawingArea.new
24
+ @drawing_area.signal_connect("expose_event") do |w, e|
25
+ on_drawing_area_expose(w, e)
26
+ true
27
+ end
28
+
29
+ add(@drawing_area)
30
+ show_all
31
+ end
32
+
33
+ def read(file)
34
+ @filename = file
35
+ if file
36
+ @reader = RCV::ZipReader.new(file)
37
+ @reader.read
38
+ print @reader.get_next
39
+ end
40
+ end
41
+
42
+ def close
43
+ @reader.close if @reader
44
+ end
45
+
46
+ def on_key_press_event(sender, e)
47
+ case e.keyval
48
+ when Gdk::Keyval::GDK_Right
49
+ on_press_right
50
+ when Gdk::Keyval::GDK_Left
51
+ on_press_left
52
+ when Gdk::Keyval::GDK_o
53
+ on_press_o
54
+ when Gdk::Keyval::GDK_s
55
+ on_press_s
56
+ when Gdk::Keyval::GDK_b
57
+ on_press_b
58
+ end
59
+ end
60
+
61
+ def on_press_right
62
+ print @reader.get_next if @reader
63
+ end
64
+
65
+ def on_press_left
66
+ print @reader.get_prev if @reader
67
+ end
68
+
69
+ def on_press_o
70
+ dialog = Gtk::FileChooserDialog.new("Open File",
71
+ self,
72
+ Gtk::FileChooser::ACTION_OPEN,
73
+ nil,
74
+ [Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL],
75
+ [Gtk::Stock::OPEN, Gtk::Dialog::RESPONSE_ACCEPT])
76
+ dialog.current_folder = ENV["HOME"] || "./"
77
+ if dialog.run == Gtk::Dialog::RESPONSE_ACCEPT
78
+ read dialog.filename
79
+ end
80
+ dialog.destroy
81
+ end
82
+
83
+ def on_press_s
84
+ RCV::Config.bookmark = { @filename => @reader.state } if @filename && @reader
85
+ end
86
+
87
+ def on_press_b
88
+ state = RCV::Config.bookmark @filename if @filename
89
+ if state && @reader
90
+ @reader.load state
91
+ print @reader.get_next
92
+ end
93
+ end
94
+
95
+ # ubuntu bug? PixbufLoader(jpg file)
96
+ def get_pixbuf(temp)
97
+ if temp
98
+ @buf = Gdk::Pixbuf.new(temp)
99
+ # loader = Gdk::PixbufLoader.new
100
+ # loader.last_write(io.read)
101
+ # @buf = loader.pixbuf
102
+ end
103
+ end
104
+
105
+ def print io
106
+ if io
107
+ get_pixbuf io
108
+ @drawing_area.signal_emit("expose_event", nil)
109
+ end
110
+ end
111
+
112
+ def on_drawing_area_expose(sender, e)
113
+ return unless @buf
114
+ context = sender.window.create_cairo_context
115
+ x, y, w, h = sender.allocation.to_a
116
+ resize1 = h / @buf.height.to_f
117
+ resize2 = w / @buf.width.to_f
118
+ resize = resize1 > resize2 ? resize2 : resize1
119
+ buf2 = @buf.scale(@buf.width * resize,
120
+ @buf.height * resize,
121
+ Gdk::Pixbuf::INTERP_BILINEAR)
122
+ bg = Gdk::Pixbuf.new(Gdk::Pixbuf::COLORSPACE_RGB, false, 8, w, h)
123
+ bg.fill!(0x00000000)
124
+
125
+ wspace = w - buf2.width
126
+ hspace = h - buf2.height
127
+ if wspace > hspace
128
+ dw = (w - buf2.width.to_i) / 2
129
+ dh = 0
130
+ else
131
+ dw = 0
132
+ dh = (h - buf2.height.to_i) / 2
133
+ end
134
+
135
+ buf2.copy_area(0, 0, buf2.width, buf2.height, bg, dw, dh)
136
+ context.set_source_pixbuf(bg)
137
+ context.paint
138
+ GC.start
139
+ end
140
+ end
141
+ end
142
+
143
+ ARGV.options do |opt|
144
+ opt.on('-v') do
145
+ puts "RCV version #{RCV.version}"
146
+ exit
147
+ end
148
+ opt.parse!
149
+ end
150
+
151
+ begin
152
+ ui = RCV::GtkWindow.new
153
+ ui.read ARGV[0]
154
+ Gtk.main
155
+ rescue
156
+ ui.close
157
+ end
@@ -0,0 +1,73 @@
1
+ require 'rcv'
2
+
3
+ AUTHOR = 'Kazuki Uchida' # can also be an array of Authors
4
+ EMAIL = "gioext at gmail.com"
5
+ DESCRIPTION = "RCV is a simple comic viewer for Linux"
6
+ GEM_NAME = 'rcv' # what ppl will type to install your gem
7
+ RUBYFORGE_PROJECT = 'rcv' # The unix name for your project
8
+ HOMEPATH = "http://#{RUBYFORGE_PROJECT}.rubyforge.org"
9
+ DOWNLOAD_PATH = "http://rubyforge.org/projects/#{RUBYFORGE_PROJECT}"
10
+ EXTRA_DEPENDENCIES = [
11
+ ['rubyzip', '>= 0.9.1']
12
+ ] # An array of rubygem dependencies [name, version]
13
+
14
+ @config_file = "~/.rubyforge/user-config.yml"
15
+ @config = nil
16
+ RUBYFORGE_USERNAME = "gioext"
17
+ def rubyforge_username
18
+ unless @config
19
+ begin
20
+ @config = YAML.load(File.read(File.expand_path(@config_file)))
21
+ rescue
22
+ puts <<-EOS
23
+ ERROR: No rubyforge config file found: #{@config_file}
24
+ Run 'rubyforge setup' to prepare your env for access to Rubyforge
25
+ - See http://newgem.rubyforge.org/rubyforge.html for more details
26
+ EOS
27
+ exit
28
+ end
29
+ end
30
+ RUBYFORGE_USERNAME.replace @config["username"]
31
+ end
32
+
33
+
34
+ REV = nil
35
+ # UNCOMMENT IF REQUIRED:
36
+ # REV = YAML.load(`svn info`)['Revision']
37
+ VERS = RCV.version + (REV ? ".#{REV}" : "")
38
+ RDOC_OPTS = ['--quiet', '--title', 'rcv documentation',
39
+ "--opname", "index.html",
40
+ "--line-numbers",
41
+ "--main", "README",
42
+ "--inline-source"]
43
+
44
+ class Hoe
45
+ def extra_deps
46
+ @extra_deps.reject! { |x| Array(x).first == 'hoe' }
47
+ @extra_deps
48
+ end
49
+ end
50
+
51
+ # Generate all the Rake tasks
52
+ # Run 'rake -T' to see list of generated tasks (from gem root directory)
53
+ $hoe = Hoe.new(GEM_NAME, VERS) do |p|
54
+ p.developer(AUTHOR, EMAIL)
55
+ p.description = DESCRIPTION
56
+ p.summary = DESCRIPTION
57
+ p.url = HOMEPATH
58
+ p.rubyforge_name = RUBYFORGE_PROJECT if RUBYFORGE_PROJECT
59
+ p.test_globs = ["test/**/test_*.rb"]
60
+ p.clean_globs |= ['**/.*.sw?', '*.gem', '.config', '**/.DS_Store'] #An array of file patterns to delete on clean.
61
+
62
+ # == Optional
63
+ p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
64
+ #p.extra_deps = EXTRA_DEPENDENCIES
65
+
66
+ #p.spec_extras = {} # A hash of extra values to set in the gemspec.
67
+ end
68
+
69
+ CHANGES = $hoe.paragraphs_of('History.txt', 0..1).join("\\n\\n")
70
+ PATH = (RUBYFORGE_PROJECT == GEM_NAME) ? RUBYFORGE_PROJECT : "#{RUBYFORGE_PROJECT}/#{GEM_NAME}"
71
+ $hoe.remote_rdoc_dir = File.join(PATH.gsub(/^#{RUBYFORGE_PROJECT}\/?/,''), 'rdoc')
72
+ $hoe.rsync_args = '-av --delete --ignore-errors'
73
+ $hoe.spec.post_install_message = File.open(File.dirname(__FILE__) + "/../PostInstall.txt").read rescue ""
@@ -0,0 +1,15 @@
1
+ require 'fileutils'
2
+ include FileUtils
3
+
4
+ require 'rubygems'
5
+ %w[rake hoe newgem rubigen].each do |req_gem|
6
+ begin
7
+ require req_gem
8
+ rescue LoadError
9
+ puts "This Rakefile requires the '#{req_gem}' RubyGem."
10
+ puts "Installation: gem install #{req_gem} -y"
11
+ exit
12
+ end
13
+ end
14
+
15
+ $:.unshift(File.join(File.dirname(__FILE__), %w[.. lib]))
@@ -0,0 +1,17 @@
1
+ # Copyright (C) 2008 Kazuki Uchida <gioext at gmail.com>
2
+ #
3
+ # RCV is simple image viewer for zip archiver.
4
+ # License Ruby's.
5
+
6
+ $:.unshift(File.dirname(__FILE__)) unless
7
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
8
+
9
+ module RCV
10
+ VERSION = [0, 0, 1]
11
+
12
+ def self.version
13
+ VERSION.join(".")
14
+ end
15
+ require "rcv/reader"
16
+ require "rcv/config"
17
+ end
@@ -0,0 +1,35 @@
1
+ require 'yaml'
2
+ require 'fileutils'
3
+
4
+ module RCV
5
+ class Config
6
+ HOME = ENV["HOME"] || ENV["AppData"] || "./"
7
+ CONF_DIR = File.join(HOME, ".rcv")
8
+ BOOKMARK_PATH = File.join(CONF_DIR, "bookmark.yaml")
9
+
10
+ class << self
11
+ def bookmark=(hash)
12
+ FileUtils.mkpath(CONF_DIR) unless File.exist?(CONF_DIR)
13
+ bm = bookmark_all
14
+ hash.update(bm) { |k, v| v } if bm
15
+ open(BOOKMARK_PATH, "w") do |f|
16
+ f.write hash.to_yaml
17
+ end
18
+ end
19
+
20
+ def bookmark(key = nil)
21
+ bm = bookmark_all
22
+ bm[key] if bm && bm.key?(key)
23
+ end
24
+
25
+ def clear_bookmark
26
+ File.open(BOOKMARK_PATH, "w").close
27
+ end
28
+
29
+ private
30
+ def bookmark_all
31
+ YAML.load(File.read(BOOKMARK_PATH)) if File.exist?(BOOKMARK_PATH)
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,251 @@
1
+ =begin
2
+ zip archive reader
3
+ =end
4
+
5
+ require "rubygems"
6
+ require "zip/zip"
7
+ require "tempfile"
8
+ require "fileutils"
9
+ require "kconv"
10
+ require "thread"
11
+ require "logger"
12
+ require "singleton"
13
+
14
+ module RCV
15
+ class ZipReader
16
+ def initialize(file)
17
+ @logger = RCVLog.instance
18
+ @zis = Zip::ZipInputStream.new(file)
19
+ @entries = []
20
+ @index = 0
21
+ end
22
+
23
+ def read
24
+ while entry = @zis.get_next_entry
25
+ case entry.name
26
+ when /\.zip$/i
27
+ @entries << ZipEntry.new(entry)
28
+ when /\.(jpg|jpeg|png)$/i
29
+ @entries << ImageEntry.new(entry)
30
+ end
31
+ end
32
+ @entries = @entries.sort_by { |e| e.name }
33
+ end
34
+
35
+ def close
36
+ @entries.each { |e| e.close }
37
+ @zis.close
38
+ end
39
+
40
+ def get_next
41
+ entry = current
42
+ unless entry
43
+ @index -= 1
44
+ entry = current
45
+ end
46
+ if entry.last?
47
+ entry.close
48
+ @index += 1
49
+ entry = current
50
+ end
51
+ return unless entry
52
+ entry.get_next
53
+ end
54
+
55
+ def get_prev
56
+ entry = current
57
+ unless entry
58
+ @index -= 1
59
+ entry = current
60
+ end
61
+ if @index == 0
62
+ return if entry.top?
63
+ end
64
+ if entry.top?
65
+ entry.close
66
+ @index -= 1
67
+ entry = current
68
+ end
69
+ return unless entry
70
+ entry.get_prev
71
+ end
72
+
73
+ def state
74
+ state = [@index, current.state].flatten
75
+ @logger.debug "Get state : #{state.join(",")}"
76
+ state
77
+ end
78
+
79
+ def load(state)
80
+ @logger.debug "Set state : #{state.join(",")}"
81
+ @index = state.shift
82
+ current.load state
83
+ end
84
+
85
+ def current
86
+ @entries[@index]
87
+ end
88
+ end
89
+
90
+ class Entry
91
+ attr_reader :name
92
+ def initialize(entry)
93
+ @logger = RCVLog.instance
94
+ @entry = entry
95
+ @name = entry.name.toutf8
96
+ @index = -1
97
+ end
98
+
99
+ def top?
100
+ @index <= 0
101
+ end
102
+
103
+ def close; end
104
+ end
105
+
106
+ # ignore nested too deep
107
+ class ZipEntry < Entry
108
+ def initialize(entry)
109
+ super
110
+ @entries = []
111
+ end
112
+
113
+ # No goodness?
114
+ # tempfile or memory ? best ?
115
+ def get_next
116
+ unless @zis
117
+ create_temp
118
+ end
119
+ if @temp.closed?
120
+ @temp.open
121
+ end
122
+ @entries[@index].close if @entries[@index]
123
+ @index += 1
124
+ @entries[@index].get_next
125
+ end
126
+
127
+ def get_prev
128
+ unless @zis
129
+ create_temp
130
+ end
131
+ if @temp.closed?
132
+ @index = @entries.size
133
+ @temp.open
134
+ end
135
+ @entries[@index].close if @entries[@index]
136
+ @index -= 1
137
+ @entries[@index].get_prev
138
+ end
139
+
140
+ def create_temp
141
+ @index = -1
142
+ @temp = Tempfile.new("rcv")
143
+ @temp.binmode
144
+ @temp.write @entry.get_input_stream.read
145
+ @temp.flush
146
+ @logger.debug "Create temp : #{@name} to #{@temp.path}"
147
+ @zis = Zip::ZipInputStream.new(@temp.path)
148
+ while entry = @zis.get_next_entry
149
+ @entries << ImageEntry.new(entry) if entry.name =~ /\.(jpg|jpeg|png)$/i
150
+ end
151
+ @entries = @entries.sort_by { |e| e.name }
152
+ end
153
+
154
+ def close
155
+ @temp.close
156
+ @entries[@index].close
157
+ # @zis.close
158
+ # @zis = nil
159
+ # @temp.close(true)
160
+ end
161
+
162
+ def last?
163
+ create_temp unless @zis
164
+ @index + 1 >= @entries.size
165
+ end
166
+
167
+ def state
168
+ [@index - 1, @entries[@index].state]
169
+ end
170
+
171
+ def current
172
+ @entries[@index]
173
+ end
174
+
175
+ def load(state)
176
+ @index = state.shift
177
+ current.load state
178
+ end
179
+ end
180
+
181
+ class ImageEntry < Entry
182
+ def initialize(entry)
183
+ super
184
+ end
185
+
186
+ def get_next
187
+ current
188
+ end
189
+
190
+ def get_prev
191
+ current
192
+ end
193
+
194
+ def current
195
+ @index = 0
196
+ @logger.debug "Read file : #{@name}"
197
+
198
+ unless @temp
199
+ @temp = Tempfile.new("rcv")
200
+ @temp.binmode
201
+ @temp.write(@entry.get_input_stream.read)
202
+ @temp.flush
203
+ @logger.debug "Create temp : #{@temp.path}"
204
+ end
205
+ if @temp.closed?
206
+ @temp.open
207
+ end
208
+
209
+ @temp.path
210
+ end
211
+
212
+ def last?
213
+ @index == 0
214
+ end
215
+
216
+ def close
217
+ @logger.debug "close #{name}"
218
+ @temp.close(true) if @temp
219
+ @temp = nil
220
+ end
221
+
222
+ def state
223
+ @index - 1
224
+ end
225
+
226
+ def load(state)
227
+ @index = state.shift
228
+ end
229
+ end
230
+
231
+ class RCVLog
232
+ include Singleton
233
+ def initialize
234
+ @logger = Logger.new(STDOUT)
235
+ @logger.level = Logger::ERROR
236
+ @m = Mutex.new
237
+ end
238
+
239
+ def debug str
240
+ @m.synchronize do
241
+ @logger.debug str
242
+ end
243
+ end
244
+
245
+ def error str
246
+ @m.synchronize do
247
+ @logger.error str
248
+ end
249
+ end
250
+ end
251
+ end