Module: Qt::Internal

Defined in:
lib/qt/qtruby4.rb

Constant Summary collapse

AccessPrivate =

From the enum MethodFlags in qt-copy/src/tools/moc/generator.cpp

0x00
AccessProtected =
0x01
AccessPublic =
0x02
MethodMethod =
0x00
MethodSignal =
0x04
MethodSlot =
0x08
MethodCompatibility =
0x10
MethodCloned =
0x20
MethodScriptable =
0x40
@@classes =
{}
@@cpp_names =
{}
@@idclass =
[]

Class Method Summary collapse

Class Method Details

.checkarg(argtype, typename) ⇒ Object



2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
# File 'lib/qt/qtruby4.rb', line 2099

def Internal.checkarg(argtype, typename)
	puts "      #{typename} (#{argtype})" if debug_level >= DebugLevel::High
	if argtype == 'i'
		if typename =~ /^int&?$|^signed int&?$|^signed$|^qint32&?$|^quint32&?$/
			return 2
		elsif typename =~ /^(?:short|ushort|unsigned short int|uchar|uint|long|ulong|unsigned long int|unsigned|float|double|WId|Q_PID|^quint16&?$|^qint16&?$)$/
			return 1
		elsif typename =~ /^(quint|qint|qulong|qlong|qreal)/
			return 1
		else 
			t = typename.sub(/^const\s+/, '')
			t.sub!(/[&*]$/, '')
			if isEnum(t)
				return 0
			end
		end
	elsif argtype == 'n'
		if typename =~ /^double$|^qreal$/
			return 2
		elsif typename =~ /^float$/
			return 1
		elsif typename =~ /^int&?$/
			return 0
		elsif typename =~ /^(?:short|ushort|uint|long|ulong|signed|unsigned|float|double)$/
			return 0
		else 
			t = typename.sub(/^const\s+/, '')
			t.sub!(/[&*]$/, '')
			if isEnum(t)
				return 0
			end
		end
	elsif argtype == 'B'
		if typename =~ /^(?:bool)[*&]?$/
			return 0
		end
	elsif argtype == 's'
		if typename =~ /^(const )?((QChar)[*&]?)$/
			return 1
		elsif typename =~ /^(?:u?char\*|const u?char\*|(?:const )?(Q(C?)String)[*&]?)$/
			qstring = !$1.nil?
			c = ("C" == $2)
			return c ? 2 : (qstring ? 3 : 0)
		end
	elsif argtype == 'a'
		# 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 0
		end
	elsif argtype == 'u'
		# Give nil matched against string types a higher score than anything else
		if typename =~ /^(?:u?char\*|const u?char\*|(?:const )?((Q(C?)String))[*&]?)$/
			return 1
		# 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 0
		end
	elsif argtype == 'U'
		if typename =~ /QStringList/
			return 1
		else
			return 0
		end
	else
		t = typename.sub(/^const\s+/, '')
		t.sub!(/[&*]$/, '')
		if argtype == t
			return 1
		elsif classIsa(argtype, t)
			return 0
		elsif isEnum(argtype) and 
				(t =~ /int|qint32|uint|quint32|long|ulong/ or isEnum(t))
			return 0
		end
	end
	return -99
end

.connect(src, signal, target, block) ⇒ Object



2517
2518
2519
2520
2521
2522
2523
2524
# File 'lib/qt/qtruby4.rb', line 2517

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, signature),
								SLOT(signature) )
end

.create_qenum(num, type) ⇒ Object



2354
2355
2356
# File 'lib/qt/qtruby4.rb', line 2354

def Internal.create_qenum(num, type)
	return Qt::Enum.new(num, type)
end

.debug_levelObject



2095
2096
2097
# File 'lib/qt/qtruby4.rb', line 2095

def Internal.debug_level
	Qt.debug_level
end

.do_method_missing(package, method, klass, this, *args) ⇒ Object



2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
# File 'lib/qt/qtruby4.rb', line 2217

