diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..d1d2d72 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,21 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Python Debugger: Current File", + "type": "debugpy", + "request": "launch", + "program": "${file}", + "console": "externalTerminal" + }, + { + "name": "Python Debugger: Python File", + "type": "debugpy", + "request": "launch", + "program": "${file}" + } + ] +} diff --git a/mucapy/main.py b/mucapy/main.py index 5afbcd2..07161d9 100644 --- a/mucapy/main.py +++ b/mucapy/main.py @@ -17,6 +17,7 @@ from PyQt5.QtCore import Qt, QTimer, QDir, QSize, QSettings, QDateTime, QRect, Q from PyQt5.QtGui import (QImage, QPixmap, QIcon, QColor, QKeySequence, QPainter, QPen, QBrush) import platform +import todo import time import requests import subprocess @@ -68,8 +69,11 @@ class Config: try: # Ensure the file's directory exists os.makedirs(os.path.dirname(self.config_file), exist_ok=True) - with open(self.config_file, 'w') as f: - json.dump(self.settings, f, indent=4) + try: + with open(self.config_file, 'w') as f: + json.dump(self.settings, f, indent=4) + except FileNotFoundError: + exit(1) except Exception as e: print(f"Error saving config: {e}") @@ -421,8 +425,11 @@ class MultiCamYOLODetector(QObject): self.net.setPreferableBackend(cv2.dnn.DNN_BACKEND_OPENCV) self.net.setPreferableTarget(cv2.dnn.DNN_TARGET_CPU) - with open(classes_path, 'r') as f: - self.classes = f.read().strip().split('\n') + try: + with open(classes_path, 'r') as f: + self.classes = f.read().strip().split('\n') + except FileNotFoundError: + exit(1) np.random.seed(42) self.colors = np.random.randint(0, 255, size=(len(self.classes), 3), dtype='uint8') @@ -566,8 +573,11 @@ class CameraDisplay(QLabel): self.setText("No camera feed") self.get_camera_display_style = getpath.resource_path("styling/camera_display.qss") - with open(self.get_camera_display_style,"r") as cdst: - self.setStyleSheet(cdst.read()) + try: + with open(self.get_camera_display_style,"r") as cdst: + self.setStyleSheet(cdst.read()) + except FileNotFoundError: + exit(1) self.setMinimumSize(320, 240) self.fullscreen_window = None @@ -816,8 +826,11 @@ class AboutWindow(QDialog): self.toggle_btn.setCheckable(True) self.toggle_btn.setChecked(False) toggle_btn_style = getpath.resource_path("styling/togglebtnabout.qss") - with open(toggle_btn_style,"r") as tgbstyle: - self.toggle_btn.setStyleSheet(tgbstyle.read()) + try: + with open(toggle_btn_style,"r") as tgbstyle: + self.toggle_btn.setStyleSheet(tgbstyle.read()) + except FileNotFoundError: + exit(1) # Debug shit #print("i did shit") @@ -855,11 +868,44 @@ class AboutWindow(QDialog): # Set Styling for About Section style_file = getpath.resource_path("styling/about.qss") - with open(style_file,"r") as aboutstyle: - self.setStyleSheet(aboutstyle.read()) + try: + with open(style_file,"r") as aboutstyle: + self.setStyleSheet(aboutstyle.read()) + except FileNotFoundError: + exit(1) self.setLayout(layout) + # Todo Label Shit + self.todo_obj = todo.todo() + todo_text = self.get_todo_text() + todo_label = QLabel(f"
{todo_text}")
+ todo_label.setWordWrap(True)
+ todo_label.setAlignment(Qt.AlignCenter)
+
+ # TODO: Fix this xD ; Fixing a TODO lol
+ try:
+ todo_style_path = getpath.resource_path("styling/todostyle.qss")
+ with open(todo_style_path,"r") as tdf:
+ todo_label.setStyleSheet(tdf.read())
+ # here we have our wonderfull fix
+ if True == True:
+ todo_label.setStyleSheet("color: #f7ef02; font-style: italic;")
+ else:
+ pass
+ except FileNotFoundError:
+ print(f"Missing a Style File! => {todo_style_path}")
+ exit(1)
+
+ self.camobj = todo.todo()
+ cam_text = self.get_cam_text()
+ cam_label = QLabel(f"{cam_text}")
+ cam_label.setWordWrap(True)
+ cam_label.setAlignment(Qt.AlignCenter)
+ cam_label.setStyleSheet("color: #FFFF; font-style: italic;")
+ layout.addWidget(todo_label)
+ layout.addWidget(cam_label)
+
def toggle_expand(self, checked):
for key, label in self.full_labels.items():
if key not in self.important_keys:
@@ -946,6 +992,26 @@ class AboutWindow(QDialog):
return info
+ def get_todo_text(self):
+ try:
+ todo_text = self.todo_obj.gettodo()
+ if isinstance(todo_text, str):
+ return todo_text.strip()
+ else:
+ return "Invalid TODO format."
+ except Exception as e:
+ return f"Error retrieving TODO: {e}"
+
+ def get_cam_text(self):
+ try:
+ cam_text = self.camobj.getcams()
+ if isinstance(cam_text,str):
+ return cam_text.strip()
+ else:
+ return "invalid cam format"
+ except Exception as e:
+ return f"You are fuck you {e}"
+
class NetworkCameraDialog(QDialog):
@@ -1438,8 +1504,11 @@ class MainWindow(QMainWindow):
# Set dark theme style
style_file = getpath.resource_path("styling/mainwindow.qss")
- with open(style_file, "r") as mainstyle:
- self.setStyleSheet(mainstyle.read())
+ try:
+ with open(style_file, "r") as mainstyle:
+ self.setStyleSheet(mainstyle.read())
+ except FileNotFoundError:
+ exit(1)
# Set palette for better dark mode support
palette = self.palette()
@@ -1958,9 +2027,12 @@ class MainWindow(QMainWindow):
# Set Styling from cpu progress QSS file
style_file = getpath.resource_path("styling/cpu_progress.qss")
- with open(style_file,"r") as cpu_progress_style:
- self.cpu_progress.setStyleSheet(cpu_progress_style.read())
-
+ try:
+ with open(style_file,"r") as cpu_progress_style:
+ self.cpu_progress.setStyleSheet(cpu_progress_style.read())
+ except FileNotFoundError:
+ pass
+
cpu_layout.addWidget(self.cpu_progress)
hw_monitor_layout.addLayout(cpu_layout)
@@ -1976,9 +2048,12 @@ class MainWindow(QMainWindow):
core_bar.setFormat("%p%")
core_file = getpath.resource_path("styling/core_bar.qss")
- with open(core_file,"r") as core_bar_styling:
- core_bar.setStyleSheet(core_bar_styling.read())
-
+ try:
+ with open(core_file,"r") as core_bar_styling:
+ core_bar.setStyleSheet(core_bar_styling.read())
+ except FileNotFoundError:
+ pass
+
cores_layout.addWidget(core_label, i, 0)
cores_layout.addWidget(core_bar, i, 1)
self.core_bars.append(core_bar)
@@ -2043,8 +2118,11 @@ class MainWindow(QMainWindow):
for display in self.camera_displays:
display.setText("No camera feed")
cleardisplaypath = getpath.resource_path("styling/cleardisplay.qss")
- with open(cleardisplaypath,"r") as cdstyle:
- display.setStyleSheet(cdstyle.read())
+ try:
+ with open(cleardisplaypath,"r") as cdstyle:
+ display.setStyleSheet(cdstyle.read())
+ except FileNotFoundError:
+ pass
def update_feeds(self):
"""Update the camera feeds in the display"""
@@ -2271,6 +2349,13 @@ class MainWindow(QMainWindow):
self.stop_btn.setEnabled(False)
class initQT():
+ """
+ This is a QOL Change if you prefer to do it the hard way. Or you just like to get Fist Fucked then i suggest you remove the Function Calls in the
+ Main Call of the Class!
+
+ This is not needed for Windows as it does this Automatically (at least i think)
+ If some shit that is supposed to happen isnt happening. Step through this Class Via Debuggers!
+ """
def __init__(self):
self.session_type = None # This is for QT #
#--------------------#
@@ -2280,11 +2365,6 @@ class initQT():
# If the OS is Linux get Qts Session Type
if platform.system() == "Linux":
self.session_type = os.getenv("XDG_SESSION_TYPE")
-
-# Enable this is stuff is exiting!
-
-# print(f"got {self.session_type} ")
-
return self.session_type
else:
# If theres no Type then Exit 1
@@ -2299,10 +2379,6 @@ class initQT():
# Set the Session Type to the one it got
if self.session_type:
os.environ["XDG_SESSION_TYPE"] = self.session_type
-
-# Enable if stuff is exiting!
-
-# print(f"set the ENVVAR to {self.session_type}")
else:
# If this fails then just exit with 1
print(
@@ -2319,14 +2395,14 @@ class initQT():
pass
if __name__ == "__main__":
- # Initialize Qt if on Linux
+ # Initialize Qt if on Linux ; If shit fails then modify these Functions
if platform.system() == "Linux":
qt = initQT()
qt.getenv()
qt.setenv()
qt.shutupCV()
else:
- # We do nothing, Windows doesnt need this
+ # We do nothing, Windows doesnt need this ; better shit anyways
pass
app = QApplication(sys.argv)
@@ -2339,7 +2415,6 @@ if __name__ == "__main__":
# Set application style to Fusion for better dark mode support
app.setStyle("Fusion")
-
window = MainWindow()
window.show()
diff --git a/mucapy/styling/mw.qss b/mucapy/styling/mw.qss
new file mode 100644
index 0000000..b8b9464
--- /dev/null
+++ b/mucapy/styling/mw.qss
@@ -0,0 +1,95 @@
+QMainWindow, QWidget {
+ background-color: #2D2D2D;
+ color: #DDD;
+}
+
+QLabel {
+ color: #DDD;
+}
+
+QPushButton {
+ background-color: #3A3A3A;
+ color: #DDD;
+ border: 1px solid #555;
+ border-radius: 4px;
+ padding: 5px;
+}
+
+QPushButton:hover {
+ background-color: #4A4A4A;
+}
+
+QPushButton:pressed {
+ background-color: #2A2A2A;
+}
+
+QPushButton:disabled {
+ background-color: #2A2A2A;
+ color: #777;
+}
+
+QComboBox, QSpinBox {
+ background-color: #3A3A3A;
+ color: #DDD;
+ border: 1px solid #555;
+ border-radius: 4px;
+ padding: 3px;
+}
+
+QGroupBox {
+ border: 1px solid #555;
+ border-radius: 4px;
+ margin-top: 10px;
+ padding-top: 15px;
+ background-color: #252525;
+}
+
+QGroupBox::title {
+ subcontrol-origin: margin;
+ left: 10px;
+ padding: 0 3px;
+ color: #DDD;
+}
+
+QMenuBar {
+ background-color: #252525;
+ color: #DDD;
+}
+
+QMenuBar::item {
+ background-color: transparent;
+ padding: 5px 10px;
+}
+
+QMenuBar::item:selected {
+ background-color: #3A3A3A;
+}
+
+QMenu {
+ background-color: #252525;
+ border: 1px solid #444;
+ color: #DDD;
+}
+
+QMenu::item:selected {
+ background-color: #3A3A3A;
+}
+
+QScrollArea {
+ border: none;
+}
+
+QDockWidget {
+ titlebar-close-icon: url(none);
+ titlebar-normal-icon: url(none);
+}
+
+QDockWidget::title {
+ background: #252525;
+ padding-left: 5px;
+}
+
+QToolButton {
+ background-color: transparent;
+ border: none;
+}
\ No newline at end of file
diff --git a/mucapy/styling/todostyle.qss b/mucapy/styling/todostyle.qss
new file mode 100644
index 0000000..70412f5
--- /dev/null
+++ b/mucapy/styling/todostyle.qss
@@ -0,0 +1,5 @@
+QLabel#todoLabel {
+ color:rgb(21, 255, 0);
+ font-family: monospace;
+ font-size: 12px;
+}
diff --git a/mucapy/todo.py b/mucapy/todo.py
new file mode 100644
index 0000000..998c75b
--- /dev/null
+++ b/mucapy/todo.py
@@ -0,0 +1,50 @@
+"""
+Here we have a simple fucking class to get the fuckass Todo thing
+Probably will do none of them
+anyways, if you have suggestions pr this shit
+
+idk if you are smarter than me then actually do them.
+
+fuck you
+ -Rattatwinko 8.jun.25 (20:25)
+"""
+
+class todo:
+ def __init__(self):
+#------------------------------------------------------------------------------------------------------------------------------------------------#
+ self.todo : str = """
+
+Very Good Very Nice Todo List:
+
+NOTE: If you want to run this in Visual Studio Codes built in Terminal you will get fucked in your tiny tight ass.
+NOTE: If you are running this from the Build Executable from the Workflow , you ass is fine (you wont get fucked you slut)
+NOTE: If you compiled this yourself ; you are one Fucking Genious
+
+#-----------------------#
+# Changes: #
+# Not Very Much lolz #
+#-----------------------#
+
+TODO:
+ [] - Fix Network Cameras from Crashing the Programm (This sometimes happens when only network cams are selected and it times out)
+ [] - Make Seperate Styling (unlikely that this will happen)
+ [] - RTSP Camera Streaming
+ [] - Make MJPEG more stable and efficient. (maybe use c++ for this or rust)
+ - NOTE: http://pendelcam.kip.uni-heidelberg.de/mjpg/video.mjpg
+ This is a Testing URL for MJPEG (stable and renders fine)
+
+""" # This will display Centered (look in about window class)
+#------------------------------------------------------------------------------------------------------------------------------------------------#
+
+ self.cameraURL : str = """
+Cameras:
+ - http://pendelcam.kip.uni-heidelberg.de/mjpg/video.mjpg
+""" # This will also display centered
+
+#------------------------------------------------------------------------------------------------------------------------------------------------#
+
+ def gettodo(self) -> str:
+ return self.todo
+ def getcams(self) -> str:
+ return self.cameraURL
+