Partial expanded view implementation
Not all metadata is correctly displayed yet
This commit is contained in:
126
bpkg/__init__.py
126
bpkg/__init__.py
@@ -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)
|
||||||
|
@@ -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."""
|
||||||
|
Reference in New Issue
Block a user