2009-04-09 18:55:47 +00:00
/*
2010-08-01 20:36:13 +00:00
* This file Copyright ( C ) Mnemosyne LLC
2009-04-09 18:55:47 +00:00
*
2010-08-01 20:36:13 +00:00
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation .
*
* http : //www.gnu.org/licenses/old-licenses/gpl-2.0.html
2009-04-09 18:55:47 +00:00
*
2009-05-31 19:33:48 +00:00
* $ Id $
2009-04-09 18:55:47 +00:00
*/
# include <cassert>
# include <ctime>
# include <iostream>
2010-04-27 03:10:32 +00:00
# include <QDBusConnection>
2010-08-01 14:51:28 +00:00
# include <QDBusConnectionInterface>
2010-04-27 03:10:32 +00:00
# include <QDBusError>
# include <QDBusMessage>
2009-10-02 22:53:19 +00:00
# include <QDialogButtonBox>
2009-04-09 18:55:47 +00:00
# include <QIcon>
2009-10-02 22:53:19 +00:00
# include <QLabel>
2009-10-06 00:27:26 +00:00
# include <QLibraryInfo>
2009-04-09 18:55:47 +00:00
# include <QRect>
# include <libtransmission/transmission.h>
# include <libtransmission/tr-getopt.h>
2010-06-22 04:34:16 +00:00
# include <libtransmission/utils.h>
2009-04-13 19:04:21 +00:00
# include <libtransmission/version.h>
2009-04-09 18:55:47 +00:00
2010-08-01 18:55:04 +00:00
# include "add-data.h"
2009-04-09 18:55:47 +00:00
# include "app.h"
2010-04-27 03:10:32 +00:00
# include "dbus-adaptor.h"
2010-07-03 01:10:36 +00:00
# include "formatter.h"
2009-04-09 18:55:47 +00:00
# include "mainwin.h"
# include "options.h"
# include "prefs.h"
# include "session.h"
2009-05-03 17:37:39 +00:00
# include "session-dialog.h"
# include "torrent-model.h"
2009-04-09 18:55:47 +00:00
# include "utils.h"
# include "watchdir.h"
namespace
{
2011-08-20 05:19:27 +00:00
const QString DBUS_SERVICE = QString : : fromAscii ( " com.transmissionbt.Transmission " ) ;
const QString DBUS_OBJECT_PATH = QString : : fromAscii ( " /com/transmissionbt/Transmission " ) ;
const QString DBUS_INTERFACE = QString : : fromAscii ( " com.transmissionbt.Transmission " ) ;
2010-04-27 03:10:32 +00:00
2010-08-09 00:18:26 +00:00
const char * MY_READABLE_NAME ( " transmission-qt " ) ;
2009-04-09 18:55:47 +00:00
const tr_option opts [ ] =
{
{ ' g ' , " config-dir " , " Where to look for configuration files " , " g " , 1 , " <path> " } ,
{ ' m ' , " minimized " , " Start minimized in system tray " , " m " , 0 , NULL } ,
2009-10-05 21:33:39 +00:00
{ ' p ' , " port " , " Port to use when connecting to an existing session " , " p " , 1 , " <port> " } ,
{ ' r ' , " remote " , " Connect to an existing session at the specified hostname " , " r " , 1 , " <host> " } ,
2010-06-05 00:02:20 +00:00
{ ' u ' , " username " , " Username to use when connecting to an existing session " , " u " , 1 , " <username> " } ,
2009-04-09 18:55:47 +00:00
{ ' v ' , " version " , " Show version number and exit " , " v " , 0 , NULL } ,
2009-10-05 21:33:39 +00:00
{ ' w ' , " password " , " Password to use when connecting to an existing session " , " w " , 1 , " <password> " } ,
2009-04-09 18:55:47 +00:00
{ 0 , NULL , NULL , NULL , 0 , NULL }
} ;
const char *
getUsage ( void )
{
2009-09-26 04:11:00 +00:00
return " Usage: \n "
" transmission [OPTIONS...] [torrent files] " ;
2009-04-09 18:55:47 +00:00
}
void
showUsage ( void )
{
2010-08-09 00:18:26 +00:00
tr_getopt_usage ( MY_READABLE_NAME , getUsage ( ) , opts ) ;
2009-04-09 18:55:47 +00:00
exit ( 0 ) ;
}
enum
{
STATS_REFRESH_INTERVAL_MSEC = 3000 ,
SESSION_REFRESH_INTERVAL_MSEC = 3000 ,
MODEL_REFRESH_INTERVAL_MSEC = 3000
} ;
}
MyApp : : MyApp ( int & argc , char * * argv ) :
QApplication ( argc , argv ) ,
myLastFullUpdateTime ( 0 )
{
2011-08-20 05:19:27 +00:00
const QString MY_CONFIG_NAME = QString : : fromAscii ( " transmission " ) ;
2010-08-09 00:18:26 +00:00
setApplicationName ( MY_CONFIG_NAME ) ;
2009-04-09 18:55:47 +00:00
// install the qt translator
2010-07-28 20:17:16 +00:00
qtTranslator . load ( " qt_ " + QLocale : : system ( ) . name ( ) , QLibraryInfo : : location ( QLibraryInfo : : TranslationsPath ) ) ;
installTranslator ( & qtTranslator ) ;
2009-04-09 18:55:47 +00:00
// install the transmission translator
2010-11-25 03:00:25 +00:00
appTranslator . load ( QString ( MY_CONFIG_NAME ) + " _ " + QLocale : : system ( ) . name ( ) , QCoreApplication : : applicationDirPath ( ) + " /translations " ) ;
2010-07-28 20:17:16 +00:00
installTranslator ( & appTranslator ) ;
2010-07-07 00:30:42 +00:00
Formatter : : initUnits ( ) ;
2010-06-22 04:34:16 +00:00
2009-04-09 18:55:47 +00:00
// set the default icon
QIcon icon ;
2011-08-20 05:19:27 +00:00
QList < int > sizes ;
sizes < < 16 < < 22 < < 24 < < 32 < < 48 ;
foreach ( int size , sizes )
icon . addPixmap ( QPixmap ( QString : : fromAscii ( " :/icons/transmission-%1.png " ) . arg ( size ) ) ) ;
2009-04-09 18:55:47 +00:00
setWindowIcon ( icon ) ;
// parse the command-line arguments
int c ;
bool minimized = false ;
const char * optarg ;
2009-10-05 21:33:39 +00:00
const char * host = 0 ;
const char * port = 0 ;
const char * username = 0 ;
const char * password = 0 ;
2009-04-09 18:55:47 +00:00
const char * configDir = 0 ;
2009-09-26 04:11:00 +00:00
QStringList filenames ;
2009-04-09 18:55:47 +00:00
while ( ( c = tr_getopt ( getUsage ( ) , argc , ( const char * * ) argv , opts , & optarg ) ) ) {
switch ( c ) {
case ' g ' : configDir = optarg ; break ;
2009-10-05 21:33:39 +00:00
case ' p ' : port = optarg ; break ;
case ' r ' : host = optarg ; break ;
case ' u ' : username = optarg ; break ;
case ' w ' : password = optarg ; break ;
2009-04-09 18:55:47 +00:00
case ' m ' : minimized = true ; break ;
2010-08-09 00:18:26 +00:00
case ' v ' : std : : cerr < < MY_READABLE_NAME < < ' ' < < LONG_VERSION_STRING < < std : : endl ; : : exit ( 0 ) ; break ;
2009-04-09 18:55:47 +00:00
case TR_OPT_ERR : Utils : : toStderr ( QObject : : tr ( " Invalid option " ) ) ; showUsage ( ) ; break ;
2009-09-26 04:11:00 +00:00
default : filenames . append ( optarg ) ; break ;
2009-04-09 18:55:47 +00:00
}
}
// set the fallback config dir
2011-01-23 18:40:29 +00:00
if ( configDir = = 0 )
2011-08-20 05:19:27 +00:00
configDir = tr_getDefaultConfigDir ( " transmission " ) ;
2009-04-09 18:55:47 +00:00
2011-01-23 18:40:29 +00:00
// ensure our config directory exists
QDir dir ( configDir ) ;
if ( ! dir . exists ( ) )
dir . mkpath ( configDir ) ;
2011-01-23 16:55:15 +00:00
2009-05-03 17:37:39 +00:00
// is this the first time we've run transmission?
const bool firstTime = ! QFile ( QDir ( configDir ) . absoluteFilePath ( " settings.json " ) ) . exists ( ) ;
2009-10-05 21:33:39 +00:00
// initialize the prefs
2009-04-09 18:55:47 +00:00
myPrefs = new Prefs ( configDir ) ;
2009-10-05 21:33:39 +00:00
if ( host ! = 0 )
myPrefs - > set ( Prefs : : SESSION_REMOTE_HOST , host ) ;
if ( port ! = 0 )
myPrefs - > set ( Prefs : : SESSION_REMOTE_PORT , port ) ;
if ( username ! = 0 )
myPrefs - > set ( Prefs : : SESSION_REMOTE_USERNAME , username ) ;
if ( password ! = 0 )
2010-04-16 20:17:52 +00:00
myPrefs - > set ( Prefs : : SESSION_REMOTE_PASSWORD , password ) ;
2009-10-05 21:33:39 +00:00
if ( ( host ! = 0 ) | | ( port ! = 0 ) | | ( username ! = 0 ) | | ( password ! = 0 ) )
myPrefs - > set ( Prefs : : SESSION_IS_REMOTE , true ) ;
2012-12-30 22:51:55 +00:00
if ( myPrefs - > getBool ( Prefs : : START_MINIMIZED ) )
minimized = true ;
// start as minimized only if the system tray present
if ( ! myPrefs - > getBool ( Prefs : : SHOW_TRAY_ICON ) )
minimized = false ;
2009-10-05 21:33:39 +00:00
2009-05-03 17:37:39 +00:00
mySession = new Session ( configDir , * myPrefs ) ;
2009-04-09 18:55:47 +00:00
myModel = new TorrentModel ( * myPrefs ) ;
myWindow = new TrMainWindow ( * mySession , * myPrefs , * myModel , minimized ) ;
myWatchDir = new WatchDir ( * myModel ) ;
2009-05-03 17:37:39 +00:00
// when the session gets torrent info, update the model
2012-12-14 04:34:42 +00:00
connect ( mySession , SIGNAL ( torrentsUpdated ( tr_variant * , bool ) ) , myModel , SLOT ( updateTorrents ( tr_variant * , bool ) ) ) ;
connect ( mySession , SIGNAL ( torrentsUpdated ( tr_variant * , bool ) ) , myWindow , SLOT ( refreshActionSensitivity ( ) ) ) ;
connect ( mySession , SIGNAL ( torrentsRemoved ( tr_variant * ) ) , myModel , SLOT ( removeTorrents ( tr_variant * ) ) ) ;
2010-06-16 03:11:10 +00:00
// when the session source gets changed, request a full refresh
connect ( mySession , SIGNAL ( sourceChanged ( ) ) , this , SLOT ( onSessionSourceChanged ( ) ) ) ;
2009-05-03 17:37:39 +00:00
// when the model sees a torrent for the first time, ask the session for full info on it
2009-04-09 18:55:47 +00:00
connect ( myModel , SIGNAL ( torrentsAdded ( QSet < int > ) ) , mySession , SLOT ( initTorrents ( QSet < int > ) ) ) ;
2010-08-02 03:07:42 +00:00
connect ( myModel , SIGNAL ( torrentsAdded ( QSet < int > ) ) , this , SLOT ( onTorrentsAdded ( QSet < int > ) ) ) ;
2009-04-09 18:55:47 +00:00
mySession - > initTorrents ( ) ;
mySession - > refreshSessionStats ( ) ;
2009-05-03 17:37:39 +00:00
// when torrents are added to the watch directory, tell the session
2009-04-09 18:55:47 +00:00
connect ( myWatchDir , SIGNAL ( torrentFileAdded ( QString ) ) , this , SLOT ( addTorrent ( QString ) ) ) ;
2009-05-03 17:37:39 +00:00
// init from preferences
2009-04-09 18:55:47 +00:00
QList < int > initKeys ;
initKeys < < Prefs : : DIR_WATCH ;
foreach ( int key , initKeys )
refreshPref ( key ) ;
connect ( myPrefs , SIGNAL ( changed ( int ) ) , this , SLOT ( refreshPref ( const int ) ) ) ;
QTimer * timer = & myModelTimer ;
connect ( timer , SIGNAL ( timeout ( ) ) , this , SLOT ( refreshTorrents ( ) ) ) ;
timer - > setSingleShot ( false ) ;
timer - > setInterval ( MODEL_REFRESH_INTERVAL_MSEC ) ;
timer - > start ( ) ;
timer = & myStatsTimer ;
connect ( timer , SIGNAL ( timeout ( ) ) , mySession , SLOT ( refreshSessionStats ( ) ) ) ;
timer - > setSingleShot ( false ) ;
timer - > setInterval ( STATS_REFRESH_INTERVAL_MSEC ) ;
timer - > start ( ) ;
timer = & mySessionTimer ;
connect ( timer , SIGNAL ( timeout ( ) ) , mySession , SLOT ( refreshSessionInfo ( ) ) ) ;
timer - > setSingleShot ( false ) ;
timer - > setInterval ( SESSION_REFRESH_INTERVAL_MSEC ) ;
timer - > start ( ) ;
maybeUpdateBlocklist ( ) ;
2009-05-03 17:37:39 +00:00
if ( ! firstTime )
mySession - > restart ( ) ;
else {
QDialog * d = new SessionDialog ( * mySession , * myPrefs , myWindow ) ;
d - > show ( ) ;
}
2009-09-26 04:11:00 +00:00
2009-10-02 22:53:19 +00:00
if ( ! myPrefs - > getBool ( Prefs : : USER_HAS_GIVEN_INFORMED_CONSENT ) )
{
QDialog * dialog = new QDialog ( myWindow ) ;
dialog - > setModal ( true ) ;
QVBoxLayout * v = new QVBoxLayout ( dialog ) ;
2010-05-01 02:33:44 +00:00
QLabel * l = new QLabel ( tr ( " Transmission is a file-sharing program. When you run a torrent, its data will be made available to others by means of upload. You and you alone are fully responsible for exercising proper judgement and abiding by your local laws. " ) ) ;
2009-10-02 22:53:19 +00:00
l - > setWordWrap ( true ) ;
v - > addWidget ( l ) ;
QDialogButtonBox * box = new QDialogButtonBox ;
box - > addButton ( new QPushButton ( tr ( " &Cancel " ) ) , QDialogButtonBox : : RejectRole ) ;
QPushButton * agree = new QPushButton ( tr ( " I &Agree " ) ) ;
agree - > setDefault ( true ) ;
box - > addButton ( agree , QDialogButtonBox : : AcceptRole ) ;
box - > setSizePolicy ( QSizePolicy : : Expanding , QSizePolicy : : Fixed ) ;
box - > setOrientation ( Qt : : Horizontal ) ;
v - > addWidget ( box ) ;
connect ( box , SIGNAL ( rejected ( ) ) , this , SLOT ( quit ( ) ) ) ;
connect ( box , SIGNAL ( accepted ( ) ) , dialog , SLOT ( deleteLater ( ) ) ) ;
connect ( box , SIGNAL ( accepted ( ) ) , this , SLOT ( consentGiven ( ) ) ) ;
dialog - > show ( ) ;
}
2009-09-26 04:11:00 +00:00
for ( QStringList : : const_iterator it = filenames . begin ( ) , end = filenames . end ( ) ; it ! = end ; + + it )
2010-05-13 23:54:32 +00:00
addTorrent ( * it ) ;
2010-04-27 03:10:32 +00:00
// register as the dbus handler for Transmission
new TrDBusAdaptor ( this ) ;
QDBusConnection bus = QDBusConnection : : sessionBus ( ) ;
2010-08-01 18:55:04 +00:00
if ( ! bus . registerService ( DBUS_SERVICE ) )
2011-08-20 05:19:27 +00:00
std : : cerr < < " couldn't register " < < qPrintable ( DBUS_SERVICE ) < < std : : endl ;
2010-08-01 18:55:04 +00:00
if ( ! bus . registerObject ( DBUS_OBJECT_PATH , this ) )
2011-08-20 05:19:27 +00:00
std : : cerr < < " couldn't register " < < qPrintable ( DBUS_OBJECT_PATH ) < < std : : endl ;
2009-04-09 18:55:47 +00:00
}
2011-07-26 02:56:30 +00:00
/* these functions are for popping up desktop notifications */
2010-08-01 14:51:28 +00:00
void
2010-08-02 03:07:42 +00:00
MyApp : : onTorrentsAdded ( QSet < int > torrents )
2010-08-01 14:51:28 +00:00
{
2010-08-02 03:07:42 +00:00
if ( ! myPrefs - > getBool ( Prefs : : SHOW_DESKTOP_NOTIFICATION ) )
return ;
2010-08-01 15:47:42 +00:00
foreach ( int id , torrents )
{
Torrent * tor = myModel - > getTorrentFromId ( id ) ;
2011-07-26 02:56:30 +00:00
if ( tor - > name ( ) . isEmpty ( ) ) // wait until the torrent's INFO fields are loaded
2010-08-02 03:07:42 +00:00
connect ( tor , SIGNAL ( torrentChanged ( int ) ) , this , SLOT ( onNewTorrentChanged ( int ) ) ) ;
2011-07-26 02:56:30 +00:00
else {
onNewTorrentChanged ( id ) ;
if ( ! tor - > isSeed ( ) )
connect ( tor , SIGNAL ( torrentCompleted ( int ) ) , this , SLOT ( onTorrentCompleted ( int ) ) ) ;
}
2010-08-01 15:47:42 +00:00
}
}
2011-07-26 02:56:30 +00:00
void
MyApp : : onTorrentCompleted ( int id )
{
Torrent * tor = myModel - > getTorrentFromId ( id ) ;
if ( tor & & ! tor - > name ( ) . isEmpty ( ) )
{
notify ( tr ( " Torrent Completed " ) , tor - > name ( ) ) ;
disconnect ( tor , SIGNAL ( torrentCompleted ( int ) ) , this , SLOT ( onTorrentCompleted ( int ) ) ) ;
}
}
2010-08-01 15:47:42 +00:00
void
2010-08-02 03:07:42 +00:00
MyApp : : onNewTorrentChanged ( int id )
2010-08-01 15:47:42 +00:00
{
Torrent * tor = myModel - > getTorrentFromId ( id ) ;
if ( tor & & ! tor - > name ( ) . isEmpty ( ) )
{
const int age_secs = tor - > dateAdded ( ) . secsTo ( QDateTime : : currentDateTime ( ) ) ;
if ( age_secs < 30 )
notify ( tr ( " Torrent Added " ) , tor - > name ( ) ) ;
2010-08-02 03:07:42 +00:00
disconnect ( tor , SIGNAL ( torrentChanged ( int ) ) , this , SLOT ( onNewTorrentChanged ( int ) ) ) ;
2011-07-26 02:56:30 +00:00
if ( ! tor - > isSeed ( ) )
connect ( tor , SIGNAL ( torrentCompleted ( int ) ) , this , SLOT ( onTorrentCompleted ( int ) ) ) ;
2010-08-01 15:47:42 +00:00
}
2010-08-01 14:51:28 +00:00
}
2011-07-26 02:56:30 +00:00
/***
* * * *
* * */
2009-10-02 22:53:19 +00:00
void
MyApp : : consentGiven ( )
{
myPrefs - > set < bool > ( Prefs : : USER_HAS_GIVEN_INFORMED_CONSENT , true ) ;
}
2009-04-09 18:55:47 +00:00
MyApp : : ~ MyApp ( )
{
const QRect mainwinRect ( myWindow - > geometry ( ) ) ;
delete myWatchDir ;
delete myWindow ;
delete myModel ;
delete mySession ;
myPrefs - > set ( Prefs : : MAIN_WINDOW_HEIGHT , std : : max ( 100 , mainwinRect . height ( ) ) ) ;
myPrefs - > set ( Prefs : : MAIN_WINDOW_WIDTH , std : : max ( 100 , mainwinRect . width ( ) ) ) ;
myPrefs - > set ( Prefs : : MAIN_WINDOW_X , mainwinRect . x ( ) ) ;
myPrefs - > set ( Prefs : : MAIN_WINDOW_Y , mainwinRect . y ( ) ) ;
delete myPrefs ;
}
/***
* * * *
* * */
void
MyApp : : refreshPref ( int key )
{
switch ( key )
{
case Prefs : : BLOCKLIST_UPDATES_ENABLED :
maybeUpdateBlocklist ( ) ;
break ;
case Prefs : : DIR_WATCH :
case Prefs : : DIR_WATCH_ENABLED : {
const QString path ( myPrefs - > getString ( Prefs : : DIR_WATCH ) ) ;
const bool isEnabled ( myPrefs - > getBool ( Prefs : : DIR_WATCH_ENABLED ) ) ;
myWatchDir - > setPath ( path , isEnabled ) ;
break ;
}
default :
break ;
}
}
void
MyApp : : maybeUpdateBlocklist ( )
{
if ( ! myPrefs - > getBool ( Prefs : : BLOCKLIST_UPDATES_ENABLED ) )
return ;
const QDateTime lastUpdatedAt = myPrefs - > getDateTime ( Prefs : : BLOCKLIST_DATE ) ;
const QDateTime nextUpdateAt = lastUpdatedAt . addDays ( 7 ) ;
const QDateTime now = QDateTime : : currentDateTime ( ) ;
if ( now < nextUpdateAt )
{
mySession - > updateBlocklist ( ) ;
myPrefs - > set ( Prefs : : BLOCKLIST_DATE , now ) ;
}
}
2010-06-16 03:11:10 +00:00
void
MyApp : : onSessionSourceChanged ( )
{
mySession - > initTorrents ( ) ;
mySession - > refreshSessionStats ( ) ;
mySession - > refreshSessionInfo ( ) ;
}
2009-04-09 18:55:47 +00:00
void
MyApp : : refreshTorrents ( )
{
// usually we just poll the torrents that have shown recent activity,
// but we also periodically ask for updates on the others to ensure
// nothing's falling through the cracks.
const time_t now = time ( NULL ) ;
if ( myLastFullUpdateTime + 60 > = now )
mySession - > refreshActiveTorrents ( ) ;
else {
myLastFullUpdateTime = now ;
mySession - > refreshAllTorrents ( ) ;
}
}
2010-04-27 03:10:32 +00:00
/***
* * * *
* * */
2009-04-09 18:55:47 +00:00
void
2010-04-27 03:10:32 +00:00
MyApp : : addTorrent ( const QString & key )
2010-08-01 18:55:04 +00:00
{
const AddData addme ( key ) ;
if ( addme . type ! = addme . NONE )
addTorrent ( addme ) ;
}
void
MyApp : : addTorrent ( const AddData & addme )
2009-04-09 18:55:47 +00:00
{
2010-04-27 03:10:32 +00:00
if ( ! myPrefs - > getBool ( Prefs : : OPTIONS_PROMPT ) )
2010-05-13 23:54:32 +00:00
{
2010-08-01 18:55:04 +00:00
mySession - > addTorrent ( addme ) ;
2010-05-13 23:54:32 +00:00
}
2010-08-01 18:55:04 +00:00
else if ( addme . type = = addme . URL )
2010-05-13 23:54:32 +00:00
{
2010-08-01 18:55:04 +00:00
myWindow - > openURL ( addme . url . toString ( ) ) ;
2009-04-09 18:55:47 +00:00
}
2012-07-13 00:29:40 +00:00
else if ( addme . type = = addme . MAGNET )
{
myWindow - > openURL ( addme . magnet ) ;
}
2010-08-01 18:55:04 +00:00
else
2010-05-13 23:54:32 +00:00
{
2010-08-01 18:55:04 +00:00
Options * o = new Options ( * mySession , * myPrefs , addme , myWindow ) ;
o - > show ( ) ;
2010-05-13 23:54:32 +00:00
}
2010-04-27 03:10:32 +00:00
raise ( ) ;
2009-04-09 18:55:47 +00:00
}
2010-08-01 14:51:28 +00:00
/***
* * * *
* * */
2010-04-27 03:10:32 +00:00
void
MyApp : : raise ( )
{
QApplication : : alert ( myWindow ) ;
}
2009-04-09 18:55:47 +00:00
2010-08-01 14:51:28 +00:00
bool
2010-08-01 15:47:42 +00:00
MyApp : : notify ( const QString & title , const QString & body ) const
2010-08-01 14:51:28 +00:00
{
2011-08-20 05:19:27 +00:00
const QString dbusServiceName = QString : : fromAscii ( " org.freedesktop.Notifications " ) ;
const QString dbusInterfaceName = QString : : fromAscii ( " org.freedesktop.Notifications " ) ;
const QString dbusPath = QString : : fromAscii ( " /org/freedesktop/Notifications " ) ;
2010-08-01 14:51:28 +00:00
2011-08-20 05:19:27 +00:00
QDBusMessage m = QDBusMessage : : createMethodCall ( dbusServiceName , dbusPath , dbusInterfaceName , QString : : fromAscii ( " Notify " ) ) ;
2010-08-01 14:51:28 +00:00
QList < QVariant > args ;
2011-08-20 05:19:27 +00:00
args . append ( QString : : fromAscii ( " Transmission " ) ) ; // app_name
args . append ( 0U ) ; // replaces_id
args . append ( QString : : fromAscii ( " transmission " ) ) ; // icon
args . append ( title ) ; // summary
args . append ( body ) ; // body
args . append ( QStringList ( ) ) ; // actions - unused for plain passive popups
args . append ( QVariantMap ( ) ) ; // hints - unused atm
args . append ( int32_t ( - 1 ) ) ; // use the default timeout period
2010-08-01 14:51:28 +00:00
m . setArguments ( args ) ;
QDBusMessage replyMsg = QDBusConnection : : sessionBus ( ) . call ( m ) ;
//std::cerr << qPrintable(replyMsg.errorName()) << std::endl;
//std::cerr << qPrintable(replyMsg.errorMessage()) << std::endl;
return ( replyMsg . type ( ) = = QDBusMessage : : ReplyMessage ) & & ! replyMsg . arguments ( ) . isEmpty ( ) ;
}
2009-04-09 18:55:47 +00:00
/***
* * * *
* * */
int
main ( int argc , char * argv [ ] )
{
2010-04-27 03:10:32 +00:00
// find .torrents, URLs, magnet links, etc in the command-line args
int c ;
QStringList addme ;
const char * optarg ;
char * * argvv = argv ;
while ( ( c = tr_getopt ( getUsage ( ) , argc , ( const char * * ) argvv , opts , & optarg ) ) )
if ( c = = TR_OPT_UNK )
addme . append ( optarg ) ;
// try to delegate the work to an existing copy of Transmission
// before starting ourselves...
bool delegated = false ;
QDBusConnection bus = QDBusConnection : : sessionBus ( ) ;
for ( int i = 0 , n = addme . size ( ) ; i < n ; + + i )
{
QDBusMessage request = QDBusMessage : : createMethodCall ( DBUS_SERVICE ,
DBUS_OBJECT_PATH ,
DBUS_INTERFACE ,
2011-08-20 05:19:27 +00:00
QString : : fromAscii ( " AddMetainfo " ) ) ;
2010-04-27 03:10:32 +00:00
QList < QVariant > arguments ;
2010-08-06 14:50:57 +00:00
AddData a ( addme [ i ] ) ;
switch ( a . type ) {
case AddData : : URL : arguments . push_back ( a . url . toString ( ) ) ; break ;
case AddData : : MAGNET : arguments . push_back ( a . magnet ) ; break ;
case AddData : : FILENAME : arguments . push_back ( a . toBase64 ( ) . constData ( ) ) ; break ;
case AddData : : METAINFO : arguments . push_back ( a . toBase64 ( ) . constData ( ) ) ; break ;
default : break ;
}
2010-04-27 03:10:32 +00:00
request . setArguments ( arguments ) ;
QDBusMessage response = bus . call ( request ) ;
2010-08-01 18:55:04 +00:00
//std::cerr << qPrintable(response.errorName()) << std::endl;
//std::cerr << qPrintable(response.errorMessage()) << std::endl;
2010-04-27 03:10:32 +00:00
arguments = response . arguments ( ) ;
delegated | = ( arguments . size ( ) = = 1 ) & & arguments [ 0 ] . toBool ( ) ;
}
if ( delegated )
return 0 ;
tr_optind = 1 ;
2009-04-09 18:55:47 +00:00
MyApp app ( argc , argv ) ;
return app . exec ( ) ;
}