]> Shamusworld >> Repos - architektonas/blob - src/mainapp/commands.cpp
429c04e7f1c326bb5bbef6c4867d153e0229daba
[architektonas] / src / mainapp / commands.cpp
1 // commands.cpp
2 //
3 // Part of the Architektonas Project
4 // Originally part of QCad Community Edition by Andrew Mustun
5 // Extensively rewritten and refactored by James L. Hammons
6 // (C) 2010 Underground Software
7 //
8 // JLH = James L. Hammons <jlhamm@acm.org>
9 //
10 // Who  When        What
11 // ---  ----------  -----------------------------------------------------------
12 // JLH  05/17/2010  Added this text. :-)
13 //
14
15 #include "commands.h"
16
17 #include "rs_dialogfactory.h"
18 #include "rs_debug.h"
19
20 // Class variable
21 Commands * Commands::uniqueInstance = NULL;
22
23 /**
24  * Constructor. Initiates main command dictionary.
25  */
26 Commands::Commands()
27 {
28         // This is NOT necessary; we don't anything out of the hash
29 //      mainCommands.setAutoDelete(true);
30 //      shortCommands.setAutoDelete(true);
31
32         // draw:
33         mainCommands.insert(tr("point"), new RS2::ActionType(RS2::ActionDrawPoint));
34         shortCommands.insert(tr("po"), new RS2::ActionType(RS2::ActionDrawPoint));
35
36         mainCommands.insert(tr("line"), new RS2::ActionType(RS2::ActionDrawLine));
37         shortCommands.insert(tr("ln"), new RS2::ActionType(RS2::ActionDrawLine));
38         shortCommands.insert(tr("l"), new RS2::ActionType(RS2::ActionDrawLine));
39
40         mainCommands.insert(tr("polyline"), new RS2::ActionType(RS2::ActionDrawPolyline));
41
42         mainCommands.insert(tr("offset"), new RS2::ActionType(RS2::ActionDrawLineParallel));
43         shortCommands.insert(tr("o", "offset"), new RS2::ActionType(RS2::ActionDrawLineParallel));
44         mainCommands.insert(tr("parallel"), new RS2::ActionType(RS2::ActionDrawLineParallel));
45         shortCommands.insert(tr("par", "parallel"), new RS2::ActionType(RS2::ActionDrawLineParallel));
46
47         mainCommands.insert(tr("arc"), new RS2::ActionType(RS2::ActionDrawArc3P));
48         shortCommands.insert(tr("a"), new RS2::ActionType(RS2::ActionDrawArc3P));
49
50         mainCommands.insert(tr("circle"), new RS2::ActionType(RS2::ActionDrawCircle));
51         shortCommands.insert(tr("ci"), new RS2::ActionType(RS2::ActionDrawCircle));
52
53         mainCommands.insert(tr("rectangle"), new RS2::ActionType(RS2::ActionDrawLineRectangle));
54         shortCommands.insert(tr("rec"), new RS2::ActionType(RS2::ActionDrawLineRectangle));
55         shortCommands.insert(tr("rectang"), new RS2::ActionType(RS2::ActionDrawLineRectangle));
56
57         mainCommands.insert(tr("polyline"), new RS2::ActionType(RS2::ActionDrawPolyline));
58
59         mainCommands.insert(tr("text"), new RS2::ActionType(RS2::ActionDrawText));
60
61         // zoom:
62         mainCommands.insert(tr("regen"), new RS2::ActionType(RS2::ActionZoomRedraw));
63         shortCommands.insert(tr("rg", "zoom - redraw"), new RS2::ActionType(RS2::ActionZoomRedraw));
64         shortCommands.insert(tr("zr", "zoom - redraw"), new RS2::ActionType(RS2::ActionZoomRedraw));
65
66         mainCommands.insert(tr("zw", "zoom - window"), new RS2::ActionType(RS2::ActionZoomWindow));
67
68         mainCommands.insert(tr("za", "zoom - auto"), new RS2::ActionType(RS2::ActionZoomAuto));
69
70         mainCommands.insert(tr("zp", "zoom - pan"), new RS2::ActionType(RS2::ActionZoomPan));
71
72         mainCommands.insert(tr("zv", "zoom - previous"), new RS2::ActionType(RS2::ActionZoomPrevious));
73
74         // edit:
75         mainCommands.insert(tr("undo"), new RS2::ActionType(RS2::ActionEditUndo));
76         shortCommands.insert(tr("u", "undo"), new RS2::ActionType(RS2::ActionEditUndo));
77
78         mainCommands.insert(tr("redo"), new RS2::ActionType(RS2::ActionEditRedo));
79         shortCommands.insert(tr("r"), new RS2::ActionType(RS2::ActionEditRedo));
80
81         // tools:
82         mainCommands.insert(tr("dimregen"), new RS2::ActionType(RS2::ActionToolRegenerateDimensions));
83 }
84
85 // Destructor needed to clean up memory used by the hash
86 Commands::~Commands()
87 {
88         while (!mainCommands.isEmpty())
89         {
90                 RS2::ActionType * value = *mainCommands.begin();
91                 mainCommands.erase(mainCommands.begin());
92                 delete value;
93         }
94
95         while (!shortCommands.isEmpty())
96         {
97                 RS2::ActionType * value = *shortCommands.begin();
98                 shortCommands.erase(shortCommands.begin());
99                 delete value;
100         }
101 }
102
103 // Class method
104 /**
105  * @return Instance to the unique commands object.
106  */
107 Commands * Commands::instance()
108 {
109         if (uniqueInstance == NULL)
110                 uniqueInstance = new Commands();
111
112         return uniqueInstance;
113 }
114
115 /**
116  * Tries to complete the given command (e.g. when tab is pressed).
117  */
118 QStringList Commands::complete(const QString & cmd)
119 {
120 /*
121  Q3DictIterator<QWidget> i(dict);
122  while (i.current() != 0) {
123      do_something(i.currentKey(), i.current());
124      ++i;
125  }
126
127 Here's the equivalent QHashIterator loop:
128
129  QHashIterator<QString, QWidget *> i(hash);
130  while (i.hasNext()) {
131      i.next();                   // must come first
132      do_something(i.key(), i.value());
133  }
134 */
135 #if 0
136         Q3DictIterator<RS2::ActionType> it(mainCommands);
137         QStringList ret;
138
139         for(; it.current(); ++it)
140         {
141         //cout << it.currentKey() << ": " << it.current()->text() << endl;
142                 if (it.currentKey().startsWith(cmd))
143                         ret << it.currentKey();
144         }
145
146         ret.sort();
147
148         return ret;
149 #else
150         QHashIterator<QString, RS2::ActionType *> it(mainCommands);
151         QStringList ret;
152
153         while (it.hasNext())
154         {
155                 it.next();                                                              // MUST come before access
156
157                 if (it.key().startsWith(cmd))
158                         ret << it.key();
159         }
160
161         ret.sort();
162
163         return ret;
164 #endif
165 }
166
167 /**
168  * @return Command for triggering the given action in the currently chosen
169  * language for commands.
170  *
171  * @param action ID of the action who's command will be returned.
172  * @param num Number of the command. There might be multiple commands
173  *            for the same action (e.g. 'line' and 'l')
174  *
175  * @return The translated command.
176  */
177 RS2::ActionType Commands::cmdToAction(const QString & cmd)
178 {
179     QString c = cmd.toLower();
180     QString full = cmd;          // full command defaults to given command
181     RS2::ActionType ret = RS2::ActionNone;
182
183         // find command:
184 //      RS2::ActionType * retPtr = mainCommands[cmd];
185         RS2::ActionType * retPtr = mainCommands.value(cmd);
186
187         if (retPtr != NULL)
188                 ret = *retPtr;
189         else
190         {
191 //              retPtr = shortCommands[cmd];
192                 retPtr = shortCommands.value(cmd);
193
194                 if (retPtr != NULL)
195                         ret = *retPtr;
196         }
197
198         // find full command to confirm to user:
199 //      Q3DictIterator<RS2::ActionType> it(mainCommands);
200         QHashIterator<QString, RS2::ActionType *> it(mainCommands);
201
202 //      for(; it.current(); ++it)
203         while (it.hasNext())
204         {
205                 it.next();                                                              // MUST come before access
206
207 //              if (*it.current() == ret)
208                 if (*it.value() == ret)
209                 {
210                         if (RS_DialogFactory::instance() != NULL)
211                         {
212                                 //if (RS_DIALOGFACTORY!=NULL) {
213                                 RS_DEBUG->print("Commands::cmdToAction: commandMessage");
214                                         //RS_DIALOGFACTORY->commandMessage(tr("Command: %1")
215                                         //      .arg(full));
216                                 RS_DialogFactory::instance()->commandMessage(tr("Command: %1").arg(full));
217                                 RS_DEBUG->print("Commands::cmdToAction: commandMessage: ok");
218                                 //}
219                         }
220                         else
221                                 RS_DEBUG->print("Commands::cmdToAction: dialog factory instance is NULL");
222
223                         break;
224                 }
225         }
226
227         return ret;
228 }
229
230 /**
231  * Gets the action for the given keycode. A keycode is a sequence
232  * of key-strokes that is entered like hotkeys.
233  */
234 RS2::ActionType Commands::keycodeToAction(const QString & code)
235 {
236         QString c = code.toLower();
237         RS2::ActionType ret = RS2::ActionNone;
238
239         // draw:
240         if (c == tr("po", "point"))
241                 ret = RS2::ActionDrawPoint;
242         else if (c == tr("li", "line"))
243                 ret = RS2::ActionDrawLine;
244         else if (c == tr("pa", "parallel"))
245                 ret = RS2::ActionDrawLine;
246         else if (c == tr("re", "rectangle"))
247                 ret = RS2::ActionDrawLineRectangle;
248         else if (c == tr("rp", "regular polygon"))
249                 ret = RS2::ActionDrawLinePolygon;
250         else if (c == tr("ci", "circle"))
251                 ret = RS2::ActionDrawCircle;
252         else if (c == tr("c2", "2 point circle"))
253                 ret = RS2::ActionDrawCircle2P;
254         else if (c == tr("c3", "3 point circle"))
255                 ret = RS2::ActionDrawCircle3P;
256         else if (c == tr("ar", "arc"))
257                 ret = RS2::ActionDrawArc;
258         else if (c == tr("a3", "3 point arc"))
259                 ret = RS2::ActionDrawArc3P;
260         else if (c == tr("ep", "ellipse"))
261                 ret = RS2::ActionDrawEllipseAxis;
262         else if (c == tr("tx", "text") || c == tr("mt", "text"))
263                 ret = RS2::ActionDrawText;
264
265         // dimensions:
266         else if (c == tr("da", "dimension - aligned"))
267                 ret = RS2::ActionDimAligned;
268         else if (c == tr("dh", "dimension - horizontal"))
269                 ret = RS2::ActionDimLinearHor;
270         else if (c == tr("dv", "dimension - vertical"))
271                 ret = RS2::ActionDimLinearVer;
272         else if (c == tr("dr", "dimension - linear"))
273                 ret = RS2::ActionDimLinear;
274         else if (c == tr("ld", "dimension - leader"))
275                 ret = RS2::ActionDimLeader;
276
277         // zoom:
278         else if (c == tr("rd", "redraw"))
279                 ret = RS2::ActionZoomRedraw;
280         else if (c == tr("zw", "zoom - window"))
281                 ret = RS2::ActionZoomWindow;
282         else if (c == tr("za", "zoom - auto"))
283                 ret = RS2::ActionZoomAuto;
284         else if (c == tr("zi", "zoom - in"))
285                 ret = RS2::ActionZoomIn;
286         else if (c == tr("zo", "zoom - out"))
287                 ret = RS2::ActionZoomOut;
288         else if (c == tr("zp", "zoom - pan"))
289                 ret = RS2::ActionZoomPan;
290         else if (c == tr("zv", "zoom - previous"))
291                 ret = RS2::ActionZoomPrevious;
292
293         // snap:
294         else if (c == tr("os", "snap - none"))
295                 ret = RS2::ActionSnapFree;
296         else if (c == tr("sg", "snap - grid"))
297                 ret = RS2::ActionSnapGrid;
298         else if (c == tr("se", "snap - end"))
299                 ret = RS2::ActionSnapEndpoint;
300         else if (c == tr("si", "snap - intersection"))
301                 ret = RS2::ActionSnapIntersection;
302         else if (c == tr("sn", "snap - center"))
303                 ret = RS2::ActionSnapCenter;
304         else if (c == tr("sm", "snap - middle"))
305                 ret = RS2::ActionSnapMiddle;
306         else if (c == tr("sn", "snap - nearest"))
307                 ret = RS2::ActionSnapMiddle;
308         else if (c == tr("np", "snap - nearest point"))
309                 ret = RS2::ActionSnapOnEntity;
310
311         // layer:
312         else if (c == tr("fr*", "layers - freeze all"))
313                 ret = RS2::ActionLayersFreezeAll;
314         else if (c == tr("th*", "layers - defreeze all"))
315                 ret = RS2::ActionLayersDefreezeAll;
316
317         // selection:
318         else if (c == tr("tn", "Deselect all"))
319                 ret = RS2::ActionDeselectAll;
320
321         // modify:
322         else if (c == tr("ch", "modify - bevel (chamfer)"))
323                 ret = RS2::ActionModifyBevel;
324         else if (c == tr("tm", "modify - multi trim (extend)"))
325                 ret = RS2::ActionModifyTrim2;
326         else if (c == tr("xt", "modify - trim (extend)"))
327                 ret = RS2::ActionModifyTrim;
328         else if (c == tr("rm", "modify - trim"))
329                 ret = RS2::ActionModifyTrim;
330         else if (c == tr("mv", "modify - move"))
331                 ret = RS2::ActionModifyMove;
332         else if (c == tr("mi", "modify - mirror"))
333                 ret = RS2::ActionModifyMirror;
334         else if (c == tr("ro", "modify - rotate"))
335                 ret = RS2::ActionModifyRotate;
336         else if (c == tr("sz", "modify - scale"))
337                 ret = RS2::ActionModifyMove;
338         else if (c == tr("ss", "modify - stretch"))
339                 ret = RS2::ActionModifyStretch;
340         else if (c == tr("er", "modify - delete (erase)"))
341                 ret = RS2::ActionModifyDelete;
342         else if (c == tr("oo", "modify - undo (oops)"))
343                 ret = RS2::ActionEditUndo;
344         else if (c == tr("uu", "modify - redo"))
345                 ret = RS2::ActionEditRedo;
346         else if (c == tr("xp", "modify - explode") || c == tr("ex", "modify - explode"))
347                 ret = RS2::ActionBlocksExplode;
348
349         return ret;
350 }
351
352 /**
353  * @return translated command for the given English command.
354  */
355 QString Commands::command(const QString & cmd)
356 {
357         if (cmd == "angle")
358                 return tr("angle");
359         else if (cmd == "close")
360                 return tr("close");
361         else if (cmd == "chord length")
362                 return tr("chord length");
363         else if (cmd == "columns")
364                 return tr("columns");
365         else if (cmd == "columnspacing")
366                 return tr("columnspacing");
367         else if (cmd == "factor")
368                 return tr("factor");
369         else if (cmd == "length")
370                 return tr("length");
371         else if (cmd == "length1")
372                 return tr("length1");
373         else if (cmd == "length2")
374                 return tr("length2");
375         else if (cmd == "number")
376                 return tr("number");
377         else if (cmd == "radius")
378                 return tr("radius");
379         else if (cmd == "rows")
380                 return tr("rows");
381         else if (cmd == "rowspacing")
382                 return tr("rowspacing");
383         else if (cmd == "text")
384                 return tr("text");
385         else if (cmd == "through")
386                 return tr("through");
387         else if (cmd == "trim")
388                 return tr("trim");
389         else if (cmd == "undo")
390                 return tr("undo");
391
392 //      RS_DEBUG->print(RS_Debug::D_WARNING, "Commands::command: command '%s' unknown", cmd.latin1());
393         RS_DEBUG->print(RS_Debug::D_WARNING, "Commands::command: command '%s' unknown", cmd.toLatin1().data());
394         return "";
395 }
396
397 /**
398  * Checks if the given string 'str' matches the given command 'cmd' for action
399  * 'action'.
400  *
401  * @param cmd The command we want to check for (e.g. 'angle').
402  * @param action The action which wants to know.
403  * @param str The string typically entered by the user.
404  */
405 bool Commands::checkCommand(const QString & cmd, const QString & str, RS2::ActionType /*action*/)
406 {
407         QString strl = str.toLower();
408
409         if (cmd == "angle")
410         {
411                 if (strl == tr("angle") || strl == tr("ang", "angle") || strl == tr("a", "angle"))
412                         return true;
413         }
414         else if (cmd == "center")
415         {
416                 if (strl == tr("center") || strl == tr("cen", "center") || strl == tr("c", "center"))
417                         return true;
418         }
419         else if (cmd == "chord length")
420         {
421                 if (strl == tr("length", "chord length") || strl == tr("l", "chord length"))
422                         return true;
423         }
424         else if (cmd == "close")
425         {
426                 if (strl == tr("close") || strl == tr("c", "close"))
427                         return true;
428         }
429         else if (cmd == "columns")
430         {
431                 if (strl == tr("columns") || strl == tr("cols", "columns") || strl == tr("c", "columns"))
432                         return true;
433         }
434         else if (cmd == "columnspacing")
435         {
436                 if (strl == tr("columnspacing", "columnspacing for inserts")
437                         || strl == tr("colspacing", "columnspacing for inserts")
438                         || strl == tr("cs", "columnspacing for inserts"))
439                         return true;
440         }
441         else if (cmd == "factor")
442         {
443                 if (strl == tr("factor") || strl == tr("fact", "factor") || strl == tr("f", "factor"))
444                         return true;
445         }
446         else if (cmd == "help")
447         {
448                 if (strl == tr("help") || strl == tr("?", "help"))
449                         return true;
450         }
451         else if (cmd == "length")
452         {
453                 if (strl == tr("length", "length") || strl == tr("len", "length") || strl == tr("l", "length"))
454                         return true;
455         }
456         else if (cmd == "length1")
457         {
458                 if (strl == tr("length1", "length1") || strl == tr("len1", "length1")
459                         || strl == tr("l1", "length1"))
460                         return true;
461         }
462         else if (cmd == "length2")
463         {
464                 if (strl == tr("length2", "length2") || strl == tr("len2", "length2")
465                         || strl == tr("l2", "length2"))
466                         return true;
467         }
468         else if (cmd == "number")
469         {
470                 if (strl == tr("number") || strl == tr("num", "number") || strl == tr("n", "number"))
471                         return true;
472         }
473         else if (cmd == "radius")
474         {
475                 if (strl == tr("radius") || strl == tr("r", "radius"))
476                         return true;
477         }
478         else if (cmd == "reversed")
479         {
480                 if (strl == tr("reversed", "reversed arc") || strl == tr("rev", "reversed arc")
481                         || strl == tr("r", "reversed arc"))
482                         return true;
483         }
484         else if (cmd == "rows")
485         {
486                 if (strl == tr("rows") || strl == tr("r", "rows"))
487                         return true;
488         }
489         else if (cmd == "rowspacing")
490         {
491                 if (strl == tr("rowspacing", "rowspacing for inserts")
492                         || strl == tr("rs", "rowspacing for inserts"))
493                         return true;
494         }
495         else if (cmd == "text")
496         {
497                 if (strl == tr("text") || strl == tr("t", "text"))
498                         return true;
499         }
500         else if (cmd == "through")
501         {
502                 if (strl == tr("through") || strl == tr("t", "through"))
503                         return true;
504         }
505         else if (cmd == "undo")
506         {
507                 if (strl == tr("undo") || strl == tr("u", "undo"))
508                         return true;
509         }
510
511         return false;
512 }
513
514 /**
515  * @return the local translation for "Commands available:".
516  */
517 QString Commands::msgAvailableCommands()
518 {
519         return tr("Available commands:");
520 }