mirror of
https://github.com/gaasedelen/lighthouse
synced 2026-06-08 14:19:10 +00:00
221 lines
5.9 KiB
Python
221 lines
5.9 KiB
Python
import os
|
|
import re
|
|
import errno
|
|
import struct
|
|
import weakref
|
|
import datetime
|
|
import threading
|
|
import collections
|
|
|
|
from .python import *
|
|
|
|
BADADDR = 0xFFFFFFFFFFFFFFFF
|
|
|
|
#------------------------------------------------------------------------------
|
|
# Plugin Util
|
|
#------------------------------------------------------------------------------
|
|
|
|
PLUGIN_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
|
|
|
|
def plugin_resource(resource_name):
|
|
"""
|
|
Return the full path for a given plugin resource file.
|
|
"""
|
|
return os.path.join(
|
|
PLUGIN_PATH,
|
|
"ui",
|
|
"resources",
|
|
resource_name
|
|
)
|
|
|
|
#------------------------------------------------------------------------------
|
|
# Thread Util
|
|
#------------------------------------------------------------------------------
|
|
|
|
def is_mainthread():
|
|
"""
|
|
Return a bool that indicates if this is the main application thread.
|
|
"""
|
|
return isinstance(threading.current_thread(), threading._MainThread)
|
|
|
|
def mainthread(f):
|
|
"""
|
|
A debug decorator to ensure that a function is always called from the main thread.
|
|
"""
|
|
def wrapper(*args, **kwargs):
|
|
assert is_mainthread()
|
|
return f(*args, **kwargs)
|
|
return wrapper
|
|
|
|
def not_mainthread(f):
|
|
"""
|
|
A debug decorator to ensure that a function is never called from the main thread.
|
|
"""
|
|
def wrapper(*args, **kwargs):
|
|
assert not is_mainthread()
|
|
return f(*args, **kwargs)
|
|
return wrapper
|
|
|
|
#------------------------------------------------------------------------------
|
|
# Theme Util
|
|
#------------------------------------------------------------------------------
|
|
|
|
def swap_rgb(i):
|
|
"""
|
|
Swap RRGGBB (integer) to BBGGRR.
|
|
"""
|
|
return struct.unpack("<I", struct.pack(">I", i))[0] >> 8
|
|
|
|
def test_color_brightness(color):
|
|
"""
|
|
Test the brightness of a color.
|
|
"""
|
|
if color.lightness() > 255.0/2:
|
|
return "light"
|
|
else:
|
|
return "dark"
|
|
|
|
#------------------------------------------------------------------------------
|
|
# Python Util
|
|
#------------------------------------------------------------------------------
|
|
|
|
def makedirs(path, exists_ok=True):
|
|
"""
|
|
Make a fully qualified path.
|
|
"""
|
|
try:
|
|
os.makedirs(path)
|
|
except OSError as e:
|
|
if e.errno != errno.EEXIST:
|
|
raise e
|
|
if not exists_ok:
|
|
raise e
|
|
|
|
def chunks(l, n):
|
|
"""
|
|
Yield successive n-sized chunks from a list (l).
|
|
|
|
From http://stackoverflow.com/a/312464
|
|
"""
|
|
for i in xrange(0, len(l), n):
|
|
yield l[i:i + n]
|
|
|
|
def hex_list(items):
|
|
"""
|
|
Return a string of a python-like list, with hex numbers.
|
|
|
|
[0, 5420, 1942512] --> '[0x0, 0x152C, 0x1DA30]'
|
|
"""
|
|
return '[{}]'.format(', '.join('0x%X' % x for x in items))
|
|
|
|
def human_timestamp(timestamp):
|
|
"""
|
|
Return a human readable timestamp for a given epoch.
|
|
"""
|
|
dt = datetime.datetime.fromtimestamp(timestamp)
|
|
return dt.strftime("%b %d %Y %H:%M:%S")
|
|
|
|
def get_string_between(text, before, after):
|
|
"""
|
|
Get the string between two strings.
|
|
"""
|
|
pattern = "%s(.*)%s" % (before, after)
|
|
result = re.search(pattern, text)
|
|
if not result:
|
|
return None
|
|
return result.group(1)
|
|
|
|
#------------------------------------------------------------------------------
|
|
# Python Callback / Signals
|
|
#------------------------------------------------------------------------------
|
|
|
|
def register_callback(callback_list, callback):
|
|
"""
|
|
Register a callable function to the given callback_list.
|
|
|
|
Adapted from http://stackoverflow.com/a/21941670
|
|
"""
|
|
|
|
# create a weakref callback to an object method
|
|
try:
|
|
callback_ref = weakref.ref(callback.__func__), weakref.ref(callback.__self__)
|
|
|
|
# create a wweakref callback to a stand alone function
|
|
except AttributeError:
|
|
callback_ref = weakref.ref(callback), None
|
|
|
|
# 'register' the callback
|
|
callback_list.append(callback_ref)
|
|
return callback_ref
|
|
|
|
def notify_callback(callback_list, *args):
|
|
"""
|
|
Notify the given list of registered callbacks of an event.
|
|
|
|
The given list (callback_list) is a list of weakref'd callables
|
|
registered through the register_callback() function. To notify the
|
|
callbacks of an event, this function will simply loop through the list
|
|
and call them.
|
|
|
|
This routine self-heals by removing dead callbacks for deleted objects as
|
|
it encounters them.
|
|
|
|
Adapted from http://stackoverflow.com/a/21941670
|
|
"""
|
|
cleanup = []
|
|
|
|
#
|
|
# loop through all the registered callbacks in the given callback_list,
|
|
# notifying active callbacks, and removing dead ones.
|
|
#
|
|
|
|
for callback_ref in callback_list:
|
|
callback, obj_ref = callback_ref[0](), callback_ref[1]
|
|
|
|
#
|
|
# if the callback is an instance method, deference the instance
|
|
# (an object) first to check that it is still alive
|
|
#
|
|
|
|
if obj_ref:
|
|
obj = obj_ref()
|
|
|
|
# if the object instance is gone, mark this callback for cleanup
|
|
if obj is None:
|
|
cleanup.append(callback_ref)
|
|
continue
|
|
|
|
# call the object instance callback
|
|
try:
|
|
callback(obj, *args)
|
|
|
|
# assume a Qt cleanup/deletion occurred
|
|
except RuntimeError as e:
|
|
cleanup.append(callback_ref)
|
|
continue
|
|
|
|
# if the callback is a static method...
|
|
else:
|
|
|
|
# if the static method is deleted, mark this callback for cleanup
|
|
if callback is None:
|
|
cleanup.append(callback_ref)
|
|
continue
|
|
|
|
# call the static callback
|
|
callback(*args)
|
|
|
|
# remove the deleted callbacks
|
|
for callback_ref in cleanup:
|
|
callback_list.remove(callback_ref)
|
|
|
|
def unregister_callback(callback_list, callback_ref):
|
|
"""
|
|
Remove a previously-registered callback reference.
|
|
"""
|
|
|
|
try:
|
|
callback_list.remove(callback_ref)
|
|
except (ValueError, AttributeError):
|
|
pass
|