XDCC-Fetch 1.386 → 1.409

Sign up to get free protection for your applications and to get access to all the features.
@@ -4,14 +4,14 @@
4
4
  # Redistribution and use in source and binary forms, with or without modification,
5
5
  # are permitted provided that the following conditions are met:
6
6
  #
7
- # * Redistributions of source code must retain the above copyright notice, this list
8
- # of conditions and the following disclaimer.
9
- # * Redistributions in binary form must reproduce the above copyright notice, this list
10
- # of conditions and the following disclaimer in the documentation and/or other materials
11
- # provided with the distribution.
12
- # * Neither the name of Martin Ankerl nor the names of its contributors may be used to
13
- # endorse or promote products derived from this software without specific prior written
14
- # permission.
7
+ # * Redistributions of source code must retain the above copyright notice, this list
8
+ # of conditions and the following disclaimer.
9
+ # * Redistributions in binary form must reproduce the above copyright notice, this list
10
+ # of conditions and the following disclaimer in the documentation and/or other materials
11
+ # provided with the distribution.
12
+ # * Neither the name of Martin Ankerl nor the names of its contributors may be used to
13
+ # endorse or promote products derived from this software without specific prior written
14
+ # permission.
15
15
  #
16
16
  # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
17
17
  # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
@@ -68,6 +68,7 @@ require 'src/GUI/About_Dialog'
68
68
  require 'src/GUI/Download_Finished_Box'
69
69
  require 'src/GUI/Application_Builder'
70
70
  require 'src/GUI/Gui_Logic'
71
+ require 'src/GUI/Search_Engine'
71
72
 
72
73
  require 'src/Network/IRC_Server'
73
74
  require 'src/Network/XDCC_Announcement_Storage'
@@ -125,6 +126,8 @@ class Main_Window < FXMainWindow
125
126
  @data = Recursive_Open_Struct.new
126
127
  @gui = Recursive_Open_Struct.new
127
128
  @logic = Gui_Logic.new(@gui, @data)
129
+ @gui.logic = @logic
130
+
128
131
 
129
132
  # load configuration
130
133
  @data.config = Configuration.new($cfg)
@@ -149,9 +152,7 @@ class Main_Window < FXMainWindow
149
152
  Application_Builder.new(self, @gui, @data, @logic)
150
153
 
151
154
  # TODO start
152
- #sleep 1
153
- #just_testing
154
- @logic.connect_to_saved_servers
155
+ @logic.connect_to_saved_servers
155
156
  end
156
157
 
157
158
  # Automatically called when the Fox application is created
@@ -190,18 +191,17 @@ class Main_Window < FXMainWindow
190
191
  @data.ann_storage.connect_to_events(XDCC_Announcement_Storage::ON_ANNOUNCEMENT_NEW, @logic)
191
192
  @data.ann_storage.connect_to_events(XDCC_Announcement_Storage::ON_ANNOUNCEMENT_LOST, @logic)
192
193
  @data.download_handlers = Hash.new
193
- end
194
-
195
-
194
+ end
196
195
 
197
196
  # debugging stuff
198
197
  def just_testing
199
198
  icons = [$cfg.icons.packet, $cfg.icons.free_slots, $cfg.icons.slots_unknown]
200
- 50000.times do |i|
199
+ 5000.times do |i|
201
200
  # set slot representing icon
202
201
  icon = icons[rand(3)]
203
202
  # create an unconnected item
204
- item = Packet_Item.new(nil, icon, "bot-#{rand(1e3)}", "#{rand(1e10).to_s(36)}", rand(100).to_s + ["M","K","G"][rand(3)])
203
+ name = rand(1e10).to_s(36).upcase + " " + rand(1e10).to_s(36)
204
+ item = Packet_Item.new(nil, icon, "bot-#{rand(1e3)}", name, rand(100).to_s + ["M","K","G"][rand(3)])
205
205
  @data.allpack_to_item[i] = item
206
206
  # item needs to be added to a list, before calling match()
207
207
  item.parent = @gui.packet_list
@@ -217,6 +217,50 @@ class Main_Window < FXMainWindow
217
217
  #@gui.packet_list.on_cmd_header(2)
