Check-in [ec7df3c333]
Overview
Comment: | new plugin: theme installer for Gtk2 and Windows; fixed for support of JSON format; gtk_reset_styles -- Oliver |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
ec7df3c333f5cf80442dc960e8acd036 |
User & Date: | mario on 2016-12-14 15:57:06 |
Other Links: | manifest | tags |
Context
2016-12-15
| ||
20:29 | Change priority from obsolete to outdated check-in: 45774fa6d9 user: mario tags: trunk | |
2016-12-14
| ||
15:57 | new plugin: theme installer for Gtk2 and Windows; fixed for support of JSON format; gtk_reset_styles -- Oliver check-in: ec7df3c333 user: mario tags: trunk | |
2016-12-11
| ||
19:16 | Support file open dialog check-in: fdc2e9e4c4 user: mario tags: trunk | |
Changes
Modified channels/favicon.py from [8c7cddb000] to [ef3ab53102].
︙ | ︙ | |||
321 322 323 324 325 326 327 | image.save(out, "PNG", quality=98) imgdata = out.getvalue() except Exception as e: #traceback.print_exc() return log.ERR("favicon/logo conversion error:", e) and False else: | | | 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 | image.save(out, "PNG", quality=98) imgdata = out.getvalue() except Exception as e: #traceback.print_exc() return log.ERR("favicon/logo conversion error:", e) and False else: log.WARN("Couldn't detect valid image type from its raw content") # PNG already? if re.match(b"^.(PNG)", imgdata): try: with open(fn, "wb") as f: f.write(imgdata) return True |
︙ | ︙ |
Modified contrib/gtk_theme.py from [1923315d1d] to [9433f9c695].
︙ | ︙ | |||
56 57 58 59 60 61 62 63 64 65 66 67 68 69 | if not os.path.exists(fn): continue log.GTK_THEME_FILE(fn) # .GTKRC/Gtk2 if uikit.ver == 2: uikit.gtk.rc_parse(fn) if now or conf.theme_instant: uikit.gtk.rc_reparse_all() # .CSS/Gtk3 elif now or conf.theme_instant: #ctx = uikit.gtk.StyleContext # global ctx = self.parent.win_streamtuner2.get_style_context() # main window screen = uikit.gtk.gdk.Screen.get_default() style = uikit.gtk.CssProvider() | > | 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | if not os.path.exists(fn): continue log.GTK_THEME_FILE(fn) # .GTKRC/Gtk2 if uikit.ver == 2: uikit.gtk.rc_parse(fn) if now or conf.theme_instant: uikit.gtk.reset_styles(uikit.gtk.settings_get_for_screen(uikit.gtk.gdk.screen_get_default())) uikit.gtk.rc_reparse_all() # .CSS/Gtk3 elif now or conf.theme_instant: #ctx = uikit.gtk.StyleContext # global ctx = self.parent.win_streamtuner2.get_style_context() # main window screen = uikit.gtk.gdk.Screen.get_default() style = uikit.gtk.CssProvider() |
︙ | ︙ |
Added contrib/theme_installer.py version [d37a7bfc56].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 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 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 | # encoding: UTF-8 # api: streamtuner2 # title: Gtk2 theme installer # description: Shows themes in the bookmarks pane for installation # type: feature # category: ui # version: 0.3 # priority: experimental # # Downloads a list of Gtk themes and presents it in the bookmarks # tab under... Β»themesΒ«. Double clicking will download and install # a theme right away. # # Note that this is primarily meant for Windows, as it unpacks # *.dll engines if found. Should work on BSD/Linux still, but would # require setting up .gtkrc, and writeable module_path for engines. # It only handles Gtk2 themes currently. # # Reuses the `conf.theme` setting from the `gtk_theme` plugin, and # should work in conjunction to it. # # The theme repository is a CSV file of: # themepkg.zip, theme.png, Title, Author, http://homepage/ # with the packages residing next to it. # # Using a repo.json works better however, and would allow to # integrate it with the regular plugin manager somewhen. # The bookmark/themes channel provides the nicer UI however. # # A theme.zip should contain a structure like: # --------- ---------- ----- ---- # 62937 2016-12-12 16:39 librezlooks.dll # 0 2016-12-12 16:40 Rezlooks-dark/ # 0 2016-12-03 20:58 Rezlooks-dark/gtk-2.0/ # 5332 2006-06-30 05:28 Rezlooks-dark/gtk-2.0/gtkrc # --------- ---------- ----- ---- # With the dll in the root, and theme files in a named subdir. # Zips are extracted into the config dir ../streamtuner2/themes/ # and copies left there even. import os, shutil import csv import zipfile import re import json import ahttp from config import * import uikit from compat2and3 import * import action import channels.favicon as fi # register a key class theme_installer(object): # plugin info module = "theme_installer" meta = plugin_meta() category = "themes" theme_dir = conf.dir + "/themes/" themes_url = "http://milki.include-once.org/streamtuner2/themes/" themes_csv = "themes.json" mime = "zip/gtk-theme" parent = None bm = None # register def __init__(self, parent): if not parent: return if not uikit.ver == 2: return if not "theme" in conf: conf.theme = "default" if not os.path.exists(self.theme_dir): os.mkdir(self.theme_dir) self.parent = parent self.bm = parent.bookmarks # register hooks action.handler[self.mime] = self.install_handler # zip/gtk-theme downloader self.bm.add_category(self.category) # add subcategory self.bm.category_plugins[self.category] = self # reloading theme list parent.hooks["init"].append(self.apply_theme) # load gtk theme on start # gtk.rc_parse() called on configwin.save and ST2 startup def apply_theme(self, now=True): if conf.theme == "default": return # look if theme exists fn = "%s%s/%s" % (self.theme_dir, conf.theme, "gtk-2.0/gtkrc") if not os.path.exists(fn): return log.GTK_THEME_FILE(fn) # .GTKRC/Gtk2 uikit.gtk.rc_parse_string("module_path \"%s:%s\"\n" % (uikit.gtk.rc_get_module_dir(), self.theme_dir)) uikit.gtk.rc_parse(fn) uikit.gtk.rc_reset_styles(uikit.gtk.settings_get_for_screen(uikit.gtk.gdk.screen_get_default())) # download list of themes def update_streams(self, cat): r = [] data = ahttp.get(self.themes_url + self.themes_csv) #-- repo.JSON if re.match("^\s*\[\s*\{", data): r = json.loads(data) # can contain a literal rows-list + repo meta data #-- themes.CSV else: for row in re.findall("^(?!#)\s*(.+?),\s*(.+?),\s*(.+?),\s*(.+?),\s*(.+)", data, re.M): # prepare row d = dict( genre = "gtk2", url = row[0], img = row[1], title = row[2], playing = row[3], homepage = row[4], state = "gtk-zoom-fit", format = self.mime, listformat = "href" ) # add r.append(d) # convert relative references for d in r: for field in ("url", "img", '$file'): v = str(d.get(field)) if v and v.find("://") < 0: d[field] = self.themes_url + v d["title"] = "\n%s\n" % d.get("title", "-") # predownload favicons for d in r: d["favicon"] = fi.row_to_fn(d) if not os.path.exists(d["favicon"]): fi.banner_localcopy(d["img"], d["favicon"], 64) log.COPY( d["img"], d["favicon"] ) return r # invoked by action. module when encounterin a zip/gtk-theme links def install_handler(self, row, audioformat, source, assoc): if not "url" in row: return # download log.THEME_INSTALL(row["url"]) zip = self.theme_dir + os.path.basename(row["url"]) #if not os.path.exists(zip): with open(zip, "wb") as f: f.write(ahttp.get(row["url"], binary=True)) # extract z = zipfile.ZipFile(zip) z.extractall(self.theme_dir) ls = z.namelist() dll = [fn for fn in ls if re.search("\w+\.(dll|so)$", fn)] base = [m.group(1) for fn in ls for m in [re.match("^([\w\s\-\.]+)/gtk-2.0/.+", fn)] if m] # move *.dll / *.so for gtk_dir in uikit.gtk.rc_get_module_dir().split(":"): if os.path.exists(gtk_dir) and os.access(gtk_dir, os.W_OK): for fn in dll: if fn.find("/") > 0: # create lib/engines/.../ if given try: os.makedirs(self.theme_dir + os.path.basename(fn)) except: pass # copy file if shutil.copy(self.theme_dir + fn, gtk_dir): break # enable conf.theme = base[0] self.apply_theme(True) conf.save() |
Modified dev/install_python_gtk.ps1 from [e1ab50fb3b] to [d1faae1ee5].
︙ | ︙ | |||
18 19 20 21 22 23 24 | [string]$TEMP = $env:TEMP, [string]$PYTHON = "C:\Python27", [string]$StartMenu = "$env:USERPROFILE\AppData\Roaming\Microsoft\Windows\Start Menu\Programs", #[string]$UsrFolder = $MyInvocation.MyCommand.Path -replace ("([\\/][^\\/]+){4}$",""), [string]$ProgramFiles = "%ProgramFiles(x86)%", [string]$AboutLink = "http://freshcode.club/projects/streamtuner2", [string]$VERSION = "2.2.0" | | | 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | [string]$TEMP = $env:TEMP, [string]$PYTHON = "C:\Python27", [string]$StartMenu = "$env:USERPROFILE\AppData\Roaming\Microsoft\Windows\Start Menu\Programs", #[string]$UsrFolder = $MyInvocation.MyCommand.Path -replace ("([\\/][^\\/]+){4}$",""), [string]$ProgramFiles = "%ProgramFiles(x86)%", [string]$AboutLink = "http://freshcode.club/projects/streamtuner2", [string]$VERSION = "2.2.0" ) #-- paths $UsrFolder = $MyInvocation.MyCommand.Path -replace ("([\\/][^\\/]+){4}$","") $UninstallPath = "$UsrFolder\share\streamtuner2\dev\uninstall.cmd" $ResetPrefsPath = $UninstallPath -replace ("uninstall", "resetprefs") $ModifyPath = $MyInvocation.MyCommand.Path -replace ("[.]ps1$", ".bat") $IconPath = "$UsrFolder\share\pixmaps\streamtuner2.ico" |
︙ | ︙ | |||
189 190 191 192 193 194 195 196 197 198 199 200 201 202 | $MyWindow = $Host.UI.RawUI.WindowSize $MyWindow.Height = ($MaxHeight) $MyWindow.Width = (80) $MyBuffer.Height = (9999) #$MyBuffer.Width = (80) $host.UI.RawUI.set_bufferSize($MyBuffer) $host.UI.RawUI.set_windowSize($MyWindow) } } #-- create Desktop/Startmenu shortcuts function Make-Shortcut { param($dir, $name, $target, $arg=$false, $parm=$false, [parameter(ValueFromRemainingArguments=$true)]$kwargs=0) if (!(Test-Path -Path $dir)) { | > | 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 | $MyWindow = $Host.UI.RawUI.WindowSize $MyWindow.Height = ($MaxHeight) $MyWindow.Width = (80) $MyBuffer.Height = (9999) #$MyBuffer.Width = (80) $host.UI.RawUI.set_bufferSize($MyBuffer) $host.UI.RawUI.set_windowSize($MyWindow) $host.ui.RawUI.BackgroundColor = ($bckgrnd = 'Black') } } #-- create Desktop/Startmenu shortcuts function Make-Shortcut { param($dir, $name, $target, $arg=$false, $parm=$false, [parameter(ValueFromRemainingArguments=$true)]$kwargs=0) if (!(Test-Path -Path $dir)) { |
︙ | ︙ | |||
323 324 325 326 327 328 329 | ForEach ($t in $tasks) { $t.found = 0 $t.testpth = $t.testpth -replace "{PYTHON}","$PYTHON" if (!$t.regkey -and !$t.testpth) { continue } if ($t.prescn) { # expression for e.g. registry β path lookup | | | 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 | ForEach ($t in $tasks) { $t.found = 0 $t.testpth = $t.testpth -replace "{PYTHON}","$PYTHON" if (!$t.regkey -and !$t.testpth) { continue } if ($t.prescn) { # expression for e.g. registry β path lookup Invoke-Expression $t.prescn # should set $t.found + global $PLACEHOLDER variable } elseif ($t.testpth) { if (Test-Path $t.testpth) { $t.found = $t.testpth } elseif ($t.regkey -and (Test-Path $t.regkey)) { $t.found = "installer/registry" |
︙ | ︙ | |||
361 362 363 364 365 366 367 | } #-- Operates on parameters of each hash from `$tasks` # # Β· $title β print current step # Β· $url β download from given link, keep as local `$file` # Β· $cmd β instead of running file, run a custom command | | | | 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 | } #-- Operates on parameters of each hash from `$tasks` # # Β· $title β print current step # Β· $url β download from given link, keep as local `$file` # Β· $cmd β instead of running file, run a custom command # Β· $iargs β used for MSI installation # Β· $testpth β check for exisiting dir/file # Β· $regkey β set registry key if successful # Β· $is_opt β run as expression # Β· $prescn β used in check-prereq() # filter Run-Task { # extract flags/vars from $tasks pipe $title=""; $cmd=""; $url=""; $iargs=""; $testpth=""; $regkey=""; $is_opt=""; $prescn=""; $found="" ($task = $_).GetEnumerator() | % { Set-Variable -Scope Local -Name $_.key -Value ([regex]::Replace($_.value, "[#{](\w+)[}#]", { param($m) Invoke-Expression ("$"+$m.Groups[1].Value) })) } # skip optionals if ($is_opt -AND !(Invoke-Expression $is_opt)) { return } # print step if ($title -match "\d+\.\d+") { $title = "Installing $title" } |
︙ | ︙ | |||
429 430 431 432 433 434 435 | Start-Process -Wait msiexec -ArgumentList /i,"$TEMP\$file", $iargs if ($regkey) { Set-ItemProperty -Path "$regkey" -Name "WindowsInstaller" -Value "0" } } # exe elseif ($file -match ".+.exe$") { | | < | 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 | Start-Process -Wait msiexec -ArgumentList /i,"$TEMP\$file", $iargs if ($regkey) { Set-ItemProperty -Path "$regkey" -Name "WindowsInstaller" -Value "0" } } # exe elseif ($file -match ".+.exe$") { Write-Host -f DarkGray " β $file $iargs" if ($iargs) { Start-Process -Wait "$TEMP\$file" -ArgumentList $iargs } else { Start-Process -Wait "$TEMP\$file" } } # other files elseif ($file) { echo " β $file" & "$TEMP\$file" } } #-- run through tasks Clear-Host Console-MaxHeight Display-Logo Check-Package $PYTHON = Check-PythonInstall $reuseCachedFiles, $optionalInstall = Ask-First Check-Prerequisites $tasks | Run-Task # <-- main loop: process all commands Any-Key Green |