XDCC-Fetch 1.386

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. data/COPYING +23 -0
  2. data/XDCC-Fetch.rbw +54 -0
  3. data/doc/ark.png +0 -0
  4. data/doc/connect_established.png +0 -0
  5. data/doc/index.html +300 -0
  6. data/doc/mega_ark.png +0 -0
  7. data/doc/package.png +0 -0
  8. data/doc/package_unknown.png +0 -0
  9. data/doc/shot1.png +0 -0
  10. data/doc/shot1_mini.png +0 -0
  11. data/doc/shot2.png +0 -0
  12. data/doc/shot2_mini.png +0 -0
  13. data/doc/xdccfetch.css +155 -0
  14. data/icons/ark.png +0 -0
  15. data/icons/ark_big.png +0 -0
  16. data/icons/camera_test.png +0 -0
  17. data/icons/cancel.png +0 -0
  18. data/icons/connect_creating.png +0 -0
  19. data/icons/connect_established.png +0 -0
  20. data/icons/connect_failed.png +0 -0
  21. data/icons/connect_no.png +0 -0
  22. data/icons/edit_add.png +0 -0
  23. data/icons/edit_remove.png +0 -0
  24. data/icons/exit.png +0 -0
  25. data/icons/fileclose.png +0 -0
  26. data/icons/folder_inbox.png +0 -0
  27. data/icons/idea.png +0 -0
  28. data/icons/mega_ark.png +0 -0
  29. data/icons/messagebox_critical.png +0 -0
  30. data/icons/messagebox_info.png +0 -0
  31. data/icons/messagebox_warning.png +0 -0
  32. data/icons/messagebox_warning_small.png +0 -0
  33. data/icons/package.png +0 -0
  34. data/icons/package_favourite.png +0 -0
  35. data/icons/package_unknown.png +0 -0
  36. data/src/Console/Console_Parser.rb +71 -0
  37. data/src/Console/XDCC_Pack_Match_Template.rb +29 -0
  38. data/src/Console/xdcc-fetch.rb +123 -0
  39. data/src/GUI/About_Dialog.rb +50 -0
  40. data/src/GUI/Application_Builder.rb +280 -0
  41. data/src/GUI/Context_Menu.rb +81 -0
  42. data/src/GUI/Custom_Tabs.rb +60 -0
  43. data/src/GUI/Dialog_Box.rb +116 -0
  44. data/src/GUI/Download_Finished_Box.rb +41 -0
  45. data/src/GUI/Empty_Text_Field_Handler.rb +86 -0
  46. data/src/GUI/Gui_Logic.rb +629 -0
  47. data/src/GUI/Icon_Loader.rb +58 -0
  48. data/src/GUI/Main_Window.rb +227 -0
  49. data/src/GUI/Packet_Item.rb +171 -0
  50. data/src/GUI/Packet_List.rb +145 -0
  51. data/src/GUI/Speed_Widget.rb +101 -0
  52. data/src/GUI/Talk_Back.rb +118 -0
  53. data/src/GUI/Toggle_Button.rb +56 -0
  54. data/src/Network/CTCP_Handler.rb +61 -0
  55. data/src/Network/DCC_File.rb +323 -0
  56. data/src/Network/DCC_Parser.rb +71 -0
  57. data/src/Network/IPAddr_Ext.rb +76 -0
  58. data/src/Network/IRC_Message.rb +161 -0
  59. data/src/Network/IRC_Server.rb +273 -0
  60. data/src/Network/IRC_Server_Respond_Map.rb +223 -0
  61. data/src/Network/IRC_User.rb +58 -0
  62. data/src/Network/TCP_Connection.rb +168 -0
  63. data/src/Network/XDCC_Announcement.rb +120 -0
  64. data/src/Network/XDCC_Announcement_Storage.rb +167 -0
  65. data/src/Network/XDCC_Download_Handler.rb +412 -0
  66. data/src/Network/XDCC_Pack.rb +58 -0
  67. data/src/Network/XDCC_Parser.rb +253 -0
  68. data/src/Translations/README +61 -0
  69. data/src/Translations/check_translations +83 -0
  70. data/src/Translations/de.rb +140 -0
  71. data/src/Translations/en.rb +145 -0
  72. data/src/Utilities/Configuration.rb +91 -0
  73. data/src/Utilities/Events.rb +87 -0
  74. data/src/Utilities/Globals.rb +138 -0
  75. data/src/Utilities/PrettyException.rb +1091 -0
  76. data/src/Utilities/Recursive_Open_Struct.rb +159 -0
  77. data/src/Utilities/Timer.rb +71 -0
  78. metadata +135 -0
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,71 @@
1
+ # Parses command line input and selects the appropriate action if any
2
+ class Console_Parser
3
+ def initialize
4
+ @commands = Hash.new
5
+ @commands["help"] = [0, "Prints this help", "Need help on help?",
6
+ proc do |parser, params|
7
+ puts ""
8
+ puts "COMMAND\t\t\tDESCRIPTION"
9
+ puts "------------------------------------"
10
+ parser.commands_each do |command, params|
11
+ puts "#{command}\t\t\t#{params[1] if params[1]}"
12
+ end
13
+ puts ""
14
+ end
15
+ ]
16
+ @commands["details"] = [1, "Prints detail information on the given command", nil,
17
+ proc do |parser, params|
18
+ puts ""
19
+ puts "DETAILS"
20
+ puts "------------"
21
+ details = parser.get_details(params[0])
22
+ if details
23
+ puts "#{params[0]}:\r\n#{details}"
24
+ else
25
+ puts "#{params[0]}:\r\nNo detail help available"
26
+ end
27
+ puts ""
28
+ end
29
+ ]
30
+ end
31
+
32
+ def add_command(command, action, nrOfParameters, description=nil, details=nil)
33
+ @commands[command.downcase] ||= [nrOfParameters, description, details, action]
34
+ end
35
+
36
+ def remove_command(command)
37
+ @commands.delete[command.downcase]
38
+ end
39
+
40
+ def commands_each
41
+ @commands.each_pair do |key, value| yield key, value end
42
+ end
43
+
44
+ def get_details(command)
45
+ nrOfParameters, description, details, action = @commands[command.downcase]
46
+ details
47
+ end
48
+
49
+ def call_command(str)
50
+ args = str.scan(/\S+/)
51
+ # Locate the given command
52
+ if !@commands.has_key?(args[0].downcase)
53
+ puts "Unknown command, type \"help\" for help"
54
+ else
55
+ nrOfParameters, description, details, action = @commands[args[0].downcase]
56
+ if nrOfParameters != args[1..-1].length
57
+ puts "Wrong number of arguments"
58
+ self.call_command("details #{args[0]} #{details}")
59
+ else
60
+ action.call(self, args[1..-1])
61
+ end
62
+ end
63
+ end
64
+ end
65
+
66
+ $console_parser = Console_Parser.new
67
+ $console_parser.add_command("huhu", proc do |parser, params| puts "jojo huhu hehe" end, 0, "Some help on this")
68
+ $console_parser.add_command("bla", proc do |parser, params| puts "jojo huhu hehe" end, 0, "Some help on this")
69
+ while ((str = gets.chop).downcase != "quit")
70
+ $console_parser.call_command(str)
71
+ end
@@ -0,0 +1,29 @@
1
+ class XDCC_Pack_Match_Template
2
+ attr_accessor :minsize, :maxsize, :minsize_unit, :maxsize_unit
3
+ attr_accessor :botname
4
+ attr_accessor :packname
5
+
6
+ # Initialize to default values
7
+ def initialize
8
+ @minsize = nil; @maxsize = nil; @minsize_unit = "M"; @maxsize_unit = "M"
9
+ @botname = Regexp.new("^.*$", Regexp::IGNORECASE);
10
+ @packname = Regexp.new("^.*$", Regexp::IGNORECASE);
11
+ end
12
+
13
+ def match(pack)
14
+ self.match_size(pack) && self.match_botname(pack) && self.match_packname(pack)
15
+ end
16
+
17
+ def match_size(pack)
18
+ true
19
+ end
20
+
21
+ def match_botname(pack)
22
+ pack.irc_user_bot.name =~ @botname
23
+ end
24
+
25
+ def match_packname(pack)
26
+ pack.name =~ @packname
27
+ end
28
+
29
+ end
@@ -0,0 +1,123 @@
1
+ require 'thread'
2
+ require 'src/Network/IRC_Server'
3
+ require 'src/Network/XDCC_Announcement_Factory'
4
+ require 'src/Network/XDCC_Announcement_Storage'
5
+ require 'src/Network/XDCC_Download_Handler'
6
+ require 'src/Console/XDCC_Pack_Match_Template'
7
+
8
+ # demo
9
+ class SomeListener
10
+ def initialize
11
+ @downloads = Hash.new
12
+ @handlers = Hash.new
13
+ @path = "/home/grip/dl/irc"
14
+ @anns = Array.new
15
+ end
16
+
17
+ def on_event(caller, eventtype, eventargs)
18
+ case eventtype
19
+ when XDCC_Announcement_Storage::ON_ANNOUNCEMENT_NEW then begin
20
+ puts ""
21
+ puts eventargs[0].to_s
22
+ @anns.push(eventargs[0])
23
+ end
24
+
25
+ when XDCC_Download_Handler::ON_SHUTDOWN then begin
26
+ @handlers[caller].puts("Handler is shutting down")
27
+ @handlers[caller].close
28
+ end
29
+
30
+ when XDCC_Download_Handler::ON_PACK_REQUESTED then begin
31
+ @handlers[caller].puts("Requesting pack #{eventargs[0].name}")
32
+ end
33
+
34
+ when XDCC_Download_Handler::ON_QUEUED_LOCALLY then begin
35
+ @handlers[caller].puts("Pack #{eventargs[0].name} has been locally queued in position #{eventargs[1]} of #{eventargs[2]}")
36
+ end
37
+
38
+ when XDCC_Download_Handler::ON_QUEUED_REMOTELY then begin
39
+ @handlers[caller].puts("Pack #{eventargs[0].name} has been remotely queued in position #{eventargs[1]} of #{!eventargs[2] ? "??" : eventargs[2]}")
40
+ end
41
+
42
+ when XDCC_Download_Handler::ON_DOWNLOAD_STARTED then begin
43
+ @handlers[caller].puts("Downloading pack #{eventargs[0].name}")
44
+ end
45
+
46
+ when XDCC_Download_Handler::ON_DOWNLOAD_FINISHED then begin
47
+ @handlers[caller].puts("Finished downloading pack #{eventargs[0].name}")
48
+ end
49
+
50
+ when XDCC_Download_Handler::ON_DOWNLOAD_FAILED then begin
51
+ @handlers[caller].puts("Failed to downloading pack #{eventargs[0].name} because of #{eventargs[1]}")
52
+ end
53
+
54
+ when XDCC_Download_Handler::ON_DOWNLOAD_PROGRESS then begin
55
+ @handlers[caller].puts("Pack #{eventargs[0].name} #{eventargs[1]}% #{eventargs[2]}bytes #{eventargs[3]}kb")
56
+ end
57
+ end
58
+ end
59
+
60
+ def match_template(template)
61
+ handler = nil
62
+ logfilename = ""
63
+ @anns.each do |ann|
64
+ ann.packs.each do |pack|
65
+ if (template.match(pack))
66
+ puts "New download spotted: #{pack.name}"
67
+ logfilename = "#{@path}/#{pack.irc_user_bot.name}.log"
68
+ # Check if there is already a downloader for the bot
69
+ if !@downloads.key?(pack.irc_user_bot)
70
+ handler = XDCC_Download_Handler.new(pack.irc_user_bot)
71
+ @downloads[pack.irc_user_bot] = handler
72
+ @handlers[handler] = File.new(logfilename, File::CREAT | File::APPEND | File::WRONLY)
73
+ @handlers[handler].sync = true
74
+ puts "Writing log to #{logfilename}"
75
+ handler.connect_to_events(XDCC_Download_Handler::ON_ALL_EVENTS, self)
76
+ else
77
+ handler = @downloads[pack.irc_user_bot]
78
+ puts "Appending log to #{logfilename}"
79
+ end
80
+ # Add pack to handler
81
+ handler.add_pack(pack, @path)
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
87
+
88
+ # Main ###############################################
89
+ Thread.abort_on_exception = true
90
+
91
+ #s = IRC_Server.new
92
+ #s.connect("irc.freshirc.net", 6667, "dataxb", "wuff")
93
+ #s.join("#ocs")
94
+
95
+ s = IRC_Server.new
96
+ s.connect("192.168.0.7", 6667, "wuff", "data")
97
+ s.join("#xdcc-test")
98
+
99
+ ann_fact = XDCC_Announcement_Factory.new
100
+ ann_fact.add_irc_server(s)
101
+
102
+ l = SomeListener.new
103
+
104
+ storage = XDCC_Announcement_Storage.new(ann_fact)
105
+ storage.connect_to_events(XDCC_Announcement_Storage::ON_ANNOUNCEMENT_NEW, l)
106
+
107
+
108
+ while ((str = gets.chop) != "quit")
109
+ if str == "list"
110
+ p s.user_list
111
+ elsif str == "template"
112
+ puts "botreg:"; botreg = gets.chop
113
+ puts "packreg:"; packreg = gets.chop
114
+
115
+ t = XDCC_Pack_Match_Template.new
116
+ t.botname = Regexp.new(botreg, Regexp::IGNORECASE)
117
+ t.packname = Regexp.new(packreg, Regexp::IGNORECASE)
118
+
119
+ l.match_template(t)
120
+ else
121
+ s.send(IRC_Message.parse(str.gsub(/\\001/, "\001") +"\r\n"))
122
+ end
123
+ end
@@ -0,0 +1,50 @@
1
+ # Copyright (c) 2004, Christoph Heindl and 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
+ # Shows a nifty �ber-cool about dialog.
26
+ class About_Dialog < FXMessageBox
27
+ # Set parent
28
+ def initialize(parent)
29
+ @sep = "\n * "
30
+ text = create_text
31
+ super(parent, $cfg.app.name, text, $cfg.icons.app_mega, MBOX_OK|DECOR_TITLE|DECOR_BORDER)
32
+ end
33
+
34
+ # create the dialog boxes text
35
+ def create_text
36
+ text = $cfg.app.name + "\n"
37
+ text << "#{$cfg.text.version} #{$cfg.app.version}, #{$cfg.text.revision} #{$cfg.app.revision}\n"
38
+ text << $cfg.app.copyright + "\n\n"
39
+ text << $cfg.app.url
40
+ # credits
41
+ text << "\n\n#{$cfg.text.credits}"
42
+ text << @sep + $cfg.app.developers.sort_by { rand }.join(@sep)
43
+ # thanks
44
+ text << "\n\n#{$cfg.text.thanks}"
45
+ text << @sep + $cfg.app.thanks.sort_by { rand }.join(@sep)
46
+ text << "\n\nRuby #{RUBY_VERSION}, "
47
+ text << "FXRuby #{Fox::fxrubyversion}"
48
+ text
49
+ end
50
+ end
@@ -0,0 +1,280 @@
1
+ # Copyright (c) 2004, Christoph Heindl and 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 Application_Builder
26
+ def initialize(parent, gui, data, logic)
27
+ @gui = gui
28
+ @data = data
29
+ @parent = parent
30
+ @logic = logic
31
+ build_menu(parent)
32
+ FXVerticalFrame.new(parent , LAYOUT_FILL_X|LAYOUT_FILL_Y, 0,0,0,0, 0,0,0,0,0,0) do |base|
33
+ build_main_frame(base) do |left_frame, right_frame, bottom_frame|
34
+ build_connections(left_frame)
35
+ build_search(right_frame)
36
+ build_status(bottom_frame)
37
+ end
38
+ build_status_bar(base)
39
+ end
40
+ build_dialog_boxes(parent)
41
+ # return created stuff
42
+ @gui.close
43
+ end
44
+
45
+ # Build menu controls.
46
+ def build_menu(parent)
47
+ FXMenuBar.new(parent , LAYOUT_SIDE_TOP|LAYOUT_FILL_X) do |menu_bar|
48
+ file = Context_Menu.new(menu_bar, $cfg.text.file)
49
+ file.add($cfg.text.add_server, $cfg.icons.add) { |*args| @logic.on_add_server_click(*args) }
50
+ file.add_separator
51
+ file.add($cfg.text.quit, $cfg.icons.quit) { FXApp::instance.exit }
52
+
53
+ help = Context_Menu.new(menu_bar, $cfg.text.help)
54
+ help.add($cfg.text.about, $cfg.icons.about) { @logic.on_about_click }
55
+ end
56
+ end
57
+
58
+ # Build all dialog boxes.
59
+ def build_dialog_boxes(parent)
60
+ @gui.add_server_box = Dialog_Box.new(parent , $cfg.text.specify_server)
61
+
62
+ @gui.add_server_box.add($cfg.text.server, FRAME_SUNKEN, nil, true, $cfg.text.enter_ip_or_domain)
63
+ @gui.add_server_box.add($cfg.text.port, FRAME_SUNKEN|TEXTFIELD_INTEGER, $cfg.network.irc.default_port , true, $cfg.text.the_servers_port)
64
+ @gui.add_server_box.add($cfg.text.nickname, FRAME_SUNKEN)
65
+ @gui.add_server_box.add($cfg.text.password, TEXTFIELD_PASSWD|FRAME_SUNKEN, nil, false, nil)
66
+
67
+ @gui.join_channel_box = Dialog_Box.new(parent, $cfg.text.add_channel_dialog)
68
+ @gui.join_channel_box.add($cfg.text.channel, FRAME_SUNKEN, nil, true, $cfg.text.channel_name)
69
+ @gui.join_channel_box.add($cfg.text.password, TEXTFIELD_PASSWD|FRAME_SUNKEN, nil, false, nil)
70
+ end
71
+
72
+ # Build overall frame layout.
73
+ def build_main_frame(parent) # :yields: left_frame, right_frame, bottom_frame
74
+ left = right = bottom = nil
75
+ # [---]
76
+ FXSplitter.new(parent, SPLITTER_TRACKING|SPLITTER_VERTICAL|SPLITTER_REVERSED|LAYOUT_FILL_X|LAYOUT_FILL_Y) do |root_splitter|
77
+ # [ | ]
78
+ FXSplitter.new(root_splitter, SPLITTER_TRACKING|SPLITTER_HORIZONTAL|LAYOUT_FILL_X|LAYOUT_FILL_Y) do |splitter|
79
+ left = FXVerticalFrame.new(splitter,
80
+ FRAME_SUNKEN|LAYOUT_FILL_X|LAYOUT_FILL_Y, 0,0,$cfg.left.width,0, 0,0,0,0,0,0)
81
+ right = FXVerticalFrame.new(splitter,
82
+ FRAME_SUNKEN|LAYOUT_FILL_X|LAYOUT_FILL_Y, 0,0,0,0, 0,0,0,0,0,0)
83
+ end
84
+ bottom = FXVerticalFrame.new(root_splitter,
85
+ LAYOUT_FILL_X, 0,0,0,$cfg.bottom.height, 0,0,0,0,0,0)
86
+ end
87
+ yield(left, right, bottom)
88
+ end
89
+
90
+ # Build the connections frame (on the left side).
91
+ def build_connections(parent)
92
+ FXLabel.new(parent, $cfg.text.connections, nil, JUSTIFY_CENTER_X|LAYOUT_FILL_X|FRAME_RAISED)
93
+ if FOXVERSION=="1.0"
94
+ @gui.connections = FXTreeList.new(parent, 20, nil, 0,
95
+ (FRAME_SUNKEN|
96
+ TREELIST_SINGLESELECT|
97
+ TREELIST_SHOWS_LINES|
98
+ TREELIST_SHOWS_BOXES|
99
+ TREELIST_ROOT_BOXES|
100
+ LAYOUT_FILL_X|
101
+ LAYOUT_FILL_Y))
102
+ else
103
+ @gui.connections = FXTreeList.new(parent, nil, 0,
104
+ (FRAME_SUNKEN|
105
+ TREELIST_SINGLESELECT|
106
+ TREELIST_SHOWS_LINES|
107
+ TREELIST_SHOWS_BOXES|
108
+ TREELIST_ROOT_BOXES|
109
+ LAYOUT_FILL_X|
110
+ LAYOUT_FILL_Y))
111
+ end
112
+
113
+ # empty area menu
114
+ menu_empty_area = Context_Menu.new(@gui.connections)
115
+ menu_empty_area.add($cfg.text.add_server, $cfg.icons.add) { |*args| @logic.on_add_server_click(*args) }
116
+
117
+ # server menu
118
+ menu_server = Context_Menu.new(@gui.connections) do |menu, sender, sel, data|
119
+ # menu.data contains the server item
120
+ # item's data is either CONNECTED, DISCONNECTED, CONNECTING
121
+ menu.load_state(@data.server_item_to_status[menu.data])
122
+ end
123
+ menu_server.add($cfg.text.add_channel, $cfg.icons.add) { |*args| @logic.on_add_channel_click(*args) }
124
+ menu_server.add_separator
125
+ menu_server.add($cfg.text.connect, $cfg.icons.connected) { |*args| @logic.on_server_connect_click(*args) }
126
+ menu_server.add($cfg.text.disconnect, $cfg.icons.disconnected) { |*args| @logic.on_server_disconnect_click(*args) }
127
+ menu_server.add($cfg.text.remove_server, $cfg.icons.remove) { |*args| @logic.on_remove_server_click(*args) }
128
+ menu_server.add_separator
129
+ menu_server.add($cfg.text.show_warning, $cfg.icons.warning) { |*args| @logic.on_show_warning(*args) }
130
+ menu_server.new_state(Gui_Logic::CONNECTED, true, false, true, true, false)
131
+ menu_server.new_state(Gui_Logic::CONNECTING, true, false, false, true, false)
132
+ menu_server.new_state(Gui_Logic::DISCONNECTED, true, true, false, true, false)
133
+ menu_server.new_state(Gui_Logic::CONNECTION_FAILED, true, true, false, true, true)
134
+
135
+ # channel menu
136
+ menu_channel = Context_Menu.new(@gui.connections)
137
+ menu_channel.add($cfg.text.remove_channel, $cfg.icons.remove) { |*args| @logic.on_remove_channel_click(*args) }
138
+
139
+ @gui.connections.init_clickedItem
140
+ # which menu to show?
141
+ @gui.connections.connect(SEL_RIGHTBUTTONRELEASE) do |sender, sel, data|
142
+ #item = current_connections_item
143
+ item = @gui.connections.clickedItem
144
+ menu = nil
145
+ if !item
146
+ menu = menu_empty_area
147
+ elsif item.parent
148
+ menu = menu_channel
149
+ else
150
+ menu = menu_server
151
+ end
152
+ menu.data = item
153
+ menu.execute(sender, sel, data)
154
+ end
155
+ end
156
+
157
+ # Build search controls
158
+ def build_search(parent)
159
+ FXHorizontalFrame.new(parent, LAYOUT_FILL_X|FRAME_RAISED, 0,0,0,0, 0,0,0,0,0,0) do |search_frame|
160
+
161
+ @gui.search_label = FXLabel.new(search_frame, $cfg.text.search, nil, LAYOUT_CENTER_Y)
162
+ search = FXTextField.new(search_frame, 1, nil, 0, LAYOUT_FILL_Y|FRAME_SUNKEN|LAYOUT_FILL_X)
163
+ search.connect(SEL_CHANGED) { @logic.on_search }
164
+ @gui.search_field = Empty_Text_Field_Handler.new(search, $cfg.text.what_do_you_want_to_fetch_today)
165
+
166
+ # create toggle buttons
167
+ @gui.search_btn_free_slots = Toggle_Button.new(search_frame, $cfg.icons.free_slots , $cfg.text.free_slots, true) { @logic.on_search }
168
+ @gui.search_btn_slots_unknown = Toggle_Button.new(search_frame, $cfg.icons.slots_unknown, $cfg.text.slots_unknown, true) { @logic.on_search }
169
+ @gui.search_btn_packet = Toggle_Button.new(search_frame, $cfg.icons.packet, $cfg.text.no_free_slots, true) { @logic.on_search }
170
+
171
+ # icon -> button, required in match?()
172
+ @data.packet_icon_to_toggle_btn[$cfg.icons.free_slots] = @gui.search_btn_free_slots
173
+ @data.packet_icon_to_toggle_btn[$cfg.icons.slots_unknown] = @gui.search_btn_slots_unknown
174
+ @data.packet_icon_to_toggle_btn[$cfg.icons.packet] = @gui.search_btn_packet
175
+
176
+ @gui.search_status_label = FXLabel.new(search_frame, $cfg.text.status_label_tooltip, nil, LAYOUT_CENTER_Y)
177
+ end
178
+ @gui.packet_list = Packet_List.new(@data, parent, nil, 0, $cfg.list.opts) do |packet_list|
179
+ packet_list.add_header($cfg.text.bot, 70) { |x| x.downcase }
180
+ packet_list.add_header($cfg.text.name, 250) { |x| x.downcase }
181
+ packet_list.add_header($cfg.text.size, 70) { |x| -@logic.size_to_nr(x) }
182
+ end
183
+ @gui.packet_list.on_cmd_header(1)
184
+
185
+ menu_packet_list = Context_Menu.new(@gui.packet_list) do |menu, sender, sel, data|
186
+ menu.load_state(menu.data != nil)
187
+ end
188
+
189
+ menu_packet_list.add($cfg.text.download, $cfg.icons.add) { |*args| @logic.on_download_click(*args) }
190
+ menu_packet_list.new_state(true, true)
191
+ menu_packet_list.new_state(false, false)
192
+ @gui.packet_list.connect(SEL_RIGHTBUTTONRELEASE) do |sender, sel, data|
193
+ menu_packet_list.data = @logic.current_item(@gui.packet_list)
194
+ menu_packet_list.execute(sender, sel, data)
195
+ end
196
+ @gui.packet_list.connect(SEL_DOUBLECLICKED) do |sender, sel, data|
197
+ menu_packet_list.data = @logic.current_item(@gui.packet_list)
198
+ @logic.on_download_click(menu_packet_list, sender, sel, data)
199
+ end
200
+ end
201
+
202
+ # Build status controls (bottom frame).
203
+ def build_status(parent)
204
+ # active list
205
+ active_btn = completed_btn = error_btn = nil
206
+ FXHorizontalFrame.new(parent, LAYOUT_FILL_X, 0,0,0,0, 0,0,0,0,0,0) do |selection_frame|
207
+ active_btn = FXButton.new(selection_frame, $cfg.text.active, $cfg.icons.active, nil, 0, ICON_BEFORE_TEXT|FRAME_RAISED|LAYOUT_FILL_X)
208
+ completed_btn = FXButton.new(selection_frame, $cfg.text.completed, $cfg.icons.completed, nil, 0, ICON_BEFORE_TEXT|FRAME_RAISED|LAYOUT_FILL_X)
209
+ error_btn = FXButton.new(selection_frame, $cfg.text.error, $cfg.icons.error, nil, 0, ICON_BEFORE_TEXT|FRAME_RAISED|LAYOUT_FILL_X)
210
+ end
211
+ @gui.active_list = Packet_List.new(@data, parent, nil, 0, $cfg.list.opts) do |active_list|
212
+ active_list.add_header($cfg.text.bot, 70) { |x| x.downcase }
213
+ active_list.add_header($cfg.text.name, 250) { |x| x.downcase }
214
+ active_list.add_header($cfg.text.size, 70) { |x| -@logic.size_to_nr(x) }
215
+ active_list.add_header($cfg.text.status, 130) { |x| -@logic.sortable_status(x) }
216
+ active_list.add_header($cfg.text.speed, 60) { |x| x ? -x.to_f : 0.0 }
217
+ end
218
+ @gui.active_list.on_cmd_header(3)
219
+ menu_active_list = Context_Menu.new(@gui.active_list) do |menu, sender, sel, data|
220
+ menu.load_state(menu.data != nil)
221
+ end
222
+ menu_active_list.add($cfg.text.cancel, $cfg.icons.cancel) { |*args| @logic.on_cancel_download_click(*args) }
223
+ menu_active_list.new_state(true, true)
224
+ menu_active_list.new_state(false, false)
225
+ @gui.active_list.connect(SEL_RIGHTBUTTONRELEASE) do |sender, sel, data|
226
+ menu_active_list.data = @logic.current_item(@gui.active_list)
227
+ menu_active_list.execute(sender, sel, data)
228
+ end
229
+
230
+ # completed list
231
+ @gui.completed_list = Packet_List.new(@data, parent, nil, 0, $cfg.list.opts) do |completed_list|
232
+ completed_list.add_header($cfg.text.bot, 70) { |x| x.downcase }
233
+ completed_list.add_header($cfg.text.name, 250) { |x| x.downcase }
234
+ completed_list.add_header($cfg.text.size, 70) { |x| -@logic.size_to_nr(x) }
235
+ completed_list.add_header($cfg.text.checksum, 100) { |x| @logic.sortable_md5_status(x) }
236
+ end
237
+ @gui.completed_list.on_cmd_header(1)
238
+
239
+ menu_completed_list = Context_Menu.new(@gui.completed_list)
240
+ menu_completed_list.add($cfg.text.clear_list, $cfg.icons.clear) { @logic.on_clear_completed_list }
241
+ @gui.completed_list.connect(SEL_RIGHTBUTTONRELEASE) do |sender, sel, data|
242
+ menu_completed_list.data = @logic.current_item(@gui.completed_list)
243
+ menu_completed_list.execute(sender, sel, data)
244
+ end
245
+
246
+ # error list
247
+ @gui.error_list = Packet_List.new(@data, parent, nil, 0, $cfg.list.opts) do |error_list|
248
+ error_list.add_header($cfg.text.bot, 70) { |x| x.downcase }
249
+ error_list.add_header($cfg.text.name, 250) { |x| x.downcase }
250
+ error_list.add_header($cfg.text.size, 70) { |x| -@logic.size_to_nr(x) }
251
+ error_list.add_header($cfg.text.status, 100) { |x| x }
252
+ end
253
+ @gui.error_list.on_cmd_header(1)
254
+
255
+ menu_error_list = Context_Menu.new(@gui.error_list)
256
+ menu_error_list.add($cfg.text.clear_list, $cfg.icons.clear) { @logic.on_clear_error_list }
257
+ @gui.error_list.connect(SEL_RIGHTBUTTONRELEASE) do |sender, sel, data|
258
+ menu_error_list.data = @logic.current_item(@gui.error_list)
259
+ menu_error_list.execute(sender, sel, data)
260
+ end
261
+
262
+ # create beautiful "tabs"
263
+ tab_data = {
264
+ active_btn => @gui.active_list,
265
+ completed_btn => @gui.completed_list,
266
+ error_btn => @gui.error_list
267
+ }
268
+ tabs = Custom_Tabs.new(tab_data)
269
+ tabs.show(active_btn)
270
+ end
271
+
272
+ # Build the bottom status bar
273
+ def build_status_bar(parent)
274
+ @gui.status_bar = FXStatusBar.new(parent, LAYOUT_SIDE_BOTTOM|LAYOUT_FILL_X|STATUSBAR_WITH_DRAGCORNER)
275
+ @gui.speed_widget = Speed_Widget.new(@gui.status_bar, 200, $cfg.text.speed_widget_init) do |val|
276
+ sprintf("%.1fkb", val)
277
+ end
278
+ @gui.speed_widget.slowness = 0.8
279
+ end
280
+ end