enebootools 2.3.1__tar.gz → 2.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. {enebootools-2.3.1/enebootools.egg-info → enebootools-2.4}/PKG-INFO +3 -2
  2. {enebootools-2.3.1 → enebootools-2.4}/enebootools/__init__.py +1 -1
  3. {enebootools-2.3.1 → enebootools-2.4}/enebootools/assembler/__init__.py +23 -1
  4. enebootools-2.4/enebootools/assembler/copylib.py +40 -0
  5. {enebootools-2.3.1 → enebootools-2.4}/enebootools/assembler/database.py +37 -1
  6. {enebootools-2.3.1 → enebootools-2.4}/enebootools/assembler/kobjects.py +2 -2
  7. {enebootools-2.3.1 → enebootools-2.4}/enebootools/entry_points.py +9 -0
  8. {enebootools-2.3.1 → enebootools-2.4}/enebootools/mergetool/flpatchdir.py +7 -0
  9. enebootools-2.4/enebootools/uiimage/__init__.py +102 -0
  10. enebootools-2.4/enebootools/uiimage/uiimage.py +406 -0
  11. {enebootools-2.3.1 → enebootools-2.4/enebootools.egg-info}/PKG-INFO +3 -2
  12. {enebootools-2.3.1 → enebootools-2.4}/enebootools.egg-info/SOURCES.txt +3 -0
  13. {enebootools-2.3.1 → enebootools-2.4}/AUTHORS +0 -0
  14. {enebootools-2.3.1 → enebootools-2.4}/LICENSE.gplv3 +0 -0
  15. {enebootools-2.3.1 → enebootools-2.4}/README.rst +0 -0
  16. {enebootools-2.3.1 → enebootools-2.4}/enebootools/__init__.pyc +0 -0
  17. {enebootools-2.3.1 → enebootools-2.4}/enebootools/assembler/config.py +0 -0
  18. {enebootools-2.3.1 → enebootools-2.4}/enebootools/assembler/databasemodels.py +0 -0
  19. {enebootools-2.3.1 → enebootools-2.4}/enebootools/assembler/featureconfig.py +0 -0
  20. {enebootools-2.3.1 → enebootools-2.4}/enebootools/assembler/mypeewee.py +0 -0
  21. {enebootools-2.3.1 → enebootools-2.4}/enebootools/assembler/save_auto.py +0 -0
  22. {enebootools-2.3.1 → enebootools-2.4}/enebootools/autoconfig/__init__.py +0 -0
  23. {enebootools-2.3.1 → enebootools-2.4}/enebootools/autoconfig/autoconfig.py +0 -0
  24. {enebootools-2.3.1 → enebootools-2.4}/enebootools/autoconfig/parsers.py +0 -0
  25. {enebootools-2.3.1 → enebootools-2.4}/enebootools/config/__init__.py +0 -0
  26. {enebootools-2.3.1 → enebootools-2.4}/enebootools/crypto/__init__.py +0 -0
  27. {enebootools-2.3.1 → enebootools-2.4}/enebootools/crypto/certificates/CA_Partners_Gestiweb.crt +0 -0
  28. {enebootools-2.3.1 → enebootools-2.4}/enebootools/crypto/certificates/CA_Test_Partners.crt +0 -0
  29. {enebootools-2.3.1 → enebootools-2.4}/enebootools/crypto/certificates/Eneboo_Open_Source_ERP.crt +0 -0
  30. {enebootools-2.3.1 → enebootools-2.4}/enebootools/crypto/certificates/Partner_Test.crt +0 -0
  31. {enebootools-2.3.1 → enebootools-2.4}/enebootools/crypto/certificates/Partner_Test.pem +0 -0
  32. {enebootools-2.3.1 → enebootools-2.4}/enebootools/crypto/certificates/README.txt +0 -0
  33. {enebootools-2.3.1 → enebootools-2.4}/enebootools/crypto/certificates/__init__.py +0 -0
  34. {enebootools-2.3.1 → enebootools-2.4}/enebootools/crypto/main.py +0 -0
  35. {enebootools-2.3.1 → enebootools-2.4}/enebootools/databaseadmin/__init__.py +0 -0
  36. {enebootools-2.3.1 → enebootools-2.4}/enebootools/databaseadmin/dblayer/__init__.py +0 -0
  37. {enebootools-2.3.1 → enebootools-2.4}/enebootools/databaseadmin/dblayer/drivers.py +0 -0
  38. {enebootools-2.3.1 → enebootools-2.4}/enebootools/extracttool/__init__.py +0 -0
  39. {enebootools-2.3.1 → enebootools-2.4}/enebootools/extracttool/extractfunctions.py +0 -0
  40. {enebootools-2.3.1 → enebootools-2.4}/enebootools/lib/__init__.py +0 -0
  41. {enebootools-2.3.1 → enebootools-2.4}/enebootools/lib/etree/ElementInclude.py +0 -0
  42. {enebootools-2.3.1 → enebootools-2.4}/enebootools/lib/etree/ElementPath.py +0 -0
  43. {enebootools-2.3.1 → enebootools-2.4}/enebootools/lib/etree/ElementTree.py +0 -0
  44. {enebootools-2.3.1 → enebootools-2.4}/enebootools/lib/etree/__init__.py +0 -0
  45. {enebootools-2.3.1 → enebootools-2.4}/enebootools/lib/etree/cElementTree.py +0 -0
  46. {enebootools-2.3.1 → enebootools-2.4}/enebootools/lib/peewee.py +0 -0
  47. {enebootools-2.3.1 → enebootools-2.4}/enebootools/lib/utils.py +0 -0
  48. {enebootools-2.3.1 → enebootools-2.4}/enebootools/mergetool/__init__.py +0 -0
  49. {enebootools-2.3.1 → enebootools-2.4}/enebootools/mergetool/etc/__init__.py +0 -0
  50. {enebootools-2.3.1 → enebootools-2.4}/enebootools/mergetool/etc/formats/__init__.py +0 -0
  51. {enebootools-2.3.1 → enebootools-2.4}/enebootools/mergetool/etc/formats/aq23-kut.xml +0 -0
  52. {enebootools-2.3.1 → enebootools-2.4}/enebootools/mergetool/etc/formats/aq23-mtd.xml +0 -0
  53. {enebootools-2.3.1 → enebootools-2.4}/enebootools/mergetool/etc/formats/aq23-xml.xml +0 -0
  54. {enebootools-2.3.1 → enebootools-2.4}/enebootools/mergetool/etc/formats/qt3-ts.xml +0 -0
  55. {enebootools-2.3.1 → enebootools-2.4}/enebootools/mergetool/etc/formats/qt3-ui.xml +0 -0
  56. {enebootools-2.3.1 → enebootools-2.4}/enebootools/mergetool/etc/index.xml +0 -0
  57. {enebootools-2.3.1 → enebootools-2.4}/enebootools/mergetool/etc/patch-styles/__init__.py +0 -0
  58. {enebootools-2.3.1 → enebootools-2.4}/enebootools/mergetool/etc/patch-styles/legacy1-savepatch1.xsl +0 -0
  59. {enebootools-2.3.1 → enebootools-2.4}/enebootools/mergetool/etc/patch-styles/legacy1.xml +0 -0
  60. {enebootools-2.3.1 → enebootools-2.4}/enebootools/mergetool/etc/patch-styles/semantic1.xml +0 -0
  61. {enebootools-2.3.1 → enebootools-2.4}/enebootools/mergetool/flpatchapipy.py +0 -0
  62. {enebootools-2.3.1 → enebootools-2.4}/enebootools/mergetool/flpatchlxml.py +0 -0
  63. {enebootools-2.3.1 → enebootools-2.4}/enebootools/mergetool/flpatchmodel.py +0 -0
  64. {enebootools-2.3.1 → enebootools-2.4}/enebootools/mergetool/flpatchpy.py +0 -0
  65. {enebootools-2.3.1 → enebootools-2.4}/enebootools/mergetool/flpatchqs.py +0 -0
  66. {enebootools-2.3.1 → enebootools-2.4}/enebootools/mergetool/flpatchtest.py +0 -0
  67. {enebootools-2.3.1 → enebootools-2.4}/enebootools/mergetool/flpatchxml.py +0 -0
  68. {enebootools-2.3.1 → enebootools-2.4}/enebootools/mergetool/projectbuilder.py +0 -0
  69. {enebootools-2.3.1 → enebootools-2.4}/enebootools/mergetool/test/__init__.py +0 -0
  70. {enebootools-2.3.1 → enebootools-2.4}/enebootools/mergetool/test/test_mergetool.py +0 -0
  71. {enebootools-2.3.1 → enebootools-2.4}/enebootools/packager/__init__.py +0 -0
  72. {enebootools-2.3.1 → enebootools-2.4}/enebootools/packager/pkgjoiner.py +0 -0
  73. {enebootools-2.3.1 → enebootools-2.4}/enebootools/packager/pkgsplitter.py +0 -0
  74. {enebootools-2.3.1 → enebootools-2.4}/enebootools/parseargs.py +0 -0
  75. {enebootools-2.3.1 → enebootools-2.4}/enebootools/parseargs.pyc +0 -0
  76. {enebootools-2.3.1 → enebootools-2.4}/enebootools/parser/__init__.py +0 -0
  77. {enebootools-2.3.1 → enebootools-2.4}/enebootools/tools/__init__.py +0 -0
  78. {enebootools-2.3.1 → enebootools-2.4}/enebootools/tools/ar2kut.py +0 -0
  79. {enebootools-2.3.1 → enebootools-2.4}/enebootools/tools/dumps.py +0 -0
  80. {enebootools-2.3.1 → enebootools-2.4}/enebootools/tools/git.py +0 -0
  81. {enebootools-2.3.1 → enebootools-2.4}/enebootools/vcsworkflow/__init__.py +0 -0
  82. {enebootools-2.3.1 → enebootools-2.4}/enebootools.egg-info/dependency_links.txt +0 -0
  83. {enebootools-2.3.1 → enebootools-2.4}/enebootools.egg-info/entry_points.txt +0 -0
  84. {enebootools-2.3.1 → enebootools-2.4}/enebootools.egg-info/requires.txt +0 -0
  85. {enebootools-2.3.1 → enebootools-2.4}/enebootools.egg-info/top_level.txt +0 -0
  86. {enebootools-2.3.1 → enebootools-2.4}/setup.cfg +0 -0
  87. {enebootools-2.3.1 → enebootools-2.4}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: enebootools
