2
* This file Copyright (C) 2009 Charles Kerr <charles@transmissionbt.com>
4
* This file is licensed by the GPL version 2. Works owned by the
5
* Transmission project are granted a special exemption to clause 2(b)
6
* so that the bulk of its code can remain under the MIT license.
7
* This exemption does not extend to derived works not owned by
8
* the Transmission project.
17
#include <QDesktopServices>
18
#include <QFileDialog>
21
#include <QHBoxLayout>
22
#include <QSystemTrayIcon>
28
#include "make-dialog.h"
31
#include "prefs-dialog.h"
34
#include "stats-dialog.h"
35
#include "torrent-delegate.h"
36
#include "torrent-delegate-min.h"
37
#include "torrent-filter.h"
38
#include "torrent-model.h"
39
#include "ui_mainwin.h"
41
#include "qticonloader.h"
43
#define PREFS_KEY "prefs-key";
46
TrMainWindow :: getStockIcon( const QString& freedesktop_name, int fallback )
51
fallbackIcon = style()->standardIcon( QStyle::StandardPixmap( fallback ), 0, this );
53
return QtIconLoader::icon( freedesktop_name, fallbackIcon );
58
QSize calculateTextButtonSizeHint( QPushButton * button )
60
QStyleOptionButton opt;
61
opt.initFrom( button );
62
QString s( button->text( ) );
64
s = QString::fromLatin1( "XXXX" );
65
QFontMetrics fm = button->fontMetrics( );
66
QSize sz = fm.size( Qt::TextShowMnemonic, s );
67
return button->style()->sizeFromContents( QStyle::CT_PushButton, &opt, sz, button ).expandedTo( QApplication::globalStrut( ) );
70
void setTextButtonSizeHint( QPushButton * button )
72
/* this is kind of a hack, possibly coming from my being new to Qt.
73
* Qt 4.4's sizeHint calculations for QPushButton have it include
74
* space for an icon, even if no icon is used. because of this,
75
* default pushbuttons look way too wide in the filterbar...
76
* so this routine recalculates the sizeHint without icons.
77
* If there's a Right Way to do this that I've missed, let me know */
78
button->setMaximumSize( calculateTextButtonSizeHint( button ) );
83
TrMainWindow :: TrMainWindow( Session& session, Prefs& prefs, TorrentModel& model, bool minimized ):
84
myLastFullUpdateTime( 0 ),
85
myPrefsDialog( new PrefsDialog( session, prefs, this ) ),
86
myAboutDialog( new AboutDialog( this ) ),
87
myStatsDialog( new StatsDialog( session, this ) ),
89
myFilterModel( prefs ),
90
myTorrentDelegate( new TorrentDelegate( this ) ),
91
myTorrentDelegateMin( new TorrentDelegateMin( this ) ),
95
mySpeedModeOffIcon( ":/icons/alt-limit-off.png" ),
96
mySpeedModeOnIcon( ":/icons/alt-limit-on.png" ),
99
myNetworkTimer( this )
101
QAction * sep = new QAction( this );
102
sep->setSeparator( true );
106
QString title( "Transmission" );
107
const QUrl remoteUrl( session.getRemoteUrl( ) );
108
if( !remoteUrl.isEmpty( ) )
109
title += tr( " - %1" ).arg( remoteUrl.toString() );
110
setWindowTitle( title );
112
QStyle * style = this->style();
114
int i = style->pixelMetric( QStyle::PM_SmallIconSize, 0, this );
115
const QSize smallIconSize( i, i );
118
ui.action_Add->setIcon( getStockIcon( "list-add", QStyle::SP_DialogOpenButton ) );
119
ui.action_New->setIcon( getStockIcon( "document-new", QStyle::SP_DesktopIcon ) );
120
ui.action_Properties->setIcon( getStockIcon( "document-properties", QStyle::SP_DesktopIcon ) );
121
ui.action_OpenFolder->setIcon( getStockIcon( "folder-open", QStyle::SP_DirOpenIcon ) );
122
ui.action_Start->setIcon( getStockIcon( "media-playback-start", QStyle::SP_MediaPlay ) );
123
ui.action_Announce->setIcon( getStockIcon( "network-transmit-receive" ) );
124
ui.action_Pause->setIcon( getStockIcon( "media-playback-pause", QStyle::SP_MediaPause ) );
125
ui.action_Remove->setIcon( getStockIcon( "list-remove", QStyle::SP_TrashIcon ) );
126
ui.action_Delete->setIcon( getStockIcon( "edit-delete", QStyle::SP_TrashIcon ) );
127
ui.action_StartAll->setIcon( getStockIcon( "media-playback-start", QStyle::SP_MediaPlay ) );
128
ui.action_PauseAll->setIcon( getStockIcon( "media-playback-pause", QStyle::SP_MediaPause ) );
129
ui.action_Quit->setIcon( getStockIcon( "application-exit" ) );
130
ui.action_SelectAll->setIcon( getStockIcon( "edit-select-all" ) );
131
ui.action_ReverseSortOrder->setIcon( getStockIcon( "view-sort-ascending", QStyle::SP_ArrowDown ) );
132
ui.action_Preferences->setIcon( getStockIcon( "preferences-system" ) );
133
ui.action_Contents->setIcon( getStockIcon( "help-contents", QStyle::SP_DialogHelpButton ) );
134
ui.action_About->setIcon( getStockIcon( "help-about" ) );
135
ui.statusbarStatsButton->setIcon( getStockIcon( "view-refresh", QStyle::SP_BrowserReload ) );
136
ui.downloadIconLabel->setPixmap( getStockIcon( "go-down", QStyle::SP_ArrowDown ).pixmap( smallIconSize ) );
137
ui.uploadIconLabel->setPixmap( getStockIcon( "go-up", QStyle::SP_ArrowUp ).pixmap( smallIconSize ) );
138
ui.filterEntryModeButton->setIcon( getStockIcon( "edit-find", QStyle::SP_ArrowForward ) );
139
ui.filterEntryClearButton->setIcon( getStockIcon( "edit-clear", QStyle::SP_DialogCloseButton ) );
143
connect( ui.action_Toolbar, SIGNAL(toggled(bool)), this, SLOT(setToolbarVisible(bool)));
144
connect( ui.action_TrayIcon, SIGNAL(toggled(bool)), this, SLOT(setTrayIconVisible(bool)));
145
connect( ui.action_Filterbar, SIGNAL(toggled(bool)), this, SLOT(setFilterbarVisible(bool)));
146
connect( ui.action_Statusbar, SIGNAL(toggled(bool)), this, SLOT(setStatusbarVisible(bool)));
147
connect( ui.action_MinimalView, SIGNAL(toggled(bool)), this, SLOT(setMinimalView(bool)));
148
connect( ui.action_SortByActivity, SIGNAL(toggled(bool)), &myFilterModel, SLOT(sortByActivity()) );
149
connect( ui.action_SortByAge, SIGNAL(toggled(bool)), &myFilterModel, SLOT(sortByAge()) );
150
connect( ui.action_SortByETA, SIGNAL(toggled(bool)), &myFilterModel, SLOT(sortByETA()));
151
connect( ui.action_SortByName, SIGNAL(toggled(bool)), &myFilterModel, SLOT(sortByName()));
152
connect( ui.action_SortByProgress, SIGNAL(toggled(bool)), &myFilterModel, SLOT(sortByProgress()));
153
connect( ui.action_SortByRatio, SIGNAL(toggled(bool)), &myFilterModel, SLOT(sortByRatio()));
154
connect( ui.action_SortBySize, SIGNAL(toggled(bool)), &myFilterModel, SLOT(sortBySize()));
155
connect( ui.action_SortByState, SIGNAL(toggled(bool)), &myFilterModel, SLOT(sortByState()));
156
connect( ui.action_SortByTracker, SIGNAL(toggled(bool)), &myFilterModel, SLOT(sortByTracker()));
157
connect( ui.action_ReverseSortOrder, SIGNAL(toggled(bool)), &myFilterModel, SLOT(setAscending(bool)));
158
connect( ui.action_Start, SIGNAL(triggered()), this, SLOT(startSelected()));
159
connect( ui.action_Pause, SIGNAL(triggered()), this, SLOT(pauseSelected()));
160
connect( ui.action_Remove, SIGNAL(triggered()), this, SLOT(removeSelected()));
161
connect( ui.action_Delete, SIGNAL(triggered()), this, SLOT(deleteSelected()));
162
connect( ui.action_Verify, SIGNAL(triggered()), this, SLOT(verifySelected()) );
163
connect( ui.action_Announce, SIGNAL(triggered()), this, SLOT(reannounceSelected()) );
164
connect( ui.action_StartAll, SIGNAL(triggered()), this, SLOT(startAll()));
165
connect( ui.action_PauseAll, SIGNAL(triggered()), this, SLOT(pauseAll()));
166
connect( ui.action_Add, SIGNAL(triggered()), this, SLOT(openTorrent()));
167
connect( ui.action_New, SIGNAL(triggered()), this, SLOT(newTorrent()));
168
connect( ui.action_Preferences, SIGNAL(triggered()), myPrefsDialog, SLOT(show()));
169
connect( ui.action_Statistics, SIGNAL(triggered()), myStatsDialog, SLOT(show()));
170
connect( ui.action_About, SIGNAL(triggered()), myAboutDialog, SLOT(show()));
171
connect( ui.action_Contents, SIGNAL(triggered()), this, SLOT(openHelp()));
172
connect( ui.action_OpenFolder, SIGNAL(triggered()), this, SLOT(openFolder()));
173
connect( ui.action_Properties, SIGNAL(triggered()), this, SLOT(openProperties()));
174
connect( ui.listView, SIGNAL(activated(const QModelIndex&)), ui.action_Properties, SLOT(trigger()));
177
QList<QAction*> actions;
178
actions << ui.action_Properties
179
<< ui.action_OpenFolder
184
<< ui.action_Announce
188
addActions( actions );
189
setContextMenuPolicy( Qt::ActionsContextMenu );
192
connect( ui.speedLimitModeButton, SIGNAL(clicked()), this, SLOT(toggleSpeedMode()));
193
connect( ui.filterAll, SIGNAL(clicked()), this, SLOT(showAll()));
194
connect( ui.filterActive, SIGNAL(clicked()), this, SLOT(showActive()));
195
connect( ui.filterDownloading, SIGNAL(clicked()), this, SLOT(showDownloading()));
196
connect( ui.filterSeeding, SIGNAL(clicked()), this, SLOT(showSeeding()));
197
connect( ui.filterPaused, SIGNAL(clicked()), this, SLOT(showPaused()));
198
connect( ui.filterEntryClearButton, SIGNAL(clicked()), ui.filterEntry, SLOT(clear()));
199
connect( ui.filterEntry, SIGNAL(textChanged(QString)), &myFilterModel, SLOT(setText(QString)));
200
connect( ui.action_SelectAll, SIGNAL(triggered()), ui.listView, SLOT(selectAll()));
201
connect( ui.action_DeselectAll, SIGNAL(triggered()), ui.listView, SLOT(clearSelection()));
202
setTextButtonSizeHint( ui.filterAll );
203
setTextButtonSizeHint( ui.filterActive );
204
setTextButtonSizeHint( ui.filterDownloading );
205
setTextButtonSizeHint( ui.filterSeeding );
206
setTextButtonSizeHint( ui.filterPaused );
207
setShowMode( myFilterModel.getShowMode( ) );
209
connect( &myFilterModel, SIGNAL(rowsInserted(const QModelIndex&,int,int)), this, SLOT(refreshVisibleCount()));
210
connect( &myFilterModel, SIGNAL(rowsRemoved(const QModelIndex&,int,int)), this, SLOT(refreshVisibleCount()));
211
connect( &myFilterModel, SIGNAL(rowsInserted(const QModelIndex&,int,int)), this, SLOT(refreshActionSensitivity()));
212
connect( &myFilterModel, SIGNAL(rowsRemoved(const QModelIndex&,int,int)), this, SLOT(refreshActionSensitivity()));
214
connect( ui.action_Quit, SIGNAL(triggered()), QCoreApplication::instance(), SLOT(quit()) );
217
myFilterModel.setSourceModel( &myModel );
218
ui.listView->setModel( &myFilterModel );
219
connect( ui.listView->selectionModel(), SIGNAL(selectionChanged(const QItemSelection&,const QItemSelection&)), this, SLOT(refreshActionSensitivity()));
221
QActionGroup * actionGroup = new QActionGroup( this );
222
actionGroup->addAction( ui.action_FilterByName );
223
actionGroup->addAction( ui.action_FilterByFiles );
224
actionGroup->addAction( ui.action_FilterByTracker );
225
QMenu * menu = new QMenu( );
226
menu->addAction( ui.action_FilterByName );
227
menu->addAction( ui.action_FilterByFiles );
228
menu->addAction( ui.action_FilterByTracker );
229
ui.filterEntryModeButton->setMenu( menu );
230
connect( ui.action_FilterByName, SIGNAL(triggered()), this, SLOT(filterByName()));
231
connect( ui.action_FilterByFiles, SIGNAL(triggered()), this, SLOT(filterByFiles()));
232
connect( ui.action_FilterByTracker, SIGNAL(triggered()), this, SLOT(filterByTracker()));
233
ui.action_FilterByName->setChecked( true );
235
actionGroup = new QActionGroup( this );
236
actionGroup->addAction( ui.action_TotalRatio );
237
actionGroup->addAction( ui.action_TotalTransfer );
238
actionGroup->addAction( ui.action_SessionRatio );
239
actionGroup->addAction( ui.action_SessionTransfer );
241
menu->addAction( ui.action_TotalRatio );
242
menu->addAction( ui.action_TotalTransfer );
243
menu->addAction( ui.action_SessionRatio );
244
menu->addAction( ui.action_SessionTransfer );
245
connect( ui.action_TotalRatio, SIGNAL(triggered()), this, SLOT(showTotalRatio()));
246
connect( ui.action_TotalTransfer, SIGNAL(triggered()), this, SLOT(showTotalTransfer()));
247
connect( ui.action_SessionRatio, SIGNAL(triggered()), this, SLOT(showSessionRatio()));
248
connect( ui.action_SessionTransfer, SIGNAL(triggered()), this, SLOT(showSessionTransfer()));
249
ui.statusbarStatsButton->setMenu( menu );
251
actionGroup = new QActionGroup( this );
252
actionGroup->addAction( ui.action_SortByActivity );
253
actionGroup->addAction( ui.action_SortByAge );
254
actionGroup->addAction( ui.action_SortByETA );
255
actionGroup->addAction( ui.action_SortByName );
256
actionGroup->addAction( ui.action_SortByProgress );
257
actionGroup->addAction( ui.action_SortByRatio );
258
actionGroup->addAction( ui.action_SortBySize );
259
actionGroup->addAction( ui.action_SortByState );
260
actionGroup->addAction( ui.action_SortByTracker );
263
menu->addAction( ui.action_Add );
264
menu->addSeparator( );
265
menu->addAction( ui.action_ShowMainWindow );
266
menu->addAction( ui.action_ShowMessageLog );
267
menu->addAction( ui.action_About );
268
menu->addSeparator( );
269
menu->addAction( ui.action_StartAll );
270
menu->addAction( ui.action_PauseAll );
271
menu->addSeparator( );
272
menu->addAction( ui.action_Quit );
273
myTrayIcon.setContextMenu( menu );
274
myTrayIcon.setIcon( QApplication::windowIcon( ) );
276
connect( ui.action_ShowMainWindow, SIGNAL(toggled(bool)), this, SLOT(toggleWindows()));
277
connect( &myTrayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(trayActivated(QSystemTrayIcon::ActivationReason)));
278
connect( &myPrefs, SIGNAL(changed(int)), this, SLOT(refreshPref(int)) );
280
ui.action_ShowMainWindow->setChecked( !minimized );
281
ui.action_TrayIcon->setChecked( minimized || prefs.getBool( Prefs::SHOW_TRAY_ICON ) );
284
initKeys << Prefs :: MAIN_WINDOW_X
285
<< Prefs :: SHOW_TRAY_ICON
286
<< Prefs :: SORT_REVERSED
287
<< Prefs :: SORT_MODE
288
<< Prefs :: FILTERBAR
289
<< Prefs :: STATUSBAR
290
<< Prefs :: STATUSBAR_STATS
292
<< Prefs :: ALT_SPEED_LIMIT_ENABLED
293
<< Prefs :: MINIMAL_VIEW;
294
foreach( int key, initKeys )
297
connect( &mySession, SIGNAL(statsUpdated()), this, SLOT(refreshStatusBar()) );
298
connect( &mySession, SIGNAL(dataReadProgress()), this, SLOT(dataReadProgress()) );
299
connect( &mySession, SIGNAL(dataSendProgress()), this, SLOT(dataSendProgress()) );
301
if( mySession.isServer( ) )
302
ui.networkLabel->hide( );
304
connect( &myNetworkTimer, SIGNAL(timeout()), this, SLOT(onNetworkTimer()));
305
myNetworkTimer.start( 1000 );
308
refreshActionSensitivity( );
310
refreshVisibleCount( );
313
TrMainWindow :: ~TrMainWindow( )
322
TrMainWindow :: openProperties( )
324
const int id( *getSelectedTorrents().begin() );
325
Torrent * torrent( myModel.getTorrentFromId( id ) );
326
assert( torrent != 0 );
327
QDialog * d( new Details( mySession, *torrent, this ) );
332
TrMainWindow :: openFolder( )
334
const int torrentId( *getSelectedTorrents().begin() );
335
const Torrent * tor( myModel.getTorrentFromId( torrentId ) );
336
const QString path( tor->getPath( ) );
337
QDesktopServices :: openUrl( QUrl::fromLocalFile( path ) );
341
TrMainWindow :: openHelp( )
343
const char * fmt = "http://www.transmissionbt.com/help/gtk/%d.%dx";
345
sscanf( SHORT_VERSION_STRING, "%d.%d", &major, &minor );
347
snprintf( url, sizeof( url ), fmt, major, minor/10 );
348
QDesktopServices :: openUrl( QUrl( QString( url ) ) );
352
TrMainWindow :: refreshVisibleCount( )
354
const int visibleCount( myFilterModel.rowCount( ) );
355
const int totalCount( visibleCount + myFilterModel.hiddenRowCount( ) );
357
if( visibleCount == totalCount )
358
str = tr( "%Ln Torrent(s)", 0, totalCount );
360
str = tr( "%L1 of %Ln Torrent(s)", 0, totalCount ).arg( visibleCount );
361
ui.visibleCountLabel->setText( str );
365
TrMainWindow :: refreshStatusBar( )
367
const Speed up( myModel.getUploadSpeed( ) );
368
const Speed down( myModel.getDownloadSpeed( ) );
369
ui.uploadTextLabel->setText( Utils :: speedToString( up ) );
370
ui.downloadTextLabel->setText( Utils :: speedToString( down ) );
371
const QString mode( myPrefs.getString( Prefs::STATUSBAR_STATS ) );
374
if( mode == "session-ratio" )
376
str = tr( "Ratio: %1" ).arg( Utils :: ratioToString( mySession.getStats().ratio ) );
378
else if( mode == "session-transfer" )
380
const tr_session_stats& stats( mySession.getStats( ) );
381
str = tr( "Down: %1, Up: %2" ).arg( Utils :: sizeToString( stats.downloadedBytes ) )
382
.arg( Utils :: sizeToString( stats.uploadedBytes ) );
384
else if( mode == "total-transfer" )
386
const tr_session_stats& stats( mySession.getCumulativeStats( ) );
387
str = tr( "Down: %1, Up: %2" ).arg( Utils :: sizeToString( stats.downloadedBytes ) )
388
.arg( Utils :: sizeToString( stats.uploadedBytes ) );
390
else /* default is "total-ratio" */
392
str = tr( "Ratio: %1" ).arg( Utils :: ratioToString( mySession.getCumulativeStats().ratio ) );
395
ui.statusbarStatsLabel->setText( str );
399
TrMainWindow :: refreshActionSensitivity( )
403
int selectedAndPaused( 0 );
404
int canAnnounce( 0 );
405
const QAbstractItemModel * model( ui.listView->model( ) );
406
const QItemSelectionModel * selectionModel( ui.listView->selectionModel( ) );
407
const int rowCount( model->rowCount( ) );
409
/* count how many torrents are selected, paused, etc */
410
for( int row=0; row<rowCount; ++row ) {
411
const QModelIndex modelIndex( model->index( row, 0 ) );
412
assert( model == modelIndex.model( ) );
413
const Torrent * tor( model->data( modelIndex, TorrentModel::TorrentRole ).value<const Torrent*>( ) );
414
const bool isSelected( selectionModel->isSelected( modelIndex ) );
415
const bool isPaused( tor->isPaused( ) );
420
if( isSelected && isPaused )
422
if( tor->canManualAnnounce( ) )
426
const bool haveSelection( selected > 0 );
427
ui.action_Verify->setEnabled( haveSelection );
428
ui.action_Remove->setEnabled( haveSelection );
429
ui.action_Delete->setEnabled( haveSelection );
430
ui.action_DeselectAll->setEnabled( haveSelection );
432
const bool oneSelection( selected == 1 );
433
ui.action_Properties->setEnabled( oneSelection );
434
ui.action_OpenFolder->setEnabled( oneSelection );
436
ui.action_SelectAll->setEnabled( selected < rowCount );
437
ui.action_StartAll->setEnabled( paused > 0 );
438
ui.action_PauseAll->setEnabled( paused < rowCount );
439
ui.action_Start->setEnabled( selectedAndPaused > 0 );
440
ui.action_Pause->setEnabled( selectedAndPaused < selected );
441
ui.action_Announce->setEnabled( selected > 0 && ( canAnnounce == selected ) );
449
TrMainWindow :: clearSelection( )
451
ui.action_DeselectAll->trigger( );
455
TrMainWindow :: getSelectedTorrents( ) const
459
foreach( QModelIndex index, ui.listView->selectionModel( )->selectedRows( ) )
461
const Torrent * tor( index.model()->data( index, TorrentModel::TorrentRole ).value<const Torrent*>( ) );
462
ids.insert( tor->id( ) );
469
TrMainWindow :: startSelected( )
471
mySession.start( getSelectedTorrents( ) );
474
TrMainWindow :: pauseSelected( )
476
mySession.pause( getSelectedTorrents( ) );
479
TrMainWindow :: startAll( )
484
TrMainWindow :: pauseAll( )
489
TrMainWindow :: removeSelected( )
491
mySession.removeTorrents( getSelectedTorrents( ), false );
494
TrMainWindow :: deleteSelected( )
496
mySession.removeTorrents( getSelectedTorrents( ), true );
499
TrMainWindow :: verifySelected( )
501
mySession.verifyTorrents( getSelectedTorrents( ) );
504
TrMainWindow :: reannounceSelected( )
506
mySession.reannounceTorrents( getSelectedTorrents( ) );
514
TrMainWindow :: setShowMode( TorrentFilter :: ShowMode mode )
516
ui.filterAll->setChecked( mode == TorrentFilter::SHOW_ALL );
517
ui.filterActive->setChecked( mode == TorrentFilter::SHOW_ACTIVE );
518
ui.filterDownloading->setChecked( mode == TorrentFilter::SHOW_DOWNLOADING );
519
ui.filterSeeding->setChecked( mode == TorrentFilter::SHOW_SEEDING );
520
ui.filterPaused->setChecked( mode == TorrentFilter::SHOW_PAUSED );
522
myFilterModel.setShowMode( mode );
525
void TrMainWindow :: showAll ( ) { setShowMode( TorrentFilter :: SHOW_ALL ); }
526
void TrMainWindow :: showActive ( ) { setShowMode( TorrentFilter :: SHOW_ACTIVE ); }
527
void TrMainWindow :: showDownloading ( ) { setShowMode( TorrentFilter :: SHOW_DOWNLOADING ); }
528
void TrMainWindow :: showSeeding ( ) { setShowMode( TorrentFilter :: SHOW_SEEDING ); }
529
void TrMainWindow :: showPaused ( ) { setShowMode( TorrentFilter :: SHOW_PAUSED ); }
531
void TrMainWindow :: filterByName ( ) { myFilterModel.setTextMode( TorrentFilter :: FILTER_BY_NAME ); }
532
void TrMainWindow :: filterByTracker ( ) { myFilterModel.setTextMode( TorrentFilter :: FILTER_BY_TRACKER ); }
533
void TrMainWindow :: filterByFiles ( ) { myFilterModel.setTextMode( TorrentFilter :: FILTER_BY_FILES ); }
536
TrMainWindow :: showTotalRatio( )
538
myPrefs.set( Prefs::STATUSBAR_STATS, "total-ratio" );
541
TrMainWindow :: showTotalTransfer( )
543
myPrefs.set( Prefs::STATUSBAR_STATS, "total-transfer" );
546
TrMainWindow :: showSessionRatio( )
548
myPrefs.set( Prefs::STATUSBAR_STATS, "session-ratio" );
551
TrMainWindow :: showSessionTransfer( )
553
myPrefs.set( Prefs::STATUSBAR_STATS, "session-transfer" );
561
TrMainWindow :: setMinimalView( bool visible )
563
myPrefs.set( Prefs :: MINIMAL_VIEW, visible );
566
TrMainWindow :: setTrayIconVisible( bool visible )
568
myPrefs.set( Prefs :: SHOW_TRAY_ICON, visible );
571
TrMainWindow :: toggleSpeedMode( )
573
myPrefs.toggleBool( Prefs :: ALT_SPEED_LIMIT_ENABLED );
576
TrMainWindow :: setToolbarVisible( bool visible )
578
myPrefs.set( Prefs::TOOLBAR, visible );
581
TrMainWindow :: setFilterbarVisible( bool visible )
583
myPrefs.set( Prefs::FILTERBAR, visible );
586
TrMainWindow :: setStatusbarVisible( bool visible )
588
myPrefs.set( Prefs::STATUSBAR, visible );
596
TrMainWindow :: toggleWindows( )
598
setVisible( !isVisible( ) );
602
TrMainWindow :: trayActivated( QSystemTrayIcon::ActivationReason reason )
604
if( reason == QSystemTrayIcon::Trigger )
605
ui.action_ShowMainWindow->toggle( );
610
TrMainWindow :: refreshPref( int key )
617
case Prefs::STATUSBAR_STATS:
618
str = myPrefs.getString( key );
619
ui.action_TotalRatio->setChecked ( str == "total-ratio" );
620
ui.action_TotalTransfer->setChecked ( str == "total-transfer" );
621
ui.action_SessionRatio->setChecked ( str == "session-ratio" );
622
ui.action_SessionTransfer->setChecked( str == "session-transfer" );
626
case Prefs::SORT_REVERSED:
627
ui.action_ReverseSortOrder->setChecked( myPrefs.getBool( key ) );
630
case Prefs::SORT_MODE:
631
str = myPrefs.getString( key );
632
ui.action_SortByActivity->setChecked ( str == "sort-by-activity" );
633
ui.action_SortByAge->setChecked ( str == "sort-by-age" );
634
ui.action_SortByETA->setChecked ( str == "sort-by-eta" );
635
ui.action_SortByName->setChecked ( str == "sort-by-name" );
636
ui.action_SortByProgress->setChecked ( str == "sort-by-progress" );
637
ui.action_SortByRatio->setChecked ( str == "sort-by-ratio" );
638
ui.action_SortBySize->setChecked ( str == "sort-by-size" );
639
ui.action_SortByState->setChecked ( str == "sort-by-state" );
640
ui.action_SortByTracker->setChecked ( str == "sort-by-tracker" );
643
case Prefs::FILTERBAR:
644
b = myPrefs.getBool( key );
645
ui.filterbar->setVisible( b );
646
ui.action_Filterbar->setChecked( b );
649
case Prefs::STATUSBAR:
650
b = myPrefs.getBool( key );
651
ui.statusbar->setVisible( b );
652
ui.action_Statusbar->setChecked( b );
656
b = myPrefs.getBool( key );
657
ui.toolBar->setVisible( b );
658
ui.action_Toolbar->setChecked( b );
661
case Prefs::SHOW_TRAY_ICON:
662
b = myPrefs.getBool( key );
663
ui.action_TrayIcon->setChecked( b );
664
myTrayIcon.setVisible( b );
667
case Prefs::MINIMAL_VIEW:
668
b = myPrefs.getBool( key );
669
ui.action_MinimalView->setChecked( b );
670
ui.listView->setItemDelegate( b ? myTorrentDelegateMin : myTorrentDelegate );
671
ui.listView->reset( ); // force the rows to resize
674
case Prefs::MAIN_WINDOW_X:
675
case Prefs::MAIN_WINDOW_Y:
676
case Prefs::MAIN_WINDOW_WIDTH:
677
case Prefs::MAIN_WINDOW_HEIGHT:
678
setGeometry( myPrefs.getInt( Prefs::MAIN_WINDOW_X ),
679
myPrefs.getInt( Prefs::MAIN_WINDOW_Y ),
680
myPrefs.getInt( Prefs::MAIN_WINDOW_WIDTH ),
681
myPrefs.getInt( Prefs::MAIN_WINDOW_HEIGHT ) );
684
case Prefs :: ALT_SPEED_LIMIT_ENABLED:
685
b = myPrefs.getBool( key );
686
ui.speedLimitModeButton->setChecked( b );
687
ui.speedLimitModeButton->setIcon( b ? mySpeedModeOnIcon : mySpeedModeOffIcon );
688
ui.speedLimitModeButton->setToolTip( b ? tr( "Click to disable Speed Limit Mode" )
689
: tr( "Click to enable Speed Limit Mode" ) );
702
TrMainWindow :: newTorrent( )
704
MakeDialog * d = new MakeDialog( mySession, this );
709
TrMainWindow :: openTorrent( )
711
if( myFileDialog == 0 )
713
myFileDialog = new QFileDialog( this,
715
myPrefs.getString( Prefs::OPEN_DIALOG_FOLDER ),
716
tr( "Torrent Files (*.torrent);;All Files (*.*)" ) );
717
myFileDialog->setFileMode( QFileDialog::ExistingFiles );
720
QCheckBox * button = new QCheckBox( tr( "Display &options dialog" ) );
721
button->setChecked( myPrefs.getBool( Prefs::OPTIONS_PROMPT ) );
722
QGridLayout * layout = dynamic_cast<QGridLayout*>(myFileDialog->layout());
723
layout->addWidget( button, layout->rowCount( ), 0, 1, -1, Qt::AlignLeft );
724
myFileDialogOptionsCheck = button;
726
connect( myFileDialog, SIGNAL(filesSelected(const QStringList&)), this, SLOT(addTorrents(const QStringList&)));
729
myFileDialog->show( );
733
TrMainWindow :: addTorrents( const QStringList& filenames )
735
foreach( const QString& filename, filenames )
736
addTorrent( filename );
740
TrMainWindow :: addTorrent( const QString& filename )
742
if( !myFileDialogOptionsCheck->isChecked( ) ) {
743
mySession.addTorrent( filename );
744
QApplication :: alert ( this );
746
Options * o = new Options( mySession, myPrefs, filename, this );
748
QApplication :: alert( o );
757
TrMainWindow :: updateNetworkIcon( )
759
const time_t now = time( NULL );
760
const int period = 3;
761
const bool isSending = now - myLastSendTime <= period;
762
const bool isReading = now - myLastReadTime <= period;
765
if( isSending && isReading )
766
key = "network-transmit-receive";
768
key = "network-transmit";
770
key = "network-receive";
772
key = "network-idle";
774
QIcon icon = getStockIcon( key, QStyle::SP_DriveNetIcon );
775
QPixmap pixmap = icon.pixmap ( 16, 16 );
776
ui.networkLabel->setPixmap( pixmap );
777
ui.networkLabel->setToolTip( isSending || isReading
778
? tr( "Transmission server is responding" )
779
: tr( "Last response from server was %1 ago" ).arg( Utils::timeToString( now-std::max(myLastReadTime,myLastSendTime))));
783
TrMainWindow :: onNetworkTimer( )
785
updateNetworkIcon( );
789
TrMainWindow :: dataReadProgress( )
791
myLastReadTime = time( NULL );
792
updateNetworkIcon( );
796
TrMainWindow :: dataSendProgress( )
798
myLastSendTime = time( NULL );
799
updateNetworkIcon( );