Check-in [ebae9e51ac]
Comment: | Replace old __print__/dbg.XYZ references with new log.XYZ() wrapper. |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
ebae9e51ace587c776685fc0416db7a2 |
User & Date: | mario on 2015-04-21 06:05:56 |
Other Links: | manifest | tags |
2015-04-21
| ||
22:00 | Fix missing .module property for add_plugin_defaults. check-in: 266321da13 user: mario tags: trunk | |
06:05 | Replace old __print__/dbg.XYZ references with new log.XYZ() wrapper. check-in: ebae9e51ac user: mario tags: trunk | |
2015-04-20
| ||
23:19 | Fix explanation on why iCast fetching takes a little while for some categories. check-in: de5d9ad092 user: mario tags: trunk | |
Modified action.py from [d87b406b97] to [b04a438de7].
︙ | |||
27 28 29 30 31 32 33 | 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | - + | # And finally this module is also used by exporting and (perhaps # in the future) playlist importing features. import re import os from ahttp import fix_url as http_fix_url, session |
︙ | |||
109 110 111 112 113 114 115 | 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 | - + - + | ] # Exec wrapper # def run(cmd): |
︙ | |||
205 206 207 208 209 210 211 | 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 | - + - + - + - + | # Substitute .pls URL with local .m3u, or direct srv addresses, or leaves URL asis. # ยท Takes a single input `url` (and original row{} as template). # ยท But returns a list of [urls] after playlist extraction. # ยท If repackaging as .m3u/.pls/.xspf, returns the local [fn]. # def convert_playlist(url, source, dest, local_file=True, row={}): urls = [] |
︙ | |||
285 286 287 288 289 290 291 | 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 | - + | mime = r.headers.get("content-type", "href") mime = mime.split(";")[0].strip() # Map MIME to abbr type (pls, m3u, xspf) if listfmt_t.get(mime): mime = listfmt_t.get(mime) # Raw content (mp3, flv) elif mediafmt_t.get(mime): |
︙ | |||
309 310 311 312 313 314 315 | 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 | - + | # Content of playlist file src = "" def __init__(self, text): self.src = text # Extract only URLs from given source type def format(self, fmt): |
︙ | |||
409 410 411 412 413 414 415 | 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 | - + | row["url"] = url new_rows.append(row) # Or just allow one stream per station in a playlist entry if not self.multiply: break rows = new_rows |
︙ |
Modified ahttp.py from [46b2bffbda] to [1c2ab28748].
︙ | |||
10 11 12 13 14 15 16 | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | - + | # # Provides a http "GET" method, but also does POST and AJAX- # simulating requests too. Hooks into mains gtk.statusbar(). # And can normalize URLs to always carry a trailing slash # after the domain name. |
︙ | |||
50 51 52 53 54 55 56 | 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | - + | #-- Retrieve data via HTTP # # Well, it says "get", but it actually does POST and AJAXish GET requests too. # def get(url, params={}, referer="", post=0, ajax=0, binary=0, feedback=None, content=True): |
︙ | |||
72 73 74 75 76 77 78 | 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | - - + + - + | # read if post: r = session.post(url, params=params, headers=headers, timeout=7.5) else: r = session.get(url, params=params, headers=headers, timeout=9.75) |
︙ |
Modified channels/__init__.py from [f6644128e5] to [5cecf16359].
︙ | |||
100 101 102 103 104 105 106 | 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | - + | #-- keep track of currently selected genre/category __current = None @property def current(self): return self.__current @current.setter def current(self, newcat): |
︙ | |||
163 164 165 166 167 168 169 | 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 | - + | # add to main menu uikit.add_menu([parent.channelmenuitems], self.meta["title"], lambda w: parent.channel_switch_by_name(self.module) or 1) # Statusbar stub (defers to parent/main window, if in GUI mode) def status(self, *v): if self.parent: self.parent.status(*v) |
︙ | |||
243 244 245 246 247 248 249 | 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 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 | - + - + - + | # called to early if not category: print "load(None)" return # get data from cache or download if force or not category in self.streams: |
︙ | |||
379 380 381 382 383 384 385 | 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 | - + - + - + - + - + - + | # display .current category, once notebook/channel tab is first opened def first_show(self): # Already processed if (self.shown == 55555): return |
︙ |
Modified channels/bookmarks.py from [baf2fe6dd0] to [44aa6ec97b].
︙ | |||
71 72 73 74 75 76 77 | 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | - + | # all entries just come from "bookmarks.json" def cache(self): # stream list cache = conf.load(self.module) if (cache): |
︙ | |||
136 137 138 139 140 141 142 | 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 | - + | return self.currentcat() # update bookmarks from freshly loaded streams data def heuristic_update(self, updated_channel, updated_category): if not conf.heuristic_bookmark_update: return |
︙ |
Modified channels/configwin.py from [913bf48a5c] to [fa4ff7a844].
︙ | |||
63 64 65 66 67 68 69 | 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | - + | w.set_default(val) # list elif type(w) is gtk.ListStore: w.clear() for k,v in val.items(): w.append([k, v, True, self.app_bin_check(v)]) w.append(["", "", True, gtk.STOCK_NEW]) |
︙ | |||
85 86 87 88 89 90 91 | 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | - + | config[key] = w.get_active() # dict elif type(w) is gtk.ListStore: config[key] = {} for row in w: if row[0] and row[1]: config[key][row[0]] = row[1] |
︙ |
Modified channels/dnd.py from [ef4879a2ca] to [fa727fbb20].
1 2 3 4 5 6 7 8 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | - + - + + | # encoding: UTF-8 # api: streamtuner2 # title: Drag and Drop (experimental) # description: Copy streams/stations from and to other applications. # depends: uikit # version: 0.5 # type: interface # config: |
︙ |
Modified channels/exportcat.py from [2dd3da6db4] to [fa4b19ec2a].
︙ | |||
42 43 44 45 46 47 48 | 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | - + | # Fetch streams from category, show "Save as" dialog, then convert URLs and export as playlist file def savewindow(self, *w): cn = self.parent.channel() source = cn.listformat streams = cn.streams[cn.current] fn = uikit.save_file("Export category", None, "%s.%s.%s" % (cn.module, cn.current, conf.export_format)) |
Modified channels/file.py from [62f947846d] to [710b8d2e10].
︙ | |||
23 24 25 26 27 28 29 | 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | - + - + | # ID3 libraries try: from mutagen import File as get_meta except: try: from ID3 import ID3 |
︙ |
Modified channels/global_key.py from [d213cc695c] to [9906a49477].
︙ | |||
39 40 41 42 43 44 45 | 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | - + | def __init__(self, parent): self.parent = parent conf.add_plugin_defaults(self.meta, self.module) try: for i,keyname in enumerate(conf.switch_key.split(",")): # allow multiple keys keybinder.bind(keyname, self.switch, ((-1 if i else +1))) # forward +1 or backward -1 except: |
︙ |
Modified channels/icast.py from [79c2eaaa83] to [84d1b6b174].
︙ | |||
31 32 33 34 35 36 37 | 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | - + | # because each query result has only 10 entries. # Which is why reloading takes a few seconds to # collect 200 station entries (see main options). import re import json |
︙ | |||
87 88 89 90 91 92 93 | 87 88 89 90 91 92 93 94 95 96 | - + | data = json.loads(http.get( self.base + method + path, params)) r += data["stations"] if len(r) >= data["meta"]["total_count"] or len(data["stations"]) < 10: break else: params["page"] = int(data["meta"]["current_page"]) + 1 self.parent.status(params["page"] * 9.5 / float(conf.max_streams)) |
Modified channels/internet_radio.py from [32acc0c3fa] to [69d9499a8c].
︙ | |||
24 25 26 27 28 29 30 | 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | - + | # HTTP retrieval happens in one batch, determined by the number of pages # setting, rather than the global max_streams option. # from channels import * import re |
︙ | |||
80 81 82 83 84 85 86 | 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 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 | - + - + - + - + - + - + | # Is there a next page? if str(page+1) not in rx_pages.findall(html[-1]): break self.parent.status(float(page)/float(max_pages+1)) # Alternatively try regex or pyquery parsing |
︙ |
Modified channels/itunes.py from [4b51b14809] to [43771b8835].
︙ | |||
28 29 30 31 32 33 34 | 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | - + | # โ AccuRadio # โ BBC # # In this module only iTunes will be queried for now. # import re |
︙ | |||
82 83 84 85 86 87 88 | 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | - + | pass # Just copy over stream URLs and station titles def update_streams(self, cat): m3u = http.get(self.base, {"category": cat.lower()}) if len(m3u) < 256: |
︙ |
Modified channels/jamendo.py from [92fc7a9153] to [43417ad008].
︙ | |||
34 35 36 37 38 39 40 | 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | - + | # back directly. Playlists and albums now require a roundtrip over the action # module to extract the JAMJson format into pls/m3u/xspf. (The previous v2 API # retrieval is going to become inaccessible soon.) import re import ahttp as http |
︙ |
Modified channels/live365.py from [7936759236] to [43a955e299].
︙ | |||
22 23 24 25 26 27 28 | 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | - + | # streamtuner2 modules from config import conf from uikit import uikit import ahttp as http from channels import * |
︙ |
Modified channels/modarchive.py from [b5a34220a3] to [90763cbfb7].
︙ | |||
25 26 27 28 29 30 31 | 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | - + | # setup wget/curl to download them. import re import ahttp as http from config import conf from channels import * |
︙ | |||
95 96 97 98 99 100 101 | 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | - + | .*? /formats/(\w+)\.png" .*? title="([^">]+)">([^<>]+)</a> .*? >(?:Rated|Unrated)</a>\s*(\d*) """, re.X|re.S) for uu in rx_mod.findall(html): (url, id, fmt, title, file, rating) = uu |
︙ |
Modified channels/punkcast.py from [946f14f97b] to [53641222c8].
︙ | |||
24 25 26 27 28 29 30 | 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | - + | import re import ahttp as http from config import conf import action from channels import * |
︙ | |||
77 78 79 80 81 82 83 | 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | - + | def play(self, row): rx_sound = re.compile("""(http://[^"<>]+[.](mp3|ogg|m3u|pls|ram))""") html = http.get(row["homepage"]) # look up ANY audio url for uu in rx_sound.findall(html): |
Modified channels/radiobrowser.py from [eb4063d5ff] to [11cf6e90ac].
︙ | |||
31 32 33 34 35 36 37 | 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | - + | # entries. Furthermore includes station homepage links! # # Also has a neat JSON API, so is quite easy to support. import re import json |
︙ |
Modified channels/radiotray.py from [1ad37964fc] to [60345f8f8f].
︙ | |||
99 100 101 102 103 104 105 | 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | - + | # send to def share(self, *w): row = self.parent.row() if row: # RadioTray doesn't have an addRadio method yet, so just fall back to play the stream URL try: group = self.map_group(row.get("genre")) |
︙ |
Modified channels/search.py from [e665e21e39] to [14f30d1313].
︙ | |||
98 99 100 101 102 103 104 | 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | - + | # live search on directory server homepages def server_search(self, w): self.prepare_search() entries = [] for i,cn in enumerate([self.main.channels[c] for c in self.targets]): if cn.has_search: # "search" in cn.update_streams.func_code.co_varnames: self.main.status("Server searching: " + cn.module) |
︙ |
Modified channels/shoutcast.py from [1fad5ce44e] to [7ab0770356].
︙ | |||
22 23 24 25 26 27 28 | 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | - + + - | # It has been aquired by Radionomy in 2014, since then significant changes # took place. The former yellow pages API got deprecated. import ahttp as http from json import loads as json_decode import re |
︙ | |||
63 64 65 66 67 68 69 | 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | - + | streams = {} # Extracts the category list from www.shoutcast.com, # stores a catmap (title => id) def update_categories(self): html = http.get(self.base_url) |
︙ | |||
90 91 92 93 94 95 96 | 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | - + - + - + | pass # downloads stream list from shoutcast for given category def update_streams(self, cat): if (cat not in self.catmap): |
Modified channels/somafm.py from [353f76d560] to [b4e377590b].
︙ | |||
22 23 24 25 26 27 28 | 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | - + | # only rewritten depending on bitrate configuration. # # Note that only 64bit AAC and 128bit MP3 are guaranteed # to be available. Most stations offer different bitrates, # but not all of them! |
︙ |
Modified channels/surfmusik.py from [a963360d8b] to [c2116e521c].
︙ | |||
30 31 32 33 34 35 36 | 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | - + | # be somewhat slow (for querying the actual mms:// streams). # # # import re import ahttp as http |
︙ |
Modified channels/timer.py from [f6d2128cb5] to [d2257940ad].
︙ | |||
72 73 74 75 76 77 78 | 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | - + | ("timer_dialog", "delete-event"): self.hide, }) # prepare spool self.sched = kronos.ThreadedScheduler() for row in self.streams: try: self.queue(row) |
︙ | |||
132 133 134 135 136 137 138 | 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 | - + | activity, action_method = "record", self.record else: activity, action_method = "play", self.play # add task = self.sched.add_daytime_task(action_method, activity, days, None, time, kronos.method.threaded, [row], {}) |
︙ |
Modified channels/tunein.py from [9721a1e7b7] to [0bca890c80].
︙ | |||
22 23 24 25 26 27 28 | 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | - + | # heaps more talk and local show entries, etc. (Would require # more deeply nested category tree.) # import re import json |
︙ |
Modified channels/ubuntuusers.py from [8e76324f70] to [e0b735eacf].
︙ | |||
18 19 20 21 22 23 24 | 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | - + | # Short user-collected list of internet radio stations # on UbuntuUsers.de wiki. Only provides a single category, # but stations are grouped by country already. # import re |
︙ |
Modified channels/useragentswitcher.py from [08fd23fe89] to [51e2b87f3f].
︙ | |||
39 40 41 42 43 44 45 | 39 40 41 42 43 44 45 46 47 48 49 | - + | parent.hooks["config_save"].append(self.apply) self.apply() # set new browser string in requests session def apply(self): ua = self.map.get(conf.useragent.lower(), self.map["default"]) if ua: |
Modified channels/xiph.py from [df3676cdef] to [c02f4fea70].
︙ | |||
101 102 103 104 105 106 107 | 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 | - + - + - + | if cat: params["cat"] = cat.lower() if search: params["search"] = search #-- get data data = http.get(self.json_url, params=params) |
︙ |
Modified channels/youtube.py from [0b836cb39e] to [16920f30fd].
︙ | |||
239 240 241 242 243 244 245 | 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 | - + | # URL and default parameters (base_url, defaults) = self.service[ver] params = dict( list(defaults.items()) + list(params.items()) ) # Retrieve data set while pages > 0: j = ahttp.get(base_url + method, params=params) |
︙ | |||
300 301 302 303 304 305 306 | 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 | - + | data["description"] = row["snippet"]["description"], return data # API version 2.0s jsonified XML needs different unpacking: def wrap2(self, row): |
Modified config.py from [8f2ac16ca3] to [b88512db4c].
1 2 3 4 5 6 7 8 9 10 11 12 13 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | - + - + - + | # # encoding: UTF-8 # api: streamtuner2 # type: class # title: global config object # description: reads ~/.config/streamtuner/*.json files # config: # { arg: -d, type: str, name: disable[], description: Omit plugin from initialization. } # { arg: -e, type: str, name: enable[], description: Add channel plugin. } # { arg: --gtk3, type: boolean, name: gtk3, description: Start with Gtk3 interface. } # { arg: -D, type: boolean, name: debug, description: Enable debug messages on console } # { arg: action, type: str *, name: action[], description: CLI interface commands. } # { arg: -x, type: boolean, name: exit, hidden: 1 } |
︙ | |||
462 463 464 465 466 467 468 | 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 | - - - - - - - - - - - - - - - - - - - - - - + - + | | ' ([^']*) ' # "quoted" or 'singl' values | ([^,]*) # or unquoted literals ) """, re.X) |
︙ |
Modified contrib/8tracks.py from [f8775355d0] to [8dc7ba54d9].
︙ | |||
14 15 16 17 18 19 20 | 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | - + | # Requires a pingback on playing, which is near impossible to implement # without also controlling the player. Automatic/implied notifications # could work, or checking via dbus/mpris even. # import re import json |
︙ |
Modified help/action_saving.page from [fb016701c8] to [8a7c8020d6].
︙ | |||
15 16 17 18 19 20 21 | 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | - - - - + + + + | <key>F2</key>. A file dialog opens, where you can adapt the title. </p> <p>The extension of the filename decides on the saved link format. Per default a .m3u file is created, because that's what most audio players understand.</p> |
Modified help/search.page from [201f70e153] to [48c7a270bc].
︙ | |||
29 30 31 32 33 34 35 | 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | - + - + - + - + | to scan for.</p> <media src="img/search.png" type="image" mime="image/png" /> <p>It either will search in all channels, or just the last active channel/service.</p> |
Modified st2.py from [5611c8c9c5] to [0608c8f1cb].
︙ | |||
119 120 121 122 123 124 125 | 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 | - + | # and late plugin initializations [callback(self) for callback in self.hooks["init"]] # display current open channel/notebook tab gui_startup(18/20.0) self.current_channel = self.current_channel_gtk() try: self.channel().first_show() |
︙ | |||
228 229 230 231 232 233 234 | 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 | - + | def current_channel_gtk(self): return self.channel_names[self.notebook_channels.get_current_page()] # Notebook tab has been clicked (receives numeric page_num), but *NOT* yet changed (visually). def channel_switch(self, notebook, page, page_num=0, *args): self.current_channel = notebook.get_menu_label_text(notebook.get_nth_page(page_num)) |
︙ | |||
275 276 277 278 279 280 281 | 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 | - + - + - + | url = self.selected("homepage") if url and len(url): action.browser(url) else: self.status("No homepage URL present.") # Browse to channel homepage (double click on notebook tab) def on_homepage_channel_clicked(self, widget, event=2): if event == 2 or event.type == gtk.gdk._2BUTTON_PRESS: |
︙ | |||
387 388 389 390 391 392 393 | 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 | - + - + | # load defaults on first startup if not name in conf.plugins: conf.add_plugin_defaults(plugin_meta(module=name), name) # skip module if disabled if conf.plugins.get(name, 1) == False: |
︙ | |||
494 495 496 497 498 499 500 | 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 | - + | if (conf.get("firstrun")): main.configwin.open(None) del conf.firstrun # run gtk.main() [callback() for callback in main.hooks["quit"]] |
Modified uikit.py from [59736bfdc8] to [14781849fd].
︙ | |||
42 43 44 45 46 47 48 | 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | - - + + | if ver==3: from gi import pygtkcompat as pygtk pygtk.enable() pygtk.enable_gtk(version='3.0') from gi.repository import Gtk as gtk from gi.repository import GObject as gobject from gi.repository import GdkPixbuf |
︙ | |||
127 128 129 130 131 132 133 | 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 | - + | # attach cell to column col.pack_end(rend, expand=cell[3].get("expand",True)) # apply attributes for attr,val in list(cell[3].items()): col.add_attribute(rend, attr, val) # next datapos += 1 |
︙ | |||
151 152 153 154 155 156 157 | 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 | - - + + | if (not rowmap): for desc in datamap: for var in xrange(2, len(desc)): vartypes.append(desc[var][1]) # content types rowmap.append(desc[var][0]) # dict{} column keys in entries[] list # create gtk array storage ls = gtk.ListStore(*vartypes) # could be a TreeStore, too |
︙ | |||
192 193 194 195 196 197 198 | 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 | - + - + | ls.append(row) # had to be adapted for real TreeStore (would require additional input for grouping/level/parents) except: # brute-force typecast ls.append( [va if ty==gtk.gdk.Pixbuf else ty(va) for va,ty in zip(row,vartypes)] ) #if entries: |
︙ |