Skip to content

Commit

Permalink
Add support for adding/removing/announcing trackers (#539)
Browse files Browse the repository at this point in the history
Closes #372, closes #538
  • Loading branch information
vktr committed Mar 6, 2018
1 parent 2dab458 commit eb1f9d8
Show file tree
Hide file tree
Showing 7 changed files with 273 additions and 26 deletions.
7 changes: 6 additions & 1 deletion lang/1033.json
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,11 @@
"added_on": "Added on",
"completed_on": "Completed on",
"config_error_s": "Failed to parse configuration file. Default configuration has been loaded.\n---\n%s",
"config_error_title": "Config error"
"config_error_title": "Config error",
"error_s": "Error: %s",
"add_trackers": "Add trackers",
"tracker_urls": "Tracker URLs",
"force_reannounce": "Force reannounce",
"copy_url": "Copy URL"
}
}
10 changes: 10 additions & 0 deletions src/picotorrent/torrentcontextmenu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ BEGIN_EVENT_TABLE(TorrentContextMenu, wxMenu)
EVT_MENU(ptID_COPY_INFO_HASH, TorrentContextMenu::CopyInfoHash)
EVT_MENU(ptID_OPEN_IN_EXPLORER, TorrentContextMenu::OpenInExplorer)
EVT_MENU(ptID_FORCE_RECHECK, TorrentContextMenu::ForceRecheck)
EVT_MENU(ptID_FORCE_REANNOUNCE, TorrentContextMenu::ForceReannounce)
END_EVENT_TABLE()

TorrentContextMenu::TorrentContextMenu(
Expand Down Expand Up @@ -80,6 +81,7 @@ TorrentContextMenu::TorrentContextMenu(
}

AppendSeparator();
Append(ptID_FORCE_REANNOUNCE, i18n(tr, "force_reannounce"));
Append(ptID_FORCE_RECHECK, i18n(tr, "force_recheck"));
Append(ptID_MOVE, i18n(tr, "move"));
Append(ptID_REMOVE, i18n(tr, "remove"));
Expand All @@ -106,6 +108,14 @@ void TorrentContextMenu::CopyInfoHash(wxCommandEvent& WXUNUSED(event))
}
}

void TorrentContextMenu::ForceReannounce(wxCommandEvent& WXUNUSED(event))
{
for (lt::torrent_handle& th : m_state->selected_torrents)
{
th.force_reannounce();
}
}

void TorrentContextMenu::ForceRecheck(wxCommandEvent& WXUNUSED(event))
{
for (lt::torrent_handle& th : m_state->selected_torrents)
Expand Down
4 changes: 3 additions & 1 deletion src/picotorrent/torrentcontextmenu.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,14 @@ namespace pt
ptID_QUEUE_BOTTOM,
ptID_COPY_INFO_HASH,
ptID_OPEN_IN_EXPLORER,
ptID_FORCE_RECHECK
ptID_FORCE_RECHECK,
ptID_FORCE_REANNOUNCE
};

wxDECLARE_EVENT_TABLE();

void CopyInfoHash(wxCommandEvent&);
void ForceReannounce(wxCommandEvent&);
void ForceRecheck(wxCommandEvent&);
void Move(wxCommandEvent&);
void OpenInExplorer(wxCommandEvent&);
Expand Down
168 changes: 159 additions & 9 deletions src/picotorrent/trackerspage.cpp
Original file line number Diff line number Diff line change
@@ -1,29 +1,69 @@
#include "trackerspage.hpp"

#include "trackersviewmodel.hpp"
#include "translator.hpp"

#include <libtorrent/announce_entry.hpp>
#include <libtorrent/torrent_handle.hpp>
#include <libtorrent/torrent_status.hpp>
#include <wx/clipbrd.h>
#include <wx/dataview.h>

#include "string.hpp"
#include "trackersviewmodel.hpp"
#include "translator.hpp"

namespace lt = libtorrent;
using pt::TrackersPage;

