1 | /* |
---|
2 | * This file Copyright (C) Mnemosyne LLC |
---|
3 | * |
---|
4 | * This program is free software; you can redistribute it and/or modify |
---|
5 | * it under the terms of the GNU General Public License version 2 |
---|
6 | * as published by the Free Software Foundation. |
---|
7 | * |
---|
8 | * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html |
---|
9 | * |
---|
10 | * $Id: watchdir.cc 12697 2011-08-20 05:19:27Z jordan $ |
---|
11 | */ |
---|
12 | |
---|
13 | #include <iostream> |
---|
14 | |
---|
15 | #include <QDir> |
---|
16 | #include <QFileSystemWatcher> |
---|
17 | #include <QTimer> |
---|
18 | |
---|
19 | #include <libtransmission/transmission.h> |
---|
20 | |
---|
21 | #include "prefs.h" |
---|
22 | #include "torrent-model.h" |
---|
23 | #include "watchdir.h" |
---|
24 | |
---|
25 | /*** |
---|
26 | **** |
---|
27 | ***/ |
---|
28 | |
---|
29 | WatchDir :: WatchDir( const TorrentModel& model ): |
---|
30 | myModel( model ), |
---|
31 | myWatcher( 0 ) |
---|
32 | { |
---|
33 | } |
---|
34 | |
---|
35 | WatchDir :: ~WatchDir( ) |
---|
36 | { |
---|
37 | } |
---|
38 | |
---|
39 | /*** |
---|
40 | **** |
---|
41 | ***/ |
---|
42 | |
---|
43 | int |
---|
44 | WatchDir :: metainfoTest( const QString& filename ) const |
---|
45 | { |
---|
46 | int ret; |
---|
47 | tr_info inf; |
---|
48 | tr_ctor * ctor = tr_ctorNew( 0 ); |
---|
49 | |
---|
50 | // parse |
---|
51 | tr_ctorSetMetainfoFromFile( ctor, filename.toUtf8().constData() ); |
---|
52 | const int err = tr_torrentParse( ctor, &inf ); |
---|
53 | if( err ) |
---|
54 | ret = ERROR; |
---|
55 | else if( myModel.hasTorrent( QString::fromAscii( inf.hashString ) ) ) |
---|
56 | ret = DUPLICATE; |
---|
57 | else |
---|
58 | ret = OK; |
---|
59 | |
---|
60 | // cleanup |
---|
61 | if( !err ) |
---|
62 | tr_metainfoFree( &inf ); |
---|
63 | tr_ctorFree( ctor ); |
---|
64 | return ret; |
---|
65 | } |
---|
66 | |
---|
67 | void |
---|
68 | WatchDir :: onTimeout( ) |
---|
69 | { |
---|
70 | QTimer * t = qobject_cast<QTimer*>(sender()); |
---|
71 | const QString filename = t->objectName( ); |
---|
72 | if( metainfoTest( filename ) == OK ) |
---|
73 | emit torrentFileAdded( filename ); |
---|
74 | t->deleteLater( ); |
---|
75 | } |
---|
76 | |
---|
77 | void |
---|
78 | WatchDir :: setPath( const QString& path, bool isEnabled ) |
---|
79 | { |
---|
80 | // clear out any remnants of the previous watcher, if any |
---|
81 | myWatchDirFiles.clear( ); |
---|
82 | if( myWatcher ) { |
---|
83 | delete myWatcher; |
---|
84 | myWatcher = 0; |
---|
85 | } |
---|
86 | |
---|
87 | // maybe create a new watcher |
---|
88 | if( isEnabled ) { |
---|
89 | myWatcher = new QFileSystemWatcher( ); |
---|
90 | myWatcher->addPath( path ); |
---|
91 | connect( myWatcher, SIGNAL(directoryChanged(const QString&)), this, SLOT(watcherActivated(const QString&))); |
---|
92 | //std::cerr << "watching " << qPrintable(path) << " for new .torrent files" << std::endl; |
---|
93 | watcherActivated( path ); // trigger the watchdir for .torrent files in there already |
---|
94 | } |
---|
95 | } |
---|
96 | |
---|
97 | void |
---|
98 | WatchDir :: watcherActivated( const QString& path ) |
---|
99 | { |
---|
100 | const QDir dir(path); |
---|
101 | |
---|
102 | // get the list of files currently in the watch directory |
---|
103 | QSet<QString> files; |
---|
104 | foreach( QString str, dir.entryList( QDir::Readable|QDir::Files ) ) |
---|
105 | files.insert( str ); |
---|
106 | |
---|
107 | // try to add any new files which end in .torrent |
---|
108 | const QSet<QString> newFiles( files - myWatchDirFiles ); |
---|
109 | const QString torrentSuffix = QString::fromAscii( ".torrent" ); |
---|
110 | foreach( QString name, newFiles ) { |
---|
111 | if( name.endsWith( torrentSuffix, Qt::CaseInsensitive ) ) { |
---|
112 | const QString filename = dir.absoluteFilePath( name ); |
---|
113 | switch( metainfoTest( filename ) ) { |
---|
114 | case OK: |
---|
115 | emit torrentFileAdded( filename ); |
---|
116 | break; |
---|
117 | case DUPLICATE: |
---|
118 | break; |
---|
119 | case ERROR: { |
---|
120 | // give the .torrent a few seconds to finish downloading |
---|
121 | QTimer * t = new QTimer( this ); |
---|
122 | t->setObjectName( dir.absoluteFilePath( name ) ); |
---|
123 | t->setSingleShot( true ); |
---|
124 | connect( t, SIGNAL(timeout()), this, SLOT(onTimeout())); |
---|
125 | t->start( 5000 ); |
---|
126 | } |
---|
127 | } |
---|
128 | } |
---|
129 | } |
---|
130 | |
---|
131 | // update our file list so that we can use it |
---|
132 | // for comparison the next time around |
---|
133 | myWatchDirFiles = files; |
---|
134 | } |
---|