Mercurial > minori
annotate src/gui/pages/torrents.cc @ 118:39521c47c7a3
*: another huge megacommit, SORRY
The torrents page works a lot better now
Added the edit option to the anime list right click menu
Vectorized currently playing files
Available player and extensions are now loaded at runtime
from files in (dotpath)/players.json and (dotpath)/extensions.json
These paths are not permanent and will likely be moved to
(dotpath)/recognition
...
...
...
author | Paper <mrpapersonic@gmail.com> |
---|---|
date | Tue, 07 Nov 2023 23:40:54 -0500 |
parents | 2c1b6782e1d0 |
children | d43d68408d3c |
rev | line source |
---|---|
54
466ac9870df9
add stub pages (to be implemented)
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
1 #include "gui/pages/torrents.h" |
114 | 2 #include "core/strings.h" |
3 #include "core/http.h" | |
4 #include "core/session.h" | |
5 #include "gui/widgets/text.h" | |
6 #include "track/media.h" | |
7 #include "pugixml.hpp" | |
8 #include <QVBoxLayout> | |
9 #include <QToolBar> | |
10 #include <QTreeView> | |
11 #include <QMainWindow> | |
12 #include <QByteArray> | |
13 #include <QDataStream> | |
14 #include <QThreadPool> | |
15 #include <QDebug> | |
16 #include <iostream> | |
17 #include <sstream> | |
18 #include <algorithm> | |
19 | |
118
39521c47c7a3
*: another huge megacommit, SORRY
Paper <mrpapersonic@gmail.com>
parents:
117
diff
changeset
|
20 /* This file is very, very similar to the anime list page. |
39521c47c7a3
*: another huge megacommit, SORRY
Paper <mrpapersonic@gmail.com>
parents:
117
diff
changeset
|
21 |
39521c47c7a3
*: another huge megacommit, SORRY
Paper <mrpapersonic@gmail.com>
parents:
117
diff
changeset
|
22 It differs from Taiga in that it uses tabs instead of |
39521c47c7a3
*: another huge megacommit, SORRY
Paper <mrpapersonic@gmail.com>
parents:
117
diff
changeset
|
23 those "groups", but those are custom painted and a pain in the ass to |
39521c47c7a3
*: another huge megacommit, SORRY
Paper <mrpapersonic@gmail.com>
parents:
117
diff
changeset
|
24 maintain over multiple platforms. */ |
39521c47c7a3
*: another huge megacommit, SORRY
Paper <mrpapersonic@gmail.com>
parents:
117
diff
changeset
|
25 |
114 | 26 TorrentsPageListSortFilter::TorrentsPageListSortFilter(QObject* parent) : QSortFilterProxyModel(parent) { |
27 } | |
28 | |
29 bool TorrentsPageListSortFilter::lessThan(const QModelIndex& l, const QModelIndex& r) const { | |
30 QVariant left = sourceModel()->data(l, sortRole()); | |
31 QVariant right = sourceModel()->data(r, sortRole()); | |
32 | |
33 switch (left.userType()) { | |
34 case QMetaType::Int: | |
35 case QMetaType::UInt: | |
36 case QMetaType::LongLong: | |
37 case QMetaType::ULongLong: return left.toInt() < right.toInt(); | |
38 case QMetaType::QDate: return left.toDate() < right.toDate(); | |
39 case QMetaType::QString: | |
40 default: return QString::compare(left.toString(), right.toString(), Qt::CaseInsensitive) < 0; | |
41 } | |
42 } | |
43 | |
44 /* -------------------------------------------- */ | |
45 | |
46 TorrentsPageListModel::TorrentsPageListModel(QObject* parent) : QAbstractListModel(parent) { | |
47 } | |
48 | |
49 QByteArray TorrentsPageListModel::DownloadTorrentList() { | |
116
254b1d2b7096
settings: add torrents page, make rss feed configurable
Paper <mrpapersonic@gmail.com>
parents:
114
diff
changeset
|
50 return HTTP::Get(session.config.torrents.feed_link); |
114 | 51 } |
52 | |
53 void TorrentsPageListModel::ParseTorrentList(const QByteArray& ba) { | |
54 std::istringstream stdstream(Strings::ToUtf8String(ba)); | |
55 | |
56 pugi::xml_document doc; | |
57 if (!doc.load(stdstream)) | |
58 return; // peace out | |
59 | |
60 /* my extra special dumb hack. */ | |
61 if (!rowCount(index(0))) { | |
62 beginInsertRows(QModelIndex(), 0, 0); | |
63 endInsertRows(); | |
64 } | |
65 | |
66 beginResetModel(); | |
67 | |
68 list.clear(); | |
69 /* this is just an rss parser; it should be in a separate class... */ | |
70 for (pugi::xml_node item : doc.child("rss").child("channel").children("item")) { | |
71 TorrentModelItem torrent; | |
72 torrent.SetFilename(item.child_value("title")); /* "title" == filename */ | |
73 { | |
74 /* Use Anitomy to parse the file's elements (we should *really* not be doing this this way!) */ | |
75 std::unordered_map<std::string, std::string> elements = Track::Media::GetFileElements(torrent.GetFilename()); | |
76 torrent.SetTitle(elements["title"]); | |
77 torrent.SetEpisode(Strings::RemoveLeadingChars(elements["episode"], '0')); | |
78 torrent.SetGroup(elements["group"]); | |
79 torrent.SetResolution(elements["resolution"]); | |
80 } | |
81 torrent.SetDescription(Strings::TextifySynopsis(item.child_value("description"))); | |
82 { | |
118
39521c47c7a3
*: another huge megacommit, SORRY
Paper <mrpapersonic@gmail.com>
parents:
117
diff
changeset
|
83 /* Parse description... */ |
39521c47c7a3
*: another huge megacommit, SORRY
Paper <mrpapersonic@gmail.com>
parents:
117
diff
changeset
|
84 enum class Keys { SIZE, AUTHORIZED, SUBMITTER, COMMENT }; |
39521c47c7a3
*: another huge megacommit, SORRY
Paper <mrpapersonic@gmail.com>
parents:
117
diff
changeset
|
85 |
39521c47c7a3
*: another huge megacommit, SORRY
Paper <mrpapersonic@gmail.com>
parents:
117
diff
changeset
|
86 const std::unordered_map<std::string, Keys> KeyMap = { |
39521c47c7a3
*: another huge megacommit, SORRY
Paper <mrpapersonic@gmail.com>
parents:
117
diff
changeset
|
87 {"Size", Keys::SIZE}, |
39521c47c7a3
*: another huge megacommit, SORRY
Paper <mrpapersonic@gmail.com>
parents:
117
diff
changeset
|
88 {"Authorized", Keys::AUTHORIZED}, |
39521c47c7a3
*: another huge megacommit, SORRY
Paper <mrpapersonic@gmail.com>
parents:
117
diff
changeset
|
89 {"Submitter", Keys::SUBMITTER}, |
39521c47c7a3
*: another huge megacommit, SORRY
Paper <mrpapersonic@gmail.com>
parents:
117
diff
changeset
|
90 {"Comment", Keys::COMMENT} |
39521c47c7a3
*: another huge megacommit, SORRY
Paper <mrpapersonic@gmail.com>
parents:
117
diff
changeset
|
91 }; |
39521c47c7a3
*: another huge megacommit, SORRY
Paper <mrpapersonic@gmail.com>
parents:
117
diff
changeset
|
92 |
39521c47c7a3
*: another huge megacommit, SORRY
Paper <mrpapersonic@gmail.com>
parents:
117
diff
changeset
|
93 const std::string description = Strings::TextifySynopsis(item.child_value("description")); |
39521c47c7a3
*: another huge megacommit, SORRY
Paper <mrpapersonic@gmail.com>
parents:
117
diff
changeset
|
94 |
114 | 95 /* Parse size from description */ |
118
39521c47c7a3
*: another huge megacommit, SORRY
Paper <mrpapersonic@gmail.com>
parents:
117
diff
changeset
|
96 std::istringstream descstream(description); |
114 | 97 |
98 for (std::string line; std::getline(descstream, line);) { | |
118
39521c47c7a3
*: another huge megacommit, SORRY
Paper <mrpapersonic@gmail.com>
parents:
117
diff
changeset
|
99 const size_t pos = line.find_first_of(':', 0); |
39521c47c7a3
*: another huge megacommit, SORRY
Paper <mrpapersonic@gmail.com>
parents:
117
diff
changeset
|
100 if (pos == std::string::npos) |
39521c47c7a3
*: another huge megacommit, SORRY
Paper <mrpapersonic@gmail.com>
parents:
117
diff
changeset
|
101 continue; |
39521c47c7a3
*: another huge megacommit, SORRY
Paper <mrpapersonic@gmail.com>
parents:
117
diff
changeset
|
102 |
39521c47c7a3
*: another huge megacommit, SORRY
Paper <mrpapersonic@gmail.com>
parents:
117
diff
changeset
|
103 const std::string key = line.substr(0, pos); |
39521c47c7a3
*: another huge megacommit, SORRY
Paper <mrpapersonic@gmail.com>
parents:
117
diff
changeset
|
104 const std::string value = line.substr(line.find_first_not_of(": ", pos)); |
114 | 105 |
118
39521c47c7a3
*: another huge megacommit, SORRY
Paper <mrpapersonic@gmail.com>
parents:
117
diff
changeset
|
106 switch (KeyMap.at(key)) { |
39521c47c7a3
*: another huge megacommit, SORRY
Paper <mrpapersonic@gmail.com>
parents:
117
diff
changeset
|
107 case Keys::COMMENT: |
39521c47c7a3
*: another huge megacommit, SORRY
Paper <mrpapersonic@gmail.com>
parents:
117
diff
changeset
|
108 torrent.SetDescription(value); |
39521c47c7a3
*: another huge megacommit, SORRY
Paper <mrpapersonic@gmail.com>
parents:
117
diff
changeset
|
109 break; |
39521c47c7a3
*: another huge megacommit, SORRY
Paper <mrpapersonic@gmail.com>
parents:
117
diff
changeset
|
110 case Keys::SIZE: |
39521c47c7a3
*: another huge megacommit, SORRY
Paper <mrpapersonic@gmail.com>
parents:
117
diff
changeset
|
111 torrent.SetSize(Strings::HumanReadableSizeToBytes(value)); |
39521c47c7a3
*: another huge megacommit, SORRY
Paper <mrpapersonic@gmail.com>
parents:
117
diff
changeset
|
112 break; |
39521c47c7a3
*: another huge megacommit, SORRY
Paper <mrpapersonic@gmail.com>
parents:
117
diff
changeset
|
113 default: |
39521c47c7a3
*: another huge megacommit, SORRY
Paper <mrpapersonic@gmail.com>
parents:
117
diff
changeset
|
114 break; |
114 | 115 } |
116 } | |
117 } | |
118 torrent.SetLink(item.child_value("link")); | |
119 torrent.SetGuid(item.child_value("guid")); | |
120 { | |
121 const QString date_str = Strings::ToQString(item.child_value("pubDate")); | |
122 torrent.SetDate(QDateTime::fromString(date_str, "ddd, dd MMM yyyy HH:mm:ss t")); | |
123 } | |
124 list.push_back(torrent); | |
125 } | |
126 | |
127 endResetModel(); | |
128 } | |
129 | |
130 void TorrentsPageListModel::RefreshTorrentList() { | |
131 ParseTorrentList(DownloadTorrentList()); | |
132 } | |
133 | |
134 int TorrentsPageListModel::rowCount(const QModelIndex& parent) const { | |
135 return list.size(); | |
136 (void)(parent); | |
137 } | |
138 | |
139 int TorrentsPageListModel::columnCount(const QModelIndex& parent) const { | |
140 return NB_COLUMNS; | |
141 (void)(parent); | |
142 } | |
143 | |
144 QVariant TorrentsPageListModel::headerData(const int section, const Qt::Orientation orientation, const int role) const { | |
145 switch (role) { | |
146 case Qt::DisplayRole: { | |
147 switch (section) { | |
148 case TL_TITLE: return tr("Anime title"); | |
149 case TL_EPISODE: return tr("Episode"); | |
150 case TL_GROUP: return tr("Group"); | |
151 case TL_SIZE: return tr("Size"); | |
152 case TL_RESOLUTION: return tr("Resolution"); /* this is named "Video" in Taiga */ | |
153 case TL_SEEDERS: return tr("Seeding"); /* named "S" in Taiga */ | |
154 case TL_LEECHERS: return tr("Leeching"); /* named "L" in Taiga */ | |
155 case TL_DOWNLOADERS: return tr("Downloading"); /* named "D" in Taiga */ | |
156 case TL_DESCRIPTION: return tr("Description"); | |
157 case TL_FILENAME: return tr("Filename"); | |
158 case TL_RELEASEDATE: return tr("Release date"); | |
159 default: return {}; | |
160 } | |
161 break; | |
162 } | |
163 case Qt::TextAlignmentRole: { | |
164 switch (section) { | |
165 case TL_FILENAME: | |
166 case TL_GROUP: | |
167 case TL_DESCRIPTION: | |
168 case TL_RESOLUTION: | |
169 case TL_TITLE: return QVariant(Qt::AlignLeft | Qt::AlignVCenter); | |
170 case TL_SEEDERS: | |
171 case TL_LEECHERS: | |
172 case TL_DOWNLOADERS: | |
173 case TL_SIZE: | |
174 case TL_EPISODE: | |
175 case TL_RELEASEDATE: return QVariant(Qt::AlignRight | Qt::AlignVCenter); | |
176 default: return {}; | |
177 } | |
178 break; | |
179 } | |
180 } | |
181 return QAbstractListModel::headerData(section, orientation, role); | |
182 } | |
183 | |
184 bool TorrentsPageListModel::setData(const QModelIndex& index, const QVariant& value, int role) { | |
185 TorrentModelItem& item = list.at(index.row()); | |
54
466ac9870df9
add stub pages (to be implemented)
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
186 |
114 | 187 if (index.column() == 0) { |
188 switch (role) { | |
189 case Qt::EditRole: | |
190 return false; | |
191 case Qt::CheckStateRole: | |
192 item.SetChecked(value.toBool()); | |
193 emit dataChanged(index, index); | |
194 return true; | |
195 } | |
196 } | |
197 | |
198 return QAbstractItemModel::setData(index, value, role); | |
199 } | |
200 | |
201 QVariant TorrentsPageListModel::data(const QModelIndex& index, int role) const { | |
202 if (!index.isValid()) | |
203 return QVariant(); | |
116
254b1d2b7096
settings: add torrents page, make rss feed configurable
Paper <mrpapersonic@gmail.com>
parents:
114
diff
changeset
|
204 |
254b1d2b7096
settings: add torrents page, make rss feed configurable
Paper <mrpapersonic@gmail.com>
parents:
114
diff
changeset
|
205 const TorrentModelItem& item = list.at(index.row()); |
254b1d2b7096
settings: add torrents page, make rss feed configurable
Paper <mrpapersonic@gmail.com>
parents:
114
diff
changeset
|
206 |
114 | 207 switch (role) { |
208 case Qt::DisplayRole: | |
209 switch (index.column()) { | |
116
254b1d2b7096
settings: add torrents page, make rss feed configurable
Paper <mrpapersonic@gmail.com>
parents:
114
diff
changeset
|
210 case TL_TITLE: return Strings::ToQString(item.GetTitle()); |
254b1d2b7096
settings: add torrents page, make rss feed configurable
Paper <mrpapersonic@gmail.com>
parents:
114
diff
changeset
|
211 case TL_EPISODE: return Strings::ToQString(item.GetEpisode()); |
254b1d2b7096
settings: add torrents page, make rss feed configurable
Paper <mrpapersonic@gmail.com>
parents:
114
diff
changeset
|
212 case TL_GROUP: return Strings::ToQString(item.GetGroup()); |
254b1d2b7096
settings: add torrents page, make rss feed configurable
Paper <mrpapersonic@gmail.com>
parents:
114
diff
changeset
|
213 case TL_SIZE: return session.config.locale.GetLocale().formattedDataSize(item.GetSize()); |
254b1d2b7096
settings: add torrents page, make rss feed configurable
Paper <mrpapersonic@gmail.com>
parents:
114
diff
changeset
|
214 case TL_RESOLUTION: return Strings::ToQString(item.GetResolution()); |
254b1d2b7096
settings: add torrents page, make rss feed configurable
Paper <mrpapersonic@gmail.com>
parents:
114
diff
changeset
|
215 case TL_SEEDERS: return item.GetSeeders(); |
254b1d2b7096
settings: add torrents page, make rss feed configurable
Paper <mrpapersonic@gmail.com>
parents:
114
diff
changeset
|
216 case TL_LEECHERS: return item.GetLeechers(); |
254b1d2b7096
settings: add torrents page, make rss feed configurable
Paper <mrpapersonic@gmail.com>
parents:
114
diff
changeset
|
217 case TL_DOWNLOADERS: return item.GetDownloaders(); |
254b1d2b7096
settings: add torrents page, make rss feed configurable
Paper <mrpapersonic@gmail.com>
parents:
114
diff
changeset
|
218 case TL_DESCRIPTION: return Strings::ToQString(item.GetDescription()); |
254b1d2b7096
settings: add torrents page, make rss feed configurable
Paper <mrpapersonic@gmail.com>
parents:
114
diff
changeset
|
219 case TL_FILENAME: return Strings::ToQString(item.GetFilename()); |
254b1d2b7096
settings: add torrents page, make rss feed configurable
Paper <mrpapersonic@gmail.com>
parents:
114
diff
changeset
|
220 case TL_RELEASEDATE: return item.GetDate(); |
114 | 221 default: return ""; |
222 } | |
223 break; | |
224 case Qt::UserRole: | |
225 switch (index.column()) { | |
116
254b1d2b7096
settings: add torrents page, make rss feed configurable
Paper <mrpapersonic@gmail.com>
parents:
114
diff
changeset
|
226 case TL_EPISODE: return Strings::ToInt(item.GetEpisode(), -1); |
117
2c1b6782e1d0
pages/torrents: work around conversion error on Linux
Paper <mrpapersonic@gmail.com>
parents:
116
diff
changeset
|
227 /* We have to use this to work around some stupid |
2c1b6782e1d0
pages/torrents: work around conversion error on Linux
Paper <mrpapersonic@gmail.com>
parents:
116
diff
changeset
|
228 "conversion ambiguous" error on Linux */ |
2c1b6782e1d0
pages/torrents: work around conversion error on Linux
Paper <mrpapersonic@gmail.com>
parents:
116
diff
changeset
|
229 case TL_SIZE: return QVariant::fromValue(item.GetSize()); |
114 | 230 default: return data(index, Qt::DisplayRole); |
231 } | |
232 break; | |
233 case Qt::SizeHintRole: { | |
234 switch (index.column()) { | |
235 default: { | |
116
254b1d2b7096
settings: add torrents page, make rss feed configurable
Paper <mrpapersonic@gmail.com>
parents:
114
diff
changeset
|
236 /* max horizontal size of 100, height size = size of current font */ |
114 | 237 const QString d = data(index, Qt::DisplayRole).toString(); |
238 const QFontMetrics metric = QFontMetrics(QFont()); | |
239 | |
240 return QSize(std::max(metric.horizontalAdvance(d), 100), metric.height()); | |
241 } | |
242 } | |
243 break; | |
244 } | |
245 case Qt::TextAlignmentRole: | |
246 switch (index.column()) { | |
247 case TL_FILENAME: | |
248 case TL_GROUP: | |
249 case TL_DESCRIPTION: | |
250 case TL_RESOLUTION: | |
251 case TL_TITLE: return QVariant(Qt::AlignLeft | Qt::AlignVCenter); | |
252 case TL_SEEDERS: | |
253 case TL_LEECHERS: | |
254 case TL_DOWNLOADERS: | |
255 case TL_SIZE: | |
256 case TL_EPISODE: | |
257 case TL_RELEASEDATE: return QVariant(Qt::AlignRight | Qt::AlignVCenter); | |
258 default: return {}; | |
259 } | |
260 break; | |
261 } | |
262 return QVariant(); | |
263 } | |
264 | |
265 Qt::ItemFlags TorrentsPageListModel::flags(const QModelIndex& index) const { | |
266 if (!index.isValid()) | |
267 return Qt::NoItemFlags; | |
268 | |
118
39521c47c7a3
*: another huge megacommit, SORRY
Paper <mrpapersonic@gmail.com>
parents:
117
diff
changeset
|
269 return Qt::ItemIsEnabled | Qt::ItemIsSelectable; |
114 | 270 } |
271 | |
272 TorrentsPage::TorrentsPage(QWidget* parent) : QFrame(parent) { | |
273 setFrameShape(QFrame::Box); | |
274 setFrameShadow(QFrame::Sunken); | |
275 | |
276 QVBoxLayout* layout = new QVBoxLayout(this); | |
277 layout->setContentsMargins(0, 0, 0, 0); | |
278 layout->setSpacing(0); | |
279 | |
280 { | |
281 /* Toolbar */ | |
282 QToolBar* toolbar = new QToolBar(this); | |
283 toolbar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); | |
284 toolbar->setIconSize(QSize(16, 16)); | |
285 toolbar->setMovable(false); | |
286 | |
287 { | |
288 /* this needs to be stored somewhere to replicate Taiga's | |
289 "timer" feature */ | |
116
254b1d2b7096
settings: add torrents page, make rss feed configurable
Paper <mrpapersonic@gmail.com>
parents:
114
diff
changeset
|
290 toolbar->addAction(QIcon(":/icons/16x16/arrow-circle-315.png"), tr("&Check new torrents"), [this]{ |
114 | 291 QThreadPool::globalInstance()->start([this] { |
292 Refresh(); | |
293 }); | |
294 }); | |
295 } | |
296 | |
297 toolbar->addSeparator(); | |
298 | |
299 { | |
116
254b1d2b7096
settings: add torrents page, make rss feed configurable
Paper <mrpapersonic@gmail.com>
parents:
114
diff
changeset
|
300 toolbar->addAction(QIcon(":/icons/16x16/navigation-270-button.png"), tr("Download &marked torrents")); |
114 | 301 } |
302 | |
303 { | |
116
254b1d2b7096
settings: add torrents page, make rss feed configurable
Paper <mrpapersonic@gmail.com>
parents:
114
diff
changeset
|
304 toolbar->addAction(QIcon(":/icons/16x16/cross-button.png"), tr("&Discard all")); |
114 | 305 } |
306 | |
307 toolbar->addSeparator(); | |
308 | |
309 { | |
116
254b1d2b7096
settings: add torrents page, make rss feed configurable
Paper <mrpapersonic@gmail.com>
parents:
114
diff
changeset
|
310 toolbar->addAction(QIcon(":/icons/16x16/gear.png"), tr("&Settings")); |
114 | 311 } |
312 | |
313 layout->addWidget(toolbar); | |
314 } | |
315 | |
316 { | |
317 QFrame* line = new QFrame(this); | |
318 line->setFrameShape(QFrame::HLine); | |
319 line->setFrameShadow(QFrame::Sunken); | |
320 line->setLineWidth(1); | |
321 layout->addWidget(line); | |
322 } | |
323 | |
324 { | |
325 QTreeView* treeview = new QTreeView(this); | |
326 treeview->setUniformRowHeights(true); | |
327 treeview->setAllColumnsShowFocus(false); | |
328 treeview->setAlternatingRowColors(true); | |
329 treeview->setSortingEnabled(true); | |
330 treeview->setSelectionMode(QAbstractItemView::ExtendedSelection); | |
331 treeview->setItemsExpandable(false); | |
332 treeview->setRootIsDecorated(false); | |
333 treeview->setContextMenuPolicy(Qt::CustomContextMenu); | |
334 treeview->setFrameShape(QFrame::NoFrame); | |
335 | |
336 { | |
337 sort_model = new TorrentsPageListSortFilter(treeview); | |
338 model = new TorrentsPageListModel(treeview); | |
339 sort_model->setSourceModel(model); | |
340 sort_model->setSortRole(Qt::UserRole); | |
341 sort_model->setSortCaseSensitivity(Qt::CaseInsensitive); | |
342 treeview->setModel(sort_model); | |
343 } | |
344 | |
345 layout->addWidget(treeview); | |
346 } | |
347 } | |
348 | |
349 void TorrentsPage::Refresh() { | |
350 if (!model) | |
351 return; | |
352 model->RefreshTorrentList(); | |
54
466ac9870df9
add stub pages (to be implemented)
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
353 } |
466ac9870df9
add stub pages (to be implemented)
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
354 |
466ac9870df9
add stub pages (to be implemented)
Paper <mrpapersonic@gmail.com>
parents:
diff
changeset
|
355 #include "gui/pages/moc_torrents.cpp" |