Generate settings tabs for each talker

This commit is contained in:
Mizaki 2023-02-11 01:18:56 +00:00
parent 3422a1093d
commit 83a8d5d5e1
4 changed files with 252 additions and 207 deletions

View File

@ -39,7 +39,7 @@ class RenameWindow(QtWidgets.QDialog):
comic_archive_list: list[ComicArchive],
data_style: int,
config: settngs.Config[settngs.Namespace],
talker: ComicTalker,
talkers: dict[str, ComicTalker],
) -> None:
super().__init__(parent)
@ -55,7 +55,7 @@ class RenameWindow(QtWidgets.QDialog):
)
self.config = config
self.talker = talker
self.talkers = talkers
self.comic_archive_list = comic_archive_list
self.data_style = data_style
self.rename_list: list[str] = []
@ -160,7 +160,7 @@ class RenameWindow(QtWidgets.QDialog):
self.twList.setSortingEnabled(True)
def modify_settings(self) -> None:
settingswin = SettingsWindow(self, self.config, self.talker)
settingswin = SettingsWindow(self, self.config, self.talkers)
settingswin.setModal(True)
settingswin.show_rename_tab()
settingswin.exec()

View File

@ -15,6 +15,7 @@
# limitations under the License.
from __future__ import annotations
import argparse
import html
import logging
import os
@ -131,7 +132,7 @@ Spider-Geddon #1 - New Players; Check In
class SettingsWindow(QtWidgets.QDialog):
def __init__(
self, parent: QtWidgets.QWidget, config: settngs.Config[settngs.Namespace], talker: ComicTalker
self, parent: QtWidgets.QWidget, config: settngs.Config[settngs.Namespace], talkers: dict[str, ComicTalker]
) -> None:
super().__init__(parent)
@ -142,7 +143,7 @@ class SettingsWindow(QtWidgets.QDialog):
)
self.config = config
self.talker = talker
self.talkers = talkers
self.name = "Settings"
if platform.system() == "Windows":
@ -194,7 +195,6 @@ class SettingsWindow(QtWidgets.QDialog):
self.btnBrowseRar.clicked.connect(self.select_rar)
self.btnClearCache.clicked.connect(self.clear_cache)
self.btnResetSettings.clicked.connect(self.reset_settings)
self.btnTestKey.clicked.connect(self.test_api_key)
self.btnTemplateHelp.clicked.connect(self.show_template_help)
self.cbxMoveFiles.clicked.connect(self.dir_test)
self.leDirectory.textEdited.connect(self.dir_test)
@ -223,7 +223,6 @@ class SettingsWindow(QtWidgets.QDialog):
self.btnRemoveValueReplacement.clicked.disconnect()
self.btnResetSettings.clicked.disconnect()
self.btnTemplateHelp.clicked.disconnect()
self.btnTestKey.clicked.disconnect()
self.cbxChangeExtension.clicked.disconnect()
self.cbxComplicatedParser.clicked.disconnect()
self.cbxMoveFiles.clicked.disconnect()
@ -235,6 +234,100 @@ class SettingsWindow(QtWidgets.QDialog):
self.twLiteralReplacements.cellChanged.disconnect()
self.twValueReplacements.cellChanged.disconnect()
self.sources: dict = {}
self.generate_source_option_tabs()
def generate_source_option_tabs(self) -> None:
def format_internal_name(int_name: str = "") -> str:
# Presume talker_<name>_<nm>
int_name_split = int_name.split("_")
del int_name_split[0:3]
int_name_split[0] = int_name_split[0].capitalize()
new_name = " ".join(int_name_split)
return new_name
# Add source sub tabs to Comic Sources tab
for talker_id, talker_obj in self.talkers.items():
# Add source to general tab dropdown list
self.cobxInfoSource.addItem(talker_obj.name, talker_id)
# Use a dict to make a var name from var
source_info = {}
tab_name = talker_id
source_info[tab_name] = {"tab": QtWidgets.QWidget(), "widgets": {}}
layout_grid = QtWidgets.QGridLayout()
row = 0
full_talker_name = "talker_" + talker_id
for option in self.config[1][full_talker_name][1].values():
current_widget = None
if option.action is not None and isinstance(option.action, type(argparse.BooleanOptionalAction)):
# bool equals a checkbox (QCheckBox)
current_widget = QtWidgets.QCheckBox(format_internal_name(option.internal_name))
# Set widget status
current_widget.setChecked(getattr(self.config[0], option.internal_name))
# Add widget and span all columns
layout_grid.addWidget(current_widget, row, 0, 1, -1)
elif isinstance(option.type, type(int)):
# int equals a spinbox (QSpinBox)
lbl = QtWidgets.QLabel(option.internal_name)
# Create a label
layout_grid.addWidget(lbl, row, 0)
current_widget = QtWidgets.QSpinBox()
current_widget.setRange(0, 9999)
current_widget.setValue(getattr(self.config[0], option.internal_name))
layout_grid.addWidget(current_widget, row, 1, alignment=QtCore.Qt.AlignLeft)
elif isinstance(option.type, type(float)):
# float equals a spinbox (QDoubleSpinBox)
lbl = QtWidgets.QLabel(format_internal_name(option.internal_name))
# Create a label
layout_grid.addWidget(lbl, row, 0)
current_widget = QtWidgets.QDoubleSpinBox()
current_widget.setRange(0, 9999.99)
current_widget.setValue(getattr(self.config[0], option.internal_name))
layout_grid.addWidget(current_widget, row, 1, alignment=QtCore.Qt.AlignLeft)
# type of None should be string
elif option.type is None or isinstance(option.type, type(str)):
# str equals a text field (QLineEdit)
lbl = QtWidgets.QLabel(format_internal_name(option.internal_name))
# Create a label
layout_grid.addWidget(lbl, row, 0)
current_widget = QtWidgets.QLineEdit()
# Set widget status
current_widget.setText(getattr(self.config[0], option.internal_name))
layout_grid.addWidget(current_widget, row, 1)
# Special case for api_key, make a test button
if option.internal_name.endswith("api_key"):
btn = QtWidgets.QPushButton("Test Key")
layout_grid.addWidget(btn, row, 2)
btn.clicked.connect(lambda state, sn=talker_id: self.test_api_key(sn))
row += 1
if current_widget:
# Add tooltip text
current_widget.setToolTip(option.help)
source_info[tab_name]["widgets"][option.internal_name] = current_widget
else:
# An empty current_widget implies an unsupported type
logger.info(f"Unsupported talker option found. Name: {option.internal_name} Type: {option.type}")
# Add vertical spacer
vspacer = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
layout_grid.addItem(vspacer, row, 0)
# Display the new widgets
source_info[tab_name]["tab"].setLayout(layout_grid)
# Add new sub tab to Comic Source tab
self.tTalkerTabs.addTab(source_info[tab_name]["tab"], talker_obj.name)
self.sources.update(source_info)
# Select active source in dropdown
self.cobxInfoSource.setCurrentIndex(self.cobxInfoSource.findData(self.config[0].talker_source))
# Set General as start tab
self.tabWidget.setCurrentIndex(0)
def addLiteralReplacement(self) -> None:
self.insertRow(self.twLiteralReplacements, self.twLiteralReplacements.rowCount(), Replacement("", "", False))
@ -312,17 +405,11 @@ class SettingsWindow(QtWidgets.QDialog):
self.cbxRemovePublisher.setChecked(self.config[0].filename_remove_publisher)
self.switch_parser()
self.cbxUseSeriesStartAsVolume.setChecked(self.config[0].talker_comicvine_cv_use_series_start_as_volume)
self.cbxClearFormBeforePopulating.setChecked(self.config[0].talker_clear_form_before_populating)
self.cbxRemoveHtmlTables.setChecked(self.config[0].talker_comicvine_cv_remove_html_tables)
self.cbxUseFilter.setChecked(self.config[0].talker_always_use_publisher_filter)
self.cbxSortByYear.setChecked(self.config[0].talker_sort_series_by_year)
self.cbxExactMatches.setChecked(self.config[0].talker_exact_series_matches_first)
self.leKey.setText(self.config[0].talker_comicvine_cv_api_key)
self.leURL.setText(self.config[0].talker_comicvine_cv_url)
self.cbxAssumeLoneCreditIsPrimary.setChecked(self.config[0].cbl_assume_lone_credit_is_primary)
self.cbxCopyCharactersToTags.setChecked(self.config[0].cbl_copy_characters_to_tags)
self.cbxCopyTeamsToTags.setChecked(self.config[0].cbl_copy_teams_to_tags)
@ -428,21 +515,12 @@ class SettingsWindow(QtWidgets.QDialog):
self.config[0].filename_remove_fcbd = self.cbxRemoveFCBD.isChecked()
self.config[0].filename_remove_publisher = self.cbxRemovePublisher.isChecked()
self.config[0].talker_comicvine_cv_use_series_start_as_volume = self.cbxUseSeriesStartAsVolume.isChecked()
self.config[0].talker_clear_form_before_populating = self.cbxClearFormBeforePopulating.isChecked()
self.config[0].talker_comicvine_cv_remove_html_tables = self.cbxRemoveHtmlTables.isChecked()
self.config[0].talker_always_use_publisher_filter = self.cbxUseFilter.isChecked()
self.config[0].talker_sort_series_by_year = self.cbxSortByYear.isChecked()
self.config[0].talker_exact_series_matches_first = self.cbxExactMatches.isChecked()
if self.leKey.text().strip():
self.config[0].talker_comicvine_cv_api_key = self.leKey.text().strip()
self.talker.api_key = self.config[0].talker_comicvine_cv_api_key
if self.leURL.text().strip():
self.config[0].talker_comicvine_cv_url = self.leURL.text().strip()
self.talker.api_url = self.config[0].talker_comicvine_cv_url
self.config[0].talker_source = str(self.cobxInfoSource.itemData(self.cobxInfoSource.currentIndex()))
self.config[0].cbl_assume_lone_credit_is_primary = self.cbxAssumeLoneCreditIsPrimary.isChecked()
self.config[0].cbl_copy_characters_to_tags = self.cbxCopyCharactersToTags.isChecked()
@ -464,6 +542,19 @@ class SettingsWindow(QtWidgets.QDialog):
self.config[0].rename_strict = self.cbxRenameStrict.isChecked()
self.config[0].rename_replacements = self.get_replacements()
# Read settings from sources tabs and generate self.settings.config data
for tab in self.sources.items():
for name, widget in tab[1]["widgets"].items():
widget_value = None
if isinstance(widget, (QtWidgets.QSpinBox, QtWidgets.QDoubleSpinBox)):
widget_value = widget.value()
elif isinstance(widget, QtWidgets.QLineEdit):
widget_value = widget.text().strip()
elif isinstance(widget, QtWidgets.QCheckBox):
widget_value = widget.isChecked()
setattr(self.config[0], name, widget_value)
self.update_talkers_config()
settngs.save_file(self.config, self.config[0].runtime_config.user_config_dir / "settings.json")
@ -472,8 +563,8 @@ class SettingsWindow(QtWidgets.QDialog):
def update_talkers_config(self) -> None:
cfg = settngs.normalize_config(self.config, True, True)
if f"talker_{self.talker.id}" in cfg[0]:
self.talker.parse_settings(cfg[0][f"talker_{self.talker.id}"])
for talker, talker_obj in self.talkers.items():
talker_obj.parse_settings(cfg[0][f"talker_{talker}"])
def select_rar(self) -> None:
self.select_file(self.leRarExePath, "RAR")
@ -483,11 +574,20 @@ class SettingsWindow(QtWidgets.QDialog):
ComicCacher(self.config[0].runtime_config.user_cache_dir, version).clear_cache()
QtWidgets.QMessageBox.information(self, self.name, "Cache has been cleared.")
def test_api_key(self) -> None:
if self.talker.check_api_key(self.leKey.text().strip(), self.leURL.text().strip()):
def test_api_key(self, source_id) -> None:
# Find URL and API key
for tab in self.sources.items():
for name, widget in tab[1]["widgets"].items():
if tab[0] == source_id:
if name.endswith("api_key"):
key = widget.text().strip()
if name.endswith("url"):
url = widget.text().strip()
if self.talkers[source_id].check_api_key(key, url):
QtWidgets.QMessageBox.information(self, "API Key Test", "Key is valid!")
else:
QtWidgets.QMessageBox.warning(self, "API Key Test", "Key is NOT valid.")
QtWidgets.QMessageBox.warning(self, "API Key Test", "Key is NOT valid!")
def reset_settings(self) -> None:
self.config = settngs.get_namespace(settngs.defaults(self.config[1]))

