Finished welcome dialog. New project dialog prototype.
This commit is contained in:
		
							
								
								
									
										5
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								Makefile
									
									
									
									
									
								
							@@ -7,8 +7,9 @@ UI_OUT=$(UI:.ui=_ui.py)
 | 
			
		||||
all: $(RESOURCES_OUT) $(UI_OUT)
 | 
			
		||||
 | 
			
		||||
clean:
 | 
			
		||||
	rm ${UI_OUT}
 | 
			
		||||
	rm ${RESOURCES_OUT}
 | 
			
		||||
	rm -f ${UI_OUT}
 | 
			
		||||
	rm -f ${RESOURCES_OUT}
 | 
			
		||||
	find -name '__pycache__' -exec rm -rf "{}" \;
 | 
			
		||||
 | 
			
		||||
%_rc.py: %.qrc
 | 
			
		||||
	pyrcc5 $< -o $@
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1 @@
 | 
			
		||||
from .project_manager import ProjectManager
 | 
			
		||||
@@ -1,49 +1,90 @@
 | 
			
		||||
from typing import Iterable
 | 
			
		||||
 | 
			
		||||
from model.project import Project
 | 
			
		||||
from model import Project, RecentProject
 | 
			
		||||
from storage import AppDataStorage
 | 
			
		||||
 | 
			
		||||
class ProjectManager(object):
 | 
			
		||||
 | 
			
		||||
    def __init__(self, appDataStorage):
 | 
			
		||||
    def __init__(self, appDataStorage : AppDataStorage):
 | 
			
		||||
        self.__appDataStorage = appDataStorage
 | 
			
		||||
        self.__recentProjects = None
 | 
			
		||||
        self.__recentProjects : dict = None
 | 
			
		||||
 | 
			
		||||
    def getRecentProjects(self):
 | 
			
		||||
    """
 | 
			
		||||
    Gets a list of recent projects. The list is lazily loaded on the first call.
 | 
			
		||||
 | 
			
		||||
    Returns:
 | 
			
		||||
        list of RecentProjects
 | 
			
		||||
    """
 | 
			
		||||
    def getRecentProjects(self) -> Iterable[RecentProject]:
 | 
			
		||||
        if self.__recentProjects is None:
 | 
			
		||||
            self.__recentProjects = {}
 | 
			
		||||
            for item in self.__appDataStorage.readRecentProjects():
 | 
			
		||||
                self.__recentProjects[item['path']] = item
 | 
			
		||||
                self.__recentProjects[item.path] = item
 | 
			
		||||
 | 
			
		||||
        return self.__recentProjects.values()
 | 
			
		||||
 | 
			
		||||
    def pinRecentProject(self, entry, isPinned = True):
 | 
			
		||||
        entry['pinned'] = isPinned
 | 
			
		||||
    """
 | 
			
		||||
    Pins a recent project.
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
        entry: recent project
 | 
			
		||||
        isPinned: pinned or not
 | 
			
		||||
    """
 | 
			
		||||
    def pinRecentProject(self, entry : RecentProject, isPinned : bool = True):
 | 
			
		||||
        entry.pinned = isPinned
 | 
			
		||||
        self.__appDataStorage.writeRecentProjects(self.__recentProjects.values())
 | 
			
		||||
 | 
			
		||||
    def deleteRecentProject(self, entry):
 | 
			
		||||
        self.__recentProjects.pop(entry['path'], None)
 | 
			
		||||
    """
 | 
			
		||||
    Deletes a recent project.
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
        entry: recent project
 | 
			
		||||
    """
 | 
			
		||||
    def deleteRecentProject(self, entry : RecentProject):
 | 
			
		||||
        self.__recentProjects.pop(entry.path, None)
 | 
			
		||||
        self.__appDataStorage.writeRecentProjects(self.__recentProjects.values())
 | 
			
		||||
 | 
			
		||||
    def debug_populateRecentProjects(self):
 | 
			
		||||
        self.__recentProjects['/home/tibi/Videos/project.pro'] = {
 | 
			
		||||
            'name' : 'Debug project',
 | 
			
		||||
            'path' : '/home/tibi/Videos/project.pro',
 | 
			
		||||
            'pinned' : True,
 | 
			
		||||
            'date' : 1
 | 
			
		||||
        }
 | 
			
		||||
        self.__recentProjects['/home/tibi/Videos/project2.pro'] = {
 | 
			
		||||
            'name' : 'Debug project 2',
 | 
			
		||||
            'path' : '/home/tibi/Videos/project2.pro',
 | 
			
		||||
            'pinned' : False,
 | 
			
		||||
            'date' : 2
 | 
			
		||||
        }
 | 
			
		||||
        self.__recentProjects['/home/tibi/Videos/project3.pro'] = {
 | 
			
		||||
            'name' : 'Debug project 3',
 | 
			
		||||
            'path' : '/home/tibi/Videos/project3.pro',
 | 
			
		||||
            'pinned' : False,
 | 
			
		||||
            'date' : 3
 | 
			
		||||
        }
 | 
			
		||||
        self.__recentProjects['/home/tibi/Videos/project4.pro'] = {
 | 
			
		||||
            'name' : 'Debug project 4',
 | 
			
		||||
            'path' : '/home/tibi/Videos/project4.pro',
 | 
			
		||||
            'pinned' : False,
 | 
			
		||||
            'date' : 4
 | 
			
		||||
        }
 | 
			
		||||
    """
 | 
			
		||||
    Creates a new project at the given path, and returns the created project.
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
        path: path to project file
 | 
			
		||||
    """
 | 
			
		||||
    def newProject(self, path : str) -> Project:
 | 
			
		||||
        return Project(path)
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    Opens an existing project.
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
        path: path to project file
 | 
			
		||||
    """
 | 
			
		||||
    def openProject(self, path : str) -> Project:
 | 
			
		||||
        return Project(path)
 | 
			
		||||
 | 
			
		||||
    # def debug_populateRecentProjects(self):
 | 
			
		||||
    #     self.__recentProjects['/home/tibi/Videos/project.pro'] = {
 | 
			
		||||
    #         'name' : 'Debug project',
 | 
			
		||||
    #         'path' : '/home/tibi/Videos/project.pro',
 | 
			
		||||
    #         'pinned' : True,
 | 
			
		||||
    #         'date' : 1
 | 
			
		||||
    #     }
 | 
			
		||||
    #     self.__recentProjects['/home/tibi/Videos/project2.pro'] = {
 | 
			
		||||
    #         'name' : 'Debug project 2',
 | 
			
		||||
    #         'path' : '/home/tibi/Videos/project2.pro',
 | 
			
		||||
    #         'pinned' : False,
 | 
			
		||||
    #         'date' : 2
 | 
			
		||||
    #     }
 | 
			
		||||
    #     self.__recentProjects['/home/tibi/Videos/project3.pro'] = {
 | 
			
		||||
    #         'name' : 'Debug project 3',
 | 
			
		||||
    #         'path' : '/home/tibi/Videos/project3.pro',
 | 
			
		||||
    #         'pinned' : False,
 | 
			
		||||
    #         'date' : 3
 | 
			
		||||
    #     }
 | 
			
		||||
    #     self.__recentProjects['/home/tibi/Videos/project4.pro'] = {
 | 
			
		||||
    #         'name' : 'Debug project 4',
 | 
			
		||||
    #         'path' : '/home/tibi/Videos/project4.pro',
 | 
			
		||||
    #         'pinned' : False,
 | 
			
		||||
    #         'date' : 4
 | 
			
		||||
    #     }
 | 
			
		||||
@@ -0,0 +1,2 @@
 | 
			
		||||
from .recent_project import RecentProject
 | 
			
		||||
from .project import Project
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
class Project(object):
 | 
			
		||||
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        self.root_dir = None
 | 
			
		||||
    def __init__(self, path):
 | 
			
		||||
        self.root_dir = path
 | 
			
		||||
        
 | 
			
		||||
    def get_items(self):
 | 
			
		||||
        pass
 | 
			
		||||
							
								
								
									
										60
									
								
								model/recent_project.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								model/recent_project.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,60 @@
 | 
			
		||||
import time
 | 
			
		||||
from typing import List
 | 
			
		||||
 | 
			
		||||
class RecentProject(object):
 | 
			
		||||
 | 
			
		||||
    DICT_FIELDS = [ 'path', 'name', 'dateAccessed', 'pinned' ]
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    Creates new instance of RecentProject.
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
        name: name of the project
 | 
			
		||||
        path: path to the project
 | 
			
		||||
        dateAccessed: date (unix time) when project was last accessed
 | 
			
		||||
        pinned: the project is pinned by the user
 | 
			
		||||
 | 
			
		||||
    Remarks:
 | 
			
		||||
        If dateAccessed = None, it will be set to the current date and time.
 | 
			
		||||
    """
 | 
			
		||||
    def __init__(self, name: str, path: str, dateAccessed : int = None, pinned : bool = False):
 | 
			
		||||
        self.name = name
 | 
			
		||||
        self.path = path
 | 
			
		||||
        self.dateAccessed = dateAccessed
 | 
			
		||||
        self.pinned = pinned
 | 
			
		||||
 | 
			
		||||
        if (self.dateAccessed is None):
 | 
			
		||||
            self.dateAccessed = int(time.time())
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    Creates new instance of RecentProject from a dictionary.
 | 
			
		||||
    If the dateAccessed and pinned fields are strings, they are parsed.
 | 
			
		||||
 | 
			
		||||
    Raises:
 | 
			
		||||
        ValueError if date cannot be parsed.
 | 
			
		||||
    """
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def fromDictionary(data : dict) -> 'RecentProject':
 | 
			
		||||
        name = data['name']
 | 
			
		||||
        path = data['path']
 | 
			
		||||
        dateAccessed = data['dateAccessed']
 | 
			
		||||
        pinned = data['pinned']
 | 
			
		||||
 | 
			
		||||
        if isinstance(dateAccessed, str):
 | 
			
		||||
            dateAccessed = int(dateAccessed)
 | 
			
		||||
 | 
			
		||||
        if isinstance(pinned, str):
 | 
			
		||||
            pinned = pinned.lower() in [ 'yes', 'y', 'true', '1', 'on' ]
 | 
			
		||||
 | 
			
		||||
        return RecentProject(name, path, dateAccessed, pinned)
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    Serialize to dictionary.
 | 
			
		||||
    """
 | 
			
		||||
    def toDictionary(self) -> dict:
 | 
			
		||||
        return {
 | 
			
		||||
            "name" : self.name,
 | 
			
		||||
            "path" : self.path,
 | 
			
		||||
            "dateAccessed" : self.dateAccessed,
 | 
			
		||||
            "pinned" : self.pinned
 | 
			
		||||
        }
 | 
			
		||||
@@ -3,4 +3,6 @@ APP_VERSION = "1.0"
 | 
			
		||||
APP_AUTHOR = "Tiberiu Chibici"
 | 
			
		||||
APP_AUTHOR_SHORT = "TibiCh"
 | 
			
		||||
 | 
			
		||||
PROJECT_EXTENSION = "emproj"
 | 
			
		||||
 | 
			
		||||
DEBUG = 1
 | 
			
		||||
							
								
								
									
										17460
									
								
								resources_rc.py
									
									
									
									
									
								
							
							
						
						
									
										17460
									
								
								resources_rc.py
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1
									
								
								storage/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								storage/__init__.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
from .appdata_storage import AppDataStorage
 | 
			
		||||
@@ -2,14 +2,15 @@ import appdirs
 | 
			
		||||
import os
 | 
			
		||||
from configparser import ConfigParser
 | 
			
		||||
import csv
 | 
			
		||||
from typing import Iterable
 | 
			
		||||
 | 
			
		||||
from properties import config
 | 
			
		||||
from model import RecentProject
 | 
			
		||||
 | 
			
		||||
class AppDataStorage(object):
 | 
			
		||||
 | 
			
		||||
    SETTINGS_FILE = "config.ini"
 | 
			
		||||
    RECENT_PROJECTS_FILE = "recent.cfg"
 | 
			
		||||
    RECENT_PROJECTS_FIELDS = ["path", "name", "date", "pinned"]
 | 
			
		||||
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        self.__appDataPath = appdirs.user_data_dir(config.APP_NAME, config.APP_AUTHOR_SHORT, config.APP_VERSION)
 | 
			
		||||
@@ -30,20 +31,33 @@ class AppDataStorage(object):
 | 
			
		||||
    def writeSettings(self, settings):
 | 
			
		||||
        pass # todo: finish this
 | 
			
		||||
 | 
			
		||||
    def __parseRow(self, row):
 | 
			
		||||
        row['date'] = int(row['date'])
 | 
			
		||||
        row['pinned'] = row['pinned'].lower() in ['true', 'yes', '1', 'on']
 | 
			
		||||
        return row
 | 
			
		||||
    """
 | 
			
		||||
    Reads recent projects list.
 | 
			
		||||
 | 
			
		||||
    def readRecentProjects(self):
 | 
			
		||||
    Returns:
 | 
			
		||||
        list of recent projects
 | 
			
		||||
    """
 | 
			
		||||
    def readRecentProjects(self) -> Iterable[RecentProject]:
 | 
			
		||||
        if (os.path.exists(self.__recentProjectsPath)):
 | 
			
		||||
            with open(self.__recentProjectsPath, 'r') as recentProjectsFile:
 | 
			
		||||
                csvreader = csv.DictReader(recentProjectsFile, fieldnames=AppDataStorage.RECENT_PROJECTS_FIELDS)
 | 
			
		||||
                csvreader = csv.DictReader(recentProjectsFile, fieldnames=RecentProject.DICT_FIELDS)
 | 
			
		||||
                for row in csvreader:
 | 
			
		||||
                    yield self.__parseRow(row)
 | 
			
		||||
                    try:
 | 
			
		||||
                        yield RecentProject.fromDictionary(row)
 | 
			
		||||
                    except ValueError:
 | 
			
		||||
                        print("Recent projects parse error - invalid date.", row)
 | 
			
		||||
                    except KeyError:
 | 
			
		||||
                        print("Recent projects parse error - fields not valid.", row)
 | 
			
		||||
 | 
			
		||||
    def writeRecentProjects(self, items):
 | 
			
		||||
    """
 | 
			
		||||
    Writes a list of recent projects.
 | 
			
		||||
    
 | 
			
		||||
    Args:
 | 
			
		||||
        items: list of RecentProjects
 | 
			
		||||
    """
 | 
			
		||||
    def writeRecentProjects(self, items : Iterable[RecentProject]) -> None:
 | 
			
		||||
        self.__createPath(self.__recentProjectsPath)
 | 
			
		||||
        with open(self.__recentProjectsPath, 'w') as recentProjectsFile:
 | 
			
		||||
            csvwriter = csv.DictWriter(recentProjectsFile, AppDataStorage.RECENT_PROJECTS_FIELDS)
 | 
			
		||||
            csvwriter.writerows(items)
 | 
			
		||||
            csvwriter = csv.DictWriter(recentProjectsFile, RecentProject.DICT_FIELDS)
 | 
			
		||||
            for item in items:
 | 
			
		||||
                csvwriter.writerow(item.toDictionary())
 | 
			
		||||
