QWebChannel 2019.1.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ce07be00157d3eee912b213bf18e2b92d1448aa8
4
+ data.tar.gz: 5084ac99eceb709a464ff0fafe5045fc9c0ec65c
5
+ SHA512:
6
+ metadata.gz: cdb5fb1f2450cf76ed90094b43e3fdc3acd65a76f89fe3c610dd8c7a1d993ebf889045ebd584aa76a499bd7eda394e1b66ff4dbb3f854175d364058d156d5c78
7
+ data.tar.gz: 784b99bf85a8d6c6f3a191ade87623ad2da6cf35f885aa5ada5b7f20383eee0f6383e5d16ee297485ea40394090ef9fe7af5f243a9133f04398d1f0968be893a
@@ -0,0 +1,137 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH.unshift File.expand_path('../QWebChannel', __FILE__)
4
+
5
+ # require 'Hearch/HearchIndexEntry_pb'
6
+ require 'QWebChannel/QSignal'
7
+ require 'QWebChannel/QObject'
8
+ require 'set'
9
+ require 'oj' #optimized json
10
+ require 'json' #json解析库。
11
+
12
+ module QWebChannelMessageTypes
13
+ SIGNAL=1
14
+ PROPERTYUPDATE=2
15
+ INIT=3
16
+ IDLE=4
17
+ DEBUG=5
18
+ INVOKEMETHOD=6
19
+ CONNECTTOSIGNAL=7
20
+ DISCONNECTFROMSIGNAL=8
21
+ SETPROPERTY=9
22
+ RESPONSE=10
23
+ end
24
+
25
+
26
+ class QWebChannel
27
+ attr_reader :execId
28
+ attr_writer :execId
29
+ attr_reader :execCallbacks
30
+ attr_writer :execCallbacks
31
+ attr_reader :transport
32
+ attr_writer :transport
33
+ attr_reader :objects
34
+ attr_writer :objects
35
+
36
+ def send(data)
37
+ if ( !( data.is_a?(String) ) )
38
+ data=Oj.dump(data)
39
+ end
40
+
41
+ puts "Sending: #{data}"
42
+
43
+ @channel.transport.send(data)
44
+ end
45
+
46
+ def exec(data, &block)
47
+ if !(block_given?)
48
+ @channel.send(data)
49
+ end
50
+
51
+ @channel.execId=@channel.execId+1
52
+ data['id']=@channel.execId
53
+
54
+ puts "data id: #{data['id']}"
55
+
56
+ @channel.execCallbacks[data['id']]=block
57
+ @channel.send(data)
58
+ end
59
+
60
+ def handleResponse(message)
61
+ @channel.execCallbacks[message['id']].call(message['data'])
62
+
63
+ @channel.execCallbacks[message['id']]=nil
64
+ end
65
+
66
+ def handleSignal(message)
67
+ object=@channel.objects[message['object']]
68
+
69
+ if (object)
70
+ object.signalEmitted(message['signal'], message['args'])
71
+ end
72
+ end #def handleSignal(message)
73
+
74
+
75
+ def initialize(websocket, &block)
76
+ @index = nil #索引对象。
77
+ @execId=0
78
+ @execCallbacks={}
79
+ @objects={}
80
+
81
+ @transport=websocket
82
+ @channel = self
83
+
84
+
85
+ @transport.onmessage do |msg, type|
86
+ # puts "Received message: #{msg}"
87
+
88
+ puts "msg type: #{msg.class}"
89
+
90
+ data =msg.to_s
91
+
92
+ puts "data: #{data}"
93
+
94
+ if (data.is_a?(String))
95
+ data=JSON.parse(data)
96
+ end
97
+
98
+ puts "type: #{data.class}"
99
+
100
+ case(data['type'])
101
+ when QWebChannelMessageTypes::SIGNAL
102
+ @channel.handleSignal(data)
103
+ when QWebChannelMessageTypes::RESPONSE
104
+ @channel.handleResponse(data)
105
+ when QWebChannelMessageTypes::PROPERTYUPDATE
106
+ @channel.handlePropertyUpdate(data)
107
+ else
108
+ puts("Invalid message arrived: #{data}")
109
+ end
110
+ end
111
+
112
+
113
+ @channel.exec({'type' => QWebChannelMessageTypes::INIT}) do |data|
114
+
115
+ puts "data type: #{data.class}"
116
+ puts "data content: #{data}"
117
+
118
+ data.each do |objectName, objectContent|
119
+ puts "objectName type: #{objectName.class}"
120
+
121
+ object=QObject.new(objectName, data[objectName], @channel)
122
+ end
123
+
124
+ @channel.objects.each do |objectName, objectObject|
125
+ @channel.objects[objectName].unwrapProperties()
126
+ end
127
+
128
+
129
+ puts "Self: #{self}"
130
+ yield(self)
131
+
132
+
133
+ @channel.exec({ "type" => QWebChannelMessageTypes::IDLE})
134
+ end #@channel.exec({'type' => QWebChannelMessageTypes::INIT}) do |data|
135
+ end #def initialize(websocket, &block)
136
+
137
+ end
@@ -0,0 +1,19 @@
1
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
2
+ # source: HearchIndexEntry.proto
3
+
4
+ require 'google/protobuf'
5
+
6
+ Google::Protobuf::DescriptorPool.generated_pool.build do
7
+ add_message "com.stupidbeauty.hearch.HearchIndexEntry" do
8
+ optional :keyword, :string, 1
9
+ repeated :articleId, :int32, 2
10
+ end
11
+ end
12
+
13
+ module Com
14
+ module Stupidbeauty
15
+ module Hearch
16
+ HearchIndexEntry = Google::Protobuf::DescriptorPool.generated_pool.lookup("com.stupidbeauty.hearch.HearchIndexEntry").msgclass
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'eventmachine'
4
+ require 'ipaddr'
5
+
6
+ class MulticastHandler < EventMachine::Connection
7
+ def castData(packageString)
8
+ multicastHost = '239.173.40.5' #组播组主机地址。
9
+ multicastPort = 11500 #组播组端口。
10
+
11
+ # print("castData\n") #Debug.
12
+ # send_data(packageString)
13
+ send_datagram(packageString, multicastHost, multicastPort) #发送组播数据包。
14
+ end
15
+
16
+ def receive_data(data)
17
+ # puts data
18
+ end
19
+
20
+ def post_init
21
+ # print("post_init\n") #Debug.
22
+ port, host = Socket::unpack_sockaddr_in( get_sockname() )
23
+ ip = IPAddr.new( host ).hton + IPAddr.new("0.0.0.0").hton
24
+ set_sock_opt( Socket::IPPROTO_IP, Socket::IP_ADD_MEMBERSHIP, ip )
25
+ end
26
+ end
27
+
@@ -0,0 +1,214 @@
1
+ class QObject
2
+ attr_accessor :__propertyCache__
3
+ attr_accessor :__id__
4
+ attr_accessor :__objectSignals__
5
+ attr_accessor :webChannel
6
+
7
+ def unwrapQObject(response)
8
+ puts "response class: #{response.class}" #debug
9
+ if (response.is_a?(Array))
10
+ ret = []
11
+
12
+ response.each do |responseI|
13
+ ret << @object.unwrapQObject(responseI)
14
+ end
15
+
16
+ return ret
17
+ end #if (response.is_a?(Array))
18
+
19
+
20
+ if (!response || response.is_a?(Fixnum) || response.is_a?(TrueClass) || !response["__QObject*__"] || response.id == nil)
21
+ return response
22
+ end
23
+
24
+ objectId=response.id
25
+
26
+ if (@webChannel.objects[objectId])
27
+ return @webChannel.objects[objectId]
28
+ end
29
+
30
+
31
+ qObject=QObject.new(objectId, response.data, @webChannel)
32
+
33
+ qObject.destroyed.connect() do
34
+ if (@webChannel.objects[objectId]==qObject)
35
+ @webChannel.objects.delete(objectId)
36
+
37
+ propertyNames=[]
38
+
39
+ qObject.each do |propertyName|
40
+ propertyNames << propertyName
41
+ end
42
+
43
+ propertyNames.each do |propertyName|
44
+ qObject.delete(propertyName)
45
+ end
46
+ end #if (@webChannel.objects[objectId]==qObject)
47
+ end #qObject.destroyed.connect() do
48
+
49
+ qObject.unwrapProperties()
50
+
51
+ return qObject
52
+ end #def unwrapQObject(response)
53
+
54
+ def unwrapProperties()
55
+ @object.__propertyCache__.each do |propertyIdx, propertyObject|
56
+ @object.__propertyCache__[propertyIdx]=@object.unwrapQObject(@object.__propertyCache__[propertyIdx])
57
+ end
58
+ end #def unwrapProperties()
59
+
60
+ def []=(signalName, signalObject)
61
+ @signalNameObjectHash[signalName]=signalObject
62
+ end #def []=(signalName, signalObject)
63
+
64
+ def [](signalName)
65
+ @signalNameObjectHash[signalName]
66
+ end #def [](signalName)
67
+
68
+ def bindGetterSetter(propertyInfo)
69
+ propertyIndex=propertyInfo[0]
70
+ propertyName=propertyInfo[1]
71
+ notifySignalData=propertyInfo[2]
72
+
73
+ @object.__propertyCache__[propertyIndex]=propertyInfo[3]
74
+
75
+ if (notifySignalData)
76
+ if (notifySignalData[0] == 1)
77
+ notifySignalData[0]=propertyName+"Changed"
78
+ end
79
+ addSignal(notifySignalData, true)
80
+ end #if (notifySignalData)
81
+
82
+ defineProperty(propertyName) #定义属性。对应于Object.defineProperty.
83
+ end #def bindGetterSetter(propertyInfo)
84
+
85
+ def defineProperty(propertyName)
86
+ # define_property_by_prototype(propertyName)
87
+
88
+
89
+ #getter
90
+ # self.class_eval( " def #{attr_name}; @#{attr_name}; end " )
91
+ self.instance_eval %Q{
92
+ def #{propertyName}
93
+ @object.__propertyCache__[propertyIndex]
94
+ end
95
+ }
96
+
97
+ #setter
98
+ self.instance_eval %Q{
99
+ def #{propertyName}=(val)
100
+
101
+ @object.__propertyCache__[propertyIndex]=val
102
+
103
+ valueToSend=val
104
+
105
+ if (valueToSend.is_a?(QObject) && @webChannel.objects[valueToSend.__id__] != nil)
106
+ valueToSend={"id" => valueToSend.__id__}
107
+
108
+ @webChannel.exec( {"type" => QWebChannelMessageTypes::SETPROPERTY, "object" => @object.__id__ , "property" => propertyIndex, "value" => valueToSend } )
109
+ end
110
+
111
+
112
+
113
+ end
114
+
115
+
116
+ }
117
+
118
+ end #def defineProperty(propertyName)
119
+
120
+ def invokeSignalCallbacks(signalName, signalArgs)
121
+ connections=@object.__objectSignals__[signalName]
122
+
123
+ if (connections) #存在连接。
124
+ connections.each do |callback| #一个个连接地处理。
125
+ callback.call(*signalArgs) #抹平数组。
126
+ end #connections.each do |callback| #一个个连接地处理。
127
+ end #if (connections)
128
+ end #def invokeSignalCallbacks(signalName, signalArgs)
129
+
130
+ def signalEmitted(signalName, signalArgs)
131
+ puts "signalArgs: #{signalArgs}" #debug.
132
+ invokeSignalCallbacks(signalName, self.unwrapQObject(signalArgs))
133
+ end #def signalEmitted(signalName, signalArgs)
134
+
135
+ def addSignal(signalData, isPropertyNotifySignal)
136
+ signalName=signalData[0]
137
+ signalIndex=signalData[1]
138
+
139
+ @object[signalName]=QSignal.new(signalName, signalIndex, @object, isPropertyNotifySignal) #添加信号。
140
+ end #def addSignal(signalData, isPropertyNotifySignal)
141
+
142
+ def addMethod(methodData)
143
+ methodName=methodData[0]
144
+ methodIdx=methodData[1]
145
+
146
+ @object.define_singleton_method(methodName) do |*arguments|
147
+ args=[]
148
+ callback=nil
149
+
150
+ arguments.each do |argument|
151
+ puts "argument class: #{argument.class}" #debug.
152
+ if (argument.is_a?(Proc))
153
+ callback=argument
154
+ elsif ( (argument.is_a?(QObject)) && (@webChannel.objects[argument.__id__] !=nil ) )
155
+ args << ({"id" => argument.__id__})
156
+ else
157
+ args << argument
158
+ end
159
+ end #arguments.each do |argument|
160
+
161
+ puts "__id__: #{@object.__id__}" #debug.
162
+
163
+
164
+ @webChannel.exec({ "type" => QWebChannelMessageTypes::INVOKEMETHOD, "object" => @object.__id__, "method" => methodIdx, "args" => args }) do |response|
165
+ if (response!=nil)
166
+ result = @object.unwrapQObject(response)
167
+
168
+ if (callback)
169
+ callback.call(result)
170
+ end
171
+ end #if (response!=nil)
172
+ end #@webChannel.exec() do |response|
173
+
174
+
175
+ end #@object.define_singleton_method(methodName) do |*arguments|
176
+ end #def addMethod(methodData)
177
+
178
+ def initialize(name, data, webChannel)
179
+ @signalNameObjectHash={} #信号名字与信号对象的映射。
180
+ @__id__=name
181
+ @webChannel=webChannel
182
+ webChannel.objects[name]=self
183
+
184
+ puts "__id__: #{@__id__}" #debug.
185
+
186
+
187
+ @__objectSignals__ = {}
188
+
189
+ @__propertyCache__ = {}
190
+
191
+ @object=self
192
+
193
+ data['methods'].each do |method|
194
+ puts "current method: #{method}" #debug
195
+ addMethod(method)
196
+ end
197
+
198
+ data['properties'].each do |property|
199
+ bindGetterSetter(property)
200
+ end
201
+
202
+ data['signals'].each do |signal|
203
+ addSignal(signal, false)
204
+ end
205
+
206
+ puts "enums: #{data['enums']}" #Debug.
207
+
208
+ if data['enums']
209
+ data['enums'].each do |name|
210
+ @object[name]=data['enums'][name]
211
+ end #data['enums'].each do |name|
212
+ end #if data['enums']
213
+ end
214
+ end
@@ -0,0 +1,31 @@
1
+ class QSignal
2
+ def initialize(signalName, signalIndex, object, isPropertyNotifySignal)
3
+ @signalName=signalName
4
+ @signalIndex=signalIndex
5
+ @object=object
6
+ @webChannel=@object.webChannel
7
+ @isPropertyNotifySignal=isPropertyNotifySignal
8
+ end
9
+
10
+ def connect(callback)
11
+ @object.__objectSignals__[@signalIndex]=@object.__objectSignals__[@signalIndex] || []
12
+ @object.__objectSignals__[@signalIndex] << callback
13
+
14
+ if (!@isPropertyNotifySignal && @signalName!= "destroyed")
15
+ @webChannel.exec( { "type" => QWebChannelMessageTypes::CONNECTTOSIGNAL, "object" => @object.__id__, "signal" => @signalIndex } )
16
+ end
17
+ end #def connect(callback)
18
+
19
+ def disconnect(callback)
20
+ @object.__objectSignals__[signalIndex]=@object.__objectSignals__[signalIndex] || []
21
+ idx=@object.__objectSignals__[signalIndex].indexOf(callback)
22
+
23
+
24
+ @object.__objectSignals__[signalIndex].delete_at(idx)
25
+
26
+ if (!isPropertyNotifySignal && @object.__objectSignals__[signalIndex].length == 0)
27
+ @webChannel.exec( { "type" => QWebChannelMessageTypes::DISCONNECTFROMSIGNAL, "object" => @object.__id__, "signal" => signalIndex } )
28
+ end #if (!isPropertyNotifySignal && @object.__objectSignals__[signalIndex].length == 0)
29
+ end #def disconnect(callback)
30
+ end #class QSignal
31
+
metadata ADDED
@@ -0,0 +1,68 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: QWebChannel
3
+ version: !ruby/object:Gem::Version
4
+ version: 2019.1.4
5
+ platform: ruby
6
+ authors:
7
+ - Hxcan Cai
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-01-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: websocket-eventmachine-client
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.2'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 1.2.0
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '1.2'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 1.2.0
33
+ description: QWebChannel ruby. Work with QWebChannel in pure ruby.
34
+ email: caihuosheng@gmail.com
35
+ executables: []
36
+ extensions: []
37
+ extra_rdoc_files: []
38
+ files:
39
+ - lib/QWebChannel.rb
40
+ - lib/QWebChannel/HearchIndexEntry_pb.rb
41
+ - lib/QWebChannel/MulticastHandler.rb
42
+ - lib/QWebChannel/QObject.rb
43
+ - lib/QWebChannel/QSignal.rb
44
+ homepage: http://rubygems.org/gems/QWebChannel
45
+ licenses:
46
+ - MIT
47
+ metadata: {}
48
+ post_install_message:
49
+ rdoc_options: []
50
+ require_paths:
51
+ - lib
52
+ required_ruby_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ required_rubygems_version: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ requirements: []
63
+ rubyforge_project:
64
+ rubygems_version: 2.5.2.3
65
+ signing_key:
66
+ specification_version: 4
67
+ summary: QWebChannel ruby.
68
+ test_files: []