Compare commits

..

10 Commits

Author SHA1 Message Date
yumoqing
9e2b5db1a6 bugfix 2023-10-26 17:55:34 +08:00
yumoqing
01442309d9 bugfix 2023-10-13 15:53:33 +08:00
yumoqing
f1e493ca8e bugfix 2023-10-12 18:29:15 +08:00
yumoqing
313274b376 bugfix 2023-10-12 15:49:31 +08:00
yumoqing
9e60443e79 bugfix 2023-10-09 13:52:30 +08:00
yumoqing
263636779b bugfix 2022-12-16 18:14:59 +08:00
yumoqing
8e9719ac57 bugfix 2022-12-05 16:37:59 +08:00
yumoqing
2532efa9f2 bugfix 2022-11-26 15:16:43 +08:00
yumoqing
ef5c160c40 bugfix 2022-11-26 14:59:20 +08:00
yumoqing
c3ef3a99b3 bugfix 2022-11-26 13:31:13 +08:00
254 changed files with 1306 additions and 1516 deletions

0
README.md Normal file → Executable file
View File

0
docs/blocks.md Normal file → Executable file
View File

0
docs/changelog.md Normal file → Executable file
View File

0
docs/cn/binds.md Normal file → Executable file
View File

0
docs/cn/cdf.md Normal file → Executable file
View File

0
docs/cn/index.md Normal file → Executable file
View File

0
docs/cn/intro.md Normal file → Executable file
View File

0
docs/en/box.md Normal file → Executable file
View File

0
docs/imgs/hello_window.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

0
github-speed-up.md Normal file → Executable file
View File

0
kivyblocks/__init__.py Normal file → Executable file
View File

0
kivyblocks/android_rotation.py Normal file → Executable file
View File

0
kivyblocks/anz/__init__.py Normal file → Executable file
View File

0
kivyblocks/anz/bluetooth.py Normal file → Executable file
View File

0
kivyblocks/aplayer.py Normal file → Executable file
View File

0
kivyblocks/backendfunction.py Normal file → Executable file
View File

47
kivyblocks/baseWidget.py Normal file → Executable file
View File

@ -75,7 +75,7 @@ from .threadcall import HttpClient
from .i18n import I18n from .i18n import I18n
from .widget_css import WidgetCSS from .widget_css import WidgetCSS
from .ready import WidgetReady from .ready import WidgetReady
from .utils import CSize, SUPER from .utils import CSize
from .swipebehavior import SwipeBehavior from .swipebehavior import SwipeBehavior
from .widgetExt.inputext import MyDropDown from .widgetExt.inputext import MyDropDown
@ -89,16 +89,6 @@ font_names = {
'title1':resource_find('Alimama_ShuHeiTi_Bold.ttf') 'title1':resource_find('Alimama_ShuHeiTi_Bold.ttf')
} }
font_sizes = {
'text':CSize(1),
'title6':CSize(1.1),
'title5':CSize(1.3),
'title4':CSize(1.5),
'title3':CSize(1.7),
'title2':CSize(1.9),
'title1':CSize(2.1)
}
if platform == 'android': if platform == 'android':
from .widgetExt.phonebutton import PhoneButton from .widgetExt.phonebutton import PhoneButton
from .widgetExt.androidwebview import AWebView from .widgetExt.androidwebview import AWebView
@ -140,7 +130,7 @@ def ScatterBox(WidgetCSS, WidgetReady, ScatterLayout):
class Box(WidgetCSS, WidgetReady, BoxLayout): class Box(WidgetCSS, WidgetReady, BoxLayout):
def __init__(self, **kw): def __init__(self, **kw):
try: try:
SUPER(Box, self, kw) super(Box, self).__init__(**kw)
except Exception as e: except Exception as e:
print('Box(',kw,') Error') print('Box(',kw,') Error')
raise e raise e
@ -157,17 +147,17 @@ class VBox(Box):
Box.__init__(self, **kw) Box.__init__(self, **kw)
class SwipeBox(SwipeBehavior, Box): class SwipeBox(SwipeBehavior, Box):
def __init__(self, **kw): pass
SUPER(SwipeBox, self, kw)
class Text(Label): class Text(Label):
lang=StringProperty('') lang=StringProperty('')
otext = StringProperty('') otext = StringProperty('')
def __init__(self,i18n=False, texttype='text', wrap=False, def __init__(self,i18n=False, texttype='text', wrap=False, rate=1,
fgcolor=None, **kw): fgcolor=None, **kw):
fontsize = font_sizes.get(texttype) app = App.get_running_app()
self.rate = 1
fontsize = app.get_font_size(texttype) * self.rate
fontname = font_names.get(texttype) fontname = font_names.get(texttype)
self._i18n = i18n self._i18n = i18n
self.i18n = I18n() self.i18n = I18n()
@ -182,7 +172,9 @@ class Text(Label):
if not kwargs.get('text'): if not kwargs.get('text'):
kwargs['text'] = kwargs.get('otext','') kwargs['text'] = kwargs.get('otext','')
SUPER(Text, self, kwargs) super(Text, self).__init__(**kwargs)
app.bind(font_size=self.reset_font_size)
# self.bind(texture_size=self.setter('size'))
if self._i18n: if self._i18n:
self.i18n.addI18nWidget(self) self.i18n.addI18nWidget(self)
if self.wrap: if self.wrap:
@ -192,6 +184,9 @@ class Text(Label):
if self.bgcolor: if self.bgcolor:
self.color = self.bgcolor self.color = self.bgcolor
def reset_font_size(self, app, fsize):
self.font_size = fsize * self.rate
def resize(self, *args): def resize(self, *args):
if not self.size_hint_y: if not self.size_hint_y:
ps = [0,0,0,0] ps = [0,0,0,0]
@ -277,6 +272,7 @@ class Modal(VBox):
self._target = None self._target = None
super(Modal, self).__init__(**kw) super(Modal, self).__init__(**kw)
self.set_size_position() self.set_size_position()
print('size_hint=', self.size_hint, kw)
self._target.bind(size=self.set_size_position) self._target.bind(size=self.set_size_position)
self.register_event_type('on_open') self.register_event_type('on_open')
self.register_event_type('on_pre_open') self.register_event_type('on_pre_open')
@ -299,7 +295,7 @@ class Modal(VBox):
return super().on_touch_down(touch) return super().on_touch_down(touch)
def on_target(self): def on_target(self, o, target):
w = Window w = Window
if self.target is not None: if self.target is not None:
w = Factory.Blocks.getWidgetById(self.target) w = Factory.Blocks.getWidgetById(self.target)
@ -324,9 +320,9 @@ class Modal(VBox):
self.width = self.size_hint_x * self._target.width self.width = self.size_hint_x * self._target.width
if self.size_hint_y: if self.size_hint_y:
self.height = self.size_hint_y * self._target.height self.height = self.size_hint_y * self._target.height
print(self.width, self.height, print("size with target:", self.width, self.height,
self.size_hint_x, self.size_hint_y, self.size_hint, self.size_hint,
self._target.size "target size=", self._target.size
) )
self.set_modal_position() self.set_modal_position()
@ -343,7 +339,7 @@ class Modal(VBox):
x = 0 x = 0
if yn == 'c': if yn == 'c':
y = (self._target.height - self.height) / 2 y = (self._target.height - self.height) / 2
elif yn == 't': elif yn == 'b':
y = self._target.height - self.height y = self._target.height - self.height
if y < 0: if y < 0:
y = 0 y = 0
@ -351,6 +347,9 @@ class Modal(VBox):
self.pos = x, y self.pos = x, y
else: else:
self.pos = self._target.pos[0] + x, self._target.pos[1] + y self.pos = self._target.pos[0] + x, self._target.pos[1] + y
Mx = Window.width
My = Window.height
self.pos_hint = {'x':self.pos[0]/Mx, 'y':self.pos[1]/My}
def open(self): def open(self):
if self.parent: if self.parent:
@ -389,7 +388,7 @@ class TimedModal(Modal):
show_time = NumericProperty(0) show_time = NumericProperty(0)
def __init__(self, **kw): def __init__(self, **kw):
self.time_task = None self.time_task = None
SUPER(TimedModal, self, kw) super(TimedModal, self).__init__(**kw)
def open(self, *args, **kw): def open(self, *args, **kw):
if self.time_task is not None: if self.time_task is not None:

