mirror of
https://github.com/qbittorrent/qBittorrent.git
synced 2024-11-29 05:48:47 +03:00
FEATURE: Search engine results can now be opened in a Web browser (plugins will be progressively ported, only btjunkie is working atm)
This commit is contained in:
parent
35ea06214a
commit
c14deec893
14 changed files with 224 additions and 177 deletions
|
@ -7,6 +7,7 @@
|
||||||
- FEATURE: Added "Time Active/Seeded" column to transfer list
|
- FEATURE: Added "Time Active/Seeded" column to transfer list
|
||||||
- FEATURE: Give feedback regarding the IP filter parsing
|
- FEATURE: Give feedback regarding the IP filter parsing
|
||||||
- FEATURE: Added a button to reload the IP filter
|
- FEATURE: Added a button to reload the IP filter
|
||||||
|
- FEATURE: Search engine results can now be opened in a Web browser
|
||||||
- COSMETIC: Same deletion confirmation dialog in the GUI and Web UI
|
- COSMETIC: Same deletion confirmation dialog in the GUI and Web UI
|
||||||
- COSMETIC: Simplified the top toolbar
|
- COSMETIC: Simplified the top toolbar
|
||||||
- COSMETIC: Display execution log as a tab instead of a modal window
|
- COSMETIC: Display execution log as a tab instead of a modal window
|
||||||
|
|
|
@ -39,11 +39,7 @@
|
||||||
#include <QProgressBar>
|
#include <QProgressBar>
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
|
#include "previewselect.h"
|
||||||
// Defines for properties list columns
|
|
||||||
#define NAME 0
|
|
||||||
#define SIZE 1
|
|
||||||
#define PROGRESS 2
|
|
||||||
|
|
||||||
class PreviewListDelegate: public QItemDelegate {
|
class PreviewListDelegate: public QItemDelegate {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -58,11 +54,11 @@ class PreviewListDelegate: public QItemDelegate {
|
||||||
QStyleOptionViewItemV2 opt = QItemDelegate::setOptions(index, option);
|
QStyleOptionViewItemV2 opt = QItemDelegate::setOptions(index, option);
|
||||||
|
|
||||||
switch(index.column()){
|
switch(index.column()){
|
||||||
case SIZE:
|
case PreviewSelect::SIZE:
|
||||||
QItemDelegate::drawBackground(painter, opt, index);
|
QItemDelegate::drawBackground(painter, opt, index);
|
||||||
QItemDelegate::drawDisplay(painter, opt, option.rect, misc::friendlyUnit(index.data().toLongLong()));
|
QItemDelegate::drawDisplay(painter, opt, option.rect, misc::friendlyUnit(index.data().toLongLong()));
|
||||||
break;
|
break;
|
||||||
case PROGRESS:{
|
case PreviewSelect::PROGRESS:{
|
||||||
float progress = index.data().toDouble()*100.;
|
float progress = index.data().toDouble()*100.;
|
||||||
QStyleOptionProgressBarV2 newopt;
|
QStyleOptionProgressBarV2 newopt;
|
||||||
newopt.rect = opt.rect;
|
newopt.rect = opt.rect;
|
||||||
|
|
92
src/previewselect.cpp
Normal file
92
src/previewselect.cpp
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
#include <QStandardItemModel>
|
||||||
|
#include <QHeaderView>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QFile>
|
||||||
|
|
||||||
|
#include <libtorrent/version.hpp>
|
||||||
|
#include <libtorrent/session.hpp>
|
||||||
|
|
||||||
|
#include "misc.h"
|
||||||
|
#include "previewlistdelegate.h"
|
||||||
|
#include "previewselect.h"
|
||||||
|
|
||||||
|
PreviewSelect::PreviewSelect(QWidget* parent, QTorrentHandle h): QDialog(parent), h(h){
|
||||||
|
setupUi(this);
|
||||||
|
setAttribute(Qt::WA_DeleteOnClose);
|
||||||
|
// Preview list
|
||||||
|
previewListModel = new QStandardItemModel(0, 3);
|
||||||
|
previewListModel->setHeaderData(NAME, Qt::Horizontal, tr("Name"));
|
||||||
|
previewListModel->setHeaderData(SIZE, Qt::Horizontal, tr("Size"));
|
||||||
|
previewListModel->setHeaderData(PROGRESS, Qt::Horizontal, tr("Progress"));
|
||||||
|
previewList->setModel(previewListModel);
|
||||||
|
listDelegate = new PreviewListDelegate(this);
|
||||||
|
previewList->setItemDelegate(listDelegate);
|
||||||
|
previewList->header()->resizeSection(0, 200);
|
||||||
|
// Fill list in
|
||||||
|
std::vector<libtorrent::size_type> fp;
|
||||||
|
h.file_progress(fp);
|
||||||
|
unsigned int nbFiles = h.num_files();
|
||||||
|
for(unsigned int i=0; i<nbFiles; ++i){
|
||||||
|
QString fileName = h.filename_at(i);
|
||||||
|
QString extension = fileName.split(QString::fromUtf8(".")).last().toUpper();
|
||||||
|
if(misc::isPreviewable(extension)) {
|
||||||
|
int row = previewListModel->rowCount();
|
||||||
|
previewListModel->insertRow(row);
|
||||||
|
previewListModel->setData(previewListModel->index(row, NAME), QVariant(fileName));
|
||||||
|
previewListModel->setData(previewListModel->index(row, SIZE), QVariant((qlonglong)h.filesize_at(i)));
|
||||||
|
previewListModel->setData(previewListModel->index(row, PROGRESS), QVariant((double)fp[i]/h.filesize_at(i)));
|
||||||
|
indexes << i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
previewList->selectionModel()->select(previewListModel->index(0, NAME), QItemSelectionModel::Select);
|
||||||
|
previewList->selectionModel()->select(previewListModel->index(0, SIZE), QItemSelectionModel::Select);
|
||||||
|
previewList->selectionModel()->select(previewListModel->index(0, PROGRESS), QItemSelectionModel::Select);
|
||||||
|
if(!previewListModel->rowCount()){
|
||||||
|
QMessageBox::critical(0, tr("Preview impossible"), tr("Sorry, we can't preview this file"));
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
connect(this, SIGNAL(readyToPreviewFile(QString)), parent, SLOT(previewFile(QString)));
|
||||||
|
if(previewListModel->rowCount() == 1){
|
||||||
|
qDebug("Torrent file only contains one file, no need to display selection dialog before preview");
|
||||||
|
// Only one file : no choice
|
||||||
|
on_previewButton_clicked();
|
||||||
|
}else{
|
||||||
|
qDebug("Displaying media file selection dialog for preview");
|
||||||
|
show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PreviewSelect::~PreviewSelect(){
|
||||||
|
delete previewListModel;
|
||||||
|
delete listDelegate;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PreviewSelect::on_previewButton_clicked(){
|
||||||
|
QModelIndex index;
|
||||||
|
QModelIndexList selectedIndexes = previewList->selectionModel()->selectedRows(NAME);
|
||||||
|
if(selectedIndexes.size() == 0) return;
|
||||||
|
#if LIBTORRENT_VERSION_MINOR > 14
|
||||||
|
// Flush data
|
||||||
|
h.flush_cache();
|
||||||
|
#endif
|
||||||
|
QString path;
|
||||||
|
foreach(index, selectedIndexes){
|
||||||
|
path = h.files_path().at(indexes.at(index.row()));
|
||||||
|
// File
|
||||||
|
if(QFile::exists(path)){
|
||||||
|
emit readyToPreviewFile(path);
|
||||||
|
} else {
|
||||||
|
QMessageBox::critical(0, tr("Preview impossible"), tr("Sorry, we can't preview this file"));
|
||||||
|
}
|
||||||
|
close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
qDebug("Cannot find file: %s", path.toLocal8Bit().data());
|
||||||
|
QMessageBox::critical(0, tr("Preview impossible"), tr("Sorry, we can't preview this file"));
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PreviewSelect::on_cancelButton_clicked(){
|
||||||
|
close();
|
||||||
|
}
|
|
@ -32,114 +32,36 @@
|
||||||
#define PREVIEWSELECT_H
|
#define PREVIEWSELECT_H
|
||||||
|
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
#include <QStandardItemModel>
|
#include <QList>
|
||||||
#include <QHeaderView>
|
|
||||||
#include <QMessageBox>
|
|
||||||
#include <QFile>
|
|
||||||
#include <libtorrent/version.hpp>
|
|
||||||
#include <libtorrent/session.hpp>
|
|
||||||
#include "ui_preview.h"
|
#include "ui_preview.h"
|
||||||
#include "previewlistdelegate.h"
|
|
||||||
#include "misc.h"
|
|
||||||
#include "qtorrenthandle.h"
|
#include "qtorrenthandle.h"
|
||||||
|
|
||||||
#define NAME 0
|
class QStandardItemModel;
|
||||||
#define SIZE 1
|
class PreviewListDelegate;
|
||||||
#define PROGRESS 2
|
|
||||||
|
|
||||||
class previewSelect: public QDialog, private Ui::preview {
|
class PreviewSelect: public QDialog, private Ui::preview {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum PreviewColumn { NAME, SIZE, PROGRESS };
|
||||||
|
|
||||||
|
public:
|
||||||
|
PreviewSelect(QWidget* parent, QTorrentHandle h);
|
||||||
|
~PreviewSelect();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void readyToPreviewFile(QString) const;
|
||||||
|
|
||||||
|
protected slots:
|
||||||
|
void on_previewButton_clicked();
|
||||||
|
void on_cancelButton_clicked();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QStandardItemModel *previewListModel;
|
QStandardItemModel *previewListModel;
|
||||||
PreviewListDelegate *listDelegate;
|
PreviewListDelegate *listDelegate;
|
||||||
QTorrentHandle h;
|
QTorrentHandle h;
|
||||||
QList<int> indexes;
|
QList<int> indexes;
|
||||||
|
|
||||||
signals:
|
|
||||||
void readyToPreviewFile(QString) const;
|
|
||||||
|
|
||||||
protected slots:
|
|
||||||
void on_previewButton_clicked(){
|
|
||||||
QModelIndex index;
|
|
||||||
QModelIndexList selectedIndexes = previewList->selectionModel()->selectedRows(NAME);
|
|
||||||
if(selectedIndexes.size() == 0) return;
|
|
||||||
#if LIBTORRENT_VERSION_MINOR > 14
|
|
||||||
// Flush data
|
|
||||||
h.flush_cache();
|
|
||||||
#endif
|
|
||||||
QString path;
|
|
||||||
foreach(index, selectedIndexes){
|
|
||||||
path = h.files_path().at(indexes.at(index.row()));
|
|
||||||
// File
|
|
||||||
if(QFile::exists(path)){
|
|
||||||
emit readyToPreviewFile(path);
|
|
||||||
} else {
|
|
||||||
QMessageBox::critical(0, tr("Preview impossible"), tr("Sorry, we can't preview this file"));
|
|
||||||
}
|
|
||||||
close();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
qDebug("Cannot find file: %s", path.toLocal8Bit().data());
|
|
||||||
QMessageBox::critical(0, tr("Preview impossible"), tr("Sorry, we can't preview this file"));
|
|
||||||
close();
|
|
||||||
}
|
|
||||||
|
|
||||||
void on_cancelButton_clicked(){
|
|
||||||
close();
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
previewSelect(QWidget* parent, QTorrentHandle h): QDialog(parent), h(h){
|
|
||||||
setupUi(this);
|
|
||||||
setAttribute(Qt::WA_DeleteOnClose);
|
|
||||||
// Preview list
|
|
||||||
previewListModel = new QStandardItemModel(0, 3);
|
|
||||||
previewListModel->setHeaderData(NAME, Qt::Horizontal, tr("Name"));
|
|
||||||
previewListModel->setHeaderData(SIZE, Qt::Horizontal, tr("Size"));
|
|
||||||
previewListModel->setHeaderData(PROGRESS, Qt::Horizontal, tr("Progress"));
|
|
||||||
previewList->setModel(previewListModel);
|
|
||||||
listDelegate = new PreviewListDelegate(this);
|
|
||||||
previewList->setItemDelegate(listDelegate);
|
|
||||||
previewList->header()->resizeSection(0, 200);
|
|
||||||
// Fill list in
|
|
||||||
std::vector<libtorrent::size_type> fp;
|
|
||||||
h.file_progress(fp);
|
|
||||||
unsigned int nbFiles = h.num_files();
|
|
||||||
for(unsigned int i=0; i<nbFiles; ++i){
|
|
||||||
QString fileName = h.filename_at(i);
|
|
||||||
QString extension = fileName.split(QString::fromUtf8(".")).last().toUpper();
|
|
||||||
if(misc::isPreviewable(extension)) {
|
|
||||||
int row = previewListModel->rowCount();
|
|
||||||
previewListModel->insertRow(row);
|
|
||||||
previewListModel->setData(previewListModel->index(row, NAME), QVariant(fileName));
|
|
||||||
previewListModel->setData(previewListModel->index(row, SIZE), QVariant((qlonglong)h.filesize_at(i)));
|
|
||||||
previewListModel->setData(previewListModel->index(row, PROGRESS), QVariant((double)fp[i]/h.filesize_at(i)));
|
|
||||||
indexes << i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
previewList->selectionModel()->select(previewListModel->index(0, NAME), QItemSelectionModel::Select);
|
|
||||||
previewList->selectionModel()->select(previewListModel->index(0, SIZE), QItemSelectionModel::Select);
|
|
||||||
previewList->selectionModel()->select(previewListModel->index(0, PROGRESS), QItemSelectionModel::Select);
|
|
||||||
if(!previewListModel->rowCount()){
|
|
||||||
QMessageBox::critical(0, tr("Preview impossible"), tr("Sorry, we can't preview this file"));
|
|
||||||
close();
|
|
||||||
}
|
|
||||||
connect(this, SIGNAL(readyToPreviewFile(QString)), parent, SLOT(previewFile(QString)));
|
|
||||||
if(previewListModel->rowCount() == 1){
|
|
||||||
qDebug("Torrent file only contains one file, no need to display selection dialog before preview");
|
|
||||||
// Only one file : no choice
|
|
||||||
on_previewButton_clicked();
|
|
||||||
}else{
|
|
||||||
qDebug("Displaying media file selection dialog for preview");
|
|
||||||
show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
~previewSelect(){
|
|
||||||
delete previewListModel;
|
|
||||||
delete listDelegate;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#VERSION: 2.23
|
#VERSION: 2.31
|
||||||
#AUTHORS: Christophe Dumez (chris@qbittorrent.org)
|
#AUTHORS: Christophe Dumez (chris@qbittorrent.org)
|
||||||
|
|
||||||
# Redistribution and use in source and binary forms, with or without
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -54,10 +54,13 @@ class btjunkie(object):
|
||||||
def start_a(self, attr):
|
def start_a(self, attr):
|
||||||
params = dict(attr)
|
params = dict(attr)
|
||||||
#print params
|
#print params
|
||||||
if params.has_key('href') and params['href'].startswith("http://dl.btjunkie.org/torrent"):
|
if params.has_key('href'):
|
||||||
|
if params['href'].startswith("http://dl.btjunkie.org/torrent"):
|
||||||
self.current_item = {}
|
self.current_item = {}
|
||||||
self.th_counter = 0
|
self.th_counter = 0
|
||||||
self.current_item['link']=params['href'].strip()
|
self.current_item['link']=params['href'].strip()
|
||||||
|
elif self.th_counter == 0 and params['href'].startswith("/torrent/") and params['href'].find('/files/') == -1:
|
||||||
|
self.current_item['desc_link'] = 'http://btjunkie.org'+params['href'].strip()
|
||||||
|
|
||||||
def handle_data(self, data):
|
def handle_data(self, data):
|
||||||
if self.th_counter == 0:
|
if self.th_counter == 0:
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
isohunt: 1.32
|
isohunt: 1.32
|
||||||
torrentreactor: 1.21
|
torrentreactor: 1.21
|
||||||
btjunkie: 2.23
|
btjunkie: 2.31
|
||||||
mininova: 1.40
|
mininova: 1.40
|
||||||
piratebay: 1.30
|
piratebay: 1.30
|
||||||
vertor: 1.1
|
vertor: 1.1
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#VERSION: 1.33
|
#VERSION: 1.41
|
||||||
|
|
||||||
# Redistribution and use in source and binary forms, with or without
|
# Redistribution and use in source and binary forms, with or without
|
||||||
# modification, are permitted provided that the following conditions are met:
|
# modification, are permitted provided that the following conditions are met:
|
||||||
|
@ -35,6 +35,9 @@ def prettyPrinter(dictionary):
|
||||||
if isinstance(dictionary[key], str):
|
if isinstance(dictionary[key], str):
|
||||||
dictionary[key] = unicode(dictionary[key], 'utf-8')
|
dictionary[key] = unicode(dictionary[key], 'utf-8')
|
||||||
dictionary['size'] = anySizeToBytes(dictionary['size'])
|
dictionary['size'] = anySizeToBytes(dictionary['size'])
|
||||||
|
if dictionary.has_key('desc_link'):
|
||||||
|
print u"%s|%s|%s|%s|%s|%s|%s"%(dictionary['link'],dictionary['name'],dictionary['size'],dictionary['seeds'],dictionary['leech'],dictionary['engine_url'],dictionary['desc_link'])
|
||||||
|
else:
|
||||||
print u"%s|%s|%s|%s|%s|%s"%(dictionary['link'],dictionary['name'],dictionary['size'],dictionary['seeds'],dictionary['leech'],dictionary['engine_url'])
|
print u"%s|%s|%s|%s|%s|%s"%(dictionary['link'],dictionary['name'],dictionary['size'],dictionary['seeds'],dictionary['leech'],dictionary['engine_url'])
|
||||||
|
|
||||||
def anySizeToBytes(size_string):
|
def anySizeToBytes(size_string):
|
||||||
|
|
|
@ -136,6 +136,13 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="goToDescBtn">
|
||||||
|
<property name="text">
|
||||||
|
<string>Go to description page</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<spacer>
|
<spacer>
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
|
|
|
@ -42,6 +42,7 @@
|
||||||
#include <QMimeData>
|
#include <QMimeData>
|
||||||
#include <QSortFilterProxyModel>
|
#include <QSortFilterProxyModel>
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
|
#include <QDesktopServices>
|
||||||
|
|
||||||
#ifdef Q_WS_WIN
|
#ifdef Q_WS_WIN
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -64,6 +65,7 @@ SearchEngine::SearchEngine(MainWindow *parent) : QWidget(parent), mp_mainWindow(
|
||||||
// Icons
|
// Icons
|
||||||
search_button->setIcon(misc::getIcon("edit-find"));
|
search_button->setIcon(misc::getIcon("edit-find"));
|
||||||
download_button->setIcon(misc::getIcon("download"));
|
download_button->setIcon(misc::getIcon("download"));
|
||||||
|
goToDescBtn->setIcon(misc::getIcon("application-x-mswinurl"));
|
||||||
enginesButton->setIcon(misc::getIcon("preferences-system-network"));
|
enginesButton->setIcon(misc::getIcon("preferences-system-network"));
|
||||||
// new qCompleter to the search pattern
|
// new qCompleter to the search pattern
|
||||||
startSearchHistory();
|
startSearchHistory();
|
||||||
|
@ -253,8 +255,10 @@ void SearchEngine::tab_changed(int t)
|
||||||
{//-1 = no more tab
|
{//-1 = no more tab
|
||||||
if(all_tab.at(tabWidget->currentIndex())->getCurrentSearchListModel()->rowCount()) {
|
if(all_tab.at(tabWidget->currentIndex())->getCurrentSearchListModel()->rowCount()) {
|
||||||
download_button->setEnabled(true);
|
download_button->setEnabled(true);
|
||||||
|
goToDescBtn->setEnabled(true);
|
||||||
} else {
|
} else {
|
||||||
download_button->setEnabled(false);
|
download_button->setEnabled(false);
|
||||||
|
goToDescBtn->setEnabled(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -487,39 +491,39 @@ void SearchEngine::updateNova() {
|
||||||
package_file2.close();
|
package_file2.close();
|
||||||
// Copy search plugin files (if necessary)
|
// Copy search plugin files (if necessary)
|
||||||
QString filePath = search_dir.absoluteFilePath("nova2.py");
|
QString filePath = search_dir.absoluteFilePath("nova2.py");
|
||||||
if(getPluginVersion(":/nova/nova2.py") > getPluginVersion(filePath)) {
|
if(getPluginVersion(":/nova2/nova2.py") > getPluginVersion(filePath)) {
|
||||||
if(QFile::exists(filePath)) {
|
if(QFile::exists(filePath)) {
|
||||||
misc::safeRemove(filePath);
|
misc::safeRemove(filePath);
|
||||||
misc::safeRemove(filePath+"c");
|
misc::safeRemove(filePath+"c");
|
||||||
}
|
}
|
||||||
QFile::copy(":/nova/nova2.py", filePath);
|
QFile::copy(":/nova2/nova2.py", filePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
filePath = search_dir.absoluteFilePath("nova2dl.py");
|
filePath = search_dir.absoluteFilePath("nova2dl.py");
|
||||||
if(getPluginVersion(":/nova/nova2dl.py") > getPluginVersion(filePath)) {
|
if(getPluginVersion(":/nova2/nova2dl.py") > getPluginVersion(filePath)) {
|
||||||
if(QFile::exists(filePath)){
|
if(QFile::exists(filePath)){
|
||||||
misc::safeRemove(filePath);
|
misc::safeRemove(filePath);
|
||||||
misc::safeRemove(filePath+"c");
|
misc::safeRemove(filePath+"c");
|
||||||
}
|
}
|
||||||
QFile::copy(":/nova/nova2dl.py", filePath);
|
QFile::copy(":/nova2/nova2dl.py", filePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
filePath = search_dir.absoluteFilePath("novaprinter.py");
|
filePath = search_dir.absoluteFilePath("novaprinter.py");
|
||||||
if(getPluginVersion(":/nova/novaprinter.py") > getPluginVersion(filePath)) {
|
if(getPluginVersion(":/nova2/novaprinter.py") > getPluginVersion(filePath)) {
|
||||||
if(QFile::exists(filePath)){
|
if(QFile::exists(filePath)){
|
||||||
misc::safeRemove(filePath);
|
misc::safeRemove(filePath);
|
||||||
misc::safeRemove(filePath+"c");
|
misc::safeRemove(filePath+"c");
|
||||||
}
|
}
|
||||||
QFile::copy(":/nova/novaprinter.py", filePath);
|
QFile::copy(":/nova2/novaprinter.py", filePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
filePath = search_dir.absoluteFilePath("helpers.py");
|
filePath = search_dir.absoluteFilePath("helpers.py");
|
||||||
if(getPluginVersion(":/nova/helpers.py") > getPluginVersion(filePath)) {
|
if(getPluginVersion(":/nova2/helpers.py") > getPluginVersion(filePath)) {
|
||||||
if(QFile::exists(filePath)){
|
if(QFile::exists(filePath)){
|
||||||
misc::safeRemove(filePath);
|
misc::safeRemove(filePath);
|
||||||
misc::safeRemove(filePath+"c");
|
misc::safeRemove(filePath+"c");
|
||||||
}
|
}
|
||||||
QFile::copy(":/nova/helpers.py", filePath);
|
QFile::copy(":/nova2/helpers.py", filePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
filePath = search_dir.absoluteFilePath("socks.py");
|
filePath = search_dir.absoluteFilePath("socks.py");
|
||||||
|
@ -527,9 +531,9 @@ void SearchEngine::updateNova() {
|
||||||
misc::safeRemove(filePath);
|
misc::safeRemove(filePath);
|
||||||
misc::safeRemove(filePath+"c");
|
misc::safeRemove(filePath+"c");
|
||||||
}
|
}
|
||||||
QFile::copy(":/nova/socks.py", filePath);
|
QFile::copy(":/nova2/socks.py", filePath);
|
||||||
QDir destDir(QDir(misc::searchEngineLocation()).absoluteFilePath("engines"));
|
QDir destDir(QDir(misc::searchEngineLocation()).absoluteFilePath("engines"));
|
||||||
QDir shipped_subDir(":/nova/engines/");
|
QDir shipped_subDir(":/nova2/engines/");
|
||||||
QStringList files = shipped_subDir.entryList();
|
QStringList files = shipped_subDir.entryList();
|
||||||
foreach(const QString &file, files){
|
foreach(const QString &file, files){
|
||||||
QString shipped_file = shipped_subDir.absoluteFilePath(file);
|
QString shipped_file = shipped_subDir.absoluteFilePath(file);
|
||||||
|
@ -598,7 +602,7 @@ void SearchEngine::searchFinished(int exitcode,QProcess::ExitStatus){
|
||||||
// SLOT to append one line to search results list
|
// SLOT to append one line to search results list
|
||||||
// Line is in the following form :
|
// Line is in the following form :
|
||||||
// file url | file name | file size | nb seeds | nb leechers | Search engine url
|
// file url | file name | file size | nb seeds | nb leechers | Search engine url
|
||||||
void SearchEngine::appendSearchResult(QString line){
|
void SearchEngine::appendSearchResult(const QString &line){
|
||||||
if(!currentSearchTab) {
|
if(!currentSearchTab) {
|
||||||
if(searchProcess->state() != QProcess::NotRunning){
|
if(searchProcess->state() != QProcess::NotRunning){
|
||||||
searchProcess->terminate();
|
searchProcess->terminate();
|
||||||
|
@ -609,8 +613,9 @@ void SearchEngine::appendSearchResult(QString line){
|
||||||
search_stopped = true;
|
search_stopped = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
QStringList parts = line.split("|");
|
const QStringList parts = line.split("|");
|
||||||
if(parts.size() != 6){
|
const int nb_fields = parts.size();
|
||||||
|
if(nb_fields < NB_PLUGIN_COLUMNS-1){ //-1 because desc_link is optional
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Q_ASSERT(currentSearchTab);
|
Q_ASSERT(currentSearchTab);
|
||||||
|
@ -620,28 +625,32 @@ void SearchEngine::appendSearchResult(QString line){
|
||||||
int row = cur_model->rowCount();
|
int row = cur_model->rowCount();
|
||||||
cur_model->insertRow(row);
|
cur_model->insertRow(row);
|
||||||
|
|
||||||
cur_model->setData(cur_model->index(row, 5), parts.at(0).trimmed()); // download URL
|
cur_model->setData(cur_model->index(row, DL_LINK), parts.at(PL_DL_LINK).trimmed()); // download URL
|
||||||
cur_model->setData(cur_model->index(row, 0), parts.at(1).trimmed()); // Name
|
cur_model->setData(cur_model->index(row, NAME), parts.at(PL_NAME).trimmed()); // Name
|
||||||
cur_model->setData(cur_model->index(row, 1), parts.at(2).trimmed().toLongLong()); // Size
|
cur_model->setData(cur_model->index(row, SIZE), parts.at(PL_SIZE).trimmed().toLongLong()); // Size
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
qlonglong nb_seeders = parts.at(3).trimmed().toLongLong(&ok);
|
qlonglong nb_seeders = parts.at(PL_SEEDS).trimmed().toLongLong(&ok);
|
||||||
if(!ok || nb_seeders < 0) {
|
if(!ok || nb_seeders < 0) {
|
||||||
cur_model->setData(cur_model->index(row, 2), tr("Unknown")); // Seeders
|
cur_model->setData(cur_model->index(row, SEEDS), tr("Unknown")); // Seeders
|
||||||
} else {
|
} else {
|
||||||
cur_model->setData(cur_model->index(row, 2), nb_seeders); // Seeders
|
cur_model->setData(cur_model->index(row, SEEDS), nb_seeders); // Seeders
|
||||||
}
|
}
|
||||||
qlonglong nb_leechers = parts.at(4).trimmed().toLongLong(&ok);
|
qlonglong nb_leechers = parts.at(PL_LEECHS).trimmed().toLongLong(&ok);
|
||||||
if(!ok || nb_leechers < 0) {
|
if(!ok || nb_leechers < 0) {
|
||||||
cur_model->setData(cur_model->index(row, 3), tr("Unknown")); // Leechers
|
cur_model->setData(cur_model->index(row, LEECHS), tr("Unknown")); // Leechers
|
||||||
} else {
|
} else {
|
||||||
cur_model->setData(cur_model->index(row, 3), nb_leechers); // Leechers
|
cur_model->setData(cur_model->index(row, LEECHS), nb_leechers); // Leechers
|
||||||
}
|
}
|
||||||
cur_model->setData(cur_model->index(row, 4), parts.at(5).trimmed()); // Engine URL
|
cur_model->setData(cur_model->index(row, ENGINE_URL), parts.at(PL_ENGINE_URL).trimmed()); // Engine URL
|
||||||
|
// Description Link
|
||||||
|
if(nb_fields == NB_PLUGIN_COLUMNS)
|
||||||
|
cur_model->setData(cur_model->index(row, DESC_LINK), parts.at(PL_DESC_LINK).trimmed());
|
||||||
|
|
||||||
no_search_results = false;
|
no_search_results = false;
|
||||||
++nb_search_results;
|
++nb_search_results;
|
||||||
// Enable clear & download buttons
|
// Enable clear & download buttons
|
||||||
download_button->setEnabled(true);
|
download_button->setEnabled(true);
|
||||||
|
goToDescBtn->setEnabled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if QT_VERSION >= 0x040500
|
#if QT_VERSION >= 0x040500
|
||||||
|
@ -660,6 +669,7 @@ void SearchEngine::closeTab(int index) {
|
||||||
delete all_tab.takeAt(index);
|
delete all_tab.takeAt(index);
|
||||||
if(!all_tab.size()) {
|
if(!all_tab.size()) {
|
||||||
download_button->setEnabled(false);
|
download_button->setEnabled(false);
|
||||||
|
goToDescBtn->setEnabled(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
@ -703,3 +713,16 @@ void SearchEngine::on_download_button_clicked(){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SearchEngine::on_goToDescBtn_clicked()
|
||||||
|
{
|
||||||
|
QModelIndexList selectedIndexes = all_tab.at(tabWidget->currentIndex())->getCurrentTreeView()->selectionModel()->selectedIndexes();
|
||||||
|
foreach(const QModelIndex &index, selectedIndexes){
|
||||||
|
if(index.column() == NAME) {
|
||||||
|
QSortFilterProxyModel* model = all_tab.at(tabWidget->currentIndex())->getCurrentSearchListProxy();
|
||||||
|
const QString desc_url = model->data(model->index(index.row(), DESC_LINK)).toString();
|
||||||
|
if(!desc_url.isEmpty())
|
||||||
|
QDesktopServices::openUrl(QUrl(desc_url));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -50,6 +50,11 @@ class SearchEngine : public QWidget, public Ui::search_engine{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_DISABLE_COPY(SearchEngine)
|
Q_DISABLE_COPY(SearchEngine)
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum SearchColumn { NAME, SIZE, SEEDS, LEECHS, ENGINE_URL, DL_LINK, DESC_LINK, NB_SEARCH_COLUMNS };
|
||||||
|
private:
|
||||||
|
enum PluginColumn { PL_DL_LINK, PL_NAME, PL_SIZE, PL_SEEDS, PL_LEECHS, PL_ENGINE_URL, PL_DESC_LINK, NB_PLUGIN_COLUMNS };
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SearchEngine(MainWindow *mp_mainWindow);
|
SearchEngine(MainWindow *mp_mainWindow);
|
||||||
~SearchEngine();
|
~SearchEngine();
|
||||||
|
@ -91,7 +96,7 @@ protected slots:
|
||||||
#else
|
#else
|
||||||
void closeTab(int index);
|
void closeTab(int index);
|
||||||
#endif
|
#endif
|
||||||
void appendSearchResult(QString line);
|
void appendSearchResult(const QString &line);
|
||||||
void searchFinished(int exitcode,QProcess::ExitStatus);
|
void searchFinished(int exitcode,QProcess::ExitStatus);
|
||||||
void readSearchOutput();
|
void readSearchOutput();
|
||||||
void searchStarted();
|
void searchStarted();
|
||||||
|
@ -113,6 +118,9 @@ protected slots:
|
||||||
void pythonDownloadFailure(QString url, QString error);
|
void pythonDownloadFailure(QString url, QString error);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void on_goToDescBtn_clicked();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Search related
|
// Search related
|
||||||
QProcess *searchProcess;
|
QProcess *searchProcess;
|
||||||
|
|
|
@ -38,13 +38,7 @@
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <QProgressBar>
|
#include <QProgressBar>
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
|
#include "searchengine.h"
|
||||||
// Defines for search results list columns
|
|
||||||
#define NAME 0
|
|
||||||
#define SIZE 1
|
|
||||||
#define SEEDERS 2
|
|
||||||
#define LEECHERS 3
|
|
||||||
#define ENGINE 4
|
|
||||||
|
|
||||||
class SearchListDelegate: public QItemDelegate {
|
class SearchListDelegate: public QItemDelegate {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -58,7 +52,7 @@ class SearchListDelegate: public QItemDelegate {
|
||||||
painter->save();
|
painter->save();
|
||||||
QStyleOptionViewItemV2 opt = QItemDelegate::setOptions(index, option);
|
QStyleOptionViewItemV2 opt = QItemDelegate::setOptions(index, option);
|
||||||
switch(index.column()){
|
switch(index.column()){
|
||||||
case SIZE:
|
case SearchEngine::SIZE:
|
||||||
QItemDelegate::drawBackground(painter, opt, index);
|
QItemDelegate::drawBackground(painter, opt, index);
|
||||||
QItemDelegate::drawDisplay(painter, opt, option.rect, misc::friendlyUnit(index.data().toLongLong()));
|
QItemDelegate::drawDisplay(painter, opt, option.rect, misc::friendlyUnit(index.data().toLongLong()));
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -40,12 +40,6 @@
|
||||||
#include "searchengine.h"
|
#include "searchengine.h"
|
||||||
#include "qinisettings.h"
|
#include "qinisettings.h"
|
||||||
|
|
||||||
#define SEARCH_NAME 0
|
|
||||||
#define SEARCH_SIZE 1
|
|
||||||
#define SEARCH_SEEDERS 2
|
|
||||||
#define SEARCH_LEECHERS 3
|
|
||||||
#define SEARCH_ENGINE 4
|
|
||||||
|
|
||||||
SearchTab::SearchTab(SearchEngine *parent) : QWidget(), parent(parent)
|
SearchTab::SearchTab(SearchEngine *parent) : QWidget(), parent(parent)
|
||||||
{
|
{
|
||||||
box=new QVBoxLayout();
|
box=new QVBoxLayout();
|
||||||
|
@ -57,12 +51,12 @@ SearchTab::SearchTab(SearchEngine *parent) : QWidget(), parent(parent)
|
||||||
|
|
||||||
setLayout(box);
|
setLayout(box);
|
||||||
// Set Search results list model
|
// Set Search results list model
|
||||||
SearchListModel = new QStandardItemModel(0,6);
|
SearchListModel = new QStandardItemModel(0, SearchEngine::NB_SEARCH_COLUMNS);
|
||||||
SearchListModel->setHeaderData(SEARCH_NAME, Qt::Horizontal, tr("Name", "i.e: file name"));
|
SearchListModel->setHeaderData(SearchEngine::NAME, Qt::Horizontal, tr("Name", "i.e: file name"));
|
||||||
SearchListModel->setHeaderData(SEARCH_SIZE, Qt::Horizontal, tr("Size", "i.e: file size"));
|
SearchListModel->setHeaderData(SearchEngine::SIZE, Qt::Horizontal, tr("Size", "i.e: file size"));
|
||||||
SearchListModel->setHeaderData(SEARCH_SEEDERS, Qt::Horizontal, tr("Seeders", "i.e: Number of full sources"));
|
SearchListModel->setHeaderData(SearchEngine::SEEDS, 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(SearchEngine::LEECHS, Qt::Horizontal, tr("Leechers", "i.e: Number of partial sources"));
|
||||||
SearchListModel->setHeaderData(SEARCH_ENGINE, Qt::Horizontal, tr("Search engine"));
|
SearchListModel->setHeaderData(SearchEngine::ENGINE_URL, Qt::Horizontal, tr("Search engine"));
|
||||||
|
|
||||||
proxyModel = new QSortFilterProxyModel();
|
proxyModel = new QSortFilterProxyModel();
|
||||||
proxyModel->setDynamicSortFilter(true);
|
proxyModel->setDynamicSortFilter(true);
|
||||||
|
@ -72,7 +66,8 @@ SearchTab::SearchTab(SearchEngine *parent) : QWidget(), parent(parent)
|
||||||
SearchDelegate = new SearchListDelegate();
|
SearchDelegate = new SearchListDelegate();
|
||||||
resultsBrowser->setItemDelegate(SearchDelegate);
|
resultsBrowser->setItemDelegate(SearchDelegate);
|
||||||
|
|
||||||
resultsBrowser->hideColumn(URL_COLUMN); // Hide url column
|
resultsBrowser->hideColumn(SearchEngine::DL_LINK); // Hide url column
|
||||||
|
resultsBrowser->hideColumn(SearchEngine::DESC_LINK);
|
||||||
|
|
||||||
resultsBrowser->setRootIsDecorated(false);
|
resultsBrowser->setRootIsDecorated(false);
|
||||||
resultsBrowser->setAllColumnsShowFocus(true);
|
resultsBrowser->setAllColumnsShowFocus(true);
|
||||||
|
@ -87,12 +82,12 @@ SearchTab::SearchTab(SearchEngine *parent) : QWidget(), parent(parent)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort by Seeds
|
// Sort by Seeds
|
||||||
resultsBrowser->sortByColumn(SEEDERS, Qt::DescendingOrder);
|
resultsBrowser->sortByColumn(SearchEngine::SEEDS, Qt::DescendingOrder);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SearchTab::downloadSelectedItem(const QModelIndex& index) {
|
void SearchTab::downloadSelectedItem(const QModelIndex& index) {
|
||||||
QString engine_url = proxyModel->data(proxyModel->index(index.row(), ENGINE_URL_COLUMN)).toString();
|
QString engine_url = proxyModel->data(proxyModel->index(index.row(), SearchEngine::ENGINE_URL)).toString();
|
||||||
QString torrent_url = proxyModel->data(proxyModel->index(index.row(), URL_COLUMN)).toString();
|
QString torrent_url = proxyModel->data(proxyModel->index(index.row(), SearchEngine::DL_LINK)).toString();
|
||||||
setRowColor(index.row(), "red");
|
setRowColor(index.row(), "red");
|
||||||
parent->downloadTorrent(engine_url, torrent_url);
|
parent->downloadTorrent(engine_url, torrent_url);
|
||||||
}
|
}
|
||||||
|
|
|
@ -139,7 +139,8 @@ nox {
|
||||||
torrentadditiondlg.cpp \
|
torrentadditiondlg.cpp \
|
||||||
sessionapplication.cpp \
|
sessionapplication.cpp \
|
||||||
torrentimportdlg.cpp \
|
torrentimportdlg.cpp \
|
||||||
executionlog.cpp
|
executionlog.cpp \
|
||||||
|
previewselect.cpp
|
||||||
|
|
||||||
win32 {
|
win32 {
|
||||||
HEADERS += programupdater.h
|
HEADERS += programupdater.h
|
||||||
|
|
|
@ -28,6 +28,23 @@
|
||||||
* Contact : chris@qbittorrent.org
|
* Contact : chris@qbittorrent.org
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <QStandardItemModel>
|
||||||
|
#include <QSortFilterProxyModel>
|
||||||
|
#include <QDesktopServices>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <QClipboard>
|
||||||
|
#include <QInputDialog>
|
||||||
|
#include <QColor>
|
||||||
|
#include <QUrl>
|
||||||
|
#include <QMenu>
|
||||||
|
#include <QRegExp>
|
||||||
|
#include <QFileDialog>
|
||||||
|
#include <QMessageBox>
|
||||||
|
|
||||||
|
#include <libtorrent/version.hpp>
|
||||||
|
#include <vector>
|
||||||
|
#include <queue>
|
||||||
|
|
||||||
#include "transferlistwidget.h"
|
#include "transferlistwidget.h"
|
||||||
#include "qbtsession.h"
|
#include "qbtsession.h"
|
||||||
#include "torrentpersistentdata.h"
|
#include "torrentpersistentdata.h"
|
||||||
|
@ -40,21 +57,6 @@
|
||||||
#include "torrentmodel.h"
|
#include "torrentmodel.h"
|
||||||
#include "deletionconfirmationdlg.h"
|
#include "deletionconfirmationdlg.h"
|
||||||
#include "propertieswidget.h"
|
#include "propertieswidget.h"
|
||||||
#include <libtorrent/version.hpp>
|
|
||||||
#include <QStandardItemModel>
|
|
||||||
#include <QSortFilterProxyModel>
|
|
||||||
#include <QDesktopServices>
|
|
||||||
#include <QTimer>
|
|
||||||
#include <QClipboard>
|
|
||||||
#include <QInputDialog>
|
|
||||||
#include <QColor>
|
|
||||||
#include <QUrl>
|
|
||||||
#include <QMenu>
|
|
||||||
#include <QRegExp>
|
|
||||||
#include <QFileDialog>
|
|
||||||
#include <vector>
|
|
||||||
#include <queue>
|
|
||||||
|
|
||||||
#include "qinisettings.h"
|
#include "qinisettings.h"
|
||||||
|
|
||||||
using namespace libtorrent;
|
using namespace libtorrent;
|
||||||
|
@ -426,7 +428,7 @@ void TransferListWidget::previewSelectedTorrents() {
|
||||||
foreach(const QString &hash, hashes) {
|
foreach(const QString &hash, hashes) {
|
||||||
const QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
const QTorrentHandle h = BTSession->getTorrentHandle(hash);
|
||||||
if(h.is_valid() && h.has_metadata()) {
|
if(h.is_valid() && h.has_metadata()) {
|
||||||
new previewSelect(this, h);
|
new PreviewSelect(this, h);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue