Started work on Ember
This commit is contained in:
commit
ac582a8b0b
105
.gitignore
vendored
Normal file
105
.gitignore
vendored
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
# Byte-compiled / optimized / DLL files
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
|
||||||
|
# C extensions
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Distribution / packaging
|
||||||
|
.Python
|
||||||
|
build/
|
||||||
|
develop-eggs/
|
||||||
|
dist/
|
||||||
|
downloads/
|
||||||
|
eggs/
|
||||||
|
.eggs/
|
||||||
|
lib/
|
||||||
|
lib64/
|
||||||
|
parts/
|
||||||
|
sdist/
|
||||||
|
var/
|
||||||
|
wheels/
|
||||||
|
*.egg-info/
|
||||||
|
.installed.cfg
|
||||||
|
*.egg
|
||||||
|
MANIFEST
|
||||||
|
|
||||||
|
# PyInstaller
|
||||||
|
# Usually these files are written by a python script from a template
|
||||||
|
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||||
|
*.manifest
|
||||||
|
*.spec
|
||||||
|
|
||||||
|
# Installer logs
|
||||||
|
pip-log.txt
|
||||||
|
pip-delete-this-directory.txt
|
||||||
|
|
||||||
|
# Unit test / coverage reports
|
||||||
|
htmlcov/
|
||||||
|
.tox/
|
||||||
|
.coverage
|
||||||
|
.coverage.*
|
||||||
|
.cache
|
||||||
|
nosetests.xml
|
||||||
|
coverage.xml
|
||||||
|
*.cover
|
||||||
|
.hypothesis/
|
||||||
|
.pytest_cache/
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
*.mo
|
||||||
|
*.pot
|
||||||
|
|
||||||
|
# Django stuff:
|
||||||
|
*.log
|
||||||
|
local_settings.py
|
||||||
|
db.sqlite3
|
||||||
|
|
||||||
|
# Flask stuff:
|
||||||
|
instance/
|
||||||
|
.webassets-cache
|
||||||
|
|
||||||
|
# Scrapy stuff:
|
||||||
|
.scrapy
|
||||||
|
|
||||||
|
# Sphinx documentation
|
||||||
|
docs/_build/
|
||||||
|
|
||||||
|
# PyBuilder
|
||||||
|
target/
|
||||||
|
|
||||||
|
# Jupyter Notebook
|
||||||
|
.ipynb_checkpoints
|
||||||
|
|
||||||
|
# pyenv
|
||||||
|
.python-version
|
||||||
|
|
||||||
|
# celery beat schedule file
|
||||||
|
celerybeat-schedule
|
||||||
|
|
||||||
|
# SageMath parsed files
|
||||||
|
*.sage.py
|
||||||
|
|
||||||
|
# Environments
|
||||||
|
.env
|
||||||
|
.venv
|
||||||
|
env/
|
||||||
|
venv/
|
||||||
|
ENV/
|
||||||
|
env.bak/
|
||||||
|
venv.bak/
|
||||||
|
|
||||||
|
# Spyder project settings
|
||||||
|
.spyderproject
|
||||||
|
.spyproject
|
||||||
|
|
||||||
|
# Rope project settings
|
||||||
|
.ropeproject
|
||||||
|
|
||||||
|
# mkdocs documentation
|
||||||
|
/site
|
||||||
|
|
||||||
|
# mypy
|
||||||
|
.mypy_cache/
|
||||||
|
|
30
.vscode/launch.json
vendored
Normal file
30
.vscode/launch.json
vendored
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
{
|
||||||
|
// 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: Current File",
|
||||||
|
"type": "python",
|
||||||
|
"request": "launch",
|
||||||
|
"program": "${file}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Python: Attach",
|
||||||
|
"type": "python",
|
||||||
|
"request": "attach",
|
||||||
|
"localRoot": "${workspaceFolder}",
|
||||||
|
"remoteRoot": "${workspaceFolder}",
|
||||||
|
"port": 3000,
|
||||||
|
"secret": "my_secret",
|
||||||
|
"host": "localhost"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Python: main.py",
|
||||||
|
"type": "python",
|
||||||
|
"request": "launch",
|
||||||
|
"program": "${workspaceFolder}/main.py"
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
3
.vscode/settings.json
vendored
Normal file
3
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"python.pythonPath": "/usr/bin/python3"
|
||||||
|
}
|
19
.vscode/tasks.json
vendored
Normal file
19
.vscode/tasks.json
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
// See https://go.microsoft.com/fwlink/?LinkId=733558
|
||||||
|
// for the documentation about the tasks.json format
|
||||||
|
"version": "2.0.0",
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
"label": "Build Resources",
|
||||||
|
"type": "process",
|
||||||
|
"command": "make",
|
||||||
|
"options": {
|
||||||
|
"cwd": "${workspaceFolder}"
|
||||||
|
},
|
||||||
|
"group": {
|
||||||
|
"kind": "build",
|
||||||
|
"isDefault": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
19
Makefile
Normal file
19
Makefile
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
RESOURCES=$(shell find . -name '*.qrc')
|
||||||
|
RESOURCES_OUT=$(RESOURCES:.qrc=_rc.py)
|
||||||
|
|
||||||
|
UI=$(shell find . -name '*.ui')
|
||||||
|
UI_OUT=$(UI:.ui=_ui.py)
|
||||||
|
|
||||||
|
all: $(RESOURCES_OUT) $(UI_OUT)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm ${UI_OUT}
|
||||||
|
rm ${RESOURCES_OUT}
|
||||||
|
|
||||||
|
%_rc.py: %.qrc
|
||||||
|
pyrcc5 $< -o $@
|
||||||
|
|
||||||
|
%_ui.py: %.ui
|
||||||
|
pyuic5 $< -o $@
|
||||||
|
|
||||||
|
.PHONY: all clean
|
0
business/__init__.py
Normal file
0
business/__init__.py
Normal file
42
business/project_manager.py
Normal file
42
business/project_manager.py
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
from model.project import Project
|
||||||
|
|
||||||
|
class ProjectManager(object):
|
||||||
|
|
||||||
|
def __init__(self, appDataStorage):
|
||||||
|
self.__appDataStorage = appDataStorage
|
||||||
|
self.__recentProjects = []
|
||||||
|
|
||||||
|
def getRecentProjects(self):
|
||||||
|
if self.__recentProjects is None:
|
||||||
|
self.__recentProjects = list(self.__appDataStorage.readRecentProjects())
|
||||||
|
return self.__recentProjects
|
||||||
|
|
||||||
|
def pinRecentProject(self, entry, isPinned = True):
|
||||||
|
entry['pinned'] = isPinned
|
||||||
|
self.__appDataStorage.writeRecentProjects(self.__recentProjects)
|
||||||
|
|
||||||
|
def debug_populateRecentProjects(self):
|
||||||
|
self.__recentProjects.append({
|
||||||
|
'name' : 'Debug project',
|
||||||
|
'path' : '/home/tibi/Videos/project.pro',
|
||||||
|
'pinned' : True,
|
||||||
|
'date' : 1
|
||||||
|
})
|
||||||
|
self.__recentProjects.append({
|
||||||
|
'name' : 'Debug project 2',
|
||||||
|
'path' : '/home/tibi/Videos/project2.pro',
|
||||||
|
'pinned' : False,
|
||||||
|
'date' : 2
|
||||||
|
})
|
||||||
|
self.__recentProjects.append({
|
||||||
|
'name' : 'Debug project 3',
|
||||||
|
'path' : '/home/tibi/Videos/project3.pro',
|
||||||
|
'pinned' : False,
|
||||||
|
'date' : 3
|
||||||
|
})
|
||||||
|
self.__recentProjects.append({
|
||||||
|
'name' : 'Debug project 4',
|
||||||
|
'path' : '/home/tibi/Videos/project4.pro',
|
||||||
|
'pinned' : False,
|
||||||
|
'date' : 4
|
||||||
|
})
|
34
fonts/FontAwesome-LICENSE.txt
Normal file
34
fonts/FontAwesome-LICENSE.txt
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
Font Awesome Free License
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
Font Awesome Free is free, open source, and GPL friendly. You can use it for
|
||||||
|
commercial projects, open source projects, or really almost whatever you want.
|
||||||
|
Full Font Awesome Free license: https://fontawesome.com/license.
|
||||||
|
|
||||||
|
# Icons: CC BY 4.0 License (https://creativecommons.org/licenses/by/4.0/)
|
||||||
|
In the Font Awesome Free download, the CC BY 4.0 license applies to all icons
|
||||||
|
packaged as SVG and JS file types.
|
||||||
|
|
||||||
|
# Fonts: SIL OFL 1.1 License (https://scripts.sil.org/OFL)
|
||||||
|
In the Font Awesome Free download, the SIL OLF license applies to all icons
|
||||||
|
packaged as web and desktop font files.
|
||||||
|
|
||||||
|
# Code: MIT License (https://opensource.org/licenses/MIT)
|
||||||
|
In the Font Awesome Free download, the MIT license applies to all non-font and
|
||||||
|
non-icon files.
|
||||||
|
|
||||||
|
# Attribution
|
||||||
|
Attribution is required by MIT, SIL OLF, and CC BY licenses. Downloaded Font
|
||||||
|
Awesome Free files already contain embedded comments with sufficient
|
||||||
|
attribution, so you shouldn't need to do anything additional when using these
|
||||||
|
files normally.
|
||||||
|
|
||||||
|
We've kept attribution comments terse, so we ask that you do not actively work
|
||||||
|
to remove them from files, especially code. They're a great way for folks to
|
||||||
|
learn about Font Awesome.
|
||||||
|
|
||||||
|
# Brand Icons
|
||||||
|
All brand icons are trademarks of their respective owners. The use of these
|
||||||
|
trademarks does not indicate endorsement of the trademark holder by Font
|
||||||
|
Awesome, nor vice versa. **Please do not use brand logos for any purpose except
|
||||||
|
to represent the company, product, or service to which they refer.**
|
BIN
fonts/FontAwesomeRegular-5.2.otf
Normal file
BIN
fonts/FontAwesomeRegular-5.2.otf
Normal file
Binary file not shown.
BIN
fonts/FontAwesomeSolid-5.2.otf
Normal file
BIN
fonts/FontAwesomeSolid-5.2.otf
Normal file
Binary file not shown.
BIN
img/charcoal-2396754.jpg
Normal file
BIN
img/charcoal-2396754.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.0 MiB |
BIN
img/spark-959254.jpg
Normal file
BIN
img/spark-959254.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.7 MiB |
4
main.py
Normal file
4
main.py
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
import sys
|
||||||
|
from ui.ember_application import EmberApplication
|
||||||
|
|
||||||
|
EmberApplication(sys.argv).start()
|
0
model/__init__.py
Normal file
0
model/__init__.py
Normal file
2
model/composition.py
Normal file
2
model/composition.py
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
class CompositionClip(object):
|
||||||
|
|
7
model/project.py
Normal file
7
model/project.py
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
class Project(object):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.root_dir = None
|
||||||
|
|
||||||
|
def get_items(self):
|
||||||
|
pass
|
6
model/project_item.py
Normal file
6
model/project_item.py
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
class ProjectItem(object):
|
||||||
|
|
||||||
|
def __init__(self, filename):
|
||||||
|
self.filename = filename
|
||||||
|
|
||||||
|
|
0
properties/__init__.py
Normal file
0
properties/__init__.py
Normal file
6
properties/config.py
Normal file
6
properties/config.py
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
APP_NAME = "Ember"
|
||||||
|
APP_VERSION = "1.0"
|
||||||
|
APP_AUTHOR = "Tiberiu Chibici"
|
||||||
|
APP_AUTHOR_SHORT = "TibiCh"
|
||||||
|
|
||||||
|
DEBUG = 1
|
11
resources.qrc
Normal file
11
resources.qrc
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<!DOCTYPE RCC>
|
||||||
|
<RCC version="1.0">
|
||||||
|
<qresource prefix="/">
|
||||||
|
<!-- Fonts -->
|
||||||
|
<file alias="FontAwesome-Solid.otf">fonts/FontAwesomeSolid-5.2.otf</file>
|
||||||
|
<file alias="FontAwesome-Regular.otf">fonts/FontAwesomeRegular-5.2.otf</file>
|
||||||
|
|
||||||
|
<!-- Picture -->
|
||||||
|
<file alias="WelcomeBanner.jpg">img/charcoal-2396754.jpg</file>
|
||||||
|
</qresource>
|
||||||
|
</RCC>
|
238313
resources_rc.py
Normal file
238313
resources_rc.py
Normal file
File diff suppressed because it is too large
Load Diff
44
storage/appdata_storage.py
Normal file
44
storage/appdata_storage.py
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
import appdirs
|
||||||
|
import os
|
||||||
|
from configparser import ConfigParser
|
||||||
|
import csv
|
||||||
|
|
||||||
|
from properties import config
|
||||||
|
|
||||||
|
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)
|
||||||
|
self.__settingsPath = os.path.join(self.__appDataPath, AppDataStorage.SETTINGS_FILE)
|
||||||
|
self.__recentProjectsPath = os.path.join(self.__appDataPath, AppDataStorage.RECENT_PROJECTS_FILE)
|
||||||
|
|
||||||
|
# make missing dirs in path
|
||||||
|
def __createPath(self, path):
|
||||||
|
dir = os.path.dirname(path)
|
||||||
|
os.makedirs(dir, exist_ok=True)
|
||||||
|
|
||||||
|
def readSettings(self):
|
||||||
|
if (os.path.exists(self.__settingsPath)):
|
||||||
|
parser = ConfigParser()
|
||||||
|
parser.read(self.__settingsPath)
|
||||||
|
# todo: finish this
|
||||||
|
|
||||||
|
def writeSettings(self, settings):
|
||||||
|
pass # todo: finish this
|
||||||
|
|
||||||
|
def readRecentProjects(self):
|
||||||
|
if (os.path.exists(self.__recentProjectsPath)):
|
||||||
|
with open(self.__recentProjectsPath, 'rb') as recentProjectsFile:
|
||||||
|
csvreader = csv.DictReader(recentProjectsFile, fieldnames=AppDataStorage.RECENT_PROJECTS_FIELDS)
|
||||||
|
for row in csvreader:
|
||||||
|
yield row
|
||||||
|
|
||||||
|
def writeRecentProjects(self, items):
|
||||||
|
self.__createPath(self.__recentProjectsPath)
|
||||||
|
with open(self.__recentProjectsPath, 'wb') as recentProjectsFile:
|
||||||
|
csvwriter = csv.DictWriter(recentProjectsFile, AppDataStorage.RECENT_PROJECTS_FIELDS)
|
||||||
|
csvwriter.writerows(items)
|
26
ui/ember_application.py
Normal file
26
ui/ember_application.py
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
from PyQt5.QtWidgets import QApplication
|
||||||
|
from PyQt5.QtGui import QFontDatabase
|
||||||
|
from ui.main_window import MainWindow
|
||||||
|
from business.project_manager import ProjectManager
|
||||||
|
from storage.appdata_storage import AppDataStorage
|
||||||
|
|
||||||
|
class EmberApplication(QApplication):
|
||||||
|
|
||||||
|
def __init__(self, argv):
|
||||||
|
super().__init__(argv)
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
|
||||||
|
QFontDatabase.addApplicationFont(":/FontAwesome-Solid.otf")
|
||||||
|
QFontDatabase.addApplicationFont(":/FontAwesome-Regular.otf")
|
||||||
|
|
||||||
|
# setup resources
|
||||||
|
appDataStorage = AppDataStorage()
|
||||||
|
projectManager = ProjectManager(appDataStorage)
|
||||||
|
projectManager.debug_populateRecentProjects()
|
||||||
|
|
||||||
|
# show main window
|
||||||
|
mainwindow = MainWindow(projectManager)
|
||||||
|
mainwindow.show()
|
||||||
|
|
||||||
|
exit(self.exec_())
|
31
ui/main_window.py
Normal file
31
ui/main_window.py
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
from PyQt5.QtWidgets import QMainWindow, QVBoxLayout, QWidget
|
||||||
|
|
||||||
|
from ui.project.project_panel import ProjectPanel
|
||||||
|
from ui.welcome.welcome_dialog import WelcomeDialog
|
||||||
|
|
||||||
|
class MainWindow(QMainWindow):
|
||||||
|
|
||||||
|
def __init__(self, projectManager):
|
||||||
|
super().__init__()
|
||||||
|
self.__projectManager = projectManager
|
||||||
|
self.setupUi()
|
||||||
|
self.initializeApp()
|
||||||
|
|
||||||
|
def setupUi(self):
|
||||||
|
self.projectPanel = ProjectPanel()
|
||||||
|
|
||||||
|
layout = QVBoxLayout()
|
||||||
|
layout.addWidget(self.projectPanel)
|
||||||
|
|
||||||
|
cwidget = QWidget()
|
||||||
|
cwidget.setLayout(layout)
|
||||||
|
|
||||||
|
self.setCentralWidget(cwidget)
|
||||||
|
|
||||||
|
def initializeApp(self):
|
||||||
|
|
||||||
|
# Show welcome dialog
|
||||||
|
welcome = WelcomeDialog(self.__projectManager)
|
||||||
|
res = welcome.exec()
|
||||||
|
|
||||||
|
print("Dialog result:", res)
|
12
ui/project/project_panel.py
Normal file
12
ui/project/project_panel.py
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
from PyQt5 import QtCore, QtWidgets, uic
|
||||||
|
import os
|
||||||
|
|
||||||
|
from ui.project.project_panel_ui import Ui_Form
|
||||||
|
|
||||||
|
class ProjectPanel(QtWidgets.QWidget):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super(ProjectPanel, self).__init__()
|
||||||
|
self.ui = Ui_Form()
|
||||||
|
self.ui.setupUi(self)
|
||||||
|
|
58
ui/project/project_panel.ui
Normal file
58
ui/project/project_panel.ui
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>Form</class>
|
||||||
|
<widget class="QWidget" name="Form">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>400</width>
|
||||||
|
<height>300</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Form</string>
|
||||||
|
</property>
|
||||||
|
<widget class="QPushButton" name="pushButton">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>90</x>
|
||||||
|
<y>40</y>
|
||||||
|
<width>84</width>
|
||||||
|
<height>34</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>PushButton</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QCheckBox" name="checkBox">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>80</x>
|
||||||
|
<y>150</y>
|
||||||
|
<width>86</width>
|
||||||
|
<height>22</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>CheckBox</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QCheckBox" name="checkBox_2">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>80</x>
|
||||||
|
<y>180</y>
|
||||||
|
<width>86</width>
|
||||||
|
<height>22</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>CheckBox</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
34
ui/project/project_panel_ui.py
Normal file
34
ui/project/project_panel_ui.py
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Form implementation generated from reading ui file 'ui/project/project_panel.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_Form(object):
|
||||||
|
def setupUi(self, Form):
|
||||||
|
Form.setObjectName("Form")
|
||||||
|
Form.resize(400, 300)
|
||||||
|
self.pushButton = QtWidgets.QPushButton(Form)
|
||||||
|
self.pushButton.setGeometry(QtCore.QRect(90, 40, 84, 34))
|
||||||
|
self.pushButton.setObjectName("pushButton")
|
||||||
|
self.checkBox = QtWidgets.QCheckBox(Form)
|
||||||
|
self.checkBox.setGeometry(QtCore.QRect(80, 150, 86, 22))
|
||||||
|
self.checkBox.setObjectName("checkBox")
|
||||||
|
self.checkBox_2 = QtWidgets.QCheckBox(Form)
|
||||||
|
self.checkBox_2.setGeometry(QtCore.QRect(80, 180, 86, 22))
|
||||||
|
self.checkBox_2.setObjectName("checkBox_2")
|
||||||
|
|
||||||
|
self.retranslateUi(Form)
|
||||||
|
QtCore.QMetaObject.connectSlotsByName(Form)
|
||||||
|
|
||||||
|
def retranslateUi(self, Form):
|
||||||
|
_translate = QtCore.QCoreApplication.translate
|
||||||
|
Form.setWindowTitle(_translate("Form", "Form"))
|
||||||
|
self.pushButton.setText(_translate("Form", "PushButton"))
|
||||||
|
self.checkBox.setText(_translate("Form", "CheckBox"))
|
||||||
|
self.checkBox_2.setText(_translate("Form", "CheckBox"))
|
||||||
|
|
33
ui/welcome/recent_project.py
Normal file
33
ui/welcome/recent_project.py
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
from PyQt5.QtWidgets import QWidget, QHBoxLayout, QLabel, QToolButton, QLayout
|
||||||
|
from PyQt5.QtGui import QFont
|
||||||
|
|
||||||
|
class RecentProjectWidget(QWidget):
|
||||||
|
def __init__(self, recentProject):
|
||||||
|
super().__init__()
|
||||||
|
self.setupUi()
|
||||||
|
self.setProject(recentProject)
|
||||||
|
|
||||||
|
def setupUi(self):
|
||||||
|
layout = QHBoxLayout()
|
||||||
|
|
||||||
|
# label
|
||||||
|
self.__text = QLabel()
|
||||||
|
layout.addWidget(self.__text)
|
||||||
|
|
||||||
|
# space
|
||||||
|
layout.addStretch()
|
||||||
|
|
||||||
|
# pin button
|
||||||
|
self.__button = QToolButton()
|
||||||
|
self.__button.setFont(QFont("Font Awesome 5 Free"))
|
||||||
|
self.__button.setText("\uf08d")
|
||||||
|
self.__button.setCheckable(True)
|
||||||
|
layout.addWidget(self.__button)
|
||||||
|
|
||||||
|
# done
|
||||||
|
layout.setSizeConstraint(QLayout.SetMinimumSize)
|
||||||
|
self.setLayout(layout)
|
||||||
|
|
||||||
|
def setProject(self, project):
|
||||||
|
self.__text = project['name']
|
||||||
|
self.__button.setChecked(project['pinned'])
|
65
ui/welcome/welcome_dialog.py
Normal file
65
ui/welcome/welcome_dialog.py
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
import os
|
||||||
|
import functools
|
||||||
|
from enum import Enum
|
||||||
|
|
||||||
|
from PyQt5.QtWidgets import QDialog, QVBoxLayout, QWidget, QCommandLinkButton, QListWidgetItem
|
||||||
|
from PyQt5.QtGui import QPixmap
|
||||||
|
from PyQt5.QtCore import Qt
|
||||||
|
from PyQt5 import uic
|
||||||
|
|
||||||
|
from util import str_compare
|
||||||
|
from ui.welcome.recent_project import RecentProjectWidget
|
||||||
|
from ui.welcome.welcome_dialog_ui import Ui_WelcomeDialog
|
||||||
|
|
||||||
|
class WelcomeDialogResult(Enum):
|
||||||
|
NewProject = 0
|
||||||
|
OpenProject = 1
|
||||||
|
OpenRecentProject = 2
|
||||||
|
|
||||||
|
class WelcomeDialog(QDialog):
|
||||||
|
|
||||||
|
def __init__(self, projectManager):
|
||||||
|
super().__init__()
|
||||||
|
self.__projectManager = projectManager
|
||||||
|
self.__resultAction = None
|
||||||
|
self.setResult(QDialog.Rejected)
|
||||||
|
self.setupUi()
|
||||||
|
self.setupActions()
|
||||||
|
self.populateRecentProjects()
|
||||||
|
|
||||||
|
def setupUi(self):
|
||||||
|
self.ui = Ui_WelcomeDialog()
|
||||||
|
self.ui.setupUi(self)
|
||||||
|
self.image = QPixmap(self.ui.picture.pixmap())
|
||||||
|
|
||||||
|
def setupActions(self):
|
||||||
|
self.ui.buttonNewProject.pressed.connect(self.newProjectPressed)
|
||||||
|
self.ui.buttonOpenProject.pressed.connect(self.openProjectPressed)
|
||||||
|
|
||||||
|
def resizeEvent(self, event):
|
||||||
|
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):
|
||||||
|
projects = list(self.__projectManager.getRecentProjects())
|
||||||
|
projects = sorted(projects, key=lambda x: (x['pinned'], x['date']), reverse=True)
|
||||||
|
|
||||||
|
for project in projects:
|
||||||
|
item = QListWidgetItem(project['name'])
|
||||||
|
item.setData(Qt.UserRole, project)
|
||||||
|
widget = RecentProjectWidget(project)
|
||||||
|
item.setSizeHint(widget.sizeHint())
|
||||||
|
|
||||||
|
self.ui.listRecentProjects.addItem(item)
|
||||||
|
self.ui.listRecentProjects.setItemWidget(item, widget)
|
||||||
|
|
||||||
|
def newProjectPressed(self):
|
||||||
|
self.__resultAction = WelcomeDialogResult.NewProject
|
||||||
|
self.accept()
|
||||||
|
|
||||||
|
def openProjectPressed(self):
|
||||||
|
self.__resultAction = WelcomeDialogResult.OpenProject
|
||||||
|
self.accept()
|
146
ui/welcome/welcome_dialog.ui
Normal file
146
ui/welcome/welcome_dialog.ui
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>WelcomeDialog</class>
|
||||||
|
<widget class="QDialog" name="WelcomeDialog">
|
||||||
|
<property name="windowModality">
|
||||||
|
<enum>Qt::WindowModal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>667</width>
|
||||||
|
<height>601</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Welcome</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="picture">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Ignored" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>120</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>16777215</width>
|
||||||
|
<height>120</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="pixmap">
|
||||||
|
<pixmap resource="../../resources.qrc">:/WelcomeBanner.jpg</pixmap>
|
||||||
|
</property>
|
||||||
|
<property name="scaledContents">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QWidget" name="panelRecentProjects" native="true">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
|
<horstretch>2</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="labelRecentProjects">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>13</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Recent projects</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QListWidget" name="listRecentProjects">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>1</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QWidget" name="panelButtons" native="true">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
|
<horstretch>1</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
|
<item>
|
||||||
|
<spacer name="verticalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeType">
|
||||||
|
<enum>QSizePolicy::MinimumExpanding</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>40</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCommandLinkButton" name="buttonNewProject">
|
||||||
|
<property name="text">
|
||||||
|
<string>&New Project</string>
|
||||||
|
</property>
|
||||||
|
<property name="description">
|
||||||
|
<string>Create a new project.</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCommandLinkButton" name="buttonOpenProject">
|
||||||
|
<property name="text">
|
||||||
|
<string>&Open Project</string>
|
||||||
|
</property>
|
||||||
|
<property name="description">
|
||||||
|
<string>Open an existing project.</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources>
|
||||||
|
<include location="../../resources.qrc"/>
|
||||||
|
</resources>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
90
ui/welcome/welcome_dialog_ui.py
Normal file
90
ui/welcome/welcome_dialog_ui.py
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Form implementation generated from reading ui file 'ui/welcome/welcome_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_WelcomeDialog(object):
|
||||||
|
def setupUi(self, WelcomeDialog):
|
||||||
|
WelcomeDialog.setObjectName("WelcomeDialog")
|
||||||
|
WelcomeDialog.setWindowModality(QtCore.Qt.WindowModal)
|
||||||
|
WelcomeDialog.resize(667, 601)
|
||||||
|
self.verticalLayout = QtWidgets.QVBoxLayout(WelcomeDialog)
|
||||||
|
self.verticalLayout.setObjectName("verticalLayout")
|
||||||
|
self.picture = QtWidgets.QLabel(WelcomeDialog)
|
||||||
|
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Ignored, QtWidgets.QSizePolicy.Fixed)
|
||||||
|
sizePolicy.setHorizontalStretch(0)
|
||||||
|
sizePolicy.setVerticalStretch(0)
|
||||||
|
sizePolicy.setHeightForWidth(self.picture.sizePolicy().hasHeightForWidth())
|
||||||
|
self.picture.setSizePolicy(sizePolicy)
|
||||||
|
self.picture.setMinimumSize(QtCore.QSize(0, 120))
|
||||||
|
self.picture.setMaximumSize(QtCore.QSize(16777215, 120))
|
||||||
|
self.picture.setText("")
|
||||||
|
self.picture.setPixmap(QtGui.QPixmap(":/WelcomeBanner.jpg"))
|
||||||
|
self.picture.setScaledContents(False)
|
||||||
|
self.picture.setAlignment(QtCore.Qt.AlignCenter)
|
||||||
|
self.picture.setObjectName("picture")
|
||||||
|
self.verticalLayout.addWidget(self.picture)
|
||||||
|
self.horizontalLayout = QtWidgets.QHBoxLayout()
|
||||||
|
self.horizontalLayout.setObjectName("horizontalLayout")
|
||||||
|
self.panelRecentProjects = QtWidgets.QWidget(WelcomeDialog)
|
||||||
|
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
|
||||||
|
sizePolicy.setHorizontalStretch(2)
|
||||||
|
sizePolicy.setVerticalStretch(0)
|
||||||
|
sizePolicy.setHeightForWidth(self.panelRecentProjects.sizePolicy().hasHeightForWidth())
|
||||||
|
self.panelRecentProjects.setSizePolicy(sizePolicy)
|
||||||
|
self.panelRecentProjects.setObjectName("panelRecentProjects")
|
||||||
|
self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.panelRecentProjects)
|
||||||
|
self.verticalLayout_3.setObjectName("verticalLayout_3")
|
||||||
|
self.labelRecentProjects = QtWidgets.QLabel(self.panelRecentProjects)
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setPointSize(13)
|
||||||
|
self.labelRecentProjects.setFont(font)
|
||||||
|
self.labelRecentProjects.setObjectName("labelRecentProjects")
|
||||||
|
self.verticalLayout_3.addWidget(self.labelRecentProjects)
|
||||||
|
self.listRecentProjects = QtWidgets.QListWidget(self.panelRecentProjects)
|
||||||
|
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
|
||||||
|
sizePolicy.setHorizontalStretch(0)
|
||||||
|
sizePolicy.setVerticalStretch(1)
|
||||||
|
sizePolicy.setHeightForWidth(self.listRecentProjects.sizePolicy().hasHeightForWidth())
|
||||||
|
self.listRecentProjects.setSizePolicy(sizePolicy)
|
||||||
|
self.listRecentProjects.setObjectName("listRecentProjects")
|
||||||
|
self.verticalLayout_3.addWidget(self.listRecentProjects)
|
||||||
|
self.horizontalLayout.addWidget(self.panelRecentProjects)
|
||||||
|
self.panelButtons = QtWidgets.QWidget(WelcomeDialog)
|
||||||
|
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
|
||||||
|
sizePolicy.setHorizontalStretch(1)
|
||||||
|
sizePolicy.setVerticalStretch(0)
|
||||||
|
sizePolicy.setHeightForWidth(self.panelButtons.sizePolicy().hasHeightForWidth())
|
||||||
|
self.panelButtons.setSizePolicy(sizePolicy)
|
||||||
|
self.panelButtons.setObjectName("panelButtons")
|
||||||
|
self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.panelButtons)
|
||||||
|
self.verticalLayout_2.setObjectName("verticalLayout_2")
|
||||||
|
spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.MinimumExpanding)
|
||||||
|
self.verticalLayout_2.addItem(spacerItem)
|
||||||
|
self.buttonNewProject = QtWidgets.QCommandLinkButton(self.panelButtons)
|
||||||
|
self.buttonNewProject.setObjectName("buttonNewProject")
|
||||||
|
self.verticalLayout_2.addWidget(self.buttonNewProject)
|
||||||
|
self.buttonOpenProject = QtWidgets.QCommandLinkButton(self.panelButtons)
|
||||||
|
self.buttonOpenProject.setObjectName("buttonOpenProject")
|
||||||
|
self.verticalLayout_2.addWidget(self.buttonOpenProject)
|
||||||
|
self.horizontalLayout.addWidget(self.panelButtons)
|
||||||
|
self.verticalLayout.addLayout(self.horizontalLayout)
|
||||||
|
|
||||||
|
self.retranslateUi(WelcomeDialog)
|
||||||
|
QtCore.QMetaObject.connectSlotsByName(WelcomeDialog)
|
||||||
|
|
||||||
|
def retranslateUi(self, WelcomeDialog):
|
||||||
|
_translate = QtCore.QCoreApplication.translate
|
||||||
|
WelcomeDialog.setWindowTitle(_translate("WelcomeDialog", "Welcome"))
|
||||||
|
self.labelRecentProjects.setText(_translate("WelcomeDialog", "Recent projects"))
|
||||||
|
self.buttonNewProject.setText(_translate("WelcomeDialog", "&New Project"))
|
||||||
|
self.buttonNewProject.setDescription(_translate("WelcomeDialog", "Create a new project."))
|
||||||
|
self.buttonOpenProject.setText(_translate("WelcomeDialog", "&Open Project"))
|
||||||
|
self.buttonOpenProject.setDescription(_translate("WelcomeDialog", "Open an existing project."))
|
||||||
|
|
||||||
|
import resources_rc
|
9
util/str_compare.py
Normal file
9
util/str_compare.py
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import unicodedata
|
||||||
|
|
||||||
|
def normalize_caseless(text):
|
||||||
|
return unicodedata.normalize("NFKD", text.casefold())
|
||||||
|
|
||||||
|
def unicode_compare_ignore_case(str1, str2):
|
||||||
|
str1 = normalize_caseless(str1)
|
||||||
|
str2 = normalize_caseless(str2)
|
||||||
|
return (str1>str2) - (str1<str2)
|
Loading…
Reference in New Issue
Block a user