0
kivyblocks/bgcolorbehavior.py Normal file → Executable file
View File

0
kivyblocks/block_test.py Normal file → Executable file
View File

25
kivyblocks/blocks.py Normal file → Executable file
View File

@ -204,7 +204,7 @@ x = ClassX{klass_cnt}()
return None return None
if url.startswith('file://'): if url.startswith('file://'):
return self.script.dispatch(url, **params) return self.script.dispatch(url, params)
elif url.startswith('http://') or url.startswith('https://'): elif url.startswith('http://') or url.startswith('https://'):
try: try:
hc = HttpClient() hc = HttpClient()
@ -214,7 +214,14 @@ x = ClassX{klass_cnt}()
print_exc() print_exc()
if errback: if errback:
return errback(None,e) return errback(None,e)
return None return {
"widgettype":"Text",
"options":{
"text":f"{url=} error",
"wrap":True,
"halign":"left"
}
}
else: else:
config = getConfig() config = getConfig()
url = config.uihome + url url = config.uihome + url
@ -727,7 +734,7 @@ x = ClassX{klass_cnt}()
print('Block3: desc must be a dict object not None') print('Block3: desc must be a dict object not None')
return None return None
w = doit(desc) w = doit(desc)
print('widgetBuild():w=', w) # print('widgetBuild():w=', w)
return w return w
@classmethod @classmethod
@ -781,8 +788,16 @@ x = ClassX{klass_cnt}()
return _find_widget(name, return _find_widget(name,
from_widget=from_widget.parent, from_widget=from_widget.parent,
dir=dir) dir=dir)
Logger.info('Block:_find_widget(), %s, %s %s return None', wid = None
name, from_widget.__class__.__name__, dir) if hasattr(from_widget, 'widget_id'):
wid = getattr(from_widget, 'widget_id')
if wid == 'channel_list':
print('channel_list=', from_widget.__class__.__name__, 'children cnt=', len(from_widget.children))
for c in children:
cid = None
if hasattr(c, 'widget_id'):
cid = getattr(c, 'widget_id')
print('channel_list children:', c.__class__.__name__, cid)
return None return None
def find_widget(step, from_widget): def find_widget(step, from_widget):

51
kivyblocks/blocksapp.py Normal file → Executable file
View File

@ -12,6 +12,7 @@ from appPublic.folderUtils import ProgramPath
from appPublic.uniqueID import getID from appPublic.uniqueID import getID
from appPublic.rsawrap import RSA from appPublic.rsawrap import RSA
from kivy.properties import NumericProperty
from kivy.factory import Factory from kivy.factory import Factory
from kivy.metrics import sp,dp,mm from kivy.metrics import sp,dp,mm
from kivy.core.window import WindowBase, Window from kivy.core.window import WindowBase, Window
@ -48,6 +49,7 @@ signal.signal(signal.SIGINT, signal_handler)
class BlocksApp(App): class BlocksApp(App):
font_size = NumericProperty(24)
def get_rotation(self): def get_rotation(self):
return get_rotation() return get_rotation()
@ -60,10 +62,13 @@ class BlocksApp(App):
with codecs.open(config.css.css_filename, 'r', 'utf-8') as f: with codecs.open(config.css.css_filename, 'r', 'utf-8') as f:
d = json.load(f) d = json.load(f)
self.buildCsses(d) self.buildCsses(d)
if config.css.css_url: try:
hc = HttpClient() if config.css.css_url:
d = hc.get(self.realurl(config.css.css_url)) hc = HttpClient()
self.buildCsses(d) d = hc.get(self.realurl(config.css.css_url))
self.buildCsses(d)
except:
pass
def on_rotate(self,*largs): def on_rotate(self,*largs):
self.current_rotation = Window.rotation self.current_rotation = Window.rotation
@ -75,21 +80,47 @@ class BlocksApp(App):
if isinstance(v,dict): if isinstance(v,dict):
register_css(k,v) register_css(k,v)
def set_fontsize(self, x):
self.font_size = x
def get_font_size(self, ttype='text'):
text_fontrates = {
'text':1,
'title6':1.1,
'title5':1.3,
'title4':1.5,
'title3':1.7,
'title2':1.9,
'title1':2.1
}
v = text_fontrates.get(ttype, 'text')
return v * self.font_size
def build(self): def build(self):
i18n = I18n() tl = Label(text='test')
self.font_size = tl.font_size
print('##################app_font_size=', self.font_size)
config = getConfig()
self.workers = Workers(maxworkers=config.maxworkers or 80)
self.workers.start()
try:
i18n = I18n()
except:
i18n = None
self.platform = platform self.platform = platform
self.is_desktop = platform in ['win', 'linux', 'macosx'] self.is_desktop = platform in ['win', 'linux', 'macosx']
config = getConfig() self.default_params = {}
if config.default_params:
self.default_params.update(config.default_params)
self.public_headers = { self.public_headers = {
"client_uuid":getID(),
"platform":self.platform "platform":self.platform
} }
# Window.borderless = True # Window.borderless = True
print('Window.dpi=', Window.dpi, 'Metrics.dpi=', Metrics.dpi)
Window.bind(on_request_close=self.on_close) Window.bind(on_request_close=self.on_close)
Window.bind(on_rotate=self.on_rotate) Window.bind(on_rotate=self.on_rotate)
Window.bind(size=self.device_info) Window.bind(size=self.device_info)
self.workers = Workers(maxworkers=config.maxworkers or 80)
self.workers.start()
self.load_csses() self.load_csses()
self.running = True self.running = True
if config.root: if config.root:
@ -163,7 +194,7 @@ class BlocksApp(App):
} }
self.public_headers.update(device) self.public_headers.update(device)
def on_close(self, *args): def on_close(self, *args, **kwargs):
self.workers.running = False self.workers.running = False
return False return False

