__init__.py 38 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099
  1. # -*- coding: utf-8 -*-
  2. import os
  3. import pygame
  4. import platform
  5. #import commands
  6. import glob
  7. import json
  8. import gobject
  9. import sqlite3
  10. #from beeprint import pp
  11. from libs.roundrects import aa_round_rect
  12. from shutil import copyfile
  13. ## local UI import
  14. from UI.constants import Width,Height,ICON_TYPES,RESTARTUI
  15. from UI.page import Page,PageSelector
  16. from UI.label import Label
  17. from UI.util_funcs import midRect,FileExists,ArmSystem
  18. from UI.keys_def import CurKeys, IsKeyStartOrA, IsKeyMenuOrB
  19. from UI.scroller import ListScroller
  20. from UI.icon_pool import MyIconPool
  21. from UI.icon_item import IconItem
  22. from UI.multilabel import MultiLabel
  23. from UI.skin_manager import MySkinManager
  24. from UI.lang_manager import MyLangManager
  25. from UI.info_page_list_item import InfoPageListItem
  26. from UI.info_page_selector import InfoPageSelector
  27. from UI.yes_cancel_confirm_page import YesCancelConfirmPage
  28. from UI.keyboard import Keyboard
  29. from UI.download import Download
  30. import config
  31. class RPCStack:
  32. def __init__(self):
  33. self.stack = list()
  34. def Push(self,data):
  35. if data not in self.stack:
  36. self.stack.append(data)
  37. return True
  38. return False
  39. def Pop(self):
  40. if len(self.stack)<=0:
  41. return None,False
  42. return self.stack.pop(),True
  43. def Last(self):
  44. idx = len(self.stack) -1
  45. if idx < 0:
  46. return None
  47. else:
  48. return self.stack[ idx ]
  49. def Length(self):
  50. return len(self.stack)
  51. class LoadHousePage(Page):
  52. _FootMsg = ["Nav.","","","Back","Cancel"]
  53. _DownloaderTimer = -1
  54. _Value = 0
  55. _URL = None
  56. _ListFontObj = MyLangManager.TrFont("varela18")
  57. _URLColor = MySkinManager.GiveColor('URL')
  58. _TextColor = MySkinManager.GiveColor('Text')
  59. _Caller=None
  60. _img = None
  61. _Downloader=None
  62. _DownloaderTimer=-1
  63. def __init__(self):
  64. Page.__init__(self)
  65. self._Icons = {}
  66. self._CanvasHWND = None
  67. def Init(self):
  68. self._PosX = self._Index * self._Screen._Width
  69. self._Width = self._Screen._Width
  70. self._Height = self._Screen._Height
  71. self._CanvasHWND = self._Screen._CanvasHWND
  72. self._LoadingLabel = Label()
  73. self._LoadingLabel.SetCanvasHWND(self._CanvasHWND)
  74. self._LoadingLabel.Init("Loading",self._ListFontObj)
  75. self._LoadingLabel.SetColor(self._TextColor )
  76. def OnLoadCb(self):
  77. if self._URL is None:
  78. return
  79. self._img = None
  80. self.ClearCanvas()
  81. self._Screen.Draw()
  82. self._Screen.SwapAndShow()
  83. filename = self._URL.split("/")[-1].strip()
  84. local_dir = self._URL.split("raw.githubusercontent.com")
  85. if len(local_dir) >1:
  86. menu_file = local_dir[1]
  87. local_menu_file = "%s/aria2download%s" % (os.path.expanduser('~'),menu_file )
  88. if FileExists(local_menu_file):
  89. #load json
  90. with open(local_menu_file) as json_file:
  91. try:
  92. local_menu_json = json.load(json_file)
  93. self._Caller._MyStack.Push(local_menu_json["list"])
  94. except:
  95. pass
  96. self.Leave()
  97. else:
  98. self._Downloader = Download(self._URL,"/tmp",None)
  99. self._Downloader.start()
  100. self._DownloaderTimer = gobject.timeout_add(400, self.GObjectUpdateProcessInterval)
  101. def GObjectUpdateProcessInterval(self):
  102. ret = True
  103. if self._Screen.CurPage() == self:
  104. if self._Downloader._stop == True:
  105. ret = False
  106. dst_filename = self._Downloader.get_dest()
  107. if self._Downloader.isFinished():
  108. if self._Downloader.isSuccessful():
  109. filename = self._URL.split("/")[-1].strip()
  110. local_dir = self._URL.split("raw.githubusercontent.com")
  111. menu_file = local_dir[1]
  112. local_menu_file = "%s/aria2download%s" % (os.path.expanduser('~'),menu_file )
  113. dl_file = os.path.join("/tmp",filename)
  114. if not os.path.exists(os.path.dirname(local_menu_file)):
  115. os.makedirs(os.path.dirname(local_menu_file))
  116. copyfile(dl_file, local_menu_file)
  117. with open(local_menu_file) as json_file:
  118. try:
  119. local_menu_json = json.load(json_file)
  120. self._Caller._MyStack.Push(local_menu_json["list"])
  121. except:
  122. pass
  123. ret = False
  124. self.Leave()
  125. return ret
  126. else:
  127. return False
  128. def Leave(self):
  129. if self._DownloaderTimer != -1:
  130. gobject.source_remove(self._DownloaderTimer)
  131. self._DownloaderTimer = -1
  132. if self._Downloader != None:
  133. try:
  134. self._Downloader.stop()
  135. except:
  136. print("user canceled ")
  137. self.ReturnToUpLevelPage()
  138. self._Screen.Draw()
  139. self._Screen.SwapAndShow()
  140. self._URL = None
  141. def KeyDown(self,event):
  142. if IsKeyMenuOrB(event.key):
  143. self.Leave()
  144. def Draw(self):
  145. self.ClearCanvas()
  146. self._LoadingLabel.NewCoord( (Width-self._LoadingLabel._Width)/2,(Height-44)/2)
  147. self._LoadingLabel.Draw()
  148. if self._img is not None:
  149. self._CanvasHWND.blit(self._img,midRect(Width/2,
  150. (Height-44)/2,
  151. pygame.Surface.get_width(self._img),pygame.Surface.get_height(self._img),Width,Height-44))
  152. class ImageDownloadProcessPage(Page):
  153. _FootMsg = ["Nav.","","","Back","Cancel"]
  154. _DownloaderTimer = -1
  155. _Value = 0
  156. _URL = None
  157. _ListFontObj = MyLangManager.TrFont("varela13")
  158. _URLColor = MySkinManager.GiveColor('URL')
  159. _TextColor = MySkinManager.GiveColor('Text')
  160. _img = None
  161. _Downloader=None
  162. _DownloaderTimer=-1
  163. def __init__(self):
  164. Page.__init__(self)
  165. self._Icons = {}
  166. self._CanvasHWND = None
  167. def Init(self):
  168. self._PosX = self._Index * self._Screen._Width
  169. self._Width = self._Screen._Width
  170. self._Height = self._Screen._Height
  171. self._CanvasHWND = self._Screen._CanvasHWND
  172. self._LoadingLabel = Label()
  173. self._LoadingLabel.SetCanvasHWND(self._CanvasHWND)
  174. self._LoadingLabel.Init("Loading",self._ListFontObj)
  175. self._LoadingLabel.SetColor(self._TextColor )
  176. def OnLoadCb(self):
  177. if self._URL is None:
  178. return
  179. self._img = None
  180. self.ClearCanvas()
  181. self._Screen.Draw()
  182. self._Screen.SwapAndShow()
  183. filename = self._URL.split("/")[-1].strip()
  184. local_dir = self._URL.split("raw.githubusercontent.com")
  185. if len(local_dir) >1:
  186. menu_file = local_dir[1]
  187. local_menu_file = "%s/aria2download%s" % (os.path.expanduser('~'),menu_file )
  188. if FileExists(local_menu_file):
  189. self._img = pygame.image.load(local_menu_file).convert_alpha()
  190. self._Screen.Draw()
  191. self._Screen.SwapAndShow()
  192. else:
  193. self._Downloader = Download(self._URL,"/tmp",None)
  194. self._Downloader.start()
  195. self._DownloaderTimer = gobject.timeout_add(300, self.GObjectUpdateProcessInterval)
  196. def GObjectUpdateProcessInterval(self):
  197. ret = True
  198. if self._Screen.CurPage() == self:
  199. if self._Downloader._stop == True:
  200. ret = False
  201. dst_filename = self._Downloader.get_dest()
  202. if self._Downloader.isFinished():
  203. if self._Downloader.isSuccessful():
  204. filename = self._URL.split("/")[-1].strip()
  205. local_dir = self._URL.split("raw.githubusercontent.com")
  206. menu_file = local_dir[1]
  207. local_menu_file = "%s/aria2download%s" % (os.path.expanduser('~'),menu_file )
  208. dl_file = os.path.join("/tmp",filename)
  209. if not os.path.exists(os.path.dirname(local_menu_file)):
  210. os.makedirs(os.path.dirname(local_menu_file))
  211. copyfile(dl_file, local_menu_file)
  212. ret = False
  213. #print("dest ",dst_filename)
  214. if FileExists(dst_filename):
  215. try:
  216. #print("load and draw")
  217. self._img = pygame.image.load(dst_filename).convert_alpha()
  218. self._Screen.Draw()
  219. self._Screen.SwapAndShow()
  220. except Exception as ex:
  221. print(ex)
  222. return ret
  223. else:
  224. return False
  225. def KeyDown(self,event):
  226. if IsKeyMenuOrB(event.key):
  227. gobject.source_remove(self._DownloaderTimer)
  228. self._DownloaderTimer = -1
  229. if self._Downloader != None:
  230. try:
  231. self._Downloader.stop()
  232. except:
  233. print("user canceled ")
  234. self.ReturnToUpLevelPage()
  235. self._Screen.Draw()
  236. self._Screen.SwapAndShow()
  237. self._URL = None
  238. def Draw(self):
  239. self.ClearCanvas()
  240. self._LoadingLabel.NewCoord( (Width-self._LoadingLabel._Width)/2,(Height-44)/2)
  241. self._LoadingLabel.Draw()
  242. if self._img is not None:
  243. self._CanvasHWND.blit(self._img,midRect(Width/2,
  244. (Height-44)/2,
  245. pygame.Surface.get_width(self._img),pygame.Surface.get_height(self._img),Width,Height-44))
  246. class Aria2DownloadProcessPage(Page):
  247. _FootMsg = ["Nav.","","Pause","Back","Cancel"]
  248. _DownloaderTimer = -1
  249. _Value = 0
  250. _GID = None
  251. _PngSize = {}
  252. _FileNameLabel = None
  253. _SizeLabel = None
  254. _URLColor = MySkinManager.GiveColor('URL')
  255. _TextColor = MySkinManager.GiveColor('Text')
  256. def __init__(self):
  257. Page.__init__(self)
  258. self._Icons = {}
  259. self._CanvasHWND = None
  260. def Init(self):
  261. self._PosX = self._Index * self._Screen._Width
  262. self._Width = self._Screen._Width
  263. self._Height = self._Screen._Height
  264. self._CanvasHWND = self._Screen._CanvasHWND
  265. bgpng = IconItem()
  266. bgpng._ImgSurf = MyIconPool.GiveIconSurface("rom_download")
  267. bgpng._MyType = ICON_TYPES["STAT"]
  268. bgpng._Parent = self
  269. bgpng.Adjust(0,0,self._PngSize["bg"][0],self._PngSize["bg"][1],0)
  270. self._Icons["bg"] = bgpng
  271. self._FileNameLabel = Label()
  272. self._FileNameLabel.SetCanvasHWND(self._CanvasHWND)
  273. self._FileNameLabel.Init("", MyLangManager.TrFont("varela12"))
  274. self._SizeLabel = Label()
  275. self._SizeLabel.SetCanvasHWND(self._CanvasHWND)
  276. self._SizeLabel.Init("0/0Kb",MyLangManager.TrFont("varela12"))
  277. self._SizeLabel.SetColor( self._URLColor )
  278. def GObjectUpdateProcessInterval(self):
  279. if self._Screen.CurPage() == self and self._GID is not None:
  280. self._Value = config.RPC.tellStatus(self._GID)
  281. downloaded = 0
  282. total = 0
  283. if self._Value["status"] == "waiting":
  284. self._FileNameLabel.SetText( "waiting to download..." )
  285. if self._Value["status"] == "paused":
  286. self._FileNameLabel.SetText( "download paused..." )
  287. if self._Value["status"] == "error":
  288. self._FileNameLabel.SetText("download errors,cancel it please")
  289. if self._Value["status"] == "active":
  290. downloaded = self._Value["completedLength"]
  291. total = self._Value["totalLength"]
  292. downloaded = downloaded/1000.0/1000.0
  293. total = total/1000.0/1000.0
  294. self._SizeLabel.SetText( "%.2f" % downloaded+"/"+ "%.2f" % total +"Mb")
  295. print("Progress: %d%%" % (self._Value))
  296. self._Screen.Draw()
  297. self._Screen.SwapAndShow()
  298. return True
  299. else:
  300. return False
  301. def CheckDownload(self,aria2_gid):
  302. self._GID = aria2_gid
  303. self._DownloaderTimer = gobject.timeout_add(123, self.GObjectUpdateProcessInterval)
  304. def KeyDown(self,event):
  305. if IsKeyMenuOrB(event.key):
  306. gobject.source_remove(self._DownloaderTimer)
  307. self._DownloaderTimer = -1
  308. #if self._Downloader != None:
  309. # try:
  310. # self._Downloader.stop()
  311. # except:
  312. # print("user canceled ")
  313. self.ReturnToUpLevelPage()
  314. self._Screen.Draw()
  315. self._Screen.SwapAndShow()
  316. def Draw(self):
  317. self.ClearCanvas()
  318. self._Icons["bg"].NewCoord(self._Width/2,self._Height/2-20)
  319. self._Icons["bg"].Draw()
  320. percent = self._Value
  321. if percent < 10:
  322. percent = 10
  323. rect_ = midRect(self._Width/2,self._Height/2+33,170,17, Width,Height)
  324. aa_round_rect(self._CanvasHWND,rect_,MySkinManager.GiveColor('TitleBg'),5,0,MySkinManager.GiveColor('TitleBg'))
  325. rect2 = midRect(self._Width/2,self._Height/2+33,int(170*(percent/100.0)),17, Width,Height)
  326. rect2.left = rect_.left
  327. rect2.top = rect_.top
  328. aa_round_rect(self._CanvasHWND,rect2,MySkinManager.GiveColor('Front'),5,0,MySkinManager.GiveColor('Front'))
  329. rect3 = midRect(self._Width/2,self._Height/2+53,self._FileNameLabel._Width, self._FileNameLabel._Height,Width,Height)
  330. rect4 = midRect(self._Width/2,self._Height/2+70,self._SizeLabel._Width, self._SizeLabel._Height,Width,Height)
  331. self._FileNameLabel.NewCoord(rect3.left,rect3.top)
  332. self._SizeLabel.NewCoord(rect4.left, rect4.top)
  333. self._FileNameLabel.Draw()
  334. self._SizeLabel.Draw()
  335. def dict_factory(cursor, row):
  336. d = {}
  337. for idx, col in enumerate(cursor.description):
  338. d[col[0]] = row[idx]
  339. return d
  340. class GameStoreListItem(InfoPageListItem):
  341. _Type = None #source,dir,launcher,pico8
  342. _CanvasHWND = None
  343. def Init(self,text):
  344. #self._Fonts["normal"] = fonts["veramono12"]
  345. l = Label()
  346. l._PosX = 10
  347. l.SetCanvasHWND(self._Parent._CanvasHWND)
  348. l.Init(text,self._Fonts["normal"])
  349. self._Labels["Text"] = l
  350. add_icon = IconItem()
  351. add_icon._ImgSurf = MyIconPool.GiveIconSurface("add")
  352. add_icon._CanvasHWND = self._CanvasHWND
  353. add_icon._Parent = self
  354. add_icon.Init(0,0,MyIconPool.Width("add"),MyIconPool.Height("add"),0)
  355. ware_icon = IconItem()
  356. ware_icon._ImgSurf = MyIconPool.GiveIconSurface("ware")
  357. ware_icon._CanvasHWND = self._CanvasHWND
  358. ware_icon._Parent = self
  359. ware_icon.Init(0,0,MyIconPool.Width("ware"),MyIconPool.Height("ware"),0)
  360. app_icon = IconItem()
  361. app_icon._ImgSurf = MyIconPool.GiveIconSurface("app")
  362. app_icon._CanvasHWND = self._CanvasHWND
  363. app_icon._Parent = self
  364. app_icon.Init(0,0,MyIconPool.Width("app"),MyIconPool.Height("app"),0)
  365. appdling_icon = IconItem()
  366. appdling_icon._ImgSurf = MyIconPool.GiveIconSurface("appdling")
  367. appdling_icon._CanvasHWND = self._CanvasHWND
  368. appdling_icon._Parent = self
  369. app_icon.Init(0,0,MyIconPool.Width("appdling"),MyIconPool.Height("appdling"),0)
  370. blackheart_icon = IconItem()
  371. blackheart_icon._ImgSurf = MyIconPool.GiveIconSurface("blackheart")
  372. blackheart_icon._Width = MyIconPool.Width("blackheart")
  373. blackheart_icon._Height = MyIconPool.Height("blackheart")
  374. blackheart_icon._CanvasHWND = self._CanvasHWND
  375. blackheart_icon._Parent = self
  376. self._Icons["add"] = add_icon
  377. self._Icons["ware"] = ware_icon
  378. self._Icons["app"] = app_icon
  379. self._Icons["appdling"] = appdling_icon
  380. self._Icons["blackheart"] = blackheart_icon
  381. def Draw(self):
  382. if self._ReadOnly == True:
  383. self._Labels["Text"].SetColor(MySkinManager.GiveColor("ReadOnlyText"))
  384. else:
  385. self._Labels["Text"].SetColor(MySkinManager.GiveColor("Text"))
  386. padding = 17
  387. if self._Type == None:
  388. padding = 0
  389. if self._Type == "source" or self._Type == "dir":
  390. self._Icons["ware"].NewCoord( 4, (self._Height - self._Icons["ware"]._Height)/2 )
  391. self._Icons["ware"].DrawTopLeft()
  392. if self._Type == "launcher" or self._Type == "pico8":
  393. _icon = "app"
  394. if self._ReadOnly == True:
  395. _icon = "appdling"
  396. self._Icons[_icon].NewCoord( 4, (self._Height - self._Icons[_icon]._Height)/2)
  397. self._Icons[_icon].DrawTopLeft()
  398. if self._Type == "add_house":
  399. self._Icons["add"].NewCoord( 4, (self._Height - self._Icons["add"]._Height)/2)
  400. self._Icons["add"].DrawTopLeft()
  401. self._Labels["Text"]._PosX = self._Labels["Text"]._PosX + self._PosX + padding
  402. self._Labels["Text"]._PosY = self._PosY + (self._Height - self._Labels["Text"]._Height)/2
  403. self._Labels["Text"].Draw()
  404. self._Labels["Text"]._PosX = self._Labels["Text"]._PosX - self._PosX - padding
  405. if "Small" in self._Labels:
  406. self._Labels["Small"]._PosX = self._Width - self._Labels["Small"]._Width-5
  407. self._Labels["Small"]._PosY = self._PosY + (self._Height - self._Labels["Small"]._Height)/2
  408. self._Labels["Small"].Draw()
  409. #pygame.draw.line(self._Parent._CanvasHWND,MySkinManager.GiveColor('Line'),(self._PosX,self._PosY+self._Height-1),(self._PosX+self._Width,self._PosY+self._Height-1),1)
  410. class GameStorePage(Page):
  411. _FootMsg = ["Nav","UpdateWare","Up","Back","Select"]
  412. _MyList = []
  413. _ListFont12 = MyLangManager.TrFont("notosanscjk12")
  414. _ListFont15 = MyLangManager.TrFont("varela15")
  415. _AList = {}
  416. _Scrolled = 0
  417. _BGwidth = 320
  418. _BGheight = 240-24-20
  419. _DrawOnce = False
  420. _Scroller = None
  421. _InfoPage = None
  422. _Downloading = None
  423. _aria2_db = "aria2tasks.db"
  424. _warehouse_db = "warehouse.db"
  425. def __init__(self):
  426. Page.__init__(self)
  427. self._Icons = {}
  428. self._MyStack = RPCStack()
  429. #title path type
  430. repos = [
  431. {"title":"github.com/cuu/gamestore","file":"https://raw.githubusercontent.com/cuu/gamestore/master/index.json","type":"source"}
  432. ]
  433. self._MyStack.Push(repos)
  434. def SyncWarehouse(self):
  435. try:
  436. conn = sqlite3.connect(self._warehouse_db)
  437. conn.row_factory = dict_factory
  438. c = conn.cursor()
  439. ret = c.execute("SELECT * FROM warehouse").fetchall()
  440. conn.close()
  441. return ret
  442. except Exception as ex:
  443. print(ex)
  444. return None
  445. return None
  446. def SyncTasks(self):
  447. try:
  448. conn = sqlite3.connect(self._aria2_db)
  449. conn.row_factory = dict_factory
  450. c = conn.cursor()
  451. ret = c.execute("SELECT * FROM tasks").fetchall()
  452. conn.close()
  453. return ret
  454. except Exception as ex:
  455. print(ex)
  456. return None
  457. return None
  458. def SyncList(self):
  459. self._MyList = []
  460. start_x = 0
  461. start_y = 0
  462. last_height = 0
  463. repos = []
  464. stk = self._MyStack.Last()
  465. stk_lev = self._MyStack.Length()
  466. repos.extend(stk)
  467. add_new_house = [
  468. {"title":"Add new warehouse...","file":"master/index.json","type":"add_house","status":"complete"}
  469. ]
  470. if stk_lev == 1: # on top
  471. ware_menu= self.SyncWarehouse()
  472. if ware_menu != None and len(ware_menu) > 0:
  473. #print(ware_menu)
  474. repos.extend(ware_menu )
  475. tasks_menu= self.SyncTasks()
  476. if tasks_menu != None and len(tasks_menu) > 0:
  477. #print(tasks_menu)
  478. repos.extend(tasks_menu )
  479. #print(repos)
  480. repos.extend(add_new_house)
  481. for i,u in enumerate( repos ):
  482. #print(i,u)
  483. li = GameStoreListItem()
  484. li._CanvasHWND = self._CanvasHWND
  485. li._Parent = self
  486. li._PosX = start_x
  487. li._PosY = start_y + last_height
  488. li._Width = Width
  489. li._Fonts["normal"] = self._ListFont15
  490. li._Active = False
  491. li._ReadOnly = True
  492. li._Value = u
  493. li._Type = u["type"]
  494. li.Init( u["title"] )
  495. if stk_lev >1:
  496. li._ReadOnly = False
  497. elif stk_lev == 1:
  498. if "status" in u:
  499. if u["status"] == "complete":
  500. li._ReadOnly = False
  501. if u["type"]=="source":
  502. li._ReadOnly = False
  503. last_height += li._Height
  504. self._MyList.append(li)
  505. def Init(self):
  506. if self._Screen != None:
  507. if self._Screen._CanvasHWND != None and self._CanvasHWND == None:
  508. self._HWND = self._Screen._CanvasHWND
  509. self._CanvasHWND = pygame.Surface( (self._Screen._Width,self._BGheight) )
  510. self._PosX = self._Index*self._Screen._Width
  511. self._Width = self._Screen._Width ## equal to screen width
  512. self._Height = self._Screen._Height
  513. done = IconItem()
  514. done._ImgSurf = MyIconPool.GiveIconSurface("done")
  515. done._MyType = ICON_TYPES["STAT"]
  516. done._Parent = self
  517. self._Icons["done"] = done
  518. ps = InfoPageSelector()
  519. ps._Parent = self
  520. self._Ps = ps
  521. self._PsIndex = 0
  522. self.SyncList()
  523. self._Scroller = ListScroller()
  524. self._Scroller._Parent = self
  525. self._Scroller._PosX = self._Width - 10
  526. self._Scroller._PosY = 2
  527. self._Scroller.Init()
  528. self._Scroller.SetCanvasHWND(self._HWND)
  529. self._remove_page = YesCancelConfirmPage()
  530. self._remove_page._Screen = self._Screen
  531. self._remove_page._StartOrA_Event = self.RemoveGame
  532. self._remove_page._Name ="Are you sure?"
  533. self._remove_page.Init()
  534. self._Keyboard = Keyboard()
  535. self._Keyboard._Name = "Enter warehouse addr"
  536. self._Keyboard._Screen = self._Screen
  537. self._Keyboard.Init()
  538. self._Keyboard.SetPassword("github.com/clockworkpi/warehouse")
  539. self._Keyboard._Caller = self
  540. self._PreviewPage = ImageDownloadProcessPage()
  541. self._PreviewPage._Screen = self._Screen
  542. self._PreviewPage._Name = "preview"
  543. self._PreviewPage.Init()
  544. self._LoadHousePage = LoadHousePage()
  545. self._LoadHousePage._Screen = self._Screen
  546. self._LoadHousePage._Name = "Warehouse"
  547. self._LoadHousePage._Caller = self
  548. self._LoadHousePage.Init()
  549. def ResetHouse(self):
  550. if self._PsIndex > len(self._MyList) -1:
  551. return
  552. cur_li = self._MyList[self._PsIndex]
  553. if cur_li._Value["type"] == "source":
  554. remote_file_url = cur_li._Value["file"]
  555. menu_file = remote_file_url.split("raw.githubusercontent.com")[1] #assume master branch
  556. local_menu_file = "%s/aria2download%s" % (os.path.expanduser('~'),menu_file )
  557. print(local_menu_file)
  558. try:
  559. if os.path.exists(local_menu_file):
  560. os.remove(local_menu_file)
  561. if os.path.exists(local_menu_file+".aria2"):
  562. os.remove(local_menu_file+".aria2")
  563. except Exception as ex:
  564. print(ex)
  565. self._Screen._MsgBox.SetText("Done")
  566. self._Screen._MsgBox.Draw()
  567. self._Screen.SwapAndShow()
  568. def LoadHouse(self):
  569. if self._PsIndex > len(self._MyList) -1:
  570. return
  571. cur_li = self._MyList[self._PsIndex]
  572. if cur_li._Value["type"] == "source" or cur_li._Value["type"] == "dir":
  573. self._LoadHousePage._URL = cur_li._Value["file"]
  574. self._Screen.PushPage(self._LoadHousePage)
  575. self._Screen.Draw()
  576. self._Screen.SwapAndShow()
  577. def PreviewGame(self):
  578. if self._PsIndex > len(self._MyList) -1:
  579. return
  580. cur_li = self._MyList[self._PsIndex]
  581. if cur_li._Value["type"] == "launcher" or cur_li._Value["type"] == "pico8" or cur_li._Value["type"] == "tic80":
  582. print(cur_li._Value["shots"])
  583. self._PreviewPage._URL = cur_li._Value["shots"]
  584. self._Screen.PushPage(self._PreviewPage)
  585. self._Screen.Draw()
  586. self._Screen.SwapAndShow()
  587. def RemoveGame(self):
  588. if self._PsIndex > len(self._MyList) -1:
  589. return
  590. cur_li = self._MyList[self._PsIndex]
  591. #if cur_li._Active == True:
  592. # return
  593. print("Remove cur_li._Value",cur_li._Value)
  594. if cur_li._Value["type"] == "source":
  595. print("remove a source")
  596. try:
  597. conn = sqlite3.connect(self._warehouse_db)
  598. conn.row_factory = dict_factory
  599. c = conn.cursor()
  600. c.execute("DELETE FROM warehouse WHERE file = '%s'" % cur_li._Value["file"] )
  601. conn.commit()
  602. conn.close()
  603. except Exception as ex:
  604. print(ex)
  605. elif "gid" in cur_li._Value:
  606. try:
  607. gid = cur_li._Value["gid"]
  608. conn = sqlite3.connect(self._aria2_db)
  609. conn.row_factory = dict_factory
  610. c = conn.cursor()
  611. ret = c.execute("SELECT * FROM tasks WHERE gid='%s'" % gid ).fetchone()
  612. if ret != None:
  613. remote_file_url = ret["file"]
  614. menu_file = remote_file_url.split("raw.githubusercontent.com")[1]
  615. local_menu_file = "%s/aria2download%s" % (os.path.expanduser('~'),menu_file )
  616. try:
  617. if os.path.exists(local_menu_file):
  618. os.remove(local_menu_file)
  619. if os.path.exists(local_menu_file+".aria2"):
  620. os.remove(local_menu_file+".aria2")
  621. except Exception as ex:
  622. print(ex)
  623. c.execute("DELETE FROM tasks WHERE gid = '%s'" % gid )
  624. conn.commit()
  625. conn.close()
  626. except Exception as ex:
  627. print(ex)
  628. def Click(self):
  629. if self._PsIndex > len(self._MyList) -1:
  630. return
  631. cur_li = self._MyList[self._PsIndex]
  632. #if cur_li._Active == True:
  633. # return
  634. print("cur_li._Value",cur_li._Value)
  635. if cur_li._Value["type"] == "source" or cur_li._Value["type"] == "dir":
  636. remote_file_url = cur_li._Value["file"]
  637. menu_file = remote_file_url.split("raw.githubusercontent.com")[1] #assume master branch
  638. local_menu_file = "%s/aria2download%s" % (os.path.expanduser('~'),menu_file )
  639. print(local_menu_file)
  640. if FileExists( local_menu_file ) == False:
  641. self.LoadHouse()
  642. else:
  643. #read the local_menu_file, push into stack,display menu
  644. self._Downloading = None
  645. try:
  646. with open(local_menu_file) as json_file:
  647. local_menu_json = json.load(json_file)
  648. print(local_menu_json)
  649. self._MyStack.Push(local_menu_json["list"])
  650. self.SyncList()
  651. self._Screen.Draw()
  652. self._Screen.SwapAndShow()
  653. except Exception as ex:
  654. print(ex)
  655. self._Screen._MsgBox.SetText("Open house failed ")
  656. self._Screen._MsgBox.Draw()
  657. self._Screen.SwapAndShow()
  658. elif cur_li._Value["type"] == "add_house":
  659. print("show keyboard to add ware house")
  660. self._Screen.PushCurPage()
  661. self._Screen.SetCurPage( self._Keyboard )
  662. else:
  663. #download the game probably
  664. remote_file_url = cur_li._Value["file"]
  665. menu_file = remote_file_url.split("raw.githubusercontent.com")[1]
  666. local_menu_file = "%s/aria2download%s" % (os.path.expanduser('~'),menu_file )
  667. if FileExists( local_menu_file ) == False:
  668. gid,ret = config.RPC.urlDownloading(remote_file_url)
  669. if ret == False:
  670. gid = config.RPC.addUri( remote_file_url, options={"out": menu_file})
  671. self._Downloading = gid
  672. print("stack length ",self._MyStack.Length())
  673. if self._MyStack.Length() > 1:## not on the top list page
  674. try:
  675. conn = sqlite3.connect(self._aria2_db)
  676. c = conn.cursor()
  677. c.execute("INSERT INTO tasks(gid,title,file,type,status,fav) VALUES ('"+gid+"','"+cur_li._Value["title"]+"','"+cur_li._Value["file"]+"','"+cur_li._Value["type"]+"','active','0')")
  678. conn.commit()
  679. conn.close()
  680. except Exception as ex:
  681. print("SQLITE3 ",ex)
  682. else:
  683. print(config.RPC.tellStatus(gid,["status","totalLength","completedLength"]))
  684. self._Screen._MsgBox.SetText("Getting the game now")
  685. self._Screen._MsgBox.Draw()
  686. self._Screen.SwapAndShow()
  687. pygame.time.delay(800)
  688. self._Screen._TitleBar.Redraw()
  689. else:
  690. print("file downloaded")# maybe check it if is installed,then execute it
  691. if cur_li._Value["type"]=="launcher" and cur_li._ReadOnly == False:
  692. game_sh = os.path.join( "%s/apps/Menu/21_Indie Games/" % os.path.expanduser('~'),cur_li._Value["title"],cur_li._Value["title"]+".sh")
  693. #game_sh = reconstruct_broken_string( game_sh)
  694. print("run game: ",game_sh, os.path.exists( game_sh))
  695. self._Screen.RunEXE(game_sh)
  696. if cur_li._Value["type"]=="pico8" and cur_li._ReadOnly == False:
  697. if os.path.exists("/home/cpi/games/PICO-8/pico-8/pico8") == True:
  698. game_sh = "/home/cpi/launcher/Menu/GameShell/50_PICO-8/PICO-8.sh"
  699. self._Screen.RunEXE(game_sh)
  700. else:
  701. self._Screen._MsgBox.SetText("Purchase pico8")
  702. self._Screen._MsgBox.Draw()
  703. self._Screen.SwapAndShow()
  704. if cur_li._Value["type"]=="tic80" and cur_li._ReadOnly == False:
  705. game_sh = "/home/cpi/apps/Menu/51_TIC-80/TIC-80.sh"
  706. self._Screen.RunEXE(game_sh)
  707. def OnAria2CompleteCb(self,gid):
  708. print("OnAria2CompleteCb ", gid)
  709. def raw_github_com(self,_url):#eg: github.com/clockworkpi/warehouse
  710. if _url.startswith("github.com")== False:
  711. return False
  712. parts = _url.split("/")
  713. if len(parts) != 3:
  714. return False
  715. return "/".join(["https://raw.githubusercontent.com",parts[1],parts[2],"master/index.json"])
  716. def OnKbdReturnBackCb(self):
  717. inputed = "".join(self._Keyboard._Textarea._MyWords).strip()
  718. inputed = inputed.replace("http://","")
  719. inputed = inputed.replace("https://","")
  720. if inputed.endswith(".git"):
  721. inputed = inputed[:len(inputed)-4]
  722. if inputed.endswith("/"):
  723. inputed = inputed[:len(inputed)-1]
  724. print("last: ",inputed)
  725. try:
  726. conn = sqlite3.connect(self._warehouse_db)
  727. conn.row_factory = dict_factory
  728. c = conn.cursor()
  729. ret = c.execute("SELECT * FROM warehouse WHERE title='%s'" % inputed ).fetchone()
  730. if ret != None:
  731. self._Screen._MsgBox.SetText("Warehouse existed!")
  732. self._Screen._MsgBox.Draw()
  733. self._Screen.SwapAndShow()
  734. else:
  735. valid_url= self.raw_github_com(inputed)
  736. if valid_url == False:
  737. self._Screen._MsgBox.SetText("Warehouse existed!")
  738. self._Screen._MsgBox.Draw()
  739. self._Screen.SwapAndShow()
  740. else:
  741. sql_insert = """ INSERT INTO warehouse(title,file,type) VALUES(
  742. '%s',
  743. '%s',
  744. 'source');""" % (inputed,valid_url)
  745. c.execute(sql_insert)
  746. conn.commit()
  747. self.SyncList()
  748. conn.close()
  749. except Exception as ex:
  750. print(ex)
  751. def OnLoadCb(self):
  752. self._Scrolled = 0
  753. self._PosY = 0
  754. self._DrawOnce = False
  755. #sync
  756. print("OnLoadCb")
  757. if self._MyStack.Length() == 1:
  758. self._FootMsg[2] = "Remove"
  759. self._FootMsg[1] = "UpdateWare"
  760. else:
  761. self._FootMsg[2] = "Up"
  762. self._FootMsg[1] = ""
  763. self.SyncList()
  764. def OnReturnBackCb(self):
  765. if self._MyStack.Length() == 1:
  766. self._FootMsg[2] = "Remove"
  767. self._FootMsg[1] = "UpdateWare"
  768. else:
  769. self._FootMsg[2] = ""
  770. self._FootMsg[1] = ""
  771. self.SyncList()
  772. self._Screen.Draw()
  773. self._Screen.SwapAndShow()
  774. """
  775. self.ReturnToUpLevelPage()
  776. self._Screen.Draw()
  777. self._Screen.SwapAndShow()
  778. """
  779. def KeyDown(self,event):
  780. if IsKeyMenuOrB(event.key):
  781. if self._MyStack.Length() > 1:
  782. self._MyStack.Pop()
  783. if self._MyStack.Length() == 1:
  784. self._FootMsg[2] = "Remove"
  785. self._FootMsg[1] = "UpdateWare"
  786. else:
  787. self._FootMsg[2] = ""
  788. self._FootMsg[1] = "Preview"
  789. self.SyncList()
  790. self._Screen.Draw()
  791. self._Screen.SwapAndShow()
  792. elif self._MyStack.Length() == 1:
  793. self.ReturnToUpLevelPage()
  794. self._Screen.Draw()
  795. self._Screen.SwapAndShow()
  796. if IsKeyStartOrA(event.key):
  797. self.Click()
  798. if self._MyStack.Length() == 1:
  799. self._FootMsg[2] = "Remove"
  800. self._FootMsg[1] = "UpdateWare"
  801. else:
  802. self._FootMsg[2] = ""
  803. self._FootMsg[1] = "Preview"
  804. self._Screen.Draw()
  805. self._Screen.SwapAndShow()
  806. if event.key == CurKeys["X"]:
  807. #print(self._MyStack.Length() )
  808. if self._MyStack.Length() == 1 and self._PsIndex > 0:
  809. self._Screen.PushPage(self._remove_page)
  810. self._remove_page._StartOrA_Event = self.RemoveGame
  811. self._Screen.Draw()
  812. self._Screen.SwapAndShow()
  813. return
  814. """
  815. if self._MyStack.Length() > 1:
  816. self._MyStack.Pop()
  817. if self._MyStack.Length() == 1:
  818. self._FootMsg[2] = "Remove"
  819. self._FootMsg[1] = "UpdateWare"
  820. else:
  821. self._FootMsg[2] = "Up"
  822. self._FootMsg[1] = "Preview"
  823. """
  824. self.SyncList()
  825. self._Screen.Draw()
  826. self._Screen.SwapAndShow()
  827. if event.key == CurKeys["Y"]:
  828. if self._MyStack.Length() == 1:
  829. self.ResetHouse()
  830. else:
  831. self.PreviewGame()
  832. if event.key == CurKeys["Up"]:
  833. self.ScrollUp()
  834. self._Screen.Draw()
  835. self._Screen.SwapAndShow()
  836. if event.key == CurKeys["Down"]:
  837. self.ScrollDown()
  838. self._Screen.Draw()
  839. self._Screen.SwapAndShow()
  840. def Draw(self):
  841. self.ClearCanvas()
  842. if len(self._MyList) == 0:
  843. return
  844. else:
  845. if len(self._MyList) * self._MyList[0]._Height > self._Height:
  846. self._Ps._Width = self._Width - 11
  847. self._Ps.Draw()
  848. for i in self._MyList:
  849. if i._PosY > self._Height + self._Height/2:
  850. break
  851. if i._PosY < 0:
  852. continue
  853. i.Draw()
  854. self._Scroller.UpdateSize( len(self._MyList)*self._MyList[0]._Height, self._PsIndex*self._MyList[0]._Height)
  855. self._Scroller.Draw()
  856. else:
  857. self._Ps._Width = self._Width
  858. self._Ps.Draw()
  859. for i in self._MyList:
  860. if i._PosY > self._Height + self._Height/2:
  861. break
  862. if i._PosY < 0:
  863. continue
  864. i.Draw()
  865. if self._HWND != None:
  866. self._HWND.fill(MySkinManager.GiveColor("White"))
  867. self._HWND.blit(self._CanvasHWND,(self._PosX,self._PosY,self._Width, self._Height ) )
  868. class APIOBJ(object):
  869. _Page = None
  870. def __init__(self):
  871. pass
  872. def Init(self,main_screen):
  873. self._Page = GameStorePage()
  874. self._Page._Screen = main_screen
  875. self._Page._Name ="Warehouse"
  876. self._Page.Init()
  877. def API(self,main_screen):
  878. if main_screen !=None:
  879. main_screen.PushPage(self._Page)
  880. main_screen.Draw()
  881. main_screen.SwapAndShow()
  882. OBJ = APIOBJ()
  883. def Init(main_screen):
  884. OBJ.Init(main_screen)
  885. def API(main_screen):
  886. OBJ.API(main_screen)