IO4IT 4.0.18__tar.gz → 4.0.22__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-4.0.22/PKG-INFO +7 -0
- io4it-4.0.22/io4it.egg-info/PKG-INFO +7 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/utils/pst_extractor/export_pst.py +0 -1
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/OWInboxMailMonitoring.py +17 -22
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/OWJsonToDataTable.py +28 -8
- io4it-4.0.22/orangecontrib/IO4IT/widgets/OWwordpdf2docx.py +451 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/designer/ow_json_to_data_table.ui +0 -13
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/designer/owinboxmailmonitoring.ui +1 -30
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/designer/wordpdf2docx.ui +79 -34
- {io4it-4.0.18 → io4it-4.0.22}/setup.py +1 -1
- io4it-4.0.18/PKG-INFO +0 -28
- io4it-4.0.18/io4it.egg-info/PKG-INFO +0 -28
- io4it-4.0.18/orangecontrib/IO4IT/widgets/OWwordpdf2docx.py +0 -277
- {io4it-4.0.18 → io4it-4.0.22}/io4it.egg-info/SOURCES.txt +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/io4it.egg-info/dependency_links.txt +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/io4it.egg-info/entry_points.txt +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/io4it.egg-info/namespace_packages.txt +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/io4it.egg-info/requires.txt +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/io4it.egg-info/top_level.txt +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/__init__.py +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/ocr_function/__init__.py +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/ocr_function/word_converter.py +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/toolViews/designer/key_manager_ui.ui +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/toolViews/designer/link_workflow_manager_ui.ui +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/toolViews/key_manager_ui.py +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/toolViews/linkHTLMWorkflow_manager_ui.py +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/utils/__init__.py +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/utils/environment_collector.py +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/utils/keys_manager.py +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/utils/mail.py +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/utils/pool_exec_utils.py +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/utils/pptx2jpg.py +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/utils/pst_extractor/TigerODMPST.dll +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/utils/pst_extractor/__init__.py +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/utils/pst_extractor/libpff.dll +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/utils/pst_extractor/z.dll +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/utils/secret_manager.py +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/utils/utils_md.py +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/OWChatGpt.py +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/OWDeep_Search.py +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/OWDoclingToMarkdown.py +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/OWExportMarkdown.py +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/OWExtractTablesDocxToXlsx.py +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/OWMD2HTML.py +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/OWMarkdownLoader.py +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/OWMarkdownizer.py +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/OWOfficeNormalizer.py +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/OWPPTX2JPG.py +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/OWParserHTML.py +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/OWPdfType.py +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/OWPipAuditor.py +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/OWProcessPoolExecutor.py +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/OWS3Uploader.py +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/OWS3downloader.py +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/OWS3list.py +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/OWWebSearch.py +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/OWXLSX_insert.py +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/OWmailLoader.py +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/OWmailSender.py +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/__init__.py +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/designer/__init__.py +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/designer/nogui.ui +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/designer/ow_extract_tables_docx_to_xlsx.ui +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/designer/ow_file_ext_selector.ui +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/designer/owchatgpt.ui +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/designer/owdeepsearch.ui +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/designer/owdoclingtomarkdown.ui +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/designer/owexportmarkdown.ui +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/designer/owinsertdatatoexcel.ui +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/designer/owmailloader.ui +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/designer/owmailsender.ui +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/designer/owmarkdownizer.ui +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/designer/owmarkdownloader.ui +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/designer/owmd2html.ui +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/designer/owofficenormalizer.ui +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/designer/owparserhtml.ui +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/designer/owpdftype.ui +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/designer/owpipauditor.ui +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/designer/owpptx2jpg.ui +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/designer/owprocesspoolexecutor.ui +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/designer/owspeechtotext.ui +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/designer/owvisualizationer.ui +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/designer/owwebsearch.ui +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/icons/__init__.py +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/icons/chatgpt.png +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/icons/check_pdf.png +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/icons/deepsearch.svg +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/icons/dep_md_old.png +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/icons/download.png +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/icons/export_md.png +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/icons/extract_table.png +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/icons/file_extensor.png +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/icons/html.png +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/icons/json-file.png +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/icons/list_aws.png +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/icons/load_md.png +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/icons/mail_loader.png +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/icons/mail_writer.png +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/icons/md.png +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/icons/monitor-email.svg +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/icons/office_normalizer.png +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/icons/owmd2html.svg +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/icons/pip_auditor.png +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/icons/pptx2jpg.png +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/icons/process_pool_executor.png +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/icons/speech_to_text.png +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/icons/upload.png +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/icons/visualizationer.png +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/icons/websearch.png +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/icons/wordpdf2docx.png +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/icons/xlsx_insert.png +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/IO4IT/widgets/icons_dev/__init__.py +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/orangecontrib/__init__.py +0 -0
- {io4it-4.0.18 → io4it-4.0.22}/setup.cfg +0 -0
io4it-4.0.22/PKG-INFO
ADDED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import sys
|
|
3
3
|
import Orange.data
|
|
4
|
-
from AnyQt.QtWidgets import QPushButton, QApplication, QRadioButton, QComboBox, QCheckBox, QSpinBox, QLabel
|
|
4
|
+
from AnyQt.QtWidgets import QPushButton, QApplication, QRadioButton, QComboBox, QCheckBox, QSpinBox, QLabel
|
|
5
5
|
from Orange.widgets import widget
|
|
6
6
|
from Orange.widgets.utils.signals import Input, Output
|
|
7
7
|
from Orange.widgets.settings import Setting
|
|
@@ -59,9 +59,6 @@ class OWInboxMailMonitoring(widget.OWWidget):
|
|
|
59
59
|
if new_text == self.type_co:
|
|
60
60
|
return
|
|
61
61
|
self.update_setting_from_qt_view()
|
|
62
|
-
visible = (self.type_co == "ARCHIVE PST")
|
|
63
|
-
self.lineEdit_pst_folder.setVisible(visible)
|
|
64
|
-
self.pushButton_browse_pst.setVisible(visible)
|
|
65
62
|
|
|
66
63
|
def on_text_changed2(self):
|
|
67
64
|
self.your_email_conf = str(self.comboBox2.currentText())
|
|
@@ -76,15 +73,6 @@ class OWInboxMailMonitoring(widget.OWWidget):
|
|
|
76
73
|
def on_email_count_changed(self, value: int):
|
|
77
74
|
self.email_count = value
|
|
78
75
|
|
|
79
|
-
def select_pst_folder(self):
|
|
80
|
-
if self.type_co != "ARCHIVE PST":
|
|
81
|
-
return
|
|
82
|
-
|
|
83
|
-
folder = QFileDialog.getExistingDirectory(self, "Select PST folder")
|
|
84
|
-
|
|
85
|
-
if folder:
|
|
86
|
-
self.pst_folder = folder
|
|
87
|
-
self.lineEdit_pst_folder.setText(folder)
|
|
88
76
|
|
|
89
77
|
|
|
90
78
|
# ------------------------------------------------------------------
|
|
@@ -139,7 +127,7 @@ class OWInboxMailMonitoring(widget.OWWidget):
|
|
|
139
127
|
self.checkBox_read_all.setChecked(self.read_all)
|
|
140
128
|
self.spinBox_email_count.setValue(self.email_count)
|
|
141
129
|
self._update_email_count_visibility()
|
|
142
|
-
|
|
130
|
+
|
|
143
131
|
|
|
144
132
|
def update_setting_from_qt_view(self):
|
|
145
133
|
self.type_co = str(self.comboBox.currentText())
|
|
@@ -156,7 +144,6 @@ class OWInboxMailMonitoring(widget.OWWidget):
|
|
|
156
144
|
self.sort_order = str(self.comboBox_sort_order.currentText())
|
|
157
145
|
self.read_all = self.checkBox_read_all.isChecked()
|
|
158
146
|
self.email_count = self.spinBox_email_count.value()
|
|
159
|
-
self.pst_folder = self.lineEdit_pst_folder.text()
|
|
160
147
|
|
|
161
148
|
# ------------------------------------------------------------------
|
|
162
149
|
# Init
|
|
@@ -181,9 +168,6 @@ class OWInboxMailMonitoring(widget.OWWidget):
|
|
|
181
168
|
self.checkBox_read_all = self.findChild(QCheckBox, 'checkBox_read_all')
|
|
182
169
|
self.spinBox_email_count = self.findChild(QSpinBox, 'spinBox_email_count')
|
|
183
170
|
self.label_email_count = self.findChild(QLabel, 'label_email_count')
|
|
184
|
-
self.pushButton_browse_pst = self.findChild(QPushButton, "pushButton_browse_pst")
|
|
185
|
-
self.lineEdit_pst_folder = self.findChild(QLineEdit, "lineEdit_pst_folder")
|
|
186
|
-
self.pushButton_browse_pst.clicked.connect(self.select_pst_folder)
|
|
187
171
|
|
|
188
172
|
# Populate connection type combobox
|
|
189
173
|
types_co = [
|
|
@@ -303,10 +287,21 @@ class OWInboxMailMonitoring(widget.OWWidget):
|
|
|
303
287
|
self.thread.safe_quit()
|
|
304
288
|
|
|
305
289
|
if self.type_co == "ARCHIVE PST":
|
|
306
|
-
self.
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
290
|
+
if self.data is None:
|
|
291
|
+
self.error("No input data detected")
|
|
292
|
+
return
|
|
293
|
+
meta_names = [m.name for m in self.data.domain.metas]
|
|
294
|
+
|
|
295
|
+
if "input_dir" not in meta_names:
|
|
296
|
+
self.error("Missing meta column 'input_dir'")
|
|
297
|
+
return
|
|
298
|
+
|
|
299
|
+
# Récupération de la première valeur
|
|
300
|
+
input_dir_idx = meta_names.index("input_dir")
|
|
301
|
+
self.pst_folder = str(self.data[0].metas[input_dir_idx])
|
|
302
|
+
|
|
303
|
+
if self.pst_folder == "" or self.pst_folder == "None":
|
|
304
|
+
self.error("The meta 'input_dir' is empty")
|
|
310
305
|
return
|
|
311
306
|
else:
|
|
312
307
|
if self.your_email_conf == "":
|
|
@@ -105,6 +105,7 @@ class OWJsonToDataTable(base_widget.BaseListWidget):
|
|
|
105
105
|
self.Outputs.data.send(None)
|
|
106
106
|
self.data = None
|
|
107
107
|
self.path = None
|
|
108
|
+
return
|
|
108
109
|
|
|
109
110
|
|
|
110
111
|
|
|
@@ -112,13 +113,32 @@ class OWJsonToDataTable(base_widget.BaseListWidget):
|
|
|
112
113
|
|
|
113
114
|
try :
|
|
114
115
|
if self.data:
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
116
|
+
obj = []
|
|
117
|
+
values = self.data.get_column(self.selected_column_name)
|
|
118
|
+
|
|
119
|
+
for row_index, raw in enumerate(values):
|
|
120
|
+
try:
|
|
121
|
+
if isinstance(raw, str):
|
|
122
|
+
if raw.strip() == "":
|
|
123
|
+
continue
|
|
124
|
+
current_obj = json.loads(raw)
|
|
125
|
+
if isinstance(current_obj, str):
|
|
126
|
+
current_obj = json.loads(current_obj)
|
|
127
|
+
else:
|
|
128
|
+
current_obj = raw
|
|
129
|
+
|
|
130
|
+
if isinstance(current_obj, list):
|
|
131
|
+
obj.extend(current_obj)
|
|
132
|
+
else:
|
|
133
|
+
obj.append(current_obj)
|
|
134
|
+
except Exception as e:
|
|
135
|
+
self.error(f"Error: {e}")
|
|
136
|
+
self.Outputs.data.send(None)
|
|
137
|
+
self.data = None
|
|
138
|
+
self.path = None
|
|
139
|
+
return
|
|
140
|
+
|
|
141
|
+
|
|
122
142
|
if self.path:
|
|
123
143
|
raw = self.path.get_column(self.selected_column_name)[0]
|
|
124
144
|
with open(raw, "r", encoding="utf-8") as f:
|
|
@@ -144,4 +164,4 @@ if __name__ == "__main__":
|
|
|
144
164
|
if hasattr(app, "exec"):
|
|
145
165
|
sys.exit(app.exec())
|
|
146
166
|
else:
|
|
147
|
-
sys.exit(app.exec_())
|
|
167
|
+
sys.exit(app.exec_())
|
|
@@ -0,0 +1,451 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import shutil
|
|
3
|
+
import sys
|
|
4
|
+
import tempfile
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
import Orange.data
|
|
8
|
+
from AnyQt.QtWidgets import QApplication, QCheckBox, QLabel
|
|
9
|
+
|
|
10
|
+
from Orange.widgets import widget
|
|
11
|
+
from Orange.widgets.utils.signals import Input, Output
|
|
12
|
+
from Orange.widgets.settings import Setting
|
|
13
|
+
|
|
14
|
+
if "site-packages/Orange/widgets" in os.path.dirname(os.path.abspath(__file__)).replace("\\", "/"):
|
|
15
|
+
from Orange.widgets.orangecontrib.AAIT.utils import thread_management
|
|
16
|
+
from Orange.widgets.orangecontrib.AAIT.utils.import_uic import uic
|
|
17
|
+
from Orange.widgets.orangecontrib.IO4IT.ocr_function import word_converter
|
|
18
|
+
else:
|
|
19
|
+
from orangecontrib.AAIT.utils import thread_management
|
|
20
|
+
from orangecontrib.AAIT.utils.import_uic import uic
|
|
21
|
+
from orangecontrib.IO4IT.ocr_function import word_converter
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _import_convert_to_pdf():
|
|
25
|
+
"""Import paresseux de `convert_to_pdf` (PageIndex)."""
|
|
26
|
+
if "site-packages/Orange/widgets" in os.path.dirname(os.path.abspath(__file__)).replace("\\", "/"):
|
|
27
|
+
from Orange.widgets.orangecontrib.AAIT.llm.PageIndex_functions import convert_to_pdf
|
|
28
|
+
else:
|
|
29
|
+
from orangecontrib.AAIT.llm.PageIndex_functions import convert_to_pdf
|
|
30
|
+
return convert_to_pdf
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def convert_single_pdf_to_docx(src: Path, dst: Path, force_basic_convertion: bool) -> None:
|
|
34
|
+
"""Convertit UN pdf vers UN docx dont le nom/chemin est imposé.
|
|
35
|
+
|
|
36
|
+
`word_converter.convert_pdf_structure` ne sait travailler que sur des
|
|
37
|
+
répertoires : on passe donc par un répertoire temporaire, puis on déplace
|
|
38
|
+
le fichier produit vers `dst`.
|
|
39
|
+
"""
|
|
40
|
+
dst.parent.mkdir(parents=True, exist_ok=True)
|
|
41
|
+
with tempfile.TemporaryDirectory() as tmp:
|
|
42
|
+
tmp_in = Path(tmp) / "in"
|
|
43
|
+
tmp_out = Path(tmp) / "out"
|
|
44
|
+
tmp_in.mkdir()
|
|
45
|
+
tmp_out.mkdir()
|
|
46
|
+
shutil.copy2(str(src), str(tmp_in / src.name))
|
|
47
|
+
word_converter.convert_pdf_structure(
|
|
48
|
+
[str(tmp_in)],
|
|
49
|
+
[str(tmp_out)],
|
|
50
|
+
ignore_exsting_out_put=False,
|
|
51
|
+
forceBasicConvertion=force_basic_convertion,
|
|
52
|
+
)
|
|
53
|
+
produced = sorted(tmp_out.rglob("*.docx"))
|
|
54
|
+
if not produced:
|
|
55
|
+
raise RuntimeError("aucun docx produit par la conversion")
|
|
56
|
+
os.replace(str(produced[0]), str(dst))
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class OWwordpdf2docx(widget.OWWidget):
|
|
60
|
+
name = "WordPdf2Docx"
|
|
61
|
+
description = "Convert PDF to DOCX and/or DOCX to PDF"
|
|
62
|
+
icon = "icons/wordpdf2docx.png"
|
|
63
|
+
if "site-packages/Orange/widgets" in os.path.dirname(os.path.abspath(__file__)).replace("\\", "/"):
|
|
64
|
+
icon = "icons_dev/wordpdf2docx.png"
|
|
65
|
+
gui = os.path.join(os.path.dirname(os.path.abspath(__file__)), "designer/wordpdf2docx.ui")
|
|
66
|
+
want_control_area = False
|
|
67
|
+
priority = 3000
|
|
68
|
+
category = "AAIT - TOOLBOX"
|
|
69
|
+
strDirectoryMode: str = Setting('True')
|
|
70
|
+
strFileMode: str = Setting('False')
|
|
71
|
+
strConvertPdfToDocx : str =Setting('True')
|
|
72
|
+
strConvertDocxToPdf : str =Setting('False')
|
|
73
|
+
strIgnoreExistingOuput :str =Setting('True')
|
|
74
|
+
strForceBasicConvertion :str =Setting('False')
|
|
75
|
+
|
|
76
|
+
class Inputs:
|
|
77
|
+
data = Input("Data", Orange.data.Table)
|
|
78
|
+
|
|
79
|
+
class Outputs:
|
|
80
|
+
data = Output("Data", Orange.data.Table)
|
|
81
|
+
|
|
82
|
+
@Inputs.data
|
|
83
|
+
def set_data(self, in_data):
|
|
84
|
+
self.data = in_data
|
|
85
|
+
if self.autorun:
|
|
86
|
+
self.run()
|
|
87
|
+
|
|
88
|
+
# ------------------------------------------------------------------ modes
|
|
89
|
+
def on_mode_dir_toggled(self):
|
|
90
|
+
if self._mode_updating:
|
|
91
|
+
return
|
|
92
|
+
self._mode_updating = True
|
|
93
|
+
try:
|
|
94
|
+
if not self.check_box_mode_dir.isChecked() and not self.check_box_mode_file.isChecked():
|
|
95
|
+
self.check_box_mode_dir.setChecked(True)
|
|
96
|
+
self.check_box_mode_file.setChecked(not self.check_box_mode_dir.isChecked())
|
|
97
|
+
finally:
|
|
98
|
+
self._mode_updating = False
|
|
99
|
+
self._store_mode()
|
|
100
|
+
|
|
101
|
+
def on_mode_file_toggled(self):
|
|
102
|
+
if self._mode_updating:
|
|
103
|
+
return
|
|
104
|
+
self._mode_updating = True
|
|
105
|
+
try:
|
|
106
|
+
if not self.check_box_mode_dir.isChecked() and not self.check_box_mode_file.isChecked():
|
|
107
|
+
self.check_box_mode_file.setChecked(True)
|
|
108
|
+
self.check_box_mode_dir.setChecked(not self.check_box_mode_file.isChecked())
|
|
109
|
+
finally:
|
|
110
|
+
self._mode_updating = False
|
|
111
|
+
self._store_mode()
|
|
112
|
+
|
|
113
|
+
def _store_mode(self):
|
|
114
|
+
self.strDirectoryMode = 'True' if self.check_box_mode_dir.isChecked() else 'False'
|
|
115
|
+
self.strFileMode = 'True' if self.check_box_mode_file.isChecked() else 'False'
|
|
116
|
+
self._update_options_enabled()
|
|
117
|
+
|
|
118
|
+
# ------------------------------------------------------------- checkboxes
|
|
119
|
+
def on_checkbox_toggled(self):
|
|
120
|
+
if self.check_box.isChecked():
|
|
121
|
+
self.strConvertPdfToDocx = 'True'
|
|
122
|
+
else:
|
|
123
|
+
self.strConvertPdfToDocx = 'False'
|
|
124
|
+
self._update_options_enabled()
|
|
125
|
+
|
|
126
|
+
def on_checkbox_toggled2(self):
|
|
127
|
+
if self.check_box2.isChecked():
|
|
128
|
+
self.strConvertDocxToPdf = 'True'
|
|
129
|
+
else:
|
|
130
|
+
self.strConvertDocxToPdf = 'False'
|
|
131
|
+
|
|
132
|
+
def on_checkbox_toggled3(self):
|
|
133
|
+
if self.check_box3.isChecked():
|
|
134
|
+
self.strIgnoreExistingOuput = 'True'
|
|
135
|
+
else:
|
|
136
|
+
self.strIgnoreExistingOuput ='False'
|
|
137
|
+
|
|
138
|
+
def on_checkbox_toggled4(self):
|
|
139
|
+
if self.check_box4.isChecked():
|
|
140
|
+
self.strForceBasicConvertion = 'True'
|
|
141
|
+
else:
|
|
142
|
+
self.strForceBasicConvertion ='False'
|
|
143
|
+
|
|
144
|
+
def _update_options_enabled(self):
|
|
145
|
+
file_mode = self.check_box_mode_file.isChecked()
|
|
146
|
+
# en mode fichier, le sens de conversion est déduit du couple path / path_out
|
|
147
|
+
self.check_box.setEnabled(not file_mode)
|
|
148
|
+
self.check_box2.setEnabled(not file_mode)
|
|
149
|
+
self.check_box4.setEnabled(file_mode or self.check_box.isChecked())
|
|
150
|
+
if self.label_description is not None:
|
|
151
|
+
if file_mode:
|
|
152
|
+
self.label_description.setText(
|
|
153
|
+
"Convert each file from the \"path\" column to the \"path_out\" column "
|
|
154
|
+
"(.pdf -> .docx or .docx -> .pdf)")
|
|
155
|
+
else:
|
|
156
|
+
self.label_description.setText(
|
|
157
|
+
"Convert PDF <-> DOCX for every file, from input_dir to output_dir")
|
|
158
|
+
|
|
159
|
+
def __init__(self):
|
|
160
|
+
super().__init__()
|
|
161
|
+
|
|
162
|
+
# Qt Management
|
|
163
|
+
self.setFixedWidth(470)
|
|
164
|
+
self.setFixedHeight(380)
|
|
165
|
+
uic.loadUi(self.gui, self)
|
|
166
|
+
|
|
167
|
+
self._mode_updating = True
|
|
168
|
+
|
|
169
|
+
self.check_box_mode_dir = self.findChild(QCheckBox, 'checkBox_mode_dir')
|
|
170
|
+
self.check_box_mode_file = self.findChild(QCheckBox, 'checkBox_mode_file')
|
|
171
|
+
self.check_box = self.findChild(QCheckBox, 'checkBox')
|
|
172
|
+
self.check_box2 = self.findChild(QCheckBox, 'checkBox_2')
|
|
173
|
+
self.check_box3 = self.findChild(QCheckBox, 'checkBox_3')
|
|
174
|
+
self.check_box4 = self.findChild(QCheckBox, 'checkBox_4')
|
|
175
|
+
self.label_description = self.findChild(QLabel, 'Description')
|
|
176
|
+
|
|
177
|
+
# sécurité : si les deux settings sont incohérents, on retombe sur le
|
|
178
|
+
# mode historique (dossier)
|
|
179
|
+
file_mode = (self.strFileMode == 'True' and self.strDirectoryMode != 'True')
|
|
180
|
+
self.check_box_mode_dir.setChecked(not file_mode)
|
|
181
|
+
self.check_box_mode_file.setChecked(file_mode)
|
|
182
|
+
|
|
183
|
+
self.check_box.setChecked(self.strConvertPdfToDocx == 'True')
|
|
184
|
+
self.check_box2.setChecked(self.strConvertDocxToPdf == 'True')
|
|
185
|
+
self.check_box3.setChecked(self.strIgnoreExistingOuput == 'True')
|
|
186
|
+
self.check_box4.setChecked(self.strForceBasicConvertion == 'True')
|
|
187
|
+
|
|
188
|
+
self.check_box_mode_dir.stateChanged.connect(self.on_mode_dir_toggled)
|
|
189
|
+
self.check_box_mode_file.stateChanged.connect(self.on_mode_file_toggled)
|
|
190
|
+
self.check_box.stateChanged.connect(self.on_checkbox_toggled)
|
|
191
|
+
self.check_box2.stateChanged.connect(self.on_checkbox_toggled2)
|
|
192
|
+
self.check_box3.stateChanged.connect(self.on_checkbox_toggled3)
|
|
193
|
+
self.check_box4.stateChanged.connect(self.on_checkbox_toggled4)
|
|
194
|
+
|
|
195
|
+
self._mode_updating = False
|
|
196
|
+
self._store_mode()
|
|
197
|
+
|
|
198
|
+
# Data Management
|
|
199
|
+
self.data = None
|
|
200
|
+
self.thread = None
|
|
201
|
+
self.autorun = True
|
|
202
|
+
self.result = None
|
|
203
|
+
self.post_initialized()
|
|
204
|
+
|
|
205
|
+
# -------------------------------------------------------------- utilities
|
|
206
|
+
def _check_string_column(self, column_name):
|
|
207
|
+
"""Retourne True si la colonne existe et est de type Text."""
|
|
208
|
+
try:
|
|
209
|
+
self.data.domain[column_name]
|
|
210
|
+
except KeyError:
|
|
211
|
+
self.error('You need a "%s" column in input data' % column_name)
|
|
212
|
+
return False
|
|
213
|
+
if type(self.data.domain[column_name]).__name__ != 'StringVariable':
|
|
214
|
+
self.error('"%s" column needs to be a Text' % column_name)
|
|
215
|
+
return False
|
|
216
|
+
return True
|
|
217
|
+
|
|
218
|
+
# -------------------------------------------------------------------- run
|
|
219
|
+
def run(self):
|
|
220
|
+
self.error("")
|
|
221
|
+
|
|
222
|
+
# if thread is running quit
|
|
223
|
+
if self.thread is not None:
|
|
224
|
+
self.thread.safe_quit()
|
|
225
|
+
|
|
226
|
+
if self.data is None:
|
|
227
|
+
return
|
|
228
|
+
|
|
229
|
+
ignore_existing_docx = (self.strIgnoreExistingOuput == 'True')
|
|
230
|
+
force_basic_convertion = (self.strForceBasicConvertion == 'True')
|
|
231
|
+
|
|
232
|
+
if self.strFileMode == 'True':
|
|
233
|
+
worker_process = self._build_file_worker(ignore_existing_docx, force_basic_convertion)
|
|
234
|
+
else:
|
|
235
|
+
worker_process = self._build_directory_worker(ignore_existing_docx, force_basic_convertion)
|
|
236
|
+
|
|
237
|
+
if worker_process is None:
|
|
238
|
+
return
|
|
239
|
+
|
|
240
|
+
# Start progress bar
|
|
241
|
+
self.progressBarInit()
|
|
242
|
+
|
|
243
|
+
# Connexion et démarrage du thread avec la fonction interne unifiée
|
|
244
|
+
self.thread = thread_management.Thread(worker_process)
|
|
245
|
+
self.thread.progress.connect(self.handle_progress)
|
|
246
|
+
self.thread.result.connect(self.handle_result)
|
|
247
|
+
self.thread.finish.connect(self.handle_finish)
|
|
248
|
+
self.thread.start()
|
|
249
|
+
|
|
250
|
+
# --------------------------------------------------------- mode répertoire
|
|
251
|
+
def _build_directory_worker(self, ignore_existing_docx, force_basic_convertion):
|
|
252
|
+
convert_pdf = (self.strConvertPdfToDocx == 'True')
|
|
253
|
+
convert_docx = (self.strConvertDocxToPdf == 'True')
|
|
254
|
+
|
|
255
|
+
# Verification of in_data
|
|
256
|
+
if not self._check_string_column("input_dir"):
|
|
257
|
+
return None
|
|
258
|
+
if not self._check_string_column("output_dir"):
|
|
259
|
+
return None
|
|
260
|
+
|
|
261
|
+
input_dir = self.data.get_column("input_dir")
|
|
262
|
+
output_dir = self.data.get_column("output_dir")
|
|
263
|
+
|
|
264
|
+
def worker_process():
|
|
265
|
+
errors = []
|
|
266
|
+
pdf_tasks = []
|
|
267
|
+
docx_tasks = []
|
|
268
|
+
|
|
269
|
+
# 1. Scan global initial pour compter tous les fichiers
|
|
270
|
+
for in_dir, out_dir in zip(input_dir, output_dir):
|
|
271
|
+
if not in_dir or not out_dir:
|
|
272
|
+
continue
|
|
273
|
+
in_dir, out_dir = str(in_dir), str(out_dir)
|
|
274
|
+
if not os.path.exists(in_dir):
|
|
275
|
+
continue
|
|
276
|
+
|
|
277
|
+
for root, _, files in os.walk(in_dir):
|
|
278
|
+
for name in files:
|
|
279
|
+
src = Path(root) / name
|
|
280
|
+
rel = os.path.relpath(root, in_dir)
|
|
281
|
+
dst_dir = Path(out_dir) if rel == "." else Path(out_dir) / rel
|
|
282
|
+
|
|
283
|
+
if convert_pdf and name.lower().endswith(".pdf"):
|
|
284
|
+
dst = dst_dir / f"{src.stem}.docx"
|
|
285
|
+
if not (ignore_existing_docx and dst.exists()):
|
|
286
|
+
pdf_tasks.append((src, dst))
|
|
287
|
+
elif convert_docx and name.lower().endswith((".docx", ".doc")):
|
|
288
|
+
dst = dst_dir / f"{src.stem}.pdf"
|
|
289
|
+
if not (ignore_existing_docx and dst.exists()):
|
|
290
|
+
docx_tasks.append((src, dst))
|
|
291
|
+
|
|
292
|
+
total_files = len(pdf_tasks) + len(docx_tasks)
|
|
293
|
+
if total_files == 0:
|
|
294
|
+
return "Success"
|
|
295
|
+
|
|
296
|
+
processed_count = 0
|
|
297
|
+
|
|
298
|
+
# 2. Exécution séquentielle : PDF -> DOCX
|
|
299
|
+
for src, dst in pdf_tasks:
|
|
300
|
+
try:
|
|
301
|
+
dst.parent.mkdir(parents=True, exist_ok=True)
|
|
302
|
+
word_converter.convert_pdf_structure(
|
|
303
|
+
[str(src.parent)],
|
|
304
|
+
[str(dst.parent)],
|
|
305
|
+
ignore_exsting_out_put=ignore_existing_docx,
|
|
306
|
+
forceBasicConvertion=force_basic_convertion
|
|
307
|
+
)
|
|
308
|
+
except Exception as e:
|
|
309
|
+
errors.append(f"Erreur PDF->DOCX ({src.name}): {e}")
|
|
310
|
+
|
|
311
|
+
processed_count += 1
|
|
312
|
+
try:
|
|
313
|
+
self.thread.progress.emit((processed_count / total_files) * 100)
|
|
314
|
+
except Exception:
|
|
315
|
+
pass
|
|
316
|
+
|
|
317
|
+
# 3. Exécution séquentielle : DOCX -> PDF
|
|
318
|
+
if docx_tasks:
|
|
319
|
+
convert_to_pdf = _import_convert_to_pdf()
|
|
320
|
+
for src, dst in docx_tasks:
|
|
321
|
+
try:
|
|
322
|
+
dst.parent.mkdir(parents=True, exist_ok=True)
|
|
323
|
+
convert_to_pdf(Path(src), Path(dst))
|
|
324
|
+
except Exception as e:
|
|
325
|
+
errors.append(f"Erreur DOCX->PDF ({src.name}): {e}")
|
|
326
|
+
|
|
327
|
+
processed_count += 1
|
|
328
|
+
try:
|
|
329
|
+
self.thread.progress.emit((processed_count / total_files) * 100)
|
|
330
|
+
except Exception:
|
|
331
|
+
pass
|
|
332
|
+
|
|
333
|
+
if errors:
|
|
334
|
+
return "\n".join(errors)
|
|
335
|
+
return "Success"
|
|
336
|
+
|
|
337
|
+
return worker_process
|
|
338
|
+
|
|
339
|
+
# ------------------------------------------------------------ mode fichier
|
|
340
|
+
def _build_file_worker(self, ignore_existing_docx, force_basic_convertion):
|
|
341
|
+
# Verification of in_data
|
|
342
|
+
if not self._check_string_column("path"):
|
|
343
|
+
return None
|
|
344
|
+
if not self._check_string_column("path_out"):
|
|
345
|
+
return None
|
|
346
|
+
|
|
347
|
+
path_in = self.data.get_column("path")
|
|
348
|
+
path_out = self.data.get_column("path_out")
|
|
349
|
+
|
|
350
|
+
def worker_process():
|
|
351
|
+
errors = []
|
|
352
|
+
tasks = []
|
|
353
|
+
|
|
354
|
+
# 1. Construction et validation des couples path / path_out
|
|
355
|
+
for index, (p_in, p_out) in enumerate(zip(path_in, path_out), start=1):
|
|
356
|
+
if not p_in or not p_out:
|
|
357
|
+
continue
|
|
358
|
+
src = Path(str(p_in))
|
|
359
|
+
dst = Path(str(p_out))
|
|
360
|
+
src_ext = src.suffix.lower()
|
|
361
|
+
dst_ext = dst.suffix.lower()
|
|
362
|
+
|
|
363
|
+
if src_ext == ".pdf" and dst_ext == ".docx":
|
|
364
|
+
direction = "pdf2docx"
|
|
365
|
+
elif src_ext in (".docx", ".doc") and dst_ext == ".pdf":
|
|
366
|
+
direction = "docx2pdf"
|
|
367
|
+
else:
|
|
368
|
+
errors.append(
|
|
369
|
+
f"Ligne {index} : couple invalide ({src.name} -> {dst.name}), "
|
|
370
|
+
f"attendu .pdf -> .docx ou .docx -> .pdf")
|
|
371
|
+
continue
|
|
372
|
+
|
|
373
|
+
if not src.exists():
|
|
374
|
+
errors.append(f"Ligne {index} : fichier introuvable ({src})")
|
|
375
|
+
continue
|
|
376
|
+
|
|
377
|
+
if ignore_existing_docx and dst.exists():
|
|
378
|
+
continue
|
|
379
|
+
|
|
380
|
+
tasks.append((direction, src, dst))
|
|
381
|
+
|
|
382
|
+
total_files = len(tasks)
|
|
383
|
+
if total_files == 0:
|
|
384
|
+
if errors:
|
|
385
|
+
return "\n".join(errors)
|
|
386
|
+
return "Success"
|
|
387
|
+
|
|
388
|
+
convert_to_pdf = None
|
|
389
|
+
if any(direction == "docx2pdf" for direction, _, _ in tasks):
|
|
390
|
+
convert_to_pdf = _import_convert_to_pdf()
|
|
391
|
+
|
|
392
|
+
processed_count = 0
|
|
393
|
+
|
|
394
|
+
# 2. Exécution séquentielle, fichier par fichier
|
|
395
|
+
for direction, src, dst in tasks:
|
|
396
|
+
try:
|
|
397
|
+
dst.parent.mkdir(parents=True, exist_ok=True)
|
|
398
|
+
if direction == "pdf2docx":
|
|
399
|
+
convert_single_pdf_to_docx(src, dst, force_basic_convertion)
|
|
400
|
+
else:
|
|
401
|
+
convert_to_pdf(Path(src), Path(dst))
|
|
402
|
+
except Exception as e:
|
|
403
|
+
if direction == "pdf2docx":
|
|
404
|
+
errors.append(f"Erreur PDF->DOCX ({src.name}): {e}")
|
|
405
|
+
else:
|
|
406
|
+
errors.append(f"Erreur DOCX->PDF ({src.name}): {e}")
|
|
407
|
+
|
|
408
|
+
processed_count += 1
|
|
409
|
+
try:
|
|
410
|
+
self.thread.progress.emit((processed_count / total_files) * 100)
|
|
411
|
+
except Exception:
|
|
412
|
+
pass
|
|
413
|
+
|
|
414
|
+
if errors:
|
|
415
|
+
return "\n".join(errors)
|
|
416
|
+
return "Success"
|
|
417
|
+
|
|
418
|
+
return worker_process
|
|
419
|
+
|
|
420
|
+
def handle_progress(self, value: float) -> None:
|
|
421
|
+
self.progressBarSet(value)
|
|
422
|
+
|
|
423
|
+
def handle_result(self, result):
|
|
424
|
+
try:
|
|
425
|
+
self.result = result
|
|
426
|
+
if result == "Success":
|
|
427
|
+
self.error("")
|
|
428
|
+
else:
|
|
429
|
+
self.error(result)
|
|
430
|
+
|
|
431
|
+
self.Outputs.data.send(self.data)
|
|
432
|
+
except Exception as e:
|
|
433
|
+
print("An error occurred when sending out_data:", e)
|
|
434
|
+
self.Outputs.data.send(None)
|
|
435
|
+
return
|
|
436
|
+
|
|
437
|
+
def handle_finish(self):
|
|
438
|
+
print("conversion finished")
|
|
439
|
+
self.progressBarFinished()
|
|
440
|
+
|
|
441
|
+
def post_initialized(self):
|
|
442
|
+
pass
|
|
443
|
+
|
|
444
|
+
if __name__ == "__main__":
|
|
445
|
+
app = QApplication(sys.argv)
|
|
446
|
+
my_widget = OWwordpdf2docx()
|
|
447
|
+
my_widget.show()
|
|
448
|
+
if hasattr(app, "exec"):
|
|
449
|
+
sys.exit(app.exec())
|
|
450
|
+
else:
|
|
451
|
+
sys.exit(app.exec_())
|
|
@@ -38,19 +38,6 @@
|
|
|
38
38
|
<string>Convert Json to Orange data table. You need to pass a content in input.</string>
|
|
39
39
|
</property>
|
|
40
40
|
</widget>
|
|
41
|
-
<widget class="QLabel" name="label_2">
|
|
42
|
-
<property name="geometry">
|
|
43
|
-
<rect>
|
|
44
|
-
<x>10</x>
|
|
45
|
-
<y>50</y>
|
|
46
|
-
<width>401</width>
|
|
47
|
-
<height>21</height>
|
|
48
|
-
</rect>
|
|
49
|
-
</property>
|
|
50
|
-
<property name="text">
|
|
51
|
-
<string>You can only convert the first row from the table.</string>
|
|
52
|
-
</property>
|
|
53
|
-
</widget>
|
|
54
41
|
<widget class="QLabel" name="label_3">
|
|
55
42
|
<property name="geometry">
|
|
56
43
|
<rect>
|
|
@@ -200,36 +200,7 @@
|
|
|
200
200
|
<height>22</height>
|
|
201
201
|
</rect>
|
|
202
202
|
</property>
|
|
203
|
-
|
|
204
|
-
<string>PST folder :</string>
|
|
205
|
-
</property>
|
|
206
|
-
</widget>
|
|
207
|
-
|
|
208
|
-
<widget class="QLineEdit" name="lineEdit_pst_folder">
|
|
209
|
-
<property name="geometry">
|
|
210
|
-
<rect>
|
|
211
|
-
<x>110</x>
|
|
212
|
-
<y>280</y>
|
|
213
|
-
<width>480</width>
|
|
214
|
-
<height>22</height>
|
|
215
|
-
</rect>
|
|
216
|
-
</property>
|
|
217
|
-
</widget>
|
|
218
|
-
|
|
219
|
-
<widget class="QPushButton" name="pushButton_browse_pst">
|
|
220
|
-
<property name="geometry">
|
|
221
|
-
<rect>
|
|
222
|
-
<x>600</x>
|
|
223
|
-
<y>280</y>
|
|
224
|
-
<width>60</width>
|
|
225
|
-
<height>22</height>
|
|
226
|
-
</rect>
|
|
227
|
-
</property>
|
|
228
|
-
<property name="text">
|
|
229
|
-
<string>...</string>
|
|
230
|
-
</property>
|
|
231
|
-
</widget>
|
|
232
|
-
|
|
203
|
+
</widget>
|
|
233
204
|
</widget>
|
|
234
205
|
|
|
235
206
|
<widget class="QCheckBox" name="checkBox_send">
|