MuseScore/mscore/newwizard.cpp
Marc Sabatella cc1327f874 fix #293169: read accidentals in key signatures and notes
Added new "makeReadable" function to replace Unicode characters with readable strings,
and called this where needed in the places where the screenreader text is assembled.
2019-09-17 13:33:27 +02:00

556 lines
18 KiB
C++

//=============================================================================
// MusE Score
// Linux Music Score Editor
//
// Copyright (C) 2008 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 "newwizard.h"
#include "musescore.h"
#include "preferences.h"
#include "palette.h"
#include "instrdialog.h"
#include "templateBrowser.h"
#include "extension.h"
#include "icons.h"
#include "scoreaccessibility.h"
#include "libmscore/instrtemplate.h"
#include "libmscore/score.h"
#include "libmscore/staff.h"
#include "libmscore/clef.h"
#include "libmscore/part.h"
#include "libmscore/drumset.h"
#include "libmscore/keysig.h"
#include "libmscore/measure.h"
#include "libmscore/stafftype.h"
#include "libmscore/timesig.h"
#include "libmscore/sym.h"
namespace Ms {
extern Palette* newKeySigPalette();
extern void filterInstruments(QTreeWidget *instrumentList, const QString &searchPhrase = QString(""));
//---------------------------------------------------------
// TimesigWizard
//---------------------------------------------------------
TimesigWizard::TimesigWizard(QWidget* parent)
: QWidget(parent)
{
setupUi(this);
connect(tsCommonTime, SIGNAL(toggled(bool)), SLOT(commonTimeToggled(bool)));
connect(tsCutTime, SIGNAL(toggled(bool)), SLOT(cutTimeToggled(bool)));
connect(tsFraction, SIGNAL(toggled(bool)), SLOT(fractionToggled(bool)));
pickupMeasure->setChecked(false); // checked in the UI file to enable screen reader on pickup duration controls
tsCommonTime->setIcon(*icons[int(Icons::timesig_common_ICON)]);
tsCutTime->setIcon(*icons[int(Icons::timesig_allabreve_ICON)]);
}
//---------------------------------------------------------
// measures
//---------------------------------------------------------
int TimesigWizard::measures() const
{
return measureCount->value();
}
//---------------------------------------------------------
// timesig
//---------------------------------------------------------
Fraction TimesigWizard::timesig() const
{
if (tsFraction->isChecked())
return Fraction(timesigZ->value(), 1 << timesigN->currentIndex());
else if (tsCommonTime->isChecked())
return Fraction(4, 4);
else
return Fraction(2, 2);
}
//---------------------------------------------------------
// pickupMeasure
//---------------------------------------------------------
bool TimesigWizard::pickup(int* z, int* n) const
{
*z = pickupTimesigZ->value();
*n = 1 << pickupTimesigN->currentIndex();
return pickupMeasure->isChecked();
}
//---------------------------------------------------------
// type
//---------------------------------------------------------
TimeSigType TimesigWizard::type() const
{
if (tsFraction->isChecked())
return TimeSigType::NORMAL;
if (tsCommonTime->isChecked())
return TimeSigType::FOUR_FOUR;
return TimeSigType::ALLA_BREVE;
}
//---------------------------------------------------------
// commonTimeToggled
//---------------------------------------------------------
void TimesigWizard::commonTimeToggled(bool val)
{
if (val) {
// timesigZ->setValue(4);
// timesigN->setValue(4);
timesigZ->setEnabled(false);
timesigN->setEnabled(false);
}
}
//---------------------------------------------------------
// cutTimeToggled
//---------------------------------------------------------
void TimesigWizard::cutTimeToggled(bool val)
{
if (val) {
// timesigZ->setValue(2);
// timesigN->setValue(2);
timesigZ->setEnabled(false);
timesigN->setEnabled(false);
}
}
//---------------------------------------------------------
// fractionToggled
//---------------------------------------------------------
void TimesigWizard::fractionToggled(bool val)
{
if (val) {
timesigZ->setEnabled(true);
timesigN->setEnabled(true);
}
}
//---------------------------------------------------------
// TitleWizard
//---------------------------------------------------------
TitleWizard::TitleWizard(QWidget* parent)
: QWidget(parent)
{
setupUi(this);
}
//---------------------------------------------------------
// NewWizardInfoPage
//---------------------------------------------------------
NewWizardInfoPage::NewWizardInfoPage(QWidget* parent)
: QWizardPage(parent)
{
setTitle(tr("Create New Score"));
setSubTitle(tr("Enter score information:"));
setAccessibleName(QWizardPage::title());
setAccessibleDescription(QWizardPage::subTitle());
w = new TitleWizard;
QGridLayout* grid = new QGridLayout;
grid->addWidget(w, 0, 0);
setLayout(grid);
}
//---------------------------------------------------------
// initializePage
//---------------------------------------------------------
void NewWizardInfoPage::initializePage()
{
w->title->setText("");
w->subtitle->setText("");
}
//---------------------------------------------------------
// NewWizardInstrumentsPage
//---------------------------------------------------------
NewWizardInstrumentsPage::NewWizardInstrumentsPage(QWidget* parent)
: QWizardPage(parent)
{
setFinalPage(true);
setTitle(tr("Create New Score"));
setSubTitle(tr("Choose instruments on the left to add to instrument list on the right:"));
setAccessibleName(title());
setAccessibleDescription(subTitle());
instrumentsWidget = new InstrumentsWidget;
QGridLayout* grid = new QGridLayout;
grid->setSpacing(0);
grid->setContentsMargins(0, 0, 0, 0);
grid->addWidget(instrumentsWidget, 0, 0);
setLayout(grid);
connect(instrumentsWidget, SIGNAL(completeChanged(bool)), SLOT(setComplete(bool)));
}
//---------------------------------------------------------
// initializePage
//---------------------------------------------------------
void NewWizardInstrumentsPage::initializePage()
{
complete = false;
instrumentsWidget->init();
}
//---------------------------------------------------------
// setComplete
//---------------------------------------------------------
void NewWizardInstrumentsPage::setComplete(bool val)
{
complete = val;
emit completeChanged();
}
//---------------------------------------------------------
// isComplete
//---------------------------------------------------------
bool NewWizardInstrumentsPage::isComplete() const
{
return complete;
}
//---------------------------------------------------------
// createInstruments
//---------------------------------------------------------
void NewWizardInstrumentsPage::createInstruments(Score* s)
{
instrumentsWidget->createInstruments(s);
}
//---------------------------------------------------------
// NewWizardTimesigPage
//---------------------------------------------------------
NewWizardTimesigPage::NewWizardTimesigPage(QWidget* parent)
: QWizardPage(parent)
{
setFinalPage(true);
setTitle(tr("Create New Score"));
setSubTitle(tr("Choose time signature:"));
setAccessibleName(title());
setAccessibleDescription(subTitle());
w = new TimesigWizard;
QGridLayout* grid = new QGridLayout;
grid->addWidget(w, 0, 0);
setLayout(grid);
}
//---------------------------------------------------------
// NewWizardTemplatePage
//---------------------------------------------------------
NewWizardTemplatePage::NewWizardTemplatePage(QWidget* parent)
: QWizardPage(parent)
{
setFinalPage(true);
setTitle(tr("Create New Score"));
setSubTitle(tr("Choose template file:"));
setAccessibleName(title());
setAccessibleDescription(subTitle());
templateFileBrowser = new TemplateBrowser(this);
templateFileBrowser->setStripNumbers(true);
QVBoxLayout* layout = new QVBoxLayout;
layout->addWidget(templateFileBrowser);
setLayout(layout);
connect(templateFileBrowser, SIGNAL(scoreSelected(const QString&)), SLOT(templateChanged(const QString&)));
connect(templateFileBrowser, SIGNAL(scoreActivated(const QString&)), SLOT(fileAccepted(const QString&)));
buildTemplatesList();
}
//---------------------------------------------------------
// initializePage
//---------------------------------------------------------
void NewWizardTemplatePage::initializePage()
{
}
//---------------------------------------------------------
// buildTemplatesList
//---------------------------------------------------------
void NewWizardTemplatePage::buildTemplatesList()
{
QDir dir(mscoreGlobalShare + "/templates");
QFileInfoList fil = dir.entryInfoList(QDir::NoDotAndDotDot | QDir::Readable | QDir::Dirs | QDir::Files, QDir::Name);
if(fil.isEmpty()){
fil.append(QFileInfo(QFile(":data/Empty_Score.mscz")));
}
QDir myTemplatesDir(preferences.getString(PREF_APP_PATHS_MYTEMPLATES));
fil.append(myTemplatesDir.entryInfoList(QDir::NoDotAndDotDot | QDir::Readable | QDir::Dirs | QDir::Files, QDir::Name));
// append templates directories from extensions
QStringList extensionsDir = Extension::getDirectoriesByType(Extension::templatesDir);
for (QString extDir : extensionsDir) {
QDir extTemplateDir(extDir);
fil.append(extTemplateDir.entryInfoList(QDir::NoDotAndDotDot | QDir::Readable | QDir::Dirs | QDir::Files, QDir::Name));
}
templateFileBrowser->setScores(fil);
}
//---------------------------------------------------------
// isComplete
//---------------------------------------------------------
bool NewWizardTemplatePage::isComplete() const
{
return !path.isEmpty();
}
//---------------------------------------------------------
// fileAccepted
//---------------------------------------------------------
void NewWizardTemplatePage::fileAccepted(const QString& s)
{
path = s;
templateFileBrowser->show();
if (wizard()->currentPage() == this)
wizard()->next();
}
//---------------------------------------------------------
// templateChanged
//---------------------------------------------------------
void NewWizardTemplatePage::templateChanged(const QString& s)
{
setFinalPage(QFileInfo(s).completeBaseName() != "00-Blank");
path = s;
emit completeChanged();
}
//---------------------------------------------------------
// templatePath
//---------------------------------------------------------
QString NewWizardTemplatePage::templatePath() const
{
return path;
}
//---------------------------------------------------------
// NewWizardKeysigPage
//---------------------------------------------------------
NewWizardKeysigPage::NewWizardKeysigPage(QWidget* parent)
: QWizardPage(parent)
{
setFinalPage(true);
setTitle(tr("Create New Score"));
setSubTitle(tr("Choose key signature and tempo:"));
setAccessibleName(title());
setAccessibleDescription(subTitle());
QGroupBox* b1 = new QGroupBox;
b1->setTitle(tr("Key Signature"));
b1->setAccessibleName(b1->title());
b1->setAccessibleDescription(tr("Choose a key signature"));
sp = MuseScore::newKeySigPalette();
sp->setMoreElements(false);
sp->setShowContextMenu(false);
sp->setSelectable(true);
sp->setDisableDoubleClick(true);
int keysigCMajorIdx = 14;
sp->setSelected(keysigCMajorIdx);
PaletteScrollArea* sa = new PaletteScrollArea(sp);
// set widget name to include name of selected element
// we could set the description, but some screen readers ignore it
QString name = tr("Key Signature: %1").arg(qApp->translate("Palette", sp->cellAt(keysigCMajorIdx)->name.toUtf8()));
ScoreAccessibility::makeReadable(name);
sa->setAccessibleName(name);
QAccessibleEvent event(sa, QAccessible::NameChanged);
QAccessible::updateAccessibility(&event);
QVBoxLayout* l1 = new QVBoxLayout;
l1->addWidget(sa);
b1->setLayout(l1);
tempoGroup = new QGroupBox;
tempoGroup->setCheckable(true);
tempoGroup->setChecked(false);
tempoGroup->setTitle(tr("Tempo"));
tempoGroup->setAccessibleName(tempoGroup->title());
tempoGroup->setAccessibleDescription(tr("Add tempo marking to score"));
QLabel* bpm = new QLabel;
bpm->setText(tr("BPM:"));
_tempo = new QDoubleSpinBox;
_tempo->setAccessibleName(tr("Beats per minute"));
_tempo->setRange(20.0, 400.0);
_tempo->setValue(120.0);
_tempo->setDecimals(1);
QHBoxLayout* l2 = new QHBoxLayout;
l2->addWidget(bpm);
l2->addWidget(_tempo);
l2->addStretch(100);
tempoGroup->setLayout(l2);
QVBoxLayout* l3 = new QVBoxLayout;
l3->addWidget(b1);
l3->addWidget(tempoGroup);
l3->addStretch(100);
setLayout(l3);
setFocusPolicy(Qt::StrongFocus);
}
//---------------------------------------------------------
// keysig
//---------------------------------------------------------
KeySigEvent NewWizardKeysigPage::keysig() const
{
int idx = sp->getSelectedIdx();
Element* e = sp->element(idx);
return static_cast<KeySig*>(e)->keySigEvent();
}
//---------------------------------------------------------
// NewWizard
//---------------------------------------------------------
NewWizard::NewWizard(QWidget* parent)
: QWizard(parent)
{
setObjectName("NewWizard");
setWindowFlags(this->windowFlags() & ~Qt::WindowContextHelpButtonHint);
auto wizardStyleValue = QWizard::ModernStyle; //Modern Winsows look
#ifdef Q_OS_MAC
wizardStyleValue = QWizard::MacStyle;
setOption(QWizard::CancelButtonOnLeft, true);
#endif
setWizardStyle(wizardStyleValue);
setPixmap(QWizard::LogoPixmap, QPixmap(":/data/mscore.png"));
setPixmap(QWizard::WatermarkPixmap, QPixmap());
setWindowTitle(tr("New Score Wizard"));
setOption(QWizard::NoCancelButton, false);
setOption(QWizard::HaveFinishButtonOnEarlyPages, true);
setOption(QWizard::HaveNextButtonOnLastPage, true);
infoPage = new NewWizardInfoPage;
instrumentsPage = new NewWizardInstrumentsPage;
timesigPage = new NewWizardTimesigPage;
templatePage = new NewWizardTemplatePage;
keysigPage = new NewWizardKeysigPage;
// enum Page { Invalid = -1, Type, Instruments, Template, Keysig, Timesig};
setPage(Page::Type, infoPage);
setPage(Page::Instruments, instrumentsPage);
setPage(Page::Template, templatePage);
setPage(Page::Keysig, keysigPage);
setPage(Page::Timesig, timesigPage);
resize(QSize(840, 560)); //ensure default size if no geometry in settings
MuseScore::restoreGeometry(this);
connect(this, SIGNAL(currentIdChanged(int)), SLOT(idChanged(int)));
}
//---------------------------------------------------------
// idChanged
//---------------------------------------------------------
void NewWizard::idChanged(int /*id*/)
{
//printf("\n===\nWizard: id changed %d\n", id);
}
//---------------------------------------------------------
// nextId
//---------------------------------------------------------
int NewWizard::nextId() const
{
int next;
switch (Page(currentId())) {
case Page::Type:
next = Page::Template;
break;
case Page::Template:
next = emptyScore() ? Page::Instruments : Page::Keysig;
break;
case Page::Instruments:
next = Page::Keysig;
break;
case Page::Keysig:
next = Page::Timesig;
break;
case Page::Timesig:
default:
next = Page::Invalid;
break;
}
return next;
}
//---------------------------------------------------------
// emptyScore
//---------------------------------------------------------
bool NewWizard::emptyScore() const
{
QString p = templatePage->templatePath();
QFileInfo fi(p);
bool val = fi.completeBaseName() == "00-Blank";
return val;
}
//---------------------------------------------------------
// updateValues
//---------------------------------------------------------
void NewWizard::updateValues() const
{
//p2->buildInstrumentsList();
templatePage->buildTemplatesList();
}
//---------------------------------------------------------
// hideEvent
//---------------------------------------------------------
void NewWizard::hideEvent(QHideEvent* event)
{
MuseScore::saveGeometry(this);
QWidget::hideEvent(event);
}
}