Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion System/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ def formatDefault() -> None:
open("System/config/themes.json", "w").write("{\n \"default\": \"light\"\n}\n")



class FontConfig:
"""
Font Configuration
Expand Down
2 changes: 1 addition & 1 deletion System/config/themes/light.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"text-color": "#000000",
"background-color": "#FFFFFF",
"background-color-2": "#EFEFEF",
"background-color-2": "#F5F5F5",
"background-color-3": "#DFDFDF"
}
273 changes: 173 additions & 100 deletions System/dialogs.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,117 +14,190 @@
from PyQt6.QtGui import *
from PyQt6.QtCore import *
from PyQt6.QtWidgets import *
from PyQt6.QtNetwork import *


class Preferences(QWidget):
"""System Preferences Application"""
class Appearance(QWidget):
class ThemeLabel(QLabel):
def __init__(self, parent):
super(Preferences.Appearance.ThemeLabel, self).__init__(parent)
self.setCursor(Qt.CursorShape.PointingHandCursor)
self.index = None
self.setFont(QFont(returnProperties()["font-family"], returnProperties()["font-size"]))
self.setAlignment(Qt.AlignmentFlag.AlignCenter)

def mousePressEvent(self, event):
self.parent().parent().changeTheme(self.index)
super(Preferences.Appearance.ThemeLabel, self).mousePressEvent(event)

class Theme(QWidget):
def __init__(self, parent, update_function):
super(Preferences.Appearance.Theme, self).__init__(parent=parent)
self.update_function = update_function
self.layout = QGridLayout()
self.theme, self.font_size, self.font_family = returnProperties()["theme"], returnProperties()["font-size"], returnProperties()["font-family"]
self.top_bar = QGroupBox(self)
self.top_bar.setLayout(QHBoxLayout())
self.back_button = QPushButton("Back", self.top_bar)
self.back_button.pressed.connect(lambda self=self: self.parent().setCurrentIndex(0))
self.top_bar.layout().addWidget(self.back_button)
# self.layout.addWidget(self.top_bar, 0, 0)
self.widgets, self.group_box_widgets = {
"top-bar": [self.top_bar, [0, 0]],
"theme-label": [QLabel("Theme"), [3, 0]],
"theme-group-box": [QGroupBox(self), [3, 1]],
"font-size-label": [QLabel("Font Size"), [5, 0]],
"font-size": [Slider(5, 20, int(returnProperties()["font-size"]), self.changeFontSize), [5, 1]],
"reset-font-size": [PushButton("Reset"), [5, 2]],
"font-family-label": [QLabel("Font Family"), [6, 0]],
"font-family": [QComboBox(self), [6, 1]]
}, {}
# Append to self.group_box_widgets
for x, y in zip(Themes.getThemes(), range(1, len(Themes.getThemes().keys()) + 1)):
self.group_box_widgets[x] = [Preferences.Appearance.ThemeLabel(self), [1, y]]
# Specific widget properties
# # Font family properties
self.widgets["font-family"][0].addItems(returnProperties()["fonts"])
self.widgets["font-family"][0].setStyleSheet(f"QComboBox QAbstractItemView {{ selection-color: {'#AAAAAA' if returnProperties()['theme'] == 'light' else '#555555'}; color: {returnBackgroundProperties()['text-color']}; }};")
self.widgets["font-family"][0].setCurrentIndex(returnProperties()["fonts"].index(self.font_family))
self.widgets["font-family"][0].currentIndexChanged.connect(self.changeFontFamily)
# # Reset font size properties
self.widgets["reset-font-size"][0].clicked.connect(self.resetFontSize)
# # Label properties
for i in ["theme-label", "font-size-label", "font-family-label"]:
self.widgets[i][0].setStyleSheet(f"color: {returnBackgroundProperties()['text-color']};")
self.widgets[i][0].setFont(QFont(returnProperties()["font-family"], returnProperties()["font-size"]))
# # Theme group box properties
self.widgets["theme-group-box"][0].setStyleSheet("QGroupBox { border: none; }")
self.group_box_layout = QHBoxLayout()
for i in self.group_box_widgets:
self.group_box_layout.addWidget(self.group_box_widgets[i][0])
self.widgets["theme-group-box"][0].setLayout(self.group_box_layout)
self.widgets["theme-group-box"][0].setFixedSize(540, 100)
self.widgets["theme-group-box"][0].layout().setContentsMargins(30, 30, 30, 30)
# # Theme button properties
for i in self.group_box_widgets.keys():
self.group_box_widgets[i][0].setText(i.title())
self.group_box_widgets[i][0].setStyleSheet(f"color: #{str(Themes.getThemes()[i]['text-color'])[1:].lower()}; border: none; background: #{str(Themes.getThemes()[i]['background-color'])[1:].lower()};")
self.group_box_widgets[i][0].index = i
# exec(f"self.group_box_widgets[i][0].pressed.connect(lambda self=self: self.changeTheme('{i}'))", globals(), locals())
# Add to layout
for i in self.widgets.keys():
self.layout.addWidget(self.widgets[i][0], self.widgets[i][1][0], self.widgets[i][1][1])
self.setLayout(self.layout) # Set layout

def _update(self):
self.setStyleSheet(f"background-color: {returnBackgroundProperties()['background-color-2']}")
for i in ["theme-label", "font-size-label", "font-family-label"]:
self.widgets[i][0].setStyleSheet(f"color: {returnBackgroundProperties()['text-color']}; font-size: {returnProperties()['font-size']}")
self.widgets[i][0].setFont(QFont(returnProperties()["font-family"], returnProperties()["font-size"]))
for i in self.group_box_widgets.keys():
self.group_box_widgets[i][0].setStyleSheet(f"color: {returnBackgroundProperties()['text-color']}; border: none")
self.group_box_widgets[i][0].setFont(QFont(returnProperties()["font-family"], returnProperties()["font-size"]))
# self.widgets["font-family"][0].setStyleSheet("QComboBox QAbstractItemView {selection-color: #AAAAAA}")
if returnProperties()["theme"] == "light":
self.widgets["font-family"][0].setStyleSheet("QComboBox QAbstractItemView { selection-color: #AAAAAA; color: #000000; };")
else:
self.widgets["font-family"][0].setStyleSheet("QComboBox QAbstractItemView { selection-color: #555555; color: #FFFFFF; };")
self.update_function()

def resetFontSize(self) -> None:
self.font_size = 12
self.widgets["font-size"][0].setValue(12)
with open("System/config/font.json") as file:
data = load(file)
data["font-size"] = self.font_size
open("System/config/font.json", "w").write(str(data).replace("'", "\""))
self._update()

def changeFontFamily(self) -> None:
self.font_family = self.widgets["font-family"][0].currentText()
with open("System/config/font.json", "r+") as file:
data = load(file)
data["font-family"] = self.font_family
open("System/config/font.json", "w").write(str(data).replace("'", "\""))
self._update()

def changeFontSize(self) -> None:
self.font_size = self.widgets["font-size"][0].value()
with open("System/config/font.json", "r+") as file:
data = load(file)
data["font-size"] = self.font_size
open("System/config/font.json", "w").write(str(data).replace("'", "\""))
self._update()

def changeTheme(self, theme):
self.theme = theme
with open("System/config/theme.json", "r+") as file:
data = load(file)
data["theme"] = self.theme
open("System/config/theme.json", "w").write(str(data).replace("'", "\""))
self._update()
self.parent().parent().parent().parent().parent().restartWindow()

def resizeEvent(self, event) -> None:
self.top_bar.resize(QSize(event.size().width(), self.top_bar.size().height()))
super(Preferences.Appearance.Theme, self).resizeEvent(event)

class AppearanceWidget(QWidget):
def __init__(self, parent, update_function):
super(Preferences.Appearance.AppearanceWidget, self).__init__(parent)
self.update_function = update_function
self.buttons = []
self.buttons.append(ActionPushButton(self, "General", lambda: self.parent().setCurrentIndex(1)))
self.buttons.append(ActionPushButton(self, "Windows", lambda: self.parent().setCurrentIndex(1)))
self.buttons.append(ActionPushButton(self, "Dock", lambda: self.parent().setCurrentIndex(1)))
width = self.buttons[0].width()
for i in range(len(self.buttons)):
self.buttons[i].move(QPoint(i * (width + 5), 0))

def resizeEvent(self, event) -> None:
single_width, width, y = self.buttons[0].width(), 0, 0
for i in range(len(self.buttons)):
if (width + 5) >= self.width():
y += self.buttons[i].height() + 5
width = 0
self.buttons[i].move(QPoint(width, y))
width += single_width + 5
super(Preferences.Appearance.AppearanceWidget, self).resizeEvent(event)

def __init__(self, parent, update_function):
super(Preferences.Appearance, self).__init__(parent)
self.update_function = update_function
self.stacked_widgets, self.pages = QStackedWidget(self), {"main": Preferences.Appearance.AppearanceWidget(self, update_function), "theme": Preferences.Appearance.Theme(self, update_function)}
for i in self.pages.values():
self.stacked_widgets.addWidget(i)

def resizeEvent(self, event) -> None:
for i in self.pages.values():
i.resize(event.size())
super(Preferences.Appearance, self).resizeEvent(event)

def __init__(self, update_function) -> None:
super(Preferences, self).__init__()
self.setCursor(Qt.CursorShape.ArrowCursor)
self.update_function = update_function
self.layout = QGridLayout()
self.theme, self.font_size, self.font_family = returnProperties()["theme"], returnProperties()["font-size"], returnProperties()["font-family"]
self.widgets, self.group_box_widgets, self.theme_icons = {
"theme-label": [QLabel("Theme"), [3, 1]],
"theme-group-box": [QGroupBox(self), [3, 2]],
"font-size-label": [QLabel("Font Size"), [5, 1]],
"font-size": [Slider(5, 20, int(returnProperties()["font-size"]), self.changeFontSize), [5, 2]],
"reset-font-size": [PushButton("Reset"), [5, 3]],
"font-family-label": [QLabel("Font Family"), [6, 1]],
"font-family": [QComboBox(self), [6, 2]]
}, {}, {}
# Append to self.group_box_widgets
for x, y in zip(Themes.getThemes(), range(1, len(Themes.getThemes().keys()) + 1)):
self.group_box_widgets[x] = [QToolButton(self), [1, y]]
# Specific widget properties
# # Font family properties
self.widgets["font-family"][0].addItems(returnProperties()["fonts"])
self.widgets["font-family"][0].setStyleSheet(f"QComboBox QAbstractItemView {{ selection-color: {'#AAAAAA' if returnProperties()['theme'] == 'light' else '#555555'}; color: {returnBackgroundProperties()['text-color']}; }};")
self.widgets["font-family"][0].setCurrentIndex(returnProperties()["fonts"].index(self.font_family))
self.widgets["font-family"][0].currentIndexChanged.connect(self.changeFontFamily)
# # Reset font size properties
self.widgets["reset-font-size"][0].clicked.connect(self.resetFontSize)
# # Label properties
for i in ["theme-label", "font-size-label", "font-family-label"]:
self.widgets[i][0].setStyleSheet(f"color: {returnBackgroundProperties()['text-color']};")
self.widgets[i][0].setFont(QFont(returnProperties()["font-family"], returnProperties()["font-size"]))
# # Theme group box properties
self.widgets["theme-group-box"][0].setStyleSheet("QGroupBox { border: none; }")
self.group_box_layout = QHBoxLayout()
for i in self.group_box_widgets: self.group_box_layout.addWidget(self.group_box_widgets[i][0])
self.widgets["theme-group-box"][0].setLayout(self.group_box_layout)
self.widgets["theme-group-box"][0].setFixedSize(540, 100)
# # Theme button properties
for i in self.group_box_widgets.keys():
self.theme_icons[i] = QNetworkAccessManager(self)
exec(f"self.theme_icons[i].finished.connect(lambda reply, self=self: self.setIcon(reply, '{i}'))", globals(), locals())
self.theme_icons[i].get(QNetworkRequest(QUrl(f"https://htmlcolors.com/color-image/{str(Themes.getThemes()[i]['background-color'])[1:].lower()}.png")))
self.group_box_widgets[i][0].setText(i.title())
self.group_box_widgets[i][0].setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonTextUnderIcon)
self.group_box_widgets[i][0].setCursor(Qt.CursorShape.PointingHandCursor)
self.group_box_widgets[i][0].setStyleSheet(f"color: {returnBackgroundProperties()['text-color']}; border: none")
self.group_box_widgets[i][0].setFont(QFont(returnProperties()["font-family"], returnProperties()["font-size"]))
self.group_box_widgets[i][0].setIconSize(QSize(25, 25))
exec(f"self.group_box_widgets[i][0].pressed.connect(lambda self=self: self.changeTheme('{i}'))", globals(), locals())
# Add to layout
for i in self.widgets.keys():
self.layout.addWidget(self.widgets[i][0], self.widgets[i][1][0], self.widgets[i][1][1])
self.setLayout(self.layout) # Set layout

def setIcon(self, reply, icon):
image = QImage()
image.loadFromData(reply.readAll())
self.group_box_widgets[icon][0].setIcon(QIcon(QPixmap.fromImage(image)))
self.tabs = QScrollArea(self)
self.tabs.setWidgetResizable(True)

def _update(self):
self.setStyleSheet(f"background-color: {returnBackgroundProperties()['background-color-2']}")
for i in ["theme-label", "font-size-label", "font-family-label"]:
self.widgets[i][0].setStyleSheet(f"color: {returnBackgroundProperties()['text-color']}; font-size: {returnProperties()['font-size']}")
self.widgets[i][0].setFont(QFont(returnProperties()["font-family"], returnProperties()["font-size"]))
for i in self.group_box_widgets.keys():
self.group_box_widgets[i][0].setStyleSheet(f"color: {returnBackgroundProperties()['text-color']}; border: none")
self.group_box_widgets[i][0].setFont(QFont(returnProperties()["font-family"], returnProperties()["font-size"]))
# self.widgets["font-family"][0].setStyleSheet("QComboBox QAbstractItemView {selection-color: #AAAAAA}")
if returnProperties()["theme"] == "light":
self.widgets["font-family"][0].setStyleSheet("QComboBox QAbstractItemView { selection-color: #AAAAAA; color: #000000; };")
else:
self.widgets["font-family"][0].setStyleSheet("QComboBox QAbstractItemView { selection-color: #555555; color: #FFFFFF; };")
self.update_function()

def resetFontSize(self) -> None:
self.font_size = 12
self.widgets["font-size"][0].setValue(12)
with open("System/config/font.json") as file:
data = load(file)
data["font-size"] = self.font_size
open("System/config/font.json", "w").write(str(data).replace("'", "\""))
self._update()
self.tab_widget = QWidget()
self.tabs.setWidget(self.tab_widget)

self.tab_layout = QVBoxLayout(self.tab_widget)
self.tab_layout.addWidget(TabButton(self.tab_widget, lambda: self.stacked_widgets.setCurrentIndex(0), "Appearance"))
self.tab_layout.addItem(QSpacerItem(100, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding))

def changeFontFamily(self) -> None:
self.font_family = self.widgets["font-family"][0].currentText()
with open("System/config/font.json", "r+") as file:
data = load(file)
data["font-family"] = self.font_family
open("System/config/font.json", "w").write(str(data).replace("'", "\""))
self._update()
self.tabs.setStyleSheet("border: none; background: #F0F0F0")

def changeFontSize(self) -> None:
self.font_size = self.widgets["font-size"][0].value()
with open("System/config/font.json", "r+") as file:
data = load(file)
data["font-size"] = self.font_size
open("System/config/font.json", "w").write(str(data).replace("'", "\""))
self._update()
self.stacked_widgets, self.pages = QStackedWidget(self), {"appearance": Preferences.Appearance(self, update_function)}
for i in self.pages.values():
self.stacked_widgets.addWidget(i)

def changeTheme(self, theme):
self.theme = theme
with open("System/config/theme.json", "r+") as file:
data = load(file)
data["theme"] = self.theme
open("System/config/theme.json", "w").write(str(data).replace("'", "\""))
self._update()
self.parent().restartWindow()
def resizeEvent(self, event):
self.tabs.resize(QSize(event.size().width() // 5, event.size().height()))
self.stacked_widgets.resize(QSize(event.size().width() // 5 * 4, event.size().height()))
self.stacked_widgets.move(self.tabs.width(), 0)
super(Preferences, self).resizeEvent(event)


class ShutDownWindow(QWidget):
Expand Down
2 changes: 1 addition & 1 deletion System/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@

applications, config = _applications.returnApplications(), Config()

print("Starting the Mini Operating System...") # Print starting message
print("Starting the Mini Operating System...") # Print starting message (maybe remove?)


class Window(QMainWindow):
Expand Down
37 changes: 29 additions & 8 deletions System/widgets/buttons/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,16 +92,20 @@ def leaveEvent(self, event: QEvent) -> None:

class PushButton(QPushButton):
"""Add QPushButton Animation"""
def __init__(self, text="", color="black") -> None:
super().__init__()
def __init__(self, text="", parent=None, color="black", padding="15px", background="#F5F5F5", hover="#E6E6E6") -> None:
if parent is None:
super(PushButton, self).__init__()
else:
super(PushButton, self).__init__(parent)
self.color = color
self.padding = padding
self.setText(text)
self._animation = QVariantAnimation()
self._animation.setStartValue(QColor("black"))
self._animation.setEndValue(QColor("white"))
self._animation.setStartValue(QColor(hover))
self._animation.setEndValue(QColor(background))
self._animation.valueChanged.connect(self.valueChanged)
self._animation.setDuration(200)
self.updateStylesheet(QColor("white"))
self.updateStylesheet(QColor(background))
self.setCursor(QCursor(Qt.CursorShape.PointingHandCursor))

def valueChanged(self, color: QColor) -> None:
Expand All @@ -110,9 +114,7 @@ def valueChanged(self, color: QColor) -> None:

def updateStylesheet(self, background: QColor) -> None:
"""Update style sheet"""
self.setStyleSheet(
f"QPushButton {{background-color: {background.name()}; color: #888888; padding: 16px 32px; text-align: center; text-decoration: none; font-size: 16px; margin: 4px 2px; border: 2px solid "
f"white;}}")
self.setStyleSheet(f"background-color: {background.name()}; color: {self.color}; border: none; padding: {self.padding};")

def enterEvent(self, event: QEvent) -> None:
"""Display backward color animation on mouse hover"""
Expand All @@ -134,3 +136,22 @@ def updateColor(self, color="black") -> None:
class ToolButton(QToolButton):
def __init__(self, parent):
super(ToolButton, self).__init__(parent)


class TabButton(PushButton):
def __init__(self, parent, action, text=""):
super(TabButton, self).__init__(text, parent, padding="5px")
self.action = action

def mousePressEvent(self, event):
self.action()
super(TabButton, self).mousePressEvent(event)


class ActionPushButton(PushButton):
def __init__(self, parent, text="", action=None):
super(ActionPushButton, self).__init__(text, parent, padding="0px")
self.action = action
self.pressed.connect(lambda self=self: self.action() if self.action is not None else None)
self.setFixedSize(QSize(75, 75))