passick

TRWindow.cpp

Jan 5th, 2013
79
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 17.17 KB | None | 0 0
  1. #include "TRWindow.h"
  2. #include <Button.h>
  3. #include <View.h>
  4. #include <MenuBar.h>
  5. #include <Menu.h>
  6. #include <ListView.h>
  7. #include <ListItem.h>
  8. #include <Layout.h>
  9. #include <LayoutBuilder.h>
  10. #include <GroupLayout.h>
  11. #include <ScrollView.h>
  12. #include <StringView.h>
  13. #include <MenuItem.h>  
  14. #include <String.h>
  15. #include <NodeMonitor.h>
  16. #include <Roster.h>
  17. #include <Alert.h>
  18.  
  19. #include "libPrefs/Prefs.h"
  20. #include "TRApplication.h"
  21. #include "TRTransfer.h"
  22. #include "TRInfoWindow.h"
  23.  
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26.  
  27. #include "libtransmission/transmission.h"
  28. #include "libtransmission/utils.h"
  29. #include "libtransmission/bencode.h"
  30.  
  31. enum
  32. {
  33.     M_OPEN_TORRENT = 'tope'
  34. };
  35.  
  36. #define MENU_HEIGHT 20
  37.  
  38. TRWindow::TRWindow(void)
  39.     :   BWindow(BRect(100,100,400,300), "Transmission", B_TITLED_WINDOW,
  40.                 B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS | B_QUIT_ON_WINDOW_CLOSE)
  41. {
  42.     tr_benc settings;
  43.     const char *configDir = tr_getDefaultConfigDir("Transmission");
  44.     tr_bencInitDict(&settings, 0);
  45.     tr_sessionGetDefaultSettings(&settings);
  46.    
  47.     fSession = tr_sessionInit("haiku", configDir, true, &settings);
  48.     tr_bencFree(&settings);
  49.    
  50.     fCtor = tr_ctorNew(fSession);
  51.    
  52.     BMenuBar *menuBar = new BMenuBar("menubar");
  53.     BMenu *menu = new BMenu("File");
  54.     menu->AddItem(new BMenuItem("Quit", new BMessage(B_QUIT_REQUESTED), 'Q'));
  55.     menu->AddItem(new BMenuItem("Open", new BMessage(M_OPEN_TORRENT), 'O'));
  56.     menuBar->AddItem(menu);
  57.    
  58.     fTorrentList = static_cast<TRListView*>(new BListView(Bounds(), "torrents", B_SINGLE_SELECTION_LIST));
  59.    
  60.     BStringView *cmd = new BStringView("cmd", "hey you!");
  61.    
  62.     BScrollView *scrollView = new BScrollView("scrollview", fTorrentList, B_FOLLOW_ALL, 0, true, true);
  63.    
  64.     BLayoutBuilder::Group<>(this, B_VERTICAL, 0)
  65.         .SetInsets(0, 0, 0, 0)
  66.         .Add(menuBar)
  67.         .Add(cmd)
  68.         .Add(scrollView);
  69. }
  70.  
  71. TRWindow::~TRWindow(void)
  72. {
  73.     tr_ctorFree(fCtor);
  74.     tr_sessionClose(fSession);
  75. }
  76.  
  77. void TRWindow::LoadSettings() {
  78.     if (fSession != NULL) {
  79.         Prefs prefs(TRANSMISSION_SETTINGS);
  80.        
  81.         int32 bindPort;
  82.         if (prefs.FindInt32("transmission.bindPort", &bindPort) != B_OK) {
  83.             bindPort = atoi(PORT);
  84.             prefs.SetInt32("transmission.bindPort", bindPort);
  85.         }
  86.         //tr_setBindPort(fSession, (int)bindPort);
  87.        
  88.         //---------------------------------------------------------------------
  89.         int32 totalUploadLimit;
  90.         if (prefs.FindInt32("transmission.totalUploadLimit", &totalUploadLimit) != B_OK){
  91.             totalUploadLimit = atoi(TOTALUPLOADLIMIT);
  92.             prefs.SetInt32("transmission.totalUploadLimit", totalUploadLimit);         
  93.         }
  94.        
  95.         //-------------------------------------------------------------------------
  96.         int32 totalDownloadLimit;
  97.         if (prefs.FindInt32("transmission.totalDownloadLimit", &totalDownloadLimit) != B_OK){
  98.             totalDownloadLimit = atoi(TOTALDOWNLOADLIMIT);
  99.             prefs.SetInt32("transmission.totalDownloadLimit", totalDownloadLimit);         
  100.         }
  101.        
  102.         tr_sessionSetSpeedLimit_KBps(fSession, TR_DOWN, (int)totalDownloadLimit);
  103.         tr_sessionSetSpeedLimit_KBps(fSession, TR_UP, (int)totalUploadLimit);
  104.     }
  105. }
  106.  
  107.  
  108. /**
  109.  * Rescans the active Torrents folder, and will add all the torrents there to the
  110.  * engine. Called during initial Application Start & Stop.
  111.  */
  112. void TRWindow::RescanTorrents() {
  113.     if (Lock()) {
  114.         TRApplication *app = dynamic_cast<TRApplication*>(be_app);
  115.         BEntry *torrentEntry = new BEntry();
  116.         status_t err;
  117.        
  118.         if (app->TorrentDir()->InitCheck() == B_OK) {
  119.             err = app->TorrentDir()->Rewind();
  120.             while (err == B_OK) {
  121.                 err = app->TorrentDir()->GetNextEntry(torrentEntry, true);
  122.                 if (err != B_ENTRY_NOT_FOUND) {
  123.                     AddEntry(torrentEntry);
  124.                 }
  125.             }
  126.         }
  127.         delete torrentEntry;
  128.         Unlock();
  129.     }
  130. }
  131.  
  132.  
  133. /**
  134.  * Adds the file specified by *torrent to the Transmission engine.
  135.  * Then adds a new TRTransfer item in the fTorrentList.
  136.  * This item holds cached information about the torrent entry and node.
  137.  * These TRTransmission items are _NOT_ guaranteed to render the entry
  138.  * they were created from.
  139.  */
  140. void TRWindow::AddEntry(BEntry *torrent) {
  141.     node_ref node;
  142.     if (torrent->GetNodeRef(&node) == B_OK) {
  143.         if (watch_node(&node, B_WATCH_NAME, this) == B_OK) {
  144.             BPath path;
  145.             torrent->GetPath(&path);
  146.            
  147.             // Try adding the torrent to the engine.
  148.             int error;
  149.             tr_ctorSetMetainfoFromFile(fCtor, path.Path());
  150.             tr_torrent *nTorrent = tr_torrentNew(fCtor, &error);
  151.             if (nTorrent != NULL && Lock()) { // Success. Add the TRTorrent item.
  152.                 fTorrentList->AddItem(new TRTransfer(path.Path(), node, nTorrent));
  153.                
  154.                 bool autoStart = true;
  155.                
  156.                 // Decide if we should auto-start this torrent or not.
  157.                 BString prefName("download.");
  158.                 prefName << path.Path() << ".running";
  159.                
  160.                 Prefs *prefs = new Prefs(TRANSMISSION_SETTINGS);
  161.                 if (prefs->FindBool(prefName.String(), &autoStart) != B_OK) {
  162.                     autoStart = true;
  163.                 }
  164.                 delete prefs;
  165.                
  166.                 if (autoStart) {
  167.                     // Start the newly added torrent.
  168.                     worker_info *startData = (worker_info*)calloc(1, sizeof(worker_info));
  169.                     startData->window = this;
  170.                     startData->torrent = nTorrent;
  171.                     thread_id start_thread = spawn_thread(TRWindow::AsynchStartTorrent, "BirthCanal",
  172.                                                           B_NORMAL_PRIORITY, (void *)startData);
  173.                     if (!((start_thread) < B_OK)) {
  174.                         resume_thread(start_thread);
  175.                     } else { // Fallback and start the old way.
  176.                         StartTorrent(startData->torrent);
  177.                         free(startData);
  178.                     }
  179.                 }
  180.                 Unlock();
  181.             } else {
  182.                 bool duplicate = false;
  183.                 TRTransfer* tr;
  184.                 for (int32 i = 0; i < fTorrentList->CountItems(); i++) {
  185.                     tr = (TRTransfer*)fTorrentList->ItemAt(i);
  186.                     if (tr->GetCachedNodeRef() == node) {
  187.                         duplicate = true;
  188.                     }
  189.                 }
  190.                 if (!duplicate) {
  191.                     BString errmsg("An error occurred trying to read ");
  192.                     char namebuf[B_FILE_NAME_LENGTH];
  193.                     torrent->GetName(namebuf);
  194.                     errmsg << namebuf;
  195.                     errmsg << ".";
  196.                    
  197.                     BAlert *error = new BAlert("Error Opening Torrent",
  198.                            errmsg.String(),
  199.                            "Ok", NULL, NULL,
  200.                            B_WIDTH_AS_USUAL, B_WARNING_ALERT);
  201.                     error->Go();
  202.                     torrent->Remove();
  203.                 }
  204.             }
  205.         }
  206.     }
  207. }
  208.  
  209.  
  210. void TRWindow::MessageReceived(BMessage *msg) {
  211. //  msg->PrintToStream();
  212.     switch(msg->what){
  213.         case B_NODE_MONITOR:{
  214.         /*
  215.         * The only messages we receive from the node_monitor are if we need to
  216.         * stop watching the node. Basically, if it's been moved or removed we stop.
  217.         */
  218.             node_ref node;
  219.             ino_t fromDir;
  220.             ino_t toDir;
  221.             int32 opcode;
  222.        
  223.             if ((msg->FindInt32("opcode", &opcode) == B_OK) &&
  224.                 (msg->FindInt64("node", &node.node) == B_OK) &&
  225.                 (msg->FindInt32("device", &node.device) == B_OK))
  226.             {
  227.                 bool stop = (opcode == B_ENTRY_REMOVED);
  228.            
  229.                 if (stop) {
  230.                     msg->FindInt64("directory", &toDir);
  231.                 } else { // It must have moved.
  232.                     stop = ((msg->FindInt64("from directory", &fromDir) == B_OK) &&
  233.                             (msg->FindInt64("to directory", &toDir) == B_OK) &&
  234.                             (toDir != fromDir));
  235.                 }
  236.            
  237.                 if (stop) {
  238.                     watch_node(&node, B_STOP_WATCHING, this);
  239.                
  240.                     /* Find the full path from the TRTorrents. The index of the
  241.                     * TRTorrent that is caching the information IS NOT the
  242.                     * index of the torrent in the engine. These are Totally
  243.                     * decoupled, due to the way transmission is written.
  244.                     */
  245.                     remove_info *removeData = (remove_info*)calloc(1, sizeof(remove_info));
  246.                     removeData->window = this;
  247.                     TRTransfer* item;
  248.                     for (int32 i = 0; i < fTorrentList->CountItems(); i++) {
  249.                         item = (TRTransfer*)fTorrentList->ItemAt(i);
  250.                         if (item->GetCachedNodeRef() == node) {
  251.                             strcpy(removeData->path, item->GetCachedPath());
  252.                         }
  253.                     }
  254.                    
  255.                     fTorrentList->DoForEach(TRWindow::RemovePath, (void *)removeData);
  256.                     free(removeData);
  257.                 }
  258.             }      
  259.         }break;
  260.         case TR_INFO: {
  261.             GetTorrentInfo();
  262.         }break;
  263.         case TR_RESUME: {
  264.             ResumeTorrent();
  265.         }break;
  266.         case TR_PAUSE:{
  267.             PauseTorrent();
  268.         }break;
  269.         case TR_REMOVE: {
  270.             RemoveTorrent();
  271.         }break;
  272.         case B_SIMPLE_DATA:{
  273.             be_app->RefsReceived(msg);
  274.         }break;
  275.         default: {
  276.             //msg->PrintToStream();
  277.             BWindow::MessageReceived(msg);
  278.         }break;
  279.     }
  280. }
  281.  
  282. /**
  283.  * Handles QuitRequests.
  284.  * Displays a BAlert asking if the user really wants to quit if torrents are running.
  285.  * If affimative, then we'll stop all the running torrents.
  286.  */
  287. bool TRWindow::QuitRequested() {
  288.     if (stopping)
  289.         return true;
  290.  
  291.     bool quit = false;
  292.     int running;
  293.    
  294.     quit_info *quitData = (quit_info*)calloc(1, sizeof(quit_info));
  295.     quitData->running = 0;
  296.     fTorrentList->DoForEach(TRWindow::CheckQuitStatus, (void *)quitData);
  297.     running = quitData->running;
  298.     free(quitData);
  299.    
  300.     if (running > 0) {
  301.         BString quitMsg("");
  302.         quitMsg << "There's " << running << " torrent";
  303.         if (running > 1) {
  304.             quitMsg << "s";
  305.         }
  306.         quitMsg << " currently running.\n"
  307.                 << "What would you like to do?";
  308.        
  309.         BAlert *confirmQuit = new BAlert("Confirm Quit", quitMsg.String(),
  310.                                          "Cancel", "Quit", NULL,
  311.                                          B_WIDTH_AS_USUAL, B_WARNING_ALERT);
  312.         quit = (confirmQuit->Go() == 1);
  313.     } else {
  314.         quit = true;
  315.     }
  316.    
  317.     if (quit) {
  318.         Prefs *prefs = new Prefs(TRANSMISSION_SETTINGS);
  319.         prefs->SetRect("window.frame", Frame());
  320.        
  321.         BString strItem("");
  322.         for (int i = 0; i < fTorrentList->CountItems(); i++) {
  323.             strItem = "download.";
  324.             tr_torrent *torrent = (dynamic_cast<TRTransfer*>(fTorrentList->ItemAt(i)))->GetTorrent();
  325.             const tr_info *info = tr_torrentInfo(torrent);
  326.             const tr_stat *stat = tr_torrentStat(torrent);
  327.            
  328.             strItem << info->torrent << ".running";
  329.             if (stat->activity & (TR_STATUS_CHECK_WAIT | TR_STATUS_CHECK | TR_STATUS_DOWNLOAD | TR_STATUS_SEED)) {
  330.                 prefs->SetBool(strItem.String(), true);
  331.                 tr_torrentStop(torrent);
  332.             } else {
  333.                 prefs->SetBool(strItem.String(), false);
  334.             }
  335.         }
  336.         delete prefs;
  337.        
  338.         if (running > 0) {
  339.             stopping = true;
  340.             BAlert *waiting = new BAlert("Stopping Torrents", "Waiting for torrents to stop...", "Quit");
  341.             quitter = new BInvoker(new BMessage(B_QUIT_REQUESTED), BMessenger(be_app));
  342.             waiting->Go(quitter);
  343.             quit = false;
  344.         } else {
  345.             be_app->PostMessage(new BMessage(B_QUIT_REQUESTED));
  346.         }
  347.     }
  348.     return quit;
  349. }
  350.  
  351. void TRWindow::FrameResized(float, float) {
  352.     fTorrentList->Invalidate();
  353. }
  354.  
  355.  
  356. /**
  357.  * Called from the StopTorrent thread.
  358.  */
  359. void TRWindow::StopTorrent(tr_torrent *torrent) {
  360.     tr_torrentStop(torrent);
  361.    
  362.     UpdateList(fTorrentList->CurrentSelection(), true, NULL);
  363. }
  364.  
  365. BString TRWindow::GetFolder(void) {
  366.     // Read the settings.
  367.     BString folder("");
  368.     Prefs *prefs = new Prefs(TRANSMISSION_SETTINGS);
  369.     if (prefs->FindString("download.folder", &folder) != B_OK) {
  370.         prefs->SetString("download.folder", "/boot/home/Downloads");
  371.         folder << "/boot/home/Downloads";
  372.     }
  373.     delete prefs;
  374.     return folder;
  375. }
  376.  
  377. /**
  378.  * Called from StartTorrent thread.
  379.  */
  380. void TRWindow::StartTorrent(tr_torrent *torrent) {
  381.     // transmission.h comments recommend NOT to use tr_torrentSetDownloadDir
  382.     tr_torrentSetDownloadDir(torrent, GetFolder().String());
  383.     tr_torrentStart(torrent);
  384.    
  385.     if (fTorrentList->CurrentSelection() >= 0) {
  386.         UpdateList(fTorrentList->CurrentSelection(), true, NULL);
  387.     }
  388. }
  389.  
  390. /**
  391.  * Called from the be_app Pulse();
  392.  * This will update the data structures that the TRTorrents use to render,
  393.  * and invalidate the view.
  394.  */
  395. void TRWindow::UpdateList(int32 selection = -1, bool menus = true, BPopUpMenu *popUpMenu = NULL) {
  396.     if (stopping)
  397.     {
  398.         quit_info *quitData = (quit_info*)calloc(1, sizeof(quit_info));
  399.         quitData->running = 0;
  400.         fTorrentList->DoForEach(TRWindow::CheckQuitStatus, (void *)quitData);
  401.         if (quitData->running == 0)
  402.             be_app->PostMessage(new BMessage(B_QUIT_REQUESTED));
  403.         free(quitData);
  404.     }
  405.  
  406.     update_info *upData = (update_info*)calloc(1, sizeof(update_info));
  407.     upData->running = false;
  408.     upData->selected = selection;
  409.     upData->invalid = 0;
  410.    
  411.     fTorrentList->DoForEach(TRWindow::UpdateStats, (void *)upData);
  412.    
  413.     if (menus) {
  414.         KeyMenuBar()->FindItem(TR_INFO)->SetEnabled(selection >= 0);
  415.         KeyMenuBar()->FindItem(TR_RESUME)->SetEnabled(selection >= 0 && !upData->running);
  416.         KeyMenuBar()->FindItem(TR_PAUSE)->SetEnabled(selection >= 0 && upData->running);
  417.         KeyMenuBar()->FindItem(TR_REMOVE)->SetEnabled(selection >= 0 && !upData->running);
  418.     }
  419.    
  420.     if(popUpMenu != NULL)
  421.     {
  422.         popUpMenu->FindItem(TR_INFO)->SetEnabled(selection >= 0);
  423.         popUpMenu->FindItem(TR_RESUME)->SetEnabled(selection >= 0 && !upData->running);
  424.         popUpMenu->FindItem(TR_PAUSE)->SetEnabled(selection >= 0 && upData->running);
  425.         popUpMenu->FindItem(TR_REMOVE)->SetEnabled(selection >= 0 && !upData->running);    
  426.     }
  427.    
  428.     if (upData->invalid > 0 && fTorrentList->LockLooper()) {
  429.         fTorrentList->Invalidate();
  430.         fTorrentList->UnlockLooper();
  431.     }
  432.    
  433.     free(upData);
  434. }
  435.  
  436. /**
  437.  * Thread Function to stop Torrents. This can be expensive and causes the event loop to
  438.  * choke.
  439.  */
  440. int32 TRWindow::AsynchStopTorrent(void *data)
  441. {
  442.     worker_info* stopData = (worker_info*)data;
  443.     stopData->window->StopTorrent(stopData->torrent);
  444.     free(stopData);
  445.     return B_OK;
  446. }
  447. /*
  448. bool TRWindow::SetMenuItemEnabled(uint32 comman)
  449. {
  450.     uint32 comman  
  451. }
  452. */
  453. /**
  454.  * Thread Function to start Torrents. This can be expensive and causes the event loop to
  455.  * choke.
  456.  */
  457. int32 TRWindow::AsynchStartTorrent(void *data) {
  458.     worker_info* startData = (worker_info*)data;
  459.     startData->window->StartTorrent(startData->torrent);
  460.     free(startData);
  461.     return B_OK;
  462. }
  463.  
  464. /**
  465.  * Invoked by DoForEach upon the fTorrentList list. This will
  466.  * remove the item that is caching the path specified by
  467.  * path.
  468.  */
  469. bool TRWindow::RemovePath(BListItem *item, void *data) {
  470.     remove_info* removeData = (remove_info*)data;
  471.     TRTransfer *transfer = dynamic_cast<TRTransfer*>(item);
  472.    
  473.     if (strcmp(transfer->GetCachedPath(), removeData->path) == 0) {
  474.         removeData->window->fTorrentList->RemoveItem(transfer);
  475.         return true;
  476.     }
  477.     return false;
  478. }
  479.  
  480. /**
  481.  * Invoked during QuitRequested, iterates all Transfers and
  482.  * checks to see how many are running.
  483.  */
  484. bool TRWindow::CheckQuitStatus(BListItem *item, void *data) {
  485.     quit_info* quitData = (quit_info*)data;
  486.     TRTransfer *transfer = dynamic_cast<TRTransfer*>(item);
  487.    
  488.     if (transfer->IsRunning()) {
  489.         quitData->running++;
  490.     }
  491.     return false;
  492. }
  493.  
  494. /**
  495.  * Invoked during UpdateList()
  496.  */
  497. bool TRWindow::UpdateStats(BListItem *item, void *data) {
  498.     update_info* upData = (update_info*)data;
  499.     TRTransfer *transfer = dynamic_cast<TRTransfer*>(item);
  500.    
  501.     int32 index = fTorrentList->IndexOf(transfer);
  502.     if (transfer->UpdateStatus(tr_torrentStat(transfer->GetTorrent()), index % 2 == 0)) {
  503.         upData->invalid++;
  504.     }
  505.    
  506.     if (index == upData->selected) {
  507.         upData->running = transfer->IsRunning();
  508.     }
  509.    
  510.     return false;
  511. }
  512.  
  513. BPopUpMenu * TRWindow::GetTorrentMenu()
  514. {
  515.     BPopUpMenu * temp = new BPopUpMenu("Torrent");
  516.     temp->AddItem(new BMenuItem("Get Info", new BMessage(TR_INFO), 'I', B_COMMAND_KEY));
  517.     temp->FindItem(TR_INFO)->SetEnabled(false);
  518.     temp->AddSeparatorItem();
  519.     temp->AddItem(new BMenuItem("Resume", new BMessage(TR_RESUME)));
  520.     temp->AddItem(new BMenuItem("Pause", new BMessage(TR_PAUSE)));
  521.     temp->AddItem(new BMenuItem("Remove", new BMessage(TR_REMOVE)));
  522.     temp->SetTargetForItems(this);
  523.     return temp;
  524. }
  525.  
  526. void TRWindow::GetTorrentInfo()
  527. {
  528.     // Display an Info Window.
  529.     TRTransfer *transfer = dynamic_cast<TRTransfer*>(fTorrentList->ItemAt(fTorrentList->CurrentSelection()));
  530.     const tr_stat *s = tr_torrentStat(transfer->GetTorrent());
  531.     const tr_info *i = tr_torrentInfo(transfer->GetTorrent());
  532.    
  533.     TRInfoWindow *info = new TRInfoWindow(s, i, transfer->GetTorrent(), tr_torrentGetDownloadDir(transfer->GetTorrent()));
  534.     info->MoveTo(Frame().LeftTop() + BPoint(20, 25));
  535.     info->Show();
  536. }
  537.  
  538. void TRWindow::ResumeTorrent()
  539. {
  540.     worker_info *startData = (worker_info*)calloc(1, sizeof(worker_info));
  541.     startData->window = this;
  542.     startData->torrent = (dynamic_cast<TRTransfer*>(fTorrentList->ItemAt(fTorrentList->CurrentSelection())))->GetTorrent();
  543.     thread_id start_thread = spawn_thread(TRWindow::AsynchStartTorrent, "BirthCanal",B_NORMAL_PRIORITY, (void *)startData);
  544.     if (!((start_thread) < B_OK)) {
  545.         resume_thread(start_thread);
  546.     } else { // Fallback and start the old way.
  547.         StartTorrent(startData->torrent);
  548.         free(startData);
  549.     }
  550. }
  551.  
  552.  
  553. void TRWindow::PauseTorrent()
  554. {
  555.     worker_info *stopData = (worker_info*)calloc(1, sizeof(worker_info));
  556.     stopData->window = this;
  557.     stopData->torrent = (dynamic_cast<TRTransfer*>(fTorrentList->ItemAt(fTorrentList->CurrentSelection())))->GetTorrent();
  558.     thread_id stop_thread = spawn_thread(TRWindow::AsynchStopTorrent, "InUtero",
  559.                                                  B_NORMAL_PRIORITY, (void *)stopData);
  560.     if (!((stop_thread) < B_OK)) {
  561.         resume_thread(stop_thread);
  562.     } else { // Fallback and stop it the old way.
  563.         StopTorrent(stopData->torrent);
  564.         free(stopData);
  565.     }
  566. }
  567.  
  568. int RemoveFile(const char *filename)
  569. {
  570.     BEntry(filename).Remove();
  571. }
  572.  
  573. void TRWindow::RemoveTorrent()
  574. {
  575.     int32 index = fTorrentList->CurrentSelection();    
  576.     // Remove the file from the filesystem.
  577.     TRTransfer *item = (TRTransfer*)fTorrentList->RemoveItem(index);
  578.     tr_torrentRemove(item->GetTorrent(), false, RemoveFile);
  579.     delete item;       
  580.     UpdateList(fTorrentList->CurrentSelection(), true, NULL);
  581. }
Advertisement
Add Comment
Please, Sign In to add comment