module Qt::Internal
Constants
- AccessPrivate
From the enum MethodFlags in qt-copy/src/tools/moc/generator.cpp
- AccessProtected
- AccessPublic
- MethodCloned
- MethodCompatibility
- MethodMethod
- MethodScriptable
- MethodSignal
- MethodSlot
Public Class Methods
# File lib/Qt/qtruby4.rb, line 2541 def self.add_normalize_proc(func) @@normalize_procs << func end
# File lib/Qt/qtruby4.rb, line 2580 def Internal.checkarg(argtype, typename) const_point = typename =~ /^const\s+/ ? -1 : 0 if argtype == 'i'.freeze if typename =~ /^int&?$|^signed int&?$|^signed$|^qint32&?$/ return 6 + const_point elsif typename =~ /^quint32&?$/ return 4 + const_point elsif typename =~ /^(?:short|ushort|unsigned short int|unsigned short|uchar|char|unsigned char|uint|long|ulong|unsigned long int|unsigned|float|double|WId|HBITMAP__\*|HDC__\*|HFONT__\*|HICON__\*|HINSTANCE__\*|HPALETTE__\*|HRGN__\*|HWND__\*|Q_PID|^quint16&?$|^qint16&?$)$/ return 4 + const_point elsif typename =~ /^(quint|qint|qulong|qlong|qreal)/ return 4 + const_point else t = typename.sub(/^const\s+/, '') t.sub!(/[&*]$/, '') if isEnum(t) return 2 end end elsif argtype == 'n'.freeze if typename =~ /^double$|^qreal$/ return 6 + const_point elsif typename =~ /^float$/ return 4 + const_point elsif typename =~ /^int&?$/ return 2 + const_point elsif typename =~ /^(?:short|ushort|uint|long|ulong|signed|unsigned|float|double)$/ return 2 + const_point else t = typename.sub(/^const\s+/, '') t.sub!(/[&*]$/, '') if isEnum(t) return 2 + const_point end end elsif argtype == 'B'.freeze if typename =~ /^(?:bool)[*&]?$/ return 2 + const_point end elsif argtype == 's'.freeze if typename =~ /^(const )?((QChar)[*&]?)$/ return 6 + const_point elsif typename =~ /^(?:(u(nsigned )?)?char\*)$/ return 4 + const_point elsif typename =~ /^(?:const (u(nsigned )?)?char\*)$/ return 2 + const_point elsif typename =~ /^(?:(?:const )?(QString)[*&]?)$/ return 8 + const_point end elsif argtype == 'a'.freeze # FIXME: shouldn't be hardcoded. Installed handlers should tell what ruby type they expect. if typename =~ /^(?: const\ QCOORD\*| (?:const\ )? (?: QStringList[\*&]?| QValueList<int>[\*&]?| QRgb\*| char\*\* ) )$/x return 2 + const_point end elsif argtype == 'u'.freeze # Give nil matched against string types a higher score than anything else if typename =~ /^(?:u?char\*|const u?char\*|(?:const )?((Q(C?)String))[*&]?)$/ return 4 + const_point # Numerics will give a runtime conversion error, so they fail the match elsif typename =~ /^(?:short|ushort|uint|long|ulong|signed|unsigned|int)$/ return -99 else return 2 + const_point end elsif argtype == 'U'.freeze if typename =~ /QStringList/ return 4 + const_point else return 2 + const_point end else t = typename.sub(/^const\s+/, '') t.sub!(/(::)?Ptr$/, '') t.sub!(/[&*]$/, '') if argtype == t return 4 + const_point elsif classIsa(argtype, t) return 2 + const_point elsif isEnum(argtype) and (t =~ /int|qint32|uint|quint32|long|ulong/ or isEnum(t)) return 2 + const_point end end return -99 end
# File lib/Qt/qtruby4.rb, line 2529 def self.classes return @@classes end
Handles calls of the form:
connect(myobj, SIGNAL('mysig(int)'), mytarget) {|arg(s)| ...}
connect(myobj, SIGNAL('mysig(int)')) {|arg(s)| ...}
connect(myobj, SIGNAL(:mysig), mytarget) { ...}
connect(myobj, SIGNAL(:mysig)) { ...}
# File lib/Qt/qtruby4.rb, line 3013 def Internal.connect(src, signal, target, block) args = (signal =~ /\((.*)\)/) ? $1 : "" signature = Qt::MetaObject.normalizedSignature("invoke(%s)" % args).to_s return Qt::Object.connect( src, signal, Qt::BlockInvocation.new(target, block.to_proc, signature), SLOT(signature) ) end
# File lib/Qt/qtruby4.rb, line 2533 def self.cpp_names return @@cpp_names end
# File lib/Qt/qtruby4.rb, line 2883 def Internal.create_qenum(num, enum_type) return Qt::Enum.new(num, enum_type) end
# File lib/Qt/qtruby4.rb, line 2576 def Internal.debug_level Qt.debug_level end
Looks up and executes a Qt method
package - Always the string 'Qt' method - Methodname as a string klass - Ruby class object this - instance of class args - arguments to method call
# File lib/Qt/qtruby4.rb, line 2710 def Internal.do_method_missing(package, method, klass, this, *args) # Determine class name if klass.class == Module # If a module use the module's name - typically Qt classname = klass.name else # Lookup Qt class name from Ruby class name classname = @@cpp_names[klass.name] if classname.nil? # Make sure we haven't backed all the way up to Object if klass != Object and klass != Qt # Don't recognize this class so try the superclass return do_method_missing(package, method, klass.superclass, this, *args) else # Give up if we back all the way up to Object return nil end end end lookup_str = "#{classname}::#{method}::#{args.collect {|arg| arg.class.to_s} }" lookup = @@method_lookup_cache[lookup_str] # @@method_lookup_cache is initialized to return false values on a cache miss if lookup != false setCurrentMethod(lookup) if lookup return nil end # Modify constructor method name from new to the name of the Qt class # and remove any namespacing if method == "new".freeze method = classname.dup method.gsub!(/^.*::/,"") end # If the method contains no letters it must be an operator, append "operator" to the # method name method = "operator" + method.sub("@","") if method !~ /[a-zA-Z]+/ # Change foobar= to setFoobar() method = 'set' + method[0,1].upcase + method[1,method.length].sub("=", "") if method =~ /.*[^-+%\/|=]=$/ && method != 'operator='.freeze # Build list of munged method names which is the methodname followed # by symbols that indicate the basic type of the method's arguments # # Plain scalar = $ # Object = # # Non-scalar (reference to array or hash, undef) = ? # methods = [] methods << method.dup args.each do |arg| if arg.nil? # For each nil arg encountered, triple the number of munged method # templates, in order to cover all possible types that can match nil temp = [] methods.collect! do |meth| temp << meth + '?' temp << meth + '#' meth << '$' end methods.concat(temp) elsif isObject(arg) methods.collect! { |meth| meth << '#' } elsif arg.kind_of? Array or arg.kind_of? Hash methods.collect! { |meth| meth << '?' } else methods.collect! { |meth| meth << '$' } end end # Create list of methodIds that match classname and munged method name methodIds = [] methods.collect { |meth| methodIds.concat( findMethod(classname, meth) ) } # If we didn't find any methods and the method name contains an underscore # then convert to camelcase and try again if method =~ /._./ && methodIds.length == 0 # If the method name contains underscores, convert to camel case # form and try again method.gsub!(/(.)_(.)/) {$1 + $2.upcase} return do_method_missing(package, method, klass, this, *args) end # Debugging output for method lookup if debug_level >= DebugLevel::High puts "Searching for #{classname}##{method}" puts "Munged method names:" methods.each {|meth| puts " #{meth}"} puts "candidate list:" prototypes = dumpCandidates(methodIds).split("\n") line_len = (prototypes.collect { |p| p.length }).max prototypes.zip(methodIds) { |prototype,id| puts "#{prototype.ljust line_len} (smoke: #{id.smoke} index: #{id.index})" } end # Find the best match chosen = nil if methodIds.length > 0 best_match = -1 methodIds.each do |id| puts "matching => smoke: #{id.smoke} index: #{id.index}" if debug_level >= DebugLevel::High current_match = (isConstMethod(id) ? 1 : 0) (0...args.length).each do |i| typename = get_arg_type_name(id, i) argtype = get_value_type(args[i]) score = checkarg(argtype, typename) current_match += score puts " #{typename} (#{argtype}) score: #{score}" if debug_level >= DebugLevel::High end # Note that if current_match > best_match, then chosen must be nil if current_match > best_match best_match = current_match chosen = id # Ties are bad - but it is better to chose something than to fail elsif current_match == best_match && id.smoke == chosen.smoke puts " ****** warning: multiple methods with the same score of #{current_match}: #{chosen.index} and #{id.index}" if debug_level >= DebugLevel::Minimal chosen = id end puts " match => smoke: #{id.smoke} index: #{id.index} score: #{current_match} chosen: #{chosen ? chosen.index : nil}" if debug_level >= DebugLevel::High end end # Additional debugging output if debug_level >= DebugLevel::Minimal && chosen.nil? && method !~ /^operator/ id = find_pclassid(normalize_classname(klass.name)) hash = findAllMethods(id) constructor_names = nil if method == classname puts "No matching constructor found, possibles:\n" constructor_names = hash.keys.grep(/^#{classname}/) else puts "Possible prototypes:" constructor_names = hash.keys end method_ids = hash.values_at(*constructor_names).flatten puts dumpCandidates(method_ids) else puts "setCurrentMethod(smokeList index: #{chosen.smoke}, meth index: #{chosen.index})" if debug_level >= DebugLevel::High && chosen end # Select the chosen method @@method_lookup_cache[lookup_str] = chosen setCurrentMethod(chosen) if chosen return nil end
# File lib/Qt/qtruby4.rb, line 2674 def Internal.find_class(classname) @@classes[classname] end
# File lib/Qt/qtruby4.rb, line 2899 def Internal.getAllParents(class_id, res) getIsa(class_id).each do |s| c = findClass(s) res << c getAllParents(c, res) end end
# File lib/Qt/qtruby4.rb, line 2980 def Internal.getMetaObject(klass, qobject) if klass.nil? klass = qobject.class end parentMeta = nil if @@cpp_names[klass.superclass.name].nil? parentMeta = getMetaObject(klass.superclass, qobject) end meta = Meta[klass.name] if meta.nil? meta = Qt::MetaInfo.new(klass) end if meta.metaobject.nil? or meta.changed stringdata, data = makeMetaData( qobject.class.name, meta.classinfos, meta.dbus, meta.signals, meta.slots ) meta.metaobject = make_metaObject(qobject, parentMeta, stringdata, data) meta.changed = false end meta.metaobject end
# File lib/Qt/qtruby4.rb, line 2891 def Internal.get_qboolean(b) return b.value end
# File lib/Qt/qtruby4.rb, line 2887 def Internal.get_qenum_type(e) return e.type end
# File lib/Qt/qtruby4.rb, line 2875 def Internal.get_qinteger(num) return num.value end
# File lib/Qt/qtruby4.rb, line 2537 def self.idclass return @@idclass end
# File lib/Qt/qtruby4.rb, line 2860 def Internal.init_all_classes() Qt::Internal::getClassList().each do |c| if c == "Qt" # Don't change Qt to Qt::t, just leave as is @@cpp_names["Qt"] = c elsif c != "QInternal" && !c.empty? Qt::Internal::init_class(c) end end @@classes['Qt::Integer'] = Qt::Integer @@classes['Qt::Boolean'] = Qt::Boolean @@classes['Qt::Enum'] = Qt::Enum end
# File lib/Qt/qtruby4.rb, line 2562 def Internal.init_class(c) if c == "WebCore" || c == "std" || c == "QGlobalSpace" return end classname = Qt::Internal::normalize_classname(c) classId = Qt::Internal.findClass(c) insert_pclassid(classname, classId) @@idclass[classId.index] = classname @@cpp_names[classname] = c klass = isQObject(c) ? create_qobject_class(classname, Qt) \ : create_qt_class(classname, Qt) @@classes[classname] = klass unless klass.nil? end
# File lib/Qt/qtruby4.rb, line 2927 def Internal.makeMetaData(classname, classinfos, dbus, signals, slots) # Each entry in 'stringdata' corresponds to a string in the # qt_meta_stringdata_<classname> structure. # 'pack_string' is used to convert 'stringdata' into the # binary sequence of null terminated strings for the metaObject stringdata = [] pack_string = "" string_table = string_table_handler(stringdata, pack_string) # This is used to create the array of uints that make up the # qt_meta_data_<classname> structure in the metaObject data = [1, # revision string_table.call(classname), # classname classinfos.length, classinfos.length > 0 ? 10 : 0, # classinfo signals.length + slots.length, 10 + (2*classinfos.length), # methods 0, 0, # properties 0, 0] # enums/sets classinfos.each do |entry| data.push string_table.call(entry[0]) # key data.push string_table.call(entry[1]) # value end signals.each do |entry| data.push string_table.call(entry.full_name) # signature data.push string_table.call(entry.full_name.delete("^,")) # parameters data.push string_table.call(entry.reply_type) # type, "" means void data.push string_table.call("") # tag if dbus data.push MethodScriptable | MethodSignal | AccessPublic else data.push entry.access # flags, always protected for now end end slots.each do |entry| data.push string_table.call(entry.full_name) # signature data.push string_table.call(entry.full_name.delete("^,")) # parameters data.push string_table.call(entry.reply_type) # type, "" means void data.push string_table.call("") # tag if dbus data.push MethodScriptable | MethodSlot | AccessPublic # flags, always public for now else data.push entry.access # flags, always public for now end end data.push 0 # eod return [stringdata.pack(pack_string), data] end
Handles calls of the form:
connect(:mysig, mytarget, :mymethod))
connect(SIGNAL('mysignal(int)'), mytarget, :mymethod))
# File lib/Qt/qtruby4.rb, line 3037 def Internal.method_connect(src, signal, target, method) signal = SIGNAL(signal) if signal.is_a?Symbol args = (signal =~ /\((.*)\)/) ? $1 : "" signature = Qt::MetaObject.normalizedSignature("invoke(%s)" % args).to_s return Qt::Object.connect( src, signal, Qt::MethodInvocation.new(target, method, signature), SLOT(signature) ) end
# File lib/Qt/qtruby4.rb, line 2545 def Internal.normalize_classname(classname) @@normalize_procs.each do |func| ret = func.call(classname) if !ret.nil? return ret end end if classname =~ /^Q3/ ruby_classname = classname.sub(/^Q3(?=[A-Z])/,'Qt3::') elsif classname =~ /^Q/ ruby_classname = classname.sub(/^Q(?=[A-Z])/,'Qt::') else ruby_classname = classname end ruby_classname end
If a block was passed to the constructor, then run that now. Either run the context of the new instance if no args were passed to the block. Or otherwise, run the block in the context of the arg.
# File lib/Qt/qtruby4.rb, line 2692 def Internal.run_initializer_block(instance, block) 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} for 1)" end end
# File lib/Qt/qtruby4.rb, line 2895 def Internal.set_qboolean(b, val) return b.value = val end
# File lib/Qt/qtruby4.rb, line 2879 def Internal.set_qinteger(num, val) return num.value = val end
Handles calls of the form:
connect(SIGNAL(:mysig)) { ...}
connect(SIGNAL('mysig(int)')) {|arg(s)| ...}
# File lib/Qt/qtruby4.rb, line 3025 def Internal.signal_connect(src, signal, block) args = (signal =~ /\((.*)\)/) ? $1 : "" signature = Qt::MetaObject.normalizedSignature("invoke(%s)" % args).to_s return Qt::Object.connect( src, signal, Qt::SignalBlockInvocation.new(src, block.to_proc, signature), SLOT(signature) ) end
Handles calls of the form:
Qt::Timer.singleShot(500, myobj) { ...}
# File lib/Qt/qtruby4.rb, line 3049 def Internal.single_shot_timer_connect(interval, target, block) return Qt::Timer.singleShot( interval, Qt::BlockInvocation.new(target, block, "invoke()"), SLOT("invoke()") ) end
Keeps a hash of strings against their corresponding offsets within the qt_meta_stringdata sequence of null terminated strings. Returns a proc to get an offset given a string. That proc also adds new strings to the 'data' array, and updates the corresponding 'pack_str' Array#pack template.
# File lib/Qt/qtruby4.rb, line 2912 def Internal.string_table_handler(data, pack_str) hsh = {} offset = 0 return lambda do |str| if !hsh.has_key? str hsh[str] = offset data << str pack_str << "a*x" offset += str.length + 1 end return hsh[str] end end
Runs the initializer as far as allocating the Qt C++ instance. Then use a throw to jump back to here with the C++ instance wrapped in a new ruby variable of type T_DATA
# File lib/Qt/qtruby4.rb, line 2681 def Internal.try_initialize(instance, *args) initializer = instance.method(:initialize) catch :newqt do initializer.call(*args) end end