annotate widgets/SubdividingMenu.cpp @ 182:42118892f428

* Update copyright notes as appropriate.
author Chris Cannam
date Fri, 17 Nov 2006 16:27:39 +0000
parents 6a3f3c13173f
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