Skip to content
This repository was archived by the owner on Jun 24, 2024. It is now read-only.
Merged
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
15 changes: 14 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,21 @@
<h1 align="center">ManimStudio</h1>

</p>
<br/>

<div align="center">
<a href="https://github.com/MemerGamer/ManimStudio/actions/workflows/documentation.yml">
<img src="https://github.com/MemerGamer/ManimStudio/actions/workflows/documentation.yml/badge.svg?branch=main" alt="documentation">
</a>

<a href="https://github.com/MemerGamer/ManimStudio/actions/workflows/pages/pages-build-deployment">
<img src="https://github.com/MemerGamer/ManimStudio/actions/workflows/pages/pages-build-deployment/badge.svg" alt="pages-build-deployment">
</a>

<a href="https://github.com/MemerGamer/ManimStudio/actions/workflows/release-please.yml">
<img src="https://github.com/MemerGamer/ManimStudio/actions/workflows/release-please.yml/badge.svg" alt="release-please">
</a>
</div>
<hr>
ManimStudio is a video editor application for editing Python ManimCE video projects.

## Table of Contents
Expand Down
1 change: 1 addition & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

sys.path.insert(0, os.path.abspath("../src/core"))
sys.path.insert(0, os.path.abspath("../src/ui"))
sys.path.insert(0, os.path.abspath("../src/utils"))

print("sys.path: ", sys.path)

Expand Down
1 change: 1 addition & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Welcome to ManimStudio's documentation!
src/core/settings
src/core/project_creation_dialog
src/core/project_opening_dialog
src/utils/logger_utility
src/ui/form_ui
src/ui/settings_ui
src/ui/videoeditor_ui
Expand Down
7 changes: 7 additions & 0 deletions docs/src/utils/logger_utility.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
logger_utility module
=====================

.. automodule:: logger_utility
:members:
:undoc-members:
:show-inheritance:
5 changes: 5 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
dill==0.3.8
loguru==0.7.2
markdown-it-py==3.0.0
mdurl==0.1.2
Pygments==2.17.2
PyQt6==6.6.1
PyQt6-Qt6==6.6.1
PyQt6-sip==13.6.0
PySide6==6.6.1
PySide6-Addons==6.6.1
PySide6-Essentials==6.6.1
rich==13.7.0
shiboken6==6.6.1
23 changes: 18 additions & 5 deletions src/core/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,23 +32,28 @@
from src.core.project_creation_dialog import ProjectCreationDialog
from src.core.project_opening_dialog import ProjectOpeningDialog

# Logger
from src.utils.logger_utility import logger


class Main(QWidget):
"""Main class for the application"""

styleSheetUpdated = Signal(str)
videoEditorOpened = Signal(str)

@logger.catch
def __init__(self, parent=None):
"""Initializer"""
super().__init__(parent)
self.customStyleSheet = ""
self.settings = load_settings()
self.themes = load_themes()
self.current_theme = load_current_theme()

logger.info("Main window initialized")
self.load_ui()

@logger.catch
def apply_stylesheet(self):
"""Apply the stylesheet to the main window and update the image based on the theme"""

Expand All @@ -68,7 +73,9 @@ def apply_stylesheet(self):
self.ui.label.setPixmap(QPixmap(image_path))

self.styleSheetUpdated.emit(self.customStyleSheet)
logger.info("Stylesheet applied")

@logger.catch
def load_ui(self):
"""Load the UI from the .ui file"""
loader = QUiLoader()
Expand All @@ -86,6 +93,9 @@ def load_ui(self):
self.ui.newProjectBtn.clicked.connect(self.showProjectCreationDialog)
self.ui.openProjectBtn.clicked.connect(self.showProjectOpenDialog)

logger.info("UI loaded")

@logger.catch
def open_settings_dialog(self):
"""Open the settings dialog"""
self.settingsDialog = QDialog()
Expand Down Expand Up @@ -124,6 +134,7 @@ def open_settings_dialog(self):

self.settingsDialog.exec()

@logger.catch
def update_settings_from_dialog(self):
"""Update the settings from the dialog, and update the UI"""

Expand Down Expand Up @@ -159,6 +170,7 @@ def update_settings_from_dialog(self):
# Apply the stylesheet
self.apply_stylesheet()

@logger.catch
def showProjectCreationDialog(self):
"""Show the project creation dialog"""
try:
Expand All @@ -176,8 +188,9 @@ def showProjectCreationDialog(self):
if dialog.exec():
pass
except Exception as e:
print(f"Error showing project creation dialog: {e}")
logger.error(f"Error showing project creation dialog: {e}")

@logger.catch
def showProjectOpenDialog(self):
"""Show the project open dialog"""
try:
Expand All @@ -191,8 +204,9 @@ def showProjectOpenDialog(self):
) # Close the main window (WelcomeScreen) as well
dialog.exec()
except Exception as e:
print(f"Error showing project open dialog: {e}")
logger.error(f"Error showing project open dialog: {e}")

@logger.catch
def openVideoEditor(self, projectFilePath):
"""Open the video editor with the project file"""
try:
Expand All @@ -206,10 +220,9 @@ def openVideoEditor(self, projectFilePath):

# Emit the signal after VideoEditor dialog is opened
self.videoEditorOpened.emit(projectFilePath)

self.videoEditor.exec()
except Exception as e:
print(f"Error opening video editor: {e}")
logger.error(f"Error opening video editor: {e}")
pass


Expand Down
9 changes: 8 additions & 1 deletion src/core/project_creation_dialog.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import os
import sys
from pathlib import Path
import dill
from pathlib import Path
from PySide6.QtWidgets import QDialog, QFileDialog, QMessageBox
from PySide6.QtCore import Signal

Expand All @@ -17,12 +17,15 @@
getRecentProjectCreationPaths,
)

