Skip to content

Commit

Permalink
Fix issue 56 (thunder-engine#208)
Browse files Browse the repository at this point in the history
* Editor: Adding ContextMenu and shell for Edit/Rename/Delete & New Folder commands in ContentTree thunder-engine#56
  • Loading branch information
gguedesaz authored and eprikazchikov committed Oct 29, 2019
1 parent 2e88923 commit 41fbd83
Show file tree
Hide file tree
Showing 7 changed files with 175 additions and 42 deletions.
54 changes: 48 additions & 6 deletions develop/managers/assetmanager/src/assetmanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -338,19 +338,61 @@ void AssetManager::renameResource(const QFileInfo &oldName, const QFileInfo &new
}
}

namespace
{
// Copied from: https://forum.qt.io/topic/59245/is-there-any-api-to-recursively-copy-a-directory-and-all-it-s-sub-dirs-and-files/3
bool copyRecursively(QString sourceFolder, QString destFolder)
{
bool success = false;
QDir sourceDir(sourceFolder);

if(!sourceDir.exists())
return false;

QDir destDir(destFolder);
if(!destDir.exists())
destDir.mkdir(destFolder);

QStringList files = sourceDir.entryList(QDir::Files);
for(int i = 0; i< files.count(); i++) {
QString srcName = sourceFolder + QDir::separator() + files[i];
QString destName = destFolder + QDir::separator() + files[i];
success = QFile::copy(srcName, destName);
if(!success)
return false;
}

files.clear();
files = sourceDir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot);
for(int i = 0; i< files.count(); i++)
{
QString srcName = sourceFolder + QDir::separator() + files[i];
QString destName = destFolder + QDir::separator() + files[i];
success = copyRecursively(srcName, destName);
if(!success)
return false;
}

return true;
}
}