@@ -1,15 +1,20 @@
 | 
			
		||||
from PyQt5.QtWidgets import QMainWindow, QVBoxLayout, QWidget
 | 
			
		||||
import traceback
 | 
			
		||||
from PyQt5.QtWidgets import QMainWindow, QVBoxLayout, QWidget, QApplication, QMessageBox
 | 
			
		||||
from PyQt5.QtCore import QTimer
 | 
			
		||||
 | 
			
		||||
from model import Project
 | 
			
		||||
from business import ProjectManager
 | 
			
		||||
from ui.project.project_panel import ProjectPanel
 | 
			
		||||
from ui.project.new_project_dialog import NewProjectDialog
 | 
			
		||||
from ui.welcome.welcome_dialog import WelcomeDialog
 | 
			
		||||
 | 
			
		||||
class MainWindow(QMainWindow):
 | 
			
		||||
 | 
			
		||||
    def __init__(self, projectManager):
 | 
			
		||||
    def __init__(self, projectManager : ProjectManager):
 | 
			
		||||
        super().__init__()
 | 
			
		||||
        self.__projectManager = projectManager
 | 
			
		||||
        self.setupUi()
 | 
			
		||||
        self.initializeApp()
 | 
			
		||||
        QTimer.singleShot(0, self.showWelcomeDialog)
 | 
			
		||||
 | 
			
		||||
    def setupUi(self):
 | 
			
		||||
        self.projectPanel = ProjectPanel()
 | 
			
		||||
@@ -22,10 +27,28 @@ class MainWindow(QMainWindow):
 | 
			
		||||
 | 
			
		||||
        self.setCentralWidget(cwidget)
 | 
			
		||||
 | 
			
		||||
    def initializeApp(self):
 | 
			
		||||
 | 
			
		||||
    def showWelcomeDialog(self):
 | 
			
		||||
        # Show welcome dialog
 | 
			
		||||
        welcome = WelcomeDialog(self.__projectManager)
 | 
			
		||||
        res = welcome.exec()
 | 
			
		||||
        welcome = WelcomeDialog(self.__projectManager, self)
 | 
			
		||||
        if welcome.exec() > 0:
 | 
			
		||||
            if welcome.resultAction == WelcomeDialog.NEW_PROJECT:
 | 
			
		||||
                self.newProject()
 | 
			
		||||
            elif welcome.resultAction == WelcomeDialog.OPEN_PROJECT:
 | 
			
		||||
                self.openProject(welcome.projectToOpen)
 | 
			
		||||
 | 
			
		||||
        print("Dialog result:", res)
 | 
			
		||||
    def newProject(self):
 | 
			
		||||
        dialog = NewProjectDialog(self.__projectManager, self)
 | 
			
		||||
        if dialog.exec() > 0:
 | 
			
		||||
            self.loadProject(dialog.project)
 | 
			
		||||
 | 
			
		||||
    def openProject(self, projectPath : str = None):
 | 
			
		||||
        try:
 | 
			
		||||
            project = self.__projectManager.openProject(projectPath)
 | 
			
		||||
        except Exception as ex:
 | 
			
		||||
            print("Failed to open project: ", traceback.format_exc())
 | 
			
		||||
            QMessageBox.critical(self,
 | 
			
		||||
                self.tr('An error occurred'),
 | 
			
		||||
                self.tr('The project could not be open.'))
 | 
			
		||||
 | 
			
		||||
    def loadProject(self, project : Project):
 | 
			
		||||
        pass
 | 
			
		||||
							
								
								
									
										61
									
								
								ui/project/new_project_dialog.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								ui/project/new_project_dialog.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,61 @@
 | 
			
		||||
import traceback
 | 
			
		||||
from PyQt5.QtWidgets import QDialog, QWidget, QDialogButtonBox, QFileDialog, QPushButton, QMessageBox
 | 
			
		||||
 | 
			
		||||
from model import Project
 | 
			
		||||
from business import ProjectManager
 | 
			
		||||
from properties.config import PROJECT_EXTENSION
 | 
			
		||||
from ui.project.new_project_dialog_ui import Ui_NewProjectDialog
 | 
			
		||||
 | 
			
		||||
