pyflutter-app 0.3.7__tar.gz → 0.3.11__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 (94) hide show
  1. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/PKG-INFO +1 -1
  2. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/cartas/__init__.py +3 -3
  3. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/cartas/origin.py +1 -1
  4. pyflutter_app-0.3.7/converter/home_page/view.py → pyflutter_app-0.3.11/converter/home_page/page_sheets.py +9 -43
  5. pyflutter_app-0.3.11/converter/home_page/view.py +71 -0
  6. pyflutter_app-0.3.11/converter/page_circuit/__init__.py +20 -0
  7. pyflutter_app-0.3.11/converter/page_circuit/common.py +99 -0
  8. pyflutter_app-0.3.11/converter/page_circuit/controller_circuit.py +359 -0
  9. pyflutter_app-0.3.11/converter/page_circuit/model_circuit.py +110 -0
  10. pyflutter_app-0.3.11/converter/page_circuit/service.py +356 -0
  11. pyflutter_app-0.3.11/converter/page_circuit/view_circuit.py +208 -0
  12. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/converter/page_forms/controller_forms.py +55 -3
  13. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/converter/page_forms/model_forms.py +15 -0
  14. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/converter/page_forms/view_forms.py +11 -14
  15. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/converter/page_image/common.py +65 -6
  16. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/converter/page_image/controller_image.py +130 -4
  17. pyflutter_app-0.3.11/converter/page_image/model_image.py +222 -0
  18. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/converter/page_image/renderer.py +2 -2
  19. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/converter/page_image/view_image.py +46 -0
  20. pyflutter_app-0.3.11/converter/page_ocr/__init__.py +4 -0
  21. pyflutter_app-0.3.11/converter/page_ocr/common.py +55 -0
  22. pyflutter_app-0.3.11/converter/page_ocr/controller_ocr.py +338 -0
  23. pyflutter_app-0.3.11/converter/page_ocr/model_ocr.py +191 -0
  24. pyflutter_app-0.3.11/converter/page_ocr/view_ocr.py +183 -0
  25. pyflutter_app-0.3.11/converter/page_whatsapp/PATCH_whatsapp_files.md +245 -0
  26. pyflutter_app-0.3.11/converter/page_whatsapp/__init__.py +4 -0
  27. pyflutter_app-0.3.11/converter/page_whatsapp/common.py +41 -0
  28. pyflutter_app-0.3.11/converter/page_whatsapp/controller_whatsapp.py +370 -0
  29. pyflutter_app-0.3.11/converter/page_whatsapp/model_whatsapp.py +353 -0
  30. pyflutter_app-0.3.11/converter/page_whatsapp/view_whatsapp.py +262 -0
  31. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/converter/run_app_convert.py +6 -0
  32. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/converter/table_widget.py +34 -16
  33. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/new-export_app.sh +10 -3
  34. {pyflutter_app-0.3.7/ocrlib → pyflutter_app-0.3.11/ocr_stream}/__init__.py +3 -3
  35. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/pyproject.toml +1 -1
  36. pyflutter_app-0.3.11/teste.py +9 -0
  37. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/uv.lock +1 -1
  38. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/whatsapp_files/__init__.py +151 -50
  39. pyflutter_app-0.3.7/converter/page_image/model_image.py +0 -95
  40. pyflutter_app-0.3.7/converter/whatsapp/__init__.py +0 -0
  41. pyflutter_app-0.3.7/converter/whatsapp/model.py +0 -29
  42. pyflutter_app-0.3.7/test_claude.py +0 -505
  43. pyflutter_app-0.3.7/teste_ocr.py +0 -28
  44. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/.gitignore +0 -0
  45. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/.idea/.gitignore +0 -0
  46. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/.idea/inspectionProfiles/Project_Default.xml +0 -0
  47. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/.idea/inspectionProfiles/profiles_settings.xml +0 -0
  48. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/.idea/misc.xml +0 -0
  49. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/.idea/modules.xml +0 -0
  50. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/.idea/pyflutter_app.iml +0 -0
  51. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/.idea/vcs.xml +0 -0
  52. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/README.md +0 -0
  53. {pyflutter_app-0.3.7/pdflib → pyflutter_app-0.3.11/convert_stream}/__init__.py +0 -0
  54. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/converter/__init__.py +0 -0
  55. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/converter/__main__.py +0 -0
  56. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/converter/assets/forms_config.json +0 -0
  57. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/converter/config_app.py +0 -0
  58. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/converter/home_page/__init__.py +0 -0
  59. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/converter/home_page/_page_edit.py +0 -0
  60. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/converter/home_page/controller.py +0 -0
  61. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/converter/home_page/model.py +0 -0
  62. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/converter/lib_toi.py +0 -0
  63. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/converter/page_forms/Diagnorstico.txt +0 -0
  64. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/converter/page_forms/__init__.py +0 -0
  65. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/converter/page_forms/common.py +0 -0
  66. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/converter/page_forms/config.py +0 -0
  67. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/converter/page_forms/diagnose_forms.py +0 -0
  68. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/converter/page_forms/master_forms.py +0 -0
  69. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/converter/page_forms/service.py +0 -0
  70. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/converter/page_image/__init__.py +0 -0
  71. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/converter/page_image/widgets.py +0 -0
  72. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/converter/util.py +0 -0
  73. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/local_build/linux.sh +0 -0
  74. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/local_build/send.sh +0 -0
  75. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/main.py +0 -0
  76. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/mvc/controller.py +0 -0
  77. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/mvc/model.py +0 -0
  78. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/mvc/view.py +0 -0
  79. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/pyflutter_ui/__init__.py +0 -0
  80. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/pyflutter_ui/app.py +0 -0
  81. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/pyflutter_ui/file_picker.py +0 -0
  82. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/pyflutter_ui/navigator.py +0 -0
  83. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/pyflutter_ui/scheduler.py +0 -0
  84. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/pyflutter_ui/theme.py +0 -0
  85. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/pyflutter_ui/ui/__init__.py +0 -0
  86. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/pyflutter_ui/ui/buttons.py +0 -0
  87. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/pyflutter_ui/ui/container.py +0 -0
  88. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/pyflutter_ui/ui/core.py +0 -0
  89. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/pyflutter_ui/ui/list_builder.py +0 -0
  90. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/pyflutter_ui/ui/progress.py +0 -0
  91. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/pyflutter_ui/ui/tables.py +0 -0
  92. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/pyflutter_ui/ui/widgets.py +0 -0
  93. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/table_stream/__init__.py +0 -0
  94. {pyflutter_app-0.3.7 → pyflutter_app-0.3.11}/update.sh +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: pyflutter_app
