Changeset 13869


Ignore:
Timestamp:
Jan 26, 2013, 1:19:54 AM (8 years ago)
Author:
jordan
Message:

(qt) copyediting: modify more files to the new indentation/whitespace formatting

Location:
trunk/qt
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/qt/about.cc

    r12697 r13869  
    2929#include "license.h"
    3030
    31 AboutDialog :: AboutDialog( QWidget * parent ):
    32     QDialog( parent, Qt::Dialog ),
    33     myLicenseDialog( new LicenseDialog( this ) )
     31AboutDialog :: AboutDialog (QWidget * parent):
     32  QDialog (parent, Qt::Dialog),
     33  myLicenseDialog (new LicenseDialog (this))
    3434{
    35     setWindowTitle( tr( "About Transmission" ) );
    36     QLabel * l;
    37     QVBoxLayout * v = new QVBoxLayout( this );
     35  setWindowTitle (tr ("About Transmission"));
     36  QLabel * l;
     37  QVBoxLayout * v = new QVBoxLayout (this);
    3838
    39     l = new QLabel;
    40     l->setPixmap( QPixmap( QString::fromAscii( ":/icons/transmission-48.png" ) ) );
    41     l->setAlignment( Qt::AlignCenter );
    42     v->addWidget( l );
     39  l = new QLabel;
     40  l->setPixmap (QPixmap (QString::fromAscii (":/icons/transmission-48.png")));
     41  l->setAlignment (Qt::AlignCenter);
     42  v->addWidget (l);
    4343
    44     QFont f( font( ) );
    45     f.setWeight( QFont::Bold );
    46     f.setPointSize( int( f.pointSize( ) * 1.2 ) );
    47     l = new QLabel( tr( "<big>Transmission %1</big>" ).arg( QString::fromAscii( LONG_VERSION_STRING ) ) );
    48     l->setAlignment( Qt::AlignCenter );
    49     l->setFont( f );
    50     l->setMargin( 8 );
    51     v->addWidget( l );
     44  QFont f (font ());
     45  f.setWeight (QFont::Bold);
     46  f.setPointSize (int (f.pointSize () * 1.2));
     47  l = new QLabel (tr ("<big>Transmission %1</big>").arg (QString::fromAscii (LONG_VERSION_STRING)));
     48  l->setAlignment (Qt::AlignCenter);
     49  l->setFont (f);
     50  l->setMargin (8);
     51  v->addWidget (l);
    5252
    53     l = new QLabel( tr( "A fast and easy BitTorrent client" ) );
    54     l->setStyleSheet( QString::fromAscii( "text-align: center" ) );
    55     l->setAlignment( Qt::AlignCenter );
    56     v->addWidget( l );
     53  l = new QLabel (tr ("A fast and easy BitTorrent client"));
     54  l->setStyleSheet (QString::fromAscii ("text-align: center"));
     55  l->setAlignment (Qt::AlignCenter);
     56  v->addWidget (l);
    5757
    58     l = new QLabel( tr( "Copyright (c) The Transmission Project" ) );
    59     l->setAlignment( Qt::AlignCenter );
    60     v->addWidget( l );
     58  l = new QLabel (tr ("Copyright (c) The Transmission Project"));
     59  l->setAlignment (Qt::AlignCenter);
     60  v->addWidget (l);
    6161
    62     l = new QLabel( QString::fromAscii( "<a href=\"http://www.transmissionbt.com/\">http://www.transmissionbt.com/</a>" ) );
    63     l->setOpenExternalLinks( true );
    64     l->setAlignment( Qt::AlignCenter );
    65     v->addWidget( l );
     62  l = new QLabel (QString::fromAscii ("<a href=\"http://www.transmissionbt.com/\">http://www.transmissionbt.com/</a>"));
     63  l->setOpenExternalLinks (true);
     64  l->setAlignment (Qt::AlignCenter);
     65  v->addWidget (l);
    6666
    67     v->addSpacing( HIG::PAD_BIG );
     67  v->addSpacing (HIG::PAD_BIG);
    6868
    69     QPushButton * b;
    70     QDialogButtonBox * box = new QDialogButtonBox;
     69  QPushButton * b;
     70  QDialogButtonBox * box = new QDialogButtonBox;
    7171
    72     b = new QPushButton( tr( "C&redits" ), this );
    73     box->addButton( b, QDialogButtonBox::ActionRole );
    74     connect( b, SIGNAL(clicked()), this, SLOT(showCredits()) );
     72  b = new QPushButton (tr ("C&redits"), this);
     73  box->addButton (b, QDialogButtonBox::ActionRole);
     74  connect (b, SIGNAL (clicked ()), this, SLOT (showCredits ()));
    7575
    76     b = new QPushButton( tr( "&License" ), this );
    77     box->addButton( b, QDialogButtonBox::ActionRole );
    78     connect( b, SIGNAL(clicked()), myLicenseDialog, SLOT(show()) );
     76  b = new QPushButton (tr ("&License"), this);
     77  box->addButton (b, QDialogButtonBox::ActionRole);
     78  connect (b, SIGNAL (clicked ()), myLicenseDialog, SLOT (show ()));
    7979
    80     box->addButton( QDialogButtonBox::Close );
    81     box->setCenterButtons( true );
    82     v->addWidget( box );
    83     connect( box, SIGNAL(rejected()), this, SLOT(hide()) );
     80  box->addButton (QDialogButtonBox::Close);
     81  box->setCenterButtons (true);
     82  v->addWidget (box);
     83  connect (box, SIGNAL (rejected ()), this, SLOT (hide ()));
    8484}
    8585
    8686void
    87 AboutDialog :: showCredits( )
     87AboutDialog :: showCredits ()
    8888{
    89     QMessageBox::about( this, tr( "Credits" ),
    90         QString::fromAscii( "Jordan Lee (Backend; Daemon; GTK+; Qt)\n"
    91                             "Michell Livingston (Backend; OS X)\n"
    92                             "Kevin Glowacz (Web client)" ) );
     89  QMessageBox::about (
     90    this,
     91    tr ("Credits"),
     92    QString::fromAscii ("Jordan Lee (Backend; Daemon; GTK+; Qt)\n"
     93                        "Michell Livingston (OS X)\n"));
    9394}
    9495
  • trunk/qt/about.h

    r11092 r13869  
    1818class AboutDialog: public QDialog
    1919{
    20         Q_OBJECT
     20    Q_OBJECT
    2121
    22     private:
    23         QDialog * myLicenseDialog;
     22  private:
     23    QDialog * myLicenseDialog;
    2424
    25     public:
    26         AboutDialog( QWidget * parent = 0 );
    27         ~AboutDialog( ) { }
    28         QWidget * createAboutTab( );
    29         QWidget * createAuthorsTab( );
    30         QWidget * createLicenseTab( );
     25  public:
     26    AboutDialog (QWidget * parent = 0);
     27    ~AboutDialog () {}
     28    QWidget * createAboutTab ();
     29    QWidget * createAuthorsTab ();
     30    QWidget * createLicenseTab ();
    3131
    32     public slots:
    33         void showCredits( );
     32  public slots:
     33    void showCredits ();
    3434
    3535};
  • trunk/qt/app.cc

    r13841 r13869  
    4646namespace
    4747{
    48     const QString DBUS_SERVICE     = QString::fromAscii( "com.transmissionbt.Transmission"  );
    49     const QString DBUS_OBJECT_PATH = QString::fromAscii( "/com/transmissionbt/Transmission" );
    50     const QString DBUS_INTERFACE   = QString::fromAscii( "com.transmissionbt.Transmission"  );
    51 
    52     const char * MY_READABLE_NAME( "transmission-qt" );
    53 
    54     const tr_option opts[] =
    55     {
    56         { 'g', "config-dir", "Where to look for configuration files", "g", 1, "<path>" },
    57         { 'm', "minimized",  "Start minimized in system tray", "m", 0, NULL },
    58         { 'p', "port",  "Port to use when connecting to an existing session", "p", 1, "<port>" },
    59         { 'r', "remote",  "Connect to an existing session at the specified hostname", "r", 1, "<host>" },
    60         { 'u', "username", "Username to use when connecting to an existing session", "u", 1, "<username>" },
    61         { 'v', "version", "Show version number and exit", "v", 0, NULL },
    62         { 'w', "password", "Password to use when connecting to an existing session", "w", 1, "<password>" },
    63         { 0, NULL, NULL, NULL, 0, NULL }
    64     };
    65 
    66     const char*
    67     getUsage( void )
    68     {
    69         return "Usage:\n"
    70                "  transmission [OPTIONS...] [torrent files]";
    71     }
    72 
    73     void
    74     showUsage( void )
    75     {
    76         tr_getopt_usage( MY_READABLE_NAME, getUsage( ), opts );
    77         exit( 0 );
    78     }
    79 
    80     enum
    81     {
    82         STATS_REFRESH_INTERVAL_MSEC = 3000,
    83         SESSION_REFRESH_INTERVAL_MSEC = 3000,
    84         MODEL_REFRESH_INTERVAL_MSEC = 3000
    85     };
    86 }
    87 
    88 MyApp :: MyApp( int& argc, char ** argv ):
    89     QApplication( argc, argv ),
    90     myLastFullUpdateTime( 0 )
    91 {
    92     const QString MY_CONFIG_NAME = QString::fromAscii( "transmission" );
    93 
    94     setApplicationName( MY_CONFIG_NAME );
    95 
    96     // install the qt translator
    97     qtTranslator.load( "qt_" + QLocale::system().name(), QLibraryInfo::location(QLibraryInfo::TranslationsPath));
    98     installTranslator( &qtTranslator );
    99 
    100     // install the transmission translator
    101     appTranslator.load( QString(MY_CONFIG_NAME) + "_" + QLocale::system().name(), QCoreApplication::applicationDirPath() + "/translations" );
    102     installTranslator( &appTranslator );
    103 
    104     Formatter::initUnits( );
    105 
    106     // set the default icon
    107     QIcon icon;
    108     QList<int> sizes;
    109     sizes << 16 << 22 << 24 << 32 << 48 << 64 << 72 << 96 << 128 << 192 << 256;
    110     foreach( int size, sizes )
    111         icon.addPixmap( QPixmap( QString::fromAscii(":/icons/transmission-%1.png" ).arg(size) ) );
    112     setWindowIcon( icon );
    113 
    114     // parse the command-line arguments
    115     int c;
    116     bool minimized = false;
    117     const char * optarg;
    118     const char * host = 0;
    119     const char * port = 0;
    120     const char * username = 0;
    121     const char * password = 0;
    122     const char * configDir = 0;
    123     QStringList filenames;
    124     while( ( c = tr_getopt( getUsage( ), argc, (const char**)argv, opts, &optarg ) ) ) {
    125         switch( c ) {
    126             case 'g': configDir = optarg; break;
    127             case 'p': port = optarg; break;
    128             case 'r': host = optarg; break;
    129             case 'u': username = optarg; break;
    130             case 'w': password = optarg; break;
    131             case 'm': minimized = true; break;
    132             case 'v': std::cerr << MY_READABLE_NAME << ' ' << LONG_VERSION_STRING << std::endl; ::exit( 0 ); break;
    133             case TR_OPT_ERR: Utils::toStderr( QObject::tr( "Invalid option" ) ); showUsage( ); break;
    134             default:         filenames.append( optarg ); break;
     48  const QString DBUS_SERVICE     = QString::fromAscii ("com.transmissionbt.Transmission" );
     49  const QString DBUS_OBJECT_PATH = QString::fromAscii ("/com/transmissionbt/Transmission");
     50  const QString DBUS_INTERFACE   = QString::fromAscii ("com.transmissionbt.Transmission" );
     51
     52  const char * MY_READABLE_NAME ("transmission-qt");
     53
     54  const tr_option opts[] =
     55  {
     56    { 'g', "config-dir", "Where to look for configuration files", "g", 1, "<path>" },
     57    { 'm', "minimized",  "Start minimized in system tray", "m", 0, NULL },
     58    { 'p', "port",  "Port to use when connecting to an existing session", "p", 1, "<port>" },
     59    { 'r', "remote",  "Connect to an existing session at the specified hostname", "r", 1, "<host>" },
     60    { 'u', "username", "Username to use when connecting to an existing session", "u", 1, "<username>" },
     61    { 'v', "version", "Show version number and exit", "v", 0, NULL },
     62    { 'w', "password", "Password to use when connecting to an existing session", "w", 1, "<password>" },
     63    { 0, NULL, NULL, NULL, 0, NULL }
     64  };
     65
     66  const char*
     67  getUsage (void)
     68  {
     69    return "Usage:\n"
     70           "  transmission [OPTIONS...] [torrent files]";
     71  }
     72
     73  void
     74  showUsage (void)
     75  {
     76    tr_getopt_usage (MY_READABLE_NAME, getUsage (), opts);
     77    exit (0);
     78  }
     79
     80  enum
     81  {
     82    STATS_REFRESH_INTERVAL_MSEC   = 3000,
     83    SESSION_REFRESH_INTERVAL_MSEC = 3000,
     84    MODEL_REFRESH_INTERVAL_MSEC   = 3000
     85  };
     86}
     87
     88MyApp :: MyApp (int& argc, char ** argv):
     89  QApplication (argc, argv),
     90  myLastFullUpdateTime (0)
     91{
     92  const QString MY_CONFIG_NAME = QString::fromAscii ("transmission");
     93
     94  setApplicationName (MY_CONFIG_NAME);
     95
     96  // install the qt translator
     97  qtTranslator.load ("qt_" + QLocale::system ().name (), QLibraryInfo::location (QLibraryInfo::TranslationsPath));
     98  installTranslator (&qtTranslator);
     99
     100  // install the transmission translator
     101  appTranslator.load (QString (MY_CONFIG_NAME) + "_" + QLocale::system ().name (), QCoreApplication::applicationDirPath () + "/translations");
     102  installTranslator (&appTranslator);
     103
     104  Formatter::initUnits ();
     105
     106  // set the default icon
     107  QIcon icon;
     108  QList<int> sizes;
     109  sizes << 16 << 22 << 24 << 32 << 48 << 64 << 72 << 96 << 128 << 192 << 256;
     110  foreach (int size, sizes)
     111    icon.addPixmap (QPixmap (QString::fromAscii (":/icons/transmission-%1.png").arg (size)));
     112  setWindowIcon (icon);
     113
     114  // parse the command-line arguments
     115  int c;
     116  bool minimized = false;
     117  const char * optarg;
     118  const char * host = 0;
     119  const char * port = 0;
     120  const char * username = 0;
     121  const char * password = 0;
     122  const char * configDir = 0;
     123  QStringList filenames;
     124  while ((c = tr_getopt (getUsage(), argc, (const char**)argv, opts, &optarg)))
     125    {
     126      switch (c)
     127        {
     128          case 'g': configDir = optarg; break;
     129          case 'p': port = optarg; break;
     130          case 'r': host = optarg; break;
     131          case 'u': username = optarg; break;
     132          case 'w': password = optarg; break;
     133          case 'm': minimized = true; break;
     134          case 'v': std::cerr << MY_READABLE_NAME << ' ' << LONG_VERSION_STRING << std::endl; ::exit (0); break;
     135          case TR_OPT_ERR: Utils::toStderr (QObject::tr ("Invalid option")); showUsage (); break;
     136          default:         filenames.append (optarg); break;
    135137        }
    136138    }
    137139
    138     // set the fallback config dir
    139     if( configDir == 0 )
    140         configDir = tr_getDefaultConfigDir( "transmission" );
    141 
    142     // ensure our config directory exists
    143     QDir dir( configDir );
    144     if( !dir.exists() )
    145         dir.mkpath( configDir );
    146 
    147     // is this the first time we've run transmission?
    148     const bool firstTime = !QFile(QDir(configDir).absoluteFilePath("settings.json")).exists();
    149 
    150     // initialize the prefs
    151     myPrefs = new Prefs ( configDir );
    152     if( host != 0 )
    153         myPrefs->set( Prefs::SESSION_REMOTE_HOST, host );
    154     if( port != 0 )
    155         myPrefs->set( Prefs::SESSION_REMOTE_PORT, port );
    156     if( username != 0 )
    157         myPrefs->set( Prefs::SESSION_REMOTE_USERNAME, username );
    158     if( password != 0 )
    159         myPrefs->set( Prefs::SESSION_REMOTE_PASSWORD, password );
    160     if( ( host != 0 ) || ( port != 0 ) || ( username != 0 ) || ( password != 0 ) )
    161         myPrefs->set( Prefs::SESSION_IS_REMOTE, true );
    162     if ( myPrefs->getBool( Prefs::START_MINIMIZED) )
    163         minimized = true;
    164 
    165     // start as minimized only if the system tray present
    166     if ( !myPrefs->getBool( Prefs::SHOW_TRAY_ICON ) )
    167       minimized = false;
    168 
    169     mySession = new Session( configDir, *myPrefs );
    170     myModel = new TorrentModel( *myPrefs );
    171     myWindow = new TrMainWindow( *mySession, *myPrefs, *myModel, minimized );
    172     myWatchDir = new WatchDir( *myModel );
    173 
    174     // when the session gets torrent info, update the model
    175     connect( mySession, SIGNAL(torrentsUpdated(tr_variant*,bool)), myModel, SLOT(updateTorrents(tr_variant*,bool)) );
    176     connect( mySession, SIGNAL(torrentsUpdated(tr_variant*,bool)), myWindow, SLOT(refreshActionSensitivity()) );
    177     connect( mySession, SIGNAL(torrentsRemoved(tr_variant*)), myModel, SLOT(removeTorrents(tr_variant*)) );
    178     // when the session source gets changed, request a full refresh
    179     connect( mySession, SIGNAL(sourceChanged()), this, SLOT(onSessionSourceChanged()) );
    180     // when the model sees a torrent for the first time, ask the session for full info on it
    181     connect( myModel, SIGNAL(torrentsAdded(QSet<int>)), mySession, SLOT(initTorrents(QSet<int>)) );
    182     connect( myModel, SIGNAL(torrentsAdded(QSet<int>)), this, SLOT(onTorrentsAdded(QSet<int>)) );
    183 
    184     mySession->initTorrents( );
    185     mySession->refreshSessionStats( );
    186 
    187     // when torrents are added to the watch directory, tell the session
    188     connect( myWatchDir, SIGNAL(torrentFileAdded(QString)), this, SLOT(addTorrent(QString)) );
    189 
    190     // init from preferences
    191     QList<int> initKeys;
    192     initKeys << Prefs::DIR_WATCH;
    193     foreach( int key, initKeys )
    194         refreshPref( key );
    195     connect( myPrefs, SIGNAL(changed(int)), this, SLOT(refreshPref(const int)) );
    196 
    197     QTimer * timer = &myModelTimer;
    198     connect( timer, SIGNAL(timeout()), this, SLOT(refreshTorrents()) );
    199     timer->setSingleShot( false );
    200     timer->setInterval( MODEL_REFRESH_INTERVAL_MSEC );
    201     timer->start( );
    202 
    203     timer = &myStatsTimer;
    204     connect( timer, SIGNAL(timeout()), mySession, SLOT(refreshSessionStats()) );
    205     timer->setSingleShot( false );
    206     timer->setInterval( STATS_REFRESH_INTERVAL_MSEC );
    207     timer->start( );
    208 
    209     timer = &mySessionTimer;
    210     connect( timer, SIGNAL(timeout()), mySession, SLOT(refreshSessionInfo()) );
    211     timer->setSingleShot( false );
    212     timer->setInterval( SESSION_REFRESH_INTERVAL_MSEC );
    213     timer->start( );
    214 
    215     maybeUpdateBlocklist( );
    216 
    217     if( !firstTime )
    218         mySession->restart( );
    219     else {
    220         QDialog * d = new SessionDialog( *mySession, *myPrefs, myWindow );
    221         d->show( );
    222     }
    223 
    224     if( !myPrefs->getBool( Prefs::USER_HAS_GIVEN_INFORMED_CONSENT ))
    225     {
    226         QDialog * dialog = new QDialog( myWindow );
    227         dialog->setModal( true );
    228         QVBoxLayout * v = new QVBoxLayout( dialog );
    229         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. Any content you share is your sole responsibility."));
    230         l->setWordWrap( true );
    231         v->addWidget( l );
    232         QDialogButtonBox * box = new QDialogButtonBox;
    233         box->addButton( new QPushButton( tr( "&Cancel" ) ), QDialogButtonBox::RejectRole );
    234         QPushButton * agree = new QPushButton( tr( "I &Agree" ) );
    235         agree->setDefault( true );
    236         box->addButton( agree, QDialogButtonBox::AcceptRole );
    237         box->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed );
    238         box->setOrientation( Qt::Horizontal );
    239         v->addWidget( box );
    240         connect( box, SIGNAL(rejected()), this, SLOT(quit()) );
    241         connect( box, SIGNAL(accepted()), dialog, SLOT(deleteLater()) );
    242         connect( box, SIGNAL(accepted()), this, SLOT(consentGiven()) );
    243         dialog->show();
    244     }
    245 
    246     for( QStringList::const_iterator it=filenames.begin(), end=filenames.end(); it!=end; ++it )
    247         addTorrent( *it );
    248 
    249     // register as the dbus handler for Transmission
    250     new TrDBusAdaptor( this );
    251     QDBusConnection bus = QDBusConnection::sessionBus();
    252     if( !bus.registerService( DBUS_SERVICE ) )
    253         std::cerr << "couldn't register " << qPrintable(DBUS_SERVICE) << std::endl;
    254     if( !bus.registerObject( DBUS_OBJECT_PATH, this ) )
    255         std::cerr << "couldn't register " << qPrintable(DBUS_OBJECT_PATH) << std::endl;
     140  // set the fallback config dir
     141  if (configDir == 0)
     142    configDir = tr_getDefaultConfigDir ("transmission");
     143
     144  // ensure our config directory exists
     145  QDir dir (configDir);
     146  if (!dir.exists ())
     147    dir.mkpath (configDir);
     148
     149  // is this the first time we've run transmission?
     150  const bool firstTime = !QFile (QDir (configDir).absoluteFilePath ("settings.json")).exists ();
     151
     152  // initialize the prefs
     153  myPrefs = new Prefs (configDir);
     154  if (host != 0)
     155    myPrefs->set (Prefs::SESSION_REMOTE_HOST, host);
     156  if (port != 0)
     157    myPrefs->set (Prefs::SESSION_REMOTE_PORT, port);
     158  if (username != 0)
     159    myPrefs->set (Prefs::SESSION_REMOTE_USERNAME, username);
     160  if (password != 0)
     161    myPrefs->set (Prefs::SESSION_REMOTE_PASSWORD, password);
     162  if ((host != 0) || (port != 0) || (username != 0) || (password != 0))
     163    myPrefs->set (Prefs::SESSION_IS_REMOTE, true);
     164  if (myPrefs->getBool (Prefs::START_MINIMIZED))
     165    minimized = true;
     166
     167  // start as minimized only if the system tray present
     168  if (!myPrefs->getBool (Prefs::SHOW_TRAY_ICON))
     169    minimized = false;
     170
     171  mySession = new Session (configDir, *myPrefs);
     172  myModel = new TorrentModel (*myPrefs);
     173  myWindow = new TrMainWindow (*mySession, *myPrefs, *myModel, minimized);
     174  myWatchDir = new WatchDir (*myModel);
     175
     176  // when the session gets torrent info, update the model
     177  connect (mySession, SIGNAL (torrentsUpdated (tr_variant*,bool)), myModel, SLOT (updateTorrents (tr_variant*,bool)));
     178  connect (mySession, SIGNAL (torrentsUpdated (tr_variant*,bool)), myWindow, SLOT (refreshActionSensitivity ()));
     179  connect (mySession, SIGNAL (torrentsRemoved (tr_variant*)), myModel, SLOT (removeTorrents (tr_variant*)));
     180  // when the session source gets changed, request a full refresh
     181  connect (mySession, SIGNAL (sourceChanged ()), this, SLOT (onSessionSourceChanged ()));
     182  // when the model sees a torrent for the first time, ask the session for full info on it
     183  connect (myModel, SIGNAL (torrentsAdded (QSet<int>)), mySession, SLOT (initTorrents (QSet<int>)));
     184  connect (myModel, SIGNAL (torrentsAdded (QSet<int>)), this, SLOT (onTorrentsAdded (QSet<int>)));
     185
     186  mySession->initTorrents ();
     187  mySession->refreshSessionStats ();
     188
     189  // when torrents are added to the watch directory, tell the session
     190  connect (myWatchDir, SIGNAL (torrentFileAdded (QString)), this, SLOT (addTorrent (QString)));
     191
     192  // init from preferences
     193  QList<int> initKeys;
     194  initKeys << Prefs::DIR_WATCH;
     195  foreach (int key, initKeys)
     196    refreshPref (key);
     197  connect (myPrefs, SIGNAL (changed (int)), this, SLOT (refreshPref (const int)));
     198
     199  QTimer * timer = &myModelTimer;
     200  connect (timer, SIGNAL (timeout ()), this, SLOT (refreshTorrents ()));
     201  timer->setSingleShot (false);
     202  timer->setInterval (MODEL_REFRESH_INTERVAL_MSEC);
     203  timer->start ();
     204
     205  timer = &myStatsTimer;
     206  connect (timer, SIGNAL (timeout ()), mySession, SLOT (refreshSessionStats ()));
     207  timer->setSingleShot (false);
     208  timer->setInterval (STATS_REFRESH_INTERVAL_MSEC);
     209  timer->start ();
     210
     211  timer = &mySessionTimer;
     212  connect (timer, SIGNAL (timeout ()), mySession, SLOT (refreshSessionInfo ()));
     213  timer->setSingleShot (false);
     214  timer->setInterval (SESSION_REFRESH_INTERVAL_MSEC);
     215  timer->start ();
     216
     217  maybeUpdateBlocklist ();
     218
     219  if (!firstTime)
     220    {
     221      mySession->restart ();
     222    }
     223  else
     224    {
     225      QDialog * d = new SessionDialog (*mySession, *myPrefs, myWindow);
     226      d->show ();
     227    }
     228
     229  if (!myPrefs->getBool (Prefs::USER_HAS_GIVEN_INFORMED_CONSENT))
     230    {
     231      QDialog * dialog = new QDialog (myWindow);
     232      dialog->setModal (true);
     233      QVBoxLayout * v = new QVBoxLayout (dialog);
     234      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. Any content you share is your sole responsibility."));
     235      l->setWordWrap (true);
     236      v->addWidget (l);
     237      QDialogButtonBox * box = new QDialogButtonBox;
     238      box->addButton (new QPushButton (tr ("&Cancel")), QDialogButtonBox::RejectRole);
     239      QPushButton * agree = new QPushButton (tr ("I &Agree"));
     240      agree->setDefault (true);
     241      box->addButton (agree, QDialogButtonBox::AcceptRole);
     242      box->setSizePolicy (QSizePolicy::Expanding, QSizePolicy::Fixed);
     243      box->setOrientation (Qt::Horizontal);
     244      v->addWidget (box);
     245      connect (box, SIGNAL (rejected ()), this, SLOT (quit ()));
     246      connect (box, SIGNAL (accepted ()), dialog, SLOT (deleteLater ()));
     247      connect (box, SIGNAL (accepted ()), this, SLOT (consentGiven ()));
     248      dialog->show ();
     249    }
     250
     251  for (QStringList::const_iterator it=filenames.begin (), end=filenames.end (); it!=end; ++it)
     252    addTorrent (*it);
     253
     254  // register as the dbus handler for Transmission
     255  new TrDBusAdaptor (this);
     256  QDBusConnection bus = QDBusConnection::sessionBus ();
     257  if (!bus.registerService (DBUS_SERVICE))
     258    std::cerr << "couldn't register " << qPrintable (DBUS_SERVICE) << std::endl;
     259  if (!bus.registerObject (DBUS_OBJECT_PATH, this))
     260    std::cerr << "couldn't register " << qPrintable (DBUS_OBJECT_PATH) << std::endl;
    256261}
    257262
     
    259264
    260265void
    261 MyApp :: onTorrentsAdded( QSet<int> torrents )
    262 {
    263     if( !myPrefs->getBool( Prefs::SHOW_NOTIFICATION_ON_ADD ) )
    264         return;
    265 
    266     foreach( int id, torrents )
    267     {
    268         Torrent * tor = myModel->getTorrentFromId( id );
    269 
    270         if( tor->name().isEmpty( ) ) // wait until the torrent's INFO fields are loaded
    271             connect( tor, SIGNAL(torrentChanged(int)), this, SLOT(onNewTorrentChanged(int)) );
    272         else {
    273             onNewTorrentChanged( id );
    274             if( !tor->isSeed( ) )
    275                 connect( tor, SIGNAL(torrentCompleted(int)), this, SLOT(onTorrentCompleted(int)) );
     266MyApp :: onTorrentsAdded (QSet<int> torrents)
     267{
     268  if (!myPrefs->getBool (Prefs::SHOW_NOTIFICATION_ON_ADD))
     269    return;
     270
     271  foreach (int id, torrents)
     272    {
     273      Torrent * tor = myModel->getTorrentFromId (id);
     274
     275      if (tor->name ().isEmpty ()) // wait until the torrent's INFO fields are loaded
     276        {
     277          connect (tor, SIGNAL (torrentChanged (int)), this, SLOT (onNewTorrentChanged (int)));
    276278        }
    277     }
    278 }
    279 
    280 void
    281 MyApp :: onTorrentCompleted( int id )
     279      else
     280        {
     281          onNewTorrentChanged (id);
     282
     283          if (!tor->isSeed ())
     284            connect (tor, SIGNAL (torrentCompleted (int)), this, SLOT (onTorrentCompleted (int)));
     285        }
     286    }
     287}
     288
     289void
     290MyApp :: onTorrentCompleted (int id)
    282291{
    283292  Torrent * tor = myModel->getTorrentFromId (id);
     
    286295    {
    287296      if (myPrefs->getBool (Prefs::SHOW_NOTIFICATION_ON_COMPLETE))
    288         notify (tr("Torrent Completed"), tor->name());
     297        notify (tr ("Torrent Completed"), tor->name ());
    289298
    290299      if (myPrefs->getBool (Prefs::COMPLETE_SOUND_ENABLED))
    291300        {
    292 #if defined( Q_OS_WIN ) || defined( Q_OS_MAC )
    293           QApplication::beep();
     301#if defined (Q_OS_WIN) || defined (Q_OS_MAC)
     302          QApplication::beep ();
    294303#else
    295           QProcess::execute (myPrefs->getString(Prefs::COMPLETE_SOUND_COMMAND));
     304          QProcess::execute (myPrefs->getString (Prefs::COMPLETE_SOUND_COMMAND));
    296305#endif
    297306        }
    298307
    299       disconnect( tor, SIGNAL(torrentCompleted(int)), this, SLOT(onTorrentCompleted(int)) );
    300     }
    301 }
    302 
    303 void
    304 MyApp :: onNewTorrentChanged( int id )
    305 {
    306     Torrent * tor = myModel->getTorrentFromId( id );
    307 
    308     if( tor && !tor->name().isEmpty() )
    309     {
    310         const int age_secs = tor->dateAdded().secsTo(QDateTime::currentDateTime());
    311         if( age_secs < 30 )
    312             notify( tr( "Torrent Added" ), tor->name( ) );
    313 
    314         disconnect( tor, SIGNAL(torrentChanged(int)), this, SLOT(onNewTorrentChanged(int)) );
    315 
    316         if( !tor->isSeed( ) )
    317             connect( tor, SIGNAL(torrentCompleted(int)), this, SLOT(onTorrentCompleted(int)) );
     308      disconnect (tor, SIGNAL (torrentCompleted (int)), this, SLOT (onTorrentCompleted (int)));
     309    }
     310}
     311
     312void
     313MyApp :: onNewTorrentChanged (int id)
     314{
     315  Torrent * tor = myModel->getTorrentFromId (id);
     316
     317  if (tor && !tor->name ().isEmpty ())
     318    {
     319      const int age_secs = tor->dateAdded ().secsTo (QDateTime::currentDateTime ());
     320      if (age_secs < 30)
     321        notify (tr ("Torrent Added"), tor->name ());
     322
     323      disconnect (tor, SIGNAL (torrentChanged (int)), this, SLOT (onNewTorrentChanged (int)));
     324
     325      if (!tor->isSeed ())
     326        connect (tor, SIGNAL (torrentCompleted (int)), this, SLOT (onTorrentCompleted (int)));
    318327    }
    319328}
     
    324333
    325334void
    326 MyApp :: consentGiven( )
    327 {
    328     myPrefs->set<bool>( Prefs::USER_HAS_GIVEN_INFORMED_CONSENT, true );
    329 }
    330 
    331 MyApp :: ~MyApp( )
    332 {
    333     const QRect mainwinRect( myWindow->geometry( ) );
    334     delete myWatchDir;
    335     delete myWindow;
    336     delete myModel;
    337     delete mySession;
    338 
    339     myPrefs->set( Prefs :: MAIN_WINDOW_HEIGHT, std::max( 100, mainwinRect.height( ) ) );
    340     myPrefs->set( Prefs :: MAIN_WINDOW_WIDTH, std::max( 100, mainwinRect.width( ) ) );
    341     myPrefs->set( Prefs :: MAIN_WINDOW_X, mainwinRect.x( ) );
    342     myPrefs->set( Prefs :: MAIN_WINDOW_Y, mainwinRect.y( ) );
    343     delete myPrefs;
     335MyApp :: consentGiven ()
     336{
     337  myPrefs->set<bool> (Prefs::USER_HAS_GIVEN_INFORMED_CONSENT, true);
     338}
     339
     340MyApp :: ~MyApp ()
     341{
     342  const QRect mainwinRect (myWindow->geometry ());
     343  delete myWatchDir;
     344  delete myWindow;
     345  delete myModel;
     346  delete mySession;
     347
     348  myPrefs->set (Prefs :: MAIN_WINDOW_HEIGHT, std::max (100, mainwinRect.height ()));
     349  myPrefs->set (Prefs :: MAIN_WINDOW_WIDTH, std::max (100, mainwinRect.width ()));
     350  myPrefs->set (Prefs :: MAIN_WINDOW_X, mainwinRect.x ());
     351  myPrefs->set (Prefs :: MAIN_WINDOW_Y, mainwinRect.y ());
     352  delete myPrefs;
    344353}
    345354
     
    349358
    350359void
    351 MyApp :: refreshPref( int key )
    352 {
    353     switch( key )
    354     {
    355         case Prefs :: BLOCKLIST_UPDATES_ENABLED:
    356             maybeUpdateBlocklist( );
    357             break;
    358 
    359         case Prefs :: DIR_WATCH:
    360         case Prefs :: DIR_WATCH_ENABLED: {
    361             const QString path( myPrefs->getString( Prefs::DIR_WATCH ) );
    362             const bool isEnabled( myPrefs->getBool( Prefs::DIR_WATCH_ENABLED ) );
    363             myWatchDir->setPath( path, isEnabled );
    364             break;
     360MyApp :: refreshPref (int key)
     361{
     362  switch (key)
     363    {
     364      case Prefs :: BLOCKLIST_UPDATES_ENABLED:
     365        maybeUpdateBlocklist ();
     366        break;
     367
     368      case Prefs :: DIR_WATCH:
     369      case Prefs :: DIR_WATCH_ENABLED:
     370        {
     371          const QString path (myPrefs->getString (Prefs::DIR_WATCH));
     372          const bool isEnabled (myPrefs->getBool (Prefs::DIR_WATCH_ENABLED));
     373          myWatchDir->setPath (path, isEnabled);
     374          break;
    365375        }
    366376
    367         default:
    368             break;
    369     }
    370 }
    371 
    372 void
    373 MyApp :: maybeUpdateBlocklist( )
    374 {
    375     if( !myPrefs->getBool( Prefs :: BLOCKLIST_UPDATES_ENABLED ) )
    376         return;
    377 
    378      const QDateTime lastUpdatedAt = myPrefs->getDateTime( Prefs :: BLOCKLIST_DATE );
    379      const QDateTime nextUpdateAt = lastUpdatedAt.addDays( 7 );
    380      const QDateTime now = QDateTime::currentDateTime( );
    381      if( now < nextUpdateAt )
    382      {
    383          mySession->updateBlocklist( );
    384          myPrefs->set( Prefs :: BLOCKLIST_DATE, now );
    385      }
    386 }
    387 
    388 void
    389 MyApp :: onSessionSourceChanged( )
    390 {
    391     mySession->initTorrents( );
    392     mySession->refreshSessionStats( );
    393     mySession->refreshSessionInfo( );
    394 }
    395 
    396 void
    397 MyApp :: refreshTorrents( )
    398 {
    399     // usually we just poll the torrents that have shown recent activity,
    400     // but we also periodically ask for updates on the others to ensure
    401     // nothing's falling through the cracks.
    402     const time_t now = time( NULL );
    403     if( myLastFullUpdateTime + 60 >= now )
    404         mySession->refreshActiveTorrents( );
    405     else {
    406         myLastFullUpdateTime = now;
    407         mySession->refreshAllTorrents( );
     377      default:
     378        break;
     379    }
     380}
     381
     382void
     383MyApp :: maybeUpdateBlocklist ()
     384{
     385  if (!myPrefs->getBool (Prefs :: BLOCKLIST_UPDATES_ENABLED))
     386    return;
     387
     388  const QDateTime lastUpdatedAt = myPrefs->getDateTime (Prefs :: BLOCKLIST_DATE);
     389  const QDateTime nextUpdateAt = lastUpdatedAt.addDays (7);
     390  const QDateTime now = QDateTime::currentDateTime ();
     391
     392  if (now < nextUpdateAt)
     393    {
     394      mySession->updateBlocklist ();
     395      myPrefs->set (Prefs :: BLOCKLIST_DATE, now);
     396    }
     397}
     398
     399void
     400MyApp :: onSessionSourceChanged ()
     401{
     402  mySession->initTorrents ();
     403  mySession->refreshSessionStats ();
     404  mySession->refreshSessionInfo ();
     405}
     406
     407void
     408MyApp :: refreshTorrents ()
     409{
     410  // usually we just poll the torrents that have shown recent activity,
     411  // but we also periodically ask for updates on the others to ensure
     412  // nothing's falling through the cracks.
     413  const time_t now = time (NULL);
     414  if (myLastFullUpdateTime + 60 >= now)
     415    {
     416      mySession->refreshActiveTorrents ();
     417    }
     418  else
     419    {
     420      myLastFullUpdateTime = now;
     421      mySession->refreshAllTorrents ();
    408422    }
    409423}
     
    414428
    415429void
    416 MyApp :: addTorrent( const QString& key )
    417 {
    418     const AddData addme( key );
    419 
    420     if( addme.type != addme.NONE )
    421         addTorrent( addme );
    422 }
    423 
    424 void
    425 MyApp :: addTorrent( const AddData& addme )
    426 {
    427     if( !myPrefs->getBool( Prefs :: OPTIONS_PROMPT ) )
    428     {
    429         mySession->addTorrent( addme );
    430     }
    431     else if( addme.type == addme.URL )
    432     {
    433         myWindow->openURL( addme.url.toString( ) );
    434     }
    435     else if( addme.type == addme.MAGNET )
    436     {
    437         myWindow->openURL( addme.magnet );
    438     }
    439     else
    440     {
    441         Options * o = new Options( *mySession, *myPrefs, addme, myWindow );
    442         o->show( );
    443     }
    444 
    445     raise( );
     430MyApp :: addTorrent (const QString& key)
     431{
     432  const AddData addme (key);
     433
     434  if (addme.type != addme.NONE)
     435    addTorrent (addme);
     436}
     437
     438void
     439MyApp :: addTorrent (const AddData& addme)
     440{
     441  if (!myPrefs->getBool (Prefs :: OPTIONS_PROMPT))
     442    {
     443      mySession->addTorrent (addme);
     444    }
     445  else if (addme.type == addme.URL)
     446    {
     447      myWindow->openURL (addme.url.toString ());
     448    }
     449  else if (addme.type == addme.MAGNET)
     450    {
     451      myWindow->openURL (addme.magnet);
     452    }
     453  else
     454    {
     455      Options * o = new Options (*mySession, *myPrefs, addme, myWindow);
     456      o->show ();
     457    }
     458
     459  raise ();
    446460}
    447461
     
    451465
    452466void
    453 MyApp :: raise( )
    454 {
    455     QApplication :: alert ( myWindow );
     467MyApp :: raise ()
     468{
     469  QApplication :: alert (myWindow);
    456470}
    457471
    458472bool
    459 MyApp :: notify( const QString& title, const QString& body ) const
    460 {
    461     const QString dbusServiceName   = QString::fromAscii( "org.freedesktop.Notifications" );
    462     const QString dbusInterfaceName = QString::fromAscii( "org.freedesktop.Notifications" );
    463     const QString dbusPath          = QString::fromAscii( "/org/freedesktop/Notifications" );
    464 
    465     QDBusMessage m = QDBusMessage::createMethodCall(dbusServiceName, dbusPath, dbusInterfaceName, QString::fromAscii("Notify"));
    466     QList<QVariant> args;
    467     args.append( QString::fromAscii( "Transmission" ) ); // app_name
    468     args.append( 0U );                                   // replaces_id
    469     args.append( QString::fromAscii( "transmission" ) ); // icon
    470     args.append( title );                                // summary
    471     args.append( body );                                 // body
    472     args.append( QStringList( ) );                       // actions - unused for plain passive popups
    473     args.append( QVariantMap( ) );                       // hints - unused atm
    474     args.append( int32_t(-1) );                          // use the default timeout period
    475     m.setArguments( args );
    476     QDBusMessage replyMsg = QDBusConnection::sessionBus().call(m);
    477     //std::cerr << qPrintable(replyMsg.errorName()) << std::endl;
    478     //std::cerr << qPrintable(replyMsg.errorMessage()) << std::endl;
    479     return (replyMsg.type() == QDBusMessage::ReplyMessage) && !replyMsg.arguments().isEmpty();
     473MyApp :: notify (const QString& title, const QString& body) const
     474{
     475  const QString dbusServiceName   = QString::fromAscii ("org.freedesktop.Notifications");
     476  const QString dbusInterfaceName = QString::fromAscii ("org.freedesktop.Notifications");
     477  const QString dbusPath          = QString::fromAscii ("/org/freedesktop/Notifications");
     478
     479  QDBusMessage m = QDBusMessage::createMethodCall (dbusServiceName, dbusPath, dbusInterfaceName, QString::fromAscii ("Notify"));
     480  QList<QVariant> args;
     481  args.append (QString::fromAscii ("Transmission")); // app_name
     482  args.append (0U);                                   // replaces_id
     483  args.append (QString::fromAscii ("transmission")); // icon
     484  args.append (title);                                // summary
     485  args.append (body);                                 // body
     486  args.append (QStringList ());                       // actions - unused for plain passive popups
     487  args.append (QVariantMap ());                       // hints - unused atm
     488  args.append (int32_t (-1));                          // use the default timeout period
     489  m.setArguments (args);
     490  QDBusMessage replyMsg = QDBusConnection::sessionBus ().call (m);
     491  //std::cerr << qPrintable (replyMsg.errorName ()) << std::endl;
     492  //std::cerr << qPrintable (replyMsg.errorMessage ()) << std::endl;
     493  return (replyMsg.type () == QDBusMessage::ReplyMessage) && !replyMsg.arguments ().isEmpty ();
    480494}
    481495
     
    485499
    486500int
    487 main( int argc, char * argv[] )
    488 {
    489     // find .torrents, URLs, magnet links, etc in the command-line args
    490     int c;
    491     QStringList addme;
    492     const char * optarg;
    493     char ** argvv = argv;
    494     while( ( c = tr_getopt( getUsage( ), argc, (const char **)argvv, opts, &optarg ) ) )
    495         if( c == TR_OPT_UNK )
    496             addme.append( optarg );
    497 
    498     // try to delegate the work to an existing copy of Transmission
    499     // before starting ourselves...
    500     bool delegated = false;
    501     QDBusConnection bus = QDBusConnection::sessionBus();
    502     for( int i=0, n=addme.size(); i<n; ++i )
    503     {
    504         QDBusMessage request = QDBusMessage::createMethodCall( DBUS_SERVICE,
    505                                                                DBUS_OBJECT_PATH,
    506                                                                DBUS_INTERFACE,
    507                                                                QString::fromAscii("AddMetainfo") );
    508         QList<QVariant> arguments;
    509         AddData a( addme[i] );
    510         switch( a.type ) {
    511             case AddData::URL:      arguments.push_back( a.url.toString( ) ); break;
    512             case AddData::MAGNET:   arguments.push_back( a.magnet ); break;
    513             case AddData::FILENAME: arguments.push_back( a.toBase64().constData() ); break;
    514             case AddData::METAINFO: arguments.push_back( a.toBase64().constData() ); break;
    515             default:                break;
     501main (int argc, char * argv[])
     502{
     503  // find .torrents, URLs, magnet links, etc in the command-line args
     504  int c;
     505  QStringList addme;
     506  const char * optarg;
     507  char ** argvv = argv;
     508  while ( (c = tr_getopt (getUsage (), argc, (const char **)argvv, opts, &optarg)))
     509    if (c == TR_OPT_UNK)
     510      addme.append (optarg);
     511
     512  // try to delegate the work to an existing copy of Transmission
     513  // before starting ourselves...
     514  bool delegated = false;
     515  QDBusConnection bus = QDBusConnection::sessionBus ();
     516  for (int i=0, n=addme.size (); i<n; ++i)
     517    {
     518      QDBusMessage request = QDBusMessage::createMethodCall (DBUS_SERVICE,
     519                                                             DBUS_OBJECT_PATH,
     520                                                             DBUS_INTERFACE,
     521                                                             QString::fromAscii ("AddMetainfo"));
     522      QList<QVariant> arguments;
     523      AddData a (addme[i]);
     524      switch (a.type)
     525        {
     526          case AddData::URL:      arguments.push_back (a.url.toString ()); break;
     527          case AddData::MAGNET:   arguments.push_back (a.magnet); break;
     528          case AddData::FILENAME: arguments.push_back (a.toBase64 ().constData ()); break;
     529          case AddData::METAINFO: arguments.push_back (a.toBase64 ().constData ()); break;
     530          default:                break;
    516531        }
    517         request.setArguments( arguments );
    518 
    519         QDBusMessage response = bus.call( request );
    520         //std::cerr << qPrintable(response.errorName()) << std::endl;
    521         //std::cerr << qPrintable(response.errorMessage()) << std::endl;
    522         arguments = response.arguments( );
    523         delegated |= (arguments.size()==1) && arguments[0].toBool();
    524     }
    525 
    526     if( delegated )
    527         return 0;
    528 
    529     tr_optind = 1;
    530     MyApp app( argc, argv );
    531     return app.exec( );
    532 }
     532      request.setArguments (arguments);
     533
     534      QDBusMessage response = bus.call (request);
     535      //std::cerr << qPrintable (response.errorName ()) << std::endl;
     536      //std::cerr << qPrintable (response.errorMessage ()) << std::endl;
     537      arguments = response.arguments ();
     538      delegated |= (arguments.size ()==1) && arguments[0].toBool ();
     539    }
     540
     541  if (delegated)
     542    return 0;
     543
     544  tr_optind = 1;
     545  MyApp app (argc, argv);
     546  return app.exec ();
     547}
  • trunk/qt/app.h

    r12595 r13869  
    3030class MyApp: public QApplication
    3131{
    32         Q_OBJECT
     32    Q_OBJECT
    3333
    34     public:
    35         MyApp( int& argc, char ** argv );
    36         virtual ~MyApp( );
     34  public:
     35    MyApp (int& argc, char ** argv);
     36    virtual ~MyApp ();
    3737
    38     public:
    39         void raise( );
    40         bool notify( const QString& title, const QString& body ) const;
     38  public:
     39    void raise ();
     40    bool notify (const QString& title, const QString& body) const;
    4141
    42     public:
    43         Favicons favicons;
     42  public:
     43    Favicons favicons;
    4444
    45     private:
    46         Prefs * myPrefs;
    47         Session * mySession;
    48         TorrentModel * myModel;
    49         TrMainWindow * myWindow;
    50         WatchDir * myWatchDir;
    51         QTimer myModelTimer;
    52         QTimer myStatsTimer;
    53         QTimer mySessionTimer;
    54         time_t myLastFullUpdateTime;
    55         QTranslator qtTranslator;
    56         QTranslator appTranslator;
     45  private:
     46    Prefs * myPrefs;
     47    Session * mySession;
     48    TorrentModel * myModel;
     49    TrMainWindow * myWindow;
     50    WatchDir * myWatchDir;
     51    QTimer myModelTimer;
     52    QTimer myStatsTimer;
     53    QTimer mySessionTimer;
     54    time_t myLastFullUpdateTime;
     55    QTranslator qtTranslator;
     56    QTranslator appTranslator;
    5757
    58     private slots:
    59         void consentGiven( );
    60         void onSessionSourceChanged( );
    61         void refreshPref( int key );
    62         void refreshTorrents( );
    63         void onTorrentsAdded( QSet<int> );
    64         void onTorrentCompleted( int );
    65         void onNewTorrentChanged( int );
     58  private slots:
     59    void consentGiven ();
     60    void onSessionSourceChanged ();
     61    void refreshPref (int key);
     62    void refreshTorrents ();
     63    void onTorrentsAdded (QSet<int>);
     64    void onTorrentCompleted (int);
     65    void onNewTorrentChanged (int);
    6666
    67     public slots:
    68         void addTorrent( const QString& );
    69         void addTorrent( const AddData& );
     67  public slots:
     68    void addTorrent (const QString&);
     69    void addTorrent (const AddData&);
    7070
    71     private:
    72         void maybeUpdateBlocklist( );
     71  private:
     72    void maybeUpdateBlocklist ();
    7373};
    7474
  • trunk/qt/details.cc

    r13868 r13869  
    4545
    4646#include <libtransmission/transmission.h>
    47 #include <libtransmission/utils.h> // tr_getRatio()
     47#include <libtransmission/utils.h> // tr_getRatio ()
    4848
    4949#include "details.h"
     
    7171    const int REFRESH_INTERVAL_MSEC = 4000;
    7272
    73     const char * PREF_KEY( "pref-key" );
     73    const char * PREF_KEY ("pref-key");
    7474
    7575    enum // peer columns
     
    9797
    9898    public:
    99         virtual ~PeerItem( ) { }
    100         PeerItem( const Peer& p ) {
     99        virtual ~PeerItem () { }
     100        PeerItem (const Peer& p) {
    101101            peer = p;
    102102            int q[4];
    103             if( sscanf( p.address.toUtf8().constData(), "%d.%d.%d.%d", q+0, q+1, q+2, q+3 ) == 4 )
    104                 collatedAddress.sprintf( "%03d.%03d.%03d.%03d", q[0], q[1], q[2], q[3] );
     103            if (sscanf (p.address.toUtf8 ().constData (), "%d.%d.%d.%d", q+0, q+1, q+2, q+3) == 4)
     104                collatedAddress.sprintf ("%03d.%03d.%03d.%03d", q[0], q[1], q[2], q[3]);
    105105            else
    106106                collatedAddress = p.address;
    107107        }
    108108    public:
    109         void refresh( const Peer& p ) { peer = p; }
    110         void setStatus( const QString& s ) { status = s; }
    111         virtual bool operator< ( const QTreeWidgetItem & other ) const {
    112             const PeerItem * i = dynamic_cast<const PeerItem*>(&other);
    113             QTreeWidget * tw( treeWidget( ) );
    114             const int column = tw ? tw->sortColumn() : 0;
    115             switch( column ) {
     109        void refresh (const Peer& p) { peer = p; }
     110        void setStatus (const QString& s) { status = s; }
     111        virtual bool operator< (const QTreeWidgetItem & other) const {
     112            const PeerItem * i = dynamic_cast<const PeerItem*> (&other);
     113            QTreeWidget * tw (treeWidget ());
     114            const int column = tw ? tw->sortColumn () : 0;
     115            switch (column) {
    116116                case COL_UP: return peer.rateToPeer < i->peer.rateToPeer;
    117117                case COL_DOWN: return peer.rateToClient < i->peer.rateToClient;
     
    130130
    131131QIcon
    132 Details :: getStockIcon( const QString& freedesktop_name, int fallback )
    133 {
    134     QIcon icon = QIcon::fromTheme( freedesktop_name );
    135 
    136     if( icon.isNull( ) )
    137         icon = style()->standardIcon( QStyle::StandardPixmap( fallback ), 0, this );
     132Details :: getStockIcon (const QString& freedesktop_name, int fallback)
     133{
     134    QIcon icon = QIcon::fromTheme (freedesktop_name);
     135
     136    if (icon.isNull ())
     137        icon = style ()->standardIcon (QStyle::StandardPixmap (fallback), 0, this);
    138138
    139139    return icon;
    140140}
    141141
    142 Details :: Details( Session& session, Prefs& prefs, TorrentModel& model, QWidget * parent ):
    143     QDialog( parent, Qt::Dialog ),
    144     mySession( session ),
    145     myPrefs( prefs ),
    146     myModel( model ),
    147     myChangedTorrents( false ),
    148     myHavePendingRefresh( false )
    149 {
    150     QVBoxLayout * layout = new QVBoxLayout( this );
    151 
    152     setWindowTitle( tr( "Torrent Properties" ) );
    153 
    154     QTabWidget * t = new QTabWidget( this );
     142Details :: Details (Session& session, Prefs& prefs, TorrentModel& model, QWidget * parent):
     143    QDialog (parent, Qt::Dialog),
     144    mySession (session),
     145    myPrefs (prefs),
     146    myModel (model),
     147    myChangedTorrents (false),
     148    myHavePendingRefresh (false)
     149{
     150    QVBoxLayout * layout = new QVBoxLayout (this);
     151
     152    setWindowTitle (tr ("Torrent Properties"));
     153
     154    QTabWidget * t = new QTabWidget (this);
    155155    QWidget * w;
    156     t->addTab( w = createInfoTab( ),      tr( "Information" ) );
     156    t->addTab (w = createInfoTab (),      tr ("Information"));
    157157    myWidgets << w;
    158     t->addTab( w = createPeersTab( ),     tr( "Peers" ) );
     158    t->addTab (w = createPeersTab (),     tr ("Peers"));
    159159    myWidgets << w;
    160     t->addTab( w = createTrackerTab( ),   tr( "Tracker" ) );
     160    t->addTab (w = createTrackerTab (),   tr ("Tracker"));
    161161    myWidgets << w;
    162     t->addTab( w = createFilesTab( ),     tr( "Files" ) );
     162    t->addTab (w = createFilesTab (),     tr ("Files"));
    163163    myWidgets << w;
    164     t->addTab( w = createOptionsTab( ),   tr( "Options" ) );
     164    t->addTab (w = createOptionsTab (),   tr ("Options"));
    165165    myWidgets << w;
    166     layout->addWidget( t );
    167 
    168     QDialogButtonBox * buttons = new QDialogButtonBox( QDialogButtonBox::Close, Qt::Horizontal, this );
    169     connect( buttons, SIGNAL(rejected()), this, SLOT(close()));
    170     layout->addWidget( buttons );
    171     QWidget::setAttribute( Qt::WA_DeleteOnClose, true );
     166    layout->addWidget (t);
     167
     168    QDialogButtonBox * buttons = new QDialogButtonBox (QDialogButtonBox::Close, Qt::Horizontal, this);
     169    connect (buttons, SIGNAL (rejected ()), this, SLOT (close ()));
     170    layout->addWidget (buttons);
     171    QWidget::setAttribute (Qt::WA_DeleteOnClose, true);
    172172
    173173    QList<int> initKeys;
    174174    initKeys << Prefs :: SHOW_TRACKER_SCRAPES
    175175             << Prefs :: SHOW_BACKUP_TRACKERS;
    176     foreach( int key, initKeys )
    177         refreshPref( key );
    178 
    179     connect( &myTimer, SIGNAL(timeout()), this, SLOT(onTimer()));
    180     connect( &myPrefs, SIGNAL(changed(int)), this, SLOT(refreshPref(int)) );
    181 
    182     onTimer( );
    183     myTimer.setSingleShot( false );
    184     myTimer.start( REFRESH_INTERVAL_MSEC );
    185 }
    186 
    187 Details :: ~Details( )
    188 {
    189     myTrackerDelegate->deleteLater();
    190     myTrackerFilter->deleteLater();
    191     myTrackerModel->deleteLater();
    192 }
    193 
    194 void
    195 Details :: setIds( const QSet<int>& ids )
    196 {
    197     if( ids == myIds )
     176    foreach (int key, initKeys)
     177        refreshPref (key);
     178
     179    connect (&myTimer, SIGNAL (timeout ()), this, SLOT (onTimer ()));
     180    connect (&myPrefs, SIGNAL (changed (int)), this, SLOT (refreshPref (int)));
     181
     182    onTimer ();
     183    myTimer.setSingleShot (false);
     184    myTimer.start (REFRESH_INTERVAL_MSEC);
     185}
     186
     187Details :: ~Details ()
     188{
     189    myTrackerDelegate->deleteLater ();
     190    myTrackerFilter->deleteLater ();
     191    myTrackerModel->deleteLater ();
     192}
     193
     194void
     195Details :: setIds (const QSet<int>& ids)
     196{
     197    if (ids == myIds)
    198198        return;
    199199
     
    201201
    202202    // stop listening to the old torrents
    203     foreach( int id, myIds ) {
    204         const Torrent * tor = myModel.getTorrentFromId( id );
    205         if( tor ) {
    206             disconnect( tor, SIGNAL(torrentChanged(int)), this, SLOT(onTorrentChanged()) );
    207             disconnect( tor, SIGNAL(torrentFileListRebuilt(int)), this, SLOT(onTorrentFileListRebuilt()) );
    208         }
    209     }
    210 
    211     myFileTreeView->clear( );
     203    foreach (int id, myIds) {
     204        const Torrent * tor = myModel.getTorrentFromId (id);
     205        if (tor) {
     206            disconnect (tor, SIGNAL (torrentChanged (int)), this, SLOT (onTorrentChanged ()));
     207            disconnect (tor, SIGNAL (torrentFileListRebuilt (int)), this, SLOT (onTorrentFileListRebuilt ()));
     208        }
     209    }
     210
     211    myFileTreeView->clear ();
    212212    myIds = ids;
    213     myTrackerModel->refresh( myModel, myIds );
     213    myTrackerModel->refresh (myModel, myIds);
    214214
    215215    // listen to the new torrents
    216     foreach( int id, myIds ) {
    217         const Torrent * tor = myModel.getTorrentFromId( id );
    218         if( tor ) {
    219             connect( tor, SIGNAL(torrentChanged(int)), this, SLOT(onTorrentChanged()) );
    220             connect( tor, SIGNAL(torrentFileListRebuilt(int)), this, SLOT(onTorrentFileListRebuilt()) );
    221         }
    222     }
    223 
    224     foreach( QWidget * w, myWidgets )
    225         w->setEnabled( false );
    226 
    227     onTimer( );
    228 }
    229 
    230 void
    231 Details :: refreshPref( int key )
     216    foreach (int id, myIds) {
     217        const Torrent * tor = myModel.getTorrentFromId (id);
     218        if (tor) {
     219            connect (tor, SIGNAL (torrentChanged (int)), this, SLOT (onTorrentChanged ()));
     220            connect (tor, SIGNAL (torrentFileListRebuilt (int)), this, SLOT (onTorrentFileListRebuilt ()));
     221        }
     222    }
     223
     224    foreach (QWidget * w, myWidgets)
     225        w->setEnabled (false);
     226
     227    onTimer ();
     228}
     229
     230void
     231Details :: refreshPref (int key)
    232232{
    233233    QString str;
    234234
    235     switch( key )
     235    switch (key)
    236236    {
    237237        case Prefs :: SHOW_TRACKER_SCRAPES: {
    238             QItemSelectionModel * selectionModel( myTrackerView->selectionModel( ) );
    239             const QItemSelection selection( selectionModel->selection( ) );
    240             const QModelIndex currentIndex( selectionModel->currentIndex( ) );
    241             myTrackerDelegate->setShowMore( myPrefs.getBool( key ) );
    242             selectionModel->clear( );
    243             myTrackerView->reset( );
    244             selectionModel->select( selection, QItemSelectionModel::Select );
    245             selectionModel->setCurrentIndex( currentIndex, QItemSelectionModel::NoUpdate );
     238            QItemSelectionModel * selectionModel (myTrackerView->selectionModel ());
     239            const QItemSelection selection (selectionModel->selection ());
     240            const QModelIndex currentIndex (selectionModel->currentIndex ());
     241            myTrackerDelegate->setShowMore (myPrefs.getBool (key));
     242            selectionModel->clear ();
     243            myTrackerView->reset ();
     244            selectionModel->select (selection, QItemSelectionModel::Select);
     245            selectionModel->setCurrentIndex (currentIndex, QItemSelectionModel::NoUpdate);
    246246            break;
    247247        }
    248248
    249249        case Prefs :: SHOW_BACKUP_TRACKERS:
    250             myTrackerFilter->setShowBackupTrackers( myPrefs.getBool( key ) );
     250            myTrackerFilter->setShowBackupTrackers (myPrefs.getBool (key));
    251251            break;
    252252
     
    262262
    263263QString
    264 Details :: timeToStringRounded( int seconds )
    265 {
    266     if( seconds > 60 ) seconds -= ( seconds % 60 );
    267     return Formatter::timeToString ( seconds );
    268 }
    269 
    270 void
    271 Details :: onTimer( )
    272 {
    273     getNewData( );
    274 }
    275 
    276 void
    277 Details :: getNewData( )
    278 {
    279     if( !myIds.empty( ) )
     264Details :: timeToStringRounded (int seconds)
     265{
     266    if (seconds > 60) seconds -= (seconds % 60);
     267    return Formatter::timeToString (seconds);
     268}
     269
     270void
     271Details :: onTimer ()
     272{
     273    getNewData ();
     274}
     275
     276void
     277Details :: getNewData ()
     278{
     279    if (!myIds.empty ())
    280280    {
    281281        QSet<int> infos;
    282         foreach( int id, myIds ) {
    283             const Torrent * tor = myModel.getTorrentFromId( id );
    284             if( tor->isMagnet() )
    285                 infos.insert( tor->id() );
    286         }
    287         if( !infos.isEmpty() )
    288             mySession.initTorrents( infos );
    289         mySession.refreshExtraStats( myIds );
    290     }
    291 }
    292 
    293 void
    294 Details :: onTorrentChanged( )
    295 {
    296     if( !myHavePendingRefresh ) {
     282        foreach (int id, myIds) {
     283            const Torrent * tor = myModel.getTorrentFromId (id);
     284            if (tor->isMagnet ())
     285                infos.insert (tor->id ());
     286        }
     287        if (!infos.isEmpty ())
     288            mySession.initTorrents (infos);
     289        mySession.refreshExtraStats (myIds);
     290    }
     291}
     292
     293void
     294Details :: onTorrentChanged ()
     295{
     296    if (!myHavePendingRefresh) {
    297297        myHavePendingRefresh = true;
    298         QTimer::singleShot( 100, this, SLOT(refresh()));
    299     }
    300 }
    301 
    302 void
    303 Details :: onTorrentFileListRebuilt( )
     298        QTimer::singleShot (100, this, SLOT (refresh ()));
     299    }
     300}
     301
     302void
     303Details :: onTorrentFileListRebuilt ()
    304304{
    305305  myFilesDirty = true;
    306   onTorrentChanged( );
     306  onTorrentChanged ();
    307307}
    308308
    309309namespace
    310310{
    311     void setIfIdle( QComboBox * box, int i )
    312     {
    313         if( !box->hasFocus( ) )
     311    void setIfIdle (QComboBox * box, int i)
     312    {
     313        if (!box->hasFocus ())
    314314        {
    315             box->blockSignals( true );
    316             box->setCurrentIndex( i );
    317             box->blockSignals( false );
    318         }
    319     }
    320 
    321     void setIfIdle( QDoubleSpinBox * spin, double value )
    322     {
    323         if( !spin->hasFocus( ) )
     315            box->blockSignals (true);
     316            box->setCurrentIndex (i);
     317            box->blockSignals (false);
     318        }
     319    }
     320
     321    void setIfIdle (QDoubleSpinBox * spin, double value)
     322    {
     323        if (!spin->hasFocus ())
    324324        {
    325             spin->blockSignals( true );
    326             spin->setValue( value );
    327             spin->blockSignals( false );
    328         }
    329     }
    330 
    331     void setIfIdle( QSpinBox * spin, int value )
    332     {
    333         if( !spin->hasFocus( ) )
     325            spin->blockSignals (true);
     326            spin->setValue (value);
     327            spin->blockSignals (false);
     328        }
     329    }
     330
     331    void setIfIdle (QSpinBox * spin, int value)
     332    {
     333        if (!spin->hasFocus ())
    334334        {
    335             spin->blockSignals( true );
    336             spin->setValue( value );
    337             spin->blockSignals( false );
    338         }
    339     }
    340 }
    341 
    342 void
    343 Details :: refresh( )
    344 {
    345     const int n = myIds.size( );
     335            spin->blockSignals (true);
     336            spin->setValue (value);
     337            spin->blockSignals (false);
     338        }
     339    }
     340}
     341
     342void
     343Details :: refresh ()
     344{
     345    const int n = myIds.size ();
    346346    const bool single = n == 1;
    347347    const QString blank;
    348     const QFontMetrics fm( fontMetrics( ) );
     348    const QFontMetrics fm (fontMetrics ());
    349349    QList<const Torrent*> torrents;
    350350    QString string;
    351     const QString none = tr( "None" );
    352     const QString mixed = tr( "Mixed" );
    353     const QString unknown = tr( "Unknown" );
     351    const QString none = tr ("None");
     352    const QString mixed = tr ("Mixed");
     353    const QString unknown = tr ("Unknown");
    354354
    355355    // build a list of torrents
    356     foreach( int id, myIds ) {
    357         const Torrent * tor = myModel.getTorrentFromId( id );
    358         if( tor )
     356    foreach (int id, myIds) {
     357        const Torrent * tor = myModel.getTorrentFromId (id);
     358        if (tor)
    359359            torrents << tor;
    360360    }
     
    365365
    366366    // myStateLabel
    367     if( torrents.empty( ) )
     367    if (torrents.empty ())
    368368        string = none;
    369369    else {
     
    371371        bool allPaused = true;
    372372        bool allFinished = true;
    373         const tr_torrent_activity baseline = torrents[0]->getActivity( );
    374         foreach( const Torrent * t, torrents ) {
    375             const tr_torrent_activity activity = t->getActivity( );
    376             if( activity != baseline )
     373        const tr_torrent_activity baseline = torrents[0]->getActivity ();
     374        foreach (const Torrent * t, torrents) {
     375            const tr_torrent_activity activity = t->getActivity ();
     376            if (activity != baseline)
    377377                isMixed = true;
    378             if( activity != TR_STATUS_STOPPED )
     378            if (activity != TR_STATUS_STOPPED)
    379379                allPaused = allFinished = false;
    380             if( !t->isFinished( ) )
     380            if (!t->isFinished ())
    381381                allFinished = false;
    382382        }
    383         if( isMixed )
     383        if (isMixed)
    384384            string = mixed;
    385         else if( allFinished )
    386             string = tr( "Finished" );
    387         else if( allPaused )
    388             string = tr( "Paused" );
     385        else if (allFinished)
     386            string = tr ("Finished");
     387        else if (allPaused)
     388            string = tr ("Paused");
    389389        else
    390             string = torrents[0]->activityString( );
    391     }
    392     myStateLabel->setText( string );
     390            string = torrents[0]->activityString ();
     391    }
     392    myStateLabel->setText (string);
    393393    const QString stateString = string;
    394394
     
    401401    int64_t haveUnverified = 0;
    402402    int64_t verifiedPieces = 0;
    403     if( torrents.empty( ) )
    404         string = none;
    405     else {
    406         foreach( const Torrent * t, torrents ) {
    407             if( t->hasMetadata( ) ) {
    408                 haveTotal += t->haveTotal( );
    409                 haveUnverified += t->haveUnverified( );
    410                 const uint64_t v = t->haveVerified( );
     403    if (torrents.empty ())
     404        string = none;
     405    else {
     406        foreach (const Torrent * t, torrents) {
     407            if (t->hasMetadata ()) {
     408                haveTotal += t->haveTotal ();
     409                haveUnverified += t->haveUnverified ();
     410                const uint64_t v = t->haveVerified ();
    411411                haveVerified += v;
    412                 if( t->pieceSize( ) )
    413                     verifiedPieces += v / t->pieceSize( );
    414                 sizeWhenDone += t->sizeWhenDone( );
    415                 leftUntilDone += t->leftUntilDone( );
    416                 available += t->sizeWhenDone() - t->leftUntilDone() + t->desiredAvailable();
     412                if (t->pieceSize ())
     413                    verifiedPieces += v / t->pieceSize ();
     414                sizeWhenDone += t->sizeWhenDone ();
     415                leftUntilDone += t->leftUntilDone ();
     416                available += t->sizeWhenDone () - t->leftUntilDone () + t->desiredAvailable ();
    417417            }
    418418        }
    419419        {
    420             const double d = 100.0 * ( sizeWhenDone ? ( sizeWhenDone - leftUntilDone ) / sizeWhenDone : 1 );
    421             QString pct = Formatter::percentToString( d );
    422 
    423             if( !haveUnverified && !leftUntilDone )
     420            const double d = 100.0 * (sizeWhenDone ? (sizeWhenDone - leftUntilDone) / sizeWhenDone : 1);
     421            QString pct = Formatter::percentToString (d);
     422
     423            if (!haveUnverified && !leftUntilDone)
    424424            {
    425                 string = tr( "%1 (100%)" )
    426                              .arg( Formatter::sizeToString( haveVerified ) );
     425                string = tr ("%1 (100%)")
     426                             .arg (Formatter::sizeToString (haveVerified));
    427427            }
    428             else if( !haveUnverified )
     428            else if (!haveUnverified)
    429429            {
    430                 string = tr( "%1 of %2 (%3%)" )
    431                              .arg( Formatter::sizeToString( haveVerified ) )
    432                              .arg( Formatter::sizeToString( sizeWhenDone ) )
    433                              .arg( pct );
     430                string = tr ("%1 of %2 (%3%)")
     431                             .arg (Formatter::sizeToString (haveVerified))
     432                             .arg (Formatter::sizeToString (sizeWhenDone))
     433                             .arg (pct);
    434434            }
    435435            else
    436436            {
    437                 string = tr( "%1 of %2 (%3%), %4 Unverified" )
    438                              .arg( Formatter::sizeToString( haveVerified + haveUnverified ) )
    439                              .arg( Formatter::sizeToString( sizeWhenDone ) )
    440                              .arg( pct )
    441                              .arg( Formatter::sizeToString( haveUnverified ) );
     437                string = tr ("%1 of %2 (%3%), %4 Unverified")
     438                             .arg (Formatter::sizeToString (haveVerified + haveUnverified))
     439                             .arg (Formatter::sizeToString (sizeWhenDone))
     440                             .arg (pct)
     441                             .arg (Formatter::sizeToString (haveUnverified));
    442442            }
    443443        }
    444444    }
    445     myHaveLabel->setText( string );
     445    myHaveLabel->setText (string);
    446446
    447447    // myAvailabilityLabel
    448     if( torrents.empty( ) )
    449         string = none;
    450     else {
    451         if( sizeWhenDone == 0 )
     448    if (torrents.empty ())
     449        string = none;
     450    else {
     451        if (sizeWhenDone == 0)
    452452            string = none;
    453453        else
    454             string = QString( "%1%" ).arg( Formatter::percentToString( ( 100.0 * available ) / sizeWhenDone ) );
    455     }
    456     myAvailabilityLabel->setText( string );
     454            string = QString ("%1%").arg (Formatter::percentToString ( (100.0 * available) / sizeWhenDone));
     455    }
     456    myAvailabilityLabel->setText (string);
    457457
    458458    // myDownloadedLabel
    459     if( torrents.empty( ) )
     459    if (torrents.empty ())
    460460        string = none;
    461461    else {
    462462        uint64_t d = 0;
    463463        uint64_t f = 0;
    464         foreach( const Torrent * t, torrents ) {
    465             d += t->downloadedEver( );
    466             f += t->failedEver( );
    467         }
    468         const QString dstr = Formatter::sizeToString( d );
    469         const QString fstr = Formatter::sizeToString( f );
    470         if( f )
    471             string = tr( "%1 (%2 corrupt)" ).arg( dstr ).arg( fstr );
     464        foreach (const Torrent * t, torrents) {
     465            d += t->downloadedEver ();
     466            f += t->failedEver ();
     467        }
     468        const QString dstr = Formatter::sizeToString (d);
     469        const QString fstr = Formatter::sizeToString (f);
     470        if (f)
     471            string = tr ("%1 (%2 corrupt)").arg (dstr).arg (fstr);
    472472        else
    473473            string = dstr;
    474474    }
    475     myDownloadedLabel->setText( string );
    476 
    477     if( torrents.empty( ) )
     475    myDownloadedLabel->setText (string);
     476
     477    if (torrents.empty ())
    478478        string = none;
    479479    else {
    480480        uint64_t u = 0;
    481481        uint64_t d = 0;
    482         foreach( const Torrent * t, torrents ) {
    483             u += t->uploadedEver( );
    484             d += t->downloadedEver( );
    485         }
    486         string = tr( "%1 (Ratio: %2)" )
    487                    .arg( Formatter::sizeToString( u ) )
    488                    .arg( Formatter::ratioToString( tr_getRatio( u, d ) ) );
    489     }
    490     myUploadedLabel->setText( string );
    491 
    492     const QDateTime qdt_now = QDateTime::currentDateTime( );
     482        foreach (const Torrent * t, torrents) {
     483            u += t->uploadedEver ();
     484            d += t->downloadedEver ();
     485        }
     486        string = tr ("%1 (Ratio: %2)")
     487                   .arg (Formatter::sizeToString (u))
     488                   .arg (Formatter::ratioToString (tr_getRatio (u, d)));
     489    }
     490    myUploadedLabel->setText (string);
     491
     492    const QDateTime qdt_now = QDateTime::currentDateTime ();
    493493
    494494    // myRunTimeLabel
    495     if( torrents.empty( ) )
     495    if (torrents.empty ())
    496496        string = none;
    497497    else {
    498498        bool allPaused = true;
    499         QDateTime baseline = torrents[0]->lastStarted( );
    500         foreach( const Torrent * t, torrents ) {
    501             if( baseline != t->lastStarted( ) )
    502                 baseline = QDateTime( );
    503             if( !t->isPaused( ) )
     499        QDateTime baseline = torrents[0]->lastStarted ();
     500        foreach (const Torrent * t, torrents) {
     501            if (baseline != t->lastStarted ())
     502                baseline = QDateTime ();
     503            if (!t->isPaused ())
    504504                allPaused = false;
    505505        }
    506         if( allPaused )
     506        if (allPaused)
    507507            string = stateString; // paused || finished
    508         else if( baseline.isNull( ) )
     508        else if (baseline.isNull ())
    509509            string = mixed;
    510510        else
    511             string = Formatter::timeToString( baseline.secsTo( qdt_now ) );
    512     }
    513     myRunTimeLabel->setText( string );
     511            string = Formatter::timeToString (baseline.secsTo (qdt_now));
     512    }
     513    myRunTimeLabel->setText (string);
    514514
    515515
    516516    // myETALabel
    517     string.clear( );
    518     if( torrents.empty( ) )
    519         string = none;
    520     else {
    521         int baseline = torrents[0]->getETA( );
    522         foreach( const Torrent * t, torrents ) {
    523             if( baseline != t->getETA( ) ) {
     517    string.clear ();
     518    if (torrents.empty ())
     519        string = none;
     520    else {
     521        int baseline = torrents[0]->getETA ();
     522        foreach (const Torrent * t, torrents) {
     523            if (baseline != t->getETA ()) {
    524524                string = mixed;
    525525                break;
    526526            }
    527527        }
    528         if( string.isEmpty( ) ) {
    529             if( baseline < 0 )
    530                 string = tr( "Unknown" );
     528        if (string.isEmpty ()) {
     529            if (baseline < 0)
     530                string = tr ("Unknown");
    531531            else
    532                 string = Formatter::timeToString( baseline );
     532                string = Formatter::timeToString (baseline);
    533533       }
    534534    }
    535     myETALabel->setText( string );
     535    myETALabel->setText (string);
    536536
    537537
    538538    // myLastActivityLabel
    539     if( torrents.empty( ) )
    540         string = none;
    541     else {
    542         QDateTime latest = torrents[0]->lastActivity( );
    543         foreach( const Torrent * t, torrents ) {
    544             const QDateTime dt = t->lastActivity( );
    545             if( latest < dt )
     539    if (torrents.empty ())
     540        string = none;
     541    else {
     542        QDateTime latest = torrents[0]->lastActivity ();
     543        foreach (const Torrent * t, torrents) {
     544            const QDateTime dt = t->lastActivity ();
     545            if (latest < dt)
    546546                latest = dt;
    547547        }
    548         const int seconds = latest.isValid() ? latest.secsTo( qdt_now ) : -1;
    549         if( seconds < 0 )
     548        const int seconds = latest.isValid () ? latest.secsTo (qdt_now) : -1;
     549        if (seconds < 0)
    550550            string = none;
    551         else if( seconds < 5 )
    552             string = tr( "Active now" );
     551        else if (seconds < 5)
     552            string = tr ("Active now");
    553553        else
    554             string = tr( "%1 ago" ).arg( Formatter::timeToString( seconds ) );
    555     }
    556     myLastActivityLabel->setText( string );
    557 
    558 
    559     if( torrents.empty( ) )
    560         string = none;
    561     else {
    562         string = torrents[0]->getError( );
    563         foreach( const Torrent * t, torrents ) {
    564             if( string != t->getError( ) ) {
     554            string = tr ("%1 ago").arg (Formatter::timeToString (seconds));
     555    }
     556    myLastActivityLabel->setText (string);
     557
     558
     559    if (torrents.empty ())
     560        string = none;
     561    else {
     562        string = torrents[0]->getError ();
     563        foreach (const Torrent * t, torrents) {
     564            if (string != t->getError ()) {
    565565                string = mixed;
    566566                break;
     
    568568        }
    569569    }
    570     if( string.isEmpty( ) )
    571         string = none;
    572     myErrorLabel->setText( string );
     570    if (string.isEmpty ())
     571        string = none;
     572    myErrorLabel->setText (string);
    573573
    574574
     
    578578
    579579    // mySizeLabel
    580     if( torrents.empty( ) )
     580    if (torrents.empty ())
    581581        string = none;
    582582    else {
    583583        int pieces = 0;
    584584        uint64_t size = 0;
    585         uint32_t pieceSize = torrents[0]->pieceSize( );
    586         foreach( const Torrent * t, torrents ) {
    587             pieces += t->pieceCount( );
    588             size += t->totalSize( );
    589             if( pieceSize != t->pieceSize( ) )
     585        uint32_t pieceSize = torrents[0]->pieceSize ();
     586        foreach (const Torrent * t, torrents) {
     587            pieces += t->pieceCount ();
     588            size += t->totalSize ();
     589            if (pieceSize != t->pieceSize ())
    590590                pieceSize = 0;
    591591        }
    592         if( !size )
     592        if (!size)
    593593            string = none;
    594         else if( pieceSize > 0 )
    595             string = tr( "%1 (%Ln pieces @ %2)", "", pieces )
    596                      .arg( Formatter::sizeToString( size ) )
    597                      .arg( Formatter::memToString( pieceSize ) );
     594        else if (pieceSize > 0)
     595            string = tr ("%1 (%Ln pieces @ %2)", "", pieces)
     596                     .arg (Formatter::sizeToString (size))
     597                     .arg (Formatter::memToString (pieceSize));
    598598        else
    599             string = tr( "%1 (%Ln pieces)", "", pieces )
    600                      .arg( Formatter::sizeToString( size ) );
    601     }
    602     mySizeLabel->setText( string );
     599            string = tr ("%1 (%Ln pieces)", "", pieces)
     600                     .arg (Formatter::sizeToString (size));
     601    }
     602    mySizeLabel->setText (string);
    603603
    604604    // myHashLabel
    605     if( torrents.empty( ) )
    606         string = none;
    607     else {
    608         string = torrents[0]->hashString( );
    609         foreach( const Torrent * t, torrents ) {
    610             if( string != t->hashString( ) ) {
     605    if (torrents.empty ())
     606        string = none;
     607    else {
     608        string = torrents[0]->hashString ();
     609        foreach (const Torrent * t, torrents) {
     610            if (string != t->hashString ()) {
    611611                string = mixed;
    612612                break;
     
    614614        }
    615615    }
    616     myHashLabel->setText( string );
     616    myHashLabel->setText (string);
    617617
    618618    // myPrivacyLabel
    619     if( torrents.empty( ) )
    620         string = none;
    621     else {
    622         bool b = torrents[0]->isPrivate( );
    623         string = b ? tr( "Private to this tracker -- DHT and PEX disabled" )
    624                    : tr( "Public torrent" );
    625         foreach( const Torrent * t, torrents ) {
    626             if( b != t->isPrivate( ) ) {
     619    if (torrents.empty ())
     620        string = none;
     621    else {
     622        bool b = torrents[0]->isPrivate ();
     623        string = b ? tr ("Private to this tracker -- DHT and PEX disabled")
     624                   : tr ("Public torrent");
     625        foreach (const Torrent * t, torrents) {
     626            if (b != t->isPrivate ()) {
    627627                string = mixed;
    628628                break;
     
    630630        }
    631631    }
    632     myPrivacyLabel->setText( string );
     632    myPrivacyLabel->setText (string);
    633633
    634634    // myCommentBrowser
    635     if( torrents.empty( ) )
    636         string = none;
    637     else {
    638         string = torrents[0]->comment( );
    639         foreach( const Torrent * t, torrents ) {
    640             if( string != t->comment( ) ) {
     635    if (torrents.empty ())
     636        string = none;
     637    else {
     638        string = torrents[0]->comment ();
     639        foreach (const Torrent * t, torrents) {
     640            if (string != t->comment ()) {
    641641                string = mixed;
    642642                break;
     
    644644        }
    645645    }
    646     myCommentBrowser->setText( string );
    647     myCommentBrowser->setMaximumHeight( QWIDGETSIZE_MAX );
     646    myCommentBrowser->setText (string);
     647    myCommentBrowser->setMaximumHeight (QWIDGETSIZE_MAX);
    648648
    649649    // myOriginLabel
    650     if( torrents.empty( ) )
     650    if (torrents.empty ())
    651651        string = none;
    652652    else {
    653653        bool mixed_creator=false, mixed_date=false;
    654         const QString creator = torrents[0]->creator();
    655         const QString date = torrents[0]->dateCreated().toString();
    656         foreach( const Torrent * t, torrents ) {
    657             mixed_creator |= ( creator != t->creator() );
    658             mixed_date |=  ( date != t->dateCreated().toString() );
    659         }
    660         if( mixed_creator && mixed_date )
     654        const QString creator = torrents[0]->creator ();
     655        const QString date = torrents[0]->dateCreated ().toString ();
     656        foreach (const Torrent * t, torrents) {
     657            mixed_creator |= (creator != t->creator ());
     658            mixed_date |= (date != t->dateCreated ().toString ());
     659        }
     660        if (mixed_creator && mixed_date)
    661661            string = mixed;
    662         else if( mixed_date && !creator.isEmpty())
    663             string = tr( "Created by %1" ).arg( creator );
    664         else if( mixed_creator && !date.isEmpty())
    665             string = tr( "Created on %1" ).arg( date );
    666         else if( creator.isEmpty() && date.isEmpty())
    667             string = tr( "N/A" );
     662        else if (mixed_date && !creator.isEmpty ())
     663            string = tr ("Created by %1").arg (creator);
     664        else if (mixed_creator && !date.isEmpty ())
     665            string = tr ("Created on %1").arg (date);
     666        else if (creator.isEmpty () && date.isEmpty ())
     667            string = tr ("N/A");
    668668        else
    669             string = tr( "Created by %1 on %2" ).arg( creator ).arg( date );
    670     }
    671     myOriginLabel->setText( string );
     669            string = tr ("Created by %1 on %2").arg (creator).arg (date);
     670    }
     671    myOriginLabel->setText (string);
    672672
    673673    // myLocationLabel
    674     if( torrents.empty( ) )
    675         string = none;
    676     else {
    677         string = torrents[0]->getPath( );
    678         foreach( const Torrent * t, torrents ) {
    679             if( string != t->getPath( ) ) {
     674    if (torrents.empty ())
     675        string = none;
     676    else {
     677        string = torrents[0]->getPath ();
     678        foreach (const Torrent * t, torrents) {
     679            if (string != t->getPath ()) {
    680680                string = mixed;
    681681                break;
     
    683683        }
    684684    }
    685     myLocationLabel->setText( string );
     685    myLocationLabel->setText (string);
    686686
    687687
     
    690690    ///
    691691
    692     if( myChangedTorrents && !torrents.empty( ) )
     692    if (myChangedTorrents && !torrents.empty ())
    693693    {
    694694        int i;
    695         const Torrent * baseline = *torrents.begin();
     695        const Torrent * baseline = *torrents.begin ();
    696696        const Torrent * tor;
    697697        bool uniform;
     
    701701        // mySessionLimitCheck
    702702        uniform = true;
    703         baselineFlag = baseline->honorsSessionLimits( );
    704         foreach( tor, torrents ) if( baselineFlag != tor->honorsSessionLimits( ) ) { uniform = false; break; }
    705         mySessionLimitCheck->setChecked( uniform && baselineFlag );
     703        baselineFlag = baseline->honorsSessionLimits ();
     704        foreach (tor, torrents) if (baselineFlag != tor->honorsSessionLimits ()) { uniform = false; break; }
     705        mySessionLimitCheck->setChecked (uniform && baselineFlag);
    706706
    707707        // mySingleDownCheck
    708708        uniform = true;
    709         baselineFlag = baseline->downloadIsLimited( );
    710         foreach( tor, torrents ) if( baselineFlag != tor->downloadIsLimited( ) ) { uniform = false; break; }
    711         mySingleDownCheck->setChecked( uniform && baselineFlag );
     709        baselineFlag = baseline->downloadIsLimited ();
     710        foreach (tor, torrents) if (baselineFlag != tor->downloadIsLimited ()) { uniform = false; break; }
     711        mySingleDownCheck->setChecked (uniform && baselineFlag);
    712712
    713713        // mySingleUpCheck
    714714        uniform = true;
    715         baselineFlag = baseline->uploadIsLimited( );
    716         foreach( tor, torrents ) if( baselineFlag != tor->uploadIsLimited( ) ) { uniform = false; break; }
    717         mySingleUpCheck->setChecked( uniform && baselineFlag );
     715        baselineFlag = baseline->uploadIsLimited ();
     716        foreach (tor, torrents) if (baselineFlag != tor->uploadIsLimited ()) { uniform = false; break; }
     717        mySingleUpCheck->setChecked (uniform && baselineFlag);
    718718
    719719        // myBandwidthPriorityCombo
    720720        uniform = true;
    721         baselineInt = baseline->getBandwidthPriority( );
    722         foreach( tor, torrents ) if ( baselineInt != tor->getBandwidthPriority( ) ) { uniform = false; break; }
    723         if( uniform )
    724             i = myBandwidthPriorityCombo->findData( baselineInt );
     721        baselineInt = baseline->getBandwidthPriority ();
     722        foreach (tor, torrents) if (baselineInt != tor->getBandwidthPriority ()) { uniform = false; break; }
     723        if (uniform)
     724            i = myBandwidthPriorityCombo->findData (baselineInt);
    725725        else
    726726            i = -1;
    727         setIfIdle( myBandwidthPriorityCombo, i );
    728 
    729         setIfIdle( mySingleDownSpin, int(tor->downloadLimit().KBps()) );
    730         setIfIdle( mySingleUpSpin, int(tor->uploadLimit().KBps()) );
    731         setIfIdle( myPeerLimitSpin, tor->peerLimit() );
    732     }
    733 
    734     if( !torrents.empty( ) )
     727        setIfIdle (myBandwidthPriorityCombo, i);
     728
     729        setIfIdle (mySingleDownSpin, int (tor->downloadLimit ().KBps ()));
     730        setIfIdle (mySingleUpSpin, int (tor->uploadLimit ().KBps ()));
     731        setIfIdle (myPeerLimitSpin, tor->peerLimit ());
     732    }
     733
     734    if (!torrents.empty ())
    735735    {
    736736        const Torrent * tor;
     
    738738        // ratio
    739739        bool uniform = true;
    740         int baselineInt = torrents[0]->seedRatioMode( );
    741         foreach( tor, torrents ) if( baselineInt != tor->seedRatioMode( ) ) { uniform = false; break; }
    742 
    743         setIfIdle( myRatioCombo, uniform ? myRatioCombo->findData( baselineInt ) : -1 );
    744         myRatioSpin->setVisible( uniform && ( baselineInt == TR_RATIOLIMIT_SINGLE ) );
    745 
    746         setIfIdle( myRatioSpin, tor->seedRatioLimit( ) );
     740        int baselineInt = torrents[0]->seedRatioMode ();
     741        foreach (tor, torrents) if (baselineInt != tor->seedRatioMode ()) { uniform = false; break; }
     742
     743        setIfIdle (myRatioCombo, uniform ? myRatioCombo->findData (baselineInt) : -1);
     744        myRatioSpin->setVisible (uniform && (baselineInt == TR_RATIOLIMIT_SINGLE));
     745
     746        setIfIdle (myRatioSpin, tor->seedRatioLimit ());
    747747
    748748        // idle
    749749        uniform = true;
    750         baselineInt = torrents[0]->seedIdleMode( );
    751         foreach( tor, torrents ) if( baselineInt != tor->seedIdleMode( ) ) { uniform = false; break; }
    752 
    753         setIfIdle( myIdleCombo, uniform ? myIdleCombo->findData( baselineInt ) : -1 );
    754         myIdleSpin->setVisible( uniform && ( baselineInt == TR_RATIOLIMIT_SINGLE ) );
    755 
    756         setIfIdle( myIdleSpin, tor->seedIdleLimit( ) );
     750        baselineInt = torrents[0]->seedIdleMode ();
     751        foreach (tor, torrents) if (baselineInt != tor->seedIdleMode ()) { uniform = false; break; }
     752
     753        setIfIdle (myIdleCombo, uniform ? myIdleCombo->findData (baselineInt) : -1);
     754        myIdleSpin->setVisible (uniform && (baselineInt == TR_RATIOLIMIT_SINGLE));
     755
     756        setIfIdle (myIdleSpin, tor->seedIdleLimit ());
    757757    }
    758758
     
    761761    ///
    762762
    763     myTrackerModel->refresh( myModel, myIds );
     763    myTrackerModel->refresh (myModel, myIds);
    764764
    765765    ///
     
    769769    QMap<QString,QTreeWidgetItem*> peers2;
    770770    QList<QTreeWidgetItem*> newItems;
    771     foreach( const Torrent * t, torrents )
    772     {
    773         const QString idStr( QString::number( t->id( ) ) );
    774         PeerList peers = t->peers( );
    775 
    776         foreach( const Peer& peer, peers )
     771    foreach (const Torrent * t, torrents)
     772    {
     773        const QString idStr (QString::number (t->id ()));
     774        PeerList peers = t->peers ();
     775
     776        foreach (const Peer& peer, peers)
    777777        {
    778778            const QString key = idStr + ":" + peer.address;
    779             PeerItem * item = (PeerItem*) myPeers.value( key, 0 );
    780 
    781             if( item == 0 ) // new peer has connected
     779            PeerItem * item = (PeerItem*) myPeers.value (key, 0);
     780
     781            if (item == 0) // new peer has connected
    782782            {
    783                 static const QIcon myEncryptionIcon( ":/icons/encrypted.png" );
     783                static const QIcon myEncryptionIcon (":/icons/encrypted.png");
    784784                static const QIcon myEmptyIcon;
    785                 item = new PeerItem( peer );
    786                 item->setTextAlignment( COL_UP, Qt::AlignRight|Qt::AlignVCenter );
    787                 item->setTextAlignment( COL_DOWN, Qt::AlignRight|Qt::AlignVCenter );
    788                 item->setTextAlignment( COL_PERCENT, Qt::AlignRight|Qt::AlignVCenter );
    789                 item->setIcon( COL_LOCK, peer.isEncrypted ? myEncryptionIcon : myEmptyIcon );
    790                 item->setToolTip( COL_LOCK, peer.isEncrypted ? tr( "Encrypted connection" ) : "" );
    791                 item->setText( COL_ADDRESS, peer.address );
    792                 item->setText( COL_CLIENT, peer.clientName );
     785                item = new PeerItem (peer);
     786                item->setTextAlignment (COL_UP, Qt::AlignRight|Qt::AlignVCenter);
     787                item->setTextAlignment (COL_DOWN, Qt::AlignRight|Qt::AlignVCenter);
     788                item->setTextAlignment (COL_PERCENT, Qt::AlignRight|Qt::AlignVCenter);
     789                item->setIcon (COL_LOCK, peer.isEncrypted ? myEncryptionIcon : myEmptyIcon);
     790                item->setToolTip (COL_LOCK, peer.isEncrypted ? tr ("Encrypted connection") : "");
     791                item->setText (COL_ADDRESS, peer.address);
     792                item->setText (COL_CLIENT, peer.clientName);
    793793                newItems << item;
    794794            }
    795795
    796796            const QString code = peer.flagStr;
    797             item->setStatus( code );
    798             item->refresh( peer );
     797            item->setStatus (code);
     798            item->refresh (peer);
    799799
    800800            QString codeTip;
    801             foreach( QChar ch, code ) {
     801            foreach (QChar ch, code) {
    802802                QString txt;
    803                 switch( ch.toAscii() ) {
    804                     case 'O': txt = tr( "Optimistic unchoke" ); break;
    805                     case 'D': txt = tr( "Downloading from this peer" ); break;
    806                     case 'd': txt = tr( "We would download from this peer if they would let us" ); break;
    807                     case 'U': txt = tr( "Uploading to peer" ); break;
    808                     case 'u': txt = tr( "We would upload to this peer if they asked" ); break;
    809                     case 'K': txt = tr( "Peer has unchoked us, but we're not interested" ); break;
    810                     case '?': txt = tr( "We unchoked this peer, but they're not interested" ); break;
    811                     case 'E': txt = tr( "Encrypted connection" ); break;
    812                     case 'H': txt = tr( "Peer was discovered through DHT" ); break;
    813                     case 'X': txt = tr( "Peer was discovered through Peer Exchange (PEX)" ); break;
    814                     case 'I': txt = tr( "Peer is an incoming connection" ); break;
    815                     case 'T': txt = tr( "Peer is connected over uTP" ); break;
     803                switch (ch.toAscii ()) {
     804                    case 'O': txt = tr ("Optimistic unchoke"); break;
     805                    case 'D': txt = tr ("Downloading from this peer"); break;
     806                    case 'd': txt = tr ("We would download from this peer if they would let us"); break;
     807                    case 'U': txt = tr ("Uploading to peer"); break;
     808                    case 'u': txt = tr ("We would upload to this peer if they asked"); break;
     809                    case 'K': txt = tr ("Peer has unchoked us, but we're not interested"); break;
     810                    case '?': txt = tr ("We unchoked this peer, but they're not interested"); break;
     811                    case 'E': txt = tr ("Encrypted connection"); break;
     812                    case 'H': txt = tr ("Peer was discovered through DHT"); break;
     813                    case 'X': txt = tr ("Peer was discovered through Peer Exchange (PEX)"); break;
     814                    case 'I': txt = tr ("Peer is an incoming connection"); break;
     815                    case 'T': txt = tr ("Peer is connected over uTP"); break;
    816816                }
    817                 if( !txt.isEmpty( ) )
    818                     codeTip += QString("%1: %2\n").arg(ch).arg(txt);
     817                if (!txt.isEmpty ())
     818                    codeTip += QString ("%1: %2\n").arg (ch).arg (txt);
    819819            }
    820820
    821             if( !codeTip.isEmpty() )
    822                 codeTip.resize( codeTip.size()-1 ); // eat the trailing linefeed
    823 
    824             item->setText( COL_UP, peer.rateToPeer.isZero() ? "" : Formatter::speedToString( peer.rateToPeer ) );
    825             item->setText( COL_DOWN, peer.rateToClient.isZero() ? "" : Formatter::speedToString( peer.rateToClient ) );
    826             item->setText( COL_PERCENT, peer.progress > 0 ? QString( "%1%" ).arg( (int)( peer.progress * 100.0 ) ) : "" );
    827             item->setText( COL_STATUS, code );
    828             item->setToolTip( COL_STATUS, codeTip );
    829 
    830             peers2.insert( key, item );
    831         }
    832     }
    833     myPeerTree->addTopLevelItems( newItems );
    834     foreach( QString key, myPeers.keys() ) {
    835         if( !peers2.contains( key ) ) { // old peer has disconnected
    836             QTreeWidgetItem * item = myPeers.value( key, 0 );
    837             myPeerTree->takeTopLevelItem( myPeerTree->indexOfTopLevelItem( item ) );
     821            if (!codeTip.isEmpty ())
     822                codeTip.resize (codeTip.size ()-1); // eat the trailing linefeed
     823
     824            item->setText (COL_UP, peer.rateToPeer.isZero () ? "" : Formatter::speedToString (peer.rateToPeer));
     825            item->setText (COL_DOWN, peer.rateToClient.isZero () ? "" : Formatter::speedToString (peer.rateToClient));
     826            item->setText (COL_PERCENT, peer.progress > 0 ? QString ("%1%").arg ( (int) (peer.progress * 100.0)) : "");
     827            item->setText (COL_STATUS, code);
     828            item->setToolTip (COL_STATUS, codeTip);
     829
     830            peers2.insert (key, item);
     831        }
     832    }
     833    myPeerTree->addTopLevelItems (newItems);
     834    foreach (QString key, myPeers.keys ()) {
     835        if (!peers2.contains (key)) { // old peer has disconnected
     836            QTreeWidgetItem * item = myPeers.value (key, 0);
     837            myPeerTree->takeTopLevelItem (myPeerTree->indexOfTopLevelItem (item));
    838838            delete item;
    839839        }
     
    841841    myPeers = peers2;
    842842
    843     if( !single || myFilesDirty )
    844         myFileTreeView->clear( );
    845     if( single )
    846         myFileTreeView->update( torrents[0]->files( ) , myFilesDirty || myChangedTorrents );
     843    if (!single || myFilesDirty)
     844        myFileTreeView->clear ();
     845    if (single)
     846        myFileTreeView->update (torrents[0]->files () , myFilesDirty || myChangedTorrents);
    847847
    848848    myFilesDirty = false;
    849849    myChangedTorrents = false;
    850850    myHavePendingRefresh = false;
    851     foreach( QWidget * w, myWidgets )
    852         w->setEnabled( true );
    853 }
    854 
    855 void
    856 Details :: enableWhenChecked( QCheckBox * box, QWidget * w )
    857 {
    858     connect( box, SIGNAL(toggled(bool)), w, SLOT(setEnabled(bool)) );
    859     w->setEnabled( box->isChecked( ) );
     851    foreach (QWidget * w, myWidgets)
     852        w->setEnabled (true);
     853}
     854
     855void
     856Details :: enableWhenChecked (QCheckBox * box, QWidget * w)
     857{
     858    connect (box, SIGNAL (toggled (bool)), w, SLOT (setEnabled (bool)));
     859    w->setEnabled (box->isChecked ());
    860860}
    861861
     
    866866
    867867QWidget *
    868 Details :: createInfoTab( )
    869 {
    870     HIG * hig = new HIG( this );
    871 
    872     hig->addSectionTitle( tr( "Activity" ) );
    873     hig->addRow( tr( "Have:" ), myHaveLabel = new SqueezeLabel );
    874     hig->addRow( tr( "Availability:" ), myAvailabilityLabel = new SqueezeLabel );
    875     hig->addRow( tr( "Downloaded:" ), myDownloadedLabel = new SqueezeLabel );
    876     hig->addRow( tr( "Uploaded:" ), myUploadedLabel = new SqueezeLabel );
    877     hig->addRow( tr( "State:" ), myStateLabel = new SqueezeLabel );
    878     hig->addRow( tr( "Running time:" ), myRunTimeLabel = new SqueezeLabel );
    879     hig->addRow( tr( "Remaining time:" ), myETALabel = new SqueezeLabel );
    880     hig->addRow( tr( "Last activity:" ), myLastActivityLabel = new SqueezeLabel );
    881     hig->addRow( tr( "Error:" ), myErrorLabel = new SqueezeLabel );
    882     hig->addSectionDivider( );
    883 
    884     hig->addSectionDivider( );
    885     hig->addSectionTitle( tr( "Details" ) );
    886     hig->addRow( tr( "Size:" ), mySizeLabel = new SqueezeLabel );
    887     hig->addRow( tr( "Location:" ), myLocationLabel = new SqueezeLabel );
    888     hig->addRow( tr( "Hash:" ), myHashLabel = new SqueezeLabel );
    889     hig->addRow( tr( "Privacy:" ), myPrivacyLabel = new SqueezeLabel );
    890     hig->addRow( tr( "Origin:" ), myOriginLabel = new SqueezeLabel );
    891     myOriginLabel->setMinimumWidth( 325 ); // stop long origin strings from resizing the widgit
    892     hig->addRow( tr( "Comment:" ), myCommentBrowser = new QTextBrowser );
    893     const int h = QFontMetrics(myCommentBrowser->font()).lineSpacing() * 4;
    894     myCommentBrowser->setFixedHeight( h );
    895 
    896     hig->finish( );
     868Details :: createInfoTab ()
     869{
     870    HIG * hig = new HIG (this);
     871
     872    hig->addSectionTitle (tr ("Activity"));
     873    hig->addRow (tr ("Have:"), myHaveLabel = new SqueezeLabel);
     874    hig->addRow (tr ("Availability:"), myAvailabilityLabel = new SqueezeLabel);
     875    hig->addRow (tr ("Downloaded:"), myDownloadedLabel = new SqueezeLabel);
     876    hig->addRow (tr ("Uploaded:"), myUploadedLabel = new SqueezeLabel);
     877    hig->addRow (tr ("State:"), myStateLabel = new SqueezeLabel);
     878    hig->addRow (tr ("Running time:"), myRunTimeLabel = new SqueezeLabel);
     879    hig->addRow (tr ("Remaining time:"), myETALabel = new SqueezeLabel);
     880    hig->addRow (tr ("Last activity:"), myLastActivityLabel = new SqueezeLabel);
     881    hig->addRow (tr ("Error:"), myErrorLabel = new SqueezeLabel);
     882    hig->addSectionDivider ();
     883
     884    hig->addSectionDivider ();
     885    hig->addSectionTitle (tr ("Details"));
     886    hig->addRow (tr ("Size:"), mySizeLabel = new SqueezeLabel);
     887    hig->addRow (tr ("Location:"), myLocationLabel = new SqueezeLabel);
     888    hig->addRow (tr ("Hash:"), myHashLabel = new SqueezeLabel);
     889    hig->addRow (tr ("Privacy:"), myPrivacyLabel = new SqueezeLabel);
     890    hig->addRow (tr ("Origin:"), myOriginLabel = new SqueezeLabel);
     891    myOriginLabel->setMinimumWidth (325); // stop long origin strings from resizing the widgit
     892    hig->addRow (tr ("Comment:"), myCommentBrowser = new QTextBrowser);
     893    const int h = QFontMetrics (myCommentBrowser->font ()).lineSpacing () * 4;
     894    myCommentBrowser->setFixedHeight (h);
     895
     896    hig->finish ();
    897897
    898898    return hig;
     
    930930Details :: onSpinBoxEditingFinished ()
    931931{
    932   const QObject * spin = sender();
    933   const tr_quark key = spin->property(PREF_KEY).toInt();
    934   const QDoubleSpinBox * d = qobject_cast<const QDoubleSpinBox*>( spin );
     932  const QObject * spin = sender ();
     933  const tr_quark key = spin->property (PREF_KEY).toInt ();
     934  const QDoubleSpinBox * d = qobject_cast<const QDoubleSpinBox*> (spin);
    935935  if (d)
    936     mySession.torrentSet( myIds, key, d->value( ) );
     936    mySession.torrentSet (myIds, key, d->value ());
    937937  else
    938     mySession.torrentSet( myIds, key, qobject_cast<const QSpinBox*>(spin)->value( ) );
    939   getNewData( );
     938    mySession.torrentSet (myIds, key, qobject_cast<const QSpinBox*> (spin)->value ());
     939  getNewData ();
    940940}
    941941
     
    950950Details :: onIdleModeChanged (int index)
    951951{
    952   const int val = myIdleCombo->itemData(index).toInt();
     952  const int val = myIdleCombo->itemData (index).toInt ();
    953953  mySession.torrentSet (myIds, TR_KEY_seedIdleMode, val);
    954954  getNewData ();
     
    958958Details :: onRatioModeChanged (int index)
    959959{
    960   const int val = myRatioCombo->itemData(index).toInt();
     960  const int val = myRatioCombo->itemData (index).toInt ();
    961961  mySession.torrentSet (myIds, TR_KEY_seedRatioMode, val);
    962962}
     
    965965Details :: onBandwidthPriorityChanged (int index)
    966966{
    967   if( index != -1 )
    968     {
    969       const int priority = myBandwidthPriorityCombo->itemData(index).toInt();
    970       mySession.torrentSet( myIds, TR_KEY_bandwidthPriority, priority );
    971       getNewData( );
     967  if (index != -1)
     968    {
     969      const int priority = myBandwidthPriorityCombo->itemData (index).toInt ();
     970      mySession.torrentSet (myIds, TR_KEY_bandwidthPriority, priority);
     971      getNewData ();
    972972    }
    973973}
     
    976976Details :: onTrackerSelectionChanged ()
    977977{
    978   const int selectionCount = myTrackerView->selectionModel()->selectedRows().size();
     978  const int selectionCount = myTrackerView->selectionModel ()->selectedRows ().size ();
    979979  myEditTrackerButton->setEnabled (selectionCount == 1);
    980980  myRemoveTrackerButton->setEnabled (selectionCount > 0);
     
    986986  bool ok = false;
    987987  const QString url = QInputDialog::getText (this,
    988                                              tr("Add URL "),
    989                                              tr("Add tracker announce URL:"),
    990                                              QLineEdit::Normal, QString(), &ok);
    991   if(!ok)
     988                                             tr ("Add URL "),
     989                                             tr ("Add tracker announce URL:"),
     990                                             QLineEdit::Normal, QString (), &ok);
     991  if (!ok)
    992992    {
    993993      // user pressed "cancel" -- noop
    994994    }
    995   else if (!QUrl(url).isValid())
    996     {
    997       QMessageBox::warning( this, tr("Error"), tr("Invalid URL \"%1\"").arg(url));
     995  else if (!QUrl (url).isValid ())
     996    {
     997      QMessageBox::warning (this, tr ("Error"), tr ("Invalid URL \"%1\"").arg (url));
    998998    }
    999999  else
     
    10021002
    10031003      foreach (int id, myIds)
    1004         if (myTrackerModel->find(id,url) == -1)
     1004        if (myTrackerModel->find (id,url) == -1)
    10051005          ids.insert (id);
    10061006
    1007       if (ids.empty()) // all the torrents already have this tracker
     1007      if (ids.empty ()) // all the torrents already have this tracker
    10081008        {
    1009           QMessageBox::warning (this, tr("Error"), tr("Tracker already exists."));
     1009          QMessageBox::warning (this, tr ("Error"), tr ("Tracker already exists."));
    10101010        }
    10111011        else
     
    10221022Details :: onEditTrackerClicked ()
    10231023{
    1024   QItemSelectionModel * selectionModel = myTrackerView->selectionModel();
    1025   QModelIndexList selectedRows = selectionModel->selectedRows();
    1026   assert (selectedRows.size() == 1);
    1027   QModelIndex i = selectionModel->currentIndex();
    1028   const TrackerInfo trackerInfo = myTrackerView->model()->data(i, TrackerModel::TrackerRole).value<TrackerInfo>();
     1024  QItemSelectionModel * selectionModel = myTrackerView->selectionModel ();
     1025  QModelIndexList selectedRows = selectionModel->selectedRows ();
     1026  assert (selectedRows.size () == 1);
     1027  QModelIndex i = selectionModel->currentIndex ();
     1028  const TrackerInfo trackerInfo = myTrackerView->model ()->data (i, TrackerModel::TrackerRole).value<TrackerInfo> ();
    10291029
    10301030  bool ok = false;
    10311031  const QString newval = QInputDialog::getText (this,
    1032                                                 tr("Edit URL "),
    1033                                                 tr("Edit tracker announce URL:"),
     1032                                                tr ("Edit URL "),
     1033                                                tr ("Edit tracker announce URL:"),
    10341034                                                QLineEdit::Normal,
    10351035                                                trackerInfo.st.announce, &ok);
     
    10391039      // user pressed "cancel" -- noop
    10401040    }
    1041   else if( !QUrl(newval).isValid( ) )
    1042     {
    1043       QMessageBox::warning (this, tr("Error"), tr("Invalid URL \"%1\"").arg(newval));
     1041  else if (!QUrl (newval).isValid ())
     1042    {
     1043      QMessageBox::warning (this, tr ("Error"), tr ("Invalid URL \"%1\"").arg (newval));
    10441044    }
    10451045    else
     
    10561056
    10571057void
    1058 Details :: onRemoveTrackerClicked( )
     1058Details :: onRemoveTrackerClicked ()
    10591059{
    10601060    // make a map of torrentIds to announce URLs to remove
    1061     QItemSelectionModel * selectionModel = myTrackerView->selectionModel( );
    1062     QModelIndexList selectedRows = selectionModel->selectedRows( );
     1061    QItemSelectionModel * selectionModel = myTrackerView->selectionModel ();
     1062    QModelIndexList selectedRows = selectionModel->selectedRows ();
    10631063    QMap<int,int> torrentId_to_trackerIds;
    1064     foreach( QModelIndex i, selectedRows )
    1065     {
    1066         const TrackerInfo inf = myTrackerView->model()->data( i, TrackerModel::TrackerRole ).value<TrackerInfo>();
    1067         torrentId_to_trackerIds.insertMulti( inf.torrentId, inf.st.id );
     1064    foreach (QModelIndex i, selectedRows)
     1065    {
     1066        const TrackerInfo inf = myTrackerView->model ()->data (i, TrackerModel::TrackerRole).value<TrackerInfo> ();
     1067        torrentId_to_trackerIds.insertMulti (inf.torrentId, inf.st.id);
    10681068    }
    10691069
    10701070    // batch all of a tracker's torrents into one command
    1071     foreach( int id, torrentId_to_trackerIds.uniqueKeys( ) )
     1071    foreach (int id, torrentId_to_trackerIds.uniqueKeys ())
    10721072    {
    10731073        QSet<int> ids;
    10741074        ids << id;
    1075         mySession.torrentSet( ids, TR_KEY_trackerRemove, torrentId_to_trackerIds.values( id ) );
    1076     }
    1077 
    1078     selectionModel->clearSelection( );
    1079     getNewData( );
     1075        mySession.torrentSet (ids, TR_KEY_trackerRemove, torrentId_to_trackerIds.values (id));
     1076    }
     1077
     1078    selectionModel->clearSelection ();
     1079    getNewData ();
    10801080}
    10811081
    10821082QWidget *
    1083 Details :: createOptionsTab( )
     1083Details :: createOptionsTab ()
    10841084{
    10851085    QSpinBox * s;
     
    10881088    QHBoxLayout * h;
    10891089    QDoubleSpinBox * ds;
    1090     const QString speed_K_str = Formatter::unitStr( Formatter::SPEED, Formatter::KB );
    1091 
    1092     HIG * hig = new HIG( this );
    1093     hig->addSectionTitle( tr( "Speed" ) );
    1094 
    1095     c = new QCheckBox( tr( "Honor global &limits" ) );
     1090    const QString speed_K_str = Formatter::unitStr (Formatter::SPEED, Formatter::KB);
     1091
     1092    HIG * hig = new HIG (this);
     1093    hig->addSectionTitle (tr ("Speed"));
     1094
     1095    c = new QCheckBox (tr ("Honor global &limits"));
    10961096    mySessionLimitCheck = c;
    1097     hig->addWideControl( c );
    1098     connect( c, SIGNAL(clicked(bool)), this, SLOT(onHonorsSessionLimitsToggled(bool)) );
    1099 
    1100     c = new QCheckBox( tr( "Limit &download speed (%1):" ).arg( speed_K_str ) );
     1097    hig->addWideControl (c);
     1098    connect (c, SIGNAL (clicked (bool)), this, SLOT (onHonorsSessionLimitsToggled (bool)));
     1099
     1100    c = new QCheckBox (tr ("Limit &download speed (%1):").arg (speed_K_str));
    11011101    mySingleDownCheck = c;
    1102     s = new QSpinBox( );
     1102    s = new QSpinBox ();
    11031103    s->setProperty (PREF_KEY, TR_KEY_downloadLimit);
    1104     s->setSingleStep( 5 );
    1105     s->setRange( 0, INT_MAX );
     1104    s->setSingleStep (5);
     1105    s->setRange (0, INT_MAX);
    11061106    mySingleDownSpin = s;
    1107     hig->addRow( c, s );
    1108     enableWhenChecked( c, s );
    1109     connect( c, SIGNAL(clicked(bool)), this, SLOT(onDownloadLimitedToggled(bool)) );
    1110     connect( s, SIGNAL(editingFinished()), this, SLOT(onSpinBoxEditingFinished()));
    1111 
    1112     c = new QCheckBox( tr( "Limit &upload speed (%1):" ).arg( speed_K_str ) );
     1107    hig->addRow (c, s);
     1108    enableWhenChecked (c, s);
     1109    connect (c, SIGNAL (clicked (bool)), this, SLOT (onDownloadLimitedToggled (bool)));
     1110    connect (s, SIGNAL (editingFinished ()), this, SLOT (onSpinBoxEditingFinished ()));
     1111
     1112    c = new QCheckBox (tr ("Limit &upload speed (%1):").arg (speed_K_str));
    11131113    mySingleUpCheck = c;
    1114     s = new QSpinBox( );
    1115     s->setSingleStep( 5 );
    1116     s->setRange( 0, INT_MAX );
    1117     s->setProperty( PREF_KEY, TR_KEY_uploadLimit );
     1114    s = new QSpinBox ();
     1115    s->setSingleStep (5);
     1116    s->setRange (0, INT_MAX);
     1117    s->setProperty (PREF_KEY, TR_KEY_uploadLimit);
    11181118    mySingleUpSpin = s;
    1119     hig->addRow( c, s );
    1120     enableWhenChecked( c, s );
    1121     connect( c, SIGNAL(clicked(bool)), this, SLOT(onUploadLimitedToggled(bool)) );
    1122     connect( s, SIGNAL(editingFinished()), this, SLOT(onSpinBoxEditingFinished()));
     1119    hig->addRow (c, s);
     1120    enableWhenChecked (c, s);
     1121    connect (c, SIGNAL (clicked (bool)), this, SLOT (onUploadLimitedToggled (bool)));
     1122    connect (s, SIGNAL (editingFinished ()), this, SLOT (onSpinBoxEditingFinished ()));
    11231123
    11241124    m = new QComboBox;
    1125     m->addItem( tr( "High" ),   TR_PRI_HIGH );
    1126     m->addItem( tr( "Normal" ), TR_PRI_NORMAL );
    1127     m->addItem( tr( "Low" ),    TR_PRI_LOW );
    1128     connect( m, SIGNAL(currentIndexChanged(int)), this, SLOT(onBandwidthPriorityChanged(int)));
    1129     hig->addRow( tr( "Torrent &priority:" ), m );
     1125    m->addItem (tr ("High"),   TR_PRI_HIGH);
     1126    m->addItem (tr ("Normal"), TR_PRI_NORMAL);
     1127    m->addItem (tr ("Low"),    TR_PRI_LOW);
     1128    connect (m, SIGNAL (currentIndexChanged (int)), this, SLOT (onBandwidthPriorityChanged (int)));
     1129    hig->addRow (tr ("Torrent &priority:"), m);
    11301130    myBandwidthPriorityCombo = m;
    11311131
    1132     hig->addSectionDivider( );
    1133     hig->addSectionTitle( tr( "Seeding Limits" ) );
    1134 
    1135     h = new QHBoxLayout( );
    1136     h->setSpacing( HIG :: PAD );
     1132    hig->addSectionDivider ();
     1133    hig->addSectionTitle (tr ("Seeding Limits"));
     1134
     1135    h = new QHBoxLayout ();
     1136    h->setSpacing (HIG :: PAD);
    11371137    m = new QComboBox;
    1138     m->addItem( tr( "Use Global Settings" ),      TR_RATIOLIMIT_GLOBAL );
    1139     m->addItem( tr( "Seed regardless of ratio" ), TR_RATIOLIMIT_UNLIMITED );
    1140     m->addItem( tr( "Stop seeding at ratio:" ),   TR_RATIOLIMIT_SINGLE );
    1141     connect( m, SIGNAL(currentIndexChanged(int)), this, SLOT(onRatioModeChanged(int)));
    1142     h->addWidget( myRatioCombo = m );
    1143     ds = new QDoubleSpinBox( );
    1144     ds->setRange( 0.5, INT_MAX );
    1145     ds->setProperty( PREF_KEY, TR_KEY_seedRatioLimit );
    1146     connect( ds, SIGNAL(editingFinished()), this, SLOT(onSpinBoxEditingFinished()));
    1147     h->addWidget( myRatioSpin = ds );
    1148     hig->addRow( tr( "&Ratio:" ), h, m );
    1149 
    1150     h = new QHBoxLayout( );
    1151     h->setSpacing( HIG :: PAD );
     1138    m->addItem (tr ("Use Global Settings"),      TR_RATIOLIMIT_GLOBAL);
     1139    m->addItem (tr ("Seed regardless of ratio"), TR_RATIOLIMIT_UNLIMITED);
     1140    m->addItem (tr ("Stop seeding at ratio:"),   TR_RATIOLIMIT_SINGLE);
     1141    connect (m, SIGNAL (currentIndexChanged (int)), this, SLOT (onRatioModeChanged (int)));
     1142    h->addWidget (myRatioCombo = m);
     1143    ds = new QDoubleSpinBox ();
     1144    ds->setRange (0.5, INT_MAX);
     1145    ds->setProperty (PREF_KEY, TR_KEY_seedRatioLimit);
     1146    connect (ds, SIGNAL (editingFinished ()), this, SLOT (onSpinBoxEditingFinished ()));
     1147    h->addWidget (myRatioSpin = ds);
     1148    hig->addRow (tr ("&Ratio:"), h, m);
     1149
     1150    h = new QHBoxLayout ();
     1151    h->setSpacing (HIG :: PAD);
    11521152    m = new QComboBox;
    1153     m->addItem( tr( "Use Global Settings" ),                 TR_IDLELIMIT_GLOBAL );
    1154     m->addItem( tr( "Seed regardless of activity" ),         TR_IDLELIMIT_UNLIMITED );
    1155     m->addItem( tr( "Stop seeding if idle for N minutes:" ), TR_IDLELIMIT_SINGLE );
    1156     connect( m, SIGNAL(currentIndexChanged(int)), this, SLOT(onIdleModeChanged(int)));
    1157     h->addWidget( myIdleCombo = m );
    1158     s = new QSpinBox( );
    1159     s->setSingleStep( 5 );
    1160     s->setRange( 1, 9999 );
    1161     s->setProperty( PREF_KEY, TR_KEY_seedIdleLimit );
    1162     connect( s, SIGNAL(editingFinished()), this, SLOT(onSpinBoxEditingFinished()));
    1163     h->addWidget( myIdleSpin = s );
    1164     hig->addRow( tr( "&Idle:" ), h, m );
    1165 
    1166 
    1167     hig->addSectionDivider( );
    1168     hig->addSectionTitle( tr( "Peer Connections" ) );
    1169 
    1170     s = new QSpinBox( );
    1171     s->setSingleStep( 5 );
    1172     s->setRange( 1, 300 );
    1173     s->setProperty( PREF_KEY, TR_KEY_peer_limit );
    1174     connect( s, SIGNAL(editingFinished()), this, SLOT(onSpinBoxEditingFinished()));
     1153    m->addItem (tr ("Use Global Settings"),                 TR_IDLELIMIT_GLOBAL);
     1154    m->addItem (tr ("Seed regardless of activity"),         TR_IDLELIMIT_UNLIMITED);
     1155    m->addItem (tr ("Stop seeding if idle for N minutes:"), TR_IDLELIMIT_SINGLE);
     1156    connect (m, SIGNAL (currentIndexChanged (int)), this, SLOT (onIdleModeChanged (int)));
     1157    h->addWidget (myIdleCombo = m);
     1158    s = new QSpinBox ();
     1159    s->setSingleStep (5);
     1160    s->setRange (1, 9999);
     1161    s->setProperty (PREF_KEY, TR_KEY_seedIdleLimit);
     1162    connect (s, SIGNAL (editingFinished ()), this, SLOT (onSpinBoxEditingFinished ()));
     1163    h->addWidget (myIdleSpin = s);
     1164    hig->addRow (tr ("&Idle:"), h, m);
     1165
     1166
     1167    hig->addSectionDivider ();
     1168    hig->addSectionTitle (tr ("Peer Connections"));
     1169
     1170    s = new QSpinBox ();
     1171    s->setSingleStep (5);
     1172    s->setRange (1, 300);
     1173    s->setProperty (PREF_KEY, TR_KEY_peer_limit);
     1174    connect (s, SIGNAL (editingFinished ()), this, SLOT (onSpinBoxEditingFinished ()));
    11751175    myPeerLimitSpin = s;
    1176     hig->addRow( tr( "&Maximum peers:" ), s );
    1177 
    1178     hig->finish( );
     1176    hig->addRow (tr ("&Maximum peers:"), s);
     1177
     1178    hig->finish ();
    11791179
    11801180    return hig;
     
    11861186
    11871187QWidget *
    1188 Details :: createTrackerTab( )
     1188Details :: createTrackerTab ()
    11891189{
    11901190    QCheckBox * c;
    11911191    QPushButton * p;
    11921192    QWidget * top = new QWidget;
    1193     QVBoxLayout * v = new QVBoxLayout( top );
    1194     QHBoxLayout * h = new QHBoxLayout();
    1195     QVBoxLayout * v2 = new QVBoxLayout();
    1196 
    1197     v->setSpacing( HIG::PAD_BIG );
    1198     v->setContentsMargins( HIG::PAD_BIG, HIG::PAD_BIG, HIG::PAD_BIG, HIG::PAD_BIG );
    1199 
    1200     h->setSpacing( HIG::PAD );
    1201     h->setContentsMargins( HIG::PAD_SMALL, HIG::PAD_SMALL, HIG::PAD_SMALL, HIG::PAD_SMALL );
    1202 
    1203     v2->setSpacing( HIG::PAD );
     1193    QVBoxLayout * v = new QVBoxLayout (top);
     1194    QHBoxLayout * h = new QHBoxLayout ();
     1195    QVBoxLayout * v2 = new QVBoxLayout ();
     1196
     1197    v->setSpacing (HIG::PAD_BIG);
     1198    v->setContentsMargins (HIG::PAD_BIG, HIG::PAD_BIG, HIG::PAD_BIG, HIG::PAD_BIG);
     1199
     1200    h->setSpacing (HIG::PAD);
     1201    h->setContentsMargins (HIG::PAD_SMALL, HIG::PAD_SMALL, HIG::PAD_SMALL, HIG::PAD_SMALL);
     1202
     1203    v2->setSpacing (HIG::PAD);
    12041204
    12051205    myTrackerModel = new TrackerModel;
    12061206    myTrackerFilter = new TrackerModelFilter;
    1207     myTrackerFilter->setSourceModel( myTrackerModel );
     1207    myTrackerFilter->setSourceModel (myTrackerModel);
    12081208    myTrackerView = new QTreeView;
    1209     myTrackerView->setModel( myTrackerFilter );
    1210     myTrackerView->setHeaderHidden( true );
    1211     myTrackerView->setSelectionMode( QTreeWidget::ExtendedSelection );
    1212     myTrackerView->setRootIsDecorated( false );
    1213     myTrackerView->setIndentation( 2 );
    1214     myTrackerView->setItemsExpandable( false );
    1215     myTrackerView->setAlternatingRowColors( true );
    1216     myTrackerView->setItemDelegate( myTrackerDelegate = new TrackerDelegate( ) );
    1217     connect( myTrackerView->selectionModel(), SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)), this, SLOT(onTrackerSelectionChanged()));
    1218     h->addWidget( myTrackerView, 1 );
    1219 
    1220     p = new QPushButton();
    1221     p->setIcon( getStockIcon( "list-add", QStyle::SP_DialogOpenButton ) );
    1222     p->setToolTip( tr( "Add Tracker" ));
     1209    myTrackerView->setModel (myTrackerFilter);
     1210    myTrackerView->setHeaderHidden (true);
     1211    myTrackerView->setSelectionMode (QTreeWidget::ExtendedSelection);
     1212    myTrackerView->setRootIsDecorated (false);
     1213    myTrackerView->setIndentation (2);
     1214    myTrackerView->setItemsExpandable (false);
     1215    myTrackerView->setAlternatingRowColors (true);
     1216    myTrackerView->setItemDelegate (myTrackerDelegate = new TrackerDelegate ());
     1217    connect (myTrackerView->selectionModel (), SIGNAL (selectionChanged (const QItemSelection&, const QItemSelection&)), this, SLOT (onTrackerSelectionChanged ()));
     1218    h->addWidget (myTrackerView, 1);
     1219
     1220    p = new QPushButton ();
     1221    p->setIcon (getStockIcon ("list-add", QStyle::SP_DialogOpenButton));
     1222    p->setToolTip (tr ("Add Tracker"));
    12231223    myAddTrackerButton = p;
    1224     v2->addWidget( p, 1 );
    1225     connect( p, SIGNAL(clicked(bool)), this, SLOT(onAddTrackerClicked()));
    1226 
    1227     p = new QPushButton();
    1228     p->setIcon( getStockIcon( "document-properties", QStyle::SP_DesktopIcon ) );
    1229     p->setToolTip( tr( "Edit Tracker" ));
     1224    v2->addWidget (p, 1);
     1225    connect (p, SIGNAL (clicked (bool)), this, SLOT (onAddTrackerClicked ()));
     1226
     1227    p = new QPushButton ();
     1228    p->setIcon (getStockIcon ("document-properties", QStyle::SP_DesktopIcon));
     1229    p->setToolTip (tr ("Edit Tracker"));
    12301230    myAddTrackerButton = p;
    1231     p->setEnabled( false );
     1231    p->setEnabled (false);
    12321232    myEditTrackerButton = p;
    1233     v2->addWidget( p, 1 );
    1234     connect( p, SIGNAL(clicked(bool)), this, SLOT(onEditTrackerClicked()));
    1235 
    1236     p = new QPushButton();
    1237     p->setIcon( getStockIcon( "list-remove", QStyle::SP_TrashIcon ) );
    1238     p->setToolTip( tr( "Remove Trackers" ));
    1239     p->setEnabled( false );
     1233    v2->addWidget (p, 1);
     1234    connect (p, SIGNAL (clicked (bool)), this, SLOT (onEditTrackerClicked ()));
     1235
     1236    p = new QPushButton ();
     1237    p->setIcon (getStockIcon ("list-remove", QStyle::SP_TrashIcon));
     1238    p->setToolTip (tr ("Remove Trackers"));
     1239    p->setEnabled (false);
    12401240    myRemoveTrackerButton = p;
    1241     v2->addWidget( p, 1 );
    1242     connect( p, SIGNAL(clicked(bool)), this, SLOT(onRemoveTrackerClicked()));
    1243 
    1244     v2->addStretch( 1 );
    1245 
    1246     h->addLayout( v2, 1 );
    1247     h->setStretch( 1, 0 );
    1248 
    1249     v->addLayout( h, 1 );
    1250 
    1251     c = new QCheckBox( tr( "Show &more details" ) );
    1252     c->setChecked( myPrefs.getBool( Prefs::SHOW_TRACKER_SCRAPES ) );
     1241    v2->addWidget (p, 1);
     1242    connect (p, SIGNAL (clicked (bool)), this, SLOT (onRemoveTrackerClicked ()));
     1243
     1244    v2->addStretch (1);
     1245
     1246    h->addLayout (v2, 1);
     1247    h->setStretch (1, 0);
     1248
     1249    v->addLayout (h, 1);
     1250
     1251    c = new QCheckBox (tr ("Show &more details"));
     1252    c->setChecked (myPrefs.getBool (Prefs::SHOW_TRACKER_SCRAPES));
    12531253    myShowTrackerScrapesCheck = c;
    1254     v->addWidget( c, 1 );
    1255     connect( c, SIGNAL(clicked(bool)), this, SLOT(onShowTrackerScrapesToggled(bool)) );
    1256 
    1257     c = new QCheckBox( tr( "Show &backup trackers" ) );
    1258     c->setChecked( myPrefs.getBool( Prefs::SHOW_BACKUP_TRACKERS ) );
     1254    v->addWidget (c, 1);
     1255    connect (c, SIGNAL (clicked (bool)), this, SLOT (onShowTrackerScrapesToggled (bool)));
     1256
     1257    c = new QCheckBox (tr ("Show &backup trackers"));
     1258    c->setChecked (myPrefs.getBool (Prefs::SHOW_BACKUP_TRACKERS));
    12591259    myShowBackupTrackersCheck = c;
    1260     v->addWidget( c, 1 );
    1261     connect( c, SIGNAL(clicked(bool)), this, SLOT(onShowBackupTrackersToggled(bool)) );
     1260    v->addWidget (c, 1);
     1261    connect (c, SIGNAL (clicked (bool)), this, SLOT (onShowBackupTrackersToggled (bool)));
    12621262
    12631263    return top;
     
    12691269
    12701270QWidget *
    1271 Details :: createPeersTab( )
     1271Details :: createPeersTab ()
    12721272{
    12731273    QWidget * top = new QWidget;
    1274     QVBoxLayout * v = new QVBoxLayout( top );
    1275     v->setSpacing( HIG :: PAD_BIG );
    1276     v->setContentsMargins( HIG::PAD_BIG, HIG::PAD_BIG, HIG::PAD_BIG, HIG::PAD_BIG );
     1274    QVBoxLayout * v = new QVBoxLayout (top);
     1275    v->setSpacing (HIG :: PAD_BIG);
     1276    v->setContentsMargins (HIG::PAD_BIG, HIG::PAD_BIG, HIG::PAD_BIG, HIG::PAD_BIG);
    12771277
    12781278    QStringList headers;
    1279     headers << QString() << tr("Up") << tr("Down") << tr("%") << tr("Status") << tr("Address") << tr("Client");
     1279    headers << QString () << tr ("Up") << tr ("Down") << tr ("%") << tr ("Status") << tr ("Address") << tr ("Client");
    12801280    myPeerTree = new QTreeWidget;
    1281     myPeerTree->setUniformRowHeights( true );
    1282     myPeerTree->setHeaderLabels( headers );
    1283     myPeerTree->setColumnWidth( 0, 20 );
    1284     myPeerTree->setSortingEnabled( true );
    1285     myPeerTree->sortByColumn( COL_ADDRESS, Qt::AscendingOrder );
    1286     myPeerTree->setRootIsDecorated( false );
    1287     myPeerTree->setTextElideMode( Qt::ElideRight );
    1288     v->addWidget( myPeerTree, 1 );
    1289 
    1290     const QFontMetrics m( font( ) );
    1291     QSize size = m.size( 0, "1024 MiB/s" );
    1292     myPeerTree->setColumnWidth( COL_UP, size.width( ) );
    1293     myPeerTree->setColumnWidth( COL_DOWN, size.width( ) );
    1294     size = m.size( 0, " 100% " );
    1295     myPeerTree->setColumnWidth( COL_PERCENT, size.width( ) );
    1296     size = m.size( 0, "ODUK?EXI" );
    1297     myPeerTree->setColumnWidth( COL_STATUS, size.width( ) );
    1298     size = m.size( 0, "888.888.888.888" );
    1299     myPeerTree->setColumnWidth( COL_ADDRESS, size.width( ) );
    1300     size = m.size( 0, "Some BitTorrent Client" );
    1301     myPeerTree->setColumnWidth( COL_CLIENT, size.width( ) );
    1302     myPeerTree->setAlternatingRowColors( true );
     1281    myPeerTree->setUniformRowHeights (true);
     1282    myPeerTree->setHeaderLabels (headers);
     1283    myPeerTree->setColumnWidth (0, 20);
     1284    myPeerTree->setSortingEnabled (true);
     1285    myPeerTree->sortByColumn (COL_ADDRESS, Qt::AscendingOrder);
     1286    myPeerTree->setRootIsDecorated (false);
     1287    myPeerTree->setTextElideMode (Qt::ElideRight);
     1288    v->addWidget (myPeerTree, 1);
     1289
     1290    const QFontMetrics m (font ());
     1291    QSize size = m.size (0, "1024 MiB/s");
     1292    myPeerTree->setColumnWidth (COL_UP, size.width ());
     1293    myPeerTree->setColumnWidth (COL_DOWN, size.width ());
     1294    size = m.size (0, " 100% ");
     1295    myPeerTree->setColumnWidth (COL_PERCENT, size.width ());
     1296    size = m.size (0, "ODUK?EXI");
     1297    myPeerTree->setColumnWidth (COL_STATUS, size.width ());
     1298    size = m.size (0, "888.888.888.888");
     1299    myPeerTree->setColumnWidth (COL_ADDRESS, size.width ());
     1300    size = m.size (0, "Some BitTorrent Client");
     1301    myPeerTree->setColumnWidth (COL_CLIENT, size.width ());
     1302    myPeerTree->setAlternatingRowColors (true);
    13031303
    13041304    return top;
     
    13101310
    13111311QWidget *
    1312 Details :: createFilesTab( )
    1313 {
    1314     myFileTreeView = new FileTreeView( );
    1315 
    1316     connect( myFileTreeView, SIGNAL(      priorityChanged(const QSet<int>&, int)),
    1317              this,           SLOT(  onFilePriorityChanged(const QSet<int>&, int)));
    1318 
    1319     connect( myFileTreeView, SIGNAL(      wantedChanged(const QSet<int>&, bool)),
    1320              this,           SLOT(  onFileWantedChanged(const QSet<int>&, bool)));
    1321 
    1322     connect( myFileTreeView, SIGNAL( pathEdited(const QString&, const QString&)),
    1323              this,           SLOT (onPathEdited(const QString&, const QString&)));
     1312Details :: createFilesTab ()
     1313{
     1314    myFileTreeView = new FileTreeView ();
     1315
     1316    connect (myFileTreeView, SIGNAL (     priorityChanged (const QSet<int>&, int)),
     1317             this,           SLOT ( onFilePriorityChanged (const QSet<int>&, int)));
     1318
     1319    connect (myFileTreeView, SIGNAL (     wantedChanged (const QSet<int>&, bool)),
     1320             this,           SLOT ( onFileWantedChanged (const QSet<int>&, bool)));
     1321
     1322    connect (myFileTreeView, SIGNAL (pathEdited (const QString&, const QString&)),
     1323             this,           SLOT (onPathEdited (const QString&, const QString&)));
    13241324
    13251325    return myFileTreeView;
     
    13461346    }
    13471347
    1348   mySession.torrentSet (myIds, key, indices.toList());
    1349     getNewData( );
     1348  mySession.torrentSet (myIds, key, indices.toList ());
     1349    getNewData ();
    13501350}
    13511351
     
    13541354{
    13551355  const tr_quark key = wanted ? TR_KEY_files_wanted : TR_KEY_files_unwanted;
    1356   mySession.torrentSet (myIds, key, indices.toList());
     1356  mySession.torrentSet (myIds, key, indices.toList ());
    13571357  getNewData ();
    13581358}
  • trunk/qt/details.h

    r13810 r13869  
    4343class Details: public QDialog
    4444{
    45         Q_OBJECT
     45    Q_OBJECT
    4646
    47     private:
    48         void getNewData( );
     47  private:
     48    void getNewData ();
    4949
    50     private slots:
    51         void onTorrentChanged( );
    52         void onTorrentFileListRebuilt( );
    53         void onTimer( );
     50  private slots:
     51    void onTorrentChanged ();
     52    void onTorrentFileListRebuilt ();
     53    void onTimer ();
    5454
    55     public:
    56         Details( Session&, Prefs&, TorrentModel&, QWidget * parent = 0 );
    57         ~Details( );
    58         void setIds( const QSet<int>& ids );
     55  public:
     56    Details (Session&, Prefs&, TorrentModel&, QWidget * parent = 0);
     57    ~Details ();
     58    void setIds (const QSet<int>& ids);
    5959
    60     private:
    61         QWidget * createPeersTab( );
    62         QWidget * createTrackerTab( );
    63         QWidget * createInfoTab( );
    64         QWidget * createFilesTab( );
    65         QWidget * createOptionsTab( );
     60  private:
     61    QWidget * createPeersTab ();
     62    QWidget * createTrackerTab ();
     63    QWidget * createInfoTab ();
     64    QWidget * createFilesTab ();
     65    QWidget * createOptionsTab ();
    6666
    67     private:
    68         QIcon getStockIcon( const QString& freedesktop_name, int fallback );
    69         QString timeToStringRounded( int seconds );
    70         QString trimToDesiredWidth( const QString& str );
    71         void enableWhenChecked( QCheckBox *, QWidget * );
     67  private:
     68    QIcon getStockIcon (const QString& freedesktop_name, int fallback);
     69    QString timeToStringRounded (int seconds);
     70    QString trimToDesiredWidth (const QString& str);
     71    void enableWhenChecked (QCheckBox *, QWidget *);
    7272
    73     private:
    74         Session& mySession;
    75         Prefs& myPrefs;
    76         TorrentModel& myModel;
    77         QSet<int> myIds;
    78         QTimer myTimer;
    79         bool myChangedTorrents;
    80         bool myHavePendingRefresh;
     73  private:
     74    Session& mySession;
     75    Prefs& myPrefs;
     76    TorrentModel& myModel;
     77    QSet<int> myIds;
     78    QTimer myTimer;
     79    bool myChangedTorrents;
     80    bool myHavePendingRefresh;
    8181
    82         QLabel * myStateLabel;
    83         QLabel * myHaveLabel;
    84         QLabel * myAvailabilityLabel;
    85         QLabel * myDownloadedLabel;
    86         QLabel * myUploadedLabel;
    87         QLabel * myErrorLabel;
    88         QLabel * myRunTimeLabel;
    89         QLabel * myETALabel;
    90         QLabel * myLastActivityLabel;
     82    QLabel * myStateLabel;
     83    QLabel * myHaveLabel;
     84    QLabel * myAvailabilityLabel;
     85    QLabel * myDownloadedLabel;
     86    QLabel * myUploadedLabel;
     87    QLabel * myErrorLabel;
     88    QLabel * myRunTimeLabel;
     89    QLabel * myETALabel;
     90    QLabel * myLastActivityLabel;
    9191
    92         QCheckBox * mySessionLimitCheck;
    93         QCheckBox * mySingleDownCheck;
    94         QCheckBox * mySingleUpCheck;
    95         QCheckBox * myShowTrackerScrapesCheck;
    96         QCheckBox * myShowBackupTrackersCheck;
    97         QPushButton * myAddTrackerButton;
    98         QPushButton * myEditTrackerButton;
    99         QPushButton * myRemoveTrackerButton;
    100         QSpinBox * mySingleDownSpin;
    101         QSpinBox * mySingleUpSpin;
    102         QComboBox * myRatioCombo;
    103         QDoubleSpinBox * myRatioSpin;
    104         QComboBox * myIdleCombo;
    105         QSpinBox * myIdleSpin;
    106         QSpinBox * myPeerLimitSpin;
    107         QComboBox * myBandwidthPriorityCombo;
     92    QCheckBox * mySessionLimitCheck;
     93    QCheckBox * mySingleDownCheck;
     94    QCheckBox * mySingleUpCheck;
     95    QCheckBox * myShowTrackerScrapesCheck;
     96    QCheckBox * myShowBackupTrackersCheck;
     97    QPushButton * myAddTrackerButton;
     98    QPushButton * myEditTrackerButton;
     99    QPushButton * myRemoveTrackerButton;
     100    QSpinBox * mySingleDownSpin;
     101    QSpinBox * mySingleUpSpin;
     102    QComboBox * myRatioCombo;
     103    QDoubleSpinBox * myRatioSpin;
     104    QComboBox * myIdleCombo;
     105    QSpinBox * myIdleSpin;
     106    QSpinBox * myPeerLimitSpin;
     107    QComboBox * myBandwidthPriorityCombo;
    108108
    109         QLabel * mySizeLabel;
    110         QLabel * myHashLabel;
    111         QLabel * myPrivacyLabel;
    112         QLabel * myOriginLabel;
    113         QLabel * myLocationLabel;
    114         QTextBrowser * myCommentBrowser;
     109    QLabel * mySizeLabel;
     110    QLabel * myHashLabel;
     111    QLabel * myPrivacyLabel;
     112    QLabel * myOriginLabel;
     113    QLabel * myLocationLabel;
     114    QTextBrowser * myCommentBrowser;
    115115
    116         QLabel * myTrackerLabel;
    117         QLabel * myScrapeTimePrevLabel;
    118         QLabel * myScrapeTimeNextLabel;
    119         QLabel * myScrapeResponseLabel;
    120         QLabel * myAnnounceTimePrevLabel;
    121         QLabel * myAnnounceTimeNextLabel;
    122         QLabel * myAnnounceResponseLabel;
    123         QLabel * myAnnounceManualLabel;
     116    QLabel * myTrackerLabel;
     117    QLabel * myScrapeTimePrevLabel;
     118    QLabel * myScrapeTimeNextLabel;
     119    QLabel * myScrapeResponseLabel;
     120    QLabel * myAnnounceTimePrevLabel;
     121    QLabel * myAnnounceTimeNextLabel;
     122    QLabel * myAnnounceResponseLabel;
     123    QLabel * myAnnounceManualLabel;
    124124
    125         TrackerModel * myTrackerModel;
    126         TrackerModelFilter * myTrackerFilter;
    127         TrackerDelegate * myTrackerDelegate;
    128         QTreeView * myTrackerView;
    129         //QMap<QString,QTreeWidgetItem*> myTrackerTiers;
    130         //QMap<QString,QTreeWidgetItem*> myTrackerItems;
     125    TrackerModel * myTrackerModel;
     126    TrackerModelFilter * myTrackerFilter;
     127    TrackerDelegate * myTrackerDelegate;
     128    QTreeView * myTrackerView;
     129    //QMap<QString,QTreeWidgetItem*> myTrackerTiers;
     130    //QMap<QString,QTreeWidgetItem*> myTrackerItems;
    131131
    132         QTreeWidget * myPeerTree;
    133         QMap<QString,QTreeWidgetItem*> myPeers;
     132    QTreeWidget * myPeerTree;
     133    QMap<QString,QTreeWidgetItem*> myPeers;
    134134
    135         QWidgetList myWidgets;
     135    QWidgetList myWidgets;
    136136
    137         FileTreeView * myFileTreeView;
     137    FileTreeView * myFileTreeView;
    138138
    139         bool myFilesDirty;
     139    bool myFilesDirty;
    140140
    141     private slots:
    142         void refreshPref( int key );
    143         void onBandwidthPriorityChanged( int );
    144         void onFilePriorityChanged( const QSet<int>& fileIndices, int );
    145         void onFileWantedChanged( const QSet<int>& fileIndices, bool );
    146         void onPathEdited (const QString& oldpath, const QString& newname);
    147         void onHonorsSessionLimitsToggled( bool );
    148         void onDownloadLimitedToggled( bool );
    149         void onSpinBoxEditingFinished( );
    150         void onUploadLimitedToggled( bool );
    151         void onRatioModeChanged( int );
    152         void onIdleModeChanged( int );
    153         void onShowTrackerScrapesToggled( bool );
    154         void onShowBackupTrackersToggled( bool );
    155         void onTrackerSelectionChanged( );
    156         void onAddTrackerClicked( );
    157         void onEditTrackerClicked( );
    158         void onRemoveTrackerClicked( );
    159         void refresh( );
     141  private slots:
     142    void refreshPref (int key);
     143    void onBandwidthPriorityChanged (int);
     144    void onFilePriorityChanged (const QSet<int>& fileIndices, int);
     145    void onFileWantedChanged (const QSet<int>& fileIndices, bool);
     146    void onPathEdited (const QString& oldpath, const QString& newname);
     147    void onHonorsSessionLimitsToggled (bool);
     148    void onDownloadLimitedToggled (bool);
     149    void onSpinBoxEditingFinished ();
     150    void onUploadLimitedToggled (bool);
     151    void onRatioModeChanged (int);
     152    void onIdleModeChanged (int);
     153    void onShowTrackerScrapesToggled (bool);
     154    void onShowBackupTrackersToggled (bool);
     155    void onTrackerSelectionChanged ();
     156    void onAddTrackerClicked ();
     157    void onEditTrackerClicked ();
     158    void onRemoveTrackerClicked ();
     159    void refresh ();
    160160};
    161161
  • trunk/qt/filterbar.cc

    r13720 r13869  
    3939namespace
    4040{
    41     int getHSpacing( QWidget * w )
    42     {
    43         return qMax( int(HIG::PAD_SMALL), w->style()->pixelMetric( QStyle::PM_LayoutHorizontalSpacing, 0, w ) );
    44     }
    45 }
    46 
    47 FilterBarComboBoxDelegate :: FilterBarComboBoxDelegate( QObject * parent, QComboBox * combo ):
    48     QItemDelegate( parent ),
    49     myCombo( combo )
     41  int getHSpacing (QWidget * w)
     42  {
     43    return qMax (int (HIG::PAD_SMALL), w->style ()->pixelMetric (QStyle::PM_LayoutHorizontalSpacing, 0, w));
     44  }
     45}
     46
     47FilterBarComboBoxDelegate :: FilterBarComboBoxDelegate (QObject * parent, QComboBox * combo):
     48  QItemDelegate (parent),
     49  myCombo (combo)
    5050{
    5151}
    5252
    5353bool
    54 FilterBarComboBoxDelegate :: isSeparator( const QModelIndex &index )
    55 {
    56     return index.data(Qt::AccessibleDescriptionRole).toString() == QLatin1String("separator");
    57 }
    58 void
    59 FilterBarComboBoxDelegate :: setSeparator( QAbstractItemModel * model, const QModelIndex& index )
    60 {
    61     model->setData( index, QString::fromLatin1("separator"), Qt::AccessibleDescriptionRole );
    62 
    63     if( QStandardItemModel *m = qobject_cast<QStandardItemModel*>(model) )
    64        if (QStandardItem *item = m->itemFromIndex(index))
    65            item->setFlags(item->flags() & ~(Qt::ItemIsSelectable|Qt::ItemIsEnabled));
    66 }
    67 
    68 void
    69 FilterBarComboBoxDelegate :: paint( QPainter                    * painter,
     54FilterBarComboBoxDelegate :: isSeparator (const QModelIndex &index)
     55{
     56  return index.data (Qt::AccessibleDescriptionRole).toString () == QLatin1String ("separator");
     57}
     58void
     59FilterBarComboBoxDelegate :: setSeparator (QAbstractItemModel * model, const QModelIndex& index)
     60{
     61  model->setData (index, QString::fromLatin1 ("separator"), Qt::AccessibleDescriptionRole);
     62
     63  if (QStandardItemModel *m = qobject_cast<QStandardItemModel*> (model))
     64    if (QStandardItem *item = m->itemFromIndex (index))
     65      item->setFlags (item->flags () & ~ (Qt::ItemIsSelectable|Qt::ItemIsEnabled));
     66}
     67
     68void
     69FilterBarComboBoxDelegate :: paint (QPainter                    * painter,
    7070                                    const QStyleOptionViewItem  & option,
    71                                     const QModelIndex           & index ) const
    72 {
    73     if( isSeparator( index ) )
    74     {
    75         QRect rect = option.rect;
    76         if (const QStyleOptionViewItemV3 *v3 = qstyleoption_cast<const QStyleOptionViewItemV3*>(&option))
    77             if (const QAbstractItemView *view = qobject_cast<const QAbstractItemView*>(v3->widget))
    78                 rect.setWidth(view->viewport()->width());
    79         QStyleOption opt;
    80         opt.rect = rect;
    81         myCombo->style()->drawPrimitive(QStyle::PE_IndicatorToolBarSeparator, &opt, painter, myCombo);
    82     }
    83     else
    84     {
    85         QStyleOptionViewItem disabledOption = option;
    86         disabledOption.state &= ~( QStyle::State_Enabled | QStyle::State_Selected );
    87         QRect boundingBox = option.rect;
    88 
    89         const int hmargin = getHSpacing( myCombo );
    90         boundingBox.setLeft( boundingBox.left() + hmargin );
    91         boundingBox.setRight( boundingBox.right() - hmargin );
    92 
    93         QRect decorationRect = rect( option, index, Qt::DecorationRole );
    94         decorationRect.moveLeft( decorationRect.left( ) );
    95         decorationRect.setSize( myCombo->iconSize( ) );
    96         decorationRect = QStyle::alignedRect( Qt::LeftToRight,
    97                                               Qt::AlignLeft|Qt::AlignVCenter,
    98                                               decorationRect.size(), boundingBox );
    99         boundingBox.setLeft( decorationRect.right() + hmargin );
    100 
    101         QRect countRect  = rect( option, index, TorrentCountRole );
    102         countRect = QStyle::alignedRect( Qt::LeftToRight,
    103                                          Qt::AlignRight|Qt::AlignVCenter,
    104                                          countRect.size(), boundingBox );
    105         boundingBox.setRight( countRect.left() - hmargin );
    106         const QRect displayRect = boundingBox;
    107 
    108         drawBackground( painter, option, index );
    109         QStyleOptionViewItem option2 = option;
    110         option2.decorationSize = myCombo->iconSize( );
    111         drawDecoration( painter, option, decorationRect, decoration(option2,index.data(Qt::DecorationRole)) );
    112         drawDisplay( painter, option, displayRect, index.data(Qt::DisplayRole).toString() );
    113         drawDisplay( painter, disabledOption, countRect, index.data(TorrentCountRole).toString() );
    114         drawFocus( painter, option, displayRect|countRect );
     71                                    const QModelIndex           & index) const
     72{
     73  if (isSeparator (index))
     74    {
     75      QRect rect = option.rect;
     76      if (const QStyleOptionViewItemV3 *v3 = qstyleoption_cast<const QStyleOptionViewItemV3*> (&option))
     77        if (const QAbstractItemView *view = qobject_cast<const QAbstractItemView*> (v3->widget))
     78          rect.setWidth (view->viewport ()->width ());
     79      QStyleOption opt;
     80      opt.rect = rect;
     81      myCombo->style ()->drawPrimitive (QStyle::PE_IndicatorToolBarSeparator, &opt, painter, myCombo);
     82    }
     83  else
     84    {
     85      QStyleOptionViewItem disabledOption = option;
     86      disabledOption.state &= ~ (QStyle::State_Enabled | QStyle::State_Selected);
     87      QRect boundingBox = option.rect;
     88
     89      const int hmargin = getHSpacing (myCombo);
     90      boundingBox.setLeft (boundingBox.left () + hmargin);
     91      boundingBox.setRight (boundingBox.right () - hmargin);
     92
     93      QRect decorationRect = rect (option, index, Qt::DecorationRole);
     94      decorationRect.moveLeft (decorationRect.left ());
     95      decorationRect.setSize (myCombo->iconSize ());
     96      decorationRect = QStyle::alignedRect (Qt::LeftToRight,
     97                                            Qt::AlignLeft|Qt::AlignVCenter,
     98                                            decorationRect.size (), boundingBox);
     99      boundingBox.setLeft (decorationRect.right () + hmargin);
     100
     101      QRect countRect  = rect (option, index, TorrentCountRole);
     102      countRect = QStyle::alignedRect (Qt::LeftToRight,
     103                                       Qt::AlignRight|Qt::AlignVCenter,
     104                                       countRect.size (), boundingBox);
     105      boundingBox.setRight (countRect.left () - hmargin);
     106      const QRect displayRect = boundingBox;
     107
     108      drawBackground (painter, option, index);
     109      QStyleOptionViewItem option2 = option;
     110      option2.decorationSize = myCombo->iconSize ();
     111      drawDecoration (painter, option, decorationRect, decoration (option2,index.data (Qt::DecorationRole)));
     112      drawDisplay (painter, option, displayRect, index.data (Qt::DisplayRole).toString ());
     113      drawDisplay (painter, disabledOption, countRect, index.data (TorrentCountRole).toString ());
     114      drawFocus (painter, option, displayRect|countRect);
    115115    }
    116116}
    117117
    118118QSize
    119 FilterBarComboBoxDelegate :: sizeHint( const QStyleOptionViewItem & option,
    120                                        const QModelIndex          & index ) const
    121 {
    122     if( isSeparator( index ) )
    123     {
    124         const int pm = myCombo->style()->pixelMetric(QStyle::PM_DefaultFrameWidth, 0, myCombo);
    125         return QSize( pm, pm + 10 );
    126     }
    127     else
    128     {
    129         QStyle * s = myCombo->style( );
    130         const int hmargin = getHSpacing( myCombo );
    131 
    132         QSize size = QItemDelegate::sizeHint( option, index );
    133         size.setHeight( qMax( size.height(), myCombo->iconSize().height() + 6 ) );
    134         size.rwidth() += s->pixelMetric( QStyle::PM_FocusFrameHMargin, 0, myCombo );
    135         size.rwidth() += rect(option,index,TorrentCountRole).width();
    136         size.rwidth() += hmargin * 4;
    137         return size;
     119FilterBarComboBoxDelegate :: sizeHint (const QStyleOptionViewItem & option,
     120                                       const QModelIndex          & index) const
     121{
     122  if (isSeparator (index))
     123    {
     124      const int pm = myCombo->style ()->pixelMetric (QStyle::PM_DefaultFrameWidth, 0, myCombo);
     125      return QSize (pm, pm + 10);
     126    }
     127  else
     128    {
     129      QStyle * s = myCombo->style ();
     130      const int hmargin = getHSpacing (myCombo);
     131
     132      QSize size = QItemDelegate::sizeHint (option, index);
     133      size.setHeight (qMax (size.height (), myCombo->iconSize ().height () + 6));
     134      size.rwidth () += s->pixelMetric (QStyle::PM_FocusFrameHMargin, 0, myCombo);
     135      size.rwidth () += rect (option,index,TorrentCountRole).width ();
     136      size.rwidth () += hmargin * 4;
     137      return size;
    138138    }
    139139}
     
    143143**/
    144144
    145 FilterBarComboBox :: FilterBarComboBox( QWidget * parent ):
    146     QComboBox( parent )
    147 {
    148 }
    149 
    150 void
    151 FilterBarComboBox :: paintEvent( QPaintEvent * e )
    152 {
    153     Q_UNUSED( e );
    154 
    155     QStylePainter painter(this);
    156     painter.setPen(palette().color(QPalette::Text));
    157 
    158     // draw the combobox frame, focusrect and selected etc.
    159     QStyleOptionComboBox opt;
    160     initStyleOption(&opt);
    161     painter.drawComplexControl(QStyle::CC_ComboBox, opt);
    162 
    163     // draw the icon and text
    164     const QModelIndex modelIndex = model()->index( currentIndex(), 0, rootModelIndex() );
    165     if( modelIndex.isValid( ) )
    166     {
    167         QStyle * s = style();
    168         QRect rect = s->subControlRect( QStyle::CC_ComboBox, &opt, QStyle::SC_ComboBoxEditField, this );
    169         const int hmargin = getHSpacing( this );
    170         rect.setRight( rect.right() - hmargin );
    171 
    172         // draw the icon
    173         QPixmap pixmap;
    174         QVariant variant = modelIndex.data( Qt::DecorationRole );
    175         switch( variant.type( ) ) {
    176             case QVariant::Pixmap: pixmap = qvariant_cast<QPixmap>(variant); break;
    177             case QVariant::Icon:   pixmap = qvariant_cast<QIcon>(variant).pixmap(iconSize()); break;
    178             default: break;
    179         }
    180         if( !pixmap.isNull() ) {
    181             s->drawItemPixmap( &painter, rect, Qt::AlignLeft|Qt::AlignVCenter, pixmap );
    182             rect.setLeft( rect.left() + pixmap.width() + hmargin );
    183         }
    184 
    185         // draw the count
    186         QString text = modelIndex.data(TorrentCountRole).toString();
    187         if( !text.isEmpty( ) )
    188         {
    189             const QPen pen = painter.pen( );
    190             painter.setPen( opt.palette.color( QPalette::Disabled, QPalette::Text ) );
    191             QRect r = s->itemTextRect( painter.fontMetrics(), rect, Qt::AlignRight|Qt::AlignVCenter, false, text );
    192             painter.drawText( r, 0, text );
    193             rect.setRight( r.left() - hmargin );
    194             painter.setPen( pen );
    195         }
    196 
    197         // draw the text
    198         text = modelIndex.data( Qt::DisplayRole ).toString();
    199         text = painter.fontMetrics().elidedText ( text, Qt::ElideRight, rect.width() );
    200         s->drawItemText( &painter, rect, Qt::AlignLeft|Qt::AlignVCenter, opt.palette, true, text );
     145FilterBarComboBox :: FilterBarComboBox (QWidget * parent):
     146  QComboBox (parent)
     147{
     148}
     149
     150void
     151FilterBarComboBox :: paintEvent (QPaintEvent * e)
     152{
     153  Q_UNUSED (e);
     154
     155  QStylePainter painter (this);
     156  painter.setPen (palette ().color (QPalette::Text));
     157
     158  // draw the combobox frame, focusrect and selected etc.
     159  QStyleOptionComboBox opt;
     160  initStyleOption (&opt);
     161  painter.drawComplexControl (QStyle::CC_ComboBox, opt);
     162
     163  // draw the icon and text
     164  const QModelIndex modelIndex = model ()->index (currentIndex (), 0, rootModelIndex ());
     165  if (modelIndex.isValid ())
     166    {
     167      QStyle * s = style ();
     168      QRect rect = s->subControlRect (QStyle::CC_ComboBox, &opt, QStyle::SC_ComboBoxEditField, this);
     169      const int hmargin = getHSpacing (this);
     170      rect.setRight (rect.right () - hmargin);
     171
     172      // draw the icon
     173      QPixmap pixmap;
     174      QVariant variant = modelIndex.data (Qt::DecorationRole);
     175      switch (variant.type ())
     176        {
     177          case QVariant::Pixmap: pixmap = qvariant_cast<QPixmap> (variant); break;
     178          case QVariant::Icon:   pixmap = qvariant_cast<QIcon> (variant).pixmap (iconSize ()); break;
     179          default: break;
     180        }
     181      if (!pixmap.isNull ())
     182        {
     183          s->drawItemPixmap (&painter, rect, Qt::AlignLeft|Qt::AlignVCenter, pixmap);
     184          rect.setLeft (rect.left () + pixmap.width () + hmargin);
     185        }
     186
     187      // draw the count
     188      QString text = modelIndex.data (TorrentCountRole).toString ();
     189      if (!text.isEmpty ())
     190        {
     191          const QPen pen = painter.pen ();
     192          painter.setPen (opt.palette.color (QPalette::Disabled, QPalette::Text));
     193          QRect r = s->itemTextRect (painter.fontMetrics (), rect, Qt::AlignRight|Qt::AlignVCenter, false, text);
     194          painter.drawText (r, 0, text);
     195          rect.setRight (r.left () - hmargin);
     196          painter.setPen (pen);
     197        }
     198
     199      // draw the text
     200      text = modelIndex.data (Qt::DisplayRole).toString ();
     201      text = painter.fontMetrics ().elidedText (text, Qt::ElideRight, rect.width ());
     202      s->drawItemText (&painter, rect, Qt::AlignLeft|Qt::AlignVCenter, opt.palette, true, text);
    201203    }
    202204}
     
    209211
    210212QComboBox*
    211 FilterBar :: createActivityCombo( )
    212 {
    213     QComboBox * c = new FilterBarComboBox( this );
    214     FilterBarComboBoxDelegate * delegate = new FilterBarComboBoxDelegate( 0, c );
    215     c->setItemDelegate( delegate );
    216 
    217     QPixmap blankPixmap( c->iconSize( ) );
    218     blankPixmap.fill( Qt::transparent );
    219     QIcon blankIcon( blankPixmap );
    220 
    221     QStandardItemModel * model = new QStandardItemModel;
    222 
    223     QStandardItem * row = new QStandardItem( tr( "All" ) );
    224     row->setData( FilterMode::SHOW_ALL, ActivityRole );
    225     model->appendRow( row );
    226 
    227     model->appendRow( new QStandardItem ); // separator
    228     delegate->setSeparator( model, model->index( 1, 0 ) );
    229 
    230     row = new QStandardItem( QIcon::fromTheme( "system-run", blankIcon ), tr( "Active" ) );
    231     row->setData( FilterMode::SHOW_ACTIVE, ActivityRole );
    232     model->appendRow( row );
    233 
    234     row = new QStandardItem( QIcon::fromTheme( "go-down", blankIcon ), tr( "Downloading" ) );
    235     row->setData( FilterMode::SHOW_DOWNLOADING, ActivityRole );
    236     model->appendRow( row );
    237 
    238     row = new QStandardItem( QIcon::fromTheme( "go-up", blankIcon ), tr( "Seeding" ) );
    239     row->setData( FilterMode::SHOW_SEEDING, ActivityRole );
    240     model->appendRow( row );
    241 
    242     row = new QStandardItem( QIcon::fromTheme( "media-playback-pause", blankIcon ), tr( "Paused" ) );
    243     row->setData( FilterMode::SHOW_PAUSED, ActivityRole );
    244     model->appendRow( row );
    245 
    246     row = new QStandardItem( blankIcon, tr( "Finished" ) );
    247     row->setData( FilterMode::SHOW_FINISHED, ActivityRole );
    248     model->appendRow( row );
    249 
    250     row = new QStandardItem( QIcon::fromTheme( "view-refresh", blankIcon ), tr( "Verifying" ) );
    251     row->setData( FilterMode::SHOW_VERIFYING, ActivityRole );
    252     model->appendRow( row );
    253 
    254     row = new QStandardItem( QIcon::fromTheme( "dialog-error", blankIcon ), tr( "Error" ) );
    255     row->setData( FilterMode::SHOW_ERROR, ActivityRole );
    256     model->appendRow( row );
    257 
    258     c->setModel( model );
    259     return c;
     213FilterBar :: createActivityCombo ()
     214{
     215  QComboBox * c = new FilterBarComboBox (this);
     216  FilterBarComboBoxDelegate * delegate = new FilterBarComboBoxDelegate (0, c);
     217  c->setItemDelegate (delegate);
     218
     219  QPixmap blankPixmap (c->iconSize ());
     220  blankPixmap.fill (Qt::transparent);
     221  QIcon blankIcon (blankPixmap);
     222
     223  QStandardItemModel * model = new QStandardItemModel;
     224
     225  QStandardItem * row = new QStandardItem (tr ("All"));
     226  row->setData (FilterMode::SHOW_ALL, ActivityRole);
     227  model->appendRow (row);
     228
     229  model->appendRow (new QStandardItem); // separator
     230  delegate->setSeparator (model, model->index (1, 0));
     231
     232  row = new QStandardItem (QIcon::fromTheme ("system-run", blankIcon), tr ("Active"));
     233  row->setData (FilterMode::SHOW_ACTIVE, ActivityRole);
     234  model->appendRow (row);
     235
     236  row = new QStandardItem (QIcon::fromTheme ("go-down", blankIcon), tr ("Downloading"));
     237  row->setData (FilterMode::SHOW_DOWNLOADING, ActivityRole);
     238  model->appendRow (row);
     239
     240  row = new QStandardItem (QIcon::fromTheme ("go-up", blankIcon), tr ("Seeding"));
     241  row->setData (FilterMode::SHOW_SEEDING, ActivityRole);
     242  model->appendRow (row);
     243
     244  row = new QStandardItem (QIcon::fromTheme ("media-playback-pause", blankIcon), tr ("Paused"));
     245  row->setData (FilterMode::SHOW_PAUSED, ActivityRole);
     246  model->appendRow (row);
     247
     248  row = new QStandardItem (blankIcon, tr ("Finished"));
     249  row->setData (FilterMode::SHOW_FINISHED, ActivityRole);
     250  model->appendRow (row);
     251
     252  row = new QStandardItem (QIcon::fromTheme ("view-refresh", blankIcon), tr ("Verifying"));
     253  row->setData (FilterMode::SHOW_VERIFYING, ActivityRole);
     254  model->appendRow (row);
     255
     256  row = new QStandardItem (QIcon::fromTheme ("dialog-error", blankIcon), tr ("Error"));
     257  row->setData (FilterMode::SHOW_ERROR, ActivityRole);
     258  model->appendRow (row);
     259
     260  c->setModel (model);
     261  return c;
    260262}
    261263
     
    268270namespace
    269271{
    270     QString readableHostName( const QString host )
    271     {
    272         // get the readable name...
    273         QString name = host;
    274         const int pos = name.lastIndexOf( '.' );
    275         if( pos >= 0 )
    276             name.truncate( pos );
    277         if( !name.isEmpty( ) )
    278             name[0] = name[0].toUpper( );
    279         return name;
    280     }
    281 }
    282 
    283 void
    284 FilterBar :: refreshTrackers( )
    285 {
    286     Favicons& favicons = dynamic_cast<MyApp*>(QApplication::instance())->favicons;
    287     const int firstTrackerRow = 2; // skip over the "All" and separator...
    288 
    289     // pull info from the tracker model...
    290     QSet<QString> oldHosts;
    291     for( int row=firstTrackerRow; ; ++row ) {
    292         QModelIndex index = myTrackerModel->index( row, 0 );
    293         if( !index.isValid( ) )
     272  QString readableHostName (const QString host)
     273  {
     274    // get the readable name...
     275    QString name = host;
     276    const int pos = name.lastIndexOf ('.');
     277    if (pos >= 0)
     278      name.truncate (pos);
     279    if (!name.isEmpty ())
     280      name[0] = name[0].toUpper ();
     281    return name;
     282  }
     283}
     284
     285void
     286FilterBar :: refreshTrackers ()
     287{
     288  Favicons& favicons = dynamic_cast<MyApp*> (QApplication::instance ())->favicons;
     289  const int firstTrackerRow = 2; // skip over the "All" and separator...
     290
     291  // pull info from the tracker model...
     292  QSet<QString> oldHosts;
     293  for (int row=firstTrackerRow; ; ++row)
     294    {
     295      QModelIndex index = myTrackerModel->index (row, 0);
     296      if (!index.isValid ())
     297        break;
     298      oldHosts << index.data (TrackerRole).toString ();
     299    }
     300
     301  // pull the new stats from the torrent model...
     302  QSet<QString> newHosts;
     303  QMap<QString,int> torrentsPerHost;
     304  for (int row=0; ; ++row)
     305    {
     306      QModelIndex index = myTorrents.index (row, 0);
     307      if (!index.isValid ())
     308        break;
     309      const Torrent * tor = index.data (TorrentModel::TorrentRole).value<const Torrent*> ();
     310      QSet<QString> torrentNames;
     311      foreach (QString host, tor->hosts ())
     312        {
     313          newHosts.insert (host);
     314          torrentNames.insert (readableHostName (host));
     315        }
     316      foreach (QString name, torrentNames)
     317        ++torrentsPerHost[name];
     318    }
     319
     320  // update the "All" row
     321  myTrackerModel->setData (myTrackerModel->index (0,0), getCountString (myTorrents.rowCount ()), TorrentCountRole);
     322
     323  // rows to update
     324  foreach (QString host, oldHosts & newHosts)
     325    {
     326      const QString name = readableHostName (host);
     327      QStandardItem * row = myTrackerModel->findItems (name).front ();
     328      row->setData (getCountString (torrentsPerHost[name]), TorrentCountRole);
     329      row->setData (favicons.findFromHost (host), Qt::DecorationRole);
     330    }
     331
     332  // rows to remove
     333  foreach (QString host, oldHosts - newHosts)
     334    {
     335      const QString name = readableHostName (host);
     336      QStandardItem * item = myTrackerModel->findItems (name).front ();
     337      if (!item->data (TrackerRole).toString ().isEmpty ()) // don't remove "All"
     338        myTrackerModel->removeRows (item->row (), 1);
     339    }
     340
     341  // rows to add
     342  bool anyAdded = false;
     343  foreach (QString host, newHosts - oldHosts)
     344    {
     345      const QString name = readableHostName (host);
     346
     347      if (!myTrackerModel->findItems (name).isEmpty ())
     348        continue;
     349
     350      // find the sorted position to add this row
     351      int i = firstTrackerRow;
     352      for (int n=myTrackerModel->rowCount (); i<n; ++i)
     353        {
     354          const QString rowName = myTrackerModel->index (i,0).data (Qt::DisplayRole).toString ();
     355          if (rowName >= name)
    294356            break;
    295         oldHosts << index.data(TrackerRole).toString();
    296     }
    297 
    298     // pull the new stats from the torrent model...
    299     QSet<QString> newHosts;
    300     QMap<QString,int> torrentsPerHost;
    301     for( int row=0; ; ++row )
    302     {
    303         QModelIndex index = myTorrents.index( row, 0 );
    304         if( !index.isValid( ) )
    305             break;
    306         const Torrent * tor = index.data( TorrentModel::TorrentRole ).value<const Torrent*>();
    307         QSet<QString> torrentNames;
    308         foreach (QString host, tor->hosts()) {
    309           newHosts.insert (host);
    310           torrentNames.insert (readableHostName(host));
    311         }
    312         foreach (QString name, torrentNames)
    313           ++torrentsPerHost[name];
    314     }
    315 
    316     // update the "All" row
    317     myTrackerModel->setData( myTrackerModel->index(0,0), getCountString(myTorrents.rowCount()), TorrentCountRole );
    318 
    319     // rows to update
    320     foreach( QString host, oldHosts & newHosts )
    321     {
    322         const QString name = readableHostName( host );
    323         QStandardItem * row = myTrackerModel->findItems(name).front();
    324         row->setData( getCountString(torrentsPerHost[name]), TorrentCountRole );
    325         row->setData( favicons.findFromHost(host), Qt::DecorationRole );
    326     }
    327 
    328     // rows to remove
    329     foreach( QString host, oldHosts - newHosts ) {
    330         const QString name = readableHostName( host );
    331         QStandardItem * item = myTrackerModel->findItems(name).front();
    332         if( !item->data(TrackerRole).toString().isEmpty() ) // don't remove "All"
    333             myTrackerModel->removeRows( item->row(), 1 );
    334     }
    335 
    336     // rows to add
    337     bool anyAdded = false;
    338     foreach( QString host, newHosts - oldHosts )
    339     {
    340         const QString name = readableHostName( host );
    341 
    342         if( !myTrackerModel->findItems(name).isEmpty() )
    343             continue;
    344 
    345         // find the sorted position to add this row
    346         int i = firstTrackerRow;
    347         for( int n=myTrackerModel->rowCount(); i<n; ++i ) {
    348             const QString rowName = myTrackerModel->index(i,0).data(Qt::DisplayRole).toString();
    349             if( rowName >= name )
    350                 break;
    351         }
    352 
    353         // add the row
    354         QStandardItem * row = new QStandardItem( favicons.findFromHost( host ), name );
    355         row->setData( getCountString(torrentsPerHost[host]), TorrentCountRole );
    356         row->setData( favicons.findFromHost(host), Qt::DecorationRole );
    357         row->setData( host, TrackerRole );
    358         myTrackerModel->insertRow( i, row );
    359         anyAdded = true;
    360     }
    361 
    362     if( anyAdded ) // the one added might match our filter...
    363         refreshPref( Prefs::FILTER_TRACKERS );
     357        }
     358
     359      // add the row
     360      QStandardItem * row = new QStandardItem (favicons.findFromHost (host), name);
     361      row->setData (getCountString (torrentsPerHost[host]), TorrentCountRole);
     362      row->setData (favicons.findFromHost (host), Qt::DecorationRole);
     363      row->setData (host, TrackerRole);
     364      myTrackerModel->insertRow (i, row);
     365      anyAdded = true;
     366    }
     367
     368  if (anyAdded) // the one added might match our filter...
     369    refreshPref (Prefs::FILTER_TRACKERS);
    364370}
    365371
    366372
    367373QComboBox*
    368 FilterBar :: createTrackerCombo( QStandardItemModel * model )
    369 {
    370     QComboBox * c = new FilterBarComboBox( this );
    371     FilterBarComboBoxDelegate * delegate = new FilterBarComboBoxDelegate( 0, c );
    372     c->setItemDelegate( delegate );
    373 
    374     QStandardItem * row = new QStandardItem( tr( "All" ) );
    375     row->setData( "", TrackerRole );
    376     row->setData( getCountString(myTorrents.rowCount()), TorrentCountRole );
    377     model->appendRow( row );
    378 
    379     model->appendRow( new QStandardItem ); // separator
    380     delegate->setSeparator( model, model->index( 1, 0 ) );
    381 
    382     c->setModel( model );
    383     return c;
     374FilterBar :: createTrackerCombo (QStandardItemModel * model)
     375{
     376  QComboBox * c = new FilterBarComboBox (this);
     377  FilterBarComboBoxDelegate * delegate = new FilterBarComboBoxDelegate (0, c);
     378  c->setItemDelegate (delegate);
     379
     380  QStandardItem * row = new QStandardItem (tr ("All"));
     381  row->setData ("", TrackerRole);
     382  row->setData (getCountString (myTorrents.rowCount ()), TorrentCountRole);
     383  model->appendRow (row);
     384
     385  model->appendRow (new QStandardItem); // separator
     386  delegate->setSeparator (model, model->index (1, 0));
     387
     388  c->setModel (model);
     389  return c;
    384390}
    385391
     
    390396****/
    391397
    392 FilterBar :: FilterBar( Prefs& prefs, TorrentModel& torrents, TorrentFilter& filter, QWidget * parent ):
    393     QWidget( parent ),
    394     myPrefs( prefs ),
    395     myTorrents( torrents ),
    396     myFilter( filter ),
    397     myRecountTimer( new QTimer( this ) ),
    398     myIsBootstrapping( true )
    399 {
    400     QHBoxLayout * h = new QHBoxLayout( this );
    401     const int hmargin = qMax( int(HIG::PAD), style()->pixelMetric( QStyle::PM_LayoutHorizontalSpacing ) );
    402 
    403     h->setSpacing( 0 );
    404     h->setContentsMargins( 2, 2, 2, 2 );
    405     h->addWidget( new QLabel( tr( "Show:" ), this ) );
    406     h->addSpacing( hmargin );
    407 
    408     myActivityCombo = createActivityCombo( );
    409     h->addWidget( myActivityCombo, 1 );
    410     h->addSpacing( hmargin );
    411 
    412     myTrackerModel = new QStandardItemModel;
    413     myTrackerCombo = createTrackerCombo( myTrackerModel );
    414     h->addWidget( myTrackerCombo, 1 );
    415     h->addSpacing( hmargin*2 );
    416 
    417     myLineEdit = new QLineEdit( this );
    418     h->addWidget( myLineEdit );
    419     connect( myLineEdit, SIGNAL(textChanged(QString)), this, SLOT(onTextChanged(QString)));
    420 
    421     QPushButton * p = new QPushButton;
    422     QIcon icon = QIcon::fromTheme( "edit-clear", style()->standardIcon( QStyle::SP_DialogCloseButton ) );
    423     int iconSize = style()->pixelMetric( QStyle::PM_SmallIconSize );
    424     p->setIconSize( QSize( iconSize, iconSize ) );
    425     p->setIcon( icon );
    426     p->setFlat( true );
    427     h->addWidget( p );
    428     connect( p, SIGNAL(clicked(bool)), myLineEdit, SLOT(clear()));
    429 
    430     // listen for changes from the other players
    431     connect( &myPrefs, SIGNAL(changed(int)), this, SLOT(refreshPref(int)));
    432     connect( myActivityCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(onActivityIndexChanged(int)));
    433     connect( myTrackerCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(onTrackerIndexChanged(int)));
    434     connect( &myTorrents, SIGNAL(modelReset()), this, SLOT(onTorrentModelReset()));
    435     connect( &myTorrents, SIGNAL(rowsInserted(const QModelIndex&,int,int)), this, SLOT(onTorrentModelRowsInserted(const QModelIndex&,int,int)));
    436     connect( &myTorrents, SIGNAL(rowsRemoved(const QModelIndex&,int,int)), this, SLOT(onTorrentModelRowsRemoved(const QModelIndex&,int,int)));
    437     connect( &myTorrents, SIGNAL(dataChanged(const QModelIndex&,const QModelIndex&)), this, SLOT(onTorrentModelDataChanged(const QModelIndex&,const QModelIndex&)));
    438     connect( myRecountTimer, SIGNAL(timeout()), this, SLOT(recount()) );
    439 
    440     recountSoon( );
    441     refreshTrackers( );
    442     myIsBootstrapping = false;
    443 
    444     // initialize our state
    445     QList<int> initKeys;
    446     initKeys << Prefs :: FILTER_MODE
    447              << Prefs :: FILTER_TRACKERS;
    448     foreach( int key, initKeys )
    449         refreshPref( key );
    450 }
    451 
    452 FilterBar :: ~FilterBar( )
    453 {
    454     delete myRecountTimer;
     398FilterBar :: FilterBar (Prefs& prefs, TorrentModel& torrents, TorrentFilter& filter, QWidget * parent):
     399  QWidget (parent),
     400  myPrefs (prefs),
     401  myTorrents (torrents),
     402  myFilter (filter),
     403  myRecountTimer (new QTimer (this)),
     404  myIsBootstrapping (true)
     405{
     406  QHBoxLayout * h = new QHBoxLayout (this);
     407  const int hmargin = qMax (int (HIG::PAD), style ()->pixelMetric (QStyle::PM_LayoutHorizontalSpacing));
     408
     409  h->setSpacing (0);
     410  h->setContentsMargins (2, 2, 2, 2);
     411  h->addWidget (new QLabel (tr ("Show:"), this));
     412  h->addSpacing (hmargin);
     413
     414  myActivityCombo = createActivityCombo ();
     415  h->addWidget (myActivityCombo, 1);
     416  h->addSpacing (hmargin);
     417
     418  myTrackerModel = new QStandardItemModel;
     419  myTrackerCombo = createTrackerCombo (myTrackerModel);
     420  h->addWidget (myTrackerCombo, 1);
     421  h->addSpacing (hmargin*2);
     422
     423  myLineEdit = new QLineEdit (this);
     424  h->addWidget (myLineEdit);
     425  connect (myLineEdit, SIGNAL (textChanged (QString)), this, SLOT (onTextChanged (QString)));
     426
     427  QPushButton * p = new QPushButton;
     428  QIcon icon = QIcon::fromTheme ("edit-clear", style ()->standardIcon (QStyle::SP_DialogCloseButton));
     429  int iconSize = style ()->pixelMetric (QStyle::PM_SmallIconSize);
     430  p->setIconSize (QSize (iconSize, iconSize));
     431  p->setIcon (icon);
     432  p->setFlat (true);
     433  h->addWidget (p);
     434  connect (p, SIGNAL (clicked (bool)), myLineEdit, SLOT (clear ()));
     435
     436  // listen for changes from the other players
     437  connect (&myPrefs, SIGNAL (changed (int)), this, SLOT (refreshPref (int)));
     438  connect (myActivityCombo, SIGNAL (currentIndexChanged (int)), this, SLOT (onActivityIndexChanged (int)));
     439  connect (myTrackerCombo, SIGNAL (currentIndexChanged (int)), this, SLOT (onTrackerIndexChanged (int)));
     440  connect (&myTorrents, SIGNAL (modelReset ()), this, SLOT (onTorrentModelReset ()));
     441  connect (&myTorrents, SIGNAL (rowsInserted (const QModelIndex&,int,int)), this, SLOT (onTorrentModelRowsInserted (const QModelIndex&,int,int)));
     442  connect (&myTorrents, SIGNAL (rowsRemoved (const QModelIndex&,int,int)), this, SLOT (onTorrentModelRowsRemoved (const QModelIndex&,int,int)));
     443  connect (&myTorrents, SIGNAL (dataChanged (const QModelIndex&,const QModelIndex&)), this, SLOT (onTorrentModelDataChanged (const QModelIndex&,const QModelIndex&)));
     444  connect (myRecountTimer, SIGNAL (timeout ()), this, SLOT (recount ()));
     445
     446  recountSoon ();
     447  refreshTrackers ();
     448  myIsBootstrapping = false;
     449
     450  // initialize our state
     451  QList<int> initKeys;
     452  initKeys << Prefs :: FILTER_MODE
     453           << Prefs :: FILTER_TRACKERS;
     454  foreach (int key, initKeys)
     455      refreshPref (key);
     456}
     457
     458FilterBar :: ~FilterBar ()
     459{
     460  delete myRecountTimer;
    455461}
    456462
     
    460466
    461467void
    462 FilterBar :: refreshPref( int key )
    463 {
    464     switch( key )
    465     {
    466         case Prefs :: FILTER_MODE: {
    467             const FilterMode m = myPrefs.get<FilterMode>( key );
    468             QAbstractItemModel * model = myActivityCombo->model( );
    469             QModelIndexList indices = model->match( model->index(0,0), ActivityRole, m.mode() );
    470             myActivityCombo->setCurrentIndex( indices.isEmpty() ? 0 : indices.first().row( ) );
    471             break;
    472         }
    473 
    474         case Prefs :: FILTER_TRACKERS: {
    475             const QString tracker = myPrefs.getString( key );
    476             const QString name = readableHostName( tracker );
    477             QList<QStandardItem*> rows = myTrackerModel->findItems(name);
    478             if( !rows.isEmpty() )
    479                 myTrackerCombo->setCurrentIndex( rows.front()->row() );
    480             else { // hm, we don't seem to have this tracker anymore...
    481                 const bool isBootstrapping = myTrackerModel->rowCount( ) <= 2;
    482                 if( !isBootstrapping )
    483                     myPrefs.set( key, "" );
     468FilterBar :: refreshPref (int key)
     469{
     470  switch (key)
     471    {
     472      case Prefs :: FILTER_MODE:
     473        {
     474          const FilterMode m = myPrefs.get<FilterMode> (key);
     475          QAbstractItemModel * model = myActivityCombo->model ();
     476          QModelIndexList indices = model->match (model->index (0,0), ActivityRole, m.mode ());
     477          myActivityCombo->setCurrentIndex (indices.isEmpty () ? 0 : indices.first ().row ());
     478          break;
     479        }
     480
     481      case Prefs :: FILTER_TRACKERS:
     482        {
     483          const QString tracker = myPrefs.getString (key);
     484          const QString name = readableHostName (tracker);
     485          QList<QStandardItem*> rows = myTrackerModel->findItems (name);
     486          if (!rows.isEmpty ())
     487            {
     488              myTrackerCombo->setCurrentIndex (rows.front ()->row ());
    484489            }
    485             break;
    486         }
    487     }
    488 }
    489 
    490 void
    491 FilterBar :: onTextChanged( const QString& str )
    492 {
    493     if( !myIsBootstrapping )
    494         myPrefs.set( Prefs::FILTER_TEXT, str.trimmed( ) );
    495 }
    496 
    497 void
    498 FilterBar :: onTrackerIndexChanged( int i )
    499 {
    500     if( !myIsBootstrapping )
    501     {
    502         QString str;
    503         const bool isTracker = !myTrackerCombo->itemData(i,TrackerRole).toString().isEmpty();
    504         if( !isTracker ) // show all
    505             str = "";
    506         else {
    507             str = myTrackerCombo->itemData(i,TrackerRole).toString();
    508             const int pos = str.lastIndexOf( '.' );
    509             if( pos >= 0 )
    510               str.truncate( pos+1 );
    511         }
    512         myPrefs.set( Prefs::FILTER_TRACKERS, str );
    513     }
    514 }
    515 
    516 void
    517 FilterBar :: onActivityIndexChanged( int i )
    518 {
    519     if( !myIsBootstrapping )
    520     {
    521         const FilterMode mode = myActivityCombo->itemData( i, ActivityRole ).toInt( );
    522         myPrefs.set( Prefs::FILTER_MODE, mode );
     490          else // hm, we don't seem to have this tracker anymore...
     491            {
     492              const bool isBootstrapping = myTrackerModel->rowCount () <= 2;
     493              if (!isBootstrapping)
     494                myPrefs.set (key, "");
     495            }
     496          break;
     497        }
     498    }
     499}
     500
     501void
     502FilterBar :: onTextChanged (const QString& str)
     503{
     504  if (!myIsBootstrapping)
     505    myPrefs.set (Prefs::FILTER_TEXT, str.trimmed ());
     506}
     507
     508void
     509FilterBar :: onTrackerIndexChanged (int i)
     510{
     511  if (!myIsBootstrapping)
     512    {
     513      QString str;
     514      const bool isTracker = !myTrackerCombo->itemData (i,TrackerRole).toString ().isEmpty ();
     515      if (!isTracker) // show all
     516        {
     517          str = "";
     518        }
     519      else
     520        {
     521          str = myTrackerCombo->itemData (i,TrackerRole).toString ();
     522          const int pos = str.lastIndexOf ('.');
     523          if (pos >= 0)
     524            str.truncate (pos+1);
     525        }
     526      myPrefs.set (Prefs::FILTER_TRACKERS, str);
     527    }
     528}
     529
     530void
     531FilterBar :: onActivityIndexChanged (int i)
     532{
     533  if (!myIsBootstrapping)
     534    {
     535      const FilterMode mode = myActivityCombo->itemData (i, ActivityRole).toInt ();
     536      myPrefs.set (Prefs::FILTER_MODE, mode);
    523537    }
    524538}
     
    528542***/
    529543
    530 void FilterBar :: onTorrentModelReset( ) { recountSoon( ); }
    531 void FilterBar :: onTorrentModelRowsInserted( const QModelIndex&, int, int ) { recountSoon( ); }
    532 void FilterBar :: onTorrentModelRowsRemoved( const QModelIndex&, int, int ) { recountSoon( ); }
    533 void FilterBar :: onTorrentModelDataChanged( const QModelIndex&, const QModelIndex& ) { recountSoon( ); }
    534 
    535 void
    536 FilterBar :: recountSoon( )
    537 {
    538     if( !myRecountTimer->isActive( ) )
    539     {
    540         myRecountTimer->setSingleShot( true );
    541         myRecountTimer->start( 800 );
     544void FilterBar :: onTorrentModelReset () { recountSoon (); }
     545void FilterBar :: onTorrentModelRowsInserted (const QModelIndex&, int, int) { recountSoon (); }
     546void FilterBar :: onTorrentModelRowsRemoved (const QModelIndex&, int, int) { recountSoon (); }
     547void FilterBar :: onTorrentModelDataChanged (const QModelIndex&, const QModelIndex&) { recountSoon (); }
     548
     549void
     550FilterBar :: recountSoon ()
     551{
     552  if (!myRecountTimer->isActive ())
     553    {
     554      myRecountTimer->setSingleShot (true);
     555      myRecountTimer->start (800);
    542556    }
    543557}
     
    545559FilterBar :: recount ()
    546560{
    547   QAbstractItemModel * model = myActivityCombo->model();
     561  QAbstractItemModel * model = myActivityCombo->model ();
    548562
    549563  int torrentsPerMode[FilterMode::NUM_MODES] = { };
    550564  myFilter.countTorrentsPerMode (torrentsPerMode);
    551565
    552   for (int row=0, n=model->rowCount(); row<n; ++row)
     566  for (int row=0, n=model->rowCount (); row<n; ++row)
    553567    {
    554568      QModelIndex index = model->index (row, 0);
    555       const int mode = index.data(ActivityRole).toInt();
    556       model->setData (index, getCountString(torrentsPerMode[mode]), TorrentCountRole);
     569      const int mode = index.data (ActivityRole).toInt ();
     570      model->setData (index, getCountString (torrentsPerMode[mode]), TorrentCountRole);
    557571    }
    558572
     
    561575
    562576QString
    563 FilterBar :: getCountString( int n ) const
    564 {
    565     return QString("%L1").arg(n);
    566 }
     577FilterBar :: getCountString (int n) const
     578{
     579  return QString ("%L1").arg (n);
     580}
  • trunk/qt/filterbar.h

    r11406 r13869  
    2929class FilterBarComboBoxDelegate: public QItemDelegate
    3030{
    31         Q_OBJECT
     31    Q_OBJECT
    3232
    33     public:
    34         FilterBarComboBoxDelegate( QObject * parent, QComboBox * combo );
     33  public:
     34    FilterBarComboBoxDelegate (QObject * parent, QComboBox * combo);
    3535
    36     public:
    37         static bool isSeparator( const QModelIndex &index );
    38         static void setSeparator( QAbstractItemModel * model, const QModelIndex& index );
     36  public:
     37    static bool isSeparator (const QModelIndex &index);
     38    static void setSeparator (QAbstractItemModel * model, const QModelIndex& index);
    3939
    40     protected:
    41         virtual void paint( QPainter*, const QStyleOptionViewItem&, const QModelIndex& ) const;
    42         virtual QSize sizeHint( const QStyleOptionViewItem&, const QModelIndex& ) const;
     40  protected:
     41    virtual void paint (QPainter*, const QStyleOptionViewItem&, const QModelIndex&) const;
     42    virtual QSize sizeHint (const QStyleOptionViewItem&, const QModelIndex&) const;
    4343
    44     private:
    45         QComboBox * myCombo;
     44  private:
     45    QComboBox * myCombo;
    4646
    4747};
     
    4949class FilterBarComboBox: public QComboBox
    5050{
    51         Q_OBJECT
     51    Q_OBJECT
    5252
    53     public:
    54         FilterBarComboBox( QWidget * parent = 0 );
     53  public:
     54    FilterBarComboBox (QWidget * parent = 0);
    5555
    56     protected:
    57         virtual void paintEvent( QPaintEvent * e );
     56  protected:
     57    virtual void paintEvent (QPaintEvent * e);
    5858};
    5959
     
    6161class FilterBar: public QWidget
    6262{
    63         Q_OBJECT
     63    Q_OBJECT
    6464
    65     public:
    66         FilterBar( Prefs& prefs, TorrentModel& torrents, TorrentFilter& filter, QWidget * parent = 0 );
    67         ~FilterBar( );
     65  public:
     66    FilterBar (Prefs& prefs, TorrentModel& torrents, TorrentFilter& filter, QWidget * parent = 0);
     67    ~FilterBar ();
    6868
    69     private:
    70         QComboBox * createTrackerCombo( QStandardItemModel * );
    71         QComboBox * createActivityCombo( );
    72         void recountSoon( );
    73         void refreshTrackers( );
    74         QString getCountString( int n ) const;
     69  private:
     70    QComboBox * createTrackerCombo (QStandardItemModel * );
     71    QComboBox * createActivityCombo ();
     72    void recountSoon ();
     73    void refreshTrackers ();
     74    QString getCountString (int n) const;
    7575
    76     private:
    77         Prefs& myPrefs;
    78         TorrentModel& myTorrents;
    79         TorrentFilter& myFilter;
    80         QComboBox * myActivityCombo;
    81         QComboBox * myTrackerCombo;
    82         QStandardItemModel * myTrackerModel;
    83         QTimer * myRecountTimer;
    84         bool myIsBootstrapping;
    85         QLineEdit * myLineEdit;
     76  private:
     77    Prefs& myPrefs;
     78    TorrentModel& myTorrents;
     79    TorrentFilter& myFilter;
     80    QComboBox * myActivityCombo;
     81    QComboBox * myTrackerCombo;
     82    QStandardItemModel * myTrackerModel;
     83    QTimer * myRecountTimer;
     84    bool myIsBootstrapping;
     85    QLineEdit * myLineEdit;
    8686
    87     private slots:
    88         void recount( );
    89         void refreshPref( int key );
    90         void onActivityIndexChanged( int index );
    91         void onTrackerIndexChanged( int index );
    92         void onTorrentModelReset( );
    93         void onTorrentModelRowsInserted( const QModelIndex&, int, int );
    94         void onTorrentModelRowsRemoved( const QModelIndex&, int, int );
    95         void onTorrentModelDataChanged( const QModelIndex&, const QModelIndex& );
    96         void onTextChanged( const QString& );
     87  private slots:
     88    void recount ();
     89    void refreshPref (int key);
     90    void onActivityIndexChanged (int index);
     91    void onTrackerIndexChanged (int index);
     92    void onTorrentModelReset ();
     93    void onTorrentModelRowsInserted (const QModelIndex&, int, int);
     94    void onTorrentModelRowsRemoved (const QModelIndex&, int, int);
     95    void onTorrentModelDataChanged (const QModelIndex&, const QModelIndex&);
     96    void onTextChanged (const QString&);
    9797};
    9898
  • trunk/qt/prefs.h

    r13813 r13869  
    3131class Prefs: public QObject
    3232{
    33         Q_OBJECT;
     33    Q_OBJECT;
    3434
    35     public:
     35  public:
    3636
    37         enum
     37    enum
     38    {
     39      /* client prefs */
     40      OPTIONS_PROMPT,
     41      OPEN_DIALOG_FOLDER,
     42      INHIBIT_HIBERNATION,
     43      DIR_WATCH,
     44      DIR_WATCH_ENABLED,
     45      SHOW_TRAY_ICON,
     46      START_MINIMIZED,
     47      SHOW_NOTIFICATION_ON_ADD,
     48      SHOW_NOTIFICATION_ON_COMPLETE,
     49      ASKQUIT,
     50      SORT_MODE,
     51      SORT_REVERSED,
     52      COMPACT_VIEW,
     53      FILTERBAR,
     54      STATUSBAR,
     55      STATUSBAR_STATS,
     56      SHOW_TRACKER_SCRAPES,
     57      SHOW_BACKUP_TRACKERS,
     58      TOOLBAR,
     59      BLOCKLIST_DATE,
     60      BLOCKLIST_UPDATES_ENABLED,
     61      MAIN_WINDOW_LAYOUT_ORDER,
     62      MAIN_WINDOW_HEIGHT,
     63      MAIN_WINDOW_WIDTH,
     64      MAIN_WINDOW_X,
     65      MAIN_WINDOW_Y,
     66      FILTER_MODE,
     67      FILTER_TRACKERS,
     68      FILTER_TEXT,
     69      SESSION_IS_REMOTE,
     70      SESSION_REMOTE_HOST,
     71      SESSION_REMOTE_PORT,
     72      SESSION_REMOTE_AUTH,
     73      SESSION_REMOTE_USERNAME,
     74      SESSION_REMOTE_PASSWORD,
     75      COMPLETE_SOUND_COMMAND,
     76      COMPLETE_SOUND_ENABLED,
     77      USER_HAS_GIVEN_INFORMED_CONSENT,
     78
     79      /* core prefs */
     80      FIRST_CORE_PREF,
     81      ALT_SPEED_LIMIT_UP = FIRST_CORE_PREF,
     82      ALT_SPEED_LIMIT_DOWN,
     83      ALT_SPEED_LIMIT_ENABLED,
     84      ALT_SPEED_LIMIT_TIME_BEGIN,
     85      ALT_SPEED_LIMIT_TIME_END,
     86      ALT_SPEED_LIMIT_TIME_ENABLED,
     87      ALT_SPEED_LIMIT_TIME_DAY,
     88      BLOCKLIST_ENABLED,
     89      BLOCKLIST_URL,
     90      DSPEED,
     91      DSPEED_ENABLED,
     92      DOWNLOAD_DIR,
     93      DOWNLOAD_QUEUE_ENABLED,
     94      DOWNLOAD_QUEUE_SIZE,
     95      ENCRYPTION,
     96      IDLE_LIMIT,
     97      IDLE_LIMIT_ENABLED,
     98      INCOMPLETE_DIR,
     99      INCOMPLETE_DIR_ENABLED,
     100      MSGLEVEL,
     101      PEER_LIMIT_GLOBAL,
     102      PEER_LIMIT_TORRENT,
     103      PEER_PORT,
     104      PEER_PORT_RANDOM_ON_START,
     105      PEER_PORT_RANDOM_LOW,
     106      PEER_PORT_RANDOM_HIGH,
     107      QUEUE_STALLED_MINUTES,
     108      SCRIPT_TORRENT_DONE_ENABLED,
     109      SCRIPT_TORRENT_DONE_FILENAME,
     110      SOCKET_TOS,
     111      START,
     112      TRASH_ORIGINAL,
     113      PEX_ENABLED,
     114      DHT_ENABLED,
     115      UTP_ENABLED,
     116      LPD_ENABLED,
     117      PORT_FORWARDING,
     118      PREALLOCATION,
     119      RATIO,
     120      RATIO_ENABLED,
     121      RENAME_PARTIAL_FILES,
     122      RPC_AUTH_REQUIRED,
     123      RPC_ENABLED,
     124      RPC_PASSWORD,
     125      RPC_PORT,
     126      RPC_USERNAME,
     127      RPC_WHITELIST_ENABLED,
     128      RPC_WHITELIST,
     129      USPEED_ENABLED,
     130      USPEED,
     131      UPLOAD_SLOTS_PER_TORRENT,
     132      LAST_CORE_PREF = UPLOAD_SLOTS_PER_TORRENT,
     133
     134      PREFS_COUNT
     135    };
     136
     137  private:
     138
     139    struct PrefItem
     140    {
     141      int id;
     142      tr_quark key;
     143      int type;
     144    };
     145
     146    static PrefItem myItems[];
     147
     148  private:
     149    QSet<int> myTemporaryPrefs;
     150    QString myConfigDir;
     151    mutable QVariant myValues[PREFS_COUNT];
     152    void initDefaults (struct tr_variant*);
     153
     154  public:
     155    bool isCore (int key) const { return FIRST_CORE_PREF<=key && key<=LAST_CORE_PREF; }
     156    bool isClient (int key) const { return !isCore (key); }
     157    const char * keyStr (int i) const { return tr_quark_get_string (myItems[i].key,NULL); }
     158    tr_quark getKey  (int i) const { return myItems[i].key; }
     159    int type (int i) const { return myItems[i].type; }
     160    const QVariant& variant (int i) const { return myValues[i]; }
     161
     162    Prefs (const char * configDir);
     163    ~Prefs ();
     164
     165    int getInt (int key) const;
     166    bool getBool (int key) const;
     167    QString getString (int key) const;
     168    double getDouble (int key) const;
     169    QDateTime getDateTime (int key) const;
     170
     171    template<typename T> T get (int key) const { return myValues[key].value<T>(); }
     172
     173    void set (int key, char * value) { set (key, QString::fromUtf8 (value)); }
     174    void set (int key, const char * value) { set (key, QString::fromUtf8 (value)); }
     175
     176    template<typename T> void set (int key, const T& value)
     177    {
     178      QVariant& v (myValues[key]);
     179      const QVariant tmp = QVariant::fromValue (value);
     180      if (v.isNull() || (v!=tmp))
    38181        {
    39             /* client prefs */
    40             OPTIONS_PROMPT,
    41             OPEN_DIALOG_FOLDER,
    42             INHIBIT_HIBERNATION,
    43             DIR_WATCH,
    44             DIR_WATCH_ENABLED,
    45             SHOW_TRAY_ICON,
    46             START_MINIMIZED,
    47             SHOW_NOTIFICATION_ON_ADD,
    48             SHOW_NOTIFICATION_ON_COMPLETE,
    49             ASKQUIT,
    50             SORT_MODE,
    51             SORT_REVERSED,
    52             COMPACT_VIEW,
    53             FILTERBAR,
    54             STATUSBAR,
    55             STATUSBAR_STATS,
    56             SHOW_TRACKER_SCRAPES,
    57             SHOW_BACKUP_TRACKERS,
    58             TOOLBAR,
    59             BLOCKLIST_DATE,
    60             BLOCKLIST_UPDATES_ENABLED,
    61             MAIN_WINDOW_LAYOUT_ORDER,
    62             MAIN_WINDOW_HEIGHT,
    63             MAIN_WINDOW_WIDTH,
    64             MAIN_WINDOW_X,
    65             MAIN_WINDOW_Y,
    66             FILTER_MODE,
    67             FILTER_TRACKERS,
    68             FILTER_TEXT,
    69             SESSION_IS_REMOTE,
    70             SESSION_REMOTE_HOST,
    71             SESSION_REMOTE_PORT,
    72             SESSION_REMOTE_AUTH,
    73             SESSION_REMOTE_USERNAME,
    74             SESSION_REMOTE_PASSWORD,
    75             COMPLETE_SOUND_COMMAND,
    76             COMPLETE_SOUND_ENABLED,
    77             USER_HAS_GIVEN_INFORMED_CONSENT,
     182          v = tmp;
     183          emit changed (key);
     184        }
     185    }
    78186
    79             /* core prefs */
    80             FIRST_CORE_PREF,
    81             ALT_SPEED_LIMIT_UP = FIRST_CORE_PREF,
    82             ALT_SPEED_LIMIT_DOWN,
    83             ALT_SPEED_LIMIT_ENABLED,
    84             ALT_SPEED_LIMIT_TIME_BEGIN,
    85             ALT_SPEED_LIMIT_TIME_END,
    86             ALT_SPEED_LIMIT_TIME_ENABLED,
    87             ALT_SPEED_LIMIT_TIME_DAY,
    88             BLOCKLIST_ENABLED,
    89             BLOCKLIST_URL,
    90             DSPEED,
    91             DSPEED_ENABLED,
    92             DOWNLOAD_DIR,
    93             DOWNLOAD_QUEUE_ENABLED,
    94             DOWNLOAD_QUEUE_SIZE,
    95             ENCRYPTION,
    96             IDLE_LIMIT,
    97             IDLE_LIMIT_ENABLED,
    98             INCOMPLETE_DIR,
    99             INCOMPLETE_DIR_ENABLED,
    100             MSGLEVEL,
    101             PEER_LIMIT_GLOBAL,
    102             PEER_LIMIT_TORRENT,
    103             PEER_PORT,
    104             PEER_PORT_RANDOM_ON_START,
    105             PEER_PORT_RANDOM_LOW,
    106             PEER_PORT_RANDOM_HIGH,
    107             QUEUE_STALLED_MINUTES,
    108             SCRIPT_TORRENT_DONE_ENABLED,
    109             SCRIPT_TORRENT_DONE_FILENAME,
    110             SOCKET_TOS,
    111             START,
    112             TRASH_ORIGINAL,
    113             PEX_ENABLED,
    114             DHT_ENABLED,
    115             UTP_ENABLED,
    116             LPD_ENABLED,
    117             PORT_FORWARDING,
    118             PREALLOCATION,
    119             RATIO,
    120             RATIO_ENABLED,
    121             RENAME_PARTIAL_FILES,
    122             RPC_AUTH_REQUIRED,
    123             RPC_ENABLED,
    124             RPC_PASSWORD,
    125             RPC_PORT,
    126             RPC_USERNAME,
    127             RPC_WHITELIST_ENABLED,
    128             RPC_WHITELIST,
    129             USPEED_ENABLED,
    130             USPEED,
    131             UPLOAD_SLOTS_PER_TORRENT,
    132             LAST_CORE_PREF = UPLOAD_SLOTS_PER_TORRENT,
     187    void toggleBool (int key);
    133188
    134             PREFS_COUNT
    135         };
    136 
    137     private:
    138 
    139         struct PrefItem {
    140             int id;
    141             tr_quark key;
    142             int type;
    143         };
    144 
    145         static PrefItem myItems[];
    146 
    147     private:
    148         QSet<int> myTemporaryPrefs;
    149         QString myConfigDir;
    150         mutable QVariant myValues[PREFS_COUNT];
    151         void initDefaults( struct tr_variant* );
    152 
    153     public:
    154         bool isCore( int key ) const { return FIRST_CORE_PREF<=key && key<=LAST_CORE_PREF; }
    155         bool isClient( int key ) const { return !isCore( key ); }
    156         const char * keyStr( int i ) const { return tr_quark_get_string(myItems[i].key,NULL); }
    157         tr_quark getKey (int i) const { return myItems[i].key; }
    158         int type( int i ) const { return myItems[i].type; }
    159         const QVariant& variant( int i ) const { return myValues[i]; }
    160 
    161         Prefs( const char * configDir );
    162         ~Prefs( );
    163 
    164         int getInt( int key ) const;
    165         bool getBool( int key) const;
    166         QString getString( int key ) const;
    167         double getDouble( int key) const;
    168         QDateTime getDateTime( int key ) const;
    169 
    170         template<typename T> T get( int key ) const {
    171             return myValues[key].value<T>();
    172         }
    173 
    174         void set( int key, char * value ) { set( key, QString::fromUtf8(value) ); }
    175         void set( int key, const char * value ) { set( key, QString::fromUtf8(value) ); }
    176 
    177         template<typename T> void set( int key, const T& value ) {
    178             QVariant& v( myValues[key] );
    179             const QVariant tmp = QVariant::fromValue(value);
    180             if( v.isNull() || (v!=tmp) ) {
    181                 v = tmp;
    182                 emit changed( key );
    183             }
    184         }
    185 
    186         void toggleBool( int key );
    187 
    188      signals:
    189         void changed( int key );
     189  signals:
     190    void changed (int key);
    190191};
    191192
Note: See TracChangeset for help on using the changeset viewer.