class NewProjectDialog(QDialog):
 | 
			
		||||
 | 
			
		||||
    def __init__(self, projectManager : ProjectManager, parent : QWidget = None):
 | 
			
		||||
        super().__init__(parent)
 | 
			
		||||
        self.__projectManager = projectManager
 | 
			
		||||
        self.project : Project = None
 | 
			
		||||
        self.setupUi()
 | 
			
		||||
        self.setupActions()
 | 
			
		||||
        self.validate()
 | 
			
		||||
 | 
			
		||||
    def setupUi(self):
 | 
			
		||||
        self.ui = Ui_NewProjectDialog()
 | 
			
		||||
        self.ui.setupUi(self)
 | 
			
		||||
        self.__buttonOk : QPushButton = self.ui.buttonBox.button(QDialogButtonBox.Ok)
 | 
			
		||||
 | 
			
		||||
    def setupActions(self):
 | 
			
		||||
        self.ui.buttonBrowse.pressed.connect(self.browsePressed)
 | 
			
		||||
        self.ui.textProjectPath.textChanged.connect(self.projectPathChanged)
 | 
			
		||||
        self.ui.buttonBox.accepted.connect(self.okPressed)
 | 
			
		||||
 | 
			
		||||
    def validate(self):
 | 
			
		||||
        valid = True
 | 
			
		||||
        if not self.ui.textProjectPath.text():
 | 
			
		||||
            valid = False
 | 
			
		||||
        self.__buttonOk.setEnabled(valid)
 | 
			
		||||
 | 
			
		||||
    def browsePressed(self):
 | 
			
		||||
        path = QFileDialog.getSaveFileName(
 | 
			
		||||
            self, 
 | 
			
		||||
            self.tr('New project'), 
 | 
			
		||||
            '', 
 | 
			
		||||
            self.tr(f'Project files (*.{PROJECT_EXTENSION});;All files (*.*)'))
 | 
			
		||||
 | 
			
		||||
        if path[0]:
 | 
			
		||||
            self.ui.textProjectPath.setText(path[0])
 | 
			
		||||
 | 
			
		||||
    def projectPathChanged(self):
 | 
			
		||||
        self.validate()
 | 
			
		||||
 | 
			
		||||
    def okPressed(self):
 | 
			
		||||
        try:
 | 
			
		||||
            path = self.ui.textProjectPath.text()
 | 
			
		||||
            self.project = self.__projectManager.newProject(path)
 | 
			
		||||
            self.accept()
 | 
			
		||||
 | 
			
		||||
        except Exception as ex:
 | 
			
		||||
            print("Failed to create project: ", traceback.format_exc())
 | 
			
		||||
            QMessageBox.critical(self,
 | 
			
		||||
                self.tr('An error occurred'),
 | 
			
		||||
                self.tr('The project could not be created in the given location.'))
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
         
 | 
			
		||||
							
								
								
									
										239
									
								
								ui/project/new_project_dialog.ui
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										239
									
								
								ui/project/new_project_dialog.ui
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,239 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<ui version="4.0">
 | 
			
		||||
 <class>NewProjectDialog</class>
 | 
			
		||||
 <widget class="QDialog" name="NewProjectDialog">
 | 
			
		||||
  <property name="geometry">
 | 
			
		||||
   <rect>
 | 
			
		||||
    <x>0</x>
 | 
			
		||||
    <y>0</y>
 | 
			
		||||
    <width>486</width>
 | 
			
		||||
    <height>299</height>
 | 
			
		||||
   </rect>
 | 
			
		||||
  </property>
 | 
			
		||||
  <property name="windowTitle">
 | 
			
		||||
   <string>New project</string>
 | 
			
		||||
  </property>
 | 
			
		||||
  <layout class="QVBoxLayout" name="verticalLayout">
 | 
			
		||||
   <item>
 | 
			
		||||
    <widget class="QWidget" name="_panelProjectPath" native="true">
 | 
			
		||||
     <layout class="QHBoxLayout" name="horizontalLayout_3">
 | 
			
		||||
      <item>
 | 
			
		||||
       <widget class="QLabel" name="labelProjectPath">
 | 
			
		||||
        <property name="text">
 | 
			
		||||
         <string>Project path:</string>
 | 
			
		||||
        </property>
 | 
			
		||||
       </widget>
 | 
			
		||||
      </item>
 | 
			
		||||
      <item>
 | 
			
		||||
       <widget class="QLineEdit" name="textProjectPath">
 | 
			
		||||
        <property name="sizePolicy">
 | 
			
		||||
         <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
 | 
			
		||||
          <horstretch>0</horstretch>
 | 
			
		||||
          <verstretch>0</verstretch>
 | 
			
		||||
         </sizepolicy>
 | 
			
		||||
        </property>
 | 
			
		||||
       </widget>
 | 
			
		||||
      </item>
 | 
			
		||||
      <item>
 | 
			
		||||
       <widget class="QPushButton" name="buttonBrowse">
 | 
			
		||||
        <property name="text">
 | 
			
		||||
         <string>&Browse...</string>
 | 
			
		||||
        </property>
 | 
			
		||||
       </widget>
 | 
			
		||||
      </item>
 | 
			
		||||
     </layout>
 | 
			
		||||
    </widget>
 | 
			
		||||
   </item>
 | 
			
		||||
   <item>
 | 
			
		||||
    <widget class="QGroupBox" name="groupVideoSettings">
 | 
			
		||||
     <property name="sizePolicy">
 | 
			
		||||
      <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
 | 
			
		||||
       <horstretch>0</horstretch>
 | 
			
		||||
       <verstretch>2</verstretch>
 | 
			
		||||
      </sizepolicy>
 | 
			
		||||
     </property>
 | 
			
		||||
     <property name="title">
 | 
			
		||||
      <string>Video settings</string>
 | 
			
		||||
     </property>
 | 
			
		||||
     <layout class="QFormLayout">
 | 
			
		||||
      <property name="leftMargin">
 | 
			
		||||
       <number>20</number>
 | 
			
		||||
      </property>
 | 
			
		||||
      <property name="rightMargin">
 | 
			
		||||
       <number>20</number>
 | 
			
		||||
      </property>
 | 
			
		||||
      <item row="0" column="0">
 | 
			
		||||
       <widget class="QLabel" name="labelColorDepth">
 | 
			
		||||
        <property name="minimumSize">
 | 
			
		||||
         <size>
 | 
			
		||||
          <width>110</width>
 | 
			
		||||
          <height>0</height>
 | 
			
		||||
         </size>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="text">
 | 
			
		||||
         <string>Color depth:</string>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="alignment">
 | 
			
		||||
         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
 | 
			
		||||
        </property>
 | 
			
		||||
       </widget>
 | 
			
		||||
      </item>
 | 
			
		||||
      <item row="0" column="1">
 | 
			
		||||
       <widget class="QComboBox" name="comboColorDepth">
 | 
			
		||||
        <property name="minimumSize">
 | 
			
		||||
         <size>
 | 
			
		||||
          <width>150</width>
 | 
			
		||||
          <height>0</height>
 | 
			
		||||
         </size>
 | 
			
		||||
        </property>
 | 
			
		||||
        <item>
 | 
			
		||||
         <property name="text">
 | 
			
		||||
          <string>8 bits/channel</string>
 | 
			
		||||
         </property>
 | 
			
		||||
        </item>
 | 
			
		||||
        <item>
 | 
			
		||||
         <property name="text">
 | 
			
		||||
          <string>16 bits/channel</string>
 | 
			
		||||
         </property>
 | 
			
		||||
        </item>
 | 
			
		||||
        <item>
 | 
			
		||||
         <property name="text">
 | 
			
		||||
          <string>32 bits/channel (float)</string>
 | 
			
		||||
         </property>
 | 
			
		||||
        </item>
 | 
			
		||||
       </widget>
 | 
			
		||||
      </item>
 | 
			
		||||
      <item row="1" column="0">
 | 
			
		||||
       <widget class="QLabel" name="labelColorSpace">
 | 
			
		||||
        <property name="minimumSize">
 | 
			
		||||
         <size>
 | 
			
		||||
          <width>110</width>
 | 
			
		||||
          <height>0</height>
 | 
			
		||||
         </size>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="text">
 | 
			
		||||
         <string>Color space:</string>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="alignment">
 | 
			
		||||
         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
 | 
			
		||||
        </property>
 | 
			
		||||
       </widget>
 | 
			
		||||
      </item>
 | 
			
		||||
      <item row="1" column="1">
 | 
			
		||||
       <widget class="QComboBox" name="comboColorSpace">
 | 
			
		||||
        <item>
 | 
			
		||||
         <property name="text">
 | 
			
		||||
          <string>sRGB</string>
 | 
			
		||||
         </property>
 | 
			
		||||
        </item>
 | 
			
		||||
       </widget>
 | 
			
		||||
      </item>
 | 
			
		||||
     </layout>
 | 
			
		||||
    </widget>
 | 
			
		||||
   </item>
 | 
			
		||||
   <item>
 | 
			
		||||
    <widget class="QGroupBox" name="groupAudioSettings">
 | 
			
		||||
     <property name="sizePolicy">
 | 
			
		||||
      <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
 | 
			
		||||
       <horstretch>0</horstretch>
 | 
			
		||||
       <verstretch>1</verstretch>
 | 
			
		||||
      </sizepolicy>
 | 
			
		||||
     </property>
 | 
			
		||||
     <property name="title">
 | 
			
		||||
      <string>Audio settings</string>
 | 
			
		||||
     </property>
 | 
			
		||||
     <layout class="QFormLayout" name="formLayout_2">
 | 
			
		||||
      <property name="leftMargin">
 | 
			
		||||
       <number>20</number>
 | 
			
		||||
      </property>
 | 
			
		||||
      <property name="rightMargin">
 | 
			
		||||
       <number>20</number>
 | 
			
		||||
      </property>
 | 
			
		||||
      <item row="0" column="0">
 | 
			
		||||
       <widget class="QLabel" name="labelSampleRate">
 | 
			
		||||
        <property name="minimumSize">
 | 
			
		||||
         <size>
 | 
			
		||||
          <width>110</width>
 | 
			
		||||
          <height>0</height>
 | 
			
		||||
         </size>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="text">
 | 
			
		||||
         <string>Sample rate:</string>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="alignment">
 | 
			
		||||
         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
 | 
			
		||||
        </property>
 | 
			
		||||
       </widget>
 | 
			
		||||
      </item>
 | 
			
		||||
      <item row="0" column="1">
 | 
			
		||||
       <widget class="QComboBox" name="comboSampleRate">
 | 
			
		||||
        <property name="currentIndex">
 | 
			
		||||
         <number>2</number>
 | 
			
		||||
        </property>
 | 
			
		||||
        <item>
 | 
			
		||||
         <property name="text">
 | 
			
		||||
          <string>32 kHz</string>
 | 
			
		||||
         </property>
 | 
			
		||||
        </item>
 | 
			
		||||
        <item>
 | 
			
		||||
         <property name="text">
 | 
			
		||||
          <string>44.1 kHz</string>
 | 
			
		||||
         </property>
 | 
			
		||||
        </item>
 | 
			
		||||
        <item>
 | 
			
		||||
         <property name="text">
 | 
			
		||||
          <string>48 kHz</string>
 | 
			
		||||
         </property>
 | 
			
		||||
        </item>
 | 
			
		||||
        <item>
 | 
			
		||||
         <property name="text">
 | 
			
		||||
          <string>88.2 kHz</string>
 | 
			
		||||
         </property>
 | 
			
		||||
        </item>
 | 
			
		||||
        <item>
 | 
			
		||||
         <property name="text">
 | 
			
		||||
          <string>96 kHz</string>
 | 
			
		||||
         </property>
 | 
			
		||||
        </item>
 | 
			
		||||
        <item>
 | 
			
		||||
         <property name="text">
 | 
			
		||||
          <string>192 kHz</string>
 | 
			
		||||
         </property>
 | 
			
		||||
        </item>
 | 
			
		||||
       </widget>
 | 
			
		||||
      </item>
 | 
			
		||||
     </layout>
 | 
			
		||||
    </widget>
 | 
			
		||||
   </item>
 | 
			
		||||
   <item>
 | 
			
		||||
    <widget class="QDialogButtonBox" name="buttonBox">
 | 
			
		||||
     <property name="orientation">
 | 
			
		||||
      <enum>Qt::Horizontal</enum>
 | 
			
		||||
     </property>
 | 
			
		||||
     <property name="standardButtons">
 | 
			
		||||
      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
 | 
			
		||||
     </property>
 | 
			
		||||
    </widget>
 | 
			
		||||
   </item>
 | 
			
		||||
  </layout>
 | 
			
		||||
 </widget>
 | 
			
		||||
 <resources/>
 | 
			
		||||
 <connections>
 | 
			
		||||
  <connection>
 | 
			
		||||
   <sender>buttonBox</sender>
 | 
			
		||||
   <signal>rejected()</signal>
 | 
			
		||||
   <receiver>NewProjectDialog</receiver>
 | 
			
		||||
   <slot>reject()</slot>
 | 
			
		||||
   <hints>
 | 
			
		||||
    <hint type="sourcelabel">
 | 
			
		||||
     <x>316</x>
 | 
			
		||||
     <y>260</y>
 | 
			
		||||
    </hint>
 | 
			
		||||
    <hint type="destinationlabel">
 | 
			
		||||
     <x>286</x>
 | 
			
		||||
     <y>274</y>
 | 
			
		||||
    </hint>
 | 
			
		||||
   </hints>
 | 
			
		||||
  </connection>
 | 
			
		||||
 </connections>
 | 
			
		||||
