Changeset 198:3231c0e271fc
- Timestamp:
- 06/09/09 01:43:25 (15 months ago)
- Author:
- Benjamin Wohlwend <bw@…>
- Branch:
- default
- Tags:
- tip
- Message:
-
Whitespace removal
- Location:
- src
- Files:
-
Legend:
- Unmodified
- Added
- Removed
-
|
r137
|
r198
|
|
| 96 | 96 | """ |
| 97 | 97 | Tests self.model's implementation of QtCore.QAbstractItemModel::rowCount() and hasChildren() |
| 98 | | |
| | 98 | |
| 99 | 99 | self.models that are dynamically populated are not as fully tested here. |
| 100 | 100 | """ |
| … |
… |
|
| 113 | 113 | if rows > 0: |
| 114 | 114 | assert(self.model.hasChildren(secondlvl) == True) |
| 115 | | |
| | 115 | |
| 116 | 116 | # The self.models rowCount() is tested more extensively in checkChildren, |
| 117 | 117 | # but this catches the big mistakes |
| … |
… |
|
| 248 | 248 | if variant.isValid(): |
| 249 | 249 | assert( variant.canConvert( QtCore.QVariant.String ) ) |
| 250 | | |
| | 250 | |
| 251 | 251 | # General Purpose roles that should return a QSize |
| 252 | 252 | variant = self.model.data(self.model.index(0,0,QtCore.QModelIndex()), QtCore.Qt.SizeHintRole) |
| … |
… |
|
| 258 | 258 | if variant.isValid(): |
| 259 | 259 | assert( variant.canConvert( QtCore.QVariant.Font ) ) |
| 260 | | |
| | 260 | |
| 261 | 261 | # Check that the alignment is one we know about |
| 262 | 262 | variant = self.model.data(self.model.index(0,0,QtCore.QModelIndex()), QtCore.Qt.TextAlignmentRole) |
-
|
r145
|
r198
|
|
| 59 | 59 | self.__stack = [] |
| 60 | 60 | self.__plist = self.__key = self.__characters = None |
| 61 | | # For reducing runtime type checking, |
| | 61 | # For reducing runtime type checking, |
| 62 | 62 | # the parser caches top level object type. |
| 63 | 63 | self.__in_dict = False |
| 64 | 64 | |
| 65 | 65 | def endDocument(self): |
| 66 | | self._assert(self.__plist is not None, "A top level element must be <plist>.") |
| | 66 | self._assert(self.__plist is not None, "A top level element must be <plist>.") |
| 67 | 67 | self._assert( |
| 68 | 68 | len(self.__stack) is 0, |
| … |
… |
|
| 164 | 164 | # http://www.apple.com/DTDs/PropertyList-1.0.dtd says: |
| 165 | 165 | # |
| 166 | | # Contents should conform to a subset of ISO 8601 |
| | 166 | # Contents should conform to a subset of ISO 8601 |
| 167 | 167 | # (in particular, YYYY '-' MM '-' DD 'T' HH ':' MM ':' SS 'Z'. |
| 168 | 168 | # Smaller units may be omitted with a loss of precision) |
| … |
… |
|
| 172 | 172 | def _parse_date(self, name, content): |
| 173 | 173 | import datetime |
| 174 | | |
| | 174 | |
| 175 | 175 | units = ('year', 'month', 'day', 'hour', 'minute', 'second', ) |
| 176 | 176 | pattern = XmlPropertyListParser.DATETIME_PATTERN |
| … |
… |
|
| 231 | 231 | else: |
| 232 | 232 | raise TypeError('Can\'t convert %s to file-like-object' % type(io_or_string)) |
| 233 | | |
| | 233 | |
| 234 | 234 | def _parse_using_etree(self, xml_input): |
| 235 | 235 | from xml.etree.cElementTree import iterparse |
| … |
… |
|
| 270 | 270 | Parse the property list (`.plist`, `.xml, for example) ``xml_input``, |
| 271 | 271 | which can be either a string or a file-like object. |
| 272 | | |
| | 272 | |
| 273 | 273 | >>> parser = XmlPropertyListParser() |
| 274 | 274 | >>> parser.parse(r'<plist version="1.0">' |
-
|
r142
|
r198
|
|
| 1 | 1 | from setuptools import setup |
| 2 | 2 | import shutil |
| 3 | | import os |
| | 3 | import os |
| 4 | 4 | APP = ['underCover.py'] |
| 5 | | OPTIONS = {'argv_emulation': True, |
| | 5 | OPTIONS = {'argv_emulation': True, |
| 6 | 6 | 'includes': ['sip', 'PyQt4._qt'], |
| 7 | 7 | 'iconfile': 'undercover/gui/img/logo.icns'} |
| 8 | | |
| | 8 | |
| 9 | 9 | setup( |
| 10 | 10 | app=APP, |
-
|
r124
|
r198
|
|
| 4 | 4 | # of this software and associated documentation files (the "Software"), to deal |
| 5 | 5 | # in the Software without restriction, including without limitation the rights |
| 6 | | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| 7 | | # copies of the Software, and to permit persons to whom the Software is |
| | 6 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| | 7 | # copies of the Software, and to permit persons to whom the Software is |
| 8 | 8 | # furnished to do so, subject to the following conditions: |
| 9 | 9 | # |
| 10 | | # The above copyright notice and this permission notice shall be included in |
| | 10 | # The above copyright notice and this permission notice shall be included in |
| 11 | 11 | # all copies or substantial portions of the Software. |
| 12 | 12 | # |
| 13 | | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 14 | | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| | 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| | 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 15 | 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| 16 | | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| | 16 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| 17 | 17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| 18 | 18 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
| 19 | | # SOFTWARE. |
| | 19 | # SOFTWARE. |
| 20 | 20 | |
| 21 | 21 | import urllib2 |
| … |
… |
|
| 28 | 28 | |
| 29 | 29 | class Fetcher(AbstractFetcher): |
| 30 | | """ |
| | 30 | """ |
| 31 | 31 | Gets covers from Amazon's web service. |
| 32 | | |
| | 32 | |
| 33 | 33 | Settings: |
| 34 | 34 | String amazon/api_key AWS API Key |
| 35 | 35 | String amazon/country Which country URL should be used |
| 36 | 36 | """ |
| 37 | | |
| | 37 | |
| 38 | 38 | IDENT = 'Amazon' |
| 39 | 39 | |
| … |
… |
|
| 46 | 46 | 'Canada' :'http://webservices.amazon.ca/onca/xml?Service=AWSECommerceService', |
| 47 | 47 | } |
| 48 | | |
| | 48 | |
| 49 | 49 | COUNTRY_LIST = ('USA', 'United Kingdom', 'Germany', 'Japan', 'France', 'Canada') |
| 50 | 50 | settings.set_choice('amazon/country', COUNTRY_LIST) |
-
|
r109
|
r198
|
|
| 75 | 75 | |
| 76 | 76 | register(GoogleImageFetcher) |
| 77 | | |
-
|
r134
|
r198
|
|
| 4 | 4 | # of this software and associated documentation files (the "Software"), to deal |
| 5 | 5 | # in the Software without restriction, including without limitation the rights |
| 6 | | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| 7 | | # copies of the Software, and to permit persons to whom the Software is |
| | 6 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| | 7 | # copies of the Software, and to permit persons to whom the Software is |
| 8 | 8 | # furnished to do so, subject to the following conditions: |
| 9 | 9 | # |
| 10 | | # The above copyright notice and this permission notice shall be included in |
| | 10 | # The above copyright notice and this permission notice shall be included in |
| 11 | 11 | # all copies or substantial portions of the Software. |
| 12 | 12 | # |
| 13 | | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 14 | | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| | 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| | 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 15 | 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| 16 | | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| | 16 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| 17 | 17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| 18 | 18 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
| 19 | | # SOFTWARE. |
| | 19 | # SOFTWARE. |
| 20 | 20 | |
| 21 | 21 | import urllib2 |
| … |
… |
|
| 26 | 26 | |
| 27 | 27 | class LastFMFetcher(AbstractFetcher): |
| 28 | | """ |
| | 28 | """ |
| 29 | 29 | Gets covers from Last.fm's web service. |
| 30 | | |
| | 30 | |
| 31 | 31 | Settings: |
| 32 | 32 | String lastfm/api_key Last.fm API Key |
| … |
… |
|
| 37 | 37 | URL = 'http://ws.audioscrobbler.com/2.0/?method=album.getinfo&' + \ |
| 38 | 38 | 'api_key=%(key)s&artist=%(artist)s&album=%(album)s' |
| 39 | | |
| 40 | | |
| | 39 | |
| | 40 | |
| 41 | 41 | def is_enabled(self): |
| 42 | 42 | return settings['lastfm/is_enabled'] |
-
|
r168
|
r198
|
|
| 5 | 5 | # of this software and associated documentation files (the "Software"), to deal |
| 6 | 6 | # in the Software without restriction, including without limitation the rights |
| 7 | | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| 8 | | # copies of the Software, and to permit persons to whom the Software is |
| | 7 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| | 8 | # copies of the Software, and to permit persons to whom the Software is |
| 9 | 9 | # furnished to do so, subject to the following conditions: |
| 10 | 10 | # |
| 11 | | # The above copyright notice and this permission notice shall be included in |
| | 11 | # The above copyright notice and this permission notice shall be included in |
| 12 | 12 | # all copies or substantial portions of the Software. |
| 13 | 13 | # |
| 14 | | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 15 | | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| | 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| | 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 16 | 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| 17 | | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| | 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| 18 | 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| 19 | 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
| 20 | | # SOFTWARE. |
| | 20 | # SOFTWARE. |
| 21 | 21 | |
| 22 | 22 | from codecs import open |
-
|
r180
|
r198
|
|
| 6 | 6 | # of this software and associated documentation files (the "Software"), to deal |
| 7 | 7 | # in the Software without restriction, including without limitation the rights |
| 8 | | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| 9 | | # copies of the Software, and to permit persons to whom the Software is |
| | 8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| | 9 | # copies of the Software, and to permit persons to whom the Software is |
| 10 | 10 | # furnished to do so, subject to the following conditions: |
| 11 | 11 | # |
| 12 | | # The above copyright notice and this permission notice shall be included in |
| | 12 | # The above copyright notice and this permission notice shall be included in |
| 13 | 13 | # all copies or substantial portions of the Software. |
| 14 | 14 | # |
| 15 | | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 16 | | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| | 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| | 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 17 | 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| 18 | | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| | 18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| 19 | 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| 20 | 20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
| 21 | | # SOFTWARE. |
| | 21 | # SOFTWARE. |
| 22 | 22 | |
| 23 | 23 | from __future__ import with_statement |
| … |
… |
|
| 68 | 68 | |
| 69 | 69 | lock = QtCore.QMutex() |
| 70 | | |
| | 70 | |
| 71 | 71 | def __init__(self, *args, **kwargs): |
| 72 | 72 | global parent |
| 73 | 73 | self.emitter = QtCore.QObject() |
| 74 | | QtCore.QObject.connect(self.emitter, QtCore.SIGNAL('new_query'), |
| | 74 | QtCore.QObject.connect(self.emitter, QtCore.SIGNAL('new_query'), |
| 75 | 75 | parent.show_new_query, QtCore.Qt.QueuedConnection) |
| 76 | 76 | QtCore.QObject.connect(self.emitter, QtCore.SIGNAL('showMessage(QString, int)'), |
| … |
… |
|
| 134 | 134 | self.send_xml(self.NO_COVER_FOUND_XML) |
| 135 | 135 | return |
| 136 | | |
| | 136 | |
| 137 | 137 | elif 'example.com/serve' in self.path: |
| 138 | 138 | appdir = settings['main/appdir'] |
| … |
… |
|
| 148 | 148 | self.end_headers() |
| 149 | 149 | self.wfile.write(data) |
| 150 | | self.emitter.emit(QtCore.SIGNAL('showMessage(QString, int)'), |
| | 150 | self.emitter.emit(QtCore.SIGNAL('showMessage(QString, int)'), |
| 151 | 151 | u'Served image for %s to iTunes' % unicode(image.album_query), 0) |
| 152 | 152 | return |
| 153 | | |
| | 153 | |
| 154 | 154 | # Otherwise, proxy the request to the real destination. |
| 155 | 155 | soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM) |
| … |
… |
|
| 200 | 200 | do_PUT = do_GET |
| 201 | 201 | do_DELETE=do_GET |
| 202 | | |
| | 202 | |
| 203 | 203 | def try_itms(self, album_query): |
| 204 | 204 | """ |
| … |
… |
|
| 229 | 229 | md5.update(new_data) |
| 230 | 230 | new_path = u'%s_%s' % (album_query.artist, album_query.album) |
| 231 | | new_path = Image.disallowed_chars.sub('_', new_path)[:60] + '_%s.png' % md5.hexdigest() |
| | 231 | new_path = Image.disallowed_chars.sub('_', new_path)[:60] + '_%s.png' % md5.hexdigest() |
| 232 | 232 | new_file = open(os.path.join(appdir, 'fullsize', new_path), 'wb') |
| 233 | 233 | new_file.write(new_data) |
| 234 | 234 | new_file.close() |
| 235 | 235 | with QtCore.QMutexLocker(self.lock): |
| 236 | | i = Image(path=new_path, url=None, comes_from='iTunes (locked)', |
| | 236 | i = Image(path=new_path, url=None, comes_from='iTunes (locked)', |
| 237 | 237 | bytes=len(new_data), album_query=album_query) |
| 238 | 238 | album_query.best_match = i |
| … |
… |
|
| 241 | 241 | pass |
| 242 | 242 | return False |
| 243 | | |
| | 243 | |
| 244 | 244 | def send_match_xml(self, image): |
| 245 | 245 | xml = self.COVER_INFO_XML % image.id |
| … |
… |
|
| 272 | 272 | def stop(self): |
| 273 | 273 | self.run = False |
| 274 | | |
| | 274 | |
| 275 | 275 | def serve(self): |
| 276 | 276 | while self.run: |
| … |
… |
|
| 284 | 284 | def start(self): |
| 285 | 285 | self.is_running = True |
| 286 | | self.proxy = StoppableHTTPServer((settings['main/our_proxy_host'], |
| | 286 | self.proxy = StoppableHTTPServer((settings['main/our_proxy_host'], |
| 287 | 287 | settings['main/our_proxy_port']), |
| 288 | 288 | CoverArtProxyHandler) |
| 289 | 289 | threading.Thread(target=self.proxy.serve).start() |
| 290 | | return QtCore.QCoreApplication.translate('Proxy', 'Proxy started at')+ ' %s:%i' % (self.proxy.server_address[0], |
| | 290 | return QtCore.QCoreApplication.translate('Proxy', 'Proxy started at')+ ' %s:%i' % (self.proxy.server_address[0], |
| 291 | 291 | self.proxy.server_address[1]) |
| 292 | | |
| | 292 | |
| 293 | 293 | def stop(self): |
| 294 | 294 | self.proxy.socket.close() |
-
|
r188
|
r198
|
|
| 4 | 4 | # of this software and associated documentation files (the "Software"), to deal |
| 5 | 5 | # in the Software without restriction, including without limitation the rights |
| 6 | | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| 7 | | # copies of the Software, and to permit persons to whom the Software is |
| | 6 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| | 7 | # copies of the Software, and to permit persons to whom the Software is |
| 8 | 8 | # furnished to do so, subject to the following conditions: |
| 9 | 9 | # |
| 10 | | # The above copyright notice and this permission notice shall be included in |
| | 10 | # The above copyright notice and this permission notice shall be included in |
| 11 | 11 | # all copies or substantial portions of the Software. |
| 12 | 12 | # |
| 13 | | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 14 | | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| | 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| | 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 15 | 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| 16 | | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| | 16 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| 17 | 17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| 18 | 18 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
| 19 | | # SOFTWARE. |
| | 19 | # SOFTWARE. |
| 20 | 20 | |
| 21 | 21 | import pickle |
| … |
… |
|
| 27 | 27 | A wrapper around QSettings that makes automatic handling of settings dialogs and |
| 28 | 28 | access of settings easier. |
| 29 | | |
| | 29 | |
| 30 | 30 | The name of the setting keys follows the pattern "group_name/key_name". This should |
| 31 | | be reflected in the object names of associated QWidgets in the form of |
| | 31 | be reflected in the object names of associated QWidgets in the form of |
| 32 | 32 | "group_name__key_name". |
| 33 | | |
| | 33 | |
| 34 | 34 | This class is a singleton. It should be considered as not thread safe. |
| 35 | 35 | ''' |
| 36 | | |
| | 36 | |
| 37 | 37 | def __new__(cls): |
| 38 | 38 | """Singleton pattern""" |
| … |
… |
|
| 42 | 42 | |
| 43 | 43 | __settings = QSettings(QSettings.IniFormat, QSettings.UserScope, 'piquadrat.ch', 'underCover') |
| 44 | | |
| | 44 | |
| 45 | 45 | __default_settings = { |
| 46 | 46 | # KEYNAME DEFAULT TYPE IS REQUIRED DATASTRUCTURE |
| … |
… |
|
| 56 | 56 | 'main/fetch_all' : (True, bool, ), |
| 57 | 57 | 'main/covers_view' : (0, int, ), |
| 58 | | |
| | 58 | |
| 59 | 59 | 'iTunes/cache' : (True, bool, ), |
| 60 | 60 | 'iTunes/library_path' : (None, unicode, ), |
| 61 | | |
| | 61 | |
| 62 | 62 | 'export/filename' : (u'cover.png',unicode, True, ), |
| 63 | 63 | 'export/overwrite' : (True, bool, ), |
| 64 | | |
| | 64 | |
| 65 | 65 | 'google/is_enabled' : (True, bool, ), |
| 66 | 66 | 'google/limit' : (5, int, ), |
| 67 | 67 | 'google/query_add' : (u'artwork', unicode, ), |
| 68 | 68 | 'google/safe_mode' : (True, bool, ), |
| 69 | | |
| | 69 | |
| 70 | 70 | 'amazon/is_enabled' : (False, bool, ), |
| 71 | 71 | 'amazon/api_key' : (None, unicode, True ), |
| 72 | 72 | 'amazon/country' : (0, list, False, [] ), |
| 73 | | |
| | 73 | |
| 74 | 74 | 'lastfm/is_enabled' : (True, bool, ), |
| 75 | 75 | 'lastfm/api_key' : ('f2e1eb43a86afaa065e6d826a977a0a4', unicode, True, ), |
| 76 | 76 | } |
| 77 | | |
| | 77 | |
| 78 | 78 | def __getitem__(self, key): |
| 79 | 79 | ''' |
| … |
… |
|
| 85 | 85 | else: |
| 86 | 86 | return self.__default_settings[key][0] |
| 87 | | |
| | 87 | |
| 88 | 88 | def __setitem__(self, key, value): |
| 89 | 89 | ''' |
| … |
… |
|
| 98 | 98 | raise TypeError, 'type of %s is %s, expected %s' % (key, str(type(key)), str(self.typeof(key))) |
| 99 | 99 | self.__settings.setValue(key, QVariant(pickle.dumps(value, protocol=0))) |
| 100 | | |
| | 100 | |
| 101 | 101 | def __haskey__(self, key): |
| 102 | 102 | return self.__settings.contains(key) or key in self.__default_settings |
| 103 | | |
| | 103 | |
| 104 | 104 | def setValue(self, key, value): |
| 105 | 105 | ''' |
| … |
… |
|
| 107 | 107 | ''' |
| 108 | 108 | self.__settings.setValue(key, value) |
| 109 | | |
| | 109 | |
| 110 | 110 | def value(self, key, default=QVariant()): |
| 111 | 111 | ''' |
| … |
… |
|
| 113 | 113 | ''' |
| 114 | 114 | return self.__settings.value(key, default) |
| 115 | | |
| | 115 | |
| 116 | 116 | def contains(self, key): |
| 117 | 117 | ''' |
| 118 | 118 | Direct access to the internal QSettings instance |
| 119 | 119 | ''' |
| 120 | | return self.__settings.contains(key) |
| | 120 | return self.__settings.contains(key) |
| 121 | 121 | def typeof(self, key): |
| 122 | 122 | ''' |
| … |
… |
|
| 124 | 124 | ''' |
| 125 | 125 | return self.__default_settings[key][1] |
| 126 | | |
| | 126 | |
| 127 | 127 | def keys(self, group=None): |
| 128 | 128 | ''' |
| … |
… |
|
| 134 | 134 | else: |
| 135 | 135 | return [key for key in self.__default_settings.keys() if key.startswith(group)] |
| 136 | | |
| | 136 | |
| 137 | 137 | def is_required(self, key): |
| 138 | 138 | ''' |
| 139 | 139 | Returns True if key is required, False otherwise. Requiredness should only be |
| 140 | 140 | evaluated if the group of this key is enabled. |
| 141 | | |
| | 141 | |
| 142 | 142 | Does not handle KeyErrors |
| 143 | 143 | ''' |
| … |
… |
|
| 146 | 146 | else: |
| 147 | 147 | return False |
| 148 | | |
| | 148 | |
| 149 | 149 | def set_choice(self, key, choices): |
| 150 | 150 | if len(self.__default_settings[key]) > 3: |
| … |
… |
|
| 154 | 154 | else: |
| 155 | 155 | raise KeyError, '%s has no choices list' % key |
| 156 | | |
| | 156 | |
| 157 | 157 | def choice(self, key): |
| 158 | 158 | if len(self.__default_settings[key]) > 3: |