bitcoin-ruby 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (128) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +0 -1
  3. data/.travis.yml +2 -7
  4. data/COPYING +1 -1
  5. data/Gemfile +2 -6
  6. data/Gemfile.lock +34 -0
  7. data/README.rdoc +16 -68
  8. data/Rakefile +3 -6
  9. data/bin/bitcoin_shell +0 -1
  10. data/{concept-examples/blockchain-pow.rb → examples/concept-blockchain-pow.rb} +0 -0
  11. data/lib/bitcoin.rb +350 -296
  12. data/lib/bitcoin/builder.rb +3 -1
  13. data/lib/bitcoin/connection.rb +2 -1
  14. data/lib/bitcoin/contracthash.rb +76 -0
  15. data/lib/bitcoin/dogecoin.rb +97 -0
  16. data/lib/bitcoin/ffi/bitcoinconsensus.rb +74 -0
  17. data/lib/bitcoin/ffi/openssl.rb +98 -2
  18. data/lib/bitcoin/ffi/secp256k1.rb +144 -0
  19. data/lib/bitcoin/key.rb +12 -2
  20. data/lib/bitcoin/logger.rb +3 -12
  21. data/lib/bitcoin/protocol/block.rb +3 -9
  22. data/lib/bitcoin/protocol/parser.rb +6 -2
  23. data/lib/bitcoin/protocol/tx.rb +44 -13
  24. data/lib/bitcoin/protocol/txin.rb +4 -2
  25. data/lib/bitcoin/protocol/txout.rb +2 -2
  26. data/lib/bitcoin/script.rb +212 -37
  27. data/lib/bitcoin/trezor/mnemonic.rb +130 -0
  28. data/lib/bitcoin/version.rb +1 -1
  29. data/spec/bitcoin/bitcoin_spec.rb +32 -3
  30. data/spec/bitcoin/builder_spec.rb +18 -0
  31. data/spec/bitcoin/contracthash_spec.rb +45 -0
  32. data/spec/bitcoin/dogecoin_spec.rb +176 -0
  33. data/spec/bitcoin/ffi_openssl.rb +45 -0
  34. data/spec/bitcoin/fixtures/156e6e1b84c5c3bd3a0927b25e4119fadce6e6d5186f363317511d1d680fae9a.json +24 -0
  35. data/spec/bitcoin/fixtures/8d0b238a06b5a70be75d543902d02d7a514d68d3252a949a513865ac3538874c.json +24 -0
  36. data/spec/bitcoin/fixtures/coinbase-toshi.json +33 -0
  37. data/spec/bitcoin/fixtures/coinbase.json +24 -0
  38. data/spec/bitcoin/fixtures/dogecoin-block-60323982f9c5ff1b5a954eac9dc1269352835f47c2c5222691d80f0d50dcf053.bin +0 -0
  39. data/spec/bitcoin/fixtures/rawtx-01-toshi.json +46 -0
  40. data/spec/bitcoin/fixtures/rawtx-02-toshi.json +46 -0
  41. data/spec/bitcoin/fixtures/rawtx-03-toshi.json +73 -0
  42. data/spec/bitcoin/fixtures/rawtx-testnet-04fdc38d6722ab4b12d79113fc4b2896bdcc5169710690ee4e78541b98e467b4.bin +0 -0
  43. data/spec/bitcoin/fixtures/rawtx-testnet-0b294c7d11dd21bcccb8393e6744fed7d4d1981a08c00e3e88838cc421f33c9f.bin +0 -0
  44. data/spec/bitcoin/fixtures/rawtx-testnet-3bc52ac063291ad92d95ddda5fd776a342083b95607ad32ed8bc6f8f7d30449e.bin +0 -0
  45. data/spec/bitcoin/fixtures/rawtx-testnet-6f0bbdd4e71a8af4305018d738184df32dbb6f27284fdebd5b56d16947f7c181.bin +0 -0
  46. data/spec/bitcoin/fixtures/rawtx-testnet-a7c9b06e275e8674cc19a5f7d3e557c72c6d93576e635b33212dbe08ab7cdb60.bin +0 -0
  47. data/spec/bitcoin/fixtures/rawtx-testnet-f80acbd2f594d04ddb0e1cacba662132104909157dff526935a3c88abe9201a5.bin +0 -0
  48. data/spec/bitcoin/protocol/block_spec.rb +0 -22
  49. data/spec/bitcoin/protocol/tx_spec.rb +145 -2
  50. data/spec/bitcoin/script/script_spec.rb +282 -0
  51. data/spec/bitcoin/secp256k1_spec.rb +48 -0
  52. data/spec/bitcoin/spec_helper.rb +0 -51
  53. data/spec/bitcoin/trezor/mnemonic_spec.rb +161 -0
  54. metadata +48 -98
  55. data/bin/bitcoin_dns_seed +0 -130
  56. data/bin/bitcoin_gui +0 -80
  57. data/bin/bitcoin_node +0 -153
  58. data/bin/bitcoin_node_cli +0 -81
  59. data/bin/bitcoin_wallet +0 -402
  60. data/doc/CONFIG.rdoc +0 -66
  61. data/doc/EXAMPLES.rdoc +0 -13
  62. data/doc/NAMECOIN.rdoc +0 -34
  63. data/doc/NODE.rdoc +0 -225
  64. data/doc/STORAGE.rdoc +0 -33
  65. data/doc/WALLET.rdoc +0 -102
  66. data/examples/balance.rb +0 -66
  67. data/examples/forwarder.rb +0 -73
  68. data/examples/index_nhash.rb +0 -24
  69. data/examples/reindex_p2sh_addrs.rb +0 -44
  70. data/examples/relay_tx.rb +0 -22
  71. data/examples/verify_tx.rb +0 -57
  72. data/lib/bitcoin/config.rb +0 -58
  73. data/lib/bitcoin/gui/addr_view.rb +0 -44
  74. data/lib/bitcoin/gui/bitcoin-ruby.png +0 -0
  75. data/lib/bitcoin/gui/bitcoin-ruby.svg +0 -80
  76. data/lib/bitcoin/gui/conn_view.rb +0 -38
  77. data/lib/bitcoin/gui/connection.rb +0 -70
  78. data/lib/bitcoin/gui/em_gtk.rb +0 -30
  79. data/lib/bitcoin/gui/gui.builder +0 -1643
  80. data/lib/bitcoin/gui/gui.rb +0 -292
  81. data/lib/bitcoin/gui/helpers.rb +0 -115
  82. data/lib/bitcoin/gui/tree_view.rb +0 -84
  83. data/lib/bitcoin/gui/tx_view.rb +0 -69
  84. data/lib/bitcoin/namecoin.rb +0 -280
  85. data/lib/bitcoin/network/command_client.rb +0 -104
  86. data/lib/bitcoin/network/command_handler.rb +0 -570
  87. data/lib/bitcoin/network/connection_handler.rb +0 -387
  88. data/lib/bitcoin/network/node.rb +0 -565
  89. data/lib/bitcoin/storage/dummy/dummy_store.rb +0 -179
  90. data/lib/bitcoin/storage/models.rb +0 -171
  91. data/lib/bitcoin/storage/sequel/migrations.rb +0 -99
  92. data/lib/bitcoin/storage/sequel/migrations/001_base_schema.rb +0 -52
  93. data/lib/bitcoin/storage/sequel/migrations/002_tx.rb +0 -45
  94. data/lib/bitcoin/storage/sequel/migrations/003_change_txin_script_sig_to_blob.rb +0 -18
  95. data/lib/bitcoin/storage/sequel/migrations/004_change_txin_prev_out_to_blob.rb +0 -18
  96. data/lib/bitcoin/storage/sequel/migrations/005_change_tx_hash_to_bytea.rb +0 -14
  97. data/lib/bitcoin/storage/sequel/migrations/006_add_tx_nhash.rb +0 -31
  98. data/lib/bitcoin/storage/sequel/migrations/007_add_prev_out_index_index.rb +0 -16
  99. data/lib/bitcoin/storage/sequel/migrations/008_add_txin_p2sh_type.rb +0 -31
  100. data/lib/bitcoin/storage/sequel/migrations/009_add_addrs_type.rb +0 -56
  101. data/lib/bitcoin/storage/sequel/sequel_store.rb +0 -551
  102. data/lib/bitcoin/storage/storage.rb +0 -517
  103. data/lib/bitcoin/storage/utxo/migrations/001_base_schema.rb +0 -52
  104. data/lib/bitcoin/storage/utxo/migrations/002_utxo.rb +0 -18
  105. data/lib/bitcoin/storage/utxo/migrations/003_update_indices.rb +0 -14
  106. data/lib/bitcoin/storage/utxo/migrations/004_add_addrs_type.rb +0 -14
  107. data/lib/bitcoin/storage/utxo/utxo_store.rb +0 -374
  108. data/lib/bitcoin/validation.rb +0 -400
  109. data/lib/bitcoin/wallet/coinselector.rb +0 -33
  110. data/lib/bitcoin/wallet/keygenerator.rb +0 -77
  111. data/lib/bitcoin/wallet/keystore.rb +0 -207
  112. data/lib/bitcoin/wallet/txdp.rb +0 -118
  113. data/lib/bitcoin/wallet/wallet.rb +0 -281
  114. data/spec/bitcoin/fixtures/freicoin-block-000000005d231b285e63af83edae2d8f5e50e70d396468643092b9239fd3be3c.bin +0 -0
  115. data/spec/bitcoin/fixtures/freicoin-block-000000005d231b285e63af83edae2d8f5e50e70d396468643092b9239fd3be3c.json +0 -43
  116. data/spec/bitcoin/fixtures/freicoin-genesis-block-000000005b1e3d23ecfd2dd4a6e1a35238aa0392c0a8528c40df52376d7efe2c.bin +0 -0
  117. data/spec/bitcoin/fixtures/freicoin-genesis-block-000000005b1e3d23ecfd2dd4a6e1a35238aa0392c0a8528c40df52376d7efe2c.json +0 -67
  118. data/spec/bitcoin/namecoin_spec.rb +0 -182
  119. data/spec/bitcoin/node/command_api_spec.rb +0 -663
  120. data/spec/bitcoin/storage/models_spec.rb +0 -104
  121. data/spec/bitcoin/storage/reorg_spec.rb +0 -236
  122. data/spec/bitcoin/storage/storage_spec.rb +0 -387
  123. data/spec/bitcoin/storage/validation_spec.rb +0 -300
  124. data/spec/bitcoin/wallet/coinselector_spec.rb +0 -38
  125. data/spec/bitcoin/wallet/keygenerator_spec.rb +0 -69
  126. data/spec/bitcoin/wallet/keystore_spec.rb +0 -190
  127. data/spec/bitcoin/wallet/txdp_spec.rb +0 -76
  128. data/spec/bitcoin/wallet/wallet_spec.rb +0 -238