14
kivyblocks/boxViewer.py Normal file → Executable file
View File

@ -29,7 +29,7 @@ from kivy.graphics import Fbo, Color, Rectangle
from kivy.properties import NumericProperty, StringProperty, DictProperty from kivy.properties import NumericProperty, StringProperty, DictProperty
from .responsivelayout import VResponsiveLayout from .responsivelayout import VResponsiveLayout
from .toolbar import Toolbar from .toolbar import Toolbar
from .paging import Paging, RelatedLoader from .paging import RelatedLoader
from .utils import CSize, SUPER from .utils import CSize, SUPER
from .ready import WidgetReady from .ready import WidgetReady
from .baseWidget import VBox from .baseWidget import VBox
@ -122,15 +122,9 @@ class BoxViewer(VBox):
idx = data['idx'] idx = data['idx']
widgets = data['widgets'] widgets = data['widgets']
self._fbo = Fbo(size=self.size) with self.fboContext():
with self._fbo: for r in recs:
self._background_color = Color(0,0,0,1) self.showObject(widgets, r, index=idx)
self._background_rect = Rectangle(size=self.size)
for r in recs:
self.showObject(widgets, r, index=idx)
with self.canvas:
self._fbo_rect = Rectangle(size=self.size,
texture=self._fbo.texture)
self.subwidgets += widgets self.subwidgets += widgets

0
kivyblocks/circle_progress.py Normal file → Executable file
View File

41
kivyblocks/clickable.py Normal file → Executable file
View File

@ -3,6 +3,12 @@ from kivy.logger import Logger
from kivy.uix.behaviors import TouchRippleButtonBehavior from kivy.uix.behaviors import TouchRippleButtonBehavior
from kivy.graphics import Color, Rectangle from kivy.graphics import Color, Rectangle
from kivy.uix.boxlayout import BoxLayout from kivy.uix.boxlayout import BoxLayout
from kivy.uix.anchorlayout import AnchorLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.relativelayout import RelativeLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.scatterlayout import ScatterLayout
from kivy.uix.stacklayout import StackLayout
from kivy.factory import Factory from kivy.factory import Factory
from kivy.uix.image import AsyncImage from kivy.uix.image import AsyncImage
from kivy.properties import NumericProperty, DictProperty, \ from kivy.properties import NumericProperty, DictProperty, \
@ -395,6 +401,34 @@ def build_cmdbox_view(desc, rec=None):
x.setValue(vd) x.setValue(vd)
return x return x
class PressableAnchorLayout(TouchRippleButtonBehavior, AnchorLayout):
def on_press(self, o=None, d=None):
pass
class PressableBoxLayout(TouchRippleButtonBehavior, BoxLayout):
def on_press(self, o=None, d=None):
pass
class PressableFloatLayout(TouchRippleButtonBehavior, FloatLayout):
def on_press(self, o=None, d=None):
pass
class PressableRelativeLayout(TouchRippleButtonBehavior, RelativeLayout):
def on_press(self, o=None, d=None):
pass
class PressableGridLayout(TouchRippleButtonBehavior, GridLayout):
def on_press(self, o=None, d=None):
pass
class PressableScatterLayout(TouchRippleButtonBehavior, ScatterLayout):
def on_press(self, o=None, d=None):
pass
class PressableStackLayout(TouchRippleButtonBehavior, StackLayout):
def on_press(self, o=None, d=None):
pass
UiFactory.register('checkbox', build_checkbox, build_checkbox) UiFactory.register('checkbox', build_checkbox, build_checkbox)
UiFactory.register('cmdbox', build_cmdbox_view, build_cmdbox_view) UiFactory.register('cmdbox', build_cmdbox_view, build_cmdbox_view)
@ -409,3 +443,10 @@ r('ToggleText',ToggleText)
r('ToggleIconText',ToggleIconText) r('ToggleIconText',ToggleIconText)
r('ClickableImage',ClickableImage) r('ClickableImage',ClickableImage)
r('ToggleImage',ToggleImage) r('ToggleImage',ToggleImage)
r('PressableAnchorLayout',PressableAnchorLayout)
r('PressableBoxLayout',PressableBoxLayout)
r('PressableFloatLayout',PressableFloatLayout)
r('PressableRelativeLayout',PressableRelativeLayout)
r('PressableGridLayout',PressableGridLayout)
r('PressableScatterLayout',PressableScatterLayout)
r('PressableStackLayout',PressableStackLayout)

0
kivyblocks/color_definitions.py Normal file → Executable file
View File

0
kivyblocks/colorcalc.py Normal file → Executable file
View File

0
kivyblocks/command_action.py Normal file → Executable file
View File

146
kivyblocks/container.py Normal file
View File

