changeset 152:6a3f3c13173f

* Add a friendlier setup mechanism to SubdividingMenu, and use it for all the plugin menus, not just the by-name and by-maker ones
author Chris Cannam
date Mon, 25 Sep 2006 12:05:41 +0000
parents 8f51db2434dc
children aaa3a53dbb10
files widgets/SubdividingMenu.cpp widgets/SubdividingMenu.h
diffstat 2 files changed, 116 insertions(+), 24 deletions(-) [+]
line wrap: on
line diff
--- a/widgets/SubdividingMenu.cpp	Mon Sep 25 11:21:12 2006 +0000
+++ b/widgets/SubdividingMenu.cpp	Mon Sep 25 12:05:41 2006 +0000
@@ -19,27 +19,40 @@
 using std::set;
 using std::map;
 
-SubdividingMenu::SubdividingMenu(QWidget *parent) :
-    QMenu(parent)
+SubdividingMenu::SubdividingMenu(size_t lowerLimit, size_t upperLimit,
+                                 QWidget *parent) :
+    QMenu(parent),
+    m_lowerLimit(lowerLimit ? lowerLimit : 14),
+    m_upperLimit(upperLimit ? upperLimit : (m_lowerLimit * 5) / 2),
+    m_entriesSet(false)
 {
 }
 
-SubdividingMenu::SubdividingMenu(const QString &title, QWidget *parent) :
-    QMenu(title, parent)
+SubdividingMenu::SubdividingMenu(const QString &title, size_t lowerLimit,
+                                 size_t upperLimit, QWidget *parent) :
+    QMenu(title, parent),
+    m_lowerLimit(lowerLimit ? lowerLimit : 14),
+    m_upperLimit(upperLimit ? upperLimit : (m_lowerLimit * 5) / 2),
+    m_entriesSet(false)
 {
 }
 
 SubdividingMenu::~SubdividingMenu()
 {
+    for (map<QString, QObject *>::iterator i = m_pendingEntries.begin();
+         i != m_pendingEntries.end(); ++i) {
+        delete i->second;
+    }
 }
 
 void
 SubdividingMenu::setEntries(const std::set<QString> &entries)
 {
+    m_entriesSet = true;
+
     size_t total = entries.size();
-    size_t chunk = 14;
         
-    if (total < (chunk * 3) / 2) return;
+    if (total < m_upperLimit) return;
 
     size_t count = 0;
     QMenu *chunkMenu = new QMenu();
@@ -52,7 +65,7 @@
          j != entries.end();
          ++j) {
 
-        std::cerr << "SubdividingMenu::setEntries: j -> " << j->toStdString() << std::endl;
+//        std::cerr << "SubdividingMenu::setEntries: j -> " << j->toStdString() << std::endl;
 
         m_nameToChunkMenuMap[*j] = chunkMenu;
 
@@ -66,9 +79,11 @@
             firstInitialInChunk = initial;
         }
 