from src.utils.logger_utility import logger


class ProjectCreationDialog(QDialog):
"""Dialog for creating a new project"""

projectCreated = Signal(str)

@logger.catch
def __init__(self, parent=None):
"""Initializer"""
super(ProjectCreationDialog, self).__init__(parent)
Expand All @@ -32,18 +35,21 @@ def __init__(self, parent=None):
self.ui.folderSelectComboBox.mouseDoubleClickEvent = self.selectFolder
self.ui.createProjectPushButton.clicked.connect(self.createProject)

@logger.catch
def loadRecentProjectPaths(self):
"""Load the recent project paths into the combo box"""
recentPaths = getRecentProjectCreationPaths()
for path in recentPaths:
self.ui.folderSelectComboBox.addItem(path)

@logger.catch
def selectFolder(self, event):
"""Select a folder for the project"""
folder = QFileDialog.getExistingDirectory(self, "Select Project Folder")
if folder:
self.ui.folderSelectComboBox.addItem(folder)

@logger.catch
def createProject(self):
"""Create a new project and emit the projectCreated signal"""
projectName = self.ui.projectNameLineEdit.text()
Expand All @@ -53,6 +59,7 @@ def createProject(self):
QMessageBox.critical(
self, "Error", "Please enter a project name and select a folder"
)
logger.error("Project name or folder not entered")
return

projectPath = os.path.join(projectFolder, projectName)
Expand Down
16 changes: 16 additions & 0 deletions src/core/project_opening_dialog.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,28 @@
import os
import sys
from pathlib import Path
from PySide6.QtWidgets import QDialog, QFileDialog, QMessageBox
from PySide6.QtCore import Signal


# Add the parent directory of 'src' to sys.path
current_dir = Path(__file__).resolve().parent
parent_dir = current_dir.parent.parent # Adjust according to your project structure
sys.path.append(str(parent_dir))


from src.ui.project_opening_dialog_ui import Ui_Form as Ui_ProjectOpeningDialog
from settings import getRecentProjectPaths, addRecentProjectPath

from src.utils.logger_utility import logger


class ProjectOpeningDialog(QDialog):
"""Dialog for opening an existing project"""

projectSelected = Signal(str)

@logger.catch
def __init__(self, parent=None):
"""Initializer"""
super().__init__(parent)
Expand All @@ -20,12 +33,14 @@ def __init__(self, parent=None):
self.ui.openProjectPushButton.clicked.connect(self.openProject)
self.ui.projectSelectComboBox.mouseDoubleClickEvent = self.browseForProject

@logger.catch
def loadRecentProjects(self):
"""Load the recent projects into the combo box"""
recentProjects = getRecentProjectPaths()
for projectPath in recentProjects:
self.ui.projectSelectComboBox.addItem(projectPath)

@logger.catch
def browseForProject(self, event):
"""Browse for a project"""
projectPath, _ = QFileDialog.getOpenFileName(
Expand All @@ -36,6 +51,7 @@ def browseForProject(self, event):
addRecentProjectPath(projectPath)
self.accept()

@logger.catch
def openProject(self, event):
"""Open the selected project"""
selectedProject = self.ui.projectSelectComboBox.currentText()
Expand Down
24 changes: 19 additions & 5 deletions src/core/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@
import sys
import json

"""Settings"""
from src.utils.logger_utility import logger


# Global static base settings path
# Global base settings and theme path
base_settings_path = Path(os.getcwd()) / ".config" / "settings.json"
base_theme_path = Path(os.getcwd()) / "src" / "themes" / "themes.json"


@logger.catch
def getSettingsPath():
"""Get the settings path based on the platform"""
homeDir = Path.home()
Expand Down Expand Up @@ -38,47 +40,55 @@ def getSettingsPath():
json.dump(settings, file, indent=4)


@logger.catch
def getThemesPath():
"""Get the themes path"""
return base_theme_path


themesPath = getThemesPath()

"""Settings"""


@logger.catch
def load_settings():
"""Load the settings from the settings.json file"""
try:
with open(settingsPath, "r") as file:
return json.load(file)
except Exception as e:
print(e)
logger.error(e)
return {}


@logger.catch
def update_settings(new_settings):
"""Overwrite the settings file with the new settings"""
try:
with open(settingsPath, "w") as file:
json.dump(new_settings, file, indent=4)
return True
except Exception as e:
logger.error(e)
return False


"""Themes"""


@logger.catch
def load_themes():
"""Load the themes from the themes.json file"""
try:
with open(themesPath, "r") as file:
return json.load(file)
except Exception as e:
print(e)
logger.error(e)
return {}


@logger.catch
def load_current_theme():
"""Load the current theme"""
settings = load_settings()
Expand All @@ -91,10 +101,11 @@ def load_current_theme():
) as file:
return json.load(file)
except Exception as e:
print(e)
logger.error(e)
return {}


@logger.catch
def addRecentProjectCreationPath(projectCreationPath):
"""Add a recent project creation path to the settings file"""
settings = load_settings()
Expand All @@ -107,6 +118,7 @@ def addRecentProjectCreationPath(projectCreationPath):
update_settings(settings)


@logger.catch
def addRecentProjectPath(projectPath):
"""Add a recent project path to the settings file"""
settings = load_settings()
Expand All @@ -119,11 +131,13 @@ def addRecentProjectPath(projectPath):
update_settings(settings)


@logger.catch
def getRecentProjectCreationPaths():
"""Get the recent project creation paths"""
return load_settings().get("recentProjectCreationPaths", [])


@logger.catch
def getRecentProjectPaths():
"""Get the recent project paths"""
return load_settings().get("recentProjectPaths", [])
Empty file added src/utils/__init__.py
Empty file.
Loading