def Internal.do_method_missing(package, method, klass, this, *args)
	if klass.class == Module
		classname = klass.name
	else
		classname = @@cpp_names[klass.name]
		if classname.nil?
			if klass != Object and klass != Qt
				return do_method_missing(package, method, klass.superclass, this, *args)
			else
				return nil
			end
		end
	end
	
	if method == "new"
		method = classname.dup 
		method.gsub!(/^(QTextLayout|KParts|KIO|KNS|DOM|Kontact|Kate|KTextEditor|KConfigSkeleton::ItemEnum|KConfigSkeleton|KWin)::/,"")
	end
	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='

	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
	
	methodIds = []
	methods.collect { |meth| methodIds.concat( findMethod(classname, meth) ) }
	
	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

	if debug_level >= DebugLevel::High
		puts "classname    == #{classname}"
		puts ":: method == #{method}"
		puts "-> methodIds == #{methodIds.inspect}"
		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}  (#{id})" 
		}
	end
	
	chosen = nil
	if methodIds.length > 0
		best_match = -1
		methodIds.each do
			|id|
			puts "matching => #{id}" if debug_level >= DebugLevel::High
			current_match = 0
			(0...args.length).each do
				|i|
				current_match += checkarg( getVALUEtype(args[i]), getTypeNameOfArg(id, i) )
			end
			
			# Note that if current_match > best_match, then chosen must be nil
			if current_match > best_match
				best_match = current_match
				chosen = id
			# Multiple matches are an error; the equality test below _cannot_ be commented out.
			# If ambiguous matches occur the problem must be fixed be adjusting the relative
			# ranking of the arg types involved in checkarg().
			elsif current_match == best_match
				chosen = nil
			end
			puts "match => #{id} score: #{current_match}" if debug_level >= DebugLevel::High
		end
			
		puts "Resolved to id: #{chosen}" if !chosen.nil? && debug_level >= DebugLevel::High
	end

	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)
	end

	puts "setCurrentMethod(#{chosen})" if debug_level >= DebugLevel::High
	setCurrentMethod(chosen) if chosen
	return nil
end

.find_class(classname) ⇒ Object



2188
2189
2190
2191
# File 'lib/qt/qtruby4.rb', line 2188

def Internal.find_class(classname)
	# puts @@classes.keys.sort.join "\n"
	@@classes[classname]
end

.get_qboolean(b) ⇒ Object



2362
2363
2364
# File 'lib/qt/qtruby4.rb', line 2362

def Internal.get_qboolean(b)
	return b.value
end

.get_qenum_type(e) ⇒ Object



2358
2359
2360
# File 'lib/qt/qtruby4.rb', line 2358

def Internal.get_qenum_type(e)
	return e.type
end

.get_qinteger(num) ⇒ Object



2346
2347
2348
# File 'lib/qt/qtruby4.rb', line 2346

def Internal.get_qinteger(num)
	return num.value
end

.getAllParents(class_id, res) ⇒ Object



2370
2371
2372
2373
2374
2375
2376
# File 'lib/qt/qtruby4.rb', line 2370

def Internal.getAllParents(class_id, res)
	getIsa(class_id).each do |s|
		c = idClass(s)
		res << c
		getAllParents(c, res)
	end
end

.getMetaObject(klass, qobject) ⇒ Object



