kwave  18.07.70
MenuNode.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  MenuNode.cpp - generic menu node type
3  -------------------
4  begin : Mon Jan 10 2000
5  copyright : (C) 2000 by Thomas Eschenbacher
6  email : Thomas.Eschenbacher@gmx.de
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #include "config.h"
19 
20 #include <new>
21 
22 #include <QLatin1Char>
23 #include <QPixmap>
24 
25 #include "libkwave/Parser.h"
26 #include "libkwave/String.h"
27 
28 #include "libgui/MenuGroup.h"
29 #include "libgui/MenuList.h"
30 #include "libgui/MenuNode.h"
31 #include "libgui/MenuRoot.h"
32 #include "libgui/MenuSub.h"
33 
34 //*****************************************************************************
36  const QString &name,
37  const QString &command,
38  const QKeySequence &shortcut,
39  const QString &uid)
40  :QObject(), m_children(), m_groups(), m_uid(uid), m_shortcut(shortcut),
41  m_name(name), m_command(command), m_parentNode(parent)
42 {
43 }
44 
45 //*****************************************************************************
47 {
48  // leave all groups
49  QStringList::iterator group = m_groups.begin();
50  while (group != m_groups.end()) {
51  leaveGroup(*group);
52  group = m_groups.begin();
53  }
54 
55  // remove all childs
56  clear();
57 
58  // de-register from our parent
60 }
61 
62 //*****************************************************************************
63 const QString Kwave::MenuNode::path() const
64 {
65  return (m_parentNode) ?
66  (m_parentNode->path() + _("/") + m_name) : QString();
67 }
68 
69 //*****************************************************************************
71 {
72  Q_ASSERT(command.length());
73  if (!command.length()) return ;
74 
75  if (!parentNode()) {
76  // no parent -> we are the root node -> we have to emit
77  emit sigCommand(command);
78  } else {
79  // tell the root node to emit
80  Kwave::MenuNode *root = rootNode();
81  Q_ASSERT(root);
82  if (root) root->emitCommand(command);
83  }
84 }
85 
86 //*****************************************************************************
88 {
89  if (m_command.length()) emitCommand(m_command);
90 }
91 
92 //*****************************************************************************
94 {
95  // remove all children
96  while (!m_children.isEmpty()) {
97  Kwave::MenuNode *child = m_children.takeLast();
98  delete child;
99  }
100 }
101 
102 //*****************************************************************************
104 {
105  return m_parentNode;
106 }
107 
108 //*****************************************************************************
110 {
111  return (m_parentNode) ? m_parentNode->rootNode() : this;
112 }
113 
114 //*****************************************************************************
116 {
117  static QIcon dummy;
118  Q_ASSERT(dummy.isNull());
119  return dummy;
120 }
121 
122 //*****************************************************************************
123 void Kwave::MenuNode::setIcon(const QIcon &icon)
124 {
125  qWarning("MenuNode(%s)::setIcon(%p)",
126  DBG(name()), reinterpret_cast<const void *>(&icon));
127 }
128 
129 //*****************************************************************************
131 {
132  // evaluate our own (individual) enable and our parent's enable state
134  return false;
135 
136  // find out if all our groups are enabled
137  QHash<QString, Kwave::MenuGroup *> &groups = groupList();
138  Kwave::MenuNode *root = rootNode();
139  if (root) {
140  foreach (const QString &group_name, m_groups) {
141  if (groups.contains(group_name)) {
142  Kwave::MenuGroup *group = groups[group_name];
143  if (group && !group->isEnabled()) {
144  qDebug("MenuNode(%s).isEnabled(): group %s is disabled",
145  DBG(name()), DBG(group_name));
146  return false;
147  }
148  }
149  }
150  }
151 
152  // if we get here, everything is enabled
153  return true;
154 }
155 
156 //*****************************************************************************
157 void Kwave::MenuNode::setVisible(bool visible)
158 {
159  Q_UNUSED(visible);
160 }
161 
162 //*****************************************************************************
164 {
165  Q_UNUSED(enable);
166 }
167 
168 //*****************************************************************************
170 {
171  Q_UNUSED(check);
172 }
173 
174 //*****************************************************************************
175 void Kwave::MenuNode::setText(const QString &text)
176 {
177  Q_UNUSED(text);
178 }
179 
180 //*****************************************************************************
182  Kwave::MenuNode *before)
183 {
184  if (!node) return;
185  if (before && m_children.contains(before))
186  m_children.insert(m_children.indexOf(before), node);
187  else
188  m_children.append(node);
189 }
190 
191 //*****************************************************************************
192 void Kwave::MenuNode::setUID(const QString &uid)
193 {
194  m_uid = uid;
195 }
196 
197 //*****************************************************************************
199 {
200  if (m_uid == uid) return this; // found ourself
201 
202  foreach (Kwave::MenuNode *child, m_children) {
203  Kwave::MenuNode *node = (child) ? child->findUID(uid) : Q_NULLPTR;
204  if (node) return node; // found in child
205  }
206 
207  return Q_NULLPTR; // nothing found :-(
208 }
209 
210 //*****************************************************************************
212 {
213  Q_ASSERT(name.length());
214 
215  foreach (Kwave::MenuNode *child, m_children) {
216  if (child && (name == child->name()))
217  return child;
218  }
219  return Q_NULLPTR;
220 }
221 
222 //*****************************************************************************
224 {
225  if (child && !m_children.isEmpty())
226  m_children.removeAll(child);
227 }
228 
229 //*****************************************************************************
231  const QString &command,
232  const QKeySequence &shortcut,
233  const QString &uid)
234 {
235  Q_UNUSED(name);
236  Q_UNUSED(command);
237  Q_UNUSED(shortcut);
238  Q_UNUSED(uid);
239  return Q_NULLPTR;
240 }
241 
242 //*****************************************************************************
244  const QString &command,
245  const QKeySequence &shortcut,
246  const QString &uid)
247 {
248  Q_UNUSED(name);
249  Q_UNUSED(command);
250  Q_UNUSED(shortcut);
251  Q_UNUSED(uid);
252  return Q_NULLPTR;
253 }
254 
255 //*****************************************************************************
256 void Kwave::MenuNode::insertNode(const QString &name,
257  const QString &position,
258  const QString &command,
259  const QKeySequence &shortcut,
260  const QString &uid)
261 {
262  int pos = 0;
263 
264  if (!position.length()) {
265  qWarning("MenuNode::insertNode: no position!");
266  return;
267  }
268 
269  // at start of the parsing process ?
270  if (!name.length()) {
271  // split off the first token, separated by a slash
272  pos = position.indexOf(QLatin1Char('/'));
273  if (pos < 0) pos = position.length();
274  }
275 
276  QString n = position.left(pos);
277  QString p = position;
278  p.remove(0, pos + 1);
279 
280  if ((n.length()) && (specialCommand(n))) {
281  // no new branch, only a special command
282  return;
283  }
284 
285  if ((!p.length()) || (p[0] == QLatin1Char('#'))) {
286  // end of the tree
287  Kwave::MenuNode *sub = findChild(n);
288  if (sub) {
289  // a leaf with this name already exists
290  // -> maybe we want to set new properties
291  if (!shortcut.isEmpty()) sub->setShortcut(shortcut);
292 
293  if (uid.length()) sub->setUID(uid);
294 
295  } else {
296  // insert a new leaf
297  sub = insertLeaf(n, command, shortcut, uid);
298  if (!sub) return;
299  }
300 
301  if (p[0] == QLatin1Char('#')) sub->specialCommand(p);
302 
303  } else {
304  // somewhere in the tree
305  Kwave::MenuNode *sub = findChild(n);
306  if (!sub) {
307  sub = insertBranch(n, command, shortcut, uid);
308  } else if ( !sub->isBranch() && (p[0] != QLatin1Char('#'))) {
309  // remove the "leaf" and insert a branch with
310  // the same properties
311  sub = leafToBranch(sub);
312  } else if (!p.length() || (p[0] == QLatin1Char('#')) ) {
313  // branch already exists and we are at the end of parsing
314  // -> maybe we want to set new properties
315  if (!shortcut.isEmpty()) sub->setShortcut(shortcut);
316  if (uid.length()) sub->setUID(uid);
317  }
318 
319  if (sub) {
320  sub->insertNode(QString(), p, command, shortcut, uid);
321  } else {
322  qDebug("MenuNode::insertNode: branch failed!");
323  }
324  }
325 }
326 
327 //*****************************************************************************
329 {
330  Q_ASSERT(node);
331  Q_ASSERT(node != this);
332 
333  if (!node || (node == this)) return Q_NULLPTR;
334 
335  // get the old properties
336  bool old_enable = node->isEnabled();
337  QKeySequence old_shortcut = node->shortcut();
338  QString old_uid = node->uid();
339  QIcon old_icon = node->icon();
340  QString name = node->name();
341  QString command = node->command();
342  QStringList old_groups = node->m_groups;
343 
344  // remove the old child node
345  removeChild(node);
346 
347  // insert the new branch
348  Kwave::MenuSub *sub = insertBranch(name, command, old_shortcut, old_uid);
349  if (sub) {
350  // join it to the same groups
351  foreach (const QString &group, old_groups)
352  sub->joinGroup(group, Kwave::MenuGroup::NORMAL);
353 
354  // set the old icon
355  if (!old_icon.isNull()) sub->setIcon(old_icon);
356 
357  // set the "enable"
358  sub->setEnabled(old_enable);
359  }
360 
361  // free the old node later.
362  // IMPORTANT: we must not call "delete node" now, because we get called
363  // through leafToBranch(this) !
365 
366  return sub;
367 }
368 
369 //*****************************************************************************
370 QHash<QString, Kwave::MenuGroup *> &Kwave::MenuNode::groupList()
371 {
372  static QHash<QString, Kwave::MenuGroup *> _empty_list;
373  Q_ASSERT(m_parentNode);
374  return (m_parentNode) ? m_parentNode->groupList() : _empty_list;
375 }
376 
377 //*****************************************************************************
378 void Kwave::MenuNode::joinGroup(const QString &group,
380 {
381  if (m_groups.contains(group))
382  return; // already joined
383 
384  QHash<QString, Kwave::MenuGroup *> &group_list = groupList();
385  Kwave::MenuGroup *grp = Q_NULLPTR;
386  if (group_list.contains(group)) {
387  grp = group_list[group];
388  } else {
389  // group does not already exist, create a new one
390  grp = new(std::nothrow) Kwave::MenuGroup(rootNode(), group, mode);
391  if (grp) group_list.insert(group, grp);
392  }
393 
394  // remember that we now belong to the given group
395  m_groups.append(group);
396 
397  // register this node as a child of the group
398  if (grp) grp->join(this);
399 }
400 
401 //*****************************************************************************
402 void Kwave::MenuNode::leaveGroup(const QString &group)
403 {
404  QHash<QString, Kwave::MenuGroup *> &group_list = groupList();
405  Kwave::MenuGroup *grp = (group_list.contains(group)) ?
406  group_list.value(group) : Q_NULLPTR;
407 
408  // remove the group from our list
409  m_groups.removeAll(group);
410 
411  // remove ourself from the group
412  if (grp) {
413  grp->leave(this);
414 
415  // clean up the group if nobody uses it any more
416  if (grp->isEmpty()) delete grp;
417  }
418 }
419 
420 //*****************************************************************************
422 {
423  Kwave::Parser parser(command);
424 
425  if (parser.command() == _("#icon")) {
426  // --- give the item an icon ---
427  const QString &icon_name = parser.firstParam();
428  if ( icon_name.length()) {
429  // try to load from standard dirs
430  QIcon icon = QIcon::fromTheme( icon_name );
431  if (!icon.isNull()) {
432  setIcon(icon);
433  } else {
434  qWarning("MenuNode '%s': icon '%s' not found !",
435  DBG(name()), DBG( icon_name ));
436  }
437  }
438  return true;
439  }
440 
441  if (parser.command() == _("#listmenu")) {
442  // make sure that the current node is a sub menu
443  Kwave::MenuNode *parent = parentNode();
444  Kwave::MenuNode *sub = (parent && !isBranch()) ?
445  parent->leafToBranch(this) : this;
446  if (!sub) return false;
447 
448  // append a placeholder for inserting the list
449  // (if it does not already exist)
450  const QString uid = parser.firstParam();
451  const QString cmd = parser.nextParam();
452  if (!sub->findUID(uid)) {
453  Kwave::MenuList *placeholder =
454  new(std::nothrow) Kwave::MenuList(sub, cmd, uid);
455  Q_ASSERT(placeholder);
456  if (!placeholder) return false;
457 
458  sub->insertChild(placeholder, Q_NULLPTR);
459  }
460  return true;
461  }
462 
463  if (parser.command() == _("#group")) {
464  QString group = parser.firstParam();
465  while (group.length()) {
467  group = parser.nextParam();
468  }
469  return true;
470  }
471 
472  if (command == _("#disabled")) {
473  // disable the node
474  setEnabled(false);
475  return true;
476  }
477 
478  if (command == _("#enabled")) {
479  // enable the node
480  setEnabled(true);
481  return true;
482  }
483 
484  return false;
485 }
486 
487 //***************************************************************************
488 //***************************************************************************
const QString path() const
Definition: MenuNode.cpp:63
QStringList m_groups
Definition: MenuNode.h:320
virtual Kwave::MenuNode * parentNode() const
Definition: MenuNode.cpp:103
QString m_name
Definition: MenuNode.h:331
void joinGroup(const QString &group, Kwave::MenuGroup::Mode mode)
Definition: MenuNode.cpp:378
void emitCommand(const QString &command)
Definition: MenuNode.cpp:70
virtual void join(Kwave::MenuNode *node)
Definition: MenuGroup.cpp:62
virtual QHash< QString, Kwave::MenuGroup * > & groupList()
Definition: MenuNode.cpp:370
virtual bool isBranch() const
Definition: MenuNode.h:119
void setUID(const QString &uid)
Definition: MenuNode.cpp:192
Kwave::MenuNode * m_parentNode
Definition: MenuNode.h:337
virtual Kwave::MenuNode * leafToBranch(Kwave::MenuNode *node)
Definition: MenuNode.cpp:328
virtual void setIcon(const QIcon &icon)
Definition: MenuNode.cpp:123
virtual void actionSelected()
Definition: MenuNode.cpp:87
virtual bool isEnabled() const
Definition: MenuGroup.h:82
Kwave::MenuNode * findUID(const QString &uid)
Definition: MenuNode.cpp:198
const QKeySequence & shortcut() const
Definition: MenuNode.h:95
virtual const QIcon icon()
Definition: MenuNode.cpp:115
virtual bool isEmpty() const
Definition: MenuGroup.h:87
virtual void setIcon(const QIcon &icon) Q_DECL_OVERRIDE
Definition: MenuSub.cpp:92
virtual void removeChild(Kwave::MenuNode *child)
Definition: MenuNode.cpp:223
virtual void insertChild(Kwave::MenuNode *node, Kwave::MenuNode *before)
Definition: MenuNode.cpp:181
virtual void clear()
Definition: MenuNode.cpp:93
const char name[16]
Definition: memcpy.c:510
virtual void setEnabled(bool enable)
Definition: MenuNode.cpp:163
virtual bool specialCommand(const QString &command)
Definition: MenuNode.cpp:421
const QString & name() const
Definition: MenuNode.h:74
const QString & command() const
Definition: MenuNode.h:77
void sigCommand(const QString &command)
virtual bool isEnabled()
Definition: MenuNode.cpp:130
static void deleteLater(Kwave::MenuNode *node)
Definition: MenuRoot.cpp:177
QList< Kwave::MenuNode * > m_children
Definition: MenuNode.h:317
QString m_command
Definition: MenuNode.h:334
virtual void setVisible(bool visible)
Definition: MenuNode.cpp:157
virtual void leave(Kwave::MenuNode *node)
Definition: MenuGroup.cpp:72
MenuNode(Kwave::MenuNode *parent, const QString &name, const QString &command, const QKeySequence &shortcut, const QString &uid)
Definition: MenuNode.cpp:35
virtual void setChecked(bool check)
Definition: MenuNode.cpp:169
Kwave::MenuNode * findChild(const QString &name)
Definition: MenuNode.cpp:211
const QString & firstParam()
Definition: Parser.cpp:168
#define _(m)
Definition: memcpy.c:66
QString m_uid
Definition: MenuNode.h:325
const QString & uid() const
Definition: MenuNode.h:85
#define DBG(qs)
Definition: String.h:55
virtual void setText(const QString &text)
Definition: MenuNode.cpp:175
virtual Kwave::MenuNode * insertLeaf(const QString &name, const QString &command, const QKeySequence &shortcut, const QString &uid)
Definition: MenuNode.cpp:243
Kwave::MenuNode * rootNode()
Definition: MenuNode.cpp:109
virtual ~MenuNode()
Definition: MenuNode.cpp:46
virtual Kwave::MenuSub * insertBranch(const QString &name, const QString &command, const QKeySequence &shortcut, const QString &uid)
Definition: MenuNode.cpp:230
QString command()
Definition: Parser.h:47
void leaveGroup(const QString &group)
Definition: MenuNode.cpp:402
const QString & nextParam()
Definition: Parser.cpp:175
virtual void setShortcut(const QKeySequence &shortcut)
Definition: MenuNode.h:100
virtual void setEnabled(bool enable) Q_DECL_OVERRIDE
Definition: MenuSub.cpp:80
virtual void insertNode(const QString &name, const QString &position, const QString &command, const QKeySequence &shortcut, const QString &uid)
Definition: MenuNode.cpp:256