diff --git a/tagstudio/src/core/enums.py b/tagstudio/src/core/enums.py index d61fe5a..d6b274e 100644 --- a/tagstudio/src/core/enums.py +++ b/tagstudio/src/core/enums.py @@ -17,3 +17,10 @@ class Theme(str, enum.Enum): COLOR_PRESSED = "#65EEEEEE" COLOR_DISABLED = "#65F39CAA" COLOR_DISABLED_BG = "#65440D12" + + +class SearchMode(int, enum.Enum): + """Operational modes for item searching.""" + + AND = 0 + OR = 1 diff --git a/tagstudio/src/core/library.py b/tagstudio/src/core/library.py index bf7d6b6..4a4b70f 100644 --- a/tagstudio/src/core/library.py +++ b/tagstudio/src/core/library.py @@ -20,6 +20,7 @@ from typing_extensions import Self from src.core.json_typing import JsonCollation, JsonEntry, JsonLibary, JsonTag from src.core.utils.str import strip_punctuation from src.core.utils.web import strip_web_protocol +from src.core.enums import SearchMode from src.core.constants import ( BACKUP_FOLDER_NAME, COLLAGE_FOLDER_NAME, @@ -340,7 +341,7 @@ class Library: # That filename can then be used to provide quick lookup to image metadata entries in the Library. self.filename_to_entry_id_map: dict[Path, int] = {} # A list of file extensions to be ignored by TagStudio. - self.default_ext_blacklist: list = ["json", "xmp", "aae"] + self.default_ext_blacklist: list = [".json", ".xmp", ".aae"] self.ignored_extensions: list = self.default_ext_blacklist # Tags ================================================================= @@ -1290,7 +1291,12 @@ class Library: return -1 def search_library( - self, query: str = None, entries=True, collations=True, tag_groups=True + self, + query: str = None, + entries=True, + collations=True, + tag_groups=True, + search_mode=SearchMode.AND, ) -> list[tuple[ItemType, int]]: """ Uses a search query to generate a filtered results list. @@ -1300,7 +1306,7 @@ class Library: # self.filtered_entries.clear() results: list[tuple[ItemType, int]] = [] collations_added = [] - + # print(f"Searching Library with query: {query} search_mode: {search_mode}") if query: # start_time = time.time() query = query.strip().lower() @@ -1320,6 +1326,7 @@ class Library: # Preprocess the Tag terms. if query_words: + # print(query_words, self._tag_strings_to_id_map) for i, term in enumerate(query_words): for j, term in enumerate(query_words): if ( @@ -1328,6 +1335,8 @@ class Library: in self._tag_strings_to_id_map ): all_tag_terms.append(" ".join(query_words[i : j + 1])) + # print(all_tag_terms) + # This gets rid of any accidental term inclusions because they were words # in another term. Ex. "3d" getting added in "3d art" for i, term in enumerate(all_tag_terms): @@ -1403,36 +1412,8 @@ class Library: # elif query in entry.filename.lower(): # self.filtered_entries.append(index) elif entry_tags: - # For each verified, extracted Tag term. - failure_to_union_terms = False - for term in all_tag_terms: - # If the term from the previous loop was already verified: - if not failure_to_union_terms: - cluster: set = set() - # Add the immediate associated Tags to the set (ex. Name, Alias hits) - # Since this term could technically map to multiple IDs, iterate over it - # (You're 99.9999999% likely to just get 1 item) - for id in self._tag_strings_to_id_map[term]: - cluster.add(id) - cluster = cluster.union( - set(self.get_tag_cluster(id)) - ) - # print(f'Full Cluster: {cluster}') - # For each of the Tag IDs in the term's ID cluster: - for t in cluster: - # Assume that this ID from the cluster is not in the Entry. - # Wait to see if proven wrong. - failure_to_union_terms = True - # If the ID actually is in the Entry, - if t in entry_tags: - # There wasn't a failure to find one of the term's cluster IDs in the Entry. - # There is also no more need to keep checking the rest of the terms in the cluster. - failure_to_union_terms = False - # print(f'FOUND MATCH: {t}') - break - # print(f'\tFailure to Match: {t}') - # If there even were tag terms to search through AND they all match an entry - if all_tag_terms and not failure_to_union_terms: + # function to add entry to results + def add_entry(entry: Entry): # self.filter_entries.append() # self.filtered_file_list.append(file) # results.append((SearchItemType.ENTRY, entry.id)) @@ -1457,6 +1438,54 @@ class Library: if not added: results.append((ItemType.ENTRY, entry.id)) + if search_mode == SearchMode.AND: # Include all terms + # For each verified, extracted Tag term. + failure_to_union_terms = False + for term in all_tag_terms: + # If the term from the previous loop was already verified: + if not failure_to_union_terms: + cluster: set = set() + # Add the immediate associated Tags to the set (ex. Name, Alias hits) + # Since this term could technically map to multiple IDs, iterate over it + # (You're 99.9999999% likely to just get 1 item) + for id in self._tag_strings_to_id_map[term]: + cluster.add(id) + cluster = cluster.union( + set(self.get_tag_cluster(id)) + ) + # print(f'Full Cluster: {cluster}') + # For each of the Tag IDs in the term's ID cluster: + for t in cluster: + # Assume that this ID from the cluster is not in the Entry. + # Wait to see if proven wrong. + failure_to_union_terms = True + # If the ID actually is in the Entry, + if t in entry_tags: + # There wasn't a failure to find one of the term's cluster IDs in the Entry. + # There is also no more need to keep checking the rest of the terms in the cluster. + failure_to_union_terms = False + # print(f"FOUND MATCH: {t}") + break + # print(f'\tFailure to Match: {t}') + # # failure_to_union_terms is used to determine if all terms in the query were found in the entry. + # # If there even were tag terms to search through AND they all match an entry + if all_tag_terms and not failure_to_union_terms: + add_entry(entry) + + if search_mode == SearchMode.OR: # Include any terms + # For each verified, extracted Tag term. + for term in all_tag_terms: + # Add the immediate associated Tags to the set (ex. Name, Alias hits) + # Since this term could technically map to multiple IDs, iterate over it + # (You're 99.9999999% likely to just get 1 item) + for id in self._tag_strings_to_id_map[term]: + # If the ID actually is in the Entry, + if id in entry_tags: + # check if result already contains the entry + if (ItemType.ENTRY, entry.id) not in results: + add_entry(entry) + break + # sys.stdout.write( # f'\r[INFO][FILTER]: {len(self.filtered_file_list)} matches found') # sys.stdout.flush() diff --git a/tagstudio/src/qt/main_window.py b/tagstudio/src/qt/main_window.py index 8987732..1eb2053 100644 --- a/tagstudio/src/qt/main_window.py +++ b/tagstudio/src/qt/main_window.py @@ -18,7 +18,8 @@ from PySide6.QtGui import (QFont, QAction) from PySide6.QtWidgets import (QComboBox, QFrame, QGridLayout, QHBoxLayout, QVBoxLayout, QLayout, QLineEdit, QMainWindow, QPushButton, QScrollArea, QSizePolicy, - QStatusBar, QWidget, QSplitter) + QStatusBar, QWidget, QSplitter, QCheckBox, + QSpacerItem) from src.qt.pagination import Pagination @@ -52,6 +53,36 @@ class Ui_MainWindow(QMainWindow): self.gridLayout.setObjectName(u"gridLayout") self.horizontalLayout = QHBoxLayout() self.horizontalLayout.setObjectName(u"horizontalLayout") + + # ComboBox goup for search type and thumbnail size + self.horizontalLayout_3 = QHBoxLayout() + self.horizontalLayout_3.setObjectName("horizontalLayout_3") + + # left side spacer + spacerItem = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) + self.horizontalLayout_3.addItem(spacerItem) + + # Search type selector + self.comboBox_2 = QComboBox(self.centralwidget) + self.comboBox_2.setMinimumSize(QSize(165, 0)) + self.comboBox_2.setObjectName("comboBox_2") + self.comboBox_2.addItem("") + self.comboBox_2.addItem("") + self.horizontalLayout_3.addWidget(self.comboBox_2) + + # Thumbnail Size placeholder + self.comboBox = QComboBox(self.centralwidget) + self.comboBox.setObjectName(u"comboBox") + sizePolicy = QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth( + self.comboBox.sizePolicy().hasHeightForWidth()) + self.comboBox.setSizePolicy(sizePolicy) + self.comboBox.setMinimumWidth(128) + self.comboBox.setMaximumWidth(128) + self.horizontalLayout_3.addWidget(self.comboBox) + self.gridLayout.addLayout(self.horizontalLayout_3, 5, 0, 1, 1) self.splitter = QSplitter() self.splitter.setObjectName(u"splitter") @@ -138,18 +169,18 @@ class Ui_MainWindow(QMainWindow): self.horizontalLayout_2.addWidget(self.searchButton) self.gridLayout.addLayout(self.horizontalLayout_2, 3, 0, 1, 1) - self.comboBox = QComboBox(self.centralwidget) - self.comboBox.setObjectName(u"comboBox") - sizePolicy = QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth( - self.comboBox.sizePolicy().hasHeightForWidth()) - self.comboBox.setSizePolicy(sizePolicy) - self.comboBox.setMinimumWidth(128) - self.comboBox.setMaximumWidth(128) + # self.comboBox = QComboBox(self.centralwidget) + # self.comboBox.setObjectName(u"comboBox") + # sizePolicy = QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) + # sizePolicy.setHorizontalStretch(0) + # sizePolicy.setVerticalStretch(0) + # sizePolicy.setHeightForWidth( + # self.comboBox.sizePolicy().hasHeightForWidth()) + # self.comboBox.setSizePolicy(sizePolicy) + # self.comboBox.setMinimumWidth(128) + # self.comboBox.setMaximumWidth(128) - self.gridLayout.addWidget(self.comboBox, 4, 0, 1, 1, Qt.AlignRight) + # self.gridLayout.addWidget(self.comboBox, 4, 0, 1, 1, Qt.AlignRight) self.gridLayout_2.setContentsMargins(6, 6, 6, 6) @@ -181,15 +212,24 @@ class Ui_MainWindow(QMainWindow): def retranslateUi(self, MainWindow): MainWindow.setWindowTitle(QCoreApplication.translate( "MainWindow", u"MainWindow", None)) + # Navigation buttons self.backButton.setText( QCoreApplication.translate("MainWindow", u"<", None)) self.forwardButton.setText( QCoreApplication.translate("MainWindow", u">", None)) + + # Search field self.searchField.setPlaceholderText( QCoreApplication.translate("MainWindow", u"Search Entries", None)) self.searchButton.setText( QCoreApplication.translate("MainWindow", u"Search", None)) + + # Search type selector + self.comboBox_2.setItemText(0, QCoreApplication.translate("MainWindow", "And (Includes All Tags)")) + self.comboBox_2.setItemText(1, QCoreApplication.translate("MainWindow", "Or (Includes Any Tag)")) self.comboBox.setCurrentText("") + + # Tumbnail size selector self.comboBox.setPlaceholderText( QCoreApplication.translate("MainWindow", u"Thumbnail Size", None)) # retranslateUi diff --git a/tagstudio/src/qt/modals/file_extension.py b/tagstudio/src/qt/modals/file_extension.py index f0ce919..e61368d 100644 --- a/tagstudio/src/qt/modals/file_extension.py +++ b/tagstudio/src/qt/modals/file_extension.py @@ -4,19 +4,34 @@ from PySide6.QtCore import Signal, Qt -from PySide6.QtWidgets import QVBoxLayout, QPushButton, QTableWidget, QTableWidgetItem +from PySide6.QtWidgets import ( + QVBoxLayout, + QPushButton, + QTableWidget, + QTableWidgetItem, + QStyledItemDelegate, + QLineEdit, +) from src.core.library import Library from src.qt.widgets.panel import PanelWidget +class FileExtensionItemDelegate(QStyledItemDelegate): + def setModelData(self, editor, model, index): + if isinstance(editor, QLineEdit): + if editor.text() and not editor.text().startswith("."): + editor.setText(f".{editor.text()}") + super().setModelData(editor, model, index) + + class FileExtensionModal(PanelWidget): done = Signal() def __init__(self, library: "Library"): super().__init__() self.lib = library - self.setWindowTitle(f"File Extensions") + self.setWindowTitle("File Extensions") self.setWindowModality(Qt.WindowModality.ApplicationModal) self.setMinimumSize(200, 400) self.root_layout = QVBoxLayout(self) @@ -26,6 +41,7 @@ class FileExtensionModal(PanelWidget): self.table.horizontalHeader().setVisible(False) self.table.verticalHeader().setVisible(False) self.table.horizontalHeader().setStretchLastSection(True) + self.table.setItemDelegate(FileExtensionItemDelegate()) self.add_button = QPushButton() self.add_button.setText("&Add Extension") diff --git a/tagstudio/src/qt/ts_qt.py b/tagstudio/src/qt/ts_qt.py index 6fea047..4b77bc7 100644 --- a/tagstudio/src/qt/ts_qt.py +++ b/tagstudio/src/qt/ts_qt.py @@ -43,10 +43,11 @@ from PySide6.QtWidgets import ( QSplashScreen, QMenu, QMenuBar, + QComboBox, ) from humanfriendly import format_timespan -from src.core.enums import SettingItems +from src.core.enums import SettingItems, SearchMode from src.core.library import ItemType from src.core.ts_core import TagStudioCore from src.core.constants import ( @@ -162,7 +163,7 @@ class Consumer(QThread): class QtDriver(QObject): """A Qt GUI frontend driver for TagStudio.""" - last_search_string: None = None | str, + cur_qry: None = None | str, SIGTERM = Signal() preview_panel: PreviewPanel @@ -176,6 +177,8 @@ class QtDriver(QObject): self.nav_frames: list[NavigationState] = [] self.cur_frame_idx: int = -1 + self.search_mode = SearchMode.AND + # self.main_window = None # self.main_window = Ui_MainWindow() @@ -564,6 +567,12 @@ class QtDriver(QObject): search_field.returnPressed.connect( lambda: self.filter_items(self.main_window.searchField.text(),False) # False as a parameter cancels default 'redundant search' override in filter_items() ) + search_type_selector: QComboBox = self.main_window.comboBox_2 + search_type_selector.currentIndexChanged.connect( + lambda: self.set_search_type( + SearchMode(search_type_selector.currentIndex()) + ) + ) back_button: QPushButton = self.main_window.backButton back_button.clicked.connect(self.nav_back) @@ -1322,12 +1331,11 @@ class QtDriver(QObject): index, len(self.frame_dict[query]), ) - def filter_items(self, query: str = "", override: bool = True): - if self.lib and (override or (not (self.last_search_string == query))): - if(override or (not (self.last_search_string == query))): - self.last_search_string = query + if self.lib: + if(override or (not (self.cur_qry == query))): + self.cur_qry = query # logging.info('Filtering...') self.main_window.statusbar.showMessage( f'Searching Library for "{query}"...' @@ -1378,6 +1386,10 @@ class QtDriver(QObject): # self.update_thumbs() + def set_search_type(self, mode=SearchMode.AND): + self.search_mode = mode + self.filter_items(self.main_window.searchField.text()) + def remove_recent_library(self, item_key: str): self.settings.beginGroup(SettingItems.LIBS_LIST) self.settings.remove(item_key) diff --git a/tagstudio/src/qt/ui/home.ui b/tagstudio/src/qt/ui/home.ui index e6c6699..48fc33d 100644 --- a/tagstudio/src/qt/ui/home.ui +++ b/tagstudio/src/qt/ui/home.ui @@ -16,6 +16,71 @@ + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 165 + 0 + + + + + And (includes all tags) + + + + + Or (includes any tag) + + + + + + + + + 0 + 0 + + + + + 128 + 0 + + + + + 256 + 32 + + + + + + + Thumbnail Size + + + + + + @@ -37,7 +102,7 @@ 0 0 1260 - 590 + 585 @@ -158,34 +223,6 @@ - - - - - 0 - 0 - - - - - 128 - 0 - - - - - 256 - 32 - - - - - - - Thumbnail Size - - - @@ -194,7 +231,7 @@ 0 0 1280 - 22 + 21 diff --git a/tagstudio/src/qt/ui/home_ui.py b/tagstudio/src/qt/ui/home_ui.py index 93b83a0..0d986f6 100644 --- a/tagstudio/src/qt/ui/home_ui.py +++ b/tagstudio/src/qt/ui/home_ui.py @@ -3,96 +3,88 @@ ################################################################################ ## Form generated from reading UI file 'home.ui' ## -## Created by: Qt User Interface Compiler version 6.5.1 +## Created by: Qt User Interface Compiler version 6.6.3 ## ## WARNING! All changes made in this file will be lost when recompiling UI file! ################################################################################ -from PySide6.QtCore import ( - QCoreApplication, - QDate, - QDateTime, - QLocale, - QMetaObject, - QObject, - QPoint, - QRect, - QSize, - QTime, - QUrl, - Qt, -) -from PySide6.QtGui import ( - QBrush, - QColor, - QConicalGradient, - QCursor, - QFont, - QFontDatabase, - QGradient, - QIcon, - QImage, - QKeySequence, - QLinearGradient, - QPainter, - QPalette, - QPixmap, - QRadialGradient, - QTransform, -) -from PySide6.QtWidgets import ( - QApplication, - QComboBox, - QFrame, - QGridLayout, - QHBoxLayout, - QLayout, - QLineEdit, - QMainWindow, - QMenuBar, - QPushButton, - QScrollArea, - QSizePolicy, - QStatusBar, - QWidget, -) - +from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale, + QMetaObject, QObject, QPoint, QRect, + QSize, QTime, QUrl, Qt) +from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor, + QFont, QFontDatabase, QGradient, QIcon, + QImage, QKeySequence, QLinearGradient, QPainter, + QPalette, QPixmap, QRadialGradient, QTransform) +from PySide6.QtWidgets import (QApplication, QComboBox, QFrame, QGridLayout, + QHBoxLayout, QLayout, QLineEdit, QMainWindow, + QMenuBar, QPushButton, QScrollArea, QSizePolicy, + QSpacerItem, QStatusBar, QWidget) class Ui_MainWindow(object): def setupUi(self, MainWindow): if not MainWindow.objectName(): - MainWindow.setObjectName("MainWindow") + MainWindow.setObjectName(u"MainWindow") MainWindow.resize(1280, 720) self.centralwidget = QWidget(MainWindow) - self.centralwidget.setObjectName("centralwidget") + self.centralwidget.setObjectName(u"centralwidget") self.gridLayout = QGridLayout(self.centralwidget) - self.gridLayout.setObjectName("gridLayout") + self.gridLayout.setObjectName(u"gridLayout") + self.horizontalLayout_3 = QHBoxLayout() + self.horizontalLayout_3.setObjectName(u"horizontalLayout_3") + self.horizontalSpacer = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) + + self.horizontalLayout_3.addItem(self.horizontalSpacer) + + self.comboBox_2 = QComboBox(self.centralwidget) + self.comboBox_2.addItem("") + self.comboBox_2.addItem("") + self.comboBox_2.setObjectName(u"comboBox_2") + self.comboBox_2.setMinimumSize(QSize(165, 0)) + + self.horizontalLayout_3.addWidget(self.comboBox_2) + + self.comboBox = QComboBox(self.centralwidget) + self.comboBox.setObjectName(u"comboBox") + sizePolicy = QSizePolicy(QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.comboBox.sizePolicy().hasHeightForWidth()) + self.comboBox.setSizePolicy(sizePolicy) + self.comboBox.setMinimumSize(QSize(128, 0)) + self.comboBox.setMaximumSize(QSize(256, 32)) + + self.horizontalLayout_3.addWidget(self.comboBox) + + + self.gridLayout.addLayout(self.horizontalLayout_3, 5, 0, 1, 1) + self.horizontalLayout = QHBoxLayout() - self.horizontalLayout.setObjectName("horizontalLayout") + self.horizontalLayout.setObjectName(u"horizontalLayout") self.scrollArea = QScrollArea(self.centralwidget) - self.scrollArea.setObjectName("scrollArea") + self.scrollArea.setObjectName(u"scrollArea") self.scrollArea.setFocusPolicy(Qt.WheelFocus) self.scrollArea.setFrameShape(QFrame.NoFrame) self.scrollArea.setFrameShadow(QFrame.Plain) self.scrollArea.setWidgetResizable(True) self.scrollAreaWidgetContents = QWidget() - self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents") - self.scrollAreaWidgetContents.setGeometry(QRect(0, 0, 1260, 590)) + self.scrollAreaWidgetContents.setObjectName(u"scrollAreaWidgetContents") + self.scrollAreaWidgetContents.setGeometry(QRect(0, 0, 1260, 585)) self.gridLayout_2 = QGridLayout(self.scrollAreaWidgetContents) self.gridLayout_2.setSpacing(8) - self.gridLayout_2.setObjectName("gridLayout_2") + self.gridLayout_2.setObjectName(u"gridLayout_2") self.gridLayout_2.setContentsMargins(0, 0, 0, 8) self.scrollArea.setWidget(self.scrollAreaWidgetContents) self.horizontalLayout.addWidget(self.scrollArea) - self.gridLayout.addLayout(self.horizontalLayout, 5, 0, 1, 1) + + self.gridLayout.addLayout(self.horizontalLayout, 9, 0, 1, 1) self.horizontalLayout_2 = QHBoxLayout() - self.horizontalLayout_2.setObjectName("horizontalLayout_2") + self.horizontalLayout_2.setObjectName(u"horizontalLayout_2") self.horizontalLayout_2.setSizeConstraint(QLayout.SetMinimumSize) self.backButton = QPushButton(self.centralwidget) - self.backButton.setObjectName("backButton") + self.backButton.setObjectName(u"backButton") self.backButton.setMinimumSize(QSize(0, 32)) self.backButton.setMaximumSize(QSize(32, 16777215)) font = QFont() @@ -103,7 +95,7 @@ class Ui_MainWindow(object): self.horizontalLayout_2.addWidget(self.backButton) self.forwardButton = QPushButton(self.centralwidget) - self.forwardButton.setObjectName("forwardButton") + self.forwardButton.setObjectName(u"forwardButton") self.forwardButton.setMinimumSize(QSize(0, 32)) self.forwardButton.setMaximumSize(QSize(32, 16777215)) font1 = QFont() @@ -115,7 +107,7 @@ class Ui_MainWindow(object): self.horizontalLayout_2.addWidget(self.forwardButton) self.searchField = QLineEdit(self.centralwidget) - self.searchField.setObjectName("searchField") + self.searchField.setObjectName(u"searchField") self.searchField.setMinimumSize(QSize(0, 32)) font2 = QFont() font2.setPointSize(11) @@ -125,34 +117,23 @@ class Ui_MainWindow(object): self.horizontalLayout_2.addWidget(self.searchField) self.searchButton = QPushButton(self.centralwidget) - self.searchButton.setObjectName("searchButton") + self.searchButton.setObjectName(u"searchButton") self.searchButton.setMinimumSize(QSize(0, 32)) self.searchButton.setFont(font2) self.horizontalLayout_2.addWidget(self.searchButton) + self.gridLayout.addLayout(self.horizontalLayout_2, 3, 0, 1, 1) - self.comboBox = QComboBox(self.centralwidget) - self.comboBox.setObjectName("comboBox") - sizePolicy = QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.comboBox.sizePolicy().hasHeightForWidth()) - self.comboBox.setSizePolicy(sizePolicy) - self.comboBox.setMinimumSize(QSize(128, 0)) - self.comboBox.setMaximumSize(QSize(256, 32)) - - self.gridLayout.addWidget(self.comboBox, 4, 0, 1, 1, Qt.AlignRight) - MainWindow.setCentralWidget(self.centralwidget) self.menubar = QMenuBar(MainWindow) - self.menubar.setObjectName("menubar") - self.menubar.setGeometry(QRect(0, 0, 1280, 22)) + self.menubar.setObjectName(u"menubar") + self.menubar.setGeometry(QRect(0, 0, 1280, 21)) MainWindow.setMenuBar(self.menubar) self.statusbar = QStatusBar(MainWindow) - self.statusbar.setObjectName("statusbar") - sizePolicy1 = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Maximum) + self.statusbar.setObjectName(u"statusbar") + sizePolicy1 = QSizePolicy(QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Maximum) sizePolicy1.setHorizontalStretch(0) sizePolicy1.setVerticalStretch(0) sizePolicy1.setHeightForWidth(self.statusbar.sizePolicy().hasHeightForWidth()) @@ -162,24 +143,18 @@ class Ui_MainWindow(object): self.retranslateUi(MainWindow) QMetaObject.connectSlotsByName(MainWindow) - # setupUi def retranslateUi(self, MainWindow): - MainWindow.setWindowTitle( - QCoreApplication.translate("MainWindow", "MainWindow", None) - ) - self.backButton.setText(QCoreApplication.translate("MainWindow", "<", None)) - self.forwardButton.setText(QCoreApplication.translate("MainWindow", ">", None)) - self.searchField.setPlaceholderText( - QCoreApplication.translate("MainWindow", "Search Entries", None) - ) - self.searchButton.setText( - QCoreApplication.translate("MainWindow", "Search", None) - ) - self.comboBox.setCurrentText("") - self.comboBox.setPlaceholderText( - QCoreApplication.translate("MainWindow", "Thumbnail Size", None) - ) + MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"MainWindow", None)) + self.comboBox_2.setItemText(0, QCoreApplication.translate("MainWindow", u"And (includes all tags)", None)) + self.comboBox_2.setItemText(1, QCoreApplication.translate("MainWindow", u"Or (includes any tag)", None)) + self.comboBox.setCurrentText("") + self.comboBox.setPlaceholderText(QCoreApplication.translate("MainWindow", u"Thumbnail Size", None)) + self.backButton.setText(QCoreApplication.translate("MainWindow", u"<", None)) + self.forwardButton.setText(QCoreApplication.translate("MainWindow", u">", None)) + self.searchField.setPlaceholderText(QCoreApplication.translate("MainWindow", u"Search Entries", None)) + self.searchButton.setText(QCoreApplication.translate("MainWindow", u"Search", None)) # retranslateUi +