XDCC-Fetch 1.386 → 1.409
Sign up to get free protection for your applications and to get access to all the features.
- data/XDCC-Fetch.rbw +17 -16
- data/doc/index.html +12 -1
- data/doc/xdccfetch.css +6 -1
- data/icons/locale.png +0 -0
- data/src/GUI/Application_Builder.rb +25 -9
- data/src/GUI/Context_Menu.rb +33 -9
- data/src/GUI/Download_Finished_Box.rb +13 -10
- data/src/GUI/Empty_Text_Field_Handler.rb +2 -1
- data/src/GUI/Gui_Logic.rb +36 -99
- data/src/GUI/Main_Window.rb +60 -16
- data/src/GUI/Packet_Item.rb +36 -1
- data/src/GUI/Packet_List.rb +47 -2
- data/src/GUI/Search_Engine.rb +187 -0
- data/src/GUI/Talk_Back.rb +1 -2
- data/src/GUI/Toggle_Button.rb +1 -1
- data/src/Network/DCC_File.rb +54 -44
- data/src/Network/TCP_Connection.rb +6 -5
- data/src/Network/XDCC_Download_Handler.rb +5 -1
- data/src/Translations/check_translations +5 -5
- data/src/Translations/de.rb +3 -1
- data/src/Translations/en.rb +5 -1
- data/src/Translations/pl.rb +145 -0
- data/src/Utilities/Configuration.rb +1 -1
- data/src/Utilities/Globals.rb +7 -3
- data/src/Utilities/Recursive_Open_Struct.rb +110 -11
- metadata +26 -24
- data/src/Utilities/PrettyException.rb +0 -1091
data/src/GUI/Main_Window.rb
CHANGED
@@ -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
|
-
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
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
|
-
|
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
|
-
|
199
|
+
5000.times do |i|
|
201
200
|
# set slot representing icon
|
202
201
|
icon = icons[rand(3)]
|
203
202
|
# create an unconnected item
|
204
|
-
|
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
|
data/src/GUI/Packet_Item.rb
CHANGED
@@ -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
|
data/src/GUI/Packet_List.rb
CHANGED
@@ -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
|
data/src/GUI/Talk_Back.rb
CHANGED
@@ -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
|
data/src/GUI/Toggle_Button.rb
CHANGED