1 | /* |
---|
2 | * This file Copyright (C) 2007 Charles Kerr <charles@rebelbase.com> |
---|
3 | * |
---|
4 | * This file is licensed by the GPL version 2. Works owned by the |
---|
5 | * Transmission project are granted a special exemption to clause 2(b) |
---|
6 | * so that the bulk of its code can remain under the MIT license. |
---|
7 | * This exemption does not extend to derived works not owned by |
---|
8 | * the Transmission project. |
---|
9 | */ |
---|
10 | |
---|
11 | #include <set> |
---|
12 | #include <map> |
---|
13 | #include <string> |
---|
14 | #include <vector> |
---|
15 | #include <iostream> |
---|
16 | #include <stdint.h> |
---|
17 | #include <wx/artprov.h> |
---|
18 | #include <wx/bitmap.h> |
---|
19 | #include <wx/defs.h> |
---|
20 | #include <wx/config.h> |
---|
21 | #include <wx/image.h> |
---|
22 | #include <wx/intl.h> |
---|
23 | #include <wx/listctrl.h> |
---|
24 | #include <wx/notebook.h> |
---|
25 | #include <wx/splitter.h> |
---|
26 | #include <wx/taskbar.h> |
---|
27 | #include <wx/toolbar.h> |
---|
28 | #include <wx/wx.h> |
---|
29 | #if wxCHECK_VERSION(2,8,0) |
---|
30 | #include <wx/aboutdlg.h> |
---|
31 | #endif |
---|
32 | |
---|
33 | extern "C" |
---|
34 | { |
---|
35 | #include <libtransmission/transmission.h> |
---|
36 | #include <libtransmission/utils.h> |
---|
37 | |
---|
38 | #include <images/exec.xpm> |
---|
39 | #include <images/fileopen.xpm> |
---|
40 | #include <images/gtk-properties.xpm> |
---|
41 | #include <images/gtk-remove.xpm> |
---|
42 | #include <images/stop.xpm> |
---|
43 | #include <images/transmission.xpm> |
---|
44 | } |
---|
45 | |
---|
46 | #include "torrent-filter.h" |
---|
47 | #include "torrent-list.h" |
---|
48 | |
---|
49 | class MyApp : public wxApp |
---|
50 | { |
---|
51 | virtual bool OnInit(); |
---|
52 | }; |
---|
53 | |
---|
54 | IMPLEMENT_APP(MyApp) |
---|
55 | |
---|
56 | namespace |
---|
57 | { |
---|
58 | tr_handle_t * handle = NULL; |
---|
59 | |
---|
60 | typedef std::vector<tr_torrent_t*> torrents_v; |
---|
61 | } |
---|
62 | |
---|
63 | class MyFrame : public wxFrame |
---|
64 | { |
---|
65 | public: |
---|
66 | MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size); |
---|
67 | virtual ~MyFrame(); |
---|
68 | |
---|
69 | public: |
---|
70 | void OnQuit( wxCommandEvent& ); |
---|
71 | void OnAbout( wxCommandEvent& ); |
---|
72 | void OnOpen( wxCommandEvent& ); |
---|
73 | void OnTimer( wxTimerEvent& ); |
---|
74 | |
---|
75 | private: |
---|
76 | void RefreshFilterCounts( ); |
---|
77 | |
---|
78 | protected: |
---|
79 | wxConfig * myConfig; |
---|
80 | wxTimer myPulseTimer; |
---|
81 | |
---|
82 | private: |
---|
83 | TorrentListCtrl * myTorrentList; |
---|
84 | wxListCtrl * myFilters; |
---|
85 | wxTaskBarIcon * myTaskBarIcon; |
---|
86 | wxIcon * myLogoIcon; |
---|
87 | wxIcon * myTrayLogo; |
---|
88 | torrents_v myTorrents; |
---|
89 | }; |
---|
90 | |
---|
91 | enum |
---|
92 | { |
---|
93 | ID_START, |
---|
94 | ID_STOP, |
---|
95 | ID_REMOVE, |
---|
96 | ID_QUIT, |
---|
97 | ID_TORRENT_INFO, |
---|
98 | ID_EDIT_PREFS, |
---|
99 | ID_SHOW_DEBUG_WINDOW, |
---|
100 | ID_ABOUT, |
---|
101 | ID_Pulse, |
---|
102 | N_IDS |
---|
103 | }; |
---|
104 | |
---|
105 | void MyFrame :: OnOpen( wxCommandEvent& event ) |
---|
106 | { |
---|
107 | const wxString key = _T("prev-directory"); |
---|
108 | wxString directory; |
---|
109 | myConfig->Read( key, &directory ); |
---|
110 | wxFileDialog * w = new wxFileDialog( this, _T("message"), |
---|
111 | directory, |
---|
112 | _T(""), /* default file */ |
---|
113 | _T("Torrent files|*.torrent"), |
---|
114 | wxOPEN|wxMULTIPLE ); |
---|
115 | |
---|
116 | if( w->ShowModal() == wxID_OK ) |
---|
117 | { |
---|
118 | wxArrayString paths; |
---|
119 | w->GetPaths( paths ); |
---|
120 | size_t nPaths = paths.GetCount(); |
---|
121 | for( size_t i=0; i<nPaths; ++i ) |
---|
122 | { |
---|
123 | const wxString& w = paths[i]; |
---|
124 | std::cerr << w.ToAscii() << std::endl; |
---|
125 | } |
---|
126 | myConfig->Write( key, w->GetDirectory() ); |
---|
127 | } |
---|
128 | |
---|
129 | delete w; |
---|
130 | } |
---|
131 | |
---|
132 | |
---|
133 | bool MyApp::OnInit() |
---|
134 | { |
---|
135 | handle = tr_init( "wx" ); |
---|
136 | |
---|
137 | MyFrame * frame = new MyFrame( _T("Xmission"), |
---|
138 | wxPoint(50,50), |
---|
139 | wxSize(900,600)); |
---|
140 | |
---|
141 | frame->Connect( wxID_OPEN, wxEVT_COMMAND_MENU_SELECTED, (wxObjectEventFunction) &MyFrame::OnOpen ); |
---|
142 | frame->Connect( wxID_ABOUT, wxEVT_COMMAND_MENU_SELECTED, (wxObjectEventFunction) &MyFrame::OnAbout ); |
---|
143 | frame->Connect( wxID_EXIT, wxEVT_COMMAND_MENU_SELECTED, (wxObjectEventFunction) &MyFrame::OnQuit ); |
---|
144 | frame->Connect( ID_Pulse, wxEVT_TIMER, (wxObjectEventFunction) &MyFrame::OnTimer ); |
---|
145 | |
---|
146 | frame->Show( true ); |
---|
147 | SetTopWindow( frame ); |
---|
148 | return true; |
---|
149 | } |
---|
150 | |
---|
151 | /*** |
---|
152 | **** |
---|
153 | ***/ |
---|
154 | |
---|
155 | namespace |
---|
156 | { |
---|
157 | int bestDecimal( double num ) { |
---|
158 | if ( num < 10 ) return 2; |
---|
159 | if ( num < 100 ) return 1; |
---|
160 | return 0; |
---|
161 | } |
---|
162 | |
---|
163 | wxString toWxStr( const char * s ) |
---|
164 | { |
---|
165 | return wxString( s, wxConvUTF8 ); |
---|
166 | } |
---|
167 | |
---|
168 | wxString getReadableSize( uint64_t size ) |
---|
169 | { |
---|
170 | int i; |
---|
171 | static const char *sizestrs[] = { "B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB" }; |
---|
172 | for ( i=0; size>>10; ++i ) size = size>>10; |
---|
173 | char buf[512]; |
---|
174 | snprintf( buf, sizeof(buf), "%.*f %s", bestDecimal(size), (double)size, sizestrs[i] ); |
---|
175 | return toWxStr( buf ); |
---|
176 | } |
---|
177 | |
---|
178 | wxString getReadableSize( float f ) |
---|
179 | { |
---|
180 | return getReadableSize( (uint64_t)f ); |
---|
181 | } |
---|
182 | |
---|
183 | wxString getReadableSpeed( float f ) |
---|
184 | { |
---|
185 | wxString xstr = getReadableSize(f); |
---|
186 | xstr += _T("/s"); |
---|
187 | return xstr; |
---|
188 | } |
---|
189 | } |
---|
190 | |
---|
191 | void |
---|
192 | MyFrame :: RefreshFilterCounts( ) |
---|
193 | { |
---|
194 | for( int i=0; i<TorrentFilter::N_FILTERS; ++i ) |
---|
195 | { |
---|
196 | wxString xstr = TorrentFilter::getFilterName( i ); |
---|
197 | const int count = TorrentFilter::CountHits( i, myTorrents ); |
---|
198 | if( count ) |
---|
199 | xstr += wxString::Format(_T(" (%d)"), count ); |
---|
200 | myFilters->SetItem( i, 0, xstr ); |
---|
201 | } |
---|
202 | } |
---|
203 | |
---|
204 | void |
---|
205 | MyFrame :: OnTimer(wxTimerEvent& event) |
---|
206 | { |
---|
207 | RefreshFilterCounts( ); |
---|
208 | |
---|
209 | myTorrentList->Refresh ( ); |
---|
210 | |
---|
211 | float dl, ul; |
---|
212 | tr_torrentRates( handle, &dl, &ul ); |
---|
213 | wxString s = _("Download: "); |
---|
214 | s += getReadableSpeed( dl ); |
---|
215 | s += _T("\n"); |
---|
216 | s +=_("Upload: "); |
---|
217 | s += getReadableSpeed( ul ); |
---|
218 | myTaskBarIcon->SetIcon( *myTrayLogo, s ); |
---|
219 | } |
---|
220 | |
---|
221 | MyFrame::~MyFrame() |
---|
222 | { |
---|
223 | delete myConfig; |
---|
224 | } |
---|
225 | |
---|
226 | MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size): |
---|
227 | wxFrame((wxFrame*)NULL,-1,title,pos,size), |
---|
228 | myConfig( new wxConfig( _T("xmission") ) ), |
---|
229 | myPulseTimer( this, ID_Pulse ) |
---|
230 | { |
---|
231 | myLogoIcon = new wxIcon( transmission_xpm ); |
---|
232 | SetIcon( *myLogoIcon ); |
---|
233 | |
---|
234 | /*#if wxCHECK_VERSION(2,8,0) |
---|
235 | transmission_logo.Rescale( 24, 24, wxIMAGE_QUALITY_HIGH ); |
---|
236 | #else |
---|
237 | transmission_logo.Rescale( 24, 24 ); |
---|
238 | #endif |
---|
239 | myTrayLogo = new wxIcon; |
---|
240 | myTrayLogo->CopyFromBitmap( wxBitmap( transmission_logo ) );*/ |
---|
241 | myTrayLogo = myLogoIcon; |
---|
242 | |
---|
243 | |
---|
244 | /** |
---|
245 | *** Menu |
---|
246 | **/ |
---|
247 | |
---|
248 | wxMenuBar *menuBar = new wxMenuBar; |
---|
249 | |
---|
250 | wxMenu * m = new wxMenu; |
---|
251 | m->Append( wxID_OPEN, _T("&Open") ); |
---|
252 | m->Append( ID_START, _T("&Start") ); |
---|
253 | m->Append( wxID_STOP, _T("Sto&p") ) ; |
---|
254 | m->Append( wxID_REFRESH, _T("Re&check") ); |
---|
255 | m->Append( wxID_REMOVE, _T("&Remove") ); |
---|
256 | m->AppendSeparator(); |
---|
257 | m->Append( wxID_NEW, _T("Create &New Torrent") ); |
---|
258 | m->AppendSeparator(); |
---|
259 | m->Append( wxID_CLOSE, _T("&Close") ); |
---|
260 | m->Append( wxID_EXIT, _T("&Exit") ); |
---|
261 | menuBar->Append( m, _T("&File") ); |
---|
262 | |
---|
263 | m = new wxMenu; |
---|
264 | m->Append( ID_TORRENT_INFO, _T("Torrent &Info") ); |
---|
265 | m->Append( wxID_PREFERENCES, _T("Edit &Preferences") ); |
---|
266 | menuBar->Append( m, _T("&Edit") ); |
---|
267 | |
---|
268 | m = new wxMenu; |
---|
269 | m->Append( ID_SHOW_DEBUG_WINDOW, _T("Show &Debug Window") ); |
---|
270 | m->AppendSeparator(); |
---|
271 | m->Append( wxID_ABOUT, _T("&About Xmission") ); |
---|
272 | menuBar->Append( m, _T("&Help") ); |
---|
273 | |
---|
274 | SetMenuBar(menuBar); |
---|
275 | |
---|
276 | /** |
---|
277 | *** Toolbar |
---|
278 | **/ |
---|
279 | |
---|
280 | wxIcon open_icon( fileopen_xpm ); |
---|
281 | wxIcon exec_icon( exec_xpm ); |
---|
282 | wxIcon stop_icon( stop_xpm ); |
---|
283 | wxIcon drop_icon( gtk_remove_xpm ); |
---|
284 | wxIcon info_icon( gtk_properties_xpm ); |
---|
285 | wxBitmap bitmap; |
---|
286 | |
---|
287 | wxToolBar* toolbar = CreateToolBar( wxNO_BORDER | wxTB_HORIZONTAL | wxTB_FLAT | wxTB_TEXT ); |
---|
288 | toolbar->SetToolBitmapSize( wxSize( 16, 16 ) ); |
---|
289 | bitmap.CopyFromIcon( open_icon ); |
---|
290 | toolbar->AddTool( wxID_OPEN, _T("Open"), bitmap ); |
---|
291 | bitmap.CopyFromIcon( exec_icon ); |
---|
292 | toolbar->AddTool( ID_START, _T("Start"), bitmap ); |
---|
293 | bitmap.CopyFromIcon( stop_icon ); |
---|
294 | toolbar->AddTool( wxID_STOP, _T("Stop"), bitmap ); |
---|
295 | bitmap.CopyFromIcon( drop_icon ); |
---|
296 | toolbar->AddTool( wxID_REMOVE, _T("Remove"), bitmap ); |
---|
297 | toolbar->AddSeparator(); |
---|
298 | bitmap.CopyFromIcon( info_icon ); |
---|
299 | toolbar->AddTool( ID_TORRENT_INFO, _("Torrent Info"), bitmap ); |
---|
300 | toolbar->Realize(); |
---|
301 | |
---|
302 | /** |
---|
303 | *** Row 1 |
---|
304 | **/ |
---|
305 | |
---|
306 | wxSplitterWindow * hsplit = new wxSplitterWindow( this ); |
---|
307 | hsplit->SetSashGravity( 0.8 ); |
---|
308 | |
---|
309 | wxPanel * row1 = new wxPanel( hsplit, wxID_ANY ); |
---|
310 | |
---|
311 | /* Filters */ |
---|
312 | |
---|
313 | myFilters = new wxListCtrl( row1, wxID_ANY, wxDefaultPosition, wxSize(120,-1), |
---|
314 | wxLC_REPORT|wxLC_SINGLE_SEL|wxLC_NO_HEADER ); |
---|
315 | myFilters->InsertColumn( wxLIST_FORMAT_LEFT, _("Filters"), wxLIST_FORMAT_LEFT, 120 ); |
---|
316 | for( int i=0; i<TorrentFilter::N_FILTERS; ++i ) |
---|
317 | myFilters->InsertItem( i, TorrentFilter::getFilterName(i) ); |
---|
318 | |
---|
319 | /* Torrent List */ |
---|
320 | |
---|
321 | myTorrentList = new TorrentListCtrl( handle, myConfig, row1 ); |
---|
322 | |
---|
323 | wxBoxSizer * boxSizer = new wxBoxSizer( wxHORIZONTAL ); |
---|
324 | boxSizer->Add( myFilters, 0, wxEXPAND|wxRIGHT, 5 ); |
---|
325 | boxSizer->Add( myTorrentList, 1, wxEXPAND, 0 ); |
---|
326 | row1->SetSizer( boxSizer ); |
---|
327 | //boxSizer->SetSizeHints( row1 ); |
---|
328 | |
---|
329 | |
---|
330 | wxNotebook * notebook = new wxNotebook( hsplit, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_TOP ); |
---|
331 | wxButton * tmp = new wxButton( notebook, wxID_ANY, _T("Hello World")); |
---|
332 | notebook->AddPage( tmp, _T("General"), false ); |
---|
333 | tmp = new wxButton( notebook, wxID_ANY, _T("Hello World")); |
---|
334 | notebook->AddPage( tmp, _T("Peers"), false ); |
---|
335 | tmp = new wxButton( notebook, wxID_ANY, _T("Hello World")); |
---|
336 | notebook->AddPage( tmp, _T("Pieces"), false ); |
---|
337 | tmp = new wxButton( notebook, wxID_ANY, _T("Hello World")); |
---|
338 | notebook->AddPage( tmp, _T("Files"), false ); |
---|
339 | tmp = new wxButton( notebook, wxID_ANY, _T("Hello World")); |
---|
340 | notebook->AddPage( tmp, _T("Logger"), false ); |
---|
341 | |
---|
342 | hsplit->SplitHorizontally( row1, notebook ); |
---|
343 | |
---|
344 | /** |
---|
345 | *** Statusbar |
---|
346 | **/ |
---|
347 | |
---|
348 | CreateStatusBar(); |
---|
349 | SetStatusText(_T("Welcome to Xmission!")); |
---|
350 | |
---|
351 | /** |
---|
352 | *** Refresh |
---|
353 | **/ |
---|
354 | |
---|
355 | myPulseTimer.Start( 1500 ); |
---|
356 | |
---|
357 | myTaskBarIcon = new wxTaskBarIcon( ); |
---|
358 | |
---|
359 | /** |
---|
360 | *** Load the torrents |
---|
361 | **/ |
---|
362 | |
---|
363 | const int flags = TR_FLAG_PAUSED; |
---|
364 | const char * destination = "/home/charles/torrents"; |
---|
365 | int count = 0; |
---|
366 | tr_torrent_t ** torrents = tr_loadTorrents ( handle, destination, flags, &count ); |
---|
367 | myTorrents.insert( myTorrents.end(), torrents, torrents+count ); |
---|
368 | myTorrentList->Add( myTorrents ); |
---|
369 | tr_free( torrents ); |
---|
370 | } |
---|
371 | |
---|
372 | void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event)) |
---|
373 | { |
---|
374 | Close( true ); |
---|
375 | } |
---|
376 | |
---|
377 | void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event)) |
---|
378 | { |
---|
379 | wxIcon ico( transmission_xpm ); |
---|
380 | |
---|
381 | #if wxCHECK_VERSION(2,8,0) |
---|
382 | wxAboutDialogInfo info; |
---|
383 | info.SetName(_T("Xmission")); |
---|
384 | info.SetVersion(_T(LONG_VERSION_STRING)); |
---|
385 | info.SetCopyright(_T("Copyright 2005-2007 The Transmission Project")); |
---|
386 | info.SetDescription(_T("A fast, lightweight bittorrent client")); |
---|
387 | info.SetWebSite( _T( "http://transmission.m0k.org/" ) ); |
---|
388 | info.SetIcon( ico ); |
---|
389 | info.AddDeveloper( _T("Josh Elsasser (Back-end; GTK+)") ); |
---|
390 | info.AddDeveloper( _T("Charles Kerr (Back-end, GTK+, wxWidgets)") ); |
---|
391 | info.AddDeveloper( _T("Mitchell Livingston (Back-end; OS X)") ); |
---|
392 | info.AddDeveloper( _T("Eric Petit (Back-end; OS X)") ); |
---|
393 | info.AddDeveloper( _T("Bryan Varner (BeOS)") ); |
---|
394 | wxAboutBox( info ); |
---|
395 | #else |
---|
396 | wxMessageBox(_T("Xmission " LONG_VERSION_STRING "\n" |
---|
397 | "Copyright 2005-2007 The Transmission Project"), |
---|
398 | _T("About Xmission"), |
---|
399 | wxOK|wxICON_INFORMATION, this); |
---|
400 | #endif |
---|
401 | |
---|
402 | } |
---|