source: trunk/qt/prefs.cc @ 8194

Last change on this file since 8194 was 8194, checked in by charles, 13 years ago

(trunk qt) remember sorting & filtering mode between sessions

File size: 11.2 KB
Line 
1/*
2 * This file Copyright (C) 2009 Charles Kerr <charles@transmissionbt.com>
3 *
4 * This file is licensed by the GPL version 2.  Works owned by the
5 * Transmission project are granted a special exemption to clause 2(b)
6 * so that the bulk of its code can remain under the MIT license.
7 * This exemption does not extend to derived works not owned by
8 * the Transmission project.
9 *
10 * $Id:$
11 */
12
13#include <cassert>
14#include <iostream>
15#include <cstdlib> // strtod
16
17#include <QDir>
18#include <QFile>
19
20#include <libtransmission/transmission.h>
21#include <libtransmission/bencode.h>
22#include <libtransmission/json.h>
23#include <libtransmission/utils.h>
24#include "prefs.h"
25
26/***
27****
28***/
29
30Prefs::PrefItem Prefs::myItems[] =
31{
32    /* gui settings */
33    { OPTIONS_PROMPT, "show-options-window", QVariant::Bool },
34    { OPEN_DIALOG_FOLDER, "open-dialog-dir", QVariant::String },
35    { INHIBIT_HIBERNATION, "inhibit-desktop-hibernation", QVariant::Bool },
36    { DIR_WATCH, "watch-dir", QVariant::String },
37    { DIR_WATCH_ENABLED, "watch-dir-enabled", QVariant::Bool },
38    { SHOW_TRAY_ICON, "show-notification-area-icon", QVariant::Bool },
39    { SHOW_DESKTOP_NOTIFICATION, "show-desktop-notification", QVariant::Bool },
40    { START, "start-added-torrents", QVariant::Bool },
41    { TRASH_ORIGINAL, "trash-original-torrent-files", QVariant::Bool },
42    { ASKQUIT, "prompt-before-exit", QVariant::Bool },
43    { SORT_MODE, "sort-mode", QVariant::String },
44    { SORT_REVERSED, "sort-reversed", QVariant::Bool },
45    { MINIMAL_VIEW, "minimal-view", QVariant::Bool },
46    { FILTERBAR, "show-filterbar", QVariant::Bool },
47    { STATUSBAR, "show-statusbar", QVariant::Bool },
48    { STATUSBAR_STATS, "statusbar-stats", QVariant::String },
49    { TOOLBAR, "show-toolbar" , QVariant::Bool },
50    { BLOCKLIST_DATE, "blocklist-date", QVariant::DateTime },
51    { BLOCKLIST_UPDATES_ENABLED, "blocklist-updates-enabled" , QVariant::Bool },
52    { MAIN_WINDOW_LAYOUT_ORDER, "main-window-layout-order", QVariant::Int },
53    { MAIN_WINDOW_HEIGHT, "main-window-height", QVariant::Int },
54    { MAIN_WINDOW_WIDTH, "main-window-width", QVariant::Int },
55    { MAIN_WINDOW_X, "main-window-x", QVariant::Int },
56    { MAIN_WINDOW_Y, "main-window-y", QVariant::Int },
57    { FILTER_MODE, "filter-mode", QVariant::String },
58
59    /* libtransmission settings */
60    { ALT_SPEED_LIMIT_UP, TR_PREFS_KEY_ALT_SPEED_UP, QVariant::Int },
61    { ALT_SPEED_LIMIT_DOWN, TR_PREFS_KEY_ALT_SPEED_DOWN, QVariant::Int },
62    { ALT_SPEED_LIMIT_ENABLED, TR_PREFS_KEY_ALT_SPEED_ENABLED, QVariant::Bool },
63    { ALT_SPEED_LIMIT_TIME_BEGIN, TR_PREFS_KEY_ALT_SPEED_TIME_BEGIN, QVariant::Int },
64    { ALT_SPEED_LIMIT_TIME_END, TR_PREFS_KEY_ALT_SPEED_TIME_END, QVariant::Int },
65    { ALT_SPEED_LIMIT_TIME_ENABLED, TR_PREFS_KEY_ALT_SPEED_TIME_ENABLED, QVariant::Bool },
66    { ALT_SPEED_LIMIT_TIME_DAY, TR_PREFS_KEY_ALT_SPEED_TIME_DAY, QVariant::Int },
67    { BLOCKLIST_ENABLED, TR_PREFS_KEY_BLOCKLIST_ENABLED, QVariant::Bool },
68    { DSPEED, TR_PREFS_KEY_DSPEED, QVariant::Int },
69    { DSPEED_ENABLED, TR_PREFS_KEY_DSPEED_ENABLED, QVariant::Bool },
70    { DOWNLOAD_DIR, TR_PREFS_KEY_DOWNLOAD_DIR, QVariant::String },
71    { ENCRYPTION, TR_PREFS_KEY_ENCRYPTION, QVariant::Int },
72    { LAZY_BITFIELD, TR_PREFS_KEY_LAZY_BITFIELD, QVariant::Bool },
73    { MSGLEVEL, TR_PREFS_KEY_MSGLEVEL, QVariant::Int },
74    { OPEN_FILE_LIMIT, TR_PREFS_KEY_OPEN_FILE_LIMIT, QVariant::Int },
75    { PEER_LIMIT_GLOBAL, TR_PREFS_KEY_PEER_LIMIT_GLOBAL, QVariant::Int },
76    { PEER_LIMIT_TORRENT, TR_PREFS_KEY_PEER_LIMIT_TORRENT, QVariant::Int },
77    { PEER_PORT, TR_PREFS_KEY_PEER_PORT, QVariant::Int },
78    { PEER_PORT_RANDOM_ON_START, TR_PREFS_KEY_PEER_PORT_RANDOM_ON_START, QVariant::Bool },
79    { PEER_PORT_RANDOM_LOW, TR_PREFS_KEY_PEER_PORT_RANDOM_LOW, QVariant::Int },
80    { PEER_PORT_RANDOM_HIGH, TR_PREFS_KEY_PEER_PORT_RANDOM_HIGH, QVariant::Int },
81    { SOCKET_TOS, TR_PREFS_KEY_PEER_SOCKET_TOS, QVariant::Int },
82    { PEX_ENABLED, TR_PREFS_KEY_PEX_ENABLED, QVariant::Bool },
83    { PORT_FORWARDING, TR_PREFS_KEY_PORT_FORWARDING, QVariant::Bool },
84    { PROXY_AUTH_ENABLED, TR_PREFS_KEY_PROXY_AUTH_ENABLED, QVariant::Bool },
85    { PREALLOCATION, TR_PREFS_KEY_PREALLOCATION, QVariant::Int },
86    { PROXY_ENABLED, TR_PREFS_KEY_PROXY_ENABLED, QVariant::Bool },
87    { PROXY_PASSWORD, TR_PREFS_KEY_PROXY_PASSWORD, QVariant::String },
88    { PROXY_PORT, TR_PREFS_KEY_PROXY_PORT, QVariant::Int },
89    { PROXY, TR_PREFS_KEY_PROXY, QVariant::String },
90    { PROXY_TYPE, TR_PREFS_KEY_PROXY_TYPE, QVariant::Int },
91    { PROXY_USERNAME, TR_PREFS_KEY_PROXY_USERNAME, QVariant::String },
92    { RATIO, TR_PREFS_KEY_RATIO, QVariant::Double },
93    { RATIO_ENABLED, TR_PREFS_KEY_RATIO_ENABLED, QVariant::Bool },
94    { RPC_AUTH_REQUIRED, TR_PREFS_KEY_RPC_AUTH_REQUIRED, QVariant::Bool },
95    { RPC_ENABLED, TR_PREFS_KEY_RPC_ENABLED, QVariant::Bool },
96    { RPC_PASSWORD, TR_PREFS_KEY_RPC_PASSWORD, QVariant::String },
97    { RPC_PORT, TR_PREFS_KEY_RPC_PORT, QVariant::Int },
98    { RPC_USERNAME, TR_PREFS_KEY_RPC_USERNAME, QVariant::String },
99    { RPC_WHITELIST_ENABLED, TR_PREFS_KEY_RPC_WHITELIST_ENABLED, QVariant::Bool },
100    { RPC_WHITELIST, TR_PREFS_KEY_RPC_WHITELIST, QVariant::String },
101    { SEED_RATIO_LIMIT, TR_PREFS_KEY_RATIO, QVariant::Double },
102    { SEED_RATIO_LIMITED, TR_PREFS_KEY_RATIO_ENABLED, QVariant::Bool },
103    { USPEED_ENABLED, TR_PREFS_KEY_USPEED_ENABLED, QVariant::Bool },
104    { USPEED, TR_PREFS_KEY_USPEED, QVariant::Int },
105    { UPLOAD_SLOTS_PER_TORRENT, TR_PREFS_KEY_UPLOAD_SLOTS_PER_TORRENT, QVariant::Int }
106};
107
108/***
109****
110***/
111
112Prefs :: Prefs( const char * configDir ):
113    myConfigDir( configDir )
114{
115    assert( sizeof(myItems) / sizeof(myItems[0]) == PREFS_COUNT );
116    for( int i=0; i<PREFS_COUNT; ++i )
117        assert( myItems[i].id == i );
118
119    tr_benc top;
120    tr_bencInitDict( &top, 0 );
121    initDefaults( &top );
122    tr_sessionLoadSettings( &top, configDir, NULL );
123    for( int i=0; i<PREFS_COUNT; ++i )
124    {
125        double d;
126        tr_bool boolVal;
127        int64_t intVal;
128        const char * str;
129        tr_benc * b( tr_bencDictFind( &top, myItems[i].key ) );
130
131        switch( myItems[i].type )
132        {
133            case QVariant::Int:
134                if( tr_bencGetInt( b, &intVal ) )
135                    myValues[i].setValue( qlonglong(intVal) );
136                break;
137            case QVariant::String:
138                if( tr_bencGetStr( b, &str ) )
139                    myValues[i].setValue( QString::fromUtf8(str) );
140                break;
141            case QVariant::Bool:
142                if( tr_bencGetBool( b, &boolVal ) )
143                    myValues[i].setValue( bool(boolVal) );
144                break;
145            case QVariant::Double:
146                if( tr_bencGetReal( b, &d ) )
147                    myValues[i].setValue( d );
148                break;
149            case QVariant::DateTime:
150                if( tr_bencGetInt( b, &intVal ) )
151                    myValues[i].setValue( QDateTime :: fromTime_t( intVal ) );
152                break;
153            default:
154                assert( "unhandled type" && 0 );
155                break;
156        }
157    }
158
159    tr_bencFree( &top );
160}
161
162Prefs :: ~Prefs( )
163{
164    tr_benc top;
165
166    /* load in the existing preferences file */
167    QFile file( QDir( myConfigDir ).absoluteFilePath( "settings.json" ) );
168    file.open( QIODevice::ReadOnly | QIODevice::Text );
169    const QByteArray oldPrefs = file.readAll( );
170    file.close( );
171    if( tr_jsonParse( oldPrefs.data(), oldPrefs.length(), &top, NULL ) )
172        tr_bencInitDict( &top, PREFS_COUNT );
173
174    /* merge our own settings with the ones already in the file */
175    for( int i=0; i<PREFS_COUNT; ++i ) {
176        const char * key = myItems[i].key;
177        const QVariant& val = myValues[i];
178        switch( myItems[i].type ) {
179            case QVariant::Int:
180                tr_bencDictAddInt( &top, key, val.toInt() );
181                break;
182            case QVariant::String:
183                tr_bencDictAddStr( &top, key, val.toString().toUtf8().constData() );
184                break;
185            case QVariant::Bool:
186                tr_bencDictAddBool( &top, key, val.toBool() );
187                break;
188            case QVariant::Double:
189                tr_bencDictAddReal( &top, key, val.toDouble() );
190                break;
191            case QVariant::DateTime:
192                tr_bencDictAddInt( &top, key, val.toDateTime().toTime_t() );
193                break;
194            default:
195                assert( "unhandled type" && 0 );
196                break;
197        }
198    }
199
200    /* write back out the serialized preferences */
201    char * json = tr_bencToJSON( &top );
202    if( json && *json ) {
203        file.open( QIODevice::WriteOnly | QIODevice::Text );
204        file.write( json );
205        file.close( );
206    }
207    tr_free( json );
208    tr_bencFree( &top );
209}
210
211/**
212 * This is where we initialize the preferences file with the default values.
213 * If you add a new preferences key, you /must/ add a default value here.
214 */
215void
216Prefs :: initDefaults( tr_benc * d )
217{
218    tr_bencDictAddStr( d, keyStr(DIR_WATCH), tr_getDefaultDownloadDir( ) );
219    tr_bencDictAddInt( d, keyStr(DIR_WATCH_ENABLED), false );
220    tr_bencDictAddInt( d, keyStr(INHIBIT_HIBERNATION), false );
221    tr_bencDictAddInt( d, keyStr(BLOCKLIST_DATE), 0 );
222    tr_bencDictAddInt( d, keyStr(BLOCKLIST_UPDATES_ENABLED), true );
223    tr_bencDictAddStr( d, keyStr(OPEN_DIALOG_FOLDER), QDir::home().absolutePath().toLatin1() );
224    tr_bencDictAddInt( d, keyStr(TOOLBAR), true );
225    tr_bencDictAddInt( d, keyStr(FILTERBAR), true );
226    tr_bencDictAddInt( d, keyStr(STATUSBAR), true );
227    tr_bencDictAddInt( d, keyStr(SHOW_TRAY_ICON), false );
228    tr_bencDictAddInt( d, keyStr(SHOW_DESKTOP_NOTIFICATION), true );
229    tr_bencDictAddStr( d, keyStr(STATUSBAR_STATS), "total-ratio" );
230    tr_bencDictAddInt( d, keyStr(OPTIONS_PROMPT), true );
231    tr_bencDictAddInt( d, keyStr(MAIN_WINDOW_HEIGHT), 500 );
232    tr_bencDictAddInt( d, keyStr(MAIN_WINDOW_WIDTH), 300 );
233    tr_bencDictAddInt( d, keyStr(MAIN_WINDOW_X), 50 );
234    tr_bencDictAddInt( d, keyStr(MAIN_WINDOW_Y), 50 );
235    tr_bencDictAddStr( d, keyStr(FILTER_MODE), "all" );
236    tr_bencDictAddStr( d, keyStr(MAIN_WINDOW_LAYOUT_ORDER), "menu,toolbar,filter,list,statusbar" );
237    tr_bencDictAddStr( d, keyStr(DOWNLOAD_DIR), tr_getDefaultDownloadDir( ) );
238    tr_bencDictAddInt( d, keyStr(ASKQUIT), true );
239    tr_bencDictAddStr( d, keyStr(SORT_MODE), "sort-by-name" );
240    tr_bencDictAddInt( d, keyStr(SORT_REVERSED), false );
241    tr_bencDictAddInt( d, keyStr(MINIMAL_VIEW), false );
242    tr_bencDictAddInt( d, keyStr(START), true );
243    tr_bencDictAddInt( d, keyStr(TRASH_ORIGINAL), false );
244}
245
246/***
247****
248***/
249
250bool
251Prefs :: getBool( int key ) const
252{
253    assert( myItems[key].type == QVariant::Bool );
254    return myValues[key].toBool( );
255}
256
257QString
258Prefs :: getString( int key ) const
259{
260    assert( myItems[key].type == QVariant::String );
261    return myValues[key].toString( );
262}
263
264int
265Prefs :: getInt( int key ) const
266{
267    assert( myItems[key].type == QVariant::Int );
268    return myValues[key].toInt( );
269}
270
271double
272Prefs :: getDouble( int key ) const
273{
274    assert( myItems[key].type == QVariant::Double );
275    return myValues[key].toDouble( );
276}
277
278QDateTime
279Prefs :: getDateTime( int key ) const
280{
281    assert( myItems[key].type == QVariant::DateTime );
282    return myValues[key].toDateTime( );
283}
284
285/***
286****
287***/
288
289void
290Prefs :: toggleBool( int key )
291{
292    set( key, !getBool( key ) );
293}
Note: See TracBrowser for help on using the repository browser.