547 lines
20 KiB
C++
547 lines
20 KiB
C++
//=============================================================================
|
|
// MuseScore
|
|
// Music Composition & Notation
|
|
//
|
|
// Copyright (C) 2011-2016 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
|
|
// as published by the Free Software Foundation and appearing in
|
|
// the file LICENSE.GPL
|
|
//=============================================================================
|
|
|
|
#include "palette.h"
|
|
#include "palettebox.h"
|
|
#include "musescore.h"
|
|
#include "preferences.h"
|
|
#include "libmscore/xml.h"
|
|
#include "workspace.h"
|
|
#include "workspacecombobox.h"
|
|
|
|
namespace Ms {
|
|
|
|
//---------------------------------------------------------
|
|
// PaletteBox
|
|
//---------------------------------------------------------
|
|
|
|
PaletteBox::PaletteBox(QWidget* parent)
|
|
: QDockWidget(tr("Palettes"), parent)
|
|
{
|
|
setContextMenuPolicy(Qt::ActionsContextMenu);
|
|
setObjectName("palette-box");
|
|
setAllowedAreas(Qt::DockWidgetAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea));
|
|
|
|
singlePaletteAction = new QAction(this);
|
|
singlePaletteAction->setCheckable(true);
|
|
singlePaletteAction->setChecked(preferences.getBool(PREF_APP_USESINGLEPALETTE));
|
|
addAction(singlePaletteAction);
|
|
connect(singlePaletteAction, SIGNAL(toggled(bool)), SLOT(setSinglePalette(bool)));
|
|
|
|
QWidget* w = new QWidget(this);
|
|
w->setContextMenuPolicy(Qt::NoContextMenu);
|
|
QVBoxLayout* vl = new QVBoxLayout(w);
|
|
vl->setMargin(0);
|
|
QHBoxLayout* hl = new QHBoxLayout;
|
|
hl->setContentsMargins(5,0,5,0);
|
|
|
|
workspaceList = new WorkspaceComboBox(mscore);
|
|
workspaceList->setObjectName("workspace-list");
|
|
hl->addWidget(workspaceList);
|
|
addWorkspaceButton = new QToolButton;
|
|
addWorkspaceButton->setDefaultAction(getAction("create-new-workspace"));
|
|
|
|
addWorkspaceButton->setMinimumHeight(24);
|
|
hl->addWidget(addWorkspaceButton);
|
|
|
|
setWidget(w);
|
|
|
|
_searchBox = new QLineEdit(this);
|
|
_searchBox->setFocusPolicy(Qt::StrongFocus);
|
|
_searchBox->installEventFilter(this);
|
|
_searchBox->setClearButtonEnabled(true);
|
|
_searchBox->setPlaceholderText(tr("Search"));
|
|
connect(_searchBox, SIGNAL(textChanged(const QString&)), this, SLOT(filterPalettes(const QString&)));
|
|
QHBoxLayout* hlSearch = new QHBoxLayout;
|
|
hlSearch->setContentsMargins(5,0,5,0);
|
|
hlSearch->addWidget(_searchBox);
|
|
|
|
PaletteBoxScrollArea* sa = new PaletteBoxScrollArea;
|
|
sa->setFocusPolicy(Qt::NoFocus);
|
|
sa->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
|
|
sa->setContextMenuPolicy(Qt::CustomContextMenu);
|
|
sa->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
|
sa->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
|
sa->setWidgetResizable(true);
|
|
sa->setFrameShape(QFrame::NoFrame);
|
|
vl->addWidget(sa);
|
|
vl->addLayout(hlSearch);
|
|
vl->addLayout(hl);
|
|
|
|
QWidget* paletteList = new QWidget;
|
|
sa->setWidget(paletteList);
|
|
vbox = new QVBoxLayout;
|
|
paletteList->setLayout(vbox);
|
|
vbox->setMargin(0);
|
|
vbox->setSpacing(1);
|
|
vbox->addStretch();
|
|
paletteList->show();
|
|
|
|
retranslate();
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// retranslate
|
|
//---------------------------------------------------------
|
|
|
|
void PaletteBox::retranslate()
|
|
{
|
|
setWindowTitle(tr("Palettes"));
|
|
singlePaletteAction->setText(tr("Single Palette"));
|
|
workspaceList->retranslate();
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// filterPalettes
|
|
//---------------------------------------------------------
|
|
|
|
void PaletteBox::filterPalettes(const QString& text)
|
|
{
|
|
for (int i = 0; i < vbox->count(); i++) {
|
|
QWidgetItem* wi = static_cast<QWidgetItem*>(vbox->itemAt(i));
|
|
PaletteBoxButton* b = static_cast<PaletteBoxButton*>(wi->widget());
|
|
i++;
|
|
wi = static_cast<QWidgetItem*>(vbox->itemAt(i));
|
|
if (!wi) return;
|
|
Palette* p = static_cast<Palette*>(wi->widget());
|
|
bool f = p->filter(text);
|
|
b->setVisible(!f);
|
|
if (b->isVisible()) {
|
|
b->showPalette(!text.isEmpty());
|
|
}
|
|
else
|
|
b->showPalette(false);
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// selectWorkspace
|
|
//---------------------------------------------------------
|
|
|
|
void PaletteBox::selectWorkspace(QString path)
|
|
{
|
|
int idx = workspaceList->findData(path);
|
|
selectWorkspace(idx);
|
|
}
|
|
|
|
///---------------------------------------------------------
|
|
/// selectWorkspace
|
|
/// Selects the workspace in the workspaceList dropdown widget using specified @idx
|
|
/// If @idx value is out of valid range:
|
|
/// If currentIndex is valid, keep the index
|
|
/// 1st element of the list is selected othrwise
|
|
///---------------------------------------------------------
|
|
|
|
void PaletteBox::selectWorkspace(int idx)
|
|
{
|
|
if (idx < 0 || idx >= workspaceList->count()) {
|
|
//if selected index is valid, keep the index selection
|
|
if (workspaceList->currentIndex() < workspaceList->count())
|
|
idx = workspaceList->currentIndex();
|
|
else
|
|
idx = 0;
|
|
}
|
|
|
|
workspaceList->setCurrentIndex(idx);
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// clear
|
|
//---------------------------------------------------------
|
|
|
|
void PaletteBox::clear()
|
|
{
|
|
int n = vbox->count() - 1; // do not delete stretch item
|
|
while (n--) {
|
|
QLayoutItem* item = vbox->takeAt(0);
|
|
if (item->widget())
|
|
item->widget()->hide();
|
|
delete item;
|
|
}
|
|
vbox->invalidate();
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// addPalette
|
|
//---------------------------------------------------------
|
|
|
|
void PaletteBox::addPalette(Palette* w)
|
|
{
|
|
PaletteBoxButton* b = new PaletteBoxButton(w);
|
|
|
|
int slotIdx = vbox->count() - 1; // insert before stretch
|
|
b->setId(slotIdx);
|
|
|
|
vbox->insertWidget(slotIdx, b);
|
|
vbox->insertWidget(slotIdx+1, w, paletteStretch);
|
|
|
|
connect(b, SIGNAL(paletteCmd(PaletteCommand,int)), SLOT(paletteCmd(PaletteCommand,int)));
|
|
connect(b, SIGNAL(closeAll()), SLOT(closeAll()));
|
|
connect(w, SIGNAL(changed()), SIGNAL(changed()));
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// newPalette
|
|
//---------------------------------------------------------
|
|
|
|
Palette* PaletteBox::newPalette(const QString& name, int slot)
|
|
{
|
|
Palette* p = new Palette;
|
|
p->setReadOnly(false);
|
|
p->setName(name);
|
|
PaletteBoxButton* b = new PaletteBoxButton(p);
|
|
vbox->insertWidget(slot, b);
|
|
vbox->insertWidget(slot+1, p, paletteStretch);
|
|
connect(b, SIGNAL(paletteCmd(PaletteCommand, int)), SLOT(paletteCmd(PaletteCommand, int)));
|
|
connect(p, SIGNAL(changed()), Workspace::currentWorkspace, SLOT(setDirty()));
|
|
for (int i = 0; i < (vbox->count() - 1) / 2; ++i)
|
|
static_cast<PaletteBoxButton*>(vbox->itemAt(i * 2)->widget())->setId(i*2);
|
|
return p;
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// paletteCmd
|
|
//---------------------------------------------------------
|
|
|
|
void PaletteBox::paletteCmd(PaletteCommand cmd, int slot)
|
|
{
|
|
QLayoutItem* item = vbox->itemAt(slot);
|
|
PaletteBoxButton* b = static_cast<PaletteBoxButton*>(item->widget());
|
|
Palette* palette = static_cast<Palette*>(vbox->itemAt(slot+1)->widget());
|
|
|
|
switch(cmd) {
|
|
case PaletteCommand::PDELETE:
|
|
{
|
|
QMessageBox::StandardButton reply;
|
|
reply = QMessageBox::question(0,
|
|
QWidget::tr("Are you sure?"),
|
|
QWidget::tr("Do you really want to delete the '%1' palette?").arg(palette->name()),
|
|
QMessageBox::Yes | QMessageBox::No,
|
|
QMessageBox::Yes
|
|
);
|
|
if (reply == QMessageBox::Yes) {
|
|
vbox->removeItem(item);
|
|
b->deleteLater(); // this is the button widget
|
|
delete item;
|
|
item = vbox->itemAt(slot);
|
|
vbox->removeItem(item);
|
|
delete item->widget();
|
|
delete item;
|
|
for (int i = 0; i < (vbox->count() - 1) / 2; ++i)
|
|
static_cast<PaletteBoxButton*>(vbox->itemAt(i * 2)->widget())->setId(i*2);
|
|
emit changed();
|
|
}
|
|
}
|
|
break;
|
|
|
|
case PaletteCommand::SAVE:
|
|
{
|
|
QString path = mscore->getPaletteFilename(false, palette->name());
|
|
if (!path.isEmpty())
|
|
palette->write(path);
|
|
}
|
|
break;
|
|
|
|
case PaletteCommand::LOAD:
|
|
{
|
|
QString path = mscore->getPaletteFilename(true);
|
|
if (!path.isEmpty()) {
|
|
QFileInfo fi(path);
|
|
palette = newPalette(fi.completeBaseName(), slot);
|
|
palette->read(path);
|
|
}
|
|
}
|
|
emit changed();
|
|
break;
|
|
|
|
case PaletteCommand::NEW:
|
|
palette = newPalette(tr("New Palette"), slot);
|
|
item = vbox->itemAt(slot);
|
|
b = static_cast<PaletteBoxButton*>(item->widget());
|
|
// fall through
|
|
|
|
case PaletteCommand::EDIT:
|
|
{
|
|
PaletteProperties pp(palette, 0);
|
|
int rv = pp.exec();
|
|
if (rv == 1) {
|
|
emit changed();
|
|
b->setText(palette->name());
|
|
palette->update();
|
|
}
|
|
}
|
|
emit changed();
|
|
break;
|
|
|
|
case PaletteCommand::UP:
|
|
if (slot) {
|
|
QLayoutItem* i1 = vbox->itemAt(slot);
|
|
QLayoutItem* i2 = vbox->itemAt(slot+1);
|
|
vbox->removeItem(i1);
|
|
vbox->removeItem(i2);
|
|
vbox->insertWidget(slot-2, i2->widget(), paletteStretch);
|
|
vbox->insertWidget(slot-2, i1->widget());
|
|
delete i1;
|
|
delete i2;
|
|
for (int i = 0; i < (vbox->count() - 1) / 2; ++i)
|
|
static_cast<PaletteBoxButton*>(vbox->itemAt(i * 2)->widget())->setId(i*2);
|
|
emit changed();
|
|
}
|
|
break;
|
|
|
|
case PaletteCommand::DOWN:
|
|
if (slot < (vbox->count() - 3)) {
|
|
QLayoutItem* i1 = vbox->itemAt(slot);
|
|
QLayoutItem* i2 = vbox->itemAt(slot+1);
|
|
vbox->removeItem(i1);
|
|
vbox->removeItem(i2);
|
|
vbox->insertWidget(slot+2, i2->widget(), paletteStretch);
|
|
vbox->insertWidget(slot+2, i1->widget());
|
|
delete i1;
|
|
delete i2;
|
|
for (int i = 0; i < (vbox->count() - 1) / 2; ++i)
|
|
static_cast<PaletteBoxButton*>(vbox->itemAt(i * 2)->widget())->setId(i*2);
|
|
emit changed();
|
|
}
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// closeAll
|
|
//---------------------------------------------------------
|
|
|
|
void PaletteBox::closeAll()
|
|
{
|
|
for (int i = 0; i < (vbox->count() - 1); i += 2) {
|
|
PaletteBoxButton* b = static_cast<PaletteBoxButton*> (vbox->itemAt(i)->widget() );
|
|
b->showPalette(false);
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// write
|
|
//---------------------------------------------------------
|
|
|
|
void PaletteBox::write(XmlWriter& xml)
|
|
{
|
|
xml.stag("PaletteBox");
|
|
for (int i = 0; i < (vbox->count() - 1); i += 2) {
|
|
Palette* palette = static_cast<Palette*>(vbox->itemAt(i+1)->widget());
|
|
palette->write(xml);
|
|
}
|
|
xml.etag();
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// palettes
|
|
//---------------------------------------------------------
|
|
|
|
QList<Palette*> PaletteBox::palettes()const
|
|
{
|
|
QList<Palette*> pl;
|
|
for (int i = 0; i < (vbox->count() - 1); i += 2)
|
|
pl.append(static_cast<Palette*>(vbox->itemAt(i+1)->widget()));
|
|
return pl;
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// read
|
|
// return false on error
|
|
//---------------------------------------------------------
|
|
|
|
bool PaletteBox::read(XmlReader& e)
|
|
{
|
|
while (e.readNextStartElement()) {
|
|
const QStringRef& tag(e.name());
|
|
if (tag == "Palette") {
|
|
Palette* p = new Palette();
|
|
QString name = e.attribute("name");
|
|
p->setName(name);
|
|
p->read(e);
|
|
addPalette(p);
|
|
connect(p, SIGNAL(displayMore(const QString&)), mscore, SLOT(showMasterPalette(const QString&)));
|
|
}
|
|
else
|
|
e.unknown();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// sizeHint
|
|
//---------------------------------------------------------
|
|
|
|
QSize PaletteBoxScrollArea::sizeHint() const
|
|
{
|
|
return QSize(170 * guiScaling, 170 * guiScaling);
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// setSinglePalette
|
|
//---------------------------------------------------------
|
|
|
|
void PaletteBox::setSinglePalette(bool val)
|
|
{
|
|
preferences.setPreference(PREF_APP_USESINGLEPALETTE, val);
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// changeEvent
|
|
//---------------------------------------------------------
|
|
|
|
void PaletteBox::changeEvent(QEvent *event)
|
|
{
|
|
QDockWidget::changeEvent(event);
|
|
if (event->type() == QEvent::LanguageChange)
|
|
retranslate();
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// noSelection
|
|
//---------------------------------------------------------
|
|
|
|
bool PaletteBox::noSelection()
|
|
{
|
|
for (Palette* p : palettes()) {
|
|
if (p->getCurrentIdx() != -1)
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// mousePressEvent
|
|
//---------------------------------------------------------
|
|
|
|
void PaletteBox::mousePressEvent(QMouseEvent* ev, Palette* p1)
|
|
{
|
|
for (Palette* p : palettes()) {
|
|
QList<PaletteCell*> cells = p->getDragCells();
|
|
if (cells.isEmpty())
|
|
continue;
|
|
if (p->getCurrentIdx() != -1) {
|
|
p->setCurrentIdx(-1);
|
|
p->update();
|
|
}
|
|
}
|
|
p1->setCurrentIdx(p1->idx(ev->pos()));
|
|
p1->update();
|
|
_searchBox->setFocus();
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// navigation
|
|
//---------------------------------------------------------
|
|
|
|
void PaletteBox::navigation(QKeyEvent *event)
|
|
{
|
|
const QList<Palette*> palettesList = palettes();
|
|
if (palettesList.empty() || !palettesList.first()->isFilterActive())
|
|
return;
|
|
if (event->key() == Qt::Key_Down) {
|
|
for (Palette* p : palettes()) {
|
|
if (p->getCurrentIdx() == -1)
|
|
continue;
|
|
if (p->getCurrentIdx() != p->getDragCells().size() - 1) {
|
|
p->nextPaletteElement();
|
|
return;
|
|
}
|
|
else {
|
|
int index = palettes().indexOf(p);
|
|
p->setCurrentIdx(-1);
|
|
p->update();
|
|
for (int i = index + 1; i < palettes().size(); i++) {
|
|
Palette* next = palettes()[i];
|
|
if (!next->getDragCells().isEmpty()) {
|
|
next->setCurrentIdx(0);
|
|
next->update();
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for (Palette* p : palettes()) {
|
|
if (!p->getDragCells().isEmpty()) {
|
|
p->setCurrentIdx(0);
|
|
p->update();
|
|
keyboardNavigation = true;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
else if (event->key() == Qt::Key_Up) {
|
|
for (Palette* p : palettes()) {
|
|
if (p->getCurrentIdx() == -1)
|
|
continue;
|
|
if (p->getCurrentIdx() != 0) {
|
|
p->prevPaletteElement();
|
|
return;
|
|
}
|
|
else {
|
|
int index = palettes().indexOf(p);
|
|
p->setCurrentIdx(-1);
|
|
p->update();
|
|
for (int i = index - 1; i >= 0; i--) {
|
|
Palette* prev = palettes()[i];
|
|
if (!prev->getDragCells().isEmpty()) {
|
|
QList<PaletteCell*> cells = p->getDragCells();
|
|
int l = prev->getDragCells().size() - 1;
|
|
prev->setCurrentIdx(l);
|
|
prev->update();
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for (int j = palettes().size() - 1; j >= 0; j--) {
|
|
Palette* p = palettes()[j];
|
|
if (!p->getDragCells().isEmpty()) {
|
|
int l = p->getDragCells().size() - 1;
|
|
p->setCurrentIdx(l);
|
|
p->update();
|
|
keyboardNavigation = true;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
else if ((event->key() == Qt::Key_Enter) ||
|
|
(event->key() == Qt::Key_Return)) {
|
|
for (Palette* p : palettes()) {
|
|
if (p->getCurrentIdx() != -1) {
|
|
p->applyPaletteElement();
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
bool PaletteBox::eventFilter(QObject* obj, QEvent *event)
|
|
{
|
|
if (obj == _searchBox) {
|
|
if (event->type() == QEvent::KeyPress) {
|
|
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
|
|
if (keyEvent->key() == Qt::Key_Up || keyEvent->key() == Qt::Key_Down ||
|
|
keyEvent->key() == Qt::Key_Enter || keyEvent->key() == Qt::Key_Return) {
|
|
navigation(keyEvent);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
return QDockWidget::eventFilter(obj, event);
|
|
}
|
|
|
|
}
|
|
|