annotate widgets/SubdividingMenu.cpp @ 183:5f86ae638b04

* Omit translucent blue fill for selection rectangles that are superimposed over layers that use colours for meaningful purposes such as the spectrogram (CHARM change request)
author Chris Cannam
date Fri, 24 Nov 2006 16:56:15 +0000
parents 42118892f428
children 22c99c8aa1e0
rev   line source
Chris@151 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@151 2
Chris@151 3 /*
Chris@151 4 Sonic Visualiser
Chris@151 5 An audio file viewer and annotation editor.
Chris@151 6 Centre for Digital Music, Queen Mary, University of London.
Chris@182 7 This file copyright 2006 QMUL.
Chris@151 8
Chris@151 9 This program is free software; you can redistribute it and/or
Chris@151 10 modify it under the terms of the GNU General Public License as
Chris@151 11 published by the Free Software Foundation; either version 2 of the
Chris@151 12 License, or (at your option) any later version. See the file
Chris@151 13 COPYING included with this distribution for more information.
Chris@151 14 */
Chris@151 15
Chris@151 16 #include "SubdividingMenu.h"
Chris@151 17
Chris@151 18 #include <iostream>
Chris@151 19
Chris@151 20 using std::set;
Chris@151 21 using std::map;
Chris@151 22
Chris@152 23 SubdividingMenu::SubdividingMenu(size_t lowerLimit, size_t upperLimit,
Chris@152 24 QWidget *parent) :
Chris@152 25 QMenu(parent),
Chris@152 26 m_lowerLimit(lowerLimit ? lowerLimit : 14),
Chris@152 27 m_upperLimit(upperLimit ? upperLimit : (m_lowerLimit * 5) / 2),
Chris@152 28 m_entriesSet(false)
Chris@151 29 {
Chris@151 30 }
Chris@151 31
Chris@152 32 SubdividingMenu::SubdividingMenu(const QString &title, size_t lowerLimit,
Chris@152 33 size_t upperLimit, QWidget *parent) :
Chris@152 34 QMenu(title, parent),
Chris@152 35 m_lowerLimit(lowerLimit ? lowerLimit : 14),
Chris@152 36 m_upperLimit(upperLimit ? upperLimit : (m_lowerLimit * 5) / 2),
Chris@152 37 m_entriesSet(false)
Chris@151 38 {
Chris@151 39 }
Chris@151 40
Chris@151 41 SubdividingMenu::~SubdividingMenu()
Chris@151 42 {
Chris@152 43 for (map<QString, QObject *>::iterator i = m_pendingEntries.begin();
Chris@152 44 i != m_pendingEntries.end(); ++i) {
Chris@152 45 delete i->second;
Chris@152 46 }
Chris@151 47 }
Chris@151 48
Chris@151 49 void
Chris@151 50 SubdividingMenu::setEntries(const std::set<QString> &entries)
Chris@151 51 {
Chris@152 52 m_entriesSet = true;
Chris@152 53
Chris@151 54 size_t total = entries.size();
Chris@151 55
Chris@152 56 if (total < m_upperLimit) return;
Chris@151 57
Chris@151 58 size_t count = 0;
Chris@151 59 QMenu *chunkMenu = new QMenu();
Chris@151 60
Chris@151 61 QString firstNameInChunk;
Chris@151 62 QChar firstInitialInChunk;
Chris@151 63 bool discriminateStartInitial = false;
Chris@151 64
Chris@151 65 for (set<QString>::const_iterator j = entries.begin();
Chris@151 66 j != entries.end();
Chris@151 67 ++j) {
Chris@151 68
Chris@152 69 // std::cerr << "SubdividingMenu::setEntries: j -> " << j->toStdString() << std::endl;
Chris@151 70
Chris@151 71 m_nameToChunkMenuMap[*j] = chunkMenu;
Chris@151 72
Chris@151 73 set<QString>::iterator k = j;
Chris@151 74 ++k;
Chris@151 75
Chris@151 76 QChar initial = (*j)[0];
Chris@151 77
Chris@151 78 if (count == 0) {
Chris@151 79 firstNameInChunk = *j;
Chris@151 80 firstInitialInChunk = initial;
Chris@151 81 }
Chris@151 82
Chris@152 83 // std::cerr << "count = "<< count << ", upper limit = " << m_upperLimit << std::endl;
Chris@152 84
Chris@151 85 bool lastInChunk = (k == entries.end() ||
Chris@152 86 (count >= m_lowerLimit-1 &&
Chris@152 87 (count == m_upperLimit ||
Chris@151 88 (*k)[0] != initial)));
Chris@151 89
Chris@151 90 ++count;
Chris@151 91
Chris@151 92 if (lastInChunk) {
Chris@151 93
Chris@151 94 bool discriminateEndInitial = (k != entries.end() &&
Chris@151 95 (*k)[0] == initial);
Chris@151 96
Chris@151 97 bool initialsEqual = (firstInitialInChunk == initial);
Chris@151 98
Chris@151 99 QString from = QString("%1").arg(firstInitialInChunk);
Chris@151 100 if (discriminateStartInitial ||
Chris@151 101 (discriminateEndInitial && initialsEqual)) {
Chris@151 102 from = firstNameInChunk.left(3);
Chris@151 103 }
Chris@151 104
Chris@151 105 QString to = QString("%1").arg(initial);
Chris@151 106 if (discriminateEndInitial ||
Chris@151 107 (discriminateStartInitial && initialsEqual)) {
Chris@151 108 to = j->left(3);
Chris@151 109 }
Chris@151 110
Chris@151 111 QString menuText;
Chris@151 112
Chris@151 113 if (from == to) menuText = from;
Chris@151 114 else menuText = tr("%1 - %2").arg(from).arg(to);
Chris@151 115
Chris@151 116 discriminateStartInitial = discriminateEndInitial;
Chris@151 117
Chris@151 118 chunkMenu->setTitle(menuText);
Chris@151 119
Chris@151 120 QMenu::addMenu(chunkMenu);
Chris@151 121
Chris@151 122 chunkMenu = new QMenu();
Chris@151 123
Chris@151 124 count = 0;
Chris@151 125 }
Chris@151 126 }
Chris@151 127
Chris@151 128 if (count == 0) delete chunkMenu;
Chris@151 129 }
Chris@151 130
Chris@151 131 void
Chris@152 132 SubdividingMenu::entriesAdded()
Chris@152 133 {
Chris@152 134 if (m_entriesSet) {
Chris@152 135 std::cerr << "ERROR: SubdividingMenu::entriesAdded: setEntries was also called -- should use one mechanism or the other, but not both" << std::endl;
Chris@152 136 return;
Chris@152 137 }
Chris@152 138
Chris@152 139 set<QString> entries;
Chris@152 140 for (map<QString, QObject *>::const_iterator i = m_pendingEntries.begin();
Chris@152 141 i != m_pendingEntries.end(); ++i) {
Chris@152 142 entries.insert(i->first);
Chris@152 143 }
Chris@152 144
Chris@152 145 setEntries(entries);
Chris@152 146
Chris@152 147 for (map<QString, QObject *>::iterator i = m_pendingEntries.begin();
Chris@152 148 i != m_pendingEntries.end(); ++i) {
Chris@152 149
Chris@152 150 QMenu *menu = dynamic_cast<QMenu *>(i->second);
Chris@152 151 if (menu) {
Chris@152 152 addMenu(i->first, menu);
Chris@152 153 continue;
Chris@152 154 }
Chris@152 155
Chris@152 156 QAction *action = dynamic_cast<QAction *>(i->second);
Chris@152 157 if (action) {
Chris@152 158 addAction(i->first, action);
Chris@152 159 continue;
Chris@152 160 }
Chris@152 161 }
Chris@152 162
Chris@152 163 m_pendingEntries.clear();
Chris@152 164 }
Chris@152 165
Chris@152 166 void
Chris@151 167 SubdividingMenu::addAction(QAction *action)
Chris@151 168 {
Chris@151 169 QString name = action->text();
Chris@151 170
Chris@152 171 if (!m_entriesSet) {
Chris@152 172 m_pendingEntries[name] = action;
Chris@152 173 return;
Chris@152 174 }
Chris@152 175
Chris@151 176 if (m_nameToChunkMenuMap.find(name) == m_nameToChunkMenuMap.end()) {
Chris@152 177 // std::cerr << "SubdividingMenu::addAction(" << name.toStdString() << "): not found in name-to-chunk map, adding to main menu" << std::endl;
Chris@151 178 QMenu::addAction(action);
Chris@151 179 return;
Chris@151 180 }
Chris@151 181
Chris@152 182 // std::cerr << "SubdividingMenu::addAction(" << name.toStdString() << "): found in name-to-chunk map for menu " << m_nameToChunkMenuMap[name]->title().toStdString() << std::endl;
Chris@151 183 m_nameToChunkMenuMap[name]->addAction(action);
Chris@151 184 }
Chris@151 185
Chris@151 186 QAction *
Chris@151 187 SubdividingMenu::addAction(const QString &name)
Chris@151 188 {
Chris@152 189 if (!m_entriesSet) {
Chris@152 190 QAction *action = new QAction(name, this);
Chris@152 191 m_pendingEntries[name] = action;
Chris@152 192 return action;
Chris@152 193 }
Chris@152 194
Chris@151 195 if (m_nameToChunkMenuMap.find(name) == m_nameToChunkMenuMap.end()) {
Chris@152 196 // std::cerr << "SubdividingMenu::addAction(" << name.toStdString() << "): not found in name-to-chunk map, adding to main menu" << std::endl;
Chris@151 197 return QMenu::addAction(name);
Chris@151 198 }
Chris@151 199
Chris@152 200 // std::cerr << "SubdividingMenu::addAction(" << name.toStdString() << "): found in name-to-chunk map for menu " << m_nameToChunkMenuMap[name]->title().toStdString() << std::endl;
Chris@151 201 return m_nameToChunkMenuMap[name]->addAction(name);
Chris@151 202 }
Chris@151 203
Chris@151 204 void
Chris@151 205 SubdividingMenu::addAction(const QString &name, QAction *action)
Chris@151 206 {
Chris@152 207 if (!m_entriesSet) {
Chris@152 208 m_pendingEntries[name] = action;
Chris@152 209 return;
Chris@152 210 }
Chris@152 211
Chris@151 212 if (m_nameToChunkMenuMap.find(name) == m_nameToChunkMenuMap.end()) {
Chris@152 213 // std::cerr << "SubdividingMenu::addAction(" << name.toStdString() << "): not found in name-to-chunk map, adding to main menu" << std::endl;
Chris@151 214 QMenu::addAction(action);
Chris@151 215 return;
Chris@151 216 }
Chris@151 217
Chris@152 218 // std::cerr << "SubdividingMenu::addAction(" << name.toStdString() << "): found in name-to-chunk map for menu " << m_nameToChunkMenuMap[name]->title().toStdString() << std::endl;
Chris@151 219 m_nameToChunkMenuMap[name]->addAction(action);
Chris@151 220 }
Chris@151 221
Chris@151 222 void
Chris@151 223 SubdividingMenu::addMenu(QMenu *menu)
Chris@151 224 {
Chris@151 225 QString name = menu->title();
Chris@151 226
Chris@152 227 if (!m_entriesSet) {
Chris@152 228 m_pendingEntries[name] = menu;
Chris@152 229 return;
Chris@152 230 }
Chris@152 231
Chris@151 232 if (m_nameToChunkMenuMap.find(name) == m_nameToChunkMenuMap.end()) {
Chris@152 233 // std::cerr << "SubdividingMenu::addMenu(" << name.toStdString() << "): not found in name-to-chunk map, adding to main menu" << std::endl;
Chris@151 234 QMenu::addMenu(menu);
Chris@151 235 return;
Chris@151 236 }
Chris@151 237
Chris@152 238 // std::cerr << "SubdividingMenu::addMenu(" << name.toStdString() << "): found in name-to-chunk map for menu " << m_nameToChunkMenuMap[name]->title().toStdString() << std::endl;
Chris@151 239 m_nameToChunkMenuMap[name]->addMenu(menu);
Chris@151 240 }
Chris@151 241
Chris@151 242 QMenu *
Chris@151 243 SubdividingMenu::addMenu(const QString &name)
Chris@151 244 {
Chris@152 245 if (!m_entriesSet) {
Chris@152 246 QMenu *menu = new QMenu(name, this);
Chris@152 247 m_pendingEntries[name] = menu;
Chris@152 248 return menu;
Chris@152 249 }
Chris@152 250
Chris@151 251 if (m_nameToChunkMenuMap.find(name) == m_nameToChunkMenuMap.end()) {
Chris@152 252 // std::cerr << "SubdividingMenu::addMenu(" << name.toStdString() << "): not found in name-to-chunk map, adding to main menu" << std::endl;
Chris@151 253 return QMenu::addMenu(name);
Chris@151 254 }
Chris@151 255
Chris@152 256 // std::cerr << "SubdividingMenu::addMenu(" << name.toStdString() << "): found in name-to-chunk map for menu " << m_nameToChunkMenuMap[name]->title().toStdString() << std::endl;
Chris@151 257 return m_nameToChunkMenuMap[name]->addMenu(name);
Chris@151 258 }
Chris@151 259
Chris@151 260 void
Chris@151 261 SubdividingMenu::addMenu(const QString &name, QMenu *menu)
Chris@151 262 {
Chris@152 263 if (!m_entriesSet) {
Chris@152 264 m_pendingEntries[name] = menu;
Chris@152 265 return;
Chris@152 266 }
Chris@152 267
Chris@151 268 if (m_nameToChunkMenuMap.find(name) == m_nameToChunkMenuMap.end()) {
Chris@152 269 // std::cerr << "SubdividingMenu::addMenu(" << name.toStdString() << "): not found in name-to-chunk map, adding to main menu" << std::endl;
Chris@151 270 QMenu::addMenu(menu);
Chris@151 271 return;
Chris@151 272 }
Chris@151 273
Chris@152 274 // std::cerr << "SubdividingMenu::addMenu(" << name.toStdString() << "): found in name-to-chunk map for menu " << m_nameToChunkMenuMap[name]->title().toStdString() << std::endl;
Chris@151 275 m_nameToChunkMenuMap[name]->addMenu(menu);
Chris@151 276 }
Chris@151 277