Upstream tarball 20080414
[amule.git] / src / remote-gui.net / MainWindow.cs
blob5376ee5f94113a2b92ef8ae4a8998aa07d00de37
1 //
2 // This file is part of the aMule Project.
3 //
4 // Copyright (c) 2003-2008 aMule Team ( admin@amule.org / http://www.amule.org )
5 // Copyright (c) 2003-2008 lfroen ( lfroen@gmail.com / http://www.amule.org )
6 //
7 // Any parts of this program derived from the xMule, lMule or eMule project,
8 // or contributed by third-party developers are copyrighted by their
9 // respective authors.
11 // This program is free software; you can redistribute it and/or modify
12 // it under the terms of the GNU General Public License as published by
13 // the Free Software Foundation; either version 2 of the License, or
14 // (at your option) any later version.
16 // This program is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 // GNU General Public License for more details.
20 //
21 // You should have received a copy of the GNU General Public License
22 // along with this program; if not, write to the Free Software
23 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 using System;
26 using System.Collections.Generic;
27 using System.ComponentModel;
28 using System.Data;
29 using System.Drawing;
30 using System.Text;
31 using System.Windows.Forms;
32 using System.Configuration;
34 namespace amule.net
36 public partial class MainWindow : Form
38 amuleRemote m_amuleRemote = new amuleRemote();
39 Timer m_updateTimer = null;
41 DownloadQueueContainer m_dload_info;
42 SharedFileListContainer m_shared_info;
44 amuleDownloadStatusList m_download_status_ctrl;
45 amuleSharedFilesList m_shared_list_ctrl;
47 amuleSearchControl m_search_ctrl;
48 amuleSettings m_settings = new amuleSettings();
50 public MainWindow()
52 InitializeComponent();
55 enum UpdateRequestState { Stats, MainInfo };
56 UpdateRequestState m_req_state;
58 ecProto.ecPacket GetFullInfoRequest()
60 ecProto.ecPacket req = null;
61 Control current_ctrl = panelMain.Controls[0];
62 if (current_ctrl == m_download_status_ctrl) {
63 req = m_dload_info.ReQuery();
64 } else if (current_ctrl == m_shared_list_ctrl) {
65 req = m_shared_info.ReQuery();
68 if ( req == null ) {
69 throw new Exception("unhandled GUI state");
71 return req;
74 private static void UpdateTimerProc(Object myObject,
75 EventArgs myEventArgs)
77 MainWindow w = (MainWindow)((Timer)myObject).Tag;
79 // TODO: for testing 1 request is enough
80 w.m_updateTimer.Stop();
82 ecProto.ecPacket req = null;
83 switch(w.m_req_state) {
84 case UpdateRequestState.Stats:
85 req = new ecProto.ecPacket(ECOpCodes.EC_OP_STAT_REQ);
86 w.m_req_state = UpdateRequestState.MainInfo;
87 break;
88 case UpdateRequestState.MainInfo:
89 req = w.GetFullInfoRequest();
90 w.m_req_state = UpdateRequestState.Stats;
91 break;
93 w.m_amuleRemote.SendPacket(req);
96 private void MainWindow_Load(object sender, EventArgs e)
99 // First, attempt to connect to remote core
101 ConnectDlg connectDlg = new ConnectDlg();
102 string errorMsg = null;
103 bool connect_ok = false;
104 string amuleHost = "", amulePort = "";
105 while ( !connect_ok ) {
106 if (connectDlg.ShowDialog() == DialogResult.OK) {
107 amuleHost = connectDlg.Host();
108 amulePort = connectDlg.Port();
109 string pass = connectDlg.Pass();
110 int amulePort_int = 0;
111 try {
112 amulePort_int = Convert.ToInt16(amulePort, 10);
113 }catch(Exception) {
114 MessageBox.Show("Invalid port number", "Error",
115 MessageBoxButtons.OK, MessageBoxIcon.Error);
116 continue;
118 connect_ok = m_amuleRemote.ConnectToCore(amuleHost, amulePort_int, pass, ref errorMsg);
119 if (!connect_ok) {
120 Console.WriteLine("Connect failed '{0}'", errorMsg);
121 MessageBox.Show(errorMsg, "Connection to aMule core failed",
122 MessageBoxButtons.OK, MessageBoxIcon.Stop);
124 } else {
125 Application.Exit();
126 return;
130 textLinktatus.Text = "aMule core on [" + amuleHost + ":" + amulePort + "]";
131 Text = "aMule remote control [" + amuleHost + ":" + amulePort + "]";
132 Size = m_settings.MainWindowSize;
134 m_amuleRemote.SetECHandler(new amuleMainECHanler(this));
137 // Connection OK at this point
139 m_download_status_ctrl = new amuleDownloadStatusList();
140 m_dload_info = new DownloadQueueContainer(m_download_status_ctrl);
141 m_download_status_ctrl.ItemContainer = m_dload_info;
143 m_download_status_ctrl.OnCancelItem +=
144 new DownloadStatusListEventHandler(m_download_status_ctrl_OnCancelItem);
145 m_download_status_ctrl.OnPauseItem +=
146 new DownloadStatusListEventHandler(m_download_status_ctrl_OnPauseItem);
147 m_download_status_ctrl.OnResumeItem +=
148 new DownloadStatusListEventHandler(m_download_status_ctrl_OnResumeItem);
150 m_shared_list_ctrl = new amuleSharedFilesList();
151 m_shared_info = new SharedFileListContainer(m_shared_list_ctrl);
153 m_search_ctrl = new amuleSearchControl();
155 m_updateTimer = new Timer();
156 m_updateTimer.Tag = this;
157 m_updateTimer.Tick += new EventHandler(UpdateTimerProc);
158 m_updateTimer.Interval = 1000;
159 m_updateTimer.Start();
161 // default - download list view
162 panelMain.Controls.Add(m_download_status_ctrl);
164 // for testing set needed state!
165 m_req_state = UpdateRequestState.MainInfo;
168 void m_download_status_ctrl_OnResumeItem()
170 ecProto.ecPacket cmd = new ecProto.ecPacket(ECOpCodes.EC_OP_PARTFILE_RESUME);
171 m_download_status_ctrl.SelectedItemsToCommand(cmd);
172 m_amuleRemote.SendPacket(cmd);
175 void m_download_status_ctrl_OnPauseItem()
177 ecProto.ecPacket cmd = new ecProto.ecPacket(ECOpCodes.EC_OP_PARTFILE_PAUSE);
178 m_download_status_ctrl.SelectedItemsToCommand(cmd);
179 m_amuleRemote.SendPacket(cmd);
182 void m_download_status_ctrl_OnCancelItem()
184 string msg = "Following files will be cancelled:\n";
185 foreach ( ListViewItem i in m_download_status_ctrl.SelectedItems ) {
186 msg += i.Text + "\n";
188 if ( MessageBox.Show(msg, "Cancel files", MessageBoxButtons.OKCancel,
189 MessageBoxIcon.Question) == DialogResult.OK ) {
190 ecProto.ecPacket cmd = new ecProto.ecPacket(ECOpCodes.EC_OP_PARTFILE_DELETE);
191 m_download_status_ctrl.SelectedItemsToCommand(cmd);
192 m_amuleRemote.SendPacket(cmd);
197 // Process reply for "stats"
199 delegate void StatsReplyCallback(ecProto.ecPacket packet);
200 public void StatsReplyInvoke(ecProto.ecPacket packet)
202 if ( InvokeRequired ) {
203 StatsReplyCallback d = new StatsReplyCallback(StatsReply);
204 Invoke(d, packet);
205 } else {
206 StatsReply(packet);
210 void StatsReply(ecProto.ecPacket packet)
212 ecProto.ecTag t = null;
213 t = packet.SubTag(ECTagNames.EC_TAG_STATS_DL_SPEED);
214 int dl_speed = ((ecProto.ecTagInt)t).ValueInt();
216 t = packet.SubTag(ECTagNames.EC_TAG_STATS_UL_SPEED);
217 int ul_speed = ((ecProto.ecTagInt)t).ValueInt();
218 //string server = ((ecProto.ecTagString)t).ToString();
220 ecProto.ecConnStateTag connState =
221 new ecProto.ecConnStateTag((ecProto.ecTagInt)packet.SubTag(ECTagNames.EC_TAG_CONNSTATE));
223 textBoxDownSpeed.Text = "Down:" + ValueToPrefix(dl_speed) + "/s";
224 textBoxUpSpeed.Text = "Up:" + ValueToPrefix(ul_speed) + "/s";
225 if ( connState.IsConnected() ) {
226 if (connState.IsConnectedED2K()) {
227 textLinktatus.Text = "ED2K: connected";
228 //ecProto.ecTagString server_name = (ecProto.ecTagString)server.SubTag(ECTagNames.EC_TAG_SERVER_NAME);
229 //toolStripStatusServer.Text = server_name.StringValue();
230 } else {
231 //toolStripStatusServer.Text = "";
232 if (connState.IsConnectingED2K() ) {
233 textLinktatus.Text = "ED2K: connecting ...";
234 } else {
235 textLinktatus.Text = "ED2K: disconnected";
238 if (connState.IsConnectedKademlia()) {
239 //textLinktatus.Text = "KAD: connected";
245 public void DloadQueueReply(ecProto.ecPacket packet)
247 ecProto.ecPacket reply = m_dload_info.HandlePacket(packet);
248 if ( reply != null ) {
249 m_amuleRemote.SendPacket(reply);
253 public void SharedFilesReply(ecProto.ecPacket packet)
255 ecProto.ecPacket reply = m_shared_info.HandlePacket(packet);
256 if (reply != null) {
257 m_amuleRemote.SendPacket(reply);
261 private void buttonXfer_Click(object sender, EventArgs e)
263 if ( panelMain.Controls[0] != m_download_status_ctrl ) {
264 panelMain.Controls.Clear();
265 panelMain.Controls.Add(m_download_status_ctrl);
269 private void buttonNetwork_Click(object sender, EventArgs e)
271 UpdateTimerProc(m_updateTimer, null);
274 private void buttonSearch_Click(object sender, EventArgs e)
276 if ( panelMain.Controls[0] != m_search_ctrl ) {
277 panelMain.Controls.Clear();
278 panelMain.Controls.Add(m_search_ctrl);
282 private void buttonShared_Click(object sender, EventArgs e)
284 if ( panelMain.Controls[0] != m_shared_list_ctrl ) {
285 panelMain.Controls.Clear();
286 panelMain.Controls.Add(m_shared_list_ctrl);
291 private void buttonAddLink_Click(object sender, EventArgs e)
293 AddLinkDialog dlg = new AddLinkDialog();
294 if ( dlg.ShowDialog() == DialogResult.OK ) {
295 string link = dlg.textBoxLink.Text;
296 ecProto.ecPacket cmd = new ecProto.ecPacket(ECOpCodes.EC_OP_ADD_LINK);
297 ecProto.ecTagString linktag = new ecProto.ecTagString(ECTagNames.EC_TAG_STRING, link);
298 cmd.AddSubtag(linktag);
299 m_amuleRemote.SendPacket(cmd);
303 private void buttonPrefs_Click(object sender, EventArgs e)
308 private void buttonAbout_Click(object sender, EventArgs e)
310 AboutBox dlg = new AboutBox();
311 dlg.ShowDialog();
314 private void MainWindow_FormClosed(object sender, FormClosedEventArgs e)
316 m_settings.MainWindowSize = Size;
318 m_settings.Save();
321 public string ValueToPrefix(Int64 value)
323 if ( value < 1024 ) {
324 return string.Format("{0} bytes", value);
325 } else if ( value < 1048576 ) {
326 return string.Format("{0:f} Kb", ((float)value) / 1024);
327 } else if ( value < 1073741824 ) {
328 return string.Format("{0:f} Mb", ((float)value) / 1048576);
329 } else {
330 return string.Format("{0:f} Gb", ((float)value) / 1073741824);
336 [SettingsGroupNameAttribute("Application")]
337 public class amuleSettings : ApplicationSettingsBase {
339 [UserScopedSettingAttribute()]
340 public string Host
342 get { return (string)this["Host"]; }
343 set { this["Host"] = value; }
346 [UserScopedSettingAttribute()]
347 public string Password
349 get { return (string)this["Password"]; }
350 set { this["Password"] = value; }
353 [UserScopedSetting()]
354 [DefaultSettingValueAttribute("500, 400")]
355 public Size MainWindowSize
357 get { return (Size)this["MainWindowSize"]; }
358 set { this["MainWindowSize"] = value; }
363 public class amuleMainECHanler : amuleECHandler {
364 MainWindow m_owner = null;
365 public amuleMainECHanler(MainWindow o)
367 m_owner = o;
370 public override void HandlePacket(ecProto.ecPacket packet)
372 ECOpCodes op = packet.Opcode();
373 switch(op) {
374 case ECOpCodes.EC_OP_STATS:
375 m_owner.StatsReplyInvoke(packet);
376 break;
377 case ECOpCodes.EC_OP_DLOAD_QUEUE:
378 m_owner.DloadQueueReply(packet);
379 break;
380 case ECOpCodes.EC_OP_SHARED_FILES:
381 m_owner.SharedFilesReply(packet);
382 break;
383 case ECOpCodes.EC_OP_NOOP:
384 break;
385 default:
386 throw new Exception("Unhandled EC reply");
391 public class amuleListView : ListView {
392 protected int[] m_column_index;
394 public amuleListView()
396 Dock = DockStyle.Fill;
397 View = View.Details;
398 DoubleBuffered = true;
399 FullRowSelect = true;
400 MultiSelect = true;
403 public void LoadColumns(string [] columns, int [] width)
405 int i = 0;
406 foreach (string c in columns) {
407 if ( width[i] == 0 ) {
408 continue;
410 ColumnHeader h = new ColumnHeader();
411 h.Text = c;
412 h.Width = width[i++];
413 Columns.Add(h);
417 public void CreateColumtAt(string name, int width, int index)
419 ColumnHeader h = new ColumnHeader();
420 h.Text = name;
421 h.Width = width;
422 h.Tag = index;
423 Columns.Insert(m_column_index[index], h);
425 public void RemoveColumnAt(int index)
427 Columns.RemoveAt(m_column_index[index]);
430 public void AppendItemToCtxMenu(ContextMenuStrip menu, string text,
431 object tag, bool check_state, EventHandler target)
433 ToolStripMenuItem it = new ToolStripMenuItem(text);
434 it.Click += target;
435 it.CheckState = check_state ? CheckState.Checked : CheckState.Unchecked;
436 it.Tag = tag;
437 menu.Items.Add(it);
441 public class amuleSharedFilesList : amuleListView, IContainerUI {
442 public amuleSharedFilesList()
444 string[] columns = { "File name", "Size" };
445 int[] width = { 300, 100, 100, 100 };
446 LoadColumns(columns, width);
449 #region IContainerUI Members
451 delegate void UpdateCallback();
452 void IContainerUI.MyEndUpdate()
454 if (InvokeRequired) {
455 UpdateCallback d = new UpdateCallback(EndUpdate);
456 Invoke(d);
457 } else {
458 EndUpdate();
462 void IContainerUI.MyBeginUpdate()
464 if (InvokeRequired) {
465 UpdateCallback d = new UpdateCallback(BeginUpdate);
466 Invoke(d);
467 } else {
468 BeginUpdate();
472 delegate void ItemCallback(SharedFileItem i);
474 void IContainerUI.InsertItem(object i)
476 SharedFileItem it = i as SharedFileItem;
477 if (InvokeRequired) {
478 ItemCallback d = new ItemCallback(DoInsertItem);
479 Invoke(d, it);
480 } else {
481 DoInsertItem(it);
485 void IContainerUI.UpdateItem(object i)
487 throw new Exception("The method or operation is not implemented.");
490 void DoInsertItem(SharedFileItem i)
492 ListViewItem it = new ListViewItem(i.Name);
494 it.SubItems.Add(new ListViewItem.ListViewSubItem(it, i.Size));
496 Items.Add(it);
498 i.UiItem = it;
501 void DoUpdateItem(SharedFileItem i)
503 ListViewItem it = i.UiItem as ListViewItem;
504 //Items
507 #endregion