218
218
  #@gui.packet_list.sortItems
219
219
  end
220
+
221
+ # stress testing
222
+ def stress_test_iconlist
223
+
224
+ @added=0
225
+ @removed = 0
226
+ @size = 0
227
+ items = Array.new
228
+ 100000.times do
229
+ @data.gui_mutex.synchronize do
230
+ #add
231
+ icon = [$cfg.icons.packet, $cfg.icons.free_slots, $cfg.icons.slots_unknown][rand(3)]
232
+ 10.times do
233
+ item = Packet_Item.new(nil, icon, rand(1e10).to_s(36), rand(1e50).to_s(36), rand(1e4).to_s)
234
+ items.push item
235
+ item.parent = @gui.packet_list
236
+ item.show
237
+ app.forceRefresh
238
+ @size += 1
239
+ @added += 1
240
+ end
241
+ @gui.packet_list.sortItems
242
+ app.forceRefresh
243
+ end
244
+ @data.gui_mutex.synchronize do
245
+ # remove
246
+
247
+ rand(items.size/4).times do
248
+ break if items.empty?
249
+ pos = rand(items.size)
250
+ item = items[pos]
251
+ items[pos] = items.last
252
+ items.pop
253
+ item.parent = nil
254
+ app.forceRefresh
255
+ @removed += 1
256
+ @size -= 1
257
+ end
258
+ end
259
+ printf "%5d, %5d, %5d\n", @added, @removed, @size
260
+ end
261
+ puts "Yeah! You got it!!!"
262
+ exit
263
+ end
220
264
  end
221
265
 
222
266
  Thread.abort_on_exception= true
@@ -23,6 +23,19 @@
23
23
  # OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24
24
 
25
25
 
26
+ class MutexDummy
27
+ def synchronize
28
+ yield
29
+ end
30
+ end
31
+
32
+ # Lock used to synchronize item removes.
33
+ # for now, a global lock is good enough.
34
+ $fx_icon_item_remove_mutex = Mutex.new
35
+
36
+
37
+
38
+
26
39
  # An item for Packet_List. This is a convenient wrapper for the FXIconItem.
27
40
  class Packet_Item
28
41
 
@@ -37,8 +50,26 @@ class Packet_Item
37
50
  @packet_item = packet_item
38
51
  @sort_key = nil
39
52
  @reversed = 1
53
+ @is_deleted = false
40
54
  super(*args)
41
55
  end
56
+
57
+ # Sometimes draw is called AFTER the item has been removed.
58
+ # In this case: return immediately. Otherwise a Runtime Error would occur!
59
+ def draw(*args)
60
+ $fx_icon_item_remove_mutex.synchronize do
61
+ #puts "draw"
62
+ return if @is_deleted
63
+ super
64
+ end
65
+ end
66
+
67
+ # Mark item as deleted, to prevent execution of draw afterwards
68
+ # this is called from Packet_List which uses the same mutex
69
+ # as draw.
70
+ def deleted
71
+ @is_deleted = true
72
+ end
42
73
 
43
74
  # Called from sortItems, uses packet_item's comparison.
44
75
  def <=>(other)
@@ -54,6 +85,10 @@ class Packet_Item
54
85
  def data
55
86
  @packet_item.data
56
87
  end
88
+
89
+ def draw(*args)
90
+ super
91
+ end
57
92
  end
58
93
 
59
94
  # Creates a Packet_Item with newParent as the parent list, which is allowed to be nil.
@@ -168,4 +203,4 @@ class Packet_Item
168
203
  def create_item
169
204
  @item = Fox_Item.new(self, @content.join("\t"), @icon, @icon)
170
205
  end
171
- end
206
+ end
@@ -121,6 +121,53 @@ class Packet_List < FXIconList
121
121
  item
122
122
  end
123
123
 
