Skip to content

Commit

Permalink
Toolbar customization refinements & fixes
Browse files Browse the repository at this point in the history
- make ToolbarEditor dialog show the proper names for customisable
  actions / item as previously it was showing the internal tags/ids

- allow for the view mode & page zoom dropdowns to be customised
  like all other toolbar items

- re-ordered the available and chosen lists in the dialogue box to make
  more sense - most specific is now at the right and not in the middle

- Customize Toolbars menu is greyed out / disabled when toolbars are
  not customisable, i.e. because we're in advanced or basic mode or
  because although workspace is editable the toolbars are not

- available actions now maintain STANDARD order when items are removed
  from the current toolbar

- improved the spacing of view mode and page zoom dropdowns on the toolbar
  • Loading branch information
Obliquely committed Aug 30, 2020
1 parent d0a08e7 commit abf514e
Show file tree
Hide file tree
Showing 10 changed files with 266 additions and 143 deletions.
71 changes: 49 additions & 22 deletions mscore/musescore.cpp
Expand Up @@ -288,7 +288,10 @@ const std::list<const char*> MuseScore::_allFileOperationEntries {
"file-save-online",
"print",
"undo",
"redo"
"redo",
"",
"zoom-options",
"view-mode"
};

const std::list<const char*> MuseScore::_allPlaybackControlEntries {
Expand Down Expand Up @@ -1006,34 +1009,41 @@ bool MuseScore::isInstalledExtension(QString extensionId)

void MuseScore::populateFileOperations()
{
// Save the current zoom and view-mode combobox states. if any.
const auto magState = mag ? std::make_pair(mag->currentIndex(), mag->currentText()) : std::make_pair(-1, QString());
const auto viewModeComboIndex = viewModeCombo ? viewModeCombo->currentIndex() : -1;

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 {
bool leftToRightLayout = qApp->layoutDirection() == Qt::LayoutDirection::LeftToRight;

if (!leftToRightLayout) {
_fileOperationEntries.reverse();
for (auto s : _fileOperationEntries) {
if (!*s) {
fileTools->addSeparator();
} else {
fileTools->addWidget(new AccessibleToolButton(fileTools, getAction(s)));
}
}

for (auto s : _fileOperationEntries) {
if (!*s) {
fileTools->addSeparator();
} else if (!strcmp("view-mode", s)) {
addViewModeWidget();
} else if (!strcmp("zoom-options", s)) {
addZoomOptionsWidget();
} else {
fileTools->addWidget(new AccessibleToolButton(fileTools, getAction(s)));
}
}

if (!leftToRightLayout) {
_fileOperationEntries.reverse();
}
}

// Currently not customizable in ToolbarEditor
fileTools->addSeparator();
// zoom-options is treated as a special case as it's not a QToolButton
// but, rather, a MagBox (a sub-class of QComboBox)
void MuseScore::addZoomOptionsWidget()
{
// Save the current zoom state, if any.
const auto magState = mag ? std::make_pair(mag->currentIndex(), mag->currentText()) : std::make_pair(-1, QString());
QWidget* spacer1 = new QWidget();
spacer1->setMinimumWidth(1);
spacer1->setMaximumWidth(1);
fileTools->addWidget(spacer1);
mag = new MagBox;

// Restore the saved zoom combobox index and text, if any.
Expand All @@ -1044,7 +1054,18 @@ void MuseScore::populateFileOperations()

connect(mag, SIGNAL(magChanged(MagIdx)), SLOT(magChanged(MagIdx)));
fileTools->addWidget(mag);
QWidget* spacer2 = new QWidget();
spacer2->setMinimumWidth(1);
spacer2->setMaximumWidth(1);
fileTools->addWidget(spacer2);
}

// view-mode is treated as a special case as it's not a QToolButton
// but, rather, a QComboBox
void MuseScore::addViewModeWidget()
{
// Save the current view-mode combobox state, if any.
const auto viewModeComboIndex = viewModeCombo ? viewModeCombo->currentIndex() : -1;
viewModeCombo = new QComboBox(this);
#if defined(Q_OS_MAC)
viewModeCombo->setFocusPolicy(Qt::StrongFocus);
Expand Down Expand Up @@ -4690,6 +4711,12 @@ void MuseScore::changeState(ScoreState val)
getAction("split-measure")->setEnabled(cs && cs->masterScore()->excerpts().size() == 0);
}

// currentWorkspace can be nullptr in some contexts, so check to avoid crash
Workspace* currentWorkspace = WorkspacesManager::currentWorkspace();
if (currentWorkspace) {
getAction("edit-toolbars")->setEnabled(currentWorkspace->canCustomizeToolbars());
}

// disabling top level menu entries does not
// work for MAC

Expand Down
2 changes: 2 additions & 0 deletions mscore/musescore.h
Expand Up @@ -835,6 +835,8 @@ public slots:
std::list<const char*>* fileOperationEntries() { return &_fileOperationEntries; }
void setFileOperationEntries(std::list<const char*> l) { _fileOperationEntries = l; }
void populateFileOperations();
void addViewModeWidget();
void addZoomOptionsWidget();

static const std::list<const char*>& allPlaybackControlEntries() { return _allPlaybackControlEntries; }
std::list<const char*>* playbackControlEntries() { return &_playbackControlEntries; }
Expand Down
196 changes: 136 additions & 60 deletions mscore/toolbarEditor.cpp
Expand Up @@ -13,6 +13,7 @@
#include "toolbarEditor.h"
#include "musescore.h"
#include "workspace.h"
#include "shortcut.h"
#include "icons.h"

namespace Ms {
Expand Down Expand Up @@ -64,8 +65,8 @@ ToolbarEditor::ToolbarEditor(QWidget* parent)

up->setIcon(*icons[int(Icons::arrowUp_ICON)]);
down->setIcon(*icons[int(Icons::arrowDown_ICON)]);
add->setIcon(*icons[int(Icons::goPrevious_ICON)]);
remove->setIcon(*icons[int(Icons::goNext_ICON)]);
add->setIcon(*icons[int(Icons::goNext_ICON)]);
remove->setIcon(*icons[int(Icons::goPrevious_ICON)]);

MuseScore::restoreGeometry(this);
}
Expand All @@ -76,16 +77,18 @@ ToolbarEditor::ToolbarEditor(QWidget* parent)

void ToolbarEditor::init()
{
QString name = WorkspacesManager::currentWorkspace()->name();
bool writable = !WorkspacesManager::currentWorkspace()->readOnly();
if (!writable) {
name += " " + tr("(not changeable)");
}
add->setEnabled(writable);
remove->setEnabled(writable);
up->setEnabled(writable);
down->setEnabled(writable);
workspaceName->setText(name);
Workspace* currentWorkspace = WorkspacesManager::currentWorkspace();
QString name = currentWorkspace->name();
QString mainTitle = tr("Customize Toolbars");
setWindowTitle(mainTitle + " (" + name + ")");

// defensive - don't expect to be here if workspace is not customizable
bool canBeCustomized = currentWorkspace->canCustomizeToolbars();

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();
Expand All @@ -100,7 +103,7 @@ void ToolbarEditor::init()

void ToolbarEditor::accepted()
{
if (WorkspacesManager::currentWorkspace()->readOnly()) {
if (!WorkspacesManager::currentWorkspace()->canCustomizeToolbars()) {
return;
}
// Updates the toolbars
Expand All @@ -113,54 +116,109 @@ void ToolbarEditor::accepted()
WorkspacesManager::currentWorkspace()->setDirty(true);
}

//---------------------------------------------------------
// listItem
//---------------------------------------------------------
QListWidgetItem* ToolbarEditor::listItem(const char* id)
{
QListWidgetItem* item = _listItem(id);

if (!item) {
return nullptr;
}

// add a sensible height for cases where there is no icon
// to avoid row looking squashed
item->setSizeHint(QSize(item->sizeHint().width(), 26));

item->setData(Qt::UserRole, QVariant::fromValue((void*)id));
return item;
}

QListWidgetItem* ToolbarEditor::_listItem(const char* id)
{
if (QString(id).isEmpty()) {
return new QListWidgetItem(tr("Separator"));
}

if (!strcmp("view-mode", id)) {
return new QListWidgetItem(tr("View mode"));
}

if (!strcmp("zoom-options", id)) {
return new QListWidgetItem(tr("Zoom options"));
}

QAction* action = getAction(id);

if (action) {
QString itemName = Shortcut::getShortcut(id)->text();

// in this case we can't use the menu name (it's too short
// as it's used for the button label). So use the shortcut
// description instead
if (strncmp(id, "voice-", 6) == 0) {
itemName = Shortcut::getShortcut(id)->descr();
}

return new QListWidgetItem(action->icon(), itemName);
}

qDebug() << "ToolbarEditor does not recognize id for toolbar item: " << QString(id);
return nullptr;
}

//---------------------------------------------------------
// populateLists
//---------------------------------------------------------

void ToolbarEditor::populateLists(const std::list<const char*>& all, std::list<const char*>* current)
{
actionList->clear();
availableList->clear();
for (auto i : *current) {
QAction* a = getAction(i);
QListWidgetItem* item;
QString actionName = QString(i);
if (a) {
item = new QListWidgetItem(a->icon(), actionName);
} else if (actionName.isEmpty()) {
item = new QListWidgetItem(tr("Separator"));
} else {
item = new QListWidgetItem(actionName);
for (auto currentId : *current) {
QListWidgetItem* item = listItem(currentId);
if (!item) {
continue;
}
item->setData(Qt::UserRole, QVariant::fromValue((void*)i));

actionList->addItem(item);
}
for (auto i : all) {

refreshAvailableList(all, current);
}

void ToolbarEditor::refreshAvailableList(const std::list<const char*>& all, std::list<const char*>* 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);
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));
availableList->addItem(item);
}

if (found) {
continue;
}

if (QString(id).isEmpty()) {
continue;
}

QListWidgetItem* item = listItem(id);
if (!item) {
continue;
}

availableList->addItem(item);
}
QListWidgetItem* item = new QListWidgetItem(tr("Separator"));
item->setData(Qt::UserRole, QVariant::fromValue((void*)""));
availableList->addItem(item);

// add the Separator item
availableList->addItem(listItem(""));
}

//---------------------------------------------------------
Expand All @@ -178,25 +236,28 @@ bool ToolbarEditor::isSpacer(QListWidgetItem* item) const

void ToolbarEditor::addAction()
{
int cr = availableList->currentRow();
if (cr == -1) {
int currentRow = availableList->currentRow();

if (currentRow == -1) {
return;
}
QListWidgetItem* item = availableList->item(cr);

QListWidgetItem* item = availableList->item(currentRow);

if (isSpacer(item)) {
QListWidgetItem* nitem = new QListWidgetItem(item->text());
nitem->setData(Qt::UserRole, QVariant::fromValue((void*)""));
item = nitem;
item = listItem("");
} else {
item = availableList->takeItem(cr);
item = availableList->takeItem(currentRow);
}
cr = actionList->currentRow();
if (cr == -1) {

currentRow = actionList->currentRow();

if (currentRow == -1) {
actionList->addItem(item);
} else {
actionList->insertItem(cr, item);
actionList->insertItem(currentRow, item);
}

updateNewToolbar(toolbarList->currentRow());
}

Expand All @@ -206,15 +267,30 @@ void ToolbarEditor::addAction()

void ToolbarEditor::removeAction()
{
int cr = actionList->currentRow();
if (cr == -1) {
int actionListRow = actionList->currentRow();

if (actionListRow == -1) {
return;
}
QListWidgetItem* item = actionList->takeItem(cr);
if (!isSpacer(item)) {
availableList->addItem(item);
}

QListWidgetItem* item = actionList->takeItem(actionListRow);
updateNewToolbar(toolbarList->currentRow());

if (isSpacer(item)) {
return;
}

int toolbarListRow = toolbarList->currentRow();
switch (toolbarListRow) {
case 0:
refreshAvailableList(MuseScore::allNoteInputMenuEntries(), new_toolbars->at(toolbarListRow));
break;
case 1:
refreshAvailableList(MuseScore::allFileOperationEntries(), new_toolbars->at(toolbarListRow));
break;
case 2:
refreshAvailableList(MuseScore::allPlaybackControlEntries(), new_toolbars->at(toolbarListRow));
}
}

//---------------------------------------------------------
Expand Down
3 changes: 3 additions & 0 deletions mscore/toolbarEditor.h
Expand Up @@ -28,6 +28,9 @@ class ToolbarEditor : public QDialog, public Ui::ToolbarEditor
void updateNewToolbar(int toolbar_to_update);

void populateLists(const std::list<const char*>&, std::list<const char*>*);
void refreshAvailableList(const std::list<const char*>&, std::list<const char*>*);
QListWidgetItem* listItem(const char* id);
QListWidgetItem* _listItem(const char* id);
bool isSpacer(QListWidgetItem*) const;

virtual void hideEvent(QHideEvent*);
Expand Down

0 comments on commit abf514e

Please sign in to comment.