@ -0,0 +1,146 @@
# container is ScrollView with a dataloader
import json
from appPublic.myTE import MyTemplateEngine
from kivy.uix.scrollview import ScrollView
from kivy.properties import DictProperty, ListProperty, BooleanProperty, StringProperty, NumericProperty
from kivy.clock import Clock
from kivyblocks.blocks import Blocks
from kivyblocks.paging import RelatedLoader
from kivyblocks.widget_css import WidgetCSS
class LayoutBuildFailed(Exception):
def __init__(self, desc):
self.desc = desc
def __str__(self):
return str(self.desc)
def __expr__(self):
return str(self)
class Container(WidgetCSS, ScrollView):
"""
"loader":{
"page":1,
"rows":60,
"dataurl":"eeee",
"params":{
k:v
}
},
"""
idField = StringProperty('id')
loader = DictProperty({})
data = ListProperty(None)
layout = DictProperty({})
viewer = DictProperty({})
min_threhold = NumericProperty(0.01)
max_htrehold = NumericProperty(0.99)
extend_x = BooleanProperty(False)
content = None
def __init__(self, **kw):
self.dataloader = None
self.engine = MyTemplateEngine('.')
self.id_widget = {}
super(Container, self).__init__(**kw)
self.content = Blocks().widgetBuild(self.layout)
if not self.content:
raise LayoutBuildFailed
if self.do_scroll_x:
self.content.bind(minimum_width=self.content.setter('width'))
if self.do_scroll_y:
self.content.bind(minimum_height=self.content.setter('height'))
self.add_widget(self.content)
self.viewer_tmpl = json.dumps(self.viewer)
self.bind(on_scroll_stop = self.on_scrollstop)
if self.data:
d = {
"dir":"down",
"rows":self.data,
"total":len(self.data)
}
self.add_page(d)
if self.loader:
self.dataloader = RelatedLoader(target=self, **self.loader)
self.dataloader.bind(on_deletepage=self.delete_page)
self.dataloader.bind(on_pageloaded=self.add_page)
self.dataloader.bind(on_newbegin=self.clear_records)
Clock.schedule_once(self.loadData, 0.5)
def print_info(self, *args):
print(f"{self.scroll_distance=}, {self.scroll_timeout=}, {self.do_scroll_x=} {self.do_scroll_y=}, {self.scroll_x=}, {self.scroll_y=}, {self.content.size=}")
def parse_viewer(self, rec):
return json.loads(self.engine.renders(self.viewer_tmpl, rec))
def loadData(self, *args, **kw):
kw['page'] = 1
self.dataloader.do_search(None,kw)
def add_record(self, rec, tail=True):
desc = self.parse_viewer(rec)
w = Blocks().widgetBuild(desc)
if w:
idx = 0
if not tail:
idx = -1
id = rec.get(self.idField)
self.id_widget[id] = w
self.content.add_widget(w, index=idx)
else:
print(f'create widget error {self.viewer_tmpl=}, {rec=}')
def delete_record(self, rec):
id = rec.get(self.idField)
w = self.id_widget.get(id)
if w:
self.content.remove_widget(w)
del self.id_widget[id]
def delete_page(self, o, d):
# print(f'delete_page():{o=}, {d=}')
for r in d:
self.delete_record(r)
def add_page(self, o, d):
# print(f'add_page():{o=},{d=}')
dir = d.get('dir', 'down')
recs = d.get('data', [])
tail = True
if dir != 'down':
tail = False
recs.reverse()
for r in recs:
self.add_record(r, tail=tail)
if self.extend_x:
self.scroll_x = d['locator']
else:
self.scroll_y = d['locator']
def clear_records(self, o):
# print(f'clear_records():{o=}')
self.content.clear_widgets()
self.id_Widget = {}
def on_scrollstop(self, o, d=None):
if self.dataloader is None:
return
if self.extend_x:
if self.scroll_x < self.min_threhold:
self.dataloader.loadNextPage()
if self.scroll_x > self.max_htrehold:
self.dataloader.loadPreviousPage()
print('return here ...')
return
if self.dataloader.loading:
print('loading is True')
return
if self.scroll_y < self.min_threhold:
print('load next page ...')
self.dataloader.loadNextPage()
if self.scroll_y > self.max_htrehold:
print('load previous page ...')
self.dataloader.loadPreviousPage()

0
kivyblocks/dataloader.py Normal file → Executable file
View File

0
kivyblocks/date_picker.py Normal file → Executable file
View File

0
kivyblocks/dateinput.py Normal file → Executable file
View File

1
kivyblocks/defaultimage.py Normal file → Executable file
View File

@ -1,3 +1,4 @@
import os
from kivy.uix.image import AsyncImage from kivy.uix.image import AsyncImage
from kivy.factory import Factory from kivy.factory import Factory
from kivy.properties import StringProperty from kivy.properties import StringProperty

84
kivyblocks/dg.py Normal file → Executable file
View File