</ui>
 | 
			
		||||
							
								
								
									
										124
									
								
								ui/project/new_project_dialog_ui.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										124
									
								
								ui/project/new_project_dialog_ui.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,124 @@
 | 
			
		||||
# -*- coding: utf-8 -*-
 | 
			
		||||
 | 
			
		||||
# Form implementation generated from reading ui file 'ui/project/new_project_dialog.ui'
 | 
			
		||||
#
 | 
			
		||||
# Created by: PyQt5 UI code generator 5.10.1
 | 
			
		||||
#
 | 
			
		||||
# WARNING! All changes made in this file will be lost!
 | 
			
		||||
 | 
			
		||||
from PyQt5 import QtCore, QtGui, QtWidgets
 | 
			
		||||
 | 
			
		||||
class Ui_NewProjectDialog(object):
 | 
			
		||||
    def setupUi(self, NewProjectDialog):
 | 
			
		||||
        NewProjectDialog.setObjectName("NewProjectDialog")
 | 
			
		||||
        NewProjectDialog.resize(486, 299)
 | 
			
		||||
        self.verticalLayout = QtWidgets.QVBoxLayout(NewProjectDialog)
 | 
			
		||||
        self.verticalLayout.setObjectName("verticalLayout")
 | 
			
		||||
        self._panelProjectPath = QtWidgets.QWidget(NewProjectDialog)
 | 
			
		||||
        self._panelProjectPath.setObjectName("_panelProjectPath")
 | 
			
		||||
        self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self._panelProjectPath)
 | 
			
		||||
        self.horizontalLayout_3.setObjectName("horizontalLayout_3")
 | 
			
		||||
        self.labelProjectPath = QtWidgets.QLabel(self._panelProjectPath)
 | 
			
		||||
        self.labelProjectPath.setObjectName("labelProjectPath")
 | 
			
		||||
        self.horizontalLayout_3.addWidget(self.labelProjectPath)
 | 
			
		||||
        self.textProjectPath = QtWidgets.QLineEdit(self._panelProjectPath)
 | 
			
		||||
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Fixed)
 | 
			
		||||
        sizePolicy.setHorizontalStretch(0)
 | 
			
		||||
        sizePolicy.setVerticalStretch(0)
 | 
			
		||||
        sizePolicy.setHeightForWidth(self.textProjectPath.sizePolicy().hasHeightForWidth())
 | 
			
		||||
        self.textProjectPath.setSizePolicy(sizePolicy)
 | 
			
		||||
        self.textProjectPath.setObjectName("textProjectPath")
 | 
			
		||||
        self.horizontalLayout_3.addWidget(self.textProjectPath)
 | 
			
		||||
        self.buttonBrowse = QtWidgets.QPushButton(self._panelProjectPath)
 | 
			
		||||
        self.buttonBrowse.setObjectName("buttonBrowse")
 | 
			
		||||
        self.horizontalLayout_3.addWidget(self.buttonBrowse)
 | 
			
		||||
        self.verticalLayout.addWidget(self._panelProjectPath)
 | 
			
		||||
        self.groupVideoSettings = QtWidgets.QGroupBox(NewProjectDialog)
 | 
			
		||||
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred)
 | 
			
		||||
        sizePolicy.setHorizontalStretch(0)
 | 
			
		||||
        sizePolicy.setVerticalStretch(2)
 | 
			
		||||
        sizePolicy.setHeightForWidth(self.groupVideoSettings.sizePolicy().hasHeightForWidth())
 | 
			
		||||
        self.groupVideoSettings.setSizePolicy(sizePolicy)
 | 
			
		||||
        self.groupVideoSettings.setObjectName("groupVideoSettings")
 | 
			
		||||
        self.formlayout = QtWidgets.QFormLayout(self.groupVideoSettings)
 | 
			
		||||
        self.formlayout.setContentsMargins(20, -1, 20, -1)
 | 
			
		||||
        self.formlayout.setObjectName("formlayout")
 | 
			
		||||
        self.labelColorDepth = QtWidgets.QLabel(self.groupVideoSettings)
 | 
			
		||||
        self.labelColorDepth.setMinimumSize(QtCore.QSize(110, 0))
 | 
			
		||||
        self.labelColorDepth.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
 | 
			
		||||
        self.labelColorDepth.setObjectName("labelColorDepth")
 | 
			
		||||
        self.formlayout.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.labelColorDepth)
 | 
			
		||||
        self.comboColorDepth = QtWidgets.QComboBox(self.groupVideoSettings)
 | 
			
		||||
        self.comboColorDepth.setMinimumSize(QtCore.QSize(150, 0))
 | 
			
		||||
        self.comboColorDepth.setObjectName("comboColorDepth")
 | 
			
		||||
        self.comboColorDepth.addItem("")
 | 
			
		||||
        self.comboColorDepth.addItem("")
 | 
			
		||||
        self.comboColorDepth.addItem("")
 | 
			
		||||
        self.formlayout.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.comboColorDepth)
 | 
			
		||||
        self.labelColorSpace = QtWidgets.QLabel(self.groupVideoSettings)
 | 
			
		||||
        self.labelColorSpace.setMinimumSize(QtCore.QSize(110, 0))
 | 
			
		||||
        self.labelColorSpace.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
 | 
			
		||||
        self.labelColorSpace.setObjectName("labelColorSpace")
 | 
			
		||||
        self.formlayout.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.labelColorSpace)
 | 
			
		||||
        self.comboColorSpace = QtWidgets.QComboBox(self.groupVideoSettings)
 | 
			
		||||
        self.comboColorSpace.setObjectName("comboColorSpace")
 | 
			
		||||
        self.comboColorSpace.addItem("")
 | 
			
		||||
        self.formlayout.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.comboColorSpace)
 | 
			
		||||
        self.verticalLayout.addWidget(self.groupVideoSettings)
 | 
			
		||||
        self.groupAudioSettings = QtWidgets.QGroupBox(NewProjectDialog)
 | 
			
		||||
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
 | 
			
		||||
        sizePolicy.setHorizontalStretch(0)
 | 
			
		||||
        sizePolicy.setVerticalStretch(1)
 | 
			
		||||
        sizePolicy.setHeightForWidth(self.groupAudioSettings.sizePolicy().hasHeightForWidth())
 | 
			
		||||
        self.groupAudioSettings.setSizePolicy(sizePolicy)
 | 
			
		||||
        self.groupAudioSettings.setObjectName("groupAudioSettings")
 | 
			
		||||
        self.formLayout_2 = QtWidgets.QFormLayout(self.groupAudioSettings)
 | 
			
		||||
        self.formLayout_2.setContentsMargins(20, -1, 20, -1)
 | 
			
		||||
        self.formLayout_2.setObjectName("formLayout_2")
 | 
			
		||||
        self.labelSampleRate = QtWidgets.QLabel(self.groupAudioSettings)
 | 
			
		||||
        self.labelSampleRate.setMinimumSize(QtCore.QSize(110, 0))
 | 
			
		||||
        self.labelSampleRate.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
 | 
			
		||||
        self.labelSampleRate.setObjectName("labelSampleRate")
 | 
			
		||||
        self.formLayout_2.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.labelSampleRate)
 | 
			
		||||
        self.comboSampleRate = QtWidgets.QComboBox(self.groupAudioSettings)
 | 
			
		||||
        self.comboSampleRate.setObjectName("comboSampleRate")
 | 
			
		||||
        self.comboSampleRate.addItem("")
 | 
			
		||||
        self.comboSampleRate.addItem("")
 | 
			
		||||
        self.comboSampleRate.addItem("")
 | 
			
		||||
        self.comboSampleRate.addItem("")
 | 
			
		||||
        self.comboSampleRate.addItem("")
 | 
			
		||||
        self.comboSampleRate.addItem("")
 | 
			
		||||
        self.formLayout_2.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.comboSampleRate)
 | 
			
		||||
        self.verticalLayout.addWidget(self.groupAudioSettings)
 | 
			
		||||
        self.buttonBox = QtWidgets.QDialogButtonBox(NewProjectDialog)
 | 
			
		||||
        self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
 | 
			
		||||
        self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
 | 
			
		||||
        self.buttonBox.setObjectName("buttonBox")
 | 
			
		||||
        self.verticalLayout.addWidget(self.buttonBox)
 | 
			
		||||
 | 
			
		||||
        self.retranslateUi(NewProjectDialog)
 | 
			
		||||
        self.comboSampleRate.setCurrentIndex(2)
 | 
			
		||||
        self.buttonBox.rejected.connect(NewProjectDialog.reject)
 | 
			
		||||
        QtCore.QMetaObject.connectSlotsByName(NewProjectDialog)
 | 
			
		||||
 | 
			
		||||
    def retranslateUi(self, NewProjectDialog):
 | 
			
		||||
        _translate = QtCore.QCoreApplication.translate
 | 
			
		||||
        NewProjectDialog.setWindowTitle(_translate("NewProjectDialog", "New project"))
 | 
			
		||||
        self.labelProjectPath.setText(_translate("NewProjectDialog", "Project path:"))
 | 
			
		||||
        self.buttonBrowse.setText(_translate("NewProjectDialog", "&Browse..."))
 | 
			
		||||
        self.groupVideoSettings.setTitle(_translate("NewProjectDialog", "Video settings"))
 | 
			
		||||
        self.labelColorDepth.setText(_translate("NewProjectDialog", "Color depth:"))
 | 
			
		||||
        self.comboColorDepth.setItemText(0, _translate("NewProjectDialog", "8 bits/channel"))
 | 
			
		||||
        self.comboColorDepth.setItemText(1, _translate("NewProjectDialog", "16 bits/channel"))
 | 
			
		||||
        self.comboColorDepth.setItemText(2, _translate("NewProjectDialog", "32 bits/channel (float)"))
 | 
			
		||||
        self.labelColorSpace.setText(_translate("NewProjectDialog", "Color space:"))
 | 
			
		||||
        self.comboColorSpace.setItemText(0, _translate("NewProjectDialog", "sRGB"))
 | 
			
		||||
        self.groupAudioSettings.setTitle(_translate("NewProjectDialog", "Audio settings"))
 | 
			
		||||
        self.labelSampleRate.setText(_translate("NewProjectDialog", "Sample rate:"))
 | 
			
		||||
        self.comboSampleRate.setItemText(0, _translate("NewProjectDialog", "32 kHz"))
 | 
			
		||||
        self.comboSampleRate.setItemText(1, _translate("NewProjectDialog", "44.1 kHz"))
 | 
			
		||||
        self.comboSampleRate.setItemText(2, _translate("NewProjectDialog", "48 kHz"))
 | 
			
		||||
        self.comboSampleRate.setItemText(3, _translate("NewProjectDialog", "88.2 kHz"))
 | 
			
		||||
        self.comboSampleRate.setItemText(4, _translate("NewProjectDialog", "96 kHz"))
 | 
			
		||||
        self.comboSampleRate.setItemText(5, _translate("NewProjectDialog", "192 kHz"))
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										0
									
								
								ui/welcome/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								ui/welcome/__init__.py
									
									
									
									
									
										Normal file
									
								
							@@ -1,72 +0,0 @@
 | 
			
		||||