void AssetManager::duplicateResource(const QFileInfo &source) {
QDir dir(m_pProjectManager->contentPath());
QFileInfo src(m_pProjectManager->contentPath() + "/" + source.filePath());

QString name = src.baseName();
QString path = src.absolutePath() + "/";
QString suff = "." + src.suffix();
QString suff = !src.suffix().isEmpty() ? "." + src.suffix() : "";
findFreeName(name, path, suff);

QFileInfo target(src.absoluteFilePath(), path + name + suff);
// Source and meta
QFile::copy(src.absoluteFilePath(), target.filePath());
QFile::copy(src.absoluteFilePath() + gMetaExt, target.filePath() + gMetaExt);
QFileInfo target (src.absoluteFilePath(), path + name + suff);
if (src.isDir()) {
copyRecursively(src.absoluteFilePath(), target.absoluteFilePath());
} else {
// Source and meta
QFile::copy(src.absoluteFilePath(), target.filePath());
QFile::copy(src.absoluteFilePath() + gMetaExt, target.filePath() + gMetaExt);
}

IConverterSettings *settings = createSettings(target);
QString guid = settings->destination();
Expand Down
4 changes: 4 additions & 0 deletions develop/models/include/baseobjectmodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ class BaseObjectModel : public QAbstractItemModel {

Qt::ItemFlags flags (const QModelIndex &index) const;

virtual bool removeResource (const QModelIndex &index) { return false; }

virtual QString path (const QModelIndex &index) const { Q_UNUSED(index); return QString(); }

protected:
QObject *m_rootItem;

Expand Down
107 changes: 74 additions & 33 deletions worldeditor/src/editors/contentbrowser/contentbrowser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,31 +129,7 @@ ContentBrowser::ContentBrowser(QWidget* parent) :
connect(m_pFilterMenu, SIGNAL(triggered(QAction*)), this, SLOT(onFilterMenuTriggered(QAction*)));

readSettings();

QString showIn(tr("Show in Explorer"));
{
QLabel *label = new QLabel(tr("Create Asset"), this);
QWidgetAction *a = new QWidgetAction(&m_CreationMenu);
a->setDefaultWidget(label);

m_CreationMenu.addAction(tr("New Folder"))->setData(true);
m_CreationMenu.addAction(showIn, this, SLOT(showInGraphicalShell()));
m_CreationMenu.addSeparator();
m_CreationMenu.addAction(a);
m_CreationMenu.addAction(tr("NativeBehaviour"))->setData(".cpp");
m_CreationMenu.addAction(tr("AngelBehaviour"))->setData(".as");
m_CreationMenu.addAction(tr("ParticleEffect"))->setData(".efx");
m_CreationMenu.addAction(tr("Material"))->setData(".mtl");
}

createAction(showIn, SLOT(showInGraphicalShell()));
createAction(tr("Duplicate"), SLOT(onItemDuplicate()));
createAction(tr("Rename"), SLOT(onItemRename()), QKeySequence(Qt::Key_F2));
createAction(tr("Delete"), SLOT(onItemDelete()), QKeySequence(Qt::Key_Delete));
m_ContentMenu.addSeparator();
createAction(tr("Reimport"), SLOT(onItemReimport()));

connect(&m_CreationMenu, SIGNAL(triggered(QAction*)), this, SLOT(onCreationMenuTriggered(QAction*)));
createContextMenus();
}

ContentBrowser::~ContentBrowser() {
Expand All @@ -175,6 +151,40 @@ void ContentBrowser::writeSettings() {
settings.setValue("content.geometry", ui->splitter->saveState());
}

void ContentBrowser::createContextMenus() {
QString showIn(tr("Show in Explorer"));
QLabel *label = new QLabel(tr("Create Asset"), this);
QWidgetAction *a = new QWidgetAction(&m_CreationMenu);
a->setDefaultWidget(label);

m_CreationMenu.addAction(tr("New Folder"))->setData(true);
m_CreationMenu.addAction(showIn, this, SLOT(showInGraphicalShell()));
m_CreationMenu.addSeparator();
m_CreationMenu.addAction(a);
m_CreationMenu.addAction(tr("NativeBehaviour"))->setData(".cpp");
m_CreationMenu.addAction(tr("AngelBehaviour"))->setData(".as");
m_CreationMenu.addAction(tr("ParticleEffect"))->setData(".efx");
m_CreationMenu.addAction(tr("Material"))->setData(".mtl");

createAction(showIn, SLOT(showInGraphicalShell()));
createAction(tr("Duplicate"), SLOT(onItemDuplicate()))->setData(QVariant::fromValue(ui->contentList));
createAction(tr("Rename"), SLOT(onItemRename()), QKeySequence(Qt::Key_F2))->setData(QVariant::fromValue(ui->contentList));
createAction(tr("Delete"), SLOT(onItemDelete()), QKeySequence(Qt::Key_Delete))->setData(QVariant::fromValue(ui->contentList));
m_ContentMenu.addSeparator();
createAction(tr("Reimport"), SLOT(onItemReimport()));

m_contentTreeMenu.addAction(tr("New Folder"))->setData(true);
m_contentTreeMenu.addAction(showIn, this, SLOT(showInGraphicalShell()));
m_contentTreeMenu.addSeparator();

m_contentTreeMenu.addAction(tr("Duplicate"), this, SLOT(onItemDuplicate()))->setData(QVariant::fromValue(ui->contentTree));
m_contentTreeMenu.addAction(tr("Rename"), this, SLOT(onItemRename()))->setData(QVariant::fromValue(ui->contentTree));
m_contentTreeMenu.addAction(tr("Delete"), this, SLOT(onItemDelete()))->setData(QVariant::fromValue(ui->contentTree));

connect(&m_CreationMenu, SIGNAL(triggered(QAction*)), this, SLOT(onCreationMenuTriggered(QAction*)));
connect(&m_contentTreeMenu, SIGNAL(triggered(QAction*)), this, SLOT(onCreationMenuTriggered(QAction*)));
}

void ContentBrowser::onCreationMenuTriggered(QAction *action) {
QDir dir(m_pContentProxy->rootPath());
switch(action->data().type()) {
Expand Down Expand Up @@ -217,13 +227,27 @@ void ContentBrowser::onFilterMenuTriggered(QAction *) {
}

void ContentBrowser::onItemRename() {
ui->contentList->edit(ui->contentList->currentIndex());
QAction* action = qobject_cast<QAction*>(sender());
if (action)
{
QAbstractItemView* view = qvariant_cast<QAbstractItemView*>(action->data());
view->edit(view->currentIndex());
}
}

void ContentBrowser::onItemDuplicate() {
QModelIndex index = m_pContentProxy->mapToSource(ui->contentList->currentIndex());
QString path = ContentList::instance()->path(index);
AssetManager::instance()->duplicateResource(QFileInfo(path));
QAction* action = qobject_cast<QAction*>(sender());
if (action)
{
QAbstractItemView* view = qvariant_cast<QAbstractItemView*>(action->data());
QSortFilterProxyModel* filter = static_cast<QSortFilterProxyModel*>(view->model());
BaseObjectModel* model = static_cast<BaseObjectModel*>(filter->sourceModel());

QModelIndex index = filter->mapToSource(view->currentIndex());
QString path = model->path(index);
QFileInfo info = dynamic_cast<QTreeView*>(view) != nullptr ? QFileInfo(path).fileName() : QFileInfo(path);
AssetManager::instance()->duplicateResource(info);
}
}

void ContentBrowser::onItemReimport() {
Expand All @@ -232,9 +256,17 @@ void ContentBrowser::onItemReimport() {
}

void ContentBrowser::onItemDelete() {
QMessageBox msgBox(QMessageBox::Question, tr("Delete Asset"), tr("This action cannot be reverted. Do you want to delete selected asset?"), QMessageBox::Yes | QMessageBox::No);
if(msgBox.exec() == QMessageBox::Yes) {
ContentList::instance()->removeResource(m_pContentProxy->mapToSource(ui->contentList->currentIndex()));
QAction* action = qobject_cast<QAction*>(sender());
if (action)
{
QAbstractItemView* view = qvariant_cast<QAbstractItemView*>(action->data());
QSortFilterProxyModel* filter = static_cast<QSortFilterProxyModel*>(view->model());
BaseObjectModel* model = static_cast<BaseObjectModel*>(filter->sourceModel());

QMessageBox msgBox(QMessageBox::Question, tr("Delete Asset"), tr("This action cannot be reverted. Do you want to delete selected asset?"), QMessageBox::Yes | QMessageBox::No);
if (msgBox.exec() == QMessageBox::Yes) {
model->removeResource(filter->mapToSource(view->currentIndex()));
}
}
}

Expand Down Expand Up @@ -266,13 +298,14 @@ void ContentBrowser::on_contentList_doubleClicked(const QModelIndex &index) {
}
}

void ContentBrowser::createAction(const QString &name, const char *member, const QKeySequence &shortcut) {
QAction* ContentBrowser::createAction(const QString &name, const char *member, const QKeySequence &shortcut) {
QAction *a = new QAction(name, this);
a->setShortcutContext(Qt::WidgetWithChildrenShortcut);
a->setShortcut(shortcut);
connect(a, SIGNAL(triggered(bool)), this, member);
ui->contentList->addAction(a);
m_ContentMenu.addAction(a);
return a;
}

void ContentBrowser::on_contentList_customContextMenuRequested(const QPoint &pos) {
Expand All @@ -284,6 +317,14 @@ void ContentBrowser::on_contentList_customContextMenuRequested(const QPoint &pos
}
}

void ContentBrowser::on_contentTree_customContextMenuRequested(const QPoint &pos) {
QWidget* w = static_cast<QWidget*>(QObject::sender());
if (!ui->contentTree->selectionModel()->selectedIndexes().empty())
{
m_contentTreeMenu.exec(w->mapToGlobal(pos));
}
}

void ContentBrowser::showInGraphicalShell() {
QString path;
QModelIndexList list = ui->contentList->selectionModel()->selectedIndexes();
Expand Down
8 changes: 6 additions & 2 deletions worldeditor/src/editors/contentbrowser/contentbrowser.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@

#include "converters/converter.h"

class QSortFilterProxyModel;
class ContentItemDeligate;
class ContentListFilter;
class ContentTreeFilter;
class BaseObjectModel;

namespace Ui {
class ContentBrowser;
Expand Down Expand Up @@ -57,6 +57,7 @@ class ContentBrowser : public QWidget {
protected:
void readSettings ();
void writeSettings ();
void createContextMenus ();

ContentItemDeligate *m_pContentDeligate;

Expand All @@ -79,13 +80,14 @@ private slots:
void on_contentTree_clicked (const QModelIndex &index);
void on_contentList_doubleClicked (const QModelIndex &index);

void on_contentTree_customContextMenuRequested (const QPoint &pos);
void on_contentList_customContextMenuRequested (const QPoint &pos);
void on_findContent_textChanged (const QString &arg1);

void showInGraphicalShell ();

private:
void createAction (const QString &name, const char *member, const QKeySequence &shortcut = 0);
QAction* createAction (const QString &name, const char *member, const QKeySequence &shortcut = 0);

private:
Ui::ContentBrowser *ui;
Expand All @@ -94,6 +96,8 @@ private slots:

QMenu m_CreationMenu;

QMenu m_contentTreeMenu;

};

#endif // CONTENTBROWSER_H
3 changes: 3 additions & 0 deletions worldeditor/src/editors/contentbrowser/contentbrowser.ui
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@
<property name="contextMenuPolicy">
<enum>Qt::CustomContextMenu</enum>
</property>
<property name="editTriggers">
<set>QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed</set>
</property>
<property name="dragEnabled">
<bool>true</bool>
</property>
Expand Down
37 changes: 36 additions & 1 deletion worldeditor/src/editors/contentbrowser/contenttree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,8 +174,27 @@ QVariant ContentTree::data(const QModelIndex &index, int role) const {
return QVariant();
}

bool ContentTree::setData(const QModelIndex& index, const QVariant& value, int role)
{
Q_UNUSED(role)
switch(index.column()) {
case 0: {
QDir dir(ProjectManager::instance()->contentPath());
QObject *item = static_cast<QObject *>(index.internalPointer());
QFileInfo info(item->objectName());
QString path = (info.path() != ".") ? (info.path() + QDir::separator()) : "";
QString suff = (!info.suffix().isEmpty()) ? ("." + info.suffix()) : "";
QFileInfo dest(path + value.toString() + suff);
AssetManager::instance()->renameResource(dir.relativeFilePath(info.filePath()),
dir.relativeFilePath(dest.filePath()));
} break;
default: break;
}
return true;
}

Qt::ItemFlags ContentTree::flags(const QModelIndex &index) const {
return BaseObjectModel::flags(index) | Qt::ItemIsSelectable;
return BaseObjectModel::flags(index) | Qt::ItemIsSelectable | Qt::ItemIsEditable;
}

QString ContentTree::path(const QModelIndex &index) const {
Expand Down Expand Up @@ -204,6 +223,22 @@ void ContentTree::onRendered(const QString &uuid) {
}
}

bool ContentTree::removeResource(const QModelIndex &index) {
if(index.isValid()) {
QObject *item = static_cast<QObject *>(index.internalPointer());
if(item) {
QFileInfo fullName(item->objectName());
AssetManager::instance()->removeResource(QFileInfo(fullName.fileName()));
item->setParent(nullptr);
delete item;
}
}

emit layoutAboutToBeChanged();
emit layoutChanged();
return true;
}

void ContentTree::update(const QString &path) {
QDir dir(ProjectManager::instance()->contentPath());
m_pContent->setObjectName(dir.absolutePath());
Expand Down
4 changes: 4 additions & 0 deletions worldeditor/src/editors/contentbrowser/contenttree.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,14 @@ class ContentTree : public BaseObjectModel {

QVariant data (const QModelIndex &index, int role) const;

bool setData (const QModelIndex &index, const QVariant &value, int role);

Qt::ItemFlags flags (const QModelIndex &index) const;

QString path (const QModelIndex &index) const;

bool removeResource (const QModelIndex &index);

public slots:
void onRendered (const QString &uuid);

Expand Down

0 comments on commit 41fbd83

Please sign in to comment.