@ -10,7 +10,6 @@ from kivy.uix.gridlayout import GridLayout
from kivy.uix.boxlayout import BoxLayout from kivy.uix.boxlayout import BoxLayout
from kivy.uix.scrollview import ScrollView from kivy.uix.scrollview import ScrollView
from kivy.uix.label import Label from kivy.uix.label import Label
from kivy.graphics import Fbo
from kivy.uix.button import ButtonBehavior from kivy.uix.button import ButtonBehavior
from kivy.clock import Clock from kivy.clock import Clock
from kivy.properties import BooleanProperty, StringProperty, \ from kivy.properties import BooleanProperty, StringProperty, \
@ -25,9 +24,9 @@ from appPublic.uniqueID import getID
from appPublic.myTE import string_template_render from appPublic.myTE import string_template_render
from .utils import * from .utils import *
from .baseWidget import Text, HBox, VBox, Running from .baseWidget import Text, HBox, VBox
from .scrollpanel import ScrollPanel from .scrollpanel import ScrollPanel
from .paging import Paging, RelatedLoader from .paging import RelatedLoader
from .ready import WidgetReady from .ready import WidgetReady
from .toolbar import Toolbar from .toolbar import Toolbar
from .bgcolorbehavior import BGColorBehavior from .bgcolorbehavior import BGColorBehavior
@ -56,17 +55,19 @@ class Cell(ButtonBehavior, WidgetCSS, BoxLayout):
""" """
self.desc = desc self.desc = desc
self.row = row self.row = row
self.part = self.row.part width = self.desc['width']
self.datagrid = self.part.datagrid height = self.row.part.datagrid.rowHeight()
# print(f'Cell:{width=}, {height=},value={desc["value"]}')
super().__init__(size_hint=(None,None), super().__init__(size_hint=(None,None),
width = self.desc['width'], width=width,
height = self.row.part.datagrid.rowHeight() bgcolor=[0.1,0.5,0.5],
height=height
) )
self.csscls=self.row.part.datagrid.row_normal_css self.csscls=self.row.part.datagrid.row_normal_css
if self.row.header: if self.row.header:
self.csscls=self.row.part.datagrid.header_css self.csscls=self.row.part.datagrid.header_css
if desc['header']: if desc['header']:
bl = Text(i18n=True, otext=str(desc['value']), bl = Text(i18n=True, text=str(desc['value']),
font_size=CSize(1),wrap=True, font_size=CSize(1),wrap=True,
halign='left', valign='middle' halign='left', valign='middle'
) )
@ -74,14 +75,6 @@ class Cell(ButtonBehavior, WidgetCSS, BoxLayout):
else: else:
self.cell_type = 'data' self.cell_type = 'data'
bl = UiFactory.build_view_widget(desc,self.row.row_data) bl = UiFactory.build_view_widget(desc,self.row.row_data)
if self.row.header and desc['name'] == '_checkable_action_':
id = self.row.row_data[idfield]
if self.row.part.datagrid.is_checked(id):
bl.setValue(True)
else:
bl.setValue(False)
bl.bind(select_state=self.row.checkable_action)
self.colume_name = desc['name'] self.colume_name = desc['name']
if bl: if bl:
self.add_widget(bl) self.add_widget(bl)
@ -99,7 +92,6 @@ class Row(BoxLayout):
""" """
self.part = part self.part = part
self.datagrid = self.part.datagrid
self.header = header self.header = header
self.row_data = data self.row_data = data
self.row_id = None self.row_id = None
@ -114,9 +106,6 @@ class Row(BoxLayout):
self.height = self.part.datagrid.rowHeight() self.height = self.part.datagrid.rowHeight()
self.init(0) self.init(0)
def checkable_action(self, o, *args):
self.datagrid.set_checked_rows(self.row_id, o.select_state)
def on_row_press(self, *args): def on_row_press(self, *args):
pass pass
@ -162,6 +151,7 @@ class Header(WidgetReady, ScrollPanel):
for i,f in enumerate(rd) ] for i,f in enumerate(rd) ]
self.header = Row(self.part,rd,header=True) self.header = Row(self.part,rd,header=True)
self.add_widget(self.header) self.add_widget(self.header)
self.size_hint_y = None
self.height = self.header.height self.height = self.header.height
class Body(WidgetReady, ScrollPanel): class Body(WidgetReady, ScrollPanel):
@ -327,7 +317,6 @@ class DataGrid(VBox):
] ]
} }
""" """
checkable = BooleanProperty(False)
row_selected = BooleanProperty(False) row_selected = BooleanProperty(False)
row_normal_css = StringProperty('default') row_normal_css = StringProperty('default')
row_selected_css = StringProperty('default') row_selected_css = StringProperty('default')
@ -341,16 +330,6 @@ class DataGrid(VBox):
fields = ListProperty(None) fields = ListProperty(None)
tailer = DictProperty(None) tailer = DictProperty(None)
def __init__(self,**options): def __init__(self,**options):
if self.checkable:
self.fields.insert(0, {
"name":"_checkable_action_",
"label":" ",
"type":"checkbox",
"width":CSize(2),
"freeze_flag":True
})
self.checked_rows = []
self.select_rowid = None self.select_rowid = None
self.rowheight = None self.rowheight = None
self.on_sizeTask = None self.on_sizeTask = None
@ -388,16 +367,11 @@ class DataGrid(VBox):
self.tailer_widgets = {} self.tailer_widgets = {}
self.build_tailer(self.tailer) self.build_tailer(self.tailer)
def set_checked_rows(self, rowid, flag):
if flag and rowid not in self.checked_ids:
self.checked_ids.append(rowid)
if not flag:
self.checked_ids = [ id for id in self.checked_ids if id !=rowid]
def on_rowpress(self, *args): def on_rowpress(self, *args):
print('on_rowpress fire, args=', args) print('on_rowpress fire, args=', args)
def on_cellpress(self, *args): def on_cellpress(self, *args):
print('on_cesspress fire, args=', args) print('on_cellpress fire, args=', args)
def on_headerpress(self, *args): def on_headerpress(self, *args):
print('on_headerpress fire, args=', args) print('on_headerpress fire, args=', args)
@ -462,7 +436,7 @@ class DataGrid(VBox):
desc = { desc = {
"widgettype":"Text", "widgettype":"Text",
"options":{ "options":{
"otext":n, "text":n,
"i18n":True, "i18n":True,
} }
} }
@ -555,17 +529,9 @@ class DataGrid(VBox):
idx = -1 idx = -1
recs1 = recs[:self.show_rows] recs1 = recs[:self.show_rows]
recs2 = recs[self.show_rows:] recs2 = recs[self.show_rows:]
self._fbo = Fbo(size=self.size)
with self._fbo:
self._background_color = Color(0,0,0,1)
self._background_rect = Rectangle(size=self.size)
for r in recs1: for r in recs1:
id = self.addRow(r,index=idx) id = self.addRow(r,index=idx)
ids.append(id) ids.append(id)
with self.canvas:
self._fbo_rect = Rectangle(size=self.size,
texture=self._fbo.texture)
data['idx'] = idx data['idx'] = idx
data['ids'] = ids data['ids'] = ids
data['data'] = recs2 data['data'] = recs2
@ -577,16 +543,9 @@ class DataGrid(VBox):
page = data['page'] page = data['page']
idx = data['idx'] idx = data['idx']
ids = data['ids'] ids = data['ids']
self._fbo = Fbo(size=self.size)
with self._fbo:
self._background_color = Color(0,0,0,1)
self._background_rect = Rectangle(size=self.size)
for r in recs: for r in recs:
id = self.addRow(r,index=idx) id = self.addRow(r,index=idx)
ids.append(id) ids.append(id)
with self.canvas:
self._fbo_rect = Rectangle(size=self.size,
texture=self._fbo.texture)
self._dataloader.bufferObjects(page,ids) self._dataloader.bufferObjects(page,ids)
x = self._dataloader.getLocater() x = self._dataloader.getLocater()
self.locater(x) self.locater(x)
@ -596,11 +555,13 @@ class DataGrid(VBox):
self.delRow(id) self.delRow(id)
def addRow(self,data, **kw): def addRow(self,data, **kw):
# print('#########addRow() ---------')
id = getID() id = getID()
f_row = None f_row = None
if self.freeze_part: if self.freeze_part:
self.freeze_part.body.addRow(id, data, **kw) self.freeze_part.body.addRow(id, data, **kw)
self.normal_part.body.addRow(id, data, **kw) self.normal_part.body.addRow(id, data, **kw)
# print('#########addRow()==========')
return id return id
def delRow(self,id,**kw): def delRow(self,id,**kw):
@ -639,6 +600,23 @@ class DataGrid(VBox):
fs.append(f) fs.append(f)
return fs return fs
def show_size(self, *args, **kw):
print(f'dg:{self.size}')
print(f'normal_part:{self.normal_part.size}')
print(f'body:{self.normal_part.body.size}')
print(f'row:{self.normal_part.body.children[0].size}')
print(f'row:{self.normal_part.body.children[0].size}')
sp = self.normal_part.body.children[0]
print(f'rows={len(sp.children) - 1}')
for i, r in enumerate(sp.children):
print(f'{i} {r.size=}')
if self.normal_part.parent.parent == self:
print('part ok')
else:
print('part parent=', self.normal_part.parent)
if self.normal_part.body.parent == self.normal_part:
print('body ok')
def get_selected_data(self): def get_selected_data(self):
if not self.selected_rowid: if not self.selected_rowid:
return {} return {}

