SettingsManager.cpp 9.7 KB
Newer Older
Clement CHAVANCE's avatar
Clement CHAVANCE committed
1
/*****************************************************************************
2
 * SettingsManager.cpp: Backend settings manager
Clement CHAVANCE's avatar
Clement CHAVANCE committed
3
 *****************************************************************************
Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
4
 * Copyright (C) 2008-2009 VideoLAN
Clement CHAVANCE's avatar
Clement CHAVANCE committed
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 *
 * Authors: Clement CHAVANCE <kinder@vlmc.org>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

23
24
#include "SettingsManager.h"

25
#include "SettingValue.h"
26

27
28
#include <QSettings>
#include <QDomDocument>
29
30
#include <QWriteLocker>
#include <QReadLocker>
31
#include <QXmlStreamWriter>
32
33
#include <QRegExp>
#include <QStringList>
34

35
#include <QtDebug>
Clement CHAVANCE's avatar
Clement CHAVANCE committed
36

37
38
39
40
void
SettingsManager::setValue( const QString &key,
                           const QVariant &value,
                           SettingsManager::Type type )
Clement CHAVANCE's avatar
Clement CHAVANCE committed
41
{
42
43
44
45
46
    if ( type == XML )
        m_tmpXmlSettings.insert( key, new SettingValue( value ) );
    else if ( type == QSett )
        m_tmpClassicSettings.insert( key, new SettingValue( value ) );
    return ;
Clement CHAVANCE's avatar
Clement CHAVANCE committed
47
48
}

49
50
51
52
void
SettingsManager::setImmediateValue( const QString &key,
                                    const QVariant &value,
                                    SettingsManager::Type type )
Clement CHAVANCE's avatar
Clement CHAVANCE committed
53
{
54
55
56
57
58
59
60
61
62
63
64
65
    QWriteLocker    wlock( &m_rwLock );
    SettingHash  *settMap;
    if ( type == XML )
        settMap = &m_xmlSettings;
    else if ( type == QSett )
    {
        QSettings    sett;
        sett.setValue( key, value );
        sett.sync();
        settMap = &m_classicSettings;
    }
    if ( settMap->contains( key ) )
66
    {
67
        settMap->value( key )->set( value );
68
    }
69
    else
70
    {
71
        settMap->insert( key, new SettingValue( value ) );
72
    }
73
74

    return ;
Clement CHAVANCE's avatar
Clement CHAVANCE committed
75
76
}

77
78
79
80
QVariant
SettingsManager::value( const QString &key,
                        const QVariant &defaultValue,
                        SettingsManager::Type type )
Clement CHAVANCE's avatar
Clement CHAVANCE committed
81
{
82
83
    QReadLocker rl( &m_rwLock );

84
85
86
87
88
89
90
91
92
93
94
    if ( ( type == XML || type == All ) )
    {
        if ( m_xmlSettings.contains( key ) )
            return m_xmlSettings.value( key )->get();
        else
        {
            m_xmlSettings.insert( key, new SettingValue( defaultValue ) );
            return defaultValue;
        }
    }
    else if ( type == QSett )
95
    {
96
97
98
99
100
101
102
103
104
105
106
        if ( m_classicSettings.contains( key ) )
            return m_classicSettings.value( key )->get();
        else
        {
            QSettings    sett;
            QVariant val = sett.value( key, defaultValue );
            if ( val != defaultValue )
                m_classicSettings.insert( key, new SettingValue( val ) );

            return val;
        }
107
    }
Clement CHAVANCE's avatar
Clement CHAVANCE committed
108
109
}

110
QHash<QString, QVariant>
111
SettingsManager::group( const QString &groupName, SettingsManager::Type type )
Clement CHAVANCE's avatar
Clement CHAVANCE committed
112
{
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
    QHash<QString, QVariant>    ret;
    QReadLocker rl( &m_rwLock );
    if ( ( type == XML || type == All ) )
    {
         SettingHash::const_iterator it = m_xmlSettings.begin();
         SettingHash::const_iterator ed = m_xmlSettings.end();

         for ( ; it != ed; ++it )
         {
             if ( it.key().contains( QRegExp( "^" + groupName + "/" ) ) )
                 ret.insert( it.key().right( it.key().size()
                             - it.key().indexOf( "/" ) - 1 ), it.value()->get() );
         }
    }
    if ( type == QSett || type == All )
    {
         SettingHash::const_iterator it = m_classicSettings.begin();
         SettingHash::const_iterator ed = m_classicSettings.end();

         for ( ; it != ed; ++it )
         {
             if ( it.key().contains( QRegExp( QString("^").append( groupName ).append( "/" ) ) ) )
             {
                 ret.insert( it.key().right( it.key().size()
                             - it.key().indexOf( "/" ) - 1 ), it.value()->get() );
             }
         }

         QSettings sett;
         QStringList keys = sett.allKeys();

         foreach ( QString key, keys )
         {
             QString match("^");
             match.append( groupName ).append( "/" );
             QRegExp    exp( match );
             if ( key.contains( exp ) )
             {
                 ret.insert( key.right( key.size()
                             - key.indexOf( "/" ) - 1 ), sett.value( key ) );
                 if ( !m_classicSettings.contains( key ) )
                     m_classicSettings.insert( key, new SettingValue( sett.value( key ) ) );
             }
         }
    }
    return ret;
Clement CHAVANCE's avatar
Clement CHAVANCE committed
159
160
}

161
162
163
164
bool
SettingsManager::watchValue( const QString &key,
                             QObject* receiver,
                             const char *method,
165
166
                             SettingsManager::Type type,
                             Qt::ConnectionType cType )
Clement CHAVANCE's avatar
Clement CHAVANCE committed
167
{
168
169
170
    QReadLocker rl( &m_rwLock );

    if ( ( type == XML || type == All ) && m_xmlSettings.contains( key ) )
171
    {
172
173
174
        connect( m_xmlSettings[key], SIGNAL( changed( const QVariant& ) ),
                 receiver, method );
        return true;
175
    }
176
    else if ( ( type == QSett || type == All ) )
177
    {
178
179
180
        if ( m_classicSettings.contains( key ) )
        {
            connect( m_classicSettings[key], SIGNAL( changed( const QVariant& ) ),
181
                    receiver, method, cType );
182
183
            return true;
        }
184
    }
Clement CHAVANCE's avatar
Clement CHAVANCE committed
185

186
    return false;
Clement CHAVANCE's avatar
Clement CHAVANCE committed
187
}
188

189
190
void
SettingsManager::save() const
191
{
192
193
194
195
196
197
198
199
200
201
202
    QReadLocker rl( &m_rwLock );
    QSettings    sett;
    SettingHash::const_iterator it = m_classicSettings.begin();
    SettingHash::const_iterator ed = m_classicSettings.end();

    for ( ; it != ed; ++it )
        sett.setValue( it.key(), it.value()->get() );
    sett.sync();
}

void
203
SettingsManager::save( QDomDocument &xmlfile, QDomElement &root ) const
204
205
206
207
208
209
210
211
212
{
    typedef QPair<QString, SettingValue*> settingPair;
    QMultiHash<QString, settingPair>  parts;

    QReadLocker rl( &m_rwLock );
    SettingHash::const_iterator it;
    SettingHash::const_iterator ed = m_xmlSettings.end();

    for ( it = m_xmlSettings.begin(); it != ed; ++it )
213
    {
214
215
216
217
218
        QString key = it.key();
        if ( key.count( "/" ) == 1 )
        {
            int idx = key.indexOf( "/" );
            QString part = key.left( idx );
219
            QString name = key.right( key.size() - idx - 1 );
220
221
222

            parts.insert( part, settingPair( name, it.value() ) );
        }
223
    }
224
225
    QList<QString>  keys = parts.uniqueKeys();
    foreach( QString xmlKey, keys )
226
    {
227
228
        QDomElement node = xmlfile.createElement( xmlKey );
        QList<settingPair>  pairs = parts.values( xmlKey );
229
        foreach( settingPair pair, pairs )
230
        {
231
232
233
            QDomElement item = xmlfile.createElement( pair.first );
            item.setAttribute( "value", pair.second->get().toString() );
            node.appendChild( item );
234
        }
235
        root.appendChild( node );
236
    }
237
}
238

239
bool
240
SettingsManager::load( const QDomElement &element )
241
{
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
    //For now it only handle a project node.
    if ( element.isNull() == true || element.tagName() != "project" )
    {
        qWarning() << "Invalid settings node";
        return false ;
    }
    QWriteLocker    wLock( &m_rwLock );
    QDomNodeList list = element.childNodes();
    int nbChild = list.size();

     for ( int idx = 0; idx < nbChild; ++idx )
    {
        QDomNamedNodeMap attrMap = list.at( idx ).attributes();
        if ( attrMap.count() > 1 )
        {
            qWarning() << "Invalid number of attributes for" << list.at( idx ).nodeName();
            continue ;
        }
        QString key = "project/" + list.at( idx ).toElement().tagName();
        if ( m_xmlSettings.contains( key ) )
            m_xmlSettings[key]->set( QVariant( attrMap.item( 0 ).nodeValue() ) );
        else
            m_xmlSettings.insert( key,
                                  new SettingValue( QVariant( attrMap.item( 0 ).nodeValue() ) ) );
    }
     return true;
Clement CHAVANCE's avatar
Clement CHAVANCE committed
268
269
}

270
271
bool
SettingsManager::commit( SettingsManager::Type type )
Clement CHAVANCE's avatar
Clement CHAVANCE committed
272
{
Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
273
    {
274
275
        QWriteLocker    wlock( &m_rwLock );
        if ( type == XML || type == All )
276
        {
277
278
279
            SettingHash::iterator it;
            SettingHash::iterator ed = m_tmpXmlSettings.end();
            for ( it = m_tmpXmlSettings.begin() ; it != ed; ++it )
Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
280
            {
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
                if ( m_xmlSettings.contains( it.key() ) )
                    m_xmlSettings[it.key()]->set( it.value()->get() );
                else
                    m_xmlSettings.insert( it.key(), it.value() );
            }
        }
        if ( type == QSett || type == All )
        {
            QSettings sett;
            SettingHash::iterator it;
            SettingHash::iterator ed = m_classicSettings.end();
            for ( it = m_classicSettings.begin(); it != ed; ++it )
            {
                sett.setValue( it.key(), it.value()->get() );
                if ( m_classicSettings.contains( it.key() ) )
                    m_classicSettings[it.key()]->set( it.value()->get() );
Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
297
                else
298
                    m_classicSettings.insert( it.key(), it.value() );
Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
299
            }
300
        }
Clement CHAVANCE's avatar
Clement CHAVANCE committed
301
    }
302
    flush();
Clement CHAVANCE's avatar
Clement CHAVANCE committed
303
304
}

305
306
void
SettingsManager::flush()
Clement CHAVANCE's avatar
Clement CHAVANCE committed
307
{
308
309
310
    QWriteLocker    wl( &m_rwLock );
    m_tmpXmlSettings.clear();
    m_tmpClassicSettings.clear();
311
312
}

313
314
315
316
317
318
SettingsManager::SettingsManager()
    : m_classicSettings(),
    m_xmlSettings(),
    m_tmpClassicSettings(),
    m_tmpXmlSettings(),
    m_rwLock()
319
{
320
321
}

322
SettingsManager::~SettingsManager()
323
324
{
}