source: trunk/qt/app.cc @ 8233

Last change on this file since 8233 was 8233, checked in by charles, 14 years ago

(trunk) make it possible to #include "version.h" without having to add -I${TOP}/libtransmission/ to your CFLAGS

File size: 8.0 KB
Line 
1/*
2 * This file Copyright (C) 2009 Charles Kerr <charles@transmissionbt.com>
3 *
4 * This file is licensed by the GPL version 2.  Works owned by the
5 * Transmission project are granted a special exemption to clause 2(b)
6 * so that the bulk of its code can remain under the MIT license.
7 * This exemption does not extend to derived works not owned by
8 * the Transmission project.
9 *
10 * $Id:$
11 */
12
13#include <cassert>
14#include <ctime>
15#include <iostream>
16
17#include <QIcon>
18#include <QLibraryInfo>
19#include <QRect>
20#include <QTranslator>
21
22#include <libtransmission/transmission.h>
23#include <libtransmission/tr-getopt.h>
24#include <libtransmission/version.h>
25
26#include "app.h"
27#include "mainwin.h"
28#include "options.h"
29#include "prefs.h"
30#include "torrent-model.h"
31#include "session.h"
32#include "utils.h"
33#include "watchdir.h"
34
35namespace
36{
37    const char * MY_NAME( "transmission" );
38
39    const tr_option opts[] =
40    {
41        { 'g', "config-dir", "Where to look for configuration files", "g", 1, "<path>" },
42        { 'm', "minimized",  "Start minimized in system tray", "m", 0, NULL },
43        { 'p', "paused",  "Pause all torrents on sartup", "p", 0, NULL },
44        { 'r', "remote",  "Remotely control a pre-existing session", "r", 1, "<URL>" },
45        { 'v', "version", "Show version number and exit", "v", 0, NULL },
46        { 0, NULL, NULL, NULL, 0, NULL }
47    };
48
49    const char*
50    getUsage( void )
51    {
52        return "Transmission " LONG_VERSION_STRING "\n"
53               "http://www.transmissionbt.com/\n"
54               "A fast and easy BitTorrent client";
55    }
56
57    void
58    showUsage( void )
59    {
60        tr_getopt_usage( MY_NAME, getUsage( ), opts );
61        exit( 0 );
62    }
63
64    enum
65    {
66        STATS_REFRESH_INTERVAL_MSEC = 3000,
67        SESSION_REFRESH_INTERVAL_MSEC = 3000,
68        MODEL_REFRESH_INTERVAL_MSEC = 3000
69    };
70}
71
72MyApp :: MyApp( int& argc, char ** argv ):
73    QApplication( argc, argv ),
74    myLastFullUpdateTime( 0 )
75{
76    setApplicationName( MY_NAME );
77
78    // install the qt translator
79    QTranslator * t = new QTranslator( );
80    t->load( "qt_" + QLocale::system().name(), QLibraryInfo::location(QLibraryInfo::TranslationsPath));
81    installTranslator( t );
82
83    // install the transmission translator
84    t = new QTranslator( );
85    t->load( QString(MY_NAME) + "_" + QLocale::system().name() );
86    installTranslator( t );
87
88    // set the default icon
89    QIcon icon;
90    icon.addPixmap( QPixmap( ":/icons/transmission-16.png" ) );
91    icon.addPixmap( QPixmap( ":/icons/transmission-22.png" ) );
92    icon.addPixmap( QPixmap( ":/icons/transmission-24.png" ) );
93    icon.addPixmap( QPixmap( ":/icons/transmission-32.png" ) );
94    icon.addPixmap( QPixmap( ":/icons/transmission-48.png" ) );
95    setWindowIcon( icon );
96
97    // parse the command-line arguments
98    int c;
99    bool paused = false;
100    bool minimized = false;
101    const char * optarg;
102    const char * configDir = 0;
103    const char * url = 0;
104    while( ( c = tr_getopt( getUsage( ), argc, (const char**)argv, opts, &optarg ) ) ) {
105        switch( c ) {
106            case 'g': configDir = optarg; break;
107            case 'm': minimized = true; break;
108            case 'p': paused = true; break;
109            case 'r': url = optarg; break;
110            case 'v':        Utils::toStderr( QObject::tr( "transmission %1" ).arg( LONG_VERSION_STRING ) ); exit( 0 ); break;
111            case TR_OPT_ERR: Utils::toStderr( QObject::tr( "Invalid option" ) ); showUsage( ); break;
112            default:         Utils::toStderr( QObject::tr( "Got opt %1" ).arg((int)c) ); showUsage( ); break;
113        }
114    }
115
116    // set the fallback config dir
117    if( configDir == 0 )
118        configDir = tr_getDefaultConfigDir( MY_NAME );
119
120    myPrefs = new Prefs ( configDir );
121    mySession = new Session( configDir, *myPrefs, url, paused );
122    myModel = new TorrentModel( *myPrefs );
123    myWindow = new TrMainWindow( *mySession, *myPrefs, *myModel, minimized );
124    myWatchDir = new WatchDir( *myModel );
125
126    /* when the session gets torrent info, update the model */
127    connect( mySession, SIGNAL(torrentsUpdated(tr_benc*,bool)), myModel, SLOT(updateTorrents(tr_benc*,bool)) );
128    connect( mySession, SIGNAL(torrentsUpdated(tr_benc*,bool)), myWindow, SLOT(refreshActionSensitivity()) );
129    connect( mySession, SIGNAL(torrentsRemoved(tr_benc*)), myModel, SLOT(removeTorrents(tr_benc*)) );
130    /* when the model sees a torrent for the first time, ask the session for full info on it */
131    connect( myModel, SIGNAL(torrentsAdded(QSet<int>)), mySession, SLOT(initTorrents(QSet<int>)) );
132
133    mySession->initTorrents( );
134    mySession->refreshSessionStats( );
135
136    /* when torrents are added to the watch directory, tell the session */
137    connect( myWatchDir, SIGNAL(torrentFileAdded(QString)), this, SLOT(addTorrent(QString)) );
138
139    /* init from preferences */
140    QList<int> initKeys;
141    initKeys << Prefs::DIR_WATCH;
142    foreach( int key, initKeys )
143        refreshPref( key );
144    connect( myPrefs, SIGNAL(changed(int)), this, SLOT(refreshPref(const int)) );
145
146    QTimer * timer = &myModelTimer;
147    connect( timer, SIGNAL(timeout()), this, SLOT(refreshTorrents()) );
148    timer->setSingleShot( false );
149    timer->setInterval( MODEL_REFRESH_INTERVAL_MSEC );
150    timer->start( );
151
152    timer = &myStatsTimer;
153    connect( timer, SIGNAL(timeout()), mySession, SLOT(refreshSessionStats()) );
154    timer->setSingleShot( false );
155    timer->setInterval( STATS_REFRESH_INTERVAL_MSEC );
156    timer->start( );
157
158    timer = &mySessionTimer;
159    connect( timer, SIGNAL(timeout()), mySession, SLOT(refreshSessionInfo()) );
160    timer->setSingleShot( false );
161    timer->setInterval( SESSION_REFRESH_INTERVAL_MSEC );
162    timer->start( );
163
164    maybeUpdateBlocklist( );
165}
166
167MyApp :: ~MyApp( )
168{
169    const QRect mainwinRect( myWindow->geometry( ) );
170    delete myWatchDir;
171    delete myWindow;
172    delete myModel;
173    delete mySession;
174
175    myPrefs->set( Prefs :: MAIN_WINDOW_HEIGHT, std::max( 100, mainwinRect.height( ) ) );
176    myPrefs->set( Prefs :: MAIN_WINDOW_WIDTH, std::max( 100, mainwinRect.width( ) ) );
177    myPrefs->set( Prefs :: MAIN_WINDOW_X, mainwinRect.x( ) );
178    myPrefs->set( Prefs :: MAIN_WINDOW_Y, mainwinRect.y( ) );
179    delete myPrefs;
180}
181
182/***
183****
184***/
185
186void
187MyApp :: refreshPref( int key )
188{
189    switch( key )
190    {
191        case Prefs :: BLOCKLIST_UPDATES_ENABLED:
192            maybeUpdateBlocklist( );
193            break;
194
195        case Prefs :: DIR_WATCH:
196        case Prefs :: DIR_WATCH_ENABLED: {
197            const QString path( myPrefs->getString( Prefs::DIR_WATCH ) );
198            const bool isEnabled( myPrefs->getBool( Prefs::DIR_WATCH_ENABLED ) );
199            myWatchDir->setPath( path, isEnabled );
200            break;
201        }
202
203        default:
204            break;
205    }
206}
207
208void
209MyApp :: maybeUpdateBlocklist( )
210{
211    if( !myPrefs->getBool( Prefs :: BLOCKLIST_UPDATES_ENABLED ) )
212        return;
213
214     const QDateTime lastUpdatedAt = myPrefs->getDateTime( Prefs :: BLOCKLIST_DATE );
215     const QDateTime nextUpdateAt = lastUpdatedAt.addDays( 7 );
216     const QDateTime now = QDateTime::currentDateTime( );
217     if( now < nextUpdateAt )
218     {
219         mySession->updateBlocklist( );
220         myPrefs->set( Prefs :: BLOCKLIST_DATE, now );
221     }
222}
223
224void
225MyApp :: refreshTorrents( )
226{
227    // usually we just poll the torrents that have shown recent activity,
228    // but we also periodically ask for updates on the others to ensure
229    // nothing's falling through the cracks.
230    const time_t now = time( NULL );
231    if( myLastFullUpdateTime + 60 >= now )
232        mySession->refreshActiveTorrents( );
233    else {
234        myLastFullUpdateTime = now;
235        mySession->refreshAllTorrents( );
236    }
237}
238
239void
240MyApp :: addTorrent( const QString& filename )
241{
242    if( myPrefs->getBool( Prefs :: OPTIONS_PROMPT ) ) {
243        Options * o = new Options( *mySession, *myPrefs, filename, myWindow );
244        o->show( );
245        QApplication :: alert( o );
246    } else {
247        mySession->addTorrent( filename );
248        QApplication :: alert ( myWindow );
249    }
250}
251
252
253/***
254****
255***/
256
257int
258main( int argc, char * argv[] )
259{
260    MyApp app( argc, argv );
261    return app.exec( );
262}
Note: See TracBrowser for help on using the repository browser.