diff --git a/main.py b/main.py index b96f73c..56321ef 100644 --- a/main.py +++ b/main.py @@ -21,7 +21,7 @@ from PyQt5.QtGui import ( from PyQt5.QtWidgets import ( QApplication, QWidget, QLabel, QLineEdit, QTextEdit, QPushButton, QVBoxLayout, QHBoxLayout, QFileDialog, QMessageBox, QListWidget, QRadioButton, QButtonGroup, QCheckBox, QSplitter, - QDialog, QStackedWidget, QScrollArea, + QDialog, QStackedWidget, QScrollArea, QListWidgetItem, QAbstractItemView, # Added for QListWidget.NoSelection QFrame, QAbstractButton @@ -114,11 +114,11 @@ CONFIRM_ADD_ALL_CANCEL_DOWNLOAD = 3 class ConfirmAddAllDialog(QDialog): """A dialog to confirm adding multiple new names to Known.txt.""" - def __init__(self, new_names_list, parent=None): + def __init__(self, new_filter_objects_list, parent=None): super().__init__(parent) self.setWindowTitle("Confirm Adding New Names") self.setModal(True) - self.new_names_list = new_names_list + self.new_filter_objects_list = new_filter_objects_list self.user_choice = CONFIRM_ADD_ALL_CANCEL_DOWNLOAD # Default to cancel if closed main_layout = QVBoxLayout(self) @@ -132,20 +132,41 @@ class ConfirmAddAllDialog(QDialog): main_layout.addWidget(info_label) self.names_list_widget = QListWidget() - self.names_list_widget.addItems(self.new_names_list) - self.names_list_widget.setSelectionMode(QAbstractItemView.NoSelection) # Just for display + for filter_obj in self.new_filter_objects_list: + item_text = filter_obj["name"] + # Optionally, make group display more informative + # if filter_obj["is_group"]: + # item_text += f" (Group with aliases: {', '.join(filter_obj['aliases'])})" + + list_item = QListWidgetItem(item_text) + list_item.setFlags(list_item.flags() | Qt.ItemIsUserCheckable) + list_item.setCheckState(Qt.Checked) # Default to checked + list_item.setData(Qt.UserRole, filter_obj) # Store the full filter object + self.names_list_widget.addItem(list_item) + main_layout.addWidget(self.names_list_widget) + selection_buttons_layout = QHBoxLayout() + self.select_all_button = QPushButton("Select All") + self.select_all_button.clicked.connect(self._select_all_items) + selection_buttons_layout.addWidget(self.select_all_button) + + self.deselect_all_button = QPushButton("Deselect All") + self.deselect_all_button.clicked.connect(self._deselect_all_items) + selection_buttons_layout.addWidget(self.deselect_all_button) + selection_buttons_layout.addStretch() + main_layout.addLayout(selection_buttons_layout) + + buttons_layout = QHBoxLayout() - self.add_all_button = QPushButton("Add All to Known.txt") - self.add_all_button.clicked.connect(self._accept_add_all) - buttons_layout.addWidget(self.add_all_button) + self.add_selected_button = QPushButton("Add Selected to Known.txt") + self.add_selected_button.clicked.connect(self._accept_add_selected) + buttons_layout.addWidget(self.add_selected_button) self.skip_adding_button = QPushButton("Skip Adding These") self.skip_adding_button.clicked.connect(self._reject_skip_adding) buttons_layout.addWidget(self.skip_adding_button) - buttons_layout.addStretch() self.cancel_download_button = QPushButton("Cancel Download") @@ -158,10 +179,27 @@ class ConfirmAddAllDialog(QDialog): self.setMinimumHeight(350) if parent and hasattr(parent, 'get_dark_theme'): self.setStyleSheet(parent.get_dark_theme()) - self.add_all_button.setDefault(True) + self.add_selected_button.setDefault(True) - def _accept_add_all(self): - self.user_choice = CONFIRM_ADD_ALL_ACCEPTED + def _select_all_items(self): + for i in range(self.names_list_widget.count()): + self.names_list_widget.item(i).setCheckState(Qt.Checked) + + def _deselect_all_items(self): + for i in range(self.names_list_widget.count()): + self.names_list_widget.item(i).setCheckState(Qt.Unchecked) + + def _accept_add_selected(self): + selected_objects = [] + for i in range(self.names_list_widget.count()): + item = self.names_list_widget.item(i) + if item.checkState() == Qt.Checked: + filter_obj = item.data(Qt.UserRole) + if filter_obj: # Should always be true if populated correctly + selected_objects.append(filter_obj) + + # self.user_choice will be the list of selected filter_obj, or empty list if none selected + self.user_choice = selected_objects self.accept() def _reject_skip_adding(self): @@ -174,6 +212,10 @@ class ConfirmAddAllDialog(QDialog): def exec_(self): super().exec_() + # If user accepted but selected nothing, treat it as skipping addition + if isinstance(self.user_choice, list) and not self.user_choice: + QMessageBox.information(self, "No Selection", "No names were selected to be added. Skipping addition.") + return CONFIRM_ADD_ALL_SKIP_ADDING return self.user_choice class TourStepWidget(QWidget): """A single step/page in the tour.""" @@ -289,10 +331,13 @@ class TourDialog(QDialog): step1_content = ( "Hello! This quick tour will walk you through the main features of the Kemono Downloader, including recent updates like enhanced filtering, manga mode improvements, and cookie management." "" ) @@ -304,6 +349,7 @@ class TourDialog(QDialog): "
  • πŸ”— Kemono Creator/Post URL:
    " " Paste the full web address (URL) of a creator's page (e.g., https://kemono.su/patreon/user/12345) " "or a specific post (e.g., .../post/98765).

  • " + " or a Coomer creator (e.g., https://coomer.su/onlyfans/user/artistname) " "
  • πŸ“ Download Location:
    " " Click 'Browse...' to choose a folder on your computer where all downloaded files will be saved. " "This is required unless you are using 'Only Links' mode.

  • " @@ -315,28 +361,28 @@ class TourDialog(QDialog): self.step2 = TourStepWidget("β‘  Getting Started", step2_content) step3_content = ( - "Refine what you download with these filters:" + "Refine what you download with these filters (most are disabled in 'Only Links' or 'Only Archives' modes):" "