Mercurial > hg > easaier-soundaccess
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 |