0
kivyblocks/download.py Normal file → Executable file
View File

View File

@ -0,0 +1,12 @@
import inspect
import asyncio
from functools import wraps
def eventhandler(func):
@wraps(func)
def wrapper_func(*args, **kw):
if inspect.iscoroutinefunction(func):
return asyncio.gather(func(*args, **kw))
return func(*args, **kw)
return wrapper_func

0
kivyblocks/externalwidgetmanager.py Normal file → Executable file
View File

395
kivyblocks/ffpyplayer_video.py Normal file → Executable file
View File

@ -35,7 +35,6 @@ vhks = ['v_src',
] ]
class FFVideo(WidgetReady, VideoBehavior, BoxLayout): class FFVideo(WidgetReady, VideoBehavior, BoxLayout):
# class FFVideo(VideoBehavior, BoxLayout):
def __init__(self, **kw): def __init__(self, **kw):
kw1 = {k:v for k,v in kw.items() if k in vhks} kw1 = {k:v for k,v in kw.items() if k in vhks}
kw1['renderto'] = 'background' kw1['renderto'] = 'background'
@ -44,402 +43,8 @@ class FFVideo(WidgetReady, VideoBehavior, BoxLayout):
BoxLayout.__init__(self, **kw2) BoxLayout.__init__(self, **kw2)
VideoBehavior.__init__(self, **kw1) VideoBehavior.__init__(self, **kw1)
WidgetReady.__init__(self) WidgetReady.__init__(self)
# self.msg_w = Label(text='Hello')
# self.add_widget(self.msg_w)
# self.bind(on_frame=self.show_info)
def show_info(self, o, d): def show_info(self, o, d):
txt = f"size={d['size']}, vpos={d['pos']}, vsize={d['texture_size']}" txt = f"size={d['size']}, vpos={d['pos']}, vsize={d['texture_size']}"
self.msg_w.text = txt self.msg_w.text = txt
"""
class FFVideo(WidgetReady, Image):
v_src = StringProperty(None)
status = OptionProperty('stop', \
options=['stop', 'play', 'pause'])
play_mode = OptionProperty('normal', \
options=['normal', 'preview', 'audioonly'])
header_callback = StringProperty(None)
audio_id = NumericProperty(None)
duration = NumericProperty(-1)
position = NumericProperty(-1)
volume = NumericProperty(-1)
timeout = NumericProperty(5)
in_center_focus = BooleanProperty(False)
def __init__(self, **kwargs):
self._player = None
self._update_task = None
self.running = None
self.vh_task = None
self.is_black = False
self.videosize = None
self.ff_opts = {
"framedrop":True
}
self.lib_opts = {}
self.headers_pattern = {}
super(FFVideo, self).__init__(**kwargs)
self.set_black()
self.start_task = None
self.block_task = None
self.register_event_type('on_frame')
self.register_event_type('on_open_failed')
self.register_event_type('on_leave_focus')
self.register_event_type('on_enter_focus')
self.register_event_type('on_load_success')
self.register_event_type('on_startplay')
def video_blocked(self, *args):
self._play_stop()
self.on_v_src(None, None)
def on_open_failed(self, source):
print(f'{source} open failed')
def on_load_success(self, *args):
pass
def on_enter_focus(self, *args):
pass
def on_leave_focus(self, *args):
pass
def check_focus(self,*args):
if not self.parent:
self.in_center_screen = False
return
if not self.get_root_window():
self.in_center_screen = False
w = self.parent
pos = w.to_widget(*Window.center)
if self.collide_point(*pos):
self.in_center_screen = True
else:
self.in_center_screen = False
def set_ff_opt(self, k,v):
self.ff_opts.update({k:v})
def set_lib_opt(self, k, v):
self.lib_opts.update({k:v})
def set_pattern_header(self, pattern, k,v):
dic = self.headers_pattern.get(pattern,{})
dic.update({k:v})
self.headers_pattern[pattern] = dic
def _get_spec_headers(self, filename):
for p in self.headers_pattern.keys():
if filename.startswith(p):
headers = self.headers_pattern[p]
headers_str = ''.join([f'{k}:{v}\r\n' for k,v in headers.items()])
return headers_str
return None
def on_volume(self, *args):
if self._player is None:
return
self._player.set_volume(self.volume)
def on_status(self, *args):
print('on_status called, ', self.status)
if self._player is None:
print('no _player, do nothing')
return
Window.allow_screensaver = True
if self.status == 'play':
Window.allow_screensaver = False
self._player.set_pause(False)
self.video_handle()
elif self.status == 'pause':
self._player.set_pause(True)
elif self.status == 'stop':
self._play_stop()
else:
pass
def on_parent(self, *args):
if self.parent:
return
# self._play_stop()
print('on_parent() called -----------')
def on_startplay(self, *args):
pass
def on_frame(self, *args):
if self._player is None:
return
if not self.playing:
self.dispatch('on_startplay')
self._player.request_channel( \
'audio', 'open', self.audio_id)
self.seek(self.position)
self.playing = True
if self.duration > 0:
p = self.position / self.duration * self.width
self.canvas.after.clear()
with self.canvas.after:
Color(1,1,1,1)
Line()
Line(points=[0, 0, self.width, 0], width=1)
Color(1,0,0,1)
Line(points=[0,1,p,1], width=1)
def __del__(self):
self._play_stop()
def set_volume(self, v):
if self.play_mode == 'preview':
return
if self._player is None:
return
if self.status != 'play':
return
if v > 1.0:
v = 1.0
if v < 0.0:
v = 0.0
self.volume = v
def seek(self, pts):
self.vsync = False
if self.play_mode == 'preview':
return
if self._player is None:
return
if self.status != 'play':
return
self._player.seek(pts, relative=False)
self.position = self._player.get_pts()
self.last_val = None
def mute(self, flag=None):
if self.play_mode == 'preview':
return
if self._player is None:
return
if self.status != 'play':
return
x = self._player.get_mute()
print('Video(), mute=', x)
self._player.set_mute(not x)
def switch_audio(self):
if self.play_mode == 'preview':
return
if self._player is None:
return
if self.status != 'play':
return
self._player.request_channel('audio', action='cycle')
def on_v_src(self, o, src):
# self.running = Running(self)
self.status = 'stop'
self.playing = False
ff_opts = {
'pause':False
}
if self.play_mode == 'preview':
ff_opts['lowres'] = 2 # 1/4 size
ff_opts['an'] = True
elif self.play_mode == 'audioonly':
ff_opts['vn'] = True
ff_opts.update(self.ff_opts)
lib_opts = {
}
lib_opts.update(self.lib_opts)
heads = self._get_spec_headers(self.v_src)
if heads:
lib_opts.update({'headers':heads})
ff_opts.update({'headers':heads})
print('ff_opts=', ff_opts)
print('lib_opts=', lib_opts)
print('EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEe')
print_exc()
print('EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEe')
self._player = MediaPlayer(self.v_src, ff_opts=ff_opts, \
lib_opts=lib_opts)
# self._play_start()
self.status = 'play'
self.start_task = Clock.schedule_once(self.open_failed, self.timeout)
def open_failed(self, *args):
self.dispatch('on_open_failed', self.v_src)
def on_open_failed(self, source):
print(f'{source} open failed')
def file_opened(self, files):
self.v_src = files[0]
def play(self):
if self._player is None:
return
self.status = 'play'
def pause(self):
if self._player is None:
return
# self._player.set_pause(True)
self.status = 'pause'
def _play_start(self):
self.last_frame = None
self.is_black = False
self.vsync = False
def _get_video_info(self):
if not self.playing:
self.playing = True
meta = self._player.get_metadata()
self.duration = meta['duration']
self._out_fmt = meta['src_pix_fmt']
self.frame_rate = meta['frame_rate']
self.videosize = meta['src_vid_size']
def _play_stop(self):
if self._player:
self._player.close_player()
self._player = None
if self._update_task:
self._update_task.cancel()
self._update_task = None
if self.vh_task:
self.vh_task.cancel()
self.vh_task = None
self.next_frame = None
self.duration = -1
self.position = 0
self.videosize = None
def on_size(self, *args):
if self._player is None:
return
if self.videosize == None:
return
w, h = self.videosize
r = w / h
r1 = self.width / self.height
if r1 >= r:
self._player.set_size(-1, self.height)
else:
self._player.set_size(self.width, -1)
def set_black(self):
if self.is_black:
return
image_texture = Texture.create(
size=self.size, colorfmt='rgb')
buf = b'\x00' * int(self.width * self.height * 3)
image_texture.blit_buffer(buf, colorfmt='rgb', bufferfmt='ubyte')
self.texture = image_texture
self.is_black = True
def show_yuv420(self, img):
w, h = img.get_size()
w2 = int(w / 2)
h2 = int(h / 2)
self._tex_y = Texture.create(
size=(w, h), colorfmt='luminance')
self._tex_u = Texture.create(
size=(w2, h2), colorfmt='luminance')
self._tex_v = Texture.create(
size=(w2, h2), colorfmt='luminance')
self._fbo = fbo = Fbo(size=(w, h))
with fbo:
BindTexture(texture=self._tex_u, index=1)
BindTexture(texture=self._tex_v, index=2)
Rectangle(size=fbo.size, texture=self._tex_y)
fbo.shader.fs = VideoFFPy.YUV_RGB_FS
fbo['tex_y'] = 0
fbo['tex_u'] = 1
fbo['tex_v'] = 2
dy, du, dv, _ = img.to_memoryview()
if dy and du and dv:
self._tex_y.blit_buffer(dy, colorfmt='luminance')
self._tex_u.blit_buffer(du, colorfmt='luminance')
self._tex_v.blit_buffer(dv, colorfmt='luminance')
self._fbo.ask_update()
self._fbo.draw()
texture.flip_vertical()
self.texture = texture
def show_others(self, img):
w, h = img.get_size()
texture = Texture.create(size=(w, h), colorfmt='rgb')
texture.blit_buffer(
img.to_memoryview()[0], colorfmt='rgb',
bufferfmt='ubyte')
texture.flip_vertical()
self.texture = texture
# print('img_size=', w, h, 'window size=', self.size)
def video_handle(self, *args):
if self._update_task:
self._update_task.cancel()
self._update_task = None
if self._player is None:
return
frame, val = self._player.get_frame()
if val == 'eof':
self.status = 'stop'
self.set_black()
self.last_val = None
return
if val == 'pause':
self.status = 'pause'
self.last_val = None
return
if frame is None:
self.set_black()
self.last_val = None
self.vh_task = Clock.schedule_once(self.video_handle, 0.1)
return
self. _get_video_info()
self.last_frame = frame
self.video_ts = val
if self.last_val is None:
self.last_val = val
self._update_task = Clock.schedule_once(self.do_update, 0)
else:
t = val - self.last_val
if t > 0:
self._update_task = Clock.schedule_once(self.do_update, t)
else:
self._update_task = Clock.schedule_once(self.do_update, 0)
def do_update(self, *args):
if self.start_task:
self.start_task.cancel()
self.start_task = None
if self.block_task:
self.block_task.cancel()
# if self.running:
# print('runnung dismiss ........')
# self.running.dismiss()
# self.running = None
self.position = self._player.get_pts()
self.volume = self._player.get_volume()
img, t = self.last_frame
if self._out_fmt == 'yuv420p':
self.show_yuv420(img)
else:
self.show_others(img)
self.dispatch('on_frame', self.last_frame)
self.last_frame = None
self.vh_task = Clock.schedule_once(self.video_handle, 0)
self.block_task = Clock.schedule_once(self.video_blocked, self.timeout)
"""

