import sys import json import os from PyQt5.QtWidgets import ( QApplication, QWidget, QVBoxLayout, QHBoxLayout, QLineEdit, QPushButton, QListWidget, QTextEdit, QComboBox, QMessageBox, QSpacerItem, QSizePolicy, QLabel, QFileDialog, QDialog, QFormLayout ) from PyQt5.QtGui import QIcon, QPixmap from PyQt5.QtCore import Qt, QUrl from PyQt5.QtSvg import QSvgWidget from PyQt5.QtGui import QDesktopServices class URLManager(QWidget): def __init__(self): super().__init__() self.setWindowTitle('tabRemember - URL Manager') self.setGeometry(100, 100, 340, 500) # Set the application icon self.setWindowIcon(QIcon('assets/logo.png')) self.layout = QVBoxLayout() # URL input and settings button layout self.url_layout = QHBoxLayout() self.url_input = QLineEdit() self.url_input.setPlaceholderText("URL") self.url_layout.addWidget(self.url_input) # Settings button self.settings_button = QPushButton() self.settings_button.setFixedHeight(self.url_input.sizeHint().height()) self.settings_button.setFixedWidth(self.url_input.sizeHint().height()) self.settings_button.clicked.connect(self.show_settings_dialog) self.url_layout.addWidget(self.settings_button) # Info button self.info_button = QPushButton() self.info_button.setFixedHeight(self.url_input.sizeHint().height()) self.info_button.setFixedWidth(self.url_input.sizeHint().height()) self.info_button.clicked.connect(self.show_info_dialog) self.url_layout.addWidget(self.info_button) self.layout.addLayout(self.url_layout) # Update icons based on the color mode self.update_icon_color() # Description/Thoughts input self.description_input = QTextEdit() self.description_input.setPlaceholderText("Enter Description or Thoughts") self.description_input.setMaximumHeight(100) # Limit height to approximately 5 lines self.layout.addWidget(self.description_input) # Add URL button self.add_button = QPushButton("Add URL") self.add_button.clicked.connect(self.add_url) self.layout.addWidget(self.add_button) # Add space between the Add URL button and URL list self.layout.addSpacerItem(QSpacerItem(0, 10, QSizePolicy.Minimum, QSizePolicy.Fixed)) # Group selection and search input self.group_search_layout = QHBoxLayout() self.group_combobox = QComboBox() self.group_combobox.addItem("Default") self.group_search_layout.addWidget(self.group_combobox) self.search_input = QLineEdit() self.search_input.setPlaceholderText("Search ...") self.group_search_layout.addWidget(self.search_input) self.layout.addLayout(self.group_search_layout) # Ensure the dropdown and search input are of equal width self.group_combobox.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred) self.search_input.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred) # URL list self.url_list = QListWidget() self.layout.addWidget(self.url_list) self.setLayout(self.layout) self.urls = {} # Load settings self.load_settings() def update_icon_color(self): # Heuristic to check if the application is in dark mode palette = self.palette() if palette.color(palette.Window).value() < 128: settings_icon_path = 'assets/cogwheel_dark.svg' info_icon_path = 'assets/info_dark.svg' else: settings_icon_path = 'assets/cogwheel_light.svg' info_icon_path = 'assets/info_light.svg' self.settings_button.setIcon(QIcon(settings_icon_path)) self.info_button.setIcon(QIcon(info_icon_path)) def add_url(self): url = self.url_input.text() description = self.description_input.toPlainText() group = self.group_combobox.currentText() if url: self.url_list.addItem(f"{group}: {url}") if group not in self.urls: self.urls[group] = [] self.urls[group].append({'url': url, 'description': description}) self.url_input.clear() self.description_input.clear() def update_url(self): selected_item = self.url_list.currentItem() if selected_item: group, url = selected_item.text().split(": ", 1) new_url = self.url_input.text() new_description = self.description_input.toPlainText() selected_item.setText(f"{group}: {new_url}") for item in self.urls[group]: if item['url'] == url: item['url'] = new_url item['description'] = new_description break self.url_input.clear() self.description_input.clear() def delete_url(self): selected_item = self.url_list.currentItem() if selected_item: group, url = selected_item.text().split(": ", 1) self.url_list.takeItem(self.url_list.row(selected_item)) for item in self.urls[group]: if item['url'] == url: self.urls[group].remove(item) break def search_url(self): search_term = self.search_input.text() if search_term: search_engine = "https://www.google.com/search?q=" search_url = search_engine + search_term QMessageBox.information(self, "Search", f"Searching for: {search_term}\nURL: {search_url}") self.search_input.clear() def show_info_dialog(self): dialog = QDialog(self) dialog.setWindowTitle("About tabRemember") layout = QVBoxLayout() # SVG logo svg_widget = QSvgWidget('assets/logo.svg') svg_widget.setFixedSize(256, 256) layout.addWidget(svg_widget, alignment=Qt.AlignCenter) # Written by label written_by_label = QLabel("Written by Axel Rafn Benediktsson") layout.addWidget(written_by_label, alignment=Qt.AlignCenter) # Link label link_label = QLabel() link_label.setText('https://git.axelrafn.is/axelrafn/tabRemember') link_label.setOpenExternalLinks(True) layout.addWidget(link_label, alignment=Qt.AlignCenter) dialog.setLayout(layout) dialog.exec_() def show_settings_dialog(self): dialog = SettingsDialog(self) dialog.exec_() def load_settings(self): settings_path = 'data/settings.json' if os.path.exists(settings_path): if os.path.getsize(settings_path) > 0: with open(settings_path, 'r') as file: settings = json.load(file) # Use settings (for now, we only have the data_directory) self.data_directory = settings.get('data_directory', 'data/') else: self.data_directory = 'data/' self.save_settings() else: self.data_directory = 'data/' self.save_settings() def save_settings(self): settings_path = 'data/settings.json' os.makedirs(os.path.dirname(settings_path), exist_ok=True) with open(settings_path, 'w') as file: settings = { 'data_directory': self.data_directory } json.dump(settings, file) class SettingsDialog(QDialog): def __init__(self, parent=None): super().__init__(parent) self.setWindowTitle("Settings") self.parent = parent layout = QVBoxLayout() # File/Directory selection form_layout = QFormLayout() self.directory_input = QLineEdit(self.parent.data_directory) self.browse_button = QPushButton("Browse...") self.browse_button.clicked.connect(self.browse_directory) form_layout.addRow("Data Directory:", self.directory_input) form_layout.addWidget(self.browse_button) layout.addLayout(form_layout) # Save button self.save_button = QPushButton("Save") self.save_button.clicked.connect(self.save_settings) layout.addWidget(self.save_button) self.setLayout(layout) def browse_directory(self): directory = QFileDialog.getExistingDirectory(self, "Select Directory") if directory: self.directory_input.setText(directory) def save_settings(self): self.parent.data_directory = self.directory_input.text() self.parent.save_settings() self.accept() if __name__ == '__main__': app = QApplication(sys.argv) app.setWindowIcon(QIcon('assets/logo.png')) # Set the application icon using PNG for compatibility window = URLManager() window.show() sys.exit(app.exec_())