Partial expanded view implementation

Not all metadata is correctly displayed yet
This commit is contained in:
Ellwood Zwovic
2017-07-15 02:18:18 -07:00
parent f588e3f619
commit c0d2419bea
2 changed files with 137 additions and 39 deletions

View File

@@ -392,57 +392,117 @@ class USERPREF_PT_packages(bpy.types.Panel):
return False return False
def draw_package(package, layout): def draw_package(pkg, layout):
"""Draws the given package""" """Draws the given package"""
pkgbox = layout.box() pkgbox = layout.box()
spl = pkgbox.split(.8) spl = pkgbox.split(.8)
left = spl.column(align=True) left = spl.row(align=True)
blinfo = pkg['bl_info']
# for install/uninstall buttons # for install/uninstall buttons
right = spl.row() right = spl.row()
right.alignment = 'RIGHT' right.alignment = 'RIGHT'
right.scale_y = 2 right.scale_y = 1.5
# for title & description # for collapse/expand button
lr1 = left.row() left.operator(
lr2 = left.row() WM_OT_package_toggle_expand.bl_idname,
lr2.enabled = False #Give name more visual weight icon='TRIA_DOWN' if pkg.get('expand') else 'TRIA_RIGHT',
emboss=False,
).package_id=pkg['id']
lr1.label(text=pkg['bl_info'].get('name', "MISSING NAME")) # for metadata
lr2.label(text=pkg['bl_info'].get('description', "MISSING DESCRIPTION")) leftcol = left.column(align=True)
def collapsed():
lr1 = leftcol.row()
lr2 = leftcol.row()
lr1.label(text=blinfo.get('name', "MISSING NAME"))
lr2.label(text=blinfo.get('description', "MISSING DESCRIPTION"))
lr2.enabled = False #Give name more visual weight
right.operator(BPKG_OT_install.bl_idname, right.operator(BPKG_OT_install.bl_idname,
text="Install").package_url=pkg.get('url', "") text="Install").package_url=pkg.get('url', "")
def expanded():
row1 = leftcol.row()
row1.label(blinfo.get('name'), "MISSING NAME")
if blinfo.get('description'):
row2 = leftcol.row()
row2.label(blinfo['description'])
# row2.scale_y = 1.2
if blinfo.get('version'):
vstr = str(blinfo['version'][0])
for component in blinfo['version'][1:]:
vstr += "." + str(component)
spl = leftcol.row().split(.15)
spl.label("Version:")
spl.label(vstr)
for prop in (
# "description",
"author",
"category",
# "version",
# "blender",
"location",
"warning",
"support",
# "wiki_url",
# "tracker_url",
):
if blinfo.get(prop):
row = leftcol.row()
row.scale_y = .8
spl = row.split(.15)
spl.label("{}:".format(prop.title()))
spl.label(str(blinfo[prop]))
if pkg.get('expand'):
expanded()
else:
collapsed()
for pkg in repo['packages']: for pkg in repo['packages']:
if filter_package(pkg): if filter_package(pkg):
row = pkgzone.row() row = pkgzone.row()
draw_package(pkg, row) draw_package(pkg, row)
# class WM_OT_package_expand(Operator): class WM_OT_package_toggle_expand(bpy.types.Operator):
# bl_idname = "wm.package_expand" bl_idname = "wm.package_toggle_expand"
# bl_label = "" bl_label = ""
# bl_description = "Display information and preferences for this package" bl_description = "Toggle display of all information for given package"
# bl_options = {'INTERNAL'} bl_options = {'INTERNAL'}
#
# module = StringProperty( log = logging.getLogger(__name__ + ".WM_OT_package_toggle_expand")
# name="Module",
# description="Module name of the add-on to expand", package_id = bpy.props.StringProperty(
# ) name="Package ID",
# description="ID of package to expand/shrink",
# def execute(self, context): )
# import addon_utils
# def execute(self, context):
# module_name = self.module repo = context.user_preferences.addons[__package__].preferences.get('repo')
#
# mod = addon_utils.addons_fake_modules.get(module_name) if not repo:
# if mod is not None: return {'CANCELLED'}
# info = addon_utils.module_bl_info(mod)
# info["show_expanded"] = not info["show_expanded"] pkg_id = self.package_id
#
# return {'FINISHED'} for pkg in repo['packages']:
# if pkg.get('id') == pkg_id:
# if pkg['expand'] is unset, it's not expanded
pkg['expand'] = not pkg.get('expand', False)
return {'FINISHED'}
class PackageManagerPreferences(bpy.types.AddonPreferences): class PackageManagerPreferences(bpy.types.AddonPreferences):
bl_idname = __package__ bl_idname = __package__
@@ -469,6 +529,7 @@ def register():
bpy.utils.register_class(BPKG_OT_refresh) bpy.utils.register_class(BPKG_OT_refresh)
bpy.utils.register_class(BPKG_OT_hang) bpy.utils.register_class(BPKG_OT_hang)
bpy.utils.register_class(USERPREF_PT_packages) bpy.utils.register_class(USERPREF_PT_packages)
bpy.utils.register_class(WM_OT_package_toggle_expand)
bpy.types.WindowManager.package_search = bpy.props.StringProperty( bpy.types.WindowManager.package_search = bpy.props.StringProperty(
name="Search", name="Search",
description="Filter packages by name", description="Filter packages by name",
@@ -490,6 +551,7 @@ def unregister():
bpy.utils.unregister_class(BPKG_OT_refresh) bpy.utils.unregister_class(BPKG_OT_refresh)
bpy.utils.unregister_class(BPKG_OT_hang) bpy.utils.unregister_class(BPKG_OT_hang)
bpy.utils.unregister_class(USERPREF_PT_packages) bpy.utils.unregister_class(USERPREF_PT_packages)
bpy.utils.unregister_class(WM_OT_package_toggle_expand)
del bpy.types.WindowManager.package_search del bpy.types.WindowManager.package_search
del bpy.types.WindowManager.package_install_filter del bpy.types.WindowManager.package_install_filter
bpy.utils.unregister_class(PackageManagerPreferences) bpy.utils.unregister_class(PackageManagerPreferences)

View File

@@ -175,8 +175,11 @@ class Repository:
log = logging.getLogger(__name__ + ".Repository") log = logging.getLogger(__name__ + ".Repository")
def __init__(self, url=None): def __init__(self, url=None):
if url is None:
url = ""
self.set_from_dict({'url': url}) self.set_from_dict({'url': url})
self.log.debug("Initializing repository: %s", self.to_dict()) self.log.debug("Initializing repository: %s", self.to_dict())
self.log.debug("Own URL is '%s'", self.url)
# def cleanse_packagelist(self): # def cleanse_packagelist(self):
# """Remove empty packages (no bl_info), packages with no name""" # """Remove empty packages (no bl_info), packages with no name"""
@@ -241,14 +244,21 @@ class Repository:
self.set_from_dict(repodict) self.set_from_dict(repodict)
def to_dict(self, sort=False) -> dict: def to_dict(self, sort=False, ids=False) -> dict:
""" """
Return a dict representation of the repository Return a dict representation of the repository
""" """
packages = [p.to_dict() for p in self.packages] packages = [p.to_dict() for p in self.packages]
if sort: if sort:
packages.sort(key=lambda p: p['bl_info']['name'].lower()) packages.sort(key=lambda p: p['bl_info']['name'].lower())
if ids:
for pkg in packages:
self.log.debug(pkg['url'], pkg['bl_info']['name'], self.name, self.url)
# hash may be too big for a C int
pkg['id'] = str(hash(pkg['url'] + pkg['bl_info']['name'] + self.name + self.url))
return { return {
'name': self.name, 'name': self.name,
'packages': packages, 'packages': packages,
@@ -260,10 +270,23 @@ class Repository:
""" """
Get repository attributes from a dict such as produced by `to_dict` Get repository attributes from a dict such as produced by `to_dict`
""" """
self.name = repodict.get('name', "")
self.url = repodict.get('url', "") def initialize(item, value):
self.packages = [Package(pkg) for pkg in repodict.get('packages', [])] if item is None:
self._headers = repodict.get('_headers', {}) return value
else:
return item
#Be certain to initialize everything; downloaded packagelist might contain null values
name = initialize(repodict.get('name'), "")
url = initialize(repodict.get('url'), "")
packages = initialize(repodict.get('packages'), [])
headers = initialize(repodict.get('_headers'), {})
self.name = name
self.url = url
self.packages = [Package(pkg) for pkg in packages]
self._headers = headers
@classmethod @classmethod
def from_dict(cls, repodict: dict): def from_dict(cls, repodict: dict):
@@ -466,6 +489,12 @@ def download_and_install(pipe_to_blender, package_url: str, install_path: pathli
log.exception("Failed to install package: %s", err) log.exception("Failed to install package: %s", err)
pipe_to_blender.send(InstallError(err)) pipe_to_blender.send(InstallError(err))
def _load_repo(storage_path: pathlib.Path) -> Repository:
"""Reads the stored repositories"""
repo_path = storage_path / 'repo.json'
return Repository.from_file(repo_path)
def refresh(pipe_to_blender, storage_path: pathlib.Path, repository_url: str): def refresh(pipe_to_blender, storage_path: pathlib.Path, repository_url: str):
"""Retrieves and stores the given repository""" """Retrieves and stores the given repository"""
@@ -489,10 +518,17 @@ def refresh(pipe_to_blender, storage_path: pathlib.Path, repository_url: str):
return return
repo.to_file(repo_path) # TODO: this always writes even if repo wasn't changed repo.to_file(repo_path) # TODO: this always writes even if repo wasn't changed
pipe_to_blender.send(RepositoryResult(repo.to_dict(sort=True))) pipe_to_blender.send(RepositoryResult(repo.to_dict(sort=True, ids=True)))
def load(pipe_to_blender, storage_path: pathlib.Path): def load(pipe_to_blender, storage_path: pathlib.Path):
"""Reads the stored repository""" """Reads the stored repository and sends the result to blender"""
try:
repo = _load_repo(storage_path)
pipe_to_blender.send(RepositoryResult(repo.to_dict(sort=True, ids=True)))
except BadRepository as err:
pipe_to_blender.send(SubprocError("Failed to read repository: %s" % err))
def debug_hang(): def debug_hang():
"""Hangs for an hour. For testing purposes only.""" """Hangs for an hour. For testing purposes only."""