diff --git a/Editor/CMakeLists.txt b/Editor/CMakeLists.txt index 45b9bb6..8ae2298 100644 --- a/Editor/CMakeLists.txt +++ b/Editor/CMakeLists.txt @@ -61,6 +61,10 @@ add_executable(amuse-gui WIN32 MACOSX_BUNDLE ) target_compile_definitions(amuse-gui PRIVATE + # Disable implicit conversions from ASCII to QString. + -DQT_NO_CAST_FROM_ASCII + -DQT_NO_CAST_TO_ASCII + # Allows for more efficient string concatenation, resulting in less temporaries. -DQT_USE_QSTRINGBUILDER ) diff --git a/Editor/MainWindow.cpp b/Editor/MainWindow.cpp index 9a8015f..ca98229 100644 --- a/Editor/MainWindow.cpp +++ b/Editor/MainWindow.cpp @@ -250,13 +250,12 @@ void MainWindow::updateWindowTitle() { } void MainWindow::updateRecentFileActions() { - QSettings settings; - QStringList files = settings.value("recentFileList").toStringList(); - - int numRecentFiles = std::min(files.size(), int(MaxRecentFiles)); + const QSettings settings; + const QStringList files = settings.value(QStringLiteral("recentFileList")).toStringList(); + const int numRecentFiles = std::min(files.size(), int(MaxRecentFiles)); for (int i = 0; i < numRecentFiles; ++i) { - QString text = QStringLiteral("&%1 %2").arg(i + 1).arg(QDir(files[i]).dirName()); + const QString text = QStringLiteral("&%1 %2").arg(i + 1).arg(QDir(files[i]).dirName()); m_recentFileActs[i]->setText(text); m_recentFileActs[i]->setData(files[i]); m_recentFileActs[i]->setToolTip(files[i]); @@ -321,13 +320,15 @@ bool MainWindow::setProjectPath(const QString& path) { updateNavigationButtons(); + const QString key = QStringLiteral("recentFileList"); QSettings settings; - QStringList files = settings.value("recentFileList").toStringList(); + QStringList files = settings.value(key).toStringList(); files.removeAll(dir.path()); files.prepend(dir.path()); - while (files.size() > MaxRecentFiles) + while (files.size() > MaxRecentFiles) { files.removeLast(); - settings.setValue("recentFileList", files); + } + settings.setValue(key, files); settings.sync(); updateRecentFileActions(); @@ -801,24 +802,30 @@ void MainWindow::_openAction(const QString& path) { } void MainWindow::openRecentFileAction() { - if (!askAboutSave()) + if (!askAboutSave()) { return; + } - if (QAction* action = qobject_cast(sender())) - if (!openProject(action->data().toString())) { - QString path = action->data().toString(); - QSettings settings; - QStringList files = settings.value("recentFileList").toStringList(); - files.removeAll(path); - settings.setValue("recentFileList", files); - settings.sync(); - updateRecentFileActions(); + if (const QAction* action = qobject_cast(sender())) { + const QString path = action->data().toString(); + if (openProject(path)) { + return; } + + const QString key = QStringLiteral("recentFileList"); + QSettings settings; + QStringList files = settings.value(key).toStringList(); + + files.removeAll(path); + settings.setValue(key, files); + settings.sync(); + updateRecentFileActions(); + } } void MainWindow::clearRecentFilesAction() { QSettings settings; - settings.setValue("recentFileList", QStringList()); + settings.setValue(QStringLiteral("recentFileList"), QStringList()); settings.sync(); updateRecentFileActions(); } @@ -943,11 +950,10 @@ void MainWindow::_importAction(const QString& path) { ProjectModel* model = m_projectModel; startBackgroundTask( TaskImport, tr("Importing"), tr("Scanning Project"), [model, path, importMode](BackgroundTask& task) { - QDir dir = QFileInfo(path).dir(); - QStringList filters; - filters << "*.proj" - << "*.pro"; - QStringList files = dir.entryList(filters, QDir::Files); + const QDir dir = QFileInfo(path).dir(); + const QStringList filters{QStringLiteral("*.proj"), QStringLiteral("*.pro")}; + const QStringList files = dir.entryList(filters, QDir::Files); + for (const QString& fPath : files) { auto data = amuse::ContainerRegistry::LoadContainer(QStringToSysString(dir.filePath(fPath)).c_str()); for (auto& p : data) { diff --git a/Editor/ProjectModel.cpp b/Editor/ProjectModel.cpp index f268856..e06d338 100644 --- a/Editor/ProjectModel.cpp +++ b/Editor/ProjectModel.cpp @@ -492,9 +492,9 @@ ProjectModel::ProjectModel(const QString& path, QObject* parent) : QAbstractItemModel(parent), m_dir(path), m_outlineProxy(this), m_nullProxy(this), m_pageObjectProxy(this) { m_root = amuse::MakeObj(); - GroupNode::Icon = QIcon(":/icons/IconGroup.svg"); - SongGroupNode::Icon = QIcon(":/icons/IconSongGroup.svg"); - SoundGroupNode::Icon = QIcon(":/icons/IconSoundGroup.svg"); + GroupNode::Icon = QIcon(QStringLiteral(":/icons/IconGroup.svg")); + SongGroupNode::Icon = QIcon(QStringLiteral(":/icons/IconSongGroup.svg")); + SoundGroupNode::Icon = QIcon(QStringLiteral(":/icons/IconSoundGroup.svg")); } bool ProjectModel::clearProjectData() { @@ -800,15 +800,15 @@ void ProjectModel::updateNodeNames() { gn->oneLevelTraverse([](INode* n) { if (n->type() == INode::Type::SongGroup) { SongGroupNode* sgn = static_cast(n); - sgn->m_name = amuse::GroupId::CurNameDB->resolveNameFromId(sgn->m_id).data(); + sgn->m_name = QString::fromUtf8(amuse::GroupId::CurNameDB->resolveNameFromId(sgn->m_id).data()); } else if (n->type() == INode::Type::SoundGroup) { SoundGroupNode* sgn = static_cast(n); - sgn->m_name = amuse::GroupId::CurNameDB->resolveNameFromId(sgn->m_id).data(); + sgn->m_name = QString::fromUtf8(amuse::GroupId::CurNameDB->resolveNameFromId(sgn->m_id).data()); } else if (n->type() == INode::Type::Collection) { CollectionNode* cn = static_cast(n); cn->oneLevelTraverse([](INode* n) { BasePoolObjectNode* on = static_cast(n); - on->m_name = on->getNameDb()->resolveNameFromId(on->m_id).data(); + on->m_name = QString::fromUtf8(on->getNameDb()->resolveNameFromId(on->m_id).data()); return true; }); cn->_sortChildren(); @@ -824,12 +824,13 @@ void ProjectModel::updateNodeNames() { void ProjectModel::_buildGroupNodeCollections(GroupNode& gn) { gn.reserve(6); - gn._appendChild(tr("Sound Macros"), QIcon(":/icons/IconSoundMacro.svg"), INode::Type::SoundMacro); - gn._appendChild(tr("ADSRs"), QIcon(":/icons/IconADSR.svg"), INode::Type::ADSR); - gn._appendChild(tr("Curves"), QIcon(":/icons/IconCurve.svg"), INode::Type::Curve); - gn._appendChild(tr("Keymaps"), QIcon(":/icons/IconKeymap.svg"), INode::Type::Keymap); - gn._appendChild(tr("Layers"), QIcon(":/icons/IconLayers.svg"), INode::Type::Layer); - gn._appendChild(tr("Samples"), QIcon(":/icons/IconSample.svg"), INode::Type::Sample); + gn._appendChild(tr("Sound Macros"), QIcon(QStringLiteral(":/icons/IconSoundMacro.svg")), + INode::Type::SoundMacro); + gn._appendChild(tr("ADSRs"), QIcon(QStringLiteral(":/icons/IconADSR.svg")), INode::Type::ADSR); + gn._appendChild(tr("Curves"), QIcon(QStringLiteral(":/icons/IconCurve.svg")), INode::Type::Curve); + gn._appendChild(tr("Keymaps"), QIcon(QStringLiteral(":/icons/IconKeymap.svg")), INode::Type::Keymap); + gn._appendChild(tr("Layers"), QIcon(QStringLiteral(":/icons/IconLayers.svg")), INode::Type::Layer); + gn._appendChild(tr("Samples"), QIcon(QStringLiteral(":/icons/IconSample.svg")), INode::Type::Sample); } void ProjectModel::_buildGroupNode(GroupNode& gn, amuse::AudioGroup& group) { @@ -1736,15 +1737,23 @@ QMimeData* ProjectModel::mimeData(const QModelIndexList& indexes) const { bool ProjectModel::dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) { if (data->hasFormat(QStringLiteral("application/x-amuse-subprojectpath"))) { - auto path = data->data(QStringLiteral("application/x-amuse-subprojectpath")); - QDir oldDir(path); - QString newName = MakeDedupedSubprojectName(oldDir.dirName()); + const auto path = data->data(QStringLiteral("application/x-amuse-subprojectpath")); + const QDir oldDir(QString::fromUtf8(path)); + const QString newName = MakeDedupedSubprojectName(oldDir.dirName()); + m_dir.mkdir(newName); - QDir newDir(QFileInfo(m_dir, newName).filePath()); - for (auto ent : oldDir.entryList({"*.wav", "*.dsp", "*.vadpcm", "!pool.yaml", "!project.yaml"}, QDir::Files)) + + const QDir newDir(QFileInfo(m_dir, newName).filePath()); + const auto entryList = + oldDir.entryList({QStringLiteral("*.wav"), QStringLiteral("*.dsp"), QStringLiteral("*.vadpcm"), + QStringLiteral("!pool.yaml"), QStringLiteral("!project.yaml")}, + QDir::Files); + for (const auto& ent : entryList) { QFile::copy(QFileInfo(oldDir, ent).filePath(), QFileInfo(newDir, ent).filePath()); + } + auto dataNode = std::make_unique(QStringToSysString(newDir.path())); - auto node = amuse::MakeObj(newName); + const auto node = amuse::MakeObj(newName); _buildGroupNode(*node, *dataNode); g_MainWindow->pushUndoCommand( new GroupNodeAddUndoCommand(tr("Add Subproject %1"), std::move(dataNode), node.get())); @@ -1773,14 +1782,16 @@ bool ProjectModel::dropMimeData(const QMimeData* data, Qt::DropAction action, in else if (data->hasFormat(QStringLiteral("application/x-amuse-layers"))) loadMimeData(data, QStringLiteral("application/x-amuse-layers"), gn); else if (data->hasFormat(QStringLiteral("application/x-amuse-samplepath"))) { - auto path = data->data(QStringLiteral("application/x-amuse-samplepath")); - QString newName = MakeDedupedName(QFileInfo(path).completeBaseName(), amuse::SampleId::CurNameDB); - QString newBasePath = QFileInfo(QFileInfo(m_dir, gn->name()).filePath(), newName).filePath(); - amuse::SystemString newBasePathStr = QStringToSysString(newBasePath); + const auto path = data->data(QStringLiteral("application/x-amuse-samplepath")); + const QString newName = + MakeDedupedName(QFileInfo(QString::fromUtf8(path)).completeBaseName(), amuse::SampleId::CurNameDB); + const QString newBasePath = QFileInfo(QFileInfo(m_dir, gn->name()).filePath(), newName).filePath(); + const amuse::SystemString newBasePathStr = QStringToSysString(newBasePath); + gn->getAudioGroup()->copySampleInto(QStringToSysString(QString::fromUtf8(path)), newBasePathStr); auto dataNode = amuse::MakeObj(); dataNode->loadLooseData(newBasePathStr); - auto node = amuse::MakeObj(newName, dataNode); + const auto node = amuse::MakeObj(newName, dataNode); NameUndoRegistry dummy; _addPoolNode(node.get(), gn, dummy, gn->getAudioGroup()->getSdir().sampleEntries()); } else @@ -1860,13 +1871,21 @@ QModelIndex ProjectModel::duplicate(const QModelIndex& index) { GroupNode* gn = getGroupNode(n); switch (n->type()) { case INode::Type::Group: { - GroupNode* cn = static_cast(n); + auto* const cn = static_cast(n); newName = MakeDedupedSubprojectName(n->name()); + m_dir.mkdir(newName); - QDir oldDir(QFileInfo(m_dir, n->name()).filePath()); - QDir newDir(QFileInfo(m_dir, newName).filePath()); - for (auto ent : oldDir.entryList({"*.wav", "*.dsp", "*.vadpcm", "!pool.yaml"}, QDir::Files)) + + const QDir oldDir(QFileInfo(m_dir, n->name()).filePath()); + const QDir newDir(QFileInfo(m_dir, newName).filePath()); + const auto entryList = oldDir.entryList( + {QStringLiteral("*.wav"), QStringLiteral("*.dsp"), QStringLiteral("*.vadpcm"), QStringLiteral("!pool.yaml")}, + QDir::Files); + + for (const auto& ent : entryList) { QFile::copy(QFileInfo(oldDir, ent).filePath(), QFileInfo(newDir, ent).filePath()); + } + auto data = std::make_unique(*cn->getAudioGroup(), QStringToSysString(newDir.path())); auto node = amuse::MakeObj(newName); _buildGroupNode(*node, *data); diff --git a/Editor/ProjectModel.hpp b/Editor/ProjectModel.hpp index 8c006a7..952339a 100644 --- a/Editor/ProjectModel.hpp +++ b/Editor/ProjectModel.hpp @@ -259,7 +259,7 @@ public: amuse::ObjToken m_index; SongGroupNode(const QString& name, amuse::ObjToken index) : INode(name), m_index(index) {} SongGroupNode(amuse::GroupId id, amuse::ObjToken index) - : INode(amuse::GroupId::CurNameDB->resolveNameFromId(id).data()), m_id(id), m_index(index) {} + : INode(QString::fromUtf8(amuse::GroupId::CurNameDB->resolveNameFromId(id).data())), m_id(id), m_index(index) {} static QIcon Icon; Type type() const override { return Type::SongGroup; } @@ -285,7 +285,7 @@ public: amuse::ObjToken m_index; SoundGroupNode(const QString& name, amuse::ObjToken index) : INode(name), m_index(index) {} SoundGroupNode(amuse::GroupId id, amuse::ObjToken index) - : INode(amuse::GroupId::CurNameDB->resolveNameFromId(id).data()), m_id(id), m_index(index) {} + : INode(QString::fromUtf8(amuse::GroupId::CurNameDB->resolveNameFromId(id).data())), m_id(id), m_index(index) {} static QIcon Icon; Type type() const override { return Type::SoundGroup; } @@ -336,7 +336,7 @@ public: amuse::ObjToken m_obj; PoolObjectNode(const QString& name, amuse::ObjToken obj) : BasePoolObjectNode(name), m_obj(obj) {} PoolObjectNode(ID id, amuse::ObjToken obj) - : BasePoolObjectNode(id, ID::CurNameDB->resolveNameFromId(id).data()), m_obj(obj) {} + : BasePoolObjectNode(id, QString::fromUtf8(ID::CurNameDB->resolveNameFromId(id).data())), m_obj(obj) {} Type type() const override { return TP; } AmuseItemEditFlags editFlags() const override { return TP == INode::Type::Sample ? AmuseItemNoCut : AmuseItemAll; } diff --git a/Editor/SongGroupEditor.cpp b/Editor/SongGroupEditor.cpp index 493e3e4..5bc971e 100644 --- a/Editor/SongGroupEditor.cpp +++ b/Editor/SongGroupEditor.cpp @@ -839,7 +839,7 @@ QVariant SetupListModel::data(const QModelIndex& index, int role) const { if (role == Qt::ForegroundRole) return QVariant(); g_MainWindow->projectModel()->setIdDatabases(m_node.get()); - return amuse::SongId::CurNameDB->resolveNameFromId(entry->first.id).data(); + return QString::fromUtf8(amuse::SongId::CurNameDB->resolveNameFromId(entry->first.id).data()); } else if (index.column() == 1) { QString songPath = g_MainWindow->projectModel()->getMIDIPathOfSong(entry.m_it->first); if (songPath.isEmpty()) { diff --git a/Editor/SoundGroupEditor.cpp b/Editor/SoundGroupEditor.cpp index 0ef8c41..72de4cb 100644 --- a/Editor/SoundGroupEditor.cpp +++ b/Editor/SoundGroupEditor.cpp @@ -232,7 +232,7 @@ QVariant SFXModel::data(const QModelIndex& index, int role) const { switch (index.column()) { case 0: { g_MainWindow->projectModel()->setIdDatabases(m_node.get()); - return amuse::SFXId::CurNameDB->resolveNameFromId(entry->first.id).data(); + return QString::fromUtf8(amuse::SFXId::CurNameDB->resolveNameFromId(entry->first.id).data()); } case 1: { ProjectModel::GroupNode* group = g_MainWindow->projectModel()->getGroupNode(m_node.get()); diff --git a/Editor/main.cpp b/Editor/main.cpp index a84991c..b111a9e 100644 --- a/Editor/main.cpp +++ b/Editor/main.cpp @@ -60,12 +60,12 @@ int main(int argc, char* argv[]) { QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); #endif - QApplication::setStyle(new ColoredTabBarStyle(QStyleFactory::create("Fusion"))); + QApplication::setStyle(new ColoredTabBarStyle(QStyleFactory::create(QStringLiteral("Fusion")))); QApplication a(argc, argv); QApplication::setWindowIcon(MakeAppIcon()); - a.setOrganizationName("AxioDL"); - a.setApplicationName("Amuse"); + a.setOrganizationName(QStringLiteral("AxioDL")); + a.setApplicationName(QStringLiteral("Amuse")); QPalette darkPalette; darkPalette.setColor(QPalette::Window, QColor(53, 53, 53)); @@ -102,8 +102,9 @@ int main(int argc, char* argv[]) { Q_INIT_RESOURCE(translation_res); QTranslator translator; - if (translator.load(QLocale(), QLatin1String("lang"), QLatin1String("_"), QLatin1String(":/translations"))) + if (translator.load(QLocale(), QStringLiteral("lang"), QStringLiteral("_"), QStringLiteral(":/translations"))) { a.installTranslator(&translator); + } MainWindow w; g_MainWindow = &w;