kwave  18.07.70
MenuManager.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  MenuManager.cpp - manager class for Kwave's menu structure
3  -------------------
4  begin : Sun Jun 4 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 <errno.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 
24 #include <new>
25 
26 #include <QKeySequence>
27 #include <QLatin1Char>
28 #include <QRegExp>
29 #include <QString>
30 #include <QWidget>
31 
32 #include <KLocalizedString>
33 
34 #include "libkwave/Parser.h"
35 #include "libkwave/String.h"
36 
37 #include "libgui/MenuGroup.h"
38 #include "libgui/MenuManager.h"
39 #include "libgui/MenuNode.h"
40 #include "libgui/MenuRoot.h"
41 
42 //***************************************************************************
44 QMap<QString, QKeySequence> Kwave::MenuManager::m_standard_keys;
45 
47 #define INS(n,v) m_standard_keys.insert(_(n), v)
48 
49 //***************************************************************************
50 Kwave::MenuManager::MenuManager(QWidget *parent, QMenuBar &bar)
51  :QObject(parent)
52 {
53  m_menu_root = new(std::nothrow) Kwave::MenuRoot(bar);
54  Q_ASSERT(m_menu_root);
55  if (m_menu_root) {
56  connect(
57  m_menu_root, SIGNAL(sigCommand(QString)),
58  this, SIGNAL(sigMenuCommand(QString)),
59  Qt::QueuedConnection
60  );
61  }
62 
63  // fill the list of standard keys if it is empty.
64  //
65  // HINT: I have gerated the list below through copy&paste of the
66  // description of "enum QKeySequence::StandardKey" into
67  // list.txt and then:
68  //
69  // cat list.txt | sed s/^\ \ //g | cut -d \ -f 1 | cut -d \: -f 3 |
70  // awk '{ print "\tINS(\""$0"\", QKeySequence::"$0");"}'
71 
72  if (m_standard_keys.isEmpty()) {
73  INS("UnknownKey", QKeySequence::UnknownKey);
74  INS("HelpContents", QKeySequence::HelpContents);
75  INS("WhatsThis", QKeySequence::WhatsThis);
76  INS("Open", QKeySequence::Open);
77  INS("Close", QKeySequence::Close);
78  INS("Save", QKeySequence::Save);
79  INS("New", QKeySequence::New);
80  INS("Delete", QKeySequence::Delete);
81  INS("Cut", QKeySequence::Cut);
82  INS("Copy", QKeySequence::Copy);
83  INS("Paste", QKeySequence::Paste);
84  INS("Undo", QKeySequence::Undo);
85  INS("Redo", QKeySequence::Redo);
86  INS("Back", QKeySequence::Back);
87  INS("Forward", QKeySequence::Forward);
88  INS("Refresh", QKeySequence::Refresh);
89  INS("ZoomIn", QKeySequence::ZoomIn);
90  INS("ZoomOut", QKeySequence::ZoomOut);
91  INS("Print", QKeySequence::Print);
92  INS("AddTab", QKeySequence::AddTab);
93  INS("NextChild", QKeySequence::NextChild);
94  INS("PreviousChild", QKeySequence::PreviousChild);
95  INS("Find", QKeySequence::Find);
96  INS("FindNext", QKeySequence::FindNext);
97  INS("FindPrevious", QKeySequence::FindPrevious);
98  INS("Replace", QKeySequence::Replace);
99  INS("SelectAll", QKeySequence::SelectAll);
100  INS("Bold", QKeySequence::Bold);
101  INS("Italic", QKeySequence::Italic);
102  INS("Underline", QKeySequence::Underline);
103  INS("MoveToNextChar", QKeySequence::MoveToNextChar);
104  INS("MoveToPreviousChar", QKeySequence::MoveToPreviousChar);
105  INS("MoveToNextWord", QKeySequence::MoveToNextWord);
106  INS("MoveToPreviousWord", QKeySequence::MoveToPreviousWord);
107  INS("MoveToNextLine", QKeySequence::MoveToNextLine);
108  INS("MoveToPreviousLine", QKeySequence::MoveToPreviousLine);
109  INS("MoveToNextPage", QKeySequence::MoveToNextPage);
110  INS("MoveToPreviousPage", QKeySequence::MoveToPreviousPage);
111  INS("MoveToStartOfLine", QKeySequence::MoveToStartOfLine);
112  INS("MoveToEndOfLine", QKeySequence::MoveToEndOfLine);
113  INS("MoveToStartOfBlock", QKeySequence::MoveToStartOfBlock);
114  INS("MoveToEndOfBlock", QKeySequence::MoveToEndOfBlock);
115  INS("MoveToStartOfDocument", QKeySequence::MoveToStartOfDocument);
116  INS("MoveToEndOfDocument", QKeySequence::MoveToEndOfDocument);
117  INS("SelectNextChar", QKeySequence::SelectNextChar);
118  INS("SelectPreviousChar", QKeySequence::SelectPreviousChar);
119  INS("SelectNextWord", QKeySequence::SelectNextWord);
120  INS("SelectPreviousWord", QKeySequence::SelectPreviousWord);
121  INS("SelectNextLine", QKeySequence::SelectNextLine);
122  INS("SelectPreviousLine", QKeySequence::SelectPreviousLine);
123  INS("SelectNextPage", QKeySequence::SelectNextPage);
124  INS("SelectPreviousPage", QKeySequence::SelectPreviousPage);
125  INS("SelectStartOfLine", QKeySequence::SelectStartOfLine);
126  INS("SelectEndOfLine", QKeySequence::SelectEndOfLine);
127  INS("SelectStartOfBlock", QKeySequence::SelectStartOfBlock);
128  INS("SelectEndOfBlock", QKeySequence::SelectEndOfBlock);
129  INS("SelectStartOfDocument", QKeySequence::SelectStartOfDocument);
130  INS("SelectEndOfDocument", QKeySequence::SelectEndOfDocument);
131  INS("DeleteStartOfWord", QKeySequence::DeleteStartOfWord);
132  INS("DeleteEndOfWord", QKeySequence::DeleteEndOfWord);
133  INS("DeleteEndOfLine", QKeySequence::DeleteEndOfLine);
134  }
135 }
136 
137 //***************************************************************************
138 int Kwave::MenuManager::executeCommand(const QString &command)
139 {
140 
141  Q_ASSERT(command.length());
142  if (!m_menu_root) return -EINVAL; // makes no sense if no menu root
143 
144  Kwave::Parser parser(command);
145 
146  QKeySequence shortcut; // keyboard shortcut (optional)
147  QString id ; // string id (optional)
148  QString param;
149 
150  // --- 1st parameter: command to be sent when selected ---
151  QString com = parser.firstParam();
152 
153  // --- 2nd parameter: position in the menu structure ---
154  QString pos = parser.nextParam();
155 
156  // bail out if no menu position is found
157  if (!pos.length()) {
158  qWarning("no position field !");
159  return -EINVAL;
160  }
161 
162  // --- 3rd parameter: bitmask for the key shortcut (optional) ---
163  param = parser.nextParam();
164  if (param.length()) {
165  // replace "::<StandardKeyName>" with the key sequence as string
166  QRegExp rx(_("::(\\w+)"), Qt::CaseInsensitive);
167  int p = 0;
168  while ((p = rx.indexIn(param, 0)) >= 0) {
169  QString stdname = rx.cap(1);
170  if (m_standard_keys.contains(stdname)) {
171  // translate into a key sequence
172  QKeySequence sequence = m_standard_keys[stdname];
173  QString expanded = sequence.toString();
174  param = param.replace(p, stdname.length() + 2, expanded);
175  } else {
176  // unknown standard key sequence name?
177  qWarning("MenuManager::executeCommand: pos=%d, stdname='%s' "
178  "-> UNKNOWN ???", p, DBG(stdname));
179  break;
180  }
181  }
182 
183  // default case: direct specification of a key sequence
184  shortcut = QKeySequence::fromString(i18n(param.toLatin1()));
185  }
186 
187  // --- 4rth parameter: parse the string id of the node (optional) ---
188  param = parser.nextParam();
189  if (param.length()) id = param;
190 
191 #ifdef DEBUG
192 // qDebug("MenuManager: insertNode('', '%s', '%s', %s, '%s')",
193 // DBG(pos), DBG(com), DBG(shortcut.toString()), DBG(id));
194  if (!shortcut.isEmpty()) {
195  static QMap<QString, QString> used_shortcuts;
196 
197  QString sc = shortcut.toString();
198  QString m = pos.left(pos.indexOf(_("/#")));
199 
200  if (used_shortcuts.contains(sc) && (used_shortcuts[sc] != m)) {
201  qWarning("MenuManager: insertNode('%s')", DBG(m));
202  qWarning(" shortcut %s already in use for '%s'",
203  DBG(sc), DBG(used_shortcuts[sc]));
204  } else {
205  used_shortcuts[sc] = m;
206  }
207  }
208 #endif /* DEBUG */
209 
210  // --- insert the new node into the menu structure ---
211  m_menu_root->insertNode(QString(), pos, com, shortcut, id);
212 
213  return 0;
214 }
215 
216 //***************************************************************************
218 {
219  Kwave::MenuNode *node = (m_menu_root) ?
220  m_menu_root->findUID(uid) : Q_NULLPTR;
221  if (node) node->clear();
222 }
223 
224 //***************************************************************************
226  const QString &entry,
227  const QString &param)
228 {
229  Q_ASSERT(entry.length());
230  if (!entry.length()) return;
231 
232  Q_ASSERT(m_menu_root);
233  Kwave::MenuNode *node = (m_menu_root) ? m_menu_root->findUID(uid) : Q_NULLPTR;
234  Kwave::MenuNode *parent = (node) ? node->parentNode() : Q_NULLPTR;
235  if (parent) {
236  QString cmd = node->command();
237  if (cmd.contains(_("%1"))) {
238  QString p = (param.length()) ? param : entry;
239  cmd = cmd.arg(Kwave::Parser::escape(p));
240  }
241  node->insertLeaf(entry, cmd, 0, uid);
242  } else
243  qWarning("MenuManager: could not find numbered Menu '%s'", DBG(uid));
244 
245 }
246 
247 //***************************************************************************
248 void Kwave::MenuManager::selectItem(const QString &group, const QString &uid)
249 {
250  if (!m_menu_root)
251  return;
252 
253  if (!group.length()) {
254  qWarning("MenuManager::selectItem('','%s'): no group!?", DBG(uid));
255  return;
256  }
257 
258  if (group[0] != QLatin1Char('@')) {
259  qWarning("MenuManager::selectItem('%s','%s'): "
260  "invalid group name, does not start with '@'!",
261  DBG(group), DBG(uid));
262  return;
263  }
264 
265  QHash<QString, Kwave::MenuGroup *> &groups = m_menu_root->groupList();
266  if (!groups.contains(group)) {
267  qWarning("MenuManager::selectItem(): group '%s' not found!",
268  DBG(group));
269  return;
270  }
271 
272  Kwave::MenuGroup *group_node = groups[group];
273  Q_ASSERT(group_node);
274  if (group_node) group_node->selectItem(uid);
275 }
276 
277 //***************************************************************************
278 void Kwave::MenuManager::setItemChecked(const QString &uid, bool check)
279 {
280  Kwave::MenuNode *node = (m_menu_root) ?
281  m_menu_root->findUID(uid) : Q_NULLPTR;
282  if (node) node->setChecked(check);
283 }
284 
285 //***************************************************************************
286 void Kwave::MenuManager::setItemText(const QString &uid, const QString &text)
287 {
288  Kwave::MenuNode *node = (m_menu_root) ?
289  m_menu_root->findUID(uid) : Q_NULLPTR;
290  if (node) node->setText(text);
291 }
292 
293 //***************************************************************************
294 void Kwave::MenuManager::setItemVisible(const QString &uid, bool show)
295 {
296  if (!m_menu_root) return;
297 
298  Kwave::MenuNode *node = m_menu_root->findUID(uid);
299  if (node) {
300  /* show/hide a single menu node */
301  node->setVisible(show);
302  } else {
303  qWarning("MenuManager::setItemVisible('%s', '%d'): uid not found!",
304  DBG(uid), show);
305  }
306 }
307 
308 //***************************************************************************
309 void Kwave::MenuManager::setItemEnabled(const QString &uid, bool enable)
310 {
311  if (!m_menu_root) return;
312 
313  bool found = false;
314  Kwave::MenuNode *node = m_menu_root->findUID(uid);
315  if (node) {
316  /* enable/disable a single menu node */
317  node->setEnabled(enable);
318  found = true;
319  } else {
320  /* enable/disable a group */
321  QHash<QString, Kwave::MenuGroup *> &groups = m_menu_root->groupList();
322  if (groups.contains(uid)) {
323  Kwave::MenuGroup *group = groups[uid];
324  if (group) {
325  group->setEnabled(enable);
326  found = true;
327  }
328  }
329  }
330 
331  if (!found)
332  qWarning("MenuManager::setItemEnabled('%s', '%d'): uid not found!",
333  DBG(uid), enable);
334 }
335 
336 //***************************************************************************
338 {
339  delete m_menu_root;
340  m_menu_root = Q_NULLPTR;
341 }
342 
343 //***************************************************************************
344 //***************************************************************************
MenuManager(QWidget *parent, QMenuBar &bar)
Definition: MenuManager.cpp:50
void clearNumberedMenu(const QString &uid)
virtual Kwave::MenuNode * parentNode() const
Definition: MenuNode.cpp:103
void setItemChecked(const QString &uid, bool check)
void setItemEnabled(const QString &uid, bool enable)
virtual void insertNode(const QString &name, const QString &position, const QString &command, const QKeySequence &shortcut, const QString &uid) Q_DECL_OVERRIDE
Definition: MenuRoot.cpp:57
virtual QHash< QString, Kwave::MenuGroup * > & groupList() Q_DECL_OVERRIDE
Definition: MenuRoot.cpp:51
void setItemText(const QString &uid, const QString &text)
Kwave::MenuNode * findUID(const QString &uid)
Definition: MenuNode.cpp:198
bool connect(Kwave::StreamObject &source, const char *output, Kwave::StreamObject &sink, const char *input)
Definition: Connect.cpp:48
void setItemVisible(const QString &uid, bool show)
virtual void clear()
Definition: MenuNode.cpp:93
virtual void setEnabled(bool enable)
Definition: MenuNode.cpp:163
const QString & command() const
Definition: MenuNode.h:77
void selectItem(const QString &group, const QString &uid)
static QMap< QString, QKeySequence > m_standard_keys
Definition: MenuManager.h:140
virtual void selectItem(const QString &uid)
Definition: MenuGroup.cpp:90
virtual void setVisible(bool visible)
Definition: MenuNode.cpp:157
virtual void setChecked(bool check)
Definition: MenuNode.cpp:169
virtual ~MenuManager()
const QString & firstParam()
Definition: Parser.cpp:168
#define _(m)
Definition: memcpy.c:66
Kwave::MenuRoot * m_menu_root
Definition: MenuManager.h:137
#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
static QString escape(const QString &text)
Definition: Parser.cpp:277
virtual void setEnabled(bool enable)
Definition: MenuGroup.cpp:82
int executeCommand(const QString &command)
void sigMenuCommand(const QString &command)
const QString & nextParam()
Definition: Parser.cpp:175
void addNumberedMenuEntry(const QString &uid, const QString &entry, const QString &param)