wxBEGIN_EVENT_TABLE(TrackersPage, wxPanel)
EVT_DATAVIEW_ITEM_CONTEXT_MENU(ptID_TRACKERS_LIST, TrackersPage::OnTrackersContextMenu)
EVT_MENU(ptID_ADD, TrackersPage::OnAddTrackers)
EVT_MENU(ptID_COPY_URL, TrackersPage::OnCopyUrl)
EVT_MENU(ptID_FORCE_REANNOUNCE, TrackersPage::OnForceReannounce)
EVT_MENU(ptID_REMOVE, TrackersPage::OnRemoveTrackers)
wxEND_EVENT_TABLE()

struct TrackersPage::StatusWrap
{
lt::torrent_status status;
};

TrackersPage::TrackersPage(wxWindow* parent, wxWindowID id, std::shared_ptr<pt::Translator> tr)
: wxPanel(parent, id),
m_trackersView(new wxDataViewCtrl(this, wxID_ANY)),
m_viewModel(new TrackersViewModel())
m_trackersView(new wxDataViewCtrl(this, ptID_TRACKERS_LIST, wxDefaultPosition, wxDefaultSize, wxDV_MULTIPLE)),
m_viewModel(new TrackersViewModel(tr)),
m_translator(tr),
m_wrap(std::make_unique<TrackersPage::StatusWrap>())
{
auto urlCol = m_trackersView->AppendTextColumn(i18n(tr, "url"), 0, wxDATAVIEW_CELL_INERT, 220);
m_trackersView->AppendTextColumn(i18n(tr, "fails"), 1, wxDATAVIEW_CELL_INERT, 60, wxALIGN_RIGHT);
m_trackersView->AppendTextColumn(i18n(tr, "verified"), 2, wxDATAVIEW_CELL_INERT, 60, wxALIGN_RIGHT);
m_trackersView->AppendTextColumn(i18n(tr, "next_announce"), 3, wxDATAVIEW_CELL_INERT, 80, wxALIGN_RIGHT);
auto urlCol = m_trackersView->AppendTextColumn(
i18n(tr, "url"),
TrackersViewModel::Columns::Url,
wxDATAVIEW_CELL_INERT,
220);

auto statusCol = m_trackersView->AppendTextColumn(
i18n(tr, "status"),
TrackersViewModel::Columns::Status,
wxDATAVIEW_CELL_INERT,
160);

m_trackersView->AppendTextColumn(
i18n(tr, "fails"),
TrackersViewModel::Columns::Fails,
wxDATAVIEW_CELL_INERT,
60,
wxALIGN_RIGHT);

m_trackersView->AppendTextColumn(
i18n(tr, "next_announce"),
TrackersViewModel::Columns::NextAnnounce,
wxDATAVIEW_CELL_INERT,
100,
wxALIGN_RIGHT)->SetMinWidth(100);

m_trackersView->AssociateModel(m_viewModel);
m_viewModel->DecRef();

urlCol->GetRenderer()->EnableEllipsize(wxELLIPSIZE_END);
statusCol->GetRenderer()->EnableEllipsize(wxELLIPSIZE_END);

wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL);
sizer->Add(m_trackersView, 1, wxEXPAND);
Expand All @@ -33,10 +73,120 @@ TrackersPage::TrackersPage(wxWindow* parent, wxWindowID id, std::shared_ptr<pt::

void TrackersPage::Clear()
{
m_wrap->status = lt::torrent_status();
m_viewModel->Clear();
}

void TrackersPage::Update(lt::torrent_status const& ts)
{
m_wrap->status = ts;
m_viewModel->Update(ts);
}

void TrackersPage::OnAddTrackers(wxCommandEvent&)
{
wxTextEntryDialog dlg(
m_parent,
i18n(m_translator, "add_trackers"),
i18n(m_translator, "tracker_urls"),
wxEmptyString,
wxTextEntryDialogStyle | wxTE_MULTILINE);

dlg.SetClientSize(dlg.GetClientSize().GetWidth(), 150);
// dlg.SetTextValidator(MagnetLinkValidator());

if (dlg.ShowModal() != wxID_OK)
{
return;
}

auto urls = String::Split(dlg.GetValue().ToStdString(), "\n");

for (const std::string& url : urls)
{
if (url.empty()) { continue; }
m_wrap->status.handle.add_tracker(lt::announce_entry(url));
}

m_viewModel->Update(m_wrap->status);
}

void TrackersPage::OnCopyUrl(wxCommandEvent&)
{
wxDataViewItemArray items;
m_trackersView->GetSelections(items);

std::vector<lt::announce_entry> trackers = m_wrap->status.handle.trackers();
std::stringstream ss;

for (const wxDataViewItem& item : items)
{
unsigned int row = m_viewModel->GetRow(item);
ss << trackers.at(row).url << std::endl;
}

if (wxTheClipboard->Open())
{
wxTheClipboard->SetData(new wxTextDataObject(ss.str()));
wxTheClipboard->Close();
}
}

void TrackersPage::OnForceReannounce(wxCommandEvent&)
{
wxDataViewItemArray items;
m_trackersView->GetSelections(items);

for (const wxDataViewItem& item : items)
{
unsigned int row = m_viewModel->GetRow(item);
m_wrap->status.handle.force_reannounce(0, row);
}

m_viewModel->Update(m_wrap->status);
}


void TrackersPage::OnRemoveTrackers(wxCommandEvent&)
{
wxDataViewItemArray items;
m_trackersView->GetSelections(items);

std::vector<lt::announce_entry> trackers = m_wrap->status.handle.trackers();

for (const wxDataViewItem& item : items)
{
unsigned int row = m_viewModel->GetRow(item);
trackers.erase(trackers.begin() + row);
}

m_wrap->status.handle.replace_trackers(trackers);
m_viewModel->Update(m_wrap->status);
}

void TrackersPage::OnTrackersContextMenu(wxDataViewEvent& event)
{
if (!m_wrap->status.handle.is_valid())
{
return;
}

wxDataViewItemArray items;
m_trackersView->GetSelections(items);

wxMenu trackersMenu;

if (items.Count() > 0)
{
trackersMenu.Append(ptID_COPY_URL, i18n(m_translator, "copy_url"));
trackersMenu.Append(ptID_FORCE_REANNOUNCE, i18n(m_translator, "force_reannounce"));
trackersMenu.AppendSeparator();
trackersMenu.Append(ptID_REMOVE, i18n(m_translator, "remove"));
}
else
{
trackersMenu.Append(ptID_ADD, i18n(m_translator, "add_tracker"));
}

PopupMenu(&trackersMenu);
}
23 changes: 23 additions & 0 deletions src/picotorrent/trackerspage.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <memory>

class wxDataViewCtrl;
class wxDataViewEvent;

namespace libtorrent
{
Expand All @@ -28,7 +29,29 @@ namespace pt
void Update(libtorrent::torrent_status const& ts);

private:
struct StatusWrap;

enum
{
ptID_TRACKERS_LIST = wxID_HIGHEST + 2000,
ptID_ADD,
ptID_FORCE_REANNOUNCE,
ptID_REMOVE,
ptID_COPY_URL
};

void OnAddTrackers(wxCommandEvent&);
void OnCopyUrl(wxCommandEvent&);
void OnForceReannounce(wxCommandEvent&);
void OnRemoveTrackers(wxCommandEvent&);
void OnTrackersContextMenu(wxDataViewEvent&);

wxDECLARE_EVENT_TABLE();

wxDataViewCtrl* m_trackersView;
TrackersViewModel* m_viewModel;

std::unique_ptr<StatusWrap> m_wrap;
std::shared_ptr<Translator> m_translator;
};
}

0 comments on commit eb1f9d8

Please sign in to comment.