@@ -1,292 +0,0 @@
1
- # encoding: ascii-8bit
2
-
3
- require_relative "em_gtk.rb"
4
- require_relative "helpers.rb"
5
- require_relative "tree_view.rb"
6
- require_relative "addr_view.rb"
7
- require_relative "tx_view.rb"
8
- require_relative "conn_view.rb"
9
-
10
- Gtk.init
11
-
12
- module Bitcoin::Gui
13
-
14
- class Gui
15
-
16
- include Helpers
17
-
18
- attr_reader :builder, :wallet, :storage
19
- attr_accessor :node, :addr_view, :conn_view
20
-
21
- def initialize storage, wallet_file = nil
22
- @storage = storage
23
- @node = nil
24
- build
25
- @addr_view = AddrView.new(self)
26
- @tx_view = TxView.new(self, :tx_view)
27
- @conn_view = ConnView.new(self)
28
- open_wallet(wallet_file) if wallet_file
29
- main_window.show_all
30
- # notebook.next_page
31
- statusicon.tooltip_text = "Bitcoin-Ruby GUI"
32
- GObject.signal_connect(statusicon, "activate") do
33
- main_window.visible ? main_window.hide : main_window.show
34
- end
35
- GObject.signal_connect(statusicon, "popup-menu") do
36
- popup_menu.popup_for_device(nil, nil, nil, ->(*a) {}, nil, nil, 0, 0)
37
- end
38
- end
39
-
40
- def log
41
- @log ||= Bitcoin::Logger.create(:gui)
42
- end
43
-
44
- def build
45
- @builder = Gtk::Builder.new
46
- @builder.add_from_file(File.join(File.dirname(__FILE__), "gui.builder"))
47
- @builder.connect_signals_full(->(builder, widget, signal, handler, _, _, gui) do
48
- GObject.signal_connect(widget, signal) { gui.send(handler) }
49
- end, self)
50
-
51
- {
52
- "<Control>n" => :file_new,
53
- "<Control>o" => :file_open,
54
- "<Control>q" => :file_quit,
55
- "<Control>c" => :edit_copy,
56
- "<Control>v" => :edit_paste,
57
- "<Control>p" => :edit_preferences,
58
- "<Control>h" => :help_about,
59
- }.each do |binding, action|
60
- send("menu_#{action}").add_accelerator("activate", accelgroup1,
61
- *Gtk.accelerator_parse(binding), 0)
62
- end
63
- end
64
-
65
- def update_wallet_views
66
- return unless @wallet
67
- EM.defer do
68
- @addr_view.update(@wallet.keystore.keys)#.select{|k| k[:mine] == true})
69
- @tx_view.update(@wallet.get_txouts(true))
70
- unconfirmed = check_unconfirmed.active
71
- wallet_text = "wallet: #{@wallet.keystore.config[:file]} | " +
72
- "addresses: #{@wallet.addrs.size} | " +
73
- "balance: #{"%.8f" % (@wallet.get_balance(unconfirmed) / 1e8)}"
74
- status_wallet.push 0, wallet_text
75
- end
76
- end
77
-
78
- def on_check_unconfirmed_toggled
79
- update_wallet_views
80
- end
81
-
82
- def on_preferences
83
- dialog(:preferences, :setup => ->(d) {
84
- config = Bitcoin::Config.load({}, :wallet)
85
- model = preferences_box_network.get_model
86
- row = model.append
87
- model.set_value(row, 0, "foo")
88
- preferences_box_network.set_model model
89
- # preferences_entry_network.text = config[:network]
90
- }) do |*a|
91
- p a
92
- end
93
- end
94
-
95
- def on_copy_addr
96
- addrs = []
97
- valid, i = @addr_view.model.get_iter_first
98
- while valid
99
- if @addr_view.view.selection.iter_is_selected(i)
100
- a = @addr_view.model.get_value(i, 0).get_string
101
- addrs << a
102
- end
103
- valid = @addr_view.model.iter_next(i.to_ptr)
104
- end
105
-
106
- return unless addrs.any?
107
- text = addrs.join(", ")
108
- c = Gtk::Clipboard.get(Gdk::Atom.intern("PRIMARY", false))
109
- c.set_text text, text.size
110
- c = Gtk::Clipboard.get(Gdk::Atom.intern("CLIPBOARD", false))
111
- c.set_text text, text.size
112
- end
113
-
114
- def on_paste_addr
115
- c = Gtk::Clipboard.get(Gdk::Atom.intern("PRIMARY", false))
116
- c.request_text ->(clip, text, data) {
117
- on_new_addr(text) if Bitcoin.valid_address?(text)
118
- }, self
119
- c = Gtk::Clipboard.get(Gdk::Atom.intern("CLIPBOARD", false))
120
- c.request_text ->(clip, text, data) {
121
- on_new_addr(text) if Bitcoin.valid_address?(text)
122
- }, self
123
- end
124
-
125
- def on_new_addr addr = nil
126
- dialog(:new_addr, setup: ->(d) {
127
- new_addr_check_addr.active = addr ? true : false
128
- new_addr_check_pubkey.active = false
129
- new_addr_check_mine.active = addr ? false : true
130
- new_addr_entry_label.text = ""
131
- new_addr_entry_addr.text = addr ? addr : ""
132
- new_addr_entry_pubkey.text = ""
133
- new_addr_entry_addr.hide unless addr
134
- new_addr_entry_pubkey.hide
135
- GObject.signal_connect(new_addr_check_addr, "toggled") do
136
- new_addr_check_addr.active ? new_addr_entry_addr.show :
137
- new_addr_entry_addr.hide
138
- end
139
- GObject.signal_connect(new_addr_check_pubkey, "toggled") do
140
- new_addr_check_pubkey.active ? new_addr_entry_pubkey.show :
141
- new_addr_entry_pubkey.hide
142
- end
143
- }) do |*a|
144
- begin
145
- label = new_addr_entry_label.text
146
- set_address = new_addr_check_addr.active
147
- set_pubkey = new_addr_check_pubkey.active
148
- is_mine = new_addr_check_mine.active
149
- key = {:label => label}
150
- if set_address
151
- addr = new_addr_entry_addr.text
152
- raise "Address #{addr} invalid" unless Bitcoin.valid_address?(addr)
153
- key[:addr] = addr
154
- end
155
- if set_pubkey
156
- k = Bitcoin::Key.new(nil, new_addr_entry_pubkey.text)
157
- key[:key] = k
158
- key[:addr] = k.addr
159
- end
160
- if !set_address && !set_pubkey
161
- key[:key] = Bitcoin::Key.generate
162
- key[:addr] = key[:key].addr
163
- end
164
- key[:mine] = is_mine
165
- @wallet.add_key(key)
166
- update_wallet_views
167
- rescue
168
- message(:error, "Error adding key", $!.message, [:ok]) do
169
- new_addr_dialog.show
170
- end
171
- end
172
- update_addr_store
173
- end
174
- end
175
-
176
- def on_new_tx
177
- dialog(:new_tx, :setup => ->(d) {
178
- new_tx_entry_address.text = ""
179
- new_tx_entry_amount.text = ""
180
- model = Gtk::ListStore.new([GObject::TYPE_STRING, GObject::TYPE_STRING])
181
- @wallet.keystore.keys.each do |key|
182
- row = model.append
183
- model.set_value(row, 0, key[:label] || "")
184
- model.set_value(row, 1, key[:addr])
185
- end
186
- renderer = Gtk::CellRendererText.new
187
- comp = Gtk::EntryCompletion.new_with_area(area)
188
- comp.text_column = 1
189
- comp.minimum_key_length = 1
190
- comp.set_match_func(->(comp, text, iter, _) {
191
- label = comp.get_model.value(iter, 0).get_string
192
- addr = comp.get_model.value(iter, 1).get_string
193
- !!(label =~ /#{text}/ || addr =~ /#{text}/)
194
- }, nil, nil)
195
- comp.area.pack_start renderer, false, false, false
196
- comp.area.orientation = :vertical
197
- comp.set_model model
198
- renderer.set_padding 10, 0
199
- renderer.foreground = "blue"
200
- comp.set_cell_data_func(renderer, ->(layout, renderer, model, iter, data) {
201
- renderer.text = model.get_value(iter, 0).get_string
202
- }, nil, nil)
203
- new_tx_entry_address.set_completion comp
204
- # GObject.signal_connect(comp, "match-selected") do |comp, _, iter, _|
205
- # addr = comp.get_model.get_value(iter, 1).get_string
206
- # new_tx_entry_address.text = addr
207
- # true
208
- # end
209
- }) do |dialog|
210
-
211
- address = new_tx_entry_address.text
212
- amount = new_tx_entry_amount.text
213
- unless Bitcoin.valid_address?(address)
214
- message(:error, "Invalid Address",
215
- "Address #{address} is not a valid bitcoin address.", [:ok]) do
216
- new_tx_dialog.show
217
- end
218
- next
219
- end
220
- unless amount =~ /[0-9]*\.[0-9]*/
221
- message(:error, "Invalid Amount",
222
- "Amount #{amount} can not be parsed. Please use \"0.0\" form.", [:ok]) do
223
- new_tx_dialog.show
224
- end
225
- next
226
- end
227
- value = (amount.to_f * 1e8).to_i
228
- unless value <= @wallet.get_balance
229
- message(:error, "Insufficient Balance",
230
- "Balance #{@wallet.get_balance} is not sufficient to spend #{value}.", [:ok]) do
231
- dialog.show
232
- end
233
- next
234
- end
235
- message(:question, "Really send transaction?",
236
- "Do you really want to send #{format_value value} to #{address}?", [:no, :yes]) do
237
- tx = @wallet.new_tx([[:address, *[address], value]], 0.00)
238
- # puts tx.to_json
239
- if @node.request(:relay_tx, tx)
240
- puts "Transaction #{tx} relayed."
241
- end
242
- end
243
- end
244
- end
245
-
246
- def on_new_wallet
247
- dialog(:wallet_save, :filters => :wallet, :callbacks => {
248
- "update-preview" => method(:wallet_preview)}) do
249
- file = wallet_save_dialog.filename.read_string
250
- open_wallet(file) unless File.file?(file)
251
- end
252
- end
253
-
254
- def on_open_wallet
255
- dialog(:wallet_open, :filters => :wallet, :callbacks => {
256
- "update-preview" => method(:wallet_preview)}) do
257
- open_wallet(wallet_open_dialog.filename.read_string)
258
- end
259
- end
260
-
261
- def on_about
262
- dialog(:about)
263
- end
264
-
265
- def on_exit
266
- puts "bye"
267
- Gtk.main_quit
268
- EM.stop
269
- end
270
-
271
- def open_wallet(file)
272
- keystore = Bitcoin::Wallet::SimpleKeyStore.new(:file => file)
273
- @wallet = Bitcoin::Wallet::Wallet.new(@storage, keystore,
274
- Bitcoin::Wallet::SimpleCoinSelector)
275
- @wallet.on_tx do |type, tx|
276
- puts "#{type} transaction: #{tx.hash}"
277
- update_wallet_views
278
- value = tx.out.select {|out| (@wallet.addrs & out.get_addresses).any? }
279
- .map(&:value).inject(:+)
280
- title = "#{type.to_s.capitalize} transaction"
281
- message = "#{tx.hash}\nValue: #{format_value(value)}"
282
- Notify.notify title, message
283
- end
284
- update_wallet_views
285
- rescue
286
- message(:error, "Error loading wallet", $!.message, [:ok])
287
- p $!
288
- puts *$@
289
- end
290
-
291
- end
292
- end
@@ -1,115 +0,0 @@
1
- # encoding: ascii-8bit
2
-
3
- module Bitcoin::Gui::Helpers
4
-
5
- def display_tx tx_hash
6
- tx = @storage.get_tx(tx_hash)
7
- dialog(:tx, setup: ->(d) {
8
- tx_label_hash.text = tx.hash
9
- tx_label_value.text = format_value(tx.out.map(&:value).inject(:+))
10
- tx_label_confirmations.text = tx.confirmations.to_s
11
- txin_view = Bitcoin::Gui::TxInView.new(self, :tx_txin_view)
12
- # txin_view.update(tx.in)
13
- })
14
- end
15
-
16
- def wallet_preview(dialog, *args)
17
- filename = dialog.preview_filename
18
- file = filename.read_string rescue nil
19
- if file && File.file?(file)
20
- keystore = Bitcoin::Wallet::SimpleKeyStore.new(:file => file)
21
- wallet = Bitcoin::Wallet::Wallet.new(@storage, keystore,
22
- Bitcoin::Wallet::SimpleCoinSelector)
23
- preview = Gtk::Label.new "Keys: #{wallet.addrs.size}\n" +
24
- "Balance:\n%.8f" % (wallet.get_balance / 1e8)
25
- end
26
- dialog.preview_widget = preview
27
- end
28
-
29
- def add_wallet_filters dialog
30
- filter = Gtk::FileFilter.new
31
- filter.name = "Wallet Files"
32
- filter.add_pattern("*.json")
33
- dialog.add_filter filter
34
-
35
- filter = Gtk::FileFilter.new
36
- filter.name = "All Files"
37
- filter.add_pattern("*")
38
- dialog.add_filter filter
39
- end
40
-
41
- def dialog name, opts = {}
42
- @dialog_cb_ids ||= {}
43
- ids = @dialog_cb_ids[name] || []
44
- dialog = send("#{name}_dialog")
45
- send("add_#{opts[:filters]}_filters", dialog) if opts[:filters]
46
- opts[:setup].call(dialog) if opts[:setup]
47
- while id = ids.shift
48
- GObject.signal_handler_disconnect(dialog, id)
49
- end
50
- ids << GObject.signal_connect(dialog, "response") do |dialog, response, *data|
51
- yield(dialog, *data) if response > 0
52
- dialog.hide
53
- end
54
- if dialog.is_a?(Gtk::FileChooserDialog)
55
- ids << GObject.signal_connect(dialog, "file-activated") do |dialog, *data|
56
- yield(dialog, *data)
57
- dialog.hide
58
- end
59
- end
60
- (opts[:callbacks] || {}).each do |name, block|
61
- ids << GObject.signal_connect(dialog, name) {|*a| block.call(*a) }
62
- end
63
- dialog.show
64
- @dialog_cb_ids[name] = ids
65
- rescue
66
- p $!
67
- puts *$@
68
- end
69
-
70
- def message(type, title, text, buttons)
71
- dialog(:message, :setup => ->(dialog){
72
- dialog.message_type = Gtk::MessageType.find(type.to_sym)
73
- dialog.text = title
74
- dialog.secondary_text = text
75
- [:yes, :no, :ok].each do |n|
76
- b = send("message_dialog_button_#{n}")
77
- buttons.include?(n) ? b.show : b.hide
78
- end
79
- }) do |dialog|
80
- yield(dialog) if block_given?
81
- dialog.show_all
82
- dialog.hide
83
- end
84
- rescue
85
- p $!
86
- end
87
-
88
- def method_missing name, *args
89
- @builder.get_object(name.to_s) rescue super(name, *args)
90
- end
91
-
92
- def format_value val
93
- "%.8f" % (val / 1e8)
94
- end
95
-
96
- def format_address address, label = nil
97
- "#{label} (#{address})"
98
- end
99
-
100
- def format_version ver
101
- ver.insert(-3, '.') if ver.size > 2
102
- ver.insert(-6, '.') if ver.size > 5
103
- ver.insert(0, "0.") if ver.size <= 7
104
- ver
105
- end
106
-
107
- def format_uptime started
108
- uptime = Time.now.to_i - started
109
- mm, ss = uptime.divmod(60) #=> [4515, 21]
110
- hh, mm = mm.divmod(60) #=> [75, 15]
111
- dd, hh = hh.divmod(24) #=> [3, 3]
112
- "%02d:%02d:%02d:%02d" % [dd, hh, mm, ss]
113
- end
114
-
115
- end
@@ -1,84 +0,0 @@
1
- # encoding: ascii-8bit
2
-
3
- module Bitcoin::Gui
4
- class TreeView
5
-
6
- include Helpers
7
-
8
- attr_accessor :model, :view
9
-
10
- def initialize gui, view_name, columns
11
- @gui = gui
12
- @view = @gui.builder.get_object(view_name.to_s)
13
- @model = Gtk::TreeStore.new(columns.map{|c| c[0] })
14
- @view.set_model @model
15
-
16
- columns.each_with_index do |cdef, i|
17
- type, label, cb = *cdef
18
- next unless label
19
- case type
20
- when GObject::TYPE_BOOLEAN
21
- renderer = Gtk::CellRendererToggle.new
22
- col = tree_view_col(renderer, label, "active", i) do |*args|
23
- method(cb).call(@model, i, args[1], args[3]) if cb
24
- end
25
- when GObject::TYPE_STRING, GObject::TYPE_INT
26
- renderer = Gtk::CellRendererText.new
27
- col = tree_view_col(renderer, label, "text", i) do |*args|
28
- method(cb).call(@model, i, args[1], args[3]) if cb
29
- end
30
- end
31
- @view.append_column(col)
32
- end
33
- end
34
-
35
- def embed name
36
- parent = @gui.builder.get_object(name.to_s).parent
37
- parent.remove(parent.get_child)
38
- parent.add(@view)
39
- end
40
-
41
- def tree_view_col renderer, title, key, val, &block
42
- col = Gtk::TreeViewColumn.new
43
- col.pack_start renderer, true
44
- col.add_attribute renderer, key, val
45
- col.set_title title
46
- col.set_cell_data_func(renderer, block, nil, nil)
47
- col
48
- end
49
-
50
- def format_address_col model, i, renderer, iter
51
- address = model.get_value(iter, i).get_string
52
- label = model.get_value(iter, i+1).get_string
53
- renderer.text = format_address(address, label)
54
- end
55
-
56
- def format_value_col model, i, renderer, iter
57
- val = model.get_value(iter, i).get_string.to_i
58
- renderer.text = format_value(val)
59
- if val > 0
60
- renderer.foreground = "darkgreen"
61
- elsif val < 0
62
- renderer.foreground = "red"
63
- else
64
- renderer.foreground = "black"
65
- end
66
- end
67
-
68
- def format_version_col model, i, renderer, iter
69
- ver = model.get_value(iter, i).get_int.to_s
70
- renderer.text = format_version(ver)
71
- end
72
-
73
- def format_uptime_col model, i, renderer, iter
74
- started = model.get_value(iter, i).get_int
75
- renderer.text = format_uptime(started)
76
- end
77
-
78
- def format_bool_col model, i, renderer, iter
79
- active = model.get_value(iter, i).get_boolean
80
- renderer.set_active active
81
- end
82
-
83
- end
84
- end