You've already forked qBittorrent
mirror of
https://github.com/qbittorrent/qBittorrent
synced 2025-10-09 18:32:15 +02:00
Compare commits
24 Commits
release-3.
...
release-1.
Author | SHA1 | Date | |
---|---|---|---|
![]() |
3783b11e98 | ||
![]() |
03cf510f7f | ||
![]() |
610dfefa26 | ||
![]() |
6c477fcf75 | ||
![]() |
604f8542a7 | ||
![]() |
e9b4c6c047 | ||
![]() |
985ac3be68 | ||
![]() |
562c748c50 | ||
![]() |
7a685f5ab6 | ||
![]() |
9500b212c7 | ||
![]() |
5a2e92ad79 | ||
![]() |
9772fccde3 | ||
![]() |
f26bcec56f | ||
![]() |
52a62b6f0f | ||
![]() |
f27b49f9a3 | ||
![]() |
3e4fe1f823 | ||
![]() |
a8a6911aa8 | ||
![]() |
e299288367 | ||
![]() |
de64a641d0 | ||
![]() |
ab13a58614 | ||
![]() |
c863ff6335 | ||
![]() |
e20a09ca3e | ||
![]() |
40966ae421 | ||
![]() |
a87098629b |
27
Changelog
27
Changelog
@@ -1,3 +1,30 @@
|
||||
* Sun Oct 25 2009 - Christophe Dumez <chris@qbittorrent.org> - v1.5.4
|
||||
- BUGFIX: Updated man page
|
||||
- BUGFIX: Fixed possible crash with torrents containing unicode characters
|
||||
- BUGFIX: Fixed problem when disabling systray integration and starting minimized
|
||||
- BUGFIX: Fixed PirateBay search plugin
|
||||
- BUGFIX: Using Download button in search results list now downloads the right torrents
|
||||
- BUGFIX: The search results list is no longer sorted automatically when a row color is updated
|
||||
|
||||
* Wed Sep 30 2009 - Christophe Dumez <chris@qbittorrent.org> - v1.5.3
|
||||
- BUGFIX: Fix a possible crash when pausing then deleting a torrent quickly
|
||||
- BUGFIX: Fix a race condition in folder scanning and torrent downloader
|
||||
- BUGFIX: Hide download url column in search results
|
||||
- BUGFIX: Fix a crash when scanned directory does not exist
|
||||
- BUGFIX: Fix compilation on Mac OS
|
||||
- BUGFIX: Added a command line parameter to disable splash screen
|
||||
- BUGFIX: Ignore permanent deletion button when no torrent is selected
|
||||
- BUGFIX: When a selected torrent is deleted, select next suitable torrent
|
||||
|
||||
* Sun Sep 20 2009 - Christophe Dumez <chris@qbittorrent.org> - v1.5.2
|
||||
- BUGFIX: Some torrents were pausing for no reason
|
||||
- I18N: Updated Korean translation
|
||||
|
||||
* Thu Sep 7 2009 - Christophe Dumez <chris@qbittorrent.org> - v1.5.1
|
||||
- BUGFIX: Fix crash in torrent addition dialog when save path does not exist (closes #425227)
|
||||
- BUGFIX: Fix downloading from URL (broken in v1.5.0)
|
||||
- BUGFIX: Pause torrents in error state
|
||||
|
||||
* Thu Sep 3 2009 - Christophe Dumez <chris@qbittorrent.org> - v1.5.0
|
||||
- FEATURE: Added Magnet URI support
|
||||
- FEATURE: Search engine supports category-based requests
|
||||
|
@@ -1,17 +1,19 @@
|
||||
.\" This manpage has been automatically generated by docbook2man
|
||||
.\" from a DocBook document. This tool can be found at:
|
||||
.\" <http://shell.ipoline.com/~elmert/comp/docbook2X/>.
|
||||
.TH "QBITTORRENT" "1" "September 1st 2007" "Bittorrent client written in C++ / Qt4" ""
|
||||
.TH "QBITTORRENT" "1" "September 30th 2009" "Bittorrent client written in C++ / Qt4" ""
|
||||
|
||||
.SH NAME
|
||||
.SH "NAME"
|
||||
qBittorrent \- a Bittorrent client written in C++ / Qt4
|
||||
.SH SYNOPSIS
|
||||
|
||||
\fBqbittorrent\fR [FILE | URL] [FILE | URL...]
|
||||
.SH "SYNOPSIS"
|
||||
|
||||
\fBqbittorrent\fR [--no-splash] [TORRENT_FILE | URL]...
|
||||
|
||||
\fBqbittorrent\fR \-\-help
|
||||
|
||||
\fBqbittorrent\fR \-\-version
|
||||
|
||||
.PP
|
||||
.SH "DESCRIPTION"
|
||||
|
||||
@@ -19,10 +21,21 @@ qBittorrent \- a Bittorrent client written in C++ / Qt4
|
||||
using the \fBrblibtorrent\fR library by Arvid Norberg. qBittorrent aims
|
||||
to be a good alternative to all other bittorrent clients out there. qBittorrent
|
||||
is fast, stable, light, it supports unicode and it provides a good integrated search engine.
|
||||
It also comes with UPnP port forwarding / NAT-PMP, encryption (Azureus compatible), FAST extension (mainline) and PeX support (utorrent compatible).
|
||||
It also comes with UPnP port forwarding / NAT-PMP, encryption (Azureus compatible),
|
||||
FAST extension (mainline) and PeX support (utorrent compatible).
|
||||
|
||||
.SH "OPTIONS"
|
||||
|
||||
\fB--help\fR Prints the command line options.
|
||||
|
||||
\fB--version\fR Prints qbittorrent program version number.
|
||||
|
||||
\fB--no-splash\fR Disables splash screen on startup.
|
||||
|
||||
.SH "BUGS"
|
||||
|
||||
If you find a bug, please report it at http://bugs.qbittorrent.org
|
||||
|
||||
Please report any problem to http://bugs.qbittorrent.org
|
||||
.PP
|
||||
.SH "AUTHOR"
|
||||
|
||||
Christophe Dumez <chris@qbittorrent.org>
|
||||
|
@@ -383,6 +383,20 @@ void FinishedTorrents::deleteTorrent(QString hash){
|
||||
qDebug("Torrent is not in finished list, nothing to delete");
|
||||
return;
|
||||
}
|
||||
// Select item just under (or above nothing under) the one that was deleted
|
||||
QModelIndex current_prox_index = proxyModel->mapFromSource(finishedListModel->index(row, 0, finishedList->rootIndex()));
|
||||
bool was_selected = finishedList->selectionModel()->isSelected(current_prox_index);
|
||||
if(finishedListModel->rowCount() > 1 && was_selected) {
|
||||
QModelIndex under_prox_index;
|
||||
if(current_prox_index.row() == finishedListModel->rowCount()-1)
|
||||
under_prox_index = proxyModel->index(current_prox_index.row()-1, 0);
|
||||
else
|
||||
under_prox_index = proxyModel->index(current_prox_index.row()+1, 0);
|
||||
//downloadList->selectionModel()->select(under_prox_index, QItemSelectionModel::Current|QItemSelectionModel::Columns|QItemSelectionModel::Select);
|
||||
finishedList->setCurrentIndex(under_prox_index);
|
||||
finishedList->update();
|
||||
}
|
||||
// Actually delete the row
|
||||
finishedListModel->removeRow(row);
|
||||
--nbFinished;
|
||||
emit finishedTorrentsNumberChanged(nbFinished);
|
||||
|
14
src/GUI.cpp
14
src/GUI.cpp
@@ -249,8 +249,9 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
|
||||
QMainWindow::statusBar()->addPermanentWidget(upSpeedLbl);
|
||||
QMainWindow::statusBar()->addPermanentWidget(statusSep4);
|
||||
QMainWindow::statusBar()->addPermanentWidget(ratioLbl);
|
||||
if(!settings.value(QString::fromUtf8("Preferences/General/StartMinimized"), false).toBool()) {
|
||||
show();
|
||||
show();
|
||||
if(settings.value(QString::fromUtf8("Preferences/General/StartMinimized"), false).toBool()) {
|
||||
this->setWindowState(Qt::WindowMinimized);
|
||||
}
|
||||
scrapeTimer = new QTimer(this);
|
||||
connect(scrapeTimer, SIGNAL(timeout()), this, SLOT(scrapeTrackers()));
|
||||
@@ -450,7 +451,10 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
|
||||
}
|
||||
|
||||
void GUI::setPaused(QTorrentHandle &h) const {
|
||||
if(!h.is_paused()) return;
|
||||
if(!h.is_paused()) {
|
||||
// FIXME in v1.6.0: Add Error state and stop using pause for this
|
||||
h.pause();
|
||||
}
|
||||
qDebug("Marking torrent %s as paused", h.hash().toLocal8Bit().data());
|
||||
if(h.is_seed()) {
|
||||
// In finished list
|
||||
@@ -865,6 +869,7 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
|
||||
default:
|
||||
return;
|
||||
}
|
||||
if(hashes.empty()) return;
|
||||
int ret;
|
||||
if(inDownloadList) {
|
||||
ret = QMessageBox::question(
|
||||
@@ -916,7 +921,7 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
|
||||
default:
|
||||
return;
|
||||
}
|
||||
if(!hashes.size()) return;
|
||||
if(hashes.empty()) return;
|
||||
int ret;
|
||||
if(inDownloadList) {
|
||||
ret = QMessageBox::question(
|
||||
@@ -953,6 +958,7 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
|
||||
bool useTorrentAdditionDialog = settings.value(QString::fromUtf8("Preferences/Downloads/AdditionDialog"), true).toBool();
|
||||
foreach(QString param, params) {
|
||||
param = param.trimmed();
|
||||
if(param.startsWith("--")) continue;
|
||||
if(param.startsWith(QString::fromUtf8("http://"), Qt::CaseInsensitive) || param.startsWith(QString::fromUtf8("ftp://"), Qt::CaseInsensitive) || param.startsWith(QString::fromUtf8("https://"), Qt::CaseInsensitive)) {
|
||||
BTSession->downloadFromUrl(param);
|
||||
}else{
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[Desktop Entry]
|
||||
Categories=Qt;Network;P2P;
|
||||
Comment=V1.5.0
|
||||
Comment=V1.5.4
|
||||
Exec=qbittorrent %f
|
||||
GenericName=Bittorrent client
|
||||
GenericName[bg]=Торент клиент
|
||||
@@ -25,6 +25,7 @@ GenericName[sv]=Bittorrent-klient
|
||||
GenericName[tr]=Bittorrent istemcisi
|
||||
GenericName[uk]=Bittorrent-клієнт
|
||||
GenericName[zh]=Bittorrent之用户
|
||||
GenericName[zh_TW]=Bittorrent客戶端
|
||||
Icon=qbittorrent
|
||||
MimeType=application/x-bittorrent;
|
||||
Name=qBittorrent
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 76 KiB |
@@ -63,7 +63,6 @@ SearchTab::SearchTab(SearchEngine *parent) : QWidget(), parent(parent)
|
||||
SearchListModel->setHeaderData(SEARCH_SEEDERS, Qt::Horizontal, tr("Seeders", "i.e: Number of full sources"));
|
||||
SearchListModel->setHeaderData(SEARCH_LEECHERS, Qt::Horizontal, tr("Leechers", "i.e: Number of partial sources"));
|
||||
SearchListModel->setHeaderData(SEARCH_ENGINE, Qt::Horizontal, tr("Search engine"));
|
||||
resultsBrowser->hideColumn(URL_COLUMN); // Hide url column
|
||||
|
||||
proxyModel = new QSortFilterProxyModel();
|
||||
proxyModel->setDynamicSortFilter(true);
|
||||
@@ -73,6 +72,8 @@ SearchTab::SearchTab(SearchEngine *parent) : QWidget(), parent(parent)
|
||||
SearchDelegate = new SearchListDelegate();
|
||||
resultsBrowser->setItemDelegate(SearchDelegate);
|
||||
|
||||
resultsBrowser->hideColumn(URL_COLUMN); // Hide url column
|
||||
|
||||
resultsBrowser->setRootIsDecorated(false);
|
||||
resultsBrowser->setAllColumnsShowFocus(true);
|
||||
resultsBrowser->setSortingEnabled(true);
|
||||
@@ -134,16 +135,23 @@ QTreeView* SearchTab::getCurrentTreeView()
|
||||
return resultsBrowser;
|
||||
}
|
||||
|
||||
QStandardItemModel* SearchTab::getCurrentSearchListModel()
|
||||
QSortFilterProxyModel* SearchTab::getCurrentSearchListProxy() const
|
||||
{
|
||||
return proxyModel;
|
||||
}
|
||||
|
||||
QStandardItemModel* SearchTab::getCurrentSearchListModel() const
|
||||
{
|
||||
return SearchListModel;
|
||||
}
|
||||
|
||||
// Set the color of a row in data model
|
||||
void SearchTab::setRowColor(int row, QString color){
|
||||
proxyModel->setDynamicSortFilter(false);
|
||||
for(int i=0; i<proxyModel->columnCount(); ++i){
|
||||
proxyModel->setData(proxyModel->index(row, i), QVariant(QColor(color)), Qt::ForegroundRole);
|
||||
}
|
||||
proxyModel->setDynamicSortFilter(true);
|
||||
}
|
||||
|
||||
|
||||
|
@@ -63,7 +63,8 @@ public:
|
||||
~SearchTab();
|
||||
bool loadColWidthResultsList();
|
||||
QLabel * getCurrentLabel();
|
||||
QStandardItemModel * getCurrentSearchListModel();
|
||||
QStandardItemModel* getCurrentSearchListModel() const;
|
||||
QSortFilterProxyModel* getCurrentSearchListProxy() const;
|
||||
QTreeView * getCurrentTreeView();
|
||||
void setRowColor(int row, QString color);
|
||||
QHeaderView* header() const;
|
||||
|
@@ -67,7 +67,7 @@ bittorrent::bittorrent() : DHTEnabled(false), preAllocateAll(false), addInPause(
|
||||
qDebug("Peer ID: %s", fingerprint("UT", 1, 8, 4, 0).to_string().c_str());
|
||||
} else {
|
||||
s = new session(fingerprint("qB", VERSION_MAJOR, VERSION_MINOR, VERSION_BUGFIX, 0), 0);
|
||||
qDebug("Peer ID: ", fingerprint("qB", VERSION_MAJOR, VERSION_MINOR, VERSION_BUGFIX, 0).to_string().c_str());
|
||||
qDebug("Peer ID: %s", fingerprint("qB", VERSION_MAJOR, VERSION_MINOR, VERSION_BUGFIX, 0).to_string().c_str());
|
||||
}
|
||||
|
||||
// Set severity level of libtorrent session
|
||||
@@ -987,11 +987,12 @@ void bittorrent::scanDirectory(QString scan_dir) {
|
||||
foreach(const QString &file, files) {
|
||||
QString fullPath = dir.path()+QDir::separator()+file;
|
||||
QFile torrent(fullPath);
|
||||
if(torrent.size() != 0) {
|
||||
qDebug("Adding for scan_dir: %s", fullPath.toLocal8Bit().data());
|
||||
qDebug("Adding for scan_dir: %s", fullPath.toLocal8Bit().data());
|
||||
try {
|
||||
torrent_info t(fullPath.toLocal8Bit().data());
|
||||
addTorrent(fullPath, true);
|
||||
} else {
|
||||
qDebug("Ignoring empty file: %s", fullPath.toLocal8Bit().data());
|
||||
} catch(std::exception&) {
|
||||
qDebug("Ignoring incomplete torrent file: %s", fullPath.toLocal8Bit().data());
|
||||
}
|
||||
}
|
||||
FSMutex->unlock();
|
||||
@@ -1043,6 +1044,11 @@ void bittorrent::saveTrackerFile(QString hash) {
|
||||
// Enable directory scanning
|
||||
void bittorrent::enableDirectoryScanning(QString scan_dir) {
|
||||
if(!scan_dir.isEmpty()) {
|
||||
QDir newDir(scan_dir);
|
||||
if(!newDir.exists()) {
|
||||
qDebug("Scan dir %s does not exist, create it", scan_dir.toUtf8().data());
|
||||
newDir.mkpath(scan_dir);
|
||||
}
|
||||
if(FSWatcher == 0) {
|
||||
FSMutex = new QMutex();
|
||||
FSWatcher = new QFileSystemWatcher(QStringList(scan_dir), this);
|
||||
@@ -1050,9 +1056,12 @@ void bittorrent::enableDirectoryScanning(QString scan_dir) {
|
||||
// Initial scan
|
||||
scanDirectory(scan_dir);
|
||||
} else {
|
||||
QString old_scan_dir = FSWatcher->directories().first();
|
||||
QString old_scan_dir = "";
|
||||
if(!FSWatcher->directories().empty())
|
||||
old_scan_dir = FSWatcher->directories().first();
|
||||
if(old_scan_dir != scan_dir) {
|
||||
FSWatcher->removePath(old_scan_dir);
|
||||
if(!old_scan_dir.isEmpty())
|
||||
FSWatcher->removePath(old_scan_dir);
|
||||
FSWatcher->addPath(scan_dir);
|
||||
// Initial scan
|
||||
scanDirectory(scan_dir);
|
||||
@@ -1224,7 +1233,7 @@ void bittorrent::readAlerts() {
|
||||
while (a.get()) {
|
||||
if (torrent_finished_alert* p = dynamic_cast<torrent_finished_alert*>(a.get())) {
|
||||
QTorrentHandle h(p->handle);
|
||||
if(h.is_valid()){
|
||||
if(h.is_valid()) {
|
||||
emit finishedTorrent(h);
|
||||
QString hash = h.hash();
|
||||
// Remember finished state
|
||||
@@ -1264,16 +1273,18 @@ void bittorrent::readAlerts() {
|
||||
else if (save_resume_data_alert* p = dynamic_cast<save_resume_data_alert*>(a.get())) {
|
||||
QDir torrentBackup(misc::qBittorrentPath() + "BT_backup");
|
||||
QTorrentHandle h(p->handle);
|
||||
QString file = h.hash()+".fastresume";
|
||||
// Delete old fastresume file if necessary
|
||||
if(QFile::exists(file))
|
||||
QFile::remove(file);
|
||||
qDebug("Saving fastresume data in %s", file.toLocal8Bit().data());
|
||||
if (p->resume_data)
|
||||
{
|
||||
boost::filesystem::ofstream out(fs::path(torrentBackup.path().toLocal8Bit().data()) / file.toLocal8Bit().data(), std::ios_base::binary);
|
||||
out.unsetf(std::ios_base::skipws);
|
||||
bencode(std::ostream_iterator<char>(out), *p->resume_data);
|
||||
if(h.is_valid()) {
|
||||
QString file = h.hash()+".fastresume";
|
||||
// Delete old fastresume file if necessary
|
||||
if(QFile::exists(file))
|
||||
QFile::remove(file);
|
||||
qDebug("Saving fastresume data in %s", file.toLocal8Bit().data());
|
||||
if (p->resume_data)
|
||||
{
|
||||
boost::filesystem::ofstream out(fs::path(torrentBackup.path().toLocal8Bit().data()) / file.toLocal8Bit().data(), std::ios_base::binary);
|
||||
out.unsetf(std::ios_base::skipws);
|
||||
bencode(std::ostream_iterator<char>(out), *p->resume_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (metadata_received_alert* p = dynamic_cast<metadata_received_alert*>(a.get())) {
|
||||
@@ -1290,23 +1301,25 @@ void bittorrent::readAlerts() {
|
||||
}
|
||||
else if (file_error_alert* p = dynamic_cast<file_error_alert*>(a.get())) {
|
||||
QTorrentHandle h(p->handle);
|
||||
h.auto_managed(false);
|
||||
std::cerr << "File Error: " << p->message().c_str() << std::endl;
|
||||
if(h.is_valid())
|
||||
emit fullDiskError(h, misc::toQString(p->message()));
|
||||
if(h.is_valid()) {
|
||||
h.auto_managed(false);
|
||||
std::cerr << "File Error: " << p->message().c_str() << std::endl;
|
||||
if(h.is_valid())
|
||||
emit fullDiskError(h, misc::toQString(p->message()));
|
||||
}
|
||||
}
|
||||
else if (dynamic_cast<listen_failed_alert*>(a.get())) {
|
||||
// Level: fatal
|
||||
addConsoleMessage(tr("Couldn't listen on any of the given ports."), QString::fromUtf8("red"));
|
||||
//emit portListeningFailure();
|
||||
}
|
||||
else if (torrent_paused_alert* p = dynamic_cast<torrent_paused_alert*>(a.get())) {
|
||||
/*else if (torrent_paused_alert* p = dynamic_cast<torrent_paused_alert*>(a.get())) {
|
||||
QTorrentHandle h(p->handle);
|
||||
qDebug("Received a torrent_paused_alert for %s", h.hash().toLocal8Bit().data());
|
||||
if(h.is_valid()) {
|
||||
emit torrentPaused(h);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
else if (tracker_error_alert* p = dynamic_cast<tracker_error_alert*>(a.get())) {
|
||||
// Level: fatal
|
||||
QTorrentHandle h(p->handle);
|
||||
@@ -1435,6 +1448,12 @@ void bittorrent::downloadFromUrl(QString url) {
|
||||
downloader->downloadUrl(url);
|
||||
}
|
||||
|
||||
void bittorrent::downloadFromURLList(const QStringList& urls) {
|
||||
foreach(const QString &url, urls) {
|
||||
downloadFromUrl(url);
|
||||
}
|
||||
}
|
||||
|
||||
void bittorrent::addMagnetSkipAddDlg(QString uri) {
|
||||
addMagnetUri(uri, false);
|
||||
}
|
||||
|
@@ -170,6 +170,7 @@ class bittorrent : public QObject {
|
||||
void processDownloadedFile(QString, QString);
|
||||
void saveTrackerFile(QString hash);
|
||||
void addMagnetSkipAddDlg(QString uri);
|
||||
void downloadFromURLList(const QStringList& urls);
|
||||
|
||||
protected slots:
|
||||
void scanDirectory(QString);
|
||||
|
@@ -198,6 +198,20 @@ void DownloadingTorrents::deleteTorrent(QString hash) {
|
||||
qDebug("torrent is not in download list, nothing to delete");
|
||||
return;
|
||||
}
|
||||
// Select item just under (or above nothing under) the one that was deleted
|
||||
QModelIndex current_prox_index = proxyModel->mapFromSource(DLListModel->index(row, 0, downloadList->rootIndex()));
|
||||
bool was_selected = downloadList->selectionModel()->isSelected(current_prox_index);
|
||||
if(DLListModel->rowCount() > 1 && was_selected) {
|
||||
QModelIndex under_prox_index;
|
||||
if(current_prox_index.row() == DLListModel->rowCount()-1)
|
||||
under_prox_index = proxyModel->index(current_prox_index.row()-1, 0);
|
||||
else
|
||||
under_prox_index = proxyModel->index(current_prox_index.row()+1, 0);
|
||||
//downloadList->selectionModel()->select(under_prox_index, QItemSelectionModel::Current|QItemSelectionModel::Columns|QItemSelectionModel::Select);
|
||||
downloadList->setCurrentIndex(under_prox_index);
|
||||
downloadList->update();
|
||||
}
|
||||
// Actually delete the row
|
||||
DLListModel->removeRow(row);
|
||||
--nbTorrents;
|
||||
emit unfinishedTorrentsNumberChanged(nbTorrents);
|
||||
|
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user