from PyQt5.QtWidgets import QWidget, QHBoxLayout, QLabel, QToolButton, QLayout
 | 
			
		||||
from PyQt5.QtCore import pyqtSignal
 | 
			
		||||
from PyQt5.QtGui import QFont
 | 
			
		||||
 | 
			
		||||
class RecentProjectWidget(QWidget):
 | 
			
		||||
    
 | 
			
		||||
    deleted = pyqtSignal()
 | 
			
		||||
    pinned = pyqtSignal(bool)
 | 
			
		||||
 | 
			
		||||
    def __init__(self, recentProject):
 | 
			
		||||
        super().__init__()
 | 
			
		||||
        self.project = recentProject
 | 
			
		||||
        self.__selected = False
 | 
			
		||||
        self.setupUi()
 | 
			
		||||
        self.setupActions()
 | 
			
		||||
        self.__setProject(recentProject)
 | 
			
		||||
        self.setSelected(False)
 | 
			
		||||
 | 
			
		||||
    def setupUi(self):
 | 
			
		||||
        layout = QHBoxLayout()
 | 
			
		||||
 | 
			
		||||
        # label
 | 
			
		||||
        self.__text = QLabel()
 | 
			
		||||
        layout.addWidget(self.__text)
 | 
			
		||||
 | 
			
		||||
        # space
 | 
			
		||||
        layout.addStretch()
 | 
			
		||||
 | 
			
		||||
        # pin button
 | 
			
		||||
        self.__pin_button = QToolButton()
 | 
			
		||||
        self.__pin_button.setFont(QFont("Font Awesome 5 Free"))
 | 
			
		||||
        self.__pin_button.setText("\uf08d")
 | 
			
		||||
        self.__pin_button.setCheckable(True)
 | 
			
		||||
        layout.addWidget(self.__pin_button)
 | 
			
		||||
 | 
			
		||||
        # delete button
 | 
			
		||||
        self.__del_button = QToolButton()
 | 
			
		||||
        self.__del_button.setFont(QFont("Font Awesome 5 Free"))
 | 
			
		||||
        self.__del_button.setText("\uf2ed")
 | 
			
		||||
        layout.addWidget(self.__del_button)
 | 
			
		||||
 | 
			
		||||
        # pin indicator
 | 
			
		||||
        self.__pin_indicator = QLabel()
 | 
			
		||||
        self.__pin_indicator.setFont(QFont("Font Awesome 5 Free"))
 | 
			
		||||
        self.__pin_indicator.setText("\uf08d")
 | 
			
		||||
        layout.addWidget(self.__pin_indicator)
 | 
			
		||||
 | 
			
		||||
        # done
 | 
			
		||||
        layout.setSizeConstraint(QLayout.SetMinimumSize)
 | 
			
		||||
        self.setLayout(layout)
 | 
			
		||||
 | 
			
		||||
    def setupActions(self):
 | 
			
		||||
        self.__pin_button.toggled.connect(self.__pinnedToggled)
 | 
			
		||||
        self.__del_button.pressed.connect(self.deleted)
 | 
			
		||||
        
 | 
			
		||||
    def setSelected(self, selected = True):
 | 
			
		||||
        self.__selected = selected
 | 
			
		||||
        self.__pin_button.setVisible(selected)
 | 
			
		||||
        self.__del_button.setVisible(selected)
 | 
			
		||||
        self.__pin_indicator.setVisible(not self.__selected and self.__pin_button.isChecked())
 | 
			
		||||
 | 
			
		||||
    def setPinned(self, isPinned = True):
 | 
			
		||||
        self.__pin_button.setChecked(isPinned)
 | 
			
		||||
 | 
			
		||||
    def __setProject(self, project):
 | 
			
		||||
        self.__text = project['name']
 | 
			
		||||
        self.setPinned(project['pinned'])
 | 
			
		||||
 | 
			
		||||
    def __pinnedToggled(self, isPinned):
 | 
			
		||||
        self.__pin_indicator.setVisible(not self.__selected and isPinned)
 | 
			
		||||
        if (isPinned != self.project['pinned']):
 | 
			
		||||
            self.pinned.emit(isPinned)
 | 
			
		||||
