use only one engine, small adjustments

This commit is contained in:
Martchus 2015-10-13 20:12:00 +02:00
parent c692795a9d
commit dfe17afcc6
6 changed files with 148 additions and 113 deletions

View File

@ -15,8 +15,8 @@ const QString &emptyStr() {
return emptyStr;
}
FileSystemItem::FileSystemItem(ItemStatus status, ItemType type, const QString &name) :
m_parent(nullptr),
FileSystemItem::FileSystemItem(ItemStatus status, ItemType type, const QString &name, FileSystemItem *parent) :
m_parent(parent),
m_counterpart(nullptr),
m_status(status),
m_type(type),
@ -25,7 +25,11 @@ FileSystemItem::FileSystemItem(ItemStatus status, ItemType type, const QString &
m_name(name),
m_checked(false),
m_checkable(false)
{}
{
if(m_parent) {
m_parent->m_children << this;
}
}
FileSystemItem::~FileSystemItem()
{

View File

@ -24,7 +24,7 @@ enum class ItemType {
class FileSystemItem {
public:
FileSystemItem(ItemStatus status = ItemStatus::Current, ItemType type = ItemType::File, const QString &name = QString());
FileSystemItem(ItemStatus status = ItemStatus::Current, ItemType type = ItemType::File, const QString &name = QString(), FileSystemItem *parent = nullptr);
~FileSystemItem();
FileSystemItem(const FileSystemItem &other) = delete;
FileSystemItem &operator =(const FileSystemItem &other) = delete;

View File

@ -4,6 +4,8 @@
#include "./filteredfilesystemitemmodel.h"
#include "./scriptfunctions.h"
#include <c++utilities/misc/memory.h>
#include <QDir>
#include <QScriptEngine>
#include <QScriptProgram>
@ -21,6 +23,7 @@ namespace RenamingUtility {
RemamingEngine::RemamingEngine(QObject *parent) :
QObject(parent),
m_go(m_engine.globalObject()),
m_itemsProcessed(0),
m_errorsOccured(0),
m_aborted(false),
@ -41,26 +44,24 @@ bool RemamingEngine::generatePreview(const QScriptProgram &scriptProgram, const
if(!m_mutex.try_lock()) {
return false;
}
setRootItem(nullptr);
lock_guard<mutex> guard(m_mutex, adopt_lock);
setRootItem();
m_program = scriptProgram;
m_includeSubdirs = includeSubdirs;
m_dir = rootDirectory;
auto startFunc = [this] () {
{
lock_guard<mutex> guard(m_mutex);
{
lock_guard<mutex> guard(m_abortedMutex);
m_aborted = false;
}
m_aborted.store(false);
m_itemsProcessed = 0;
m_errorsOccured = 0;
m_newlyGeneratedRootItem.reset(generatePreview(m_dir));
m_go.setProperty("persistent", m_persistent = m_engine.newObject(), QScriptValue::Undeletable);
m_newlyGeneratedRootItem = generatePreview(m_dir);
}
emit previewGenerated();
};
std::thread thread(startFunc);
thread.detach();
m_mutex.unlock();
return true;
}
@ -72,13 +73,11 @@ bool RemamingEngine::applyChangings()
if(!m_mutex.try_lock()) {
return false;
}
lock_guard<mutex> guard(m_mutex, adopt_lock);
auto startFunc = [this] () {
{
lock_guard<mutex> guard(m_mutex);
{
lock_guard<mutex> guard(m_abortedMutex);
m_aborted = false;
}
m_aborted.store(false);
m_itemsProcessed = 0;
m_errorsOccured = 0;
applyChangings(m_rootItem.get());
@ -87,7 +86,6 @@ bool RemamingEngine::applyChangings()
};
std::thread thread(startFunc);
thread.detach();
m_mutex.unlock();
return true;
}
@ -103,22 +101,20 @@ bool RemamingEngine::isBusy()
void RemamingEngine::abort()
{
lock_guard<mutex> guard(m_abortedMutex);
m_aborted = true;
m_aborted.store(true);
}
bool RemamingEngine::isAborted()
{
lock_guard<mutex> guard(m_abortedMutex);
return m_aborted;
return m_aborted.load();
}
bool RemamingEngine::clearPreview()
{
if(m_mutex.try_lock()) {
lock_guard<mutex> guard(m_mutex, adopt_lock);
updateModel(nullptr);
m_rootItem.reset();
m_mutex.unlock();
return true;
} else {
return false;
@ -153,7 +149,7 @@ FilteredFileSystemItemModel *RemamingEngine::previewModel()
void RemamingEngine::processPreviewGenerated()
{
setRootItem(m_newlyGeneratedRootItem.release());
setRootItem(move(m_newlyGeneratedRootItem));
}
void RemamingEngine::processChangingsApplied()
@ -162,10 +158,10 @@ void RemamingEngine::processChangingsApplied()
updateModel(m_rootItem.get());
}
inline void RemamingEngine::setRootItem(FileSystemItem *rootItem)
inline void RemamingEngine::setRootItem(unique_ptr<FileSystemItem> &&rootItem)
{
updateModel(rootItem);
m_rootItem.reset(rootItem);
updateModel(rootItem.get());
m_rootItem = move(rootItem);
}
void RemamingEngine::updateModel(FileSystemItem *rootItem)
@ -175,10 +171,9 @@ void RemamingEngine::updateModel(FileSystemItem *rootItem)
}
}
FileSystemItem *RemamingEngine::generatePreview(const QDir &dir, FileSystemItem *parent)
unique_ptr<FileSystemItem> RemamingEngine::generatePreview(const QDir &dir, FileSystemItem *parent)
{
FileSystemItem *item = new FileSystemItem(ItemStatus::Current, ItemType::Dir, dir.dirName());
item->setParent(parent);
auto item = make_unique<FileSystemItem>(ItemStatus::Current, ItemType::Dir, dir.dirName(), parent);
item->setApplied(false);
QFileInfoList entries = dir.entryInfoList();
foreach(const QFileInfo &entry, entries) {
@ -186,12 +181,11 @@ FileSystemItem *RemamingEngine::generatePreview(const QDir &dir, FileSystemItem
|| entry.fileName() == QLatin1String(".")) {
continue;
}
FileSystemItem *subItem;
FileSystemItem *subItem; // will be deleted by parent
if(entry.isDir() && m_includeSubdirs) {
subItem = generatePreview(QDir(entry.absoluteFilePath()), item);
subItem = generatePreview(QDir(entry.absoluteFilePath()), item.get()).release();
} else if(entry.isFile()) {
subItem = new FileSystemItem(ItemStatus::Current, ItemType::File, entry.fileName());
subItem->setParent(item);
subItem = new FileSystemItem(ItemStatus::Current, ItemType::File, entry.fileName(), item.get());
subItem->setApplied(false);
} else {
subItem = nullptr;
@ -295,20 +289,21 @@ void RemamingEngine::setError(const QList<FileSystemItem *> items)
void RemamingEngine::executeScriptForItem(const QFileInfo &fileInfo, FileSystemItem *item)
{
QScriptEngine engine;
setupGlobalObject(engine, fileInfo, item);
QScriptValue res = engine.evaluate(m_program);
if(engine.hasUncaughtException()) {
// execute script
setupGlobalObject(fileInfo, item);
QScriptValue res = m_engine.evaluate(m_program);
if(m_engine.hasUncaughtException()) {
// handle error
item->setErrorOccured(true);
item->setNote(res.toString());
m_engine.clearExceptions();
} else {
QScriptValue go = engine.globalObject();
QScriptValue newName = go.property("newName");
QScriptValue newRelativeDirectory = go.property("newRelativeDirectory");
// create preview for action
QScriptValue newName = m_go.property("newName");
QScriptValue newRelativeDirectory = m_go.property("newRelativeDirectory");
ActionType action = ActionType::Skip;
if(engine.globalObject().property("action").isNumber()) {
action = static_cast<ActionType>(engine.globalObject().property("action").toInt32());
if(m_go.property("action").isNumber()) {
action = static_cast<ActionType>(m_go.property("action").toInt32());
}
switch(action) {
case ActionType::Rename:
@ -325,8 +320,7 @@ void RemamingEngine::executeScriptForItem(const QFileInfo &fileInfo, FileSystemI
item->setNote(tr("name is already used at new location"));
item->setErrorOccured(true);
} else {
FileSystemItem *counterpart = new FileSystemItem(ItemStatus::New, item->type(), counterpartName);
counterpart->setParent(counterpartParent);
auto *counterpart = new FileSystemItem(ItemStatus::New, item->type(), counterpartName, counterpartParent);
item->setCounterpart(counterpart);
counterpart->setCheckable(true);
counterpart->setChecked(true);
@ -359,24 +353,29 @@ void RemamingEngine::executeScriptForItem(const QFileInfo &fileInfo, FileSystemI
}
}
void RemamingEngine::setupGlobalObject(QScriptEngine &engine, const QFileInfo &file, FileSystemItem *item)
void RemamingEngine::setupGlobalObject(const QFileInfo &file, FileSystemItem *item)
{
QScriptValue go = engine.globalObject();
go.setProperty("currentPath", file.absoluteFilePath(), QScriptValue::ReadOnly);
go.setProperty("currentName", item->name(), QScriptValue::ReadOnly);
go.setProperty("currentRelativeDirectory", item->relativeDir(), QScriptValue::ReadOnly);
go.setProperty("isDir", item->type() == ItemType::Dir, QScriptValue::ReadOnly);
go.setProperty("isFile", item->type() == ItemType::File, QScriptValue::ReadOnly);
go.setProperty("action", QScriptValue(static_cast<int>(ActionType::Rename)), QScriptValue::Undeletable);
go.setProperty("parseFileInfo", engine.newFunction(ScriptFunctions::parseFileInfo), QScriptValue::ReadOnly);
go.setProperty("parseFileName", engine.newFunction(ScriptFunctions::parseFileName), QScriptValue::ReadOnly);
go.setProperty("allFiles", engine.newFunction(ScriptFunctions::allFiles), QScriptValue::ReadOnly);
go.setProperty("firstFile", engine.newFunction(ScriptFunctions::firstFile), QScriptValue::ReadOnly);
go.setProperty("writeLog", engine.newFunction(ScriptFunctions::writeLog), QScriptValue::ReadOnly);
QScriptValue actionObject = engine.newObject();
// create new global object to clean previous variables ...
m_go = m_engine.newObject();
// ... except the persistent object
m_go.setProperty("persistent", m_persistent, QScriptValue::Undeletable);
// provide properties/functions
m_go.setProperty("currentPath", file.absoluteFilePath(), QScriptValue::ReadOnly);
m_go.setProperty("currentName", item->name(), QScriptValue::ReadOnly);
m_go.setProperty("currentRelativeDirectory", item->relativeDir(), QScriptValue::ReadOnly);
m_go.setProperty("isDir", item->type() == ItemType::Dir, QScriptValue::ReadOnly);
m_go.setProperty("isFile", item->type() == ItemType::File, QScriptValue::ReadOnly);
m_go.setProperty("action", QScriptValue(static_cast<int>(ActionType::Rename)), QScriptValue::Undeletable);
m_go.setProperty("parseFileInfo", m_engine.newFunction(ScriptFunctions::parseFileInfo), QScriptValue::ReadOnly);
m_go.setProperty("parseFileName", m_engine.newFunction(ScriptFunctions::parseFileName), QScriptValue::ReadOnly);
m_go.setProperty("allFiles", m_engine.newFunction(ScriptFunctions::allFiles), QScriptValue::ReadOnly);
m_go.setProperty("firstFile", m_engine.newFunction(ScriptFunctions::firstFile), QScriptValue::ReadOnly);
m_go.setProperty("writeLog", m_engine.newFunction(ScriptFunctions::writeLog), QScriptValue::ReadOnly);
QScriptValue actionObject = m_engine.newObject();
actionObject.setProperty("rename", QScriptValue(static_cast<int>(ActionType::Rename)), QScriptValue::ReadOnly);
actionObject.setProperty("skip", QScriptValue(static_cast<int>(ActionType::Skip)), QScriptValue::ReadOnly);
go.setProperty("actionType", actionObject, QScriptValue::ReadOnly);
m_go.setProperty("actionType", actionObject, QScriptValue::ReadOnly);
m_engine.setGlobalObject(m_go);
}
} // namespace RenamingUtility

View File

@ -5,17 +5,20 @@
#include <QList>
#include <QDir>
#include <QScriptProgram>
#include <QScriptEngine>
#include <QScriptValue>
QT_BEGIN_NAMESPACE
class QFileInfo;
class QScriptProgram;
class QScriptValue;
class QScriptContext;
class QScriptEngine;
//class QScriptEngine;
//class QScriptValue;
QT_END_NAMESPACE
#include <memory>
#include <mutex>
#include <atomic>
namespace RenamingUtility {
@ -57,20 +60,22 @@ private slots:
void processChangingsApplied();
private:
void setRootItem(FileSystemItem *rootItem);
void setRootItem(std::unique_ptr<FileSystemItem> &&rootItem = std::unique_ptr<FileSystemItem>());
void updateModel(FileSystemItem *rootItem);
FileSystemItem *generatePreview(const QDir &dir, FileSystemItem *parent = nullptr);
std::unique_ptr<FileSystemItem> generatePreview(const QDir &dir, FileSystemItem *parent = nullptr);
void applyChangings(FileSystemItem *parentItem);
static void setError(const QList<FileSystemItem *> items);
void executeScriptForItem(const QFileInfo &fileInfo, FileSystemItem *item);
static void setupGlobalObject(QScriptEngine &engine, const QFileInfo &file, FileSystemItem *item);
void setupGlobalObject(const QFileInfo &file, FileSystemItem *item);
QScriptEngine m_engine;
QScriptValue m_go;
QScriptValue m_persistent;
std::unique_ptr<FileSystemItem> m_rootItem;
std::unique_ptr<FileSystemItem> m_newlyGeneratedRootItem;
int m_itemsProcessed;
int m_errorsOccured;
bool m_aborted;
std::mutex m_abortedMutex;
std::atomic<bool> m_aborted;
QScriptProgram m_program;
QDir m_dir;
bool m_includeSubdirs;

View File

@ -28,33 +28,67 @@ namespace RenamingUtility {
Necessary for lupdate.
*/
QScriptValue &operator <<(QScriptValue &notificationsObject, const StatusProvider &statusProvider)
{
quint32 counter = 0;
for(const auto &notification : statusProvider.notifications()) {
QScriptValue val;
val.setProperty("msg", QString::fromLocal8Bit(notification.message().data()), QScriptValue::ReadOnly);
val.setProperty("critical", notification.type() == NotificationType::Critical, QScriptValue::ReadOnly);
notificationsObject.setProperty(counter, val);
++counter;
}
return notificationsObject;
}
QScriptValue &operator <<(QScriptValue &tagObject, const Tag &tag)
{
// text fields
tagObject.setProperty("title", tagValueToQString(tag.value(KnownField::Title)), QScriptValue::ReadOnly);
tagObject.setProperty("artist", tagValueToQString(tag.value(KnownField::Artist)), QScriptValue::ReadOnly);
tagObject.setProperty("album", tagValueToQString(tag.value(KnownField::Album)), QScriptValue::ReadOnly);
tagObject.setProperty("year", tagValueToQString(tag.value(KnownField::Year)), QScriptValue::ReadOnly);
tagObject.setProperty("comment", tagValueToQString(tag.value(KnownField::Comment)), QScriptValue::ReadOnly);
tagObject.setProperty("genre", tagValueToQString(tag.value(KnownField::Genre)), QScriptValue::ReadOnly);
tagObject.setProperty("encoder", tagValueToQString(tag.value(KnownField::Encoder)), QScriptValue::ReadOnly);
tagObject.setProperty("language", tagValueToQString(tag.value(KnownField::Language)), QScriptValue::ReadOnly);
tagObject.setProperty("descriptions", tagValueToQString(tag.value(KnownField::Description)), QScriptValue::ReadOnly);
// numeric fields
try {
tagObject.setProperty("partNumber", tag.value(KnownField::PartNumber).toInteger(), QScriptValue::ReadOnly);
} catch(ConversionException &) {}
try {
tagObject.setProperty("totalParts", tag.value(KnownField::TotalParts).toInteger(), QScriptValue::ReadOnly);
} catch(ConversionException &) {}
PositionInSet pos;
try {
pos = tag.value(KnownField::TrackPosition).toPositionIntSet();
} catch(ConversionException &) {}
tagObject.setProperty("trackPos", pos.position(), QScriptValue::ReadOnly);
tagObject.setProperty("trackTotal", pos.total(), QScriptValue::ReadOnly);
pos = PositionInSet();
try {
pos = tag.value(KnownField::DiskPosition).toPositionIntSet();
} catch(ConversionException &) {}
tagObject.setProperty("diskPos", pos.position(), QScriptValue::ReadOnly);
tagObject.setProperty("diskTotal", pos.total(), QScriptValue::ReadOnly);
// notifications
tagObject.setProperty("hasCriticalNotifications", tag.hasCriticalNotifications(), QScriptValue::ReadOnly);
return tagObject;
}
QScriptValue ScriptFunctions::parseFileInfo(QScriptContext *context, QScriptEngine *engine)
{
if(context->argumentCount() != 1 && !context->argument(0).isString()) {
return QScriptValue();
}
QString fileName = context->argument(0).toString();
auto addNotifications = [] (QScriptValue &notificationObject, const StatusProvider &statusProvider) {
quint32 counter = 0;
for(const Notification &notification : statusProvider.notifications()) {
QScriptValue val;
val.setProperty("msg", QString::fromLocal8Bit(notification.message().c_str()), QScriptValue::ReadOnly);
val.setProperty("critical", notification.type() == NotificationType::Critical, QScriptValue::ReadOnly);
notificationObject.setProperty(counter, val);
++counter;
}
};
QScriptValue fileInfoObject = engine->newObject();
QScriptValue tagObject = engine->newObject();
QScriptValue tagNotificationObject = engine->newArray();
auto fileName = context->argument(0).toString();
MediaFileInfo fileInfo(fileName.toLocal8Bit().data());
fileInfoObject.setProperty("currentName", QString::fromLocal8Bit(fileInfo.fileName(false).c_str()));
fileInfoObject.setProperty("currentBaseName", QString::fromLocal8Bit(fileInfo.fileName(true).c_str()));
QString suffix = QString::fromLocal8Bit(fileInfo.extension().c_str());
QScriptValue fileInfoObject = engine->newObject();
fileInfoObject.setProperty("currentName", QString::fromLocal8Bit(fileInfo.fileName(false).data()));
fileInfoObject.setProperty("currentBaseName", QString::fromLocal8Bit(fileInfo.fileName(true).data()));
QString suffix = QString::fromLocal8Bit(fileInfo.extension().data());
if(suffix.startsWith('.')) {
suffix.remove(0, 1);
}
@ -70,7 +104,7 @@ QScriptValue ScriptFunctions::parseFileInfo(QScriptContext *context, QScriptEngi
}
QScriptValue mainNotificationObject = engine->newArray(fileInfo.notifications().size());
addNotifications(mainNotificationObject, fileInfo);
mainNotificationObject << fileInfo;
critical |= fileInfo.hasCriticalNotifications();
fileInfoObject.setProperty("hasCriticalNotifications", critical);
fileInfoObject.setProperty("notifications", mainNotificationObject);
@ -80,32 +114,25 @@ QScriptValue ScriptFunctions::parseFileInfo(QScriptContext *context, QScriptEngi
vector<Tag *> tags;
fileInfo.tags(tags);
for(vector<Tag *>::const_iterator tagIterator = tags.cbegin(), end = tags.cend();
tagIterator != end; ++tagIterator) {
const Tag &tag = **tagIterator;
tagObject.setProperty("title", tagValueToQString(tag.value(KnownField::Title)), QScriptValue::ReadOnly);
tagObject.setProperty("artist", tagValueToQString(tag.value(KnownField::Artist)), QScriptValue::ReadOnly);
tagObject.setProperty("album", tagValueToQString(tag.value(KnownField::Album)), QScriptValue::ReadOnly);
tagObject.setProperty("year", tagValueToQString(tag.value(KnownField::Year)), QScriptValue::ReadOnly);
tagObject.setProperty("comment", tagValueToQString(tag.value(KnownField::Comment)), QScriptValue::ReadOnly);
PositionInSet pos;
try {
pos = tag.value(KnownField::TrackPosition).toPositionIntSet();
} catch(ConversionException &) {}
tagObject.setProperty("trackPos", pos.position(), QScriptValue::ReadOnly);
tagObject.setProperty("trackTotal", pos.total(), QScriptValue::ReadOnly);
pos = PositionInSet();
try {
pos = tag.value(KnownField::DiskPosition).toPositionIntSet();
} catch(ConversionException &) {}
tagObject.setProperty("diskPos", pos.position(), QScriptValue::ReadOnly);
tagObject.setProperty("diskTotal", pos.total(), QScriptValue::ReadOnly);
QScriptValue combinedTagObject = engine->newObject();
QScriptValue combinedTagNotifications = engine->newArray();
QScriptValue tagsObject = engine->newArray(tags.size());
uint32 tagIndex = 0;
addNotifications(tagNotificationObject, tag);
tagObject.setProperty("hasCriticalNotifications", tag.hasCriticalNotifications(), QScriptValue::ReadOnly);
for(auto tagIterator = tags.cbegin(), end = tags.cend(); tagIterator != end; ++tagIterator, ++tagIndex) {
const Tag &tag = **tagIterator;
QScriptValue tagObject = engine->newObject();
combinedTagObject << tag;
combinedTagNotifications << tag;
tagObject << tag;
QScriptValue tagNotificationsObject = engine->newArray(tag.notifications().size());
tagNotificationsObject << tag;
tagObject.setProperty("notifications", tagNotificationsObject, QScriptValue::ReadOnly);
tagsObject.setProperty(tagIndex, tagObject, QScriptValue::ReadOnly);
}
fileInfoObject.setProperty("notifications", tagNotificationObject, QScriptValue::ReadOnly);
fileInfoObject.setProperty("tag", tagObject, QScriptValue::ReadOnly);
combinedTagObject.setProperty("notifications", combinedTagNotifications, QScriptValue::ReadOnly);
fileInfoObject.setProperty("tag", combinedTagObject, QScriptValue::ReadOnly);
fileInfoObject.setProperty("tags", tagsObject, QScriptValue::ReadOnly);
return fileInfoObject;
}

View File

@ -58,7 +58,7 @@ function appropriateDigitCount(pos, total) {
*/
function validFileName(name) {
if(name !== undefined) {
return name.replace(/[\/\\<>?!*|:\"\n\f\r]/gi, "");
return name.replace(/[\/\\]/gi, " - ").replace(/[<>?!*|:\"\n\f\r]/gi, "");
} else {
return "";
}
@ -70,7 +70,7 @@ function validFileName(name) {
*/
function validDirectoryName(name) {
if(name !== undefined) {
return name.replace(/[\/\\<>?!*|:\".\n\f\r]/gi, "");
return name.replace(/[\/\\]/gi, " - ").replace(/[<>?!*|:\".\n\f\r]/gi, "");
} else {
return "";
}