1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ 2 3 /* 4 Rosegarden 5 A MIDI and audio sequencer and musical notation editor. 6 Copyright 2000-2021 the Rosegarden development team. 7 8 Other copyrights also apply to some parts of this work. Please 9 see the AUTHORS file and individual file headers for details. 10 11 This program is free software; you can redistribute it and/or 12 modify it under the terms of the GNU General Public License as 13 published by the Free Software Foundation; either version 2 of the 14 License, or (at your option) any later version. See the file 15 COPYING included with this distribution for more information. 16 */ 17 18 #define RG_MODULE_STRING "[NameSetEditor]" 19 20 #include "NameSetEditor.h" 21 22 #include "BankEditorDialog.h" 23 #include "misc/Debug.h" 24 #include "gui/widgets/LineEdit.h" 25 26 #include <QFrame> 27 #include <QGroupBox> 28 #include <QLabel> 29 #include <QPushButton> 30 #include <QString> 31 #include <QTabWidget> 32 #include <QWidget> 33 #include <QCompleter> 34 #include <QVBoxLayout> 35 #include <QHBoxLayout> 36 #include <QToolButton> 37 #include <QScrollArea> 38 39 namespace Rosegarden 40 { 41 42 43 NameSetEditor::NameSetEditor(BankEditorDialog *bankEditor, 44 QString title, 45 QWidget *parent, 46 bool showKeyMapButtons) : 47 QGroupBox(title, parent), 48 m_bankEditor(bankEditor), 49 m_topFrame(new QFrame(this)), 50 m_topLayout(new QGridLayout(m_topFrame)), 51 m_librarian(nullptr), 52 m_librarianEmail(nullptr), 53 m_names(), 54 m_completions(), 55 m_numberingBaseButton(nullptr), 56 m_numberingBase(1), 57 m_labels(), 58 m_keyMapButtons() 59 { 60 QVBoxLayout *mainLayout = new QVBoxLayout; 61 mainLayout->setContentsMargins(6, 2, 6, 6); 62 63 // Area above the tabbed widget. 64 65 m_topFrame->setContentsMargins(0, 0, 0, 5); 66 m_topLayout->setSpacing(0); 67 m_topLayout->setContentsMargins(0, 0, 0, 0); 68 m_topFrame->setLayout(m_topLayout); 69 mainLayout->addWidget(m_topFrame); 70 71 // "Provided by" groupbox 72 73 QGroupBox *groupBox = new QGroupBox(tr("Provided by"), m_topFrame); 74 QGridLayout *groupBoxLayout = new QGridLayout; 75 76 m_topLayout->addWidget(groupBox, 0, 3, 3, 3); 77 78 // Librarian 79 // ??? Would be nice if we could edit this. 80 m_librarian = new QLabel(groupBox); 81 groupBoxLayout->addWidget(m_librarian, 0, 1); 82 83 // Librarian email 84 // ??? Would be nice if we could edit this. 85 m_librarianEmail = new QLabel(groupBox); 86 groupBoxLayout->addWidget(m_librarianEmail, 1, 1); 87 88 groupBox->setLayout(groupBoxLayout); 89 90 // QScrollArea 91 92 QScrollArea *scrollArea = new QScrollArea(this); 93 // Make sure widget is expanded to fill the scroll area. 94 scrollArea->setWidgetResizable(true); 95 96 mainLayout->addWidget(scrollArea); 97 98 setLayout(mainLayout); 99 100 // Widget and layout to hold each of the rows. 101 QWidget *listWidget = new QWidget; 102 QVBoxLayout *listLayout = new QVBoxLayout; 103 listLayout->setSpacing(2); 104 105 unsigned index = 0; 106 107 // For each row 108 for (unsigned int row = 0; row < 128; ++row) { 109 // Widget and layout to hold the row. A row consists of the 110 // number label, optional keymap button, and name line edit. 111 QWidget *rowWidget = new QWidget; 112 QHBoxLayout *rowLayout = new QHBoxLayout; 113 // take out the excess vertical space that was making this 114 // dialog two screens tall 115 rowLayout->setContentsMargins(0, 0, 0, 0); 116 117 // If this is the very first number label, make it a button. 118 if (index == 0) { 119 m_numberingBaseButton = new QPushButton("", rowWidget); 120 m_numberingBaseButton->setFixedWidth(25); 121 connect(m_numberingBaseButton, 122 &QAbstractButton::clicked, 123 this, &NameSetEditor::slotToggleNumberingBase); 124 125 rowLayout->addWidget(m_numberingBaseButton); 126 127 } else { // All other numbers are QLabels. 128 QLabel *label = new QLabel("", rowWidget); 129 label->setFixedWidth(30); 130 label->setAlignment(Qt::AlignCenter); 131 m_labels.push_back(label); 132 133 rowLayout->addWidget(label); 134 } 135 136 if (showKeyMapButtons) { 137 QToolButton *button = new QToolButton; 138 // Object name is required or else serious data loss occurs. 139 // ??? Actually, this seems to work fine without this. Leaving 140 // it here for safety. 141 button->setObjectName(QString("Key Map Button %1").arg(index)); 142 button->setProperty("index", index); 143 connect(button, &QAbstractButton::clicked, 144 this, &NameSetEditor::slotKeyMapButtonPressed); 145 m_keyMapButtons.push_back(button); 146 147 rowLayout->addWidget(button); 148 } 149 150 // Note: ThornStyle::sizeFromContents() reduces the size 151 // of these so they will fit on smaller displays. 152 LineEdit *lineEdit = new LineEdit("", rowWidget); 153 // A unique object name is required for each widget or else serious 154 // data loss occurs when switching between nodes on the tree. Not 155 // sure why. 156 lineEdit->setObjectName(QString("Line Edit %1").arg(index)); 157 lineEdit->setProperty("index", index); 158 lineEdit->setCompleter(new QCompleter(m_completions)); 159 160 m_names.push_back(lineEdit); 161 connect(m_names[index], 162 &QLineEdit::textChanged, 163 this, &NameSetEditor::slotNameChanged); 164 165 rowLayout->addWidget(lineEdit, 1); 166 167 rowWidget->setLayout(rowLayout); 168 169 listLayout->addWidget(rowWidget); 170 171 ++index; 172 } 173 174 listWidget->setLayout(listLayout); 175 176 scrollArea->setWidget(listWidget); 177 178 m_numberingBaseButton->setMaximumSize(m_labels.front()->size()); 179 180 updateLabels(); 181 } 182 183 void 184 NameSetEditor::slotToggleNumberingBase() 185 { 186 m_numberingBase ^= 1; 187 updateLabels(); 188 } 189 190 void 191 NameSetEditor::updateLabels() 192 { 193 unsigned index = m_numberingBase; 194 195 m_numberingBaseButton->setText(QString("%1").arg(index++)); 196 197 // For each subsequent label. 198 for (size_t i = 0; i < m_labels.size(); ++i) { 199 m_labels[i]->setText(QString("%1").arg(index++)); 200 } 201 } 202 203 204 } 205