3
- Version: 0.3.7
3
+ Version: 0.3.11
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
@@ -33,7 +33,7 @@ from table_stream import (
33
33
  load_file_hash,
34
34
  )
35
35
 
36
- from ocrlib import HeaderOcr, BuilderConfigOcr, CreateRelatorioOcr
36
+ from ocr_stream import HeaderOcr, BuilderConfigOcr, CreateRelatorioOcr
37
37
 
38
38
  from whatsapp_files import (
39
39
  RowWhatsApp,
@@ -51,7 +51,7 @@ __version__ = "0.2"
51
51
  class ConfigTOI:
52
52
 
53
53
  file_relatorio_toi: File
54
- file_relatorio_forms: File
54
+ file_cartas_lancadas: File
55
55
  file_table_toi: File
56
56
  file_master_forms: File # NOVO
57
57
  dir_base_toi: Directory
@@ -126,7 +126,7 @@ class BuilderConfigTOI(object):
126
126
  dir_base_toi=self.dir_retorno_de_campo,
127
127
  file_relatorio_toi=self.file_relatorio_toi,
128
128
  file_table_toi=self.file_table_toi,
129
- file_relatorio_forms=self.file_relatorio_forms,
129
+ file_cartas_lancadas=self.file_relatorio_forms,
130
130
  dir_log_excel=self.dir_log_excel,
131
131
  dir_relatorios=self.dir_relatorios,
132
132
  file_master_forms=self.file_master_forms,
@@ -31,7 +31,7 @@ from table_stream import (
31
31
  load_file_hash,
32
32
  )
33
33
 
34
- from ocrlib import HeaderOcr, BuilderConfigOcr, CreateRelatorioOcr
34
+ from ocr_stream import HeaderOcr, BuilderConfigOcr, CreateRelatorioOcr
35
35
 
36
36
  from whatsapp_files import (
37
37
  RowWhatsApp,
@@ -1,8 +1,6 @@
1
1
  from pyflutter_ui import (
2
- ChangeNotifier,
3
2
  BuildContext,
4
3
  FlutterWidget,
5
- LinearProgress,
6
4
  StatelessWidget,
7
5
  Consumer,
8
6
  Column,
@@ -23,10 +21,7 @@ from pyflutter_ui import (
23
21
  )
24
22
 
25
23
  from tkinter import messagebox
26
- from typing import Any
27
24
  import pandas as pd
28
- from pandas import DataFrame
29
-
30
25
 
31
26
  from table_stream import (
32
27
  ArrayList,
@@ -40,24 +35,20 @@ from table_stream import (
40
35
  from converter.home_page.controller import ControllerHomePage
41
36
  from converter.table_widget import TableOrProgress
42
37
  from converter.home_page._page_edit import PageEditExcel
43
-
44
- # Páginas para navegação.
45
- from converter.page_forms import PageRespondsForms
46
- from converter.page_forms import ControllerForms
47
- from converter.config_app import MapConfig, AppConfigNotifier
48
- from converter.page_image import PageImage
38
+ from converter.config_app import AppConfigNotifier
49
39
 
50
40
 
51
- class HomePage(StatelessWidget):
41
+ class PageSheets(StatelessWidget):
42
+ """Importar/carregar planilhas. De lá se acessa a edição de dados."""
52
43
 
53
44
  def __init__(self, key: str | None = None) -> None:
54
45
  super().__init__(key)
55
46
 
56
47
  def build(self, context: BuildContext) -> FlutterWidget:
57
- return _HomePageState()
48
+ return _PageSheetsState()
58
49
 
59
50
 
60
- class _HomePageState(StatelessWidget):
51
+ class _PageSheetsState(StatelessWidget):
61
52
 
62
53
  def __init__(self, key: str | None = None) -> None:
63
54
  super().__init__(key)
@@ -94,8 +85,7 @@ class _HomePageState(StatelessWidget):
94
85
 
95
86
  @property
96
87
  def app_config(self) -> AppConfigNotifier:
97
- state = Provider.read(AppConfigNotifier)
98
- return state
88
+ return Provider.read(AppConfigNotifier)
99
89
 
100
90
  @property
101
91
  def controller(self) -> ControllerHomePage:
@@ -231,29 +221,11 @@ class _HomePageState(StatelessWidget):
231
221
  df=data.head(),
232
222
  )
233
223
 
234
- def action_open_forms(self, context: BuildContext, controller: ControllerHomePage):
235
- """
236
- Seta o DataFrame() da página atual como propriedade do ControllerForms()
237
- antes de carregar a página.
238
- """
239
- # df = controller.data_notifier.value
240
- # forms_controller: ControllerForms = context.read(ControllerForms)
241
- # forms_controller.set_data(df)
242
- # if not forms_controller.forms_state.data_is_valid():
243
- # messagebox.showerror("Erro", "Tabela TOI inválida")
244
- # return
245
-
246
- context.navigator.push(PageRespondsForms())
247
-
248
224
  def _builder_body(
249
225
  self, context: BuildContext, controller: ControllerHomePage
250
226
  ) -> FlutterWidget:
251
227
  self.context = context
252
228
 
253
- filename = controller.get_file_sheet()
254
- if filename is not None:
255
- filename = filename.basename()
256
-
257
229
  return Column(
258
230
  children=[
259
231
  # -----------------------------------#
@@ -314,20 +286,14 @@ class _HomePageState(StatelessWidget):
314
286
  Expanded(Consumer(ControllerHomePage, self._build_table)),
315
287
  Row(
316
288
  [
289
+ ElevatedButton(
290
+ "<- Voltar", lambda: context.navigator.pop()
291
+ ),
317
292
  Text("Ir para: "),
318
293
  ElevatedButton(
319
294
  "Edição de dados",
320
295
  lambda: context.navigator.push(PageEditExcel()),
321
296
  ),
322
- # ElevatedButton("Exportar dados", lambda: print()),
323
- ElevatedButton(
324
- "Responds Forms",
325
- lambda: self.action_open_forms(context, controller),
326
- ),
327
- ElevatedButton(
328
- "Renomear imagens",
329
- lambda: context.navigator.push(PageImage()),
330
- ),
331
297
  ],
332
298
  main_axis_alignment=MainAxisAlignment.START,
333
299
  ),
@@ -0,0 +1,71 @@
1
+ from typing import Callable
2
+
3
+ from pyflutter_ui import (
4
+ BuildContext,
5
+ FlutterWidget,
6
+ StatelessWidget,
7
+ Column,
8
+ Row,
9
+ ElevatedButton,
10
+ Divider,
11
+ MainAxisAlignment,
12
+ Scaffold,
13
+ Text,
14
+ )
15
+
16
+ # Páginas para navegação.
17
+ from converter.home_page.page_sheets import PageSheets
18
+ from converter.page_forms import PageRespondsForms
19
+ from converter.page_image import PageImage
20
+ from converter.page_circuit import PageCircuit
21
+ from converter.page_whatsapp import PageWhatsApp
22
+ from converter.page_ocr import PageOcr
23
+ from pyflutter_ui.ui.core import GlobalKey
24
+
25
+
26
+ class HomePage(StatelessWidget):
27
+ """Home: somente botões para navegar entre as páginas."""
28
+
29
+ def __init__(self, key: GlobalKey | None = None) -> None:
30
+ super().__init__(key)
31
+
32
+ def build(self, context: BuildContext) -> FlutterWidget:
33
+ return _HomePageState()
34
+
35
+
36
+ class _HomePageState(StatelessWidget):
37
+
38
+ # (rótulo do botão, descrição, página)
39
+ PAGES: list[tuple[str, str, Callable[[], FlutterWidget]]] = [
40
+ ("Planilhas", "Importar/carregar planilhas e editar dados", PageSheets),
41
+ ("WhatsApp", "Importar chats (.zip) para o cache do WhatsApp", PageWhatsApp),
42
+ ("Responds Forms", "Lançar cartas TOI no Microsoft Forms", PageRespondsForms),
43
+ ("Renomear imagens", "Identificar cartas (UC / TOI / data)", PageImage),
44
+ ("Dividir base (QGIS)", "Dividir a base por coluna (CSV/Excel)", PageCircuit),
45
+ ("OCR", "Aplicar OCR em PDFs e imagens de uma pasta", PageOcr),
46
+ ]
47
+
48
+ def __init__(self, key: GlobalKey | None = None) -> None:
49
+ super().__init__(key)
50
+
51
+ def _nav_item(
52
+ self,
53
+ context: BuildContext,
54
+ label: str,
55
+ description: str,
56
+ page: Callable[[], FlutterWidget],
57
+ ) -> FlutterWidget:
58
+ return Row(
59
+ [
60
+ ElevatedButton(label, lambda: context.navigator.push(page())),
61
+ Text(description),
62
+ ],
63
+ main_axis_alignment=MainAxisAlignment.START,
64
+ )
65
+
66
+ def build(self, context: BuildContext) -> FlutterWidget:
67
+ items = [
68
+ self._nav_item(context, label, desc, page)
69
+ for label, desc, page in self.PAGES
70
+ ]
71
+ return Scaffold(Column([Text("App Convert"), Divider(), *items]))
@@ -0,0 +1,20 @@
1
+ from .common import (
2
+ ItemStatus,
3
+ SplitConfig,
4
+ SplitEvent,
5
+ SplitEventType,
6
+ SplitSummary,
7
+ )
8
+ from .service import (
9
+ ConsoleObserver,
10
+ CsvExporter,
11
+ DataFrameSplitService,
12
+ ExcelExporter,
13
+ ReportObserver,
14
+ SplitGroup,
15
+ SplitObserver,
16
+ SplitPlanner,
17
+ )
18
+ from .model_circuit import ModelCircuit
19
+ from .controller_circuit import ControllerCircuit
20
+ from .view_circuit import PageCircuit
@@ -0,0 +1,99 @@
1
+ from __future__ import annotations
2
+ import re
3
+ from dataclasses import dataclass, field
4
+ from enum import Enum, StrEnum
5
+ from typing import Any
6
+
7
+ from table_stream import CsvOptions, Directory
8
+
9
+
10
+ # ============================================================
11
+ # Status / eventos (Observer)
12
+ # ============================================================
13
+ class ItemStatus(StrEnum):
14
+ PENDING = "pendente"
15
+ DONE = "exportado"
16
+ SKIPPED = "pulado"
17
+ ERROR = "erro"
18
+
19
+
20
+ class SplitEventType(Enum):
21
+ STARTED = "started"
22
+ ITEM = "item" # um grupo (ex.: numliv = 5) foi processado
23
+ FINISHED = "finished"
24
+
25
+
26
+ @dataclass(frozen=True)
27
+ class SplitSummary:
28
+ total_groups: int = 0
29
+ exported_files: int = 0
30
+ skipped_files: int = 0
31
+ errors: int = 0
32
+ stopped: bool = False
33
+ elapsed_s: float = 0.0
34
+ output_dir: str = ""
35
+ period: tuple[str, ...] = ()
36
+
37
+
38
+ @dataclass(frozen=True)
39
+ class SplitEvent:
40
+ """Evento enviado pelo service a todos os observadores."""
41
+
42
+ type: SplitEventType
43
+ done: int = 0
44
+ total: int = 0
45
+ group: str = ""
46
+ key: str = ""
47
+ period: str = ""
48
+ rows: int = 0
49
+ status: ItemStatus | None = None
50
+ files: tuple[str, ...] = ()
51
+ message: str = ""
52
+ summary: SplitSummary | None = None
53
+
54
+
55
+ # ============================================================
56
+ # Configuração
57
+ # ============================================================
58
+ @dataclass
59
+ class SplitConfig:
60
+ column_split: str
61
+ output_dir: Directory
62
+ export_csv: bool = True
63
+ export_excel: bool = True
64
+
65
+ # Estrutura OUTPUT/<numano>/<nummes>/<CSV|EXCEL>/<grupo>.<ext>
66
+ use_period_dirs: bool = True
67
+ year_column: str = "numano"
68
+ month_column: str = "nummes"
69
+
70
+ replace: bool = False
71
+ csv_options: CsvOptions = field(default_factory=CsvOptions)
72
+
73
+ # Opcional: prefixo no nome do arquivo, vindo de outra coluna ("<prefixo>-<grupo>")
74
+ filename_prefix_column: str | None = None
75
+
76
+
77
+ # ============================================================
78
+ # Utilidades de texto
79
+ # ============================================================
80
+ _INVALID_NAME = re.compile(r'[\\/:*?"<>|\r\n\t]+')
81
+ _NATURAL = re.compile(r"(\d+)")
82
+
83
+
84
+ def clean_cell(value: Any) -> str:
85
+ """'2025.0' -> '2025'; nan/None -> ''."""
86
+ s = str(value).strip()
87
+ if s in ("", "nan", "NaN", "None", "NaT"):
88
+ return ""
89
+ return s[:-2] if s.endswith(".0") and s[:-2].isdigit() else s
90
+
91
+
92
+ def safe_filename(name: str) -> str:
93
+ cleaned = _INVALID_NAME.sub("_", name).strip(" .")
94
+ return cleaned or "vazio"
95
+
96
+
97
+ def natural_key(text: str) -> list[str | int]:
98
+ """Ordenação natural: 2 vem antes de 10."""
99
+ return [int(t) if t.isdecimal() else t.lower() for t in _NATURAL.split(text)]