0
kivyblocks/filebrowser.py Normal file → Executable file
View File

1
kivyblocks/form.py Normal file → Executable file
View File

@ -32,6 +32,7 @@ form options
"method" "method"
} }
"cols":"1" "cols":"1"
"inputwidth",
"labelwidth": "labelwidth":
"textsize": "textsize":
"inputheight": "inputheight":

0
kivyblocks/gps.py Normal file → Executable file
View File

0
kivyblocks/hack_ffpyplayer.py Normal file → Executable file
View File

0
kivyblocks/hierarchy.py Normal file → Executable file
View File

0
kivyblocks/hostimage.py Normal file → Executable file
View File

0
kivyblocks/httpvplayer.py Normal file → Executable file
View File

18
kivyblocks/i18n.py Normal file → Executable file
View File

@ -58,9 +58,12 @@ class I18n:
if config.i18n_url: if config.i18n_url:
url = '%s%s' % (config.uihome, config.i18n_url) url = '%s%s' % (config.uihome, config.i18n_url)
hc = HttpClient() hc = HttpClient()
d = hc.get(url) try:
if isinstance(d, list): d = hc.get(url)
return d if isinstance(d, list):
return d
except:
pass
return [] return []
def loadI18n(self,lang): def loadI18n(self,lang):
@ -74,9 +77,12 @@ class I18n:
if config.i18n_url: if config.i18n_url:
url = '%s%s/%s' % (config.uihome, config.i18n_url, lang) url = '%s%s/%s' % (config.uihome, config.i18n_url, lang)
hc = HttpClient() hc = HttpClient()
d = hc.get(url) try:
print('i18n() %s get data=' % url, d, type(d)) d = hc.get(url)
self.kvlang[lang] = d print('i18n() %s get data=' % url, d, type(d))
self.kvlang[lang] = d
except:
pass
def __call__(self,msg,lang=None): def __call__(self,msg,lang=None):
if lang is None: if lang is None:

