Upload files to "/"
This commit is contained in:
502
app.py
Normal file
502
app.py
Normal file
@@ -0,0 +1,502 @@
|
||||
# latest
|
||||
import ctypes
|
||||
import logging
|
||||
import signal
|
||||
import sys
|
||||
|
||||
from PySide6.QtCore import QPoint, Qt
|
||||
from PySide6.QtGui import QColor
|
||||
|
||||
from PySide6.QtWidgets import (
|
||||
QApplication,
|
||||
QCheckBox,
|
||||
QColorDialog,
|
||||
QLabel,
|
||||
QPushButton,
|
||||
QSlider,
|
||||
QVBoxLayout,
|
||||
QWidget,
|
||||
)
|
||||
|
||||
logging.basicConfig(level=logging.INFO, format="%(levelname)s %(message)s")
|
||||
|
||||
try:
|
||||
ctypes.windll.user32.SetProcessDPIAware()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
DWMWA_USE_IMMERSIVE_DARK_MODE = 20
|
||||
DWMWA_WINDOW_CORNER_PREFERENCE = 33
|
||||
DWMWCP_ROUND = 2
|
||||
|
||||
|
||||
class WindowConfig:
|
||||
width = 800
|
||||
height = 500
|
||||
opacity = 0.99
|
||||
radius = 11
|
||||
resize_margin = 8
|
||||
minimum_width = 300
|
||||
minimum_height = 200
|
||||
background_alpha = 190
|
||||
border_alpha = 190
|
||||
|
||||
|
||||
class GlassWindow(QWidget):
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
None,
|
||||
Qt.FramelessWindowHint | Qt.Window | Qt.WindowStaysOnTopHint,
|
||||
)
|
||||
|
||||
self.cfg = WindowConfig()
|
||||
|
||||
self.background_color = QColor(155, 155, 155)
|
||||
|
||||
self._drag_offset = None
|
||||
self._resize_edges = None
|
||||
self._resize_start_pos = QPoint()
|
||||
self._resize_start_geo = self.geometry()
|
||||
|
||||
self.setAttribute(Qt.WA_TranslucentBackground, True)
|
||||
self.setWindowOpacity(self.cfg.opacity)
|
||||
self.resize(self.cfg.width, self.cfg.height)
|
||||
self.setMinimumSize(
|
||||
self.cfg.minimum_width,
|
||||
self.cfg.minimum_height,
|
||||
)
|
||||
self.setMouseTracking(True)
|
||||
|
||||
self.panel = QWidget(self)
|
||||
self.panel.setObjectName("panel")
|
||||
|
||||
layout = QVBoxLayout(self.panel)
|
||||
layout.setContentsMargins(24, 24, 24, 24)
|
||||
layout.setSpacing(16)
|
||||
|
||||
title = QLabel("")
|
||||
title.setStyleSheet(
|
||||
"background:transparent;color:white;font-size:24px;font-weight:600;"
|
||||
)
|
||||
|
||||
body = QLabel("opacity")
|
||||
body.setStyleSheet("background:transparent;color:transparent;")
|
||||
|
||||
layout.addWidget(title)
|
||||
layout.addWidget(body)
|
||||
|
||||
layout.addStretch()
|
||||
|
||||
self.slider = QSlider(
|
||||
Qt.Horizontal,
|
||||
self.panel,
|
||||
)
|
||||
self.slider.setRange(0, 255)
|
||||
self.slider.setFixedWidth(255)
|
||||
self.slider.setValue(
|
||||
self.cfg.background_alpha,
|
||||
)
|
||||
self.slider.valueChanged.connect(
|
||||
self.update_panel_style,
|
||||
)
|
||||
|
||||
self.color_button = QPushButton(
|
||||
self.panel,
|
||||
)
|
||||
self.color_button.setFixedSize(22, 22)
|
||||
self.color_button.clicked.connect(
|
||||
self.pick_background_color,
|
||||
)
|
||||
|
||||
self.pin_button = QPushButton(
|
||||
"🗗",
|
||||
self.panel,
|
||||
)
|
||||
self.pin_button.setCheckable(True)
|
||||
self.pin_button.setChecked(True)
|
||||
self.pin_button.setFixedSize(28, 28)
|
||||
self.pin_button.setCursor(Qt.ArrowCursor)
|
||||
self.pin_button.setToolTip("Always on Top")
|
||||
self.pin_button.toggled.connect(
|
||||
self.toggle_always_on_top,
|
||||
)
|
||||
|
||||
self.setCursor(Qt.ArrowCursor)
|
||||
self.panel.setCursor(Qt.ArrowCursor)
|
||||
self.slider.setCursor(Qt.ArrowCursor)
|
||||
self.color_button.setCursor(Qt.ArrowCursor)
|
||||
self.pin_button.setCursor(Qt.ArrowCursor)
|
||||
self.pin_button.setObjectName("pinButton")
|
||||
self.update_panel_style()
|
||||
|
||||
def toggle_always_on_top(
|
||||
self,
|
||||
enabled: bool,
|
||||
):
|
||||
geometry = self.geometry()
|
||||
|
||||
self.setWindowFlag(
|
||||
Qt.WindowStaysOnTopHint,
|
||||
enabled,
|
||||
)
|
||||
|
||||
self.show()
|
||||
self.setGeometry(geometry)
|
||||
|
||||
def pick_background_color(self):
|
||||
dialog = QColorDialog(
|
||||
self.background_color,
|
||||
self,
|
||||
)
|
||||
|
||||
dialog.setOption(
|
||||
QColorDialog.DontUseNativeDialog,
|
||||
True,
|
||||
)
|
||||
|
||||
dialog.setWindowTitle(
|
||||
"background",
|
||||
)
|
||||
|
||||
dialog.setStyleSheet("""
|
||||
QColorDialog{
|
||||
background:#030303;
|
||||
color:#f2f2f2;
|
||||
}
|
||||
|
||||
QWidget{
|
||||
background:#090909;
|
||||
color:#f2f2f2;
|
||||
}
|
||||
|
||||
QLabel{
|
||||
background:transparent;
|
||||
color:#f2f2f2;
|
||||
}
|
||||
|
||||
QGroupBox{
|
||||
color:#f2f2f2;
|
||||
border:1px solid #3a3a3a;
|
||||
margin-top:8px;
|
||||
}
|
||||
|
||||
QGroupBox::title{
|
||||
left:8px;
|
||||
padding:0 4px;
|
||||
}
|
||||
|
||||
QPushButton{
|
||||
background:#2a2a2a;
|
||||
color:white;
|
||||
border:1px solid #444;
|
||||
border-radius:4px;
|
||||
padding:5px 12px;
|
||||
}
|
||||
|
||||
QPushButton:hover{
|
||||
background:#343434;
|
||||
}
|
||||
|
||||
QPushButton:pressed{
|
||||
background:#404040;
|
||||
}
|
||||
|
||||
QLineEdit,
|
||||
QSpinBox,
|
||||
QComboBox{
|
||||
background:#2a2a2a;
|
||||
color:white;
|
||||
border:1px solid #444;
|
||||
selection-background-color:#5DFFCE;
|
||||
}
|
||||
|
||||
QTabBar::tab{
|
||||
background:#2a2a2a;
|
||||
color:white;
|
||||
padding:6px 10px;
|
||||
}
|
||||
|
||||
QTabBar::tab:selected{
|
||||
background:#404040;
|
||||
}
|
||||
""")
|
||||
|
||||
if dialog.exec():
|
||||
self.background_color = dialog.currentColor()
|
||||
self.update_panel_style()
|
||||
|
||||
# v4
|
||||
def update_panel_style(self, value=None):
|
||||
if value is not None:
|
||||
self.cfg.background_alpha = value
|
||||
|
||||
r = self.background_color.red()
|
||||
g = self.background_color.green()
|
||||
b = self.background_color.blue()
|
||||
|
||||
luminance = (0.2126 * r + 0.7152 * g + 0.0722 * b) / 255.0
|
||||
|
||||
groove = f"rgba({r},{g},{b},{max(28, self.cfg.background_alpha - 135)})"
|
||||
|
||||
fill = f"rgba({r},{g},{b},{min(255, self.cfg.background_alpha + 45)})"
|
||||
|
||||
if luminance > 0.60:
|
||||
handle = "#1b1b1d"
|
||||
handle_hover = "#121214"
|
||||
handle_pressed = "#09090b"
|
||||
handle_border = "rgba(255,255,255,32)"
|
||||
else:
|
||||
handle = "#f7f7f8"
|
||||
handle_hover = "#ffffff"
|
||||
handle_pressed = "#ececee"
|
||||
handle_border = "rgba(0,0,0,28)"
|
||||
|
||||
self.setStyleSheet(f"""
|
||||
#panel {{
|
||||
background: rgba({r},{g},{b},{self.cfg.background_alpha});
|
||||
border: 1px solid rgba(255,255,255,.2);
|
||||
border-radius: {self.cfg.radius}px;
|
||||
}}
|
||||
|
||||
QPushButton {{
|
||||
margin: 2px;
|
||||
background: rgb({r},{g},{b});
|
||||
border: 1px solid rgba(255,255,255,24);
|
||||
border-radius: 4px;
|
||||
}}
|
||||
|
||||
QPushButton:hover {{
|
||||
border: 1px solid rgba(255,255,255,48);
|
||||
}}
|
||||
|
||||
QSlider {{
|
||||
background: transparent;
|
||||
}}
|
||||
|
||||
QSlider::groove:horizontal {{
|
||||
height: 4px;
|
||||
background: {groove};
|
||||
border: none;
|
||||
border-radius: 2px;
|
||||
}}
|
||||
|
||||
QSlider::sub-page:horizontal {{
|
||||
background: {fill};
|
||||
border-radius: 2px;
|
||||
}}
|
||||
|
||||
QSlider::add-page:horizontal {{
|
||||
background: {groove};
|
||||
border-radius: 2px;
|
||||
}}
|
||||
|
||||
QSlider::handle:horizontal {{
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
margin: -5px 0;
|
||||
background: {handle};
|
||||
border: 1px solid {handle_border};
|
||||
border-radius: 7px;
|
||||
}}
|
||||
|
||||
QSlider::handle:horizontal:hover {{
|
||||
background: {handle_hover};
|
||||
}}
|
||||
|
||||
QSlider::handle:horizontal:pressed {{
|
||||
background: {handle_pressed};
|
||||
}}
|
||||
|
||||
QPushButton {{
|
||||
margin: 2px;
|
||||
background: rgb({r},{g},{b});
|
||||
border: 1px solid rgba(255,255,255,24);
|
||||
border-radius: 4px;
|
||||
}}
|
||||
|
||||
|
||||
QPushButton#pinButton {{
|
||||
color: rgba(255,255,255,180);
|
||||
}}
|
||||
|
||||
QPushButton#pinButton:checked {{
|
||||
background: #064C2C1C;
|
||||
border: 1px solid rgba(255,255,255,40);
|
||||
color: white;
|
||||
font-weight: 600;
|
||||
}}
|
||||
""")
|
||||
|
||||
def resizeEvent(self, event):
|
||||
self.panel.setGeometry(self.rect())
|
||||
|
||||
margin = 24
|
||||
|
||||
slider_y = self.panel.height() - self.slider.height() - margin
|
||||
|
||||
spacing_slider_color = 10
|
||||
spacing_color_pin = 8
|
||||
|
||||
self.slider.move(
|
||||
self.panel.width() - self.slider.width() - 67 - margin,
|
||||
slider_y,
|
||||
)
|
||||
|
||||
self.color_button.move(
|
||||
self.slider.x() + self.slider.width() + spacing_slider_color,
|
||||
slider_y + (self.slider.height() - self.color_button.height()) // 2,
|
||||
)
|
||||
|
||||
self.pin_button.move(
|
||||
self.color_button.x() + self.color_button.width() + spacing_color_pin,
|
||||
slider_y + (self.slider.height() - self.pin_button.height()) // 2,
|
||||
)
|
||||
|
||||
super().resizeEvent(event)
|
||||
|
||||
def showEvent(self, event):
|
||||
super().showEvent(event)
|
||||
|
||||
hwnd = int(self.winId())
|
||||
|
||||
try:
|
||||
dark = ctypes.c_int(1)
|
||||
|
||||
ctypes.windll.dwmapi.DwmSetWindowAttribute(
|
||||
hwnd,
|
||||
DWMWA_USE_IMMERSIVE_DARK_MODE,
|
||||
ctypes.byref(dark),
|
||||
ctypes.sizeof(dark),
|
||||
)
|
||||
|
||||
corner = ctypes.c_int(DWMWCP_ROUND)
|
||||
|
||||
ctypes.windll.dwmapi.DwmSetWindowAttribute(
|
||||
hwnd,
|
||||
DWMWA_WINDOW_CORNER_PREFERENCE,
|
||||
ctypes.byref(corner),
|
||||
ctypes.sizeof(corner),
|
||||
)
|
||||
|
||||
except Exception as ex:
|
||||
logging.warning("DWM setup failed: %s", ex)
|
||||
|
||||
# v2
|
||||
def _hit_test(self, pos):
|
||||
m = self.cfg.resize_margin + 6
|
||||
|
||||
x = pos.x()
|
||||
y = pos.y()
|
||||
|
||||
w = self.width()
|
||||
h = self.height()
|
||||
|
||||
left = x <= m
|
||||
right = x >= w - m
|
||||
top = y <= m
|
||||
bottom = y >= h - m
|
||||
|
||||
return left, top, right, bottom
|
||||
|
||||
def mousePressEvent(self, e):
|
||||
if e.button() != Qt.LeftButton:
|
||||
return super().mousePressEvent(e)
|
||||
|
||||
edges = self._hit_test(e.position().toPoint())
|
||||
|
||||
if any(edges):
|
||||
self._resize_edges = edges
|
||||
self._resize_start_pos = e.globalPosition().toPoint()
|
||||
self._resize_start_geo = self.geometry()
|
||||
return
|
||||
|
||||
self._drag_offset = (
|
||||
e.globalPosition().toPoint() - self.frameGeometry().topLeft()
|
||||
)
|
||||
|
||||
def mouseMoveEvent(self, e):
|
||||
pos = e.position().toPoint()
|
||||
|
||||
if self._resize_edges is not None:
|
||||
dx = e.globalPosition().toPoint().x() - self._resize_start_pos.x()
|
||||
dy = e.globalPosition().toPoint().y() - self._resize_start_pos.y()
|
||||
|
||||
geo = self._resize_start_geo
|
||||
|
||||
x = geo.x()
|
||||
y = geo.y()
|
||||
w = geo.width()
|
||||
h = geo.height()
|
||||
|
||||
left, top, right, bottom = self._resize_edges
|
||||
|
||||
if left:
|
||||
x += dx
|
||||
w -= dx
|
||||
|
||||
if right:
|
||||
w += dx
|
||||
|
||||
if top:
|
||||
y += dy
|
||||
h -= dy
|
||||
|
||||
if bottom:
|
||||
h += dy
|
||||
|
||||
if w < self.minimumWidth():
|
||||
if left:
|
||||
x -= self.minimumWidth() - w
|
||||
w = self.minimumWidth()
|
||||
|
||||
if h < self.minimumHeight():
|
||||
if top:
|
||||
y -= self.minimumHeight() - h
|
||||
h = self.minimumHeight()
|
||||
|
||||
self.setGeometry(x, y, w, h)
|
||||
return
|
||||
|
||||
if self._drag_offset is not None:
|
||||
self.move(e.globalPosition().toPoint() - self._drag_offset)
|
||||
return
|
||||
|
||||
left, top, right, bottom = self._hit_test(pos)
|
||||
|
||||
if (left and top) or (right and bottom):
|
||||
self.setCursor(Qt.SizeFDiagCursor)
|
||||
elif (right and top) or (left and bottom):
|
||||
self.setCursor(Qt.SizeBDiagCursor)
|
||||
elif left or right:
|
||||
self.setCursor(Qt.SizeHorCursor)
|
||||
elif top or bottom:
|
||||
self.setCursor(Qt.SizeVerCursor)
|
||||
else:
|
||||
self.setCursor(Qt.ArrowCursor)
|
||||
|
||||
# v1
|
||||
def mouseReleaseEvent(self, e):
|
||||
self._drag_offset = None
|
||||
self._resize_edges = None
|
||||
super().mouseReleaseEvent(e)
|
||||
|
||||
def keyPressEvent(self, e):
|
||||
if e.key() == Qt.Key_Escape:
|
||||
self.close()
|
||||
else:
|
||||
super().keyPressEvent(e)
|
||||
|
||||
|
||||
def main():
|
||||
signal.signal(signal.SIGINT, signal.SIG_DFL)
|
||||
|
||||
app = QApplication(sys.argv)
|
||||
|
||||
w = GlassWindow()
|
||||
w.show()
|
||||
|
||||
sys.exit(app.exec())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user