annotate widgets/SubdividingMenu.cpp @ 282:d9319859a4cf tip

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