124
+ def appendItem(*args)
125
+ $fx_icon_item_remove_mutex.synchronize do
126
+ #puts "appendItem"
127
+ super
128
+ end
129
+ end
130
+
131
+ # Before actually deleting, the item has to be marked as deleted to prevent
132
+ # drawing afterwards.
133
+ def removeItem(*args)
134
+ $fx_icon_item_remove_mutex.synchronize do
135
+ #puts "removeitem"
136
+ # at first, mark item as deleted to prevent drawing afterwards
137
+ getItem(args[0]).deleted
138
+ # do the evil delete
139
+ super
140
+ end
141
+ end
142
+
143
+ # Remove all items, but do this within the mutex to be sure everything goes ok.
144
+ def clearItems(*args)
145
+ $fx_icon_item_remove_mutex.synchronize do
146
+ #puts "clearitems"
147
+ super
148
+ end
149
+ end
150
+
151
+ # This may be called when the item is currently beeing deleted.
152
+ # this method works only before or after the delete, therefore
153
+ # the mutex is necessary.
154
+ def getContentWidth(*args)
155
+ $fx_icon_item_remove_mutex.synchronize do
156
+ #puts "contentwidth"
157
+ super
158
+ end
159
+ end
160
+
161
+ # This may be called when the item is currently beeing deleted.
162
+ # this method works only before or after the delete, therefore
163
+ # the mutex is necessary.
164
+ def getContentHeight(*args)
165
+ $fx_icon_item_remove_mutex.synchronize do
166
+ #puts "contentheight"
167
+ super
168
+ end
169
+ end
170
+
124
171
  # Removes all items from the list.
125
172
  def clear
126
173
  @items.each { |item| item.clear }
@@ -141,5 +188,3 @@ class Packet_List < FXIconList
141
188
  @conversions[header_item_index]
142
189
  end
143
190
  end
