Mercurial > hg > svgui
changeset 151:8f51db2434dc
* Pull alphabetical categorisation code out into a SubdividingMenu class
author | Chris Cannam |
---|---|
date | Mon, 25 Sep 2006 11:21:12 +0000 |
parents | b1a3a9400284 |
children | 6a3f3c13173f |
files | widgets/SubdividingMenu.cpp widgets/SubdividingMenu.h widgets/widgets.pro |
diffstat | 3 files changed, 259 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/widgets/SubdividingMenu.cpp Mon Sep 25 11:21:12 2006 +0000 @@ -0,0 +1,194 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Sonic Visualiser + An audio file viewer and annotation editor. + Centre for Digital Music, Queen Mary, University of London. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#include "SubdividingMenu.h" + +#include <iostream> + +using std::set; +using std::map; + +SubdividingMenu::SubdividingMenu(QWidget *parent) : + QMenu(parent) +{ +} + +SubdividingMenu::SubdividingMenu(const QString &title, QWidget *parent) : + QMenu(title, parent) +{ +} + +SubdividingMenu::~SubdividingMenu() +{ +} + +void +SubdividingMenu::setEntries(const std::set<QString> &entries) +{ + size_t total = entries.size(); + size_t chunk = 14; + + if (total < (chunk * 3) / 2) return; + + size_t count = 0; + QMenu *chunkMenu = new QMenu(); + + QString firstNameInChunk; + QChar firstInitialInChunk; + bool discriminateStartInitial = false; + + for (set<QString>::const_iterator j = entries.begin(); + j != entries.end(); + ++j) { + + std::cerr << "SubdividingMenu::setEntries: j -> " << j->toStdString() << std::endl; + + m_nameToChunkMenuMap[*j] = chunkMenu; + + set<QString>::iterator k = j; + ++k; + + QChar initial = (*j)[0]; + + if (count == 0) { + firstNameInChunk = *j; + firstInitialInChunk = initial; + } + + bool lastInChunk = (k == entries.end() || + (count >= chunk-1 && + (count == (5*chunk) / 2 || + (*k)[0] != initial))); + + ++count; + + if (lastInChunk) { + + bool discriminateEndInitial = (k != entries.end() && + (*k)[0] == initial); + + bool initialsEqual = (firstInitialInChunk == initial); + + QString from = QString("%1").arg(firstInitialInChunk); + if (discriminateStartInitial || + (discriminateEndInitial && initialsEqual)) { + from = firstNameInChunk.left(3); + } + + QString to = QString("%1").arg(initial); + if (discriminateEndInitial || + (discriminateStartInitial && initialsEqual)) { + to = j->left(3); + } + + QString menuText; + + if (from == to) menuText = from; + else menuText = tr("%1 - %2").arg(from).arg(to); + + discriminateStartInitial = discriminateEndInitial; + + chunkMenu->setTitle(menuText); + + QMenu::addMenu(chunkMenu); + + chunkMenu = new QMenu(); + + count = 0; + } + } + + if (count == 0) delete chunkMenu; +} + +void +SubdividingMenu::addAction(QAction *action) +{ + QString name = action->text(); + + 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; + 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; + m_nameToChunkMenuMap[name]->addAction(action); +} + +QAction * +SubdividingMenu::addAction(const QString &name) +{ + 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; + 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; + return m_nameToChunkMenuMap[name]->addAction(name); +} + +void +SubdividingMenu::addAction(const QString &name, QAction *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; + 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; + m_nameToChunkMenuMap[name]->addAction(action); +} + +void +SubdividingMenu::addMenu(QMenu *menu) +{ + QString name = menu->title(); + + 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; + 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; + m_nameToChunkMenuMap[name]->addMenu(menu); +} + +QMenu * +SubdividingMenu::addMenu(const QString &name) +{ + 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; + 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; + return m_nameToChunkMenuMap[name]->addMenu(name); +} + +void +SubdividingMenu::addMenu(const QString &name, QMenu *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; + 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; + m_nameToChunkMenuMap[name]->addMenu(menu); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/widgets/SubdividingMenu.h Mon Sep 25 11:21:12 2006 +0000 @@ -0,0 +1,63 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Sonic Visualiser + An audio file viewer and annotation editor. + Centre for Digital Music, Queen Mary, University of London. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef _SUBDIVIDING_MENU_H_ +#define _SUBDIVIDING_MENU_H_ + +#include <QMenu> + +#include <QString> +#include <set> +#include <map> + +/** + * A menu that divides its entries into submenus, alphabetically. For + * menus that may contain a very large or small number of named items + * (e.g. plugins). + * + * 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. + */ + +class SubdividingMenu : public QMenu +{ +public: + SubdividingMenu(QWidget *parent = 0); + SubdividingMenu(const QString &title, QWidget *parent = 0); + virtual ~SubdividingMenu(); + + void setEntries(const std::set<QString> &entries); + + // Action names and strings passed to addAction and addMenu must + // appear in the set previously given to setEntries. If you want + // to use a different string, use the two-argument method and pass + // the entry string (used to determine which submenu the action + // ends up on) as the first argument. + + virtual void addAction(QAction *); + virtual QAction *addAction(const QString &); + virtual void addAction(const QString &entry, QAction *); + + virtual void addMenu(QMenu *); + virtual QMenu *addMenu(const QString &); + virtual void addMenu(const QString &entry, QMenu *); + +protected: + std::map<QString, QMenu *> m_nameToChunkMenuMap; +}; + +#endif +
--- a/widgets/widgets.pro Fri Sep 22 16:46:10 2006 +0000 +++ b/widgets/widgets.pro Mon Sep 25 11:21:12 2006 +0000 @@ -24,6 +24,7 @@ PluginParameterDialog.h \ PropertyBox.h \ PropertyStack.h \ + SubdividingMenu.h \ Thumbwheel.h \ WindowShapePreview.h \ WindowTypeSelector.h @@ -37,6 +38,7 @@ PluginParameterDialog.cpp \ PropertyBox.cpp \ PropertyStack.cpp \ + SubdividingMenu.cpp \ Thumbwheel.cpp \ WindowShapePreview.cpp \ WindowTypeSelector.cpp