2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
# File 'lib/qt/qtruby4.rb', line 2489

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 = (	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

.getMocArguments(reply_type, member) ⇒ Object



2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
# File 'lib/qt/qtruby4.rb', line 2387

def Internal.getMocArguments(reply_type, member)
	argStr = member.sub(/.*\(/, '').sub(/\)$/, '')
	args = argStr.scan(/([^,]*<[^>]+>)|([^,]+)/)
	args.unshift reply_type
	mocargs = allocateMocArguments(args.length)
	args.each_with_index do |arg, i|
		arg = arg.to_s
		a = arg.sub(/^const\s+/, '')
		a = (a =~ /^(bool|int|double|char\*|QString)&?$/) ? $1 : 'ptr'
		valid = setMocType(mocargs, i, arg, a)
	end
	result = []
	result << args.length << mocargs
	result
end

.init_all_classesObject



2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
# File 'lib/qt/qtruby4.rb', line 2331

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"
			Qt::Internal::init_class(c)
		end
	end

	@@classes['Qt::Integer'] = Qt::Integer
	@@classes['Qt::Boolean'] = Qt::Boolean
	@@classes['Qt::Enum'] = Qt::Enum
end

.init_class(c) ⇒ Object



2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
# File 'lib/qt/qtruby4.rb', line 2084

def Internal.init_class(c)
	classname = Qt::Internal::normalize_classname(c)
	classId = Qt::Internal.idClass(c)
	insert_pclassid(classname, classId)
	@@idclass[classId] = classname
	@@cpp_names[classname] = c
	klass = isQObject(classId) ? create_qobject_class(classname) \
                                                 : create_qt_class(classname)
	@@classes[classname] = klass unless klass.nil?
end

.makeMetaData(classname, classinfos, dbus, signals, slots) ⇒ Object



2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
# File 'lib/qt/qtruby4.rb', line 2436

def Internal.(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 MethodSignal | AccessProtected	# 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 MethodSlot | AccessPublic		# flags, always public for now
		end
	end

	data.push 0		# eod

	return [stringdata.pack(pack_string), data]
end

.normalize_classname(classname) ⇒ Object



2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
# File 'lib/qt/qtruby4.rb', line 2064

def Internal.normalize_classname(classname)
	if classname =~ /^Qext/
		now = classname.sub(/^Qext(?=[A-Z])/,'Qext::')
	elsif classname =~ /^Qwt/
		now = classname.sub(/^Qwt(?=[A-Z])/,'Qwt::')
	elsif classname =~ /^Q3/
		now = classname.sub(/^Q3(?=[A-Z])/,'Qt3::')
	elsif classname =~ /^Q/
		now = classname.sub(/^Q(?=[A-Z])/,'Qt::')
	elsif classname =~ /^(KConfigSkeleton|KWin)::/
		now = classname.sub(/^K?(?=[A-Z])/,'KDE::')
	elsif classname !~ /::/
		now = classname.sub(/^K?(?=[A-Z])/,'KDE::')
	else
		now = classname
	end
#			puts "normalize_classname = was::#{classname}, now::#{now}"
	now
end

.run_initializer_block(instance, block) ⇒ Object

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.



2207
2208
2209
2210
2211
2212
2213
2214
2215
# File 'lib/qt/qtruby4.rb', line 2207

def Internal.run_initializer_block(instance, block)
	if block.arity == -1
		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

.set_qboolean(b, val) ⇒ Object



2366
2367
2368
# File 'lib/qt/qtruby4.rb', line 2366

def Internal.set_qboolean(b, val)
	return b.value = val
end

.set_qinteger(num, val) ⇒ Object



2350
2351
2352
# File 'lib/qt/qtruby4.rb', line 2350

def Internal.set_qinteger(num, val)
	return num.value = val
end

.signal_connect(src, signal, block) ⇒ Object



2526
2527
2528
2529
2530
2531
2532
2533
# File 'lib/qt/qtruby4.rb', line 2526

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, signature),
								SLOT(signature) )
end

.signalInfo(qobject, signal_name) ⇒ Object



2378
2379
2380
2381
2382
2383
2384
2385
# File 'lib/qt/qtruby4.rb', line 2378

def Internal.signalInfo(qobject, signal_name)
	signals = Meta[qobject.class.name].get_signals
	signals.each_with_index do |signal, i|
		if signal.name == signal_name
			return [signal.reply_type, signal.full_name, i]
		end
	end
end

.string_table_handler(data, pack_str) ⇒ Object

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.



2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
# File 'lib/qt/qtruby4.rb', line 2421

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

.try_initialize(instance, *args) ⇒ Object

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



2196
2197
2198
2199
2200
2201
# File 'lib/qt/qtruby4.rb', line 2196

def Internal.try_initialize(instance, *args)
	initializer = instance.method(:initialize)
	catch "newqt" do
		initializer.call(*args)
	end
end