From e4602eea9cc3414cc5a67f400a044bc49d90d739 Mon Sep 17 00:00:00 2001 From: Matthew Elton Date: Tue, 14 May 2019 23:15:19 +0100 Subject: [PATCH] Toolbar customization refinements & fixes - allow for the view mode / view zoom to be customised like other items - created an icon to represent view mode / zoom - only appears in this context. design adapted from existing icons so (reasonable) continuity of look and feel - fixed title of dialogue box - removed text box showing workspace name from dialogue box - it's an edit box showing information that can never be edited - unhelpful UI - added name of workspace being edited to the dialogue box title - made dialogue show the proper names for customisable actions / item previously it was showing the internal tags/ids - re-ordered the available and chosen lists in the dialogue box to make more sense - most specific is at the right and not in the middle - added tooltips to various items in dialogue box - menu is greyed out / disabled when toolbars are not customisable, i.e. because we're in advanced or basic mode - available actions now maintain STANDARD order when items are removed from the current toolbar Some "nice to do" things that could be tackled in future: - Toolbars can be customised even when these customisation will never be saved. Doesn't seem like a good idea. Options: a. treat these in the way Advanced and Basic are treated, i.e. disable the customisation menu so user doesn't get to do something that will then never be saved b. make it that toolbar customisations for user workspaces are always saved. If (b) then would be worth adding to the dialogue the option to restore the Basic or Advanced default in case a user found thing had got messy. (Restore to default is very do-able.) - The spacing of the zoombox is not quite right. There should be a small margin to the left so it matches other buttons on toolbar. Would need bit of work to create a new holding widget. - The zoombox and the pageview mode could be treated as separate items. They are closely related, but a user might prefer to, say, drop zoom because they always use mouse or track pad for this. --- mscore/data/icons/viewOptions.svg | 7 ++ mscore/icons.cpp | 3 +- mscore/icons.h | 2 +- mscore/musescore.cpp | 54 ++++++++------ mscore/musescore.h | 2 + mscore/musescore.qrc | 1 + mscore/shortcut.cpp | 21 ++++++ mscore/toolbarEditor.cpp | 91 +++++++++++++++-------- mscore/toolbarEditor.h | 1 + mscore/toolbarEditor.ui | 118 +++++++++++++++--------------- mscore/workspace.cpp | 2 + share/workspaces/Advanced.xml | 2 + share/workspaces/Basic.xml | 2 + 13 files changed, 189 insertions(+), 117 deletions(-) create mode 100644 mscore/data/icons/viewOptions.svg diff --git a/mscore/data/icons/viewOptions.svg b/mscore/data/icons/viewOptions.svg new file mode 100644 index 0000000000000..db74718e6cdc0 --- /dev/null +++ b/mscore/data/icons/viewOptions.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/mscore/icons.cpp b/mscore/icons.cpp index 69f57c2605815..418c9b5b108e9 100644 --- a/mscore/icons.cpp +++ b/mscore/icons.cpp @@ -158,7 +158,8 @@ static const char* iconNames[] = { "arrow_down.svg", "mail.svg", "bug.svg", - "note_timewise.svg" + "note_timewise.svg", + "viewOptions.svg" }; //--------------------------------------------------------- diff --git a/mscore/icons.h b/mscore/icons.h index 110541a892a38..95ef2ca366a7c 100644 --- a/mscore/icons.h +++ b/mscore/icons.h @@ -58,7 +58,7 @@ enum class Icons : signed char { Invalid_ICON = -1, timesig_prolatio08_ICON, timesig_prolatio10_ICON, timesig_prolatio11_ICON, edit_ICON, reset_ICON, close_ICON, arrowUp_ICON, arrowDown_ICON, mail_ICON, bug_ICON, - noteTimewise_ICON, + noteTimewise_ICON, viewOptions_ICON, voice1_ICON, voice2_ICON, voice3_ICON, voice4_ICON, ICONS }; diff --git a/mscore/musescore.cpp b/mscore/musescore.cpp index d27aa6381d07a..0ca5ef2a033bd 100644 --- a/mscore/musescore.cpp +++ b/mscore/musescore.cpp @@ -244,7 +244,9 @@ const std::list MuseScore::_allFileOperationEntries { "file-save-online", "print", "undo", - "redo" + "redo", + "", + "view-options" }; const std::list MuseScore::_allPlaybackControlEntries { @@ -909,27 +911,29 @@ void MuseScore::populateFileOperations() { fileTools->clear(); - if (qApp->layoutDirection() == Qt::LayoutDirection::LeftToRight) { - for (auto s : _fileOperationEntries) { - if (!*s) - fileTools->addSeparator(); - else - fileTools->addWidget(new AccessibleToolButton(fileTools, getAction(s))); - } - } - else { - _fileOperationEntries.reverse(); - for (auto s : _fileOperationEntries) { - if (!*s) - fileTools->addSeparator(); - else - fileTools->addWidget(new AccessibleToolButton(fileTools, getAction(s))); - } + bool leftToRightLayout = qApp->layoutDirection() == Qt::LayoutDirection::LeftToRight; + + if (!leftToRightLayout) _fileOperationEntries.reverse(); + + for (auto s : _fileOperationEntries) { + + if (!*s) + fileTools->addSeparator(); + else if (!strcmp("view-options", s)) + addViewOptionsDoubleWidget(); + else + fileTools->addWidget(new AccessibleToolButton(fileTools, getAction(s))); } - // Currently not customizable in ToolbarEditor - fileTools->addSeparator(); + if (!leftToRightLayout) + _fileOperationEntries.reverse(); + } + +// view-options is treated as a special case as it's not a QToolButton +// but, rather, made up of two QComboBox objects (one sub-classed). +void MuseScore::addViewOptionsDoubleWidget() + { mag = new MagBox; connect(mag, SIGNAL(magChanged(MagIdx)), SLOT(magChanged(MagIdx))); fileTools->addWidget(mag); @@ -951,6 +955,7 @@ void MuseScore::populateFileOperations() fileTools->addWidget(viewModeCombo); } + //--------------------------------------------------------- // populatePlaybackControls //--------------------------------------------------------- @@ -960,14 +965,15 @@ void MuseScore::populatePlaybackControls() transportTools->clear(); for (const auto s : _playbackControlEntries) { - if (!*s) + if (!*s) { transportTools->addSeparator(); + } else { if (QString(s) == "repeat") { - QAction* repeatAction = getAction("repeat"); - repeatAction->setChecked(preferences.getBool(PREF_APP_PLAYBACK_PLAYREPEATS)); - QWidget* w = new AccessibleToolButton(transportTools, repeatAction); - transportTools->addWidget(w); + QAction* repeatAction = getAction("repeat"); + repeatAction->setChecked(preferences.getBool(PREF_APP_PLAYBACK_PLAYREPEATS)); + QWidget* w = new AccessibleToolButton(transportTools, repeatAction); + transportTools->addWidget(w); } else if (QString(s) == "play") { _playButton = new AccessibleToolButton(transportTools, getAction("play")); diff --git a/mscore/musescore.h b/mscore/musescore.h index d4f8c171f1db7..633f6ca3786da 100644 --- a/mscore/musescore.h +++ b/mscore/musescore.h @@ -849,6 +849,7 @@ class MuseScore : public QMainWindow, public MuseScoreCore { std::list* fileOperationEntries() { return &_fileOperationEntries; } void setFileOperationEntries(std::list l) { _fileOperationEntries = l; } void populateFileOperations(); + void addViewOptionsDoubleWidget(); static const std::list& allPlaybackControlEntries() { return _allPlaybackControlEntries; } std::list* playbackControlEntries() { return &_playbackControlEntries; } @@ -882,6 +883,7 @@ MasterSynthesizer* synthesizerFactory(); Driver* driverFactory(Seq*, QString driver); extern QAction* getAction(const char*); +extern QString getShortcutText(const char*); extern Shortcut* midiActionMap[128]; extern void loadTranslation(QString fileName, QString localeName); extern void setMscoreLocale(QString localeName); diff --git a/mscore/musescore.qrc b/mscore/musescore.qrc index a865ec031de34..2979c67b6808d 100644 --- a/mscore/musescore.qrc +++ b/mscore/musescore.qrc @@ -167,6 +167,7 @@ data/icons/mail.svg data/icons/bug.svg data/icons/note_timewise.svg + data/icons/viewOptions.svg data/icons/mixer-slider-handle.svg data/icons/mixer-mute-off.svg data/icons/mixer-mute-on.svg diff --git a/mscore/shortcut.cpp b/mscore/shortcut.cpp index 02b0b357a7bbd..72116a77b447e 100644 --- a/mscore/shortcut.cpp +++ b/mscore/shortcut.cpp @@ -182,6 +182,15 @@ Shortcut Shortcut::_sc[] = { Icons::redo_ICON, Qt::ApplicationShortcut }, + { + MsWidget::MAIN_WINDOW, + STATE_NORMAL, + "view-options", + QT_TRANSLATE_NOOP("action","View Options"), + 0, + 0, + Icons::viewOptions_ICON, + }, { MsWidget::SCORE_TAB, STATE_NORMAL | STATE_NOTE_ENTRY | STATE_EDIT | STATE_TEXT_EDIT | STATE_LYRICS_EDIT @@ -3880,6 +3889,18 @@ QAction* getAction(const char* id) return s ? s->action() : 0; } + +//--------------------------------------------------------- +// getShortcutText +// returns description for shortcut +//--------------------------------------------------------- + +QString getShortcutText(const char* id) + { + Shortcut* shortcut = Shortcut::getShortcut(id); + return shortcut ? shortcut->text() : ""; + } + //--------------------------------------------------------- // aAction //--------------------------------------------------------- diff --git a/mscore/toolbarEditor.cpp b/mscore/toolbarEditor.cpp index 7d0db1bf46db0..3603a365b0d6d 100644 --- a/mscore/toolbarEditor.cpp +++ b/mscore/toolbarEditor.cpp @@ -71,15 +71,16 @@ ToolbarEditor::ToolbarEditor(QWidget* parent) void ToolbarEditor::init() { QString name = Workspace::currentWorkspace->name(); - bool writable = !Workspace::currentWorkspace->readOnly(); - if (!writable) { - name += " " + tr("(not changeable)"); - } - add->setEnabled(writable); - remove->setEnabled(writable); - up->setEnabled(writable); - down->setEnabled(writable); - workspaceName->setText(name); + QString mainTitle = tr("Customize Toolbars"); + setWindowTitle(mainTitle + " (" + name + ")"); + + // defensive - don't expect to be here if workspace is not customizable + bool canBeCustomized = !Workspace::currentWorkspace->readOnly(); + + add->setEnabled(canBeCustomized); + remove->setEnabled(canBeCustomized); + up->setEnabled(canBeCustomized); + down->setEnabled(canBeCustomized); // Syncs the editor with the current toolbars new_toolbars->at(0) = mscore->noteInputMenuEntries(); @@ -113,38 +114,52 @@ void ToolbarEditor::accepted() void ToolbarEditor::populateLists(const std::list& all, std::list* current) { actionList->clear(); - availableList->clear(); - for (auto i : *current) { - QAction* a = getAction(i); + for (auto currentId : *current) { + QString shortcutText = getShortcutText(currentId); + QAction* action = getAction(currentId); QListWidgetItem* item; - QString actionName = QString(i); - if (a) - item = new QListWidgetItem(a->icon(), actionName); - else if (actionName.isEmpty()) + + if (action) + item = new QListWidgetItem(action->icon(), shortcutText); + else if (QString(currentId).isEmpty()) item = new QListWidgetItem(tr("Separator")); else - item = new QListWidgetItem(actionName); - item->setData(Qt::UserRole, QVariant::fromValue((void*)i)); + item = new QListWidgetItem(shortcutText); + + item->setData(Qt::UserRole, QVariant::fromValue((void*)currentId)); actionList->addItem(item); } - for (auto i : all) { + + refreshAvailableList(all, current); + } + + +void ToolbarEditor::refreshAvailableList(const std::list& all, std::list* current) + { + availableList->clear(); + + for (auto id : all) { bool found = false; - for (auto k : *current) { - if (strcmp(k, i) == 0) { + + for (auto allId : *current) { + if (strcmp(allId, id) == 0) { found = true; break; } } + if (!found) { - QAction* a = getAction(i); + QString shortcutText = getShortcutText(id); + QAction* action = getAction(id); QListWidgetItem* item = 0; - QString actionName = QString(i); - if (a) - item = new QListWidgetItem(a->icon(), actionName); - else if (!actionName.isEmpty()) - item = new QListWidgetItem(QString(i)); - if (item) { - item->setData(Qt::UserRole, QVariant::fromValue((void*)i)); + + if (action) + item = new QListWidgetItem(action->icon(), shortcutText); + else if (!QString(id).isEmpty()) + item = new QListWidgetItem(shortcutText); + + if (item) { + item->setData(Qt::UserRole, QVariant::fromValue((void*)id)); availableList->addItem(item); } } @@ -198,10 +213,24 @@ void ToolbarEditor::removeAction() int cr = actionList->currentRow(); if (cr == -1) return; + QListWidgetItem* item = actionList->takeItem(cr); - if (!isSpacer(item)) - availableList->addItem(item); updateNewToolbar(toolbarList->currentRow()); + + if (isSpacer(item)) + return; + + int currentRow = toolbarList->currentRow(); + switch (currentRow) { + case 0: + refreshAvailableList(MuseScore::allNoteInputMenuEntries(), new_toolbars->at(currentRow)); + break; + case 1: + refreshAvailableList(MuseScore::allFileOperationEntries(), new_toolbars->at(currentRow)); + break; + case 2: + refreshAvailableList(MuseScore::allPlaybackControlEntries(), new_toolbars->at(currentRow)); + } } //--------------------------------------------------------- diff --git a/mscore/toolbarEditor.h b/mscore/toolbarEditor.h index 9881e4f08b592..7081de37370f1 100644 --- a/mscore/toolbarEditor.h +++ b/mscore/toolbarEditor.h @@ -28,6 +28,7 @@ class ToolbarEditor : public QDialog, public Ui::ToolbarEditor { void updateNewToolbar(int toolbar_to_update); void populateLists(const std::list&, std::list*); + void refreshAvailableList(const std::list&, std::list*); bool isSpacer(QListWidgetItem*) const; virtual void hideEvent(QHideEvent*); diff --git a/mscore/toolbarEditor.ui b/mscore/toolbarEditor.ui index 29a494fe2e15c..524940e644541 100644 --- a/mscore/toolbarEditor.ui +++ b/mscore/toolbarEditor.ui @@ -11,11 +11,11 @@ - Dialog + Customize Toolbars - - + + 0 @@ -23,25 +23,22 @@ - Toolbar + Available actions - - - - - 0 - 0 - + + + + Qt::Horizontal - - Actions + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - + + 0 @@ -49,73 +46,52 @@ - Available Actions + Actions - - - - -1 + + + + Actions available to show on toolbar - - - - - - - - - - - - - 0 - 0 - - - - Workspace: - - - - - - - true - - - - - - + + + Add action to toolbar + - :/data/icons/go-previous.svg:/data/icons/go-previous.svg + :/data/icons/go-next.svg:/data/icons/go-next.svg + + Remove action from toolbar + - :/data/icons/go-next.svg:/data/icons/go-next.svg + :/data/icons/go-previous.svg:/data/icons/go-previous.svg + + Move action up + @@ -127,6 +103,9 @@ + + Move action down + @@ -138,20 +117,39 @@ - - - - Qt::Horizontal + + + + Toolbar to customize - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + -1 + + + + + + + + 0 + 0 + + + + Toolbar + + + + + + + Actions shown on toolbar - workspaceName toolbarList actionList add diff --git a/mscore/workspace.cpp b/mscore/workspace.cpp index 6d9a00b70ab3f..93b9c542e1769 100644 --- a/mscore/workspace.cpp +++ b/mscore/workspace.cpp @@ -179,6 +179,8 @@ void MuseScore::changeWorkspace(Workspace* p, bool first) updateIcons(); preferencesChanged(true); } + + getAction("edit-toolbars")->setEnabled(!Workspace::currentWorkspace->readOnly()); } //--------------------------------------------------------- diff --git a/share/workspaces/Advanced.xml b/share/workspaces/Advanced.xml index 8ea90556f2014..eccecbd4bd1a3 100644 --- a/share/workspaces/Advanced.xml +++ b/share/workspaces/Advanced.xml @@ -4111,6 +4111,8 @@ print undo redo + + view-options midi-on diff --git a/share/workspaces/Basic.xml b/share/workspaces/Basic.xml index eda9d22887bb3..1546f78e0e77c 100644 --- a/share/workspaces/Basic.xml +++ b/share/workspaces/Basic.xml @@ -904,6 +904,8 @@ print undo redo + + view-options midi-on