SubdividingMenu.cpp

Go to the documentation of this file.
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 using std::set;
00021 using std::map;
00022 
00023 SubdividingMenu::SubdividingMenu(size_t lowerLimit, size_t upperLimit,
00024                                  QWidget *parent) :
00025     QMenu(parent),
00026     m_lowerLimit(lowerLimit ? lowerLimit : 14),
00027     m_upperLimit(upperLimit ? upperLimit : (m_lowerLimit * 5) / 2),
00028     m_entriesSet(false)
00029 {
00030 }
00031 
00032 SubdividingMenu::SubdividingMenu(const QString &title, size_t lowerLimit,
00033                                  size_t upperLimit, QWidget *parent) :
00034     QMenu(title, parent),
00035     m_lowerLimit(lowerLimit ? lowerLimit : 14),
00036     m_upperLimit(upperLimit ? upperLimit : (m_lowerLimit * 5) / 2),
00037     m_entriesSet(false)
00038 {
00039 }
00040 
00041 SubdividingMenu::~SubdividingMenu()
00042 {
00043     for (map<QString, QObject *>::iterator i = m_pendingEntries.begin();
00044          i != m_pendingEntries.end(); ++i) {
00045         delete i->second;
00046     }
00047 }
00048 
00049 void
00050 SubdividingMenu::setEntries(const std::set<QString> &entries)
00051 {
00052     m_entriesSet = true;
00053 
00054     size_t total = entries.size();
00055         
00056     if (total < m_upperLimit) return;
00057 
00058     size_t count = 0;
00059     QMenu *chunkMenu = new QMenu();
00060     chunkMenu->setTearOffEnabled(isTearOffEnabled());
00061 
00062     QString firstNameInChunk;
00063     QChar firstInitialInChunk;
00064     bool discriminateStartInitial = false;
00065 
00066     for (set<QString>::const_iterator j = entries.begin();
00067          j != entries.end();
00068          ++j) {
00069 
00070 //        std::cerr << "SubdividingMenu::setEntries: j -> " << j->toStdString() << std::endl;
00071 
00072         m_nameToChunkMenuMap[*j] = chunkMenu;
00073 
00074         set<QString>::iterator k = j;
00075         ++k;
00076 
00077         QChar initial = (*j)[0];
00078 
00079         if (count == 0) {
00080             firstNameInChunk = *j;
00081             firstInitialInChunk = initial;
00082         }
00083 
00084 //        std::cerr << "count = "<< count << ", upper limit = " << m_upperLimit << std::endl;
00085 
00086         bool lastInChunk = (k == entries.end() ||
00087                             (count >= m_lowerLimit-1 &&
00088                              (count == m_upperLimit ||
00089                               (*k)[0] != initial)));
00090 
00091         ++count;
00092 
00093         if (lastInChunk) {
00094 
00095             bool discriminateEndInitial = (k != entries.end() &&
00096                                            (*k)[0] == initial);
00097 
00098             bool initialsEqual = (firstInitialInChunk == initial);
00099 
00100             QString from = QString("%1").arg(firstInitialInChunk);
00101             if (discriminateStartInitial ||
00102                 (discriminateEndInitial && initialsEqual)) {
00103                 from = firstNameInChunk.left(3);
00104             }
00105 
00106             QString to = QString("%1").arg(initial);
00107             if (discriminateEndInitial ||
00108                 (discriminateStartInitial && initialsEqual)) {
00109                 to = j->left(3);
00110             }
00111 
00112             QString menuText;
00113             
00114             if (from == to) menuText = from;
00115             else menuText = tr("%1 - %2").arg(from).arg(to);
00116             
00117             discriminateStartInitial = discriminateEndInitial;
00118 
00119             chunkMenu->setTitle(menuText);
00120                 
00121             QMenu::addMenu(chunkMenu);
00122             
00123             chunkMenu = new QMenu();
00124             chunkMenu->setTearOffEnabled(isTearOffEnabled());
00125             
00126             count = 0;
00127         }
00128     }
00129     
00130     if (count == 0) delete chunkMenu;
00131 }
00132 
00133 void
00134 SubdividingMenu::entriesAdded()
00135 {
00136     if (m_entriesSet) {
00137         std::cerr << "ERROR: SubdividingMenu::entriesAdded: setEntries was also called -- should use one mechanism or the other, but not both" << std::endl;
00138         return;
00139     }
00140     
00141     set<QString> entries;
00142     for (map<QString, QObject *>::const_iterator i = m_pendingEntries.begin();
00143          i != m_pendingEntries.end(); ++i) {
00144         entries.insert(i->first);
00145     }
00146     
00147     setEntries(entries);
00148 
00149     for (map<QString, QObject *>::iterator i = m_pendingEntries.begin();
00150          i != m_pendingEntries.end(); ++i) {
00151 
00152         QMenu *menu = dynamic_cast<QMenu *>(i->second);
00153         if (menu) {
00154             addMenu(i->first, menu);
00155             continue;
00156         }
00157 
00158         QAction *action = dynamic_cast<QAction *>(i->second);
00159         if (action) {
00160             addAction(i->first, action);
00161             continue;
00162         }
00163     }
00164 
00165     m_pendingEntries.clear();
00166 }
00167 
00168 void
00169 SubdividingMenu::addAction(QAction *action)
00170 {
00171     QString name = action->text();
00172 
00173     if (!m_entriesSet) {
00174         m_pendingEntries[name] = action;
00175         return;
00176     }
00177 
00178     if (m_nameToChunkMenuMap.find(name) == m_nameToChunkMenuMap.end()) {
00179 //        std::cerr << "SubdividingMenu::addAction(" << name.toStdString() << "): not found in name-to-chunk map, adding to main menu" << std::endl;
00180         QMenu::addAction(action);
00181         return;
00182     }
00183 
00184 //    std::cerr << "SubdividingMenu::addAction(" << name.toStdString() << "): found in name-to-chunk map for menu " << m_nameToChunkMenuMap[name]->title().toStdString() << std::endl;
00185     m_nameToChunkMenuMap[name]->addAction(action);
00186 }
00187 
00188 QAction *
00189 SubdividingMenu::addAction(const QString &name)
00190 {
00191     if (!m_entriesSet) {
00192         QAction *action = new QAction(name, this);
00193         m_pendingEntries[name] = action;
00194         return action;
00195     }
00196 
00197     if (m_nameToChunkMenuMap.find(name) == m_nameToChunkMenuMap.end()) {
00198 //        std::cerr << "SubdividingMenu::addAction(" << name.toStdString() << "): not found in name-to-chunk map, adding to main menu" << std::endl;
00199         return QMenu::addAction(name);
00200     }
00201 
00202 //    std::cerr << "SubdividingMenu::addAction(" << name.toStdString() << "): found in name-to-chunk map for menu " << m_nameToChunkMenuMap[name]->title().toStdString() << std::endl;
00203     return m_nameToChunkMenuMap[name]->addAction(name);
00204 }
00205 
00206 void
00207 SubdividingMenu::addAction(const QString &name, QAction *action)
00208 {
00209     if (!m_entriesSet) {
00210         m_pendingEntries[name] = action;
00211         return;
00212     }
00213 
00214     if (m_nameToChunkMenuMap.find(name) == m_nameToChunkMenuMap.end()) {
00215 //        std::cerr << "SubdividingMenu::addAction(" << name.toStdString() << "): not found in name-to-chunk map, adding to main menu" << std::endl;
00216         QMenu::addAction(action);
00217         return;
00218     }
00219 
00220 //    std::cerr << "SubdividingMenu::addAction(" << name.toStdString() << "): found in name-to-chunk map for menu " << m_nameToChunkMenuMap[name]->title().toStdString() << std::endl;
00221     m_nameToChunkMenuMap[name]->addAction(action);
00222 }
00223 
00224 void
00225 SubdividingMenu::addMenu(QMenu *menu)
00226 {
00227     QString name = menu->title();
00228 
00229     if (!m_entriesSet) {
00230         m_pendingEntries[name] = menu;
00231         return;
00232     }
00233 
00234     if (m_nameToChunkMenuMap.find(name) == m_nameToChunkMenuMap.end()) {
00235 //        std::cerr << "SubdividingMenu::addMenu(" << name.toStdString() << "): not found in name-to-chunk map, adding to main menu" << std::endl;
00236         QMenu::addMenu(menu);
00237         return;
00238     }
00239 
00240 //    std::cerr << "SubdividingMenu::addMenu(" << name.toStdString() << "): found in name-to-chunk map for menu " << m_nameToChunkMenuMap[name]->title().toStdString() << std::endl;
00241     m_nameToChunkMenuMap[name]->addMenu(menu);
00242 }
00243 
00244 QMenu *
00245 SubdividingMenu::addMenu(const QString &name)
00246 {
00247     if (!m_entriesSet) {
00248         QMenu *menu = new QMenu(name, this);
00249         menu->setTearOffEnabled(isTearOffEnabled());
00250         m_pendingEntries[name] = menu;
00251         return menu;
00252     }
00253 
00254     if (m_nameToChunkMenuMap.find(name) == m_nameToChunkMenuMap.end()) {
00255 //        std::cerr << "SubdividingMenu::addMenu(" << name.toStdString() << "): not found in name-to-chunk map, adding to main menu" << std::endl;
00256         return QMenu::addMenu(name);
00257     }
00258 
00259 //    std::cerr << "SubdividingMenu::addMenu(" << name.toStdString() << "): found in name-to-chunk map for menu " << m_nameToChunkMenuMap[name]->title().toStdString() << std::endl;
00260     return m_nameToChunkMenuMap[name]->addMenu(name);
00261 }
00262 
00263 void
00264 SubdividingMenu::addMenu(const QString &name, QMenu *menu)
00265 {
00266     if (!m_entriesSet) {
00267         m_pendingEntries[name] = menu;
00268         return;
00269     }
00270 
00271     if (m_nameToChunkMenuMap.find(name) == m_nameToChunkMenuMap.end()) {
00272 //        std::cerr << "SubdividingMenu::addMenu(" << name.toStdString() << "): not found in name-to-chunk map, adding to main menu" << std::endl;
00273         QMenu::addMenu(menu);
00274         return;
00275     }
00276 
00277 //    std::cerr << "SubdividingMenu::addMenu(" << name.toStdString() << "): found in name-to-chunk map for menu " << m_nameToChunkMenuMap[name]->title().toStdString() << std::endl;
00278     m_nameToChunkMenuMap[name]->addMenu(menu);
00279 }
00280 

Generated on Wed Feb 20 15:45:28 2008 for SonicVisualiser by  doxygen 1.5.1