3
- Version: 2.3.1
3
+ Version: 2.4
4
4
  Summary: ERP tools for Eneboo
5
5
  Home-page: https://github.com/aulla/eneboo-tools
6
6
  Author: David Martínez Martí, José A. Fernández Fernández
@@ -35,6 +35,7 @@ Dynamic: description
35
35
  Dynamic: description-content-type
36
36
  Dynamic: home-page
37
37
  Dynamic: keywords
38
+ Dynamic: license-file
38
39
  Dynamic: requires-dist
39
40
  Dynamic: requires-python
40
41
  Dynamic: summary
@@ -8,7 +8,7 @@ from pprint import pformat
8
8
  import enebootools.parseargs as pa
9
9
 
10
10
 
11
- __VERSION__ = "2.3.1"
11
+ __VERSION__ = "2.4"
12
12
  QS_EXTEND_MODE = "legacy"
13
13
 
14
14
 
@@ -3,7 +3,7 @@
3
3
 
4
4
  from enebootools import EnebooToolsInterface
5
5
 
6
- from enebootools.assembler import database as asmdb
6
+ from enebootools.assembler import copylib, database as asmdb
7
7
  from enebootools.assembler import save_auto
8
8
  from enebootools.tools import dumps
9
9
 
@@ -144,6 +144,18 @@ class AssemblerInterface(EnebooToolsInterface):
144
144
  call_function=self.set_short_mode,
