source: trunk/qt/prefs.cc @ 13448

Last change on this file since 13448 was 13448, checked in by jordan, 9 years ago

(trunk, qt) #4760 'transmission-qt breaks unicode characters in the default target dir' -- fixed with patch from rb07

  • Property svn:keywords set to Date Rev Author Id
File size: 13.9 KB
Line 
1/*
2 * This file Copyright (C) Mnemosyne LLC
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2
6 * as published by the Free Software Foundation.
7 *
8 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
9 *
10 * $Id: prefs.cc 13448 2012-08-19 16:12:20Z jordan $
11 */
12
13#include <cassert>
14#include <iostream>
15
16#include <QDir>
17#include <QFile>
18
19#include <libtransmission/transmission.h>
20#include <libtransmission/bencode.h>
21#include <libtransmission/json.h>
22#include <libtransmission/utils.h>
23#include <stdlib.h>
24#include "prefs.h"
25#include "types.h"
26#include "utils.h"
27
28/***
29****
30***/
31
32Prefs::PrefItem Prefs::myItems[] =
33{
34    /* gui settings */
35    { OPTIONS_PROMPT, "show-options-window", QVariant::Bool },
36    { OPEN_DIALOG_FOLDER, "open-dialog-dir", QVariant::String },
37    { INHIBIT_HIBERNATION, "inhibit-desktop-hibernation", QVariant::Bool },
38    { DIR_WATCH, "watch-dir", QVariant::String },
39    { DIR_WATCH_ENABLED, "watch-dir-enabled", QVariant::Bool },
40    { SHOW_TRAY_ICON, "show-notification-area-icon", QVariant::Bool },
41    { SHOW_DESKTOP_NOTIFICATION, "show-desktop-notification", QVariant::Bool },
42    { ASKQUIT, "prompt-before-exit", QVariant::Bool },
43    { SORT_MODE, "sort-mode", TrTypes::SortModeType },
44    { SORT_REVERSED, "sort-reversed", QVariant::Bool },
45    { COMPACT_VIEW, "compact-view", QVariant::Bool },
46    { FILTERBAR, "show-filterbar", QVariant::Bool },
47    { STATUSBAR, "show-statusbar", QVariant::Bool },
48    { STATUSBAR_STATS, "statusbar-stats", QVariant::String },
49    { SHOW_TRACKER_SCRAPES, "show-extra-peer-details", QVariant::Bool },
50    { SHOW_BACKUP_TRACKERS, "show-backup-trackers", QVariant::Bool },
51    { TOOLBAR, "show-toolbar" , QVariant::Bool },
52    { BLOCKLIST_DATE, "blocklist-date", QVariant::DateTime },
53    { BLOCKLIST_UPDATES_ENABLED, "blocklist-updates-enabled" , QVariant::Bool },
54    { MAIN_WINDOW_LAYOUT_ORDER, "main-window-layout-order", QVariant::String },
55    { MAIN_WINDOW_HEIGHT, "main-window-height", QVariant::Int },
56    { MAIN_WINDOW_WIDTH, "main-window-width", QVariant::Int },
57    { MAIN_WINDOW_X, "main-window-x", QVariant::Int },
58    { MAIN_WINDOW_Y, "main-window-y", QVariant::Int },
59    { FILTER_MODE, "filter-mode", TrTypes::FilterModeType },
60    { FILTER_TRACKERS, "filter-trackers", QVariant::String },
61    { FILTER_TEXT, "filter-text", QVariant::String },
62    { SESSION_IS_REMOTE, "remote-session-enabled", QVariant::Bool },
63    { SESSION_REMOTE_HOST, "remote-session-host", QVariant::String },
64    { SESSION_REMOTE_PORT, "remote-session-port", QVariant::Int },
65    { SESSION_REMOTE_AUTH, "remote-session-requres-authentication", QVariant::Bool },
66    { SESSION_REMOTE_USERNAME, "remote-session-username", QVariant::String },
67    { SESSION_REMOTE_PASSWORD, "remote-session-password", QVariant::String },
68    { USER_HAS_GIVEN_INFORMED_CONSENT, "user-has-given-informed-consent", QVariant::Bool },
69
70    /* libtransmission settings */
71    { ALT_SPEED_LIMIT_UP, TR_PREFS_KEY_ALT_SPEED_UP_KBps, QVariant::Int },
72    { ALT_SPEED_LIMIT_DOWN, TR_PREFS_KEY_ALT_SPEED_DOWN_KBps, QVariant::Int },
73    { ALT_SPEED_LIMIT_ENABLED, TR_PREFS_KEY_ALT_SPEED_ENABLED, QVariant::Bool },
74    { ALT_SPEED_LIMIT_TIME_BEGIN, TR_PREFS_KEY_ALT_SPEED_TIME_BEGIN, QVariant::Int },
75    { ALT_SPEED_LIMIT_TIME_END, TR_PREFS_KEY_ALT_SPEED_TIME_END, QVariant::Int },
76    { ALT_SPEED_LIMIT_TIME_ENABLED, TR_PREFS_KEY_ALT_SPEED_TIME_ENABLED, QVariant::Bool },
77    { ALT_SPEED_LIMIT_TIME_DAY, TR_PREFS_KEY_ALT_SPEED_TIME_DAY, QVariant::Int },
78    { BLOCKLIST_ENABLED, TR_PREFS_KEY_BLOCKLIST_ENABLED, QVariant::Bool },
79    { BLOCKLIST_URL, TR_PREFS_KEY_BLOCKLIST_URL, QVariant::String },
80    { DSPEED, TR_PREFS_KEY_DSPEED_KBps, QVariant::Int },
81    { DSPEED_ENABLED, TR_PREFS_KEY_DSPEED_ENABLED, QVariant::Bool },
82    { DOWNLOAD_DIR, TR_PREFS_KEY_DOWNLOAD_DIR, QVariant::String },
83    { DOWNLOAD_QUEUE_ENABLED, TR_PREFS_KEY_DOWNLOAD_QUEUE_ENABLED, QVariant::Bool },
84    { DOWNLOAD_QUEUE_SIZE, TR_PREFS_KEY_DOWNLOAD_QUEUE_SIZE, QVariant::Int },
85    { ENCRYPTION, TR_PREFS_KEY_ENCRYPTION, QVariant::Int },
86    { IDLE_LIMIT, TR_PREFS_KEY_IDLE_LIMIT, QVariant::Int },
87    { IDLE_LIMIT_ENABLED, TR_PREFS_KEY_IDLE_LIMIT_ENABLED, QVariant::Bool },
88    { INCOMPLETE_DIR, TR_PREFS_KEY_INCOMPLETE_DIR, QVariant::String },
89    { INCOMPLETE_DIR_ENABLED, TR_PREFS_KEY_INCOMPLETE_DIR_ENABLED, QVariant::Bool },
90    { MSGLEVEL, TR_PREFS_KEY_MSGLEVEL, QVariant::Int },
91    { PEER_LIMIT_GLOBAL, TR_PREFS_KEY_PEER_LIMIT_GLOBAL, QVariant::Int },
92    { PEER_LIMIT_TORRENT, TR_PREFS_KEY_PEER_LIMIT_TORRENT, QVariant::Int },
93    { PEER_PORT, TR_PREFS_KEY_PEER_PORT, QVariant::Int },
94    { PEER_PORT_RANDOM_ON_START, TR_PREFS_KEY_PEER_PORT_RANDOM_ON_START, QVariant::Bool },
95    { PEER_PORT_RANDOM_LOW, TR_PREFS_KEY_PEER_PORT_RANDOM_LOW, QVariant::Int },
96    { PEER_PORT_RANDOM_HIGH, TR_PREFS_KEY_PEER_PORT_RANDOM_HIGH, QVariant::Int },
97    { QUEUE_STALLED_MINUTES, TR_PREFS_KEY_QUEUE_STALLED_MINUTES, QVariant::Int },
98    { SCRIPT_TORRENT_DONE_ENABLED, TR_PREFS_KEY_SCRIPT_TORRENT_DONE_ENABLED, QVariant::Bool },
99    { SCRIPT_TORRENT_DONE_FILENAME, TR_PREFS_KEY_SCRIPT_TORRENT_DONE_FILENAME, QVariant::String },
100    { SOCKET_TOS, TR_PREFS_KEY_PEER_SOCKET_TOS, QVariant::Int },
101    { START, TR_PREFS_KEY_START, QVariant::Bool },
102    { TRASH_ORIGINAL, TR_PREFS_KEY_TRASH_ORIGINAL, QVariant::Bool },
103    { PEX_ENABLED, TR_PREFS_KEY_PEX_ENABLED, QVariant::Bool },
104    { DHT_ENABLED, TR_PREFS_KEY_DHT_ENABLED, QVariant::Bool },
105    { UTP_ENABLED, TR_PREFS_KEY_UTP_ENABLED, QVariant::Bool },
106    { LPD_ENABLED, TR_PREFS_KEY_LPD_ENABLED, QVariant::Bool },
107    { PORT_FORWARDING, TR_PREFS_KEY_PORT_FORWARDING, QVariant::Bool },
108    { PREALLOCATION, TR_PREFS_KEY_PREALLOCATION, QVariant::Int },
109    { RATIO, TR_PREFS_KEY_RATIO, QVariant::Double },
110    { RATIO_ENABLED, TR_PREFS_KEY_RATIO_ENABLED, QVariant::Bool },
111    { RENAME_PARTIAL_FILES, TR_PREFS_KEY_RENAME_PARTIAL_FILES, QVariant::Bool },
112    { RPC_AUTH_REQUIRED, TR_PREFS_KEY_RPC_AUTH_REQUIRED, QVariant::Bool },
113    { RPC_ENABLED, TR_PREFS_KEY_RPC_ENABLED, QVariant::Bool },
114    { RPC_PASSWORD, TR_PREFS_KEY_RPC_PASSWORD, QVariant::String },
115    { RPC_PORT, TR_PREFS_KEY_RPC_PORT, QVariant::Int },
116    { RPC_USERNAME, TR_PREFS_KEY_RPC_USERNAME, QVariant::String },
117    { RPC_WHITELIST_ENABLED, TR_PREFS_KEY_RPC_WHITELIST_ENABLED, QVariant::Bool },
118    { RPC_WHITELIST, TR_PREFS_KEY_RPC_WHITELIST, QVariant::String },
119    { USPEED_ENABLED, TR_PREFS_KEY_USPEED_ENABLED, QVariant::Bool },
120    { USPEED, TR_PREFS_KEY_USPEED_KBps, QVariant::Int },
121    { UPLOAD_SLOTS_PER_TORRENT, TR_PREFS_KEY_UPLOAD_SLOTS_PER_TORRENT, QVariant::Int }
122};
123
124/***
125****
126***/
127
128Prefs :: Prefs( const char * configDir ):
129    myConfigDir( QString::fromUtf8( configDir ) )
130{
131    assert( sizeof(myItems) / sizeof(myItems[0]) == PREFS_COUNT );
132    for( int i=0; i<PREFS_COUNT; ++i )
133        assert( myItems[i].id == i );
134
135    // these are the prefs that don't get saved to settings.json
136    // when the application exits.
137    myTemporaryPrefs << FILTER_TEXT;
138
139    tr_benc top;
140    tr_bencInitDict( &top, 0 );
141    initDefaults( &top );
142    tr_sessionLoadSettings( &top, configDir, NULL );
143    for( int i=0; i<PREFS_COUNT; ++i )
144    {
145        double d;
146        bool boolVal;
147        int64_t intVal;
148        const char * str;
149        tr_benc * b( tr_bencDictFind( &top, myItems[i].key ) );
150
151        switch( myItems[i].type )
152        {
153            case QVariant::Int:
154                if( tr_bencGetInt( b, &intVal ) )
155                    myValues[i].setValue( qlonglong(intVal) );
156                break;
157            case TrTypes::SortModeType:
158                if( tr_bencGetStr( b, &str ) )
159                    myValues[i] = QVariant::fromValue( SortMode( str ) );
160                break;
161            case TrTypes::FilterModeType:
162                if( tr_bencGetStr( b, &str ) )
163                    myValues[i] = QVariant::fromValue( FilterMode( str ) );
164                break;
165            case QVariant::String:
166                if( tr_bencGetStr( b, &str ) )
167                    myValues[i].setValue( QString::fromUtf8( str ) );
168                break;
169            case QVariant::Bool:
170                if( tr_bencGetBool( b, &boolVal ) )
171                    myValues[i].setValue( bool(boolVal) );
172                break;
173            case QVariant::Double:
174                if( tr_bencGetReal( b, &d ) )
175                    myValues[i].setValue( d );
176                break;
177            case QVariant::DateTime:
178                if( tr_bencGetInt( b, &intVal ) )
179                    myValues[i].setValue( QDateTime :: fromTime_t( intVal ) );
180                break;
181            default:
182                assert( "unhandled type" && 0 );
183                break;
184        }
185    }
186
187    tr_bencFree( &top );
188}
189
190Prefs :: ~Prefs( )
191{
192    tr_benc top;
193
194    /* load in the existing preferences file */
195    QFile file( QDir( myConfigDir ).absoluteFilePath( "settings.json" ) );
196    file.open( QIODevice::ReadOnly | QIODevice::Text );
197    const QByteArray oldPrefs = file.readAll( );
198    file.close( );
199    if( tr_jsonParse( "settings.json", oldPrefs.data(), oldPrefs.length(), &top, NULL ) )
200        tr_bencInitDict( &top, PREFS_COUNT );
201
202    /* merge our own settings with the ones already in the file */
203    for( int i=0; i<PREFS_COUNT; ++i )
204    {
205        if( myTemporaryPrefs.contains( i ) )
206            continue;
207
208        const char * key = myItems[i].key;
209        const QVariant& val = myValues[i];
210
211        switch( myItems[i].type )
212        {
213            case QVariant::Int:
214                tr_bencDictAddInt( &top, key, val.toInt() );
215                break;
216            case TrTypes::SortModeType:
217                tr_bencDictAddStr( &top, key, val.value<SortMode>().name().toUtf8().constData() );
218                break;
219            case TrTypes::FilterModeType:
220                tr_bencDictAddStr( &top, key, val.value<FilterMode>().name().toUtf8().constData() );
221                break;
222            case QVariant::String:
223                {   const char * s = val.toByteArray().constData();
224                    if ( Utils::isValidUtf8( s ) )
225                        tr_bencDictAddStr( &top, key, s );
226                    else
227                        tr_bencDictAddStr( &top, key, val.toString().toUtf8().constData() );
228                }
229                break;
230            case QVariant::Bool:
231                tr_bencDictAddBool( &top, key, val.toBool() );
232                break;
233            case QVariant::Double:
234                tr_bencDictAddReal( &top, key, val.toDouble() );
235                break;
236            case QVariant::DateTime:
237                tr_bencDictAddInt( &top, key, val.toDateTime().toTime_t() );
238                break;
239            default:
240                assert( "unhandled type" && 0 );
241                break;
242        }
243    }
244
245    /* write back out the serialized preferences */
246    tr_bencToFile( &top, TR_FMT_JSON, file.fileName().toUtf8().constData() );
247    tr_bencFree( &top );
248}
249
250/**
251 * This is where we initialize the preferences file with the default values.
252 * If you add a new preferences key, you /must/ add a default value here.
253 */
254void
255Prefs :: initDefaults( tr_benc * d )
256{
257    tr_bencDictAddStr ( d, keyStr(DIR_WATCH), tr_getDefaultDownloadDir( ) );
258    tr_bencDictAddBool( d, keyStr(DIR_WATCH_ENABLED), false );
259    tr_bencDictAddBool( d, keyStr(INHIBIT_HIBERNATION), false );
260    tr_bencDictAddInt ( d, keyStr(BLOCKLIST_DATE), 0 );
261    tr_bencDictAddBool( d, keyStr(BLOCKLIST_UPDATES_ENABLED), true );
262    tr_bencDictAddStr ( d, keyStr(OPEN_DIALOG_FOLDER), QDir::home().absolutePath().toUtf8() );
263    tr_bencDictAddInt ( d, keyStr(SHOW_TRACKER_SCRAPES), false );
264    tr_bencDictAddBool( d, keyStr(TOOLBAR), true );
265    tr_bencDictAddBool( d, keyStr(FILTERBAR), true );
266    tr_bencDictAddBool( d, keyStr(STATUSBAR), true );
267    tr_bencDictAddBool( d, keyStr(SHOW_TRAY_ICON), false );
268    tr_bencDictAddBool( d, keyStr(SHOW_DESKTOP_NOTIFICATION), true );
269    tr_bencDictAddStr ( d, keyStr(STATUSBAR_STATS), "total-ratio" );
270    tr_bencDictAddBool( d, keyStr(SHOW_TRACKER_SCRAPES), false );
271    tr_bencDictAddBool( d, keyStr(SHOW_BACKUP_TRACKERS), false );
272    tr_bencDictAddBool( d, keyStr(OPTIONS_PROMPT), true );
273    tr_bencDictAddInt ( d, keyStr(MAIN_WINDOW_HEIGHT), 500 );
274    tr_bencDictAddInt ( d, keyStr(MAIN_WINDOW_WIDTH), 300 );
275    tr_bencDictAddInt ( d, keyStr(MAIN_WINDOW_X), 50 );
276    tr_bencDictAddInt ( d, keyStr(MAIN_WINDOW_Y), 50 );
277    tr_bencDictAddStr ( d, keyStr(FILTER_MODE), "all" );
278    tr_bencDictAddStr ( d, keyStr(MAIN_WINDOW_LAYOUT_ORDER), "menu,toolbar,filter,list,statusbar" );
279    tr_bencDictAddStr ( d, keyStr(DOWNLOAD_DIR), tr_getDefaultDownloadDir( ) );
280    tr_bencDictAddBool( d, keyStr(ASKQUIT), true );
281    tr_bencDictAddStr ( d, keyStr(SORT_MODE), "sort-by-name" );
282    tr_bencDictAddBool( d, keyStr(SORT_REVERSED), false );
283    tr_bencDictAddBool( d, keyStr(COMPACT_VIEW), false );
284    tr_bencDictAddStr ( d, keyStr(SESSION_REMOTE_HOST), "localhost" );
285    tr_bencDictAddInt ( d, keyStr(SESSION_REMOTE_PORT), atoi(TR_DEFAULT_RPC_PORT_STR) );
286    tr_bencDictAddBool( d, keyStr(SESSION_IS_REMOTE), false );
287    tr_bencDictAddBool( d, keyStr(SESSION_REMOTE_AUTH), false );
288    tr_bencDictAddBool( d, keyStr(USER_HAS_GIVEN_INFORMED_CONSENT), false );
289}
290
291/***
292****
293***/
294
295bool
296Prefs :: getBool( int key ) const
297{
298    assert( myItems[key].type == QVariant::Bool );
299    return myValues[key].toBool( );
300}
301
302QString
303Prefs :: getString( int key ) const
304{
305    assert( myItems[key].type == QVariant::String );
306    QByteArray b = myValues[key].toByteArray();
307    if ( Utils::isValidUtf8( b.constData() ) )
308       myValues[key].setValue( QString::fromUtf8( b.constData() ) );
309    return myValues[key].toString();
310}
311
312int
313Prefs :: getInt( int key ) const
314{
315    assert( myItems[key].type == QVariant::Int );
316    return myValues[key].toInt( );
317}
318
319double
320Prefs :: getDouble( int key ) const
321{
322    assert( myItems[key].type == QVariant::Double );
323    return myValues[key].toDouble( );
324}
325
326QDateTime
327Prefs :: getDateTime( int key ) const
328{
329    assert( myItems[key].type == QVariant::DateTime );
330    return myValues[key].toDateTime( );
331}
332
333/***
334****
335***/
336
337void
338Prefs :: toggleBool( int key )
339{
340    set( key, !getBool( key ) );
341}
Note: See TracBrowser for help on using the repository browser.