+//        std::cerr << "count = "<< count << ", upper limit = " << m_upperLimit << std::endl;
+
         bool lastInChunk = (k == entries.end() ||
-                            (count >= chunk-1 &&
-                             (count == (5*chunk) / 2 ||
+                            (count >= m_lowerLimit-1 &&
+                             (count == m_upperLimit ||
                               (*k)[0] != initial)));
 
         ++count;
@@ -113,42 +128,93 @@
 }
 
 void
+SubdividingMenu::entriesAdded()
+{
+    if (m_entriesSet) {
+        std::cerr << "ERROR: SubdividingMenu::entriesAdded: setEntries was also called -- should use one mechanism or the other, but not both" << std::endl;
+        return;
+    }
+    
+    set<QString> entries;
+    for (map<QString, QObject *>::const_iterator i = m_pendingEntries.begin();
+         i != m_pendingEntries.end(); ++i) {
+        entries.insert(i->first);
+    }
+    
+    setEntries(entries);
+
+    for (map<QString, QObject *>::iterator i = m_pendingEntries.begin();
+         i != m_pendingEntries.end(); ++i) {
+
+        QMenu *menu = dynamic_cast<QMenu *>(i->second);
+        if (menu) {
+            addMenu(i->first, menu);
+            continue;
+        }
+
+        QAction *action = dynamic_cast<QAction *>(i->second);
+        if (action) {
+            addAction(i->first, action);
+            continue;
+        }
+    }
+
+    m_pendingEntries.clear();
+}
+
+void
 SubdividingMenu::addAction(QAction *action)
 {
     QString name = action->text();
 
+    if (!m_entriesSet) {
+        m_pendingEntries[name] = action;
+        return;
+    }
+
     if (m_nameToChunkMenuMap.find(name) == m_nameToChunkMenuMap.end()) {
-        std::cerr << "SubdividingMenu::addAction(" << name.toStdString() << "): not found in name-to-chunk map, adding to main menu" << std::endl;
+//        std::cerr << "SubdividingMenu::addAction(" << name.toStdString() << "): not found in name-to-chunk map, adding to main menu" << std::endl;
         QMenu::addAction(action);
         return;
     }
 
-    std::cerr << "SubdividingMenu::addAction(" << name.toStdString() << "): found in name-to-chunk map for menu " << m_nameToChunkMenuMap[name]->title().toStdString() << std::endl;
+//    std::cerr << "SubdividingMenu::addAction(" << name.toStdString() << "): found in name-to-chunk map for menu " << m_nameToChunkMenuMap[name]->title().toStdString() << std::endl;
     m_nameToChunkMenuMap[name]->addAction(action);
 }
 
 QAction *
 SubdividingMenu::addAction(const QString &name)
 {
+    if (!m_entriesSet) {
+        QAction *action = new QAction(name, this);
+        m_pendingEntries[name] = action;
+        return action;
+    }
+
     if (m_nameToChunkMenuMap.find(name) == m_nameToChunkMenuMap.end()) {
-        std::cerr << "SubdividingMenu::addAction(" << name.toStdString() << "): not found in name-to-chunk map, adding to main menu" << std::endl;
+//        std::cerr << "SubdividingMenu::addAction(" << name.toStdString() << "): not found in name-to-chunk map, adding to main menu" << std::endl;
         return QMenu::addAction(name);
     }
 
-    std::cerr << "SubdividingMenu::addAction(" << name.toStdString() << "): found in name-to-chunk map for menu " << m_nameToChunkMenuMap[name]->title().toStdString() << std::endl;
+//    std::cerr << "SubdividingMenu::addAction(" << name.toStdString() << "): found in name-to-chunk map for menu " << m_nameToChunkMenuMap[name]->title().toStdString() << std::endl;
     return m_nameToChunkMenuMap[name]->addAction(name);
 }
 
 void
 SubdividingMenu::addAction(const QString &name, QAction *action)
 {
+    if (!m_entriesSet) {
+        m_pendingEntries[name] = action;
+        return;
+    }
+
     if (m_nameToChunkMenuMap.find(name) == m_nameToChunkMenuMap.end()) {
-        std::cerr << "SubdividingMenu::addAction(" << name.toStdString() << "): not found in name-to-chunk map, adding to main menu" << std::endl;
+//        std::cerr << "SubdividingMenu::addAction(" << name.toStdString() << "): not found in name-to-chunk map, adding to main menu" << std::endl;
         QMenu::addAction(action);
         return;
     }
 
-    std::cerr << "SubdividingMenu::addAction(" << name.toStdString() << "): found in name-to-chunk map for menu " << m_nameToChunkMenuMap[name]->title().toStdString() << std::endl;
+//    std::cerr << "SubdividingMenu::addAction(" << name.toStdString() << "): found in name-to-chunk map for menu " << m_nameToChunkMenuMap[name]->title().toStdString() << std::endl;
     m_nameToChunkMenuMap[name]->addAction(action);
 }
 
@@ -157,38 +223,54 @@
 {
     QString name = menu->title();
 
+    if (!m_entriesSet) {
+        m_pendingEntries[name] = menu;
+        return;
+    }
+
     if (m_nameToChunkMenuMap.find(name) == m_nameToChunkMenuMap.end()) {
-        std::cerr << "SubdividingMenu::addMenu(" << name.toStdString() << "): not found in name-to-chunk map, adding to main menu" << std::endl;
+//        std::cerr << "SubdividingMenu::addMenu(" << name.toStdString() << "): not found in name-to-chunk map, adding to main menu" << std::endl;
         QMenu::addMenu(menu);
         return;
     }
 
-    std::cerr << "SubdividingMenu::addMenu(" << name.toStdString() << "): found in name-to-chunk map for menu " << m_nameToChunkMenuMap[name]->title().toStdString() << std::endl;
+//    std::cerr << "SubdividingMenu::addMenu(" << name.toStdString() << "): found in name-to-chunk map for menu " << m_nameToChunkMenuMap[name]->title().toStdString() << std::endl;
     m_nameToChunkMenuMap[name]->addMenu(menu);
 }
 
 QMenu *
 SubdividingMenu::addMenu(const QString &name)
 {
+    if (!m_entriesSet) {
+        QMenu *menu = new QMenu(name, this);
+        m_pendingEntries[name] = menu;
+        return menu;
+    }
+
     if (m_nameToChunkMenuMap.find(name) == m_nameToChunkMenuMap.end()) {
-        std::cerr << "SubdividingMenu::addMenu(" << name.toStdString() << "): not found in name-to-chunk map, adding to main menu" << std::endl;
+//        std::cerr << "SubdividingMenu::addMenu(" << name.toStdString() << "): not found in name-to-chunk map, adding to main menu" << std::endl;
         return QMenu::addMenu(name);
     }
 
-    std::cerr << "SubdividingMenu::addMenu(" << name.toStdString() << "): found in name-to-chunk map for menu " << m_nameToChunkMenuMap[name]->title().toStdString() << std::endl;
+//    std::cerr << "SubdividingMenu::addMenu(" << name.toStdString() << "): found in name-to-chunk map for menu " << m_nameToChunkMenuMap[name]->title().toStdString() << std::endl;
     return m_nameToChunkMenuMap[name]->addMenu(name);
 }
 
 void
 SubdividingMenu::addMenu(const QString &name, QMenu *menu)
 {
+    if (!m_entriesSet) {
+        m_pendingEntries[name] = menu;
+        return;
+    }
+
     if (m_nameToChunkMenuMap.find(name) == m_nameToChunkMenuMap.end()) {
-        std::cerr << "SubdividingMenu::addMenu(" << name.toStdString() << "): not found in name-to-chunk map, adding to main menu" << std::endl;
+//        std::cerr << "SubdividingMenu::addMenu(" << name.toStdString() << "): not found in name-to-chunk map, adding to main menu" << std::endl;
         QMenu::addMenu(menu);
         return;
     }
 
-    std::cerr << "SubdividingMenu::addMenu(" << name.toStdString() << "): found in name-to-chunk map for menu " << m_nameToChunkMenuMap[name]->title().toStdString() << std::endl;
+//    std::cerr << "SubdividingMenu::addMenu(" << name.toStdString() << "): found in name-to-chunk map for menu " << m_nameToChunkMenuMap[name]->title().toStdString() << std::endl;
     m_nameToChunkMenuMap[name]->addMenu(menu);
 }
 
--- a/widgets/SubdividingMenu.h	Mon Sep 25 11:21:12 2006 +0000
+++ b/widgets/SubdividingMenu.h	Mon Sep 25 12:05:41 2006 +0000
@@ -29,17 +29,21 @@
  * The menu needs to be told, before any of the actions are added,
  * what the set of entry strings will be, so it can determine a
  * reasonable categorisation.  Do this by calling the setEntries()
- * method.
+ * method.  If it isn't practical to do this in advance, then add the
+ * entries and call entriesAdded() afterwards instead. 
  */
 
 class SubdividingMenu : public QMenu
 {
 public:
-    SubdividingMenu(QWidget *parent = 0);
-    SubdividingMenu(const QString &title, QWidget *parent = 0);
+    SubdividingMenu(size_t lowerLimit = 0, size_t upperLimit = 0,
+                    QWidget *parent = 0);
+    SubdividingMenu(const QString &title, size_t lowerLimit = 0,
+                    size_t upperLimit = 0, QWidget *parent = 0);
     virtual ~SubdividingMenu();
 
     void setEntries(const std::set<QString> &entries);
+    void entriesAdded();
 
     // Action names and strings passed to addAction and addMenu must
     // appear in the set previously given to setEntries.  If you want
@@ -57,6 +61,12 @@
 
 protected:
     std::map<QString, QMenu *> m_nameToChunkMenuMap;
+
+    size_t m_lowerLimit;
+    size_t m_upperLimit;
+
+    bool m_entriesSet;
+    std::map<QString, QObject *> m_pendingEntries;
 };
 
 #endif