144
-
145
-
@@ -0,0 +1,187 @@
1
+ # Copyright (c) 2005 Martin Ankerl
2
+ # All rights reserved.
3
+ #
4
+ # Redistribution and use in source and binary forms, with or without modification,
5
+ # are permitted provided that the following conditions are met:
6
+ #
7
+ # * Redistributions of source code must retain the above copyright notice, this list
8
+ # of conditions and the following disclaimer.
9
+ # * Redistributions in binary form must reproduce the above copyright notice, this list
10
+ # of conditions and the following disclaimer in the documentation and/or other materials
11
+ # provided with the distribution.
12
+ # * Neither the name of Christoph Heindl and Martin Ankerl nor the names of its contributors
13
+ # may be used to endorse or promote products derived from this software without specific
14
+ # prior written permission.
15
+ #
16
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
17
+ # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
18
+ # AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
19
+ # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21
+ # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
22
+ # IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
23
+ # OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24
+
25
+ class Search_Engine
26
+ def initialize(gui, data)
27
+ @gui = gui
28
+ @data = data
29
+ end
30
+
31
+ # Executed whenever a search criteria changes to update the packet list.
32
+ def on_search
33
+ # restart current search
34
+ @end_time = Time.now + 0.5
35
+ @restart_search = true
36
+ @gui.search_label.enabled = false
37
+ return if @search_thread && @search_thread.status
38
+
39
+ @search_thread = Thread.new(@search_thread) do
40
+ begin
41
+ @gui.search_label.enabled = false
42
+ # wait untill deadline
43
+ while (t = (@end_time - Time.now)) > 0
44
+ sleep(t)
45
+ end
46
+
47
+ @data.gui_mutex.synchronize do
48
+ # the thread has to use the gui mutex inside
49
+ @restart_search = false
50
+
51
+ match_data = get_match_data
52
+
53
+ # remove all items
54
+ @gui.packet_list.dirty_clear
55
+
56
+ # add all items that match the search criteria
57
+ sort_deadline = Time.now
58
+ status_text_deadline = Time.now
59
+ @data.allpack_to_item.each_value do |item|
60
+ #item.parent = @gui.packet_list if match?(item, match_data)
61
+ if match?(item, match_data)
62
+ item.show
63
+
64
+ # take only about 10% of the cpu to sort items.
65
+ # with few items this results to very fast sorts,
66
+ # with many items this leads to fast updates.
67
+ if (sort_deadline < Time.now)
68
+ before = Time.now
69
+ @gui.packet_list.sortItems
70
+ after = Time.now
71
+ sort_deadline = after + (after-before) *10
72
+ end
73
+
74
+ # update every 0.1 second
75
+ if (status_text_deadline < Time.now)
76
+ update_search_status_text
77
+ status_text_deadline = Time.now + 0.1
78
+ end
79
+ end
80
+ break if @restart_search
81
+ end
82
+ update_search_status_text
83
+ @gui.packet_list.sortItems
84
+ @gui.search_label.enabled = true
85
+
86
+ end # synchronize
87
+ end while @restart_search# || match_data != @gui.search_field.text.downcase.split
88
+ end #thread.new
89
+ end
90
+
91
+ def get_match_data
92
+ str_to_match_data(@gui.search_field.text)
93
+ end
94
+
95
+ # Converts a string into a match_data representation.
96
+ def str_to_match_data(str, index=0)
97
+ words = [ ]
98
+ exclude = [ ]
99
+ min = nil
100
+ max = nil
101
+ is_exclude = false
102
+
103
+ while str[index]
104
+ case str[index]
105
+ when ?", ?'
106
+ word, index = get_word(str, index+1, str[index])
107
+ unless word.empty?
108
+ if is_exclude
109
+ exclude.push word
110
+ is_exclude = false
111
+ else
112
+ words.push word
113
+ end
114
+ end
115
+
116
+ when 32 # space
117
+ is_exclude = false
118
+
119
+ when ?>
120
+ min, index = get_word(str, index+1)
121
+ min = @gui.logic.size_to_nr(min)
122
+
123
+ when ?<
124
+ max, index = get_word(str, index+1)
125
+ max = @gui.logic.size_to_nr(max)
126
+
127
+ when ?-
128
+ is_exclude = true
129
+
130
+ else
131
+ word, index = get_word(str, index)
132
+ if is_exclude
133
+ exclude.push word
134
+ is_exclude = false
135
+ else
136
+ words.push word
137
+ end
138
+ end
139
+
140
+ index += 1
141
+ end
142
+ [words, exclude, min, max]
143
+ end
144
+
145
+ def get_word(str, index, delim=32) # 32==space
146
+ word = ""
147
+ c = str[index]
148
+ while (c && c != delim)
149
+ word += c.chr
150
+ index += 1
151
+ c = str[index]
152
+ end
153
+ [word, index]
154
+ end
155
+
156
+ # Update the text for the number of displayed packs.
157
+ def update_search_status_text
158
+ @gui.search_status_label.text = " #{@gui.packet_list.numItems} #{$cfg.text.of} #{@data.allpack_to_item.size} #{$cfg.text.packs}"
159
+ end
160
+
161
+ # Find out if item is matched by current search criteria.
162
+ def match?(item, match_data)
163
+ # check icon
164
+ return false unless @data.packet_icon_to_toggle_btn[item.icon].toggled?
165
+
166
+ words, exclude, min, max = match_data
167
+
168
+ # check size
169
+ size = -item.sortable(2)
170
+ return false if (min && size < min) || (max && size > max)
171
+
172
+ # check text that has to be there
173
+ item_str = item.sortable(1)
174
+ words.each do |match_str|
175
+ return false unless item_str.include?(match_str)
176
+ end
177
+
178
+ # check text not allowed to be there
179
+ exclude.each do |match_str|
180
+ # the next items are not allowed to be contained in pack name
181
+ return false if item_str.include?(match_str)
182
+ end
183
+
184
+ # each check ok
185
+ true
186
+ end
187
+ end
@@ -28,7 +28,6 @@ include Fox
28
28
 
29
29
  require 'src/Utilities/Globals'
30
30
 
31
-
32
31
  # Unfortunately Talk_Back only works for email server that allow non-secure connections,
33
32
  # and therefore is useless. Let's wait until smtp supports everything requird.
34
33
  class Talk_Back < FXDialogBox
@@ -115,4 +114,4 @@ class Talk_Back < FXDialogBox
115
114
  end
116
115
  exit
117
116
  end
118
- end
117
+ end
@@ -53,4 +53,4 @@ class Toggle_Button
53
53
  @btn.state = STATE_UP
54
54
  end
55
55
  end
56
- end
56
+ end