* add code to refresh the torrent list, and a timer to call it.

* beautify some of the torrent list's columns
This commit is contained in:
Charles Kerr 2007-07-22 19:37:43 +00:00
parent fd22e508a8
commit 9f54536914
1 changed files with 103 additions and 28 deletions

View File

@ -46,17 +46,25 @@ public:
void OnQuit(wxCommandEvent& event); void OnQuit(wxCommandEvent& event);
void OnAbout(wxCommandEvent& event); void OnAbout(wxCommandEvent& event);
void OnOpen(wxCommandEvent& event); void OnOpen(wxCommandEvent& event);
void OnTimer(wxTimerEvent& event);
protected: protected:
wxConfig * myConfig; wxConfig * myConfig;
wxTimer myPulseTimer;
private: private:
void rebuildTorrentList(); void rebuildTorrentList();
void repopulateTorrentList (); void repopulateTorrentList ();
void refreshTorrentList ();
wxListCtrl * myTorrentList; wxListCtrl * myTorrentList;
typedef std::vector<tr_torrent_t*> torrents_t; typedef std::vector<tr_torrent_t*> torrents_t;
torrents_t myTorrents; torrents_t myTorrents;
void insertTorrent( tr_torrent_t*, const std::vector<int>& ); void refreshTorrent( tr_torrent_t*, int, const std::vector<int>& );
typedef std::map<std::string,int> str2int_t;
/** torrent hash -> the torrent's row in myTorrentList */
str2int_t myHashToRow;
}; };
enum enum
@ -69,6 +77,7 @@ enum
ID_EDIT_PREFS, ID_EDIT_PREFS,
ID_SHOW_DEBUG_WINDOW, ID_SHOW_DEBUG_WINDOW,
ID_ABOUT, ID_ABOUT,
ID_Pulse,
N_IDS N_IDS
}; };
@ -111,6 +120,7 @@ bool MyApp::OnInit()
frame->Connect( wxID_OPEN, wxEVT_COMMAND_MENU_SELECTED, (wxObjectEventFunction) &MyFrame::OnOpen ); frame->Connect( wxID_OPEN, wxEVT_COMMAND_MENU_SELECTED, (wxObjectEventFunction) &MyFrame::OnOpen );
frame->Connect( wxID_EXIT, wxEVT_COMMAND_MENU_SELECTED, (wxObjectEventFunction) &MyFrame::OnQuit ); frame->Connect( wxID_EXIT, wxEVT_COMMAND_MENU_SELECTED, (wxObjectEventFunction) &MyFrame::OnQuit );
frame->Connect( wxID_ABOUT, wxEVT_COMMAND_MENU_SELECTED, (wxObjectEventFunction) &MyFrame::OnAbout ); frame->Connect( wxID_ABOUT, wxEVT_COMMAND_MENU_SELECTED, (wxObjectEventFunction) &MyFrame::OnAbout );
frame->Connect( ID_Pulse, wxEVT_TIMER, (wxObjectEventFunction) &MyFrame::OnTimer );
frame->Show( true ); frame->Show( true );
SetTopWindow( frame ); SetTopWindow( frame );
@ -187,7 +197,7 @@ namespace
const wxString key = _T("TorrentListColumns"); const wxString key = _T("TorrentListColumns");
wxString columnStr; wxString columnStr;
if( !config->Read( key, &columnStr ) ) if( !config->Read( key, &columnStr ) )
columnStr = _T("name|#|size|done|status|seeds|peers|eta|uspeed|dspeed"); columnStr = _T("name|dspeed|uspeed|eta|peers|size|done|status|seeds");
int_v cols; int_v cols;
while( !columnStr.IsEmpty() ) while( !columnStr.IsEmpty() )
@ -245,10 +255,22 @@ namespace
/*** /***
**** ****
**** PEERS LIST
****
****
***/
/***
****
**** TORRENT LIST
****
****
***/ ***/
void void
MyFrame :: insertTorrent( tr_torrent_t * tor, MyFrame :: refreshTorrent( tr_torrent_t * tor,
int myTorrents_index,
const int_v & cols ) const int_v & cols )
{ {
int row = -1; int row = -1;
@ -258,7 +280,6 @@ MyFrame :: insertTorrent( tr_torrent_t * tor,
const tr_stat_t * s = tr_torrentStat( tor ); const tr_stat_t * s = tr_torrentStat( tor );
const tr_info_t* info = tr_torrentInfo( tor ); const tr_info_t* info = tr_torrentInfo( tor );
for( int_v::const_iterator it(cols.begin()), end(cols.end()); it!=end; ++it ) for( int_v::const_iterator it(cols.begin()), end(cols.end()); it!=end; ++it )
{ {
wxString xstr; wxString xstr;
@ -271,7 +292,7 @@ MyFrame :: insertTorrent( tr_torrent_t * tor,
break; break;
case COL_DONE: case COL_DONE:
snprintf( buf, sizeof(buf), "%%%.1f", s->percentDone ); snprintf( buf, sizeof(buf), "%d%%", (int)(s->percentDone*100.0) );
xstr = toWxStr( buf ); xstr = toWxStr( buf );
break; break;
@ -280,6 +301,11 @@ MyFrame :: insertTorrent( tr_torrent_t * tor,
break; break;
case COL_ETA: case COL_ETA:
if( (int)(s->percentDone*100) >= 100 )
xstr = wxString ();
else if( s->eta < 0 )
xstr = toWxStr( "\xE2\x88\x9E" ); /* infinity, in utf-8 */
else
xstr = toWxStr( getReadableTime( s->eta ) ); xstr = toWxStr( getReadableTime( s->eta ) );
break; break;
@ -343,59 +369,96 @@ MyFrame :: insertTorrent( tr_torrent_t * tor,
xstr = _T("Fixme"); xstr = _T("Fixme");
} }
if( row < 0 ) if( col ) {
myTorrentList->SetItem( row, col++, xstr );
}
else {
// first column... find the right row to put the info in.
// if the torrent's in the list already, update that row.
// otherwise, add a new row.
if( row < 0 ) {
str2int_t::const_iterator it = myHashToRow.find( info->hashString );
if( it != myHashToRow.end() ) {
row = it->second;
}
}
if( row >= 0 ) {
myTorrentList->SetItem( row, col++, xstr );
}
else {
row = myTorrentList->InsertItem( myTorrentList->GetItemCount(), xstr ); row = myTorrentList->InsertItem( myTorrentList->GetItemCount(), xstr );
else col = 1;
myTorrentList->SetItem( row, ++col, xstr ); myHashToRow[info->hashString] = row;
myTorrentList->SetItemData( row, myTorrents_index );
}
}
} }
} }
void
MyFrame :: refreshTorrentList ()
{
const int_v cols = getTorrentColumns( myConfig );
const int rowCount = myTorrentList->GetItemCount();
for( int row=0; row<rowCount; ++row )
{
int array_index = myTorrentList->GetItemData( row );
tr_torrent_t * tor = myTorrents[array_index];
refreshTorrent( tor, array_index, cols );
}
}
void void
MyFrame :: repopulateTorrentList () MyFrame :: repopulateTorrentList ()
{ {
std::cerr << __FILE__ << ':' << __LINE__ << " clearing all items from list" << std::endl;
myTorrentList->DeleteAllItems(); myTorrentList->DeleteAllItems();
myHashToRow.clear ();
const int_v cols = getTorrentColumns( myConfig ); const int_v cols = getTorrentColumns( myConfig );
int i = 0;
for( torrents_t::const_iterator it(myTorrents.begin()), for( torrents_t::const_iterator it(myTorrents.begin()),
end(myTorrents.end()); it!=end; ++it ) end(myTorrents.end()); it!=end; ++it )
insertTorrent( *it, cols ); refreshTorrent( *it, i++, cols );
} }
void void
MyFrame :: rebuildTorrentList() MyFrame :: rebuildTorrentList()
{ {
myTorrentList->ClearAll( ); myTorrentList->ClearAll( );
myHashToRow.clear ();
int i = 0; int i = 0;
const int_v cols = getTorrentColumns( myConfig ); const int_v cols = getTorrentColumns( myConfig );
for( int_v ::const_iterator it(cols.begin()), end(cols.end()); it!=end; ++it ) for( int_v ::const_iterator it(cols.begin()), end(cols.end()); it!=end; ++it )
{ {
int format = wxLIST_FORMAT_LEFT;
int width = -1;
wxString h; wxString h;
switch( *it ) switch( *it )
{ {
case COL_NUMBER: h = _T("#"); break; case COL_NUMBER: h = _T("#"); format = wxLIST_FORMAT_CENTRE; break;
case COL_DONE: h = _T("Done"); break; case COL_DONE: h = _T("Done"); format = wxLIST_FORMAT_RIGHT; break;
case COL_DOWNLOAD_SPEED: h = _T("Download"); break; case COL_DOWNLOAD_SPEED: h = _T("Download"); break;
case COL_ETA: h = _T("ETA"); break; case COL_ETA: h = _T("ETA"); format = wxLIST_FORMAT_RIGHT; break;
case COL_HASH: h = _T("SHA1 Hash"); break; case COL_HASH: h = _T("SHA1 Hash"); break;
case COL_NAME: h = _T("Name"); break; case COL_NAME: h = _T("Name"); width = 500; break;
case COL_PEERS: h = _T("Peers"); break; case COL_PEERS: h = _T("Peers"); format = wxLIST_FORMAT_RIGHT; break;
case COL_RATIO: h = _T("Ratio"); break; case COL_RATIO: h = _T("Ratio"); format = wxLIST_FORMAT_RIGHT; break;
case COL_RECEIVED: h = _T("Received"); break; case COL_RECEIVED: h = _T("Received"); format = wxLIST_FORMAT_RIGHT; break;
case COL_REMAINING: h = _T("Remaining"); break; case COL_REMAINING: h = _T("Remaining"); format = wxLIST_FORMAT_RIGHT; break;
case COL_SEEDS: h = _T("Seeds"); break; case COL_SEEDS: h = _T("Seeds"); format = wxLIST_FORMAT_RIGHT; break;
case COL_SENT: h = _T("Sent"); break; case COL_SENT: h = _T("Sent"); format = wxLIST_FORMAT_RIGHT; break;
case COL_SIZE: h = _T("Size"); break; case COL_SIZE: h = _T("Size"); format = wxLIST_FORMAT_RIGHT; break;
case COL_STATE: h = _T("State"); break; case COL_STATE: h = _T("State"); break;
case COL_STATUS: h = _T("Status"); break; case COL_STATUS: h = _T("Status"); break;
case COL_TOTAL: h = _T("Total"); break; case COL_TOTAL: h = _T("Total"); break;
case COL_UPLOAD_SPEED: h = _T("Upload"); break; case COL_UPLOAD_SPEED: h = _T("Upload"); format = wxLIST_FORMAT_RIGHT;break;
default: h = _T("Error"); break; default: h = _T("Error"); break;
} }
myTorrentList->InsertColumn( i++, h ); myTorrentList->InsertColumn( i++, h, format, width );
} }
repopulateTorrentList (); repopulateTorrentList ();
@ -405,6 +468,12 @@ MyFrame :: rebuildTorrentList()
**** ****
***/ ***/
void
MyFrame :: OnTimer(wxTimerEvent& event)
{
refreshTorrentList ();
}
MyFrame::~MyFrame() MyFrame::~MyFrame()
{ {
delete myConfig; delete myConfig;
@ -412,7 +481,8 @@ MyFrame::~MyFrame()
MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size): MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size):
wxFrame((wxFrame*)NULL,-1,title,pos,size), wxFrame((wxFrame*)NULL,-1,title,pos,size),
myConfig( new wxConfig( _T("xmission") ) ) myConfig( new wxConfig( _T("xmission") ) ),
myPulseTimer( this, ID_Pulse )
{ {
wxImage::AddHandler( new wxPNGHandler ); wxImage::AddHandler( new wxPNGHandler );
wxImage transmission_logo ( _T("images/transmission.png"), wxBITMAP_TYPE_PNG ); wxImage transmission_logo ( _T("images/transmission.png"), wxBITMAP_TYPE_PNG );
@ -425,7 +495,7 @@ MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size):
**/ **/
const int flags = TR_FLAG_PAUSED; const int flags = TR_FLAG_PAUSED;
const char * destination = "/tmp/asdf"; const char * destination = "/home/charles/torrents";
int count = 0; int count = 0;
tr_torrent_t ** torrents = tr_loadTorrents ( handle, destination, flags, &count ); tr_torrent_t ** torrents = tr_loadTorrents ( handle, destination, flags, &count );
myTorrents.insert( myTorrents.end(), torrents, torrents+count ); myTorrents.insert( myTorrents.end(), torrents, torrents+count );
@ -520,7 +590,6 @@ MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size):
rebuildTorrentList(); rebuildTorrentList();
row_sizer->Add( myTorrentList, wxSizerFlags().Expand() ); row_sizer->Add( myTorrentList, wxSizerFlags().Expand() );
row_sizer->AddGrowableCol( 1, 1 ); row_sizer->AddGrowableCol( 1, 1 );
repopulateTorrentList ();
wxNotebook * notebook = new wxNotebook( hsplit, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_TOP ); wxNotebook * notebook = new wxNotebook( hsplit, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_TOP );
@ -544,6 +613,12 @@ MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size):
CreateStatusBar(); CreateStatusBar();
SetStatusText(_T("Welcome to Xmission!")); SetStatusText(_T("Welcome to Xmission!"));
/**
*** Refresh
**/
myPulseTimer.Start( 1500 );
} }
void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event)) void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))