module Qt
Author: Cees Zeelenberg (c.zeelenberg@computer.org) Copyright: © 2010-2012 by Cees Zeelenberg License: This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. *
This software extends the basic qt_jbindings API with functionality to improve compatibility with the existing QtRuby API:
-
same shorthand notations for Enums
-
patches to classes where the API is slightly different to support both interfaces (ongoing work)
-
support for the QtRuby signals/slot interface in addition to the
QtJambi
signals interface -
implementations of Qt::Variant and
Qt::ModelIndex
to allow single source maintenance for QtRuby and QtJRuby
Constants
- DesktopType
- DialogType
WindowType=WindowType::Window
- DoubleSpinBox
- Drag
- DrawerType
- File
- FileDialog
- PopupType
- SheetType
- SplashScreenType
- SubWindowType
- ToolTipType
- ToolType
- WidgetType
compat QtRuby4 (fails for WindowType)
Public Class Methods
come here on missing constant in the Qt
namespace if the missing name maps to an existing QtJambi
class, equate the missing constant to that class and
- make Signal fields accessable to Ruby methods - define a 'new' classmethod with optional iterator block initialization - define 'shorthand' constants to be compatible with qtbindings (optional, require 'qt_compat.rb' ) - monkeypatch the underlying class with extensions defined in Qt::Internal (optional, require 'qt_compat.rb' )
# File lib/qt_connect/qt_jbindings.rb, line 240 def const_missing(name) qtclass = QtJambi.const_get("Q#{name}") rescue qtclass = QtJambi.const_get("Qt#{name}") rescue qtclass = QtJambi.const_get("#{name}") qtclass.class_eval do if self.class==Class # no constructor for modules class << self def new(*args,&block) instance=self.allocate instance.send(:initialize,*args) if block_given? if block.arity == -1 || block.arity == 0 instance.instance_eval(&block) elsif block.arity == 1 block.call(instance) else raise ArgumentError, "Wrong number of arguments to block(#{block.arity} ; should be 1 or 0)" end end return instance end end end #Ruby extensions for a class are stored in Qt::Internal as Procs with the same name as the class #the signature for each extension is logged in Qt::Internal::RUBY_extensions (for documentation only) #see examples in qt_compat.rb if Qt::Internal.const_defined?(name) puts "include extension #{name}" if $VERB self.class_eval(&Qt::Internal.const_get(name)) end end const_set(name, qtclass) Qt.create_constants(qtclass,"Qt::#{name}") if Qt.respond_to? :create_constants Qt.setup_qt_signals(qtclass) return qtclass end
'create_constants' is called whenever new Module or Class is activated
qtclass Java::ComTrollTechQtGui::QDockWidget (Class) qtname Qt::Dockwidget (String)
# File lib/qt_connect/qt_compat.rb, line 50 def self.create_constants(qtclass,qtname) qtclass.class_eval{ constants.dup.each{ |c| embedded_class=eval("#{qtclass.name}::#{c}") next unless embedded_class.respond_to?(:java_class) ancestors=(embedded_class.respond_to?(:ancestors)) ? embedded_class.ancestors : [] if ancestors.include? java.lang.Enum embedded_class.values.to_ary.each{ |s| symbol=s.toString next if Qt::Internal::DONT_ABBREVIATE["#{qtname}::#{c}::#{symbol}"] next if symbol=~/\A[^A-Z].*\Z/ next if const_defined?(symbol) qtclass.class_eval("#{symbol}=#{qtclass.name}::#{c}::#{symbol}") rescue next } else #could be class with public static final int field(s) fields=embedded_class.java_class.fields rescue next fields.each{ |field| next unless field.static? && field.final? && field.public? && (field.value_type=="int") symbol=field.name value=Java.java_to_ruby(field.static_value) qtclass.class_eval("#{symbol}=#{value}") rescue next } end } } end
deal with Qt::blue etc.
# File lib/qt_connect/qt_compat.rb, line 94 def Qt.method_missing(method,*args) return Color.send(method) if Color.respond_to?(method) return Color.new(*args).rgba if method==:qRgba super(*args) end
# File lib/qt_connect/qt_jbindings.rb, line 244 def new(*args,&block) instance=self.allocate instance.send(:initialize,*args) if block_given? if block.arity == -1 || block.arity == 0 instance.instance_eval(&block) elsif block.arity == 1 block.call(instance) else raise ArgumentError, "Wrong number of arguments to block(#{block.arity} ; should be 1 or 0)" end end return instance end
# File lib/qt_connect/qt_jbindings.rb, line 286 def Qt.setup_qt_signals(qtclass) return if @@activated[qtclass.java_class.name] org.jruby.javasupport.JavaClass.getMethods(qtclass).to_a. map{ |jm| returnclass=jm.getReturnType}. select{ |jc| jc.getClasses.to_a.include? QtJambi::ABSTRACTSIGNAL}. map{ |jc| jc.getName}. uniq. delete_if{ |jn| @@activated[jn]}. each { |klassname| klass=eval(klassname) klass.class_eval do next if @@activated[java_class.name] java_class.fields.each do |field| next unless field.type.superclass==QtJambi::ABSTRACTSIGNAL puts " #{java_class.name} fieldname: #{field.name} fieldtype: #{field.type.to_s}" if $VERB uscore_name = if (field.name =~ /\A[A-Z]+\z/) field.name.downcase else field.name.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2').gsub(/([a-z\d])([A-Z])/, '\1_\2').tr("-","_").downcase end self.class_eval %Q[ def #{field.name}(*args, &block) #puts '===> #{klass.name}.#{field.name} <=> #{field.type.to_s} -1-' return self.java_class.field(:#{field.name}).value(self) end #{(uscore_name==field.name) ? '' : "alias :#{uscore_name} :#{field.name}"} ] end @@activated[java_class.name]=true end } #@@activated[qtclass.java_class.name]=true end
# File lib/qt_connect/qt_sugar.rb, line 107 def singleShot(timeout,receiver,method) if method.kind_of? Symbol receiver.class.class_eval{ slots(method.to_s+'()')} m=SLOT(method) else m=method end orig_singleShot(timeout,receiver,m) end