2007-03-27 22:49:29 +04:00
/*
* Bittorrent Client using Qt4 and libtorrent .
2007-07-14 18:31:59 +04:00
* Copyright ( C ) 2006 Christophe Dumez
2007-03-27 22:49:29 +04:00
*
2007-07-14 18:31:59 +04:00
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation ; either version 2
* of the License , or ( at your option ) any later version .
2007-03-27 22:49:29 +04:00
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
2007-07-14 18:31:59 +04:00
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 , USA .
*
2009-04-05 21:00:55 +04:00
* In addition , as a special exception , the copyright holders give permission to
* link this program with the OpenSSL project ' s " OpenSSL " library ( or with
* modified versions of it that use the same license as the " OpenSSL " library ) ,
* and distribute the linked executables . You must obey the GNU General Public
* License in all respects for all of the code used other than " OpenSSL " . If you
* modify file ( s ) , you may extend this exception to your version of the file ( s ) ,
* but you are not obligated to do so . If you do not wish to do so , delete this
* exception statement from your version .
*
2007-07-14 18:31:59 +04:00
* Contact : chris @ qbittorrent . org
2007-03-27 22:49:29 +04:00
*/
# include <QStandardItemModel>
# include <QHeaderView>
# include <QCompleter>
# include <QMessageBox>
# include <QTemporaryFile>
# include <QSystemTrayIcon>
# include <iostream>
2007-11-30 13:48:00 +03:00
# include <QTimer>
2008-06-25 23:29:29 +04:00
# include <QDir>
2009-07-12 10:42:38 +04:00
# include <QMenu>
2009-07-12 11:12:43 +04:00
# include <QClipboard>
# include <QMimeData>
2009-10-25 02:49:10 +04:00
# include <QSortFilterProxyModel>
2010-05-30 21:51:40 +04:00
# include <QFileDialog>
2010-12-26 12:51:37 +03:00
# include <QDesktopServices>
2010-05-30 21:51:40 +04:00
# ifdef Q_WS_WIN
# include <stdlib.h>
# endif
2007-03-27 22:49:29 +04:00
2009-11-20 10:48:44 +03:00
# include "searchengine.h"
2010-10-09 18:06:35 +04:00
# include "qbtsession.h"
2009-11-20 10:48:44 +03:00
# include "downloadthread.h"
2008-06-25 23:29:29 +04:00
# include "misc.h"
2010-05-30 21:51:40 +04:00
# include "preferences.h"
2009-11-20 10:48:44 +03:00
# include "searchlistdelegate.h"
2010-07-16 19:03:18 +04:00
# include "qinisettings.h"
2010-11-14 00:15:52 +03:00
# include "mainwindow.h"
2007-03-27 22:49:29 +04:00
# define SEARCHHISTORY_MAXSIZE 50
2008-06-25 23:04:42 +04:00
/*SEARCH ENGINE START*/
2010-11-14 00:15:52 +03:00
SearchEngine : : SearchEngine ( MainWindow * parent ) : QWidget ( parent ) , mp_mainWindow ( parent ) {
2008-06-25 23:04:42 +04:00
setupUi ( this ) ;
2010-12-12 22:37:59 +03:00
// Icons
search_button - > setIcon ( misc : : getIcon ( " edit-find " ) ) ;
download_button - > setIcon ( misc : : getIcon ( " download " ) ) ;
2010-12-26 12:51:37 +03:00
goToDescBtn - > setIcon ( misc : : getIcon ( " application-x-mswinurl " ) ) ;
2010-12-12 22:37:59 +03:00
enginesButton - > setIcon ( misc : : getIcon ( " preferences-system-network " ) ) ;
2008-06-25 23:04:42 +04:00
// new qCompleter to the search pattern
startSearchHistory ( ) ;
2009-07-12 10:42:38 +04:00
createCompleter ( ) ;
2010-12-12 22:37:59 +03:00
# if (QT_VERSION >= QT_VERSION_CHECK(4,5,0))
2009-11-27 00:11:37 +03:00
tabWidget - > setTabsClosable ( true ) ;
connect ( tabWidget , SIGNAL ( tabCloseRequested ( int ) ) , this , SLOT ( closeTab ( int ) ) ) ;
# else
2008-07-06 22:39:07 +04:00
// Add close tab button
closeTab_button = new QPushButton ( ) ;
2010-12-12 22:37:59 +03:00
closeTab_button - > setIcon ( misc : : getIcon ( " tab-close " ) ) ;
2008-07-06 22:39:07 +04:00
closeTab_button - > setFlat ( true ) ;
tabWidget - > setCornerWidget ( closeTab_button ) ;
2009-11-27 00:11:37 +03:00
connect ( closeTab_button , SIGNAL ( clicked ( ) ) , this , SLOT ( closeTab_button_clicked ( ) ) ) ;
# endif
2008-06-25 23:04:42 +04:00
// Boolean initialization
search_stopped = false ;
// Creating Search Process
2010-03-30 22:59:15 +04:00
# ifdef Q_WS_WIN
2010-06-02 02:47:14 +04:00
has_python = addPythonPathToEnv ( ) ;
2010-03-30 22:59:15 +04:00
# endif
2010-05-30 21:51:40 +04:00
searchProcess = new QProcess ( this ) ;
2010-06-02 02:47:14 +04:00
searchProcess - > setEnvironment ( QProcess : : systemEnvironment ( ) ) ;
2008-06-25 23:04:42 +04:00
connect ( searchProcess , SIGNAL ( started ( ) ) , this , SLOT ( searchStarted ( ) ) ) ;
connect ( searchProcess , SIGNAL ( readyReadStandardOutput ( ) ) , this , SLOT ( readSearchOutput ( ) ) ) ;
connect ( searchProcess , SIGNAL ( finished ( int , QProcess : : ExitStatus ) ) , this , SLOT ( searchFinished ( int , QProcess : : ExitStatus ) ) ) ;
2008-07-04 20:49:08 +04:00
connect ( tabWidget , SIGNAL ( currentChanged ( int ) ) , this , SLOT ( tab_changed ( int ) ) ) ;
2008-06-25 23:04:42 +04:00
searchTimeout = new QTimer ( this ) ;
searchTimeout - > setSingleShot ( true ) ;
2009-08-25 06:31:36 +04:00
connect ( searchTimeout , SIGNAL ( timeout ( ) ) , this , SLOT ( on_search_button_clicked ( ) ) ) ;
2008-06-25 23:04:42 +04:00
// Update nova.py search plugin if necessary
updateNova ( ) ;
2009-08-25 06:31:36 +04:00
supported_engines = new SupportedEngines ( ) ;
// Fill in category combobox
fillCatCombobox ( ) ;
2009-07-12 10:42:38 +04:00
connect ( search_pattern , SIGNAL ( customContextMenuRequested ( QPoint ) ) , this , SLOT ( displayPatternContextMenu ( QPoint ) ) ) ;
2010-01-30 21:15:25 +03:00
connect ( search_pattern , SIGNAL ( textEdited ( QString ) ) , this , SLOT ( searchTextEdited ( QString ) ) ) ;
2008-06-25 23:04:42 +04:00
}
2009-08-25 06:31:36 +04:00
void SearchEngine : : fillCatCombobox ( ) {
comboCategory - > clear ( ) ;
comboCategory - > addItem ( full_cat_names [ " all " ] , QVariant ( " all " ) ) ;
QStringList supported_cat = supported_engines - > supportedCategories ( ) ;
foreach ( QString cat , supported_cat ) {
2010-03-04 23:19:25 +03:00
qDebug ( " Supported category: %s " , qPrintable ( cat ) ) ;
2009-08-25 06:31:36 +04:00
comboCategory - > addItem ( full_cat_names [ cat ] , QVariant ( cat ) ) ;
}
}
2010-05-30 21:51:40 +04:00
# ifdef Q_WS_WIN
2010-06-02 02:47:14 +04:00
bool SearchEngine : : addPythonPathToEnv ( ) {
QString python_path = Preferences : : getPythonPath ( ) ;
if ( ! python_path . isEmpty ( ) ) {
2010-05-30 21:51:40 +04:00
// Add it to PATH envvar
QString path_envar = QString : : fromLocal8Bit ( getenv ( " PATH " ) ) ;
if ( path_envar . isNull ( ) ) {
2010-06-02 02:47:14 +04:00
path_envar = " " ;
2010-05-30 21:51:40 +04:00
}
path_envar = python_path + " ; " + path_envar ;
qDebug ( " New PATH envvar is: %s " , qPrintable ( path_envar ) ) ;
QString envar = " PATH= " + path_envar ;
putenv ( envar . toLocal8Bit ( ) . data ( ) ) ;
2010-06-02 02:47:14 +04:00
return true ;
}
return false ;
}
void SearchEngine : : installPython ( ) {
setCursor ( QCursor ( Qt : : WaitCursor ) ) ;
// Download python
downloadThread * pydownloader = new downloadThread ( this ) ;
connect ( pydownloader , SIGNAL ( downloadFinished ( QString , QString ) ) , this , SLOT ( pythonDownloadSuccess ( QString , QString ) ) ) ;
connect ( pydownloader , SIGNAL ( downloadFailure ( QString , QString ) ) , this , SLOT ( pythonDownloadFailure ( QString , QString ) ) ) ;
pydownloader - > downloadUrl ( " http://python.org/ftp/python/2.6.5/python-2.6.5.msi " ) ;
2010-05-30 21:51:40 +04:00
}
2010-06-02 02:47:14 +04:00
void SearchEngine : : pythonDownloadSuccess ( QString url , QString file_path ) {
setCursor ( QCursor ( Qt : : ArrowCursor ) ) ;
Q_UNUSED ( url ) ;
QFile : : rename ( file_path , file_path + " .msi " ) ;
QProcess installer ;
qDebug ( " Launching Python installer in passive mode... " ) ;
installer . start ( " msiexec.exe /passive /i " + file_path . replace ( " / " , " \\ " ) + " .msi " ) ;
// Wait for setup to complete
installer . waitForFinished ( ) ;
qDebug ( " Installer stdout: %s " , installer . readAllStandardOutput ( ) . data ( ) ) ;
qDebug ( " Installer stderr: %s " , installer . readAllStandardError ( ) . data ( ) ) ;
qDebug ( " Setup should be complete! " ) ;
// Reload search engine
has_python = addPythonPathToEnv ( ) ;
if ( has_python ) {
supported_engines - > update ( ) ;
// Launch the search again
on_search_button_clicked ( ) ;
}
// Delete temp file
2010-07-24 23:26:26 +04:00
misc : : safeRemove ( file_path + " .msi " ) ;
2010-06-02 02:47:14 +04:00
}
void SearchEngine : : pythonDownloadFailure ( QString url , QString error ) {
Q_UNUSED ( url ) ;
setCursor ( QCursor ( Qt : : ArrowCursor ) ) ;
QMessageBox : : warning ( this , tr ( " Download error " ) , tr ( " Python setup could not be downloaded, reason: %1. \n Please install it manually. " ) . arg ( error ) ) ;
}
2010-05-30 21:51:40 +04:00
# endif
2009-08-25 06:31:36 +04:00
QString SearchEngine : : selectedCategory ( ) const {
return comboCategory - > itemData ( comboCategory - > currentIndex ( ) ) . toString ( ) ;
}
2008-06-25 23:04:42 +04:00
SearchEngine : : ~ SearchEngine ( ) {
qDebug ( " Search destruction " ) ;
// save the searchHistory for later uses
saveSearchHistory ( ) ;
searchProcess - > kill ( ) ;
searchProcess - > waitForFinished ( ) ;
2009-08-25 06:31:36 +04:00
foreach ( QProcess * downloader , downloaders ) {
2009-11-18 13:34:57 +03:00
// Make sure we disconnect the SIGNAL/SLOT first
// To avoid double free
downloader - > disconnect ( ) ;
2009-08-25 06:31:36 +04:00
downloader - > kill ( ) ;
downloader - > waitForFinished ( ) ;
2009-11-18 13:34:57 +03:00
delete downloader ;
2009-08-25 06:31:36 +04:00
}
2010-03-04 21:40:11 +03:00
# if QT_VERSION < 0x040500
2009-11-27 00:11:37 +03:00
delete closeTab_button ;
# endif
2008-06-25 23:04:42 +04:00
delete searchTimeout ;
delete searchProcess ;
2009-08-25 06:31:36 +04:00
delete supported_engines ;
2009-07-12 10:42:38 +04:00
if ( searchCompleter )
delete searchCompleter ;
}
void SearchEngine : : displayPatternContextMenu ( QPoint ) {
QMenu myMenu ( this ) ;
2010-12-12 22:37:59 +03:00
QAction cutAct ( misc : : getIcon ( " edit-cut " ) , tr ( " Cut " ) , & myMenu ) ;
QAction copyAct ( misc : : getIcon ( " edit-copy " ) , tr ( " Copy " ) , & myMenu ) ;
QAction pasteAct ( misc : : getIcon ( " edit-paste " ) , tr ( " Paste " ) , & myMenu ) ;
QAction clearAct ( misc : : getIcon ( " edit-clear " ) , tr ( " Clear field " ) , & myMenu ) ;
QAction clearHistoryAct ( misc : : getIcon ( " edit-clear-history " ) , tr ( " Clear completion history " ) , & myMenu ) ;
2009-07-12 11:12:43 +04:00
bool hasCopyAct = false ;
if ( search_pattern - > hasSelectedText ( ) ) {
myMenu . addAction ( & cutAct ) ;
myMenu . addAction ( & copyAct ) ;
hasCopyAct = true ;
}
if ( qApp - > clipboard ( ) - > mimeData ( ) - > hasText ( ) ) {
myMenu . addAction ( & pasteAct ) ;
hasCopyAct = true ;
}
if ( hasCopyAct )
myMenu . addSeparator ( ) ;
2009-07-12 10:42:38 +04:00
myMenu . addAction ( & clearHistoryAct ) ;
2009-07-12 11:12:43 +04:00
myMenu . addAction ( & clearAct ) ;
2009-07-12 10:42:38 +04:00
QAction * act = myMenu . exec ( QCursor : : pos ( ) ) ;
if ( act ! = 0 ) {
if ( act = = & clearHistoryAct ) {
2010-06-27 20:35:19 +04:00
// Ask for confirmation
if ( QMessageBox : : question ( this , tr ( " Confirmation " ) , tr ( " Are you sure you want to clear the history? " ) , QMessageBox : : Yes | QMessageBox : : No , QMessageBox : : Yes ) = = QMessageBox : : Yes ) {
// Clear history
searchHistory . setStringList ( QStringList ( ) ) ;
}
2009-12-08 22:24:14 +03:00
}
else if ( act = = & pasteAct ) {
2009-07-12 11:12:43 +04:00
search_pattern - > paste ( ) ;
}
else if ( act = = & cutAct ) {
search_pattern - > cut ( ) ;
}
else if ( act = = & copyAct ) {
search_pattern - > copy ( ) ;
}
else if ( act = = & clearAct ) {
search_pattern - > clear ( ) ;
2009-07-12 10:42:38 +04:00
}
}
2008-06-25 23:04:42 +04:00
}
2008-07-04 20:49:08 +04:00
void SearchEngine : : tab_changed ( int t )
2008-06-26 15:24:08 +04:00
{ //when we switch from a tab that is not empty to another that is empty the download button
2009-08-25 06:31:36 +04:00
//doesn't have to be available
if ( t > - 1 )
{ //-1 = no more tab
2008-06-26 15:24:08 +04:00
if ( all_tab . at ( tabWidget - > currentIndex ( ) ) - > getCurrentSearchListModel ( ) - > rowCount ( ) ) {
2009-08-25 06:31:36 +04:00
download_button - > setEnabled ( true ) ;
2010-12-26 12:51:37 +03:00
goToDescBtn - > setEnabled ( true ) ;
2008-06-26 15:24:08 +04:00
} else {
2009-08-25 06:31:36 +04:00
download_button - > setEnabled ( false ) ;
2010-12-26 12:51:37 +03:00
goToDescBtn - > setEnabled ( false ) ;
2008-06-26 15:24:08 +04:00
}
2009-08-25 06:31:36 +04:00
}
2008-06-26 15:24:08 +04:00
}
2008-06-25 23:04:42 +04:00
void SearchEngine : : on_enginesButton_clicked ( ) {
2009-08-25 06:37:11 +04:00
engineSelectDlg * dlg = new engineSelectDlg ( this , supported_engines ) ;
connect ( dlg , SIGNAL ( enginesChanged ( ) ) , this , SLOT ( fillCatCombobox ( ) ) ) ;
2008-06-25 23:04:42 +04:00
}
2007-03-27 22:49:29 +04:00
2010-07-16 19:03:18 +04:00
// get the last searchs from a QIniSettings to a QStringList
2007-03-27 22:49:29 +04:00
void SearchEngine : : startSearchHistory ( ) {
2010-07-16 19:03:18 +04:00
QIniSettings settings ( " qBittorrent " , " qBittorrent " ) ;
2009-11-14 23:24:39 +03:00
searchHistory . setStringList ( settings . value ( " Search/searchHistory " , QStringList ( ) ) . toStringList ( ) ) ;
2007-03-27 22:49:29 +04:00
}
2010-07-16 19:03:18 +04:00
// Save the history list into the QIniSettings for the next session
2009-11-14 23:24:39 +03:00
void SearchEngine : : saveSearchHistory ( ) {
2010-07-16 19:03:18 +04:00
QIniSettings settings ( " qBittorrent " , " qBittorrent " ) ;
2009-11-14 23:24:39 +03:00
settings . setValue ( " Search/searchHistory " , searchHistory . stringList ( ) ) ;
2007-03-27 22:49:29 +04:00
}
2010-01-30 21:15:25 +03:00
void SearchEngine : : searchTextEdited ( QString ) {
// Enable search button
search_button - > setText ( tr ( " Search " ) ) ;
}
2010-07-19 22:49:53 +04:00
void SearchEngine : : giveFocusToSearchInput ( ) {
search_pattern - > setFocus ( ) ;
}
2007-03-27 22:49:29 +04:00
// Function called when we click on search button
void SearchEngine : : on_search_button_clicked ( ) {
2010-06-02 02:47:14 +04:00
# ifdef Q_WS_WIN
if ( ! has_python ) {
if ( QMessageBox : : question ( this , tr ( " Missing Python Interpreter " ) ,
tr ( " Python 2.x is required to use the search engine but it does not seem to be installed. \n Do you want to install it now? " ) ,
QMessageBox : : Yes | QMessageBox : : No , QMessageBox : : Yes ) = = QMessageBox : : Yes ) {
// Download and Install Python
installPython ( ) ;
}
return ;
}
# endif
2007-07-22 17:42:09 +04:00
if ( searchProcess - > state ( ) ! = QProcess : : NotRunning ) {
2010-06-02 17:45:20 +04:00
# ifdef Q_WS_WIN
searchProcess - > kill ( ) ;
# else
2009-08-25 06:31:36 +04:00
searchProcess - > terminate ( ) ;
2010-06-02 17:45:20 +04:00
# endif
2009-08-25 06:31:36 +04:00
search_stopped = true ;
if ( searchTimeout - > isActive ( ) ) {
searchTimeout - > stop ( ) ;
}
2010-01-30 21:15:25 +03:00
if ( search_button - > text ( ) ! = tr ( " Search " ) ) {
search_button - > setText ( tr ( " Search " ) ) ;
return ;
}
2007-07-22 17:42:09 +04:00
}
2010-02-11 00:20:44 +03:00
searchProcess - > waitForFinished ( ) ;
2010-01-08 23:15:08 +03:00
// Reload environment variables (proxy)
searchProcess - > setEnvironment ( QProcess : : systemEnvironment ( ) ) ;
2007-03-27 22:49:29 +04:00
QString pattern = search_pattern - > text ( ) . trimmed ( ) ;
// No search pattern entered
if ( pattern . isEmpty ( ) ) {
QMessageBox : : critical ( 0 , tr ( " Empty search pattern " ) , tr ( " Please type a search pattern first " ) ) ;
return ;
}
2008-06-25 23:52:39 +04:00
// Tab Addition
2008-06-26 00:46:19 +04:00
currentSearchTab = new SearchTab ( this ) ;
2009-03-10 00:24:40 +03:00
connect ( currentSearchTab - > header ( ) , SIGNAL ( sectionResized ( int , int , int ) ) , this , SLOT ( propagateSectionResized ( int , int , int ) ) ) ;
2008-06-26 00:46:19 +04:00
all_tab . append ( currentSearchTab ) ;
2008-06-26 15:24:08 +04:00
tabWidget - > addTab ( currentSearchTab , pattern ) ;
2008-06-26 00:48:58 +04:00
tabWidget - > setCurrentWidget ( currentSearchTab ) ;
2010-03-04 21:40:11 +03:00
# if QT_VERSION < 0x040500
2008-06-25 23:52:39 +04:00
closeTab_button - > setEnabled ( true ) ;
2009-11-27 00:11:37 +03:00
# endif
2007-03-27 22:49:29 +04:00
// if the pattern is not in the pattern
2009-11-14 23:24:39 +03:00
QStringList wordList = searchHistory . stringList ( ) ;
if ( wordList . indexOf ( pattern ) = = - 1 ) {
2007-03-27 22:49:29 +04:00
//update the searchHistory list
2009-11-14 23:24:39 +03:00
wordList . append ( pattern ) ;
2007-03-27 22:49:29 +04:00
// verify the max size of the history
2009-11-14 23:24:39 +03:00
if ( wordList . size ( ) > SEARCHHISTORY_MAXSIZE )
wordList = wordList . mid ( wordList . size ( ) / 2 ) ;
searchHistory . setStringList ( wordList ) ;
2007-03-27 22:49:29 +04:00
}
// Getting checked search engines
QStringList params ;
search_stopped = false ;
2010-01-02 14:22:44 +03:00
params < < misc : : searchEngineLocation ( ) + QDir : : separator ( ) + " nova2.py " ;
2009-08-25 06:31:36 +04:00
params < < supported_engines - > enginesEnabled ( ) . join ( " , " ) ;
2010-03-04 23:19:25 +03:00
qDebug ( " Search with category: %s " , qPrintable ( selectedCategory ( ) ) ) ;
2009-08-25 06:31:36 +04:00
params < < selectedCategory ( ) ;
2007-03-27 22:49:29 +04:00
params < < pattern . split ( " " ) ;
// Update SearchEngine widgets
no_search_results = true ;
nb_search_results = 0 ;
search_result_line_truncated . clear ( ) ;
2008-06-25 23:04:42 +04:00
//on change le texte du label courrant
2008-06-26 00:46:19 +04:00
currentSearchTab - > getCurrentLabel ( ) - > setText ( tr ( " Results " ) + " <i>(0)</i>: " ) ;
2007-03-27 22:49:29 +04:00
// Launch search
2007-12-12 20:14:15 +03:00
searchProcess - > start ( " python " , params , QIODevice : : ReadOnly ) ;
2007-11-30 13:48:00 +03:00
searchTimeout - > start ( 180000 ) ; // 3min
2007-03-27 22:49:29 +04:00
}
2009-07-12 10:42:38 +04:00
void SearchEngine : : createCompleter ( ) {
if ( searchCompleter )
delete searchCompleter ;
2009-11-14 23:24:39 +03:00
searchCompleter = new QCompleter ( & searchHistory ) ;
2009-07-12 10:42:38 +04:00
searchCompleter - > setCaseSensitivity ( Qt : : CaseInsensitive ) ;
search_pattern - > setCompleter ( searchCompleter ) ;
}
2009-03-10 00:24:40 +03:00
void SearchEngine : : propagateSectionResized ( int index , int , int newsize ) {
foreach ( SearchTab * tab , all_tab ) {
tab - > getCurrentTreeView ( ) - > setColumnWidth ( index , newsize ) ;
}
saveResultsColumnsWidth ( ) ;
}
void SearchEngine : : saveResultsColumnsWidth ( ) {
if ( all_tab . size ( ) > 0 ) {
QTreeView * treeview = all_tab . first ( ) - > getCurrentTreeView ( ) ;
2010-07-16 19:03:18 +04:00
QIniSettings settings ( " qBittorrent " , " qBittorrent " ) ;
2009-03-10 00:24:40 +03:00
QStringList width_list ;
QStringList new_width_list ;
short nbColumns = all_tab . first ( ) - > getCurrentSearchListModel ( ) - > columnCount ( ) ;
QString line = settings . value ( " SearchResultsColsWidth " , QString ( ) ) . toString ( ) ;
if ( ! line . isEmpty ( ) ) {
width_list = line . split ( ' ' ) ;
}
for ( short i = 0 ; i < nbColumns ; + + i ) {
if ( treeview - > columnWidth ( i ) < 1 & & width_list . size ( ) = = nbColumns & & width_list . at ( i ) . toInt ( ) > = 1 ) {
// load the former width
new_width_list < < width_list . at ( i ) ;
} else if ( treeview - > columnWidth ( i ) > = 1 ) {
// usual case, save the current width
2010-03-03 20:27:25 +03:00
new_width_list < < QString : : number ( treeview - > columnWidth ( i ) ) ;
2009-03-10 00:24:40 +03:00
} else {
// default width
treeview - > resizeColumnToContents ( i ) ;
2010-03-03 20:27:25 +03:00
new_width_list < < QString : : number ( treeview - > columnWidth ( i ) ) ;
2009-03-10 00:24:40 +03:00
}
}
settings . setValue ( " SearchResultsColsWidth " , new_width_list . join ( " " ) ) ;
}
}
2009-03-28 01:11:41 +03:00
void SearchEngine : : downloadTorrent ( QString engine_url , QString torrent_url ) {
2010-07-23 02:19:42 +04:00
if ( torrent_url . startsWith ( " bc://bt/ " , Qt : : CaseInsensitive ) ) {
qDebug ( " Converting bc link to magnet link " ) ;
torrent_url = misc : : bcLinkToMagnet ( torrent_url ) ;
}
2010-01-06 01:31:06 +03:00
if ( torrent_url . startsWith ( " magnet: " ) ) {
QStringList urls ;
urls < < torrent_url ;
2010-11-14 00:15:52 +03:00
mp_mainWindow - > downloadFromURLList ( urls ) ;
2010-01-06 01:31:06 +03:00
} else {
QProcess * downloadProcess = new QProcess ( this ) ;
2010-06-02 02:47:14 +04:00
downloadProcess - > setEnvironment ( QProcess : : systemEnvironment ( ) ) ;
2010-01-06 01:31:06 +03:00
connect ( downloadProcess , SIGNAL ( finished ( int , QProcess : : ExitStatus ) ) , this , SLOT ( downloadFinished ( int , QProcess : : ExitStatus ) ) ) ;
downloaders < < downloadProcess ;
QStringList params ;
params < < misc : : searchEngineLocation ( ) + QDir : : separator ( ) + " nova2dl.py " ;
params < < engine_url ;
params < < torrent_url ;
// Launch search
downloadProcess - > start ( " python " , params , QIODevice : : ReadOnly ) ;
}
2009-03-28 01:11:41 +03:00
}
2007-03-27 22:49:29 +04:00
void SearchEngine : : searchStarted ( ) {
// Update SearchEngine widgets
search_status - > setText ( tr ( " Searching... " ) ) ;
search_status - > repaint ( ) ;
2009-08-24 14:18:11 +04:00
search_button - > setText ( " Stop " ) ;
2007-03-27 22:49:29 +04:00
}
// search Qprocess return output as soon as it gets new
// stuff to read. We split it into lines and add each
// line to search results calling appendSearchResult().
void SearchEngine : : readSearchOutput ( ) {
QByteArray output = searchProcess - > readAllStandardOutput ( ) ;
2007-12-13 00:45:44 +03:00
output . replace ( " \r " , " " ) ;
2007-03-27 22:49:29 +04:00
QList < QByteArray > lines_list = output . split ( ' \n ' ) ;
if ( ! search_result_line_truncated . isEmpty ( ) ) {
QByteArray end_of_line = lines_list . takeFirst ( ) ;
lines_list . prepend ( search_result_line_truncated + end_of_line ) ;
}
search_result_line_truncated = lines_list . takeLast ( ) . trimmed ( ) ;
2009-01-24 23:04:19 +03:00
foreach ( const QByteArray & line , lines_list ) {
2009-03-26 18:46:35 +03:00
appendSearchResult ( QString : : fromUtf8 ( line ) ) ;
2007-03-27 22:49:29 +04:00
}
2009-12-28 23:52:21 +03:00
if ( currentSearchTab )
2010-03-03 20:27:25 +03:00
currentSearchTab - > getCurrentLabel ( ) - > setText ( tr ( " Results " ) + QString : : fromUtf8 ( " <i>( " ) + QString : : number ( nb_search_results ) + QString : : fromUtf8 ( " )</i>: " ) ) ;
2007-03-27 22:49:29 +04:00
}
2009-03-28 01:11:41 +03:00
void SearchEngine : : downloadFinished ( int exitcode , QProcess : : ExitStatus ) {
2009-08-25 06:31:36 +04:00
QProcess * downloadProcess = ( QProcess * ) sender ( ) ;
if ( exitcode = = 0 ) {
QString line = QString : : fromUtf8 ( downloadProcess - > readAllStandardOutput ( ) ) . trimmed ( ) ;
QStringList parts = line . split ( ' ' ) ;
if ( parts . size ( ) = = 2 ) {
QString path = parts [ 0 ] ;
QString url = parts [ 1 ] ;
2010-11-14 00:15:52 +03:00
QBtSession : : instance ( ) - > processDownloadedFile ( url , path ) ;
2009-08-25 06:31:36 +04:00
}
}
qDebug ( " Deleting downloadProcess " ) ;
2009-11-18 13:29:20 +03:00
downloaders . removeOne ( downloadProcess ) ;
2009-08-25 06:31:36 +04:00
delete downloadProcess ;
2009-03-28 01:11:41 +03:00
}
2007-08-31 16:06:31 +04:00
// Update nova.py search plugin if necessary
void SearchEngine : : updateNova ( ) {
qDebug ( " Updating nova " ) ;
2010-10-23 00:13:22 +04:00
// create nova directory if necessary
2010-01-02 14:22:44 +03:00
QDir search_dir ( misc : : searchEngineLocation ( ) ) ;
2010-07-24 14:41:44 +04:00
QFile package_file ( search_dir . absoluteFilePath ( " __init__.py " ) ) ;
2007-08-31 16:06:31 +04:00
package_file . open ( QIODevice : : WriteOnly | QIODevice : : Text ) ;
package_file . close ( ) ;
if ( ! search_dir . exists ( " engines " ) ) {
search_dir . mkdir ( " engines " ) ;
2007-03-27 22:49:29 +04:00
}
2010-07-24 14:41:44 +04:00
QFile package_file2 ( search_dir . absolutePath ( ) . replace ( " \\ " , " / " ) + " /engines/__init__.py " ) ;
2007-08-31 16:06:31 +04:00
package_file2 . open ( QIODevice : : WriteOnly | QIODevice : : Text ) ;
package_file2 . close ( ) ;
// Copy search plugin files (if necessary)
2010-07-24 14:41:44 +04:00
QString filePath = search_dir . absoluteFilePath ( " nova2.py " ) ;
2010-12-26 12:51:37 +03:00
if ( getPluginVersion ( " :/nova2/nova2.py " ) > getPluginVersion ( filePath ) ) {
2010-10-02 00:17:04 +04:00
if ( QFile : : exists ( filePath ) ) {
2010-07-24 23:26:26 +04:00
misc : : safeRemove ( filePath ) ;
2010-10-02 00:17:04 +04:00
misc : : safeRemove ( filePath + " c " ) ;
}
2010-12-26 12:51:37 +03:00
QFile : : copy ( " :/nova2/nova2.py " , filePath ) ;
2007-03-27 22:49:29 +04:00
}
2009-03-31 00:31:30 +04:00
2010-07-24 14:41:44 +04:00
filePath = search_dir . absoluteFilePath ( " nova2dl.py " ) ;
2010-12-26 12:51:37 +03:00
if ( getPluginVersion ( " :/nova2/nova2dl.py " ) > getPluginVersion ( filePath ) ) {
2009-03-28 01:11:41 +03:00
if ( QFile : : exists ( filePath ) ) {
2010-07-24 23:26:26 +04:00
misc : : safeRemove ( filePath ) ;
2010-10-02 00:17:04 +04:00
misc : : safeRemove ( filePath + " c " ) ;
2009-03-28 01:11:41 +03:00
}
2010-12-26 12:51:37 +03:00
QFile : : copy ( " :/nova2/nova2dl.py " , filePath ) ;
2009-03-28 01:11:41 +03:00
}
2010-07-24 14:41:44 +04:00
filePath = search_dir . absoluteFilePath ( " novaprinter.py " ) ;
2010-12-26 12:51:37 +03:00
if ( getPluginVersion ( " :/nova2/novaprinter.py " ) > getPluginVersion ( filePath ) ) {
2007-09-02 11:58:25 +04:00
if ( QFile : : exists ( filePath ) ) {
2010-07-24 23:26:26 +04:00
misc : : safeRemove ( filePath ) ;
2010-10-02 00:17:04 +04:00
misc : : safeRemove ( filePath + " c " ) ;
2007-09-02 11:58:25 +04:00
}
2010-12-26 12:51:37 +03:00
QFile : : copy ( " :/nova2/novaprinter.py " , filePath ) ;
2007-03-27 22:49:29 +04:00
}
2010-07-24 14:41:44 +04:00
filePath = search_dir . absoluteFilePath ( " helpers.py " ) ;
2010-12-26 12:51:37 +03:00
if ( getPluginVersion ( " :/nova2/helpers.py " ) > getPluginVersion ( filePath ) ) {
2009-03-26 19:49:44 +03:00
if ( QFile : : exists ( filePath ) ) {
2010-07-24 23:26:26 +04:00
misc : : safeRemove ( filePath ) ;
2010-10-02 00:17:04 +04:00
misc : : safeRemove ( filePath + " c " ) ;
2009-03-26 19:49:44 +03:00
}
2010-12-26 12:51:37 +03:00
QFile : : copy ( " :/nova2/helpers.py " , filePath ) ;
2009-03-26 19:49:44 +03:00
}
2010-07-24 14:41:44 +04:00
filePath = search_dir . absoluteFilePath ( " socks.py " ) ;
2010-11-22 20:04:35 +03:00
if ( QFile : : exists ( filePath ) ) {
misc : : safeRemove ( filePath ) ;
misc : : safeRemove ( filePath + " c " ) ;
2010-01-08 23:15:08 +03:00
}
2010-12-26 12:51:37 +03:00
QFile : : copy ( " :/nova2/socks.py " , filePath ) ;
2010-07-24 14:41:44 +04:00
QDir destDir ( QDir ( misc : : searchEngineLocation ( ) ) . absoluteFilePath ( " engines " ) ) ;
2010-12-26 12:51:37 +03:00
QDir shipped_subDir ( " :/nova2/engines/ " ) ;
2007-08-31 20:02:01 +04:00
QStringList files = shipped_subDir . entryList ( ) ;
2009-01-24 23:04:19 +03:00
foreach ( const QString & file , files ) {
2010-07-24 14:41:44 +04:00
QString shipped_file = shipped_subDir . absoluteFilePath ( file ) ;
2007-08-31 16:06:31 +04:00
// Copy python classes
if ( file . endsWith ( " .py " ) ) {
2010-07-24 14:41:44 +04:00
const QString dest_file = destDir . absoluteFilePath ( file ) ;
2010-03-07 00:11:47 +03:00
if ( getPluginVersion ( shipped_file ) > getPluginVersion ( dest_file ) ) {
2010-07-24 14:41:44 +04:00
qDebug ( " shipped %s is more recent then local plugin, updating... " , qPrintable ( file ) ) ;
2010-03-07 00:11:47 +03:00
if ( QFile : : exists ( dest_file ) ) {
qDebug ( " Removing old %s " , qPrintable ( dest_file ) ) ;
2010-07-24 23:26:26 +04:00
misc : : safeRemove ( dest_file ) ;
2010-10-02 00:17:04 +04:00
misc : : safeRemove ( dest_file + " c " ) ;
2007-08-31 20:02:01 +04:00
}
2010-03-07 00:11:47 +03:00
qDebug ( " %s copied to %s " , qPrintable ( shipped_file ) , qPrintable ( dest_file ) ) ;
QFile : : copy ( shipped_file , dest_file ) ;
2007-08-31 16:06:31 +04:00
}
} else {
// Copy icons
if ( file . endsWith ( " .png " ) ) {
2010-07-24 14:41:44 +04:00
if ( ! QFile : : exists ( destDir . absoluteFilePath ( file ) ) ) {
QFile : : copy ( shipped_file , destDir . absoluteFilePath ( file ) ) ;
2007-08-31 16:06:31 +04:00
}
2007-07-21 00:30:33 +04:00
}
2007-03-27 22:49:29 +04:00
}
}
2010-10-02 00:51:08 +04:00
# ifndef Q_WS_WIN
// Fix permissions
misc : : chmod644 ( QDir ( misc : : searchEngineLocation ( ) ) ) ;
# endif
2007-03-27 22:49:29 +04:00
}
// Slot called when search is Finished
// Search can be finished for 3 reasons :
// Error | Stopped by user | Finished normally
void SearchEngine : : searchFinished ( int exitcode , QProcess : : ExitStatus ) {
2009-12-28 23:52:21 +03:00
if ( searchTimeout - > isActive ( ) ) {
searchTimeout - > stop ( ) ;
}
2010-07-16 19:03:18 +04:00
QIniSettings settings ( " qBittorrent " , " qBittorrent " ) ;
2007-09-08 21:07:29 +04:00
bool useNotificationBalloons = settings . value ( " Preferences/General/NotificationBaloons " , true ) . toBool ( ) ;
2010-11-14 00:15:52 +03:00
if ( useNotificationBalloons & & mp_mainWindow - > getCurrentTabWidget ( ) ! = this ) {
mp_mainWindow - > showNotificationBaloon ( tr ( " Search Engine " ) , tr ( " Search has finished " ) ) ;
2007-03-27 22:49:29 +04:00
}
if ( exitcode ) {
2010-06-02 17:45:20 +04:00
# ifdef Q_WS_WIN
search_status - > setText ( tr ( " Search aborted " ) ) ;
# else
2007-03-27 22:49:29 +04:00
search_status - > setText ( tr ( " An error occured during search... " ) ) ;
2010-06-02 17:45:20 +04:00
# endif
2007-03-27 22:49:29 +04:00
} else {
if ( search_stopped ) {
search_status - > setText ( tr ( " Search aborted " ) ) ;
} else {
if ( no_search_results ) {
search_status - > setText ( tr ( " Search returned no results " ) ) ;
} else {
search_status - > setText ( tr ( " Search has finished " ) ) ;
}
}
}
2008-06-26 00:46:19 +04:00
if ( currentSearchTab )
2010-03-03 20:27:25 +03:00
currentSearchTab - > getCurrentLabel ( ) - > setText ( tr ( " Results " , " i.e: Search results " ) + QString : : fromUtf8 ( " <i>( " ) + QString : : number ( nb_search_results ) + QString : : fromUtf8 ( " )</i>: " ) ) ;
2009-08-24 14:18:11 +04:00
search_button - > setText ( " Search " ) ;
2007-03-27 22:49:29 +04:00
}
// SLOT to append one line to search results list
// Line is in the following form :
// file url | file name | file size | nb seeds | nb leechers | Search engine url
2010-12-26 12:51:37 +03:00
void SearchEngine : : appendSearchResult ( const QString & line ) {
2009-12-28 23:52:21 +03:00
if ( ! currentSearchTab ) {
if ( searchProcess - > state ( ) ! = QProcess : : NotRunning ) {
searchProcess - > terminate ( ) ;
}
if ( searchTimeout - > isActive ( ) ) {
searchTimeout - > stop ( ) ;
}
search_stopped = true ;
return ;
}
2010-12-26 12:51:37 +03:00
const QStringList parts = line . split ( " | " ) ;
const int nb_fields = parts . size ( ) ;
if ( nb_fields < NB_PLUGIN_COLUMNS - 1 ) { //-1 because desc_link is optional
2007-03-27 22:49:29 +04:00
return ;
}
2009-12-28 23:52:21 +03:00
Q_ASSERT ( currentSearchTab ) ;
2007-03-27 22:49:29 +04:00
// Add item to search result list
2009-10-25 02:49:10 +04:00
QStandardItemModel * cur_model = currentSearchTab - > getCurrentSearchListModel ( ) ;
2009-12-28 23:52:21 +03:00
Q_ASSERT ( cur_model ) ;
2009-08-27 16:37:39 +04:00
int row = cur_model - > rowCount ( ) ;
cur_model - > insertRow ( row ) ;
2010-12-26 12:51:37 +03:00
cur_model - > setData ( cur_model - > index ( row , DL_LINK ) , parts . at ( PL_DL_LINK ) . trimmed ( ) ) ; // download URL
cur_model - > setData ( cur_model - > index ( row , NAME ) , parts . at ( PL_NAME ) . trimmed ( ) ) ; // Name
cur_model - > setData ( cur_model - > index ( row , SIZE ) , parts . at ( PL_SIZE ) . trimmed ( ) . toLongLong ( ) ) ; // Size
2009-08-27 16:37:39 +04:00
bool ok = false ;
2010-12-26 12:51:37 +03:00
qlonglong nb_seeders = parts . at ( PL_SEEDS ) . trimmed ( ) . toLongLong ( & ok ) ;
2009-08-27 16:37:39 +04:00
if ( ! ok | | nb_seeders < 0 ) {
2010-12-26 12:51:37 +03:00
cur_model - > setData ( cur_model - > index ( row , SEEDS ) , tr ( " Unknown " ) ) ; // Seeders
2009-08-27 16:37:39 +04:00
} else {
2010-12-26 12:51:37 +03:00
cur_model - > setData ( cur_model - > index ( row , SEEDS ) , nb_seeders ) ; // Seeders
2009-08-27 16:37:39 +04:00
}
2010-12-26 12:51:37 +03:00
qlonglong nb_leechers = parts . at ( PL_LEECHS ) . trimmed ( ) . toLongLong ( & ok ) ;
2009-08-27 16:37:39 +04:00
if ( ! ok | | nb_leechers < 0 ) {
2010-12-26 12:51:37 +03:00
cur_model - > setData ( cur_model - > index ( row , LEECHS ) , tr ( " Unknown " ) ) ; // Leechers
2009-08-27 16:37:39 +04:00
} else {
2010-12-26 12:51:37 +03:00
cur_model - > setData ( cur_model - > index ( row , LEECHS ) , nb_leechers ) ; // Leechers
2007-03-27 22:49:29 +04:00
}
2010-12-26 12:51:37 +03:00
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 ( ) ) ;
2009-08-27 16:37:39 +04:00
2007-03-27 22:49:29 +04:00
no_search_results = false ;
+ + nb_search_results ;
// Enable clear & download buttons
download_button - > setEnabled ( true ) ;
2010-12-26 12:51:37 +03:00
goToDescBtn - > setEnabled ( true ) ;
2007-03-27 22:49:29 +04:00
}
2010-03-04 21:40:11 +03:00
# if QT_VERSION >= 0x040500
2009-11-27 00:11:37 +03:00
void SearchEngine : : closeTab ( int index ) {
if ( index = = tabWidget - > indexOf ( currentSearchTab ) ) {
qDebug ( " Deleted current search Tab " ) ;
if ( searchProcess - > state ( ) ! = QProcess : : NotRunning ) {
searchProcess - > terminate ( ) ;
}
if ( searchTimeout - > isActive ( ) ) {
searchTimeout - > stop ( ) ;
}
search_stopped = true ;
currentSearchTab = 0 ;
}
2009-12-28 23:52:21 +03:00
delete all_tab . takeAt ( index ) ;
2009-11-27 00:11:37 +03:00
if ( ! all_tab . size ( ) ) {
download_button - > setEnabled ( false ) ;
2010-12-26 12:51:37 +03:00
goToDescBtn - > setEnabled ( false ) ;
2009-11-27 00:11:37 +03:00
}
}
# else
2007-03-27 22:49:29 +04:00
// Clear search results list
2008-07-06 22:39:07 +04:00
void SearchEngine : : closeTab_button_clicked ( ) {
2008-06-26 00:46:19 +04:00
if ( all_tab . size ( ) ) {
qDebug ( " currentTab rank: %d " , tabWidget - > currentIndex ( ) ) ;
qDebug ( " currentSearchTab rank: %d " , tabWidget - > indexOf ( currentSearchTab ) ) ;
if ( tabWidget - > currentIndex ( ) = = tabWidget - > indexOf ( currentSearchTab ) ) {
2009-08-25 06:31:36 +04:00
qDebug ( " Deleted current search Tab " ) ;
if ( searchProcess - > state ( ) ! = QProcess : : NotRunning ) {
searchProcess - > terminate ( ) ;
}
if ( searchTimeout - > isActive ( ) ) {
searchTimeout - > stop ( ) ;
}
search_stopped = true ;
currentSearchTab = 0 ;
2008-06-26 00:46:19 +04:00
}
delete all_tab . takeAt ( tabWidget - > currentIndex ( ) ) ;
if ( ! all_tab . size ( ) ) {
2009-08-25 06:31:36 +04:00
closeTab_button - > setEnabled ( false ) ;
download_button - > setEnabled ( false ) ;
2008-06-26 00:46:19 +04:00
}
}
2007-03-27 22:49:29 +04:00
}
2009-11-27 00:11:37 +03:00
# endif
2007-03-27 22:49:29 +04:00
// Download selected items in search results list
void SearchEngine : : on_download_button_clicked ( ) {
2008-06-26 00:46:19 +04:00
//QModelIndexList selectedIndexes = currentSearchTab->getCurrentTreeView()->selectionModel()->selectedIndexes();
QModelIndexList selectedIndexes = all_tab . at ( tabWidget - > currentIndex ( ) ) - > getCurrentTreeView ( ) - > selectionModel ( ) - > selectedIndexes ( ) ;
2009-01-24 23:04:19 +03:00
foreach ( const QModelIndex & index , selectedIndexes ) {
2007-03-27 22:49:29 +04:00
if ( index . column ( ) = = NAME ) {
// Get Item url
2009-10-25 02:49:10 +04:00
QSortFilterProxyModel * model = all_tab . at ( tabWidget - > currentIndex ( ) ) - > getCurrentSearchListProxy ( ) ;
2009-03-28 01:11:41 +03:00
QString torrent_url = model - > data ( model - > index ( index . row ( ) , URL_COLUMN ) ) . toString ( ) ;
2009-08-25 06:31:36 +04:00
QString engine_url = model - > data ( model - > index ( index . row ( ) , ENGINE_URL_COLUMN ) ) . toString ( ) ;
2009-03-28 01:11:41 +03:00
downloadTorrent ( engine_url , torrent_url ) ;
2008-06-26 00:46:19 +04:00
all_tab . at ( tabWidget - > currentIndex ( ) ) - > setRowColor ( index . row ( ) , " red " ) ;
2007-03-27 22:49:29 +04:00
}
}
}
2010-12-26 12:51:37 +03:00
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 ) ) ;
}
}
}