pyflutter-app 0.3.11__tar.gz → 0.3.12__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 (89) hide show
  1. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/PKG-INFO +1 -1
  2. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/converter/page_whatsapp/controller_whatsapp.py +21 -0
  3. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/converter/page_whatsapp/model_whatsapp.py +47 -5
  4. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/converter/page_whatsapp/view_whatsapp.py +18 -9
  5. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/pyproject.toml +1 -1
  6. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/uv.lock +5 -5
  7. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/.gitignore +0 -0
  8. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/.idea/.gitignore +0 -0
  9. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/.idea/inspectionProfiles/Project_Default.xml +0 -0
  10. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/.idea/inspectionProfiles/profiles_settings.xml +0 -0
  11. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/.idea/misc.xml +0 -0
  12. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/.idea/modules.xml +0 -0
  13. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/.idea/pyflutter_app.iml +0 -0
  14. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/.idea/vcs.xml +0 -0
  15. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/README.md +0 -0
  16. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/cartas/__init__.py +0 -0
  17. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/cartas/origin.py +0 -0
  18. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/convert_stream/__init__.py +0 -0
  19. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/converter/__init__.py +0 -0
  20. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/converter/__main__.py +0 -0
  21. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/converter/assets/forms_config.json +0 -0
  22. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/converter/config_app.py +0 -0
  23. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/converter/home_page/__init__.py +0 -0
  24. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/converter/home_page/_page_edit.py +0 -0
  25. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/converter/home_page/controller.py +0 -0
  26. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/converter/home_page/model.py +0 -0
  27. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/converter/home_page/page_sheets.py +0 -0
  28. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/converter/home_page/view.py +0 -0
  29. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/converter/lib_toi.py +0 -0
  30. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/converter/page_circuit/__init__.py +0 -0
  31. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/converter/page_circuit/common.py +0 -0
  32. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/converter/page_circuit/controller_circuit.py +0 -0
  33. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/converter/page_circuit/model_circuit.py +0 -0
  34. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/converter/page_circuit/service.py +0 -0
  35. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/converter/page_circuit/view_circuit.py +0 -0
  36. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/converter/page_forms/Diagnorstico.txt +0 -0
  37. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/converter/page_forms/__init__.py +0 -0
  38. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/converter/page_forms/common.py +0 -0
  39. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/converter/page_forms/config.py +0 -0
  40. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/converter/page_forms/controller_forms.py +0 -0
  41. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/converter/page_forms/diagnose_forms.py +0 -0
  42. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/converter/page_forms/master_forms.py +0 -0
  43. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/converter/page_forms/model_forms.py +0 -0
  44. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/converter/page_forms/service.py +0 -0
  45. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/converter/page_forms/view_forms.py +0 -0
  46. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/converter/page_image/__init__.py +0 -0
  47. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/converter/page_image/common.py +0 -0
  48. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/converter/page_image/controller_image.py +0 -0
  49. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/converter/page_image/model_image.py +0 -0
  50. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/converter/page_image/renderer.py +0 -0
  51. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/converter/page_image/view_image.py +0 -0
  52. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/converter/page_image/widgets.py +0 -0
  53. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/converter/page_ocr/__init__.py +0 -0
  54. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/converter/page_ocr/common.py +0 -0
  55. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/converter/page_ocr/controller_ocr.py +0 -0
  56. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/converter/page_ocr/model_ocr.py +0 -0
  57. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/converter/page_ocr/view_ocr.py +0 -0
  58. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/converter/page_whatsapp/PATCH_whatsapp_files.md +0 -0
  59. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/converter/page_whatsapp/__init__.py +0 -0
  60. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/converter/page_whatsapp/common.py +0 -0
  61. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/converter/run_app_convert.py +0 -0
  62. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/converter/table_widget.py +0 -0
  63. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/converter/util.py +0 -0
  64. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/local_build/linux.sh +0 -0
  65. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/local_build/send.sh +0 -0
  66. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/main.py +0 -0
  67. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/mvc/controller.py +0 -0
  68. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/mvc/model.py +0 -0
  69. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/mvc/view.py +0 -0
  70. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/new-export_app.sh +0 -0
  71. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/ocr_stream/__init__.py +0 -0
  72. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/pyflutter_ui/__init__.py +0 -0
  73. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/pyflutter_ui/app.py +0 -0
  74. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/pyflutter_ui/file_picker.py +0 -0
  75. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/pyflutter_ui/navigator.py +0 -0
  76. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/pyflutter_ui/scheduler.py +0 -0
  77. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/pyflutter_ui/theme.py +0 -0
  78. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/pyflutter_ui/ui/__init__.py +0 -0
  79. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/pyflutter_ui/ui/buttons.py +0 -0
  80. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/pyflutter_ui/ui/container.py +0 -0
  81. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/pyflutter_ui/ui/core.py +0 -0
  82. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/pyflutter_ui/ui/list_builder.py +0 -0
  83. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/pyflutter_ui/ui/progress.py +0 -0
  84. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/pyflutter_ui/ui/tables.py +0 -0
  85. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/pyflutter_ui/ui/widgets.py +0 -0
  86. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/table_stream/__init__.py +0 -0
  87. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/teste.py +0 -0
  88. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/update.sh +0 -0
  89. {pyflutter_app-0.3.11 → pyflutter_app-0.3.12}/whatsapp_files/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: pyflutter_app
