update gui
This commit is contained in:
178
gui.py
178
gui.py
@@ -9,6 +9,7 @@ import urllib.error
|
||||
import time
|
||||
import mimetypes
|
||||
import urllib.parse
|
||||
import re
|
||||
|
||||
def normalize_file_path(path_str: str) -> str:
|
||||
if not path_str:
|
||||
@@ -38,7 +39,8 @@ DEFAULT_CONFIG = {
|
||||
"api_url": "",
|
||||
"api_key": "",
|
||||
"default_rating": "",
|
||||
"default_tags": "",
|
||||
"default_visibility": "0",
|
||||
"default_tags": "screenshot",
|
||||
"default_is_oc": False,
|
||||
"enable_notifications": True,
|
||||
"show_progress_dialog": True,
|
||||
@@ -59,7 +61,7 @@ def load_config():
|
||||
return DEFAULT_CONFIG.copy()
|
||||
|
||||
def get_env_config():
|
||||
config = load_config()
|
||||
config = DEFAULT_CONFIG.copy()
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
candidates = [
|
||||
os.path.join(script_dir, ".env"),
|
||||
@@ -97,6 +99,13 @@ def get_env_config():
|
||||
config["icon_theme"] = val.lower()
|
||||
except Exception as 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
|
||||
|
||||
def save_config(config):
|
||||
@@ -183,120 +192,20 @@ class ConnectionTester(QObject):
|
||||
except Exception as e:
|
||||
self.finished.emit(False, f"Error: {str(e)}")
|
||||
|
||||
# ==========================================
|
||||
# Premium Style Sheet
|
||||
# ==========================================
|
||||
STYLE_SHEET = """
|
||||
QDialog {
|
||||
background-color: #121216;
|
||||
color: #fffffe;
|
||||
font-family: "Segoe UI", "Inter", "Roboto", "Noto Sans", sans-serif;
|
||||
font-size: 13px;
|
||||
}
|
||||
QLabel {
|
||||
color: #e2e2e9;
|
||||
}
|
||||
QLabel#title {
|
||||
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;
|
||||
}
|
||||
"""
|
||||
def get_app_icon() -> QIcon:
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
candidates = [
|
||||
os.path.join(script_dir, "icon_app.svg"),
|
||||
os.path.join(script_dir, "icon_app.png"),
|
||||
"/home/kibi/Projects/f0ckm-uploader/icon_app.svg",
|
||||
os.path.expanduser("~/.local/bin/icon_app.svg"),
|
||||
os.path.expanduser("~/.local/share/icons/hicolor/scalable/apps/f0ckm-uploader.svg"),
|
||||
os.path.expanduser("~/.local/share/icons/hicolor/128x128/apps/f0ckm-uploader.png")
|
||||
]
|
||||
for c in candidates:
|
||||
if os.path.exists(c):
|
||||
return QIcon(c)
|
||||
return QIcon.fromTheme("f0ckm-uploader")
|
||||
|
||||
# ==========================================
|
||||
# Settings Dialog Window
|
||||
@@ -307,7 +216,10 @@ class SettingsDialog(QDialog):
|
||||
self.tray_app = tray_app
|
||||
self.setWindowTitle("f0ckm Uploader Settings")
|
||||
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 = None
|
||||
@@ -327,9 +239,9 @@ class SettingsDialog(QDialog):
|
||||
|
||||
header_text_layout = QVBoxLayout()
|
||||
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.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_subtitle)
|
||||
|
||||
@@ -377,9 +289,13 @@ class SettingsDialog(QDialog):
|
||||
defaults_layout.setSpacing(10)
|
||||
|
||||
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)
|
||||
|
||||
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.setPlaceholderText("comma-separated tags (e.g., meme, anime)")
|
||||
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_key.setText(config.get("api_key", ""))
|
||||
|
||||
rating = config.get("default_rating", "")
|
||||
rating_map = {"": 0, "safe": 1, "questionable": 2, "explicit": 3}
|
||||
rating = config.get("default_rating", "").lower()
|
||||
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))
|
||||
|
||||
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.chk_oc.setChecked(config.get("default_is_oc", False))
|
||||
self.chk_notifications.setChecked(config.get("enable_notifications", True))
|
||||
@@ -490,7 +410,8 @@ class SettingsDialog(QDialog):
|
||||
config = {
|
||||
"api_url": self.txt_url.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_is_oc": self.chk_oc.isChecked(),
|
||||
"enable_notifications": self.chk_notifications.isChecked(),
|
||||
@@ -712,6 +633,11 @@ class SystemTrayApp(QObject):
|
||||
api_key = config.get("api_key", "")
|
||||
rating = config.get("default_rating", "")
|
||||
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"))
|
||||
is_oc = "1" if config.get("default_is_oc", False) else "0"
|
||||
|
||||
@@ -908,8 +834,14 @@ class SingleInstanceApp:
|
||||
|
||||
def main():
|
||||
app = QApplication(sys.argv)
|
||||
app.setApplicationName("f0ckm Uploader")
|
||||
app.setDesktopFileName("kde-uploader-gui")
|
||||
app.setQuitOnLastWindowClosed(False)
|
||||
|
||||
app_icon = get_app_icon()
|
||||
if not app_icon.isNull():
|
||||
app.setWindowIcon(app_icon)
|
||||
|
||||
instance_name = "f0ckm-uploader-gui-lock"
|
||||
single_instance = SingleInstanceApp(instance_name)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user