BIN
kivyblocks/imgs/.DS_Store vendored Executable file

Binary file not shown.

0
kivyblocks/imgs/Mute64x64.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 6.5 KiB

After

Width:  |  Height:  |  Size: 6.5 KiB

0
kivyblocks/imgs/Play64X64.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

0
kivyblocks/imgs/Sound64x64.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

BIN
kivyblocks/imgs/add.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

0
kivyblocks/imgs/backword.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 9.1 KiB

After

Width:  |  Height:  |  Size: 9.1 KiB

0
kivyblocks/imgs/broken.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 32 KiB

0
kivyblocks/imgs/bullet_arrow_down.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 201 B

After

Width:  |  Height:  |  Size: 201 B

0
kivyblocks/imgs/bullet_arrow_right.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 315 B

After

Width:  |  Height:  |  Size: 315 B

0
kivyblocks/imgs/cancel.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 29 KiB

0
kivyblocks/imgs/checkbox-off.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 7.1 KiB

After

Width:  |  Height:  |  Size: 7.1 KiB

0
kivyblocks/imgs/checkbox-on.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

0
kivyblocks/imgs/clear.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 108 KiB

After

Width:  |  Height:  |  Size: 108 KiB

0
kivyblocks/imgs/conform.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

0
kivyblocks/imgs/crud_add.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

0
kivyblocks/imgs/crud_browser.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

0
kivyblocks/imgs/crud_del.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

0
kivyblocks/imgs/crud_edit.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

0
kivyblocks/imgs/crud_filter.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 10 KiB

BIN
kivyblocks/imgs/deletex.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

0
kivyblocks/imgs/doing.gif Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 171 KiB

After

Width:  |  Height:  |  Size: 171 KiB

0
kivyblocks/imgs/download.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 37 KiB

0
kivyblocks/imgs/error.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

0
kivyblocks/imgs/folder.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 537 B

After

Width:  |  Height:  |  Size: 537 B

0
kivyblocks/imgs/icon_view.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

0
kivyblocks/imgs/info.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

0
kivyblocks/imgs/kivymd_512.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

0
kivyblocks/imgs/kivymd_logo.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 41 KiB

BIN
kivyblocks/imgs/lensid.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

0
kivyblocks/imgs/list_view.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 7.8 KiB

After

Width:  |  Height:  |  Size: 7.8 KiB

0
kivyblocks/imgs/loading.gif Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 45 KiB

0
kivyblocks/imgs/loading1.gif Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 131 KiB

After

Width:  |  Height:  |  Size: 131 KiB

0
kivyblocks/imgs/menu.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

0
kivyblocks/imgs/musictrack.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 51 KiB

0
kivyblocks/imgs/musictrack_d.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 51 KiB

0
kivyblocks/imgs/next.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 42 KiB

0
kivyblocks/imgs/next_d.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

0
kivyblocks/imgs/org_sound.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 49 KiB

0
kivyblocks/imgs/org_sound_d.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 49 KiB

0
kivyblocks/imgs/origin.jpg Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 70 KiB

After

Width:  |  Height:  |  Size: 70 KiB

0
kivyblocks/imgs/pause.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 37 KiB

0
kivyblocks/imgs/pause_d.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 9.6 KiB

After

Width:  |  Height:  |  Size: 9.6 KiB

BIN
kivyblocks/imgs/photo.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

0
kivyblocks/imgs/picture_empty.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 463 B

After

Width:  |  Height:  |  Size: 463 B

0
kivyblocks/imgs/play.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 48 KiB

0
kivyblocks/imgs/play_d.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

0
kivyblocks/imgs/power64x64.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 6.7 KiB

After

Width:  |  Height:  |  Size: 6.7 KiB

0
kivyblocks/imgs/previous.jpg Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

0
kivyblocks/imgs/quad_shadow-0.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 29 KiB

0
kivyblocks/imgs/quad_shadow-1.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

0
kivyblocks/imgs/quad_shadow-2.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

0
kivyblocks/imgs/quad_shadow.atlas Normal file → Executable file
View File

0
kivyblocks/imgs/question.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

0
kivyblocks/imgs/rec_shadow-0.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 46 KiB

Some files were not shown because too many files have changed in this diff Show More