00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
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
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
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
00180 QMenu::addAction(action);
00181 return;
00182 }
00183
00184
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
00199 return QMenu::addAction(name);
00200 }
00201
00202
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
00216 QMenu::addAction(action);
00217 return;
00218 }
00219
00220
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
00236 QMenu::addMenu(menu);
00237 return;
00238 }
00239
00240
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
00256 return QMenu::addMenu(name);
00257 }
00258
00259
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
00273 QMenu::addMenu(menu);
00274 return;
00275 }
00276
00277
00278 m_nameToChunkMenuMap[name]->addMenu(menu);
00279 }
00280