View File

@ -1354,7 +1354,7 @@ class TaggerWindow(QtWidgets.QMainWindow):
QtWidgets.QMessageBox.warning(self, self.tr("Web Link"), self.tr("Web Link is invalid."))
def show_settings(self) -> None:
settingswin = SettingsWindow(self, self.config, self.current_talker())
settingswin = SettingsWindow(self, self.config, self.talkers)
settingswin.setModal(True)
settingswin.exec()
settingswin.result()
@ -2047,7 +2047,7 @@ class TaggerWindow(QtWidgets.QMainWindow):
if self.dirty_flag_verification(
"File Rename", "If you rename files now, unsaved data in the form will be lost. Are you sure?"
):
dlg = RenameWindow(self, ca_list, self.load_data_style, self.config, self.current_talker())
dlg = RenameWindow(self, ca_list, self.load_data_style, self.config, self.talkers)
dlg.setModal(True)
if dlg.exec() and self.comic_archive is not None:
self.fileSelectionList.update_selected_rows()

View File

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>702</width>
<height>513</height>
<height>559</height>
</rect>
</property>
<property name="windowTitle">
@ -28,7 +28,7 @@
</sizepolicy>
</property>
<property name="currentIndex">
<number>0</number>
<number>3</number>
</property>
<widget class="QWidget" name="tGeneral">
<attribute name="title">
@ -308,75 +308,11 @@
</item>
</layout>
</widget>
<widget class="QWidget" name="tComicVine">
<widget class="QWidget" name="tComicTalkers">
<attribute name="title">
<string>Comic Vine</string>
<string>Comic Sources</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QGroupBox" name="grpBoxCVTop">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QCheckBox" name="cbxUseSeriesStartAsVolume">
<property name="text">
<string>Use Series Start Date as Volume</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="cbxClearFormBeforePopulating">
<property name="text">
<string>Clear Form Before Importing Comic Vine data</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="cbxRemoveHtmlTables">
<property name="text">
<string>Remove HTML tables from CV summary field</string>
</property>
</widget>
</item>
<item>
<widget class="Line" name="line_4">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="cbxSortByYear">
<property name="text">
<string>Initially sort Series search results by Starting Year instead of No. Issues</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="cbxExactMatches">
<property name="text">
<string>Initially show Series Name exact matches first</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="Line" name="line_4">
<property name="sizePolicy">
@ -391,100 +327,127 @@
</widget>
</item>
<item>
<widget class="QGroupBox" name="grpBoxKey">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
<widget class="QTabWidget" name="tTalkerTabs">
<property name="currentIndex">
<number>0</number>
</property>
<layout class="QGridLayout" name="gridLayout_8">
<item row="0" column="0" colspan="3">
<widget class="QLabel" name="lblKeyHelp">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;A personal API key from &lt;a href=&quot;http://www.comicvine.com/api/&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;Comic Vine&lt;/span&gt;&lt;/a&gt; is recommended in order to search for tag data. Login (or create a new account) there to get your key, and enter it below.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
</property>
<property name="alignment">
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse</set>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QPushButton" name="btnTestKey">
<property name="text">
<string>Test Key</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="leKey">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="readOnly">
<bool>false</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="lblKey">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>120</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>200</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Comic Vine API Key</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="lblURL">
<property name="text">
<string>Comic Vine URL</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="leURL"/>
</item>
</layout>
<widget class="QWidget" name="tabTalkersGeneral">
<attribute name="title">
<string>General</string>
</attribute>
<widget class="QCheckBox" name="cbxUseSeriesStartAsVolume">
<property name="geometry">
<rect>
<x>10</x>
<y>70</y>
<width>650</width>
<height>22</height>
</rect>
</property>
<property name="text">
<string>Use Series Start Date as Volume</string>
</property>
</widget>
<widget class="QCheckBox" name="cbxClearFormBeforePopulating">
<property name="geometry">
<rect>
<x>10</x>
<y>90</y>
<width>666</width>
<height>22</height>
</rect>
</property>
<property name="text">
<string>Clear Form Before Importing Comic Vine data</string>
</property>
</widget>
<widget class="QCheckBox" name="cbxSortByYear">
<property name="geometry">
<rect>
<x>10</x>
<y>130</y>
<width>666</width>
<height>22</height>
</rect>
</property>
<property name="text">
<string>Initially sort Series search results by Starting Year instead of No. Issues</string>
</property>
</widget>
<widget class="QCheckBox" name="cbxExactMatches">
<property name="geometry">
<rect>
<x>10</x>
<y>150</y>
<width>666</width>
<height>22</height>
</rect>
</property>
<property name="text">
<string>Initially show Series Name exact matches first</string>
</property>
</widget>
<widget class="Line" name="line_4">
<property name="geometry">
<rect>
<x>5</x>
<y>120</y>
<width>648</width>
<height>3</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
<widget class="QComboBox" name="cobxInfoSource">
<property name="geometry">
<rect>
<x>190</x>
<y>13</y>
<width>301</width>
<height>32</height>
</rect>
</property>
</widget>
<widget class="QLabel" name="leInfoSource">
<property name="geometry">
<rect>
<x>15</x>
<y>13</y>
<width>171</width>
<height>32</height>
</rect>
</property>
<property name="text">
<string>Select Information Source:</string>
</property>
</widget>
<widget class="Line" name="line">
<property name="geometry">
<rect>
<x>5</x>
<y>60</y>
<width>648</width>
<height>3</height>
</rect>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</widget>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_3"/>
</item>
<item>
<spacer name="verticalSpacer_3">
<property name="orientation">
@ -774,25 +737,16 @@
<property name="text">
<string>Find</string>
</property>
<property name="textAlignment">
<set>AlignCenter</set>
</property>
</column>
<column>
<property name="text">
<string>Replacement</string>
</property>
<property name="textAlignment">
<set>AlignCenter</set>
</property>
</column>
<column>
<property name="text">
<string>Strict Only</string>
</property>
<property name="textAlignment">
<set>AlignCenter</set>
</property>
</column>
</widget>
</item>
@ -819,25 +773,16 @@
<property name="text">
<string>Find</string>
</property>
<property name="textAlignment">
<set>AlignCenter</set>
</property>
</column>
<column>
<property name="text">
<string>Replacement</string>
</property>
<property name="textAlignment">
<set>AlignCenter</set>
</property>
</column>
<column>
<property name="text">
<string>Strict Only</string>
</property>
<property name="textAlignment">
<set>AlignCenter</set>
</property>
</column>
</widget>
</item>