145
145
  )
146
146
 
147
+ self.copy_action = self.parser.declare_action(
148
+ name="copy",
149
+ args=["ext_name", "folder"],
150
+ description="Copia la $ext_name y dependencias en la carpeta $folder",
151
+ options=[""],
152
+ call_function=self.do_copy_action,
153
+ )
154
+ self.copy_action.set_help_arg(
155
+ ext_name="Nombre de la extensión a copiar",
156
+ classlist="Carpeta donde se va a copiar la extensión y dependencias",
157
+ )
158
+
147
159
  # :::: ACTIONS ::::
148
160
 
149
161
  def do_dbupdate(self):
@@ -214,5 +226,15 @@ class AssemblerInterface(EnebooToolsInterface):
214
226
  except Exception as e:
215
227
  self.exception(type(e).__name__, str(e))
216
228
 
229
+ def do_copy_action(self, ext_name, folder):
230
+ try:
231
+ # 1 Comprobar si la carpeta es valida y existe
232
+ # 2 Sacar depednencias de extensiones y módulos
233
+ # 3 copiar.
234
+ return copylib.do_copy_action(self, ext_name, folder)
235
+
236
+ except Exception as e:
237
+ self.exception(type(e).__name__, str(e))
238
+
217
239
  def set_short_mode(self):
218
240
  self.short_mode = True
@@ -0,0 +1,40 @@
1
+ # encoding: UTF-8
2
+
3
+ import os
4
+ import shutil
5
+ from enebootools.assembler import database as asmdb
6
+
7
+ def do_copy_action(iface, ext_name, dest_folder):
8
+ if not check_if_folder_is_valid(dest_folder):
9
+ return False
10
+
11
+ if os.path.exists(dest_folder):
12
+ shutil.rmtree(dest_folder)
13
+ os.makedirs(dest_folder)
14
+
15
+ features, modules = asmdb.deps(iface, ext_name)
16
+ # Copiamos extensiones
17
+ for feat in features:
18
+ copy_dep_to_folder(iface, feat, "features" , dest_folder)
19
+ for module in modules:
20
+ copy_dep_to_folder(iface, module, "modules", dest_folder)
21
+
22
+
23
+
24
+ return True
25
+
26
+ def copy_dep_to_folder(iface, feat, subfolder, dest_folder):
27
+ orig_folder = asmdb.dep_main_folder(iface, feat)
28
+ final_folder = os.path.join(dest_folder, subfolder, feat)
29
+ #si esxiste finalfolder lo borro
30
+ print("Copiando %s desde %s a %s" % (feat, orig_folder, final_folder))
31
+ shutil.copytree(orig_folder, final_folder)
32
+
33
+ def check_if_folder_is_valid(dest_folder):
34
+ if not os.path.exists(dest_folder):
35
+ print("El directorio %s no existe" % dest_folder)
36
+ return False
37
+ if not os.path.isdir(dest_folder):
38
+ print("%s no es un directorio" % dest_folder)
39
+ return False
40
+ return True
@@ -21,7 +21,7 @@ from enebootools.mergetool import MergeToolInterface
21
21
  from .databasemodels import KnownObjects
22
22
 
23
23
  from .mypeewee import transactional
24
- from .kobjects import ObjectIndex, FeatureObject
24
+ from .kobjects import ObjectIndex, FeatureObject, ModuleObject
25
25
 
26
26
  DISABLE_AR2KUT = False
27
27
 
@@ -351,6 +351,42 @@ def test_deps(iface, feat):
351
351
  print()
352
352
 
353
353
 
