require 'dbus' module ProgressBar @klasses ||= [] class < unless 0 == l or 100 == l STDOUT.printf "\r\e[J%s / %s [%-*s] %s", format_time(dd), format_time(td), 100, b, text end alias change_progress change_text def change_error STDERR.printf "\r\e[J%s\n", error change_text end def finish STDERR.puts end end class ProgressBar::KDE < ProgressBar::Base def self.possible? 'KDE' == ENV['XDG_CURRENT_DESKTOP'] end attr_reader :bus, :service, :view def initialize max, text = nil, title = nil, app_name: nil, app_icon_name: nil, unit: nil, is_cancable: nil, is_suspendable: nil, unit: nil, **_options super max, text text = @text text = nil if text.nil? or text.empty? title = nil if title.nil? or title.empty? @unit = '' if unit.nil? or unit.empty? @errors = [] @bus = DBus::SessionBus.instance @service = @bus['org.kde.JobViewServer'] jvs = @service['/JobViewServer']['org.kde.JobViewServer'] flags = (is_cancable ? 0x1 : 0) | (is_suspendable ? 0x2 : 0) view_path = jvs.requestView app_name || $0, app_icon_name || '', flags @view = @service[view_path]['org.kde.JobViewV2'] @view.setTotalAmount max, unit end def change_text @view.setInfoMessage text end def change_progress @view.setProcessedAmount i, unit @view.setPercentage done_rel end def change_error @view.setError error end def finish @view.terminate end end class ProgressBar::KDialog < ProgressBar::Base def self.possible? path = Pathname.new `which kdialog`.chomp $?.exitstatus and path.executable? end attr_reader :dialog_service_path, :dialog_object_path, :errors, :dialog_object def initialize max, text = nil, title = nil, **_options super max, text text = @text text = nil if text.nil? or text.empty? title = nil if title.nil? or title.empty? @errors = [] args = ['kdialog', title ? ['--title', title] : [], '--progressbar', text || '.', max].flatten.compact.map &:to_s @dialog_service_path, @dialog_object_path = IO.popen( args, 'r', &:readlines).join("\n").split ' ' @dialog_bus = DBus.session_bus @dialog_service = @dialog_bus[@dialog_service_path] @dialog_object = @dialog_service.object @dialog_object_path @dialog_object.introspect @dialog_object.showCancelButton true change_text if text.nil? change_progress rescue DBus::Error raise Interrupt if $!.name == 'org.freedesktop.DBus.Error.ServiceUnknown' raise end def self.kdialog *a windowid = ENV['WINDOWID'] windowid = (windowid.is_a?(String) && !windowid.empty?) ? ['--attach', windowid] : [] system 'kdialog', *windowid, *a end def kdialog(*a) self.class.kdialog *a end def change_progress() @dialog_object.Set '', 'value', i raise Interrupt if @dialog_object.wasCancelled.first rescue DBus::Error raise Interrupt if $!.name == 'org.freedesktop.DBus.Error.ServiceUnknown' raise end def change_text() @dialog_object.setLabelText text raise Interrupt if @dialog_object.wasCancelled.first rescue DBus::Error raise Interrupt if $!.name == 'org.freedesktop.DBus.Error.ServiceUnknown' raise end def change_error() @errors.push error end def finish() @dialog_object.close rescue DBus::Error kdialog '--detailederror', "Some errors occured:", errors.join( "
\n") unless errors.empty? end def max= val @dialog_object.Set '', 'maximum', val end def max @dialog_object.Get '', 'maximum' end end ProgressBar.register ProgressBar::Console ProgressBar.register ProgressBar::KDE ProgressBar.register ProgressBar::KDialog