svgui
1.9
|
00001 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ 00002 00003 /* 00004 Sonic Visualiser 00005 An audio file viewer and annotation editor. 00006 Centre for Digital Music, Queen Mary, University of London. 00007 This file copyright 2006 QMUL. 00008 00009 This program is free software; you can redistribute it and/or 00010 modify it under the terms of the GNU General Public License as 00011 published by the Free Software Foundation; either version 2 of the 00012 License, or (at your option) any later version. See the file 00013 COPYING included with this distribution for more information. 00014 */ 00015 00016 #include "SubdividingMenu.h" 00017 00018 #include <iostream> 00019 00020 #include "base/Debug.h" 00021 00022 using std::set; 00023 using std::map; 00024 00025 SubdividingMenu::SubdividingMenu(int lowerLimit, int upperLimit, 00026 QWidget *parent) : 00027 QMenu(parent), 00028 m_lowerLimit(lowerLimit ? lowerLimit : 14), 00029 m_upperLimit(upperLimit ? upperLimit : (m_lowerLimit * 5) / 2), 00030 m_entriesSet(false) 00031 { 00032 } 00033 00034 SubdividingMenu::SubdividingMenu(const QString &title, int lowerLimit, 00035 int upperLimit, QWidget *parent) : 00036 QMenu(title, parent), 00037 m_lowerLimit(lowerLimit ? lowerLimit : 14), 00038 m_upperLimit(upperLimit ? upperLimit : (m_lowerLimit * 5) / 2), 00039 m_entriesSet(false) 00040 { 00041 } 00042 00043 SubdividingMenu::~SubdividingMenu() 00044 { 00045 for (map<QString, QObject *>::iterator i = m_pendingEntries.begin(); 00046 i != m_pendingEntries.end(); ++i) { 00047 delete i->second; 00048 } 00049 } 00050 00051 void 00052 SubdividingMenu::setEntries(const std::set<QString> &entries) 00053 { 00054 m_entriesSet = true; 00055 00056 int total = entries.size(); 00057 00058 if (total < m_upperLimit) return; 00059 00060 int count = 0; 00061 QMenu *chunkMenu = new QMenu(); 00062 chunkMenu->setTearOffEnabled(isTearOffEnabled()); 00063 00064 QString firstNameInChunk; 00065 QChar firstInitialInChunk; 00066 bool discriminateStartInitial = false; 00067 00068 for (set<QString>::const_iterator j = entries.begin(); 00069 j != entries.end(); 00070 ++j) { 00071 00072 // SVDEBUG << "SubdividingMenu::setEntries: j -> " << j->toStdString() << endl; 00073 00074 m_nameToChunkMenuMap[*j] = chunkMenu; 00075 00076 set<QString>::iterator k = j; 00077 ++k; 00078 00079 QChar initial = (*j)[0]; 00080 00081 if (count == 0) { 00082 firstNameInChunk = *j; 00083 firstInitialInChunk = initial; 00084 } 00085 00086 // cerr << "count = "<< count << ", upper limit = " << m_upperLimit << endl; 00087 00088 bool lastInChunk = (k == entries.end() || 00089 (count >= m_lowerLimit-1 && 00090 (count == m_upperLimit || 00091 (*k)[0] != initial))); 00092 00093 ++count; 00094 00095 if (lastInChunk) { 00096 00097 bool discriminateEndInitial = (k != entries.end() && 00098 (*k)[0] == initial); 00099 00100 bool initialsEqual = (firstInitialInChunk == initial); 00101 00102 QString from = QString("%1").arg(firstInitialInChunk); 00103 if (discriminateStartInitial || 00104 (discriminateEndInitial && initialsEqual)) { 00105 from = firstNameInChunk.left(3); 00106 } 00107 00108 QString to = QString("%1").arg(initial); 00109 if (discriminateEndInitial || 00110 (discriminateStartInitial && initialsEqual)) { 00111 to = j->left(3); 00112 } 00113 00114 QString menuText; 00115 00116 if (from == to) menuText = from; 00117 else menuText = tr("%1 - %2").arg(from).arg(to); 00118 00119 discriminateStartInitial = discriminateEndInitial; 00120 00121 chunkMenu->setTitle(menuText); 00122 00123 QMenu::addMenu(chunkMenu); 00124 00125 chunkMenu = new QMenu(); 00126 chunkMenu->setTearOffEnabled(isTearOffEnabled()); 00127 00128 count = 0; 00129 } 00130 } 00131 00132 if (count == 0) delete chunkMenu; 00133 } 00134 00135 void 00136 SubdividingMenu::entriesAdded() 00137 { 00138 if (m_entriesSet) { 00139 cerr << "ERROR: SubdividingMenu::entriesAdded: setEntries was also called -- should use one mechanism or the other, but not both" << endl; 00140 return; 00141 } 00142 00143 set<QString> entries; 00144 for (map<QString, QObject *>::const_iterator i = m_pendingEntries.begin(); 00145 i != m_pendingEntries.end(); ++i) { 00146 entries.insert(i->first); 00147 } 00148 00149 setEntries(entries); 00150 00151 for (map<QString, QObject *>::iterator i = m_pendingEntries.begin(); 00152 i != m_pendingEntries.end(); ++i) { 00153 00154 QMenu *menu = dynamic_cast<QMenu *>(i->second); 00155 if (menu) { 00156 addMenu(i->first, menu); 00157 continue; 00158 } 00159 00160 QAction *action = dynamic_cast<QAction *>(i->second); 00161 if (action) { 00162 addAction(i->first, action); 00163 continue; 00164 } 00165 } 00166 00167 m_pendingEntries.clear(); 00168 } 00169 00170 void 00171 SubdividingMenu::addAction(QAction *action) 00172 { 00173 QString name = action->text(); 00174 00175 if (!m_entriesSet) { 00176 m_pendingEntries[name] = action; 00177 return; 00178 } 00179 00180 if (m_nameToChunkMenuMap.find(name) == m_nameToChunkMenuMap.end()) { 00181 // SVDEBUG << "SubdividingMenu::addAction(" << name << "): not found in name-to-chunk map, adding to main menu" << endl; 00182 QMenu::addAction(action); 00183 return; 00184 } 00185 00186 // SVDEBUG << "SubdividingMenu::addAction(" << name << "): found in name-to-chunk map for menu " << m_nameToChunkMenuMap[name]->title() << endl; 00187 m_nameToChunkMenuMap[name]->addAction(action); 00188 } 00189 00190 QAction * 00191 SubdividingMenu::addAction(const QString &name) 00192 { 00193 if (!m_entriesSet) { 00194 QAction *action = new QAction(name, this); 00195 m_pendingEntries[name] = action; 00196 return action; 00197 } 00198 00199 if (m_nameToChunkMenuMap.find(name) == m_nameToChunkMenuMap.end()) { 00200 // SVDEBUG << "SubdividingMenu::addAction(" << name << "): not found in name-to-chunk map, adding to main menu" << endl; 00201 return QMenu::addAction(name); 00202 } 00203 00204 // SVDEBUG << "SubdividingMenu::addAction(" << name << "): found in name-to-chunk map for menu " << m_nameToChunkMenuMap[name]->title() << endl; 00205 return m_nameToChunkMenuMap[name]->addAction(name); 00206 } 00207 00208 void 00209 SubdividingMenu::addAction(const QString &name, QAction *action) 00210 { 00211 if (!m_entriesSet) { 00212 m_pendingEntries[name] = action; 00213 return; 00214 } 00215 00216 if (m_nameToChunkMenuMap.find(name) == m_nameToChunkMenuMap.end()) { 00217 // SVDEBUG << "SubdividingMenu::addAction(" << name << "): not found in name-to-chunk map, adding to main menu" << endl; 00218 QMenu::addAction(action); 00219 return; 00220 } 00221 00222 // SVDEBUG << "SubdividingMenu::addAction(" << name << "): found in name-to-chunk map for menu " << m_nameToChunkMenuMap[name]->title() << endl; 00223 m_nameToChunkMenuMap[name]->addAction(action); 00224 } 00225 00226 void 00227 SubdividingMenu::addMenu(QMenu *menu) 00228 { 00229 QString name = menu->title(); 00230 00231 if (!m_entriesSet) { 00232 m_pendingEntries[name] = menu; 00233 return; 00234 } 00235 00236 if (m_nameToChunkMenuMap.find(name) == m_nameToChunkMenuMap.end()) { 00237 // SVDEBUG << "SubdividingMenu::addMenu(" << name << "): not found in name-to-chunk map, adding to main menu" << endl; 00238 QMenu::addMenu(menu); 00239 return; 00240 } 00241 00242 // SVDEBUG << "SubdividingMenu::addMenu(" << name << "): found in name-to-chunk map for menu " << m_nameToChunkMenuMap[name]->title() << endl; 00243 m_nameToChunkMenuMap[name]->addMenu(menu); 00244 } 00245 00246 QMenu * 00247 SubdividingMenu::addMenu(const QString &name) 00248 { 00249 if (!m_entriesSet) { 00250 QMenu *menu = new QMenu(name, this); 00251 menu->setTearOffEnabled(isTearOffEnabled()); 00252 m_pendingEntries[name] = menu; 00253 return menu; 00254 } 00255 00256 if (m_nameToChunkMenuMap.find(name) == m_nameToChunkMenuMap.end()) { 00257 // SVDEBUG << "SubdividingMenu::addMenu(" << name << "): not found in name-to-chunk map, adding to main menu" << endl; 00258 return QMenu::addMenu(name); 00259 } 00260 00261 // SVDEBUG << "SubdividingMenu::addMenu(" << name << "): found in name-to-chunk map for menu " << m_nameToChunkMenuMap[name]->title() << endl; 00262 return m_nameToChunkMenuMap[name]->addMenu(name); 00263 } 00264 00265 void 00266 SubdividingMenu::addMenu(const QString &name, QMenu *menu) 00267 { 00268 if (!m_entriesSet) { 00269 m_pendingEntries[name] = menu; 00270 return; 00271 } 00272 00273 if (m_nameToChunkMenuMap.find(name) == m_nameToChunkMenuMap.end()) { 00274 // SVDEBUG << "SubdividingMenu::addMenu(" << name << "): not found in name-to-chunk map, adding to main menu" << endl; 00275 QMenu::addMenu(menu); 00276 return; 00277 } 00278 00279 // SVDEBUG << "SubdividingMenu::addMenu(" << name << "): found in name-to-chunk map for menu " << m_nameToChunkMenuMap[name]->title() << endl; 00280 m_nameToChunkMenuMap[name]->addMenu(menu); 00281 } 00282