Well, figuring that this had something to do with loading from an xrc, I
redid my code to just create the dialog by hand… I get a dialog now,
without error, but something seems messed up with event handling… I
cannot move or close the dialog, the Cancel button does not paint… the
gauges work though :-p
Again, this all works fine for me on my Mac - I only see this weirdness
on Windows (XP) … I’m sure it is some detail I am overlooking or,
being so new to this, something I am misinterpreting…
Attached is my code in hopes that someone will spot something… (this
is just a small app to parse an m3u playlist and download the mp3s found
there)
---- here be code ------
#!/usr/bin/env ruby
stdlib
require ‘fileutils’
require ‘open-uri’
require ‘tmpdir’
gems
require ‘rubygems’
require ‘wx’
StreamDownloaderProgress class
progress dialog for the downloads…
class StreamDownloaderProgress < Wx::Frame
attr_accessor :status_label, :progress_item, :progress_all,
:cancel_button
attr_accessor :cancelled
def initialize
super(nil, -1, StreamDownloader::TITLE, Wx::DEFAULT_POSITION,
Wx::Size.new(350, 120),
Wx::MINIMIZE_BOX | Wx::SYSTEM_MENU | Wx::CAPTION |
Wx::CLOSE_BOX)
sizer = Wx::BoxSizer.new(Wx::VERTICAL)
# label
@status_label = Wx::StaticText.new(self, -1, "Preparing downloads...
please wait.",
Wx::DEFAULT_POSITION,
Wx::DEFAULT_SIZE)
sizer.add(@status_label, 1, Wx::GROW | Wx::ALL | Wx::ALIGN_LEFT |
Wx::FIXED_MINSIZE, 2)
# item progress
@progress_item = Wx::Gauge.new(self, -1, 100,
Wx::DEFAULT_POSITION,
Wx::DEFAULT_SIZE,
Wx::GA_HORIZONTAL)
@progress_item.set_tool_tip("current item progress")
@progress_item.value = 0
sizer.add(@progress_item, 1, Wx::GROW | Wx::HORIZONTAL, 2)
# all progress
@progress_all = Wx::Gauge.new(self, -1, 100,
Wx::DEFAULT_POSITION,
Wx::DEFAULT_SIZE,
Wx::GA_HORIZONTAL)
@progress_all.set_tool_tip("overall progress")
@progress_all.value = 0
sizer.add(@progress_all, 1, Wx::GROW | Wx::HORIZONTAL, 2)
# cancel button
@cancel_button = Wx::Button.new(self, -1, 'Cancel',
Wx::DEFAULT_POSITION, Wx::DEFAULT_SIZE)
@cancel_button.set_tool_tip(“cancel downloads”)
sizer.add(@cancel_button, 1, Wx::ALIGN_CENTER_HORIZONTAL, 2)
self.set_sizer(sizer)
# on close simply set var to show intention
evt_close { |e| @cancelled = true }
evt_button(@cancel_button) { |e| @cancelled = true }
# set up location/controls
self.center(Wx::BOTH)
self.layout
end
end
StreamDownloader class
main class where all the work is donw
class StreamDownloader
attr_accessor :destdir
attr_reader :urls
attr :m3ufile
attr :dialog
NAME = ‘Stream Downloader’
VERSION = ‘1.0.0’
TITLE = “#{NAME} #{VERSION}”
def initialize
# init our progress dialog
@dialog = StreamDownloaderProgress.new
Wx::get_app.yield
# set up our destdir based on platform
if RUBY_PLATFORM =~ /mswin32/
@destdir = File.join(“C:/Documents and Settings”, ENV[‘USERNAME’],
‘Desktop’)
elsif RUBY_PLATFORM =~ /darwin/
@destdir = File.join(ENV[‘HOME’], ‘Desktop’)
else
@destdir = File.expand_path(File.dirname(FILE))
end
end
def ask
fd = Wx::FileDialog.new(@dialog, ‘Select the playlist to
process…’,
@destdir, “”, “Playlist files
(.m3u)|.m3u”,
Wx::FD_OPEN | Wx::FD_FILE_MUST_EXIST,
Wx::DEFAULT_POSITION )
if fd.show_modal == Wx::ID_OK
return(fd.get_path)
else
exit
end
end
def file=(m3u)
# ok … assign and parse
@m3ufile = m3u
@urls = parse if @m3ufile
end
def file
return @m3ufile
end
def parse(file = @m3ufile)
found = []
if File.exist?(file)
File.open(file) { |f|
while line = f.gets
found.push(line.chomp) if line =~ /.mp3$/i
end
}
end
return found
end
def grab
progress = 0
if @urls.size > 0
@dialog.show
Wx::get_app.yield
@urls.each_index { |idx|
url = @urls[idx]
fname = File.basename(url)
@dialog.status_label.label = “Downloading #{idx + 1} of
#{@urls.size}: #{fname}”
@dialog.progress_all.value = (100 * (idx/@urls.size.to_f)).to_i
begin
size = 0
@dialog.progress_item.value = 0 # reset
File.open(File.join(Dir::tmpdir, fname), ‘wb’) { |ofile|
open(url,
:content_length_proc => lambda {|total| size = total },
:progress_proc => lambda { |current|
@dialog.progress_item.value = (100 *
(current/size.to_f)).to_i if size > 0
Wx::get_app.yield # update gui…
raise “operation cancelled by user” if
@dialog.cancelled
}
) { |urlreader|
urlreader.binmode
ofile.write(urlreader.read)
}
}
rename(File.join(Dir::tmpdir, fname))
rescue => err
@dialog.hide
unless @dialog.cancelled
md = Wx::MessageDialog.new(@dialog, “An error occurred while
downloading!\n#{url}”,
TITLE, Wx::OK | Wx::ICON_ERROR,
Wx::DEFAULT_POSITION)
md.show_modal
end
File.unlink(File.join(Dir::tmpdir, fname))
@dialog.destroy
exit(1)
end
}
@dialog.progress_all.value = 100
sleep(1)
@dialog.hide
md = Wx::MessageDialog.new(@dialog, ‘Download(s) complete!’,
TITLE, Wx::OK, Wx::DEFAULT_POSITION)
md.show_modal
else
unless @m3ufile.empty?
md = Wx::MessageDialog.new(@dialog, ‘No supported media files
found to download!’,
TITLE, Wx::OK | Wx::ICON_EXCLAMATION,
Wx::DEFAULT_POSITION)
md.show_modal
end
end
@dialog.destroy # and exit…
end
def rename(file)
newname = “#{@destdir}/#{File.basename(@m3ufile,
File.extname(@m3ufile))}/#{File.basename(file)}”
FileUtils.mkdir_p(File.dirname(newname))
FileUtils.mv(file, newname)
end
end # StreamDownloader class
StreamDownloaderApp class
entry point for the app
class StreamDownloaderApp < Wx::App
def on_init
@sd = StreamDownloader.new
begin
playlist = (ARGV.first || @sd.ask)
rescue => err
$stdout.puts(err)
end
if playlist
@sd.file = playlist
@sd.grab
end
end
end
StreamDownloaderApp.new.main_loop