This commit is contained in:
yumoqing 2022-11-04 03:17:11 -04:00
parent c13dd66f05
commit 70256ae9de
3 changed files with 1337 additions and 1327 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,182 +1,193 @@
from kivy.event import EventDispatcher from kivy.event import EventDispatcher
from kivy.app import App from kivy.app import App
from kivy.factory import Factory from kivy.factory import Factory
from .threadcall import HttpClient from .threadcall import HttpClient
from .utils import absurl from .utils import absurl
from appPublic.registerfunction import RegisterFunction from appPublic.registerfunction import RegisterFunction
class DataGraber(EventDispatcher): def getUrlData(url, method='GET', params={}):
""" blocks = Factory.Blocks()
Graber format d = blocks.getUrlData(url, method=method,
{ params=params)
"widgettype":"DataGraber", return d
"options":{
"dataurl":"first", class DataGraber(EventDispatcher):
"datarfname":"second", """
"target":"third", Graber format
"params": {
"method": "widgettype":"DataGraber",
"pagging":"default false" "options":{
} "dataurl":"first",
} "datarfname":"second",
if dataurl present, the DataGraber using this dataurl to get and "target":"third",
return data "params":
else if datarfname present, it find a registered function named "method":
by 'datarfname' to return data "paging":"default false"
else if datatarget present, it find the widget and uses target }
method(default is 'getValue') to return data }
else it return None if dataurl present, the DataGraber using this dataurl to get and
""" return data
def __init__(self, **kw): else if datarfname present, it find a registered function named
super().__init__() by 'datarfname' to return data
self.options = kw else if datatarget present, it find the widget and uses target
self.register_event_type('on_success') method(default is 'getValue') to return data
self.register_event_type('on_error') else it return None
"""
def load(self, *args, **kw): def __init__(self, **kw):
ret = None super().__init__()
while True: self.options = kw
try: self.register_event_type('on_success')
dataurl = self.options.get('dataurl') self.register_event_type('on_error')
if dataurl:
ret = self.loadUrlData(*args, **kw) def load(self, *args, **kw):
break ret = None
if self.options['paging']:
rfname = self.options.get('datarfname') if kw.get('rows') is None:
if rfname: kw['rows'] = 60
ret = self.loadRFData(*args, **kw) if kw.get('page') is None:
break kw['page'] = 1
target = self.options.get('datatarget') while True:
if target: try:
ret = self.loadTargetData(*args, **kw) dataurl = self.options.get('dataurl')
break if dataurl:
except Exception as e: ret = self.loadUrlData(*args, **kw)
self.dispatch('on_error', e) break
return
if ret: rfname = self.options.get('datarfname')
self.dispatch('on_success',ret) if rfname:
else: ret = self.loadRFData(*args, **kw)
e = Exception('Not method to do load') break
self.dispatch('on_error', e) target = self.options.get('datatarget')
if target:
def loadUrlData(self, *args, **kw): ret = self.loadTargetData(*args, **kw)
dataurl = self.options.get('dataurl') break
hc = HttpClient() except Exception as e:
params = self.options.get('params',{}).copy() self.dispatch('on_error', e)
params.update(kw) return
method = self.options.get('method','GET') if ret:
d = hc(dataurl, params=params,method=method) self.dispatch('on_success',ret)
return d else:
e = Exception('Not method to do load')
def loadRFData(self, *args, **kw): self.dispatch('on_error', e)
rfname = self.options.get('datarfname')
rf = RegisterFunction() def loadUrlData(self, *args, **kw):
f = rf.get(rfname) dataurl = self.options.get('dataurl')
if not f: params = self.options.get('params',{}).copy()
return None params.update(kw)
params = self.options.get('params',{}).copy() method = self.options.get('method','GET')
params.update(kw) d = getUrlData(dataurl, method=method,
try: params=params)
d = f(**params) return d
return d
except Exception as e: def loadRFData(self, *args, **kw):
Logger.info('blocks : Exception:%s',e) rfname = self.options.get('datarfname')
print_exc() rf = RegisterFunction()
return None f = rf.get(rfname)
if not f:
def loadTargetData(self, *args, **kw): return None
target = self.options.get('datatarget') params = self.options.get('params',{}).copy()
w = Factory.Blocks.getWidgetById(target) params.update(kw)
if not w: try:
return None d = f(**params)
params = self.options.get('params',{}).copy() return d
params.update(kw) except Exception as e:
method = params.get('method', 'getValue') Logger.info('blocks : Exception:%s',e)
if not has(w, method): print_exc()
return None return None
try:
f = getattr(w, method) def loadTargetData(self, *args, **kw):
d = f() target = self.options.get('datatarget')
return d w = Factory.Blocks.getWidgetById(target)
except Exception as e: if not w:
Logger.info('blocks : Exception %s', e) return None
print_exc() params = self.options.get('params',{}).copy()
return None params.update(kw)
method = params.get('method', 'getValue')
def on_success(self,d): if not has(w, method):
pass return None
try:
def on_error(self,e): f = getattr(w, method)
pass d = f()
return d
class DataLoader(EventDispatcher): except Exception as e:
def __init__(self,data_user): Logger.info('blocks : Exception %s', e)
self.data_user = data_user print_exc()
EventDispatcher.__init__(self) return None
self.register_event_type('on_success')
self.register_event_type('on_error') def on_success(self,d):
pass
def on_success(self,d):
pass def on_error(self,e):
pass
def on_error(self,e):
pass class DataLoader(EventDispatcher):
def __init__(self,data_user):
def load(self): self.data_user = data_user
pass EventDispatcher.__init__(self)
self.register_event_type('on_success')
class HttpDataLoader(DataLoader): self.register_event_type('on_error')
def load(self, *args, **kw):
app = App.get_running_app() def on_success(self,d):
url = app.realurl(self.data_user.url) pass
method = self.data_user.method
params = self.data_user.params.copy() def on_error(self,e):
params.update({ pass
"page":self.data_user.curpage,
"rows":self.data_user.page_rows def load(self):
}) pass
hc = HttpClient()
try: class UrlDataLoader(DataLoader):
r = hc(url, method=method, params=params) def load(self, *args, **kw):
self.dispatch('on_success', r) app = App.get_running_app()
return r url = app.realurl(self.data_user.url)
except Exception as e: method = self.data_user.method
self.dispatch('on_error', e) params = self.data_user.params.copy()
params.update({
"page":self.data_user.curpage,
class ListDataLoader(DataLoader): "rows":self.data_user.page_rows
def load(self, *args, **kw): })
p = self.data_user.curpage
r = self.data_user.page_rows try:
try: r = getUrlData(url, method=method, params=params)
s = self.data_user.data[(p-1)*r:p*r] self.dispatch('on_success', r)
d = { return r
"total":len(self.data_user.data), except Exception as e:
"rows":s self.dispatch('on_error', e)
}
self.dispatch('on_success', d)
return d class ListDataLoader(DataLoader):
except Exception as e: def load(self, *args, **kw):
self.dispatch('on_error', e) p = self.data_user.curpage
r = self.data_user.page_rows
class RegisterFunctionDataLoader(DataLoader): try:
def load(self, *args, **kw): s = self.data_user.data[(p-1)*r:p*r]
rf = RegisterFunction() d = {
try: "total":len(self.data_user.data),
rfname = self.data_user.rfname "rows":s
func = rf.get(rfname) }
if func is None: self.dispatch('on_success', d)
raise Exception('%s is not a registerfunction' % rfname) return d
params = {k:v for k,v in self.user_data.params.items()} except Exception as e:
params.update({ self.dispatch('on_error', e)
"page":self.data_user.curpage,
"rows":self.data_user.page_rows class RegisterFunctionDataLoader(DataLoader):
}) def load(self, *args, **kw):
s = func(**params) rf = RegisterFunction()
self.dispatch('on_success', s) try:
return s rfname = self.data_user.rfname
except Exception as e: func = rf.get(rfname)
self.dispatch('on_error', e) if func is None:
raise Exception('%s is not a registerfunction' % rfname)
params = {k:v for k,v in self.user_data.params.items()}
params.update({
"page":self.data_user.curpage,
"rows":self.data_user.page_rows
})
s = func(**params)
self.dispatch('on_success', s)
return s
except Exception as e:
self.dispatch('on_error', e)