@@ -1,91 +1,171 @@
 | 
			
		||||
import traceback
 | 
			
		||||
 | 
			
		||||
from PyQt5.QtWidgets import QDialog, QCommandLinkButton, QListWidgetItem
 | 
			
		||||
from PyQt5.QtGui import QPixmap
 | 
			
		||||
from PyQt5.QtCore import Qt
 | 
			
		||||
from PyQt5.QtWidgets import QDialog, QCommandLinkButton, QListWidgetItem, QFileDialog, QWidget, QHBoxLayout, QLabel, QToolButton, QLayout
 | 
			
		||||
from PyQt5.QtGui import QPixmap, QResizeEvent, QFont
 | 
			
		||||
from PyQt5.QtCore import Qt, pyqtSignal
 | 
			
		||||
 | 
			
		||||
from ui.welcome.recent_project import RecentProjectWidget
 | 
			
		||||
from ui.welcome.welcome_dialog_ui import Ui_WelcomeDialog
 | 
			
		||||
from model import RecentProject
 | 
			
		||||
from business import ProjectManager
 | 
			
		||||
from properties.config import PROJECT_EXTENSION
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class RecentProjectListWidget(QWidget):
 | 
			
		||||
    
 | 
			
		||||
    deleted = pyqtSignal()
 | 
			
		||||
    pinned = pyqtSignal(bool)
 | 
			
		||||
 | 
			
		||||
    def __init__(self, recentProject : RecentProject):
 | 
			
		||||
        super().__init__()
 | 
			
		||||
        self.project = recentProject
 | 
			
		||||
        self.__selected = False
 | 
			
		||||
        self.setupUi()
 | 
			
		||||
        self.setupActions()
 | 
			
		||||
        self.__setProject(recentProject)
 | 
			
		||||
        self.setSelected(False)
 | 
			
		||||
 | 
			
		||||
    def setupUi(self):
 | 
			
		||||
        layout = QHBoxLayout()
 | 
			
		||||
 | 
			
		||||
        # label
 | 
			
		||||
        self.__text = QLabel()
 | 
			
		||||
        layout.addWidget(self.__text)
 | 
			
		||||
 | 
			
		||||
        # space
 | 
			
		||||
        layout.addStretch()
 | 
			
		||||
 | 
			
		||||
        # pin button
 | 
			
		||||
        self.__pin_button = QToolButton()
 | 
			
		||||
        self.__pin_button.setFont(QFont("Font Awesome 5 Free"))
 | 
			
		||||
        self.__pin_button.setText("\uf08d")
 | 
			
		||||
        self.__pin_button.setCheckable(True)
 | 
			
		||||
        layout.addWidget(self.__pin_button)
 | 
			
		||||
 | 
			
		||||
        # delete button
 | 
			
		||||
        self.__del_button = QToolButton()
 | 
			
		||||
        self.__del_button.setFont(QFont("Font Awesome 5 Free"))
 | 
			
		||||
        self.__del_button.setText("\uf2ed")
 | 
			
		||||
        layout.addWidget(self.__del_button)
 | 
			
		||||
 | 
			
		||||
        # pin indicator
 | 
			
		||||
        self.__pin_indicator = QLabel()
 | 
			
		||||
        self.__pin_indicator.setFont(QFont("Font Awesome 5 Free"))
 | 
			
		||||
        self.__pin_indicator.setText("\uf08d")
 | 
			
		||||
        layout.addWidget(self.__pin_indicator)
 | 
			
		||||
 | 
			
		||||
        # done
 | 
			
		||||
        layout.setSizeConstraint(QLayout.SetMinimumSize)
 | 
			
		||||
        self.setLayout(layout)
 | 
			
		||||
 | 
			
		||||
    def setupActions(self):
 | 
			
		||||
        self.__pin_button.toggled.connect(self.__pinnedToggled)
 | 
			
		||||
        self.__del_button.pressed.connect(self.deleted)
 | 
			
		||||
        
 | 
			
		||||
    def setSelected(self, selected : bool = True):
 | 
			
		||||
        self.__selected = selected
 | 
			
		||||
        self.__pin_button.setVisible(selected)
 | 
			
		||||
        self.__del_button.setVisible(selected)
 | 
			
		||||
        self.__pin_indicator.setVisible(not self.__selected and self.__pin_button.isChecked())
 | 
			
		||||
 | 
			
		||||
    def setPinned(self, isPinned : bool = True):
 | 
			
		||||
        self.__pin_button.setChecked(isPinned)
 | 
			
		||||
 | 
			
		||||
    def __setProject(self, project : RecentProject):
 | 
			
		||||
        self.__text = project.name
 | 
			
		||||
        self.setPinned(project.pinned)
 | 
			
		||||
 | 
			
		||||
    def __pinnedToggled(self, isPinned : bool):
 | 
			
		||||
        self.__pin_indicator.setVisible(not self.__selected and isPinned)
 | 
			
		||||
        if (isPinned != self.project.pinned):
 | 
			
		||||
            self.pinned.emit(isPinned)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class WelcomeDialog(QDialog):
 | 
			
		||||
    NEW_PROJECT = 0
 | 
			
		||||
    OPEN_PROJECT = 1
 | 
			
		||||
 | 
			
		||||
    def __init__(self, projectManager):
 | 
			
		||||
        super().__init__()
 | 
			
		||||
    def __init__(self, projectManager : ProjectManager, parent : QWidget = None):
 | 
			
		||||
        super().__init__(parent)
 | 
			
		||||
        self.__projectManager = projectManager
 | 
			
		||||
        self.resultAction = None
 | 
			
		||||
        self.projectToOpen = None
 | 
			
		||||
        self.resultAction : int = None
 | 
			
		||||
        self.projectToOpen : str = None
 | 
			
		||||
        self.setResult(QDialog.Rejected)
 | 
			
		||||
        self.setupUi()
 | 
			
		||||
        self.setupActions()
 | 
			
		||||
        self.populateRecentProjects()
 | 
			
		||||
 | 
			
		||||
    def setupUi(self):
 | 
			
		||||
    def setupUi(self) -> None:
 | 
			
		||||
        self.ui = Ui_WelcomeDialog()
 | 
			
		||||
        self.ui.setupUi(self)
 | 
			
		||||
        self.image = QPixmap(self.ui.picture.pixmap())
 | 
			
		||||
 | 
			
		||||
    def setupActions(self):
 | 
			
		||||
    def setupActions(self) -> None:
 | 
			
		||||
        self.ui.buttonNewProject.pressed.connect(self.newProjectPressed)
 | 
			
		||||
        self.ui.buttonOpenProject.pressed.connect(self.openProjectPressed)
 | 
			
		||||
        self.ui.listRecentProjects.currentItemChanged.connect(self.listRecentProjectsCurrentChanged)
 | 
			
		||||
        self.ui.listRecentProjects.itemActivated.connect(self.listRecentProjectsItemActivated)
 | 
			
		||||
 | 
			
		||||
    def resizeEvent(self, event):
 | 
			
		||||
    def resizeEvent(self, event : QResizeEvent) -> None:
 | 
			
		||||
        super().resizeEvent(event)
 | 
			
		||||
        
 | 
			
		||||
        picSize = self.ui.picture.size()
 | 
			
		||||
        pic = self.image.scaled(picSize, Qt.KeepAspectRatioByExpanding, Qt.SmoothTransformation)
 | 
			
		||||
        self.ui.picture.setPixmap(pic)
 | 
			
		||||
 | 
			
		||||
    def populateRecentProjects(self):
 | 
			
		||||
    def populateRecentProjects(self) -> None:
 | 
			
		||||
        projects = list(self.__projectManager.getRecentProjects())
 | 
			
		||||
        projects = sorted(projects, key=lambda x: (x['pinned'], x['date']), reverse=True)
 | 
			
		||||
        projects = sorted(projects, key=lambda x: (x.pinned, x.dateAccessed), reverse=True)
 | 
			
		||||
        
 | 
			
		||||
        for project in projects:
 | 
			
		||||
 | 
			
		||||
            widget = RecentProjectWidget(project)
 | 
			
		||||
            widget = RecentProjectListWidget(project)
 | 
			
		||||
            widget.pinned.connect(self.__projectPinned)
 | 
			
		||||
            widget.deleted.connect(self.__projectDeleted)
 | 
			
		||||
 | 
			
		||||
            item = QListWidgetItem(project['name'])
 | 
			
		||||
            item = QListWidgetItem(project.name)
 | 
			
		||||
            item.setData(Qt.UserRole, project)
 | 
			
		||||
            item.setSizeHint(widget.sizeHint())
 | 
			
		||||
 | 
			
		||||
            self.ui.listRecentProjects.addItem(item)
 | 
			
		||||
            self.ui.listRecentProjects.setItemWidget(item, widget)
 | 
			
		||||
 | 
			
		||||
    def newProjectPressed(self):
 | 
			
		||||
    def newProjectPressed(self) -> None:
 | 
			
		||||
        self.resultAction = WelcomeDialog.NEW_PROJECT
 | 
			
		||||
        self.accept()
 | 
			
		||||
 | 
			
		||||
    def openProjectPressed(self):
 | 
			
		||||
        # TODO: show open dialog
 | 
			
		||||
        self.resultAction = WelcomeDialog.OPEN_PROJECT
 | 
			
		||||
        self.accept()
 | 
			
		||||
    def openProjectPressed(self) -> None:
 | 
			
		||||
        proj = QFileDialog.getOpenFileName(
 | 
			
		||||
            self, 
 | 
			
		||||
            self.tr('Open project'), 
 | 
			
		||||
            '', 
 | 
			
		||||
            self.tr(f'Project files (*.{PROJECT_EXTENSION});;All files (*.*)'))
 | 
			
		||||
 | 
			
		||||
    def listRecentProjectsCurrentChanged(self, current, previous):
 | 
			
		||||
        if proj[0]:
 | 
			
		||||
            self.projectToOpen = proj[0]
 | 
			
		||||
            self.resultAction = WelcomeDialog.OPEN_PROJECT
 | 
			
		||||
            self.accept()
 | 
			
		||||
 | 
			
		||||
    def listRecentProjectsCurrentChanged(self, current : QListWidgetItem, previous : QListWidgetItem) -> None:
 | 
			
		||||
        if not current is None:
 | 
			
		||||
            recentProjectWidget = self.ui.listRecentProjects.itemWidget(current)
 | 
			
		||||
            recentProjectWidget.setSelected(True)
 | 
			
		||||
            RecentProjectListWidget = self.ui.listRecentProjects.itemWidget(current)
 | 
			
		||||
            RecentProjectListWidget.setSelected(True)
 | 
			
		||||
            
 | 
			
		||||
        if not previous is None:
 | 
			
		||||
            recentProjectWidget = self.ui.listRecentProjects.itemWidget(previous)
 | 
			
		||||
            if not recentProjectWidget is None:
 | 
			
		||||
                recentProjectWidget.setSelected(False)
 | 
			
		||||
            RecentProjectListWidget = self.ui.listRecentProjects.itemWidget(previous)
 | 
			
		||||
            if not RecentProjectListWidget is None:
 | 
			
		||||
                RecentProjectListWidget.setSelected(False)
 | 
			
		||||
 | 
			
		||||
    def listRecentProjectsItemActivated(self, item):
 | 
			
		||||
        project = item.data(Qt.UserRole)
 | 
			
		||||
    def listRecentProjectsItemActivated(self, item : QListWidgetItem) -> None:
 | 
			
		||||
        project : RecentProject = item.data(Qt.UserRole)
 | 
			
		||||
        self.resultAction = WelcomeDialog.OPEN_PROJECT
 | 
			
		||||
        self.projectToOpen = project['path']
 | 
			
		||||
        self.projectToOpen = project.path
 | 
			
		||||
        self.accept()
 | 
			
		||||
 | 
			
		||||
    def __projectPinned(self, isPinned):
 | 
			
		||||
    def __projectPinned(self, isPinned : bool) -> None:
 | 
			
		||||
        project = self.ui.listRecentProjects.currentItem().data(Qt.UserRole)
 | 
			
		||||
        self.__projectManager.pinRecentProject(project, isPinned)
 | 
			
		||||
 | 
			
		||||
    def __projectDeleted(self):
 | 
			
		||||
    def __projectDeleted(self) -> None:
 | 
			
		||||
        project = self.ui.listRecentProjects.currentItem().data(Qt.UserRole)
 | 
			
		||||
        try:
 | 
			
		||||
            self.__projectManager.deleteRecentProject(project)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user