update gui

This commit is contained in:
2026-08-11 22:12:35 +02:00
parent 4059dbfea2
commit b65ce306a2

178
gui.py
View File

@@ -9,6 +9,7 @@ import urllib.error
import time import time
import mimetypes import mimetypes
import urllib.parse import urllib.parse
import re
def normalize_file_path(path_str: str) -> str: def normalize_file_path(path_str: str) -> str:
if not path_str: if not path_str:
@@ -38,7 +39,8 @@ DEFAULT_CONFIG = {
"api_url": "", "api_url": "",
"api_key": "", "api_key": "",
"default_rating": "", "default_rating": "",
"default_tags": "", "default_visibility": "0",
"default_tags": "screenshot",
"default_is_oc": False, "default_is_oc": False,
"enable_notifications": True, "enable_notifications": True,
"show_progress_dialog": True, "show_progress_dialog": True,
@@ -59,7 +61,7 @@ def load_config():
return DEFAULT_CONFIG.copy() return DEFAULT_CONFIG.copy()
def get_env_config(): def get_env_config():
config = load_config() config = DEFAULT_CONFIG.copy()
script_dir = os.path.dirname(os.path.abspath(__file__)) script_dir = os.path.dirname(os.path.abspath(__file__))
candidates = [ candidates = [
os.path.join(script_dir, ".env"), os.path.join(script_dir, ".env"),
@@ -97,6 +99,13 @@ def get_env_config():
config["icon_theme"] = val.lower() config["icon_theme"] = val.lower()
except Exception as e: except Exception as e:
print(f"Error reading .env from {dotenv_path}: {e}") print(f"Error reading .env from {dotenv_path}: {e}")
# Override with GUI config.json (User GUI Settings have priority over .env)
user_cfg = load_config()
if os.path.exists(CONFIG_PATH):
for k, v in user_cfg.items():
config[k] = v
return config return config
def save_config(config): def save_config(config):
@@ -183,120 +192,20 @@ class ConnectionTester(QObject):
except Exception as e: except Exception as e:
self.finished.emit(False, f"Error: {str(e)}") self.finished.emit(False, f"Error: {str(e)}")
# ========================================== def get_app_icon() -> QIcon:
# Premium Style Sheet script_dir = os.path.dirname(os.path.abspath(__file__))
# ========================================== candidates = [
STYLE_SHEET = """ os.path.join(script_dir, "icon_app.svg"),
QDialog { os.path.join(script_dir, "icon_app.png"),
background-color: #121216; "/home/kibi/Projects/f0ckm-uploader/icon_app.svg",
color: #fffffe; os.path.expanduser("~/.local/bin/icon_app.svg"),
font-family: "Segoe UI", "Inter", "Roboto", "Noto Sans", sans-serif; os.path.expanduser("~/.local/share/icons/hicolor/scalable/apps/f0ckm-uploader.svg"),
font-size: 13px; os.path.expanduser("~/.local/share/icons/hicolor/128x128/apps/f0ckm-uploader.png")
} ]
QLabel { for c in candidates:
color: #e2e2e9; if os.path.exists(c):
} return QIcon(c)
QLabel#title { return QIcon.fromTheme("f0ckm-uploader")
font-size: 18px;
font-weight: bold;
color: #7f5af0;
margin-bottom: 5px;
}
QGroupBox {
background-color: #1a1a24;
border: 1px solid #2f2f3d;
border-radius: 8px;
margin-top: 15px;
padding-top: 15px;
font-weight: bold;
}
QGroupBox::title {
subcontrol-origin: margin;
subcontrol-position: top left;
left: 15px;
padding: 0 5px;
background-color: #121216;
color: #7f5af0;
}
QLineEdit {
background-color: #242432;
border: 1px solid #2f2f3d;
border-radius: 6px;
padding: 6px 10px;
color: #fffffe;
selection-background-color: #7f5af0;
}
QLineEdit:focus {
border: 1px solid #7f5af0;
}
QComboBox {
background-color: #242432;
border: 1px solid #2f2f3d;
border-radius: 6px;
padding: 6px 10px;
color: #fffffe;
}
QComboBox:focus {
border: 1px solid #7f5af0;
}
QComboBox::drop-down {
subcontrol-origin: padding;
subcontrol-position: top right;
width: 25px;
border-left-width: 0px;
}
QComboBox QAbstractItemView {
background-color: #242432;
border: 1px solid #2f2f3d;
selection-background-color: #7f5af0;
selection-color: #fffffe;
color: #fffffe;
}
QCheckBox {
color: #e2e2e9;
}
QCheckBox:hover {
color: #ffffff;
}
QPushButton {
background-color: #242432;
border: 1px solid #2f2f3d;
border-radius: 6px;
padding: 8px 16px;
color: #fffffe;
font-weight: bold;
}
QPushButton:hover {
background-color: #2f2f42;
border: 1px solid #42425a;
}
QPushButton:pressed {
background-color: #1a1a24;
}
QPushButton#primary {
background-color: #7f5af0;
border: 1px solid #7f5af0;
}
QPushButton#primary:hover {
background-color: #9272f2;
border: 1px solid #9272f2;
}
QPushButton#primary:pressed {
background-color: #694ad4;
}
QPushButton#test {
background-color: #2cb67d;
border: 1px solid #2cb67d;
color: #fffffe;
}
QPushButton#test:hover {
background-color: #34cf8f;
border: 1px solid #34cf8f;
}
QPushButton#test:pressed {
background-color: #249a68;
}
"""
# ========================================== # ==========================================
# Settings Dialog Window # Settings Dialog Window
@@ -307,7 +216,10 @@ class SettingsDialog(QDialog):
self.tray_app = tray_app self.tray_app = tray_app
self.setWindowTitle("f0ckm Uploader Settings") self.setWindowTitle("f0ckm Uploader Settings")
self.resize(520, 560) self.resize(520, 560)
self.setStyleSheet(STYLE_SHEET)
app_icon = get_app_icon()
if not app_icon.isNull():
self.setWindowIcon(app_icon)
self.tester_thread = None self.tester_thread = None
self.tester = None self.tester = None
@@ -327,9 +239,9 @@ class SettingsDialog(QDialog):
header_text_layout = QVBoxLayout() header_text_layout = QVBoxLayout()
header_title = QLabel("f0ckm Uploader") header_title = QLabel("f0ckm Uploader")
header_title.setObjectName("title") header_title.setStyleSheet("font-size: 16px; font-weight: bold;")
header_subtitle = QLabel("Configure connection settings and default options") header_subtitle = QLabel("Configure connection settings and default options")
header_subtitle.setStyleSheet("color: #94a1b2; font-size: 11px;") header_subtitle.setStyleSheet("font-size: 11px; opacity: 0.7;")
header_text_layout.addWidget(header_title) header_text_layout.addWidget(header_title)
header_text_layout.addWidget(header_subtitle) header_text_layout.addWidget(header_subtitle)
@@ -377,9 +289,13 @@ class SettingsDialog(QDialog):
defaults_layout.setSpacing(10) defaults_layout.setSpacing(10)
self.cb_rating = QComboBox() self.cb_rating = QComboBox()
self.cb_rating.addItems(["(None / Default)", "safe", "questionable", "explicit"]) self.cb_rating.addItems(["(None / Default)", "SFW", "NSFW", "NSFL"])
defaults_layout.addRow("Default Rating:", self.cb_rating) defaults_layout.addRow("Default Rating:", self.cb_rating)
self.cb_visibility = QComboBox()
self.cb_visibility.addItems(["Public", "Unlisted", "Private"])
defaults_layout.addRow("Default Visibility:", self.cb_visibility)
self.txt_tags = QLineEdit() self.txt_tags = QLineEdit()
self.txt_tags.setPlaceholderText("comma-separated tags (e.g., meme, anime)") self.txt_tags.setPlaceholderText("comma-separated tags (e.g., meme, anime)")
defaults_layout.addRow("Default Tags:", self.txt_tags) defaults_layout.addRow("Default Tags:", self.txt_tags)
@@ -445,10 +361,14 @@ class SettingsDialog(QDialog):
self.txt_url.setText(config.get("api_url", "")) self.txt_url.setText(config.get("api_url", ""))
self.txt_key.setText(config.get("api_key", "")) self.txt_key.setText(config.get("api_key", ""))
rating = config.get("default_rating", "") rating = config.get("default_rating", "").lower()
rating_map = {"": 0, "safe": 1, "questionable": 2, "explicit": 3} rating_map = {"": 0, "s": 1, "sfw": 1, "safe": 1, "q": 2, "nsfw": 2, "questionable": 2, "e": 3, "nsfl": 3, "explicit": 3}
self.cb_rating.setCurrentIndex(rating_map.get(rating, 0)) self.cb_rating.setCurrentIndex(rating_map.get(rating, 0))
vis = str(config.get("default_visibility", "0")).lower()
vis_map = {"0": 0, "public": 0, "1": 1, "unlisted": 1, "2": 2, "private": 2}
self.cb_visibility.setCurrentIndex(vis_map.get(vis, 0))
self.txt_tags.setText(config.get("default_tags", "")) self.txt_tags.setText(config.get("default_tags", ""))
self.chk_oc.setChecked(config.get("default_is_oc", False)) self.chk_oc.setChecked(config.get("default_is_oc", False))
self.chk_notifications.setChecked(config.get("enable_notifications", True)) self.chk_notifications.setChecked(config.get("enable_notifications", True))
@@ -490,7 +410,8 @@ class SettingsDialog(QDialog):
config = { config = {
"api_url": self.txt_url.text().strip(), "api_url": self.txt_url.text().strip(),
"api_key": self.txt_key.text().strip(), "api_key": self.txt_key.text().strip(),
"default_rating": ["", "safe", "questionable", "explicit"][self.cb_rating.currentIndex()], "default_rating": ["", "s", "q", "e"][self.cb_rating.currentIndex()],
"default_visibility": ["0", "1", "2"][self.cb_visibility.currentIndex()],
"default_tags": self.txt_tags.text().strip(), "default_tags": self.txt_tags.text().strip(),
"default_is_oc": self.chk_oc.isChecked(), "default_is_oc": self.chk_oc.isChecked(),
"enable_notifications": self.chk_notifications.isChecked(), "enable_notifications": self.chk_notifications.isChecked(),
@@ -712,6 +633,11 @@ class SystemTrayApp(QObject):
api_key = config.get("api_key", "") api_key = config.get("api_key", "")
rating = config.get("default_rating", "") rating = config.get("default_rating", "")
tags = config.get("default_tags", "") tags = config.get("default_tags", "")
if tags:
# Format tags as clean comma-separated string ("tag1, tag2") for f0ckm API tagsRaw.split(',') compatibility
tag_list = [t.strip() for t in re.split(r'[,]+', tags) if t.strip()]
tags = ", ".join(tag_list)
visibility = str(config.get("default_visibility", "0")) visibility = str(config.get("default_visibility", "0"))
is_oc = "1" if config.get("default_is_oc", False) else "0" is_oc = "1" if config.get("default_is_oc", False) else "0"
@@ -908,8 +834,14 @@ class SingleInstanceApp:
def main(): def main():
app = QApplication(sys.argv) app = QApplication(sys.argv)
app.setApplicationName("f0ckm Uploader")
app.setDesktopFileName("kde-uploader-gui")
app.setQuitOnLastWindowClosed(False) app.setQuitOnLastWindowClosed(False)
app_icon = get_app_icon()
if not app_icon.isNull():
app.setWindowIcon(app_icon)
instance_name = "f0ckm-uploader-gui-lock" instance_name = "f0ckm-uploader-gui-lock"
single_instance = SingleInstanceApp(instance_name) single_instance = SingleInstanceApp(instance_name)