3f1ee5df27
* Introduce visible workspaces that are workspaces to be shown in GUI * Introduce method `findByTranslatableName` to be used when seeking `sourceWorkspace`
1373 lines
48 KiB
C++
1373 lines
48 KiB
C++
//=============================================================================
|
|
// MuseScore
|
|
// Linux Music Score Editor
|
|
//
|
|
// Copyright (C) 2011 Werner Schweer and others
|
|
//
|
|
// This program is free software; you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License version 2.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program; if not, write to the Free Software
|
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
//=============================================================================
|
|
|
|
#include "workspace.h"
|
|
#include "musescore.h"
|
|
#include "libmscore/score.h"
|
|
#include "libmscore/imageStore.h"
|
|
#include "libmscore/xml.h"
|
|
#include "thirdparty/qzip/qzipreader_p.h"
|
|
#include "thirdparty/qzip/qzipwriter_p.h"
|
|
#include "preferences.h"
|
|
#include "palette.h"
|
|
#include "palette/paletteworkspace.h"
|
|
#include "extension.h"
|
|
|
|
|
|
namespace Ms {
|
|
|
|
bool WorkspacesManager::isWorkspacesListDirty = true;
|
|
Workspace* WorkspacesManager::m_currentWorkspace = nullptr;
|
|
QList<Workspace*> WorkspacesManager::m_workspaces {};
|
|
QList<Workspace*> WorkspacesManager::m_visibleWorkspaces {};
|
|
|
|
QList<QPair<QAction*, QString>> Workspace::actionToStringList {};
|
|
QList<QPair<QMenu* , QString>> Workspace::menuToStringList {};
|
|
|
|
static const std::vector<QString> defaultWorkspaces {
|
|
QT_TRANSLATE_NOOP("Ms::Workspace", "Basic"),
|
|
QT_TRANSLATE_NOOP("Ms::Workspace", "Advanced"),
|
|
};
|
|
|
|
static const std::vector<QString> defaultEditedWorkpaces {
|
|
QT_TRANSLATE_NOOP("Ms::Workspace", "Basic edited"),
|
|
QT_TRANSLATE_NOOP("Ms::Workspace", "Advanced edited"),
|
|
};
|
|
|
|
//---------------------------------------------------------
|
|
// editedWorkspaceName
|
|
//---------------------------------------------------------
|
|
|
|
static QString editedWorkspaceTranslatableName(const QString& oldWorkspaceTranslatableName)
|
|
{
|
|
if (oldWorkspaceTranslatableName.isEmpty())
|
|
return QString();
|
|
|
|
const auto it = std::find(defaultWorkspaces.begin(), defaultWorkspaces.end(), oldWorkspaceTranslatableName);
|
|
|
|
if (it != defaultWorkspaces.end()) {
|
|
const int idx = it - defaultWorkspaces.begin();
|
|
if (idx < int(defaultEditedWorkpaces.size()))
|
|
return defaultEditedWorkpaces[idx];
|
|
}
|
|
|
|
return QString();
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// editedWorkspaceName
|
|
//---------------------------------------------------------
|
|
|
|
static QString defaultWorkspaceTranslatableName(const QString& editedWorkspaceName)
|
|
{
|
|
const auto it = std::find(defaultEditedWorkpaces.begin(), defaultEditedWorkpaces.end(), editedWorkspaceName);
|
|
|
|
if (it != defaultEditedWorkpaces.end()) {
|
|
const int idx = it - defaultEditedWorkpaces.begin();
|
|
if (idx < int(defaultWorkspaces.size()))
|
|
return defaultWorkspaces[idx];
|
|
}
|
|
|
|
return QString();
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// undoWorkspace
|
|
//---------------------------------------------------------
|
|
|
|
void MuseScore::undoWorkspace()
|
|
{
|
|
// TODO: make a separate session start backup?
|
|
WorkspacesManager::currentWorkspace()->read();
|
|
WorkspacesManager::currentWorkspace()->setDirty(false);
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// showWorkspaceMenu
|
|
//---------------------------------------------------------
|
|
|
|
void MuseScore::showWorkspaceMenu()
|
|
{
|
|
if (workspaces == 0) {
|
|
workspaces = new QActionGroup(this);
|
|
workspaces->setExclusive(true);
|
|
connect(workspaces, SIGNAL(triggered(QAction*)), SLOT(changeWorkspace(QAction*)));
|
|
}
|
|
else {
|
|
for (QAction* a : workspaces->actions())
|
|
workspaces->removeAction(a);
|
|
}
|
|
menuWorkspaces->clear();
|
|
|
|
for (Workspace* p : WorkspacesManager::workspaces()) {
|
|
QAction* a = workspaces->addAction(qApp->translate("Ms::Workspace", p->name().toUtf8()));
|
|
a->setCheckable(true);
|
|
a->setData(p->path());
|
|
a->setChecked(p->name() == preferences.getString(PREF_APP_WORKSPACE));
|
|
menuWorkspaces->addAction(a);
|
|
}
|
|
|
|
menuWorkspaces->addSeparator();
|
|
QAction* a = new QAction(tr("New…"), this);
|
|
connect(a, SIGNAL(triggered()), SLOT(createNewWorkspace()));
|
|
menuWorkspaces->addAction(a);
|
|
|
|
a = new QAction(tr("Edit"), this);
|
|
a->setDisabled(WorkspacesManager::currentWorkspace()->readOnly());
|
|
connect(a, SIGNAL(triggered()), SLOT(editWorkspace()));
|
|
menuWorkspaces->addAction(a);
|
|
|
|
a = new QAction(tr("Delete"), this);
|
|
a->setDisabled(WorkspacesManager::currentWorkspace()->readOnly());
|
|
connect(a, SIGNAL(triggered()), SLOT(deleteWorkspace()));
|
|
menuWorkspaces->addAction(a);
|
|
|
|
a = new QAction(tr("Undo Changes"), this);
|
|
connect(a, SIGNAL(triggered()), SLOT(undoWorkspace()));
|
|
menuWorkspaces->addAction(a);
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// deleteWorkspace
|
|
//---------------------------------------------------------
|
|
|
|
void MuseScore::deleteWorkspace()
|
|
{
|
|
if (!workspaces)
|
|
return;
|
|
QAction* a = workspaces->checkedAction();
|
|
if (!a)
|
|
return;
|
|
|
|
Workspace* workspace = WorkspacesManager::findByName(a->text());
|
|
if (!workspace)
|
|
return;
|
|
|
|
QMessageBox::StandardButton reply;
|
|
reply = QMessageBox::question(0,
|
|
QWidget::tr("Are you sure?"),
|
|
QWidget::tr("Do you really want to delete the '%1' workspace?").arg(workspace->name()),
|
|
QMessageBox::Yes | QMessageBox::No,
|
|
QMessageBox::Yes
|
|
);
|
|
if (reply != QMessageBox::Yes)
|
|
return;
|
|
|
|
WorkspacesManager::remove(workspace->name());
|
|
QFile f(workspace->path());
|
|
f.remove();
|
|
delete workspace;
|
|
WorkspacesManager::setCurrentWorkspace(WorkspacesManager::workspaces().first());
|
|
changeWorkspace(WorkspacesManager::currentWorkspace());
|
|
updateIcons();
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// changeWorkspace
|
|
//---------------------------------------------------------
|
|
|
|
void MuseScore::changeWorkspace(QAction* a)
|
|
{
|
|
changeWorkspace(a->text());
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// changeWorkspace
|
|
//---------------------------------------------------------
|
|
|
|
void MuseScore::changeWorkspace(const QString& name)
|
|
{
|
|
for (Workspace* p : WorkspacesManager::workspaces()) {
|
|
if (qApp->translate("Ms::Workspace", p->name().toUtf8()) == name) {
|
|
changeWorkspace(p);
|
|
return;
|
|
}
|
|
}
|
|
qDebug(" workspace \"%s\" not found", qPrintable(name));
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// changeWorkspace
|
|
//---------------------------------------------------------
|
|
|
|
void MuseScore::changeWorkspace(Workspace* p, bool first)
|
|
{
|
|
if (!first) {
|
|
WorkspacesManager::currentWorkspace()->save();
|
|
if (WorkspacesManager::currentWorkspace())
|
|
disconnect(getPaletteWorkspace(), &PaletteWorkspace::userPaletteChanged, WorkspacesManager::currentWorkspace(), QOverload<>::of(&Workspace::setDirty));
|
|
}
|
|
|
|
|
|
p->read();
|
|
WorkspacesManager::setCurrentWorkspace(p);
|
|
if (!first) {
|
|
updateIcons();
|
|
preferencesChanged(true);
|
|
}
|
|
|
|
connect(getPaletteWorkspace(), &PaletteWorkspace::userPaletteChanged, WorkspacesManager::currentWorkspace(), QOverload<>::of(&Workspace::setDirty), Qt::UniqueConnection);
|
|
|
|
preferences.setPreference(PREF_APP_WORKSPACE, p->name());
|
|
emit mscore->workspacesChanged();
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// updateIcons
|
|
//---------------------------------------------------------
|
|
|
|
void MuseScore::updateIcons()
|
|
{
|
|
setIconSize(QSize(preferences.getInt(PREF_UI_THEME_ICONWIDTH) * guiScaling, preferences.getInt(PREF_UI_THEME_ICONHEIGHT) * guiScaling));
|
|
for (QAction* a : fileTools->actions()) {
|
|
QWidget* widget = fileTools->widgetForAction(a);
|
|
QString className = widget->metaObject()->className();
|
|
if (className != "Ms::AccessibleToolButton" && className != "QToolBarSeparator")
|
|
widget->setFixedHeight(preferences.getInt(PREF_UI_THEME_ICONHEIGHT) + 8); // hack
|
|
// apparently needed for viewModeCombo, see MuseScore::populateFileOperations
|
|
}
|
|
for (QAction* a : cpitchTools->actions()) {
|
|
QWidget* widget = cpitchTools->widgetForAction(a);
|
|
if (widget->property("iconic-text") == true)
|
|
widget->setFixedHeight(preferences.getInt(PREF_UI_THEME_ICONHEIGHT) + 8); // hack
|
|
// so that toolbar buttons with text but no icon can match
|
|
// the height of other toolbar buttons
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// initWorkspace
|
|
//---------------------------------------------------------
|
|
|
|
void WorkspacesManager::initCurrentWorkspace()
|
|
{
|
|
initWorkspaces();
|
|
m_currentWorkspace = findByName(preferences.getString(PREF_APP_WORKSPACE));
|
|
Q_ASSERT(!workspaces().empty());
|
|
if (m_currentWorkspace == 0)
|
|
m_currentWorkspace = workspaces().at(0);
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// writeFailed
|
|
//---------------------------------------------------------
|
|
|
|
static void writeFailed(const QString& _path)
|
|
{
|
|
QString s = qApp->translate("Workspace", "Writing Workspace File\n%1\nfailed: ");
|
|
QMessageBox::critical(mscore, qApp->translate("Workspace", "Writing Workspace File"), s.arg(_path));
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// Workspace
|
|
//---------------------------------------------------------
|
|
|
|
Workspace::Workspace()
|
|
: QObject(0)
|
|
{
|
|
_dirty = false;
|
|
_readOnly = false;
|
|
saveComponents = false;
|
|
saveToolbars = false;
|
|
saveMenuBar = false;
|
|
|
|
_saveTimer.setInterval(0);
|
|
_saveTimer.setSingleShot(true);
|
|
connect(&_saveTimer, &QTimer::timeout, this, &Workspace::ensureWorkspaceSaved);
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// makeUserWorkspacePath
|
|
/// Returns path for the workspace with the given \p name
|
|
/// creating all the necessary directories.
|
|
//---------------------------------------------------------
|
|
|
|
QString WorkspacesManager::makeUserWorkspacePath(const QString& name)
|
|
{
|
|
const QString ext(".workspace");
|
|
QDir dir;
|
|
dir.mkpath(dataPath);
|
|
QString path(dataPath + "/workspaces");
|
|
dir.mkpath(path);
|
|
path += "/" + name + ext;
|
|
return path;
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// write
|
|
//---------------------------------------------------------
|
|
|
|
void Workspace::write()
|
|
{
|
|
if (_path.isEmpty())
|
|
_path = WorkspacesManager::makeUserWorkspacePath(_name);
|
|
|
|
MQZipWriter f(_path);
|
|
f.setCreationPermissions(
|
|
QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner
|
|
| QFile::ReadUser | QFile::WriteUser | QFile::ExeUser
|
|
| QFile::ReadGroup | QFile::WriteGroup | QFile::ExeGroup
|
|
| QFile::ReadOther | QFile::WriteOther | QFile::ExeOther);
|
|
|
|
if (f.status() != MQZipWriter::NoError) {
|
|
writeFailed(_path);
|
|
return;
|
|
}
|
|
|
|
QBuffer cbuf;
|
|
cbuf.open(QIODevice::ReadWrite);
|
|
XmlWriter xml(gscore, &cbuf);
|
|
xml.header();
|
|
xml.stag("container");
|
|
xml.stag("rootfiles");
|
|
xml.stag(QString("rootfile full-path=\"%1\"").arg(XmlWriter::xmlString("workspace.xml")));
|
|
xml.etag();
|
|
for (ImageStoreItem* ip : imageStore) {
|
|
if (!ip->isUsed(gscore))
|
|
continue;
|
|
QString dstPath = QString("Pictures/") + ip->hashName();
|
|
xml.tag("file", dstPath);
|
|
}
|
|
xml.etag();
|
|
xml.etag();
|
|
cbuf.seek(0);
|
|
f.addFile("META-INF/container.xml", cbuf.data());
|
|
|
|
// save images
|
|
for (ImageStoreItem* ip : imageStore) {
|
|
if (!ip->isUsed(gscore))
|
|
continue;
|
|
QString dstPath = QString("Pictures/") + ip->hashName();
|
|
f.addFile(dstPath, ip->buffer());
|
|
}
|
|
{
|
|
xml.setClipboardmode(true);
|
|
xml.header();
|
|
xml.stag("museScore version=\"" MSC_VERSION "\"");
|
|
xml.stag("Workspace");
|
|
// xml.tag("name", _name);
|
|
if (!_sourceWorkspaceName.isEmpty())
|
|
xml.tag("source", _sourceWorkspaceName);
|
|
const PaletteWorkspace* w = mscore->getPaletteWorkspace();
|
|
w->write(xml);
|
|
|
|
// write toolbar settings
|
|
if (saveToolbars) {
|
|
xml.stag("Toolbar name=\"noteInput\"");
|
|
for (auto i : *mscore->noteInputMenuEntries())
|
|
xml.tag("action", i);
|
|
xml.etag();
|
|
xml.stag("Toolbar name=\"fileOperation\"");
|
|
for (auto i : *mscore->fileOperationEntries())
|
|
xml.tag("action", i);
|
|
xml.etag();
|
|
xml.stag("Toolbar name=\"playbackControl\"");
|
|
for (auto i : *mscore->playbackControlEntries())
|
|
xml.tag("action", i);
|
|
xml.etag();
|
|
}
|
|
else {
|
|
writeGlobalToolBar();
|
|
}
|
|
|
|
if (preferences.getUseLocalPreferences()) {
|
|
xml.stag("Preferences");
|
|
for (QString pref : preferences.getLocalPreferences().keys()) {
|
|
QVariant prefValue = preferences.getLocalPreferences().value(pref);
|
|
if (prefValue.isValid())
|
|
xml.tag("Preference name=\"" + pref + "\"", preferences.getLocalPreferences().value(pref));
|
|
}
|
|
xml.etag();
|
|
}
|
|
|
|
if (saveMenuBar)
|
|
writeMenuBar(xml);
|
|
|
|
if (saveComponents) {
|
|
QByteArray state_64 = mscore->saveState().toBase64();
|
|
QString state(state_64);
|
|
xml.tag("State", state);
|
|
}
|
|
else {
|
|
writeGlobalGUIState();
|
|
}
|
|
|
|
xml.etag();
|
|
xml.etag();
|
|
f.addFile("workspace.xml", cbuf.data());
|
|
cbuf.close();
|
|
}
|
|
|
|
if (f.status() != MQZipWriter::NoError)
|
|
writeFailed(_path);
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// writeGlobalMenuBar
|
|
// writes global menu bar for workspaces
|
|
//---------------------------------------------------------
|
|
|
|
void Workspace::writeGlobalMenuBar(QMenuBar* mb)
|
|
{
|
|
QString default_path = "";
|
|
QDir dir;
|
|
dir.mkpath(dataPath);
|
|
default_path = dataPath + "/workspaces";
|
|
dir.mkpath(default_path);
|
|
default_path += "/global";
|
|
dir.mkpath(default_path);
|
|
default_path += "/menubar.xml";
|
|
|
|
QFile default_menubar (default_path);
|
|
default_menubar.open(QIODevice::WriteOnly);
|
|
|
|
if (!default_menubar.exists()) {
|
|
writeFailed(default_path);
|
|
return;
|
|
}
|
|
|
|
QBuffer cbuf;
|
|
cbuf.open(QIODevice::ReadWrite);
|
|
XmlWriter xml(gscore, &cbuf);
|
|
xml.setClipboardmode(true);
|
|
xml.header();
|
|
xml.stag("museScore version=\"" MSC_VERSION "\"");
|
|
|
|
writeMenuBar(xml, mb);
|
|
|
|
xml.etag();
|
|
default_menubar.write(cbuf.data());
|
|
cbuf.close();
|
|
default_menubar.close();
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// writeGlobalToolBar
|
|
// writes global tool bar for workspaces
|
|
//---------------------------------------------------------
|
|
|
|
void Workspace::writeGlobalToolBar()
|
|
{
|
|
QString default_path = "";
|
|
QDir dir;
|
|
dir.mkpath(dataPath);
|
|
default_path = dataPath + "/workspaces";
|
|
dir.mkpath(default_path);
|
|
default_path += "/global";
|
|
dir.mkpath(default_path);
|
|
default_path += "/toolbar.xml";
|
|
|
|
QFile default_toolbar (default_path);
|
|
default_toolbar.open(QIODevice::WriteOnly);
|
|
|
|
if (!default_toolbar.exists()) {
|
|
writeFailed(default_path);
|
|
return;
|
|
}
|
|
|
|
QBuffer cbuf;
|
|
cbuf.open(QIODevice::ReadWrite);
|
|
XmlWriter xml(gscore, &cbuf);
|
|
xml.setClipboardmode(true);
|
|
xml.header();
|
|
xml.stag("museScore version=\"" MSC_VERSION "\"");
|
|
|
|
xml.stag("Toolbar name=\"noteInput\"");
|
|
for (auto i : *mscore->noteInputMenuEntries())
|
|
xml.tag("action", i);
|
|
xml.etag();
|
|
xml.stag("Toolbar name=\"fileOperation\"");
|
|
for (auto i : *mscore->fileOperationEntries())
|
|
xml.tag("action", i);
|
|
xml.etag();
|
|
xml.stag("Toolbar name=\"playbackControl\"");
|
|
for (auto i : *mscore->playbackControlEntries())
|
|
xml.tag("action", i);
|
|
xml.etag();
|
|
|
|
xml.etag();
|
|
default_toolbar.write(cbuf.data());
|
|
cbuf.close();
|
|
default_toolbar.close();
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// writeGlobalGUIState
|
|
// writes global GUI state for workspaces
|
|
//---------------------------------------------------------
|
|
|
|
void Workspace::writeGlobalGUIState()
|
|
{
|
|
QString default_path = "";
|
|
QDir dir;
|
|
dir.mkpath(dataPath);
|
|
default_path = dataPath + "/workspaces";
|
|
dir.mkpath(default_path);
|
|
default_path += "/global";
|
|
dir.mkpath(default_path);
|
|
default_path += "/guistate.xml";
|
|
|
|
QFile default_guistate (default_path);
|
|
default_guistate.open(QIODevice::WriteOnly);
|
|
|
|
if (!default_guistate.exists()) {
|
|
writeFailed(default_path);
|
|
return;
|
|
}
|
|
|
|
QBuffer cbuf;
|
|
cbuf.open(QIODevice::ReadWrite);
|
|
XmlWriter xml(gscore, &cbuf);
|
|
xml.setClipboardmode(true);
|
|
xml.header();
|
|
xml.stag("museScore version=\"" MSC_VERSION "\"");
|
|
|
|
QByteArray state_64 = mscore->saveState().toBase64();
|
|
QString state(state_64);
|
|
xml.tag("State", state);
|
|
|
|
xml.etag();
|
|
default_guistate.write(cbuf.data());
|
|
cbuf.close();
|
|
default_guistate.close();
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// writeMenuBar
|
|
//---------------------------------------------------------
|
|
|
|
void Workspace::writeMenuBar(XmlWriter& xml, QMenuBar* mb)
|
|
{
|
|
// Loop through each menu in menubar. For each menu, call writeMenu.
|
|
xml.stag("MenuBar");
|
|
if (!mb)
|
|
mb = mscore->menuBar();
|
|
for (QAction* action : mb->actions()) {
|
|
if (action->isSeparator())
|
|
xml.tag("action", "");
|
|
else if (action->menu()) {
|
|
const QString menuString = findStringFromMenu(action->menu());
|
|
if (!menuString.isEmpty()) {
|
|
xml.stag("Menu name=\"" + menuString + "\"");
|
|
writeMenu(xml, action->menu());
|
|
xml.etag();
|
|
}
|
|
}
|
|
else {
|
|
const QString actionString = findStringFromAction(action);
|
|
if (!actionString.isEmpty())
|
|
xml.tag("action", actionString);
|
|
}
|
|
|
|
}
|
|
xml.etag();
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// writeMenu
|
|
//---------------------------------------------------------
|
|
|
|
void Workspace::writeMenu(XmlWriter& xml, QMenu* menu)
|
|
{
|
|
// Recursively save QMenu
|
|
for (QAction* action : menu->actions()) {
|
|
if (action->isSeparator())
|
|
xml.tag("action", "");
|
|
else if (action->menu()) {
|
|
const QString menuString = findStringFromMenu(action->menu());
|
|
if (!menuString.isEmpty()) {
|
|
xml.stag("Menu name=\"" + menuString + "\"");
|
|
writeMenu(xml, action->menu());
|
|
xml.etag();
|
|
}
|
|
}
|
|
else {
|
|
const QString actionString = findStringFromAction(action);
|
|
if (!actionString.isEmpty())
|
|
xml.tag("action", actionString);
|
|
}
|
|
}
|
|
}
|
|
|
|
extern QString readRootFile(MQZipReader*, QList<QString>&);
|
|
|
|
//---------------------------------------------------------
|
|
// read
|
|
//---------------------------------------------------------
|
|
|
|
void WorkspacesManager::readWorkspaceFile(const QString& path, std::function<void(XmlReader&)> readWorkspace)
|
|
{
|
|
MQZipReader f(path);
|
|
QList<QString> images;
|
|
QString rootfile = readRootFile(&f, images);
|
|
//
|
|
// load images
|
|
//
|
|
for (const QString& s : images)
|
|
imageStore.add(s, f.fileData(s));
|
|
|
|
if (rootfile.isEmpty()) {
|
|
qDebug("can't find rootfile in: %s", qPrintable(path));
|
|
return;
|
|
}
|
|
|
|
QByteArray ba = f.fileData(rootfile);
|
|
XmlReader e(ba);
|
|
|
|
while (e.readNextStartElement()) {
|
|
if (e.name() == "museScore") {
|
|
while (e.readNextStartElement()) {
|
|
if (e.name() == "Workspace")
|
|
readWorkspace(e);
|
|
else
|
|
e.unknown();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void Workspace::read()
|
|
{
|
|
saveToolbars = saveMenuBar = saveComponents = false;
|
|
preferences.setUseLocalPreferences(false);
|
|
if (_path.isEmpty() || !QFile(_path).exists()) {
|
|
qDebug("cannot read workspace <%s>", qPrintable(_path));
|
|
mscore->setDefaultPalette();
|
|
readGlobalMenuBar();
|
|
readGlobalToolBar();
|
|
readGlobalGUIState();
|
|
preferences.updateLocalPreferences();
|
|
return;
|
|
}
|
|
QFileInfo fi(_path);
|
|
_readOnly = !fi.isWritable();
|
|
|
|
preferences.updateLocalPreferences();
|
|
|
|
WorkspacesManager::readWorkspaceFile(_path, [this](XmlReader& e) { read(e); });
|
|
}
|
|
|
|
std::unique_ptr<PaletteTree> Workspace::getPaletteTree() const
|
|
{
|
|
std::unique_ptr<PaletteTree> paletteTree(new PaletteTree);
|
|
WorkspacesManager::readWorkspaceFile(_path, [&](XmlReader& e) {
|
|
while (e.readNextStartElement()) {
|
|
if (e.name() == "PaletteBox")
|
|
paletteTree->read(e);
|
|
else
|
|
e.skipCurrentElement();
|
|
}
|
|
});
|
|
return paletteTree;
|
|
}
|
|
|
|
void Workspace::read(XmlReader& e)
|
|
{
|
|
bool niToolbar = false;
|
|
bool foToolbar = false;
|
|
bool pcToolbar = false;
|
|
while (e.readNextStartElement()) {
|
|
const QStringRef& tag(e.name());
|
|
if (tag == "name")
|
|
e.readElementText();
|
|
else if (tag == "source")
|
|
_sourceWorkspaceName = e.readElementText();
|
|
else if (tag == "PaletteBox") {
|
|
PaletteWorkspace* w = mscore->getPaletteWorkspace();
|
|
w->read(e);
|
|
}
|
|
else if (tag == "Toolbar") {
|
|
saveToolbars = true;
|
|
QString name = e.attribute("name");
|
|
std::list<const char *> toolbarEntries;
|
|
if (name == "noteInput")
|
|
toolbarEntries = mscore->allNoteInputMenuEntries();
|
|
else if (name == "fileOperation")
|
|
toolbarEntries = mscore->allFileOperationEntries();
|
|
else if (name == "playbackControl")
|
|
toolbarEntries = mscore->allPlaybackControlEntries();
|
|
else
|
|
qDebug() << "Error in loading workspace: " + name + " is not a toolbar";
|
|
|
|
std::list<const char*> l;
|
|
while (e.readNextStartElement()) {
|
|
const QStringRef& t(e.name());
|
|
if (t == "action") {
|
|
QString s = e.readElementText();
|
|
for (auto k : toolbarEntries) {
|
|
if (k == s) {
|
|
l.push_back(k);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
e.unknown();
|
|
}
|
|
if (name == "noteInput") {
|
|
mscore->setNoteInputMenuEntries(l);
|
|
mscore->populateNoteInputMenu();
|
|
niToolbar = true;
|
|
}
|
|
else if (name == "fileOperation") {
|
|
mscore->setFileOperationEntries(l);
|
|
mscore->populateFileOperations();
|
|
foToolbar = true;
|
|
}
|
|
else if (name == "playbackControl") {
|
|
mscore->setPlaybackControlEntries(l);
|
|
mscore->populatePlaybackControls();
|
|
pcToolbar = true;
|
|
}
|
|
}
|
|
else if (tag == "Preferences") {
|
|
preferences.setUseLocalPreferences(true);
|
|
while (e.readNextStartElement()) {
|
|
QString preference_name = e.attribute("name");
|
|
switch (preferences.defaultValue(preference_name).type()) {
|
|
case QVariant::Int:
|
|
{
|
|
int new_int = e.readInt();
|
|
preferences.setLocalPreference(preference_name, QVariant(new_int));
|
|
}
|
|
break;
|
|
case QVariant::Color:
|
|
{
|
|
QColor new_color = e.readColor();
|
|
preferences.setLocalPreference(preference_name, QVariant(new_color));
|
|
}
|
|
break;
|
|
case QVariant::String:
|
|
{
|
|
QString new_string = e.readXml();
|
|
preferences.setLocalPreference(preference_name, QVariant(new_string));
|
|
}
|
|
break;
|
|
case QVariant::Bool:
|
|
{
|
|
bool new_bool = e.readBool();
|
|
preferences.setLocalPreference(preference_name, QVariant(new_bool));
|
|
}
|
|
break;
|
|
case QVariant::LongLong:
|
|
{
|
|
bool new_longlong = e.readLongLong();
|
|
preferences.setLocalPreference(preference_name, QVariant(new_longlong));
|
|
break;
|
|
}
|
|
default:
|
|
qDebug() << preferences.defaultValue(preference_name).type() << " not handled.";
|
|
e.unknown();
|
|
}
|
|
}
|
|
}
|
|
else if (tag == "MenuBar") {
|
|
saveMenuBar = true;
|
|
QMenuBar* mb = mscore->menuBar();
|
|
const QObjectList menus(mb->children()); // need a copy
|
|
for (QObject* m : menus) {
|
|
if (qobject_cast<QMenu*>(m)) {
|
|
m->setParent(nullptr);
|
|
m->deleteLater();
|
|
}
|
|
}
|
|
mb->clear();
|
|
menuToStringList.clear();
|
|
while (e.readNextStartElement()) {
|
|
if (e.hasAttribute("name")) { // is a menu
|
|
QString menu_id = e.attribute("name");
|
|
QMenu* menu = mb->addMenu(menu_id);
|
|
addMenuAndString(menu, menu_id);
|
|
readMenu(e, menu);
|
|
}
|
|
else { // is an action
|
|
QString action_id = e.readXml();
|
|
if (action_id.isEmpty())
|
|
mb->addSeparator();
|
|
else {
|
|
QAction* action = findActionFromString(action_id);
|
|
mb->addAction(action);
|
|
}
|
|
}
|
|
}
|
|
mscore->updateMenus();
|
|
}
|
|
else if (tag == "State") {
|
|
saveComponents = true;
|
|
QString state_string = e.readXml();
|
|
QByteArray state_byte_array_64(state_string.toUtf8());
|
|
QByteArray state_byte_array = QByteArray::fromBase64(state_byte_array_64);
|
|
mscore->restoreState(state_byte_array);
|
|
}
|
|
else
|
|
e.unknown();
|
|
}
|
|
if (saveToolbars) {
|
|
if (!niToolbar) {
|
|
mscore->setNoteInputMenuEntries(mscore->allNoteInputMenuEntries());
|
|
mscore->populateNoteInputMenu();
|
|
}
|
|
if (!foToolbar) {
|
|
mscore->setFileOperationEntries(mscore->allFileOperationEntries());
|
|
mscore->populateFileOperations();
|
|
}
|
|
if (!pcToolbar) {
|
|
mscore->setPlaybackControlEntries(mscore->allPlaybackControlEntries());
|
|
mscore->populatePlaybackControls();
|
|
}
|
|
}
|
|
else {
|
|
readGlobalToolBar();
|
|
}
|
|
if (!saveMenuBar)
|
|
readGlobalMenuBar();
|
|
if (!saveComponents)
|
|
readGlobalGUIState();
|
|
|
|
if (const Workspace* src = sourceWorkspace())
|
|
mscore->getPaletteWorkspace()->setDefaultPaletteTree(src->getPaletteTree());
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// readMenu
|
|
//---------------------------------------------------------
|
|
|
|
void Workspace::readMenu(XmlReader& e, QMenu* menu)
|
|
{
|
|
while (e.readNextStartElement()) {
|
|
if (e.hasAttribute("name")) { // is a menu
|
|
QString menu_id = e.attribute("name");
|
|
QMenu* new_menu = menu->addMenu(menu_id);
|
|
addMenuAndString(new_menu, menu_id);
|
|
readMenu(e, new_menu);
|
|
}
|
|
else { // is an action
|
|
QString action_id = e.readXml();
|
|
if (action_id.isEmpty())
|
|
menu->addSeparator();
|
|
else {
|
|
QAction* action = findActionFromString(action_id);
|
|
menu->addAction(action);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// readGlobalMenuBar
|
|
//---------------------------------------------------------
|
|
|
|
void Workspace::readGlobalMenuBar()
|
|
{
|
|
QString default_path = dataPath + "/workspaces/global/menubar.xml";
|
|
|
|
QFile default_menubar(default_path);
|
|
default_menubar.open(QIODevice::ReadOnly);
|
|
|
|
QByteArray ba (default_menubar.readAll());
|
|
XmlReader e(ba);
|
|
|
|
while (e.readNextStartElement()) {
|
|
if (e.name() == "museScore") {
|
|
while (e.readNextStartElement()) {
|
|
if (e.name() == "MenuBar") {
|
|
QMenuBar* mb = mscore->menuBar();
|
|
const QObjectList menus(mb->children()); // need a copy
|
|
for (QObject* m : menus) {
|
|
if (qobject_cast<QMenu*>(m)) {
|
|
m->setParent(nullptr);
|
|
m->deleteLater();
|
|
}
|
|
}
|
|
mb->clear();
|
|
menuToStringList.clear();
|
|
while (e.readNextStartElement()) {
|
|
if (e.hasAttribute("name")) { // is a menu
|
|
QString menu_id = e.attribute("name");
|
|
QMenu* menu = mb->addMenu(menu_id);
|
|
addMenuAndString(menu, menu_id);
|
|
readMenu(e, menu);
|
|
}
|
|
else { // is an action
|
|
QString action_id = e.readXml();
|
|
if (action_id.isEmpty())
|
|
mb->addSeparator();
|
|
else {
|
|
QAction* action = findActionFromString(action_id);
|
|
mb->addAction(action);
|
|
}
|
|
}
|
|
}
|
|
mscore->updateMenus();
|
|
}
|
|
else
|
|
e.unknown();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// readGlobalToolBar
|
|
//---------------------------------------------------------
|
|
|
|
void Workspace::readGlobalToolBar()
|
|
{
|
|
QString default_path = dataPath + "/workspaces/global/toolbar.xml";
|
|
|
|
QFile default_toolbar(default_path);
|
|
default_toolbar.open(QIODevice::ReadOnly);
|
|
|
|
QByteArray ba (default_toolbar.readAll());
|
|
XmlReader e(ba);
|
|
|
|
while (e.readNextStartElement()) {
|
|
if (e.name() == "museScore") {
|
|
while (e.readNextStartElement()) {
|
|
if (e.name() == "ToolBar") {
|
|
QString name = e.attribute("name");
|
|
std::list<const char *> toolbarEntries;
|
|
if (name == "noteInput")
|
|
toolbarEntries = mscore->allNoteInputMenuEntries();
|
|
else if (name == "fileOperation")
|
|
toolbarEntries = mscore->allFileOperationEntries();
|
|
else if (name == "playbackControl")
|
|
toolbarEntries = mscore->allPlaybackControlEntries();
|
|
else
|
|
qDebug() << "Error in loading workspace: " + name + " is not a toolbar";
|
|
|
|
std::list<const char*> l;
|
|
while (e.readNextStartElement()) {
|
|
const QStringRef& tag(e.name());
|
|
if (tag == "action") {
|
|
QString s = e.readElementText();
|
|
for (auto k : toolbarEntries) {
|
|
if (k == s) {
|
|
l.push_back(k);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
e.unknown();
|
|
}
|
|
if (name == "noteInput") {
|
|
mscore->setNoteInputMenuEntries(l);
|
|
mscore->populateNoteInputMenu();
|
|
}
|
|
else if (name == "fileOperation") {
|
|
mscore->setFileOperationEntries(l);
|
|
mscore->populateFileOperations();
|
|
}
|
|
else if (name == "playbackControl") {
|
|
mscore->setPlaybackControlEntries(l);
|
|
mscore->populatePlaybackControls();
|
|
}
|
|
}
|
|
else
|
|
e.unknown();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// readGlobalGUIState
|
|
//---------------------------------------------------------
|
|
|
|
void Workspace::readGlobalGUIState()
|
|
{
|
|
QString default_path = dataPath + "/workspaces/global/guistate.xml";
|
|
|
|
QFile default_toolbar(default_path);
|
|
default_toolbar.open(QIODevice::ReadOnly);
|
|
|
|
QByteArray ba (default_toolbar.readAll());
|
|
XmlReader e(ba);
|
|
|
|
while (e.readNextStartElement()) {
|
|
if (e.name() == "museScore") {
|
|
while (e.readNextStartElement()) {
|
|
if (e.name() == "State") {
|
|
QString state_string = e.readXml();
|
|
QByteArray state_byte_array_64(state_string.toUtf8());
|
|
QByteArray state_byte_array = QByteArray::fromBase64(state_byte_array_64);
|
|
mscore->restoreState(state_byte_array);
|
|
}
|
|
else
|
|
e.unknown();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// ensureWorkspaceSaved
|
|
//---------------------------------------------------------
|
|
|
|
void Workspace::ensureWorkspaceSaved()
|
|
{
|
|
if (!_dirty)
|
|
return;
|
|
|
|
if (_readOnly) {
|
|
setTranslatableName(editedWorkspaceTranslatableName(translatableName()));
|
|
|
|
if (translatableName().isEmpty()) {
|
|
/*: Name of the edited read-only workspace, %1 is replaced with the old workspace name */
|
|
setName(tr("%1 edited").arg(name()));
|
|
}
|
|
else
|
|
setName(tr(translatableName().toUtf8()));
|
|
|
|
_path = WorkspacesManager::makeUserWorkspacePath(translatableName().isEmpty() ? name() : translatableName());
|
|
|
|
write();
|
|
|
|
const QFileInfo fi(_path);
|
|
_readOnly = !fi.isWritable();
|
|
Q_ASSERT(!_readOnly);
|
|
|
|
preferences.setPreference(PREF_APP_WORKSPACE, name());
|
|
emit mscore->workspacesChanged();
|
|
}
|
|
else
|
|
write();
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// setDirty
|
|
//---------------------------------------------------------
|
|
|
|
void Workspace::setDirty(bool val)
|
|
{
|
|
_dirty = val;
|
|
_saveTimer.start();
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// save
|
|
//---------------------------------------------------------
|
|
|
|
void Workspace::save()
|
|
{
|
|
if (!saveComponents)
|
|
writeGlobalGUIState();
|
|
if (!saveToolbars)
|
|
writeGlobalToolBar();
|
|
|
|
if (_readOnly)
|
|
return;
|
|
|
|
write();
|
|
}
|
|
|
|
static QStringList findWorkspaceFiles()
|
|
{
|
|
QStringList path;
|
|
path << mscoreGlobalShare + "workspaces";
|
|
path << dataPath + "/workspaces";
|
|
|
|
QStringList extensionsDir = Extension::getDirectoriesByType(Extension::workspacesDir);
|
|
path.append(extensionsDir);
|
|
|
|
QStringList nameFilters;
|
|
nameFilters << "*.workspace";
|
|
|
|
QStringList workspaces;
|
|
|
|
for (const QString& s : path) {
|
|
QDir dir(s);
|
|
QStringList pl = dir.entryList(nameFilters, QDir::Files, QDir::Name);
|
|
|
|
for (const QString& entry : pl) {
|
|
const QString workspacePath(s + "/" + entry);
|
|
workspaces << workspacePath;
|
|
}
|
|
}
|
|
|
|
return workspaces;
|
|
}
|
|
|
|
void WorkspacesManager::initWorkspaces()
|
|
{
|
|
if (!isWorkspacesListDirty)
|
|
return;
|
|
|
|
QList<Workspace*> oldWorkspaces(m_workspaces);
|
|
QList<Workspace*> editedWorkpaces;
|
|
|
|
for (const QString& path : findWorkspaceFiles()) {
|
|
Workspace* p = 0;
|
|
QFileInfo fi(path);
|
|
QString name(fi.completeBaseName());
|
|
|
|
const bool isDefault = std::find(defaultWorkspaces.begin(), defaultWorkspaces.end(), name) != defaultWorkspaces.end();
|
|
const bool isEditedDefault = std::find(defaultEditedWorkpaces.begin(), defaultEditedWorkpaces.end(), name) != defaultEditedWorkpaces.end();
|
|
|
|
const bool translate = isDefault || isEditedDefault;
|
|
|
|
for (Workspace* w : m_workspaces) {
|
|
if (w->name() == name || (translate && w->translatableName() == name)) {
|
|
p = w;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (p)
|
|
oldWorkspaces.removeOne(p);
|
|
else {
|
|
p = new Workspace;
|
|
m_workspaces.append(p);
|
|
}
|
|
|
|
p->setPath(path);
|
|
p->setName(name);
|
|
|
|
if (translate)
|
|
p->setTranslatableName(name);
|
|
|
|
p->setReadOnly(!fi.isWritable());
|
|
|
|
if (isEditedDefault)
|
|
editedWorkpaces.push_back(p);
|
|
}
|
|
|
|
for (Workspace* old : oldWorkspaces)
|
|
m_workspaces.removeOne(old);
|
|
|
|
// Delete default workspaces if there are corresponding user-edited ones
|
|
m_visibleWorkspaces = m_workspaces;
|
|
for (Workspace* ew : editedWorkpaces) {
|
|
const QString uneditedName = defaultWorkspaceTranslatableName(ew->translatableName());
|
|
if (uneditedName.isEmpty())
|
|
continue;
|
|
|
|
for (auto it = m_visibleWorkspaces.begin(); it != m_visibleWorkspaces.end(); ++it) {
|
|
Workspace* w = *it;
|
|
if (w->translatableName() == uneditedName) {
|
|
m_visibleWorkspaces.erase(it);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (m_workspaces.empty())
|
|
qFatal("No workspaces found");
|
|
|
|
if (oldWorkspaces.contains(WorkspacesManager::currentWorkspace()))
|
|
WorkspacesManager::setCurrentWorkspace(m_workspaces.first());
|
|
|
|
qDeleteAll(oldWorkspaces);
|
|
|
|
// hack
|
|
for (int i = 0; i < m_workspaces.size(); i++) {
|
|
const QString& trName = m_workspaces[i]->translatableName();
|
|
if (trName == defaultWorkspaces[0] || trName == defaultEditedWorkpaces[0]) {
|
|
m_workspaces.move(i, 0);
|
|
break;
|
|
}
|
|
}
|
|
retranslate(m_workspaces);
|
|
isWorkspacesListDirty = false;
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// refreshWorkspaces
|
|
//---------------------------------------------------------
|
|
|
|
void WorkspacesManager::refreshWorkspaces()
|
|
{
|
|
isWorkspacesListDirty = true;
|
|
initWorkspaces();
|
|
}
|
|
|
|
const Workspace* Workspace::sourceWorkspace() const
|
|
{
|
|
const QString sourceName = _sourceWorkspaceName.isEmpty() ? defaultWorkspaces[0] : _sourceWorkspaceName;
|
|
|
|
if (translatableName() == sourceName || name() == sourceName)
|
|
return this;
|
|
|
|
Workspace* sourceWorkspace = WorkspacesManager::findByName(sourceName);
|
|
if (!sourceWorkspace)
|
|
sourceWorkspace = WorkspacesManager::findByTranslatableName(sourceName);
|
|
|
|
return !!sourceWorkspace ? sourceWorkspace : WorkspacesManager::workspaces()[0];
|
|
}
|
|
|
|
void WorkspacesManager::retranslate(QList<Workspace*>& workspacesList)
|
|
{
|
|
for (auto w : workspacesList) {
|
|
if (!w->translatableName().isEmpty()) {
|
|
auto transName = qApp->translate("Ms::Workspace", w->translatableName().toLatin1().constData());
|
|
w->setName(transName);
|
|
}
|
|
}
|
|
}
|
|
|
|
void WorkspacesManager::retranslateAll()
|
|
{
|
|
retranslate(m_workspaces);
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// createNewWorkspace
|
|
//---------------------------------------------------------
|
|
|
|
Workspace* WorkspacesManager::createNewWorkspace(const QString& name)
|
|
{
|
|
Workspace* w = new Workspace;
|
|
w->setName(name);
|
|
w->setPath("");
|
|
w->setDirty(false);
|
|
w->setReadOnly(false);
|
|
w->write();
|
|
|
|
m_workspaces.append(w);
|
|
return w;
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// addActionAndString
|
|
//---------------------------------------------------------
|
|
|
|
void Workspace::addActionAndString(QAction* action, QString string)
|
|
{
|
|
QPair<QAction*, QString> pair;
|
|
pair.first = action;
|
|
pair.second = string;
|
|
actionToStringList.append(pair);
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// addRemainingFromMenuBar
|
|
//---------------------------------------------------------
|
|
|
|
void Workspace::addRemainingFromMenuBar(QMenuBar* mb)
|
|
{
|
|
// Loop through each menu in menubar. For each menu, call writeMenu.
|
|
for (QAction* action : mb->actions()) {
|
|
if (action->isSeparator())
|
|
continue;
|
|
else if (action->menu())
|
|
addRemainingFromMenu(action->menu());
|
|
else if (!action->data().toString().isEmpty())
|
|
addActionAndString(action, action->data().toString());
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// addRemainingFromMenu
|
|
//---------------------------------------------------------
|
|
|
|
void Workspace::addRemainingFromMenu(QMenu* menu)
|
|
{
|
|
// Recursively save QMenu
|
|
for (QAction* action : menu->actions()) {
|
|
if (action->isSeparator())
|
|
continue;
|
|
else if (action->menu())
|
|
addRemainingFromMenu(action->menu());
|
|
else if (!action->data().toString().isEmpty())
|
|
addActionAndString(action, action->data().toString());
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// findActionFromString
|
|
//---------------------------------------------------------
|
|
|
|
QAction* Workspace::findActionFromString(QString string)
|
|
{
|
|
for (auto pair : actionToStringList) {
|
|
if (pair.second == string)
|
|
return pair.first;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// findStringFromAction
|
|
//---------------------------------------------------------
|
|
|
|
QString Workspace::findStringFromAction(QAction* action)
|
|
{
|
|
for (auto pair : actionToStringList) {
|
|
if (pair.first == action)
|
|
return pair.second;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// addMenuAndString
|
|
//---------------------------------------------------------
|
|
|
|
void Workspace::addMenuAndString(QMenu* menu, QString string)
|
|
{
|
|
QPair<QMenu*, QString> pair;
|
|
pair.first = menu;
|
|
pair.second = string;
|
|
menuToStringList.append(pair);
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// findMenuFromString
|
|
//---------------------------------------------------------
|
|
|
|
QMenu* Workspace::findMenuFromString(QString string)
|
|
{
|
|
for (auto pair : menuToStringList) {
|
|
if (pair.second == string)
|
|
return pair.first;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// findStringFromMenu
|
|
//---------------------------------------------------------
|
|
|
|
QString Workspace::findStringFromMenu(QMenu* menu)
|
|
{
|
|
for (auto pair : menuToStringList) {
|
|
if (pair.first == menu)
|
|
return pair.second;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// rename
|
|
//---------------------------------------------------------
|
|
|
|
void Workspace::rename(const QString& s)
|
|
{
|
|
const QString newPath = WorkspacesManager::makeUserWorkspacePath(s);
|
|
|
|
QFile file(_path);
|
|
if (file.exists())
|
|
file.rename(newPath);
|
|
|
|
setName(s);
|
|
_path = newPath;
|
|
save();
|
|
}
|
|
}
|