MuseScore/mscore/workspace.cpp

486 lines
15 KiB
C++
Raw Normal View History

2012-05-26 14:49:10 +02:00
//=============================================================================
// 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.
//=============================================================================
2013-02-06 16:43:25 +01:00
#include "workspace.h"
2012-05-26 14:49:10 +02:00
#include "musescore.h"
#include "libmscore/score.h"
#include "libmscore/imageStore.h"
#include "libmscore/xml.h"
#include "libmscore/qzipreader_p.h"
#include "libmscore/qzipwriter_p.h"
#include "preferences.h"
#include "palette.h"
2013-02-10 14:50:18 +01:00
#include "palettebox.h"
2012-05-26 14:49:10 +02:00
2013-05-13 18:49:17 +02:00
namespace Ms {
2013-02-10 14:50:18 +01:00
bool Workspace::workspacesRead = false;
QList<Workspace*> Workspace::_workspaces;
Workspace* Workspace::currentWorkspace;
2013-02-08 11:36:50 +01:00
//---------------------------------------------------------
// undoWorkspace
//---------------------------------------------------------
void MuseScore::undoWorkspace()
{
2013-02-10 14:50:18 +01:00
Workspace::currentWorkspace->read();
Workspace::currentWorkspace->setDirty(false);
2013-02-07 17:34:44 +01:00
}
2012-05-26 14:49:10 +02:00
//---------------------------------------------------------
2013-02-06 16:43:25 +01:00
// showWorkspaceMenu
2012-05-26 14:49:10 +02:00
//---------------------------------------------------------
2013-02-06 16:43:25 +01:00
void MuseScore::showWorkspaceMenu()
2012-05-26 14:49:10 +02:00
{
2013-02-08 11:36:50 +01:00
if (workspaces == 0) {
workspaces = new QActionGroup(this);
workspaces->setExclusive(true);
connect(workspaces, SIGNAL(triggered(QAction*)), SLOT(changeWorkspace(QAction*)));
2012-05-26 14:49:10 +02:00
}
else {
2013-02-08 11:36:50 +01:00
foreach(QAction* a, workspaces->actions())
workspaces->removeAction(a);
2012-05-26 14:49:10 +02:00
}
2013-02-06 16:43:25 +01:00
menuWorkspaces->clear();
2012-05-26 14:49:10 +02:00
2013-02-08 11:36:50 +01:00
const QList<Workspace*> pl = Workspace::workspaces();
2013-02-06 16:43:25 +01:00
foreach (Workspace* p, pl) {
2013-02-08 11:36:50 +01:00
QAction* a = workspaces->addAction(p->name());
2012-05-26 14:49:10 +02:00
a->setCheckable(true);
a->setData(p->path());
2013-02-10 14:50:18 +01:00
a->setChecked(a->text() == preferences.workspace);
2013-02-06 16:43:25 +01:00
menuWorkspaces->addAction(a);
2012-05-26 14:49:10 +02:00
}
2013-02-10 14:50:18 +01:00
2013-02-06 16:43:25 +01:00
menuWorkspaces->addSeparator();
2013-02-08 11:36:50 +01:00
QAction* a = new QAction(tr("New"), this);
2013-02-06 16:43:25 +01:00
connect(a, SIGNAL(triggered()), SLOT(createNewWorkspace()));
menuWorkspaces->addAction(a);
2013-02-07 17:34:44 +01:00
2013-02-08 11:36:50 +01:00
a = new QAction(tr("Delete"), this);
2013-02-10 14:50:18 +01:00
a->setDisabled(Workspace::currentWorkspace->readOnly());
2013-02-08 11:36:50 +01:00
connect(a, SIGNAL(triggered()), SLOT(deleteWorkspace()));
menuWorkspaces->addAction(a);
2013-02-07 17:34:44 +01:00
2013-02-08 11:36:50 +01:00
a = new QAction(tr("Undo Changes"), this);
2013-02-10 14:50:18 +01:00
a->setDisabled(Workspace::currentWorkspace->readOnly());
2013-02-08 11:36:50 +01:00
connect(a, SIGNAL(triggered()), SLOT(undoWorkspace()));
menuWorkspaces->addAction(a);
2012-05-26 14:49:10 +02:00
}
//---------------------------------------------------------
2013-02-06 16:43:25 +01:00
// createNewWorkspace
2012-05-26 14:49:10 +02:00
//---------------------------------------------------------
2013-02-06 16:43:25 +01:00
void MuseScore::createNewWorkspace()
2012-05-26 14:49:10 +02:00
{
2013-02-06 16:43:25 +01:00
QString s = QInputDialog::getText(this, tr("MuseScore: Read Workspace Name"),
tr("Workspace Name:"));
2012-05-26 14:49:10 +02:00
if (s.isEmpty())
return;
for (;;) {
bool notFound = true;
2013-02-08 11:36:50 +01:00
foreach(Workspace* p, Workspace::workspaces()) {
2012-05-26 14:49:10 +02:00
if (p->name() == s) {
notFound = false;
break;
}
}
if (!notFound) {
s = QInputDialog::getText(this,
2013-02-06 16:43:25 +01:00
tr("MuseScore: Read Workspace Name"),
2012-05-26 14:49:10 +02:00
QString(tr("'%1' does already exist,\nplease choose a different name:")).arg(s)
);
if (s.isEmpty())
return;
}
else
break;
}
2013-05-07 13:51:50 +02:00
if (Workspace::currentWorkspace->dirty())
Workspace::currentWorkspace->save();
2013-02-10 14:50:18 +01:00
Workspace::currentWorkspace = Workspace::createNewWorkspace(s);
2013-02-15 19:25:00 +01:00
preferences.workspace = Workspace::currentWorkspace->name();
2013-05-07 13:51:50 +02:00
preferences.dirty = true;
2012-05-26 14:49:10 +02:00
}
//---------------------------------------------------------
2013-02-06 16:43:25 +01:00
// deleteWorkspace
2012-05-26 14:49:10 +02:00
//---------------------------------------------------------
2013-02-06 16:43:25 +01:00
void MuseScore::deleteWorkspace()
2012-05-26 14:49:10 +02:00
{
2013-02-08 11:36:50 +01:00
if (!workspaces)
2012-05-26 14:49:10 +02:00
return;
2013-02-08 11:36:50 +01:00
QAction* a = workspaces->checkedAction();
2012-05-26 14:49:10 +02:00
if (!a)
return;
preferences.dirty = true;
2013-02-08 11:36:50 +01:00
Workspace* workspace = 0;
foreach(Workspace* p, Workspace::workspaces()) {
2012-05-26 14:49:10 +02:00
if (p->name() == a->text()) {
2013-02-08 11:36:50 +01:00
workspace = p;
2012-05-26 14:49:10 +02:00
break;
}
}
2013-02-08 11:36:50 +01:00
if (!workspace)
2012-05-26 14:49:10 +02:00
return;
2013-02-08 11:36:50 +01:00
Workspace::workspaces().removeOne(workspace);
QFile f(workspace->path());
2012-05-26 14:49:10 +02:00
f.remove();
2013-02-15 19:25:00 +01:00
delete workspace;
Workspace::currentWorkspace = Workspace::workspaces().first();
preferences.workspace = Workspace::currentWorkspace->name();
2012-05-26 14:49:10 +02:00
}
//---------------------------------------------------------
2013-02-06 16:43:25 +01:00
// changeWorkspace
2012-05-26 14:49:10 +02:00
//---------------------------------------------------------
2013-02-06 16:43:25 +01:00
void MuseScore::changeWorkspace(QAction* a)
2012-05-26 14:49:10 +02:00
{
2013-02-08 11:36:50 +01:00
preferences.workspace = a->text();
2012-05-26 14:49:10 +02:00
preferences.dirty = true;
2013-02-08 11:36:50 +01:00
foreach(Workspace* p, Workspace::workspaces()) {
2012-05-26 14:49:10 +02:00
if (p->name() == a->text()) {
2013-02-06 16:43:25 +01:00
changeWorkspace(p);
2012-05-26 14:49:10 +02:00
return;
}
}
2013-02-08 11:36:50 +01:00
qDebug(" workspace not found");
2012-05-26 14:49:10 +02:00
}
//---------------------------------------------------------
2013-02-06 16:43:25 +01:00
// changeWorkspace
2012-05-26 14:49:10 +02:00
//---------------------------------------------------------
2013-02-06 16:43:25 +01:00
void MuseScore::changeWorkspace(Workspace* p)
2012-05-26 14:49:10 +02:00
{
2013-02-10 14:50:18 +01:00
Workspace::currentWorkspace->save();
2012-05-26 14:49:10 +02:00
p->read();
2013-02-10 14:50:18 +01:00
Workspace::currentWorkspace = p;
2012-05-26 14:49:10 +02:00
}
//---------------------------------------------------------
2013-02-06 16:43:25 +01:00
// initWorkspace
2012-05-26 14:49:10 +02:00
//---------------------------------------------------------
2013-02-10 14:50:18 +01:00
void Workspace::initWorkspace()
2012-05-26 14:49:10 +02:00
{
2013-02-08 11:36:50 +01:00
foreach(Workspace* p, Workspace::workspaces()) {
if (p->name() == preferences.workspace) {
2013-02-10 14:50:18 +01:00
currentWorkspace = p;
2012-05-26 14:49:10 +02:00
break;
}
}
2013-02-10 14:50:18 +01:00
if (currentWorkspace == 0) {
currentWorkspace = new Workspace;
currentWorkspace->setName("default");
Workspace::workspaces().append(currentWorkspace);
2012-05-26 14:49:10 +02:00
}
}
//---------------------------------------------------------
// writeFailed
//---------------------------------------------------------
static void writeFailed(const QString& _path)
{
2013-03-01 17:14:21 +01:00
QString s = qApp->translate("Workspace", "Open Workspace File\n") + _path
+ qApp->translate("Workspace", "\nfailed: ");
QMessageBox::critical(mscore, qApp->translate("Workspace", "MuseScore: Writing Workspace file"), s);
2012-05-26 14:49:10 +02:00
}
2013-02-10 14:50:18 +01:00
//---------------------------------------------------------
// Workspace
//---------------------------------------------------------
Workspace::Workspace()
: QObject(0)
{
_dirty = false;
_readOnly = false;
}
2012-05-26 14:49:10 +02:00
//---------------------------------------------------------
// write
//---------------------------------------------------------
2013-02-06 16:43:25 +01:00
void Workspace::write()
2012-05-26 14:49:10 +02:00
{
if (_path.isEmpty()) {
2013-03-01 17:14:21 +01:00
QString ext(".workspace");
2012-05-26 14:49:10 +02:00
QDir dir;
dir.mkpath(dataPath);
2013-02-08 11:36:50 +01:00
_path = dataPath + "/workspaces";
2012-05-26 14:49:10 +02:00
dir.mkpath(_path);
_path += "/" + _name + ext;
}
QZipWriter 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() != QZipWriter::NoError) {
writeFailed(_path);
return;
}
QBuffer cbuf;
cbuf.open(QIODevice::ReadWrite);
Xml xml(&cbuf);
xml.header();
xml.stag("container");
xml.stag("rootfiles");
2013-02-08 11:36:50 +01:00
xml.stag(QString("rootfile full-path=\"%1\"").arg(Xml::xmlString("workspace.xml")));
2012-05-26 14:49:10 +02:00
xml.etag();
foreach (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.addDirectory("META-INF");
//f.addDirectory("Pictures");
2012-05-26 14:49:10 +02:00
f.addFile("META-INF/container.xml", cbuf.data());
// save images
foreach(ImageStoreItem* ip, imageStore) {
if (!ip->isUsed(gscore))
continue;
QString dstPath = QString("Pictures/") + ip->hashName();
f.addFile(dstPath, ip->buffer());
}
{
QBuffer cbuf;
cbuf.open(QIODevice::ReadWrite);
Xml xml(&cbuf);
xml.clipboardmode = true;
xml.header();
xml.stag("museScore version=\"" MSC_VERSION "\"");
2013-02-06 16:43:25 +01:00
xml.stag("Workspace");
2012-05-26 14:49:10 +02:00
xml.tag("name", _name);
PaletteBox* pb = mscore->getPaletteBox();
pb->write(xml);
xml.etag();
xml.etag();
2013-02-08 11:36:50 +01:00
f.addFile("workspace.xml", cbuf.data());
2012-05-26 14:49:10 +02:00
cbuf.close();
}
if (f.status() != QZipWriter::NoError)
writeFailed(_path);
}
//---------------------------------------------------------
// read
//---------------------------------------------------------
2013-02-06 16:43:25 +01:00
void Workspace::read()
2012-05-26 14:49:10 +02:00
{
2012-09-11 21:10:44 +02:00
if (_path.isEmpty() || !QFile(_path).exists()) {
2012-05-26 14:49:10 +02:00
PaletteBox* paletteBox = mscore->getPaletteBox();
paletteBox->clear();
mscore->populatePalette();
return;
}
2013-02-10 14:50:18 +01:00
QFileInfo fi(_path);
_readOnly = !fi.isWritable();
2012-09-11 21:10:44 +02:00
QZipReader f(_path);
2012-05-26 14:49:10 +02:00
QByteArray ba = f.fileData("META-INF/container.xml");
2013-01-17 14:55:04 +01:00
XmlReader e(ba);
2012-05-26 14:49:10 +02:00
// extract first rootfile
QString rootfile = "";
QList<QString> images;
2013-01-17 14:55:04 +01:00
while (e.readNextStartElement()) {
if (e.name() != "container")
2013-01-17 14:55:04 +01:00
e.unknown();
while (e.readNextStartElement()) {
if (e.name() != "rootfiles") {
e.unknown();
break;
2012-05-26 14:49:10 +02:00
}
2013-01-17 14:55:04 +01:00
while (e.readNextStartElement()) {
const QStringRef& tag(e.name());
2012-05-26 14:49:10 +02:00
if (tag == "rootfile") {
if (rootfile.isEmpty())
2013-01-17 14:55:04 +01:00
rootfile = e.attribute("full-path");
e.readNext();
e.readNext();
2012-05-26 14:49:10 +02:00
}
else if (tag == "file")
2013-01-17 14:55:04 +01:00
images.append(e.readElementText());
2012-05-26 14:49:10 +02:00
else
2013-01-17 14:55:04 +01:00
e.unknown();
2012-05-26 14:49:10 +02:00
}
}
}
//
// load images
//
foreach(const QString& s, images)
imageStore.add(s, f.fileData(s));
if (rootfile.isEmpty()) {
qDebug("can't find rootfile in: %s", qPrintable(_path));
return;
}
ba = f.fileData(rootfile);
2013-01-17 14:55:04 +01:00
e.clear();
e.addData(ba);
2012-05-26 14:49:10 +02:00
2013-01-17 14:55:04 +01:00
while (e.readNextStartElement()) {
if (e.name() == "museScore") {
while (e.readNextStartElement()) {
2013-02-06 16:43:25 +01:00
if (e.name() == "Workspace")
2013-01-17 14:55:04 +01:00
read(e);
2012-05-26 14:49:10 +02:00
else
2013-01-17 14:55:04 +01:00
e.unknown();
2012-05-26 14:49:10 +02:00
}
}
}
}
2013-02-06 16:43:25 +01:00
void Workspace::read(XmlReader& e)
2012-05-26 14:49:10 +02:00
{
2013-01-11 18:10:18 +01:00
while (e.readNextStartElement()) {
const QStringRef& tag(e.name());
2012-05-26 14:49:10 +02:00
if (tag == "name")
2013-01-11 18:10:18 +01:00
_name = e.readElementText();
2012-05-26 14:49:10 +02:00
else if (tag == "PaletteBox") {
PaletteBox* paletteBox = mscore->getPaletteBox();
paletteBox->clear();
paletteBox->read(e);
2013-02-10 14:50:18 +01:00
QList<Palette*> pl = paletteBox->palettes();
foreach (Palette* p, pl) {
p->setSystemPalette(_readOnly);
connect(paletteBox, SIGNAL(changed()), SLOT(setDirty()));
}
2012-05-26 14:49:10 +02:00
}
else
2013-01-11 18:10:18 +01:00
e.unknown();
2012-05-26 14:49:10 +02:00
}
}
//---------------------------------------------------------
// save
//---------------------------------------------------------
2013-02-06 16:43:25 +01:00
void Workspace::save()
2012-05-26 14:49:10 +02:00
{
2013-02-10 14:50:18 +01:00
if (_readOnly)
return;
2012-05-26 14:49:10 +02:00
PaletteBox* pb = mscore->getPaletteBox();
2013-02-10 14:50:18 +01:00
if (pb)
2012-05-26 14:49:10 +02:00
write();
}
//---------------------------------------------------------
2013-02-08 11:36:50 +01:00
// workspaces
2012-05-26 14:49:10 +02:00
//---------------------------------------------------------
2013-02-08 11:36:50 +01:00
QList<Workspace*>& Workspace::workspaces()
2012-05-26 14:49:10 +02:00
{
2013-02-08 11:36:50 +01:00
if (!workspacesRead) {
2013-02-10 14:50:18 +01:00
QStringList path;
path << mscoreGlobalShare + "workspaces";
path << dataPath + "/workspaces";
2012-05-26 14:49:10 +02:00
QStringList nameFilters;
2013-02-08 11:36:50 +01:00
nameFilters << "*.workspace";
2012-05-26 14:49:10 +02:00
2013-02-10 14:50:18 +01:00
foreach(QString s, path) {
QDir dir(s);
QStringList pl = dir.entryList(nameFilters, QDir::Files, QDir::Name);
foreach (QString entry, pl) {
Workspace* p = 0;
QFileInfo fi(s + "/" + entry);
QString name(fi.baseName());
foreach(Workspace* w, _workspaces) {
if (w->name() == name) {
p = w;
break;
}
}
if (!p)
p = new Workspace;
p->setPath(s + "/" + entry);
p->setName(name);
2013-02-15 19:25:00 +01:00
p->setReadOnly(!fi.isWritable());
2013-02-10 14:50:18 +01:00
_workspaces.append(p);
}
2012-05-26 14:49:10 +02:00
}
2013-02-08 11:36:50 +01:00
workspacesRead = true;
2012-05-26 14:49:10 +02:00
}
2013-02-08 11:36:50 +01:00
return _workspaces;
2012-05-26 14:49:10 +02:00
}
//---------------------------------------------------------
2013-02-06 16:43:25 +01:00
// createNewWorkspace
2012-05-26 14:49:10 +02:00
//---------------------------------------------------------
2013-02-06 16:43:25 +01:00
Workspace* Workspace::createNewWorkspace(const QString& name)
2012-05-26 14:49:10 +02:00
{
2013-02-10 14:50:18 +01:00
Workspace* p = new Workspace;
2012-05-26 14:49:10 +02:00
p->setName(name);
p->setPath("");
p->setDirty(false);
p->setReadOnly(false);
2012-05-26 14:49:10 +02:00
p->write();
// all palettes in new workspace are editable
PaletteBox* paletteBox = mscore->getPaletteBox();
QList<Palette*> pl = paletteBox->palettes();
foreach (Palette* p, pl)
p->setSystemPalette(false);
2013-02-08 11:36:50 +01:00
_workspaces.append(p);
2012-05-26 14:49:10 +02:00
return p;
}
2013-03-01 17:14:21 +01:00
//---------------------------------------------------------
// writeBuiltinWorkspace
2013-03-01 17:14:21 +01:00
//---------------------------------------------------------
void Workspace::writeBuiltinWorkspace()
2013-03-01 17:14:21 +01:00
{
PaletteBox* paletteBox = mscore->getPaletteBox();
paletteBox->clear();
mscore->populatePalette();
Workspace ws;
ws.setName("advanced");
ws.setPath("advanced.workspace");
ws.write();
}
2013-05-13 18:49:17 +02:00
}
2013-03-01 17:14:21 +01:00