354
+ def dep_main_folder(iface, feat):
355
+ db = init_database()
356
+ obj = FeatureObject.find(feat)
357
+ if not obj:
358
+ obj = ModuleObject.find(feat)
359
+
360
+ if not obj:
361
+ iface.error("No se encuentra %s" % feat)
362
+ return
363
+
364
+ return obj.fullpath
365
+
366
+
367
+
368
+ def deps(iface, feat):
369
+ db = init_database()
370
+ oi = ObjectIndex(iface)
371
+ oi.analyze_objects()
372
+ patchname = oi.get_patch_name(feat, default=True)
373
+ feature = FeatureObject.find(feat)
374
+ patch_folder = os.path.join(feature.fullpath, "patches", patchname)
375
+
376
+ file_index = oi.index_by_file()
377
+ from enebootools.mergetool.flpatchdir import FolderApplyPatch
378
+
379
+ fpatch = FolderApplyPatch(iface, patch_folder)
380
+ info = fpatch.get_patch_info()
381
+ fdep_features = feature._get_full_required_features()[:]
382
+ fdep_modules = feature._get_full_required_modules()[:]
383
+ fdep_features.append(feature.formal_name())
384
+ orig_fdep_features = fdep_features[:]
385
+ orig_fdep_modules = fdep_modules[:]
386
+
387
+ return [orig_fdep_features, orig_fdep_modules]
388
+
389
+
354
390
  def select_option(
355
391
  title,
356
392
  options,
@@ -390,8 +390,8 @@ class FeatureObject(BaseObject):
390
390
  srcpath = os.path.join(self.fullpath, "patches", patchdir)
391
391
  fpatch = FolderApplyPatch(self.iface, srcpath)
392
392
  info = fpatch.get_patch_info()
393
- self.info["provides"] += info["provides"]
394
- self.info["requires"] += info["requires"]
393
+ self.info["provides"] += info["provides"] if info else []
394
+ self.info["requires"] += info["requires"] if info else []
395
395
  return self.info
396
396
 
397
397
  # * base: compila las dependencias del proyecto (todo lo que necesitamos
@@ -46,3 +46,12 @@ def main_extract_tool():
46
46
  if iface.parse_args(): # parsea los argumentos de entrada de consola
47
47
  # Si el parseo no devuelve error,
48
48
  iface.execute_actions() # ejecuta las acciones detectadas.
49
+
50
+ def main_uiimage():
51
+ from enebootools.uiimage import UIImageInterface
52
+
53
+ iface = UIImageInterface()
54
+
55
+ if iface.parse_args(): # parsea los argumentos de entrada de consola
56
+ # Si el parseo no devuelve error,
57
+ iface.execute_actions() # ejecuta las acciones detectadas.
@@ -159,6 +159,9 @@ class FolderApplyPatch(object):
159
159
  actionname = action.tag.split("}")[1]
160
160
  actionname = actionname.lower()
161
161
 
162
+ if ":" in actionname:
163
+ actionname = actionname.split(":")[1]
164
+
162
165
  pathname = os.path.join(action.get("path"), action.get("name"))
163
166
 
164
167
  atype = None
@@ -170,6 +173,10 @@ class FolderApplyPatch(object):
170
173
  atype = "requires"
171
174
  elif actionname == "patchxml":
172
175
  atype = "requires"
176
+ elif actionname == "patchpy":
177
+ atype = "requires"
178
+ elif actionname == "deletefile":
179
+ continue
173
180
  info[atype].append(pathname)
174
181
  return info
175
182
 
@@ -0,0 +1,102 @@
1
+ # encoding: UTF-8
2
+ __version__ = "1.0.0"
3
+ __PROGRAM__NAME__ = "Eneboo Tools UIImage"
4
+ from enebootools.uiimage import uiimage
5
+ from enebootools import EnebooToolsInterface
6
+
7
+ """
8
+ Packager es una utilidad para Eneboo que realiza paquetes al estilo
9
+ .eneboopkg o .abanq que luego el motor Eneboo puede leer y cargar
10
+
11
+ Un paquete .eneboopkg es una serialización de ficheros que contiene los
12
+ módulos y ficheros a cargar en una base de datos.
13
+
14
+ """
15
+
16
+
17
+ class UIImageInterface(EnebooToolsInterface):
18
+ module_description = "Herramientas para extraer imágenes de los ficheros .UI"
19
+
20
+ def __init__(self, setup_parser=True):
21
+ EnebooToolsInterface.__init__(self, False)
22
+ self.packager_mode = None
23
+ self.include_test = False
24
+ if setup_parser:
25
+ self.setup_parser()
26
+
27
+ def setup_parser(self):
28
+ EnebooToolsInterface.setup_parser(self)
29
+
30
+ self.download_action = self.parser.declare_action(
31
+ name="download",
32
+ args=["filename"],
33
+ options=[],
34
+ description="Extrae las imagenes de un fichero dado",
35
+ call_function=self.do_download,
36
+ )
37
+
38
+ self.check_action = self.parser.declare_action(
39
+ name="check",
40
+ args=["filename"],
41
+ options=[],
42
+ description="Comprueba las imagenes de un fichero dado",
43
+ call_function=self.do_check,
44
+ )
45
+
46
+ self.upload_action = self.parser.declare_action(
47
+ name="upload",
48
+ args=["filename", "files"],
49
+ options=[],
50
+ description="Inserta las imagenes $files en un fichero dado $filename",
51
+ call_function=self.do_upload,
52
+ )
53
+
54
+ self.fix_data_len_action = self.parser.declare_action(
55
+ name="fixdatalen",
56
+ args=["filename"],
57
+ options=[],
58
+ description="Repasa el tamaño de las imagenes que contiene un fichero",
59
+ call_function=self.do_fixdatalen,
60
+ )
61
+
62
+ self.theme_action = self.parser.declare_action(
63
+ name="theme",
64
+ args=["filename", "project_path", "method"],
65
+ options=[],
66
+ description="eneboo-uiimage theme [archivo theme] [ruta proyecto] [metodo]. overwrite: sobreescribe el/los archivos, modify: crea un nuevo archivo adjuntando el sufijo -modify",
67
+ call_function=self.do_theme,
68
+ )
69
+
70
+ # :::: ACTIONS ::::
71
+
72
+ def do_download(self, filename):
73
+ try:
74
+
75
+ return uiimage.download_images(filename)
76
+ except Exception as e:
77
+ self.exception(type(e).__name__, str(e))
78
+
79
+ def do_check(self, filename):
80
+ try:
81
+ return uiimage.check_images(filename)
82
+ except Exception as e:
83
+ self.exception(type(e).__name__, str(e))
84
+
85
+ def do_upload(self, filename, files):
86
+ try:
87
+ return uiimage.upload_images(filename, files)
88
+ except Exception as e:
89
+ self.exception(type(e).__name__, str(e))
90
+
91
+ def do_fixdatalen(self, filename):
92
+ try:
93
+ return uiimage.fix_datalen(filename)
94
+ except Exception as e:
95
+ self.exception(type(e).__name__, str(e))
96
+ def do_theme(self, filename, proyect_path, method):
97
+ try:
98
+ return uiimage.searchFile(filename, proyect_path, method)
99
+ except Exception as e:
100
+ self.exception(type(e).__name__, str(e))
101
+
102
+
@@ -0,0 +1,406 @@
1
+ #!/usr/bin/python3
2
+ import os, os.path
3
+ import binascii
4
+ from lxml import etree
5
+
6
+ # debug = "--debug"
7
+ debug = "no"
8
+
9
+ def download_images(filename):
10
+ parser = etree.XMLParser(ns_clean=True,recover=True,remove_blank_text=True)
11
+ tree = etree.parse(filename, parser)
12
+ for image in tree.xpath("/UI/images/image"):
13
+ imgname = image.attrib["name"]
14
+ for data in image.xpath("data"):
15
+ datalen = int(data.attrib["length"])
16
+ dataformat = str(data.attrib["format"]).lower()
17
+ hexdata = str(data.text)
18
+ try: assert(datalen == len(hexdata))
19
+ except AssertionError: print("WARN: La longitud de la imagen %s especificada en el atributo %d no cumple la real %d" % (imgname,datalen, len(hexdata)))
20
+ binary = binascii.unhexlify(hexdata)
21
+ img_filename = imgname+"."+dataformat
22
+ f1 = open(img_filename,"wb")
23
+ f1.write(binary)
24
+ f1.close()
25
+ print("Image file %s written." % (img_filename))
26
+
27
+ def check_images(filename):
28
+ parser = etree.XMLParser(ns_clean=True,recover=True,remove_blank_text=True)
29
+ tree = etree.parse(filename, parser)
30
+ image_list = []
31
+ for image in tree.xpath("/UI/images/image"):
32
+ imgname = image.attrib["name"]
33
+ for data in image.xpath("data"):
34
+ datalen = int(data.attrib["length"])
35
+ dataformat = str(data.attrib["format"]).lower()
36
+ hexdata = str(data.text)
37
+ try: assert(datalen == len(hexdata))
38
+ except AssertionError: print("WARN: La longitud de la imagen %s especificada en el atributo %d no cumple la real %d" % (imgname,datalen, len(hexdata)))
39
+ image_list.append(imgname)
40
+
41
+ used_image_list = []
42
+ for iconset in tree.xpath("//widget/property/iconset"):
43
+ imgname = iconset.text.strip()
44
+ used_image_list.append(imgname)
45
+ if imgname not in image_list:
46
+ print("Imagen '%s' no existe. Este es el control:" % imgname)
47
+ print(etree.tostring(iconset.getparent().getparent(), pretty_print=True,))
48
+ print()
49
+ unused_images = list(set(image_list) - set(used_image_list) )
50
+ if unused_images:
51
+ print("Algunas imagenes no se usan:", ", ".join(unused_images))
52
+
53
+
54
+
55
+
56
+ def upload_images(filename, files):
57
+ parser = etree.XMLParser(ns_clean=True,recover=True,remove_blank_text=True)
58
+ tree = etree.parse(filename, parser)
59
+ root = tree.getroot()
60
+ try: tagimages = tree.xpath("/UI/images")[0]
61
+ except IndexError: tagimages = etree.SubElement(root, "images")
62
+
63
+ for imgfile in files:
64
+ name, format = os.path.splitext(os.path.basename(imgfile))
65
+ bindata = open(imgfile).read()
66
+ hexdata = binascii.hexlify(bindata)
67
+ lendata = len(hexdata)
68
+ if format.startswith("."): format = format[1:]
69
+ format = format.upper()
70
+ task = "Created"
71
+ for image in tree.xpath("/UI/images/image[@name='%s']" % name):
72
+ tagimages.remove(image)
73
+ task = "Overwritten"
74
+ newimage = etree.SubElement(tagimages, "image", name = name)
75
+ newdata = etree.SubElement(newimage, "data", format = format, length = str(lendata))
76
+ newdata.text = hexdata
77
+ print("%s image %s with format %s datalen %d" % (task, name, format, lendata))
78
+
79
+
80
+ open(filename,"w").write(etree.tostring(tree, pretty_print=True, encoding='unicode'))
81
+
82
+
83
+ def fix_datalen(filename):
84
+ tree = etree.parse(filename)
85
+ for image in tree.xpath("/UI/images/image"):
86
+ imgname = image.attrib["name"]
87
+ for data in image.xpath("data"):
88
+ datalen = int(data.attrib["length"])
89
+ hexdata = str(data.text)
90
+ try: assert(datalen == len(hexdata))
91
+ except AssertionError:
92
+ data.attrib['length'] = str(len(hexdata))
93
+ print("La longitud de la imagen %s especificada %d se ha corregido por la real %d" % (imgname,datalen, len(hexdata)))
94
+ tree.write(filename, encoding='utf-8')
95
+
96
+
97
+ def eliminarImageElem(image, images, imageLast):
98
+ if image.getparent() is not None:
99
+ if image.attrib["name"] == imageLast:
100
+ images.remove(image)
101
+
102
+
103
+ def eliminarMaximumSize(widget):
104
+ widgetProp = widget.find('property')
105
+ for widgetProp in widget.iter('property'):
106
+ nameProp = widgetProp.get('name')
107
+ if nameProp == "maximumSize":
108
+ widget.remove(widgetProp)
109
+
110
+
111
+ def genImageElem(images, image_name, data_format, data_length, data_text):
112
+ imageElem = etree.SubElement(images, "image")
113
+ imageElem.set("name", image_name)
114
+ data = etree.SubElement(imageElem, "data")
115
+ data.set("format", data_format)
116
+ data.set("lenght", data_length)
117
+ data.text = data_text
118
+
119
+
120
+ def readImageName(cstring, fileTheme):
121
+ treeImg = etree.parse(fileTheme)
122
+ rootImg = treeImg.getroot()
123
+ for widgetImg in rootImg.iter('widget'):
124
+ claseImg = widgetImg.get('class')
125
+ cstringImg = widgetImg.find('property/cstring').text
126
+ icono = None
127
+ if cstringImg in cstring:
128
+ if claseImg == "QToolButton":
129
+ icono = widgetImg.find('property/iconset')
130
+ if claseImg == "QPushButton":
131
+ icono = widgetImg.find('property/pixmap')
132
+ if icono is not None:
133
+ image_name = icono.text
134
+ return image_name
135
+
136
+
137
+ def readImageData(image_name, fileTheme):
138
+ treeImg = etree.parse(fileTheme)
139
+ rootImg = treeImg.getroot()
140
+ imagesImg = rootImg.find("images")
141
+ for imageImg in imagesImg:
142
+ if imageImg.get('name') == image_name:
143
+ data = imageImg.find('data')
144
+ data_format = data.get('format')
145
+ data_length = data.get('length')
146
+ data_text = data.text
147
+ return data_format, data_length, data_text
148
+
149
+
150
+ # Configurar el QFrame barraBotones
151
+ def fixBarraBotones(tree, ficheroSalida):
152
+ if debug == "--debug":
153
+ print("------------------------------------------------------------------")
154
+ print("fixBarraBotones():: Configurar Spacing y Margin del hbox barraBotones")
155
+ print("------------------------------------------------------------------")
156
+ root = tree.getroot()
157
+ barraExist = "0"
158
+ for widget in root.iter('widget'):
159
+ cstring = widget.find('property/cstring').text
160
+ if cstring == "barraBotones":
161
+ barraExist = "1"
162
+ # Buscamos las propiedades spacing y margin
163
+ layoutSpacing = widget.find("hbox/property[@name='spacing']")
164
+ layoutMargin = widget.find("hbox/property[@name='margin']")
165
+ if layoutSpacing is None:
166
+ print(" No se encuentra la propiedad spacing")
167
+ else:
168
+ print(" actualizando layoutSpacing")
169
+ layoutSpacing.find("number").text = "2"
170
+
171
+ if layoutMargin is None:
172
+ print(" No se encuentra la propiedad margin")
173
+ else:
174
+ print(" actualizando layoutMargin")
175
+ layoutMargin.find("number").text = "4"
176
+ if barraExist == "0":
177
+ print(" No existe barraBotones en el archivo")
178
+ if barraExist == "1":
179
+ print(" Se graba el archivo")
180
+ grabarFichero(tree, ficheroSalida)
181
+
182
+
183
+ def changeButtonSize(tree, widget):
184
+ if debug == "--debug":
185
+ print("------------------------------------------------------------------")
186
+ print("changeButtonSize():: Configurar propiedades minimumSize y maximumSize a 32")
187
+ print("------------------------------------------------------------------")
188
+ minimumSize = "0"
189
+ maximumSize = "0"
190
+ widgetProp = widget.find('property')
191
+ for widgetProp in widget.iter('property'):
192
+ nameProp = widgetProp.get('name')
193
+ if nameProp == "minimumSize" or nameProp == "maximumSize":
194
+ print(" La propiedad %s coincide, se configura a 32 de alto y ancho" % nameProp)
195
+ widgetProp.find('size/width').text = "32"
196
+ widgetProp.find('size/height').text = "32"
197
+ if nameProp == "minimumSize":
198
+ minimumSize = "1"
199
+ if nameProp == "maximumSize":
200
+ maximumSize = "1"
201
+ else:
202
+ print(" NO es la propiedad que se busca")
203
+ if minimumSize == "0":
204
+ print(" minimumSize no existia, se crea")
205
+ propGen = "minimumSize"
206
+ genSizeElem(tree, widget, propGen)
207
+ if maximumSize == "0":
208
+ print(" maximumSize no existia, se crea")
209
+ propGen = "maximumSize"
210
+ genSizeElem(tree, widget, propGen)
211
+
212
+
213
+ def genSizeElem(tree, widget, propGen):
214
+ newProp = etree.SubElement(widget, "property", name = propGen)
215
+ sizeProp = etree.SubElement(newProp, "size")
216
+ widthProp = etree.SubElement(sizeProp, "width")
217
+ heightProp = etree.SubElement(sizeProp, "height")
218
+ widthProp.text = "32"
219
+ heightProp.text = "32"
220
+
221
+
222
+ def changeImageName(widget, clase, image_name):
223
+ icono = widget.find('property/iconset')
224
+ if icono is None:
225
+ icono = widget.find('property/pixmap')
226
+ if icono is not None:
227
+ if icono.text == str(image_name):
228
+ imageLast = "Ignore"
229
+ return imageLast
230
+ else:
231
+ imageLast = icono.text
232
+ icono.text = str(image_name)
233
+ return imageLast
234
+
235
+
236
+ def changeImageData(tree, imageLast, image_name, data_format, data_length, data_text):
237
+ # Comprobamos que la imagen no exista en el archivo
238
+ imageExist = tree.find("//image[@name='%s']" % image_name)
239
+ if imageExist is not None:
240
+ # Si la imagen ya existe en vez de reemplar los atributos,
241
+ # se elimina el widget image correspondiente a la imagen cambiada
242
+ print(" La imagen %s ya existe en el archivo" % image_name)
243
+ for image in tree.xpath("//image[@name='%s']" % imageLast):
244
+ # Si el archivo es un parche, se sube un nivel
245
+ # y se elimina todo el widget xupdate con la imagen
246
+ if "xupdate" in image.getparent().tag:
247
+ widget_xupdate = image.getparent()
248
+ widget_xupdate.getparent().remove(widget_xupdate)
249
+ else:
250
+ #Si no es parche solo se elimina el widget image
251
+ image.getparent().remove(image)
252
+ else:
253
+ # Si no existe la imagen, se actualizan los atributos
254
+ # de la imagen existente por los atributos de la imagen del theme
255
+ for image in tree.xpath("//image[@name='%s']" % imageLast):
256
+ data = image.find('data')
257
+ image.attrib['name'] = image_name
258
+ data.attrib['format'] = data_format
259
+ data.attrib['length'] = data_length
260
+ data.text = data_text
261
+
262
+
263
+ def grabarFichero(tree, ficheroSalida):
264
+ tree.write(ficheroSalida, encoding='utf-8')
265
+
266
+
267
+ def applyActions(tree, widget, clase, cstring, fileTheme, ficheroSalida, files):
268
+ print("------------------------------------------------------------------")
269
+ print("applyActions()::Acciones para el Boton %s" % (cstring))
270
+ print("------------------------------------------------------------------")
271
+ ### Se lee las propiedades de la imagen del theme para poder aplicarlas
272
+ image_name_theme = readImageName(cstring, fileTheme)
273
+ data_format_theme = readImageData(image_name_theme, fileTheme)[0]
274
+ data_length_theme = readImageData(image_name_theme, fileTheme)[1]
275
+ data_text_theme = readImageData(image_name_theme, fileTheme)[2]
276
+ ### Se guarda en la variable el nombre de la imagen que sustituimos
277
+ imageLast = changeImageName(widget, clase, image_name_theme)
278
+ if debug == "--debug":
279
+ print(" Leer propiedad de la imagen en el archivo theme")
280
+ print(" Leer nombre: %s" % (image_name_theme))
281
+ print(" Leer formato: %s" % (data_format_theme))
282
+ print(" Leer lenght: %s" % (data_length_theme))
283
+ # print " Leer data: %s" % (data_text_theme)
284
+ print(" ____________________________________________________________________________________________________________________")
285
+ #### Se ejecuta el cambio de size
286
+ changeButtonSize(tree, widget)
287
+ ### Si la imagen ya existe se ignora, sino se ejecuta el cambio de propiedades
288
+ if imageLast == "Ignore":
289
+ print("El cambio de imagen SE IGNORA: Imagen %s ya cambiada" % (image_name_theme))
290
+ else:
291
+ changeImageData(tree, imageLast, image_name_theme, data_format_theme, data_length_theme, data_text_theme)
292
+ #
293
+ #eliminarImageElem(image, images, imageLast)
294
+ #eliminarMaximumSize(widget)
295
+ #genImageElem(images, image_name_theme, data_format_theme, data_length_theme, data_text_theme)
296
+ #
297
+ ### Grabamos el fichero una vez ejecutadas las funciones
298
+ grabarFichero(tree, ficheroSalida)
299
+ print(" Imagen %s sustituida por %s " % (imageLast, image_name_theme))
300
+ print("-----------------------------------------------")
301
+
302
+
303
+ def checkFile(ficheroEntrada, ficheroSalida, fileTheme, files):
304
+ parser = etree.XMLParser(ns_clean=True, recover=True, remove_blank_text=False)
305
+ tree = etree.parse(ficheroEntrada, parser)
306
+ root = tree.getroot()
307
+ if root is not None:
308
+ # images = root.find("images")
309
+ print("------------------------------------------------------------------")
310
+ print("checkFile():: Comprobando Archivo: %s" % (ficheroEntrada))
311
+ print("------------------------------------------------------------------")
312
+ # print " ficheroEntrada: %s" % (ficheroEntrada)
313
+ # print " ficheroSalida: %s" % (ficheroSalida)
314
+ # print " Theme: %s" % (fileTheme)
315
+ # print " Archivo: %s" % (files)
316
+ # print " root: %s" % (root)
317
+ #
318
+ # Se ejecuta funcion para acomodar barraBotones
319
+ fixBarraBotones(tree, ficheroSalida)
320
+ # Se procesa el cambio de botones
321
+ for widget in root.iter('widget'):
322
+ clase = widget.get('class')
323
+ cstring = widget.find('property/cstring').text
324
+ if cstring is not None:
325
+ if "toolButtonInsert" in cstring:
326
+ applyActions(tree, widget, clase, cstring, fileTheme, ficheroSalida, files)
327
+ if "toolButtomInsert" in cstring:
328
+ applyActions(tree, widget, clase, cstring, fileTheme, ficheroSalida, files)
329
+ if "toolButtonEdit" in cstring:
330
+ applyActions(tree, widget, clase, cstring, fileTheme, ficheroSalida, files)
331
+ if "toolButtonDelete" in cstring:
332
+ applyActions(tree, widget, clase, cstring, fileTheme, ficheroSalida, files)
333
+ if "toolButtonZoom" in cstring:
334
+ applyActions(tree, widget, clase, cstring, fileTheme, ficheroSalida, files)
335
+ if "toolButtonBrowse" in cstring:
336
+ applyActions(tree, widget, clase, cstring, fileTheme, ficheroSalida, files)
337
+ if "toolButtonCopy" in cstring:
338
+ applyActions(tree, widget, clase, cstring, fileTheme, ficheroSalida, files)
339
+ if "tbnDuplicar" in cstring:
340
+ applyActions(tree, widget, clase, cstring, fileTheme, ficheroSalida, files)
341
+ if "toolButtonPrint" in cstring:
342
+ applyActions(tree, widget, clase, cstring, fileTheme, ficheroSalida, files)
343
+ if "tbnEnviarMail" in cstring:
344
+ applyActions(tree, widget, clase, cstring, fileTheme, ficheroSalida, files)
345
+ else:
346
+ print("ATENCION: El fichero %s no tiene un formato valido" % (files))
347
+ print("____________________________________________________________________________________________________________________")
348
+ print(" ")
349
+
350
+
351
+ def searchFile(theme, rutaProyecto, metodo):
352
+ rutaProyectoNorm = os.path.normpath(rutaProyecto)
353
+ fileTheme = os.path.normpath(theme)
354
+ if debug == "--debug":
355
+ print("--------------------------------------------------------------------------------------------------------------------")
356
+ print("searchFile :: Busqueda de ficheros .ui para la modificacion")
357
+ print("-----------------------------------------------")
358
+ print(" Ruta del proyecto: %s" % (rutaProyectoNorm))
359
+ print(" Archivo Theme: %s" % (fileTheme))
360
+ # si es solo un archivo
361
+ if rutaProyectoNorm.endswith(".ui"):
362
+ if debug == "--debug":
363
+ print(" Trabajamos con un unico archivo")
364
+ fileName, fileExtension = os.path.splitext(rutaProyectoNorm)
365
+ if metodo == "overwrite":
366
+ ficheroSalida = fileName + fileExtension
367
+ if metodo == "modify":
368
+ ficheroSalida = fileName + "-modificado" + fileExtension
369
+ files = rutaProyectoNorm
370
+ ### Ejecutamos funcion para comprobar si existen botones a cambiar
371
+ checkFile(rutaProyecto, ficheroSalida, fileTheme, files)
372
+ # Si es un directorio
373
+ else:
374
+ for r, d, f in os.walk(rutaProyectoNorm):
375
+ for files in f:
376
+ if files.endswith(".ui"):
377
+ ficheroEntrada = os.path.join(r, files)
378
+ rutaModulo = os.path.dirname(ficheroEntrada)
379
+ if metodo == "overwrite":
380
+ rutaSalida = rutaModulo
381
+ ficheroSalida = ficheroEntrada
382
+ if metodo == "modify":
383
+ rutaSalida = rutaModulo + "/forms-modificados/"
384
+ ficheroSalida = rutaModulo + "/forms-modificados/" + files
385
+ if not os.path.exists(rutaSalida):
386
+ os.makedirs(rutaSalida)
387
+ if debug == "--debug":
388
+ print(" -------------------------------------------")
389
+ print(" :: Trabajamos con un directorio")
390
+ print(" -------------------------------------------")
391
+ print(" Archivo a modificar: %s" % (ficheroEntrada))
392
+ print(" Ruta del parche o modulo: %s" % (rutaModulo))
393
+ print(" Ruta donde guardar el nuevo archivo: %s" % (rutaSalida))
394
+ print(" Fichero de salida: %s" % (ficheroSalida))
395
+ checkFile(ficheroEntrada, ficheroSalida, fileTheme, files)
396
+ # if debug == "--debug":
397
+ # print "--------------------------------------------------------------------------------------------------------------------"
398
+ # print "searchFile:: Rutas Proyecto"
399
+ # print "-----------------------------------------------"
400
+ # print "Ruta del proyecto: %s" % (rutaProyectoNorm)
401
+ # print "Archivo Theme: %s" % (fileTheme)
402
+ if debug == "--debug":
403
+ print("____________________________________________________________________________________________________________________")
404
+
405
+
406
+
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: enebootools
3
- Version: 2.3.1
3
+ Version: 2.4
4
4
  Summary: ERP tools for Eneboo
5
5
  Home-page: https://github.com/aulla/eneboo-tools
6
6
  Author: David Martínez Martí, José A. Fernández Fernández
@@ -35,6 +35,7 @@ Dynamic: description
35
35
  Dynamic: description-content-type
36
36
  Dynamic: home-page
37
37
  Dynamic: keywords
38
+ Dynamic: license-file
38
39
  Dynamic: requires-dist
39
40
  Dynamic: requires-python
40
41
  Dynamic: summary
@@ -15,6 +15,7 @@ enebootools.egg-info/requires.txt
15
15
  enebootools.egg-info/top_level.txt
16
16
  enebootools/assembler/__init__.py
17
17
  enebootools/assembler/config.py
18
+ enebootools/assembler/copylib.py
18
19
  enebootools/assembler/database.py
19
20
  enebootools/assembler/databasemodels.py
20
21
  enebootools/assembler/featureconfig.py
@@ -79,4 +80,6 @@ enebootools/tools/__init__.py
79
80
  enebootools/tools/ar2kut.py
80
81
  enebootools/tools/dumps.py
81
82
  enebootools/tools/git.py
83
+ enebootools/uiimage/__init__.py
84
+ enebootools/uiimage/uiimage.py
82
85
  enebootools/vcsworkflow/__init__.py
File without changes
File without changes
File without changes
File without changes
File without changes