comparison widgets/SubdividingMenu.cpp @ 0:fc9323a41f5a

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