3
- Version: 0.3.11
3
+ Version: 0.3.12
4
4
  Summary: Bibliotecas Python para conversão de documentos, interface e processamento de tabelas.
5
5
  Requires-Python: >=3.12
6
6
  Requires-Dist: opencv-python>=5.0.0.93
@@ -309,6 +309,27 @@ class ControllerWhatsAppPage(ChangeNotifier):
309
309
  self.working = False
310
310
  self.show_error(str(e))
311
311
 
312
+ def import_cartas_folder(self, folder: Directory) -> None:
313
+ """I) Lê a pasta (recursivo), identifica e organiza as cartas TOI (PDF/imagem)."""
314
+ if self.busy:
315
+ self.show_info("Existe outra operação em andamento.")
316
+ return
317
+ if not folder.exists():
318
+ self.show_error(f"A pasta não existe:\n{folder.absolute()}")
319
+ return
320
+
321
+ self._begin_task(
322
+ "Última operação: cartas TOI",
323
+ f"Lendo {folder.absolute()} (incluindo subpastas) e identificando as cartas ...",
324
+ )
325
+ try:
326
+ self.model.start_rename_cartas_folder(
327
+ folder, lambda r, e: _ui(lambda: self._on_task_done(r, e))
328
+ )
329
+ except Exception as e:
330
+ self.working = False
331
+ self.show_error(str(e))
332
+
312
333
  def run_chat_command(self, kind: str) -> None:
313
334
  """II) Comandos de whatsapp_files (descompactar, cache, RenameChat ...)."""
314
335
  if self.busy:
@@ -5,7 +5,14 @@ from typing import Callable
5
5
 
6
6
  import pandas as pd
7
7
 
