io4it 2.1.0.2__tar.gz → 2.1.0.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.
- {io4it-2.1.0.2 → io4it-2.1.0.4}/PKG-INFO +1 -1
- {io4it-2.1.0.2 → io4it-2.1.0.4}/io4it.egg-info/PKG-INFO +1 -1
- {io4it-2.1.0.2 → io4it-2.1.0.4}/io4it.egg-info/SOURCES.txt +2 -0
- {io4it-2.1.0.2 → io4it-2.1.0.4}/orangecontrib/IO4IT/utils/mail.py +33 -13
- {io4it-2.1.0.2 → io4it-2.1.0.4}/orangecontrib/IO4IT/utils/offuscation_basique.py +1 -1
- io4it-2.1.0.4/orangecontrib/IO4IT/utils/pool_exec_utils.py +33 -0
- io4it-2.1.0.4/orangecontrib/IO4IT/utils/utils_md.py +168 -0
- io4it-2.1.0.4/orangecontrib/IO4IT/widgets/designer/ow_file_ext_selector.ui +82 -0
- io4it-2.1.0.4/orangecontrib/IO4IT/widgets/designer/owchatgpt.ui +168 -0
- io4it-2.1.0.4/orangecontrib/IO4IT/widgets/designer/owdeepsearch.ui +87 -0
- io4it-2.1.0.4/orangecontrib/IO4IT/widgets/designer/owexportmarkdown.ui +72 -0
- io4it-2.1.0.4/orangecontrib/IO4IT/widgets/designer/owmailloader.ui +149 -0
- io4it-2.1.0.4/orangecontrib/IO4IT/widgets/designer/owmailsender.ui +149 -0
- io4it-2.1.0.4/orangecontrib/IO4IT/widgets/designer/owmarkdownizer.ui +103 -0
- io4it-2.1.0.4/orangecontrib/IO4IT/widgets/designer/owspeechtotext.ui +130 -0
- io4it-2.1.0.4/orangecontrib/IO4IT/widgets/designer/wordpdf2docx.ui +70 -0
- {io4it-2.1.0.2 → io4it-2.1.0.4}/setup.py +1 -1
- io4it-2.1.0.2/orangecontrib/IO4IT/widgets/designer/ow_file_ext_selector.ui +0 -69
- io4it-2.1.0.2/orangecontrib/IO4IT/widgets/designer/owchatgpt.ui +0 -155
- io4it-2.1.0.2/orangecontrib/IO4IT/widgets/designer/owdeepsearch.ui +0 -74
- io4it-2.1.0.2/orangecontrib/IO4IT/widgets/designer/owexportmarkdown.ui +0 -51
- io4it-2.1.0.2/orangecontrib/IO4IT/widgets/designer/owmailloader.ui +0 -32
- io4it-2.1.0.2/orangecontrib/IO4IT/widgets/designer/owmailsender.ui +0 -32
- io4it-2.1.0.2/orangecontrib/IO4IT/widgets/designer/owmarkdownizer.ui +0 -101
- io4it-2.1.0.2/orangecontrib/IO4IT/widgets/designer/owspeechtotext.ui +0 -104
- io4it-2.1.0.2/orangecontrib/IO4IT/widgets/designer/wordpdf2docx.ui +0 -57
- {io4it-2.1.0.2 → io4it-2.1.0.4}/io4it.egg-info/dependency_links.txt +0 -0
- {io4it-2.1.0.2 → io4it-2.1.0.4}/io4it.egg-info/entry_points.txt +0 -0
- {io4it-2.1.0.2 → io4it-2.1.0.4}/io4it.egg-info/namespace_packages.txt +0 -0
- {io4it-2.1.0.2 → io4it-2.1.0.4}/io4it.egg-info/requires.txt +0 -0
- {io4it-2.1.0.2 → io4it-2.1.0.4}/io4it.egg-info/top_level.txt +0 -0
- {io4it-2.1.0.2 → io4it-2.1.0.4}/orangecontrib/IO4IT/__init__.py +0 -0
- {io4it-2.1.0.2 → io4it-2.1.0.4}/orangecontrib/IO4IT/ocr_function/__init__.py +0 -0
- {io4it-2.1.0.2 → io4it-2.1.0.4}/orangecontrib/IO4IT/ocr_function/word_converter.py +0 -0
- {io4it-2.1.0.2 → io4it-2.1.0.4}/orangecontrib/IO4IT/utils/__init__.py +0 -0
- {io4it-2.1.0.2 → io4it-2.1.0.4}/orangecontrib/IO4IT/widgets/OWChatGpt.py +0 -0
- {io4it-2.1.0.2 → io4it-2.1.0.4}/orangecontrib/IO4IT/widgets/OWDeep_Search.py +0 -0
- {io4it-2.1.0.2 → io4it-2.1.0.4}/orangecontrib/IO4IT/widgets/OWExportMarkdown.py +0 -0
- {io4it-2.1.0.2 → io4it-2.1.0.4}/orangecontrib/IO4IT/widgets/OWMarkdownizer.py +0 -0
- {io4it-2.1.0.2 → io4it-2.1.0.4}/orangecontrib/IO4IT/widgets/OWS3Uploader.py +0 -0
- {io4it-2.1.0.2 → io4it-2.1.0.4}/orangecontrib/IO4IT/widgets/OWS3downloader.py +0 -0
- {io4it-2.1.0.2 → io4it-2.1.0.4}/orangecontrib/IO4IT/widgets/OWS3list.py +0 -0
- {io4it-2.1.0.2 → io4it-2.1.0.4}/orangecontrib/IO4IT/widgets/OWSpeechToText.py +0 -0
- {io4it-2.1.0.2 → io4it-2.1.0.4}/orangecontrib/IO4IT/widgets/OWmailLoader.py +0 -0
- {io4it-2.1.0.2 → io4it-2.1.0.4}/orangecontrib/IO4IT/widgets/OWmailSender.py +0 -0
- {io4it-2.1.0.2 → io4it-2.1.0.4}/orangecontrib/IO4IT/widgets/OWwordpdf2docx.py +0 -0
- {io4it-2.1.0.2 → io4it-2.1.0.4}/orangecontrib/IO4IT/widgets/__init__.py +0 -0
- {io4it-2.1.0.2 → io4it-2.1.0.4}/orangecontrib/IO4IT/widgets/designer/__init__.py +0 -0
- {io4it-2.1.0.2 → io4it-2.1.0.4}/orangecontrib/IO4IT/widgets/designer/chart.html +0 -0
- {io4it-2.1.0.2 → io4it-2.1.0.4}/orangecontrib/IO4IT/widgets/designer/nogui.ui +0 -0
- {io4it-2.1.0.2 → io4it-2.1.0.4}/orangecontrib/IO4IT/widgets/designer/owvisualizationer.ui +0 -0
- {io4it-2.1.0.2 → io4it-2.1.0.4}/orangecontrib/IO4IT/widgets/icons/__init__.py +0 -0
- {io4it-2.1.0.2 → io4it-2.1.0.4}/orangecontrib/IO4IT/widgets/icons/chatgpt.png +0 -0
- {io4it-2.1.0.2 → io4it-2.1.0.4}/orangecontrib/IO4IT/widgets/icons/deepsearch.svg +0 -0
- {io4it-2.1.0.2 → io4it-2.1.0.4}/orangecontrib/IO4IT/widgets/icons/download.png +0 -0
- {io4it-2.1.0.2 → io4it-2.1.0.4}/orangecontrib/IO4IT/widgets/icons/export_md.png +0 -0
- {io4it-2.1.0.2 → io4it-2.1.0.4}/orangecontrib/IO4IT/widgets/icons/file_extensor.png +0 -0
- {io4it-2.1.0.2 → io4it-2.1.0.4}/orangecontrib/IO4IT/widgets/icons/list_aws.png +0 -0
- {io4it-2.1.0.2 → io4it-2.1.0.4}/orangecontrib/IO4IT/widgets/icons/mail_loader.png +0 -0
- {io4it-2.1.0.2 → io4it-2.1.0.4}/orangecontrib/IO4IT/widgets/icons/mail_writer.png +0 -0
- {io4it-2.1.0.2 → io4it-2.1.0.4}/orangecontrib/IO4IT/widgets/icons/md.png +0 -0
- {io4it-2.1.0.2 → io4it-2.1.0.4}/orangecontrib/IO4IT/widgets/icons/speech_to_text.png +0 -0
- {io4it-2.1.0.2 → io4it-2.1.0.4}/orangecontrib/IO4IT/widgets/icons/upload.png +0 -0
- {io4it-2.1.0.2 → io4it-2.1.0.4}/orangecontrib/IO4IT/widgets/icons/visualizationer.png +0 -0
- {io4it-2.1.0.2 → io4it-2.1.0.4}/orangecontrib/IO4IT/widgets/icons/wordpdf2docx.png +0 -0
- {io4it-2.1.0.2 → io4it-2.1.0.4}/orangecontrib/IO4IT/widgets/icons_dev/__init__.py +0 -0
- {io4it-2.1.0.2 → io4it-2.1.0.4}/orangecontrib/__init__.py +0 -0
- {io4it-2.1.0.2 → io4it-2.1.0.4}/setup.cfg +0 -0
|
@@ -13,6 +13,8 @@ orangecontrib/IO4IT/ocr_function/word_converter.py
|
|
|
13
13
|
orangecontrib/IO4IT/utils/__init__.py
|
|
14
14
|
orangecontrib/IO4IT/utils/mail.py
|
|
15
15
|
orangecontrib/IO4IT/utils/offuscation_basique.py
|
|
16
|
+
orangecontrib/IO4IT/utils/pool_exec_utils.py
|
|
17
|
+
orangecontrib/IO4IT/utils/utils_md.py
|
|
16
18
|
orangecontrib/IO4IT/widgets/OWChatGpt.py
|
|
17
19
|
orangecontrib/IO4IT/widgets/OWDeep_Search.py
|
|
18
20
|
orangecontrib/IO4IT/widgets/OWExportMarkdown.py
|
|
@@ -4,19 +4,21 @@ import email
|
|
|
4
4
|
from email.header import decode_header
|
|
5
5
|
import time
|
|
6
6
|
import os
|
|
7
|
-
from bs4 import BeautifulSoup
|
|
8
7
|
from email import policy
|
|
9
8
|
from email.message import EmailMessage
|
|
10
9
|
import mimetypes
|
|
11
10
|
|
|
12
|
-
from exchangelib import Credentials,
|
|
11
|
+
from exchangelib import Credentials, HTMLBody, Message, Mailbox
|
|
13
12
|
from exchangelib.protocol import BaseProtocol, NoVerifyHTTPAdapter
|
|
14
13
|
from exchangelib import OAuth2Credentials, Identity, Configuration, Account, DELEGATE
|
|
15
|
-
|
|
14
|
+
|
|
16
15
|
|
|
17
16
|
from bs4 import BeautifulSoup
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
##### please uncomment this line to ignore certificate checking (owa)
|
|
20
|
+
#BaseProtocol.HTTP_ADAPTER_CLS=NoVerifyHTTPAdapter
|
|
21
|
+
|
|
20
22
|
from msal import ConfidentialClientApplication
|
|
21
23
|
from oauthlib.oauth2 import OAuth2Token
|
|
22
24
|
|
|
@@ -185,6 +187,8 @@ def check_new_emails(offusc_conf_agent,type_co, list_agent_email=[]):
|
|
|
185
187
|
with open(folder + "/" + "mail.ok", "w") as f:
|
|
186
188
|
f.close()
|
|
187
189
|
|
|
190
|
+
|
|
191
|
+
|
|
188
192
|
imap.logout()
|
|
189
193
|
except Exception as e:
|
|
190
194
|
print(f"Erreur lors de la vérification des mails : {e}")
|
|
@@ -199,7 +203,7 @@ def check_new_emails(offusc_conf_agent,type_co, list_agent_email=[]):
|
|
|
199
203
|
)
|
|
200
204
|
|
|
201
205
|
account = Account(
|
|
202
|
-
primary_smtp_address=
|
|
206
|
+
primary_smtp_address=alias,
|
|
203
207
|
credentials=credentials,
|
|
204
208
|
config=config,
|
|
205
209
|
autodiscover=False,
|
|
@@ -301,6 +305,7 @@ def check_new_emails(offusc_conf_agent,type_co, list_agent_email=[]):
|
|
|
301
305
|
f.write("\n".join(output_lines))
|
|
302
306
|
with open(os.path.join(folder, "mail.ok"), "w") as f:
|
|
303
307
|
pass
|
|
308
|
+
|
|
304
309
|
except Exception as e:
|
|
305
310
|
print(f"Erreur lors du traitement du mail : {e}")
|
|
306
311
|
elif type_co == "MICROSOFT_EXCHANGE_OAUTH2":
|
|
@@ -427,6 +432,7 @@ def check_new_emails(offusc_conf_agent,type_co, list_agent_email=[]):
|
|
|
427
432
|
with open(os.path.join(folder, "mail.ok"), "w") as f:
|
|
428
433
|
pass
|
|
429
434
|
|
|
435
|
+
|
|
430
436
|
except Exception as e:
|
|
431
437
|
print(f"Erreur OAuth2 lors du traitement du mail : {e}")
|
|
432
438
|
|
|
@@ -662,13 +668,27 @@ def check_send_new_emails(offusc_conf_agent,type_co):
|
|
|
662
668
|
else:
|
|
663
669
|
print("type de co non valide")
|
|
664
670
|
|
|
671
|
+
def list_conf_files(type_co):
|
|
672
|
+
conf_files = []
|
|
673
|
+
if type_co is None or type_co == "":
|
|
674
|
+
return conf_files
|
|
675
|
+
dossier = MetManagement.get_secret_content_dir()
|
|
676
|
+
dossier = dossier + type_co
|
|
677
|
+
files = os.listdir(dossier)
|
|
678
|
+
for file in files:
|
|
679
|
+
if file.lower().endswith(".json"):
|
|
680
|
+
conf_files.append(file)
|
|
681
|
+
return conf_files
|
|
682
|
+
|
|
683
|
+
|
|
684
|
+
|
|
665
685
|
if __name__ == "__main__":
|
|
666
|
-
|
|
667
|
-
#type_co="IMAP4_SSL"
|
|
668
|
-
type_co="MICROSOFT_EXCHANGE_OAUTH2"
|
|
686
|
+
type_co="IMAP4_SSL"
|
|
669
687
|
list_agent_email = []
|
|
688
|
+
offusc_conf_agents = list_conf_files(type_co)
|
|
670
689
|
while True:
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
690
|
+
for offusc_conf_agent in offusc_conf_agents:
|
|
691
|
+
check_new_emails(offusc_conf_agent,type_co, list_agent_email)
|
|
692
|
+
time.sleep(1)
|
|
693
|
+
check_send_new_emails(offusc_conf_agent,type_co)
|
|
694
|
+
time.sleep(1)
|
|
@@ -208,7 +208,7 @@ def enregistrer_config_owa_secure(mail, alias, server, username, password, inter
|
|
|
208
208
|
def enregistrer_config_cli_owa_secure():
|
|
209
209
|
print("\n🔐 Écriture fichier OWA avec chiffrement sécurisé :")
|
|
210
210
|
mail = input("📧 Mail (nom@domain.com) : ").strip()
|
|
211
|
-
alias = input("📛 Alias (visible) : ").strip()
|
|
211
|
+
alias = mail #input("📛 Alias (visible) : ").strip()
|
|
212
212
|
server = input("🌐 Server : ").strip()
|
|
213
213
|
username = input("👤 Username (domain\\user) : ").strip()
|
|
214
214
|
password = input("🔑 Password (non masqué) : ").strip()
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# pool_exec_utils.py
|
|
2
|
+
import os
|
|
3
|
+
from concurrent.futures import ProcessPoolExecutor
|
|
4
|
+
from typing import Optional, Tuple
|
|
5
|
+
|
|
6
|
+
def available_cpus(default: int = 4) -> int:
|
|
7
|
+
c = os.cpu_count()
|
|
8
|
+
return c if (c and c > 0) else default
|
|
9
|
+
|
|
10
|
+
def cpu_label_text() -> str:
|
|
11
|
+
return f"🖥️ CPU dispo : {available_cpus()}"
|
|
12
|
+
|
|
13
|
+
def shutdown_executor(executor: Optional[ProcessPoolExecutor]) -> None:
|
|
14
|
+
if executor is not None:
|
|
15
|
+
try:
|
|
16
|
+
executor.shutdown(wait=False, cancel_futures=True)
|
|
17
|
+
except TypeError:
|
|
18
|
+
executor.shutdown(wait=False)
|
|
19
|
+
except Exception:
|
|
20
|
+
pass
|
|
21
|
+
|
|
22
|
+
def create_or_update_executor(
|
|
23
|
+
executor: Optional[ProcessPoolExecutor],
|
|
24
|
+
current_workers: Optional[int],
|
|
25
|
+
new_workers: int,
|
|
26
|
+
) -> Tuple[ProcessPoolExecutor, int, str, bool]:
|
|
27
|
+
changed = (executor is None) or (current_workers != int(new_workers))
|
|
28
|
+
if changed:
|
|
29
|
+
shutdown_executor(executor)
|
|
30
|
+
executor = ProcessPoolExecutor(max_workers=int(new_workers))
|
|
31
|
+
return executor, int(new_workers), f"Executor prêt ({int(new_workers)} workers).", True
|
|
32
|
+
else:
|
|
33
|
+
return executor, int(current_workers), f"Executor inchangé ({int(new_workers)} workers).", False
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
# utils_md.py
|
|
2
|
+
import os, re, hashlib, secrets, urllib.parse, logging, time, datetime, numpy as np
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
import fitz # PyMuPDF
|
|
5
|
+
|
|
6
|
+
try:
|
|
7
|
+
import easyocr
|
|
8
|
+
except Exception:
|
|
9
|
+
easyocr = None
|
|
10
|
+
|
|
11
|
+
MAX_STEM_LEN = 40
|
|
12
|
+
IMAGE_RESOLUTION_SCALE = 2.0
|
|
13
|
+
|
|
14
|
+
_log = logging.getLogger(__name__)
|
|
15
|
+
logging.getLogger("fitz").setLevel(logging.ERROR)
|
|
16
|
+
logging.getLogger("PIL").setLevel(logging.WARNING)
|
|
17
|
+
|
|
18
|
+
def slugify(text: str) -> str:
|
|
19
|
+
text = text.strip().lower()
|
|
20
|
+
text = re.sub(r"[^\w\-]+", "-", text)
|
|
21
|
+
text = re.sub(r"-{2,}", "-", text)
|
|
22
|
+
return text.strip("-") or "file"
|
|
23
|
+
|
|
24
|
+
def short_stem(original_stem: str) -> str:
|
|
25
|
+
base = slugify(original_stem)[:MAX_STEM_LEN]
|
|
26
|
+
h = secrets.token_hex(6)
|
|
27
|
+
return f"{base}-{h}"
|
|
28
|
+
|
|
29
|
+
def truncate_path(path, max_length=240):
|
|
30
|
+
p = Path(path)
|
|
31
|
+
s = str(p)
|
|
32
|
+
if len(s) <= max_length:
|
|
33
|
+
return p
|
|
34
|
+
h = hashlib.md5(s.encode()).hexdigest()
|
|
35
|
+
new_name = (p.stem[:50] + "_" + h + p.suffix)
|
|
36
|
+
return p.parent / new_name
|
|
37
|
+
|
|
38
|
+
def try_read_text(path: Path) -> str:
|
|
39
|
+
for enc in ("utf-8", "utf-8-sig", "latin-1"):
|
|
40
|
+
try:
|
|
41
|
+
return urllib.parse.unquote(path.read_text(encoding=enc, errors="ignore"))
|
|
42
|
+
except Exception:
|
|
43
|
+
continue
|
|
44
|
+
return ""
|
|
45
|
+
|
|
46
|
+
def is_pdf_text_based(fpath: Path) -> bool:
|
|
47
|
+
try:
|
|
48
|
+
with fitz.open(fpath) as doc:
|
|
49
|
+
for page in doc:
|
|
50
|
+
if page.get_text().strip():
|
|
51
|
+
return True
|
|
52
|
+
return False
|
|
53
|
+
except Exception:
|
|
54
|
+
return False
|
|
55
|
+
|
|
56
|
+
def ocr_fallback(pdf_path: Path, langs=('fr','en')) -> str:
|
|
57
|
+
if easyocr is None:
|
|
58
|
+
raise RuntimeError("easyocr introuvable. Installez easyocr pour l'OCR.")
|
|
59
|
+
reader = easyocr.Reader(list(langs))
|
|
60
|
+
_ = reader.readtext(np.zeros((10, 10, 3), dtype=np.uint8), detail=0) # warm-up
|
|
61
|
+
text = []
|
|
62
|
+
with fitz.open(pdf_path) as doc:
|
|
63
|
+
for page in doc:
|
|
64
|
+
pix = page.get_pixmap(dpi=200)
|
|
65
|
+
img = np.frombuffer(pix.samples, dtype=np.uint8).reshape((pix.height, pix.width, pix.n))
|
|
66
|
+
result = reader.readtext(img)
|
|
67
|
+
text.extend([r[1] for r in result])
|
|
68
|
+
return "\n".join(text)
|
|
69
|
+
|
|
70
|
+
def strip_image_markdown(md_text: str) -> str:
|
|
71
|
+
md_text = re.sub(r'!\[[^\]]*\]\([^\)]+\)', '', md_text)
|
|
72
|
+
md_text = re.sub(r'<img\b[^>]*>', '', md_text, flags=re.IGNORECASE)
|
|
73
|
+
md_text = re.sub(r'\n{3,}', '\n\n', md_text)
|
|
74
|
+
return md_text.strip()
|
|
75
|
+
|
|
76
|
+
# --- COM helpers (Windows + Office)
|
|
77
|
+
def _make_word_invisible(word):
|
|
78
|
+
try:
|
|
79
|
+
word.Visible = False
|
|
80
|
+
word.DisplayAlerts = 0
|
|
81
|
+
word.ScreenUpdating = False
|
|
82
|
+
except Exception:
|
|
83
|
+
pass
|
|
84
|
+
|
|
85
|
+
def _make_powerpoint_invisible(ppt):
|
|
86
|
+
try:
|
|
87
|
+
ppt.Visible = 0 # 0=Hidden
|
|
88
|
+
except Exception:
|
|
89
|
+
pass
|
|
90
|
+
|
|
91
|
+
def convert_doc_to_docx(src: Path, out_dir: Path) -> Path:
|
|
92
|
+
import win32com.client
|
|
93
|
+
out_dir.mkdir(parents=True, exist_ok=True)
|
|
94
|
+
if src.suffix.lower() != ".doc":
|
|
95
|
+
return src if src.suffix.lower() == ".docx" else src
|
|
96
|
+
dst = out_dir / (src.stem + ".docx")
|
|
97
|
+
if dst.exists() and dst.stat().st_size > 0:
|
|
98
|
+
return dst
|
|
99
|
+
word = win32com.client.Dispatch("Word.Application")
|
|
100
|
+
_make_word_invisible(word)
|
|
101
|
+
try:
|
|
102
|
+
doc = word.Documents.Open(str(src), ReadOnly=True)
|
|
103
|
+
doc.SaveAs(str(dst), FileFormat=16) # DOCX
|
|
104
|
+
doc.Close(False)
|
|
105
|
+
if not dst.exists() or dst.stat().st_size == 0:
|
|
106
|
+
raise RuntimeError("DOCX non généré")
|
|
107
|
+
return dst
|
|
108
|
+
finally:
|
|
109
|
+
word.Quit()
|
|
110
|
+
|
|
111
|
+
def convert_ppt_to_pptx(src: Path, out_dir: Path) -> Path:
|
|
112
|
+
import win32com.client
|
|
113
|
+
out_dir.mkdir(parents=True, exist_ok=True)
|
|
114
|
+
if src.suffix.lower() != ".ppt":
|
|
115
|
+
return src if src.suffix.lower() == ".pptx" else src
|
|
116
|
+
dst = out_dir / (src.stem + ".pptx")
|
|
117
|
+
if dst.exists() and dst.stat().st_size > 0:
|
|
118
|
+
return dst
|
|
119
|
+
ppt = win32com.client.Dispatch("PowerPoint.Application")
|
|
120
|
+
_make_powerpoint_invisible(ppt)
|
|
121
|
+
try:
|
|
122
|
+
pres = ppt.Presentations.Open(str(src), WithWindow=False)
|
|
123
|
+
pres.SaveAs(str(dst), 24) # ppSaveAsOpenXMLPresentation
|
|
124
|
+
pres.Close()
|
|
125
|
+
if not dst.exists() or dst.stat().st_size == 0:
|
|
126
|
+
raise RuntimeError("PPTX non généré")
|
|
127
|
+
return dst
|
|
128
|
+
finally:
|
|
129
|
+
ppt.Quit()
|
|
130
|
+
|
|
131
|
+
def docx_to_pdf(src_docx: Path, out_dir: Path) -> Path:
|
|
132
|
+
import win32com.client
|
|
133
|
+
out_dir.mkdir(parents=True, exist_ok=True)
|
|
134
|
+
pdf_path = out_dir / (src_docx.stem + ".pdf")
|
|
135
|
+
if pdf_path.exists() and pdf_path.stat().st_size > 0:
|
|
136
|
+
return pdf_path
|
|
137
|
+
word = win32com.client.Dispatch("Word.Application")
|
|
138
|
+
_make_word_invisible(word)
|
|
139
|
+
try:
|
|
140
|
+
doc = word.Documents.Open(str(src_docx), ReadOnly=True)
|
|
141
|
+
try:
|
|
142
|
+
doc.ExportAsFixedFormat(OutputFileName=str(pdf_path), ExportFormat=17)
|
|
143
|
+
except Exception:
|
|
144
|
+
doc.SaveAs(str(pdf_path), FileFormat=17)
|
|
145
|
+
doc.Close(False)
|
|
146
|
+
if not pdf_path.exists() or pdf_path.stat().st_size == 0:
|
|
147
|
+
raise RuntimeError("PDF non généré depuis DOCX")
|
|
148
|
+
return pdf_path
|
|
149
|
+
finally:
|
|
150
|
+
word.Quit()
|
|
151
|
+
|
|
152
|
+
def pptx_to_pdf(src_pptx: Path, out_dir: Path) -> Path:
|
|
153
|
+
import win32com.client
|
|
154
|
+
out_dir.mkdir(parents=True, exist_ok=True)
|
|
155
|
+
pdf_path = out_dir / (src_pptx.stem + ".pdf")
|
|
156
|
+
if pdf_path.exists() and pdf_path.stat().st_size > 0:
|
|
157
|
+
return pdf_path
|
|
158
|
+
ppt = win32com.client.Dispatch("PowerPoint.Application")
|
|
159
|
+
_make_powerpoint_invisible(ppt)
|
|
160
|
+
try:
|
|
161
|
+
pres = ppt.Presentations.Open(str(src_pptx), WithWindow=False)
|
|
162
|
+
pres.SaveAs(str(pdf_path), 32) # PDF
|
|
163
|
+
pres.Close()
|
|
164
|
+
if not pdf_path.exists() or pdf_path.stat().st_size == 0:
|
|
165
|
+
raise RuntimeError("PDF non généré depuis PPTX")
|
|
166
|
+
return pdf_path
|
|
167
|
+
finally:
|
|
168
|
+
ppt.Quit()
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<ui version="4.0">
|
|
3
|
+
<class>Form</class>
|
|
4
|
+
<widget class="QWidget" name="Form">
|
|
5
|
+
<property name="geometry">
|
|
6
|
+
<rect>
|
|
7
|
+
<x>0</x>
|
|
8
|
+
<y>0</y>
|
|
9
|
+
<width>380</width>
|
|
10
|
+
<height>421</height>
|
|
11
|
+
</rect>
|
|
12
|
+
</property>
|
|
13
|
+
<property name="windowTitle">
|
|
14
|
+
<string>File Extension Selector</string>
|
|
15
|
+
</property>
|
|
16
|
+
<widget class="QGroupBox" name="groupBox">
|
|
17
|
+
<property name="geometry">
|
|
18
|
+
<rect>
|
|
19
|
+
<x>20</x>
|
|
20
|
+
<y>40</y>
|
|
21
|
+
<width>341</width>
|
|
22
|
+
<height>341</height>
|
|
23
|
+
</rect>
|
|
24
|
+
</property>
|
|
25
|
+
<property name="title">
|
|
26
|
+
<string>Parameters</string>
|
|
27
|
+
</property>
|
|
28
|
+
<widget class="QListWidget" name="listExtensions">
|
|
29
|
+
<property name="geometry">
|
|
30
|
+
<rect>
|
|
31
|
+
<x>20</x>
|
|
32
|
+
<y>70</y>
|
|
33
|
+
<width>301</width>
|
|
34
|
+
<height>192</height>
|
|
35
|
+
</rect>
|
|
36
|
+
</property>
|
|
37
|
+
</widget>
|
|
38
|
+
<widget class="QLabel" name="Description">
|
|
39
|
+
<property name="geometry">
|
|
40
|
+
<rect>
|
|
41
|
+
<x>10</x>
|
|
42
|
+
<y>20</y>
|
|
43
|
+
<width>281</width>
|
|
44
|
+
<height>51</height>
|
|
45
|
+
</rect>
|
|
46
|
+
</property>
|
|
47
|
+
<property name="sizePolicy">
|
|
48
|
+
<sizepolicy hsizetype="Maximum" vsizetype="Expanding">
|
|
49
|
+
<horstretch>0</horstretch>
|
|
50
|
+
<verstretch>0</verstretch>
|
|
51
|
+
</sizepolicy>
|
|
52
|
+
</property>
|
|
53
|
+
<property name="font">
|
|
54
|
+
<font>
|
|
55
|
+
<pointsize>8</pointsize>
|
|
56
|
+
</font>
|
|
57
|
+
</property>
|
|
58
|
+
<property name="text">
|
|
59
|
+
<string>This widget get a folder path to propagate it as a path , either as input or output path</string>
|
|
60
|
+
</property>
|
|
61
|
+
<property name="wordWrap">
|
|
62
|
+
<bool>true</bool>
|
|
63
|
+
</property>
|
|
64
|
+
</widget>
|
|
65
|
+
<widget class="QPushButton" name="fileButton">
|
|
66
|
+
<property name="geometry">
|
|
67
|
+
<rect>
|
|
68
|
+
<x>20</x>
|
|
69
|
+
<y>280</y>
|
|
70
|
+
<width>301</width>
|
|
71
|
+
<height>51</height>
|
|
72
|
+
</rect>
|
|
73
|
+
</property>
|
|
74
|
+
<property name="text">
|
|
75
|
+
<string>📂 Select a file with the selected extension</string>
|
|
76
|
+
</property>
|
|
77
|
+
</widget>
|
|
78
|
+
</widget>
|
|
79
|
+
</widget>
|
|
80
|
+
<resources/>
|
|
81
|
+
<connections/>
|
|
82
|
+
</ui>
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<ui version="4.0">
|
|
3
|
+
<class>Form</class>
|
|
4
|
+
<widget class="QWidget" name="Form">
|
|
5
|
+
<property name="geometry">
|
|
6
|
+
<rect>
|
|
7
|
+
<x>0</x>
|
|
8
|
+
<y>0</y>
|
|
9
|
+
<width>399</width>
|
|
10
|
+
<height>276</height>
|
|
11
|
+
</rect>
|
|
12
|
+
</property>
|
|
13
|
+
<property name="windowTitle">
|
|
14
|
+
<string>Form</string>
|
|
15
|
+
</property>
|
|
16
|
+
<widget class="QGroupBox" name="groupBox">
|
|
17
|
+
<property name="geometry">
|
|
18
|
+
<rect>
|
|
19
|
+
<x>20</x>
|
|
20
|
+
<y>40</y>
|
|
21
|
+
<width>361</width>
|
|
22
|
+
<height>151</height>
|
|
23
|
+
</rect>
|
|
24
|
+
</property>
|
|
25
|
+
<property name="title">
|
|
26
|
+
<string>Parameters</string>
|
|
27
|
+
</property>
|
|
28
|
+
<widget class="QLineEdit" name="modelName">
|
|
29
|
+
<property name="geometry">
|
|
30
|
+
<rect>
|
|
31
|
+
<x>100</x>
|
|
32
|
+
<y>30</y>
|
|
33
|
+
<width>241</width>
|
|
34
|
+
<height>20</height>
|
|
35
|
+
</rect>
|
|
36
|
+
</property>
|
|
37
|
+
</widget>
|
|
38
|
+
<widget class="QLabel" name="label_6">
|
|
39
|
+
<property name="geometry">
|
|
40
|
+
<rect>
|
|
41
|
+
<x>20</x>
|
|
42
|
+
<y>90</y>
|
|
43
|
+
<width>100</width>
|
|
44
|
+
<height>15</height>
|
|
45
|
+
</rect>
|
|
46
|
+
</property>
|
|
47
|
+
<property name="text">
|
|
48
|
+
<string>Max tokens</string>
|
|
49
|
+
</property>
|
|
50
|
+
<property name="alignment">
|
|
51
|
+
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
|
52
|
+
</property>
|
|
53
|
+
</widget>
|
|
54
|
+
<widget class="QLabel" name="label_3">
|
|
55
|
+
<property name="geometry">
|
|
56
|
+
<rect>
|
|
57
|
+
<x>240</x>
|
|
58
|
+
<y>90</y>
|
|
59
|
+
<width>100</width>
|
|
60
|
+
<height>15</height>
|
|
61
|
+
</rect>
|
|
62
|
+
</property>
|
|
63
|
+
<property name="text">
|
|
64
|
+
<string>Temperature</string>
|
|
65
|
+
</property>
|
|
66
|
+
<property name="alignment">
|
|
67
|
+
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
|
68
|
+
</property>
|
|
69
|
+
</widget>
|
|
70
|
+
<widget class="QSpinBox" name="boxMaxTokens">
|
|
71
|
+
<property name="geometry">
|
|
72
|
+
<rect>
|
|
73
|
+
<x>20</x>
|
|
74
|
+
<y>109</y>
|
|
75
|
+
<width>100</width>
|
|
76
|
+
<height>25</height>
|
|
77
|
+
</rect>
|
|
78
|
+
</property>
|
|
79
|
+
<property name="minimumSize">
|
|
80
|
+
<size>
|
|
81
|
+
<width>0</width>
|
|
82
|
+
<height>25</height>
|
|
83
|
+
</size>
|
|
84
|
+
</property>
|
|
85
|
+
<property name="maximumSize">
|
|
86
|
+
<size>
|
|
87
|
+
<width>100</width>
|
|
88
|
+
<height>16777215</height>
|
|
89
|
+
</size>
|
|
90
|
+
</property>
|
|
91
|
+
<property name="alignment">
|
|
92
|
+
<set>Qt::AlignCenter</set>
|
|
93
|
+
</property>
|
|
94
|
+
<property name="maximum">
|
|
95
|
+
<number>4096</number>
|
|
96
|
+
</property>
|
|
97
|
+
<property name="value">
|
|
98
|
+
<number>4096</number>
|
|
99
|
+
</property>
|
|
100
|
+
</widget>
|
|
101
|
+
<widget class="QDoubleSpinBox" name="boxTemperature">
|
|
102
|
+
<property name="geometry">
|
|
103
|
+
<rect>
|
|
104
|
+
<x>240</x>
|
|
105
|
+
<y>109</y>
|
|
106
|
+
<width>100</width>
|
|
107
|
+
<height>25</height>
|
|
108
|
+
</rect>
|
|
109
|
+
</property>
|
|
110
|
+
<property name="minimumSize">
|
|
111
|
+
<size>
|
|
112
|
+
<width>0</width>
|
|
113
|
+
<height>25</height>
|
|
114
|
+
</size>
|
|
115
|
+
</property>
|
|
116
|
+
<property name="maximumSize">
|
|
117
|
+
<size>
|
|
118
|
+
<width>100</width>
|
|
119
|
+
<height>16777215</height>
|
|
120
|
+
</size>
|
|
121
|
+
</property>
|
|
122
|
+
<property name="alignment">
|
|
123
|
+
<set>Qt::AlignCenter</set>
|
|
124
|
+
</property>
|
|
125
|
+
<property name="decimals">
|
|
126
|
+
<number>1</number>
|
|
127
|
+
</property>
|
|
128
|
+
<property name="maximum">
|
|
129
|
+
<double>1.000000000000000</double>
|
|
130
|
+
</property>
|
|
131
|
+
<property name="singleStep">
|
|
132
|
+
<double>0.100000000000000</double>
|
|
133
|
+
</property>
|
|
134
|
+
<property name="value">
|
|
135
|
+
<double>0.400000000000000</double>
|
|
136
|
+
</property>
|
|
137
|
+
</widget>
|
|
138
|
+
<widget class="QLabel" name="label">
|
|
139
|
+
<property name="geometry">
|
|
140
|
+
<rect>
|
|
141
|
+
<x>20</x>
|
|
142
|
+
<y>30</y>
|
|
143
|
+
<width>41</width>
|
|
144
|
+
<height>21</height>
|
|
145
|
+
</rect>
|
|
146
|
+
</property>
|
|
147
|
+
<property name="text">
|
|
148
|
+
<string>Model :</string>
|
|
149
|
+
</property>
|
|
150
|
+
</widget>
|
|
151
|
+
</widget>
|
|
152
|
+
<widget class="QPushButton" name="callApi">
|
|
153
|
+
<property name="geometry">
|
|
154
|
+
<rect>
|
|
155
|
+
<x>20</x>
|
|
156
|
+
<y>220</y>
|
|
157
|
+
<width>361</width>
|
|
158
|
+
<height>31</height>
|
|
159
|
+
</rect>
|
|
160
|
+
</property>
|
|
161
|
+
<property name="text">
|
|
162
|
+
<string>Call API</string>
|
|
163
|
+
</property>
|
|
164
|
+
</widget>
|
|
165
|
+
</widget>
|
|
166
|
+
<resources/>
|
|
167
|
+
<connections/>
|
|
168
|
+
</ui>
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<ui version="4.0">
|
|
3
|
+
<class>Form</class>
|
|
4
|
+
<widget class="QWidget" name="Form">
|
|
5
|
+
<property name="geometry">
|
|
6
|
+
<rect>
|
|
7
|
+
<x>0</x>
|
|
8
|
+
<y>0</y>
|
|
9
|
+
<width>700</width>
|
|
10
|
+
<height>500</height>
|
|
11
|
+
</rect>
|
|
12
|
+
</property>
|
|
13
|
+
<property name="windowTitle">
|
|
14
|
+
<string>Form</string>
|
|
15
|
+
</property>
|
|
16
|
+
<widget class="QGroupBox" name="groupBox">
|
|
17
|
+
<property name="geometry">
|
|
18
|
+
<rect>
|
|
19
|
+
<x>20</x>
|
|
20
|
+
<y>30</y>
|
|
21
|
+
<width>661</width>
|
|
22
|
+
<height>431</height>
|
|
23
|
+
</rect>
|
|
24
|
+
</property>
|
|
25
|
+
<property name="title">
|
|
26
|
+
<string>Parameters</string>
|
|
27
|
+
</property>
|
|
28
|
+
<widget class="QTextBrowser" name="textBrowser">
|
|
29
|
+
<property name="geometry">
|
|
30
|
+
<rect>
|
|
31
|
+
<x>10</x>
|
|
32
|
+
<y>130</y>
|
|
33
|
+
<width>641</width>
|
|
34
|
+
<height>291</height>
|
|
35
|
+
</rect>
|
|
36
|
+
</property>
|
|
37
|
+
</widget>
|
|
38
|
+
<widget class="QLabel" name="label">
|
|
39
|
+
<property name="geometry">
|
|
40
|
+
<rect>
|
|
41
|
+
<x>20</x>
|
|
42
|
+
<y>80</y>
|
|
43
|
+
<width>121</width>
|
|
44
|
+
<height>21</height>
|
|
45
|
+
</rect>
|
|
46
|
+
</property>
|
|
47
|
+
<property name="text">
|
|
48
|
+
<string>API Key :</string>
|
|
49
|
+
</property>
|
|
50
|
+
</widget>
|
|
51
|
+
<widget class="QLabel" name="Description">
|
|
52
|
+
<property name="geometry">
|
|
53
|
+
<rect>
|
|
54
|
+
<x>20</x>
|
|
55
|
+
<y>30</y>
|
|
56
|
+
<width>551</width>
|
|
57
|
+
<height>31</height>
|
|
58
|
+
</rect>
|
|
59
|
+
</property>
|
|
60
|
+
<property name="text">
|
|
61
|
+
<string>This widget generates a deepsearch answer on the column "prompt" of your input data.</string>
|
|
62
|
+
</property>
|
|
63
|
+
<property name="textFormat">
|
|
64
|
+
<enum>Qt::AutoText</enum>
|
|
65
|
+
</property>
|
|
66
|
+
<property name="alignment">
|
|
67
|
+
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
|
68
|
+
</property>
|
|
69
|
+
<property name="wordWrap">
|
|
70
|
+
<bool>true</bool>
|
|
71
|
+
</property>
|
|
72
|
+
</widget>
|
|
73
|
+
<widget class="QLineEdit" name="line_api_key">
|
|
74
|
+
<property name="geometry">
|
|
75
|
+
<rect>
|
|
76
|
+
<x>80</x>
|
|
77
|
+
<y>76</y>
|
|
78
|
+
<width>561</width>
|
|
79
|
+
<height>31</height>
|
|
80
|
+
</rect>
|
|
81
|
+
</property>
|
|
82
|
+
</widget>
|
|
83
|
+
</widget>
|
|
84
|
+
</widget>
|
|
85
|
+
<resources/>
|
|
86
|
+
<connections/>
|
|
87
|
+
</ui>
|