View File

@ -1,324 +1,324 @@
import traceback import traceback
import math import math
from kivy.logger import Logger from kivy.logger import Logger
from kivy.event import EventDispatcher from kivy.event import EventDispatcher
from kivy.uix.boxlayout import BoxLayout from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button from kivy.uix.button import Button
from kivy.clock import Clock from kivy.clock import Clock
from kivy.app import App from kivy.app import App
from functools import partial from functools import partial
from appPublic.dictObject import DictObject from appPublic.dictObject import DictObject
from appPublic.jsonConfig import getConfig from appPublic.jsonConfig import getConfig
from .baseWidget import Text, HTTPDataHandler from .baseWidget import Text, HTTPDataHandler
from .utils import CSize, absurl, alert from .utils import CSize, absurl, alert
from .form import StrSearchForm from .form import StrSearchForm
from .dataloader import HttpDataLoader from .dataloader import UrlDataLoader
from .dataloader import ListDataLoader from .dataloader import ListDataLoader
from .dataloader import RegisterFunctionDataLoader from .dataloader import RegisterFunctionDataLoader
class PagingButton(Button): class PagingButton(Button):
def __init__(self, **kw): def __init__(self, **kw):
super().__init__(**kw) super().__init__(**kw)
self.size_hint = (None,None) self.size_hint = (None,None)
self.size = CSize(2,1.8) self.size = CSize(2,1.8)
self.font_size = CSize(1) self.font_size = CSize(1)
""" """
{ {
dataurl dataurl
params params
method method
locater locater
filter filter
} }
PageLoader load data in a page size once. PageLoader load data in a page size once.
it fires two type of event it fires two type of event
'on_newbegin':fire when start a new parameters loading series 'on_newbegin':fire when start a new parameters loading series
'on_pageloaded':fire when a page data loads success 'on_pageloaded':fire when a page data loads success
""" """
class PageLoader(EventDispatcher): class PageLoader(EventDispatcher):
def __init__(self,target=None, **options): def __init__(self,target=None, **options):
self.loading = False self.loading = False
self.target = target self.target = target
self.options = options self.options = options
self.filter = None self.filter = None
if options.get('filter'): if options.get('filter'):
self.filter = StrSearchForm(**options['filter']) self.filter = StrSearchForm(**options['filter'])
self.filter.bind(on_submit=self.do_search) self.filter.bind(on_submit=self.do_search)
self.params = options.get('params',{}) self.params = options.get('params',{})
self.method = options.get('method','GET') self.method = options.get('method','GET')
self.url = options.get('dataurl') self.url = options.get('dataurl')
self.rfname = options.get('rfname') self.rfname = options.get('rfname')
self.data = options.get('data') self.data = options.get('data')
self.page_rows = options.get('page_rows',60) self.page_rows = options.get('page_rows',60)
self.total_cnt = 0 self.total_cnt = 0
self.total_page = 0 self.total_page = 0
self.curpage = 0 self.curpage = 0
self.dir = 'down' self.dir = 'down'
self.register_event_type('on_newbegin') self.register_event_type('on_newbegin')
self.register_event_type('on_pageloaded') self.register_event_type('on_pageloaded')
self.newbegin = True self.newbegin = True
if self.url: if self.url:
self.loader = HttpDataLoader(self) self.loader = UrlDataLoader(self)
elif self.rfname: elif self.rfname:
self.loader = RegisterFunctionDataLoader(self) self.loader = RegisterFunctionDataLoader(self)
elif self.data: elif self.data:
self.loader = ListDataLoader(self) self.loader = ListDataLoader(self)
else: else:
raise Exception('need a url or rfname or data') raise Exception('need a url or rfname or data')
self.loader.bind(on_success=self.show_page) self.loader.bind(on_success=self.show_page)
self.loader.bind(on_error=self.onerror) self.loader.bind(on_error=self.onerror)
def on_newbegin(self): def on_newbegin(self):
pass pass
def on_pageloaded(self,d): def on_pageloaded(self,d):
""" """
d={ d={
page: page:
data:[] data:[]
dir:'up' or 'down' dir:'up' or 'down'
} }
""" """
def do_search(self,o,params): def do_search(self,o,params):
self.newbegin = True self.newbegin = True
self.total_cnt = 0 self.total_cnt = 0
self.total_page = 0 self.total_page = 0
self.curpage = 0 self.curpage = 0
self.dir = 'down' self.dir = 'down'
self.dispatch('on_newbegin') self.dispatch('on_newbegin')
self.params.update(params) self.params.update(params)
self.loadPage(1) self.loadPage(1)
def calculateTotalPage(self): def calculateTotalPage(self):
self.total_page = math.floor(self.total_cnt / self.page_rows) self.total_page = math.floor(self.total_cnt / self.page_rows)
if self.total_cnt % self.page_rows != 0: if self.total_cnt % self.page_rows != 0:
self.total_page += 1 self.total_page += 1
def setPageRows(self,row_cnt): def setPageRows(self,row_cnt):
if row_cnt == 0: if row_cnt == 0:
return return
self.page_rows = row_cnt self.page_rows = row_cnt
if self.total_cnt != 0: if self.total_cnt != 0:
self.calculateTotalPage() self.calculateTotalPage()
def show_page(self,o,d): def show_page(self,o,d):
p = (self.curpage - 1) * self.page_rows + 1 p = (self.curpage - 1) * self.page_rows + 1
for r in d['rows']: for r in d['rows']:
r['__posInSet__'] = p r['__posInSet__'] = p
p += 1 p += 1
self.total_cnt = d['total'] self.total_cnt = d['total']
self.calculateTotalPage() self.calculateTotalPage()
d = { d = {
"page":self.curpage, "page":self.curpage,
"dir":self.dir, "dir":self.dir,
"data":d['rows'] "data":d['rows']
} }
self.dispatch('on_pageloaded',d) self.dispatch('on_pageloaded',d)
self.loading = False self.loading = False
def onerror(self,o,e): def onerror(self,o,e):
traceback.print_exc() traceback.print_exc()
alert(str(e),title='alert') alert(str(e),title='alert')
self.loading = False self.loading = False
def loadNextPage(self): def loadNextPage(self):
if self.loading: if self.loading:
print('is loading, return') print('is loading, return')
return return
if self.total_page > 0 and self.curpage >=self.total_page: if self.total_page > 0 and self.curpage >=self.total_page:
return return
p = self.curpage + 1 p = self.curpage + 1
self.loadPage(p) self.loadPage(p)
def loadPreviousPage(self): def loadPreviousPage(self):
if self.loading: if self.loading:
print('is loading, return') print('is loading, return')
return return
if self.curpage <= 1: if self.curpage <= 1:
return return
p = self.curpage - 1 p = self.curpage - 1
self.loadPage(p) self.loadPage(p)
def loadPage(self,p): def loadPage(self,p):
if p == self.curpage: if p == self.curpage:
return return
if self.loading: if self.loading:
print('is loading, return') print('is loading, return')
return return
self.loading = True self.loading = True
print(f'loading {p} page, {self.curpage}') print(f'loading {p} page, {self.curpage}')
if self.curpage > p: if self.curpage > p:
self.dir = 'up' self.dir = 'up'
else: else:
self.dir = 'down' self.dir = 'down'
self.curpage = p self.curpage = p
self.loader.load() self.loader.load()
""" """
{ {
adder, adder,
remover remover
target, target,
locater, locater,
dataurl, dataurl,
params, params,
method, method,
filter filter
} }
events: events:
'on_deletepage': erase 'on_deletepage': erase
""" """
class RelatedLoader(PageLoader): class RelatedLoader(PageLoader):
def __init__(self, **options): def __init__(self, **options):
super().__init__(**options) super().__init__(**options)
self.objectPages = {} self.objectPages = {}
self.totalObj = 0 self.totalObj = 0
self.MaxbufferPage = 3 self.MaxbufferPage = 3
self.locater = 1/self.MaxbufferPage self.locater = 1/self.MaxbufferPage
if self.filter: if self.filter:
self.widget = self.filter self.widget = self.filter
else: else:
self.widget = None self.widget = None
self.register_event_type('on_deletepage') self.register_event_type('on_deletepage')
def do_search(self,o,params): def do_search(self,o,params):
self.objectPages = {} self.objectPages = {}
self.totalObj = 0 self.totalObj = 0
self.MaxbufferPage = 3 self.MaxbufferPage = 3
self.locater = 1/self.MaxbufferPage self.locater = 1/self.MaxbufferPage
super().do_search(o, params) super().do_search(o, params)
def getLocater(self): def getLocater(self):
if self.newbegin: if self.newbegin:
self.newbegin = False self.newbegin = False
return 1 return 1
x = 1 / self.MaxbufferPage x = 1 / self.MaxbufferPage
if self.dir != 'down': if self.dir != 'down':
x = 1 - x x = 1 - x
return x return x
def on_deletepage(self,d): def on_deletepage(self,d):
pass pass
def setPageRows(self,row_cnt): def setPageRows(self,row_cnt):
if self.total_cnt != 0: if self.total_cnt != 0:
self.calculateTotalPage() self.calculateTotalPage()
def doBufferMaintain(self): def doBufferMaintain(self):
siz = len(self.objectPages.keys()) siz = len(self.objectPages.keys())
if siz >= self.MaxbufferPage: if siz >= self.MaxbufferPage:
if self.dir == 'up': if self.dir == 'up':
p = max(self.objectPages.keys()) p = max(self.objectPages.keys())
else: else:
p = min(self.objectPages.keys()) p = min(self.objectPages.keys())
self.deleteBuffer(p) self.deleteBuffer(p)
def deleteBuffer(self,page): def deleteBuffer(self,page):
d = self.objectPages[page] d = self.objectPages[page]
self.dispatch('on_deletepage',d) self.dispatch('on_deletepage',d)
self.totalObj -= len(self.objectPages[page]) self.totalObj -= len(self.objectPages[page])
del self.objectPages[page] del self.objectPages[page]
def bufferObjects(self,page,objects): def bufferObjects(self,page,objects):
self.objectPages[page] = objects self.objectPages[page] = objects
def show_page(self,o,data): def show_page(self,o,data):
if self.objectPages.get(self.curpage): if self.objectPages.get(self.curpage):
self.deleteBuffer(self.curpage) self.deleteBuffer(self.curpage)
else: else:
self.doBufferMaintain() self.doBufferMaintain()
self.totalObj += len(data['rows']) self.totalObj += len(data['rows'])
super().show_page(o,data) super().show_page(o,data)
def loadPreviousPage(self): def loadPreviousPage(self):
pages = self.objectPages.keys() pages = self.objectPages.keys()
if len(pages) < 1: if len(pages) < 1:
return return
page = min(pages) page = min(pages)
if page <= 1: if page <= 1:
return return
page -= 1 page -= 1
self.loadPage(page) self.loadPage(page)
def loadNextPage(self): def loadNextPage(self):
pages = self.objectPages.keys() pages = self.objectPages.keys()
if len(pages) == 0: if len(pages) == 0:
return return
page = max(pages) page = max(pages)
if page>=self.total_page: if page>=self.total_page:
return return
page += 1 page += 1
self.loadPage(page) self.loadPage(page)
""" """
{ {
adder, adder,
clearer clearer
target, target,
dataurl dataurl
params, params,
method method
} }
""" """
class Paging(PageLoader): class Paging(PageLoader):
def __init__(self,**options): def __init__(self,**options):
PageLoader.__init__(self,**options) PageLoader.__init__(self,**options)
self.target = options.get('target') self.target = options.get('target')
self.init() self.init()
def init(self): def init(self):
kwargs = {} kwargs = {}
kwargs['size_hint_y'] = None kwargs['size_hint_y'] = None
kwargs['height'] = CSize(2) kwargs['height'] = CSize(2)
kwargs['orientation'] = 'horizontal' kwargs['orientation'] = 'horizontal'
kwargs['spacing'] = CSize(1) kwargs['spacing'] = CSize(1)
self.widget = BoxLayout(**kwargs) self.widget = BoxLayout(**kwargs)
self.b_f = PagingButton(text="|<") self.b_f = PagingButton(text="|<")
self.b_p = PagingButton(text="<") self.b_p = PagingButton(text="<")
self.b_n = PagingButton(text=">") self.b_n = PagingButton(text=">")
self.b_l = PagingButton(text=">|") self.b_l = PagingButton(text=">|")
self.b_f.bind(on_press=self.loadFirstPage) self.b_f.bind(on_press=self.loadFirstPage)
self.b_p.bind(on_press=self.loadPreviousPage) self.b_p.bind(on_press=self.loadPreviousPage)
self.b_n.bind(on_press=self.loadNextPage) self.b_n.bind(on_press=self.loadNextPage)
self.b_l.bind(on_press=self.loadLastPage) self.b_l.bind(on_press=self.loadLastPage)
self.widget.add_widget(self.b_f) self.widget.add_widget(self.b_f)
self.widget.add_widget(self.b_p) self.widget.add_widget(self.b_p)
self.widget.add_widget(self.b_n) self.widget.add_widget(self.b_n)
self.widget.add_widget(self.b_l) self.widget.add_widget(self.b_l)
if self.filter: if self.filter:
self.widget.add_widget(self.filter) self.widget.add_widget(self.filter)
def loadFirstPage(self,o=None): def loadFirstPage(self,o=None):
if self.curpage == 1: if self.curpage == 1:
return return
self.loadPage(1) self.loadPage(1)
def loadPreviousPage(self,o=None): def loadPreviousPage(self,o=None):
if self.curpage < 2: if self.curpage < 2:
return return
self.loadPage(self.curpage-1) self.loadPage(self.curpage-1)
def loadNextPage(self,o=None): def loadNextPage(self,o=None):
if self.curpage >= self.total_page: if self.curpage >= self.total_page:
return return
self.loadPage(self.curpage+1) self.loadPage(self.curpage+1)
def loadLastPage(self,o=None): def loadLastPage(self,o=None):
if self.curpage >= self.total_page: if self.curpage >= self.total_page:
return return
self.loadPage(self.total_page) self.loadPage(self.total_page)