8
- from table_stream import Directory, File, Set
8
+ from table_stream import (
9
+ ContentFiles,
10
+ Directory,
11
+ EnumDocuments,
12
+ File,
13
+ Set,
14
+ )
15
+
9
16
  from whatsapp_files import (
10
17
  AddChatsOnTable,
11
18
  BuilderConfigWhatsApp,
@@ -31,6 +38,9 @@ TASK_COLUMNS: list[str] = ["ARQUIVO", "CLASSIFICAÇÃO", "STATUS", "DESTINO", "M
31
38
 
32
39
  ACCEPTED_EXTENSIONS: tuple[str, ...] = (".zip", ".txt")
33
40
 
41
+ # Extensões de cartas TOI aceitas ao varrer uma pasta (sem diferenciar maiúsculas).
42
+ CARTA_EXTENSIONS: tuple[str, ...] = (".pdf", ".png", ".jpg", ".jpeg")
43
+
34
44
  # Comandos de chat disponíveis na UI.
35
45
  CMD_UNZIP = "unzip"
36
46
  CMD_ADD_CACHE = "add_cache"
@@ -254,15 +264,30 @@ class ModelWhatsApp:
254
264
  self._job_thread.start()
255
265
 
256
266
  # ------------------------------------------------------------------ I) cartas TOI
267
+
268
+ @staticmethod
269
+ def list_cartas(folder: Directory, max_files: int = 200_000) -> list[File]:
270
+ """PDFs e imagens da pasta, lendo as subpastas (ContentFiles, recursivo)."""
271
+ content = ContentFiles(folder, max_files=max_files)
272
+ everything = content.get_files(EnumDocuments.ALL, sort=True, recursive=True)
273
+ return [
274
+ f for f in everything if (f.extension() or "").lower() in CARTA_EXTENSIONS
275
+ ]
276
+
257
277
  def rename_cartas(self, files: list[File]) -> TaskResult:
258
278
  """
259
- Identifica (nome + cache TOI + texto do cache OCR + data do chat) e MOVE as
260
- cartas para a pasta de cartas TOI (BuilderConfigTOI().dir_base_toi).
261
- Não aplica OCR: só consulta o cache.
279
+ (docstring original ...)
262
280
  """
263
281
  from cartas import rename_files_toi # lazy
264
282
 
265
- valid = [f for f in files if f.is_pdf() or f.is_image()]
283
+ # Aceita também extensões em MAIÚSCULAS (.JPG, .PDF) além do filtro antigo.
284
+ valid = [
285
+ f
286
+ for f in files
287
+ if f.is_pdf()
288
+ or f.is_image()
289
+ or (f.extension() or "").lower() in CARTA_EXTENSIONS
290
+ ]
266
291
  if not valid:
267
292
  raise ValueError("Selecione cartas em PDF ou imagem.")
268
293
 
@@ -299,6 +324,23 @@ class ModelWhatsApp:
299
324
 
300
325
  return TaskResult("Cartas TOI", "\n".join(linhas), view)
301
326
 
327
+ def start_rename_cartas_folder(
328
+ self,
329
+ folder: Directory,
330
+ on_done: Callable[[TaskResult | None, Exception | None], None],
331
+ ) -> None:
332
+ """Varre a pasta (recursivo) e renomeia/organiza as cartas, tudo na worker thread."""
333
+
334
+ def work() -> TaskResult:
335
+ files = self.list_cartas(folder)
336
+ if not files:
337
+ raise ValueError(
338
+ f"Nenhum PDF ou imagem encontrado em:\n{folder.absolute()}"
339
+ )
340
+ return self.rename_cartas(files)
341
+
342
+ self._start_job("toi-rename-folder", work, on_done)
343
+
302
344
  def start_rename_cartas(
303
345
  self,
304
346
  files: list[File],
@@ -68,11 +68,8 @@ class _PageWhatsAppState(StatelessWidget):
68
68
  allowed_extensions=["txt"],
69
69
  dialog_title="Escolha o chat do WhatsApp (.txt)",
70
70
  )
71
- self.picker_cartas = FilePickerController(
72
- type=FilePickerType.custom,
73
- allow_multiple=True,
74
- allowed_extensions=["pdf", "png", "jpg", "jpeg"],
75
- dialog_title="Escolha as cartas TOI (PDF/imagem)",
71
+ self.picker_cartas_dir = FilePickerController(
72
+ dialog_title="Escolha a pasta com as cartas TOI (PDF/imagem)",
76
73
  )
77
74
 
78
75
  ctrl = self.controller
@@ -147,18 +144,30 @@ class _PageWhatsAppState(StatelessWidget):
147
144
  ctrl.import_files(files)
148
145
 
149
146
  def action_import_cartas(self, ctrl: ControllerWhatsAppPage) -> None:
150
- files = self._pick(ctrl, self.picker_cartas)
151
- if not files:
147
+ if ctrl.busy:
148
+ self.show_info("Existe outra operação em andamento.")
149
+ return
150
+
151
+ conf = ctrl.get_config()
152
+ if conf.value.initial_dir.exists():
153
+ self.picker_cartas_dir.initial_directory = conf.value.initial_dir.absolute()
154
+
155
+ path = self.picker_cartas_dir.pick_directory()
156
+ if not path:
152
157
  return
153
158
 
159
+ folder = Directory(path)
160
+ conf.set_initial_dir(folder)
161
+
154
162
  ok = messagebox.askyesno(
155
163
  "Importar e renomear cartas TOI",
156
- f"{len(files)} arquivo(s) serão identificados pelo nome, cache TOI, "
164
+ f"Todos os PDFs e imagens de:\n{folder.absolute()}\n"
165
+ "(incluindo subpastas) serão identificados pelo nome, cache TOI, "
157
166
  "texto do cache OCR e data do chat, e MOVIDOS para a pasta de "
158
167
  "cartas TOI.\n\nContinuar?",
159
168
  )
160
169
  if ok:
161
- ctrl.import_cartas(files)
170
+ ctrl.import_cartas_folder(folder)
162
171
 
163
172
  def action_chat_command(self, ctrl: ControllerWhatsAppPage, kind: str) -> None:
164
173
  if ctrl.busy:
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "pyflutter_app"
3
- version = "0.3.11"
3
+ version = "0.3.12"
4
4
  description = "Bibliotecas Python para conversão de documentos, interface e processamento de tabelas."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.12"
@@ -38,7 +38,7 @@ name = "cffi"
38
38
  version = "2.1.1"
39
39
  source = { registry = "https://pypi.org/simple" }
40
40
  dependencies = [
41
- { name = "pycparser", marker = "implementation_name != 'PyPy'" },
41
+ { name = "pycparser", marker = "implementation_name != 'PyPy' and sys_platform != 'emscripten' and sys_platform != 'win32'" },
42
42
  ]
43
43
  sdist = { url = "https://files.pythonhosted.org/packages/9e/ef/008a1939e372c06329a3fce4279c02f328488f3526744906eeec3da7ad5f/cffi-2.1.1.tar.gz", hash = "sha256:dd31f52ea1086513bb9df30f8fcee9b8918323ae067a3d5b78bc826a000712be", size = 530807, upload-time = "2026-08-03T21:21:18.939Z" }
44
44
  wheels = [
@@ -221,7 +221,7 @@ name = "cryptography"
221
221
  version = "50.0.1"
222
222
  source = { registry = "https://pypi.org/simple" }
223
223
  dependencies = [
224
- { name = "cffi", marker = "platform_python_implementation != 'PyPy'" },
224
+ { name = "cffi", marker = "platform_python_implementation != 'PyPy' and sys_platform != 'emscripten' and sys_platform != 'win32'" },
225
225
  ]
226
226
  sdist = { url = "https://files.pythonhosted.org/packages/bb/ad/5d6702db60b1e40b41ef513b6967ff5848f307d50f8449baf1634f5908f1/cryptography-50.0.1.tar.gz", hash = "sha256:5dd9bda1c12b4162f6ff568eeb5e0ff956c28d14406e875cfe8a63a2d414ff20", size = 880381, upload-time = "2026-08-25T19:45:45.499Z" }
227
227
  wheels = [
@@ -779,7 +779,7 @@ wheels = [
779
779
 
780
780
  [[package]]
781
781
  name = "pyflutter-app"
782
- version = "0.3.11"
782
+ version = "0.3.12"
783
783
  source = { editable = "." }
784
784
  dependencies = [
785
785
  { name = "opencv-python" },
@@ -970,8 +970,8 @@ name = "secretstorage"
970
970
  version = "3.5.0"
971
971
  source = { registry = "https://pypi.org/simple" }
972
972
  dependencies = [
973
- { name = "cryptography" },
974
- { name = "jeepney" },
973
+ { name = "cryptography", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" },
974
+ { name = "jeepney", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" },
975
975
  ]
976
976
  sdist = { url = "https://files.pythonhosted.org/packages/1c/03/e834bcd866f2f8a49a85eaff47340affa3bfa391ee9912a952a1faa68c7b/secretstorage-3.5.0.tar.gz", hash = "sha256:f04b8e4689cbce351744d5537bf6b1329c6fc68f91fa666f60a380edddcd11be", size = 19884, upload-time = "2025-11-23T19:02:53.191Z" }
977
977
  wheels = [
File without changes
File without changes
File without changes
File without changes