diff --git a/.env.example b/.env.example index faf43b7..df1bb32 100644 --- a/.env.example +++ b/.env.example @@ -43,6 +43,9 @@ listWidth="100" #The wordwrap of items and help text noteWidth="75" +#CSV delimiter character (comma, semicolon, or tab) +csvDelimiter="," + # Custom input API cost - default value for gpt-3.5, replace with your actual input API cost - depends on the model, see https://openai.com/pricing input_cost= 0.002 diff --git a/gui/config_tab.py b/gui/config_tab.py index 6f06bb4..392103b 100644 --- a/gui/config_tab.py +++ b/gui/config_tab.py @@ -365,6 +365,15 @@ class ConfigTab(QWidget): self.note_width_spin.setFixedWidth(120) # Small format_form.addRow(note_label, self.note_width_spin) + csv_delim_label = QLabel("CSV Delimiter:") + csv_delim_label.setFixedWidth(150) + csv_delim_label.setAlignment(Qt.AlignRight | Qt.AlignVCenter) + self.csv_delimiter_combo = QComboBox() + self.csv_delimiter_combo.addItems([",", ";", "\t"]) + self.csv_delimiter_combo.setItemText(2, "Tab") # Display "Tab" instead of actual tab character + self.csv_delimiter_combo.setFixedWidth(120) # Small + format_form.addRow(csv_delim_label, self.csv_delimiter_combo) + right_column.addLayout(format_form) right_column.addWidget(create_horizontal_line()) @@ -474,6 +483,15 @@ class ConfigTab(QWidget): self.list_width_spin.setValue(int(os.getenv("listWidth", "100"))) self.note_width_spin.setValue(int(os.getenv("noteWidth", "75"))) + # Load CSV delimiter + csv_delim = os.getenv("csvDelimiter", ",") + if csv_delim == "\t": + self.csv_delimiter_combo.setCurrentIndex(2) # Tab + elif csv_delim == ";": + self.csv_delimiter_combo.setCurrentIndex(1) # Semicolon + else: + self.csv_delimiter_combo.setCurrentIndex(0) # Comma (default) + # Load custom API settings self.input_cost_spin.setValue(float(os.getenv("input_cost", "2.0"))) self.output_cost_spin.setValue(float(os.getenv("output_cost", "8.0"))) @@ -506,6 +524,11 @@ class ConfigTab(QWidget): set_key(self.env_file_path, "listWidth", str(self.list_width_spin.value())) set_key(self.env_file_path, "noteWidth", str(self.note_width_spin.value())) + # Save CSV delimiter + csv_delim_index = self.csv_delimiter_combo.currentIndex() + csv_delim_value = [",", ";", "\t"][csv_delim_index] + set_key(self.env_file_path, "csvDelimiter", csv_delim_value) + # Save custom API settings set_key(self.env_file_path, "input_cost", str(self.input_cost_spin.value())) set_key(self.env_file_path, "output_cost", str(self.output_cost_spin.value())) @@ -556,6 +579,7 @@ class ConfigTab(QWidget): self.width_spin.setValue(60) self.list_width_spin.setValue(100) self.note_width_spin.setValue(75) + self.csv_delimiter_combo.setCurrentIndex(0) # Comma (default) # Custom API settings self.input_cost_spin.setValue(2.0) @@ -582,6 +606,7 @@ class ConfigTab(QWidget): "width": self.width_spin.value(), "listWidth": self.list_width_spin.value(), "noteWidth": self.note_width_spin.value(), + "csvDelimiter": [",", ";", "\t"][self.csv_delimiter_combo.currentIndex()], "input_cost": self.input_cost_spin.value(), "output_cost": self.output_cost_spin.value() } diff --git a/gui/translation_tab.py b/gui/translation_tab.py index 2e7ecd6..922551d 100644 --- a/gui/translation_tab.py +++ b/gui/translation_tab.py @@ -986,6 +986,21 @@ class TranslationTab(QWidget): self.mode_combo.currentTextChanged.connect(self._on_mode_changed) trans_form.addRow(mode_label, self.mode_combo) + # CSV Format dropdown (only visible when CSV engine is selected) + self.csv_format_label = QLabel("CSV Format:") + self.csv_format_label.setFixedWidth(100) + self.csv_format_label.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) + self.csv_format_combo = QComboBox() + self.csv_format_combo.addItem("Translator++") + self.csv_format_combo.addItem("Single") + self.csv_format_combo.addItem("Multiple") + self.csv_format_combo.addItem("Speaker&Text") + self.csv_format_combo.setFixedWidth(300) + trans_form.addRow(self.csv_format_label, self.csv_format_combo) + # Hide by default (shown when CSV is selected) + self.csv_format_label.setVisible(False) + self.csv_format_combo.setVisible(False) + layout.addLayout(trans_form) layout.addWidget(create_horizontal_line()) @@ -1126,6 +1141,11 @@ class TranslationTab(QWidget): else: self.mode_combo.setCurrentIndex(0) + # Show/hide CSV format dropdown based on engine selection + is_csv = "csv" in lowered + self.csv_format_label.setVisible(is_csv) + self.csv_format_combo.setVisible(is_csv) + # Refresh file list to show only files matching the selected module's extensions self.refresh_file_lists() @@ -1607,6 +1627,13 @@ class TranslationTab(QWidget): ) if reply == QMessageBox.Yes: + # Write CSV format to csv.tmp if CSV module is selected + if "csv" in selected_module[0].lower(): + csv_format_index = self.csv_format_combo.currentIndex() + 1 # 1-based (1-4) + csv_tmp_path = self.project_root / "csv.tmp" + with open(csv_tmp_path, "w", encoding="utf-8") as f: + f.write(str(csv_format_index)) + # Switch to progress view self.file_stack.setCurrentIndex(1) diff --git a/modules/csv.py b/modules/csv.py index cd4a9ca..a73165c 100644 --- a/modules/csv.py +++ b/modules/csv.py @@ -26,6 +26,7 @@ LOCK = threading.Lock() WIDTH = int(os.getenv("width")) LISTWIDTH = int(os.getenv("listWidth")) NOTEWIDTH = int(os.getenv("noteWidth")) +CSV_DELIMITER = os.getenv("csvDelimiter", ",") # CSV delimiter character (comma, semicolon, tab) MAXHISTORY = 10 ESTIMATE = "" TOKENS = [0, 0] @@ -179,11 +180,11 @@ def parseCSV(readFile, writeFile, filename): totalLines = len(readFile.readlines()) readFile.seek(0) - reader = csv.reader(readFile, delimiter=",") + reader = csv.reader(readFile, delimiter=CSV_DELIMITER) if not ESTIMATE: writer = csv.writer( writeFile, - delimiter=",", + delimiter=CSV_DELIMITER, ) else: writer = "" @@ -214,7 +215,7 @@ def flush_progress_csv(writeFile, writer, rows): with LOCK: writeFile.seek(0) # Recreate writer at current position to avoid state issues - tmp_writer = csv.writer(writeFile, delimiter=",") + tmp_writer = csv.writer(writeFile, delimiter=CSV_DELIMITER) tmp_writer.writerows(rows) writeFile.truncate() writeFile.flush()