Converted project to C++.
This commit is contained in:
@ -1,2 +0,0 @@
|
||||
from .recent_project import RecentProject
|
||||
from .project import Project, ProjectItem, ItemType
|
@ -1,2 +0,0 @@
|
||||
class CompositionClip(object):
|
||||
pass
|
95
model/project.cpp
Normal file
95
model/project.cpp
Normal file
@ -0,0 +1,95 @@
|
||||
#include <pugixml.hpp>
|
||||
|
||||
#include "project.h"
|
||||
|
||||
namespace Ember
|
||||
{
|
||||
|
||||
Project::Project(boost::filesystem::path projectFilePath)
|
||||
: m_path(projectFilePath),
|
||||
m_name(),
|
||||
m_bitsPerChannel(8),
|
||||
m_audioSampleRate(48000),
|
||||
m_rootItem(projectFilePath.parent_path(), nullptr, this)
|
||||
{
|
||||
}
|
||||
|
||||
boost::filesystem::path Project::path() const
|
||||
{
|
||||
return m_path;
|
||||
}
|
||||
|
||||
std::string Project::name() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
int Project::bitsPerChannel() const
|
||||
{
|
||||
return m_bitsPerChannel;
|
||||
}
|
||||
|
||||
int Project::audioSampleRate() const
|
||||
{
|
||||
return m_audioSampleRate;
|
||||
}
|
||||
|
||||
ProjectItem& Project::rootItem()
|
||||
{
|
||||
return m_rootItem;
|
||||
}
|
||||
|
||||
void Project::setName(const std::string &name)
|
||||
{
|
||||
m_name = name;
|
||||
}
|
||||
|
||||
void Project::setBitsPerChannel(int bitsPerChannel)
|
||||
{
|
||||
m_bitsPerChannel = bitsPerChannel;
|
||||
}
|
||||
|
||||
void Project::setAudioSampleRate(int audioSampleRate)
|
||||
{
|
||||
m_audioSampleRate = audioSampleRate;
|
||||
}
|
||||
|
||||
void Project::load()
|
||||
{
|
||||
pugi::xml_document doc;
|
||||
|
||||
if (!doc.load_file(m_path.c_str()))
|
||||
{
|
||||
// TODO: proper error handlign
|
||||
throw 0;
|
||||
}
|
||||
|
||||
pugi::xml_node root = doc.document_element();
|
||||
|
||||
// Get name
|
||||
pugi::xml_attribute attr;
|
||||
if ((attr = root.attribute("name")))
|
||||
m_name = attr.as_string();
|
||||
|
||||
// Get other properties
|
||||
if ((attr = root.attribute("bitsPerChannel")))
|
||||
m_bitsPerChannel = attr.as_int();
|
||||
|
||||
if ((attr = root.attribute("audioSampleRate")))
|
||||
m_audioSampleRate = attr.as_int();
|
||||
}
|
||||
|
||||
void Project::save()
|
||||
{
|
||||
pugi::xml_document doc;
|
||||
doc.append_child(pugi::node_declaration);
|
||||
|
||||
auto proj = doc.append_child("project");
|
||||
proj.append_attribute("name").set_value(m_name.c_str());
|
||||
proj.append_attribute("bitsPerChannel").set_value(m_bitsPerChannel);
|
||||
proj.append_attribute("audioSampleRate").set_value(m_audioSampleRate);
|
||||
|
||||
doc.save_file(m_path.string().c_str());
|
||||
}
|
||||
|
||||
}
|
57
model/project.h
Normal file
57
model/project.h
Normal file
@ -0,0 +1,57 @@
|
||||
#ifndef PROJECT_H
|
||||
#define PROJECT_H
|
||||
|
||||
#include <string>
|
||||
#include <time.h>
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#include "projectitem.h"
|
||||
|
||||
namespace Ember
|
||||
{
|
||||
|
||||
class Project
|
||||
{
|
||||
public:
|
||||
Project(boost::filesystem::path projectFilePath);
|
||||
|
||||
// Getters
|
||||
boost::filesystem::path path() const;
|
||||
|
||||
std::string name() const;
|
||||
int bitsPerChannel() const;
|
||||
int audioSampleRate() const;
|
||||
|
||||
ProjectItem& rootItem();
|
||||
|
||||
// Setters
|
||||
void setName(const std::string &name);
|
||||
void setBitsPerChannel(int bitsPerChannel);
|
||||
void setAudioSampleRate(int audioSampleRate);
|
||||
|
||||
// Actions
|
||||
void load();
|
||||
void save();
|
||||
|
||||
private:
|
||||
boost::filesystem::path m_path;
|
||||
|
||||
// Details (that will be stored in project file)
|
||||
std::string m_name;
|
||||
int m_bitsPerChannel = 8;
|
||||
int m_audioSampleRate = 48000;
|
||||
|
||||
// Items
|
||||
ProjectItem m_rootItem;
|
||||
};
|
||||
|
||||
struct RecentProject
|
||||
{
|
||||
std::string name;
|
||||
boost::filesystem::path path;
|
||||
time_t access;
|
||||
bool pinned;
|
||||
};
|
||||
|
||||
}
|
||||
#endif // PROJECT_H
|
@ -1,74 +0,0 @@
|
||||
import os
|
||||
from enum import Enum
|
||||
from typing import List
|
||||
|
||||
class ItemType(Enum):
|
||||
MISSING = 0
|
||||
DIRECTORY = 1
|
||||
IMAGE = 2
|
||||
AUDIO = 3
|
||||
VIDEO = 4
|
||||
SUBTITLES = 5
|
||||
PROJECT = 6
|
||||
COMPOSITION = 7
|
||||
SEQUENCE = 8
|
||||
UNKNOWN = 1000
|
||||
|
||||
class ProjectItem(object):
|
||||
def __init__(self, name : str, project : "Project", storage : "ProjectStorage", parent : "ProjectItem" = None):
|
||||
self.__storage = storage
|
||||
self.name = name
|
||||
self.project = project
|
||||
self.parent = parent
|
||||
self.__type : ItemType = None
|
||||
self.__children : list = None
|
||||
|
||||
"""
|
||||
Gets the path relative to the project directory.
|
||||
|
||||
Returns:
|
||||
path relative to the project root folder.
|
||||
"""
|
||||
def path(self) -> str:
|
||||
if self.parent:
|
||||
return os.path.join(self.parent.path(), self.name)
|
||||
return self.name
|
||||
|
||||
"""
|
||||
Gets the absolute path to this project item.
|
||||
"""
|
||||
def absolutePath(self) -> str:
|
||||
return os.path.join(self.project.rootDir, self.path())
|
||||
|
||||
"""
|
||||
Gets the type of this project item.
|
||||
"""
|
||||
def itemType(self) -> str:
|
||||
if self.__type is None:
|
||||
self.__type = self.__storage.itemType(self)
|
||||
return self.__type
|
||||
|
||||
"""
|
||||
Gets the children project items.
|
||||
"""
|
||||
def children(self) -> List["ProjectItem"]:
|
||||
if self.__children is None:
|
||||
self.__children = list(self.__storage.itemChildren(self))
|
||||
return self.__children
|
||||
|
||||
|
||||
class Project(object):
|
||||
|
||||
def __init__(self, path : str, storage : "ProjectStorage"):
|
||||
self.__storage = storage
|
||||
self.projectFile : str = path
|
||||
self.rootDir : str = None
|
||||
self.videoBitsPerChannel : int = 8
|
||||
self.videoColorSpace : str = None
|
||||
self.audioSampleRate : int = 48000
|
||||
self.__items : List[ProjectItem] = None
|
||||
|
||||
def items(self) -> List[ProjectItem]:
|
||||
if self.__items is None:
|
||||
self.__items = list(self.__storage.projectItems(self))
|
||||
return self.__items
|
137
model/projectitem.cpp
Normal file
137
model/projectitem.cpp
Normal file
@ -0,0 +1,137 @@
|
||||
#include <algorithm>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <properties/config.h>
|
||||
|
||||
#include "project.h"
|
||||
#include "projectitem.h"
|
||||
|
||||
namespace Ember
|
||||
{
|
||||
|
||||
ProjectItem::ProjectItem(boost::filesystem::path path, ProjectItem* parent, Project* project)
|
||||
: m_path(path),
|
||||
m_type(),
|
||||
m_typeLoaded(false),
|
||||
m_parent(parent),
|
||||
m_children(),
|
||||
m_childrenLoaded(false),
|
||||
m_project(project)
|
||||
{
|
||||
}
|
||||
|
||||
std::string ProjectItem::name() const
|
||||
{
|
||||
return m_path.filename().string();
|
||||
}
|
||||
|
||||
ProjectItem::ProjectItemType ProjectItem::type()
|
||||
{
|
||||
if (!m_typeLoaded)
|
||||
{
|
||||
if (boost::filesystem::is_directory(m_path))
|
||||
{
|
||||
m_type = ProjectItemType::DIRECTORY;
|
||||
}
|
||||
else if (boost::filesystem::exists(m_path))
|
||||
{
|
||||
std::string ext = m_path.extension().string();
|
||||
|
||||
if (ext == ".png" || ext == ".jpg" || ext == ".bmp" || ext == ".jpeg")
|
||||
m_type = ProjectItemType::IMAGE;
|
||||
else if (ext == ".mp3" || ext == ".ogg" || ext == ".wav")
|
||||
m_type = ProjectItemType::AUDIO;
|
||||
else if (ext == ".avi" || ext == ".mp4" || ext == ".wmv")
|
||||
m_type = ProjectItemType::VIDEO;
|
||||
else if (ext == ".srt")
|
||||
m_type = ProjectItemType::SUBTITLES;
|
||||
else if (ext == EMBER_PROJECT_EXTENSION)
|
||||
m_type = ProjectItemType::PROJECT;
|
||||
else if (ext == EMBER_COMPOSITION_EXTENSION)
|
||||
m_type = ProjectItemType::COMPOSITION;
|
||||
else if (ext == EMBER_SEQUENCE_EXTENSION)
|
||||
m_type = ProjectItemType::SEQUENCE;
|
||||
|
||||
else m_type = ProjectItemType::UNKNOWN;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_type = ProjectItemType::MISSING;
|
||||
}
|
||||
|
||||
m_typeLoaded = true;
|
||||
}
|
||||
|
||||
return m_type;
|
||||
}
|
||||
|
||||
ProjectItem *ProjectItem::parent() const
|
||||
{
|
||||
return m_parent;
|
||||
}
|
||||
|
||||
Project *ProjectItem::project() const
|
||||
{
|
||||
return m_project;
|
||||
}
|
||||
|
||||
const std::vector<ProjectItem *>& ProjectItem::children()
|
||||
{
|
||||
if (!m_childrenLoaded)
|
||||
{
|
||||
if (type() == ProjectItemType::DIRECTORY)
|
||||
{
|
||||
for (auto&& entry : boost::filesystem::directory_iterator(m_path))
|
||||
{
|
||||
ProjectItem* child = new ProjectItem(entry.path(), this, m_project);
|
||||
m_children.push_back(child);
|
||||
}
|
||||
}
|
||||
|
||||
m_childrenLoaded = true;
|
||||
}
|
||||
|
||||
return m_children;
|
||||
}
|
||||
|
||||
boost::filesystem::path ProjectItem::path() const
|
||||
{
|
||||
return m_path;
|
||||
}
|
||||
|
||||
void ProjectItem::rename(const std::string &name)
|
||||
{
|
||||
auto newPath = m_path.parent_path().append(name);
|
||||
boost::filesystem::rename(m_path, newPath);
|
||||
}
|
||||
|
||||
void ProjectItem::move(ProjectItem *newParent)
|
||||
{
|
||||
auto newPath = newParent->path().append(name());
|
||||
boost::filesystem::rename(m_path, newPath);
|
||||
|
||||
// Update parenting
|
||||
if (m_parent)
|
||||
m_parent->unparentChild(this);
|
||||
|
||||
newParent->m_children.push_back(this);
|
||||
}
|
||||
|
||||
void ProjectItem::unlink()
|
||||
{
|
||||
boost::filesystem::remove(m_path);
|
||||
|
||||
// Update parenting
|
||||
if (m_parent)
|
||||
delete m_parent->unparentChild(this);
|
||||
}
|
||||
|
||||
ProjectItem *ProjectItem::unparentChild(ProjectItem *child)
|
||||
{
|
||||
auto it = std::find(m_children.begin(), m_children.end(), child);
|
||||
if (it != m_children.end())
|
||||
m_parent->m_children.erase(it);
|
||||
|
||||
return child;
|
||||
}
|
||||
|
||||
}
|
105
model/projectitem.h
Normal file
105
model/projectitem.h
Normal file
@ -0,0 +1,105 @@
|
||||
#ifndef PROJECTITEM_H
|
||||
#define PROJECTITEM_H
|
||||
|
||||
#include <string>
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
namespace Ember
|
||||
{
|
||||
class Project;
|
||||
|
||||
class ProjectItem
|
||||
{
|
||||
public:
|
||||
enum ProjectItemType
|
||||
{
|
||||
UNKNOWN,
|
||||
MISSING,
|
||||
DIRECTORY,
|
||||
IMAGE,
|
||||
AUDIO,
|
||||
VIDEO,
|
||||
SUBTITLES,
|
||||
PROJECT,
|
||||
COMPOSITION,
|
||||
SEQUENCE
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief ProjectItem constructor
|
||||
* @param name Name corresponding to file on disk
|
||||
* @param parent Parent project item
|
||||
* @param project Assigned project
|
||||
*/
|
||||
ProjectItem(boost::filesystem::path path, ProjectItem* parent, Project* project);
|
||||
|
||||
// Getters
|
||||
/**
|
||||
* @brief Gets the name of the item
|
||||
* @return Name
|
||||
*/
|
||||
std::string name() const;
|
||||
|
||||
/**
|
||||
* @brief Gets the type of the item.
|
||||
* @return Type of item
|
||||
*/
|
||||
ProjectItemType type();
|
||||
|
||||
/**
|
||||
* @brief Gets the parent project item.
|
||||
* @return Parent item
|
||||
*/
|
||||
ProjectItem *parent() const;
|
||||
|
||||
/**
|
||||
* @brief Gets the parent project
|
||||
* @return Parent project
|
||||
*/
|
||||
Project *project() const;
|
||||
|
||||
/**
|
||||
* @brief Gets a list of children. If not a directory, the list will be empty.
|
||||
* @return Vector of children.
|
||||
*/
|
||||
const std::vector<ProjectItem *>& children();
|
||||
|
||||
/**
|
||||
* @brief Gets the path of this project item
|
||||
* @return
|
||||
*/
|
||||
boost::filesystem::path path() const;
|
||||
|
||||
// Action
|
||||
/**
|
||||
* @brief Sets the name of the item. Will result in a disk rename.
|
||||
* @param name New name
|
||||
*/
|
||||
void rename(const std::string &name);
|
||||
|
||||
/**
|
||||
* @brief Sets the parent project item. Will result in a disk move.
|
||||
* @param newParent New parent
|
||||
*/
|
||||
void move(ProjectItem *newParent);
|
||||
|
||||
/**
|
||||
* @brief Delete from the disk. 'this' object is DELETED!
|
||||
* TODO: recycle bin or permanent delete?
|
||||
*/
|
||||
void unlink();
|
||||
|
||||
private:
|
||||
ProjectItem* unparentChild(ProjectItem* child);
|
||||
|
||||
boost::filesystem::path m_path;
|
||||
ProjectItemType m_type;
|
||||
bool m_typeLoaded;
|
||||
ProjectItem* m_parent;
|
||||
std::vector<ProjectItem*> m_children;
|
||||
bool m_childrenLoaded;
|
||||
Project* m_project;
|
||||
};
|
||||
|
||||
}
|
||||
#endif // PROJECTITEM_H
|
@ -1,60 +0,0 @@
|
||||
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
|
||||
}
|
Reference in New Issue
Block a user