annotate widgets/SubdividingMenu.cpp @ 158:9c3a4b42d8f8

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