skin: find event of menu button from list of context menu
[sdk/emulator/qemu.git] / tizen / src / ui / menu / contextmenu.cpp
1 /*
2  * Qt UI
3  *
4  * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact:
7  * SungMin Ha <sungmin82.ha@samsung.com>
8  * GiWoong Kim <giwoong.kim@samsung.com>
9  * SeokYeon Hwang <syeon.hwang@samsung.com>
10  * Sangho Park <sangho.p@samsung.com>
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
25  * MA 02110-1301, USA.
26  *
27  * Contributors:
28  * - S-Core Co., Ltd
29  *
30  */
31
32 #include "contextmenu.h"
33 #include "resource/ui_strings.h"
34 #include "emulator_common.h"
35 #include "mainwindow.h"
36 #include "uiutil.h"
37 #include "menu/advancedmenuitem.h"
38 #include "menu/scalemenuitem.h"
39 #include "emul_state.h"
40
41 extern "C" {
42 // FIXME: To avoid very complex header inclusion chains
43 void qemu_system_graceful_shutdown_request(unsigned int sec);
44 void qemu_system_reset_request(void);
45 #define MENU_ACTION_REBOOT      1
46 void send_shutdown_request(int action);
47
48 #define QObject qemu_QObject
49 #include "util/net_helper.h"
50 #include "util/osutil.h"
51 #include "util/device_hotplug.h"
52 #include "util/ui_operations.h"
53 #undef QObject
54 }
55
56 #undef connect
57
58 ContextMenu::ContextMenu(QWidget *parent) : QMenu(parent)
59 {
60     this->parent = (MainWindow *)parent;
61     this->infoDialog = NULL;
62     this->aboutDialog = NULL;
63     this->screenshotDialog = NULL;
64
65     this->advancedMenu = NULL;
66     this->switchMenu = NULL;
67     this->scaleMenu = NULL;
68     this->controllerMenu = NULL;
69
70     this->actionDetailedInfo = NULL;
71     this->actionOnTop = NULL;
72     this->actionShell = NULL;
73     this->actionControlPanel = NULL;
74     this->actionScreenShot = NULL;
75     this->actionAbout = NULL;
76     this->actionForceClose = NULL;
77     this->actionClose = NULL;
78
79     this->switchMapper = NULL;
80     this->scaleMapper = NULL;
81     this->controllerMapper = NULL;
82
83     vmName = this->parent->getUiInfo()->getVmName() + " : "
84         + QString::number(get_vm_device_serial_number());
85
86     /* for SDB shell */
87     sdbHelper = new SdbHelper(this->parent, this->parent->getDisplay());
88
89     /* for close */
90     longPressTimer = new QTimer(this);
91
92     /* for system reset */
93     rebootTimer = new QTimer(this);
94     rebootTimer->setInterval(HARDWARE_REBOOT_INTERVAL);
95     rebootTimer->setSingleShot(true);
96     QObject::connect(rebootTimer, SIGNAL(timeout()), this, SLOT(slotDeviceReset()));
97
98     createItems(this, this->parent->getUiInfo()->getMenuList());
99
100     installEventFilter(this);
101 }
102
103 QAction *ContextMenu::getOnTopAction() {
104     return actionOnTop;
105 }
106
107 void ContextMenu::createItems(QMenu *menu, QList<MenuItem *> &list)
108 {
109     MenuItem *item = NULL;
110     for (int i = 0; i < list.count(); i++) {
111         item = list.at(i);
112
113         switch (item->getType()) {
114         case MenuItemType::separator:
115             createSeparator(menu);
116             break;
117         case MenuItemType::advancedItem:
118             /* Advanced menu */
119             createAdvancedItem(menu, item);
120             break;
121         case MenuItemType::infoItem:
122             /* Detailed Info menu */
123             createInfoItem(menu, item);
124             break;
125         case MenuItemType::onTopItem:
126             /* Always On Top menu */
127             createOnTopItem(menu, item);
128             break;
129         case MenuItemType::moveItem:
130             /* Move menu */
131             createMoveItem(menu, item);
132             break;
133         case MenuItemType::switchItem:
134             /* Rotate menu */
135             createSwitchItem(menu, item);
136             break;
137         case MenuItemType::scaleItem:
138             /* Scale menu */
139             createScaleItem(menu, item);
140             break;
141         case MenuItemType::controllerItem:
142             /* Controller menu */
143             createControllerItem(menu, item);
144             break;
145         case MenuItemType::hostKeyboardItem:
146             /* Host Keyboard menu */
147             createHostKeyboardItem(menu, item);
148             break;
149         case MenuItemType::shellItem:
150             /* Shell menu */
151             createShellItem(menu, item);
152             break;
153         case MenuItemType::controlPanelItem:
154             /* Control Panel menu */
155             createControlPanelItem(menu, item);
156             break;
157         case MenuItemType::screenShotItem:
158             /* Screen Shot menu */
159             createScreenShotItem(menu, item);
160             break;
161         case MenuItemType::aboutItem:
162             /* About menu */
163             createAboutItem(menu, item);
164             break;
165         case MenuItemType::systemResetItem:
166             /* System Reset menu */
167             createSystemResetItem(menu, item);
168             break;
169         case MenuItemType::forceCloseItem:
170             /* Force Close menu */
171             createForceCloseItem(menu, item);
172             break;
173         case MenuItemType::closeItem:
174             /* Close menu */
175             createCloseItem(menu, item);
176             break;
177         default:
178             qWarning("unknown menu item type: %d", item->getType());
179         }
180     }
181 }
182
183 void ContextMenu::createSeparator(QMenu *menu)
184 {
185     if (menu == NULL) {
186         return;
187     }
188
189     menu->addSeparator();
190 }
191
192 void ContextMenu::createAdvancedItem(QMenu *menu, MenuItem *item)
193 {
194     if (menu == NULL || item == NULL) {
195         return;
196     }
197
198     QString menuName = item->getName();
199     advancedMenu = menu->addMenu(QIcon(QPixmap(":/icons/advanced.png")),
200         menuName.isEmpty() ? "Advanced" : menuName);
201
202     createItems(advancedMenu, ((AdvancedMenuItem *)item)->getMenuList());
203 }
204
205 void ContextMenu::createInfoItem(QMenu *menu, MenuItem *item)
206 {
207     if (menu == NULL || item == NULL) {
208         return;
209     }
210
211     QString menuName = item->getName();
212     actionDetailedInfo = addGeneralAction(
213         menu, QIcon(QPixmap(":/icons/detailed_info.png")),
214         menuName.isEmpty() ? vmName : menuName,
215         item->getShortcuts().isEmpty()? NULL :
216         new QShortcut(item->getShortcuts().begin().value(), parent),
217         SLOT(slotDetailedInfo()));
218
219     actionDetailedInfo->setIconText(menuName.isEmpty() ? QString(DETAILED_INFO_TITLE) : menuName);
220
221     item->setSlot(SLOT(slotDetailedInfo()));
222     item->setAction(actionDetailedInfo);
223 }
224
225 void ContextMenu::createOnTopItem(QMenu *menu, MenuItem *item)
226 {
227     if (menu == NULL || item == NULL) {
228         return;
229     }
230
231     QString menuName = item->getName();
232     actionOnTop = menu->addAction(
233         menuName.isEmpty() ? MENU_ONTOP_ITEM_TEXT : menuName);
234 #ifdef CONFIG_DARWIN
235         // add dummy icon
236         QPixmap pix = QPixmap(QSize(16, 16));
237         pix.fill(Qt::transparent);
238         actionOnTop->setIcon(QIcon(pix));
239 #endif
240
241     actionOnTop->setCheckable(true);
242     QObject::connect(actionOnTop, SIGNAL(triggered(bool)), this, SLOT(slotOnTop(bool)));
243
244     /* shortcut */
245     if (item->getShortcuts().isEmpty() == false) {
246         QShortcut *shortcut = new QShortcut(
247             item->getShortcuts().begin().value(), parent);
248         attachShortcut(actionOnTop, shortcut, SLOT(slotOnTopShortcut()));
249     }
250
251     item->setSlot(SLOT(slotOnTopShortcut()));
252     item->setAction(actionOnTop);
253 }
254
255 void ContextMenu::createMoveItem(QMenu *menu, MenuItem *item)
256 {
257     if (menu == NULL || item == NULL) {
258         return;
259     }
260
261     QString menuName = item->getName();
262     actionMove = addGeneralAction(menu, QIcon(QPixmap(":/icons/move.png")),
263         menuName.isEmpty() ? MENU_MOVE_ITEM_TEXT : menuName,
264         item->getShortcuts().isEmpty() ? NULL
265         : new QShortcut(item->getShortcuts().begin().value(), parent),
266         SLOT(slotMove()));
267
268     item->setSlot(SLOT(slotMove()));
269     item->setAction(actionMove);
270 }
271
272 void ContextMenu::createSwitchItem(QMenu *menu, MenuItem *item)
273 {
274     if (menu == NULL || item == NULL) {
275         return;
276     }
277
278     QList<MainForm *> &mainFormList = parent->getUiInfo()->getMainFormList();
279
280     if (mainFormList.isEmpty() == false) {
281         QString menuName = item->getName();
282         switchMenu = menu->addMenu(QIcon(QPixmap(":/icons/rotate.png")),
283             menuName.isEmpty() ? MENU_SWITCH_ITEM_TEXT : menuName);
284
285         switchGroup = new QActionGroup(this);
286         switchMapper = new QSignalMapper(this);
287         QObject::connect(switchMapper, SIGNAL(mapped(int)), this, SLOT(slotSwitch(int)));
288
289         /* shortcuts */
290         QAction *switchAction = switchMenu->menuAction();
291         QMap<QString, QKeySequence> shortcuts = item->getShortcuts();
292
293         if (shortcuts.isEmpty() == false) {
294             QMap<QString, QKeySequence>::const_iterator iter;
295             if ((iter = shortcuts.find("prev")) != shortcuts.end()) {
296                 QShortcut *shortcut = new QShortcut(iter.value(), parent);
297                 attachShortcut(switchAction, shortcut, SLOT(slotSwitchShortcutPrev()));
298             }
299             if ((iter = shortcuts.find("next")) != shortcuts.end()) {
300                 QShortcut *shortcut = new QShortcut(iter.value(), parent);
301                 attachShortcut(switchAction, shortcut, SLOT(slotSwitchShortcutNext()));
302             }
303
304             if (switchAction->shortcut().isEmpty() == true) {
305                 QShortcut *shortcut = new QShortcut(
306                     item->getShortcuts().begin().value(), parent);
307                 attachShortcut(switchAction, shortcut, SLOT(slotSwitchShortcutNext()));
308             }
309         }
310
311         QAction *action = NULL;
312         for (int i = 0; i < mainFormList.count(); i++) {
313             action = switchMenu->addAction(mainFormList.at(i)->getName());
314             action->setActionGroup(switchGroup);
315             action->setCheckable(true);
316             switchMapper->setMapping(action, i);
317             QObject::connect(action, SIGNAL(triggered()), switchMapper, SLOT(map()));
318         }
319
320         action = (QAction *) switchMapper->mapping(
321             parent->getUiState()->getMainFormIndex());
322         action->setChecked(true);
323     } else {
324         qWarning("cannot create a switchItem");
325     }
326
327     item->setSlot(SLOT(slotSwitchShortcutNext()));
328     item->setAction(switchMenu->menuAction());
329 }
330
331 void ContextMenu::createScaleItem(QMenu *menu, MenuItem *item)
332 {
333     if (menu == NULL || item == NULL) {
334         return;
335     }
336
337     QMap<int, QString> factorMap = ((ScaleMenuItem *)item)->getFactorMap();
338
339     if (factorMap.isEmpty() == false) {
340         QString menuName = item->getName();
341         scaleMenu = menu->addMenu(QIcon(QPixmap(":/icons/scale.png")),
342             menuName.isEmpty() ? MENU_SCALE_ITEM_TEXT : menuName);
343
344         scaleGroup = new QActionGroup(this);
345         scaleMapper = new QSignalMapper(this);
346         QObject::connect(scaleMapper, SIGNAL(mapped(int)), this, SLOT(slotScale(int)));
347
348         /* shortcuts */
349         QAction *scaleAction = scaleMenu->menuAction();
350         QMap<QString, QKeySequence> shortcuts = item->getShortcuts();
351
352         if (shortcuts.isEmpty() == false) {
353             QMap<QString, QKeySequence>::const_iterator shortcutIter;
354             if ((shortcutIter = shortcuts.find("prev")) != shortcuts.end()) {
355                 QShortcut *shortcut = new QShortcut(shortcutIter.value(), parent);
356                 attachShortcut(scaleAction, shortcut, SLOT(slotScaleShortcutPrev()));
357             }
358             if ((shortcutIter = shortcuts.find("next")) != shortcuts.end()) {
359                 QShortcut *shortcut = new QShortcut(shortcutIter.value(), parent);
360                 attachShortcut(scaleAction, shortcut, SLOT(slotScaleShortcutNext()));
361             }
362
363             if (scaleAction->shortcut().isEmpty() == true) {
364                 QShortcut *shortcut = new QShortcut(
365                     item->getShortcuts().begin().value(), parent);
366                 attachShortcut(scaleAction, shortcut, SLOT(slotScaleShortcutNext()));
367             }
368         }
369
370         QAction *action = NULL;
371
372         QMapIterator<int, QString> factorIter(factorMap);
373         factorIter.toBack();
374         while(factorIter.hasPrevious() == true) {
375             factorIter.previous();
376
377             QString factorName = factorIter.value();
378             action = scaleMenu->addAction(
379                 factorName.isEmpty() ? (QString::number(factorIter.key()) + '%') : factorName);
380             action->setActionGroup(scaleGroup);
381             action->setCheckable(true);
382             scaleMapper->setMapping(action, factorIter.key());
383             QObject::connect(action, SIGNAL(triggered()), scaleMapper, SLOT(map()));
384         }
385
386         // TODO: interpolation
387
388         action = (QAction *) scaleMapper->mapping(
389             parent->getUiState()->getScalePct());
390         action->setChecked(true);
391     } else {
392         qWarning("cannot create a scaleItem");
393     }
394
395     item->setSlot(SLOT(slotScaleShortcutNext()));
396     item->setAction(scaleMenu->menuAction());
397 }
398
399 void ContextMenu::createControllerItem(QMenu *menu, MenuItem *item)
400 {
401     if (menu == NULL || item == NULL) {
402         return;
403     }
404
405     QList<ControllerForm *> &conFormList = parent->getUiInfo()->getConFormList();
406
407     if (conFormList.isEmpty() == false) {
408         QString menuName = item->getName();
409
410 #ifdef CONFIG_DARWIN
411         // add dummy icon
412         QPixmap pix = QPixmap(QSize(16, 16));
413         pix.fill(Qt::transparent);
414         controllerMenu = menu->addMenu(QIcon(pix),
415                     menuName.isEmpty() ? MENU_CONTROLLER_ITEM_TEXT : menuName);
416 #else
417         controllerMenu = menu->addMenu(
418                     menuName.isEmpty() ? MENU_CONTROLLER_ITEM_TEXT : menuName);
419 #endif
420         controllerGroup = new QActionGroup(this);
421         controllerMapper = new QSignalMapper(this);
422         QObject::connect(controllerMapper, SIGNAL(mapped(int)), this, SLOT(slotController(int)));
423
424         /* shortcuts */
425         QAction *conAction = controllerMenu->menuAction();
426         QMap<QString, QKeySequence> shortcuts = item->getShortcuts();
427
428         if (shortcuts.isEmpty() == false) {
429             QMap<QString, QKeySequence>::const_iterator iter;
430             if ((iter = shortcuts.find("prev")) != shortcuts.end()) {
431                 QShortcut *shortcut = new QShortcut(iter.value(), parent);
432                 attachShortcut(conAction, shortcut, SLOT(slotConShortcutPrev()));
433             }
434             if ((iter = shortcuts.find("next")) != shortcuts.end()) {
435                 QShortcut *shortcut = new QShortcut(iter.value(), parent);
436                 attachShortcut(conAction, shortcut, SLOT(slotConShortcutNext()));
437             }
438
439             if (conAction->shortcut().isEmpty() == true) {
440                 QShortcut *shortcut = new QShortcut(
441                     item->getShortcuts().begin().value(), parent);
442                 attachShortcut(conAction, shortcut, SLOT(slotConShortcutNext()));
443             }
444         }
445
446         QAction *action = NULL;
447         action = controllerMenu->addAction(GENERIC_TEXT_NONE);
448         action->setActionGroup(controllerGroup);
449         action->setCheckable(true);
450         action->setChecked(true);
451         QObject::connect(action, SIGNAL(triggered()), this, SLOT(slotCloseCon()));
452
453         for (int i = 0; i < conFormList.count(); i++) {
454             action = controllerMenu->addAction(conFormList.at(i)->getName());
455             action->setActionGroup(controllerGroup);
456             action->setCheckable(true);
457             controllerMapper->setMapping(action, i);
458             QObject::connect(action, SIGNAL(triggered()), controllerMapper, SLOT(map()));
459         }
460     } else {
461         qWarning("cannot create a controllerItem");
462     }
463
464     item->setSlot(SLOT(slotConShortcutNext()));
465     item->setAction(controllerMenu->menuAction());
466 }
467
468 void ContextMenu::createHostKeyboardItem(QMenu *menu, MenuItem *item)
469 {
470     if (menu == NULL || item == NULL) {
471         return;
472     }
473
474     QString menuName = item->getName();
475     QMenu *keyboardMenu = menu->addMenu(QIcon(),
476         menuName.isEmpty() ? MENU_HOSTKBD_ITEM_TEXT : menuName);
477     keyboardGroup = new QActionGroup(this);
478
479     QAction *hostKbdAction = keyboardMenu->addAction(MENU_ON_ITEM_TEXT);
480     hostKbdAction->setActionGroup(keyboardGroup);
481     hostKbdAction->setCheckable(true);
482     QObject::connect(hostKbdAction, SIGNAL(toggled(bool)), this, SLOT(slotHostKeyboard(bool)));
483
484     /* shortcuts */
485     // TODO:
486
487     hostKbdAction = keyboardMenu->addAction(MENU_OFF_ITEM_TEXT);
488     hostKbdAction->setActionGroup(keyboardGroup);
489     hostKbdAction->setCheckable(true);
490     hostKbdAction->setChecked(true);
491
492     // item->setSlot(slotHostKeyboardShortcut());
493     item->setAction(hostKbdAction);
494 }
495
496 void ContextMenu::createShellItem(QMenu *menu, MenuItem *item)
497 {
498     if (menu == NULL || item == NULL) {
499         return;
500     }
501
502     QString menuName = item->getName();
503     actionShell = addGeneralAction(
504         menu, QIcon(QPixmap(":/icons/shell.png")),
505         menuName.isEmpty() ? MENU_SHELL_ITEM_TEXT : menuName,
506         item->getShortcuts().isEmpty()? NULL :
507             new QShortcut(item->getShortcuts().begin().value(), parent),
508         SLOT(slotShell()));
509
510     item->setSlot(SLOT(slotShell()));
511     item->setAction(actionShell);
512 }
513
514 void ContextMenu::createControlPanelItem(QMenu *menu, MenuItem *item)
515 {
516     if (menu == NULL || item == NULL) {
517         return;
518     }
519
520     QString menuName = item->getName();
521     actionControlPanel = addGeneralAction(
522         menu, QIcon(QPixmap(":/icons/control_panel.png")),
523         menuName.isEmpty() ? MENU_ECP_ITEM_TEXT : menuName,
524         item->getShortcuts().isEmpty()? NULL :
525             new QShortcut(item->getShortcuts().begin().value(), parent),
526         SLOT(slotControlPanel()));
527
528     item->setSlot(SLOT(slotControlPanel()));
529     item->setAction(actionControlPanel);
530 }
531
532 void ContextMenu::createScreenShotItem(QMenu *menu, MenuItem *item)
533 {
534     if (menu == NULL || item == NULL) {
535         return;
536     }
537
538     QString menuName = item->getName();
539     actionScreenShot = addGeneralAction(
540         menu, QIcon(QPixmap(":/icons/screen_shot.png")),
541         menuName.isEmpty() ? MENU_SCREENSHOT_ITEM_TEXT : menuName,
542         item->getShortcuts().isEmpty()? NULL :
543             new QShortcut(item->getShortcuts().begin().value(), parent),
544         SLOT(slotRequestScreenshot()));
545
546     item->setSlot(SLOT(slotRequestScreenshot()));
547     item->setAction(actionScreenShot);
548 }
549
550 void ContextMenu::createAboutItem(QMenu *menu, MenuItem *item)
551 {
552     if (menu == NULL || item == NULL) {
553         return;
554     }
555
556     QString menuName = item->getName();
557     actionAbout = addGeneralAction(
558         menu, QIcon(QPixmap(":/icons/about.png")),
559         menuName.isEmpty() ? MENU_ABOUT_ITEM_TEXT : menuName,
560         item->getShortcuts().isEmpty()? NULL :
561             new QShortcut(item->getShortcuts().begin().value(), parent),
562         SLOT(slotAbout()));
563
564     item->setSlot(SLOT(slotAbout()));
565     item->setAction(actionAbout);
566 }
567
568 void ContextMenu::createSystemResetItem(QMenu *menu, MenuItem *item)
569 {
570     if (menu == NULL || item == NULL) {
571         return;
572     }
573
574     QString menuName = item->getName();
575     actionSystemReset = addGeneralAction(
576         menu, QIcon(),
577         menuName.isEmpty() ? MENU_FORCECLOSE_ITEM_TEXT : menuName,
578         item->getShortcuts().isEmpty()? NULL :
579             new QShortcut(item->getShortcuts().begin().value(), parent),
580         SLOT(slotSystemReset()));
581
582     item->setSlot(SLOT(slotSystemReset()));
583     item->setAction(actionSystemReset);
584 }
585
586 void ContextMenu::createForceCloseItem(QMenu *menu, MenuItem *item)
587 {
588     if (menu == NULL || item == NULL) {
589         return;
590     }
591
592     QString menuName = item->getName();
593     actionForceClose = addGeneralAction(
594         menu, QIcon(),
595         menuName.isEmpty() ? MENU_FORCECLOSE_ITEM_TEXT : menuName,
596         item->getShortcuts().isEmpty()? NULL :
597             new QShortcut(item->getShortcuts().begin().value(), parent),
598         SLOT(slotForceClose()));
599
600     item->setSlot(SLOT(slotForceClose()));
601     item->setAction(actionForceClose);
602 }
603
604 void ContextMenu::createCloseItem(QMenu *menu, MenuItem *item)
605 {
606     if (menu == NULL || item == NULL) {
607         return;
608     }
609
610     QString menuName = item->getName();
611     actionClose = addGeneralAction(
612         menu, QIcon(QPixmap(":/icons/close.png")),
613         menuName.isEmpty() ? MENU_CLOSE_ITEM_TEXT : menuName,
614         item->getShortcuts().isEmpty()? NULL :
615             new QShortcut(item->getShortcuts().begin().value(), parent),
616         SLOT(slotClose()));
617
618     item->setSlot(SLOT(slotClose()));
619     item->setAction(actionClose);
620 }
621
622 QAction *ContextMenu::addGeneralAction(QMenu *menu,
623     const QIcon &icon, const QString &text, QShortcut *shortcut, const char *slot)
624 {
625     QAction *action = menu->addAction(text);
626
627 #ifdef CONFIG_DARWIN
628     // set dummy icon
629     if (icon.isNull()) {
630         QPixmap pix = QPixmap(QSize(16, 16));
631         pix.fill(Qt::transparent);
632         action->setIcon(QIcon(pix));
633     } else {
634         action->setIcon(icon);
635     }
636 #else
637     action->setIcon(icon);
638 #endif
639     QObject::connect(action, SIGNAL(triggered()), this, slot);
640
641     attachShortcut(action, shortcut, slot);
642
643     return action;
644 }
645
646 void ContextMenu::attachShortcut(
647     QAction *action, QShortcut *shortcut, const char *slot)
648 {
649     if (action != NULL && shortcut != NULL) {
650         QObject::connect(shortcut, SIGNAL(activated()), this, slot);
651         QObject::connect(shortcut, SIGNAL(activatedAmbiguously()),
652             this, SLOT(slotAmbiguousShortcut()));
653
654         action->setShortcut(shortcut->key());
655     }
656 }
657
658 /* override */
659 bool ContextMenu::eventFilter(QObject *obj, QEvent *event)
660 {
661     ContextMenu *menu = dynamic_cast<ContextMenu *>(obj);
662     if (menu == NULL) {
663         return QObject::eventFilter(obj, event);
664     }
665
666     if (event->type() == QEvent::MouseButtonPress ||
667         event->type() == QEvent::MouseButtonRelease) {
668         QMouseEvent *mouseEvent = dynamic_cast<QMouseEvent *>(event);
669
670         if (mouseEvent != NULL && mouseEvent->button() == Qt::RightButton) {
671             /* if menu was selected then filter out the this event */
672             if (mouseEvent->x() >= 0 && mouseEvent->y() >= 0 &&
673                 mouseEvent->x() <= geometry().width() &&
674                 mouseEvent->y() <= geometry().height()) {
675                 mouseEvent->ignore(); /* filtering */
676                 return true;
677             }
678         }
679     } else if (event->type() == QEvent::Show) {
680         if (parent->getMainView()->isGrabWindow() == true) {
681             parent->getMainView()->releaseWindow();
682         }
683     }
684
685     return QObject::eventFilter(obj, event);
686 }
687
688 void ContextMenu::slotUndefinedMenu()
689 {
690     QMessageBox::warning(parent, EMULATOR_TITLE, MENU_UNDEFINED_ERROR);
691 }
692
693 void ContextMenu::slotAmbiguousShortcut()
694 {
695     /* When a shortcut's key sequence is completed, activatedAmbiguously()
696      * is emitted if the key sequence is still ambiguous (i.e., it is the
697      * start of one or more other shortcuts). */
698     qWarning("one shortcut key was overlapped with another");
699
700     QMessageBox::warning(parent, EMULATOR_TITLE, MENE_AMBIGUOUS_SHORTCUT);
701 }
702
703 void ContextMenu::slotDetailedInfo()
704 {
705     qDebug("VM info");
706
707     if (infoDialog == NULL) {
708         infoDialog = new DetailedInfoDialog((QWidget *)parent);
709     }
710
711     infoDialog->show();
712
713 #ifdef CONFIG_LINUX
714     slotOnTop(parent->getUiState()->isOnTop());
715 #endif
716 }
717
718 void ContextMenu::slotOnTop(bool on)
719 {
720     qDebug("stays on top: %s", on? "on" : "off");
721
722 #ifdef CONFIG_LINUX
723     /* On Ubuntu, all of the child windows which are higher than parent window in z-order
724      * should be getting a "ABOVE" state. */
725
726     QWidgetList list = QApplication::topLevelWidgets();
727     QWidget *widget = NULL;
728     for (int i = 0; i < list.count(); i++) {
729         widget = list.at(i);
730         if (widget->isWindow() && widget->parentWidget() == parent &&
731             this != widget) {
732             UiUtil::setTopMost(widget, on);
733         }
734     }
735 #endif
736
737     UiUtil::setTopMost(parent, on);
738
739     if (actionOnTop != NULL) {
740         actionOnTop->setChecked(on);
741     }
742     parent->getUiState()->setOnTop(on);
743 }
744
745 void ContextMenu::slotOnTopShortcut()
746 {
747     /* toggle */
748     slotOnTop(!actionOnTop->isChecked());
749
750     qDebug() << "shortcut:" << actionOnTop->text() << actionOnTop->isChecked();
751 }
752
753 void ContextMenu::slotMove()
754 {
755     parent->turnOnMovingMode();
756 }
757
758 void ContextMenu::slotSwitch(int index)
759 {
760     qDebug("switch: %d", index);
761
762     parent->switchForm(index);
763 }
764
765 void ContextMenu::slotSwitchShortcutPrev()
766 {
767     QList<QAction *> switchActions = switchGroup->actions();
768     if (switchActions.count() < 2) {
769         return;
770     }
771
772     int index = 0;
773
774     QAction *action = switchGroup->checkedAction();
775     if (action != NULL) {
776         index = switchActions.indexOf(action);
777         if (index == 0) {
778             index = switchActions.count() - 1;
779         } else {
780             index--;
781         }
782     }
783
784     QAction *prevAction = switchActions.at(index);
785     prevAction->setChecked(true);
786     prevAction->trigger();
787
788     qDebug() << "shortcut: prev" << switchMenu->title() << prevAction->text();
789 }
790
791 void ContextMenu::slotSwitchShortcutNext()
792 {
793     QList<QAction *> switchActions = switchGroup->actions();
794     if (switchActions.count() < 2) {
795         return;
796     }
797
798     int index = 0;
799
800     QAction *action = switchGroup->checkedAction();
801     if (action != NULL) {
802         index = switchActions.indexOf(action);
803         if (index == switchActions.count() - 1) {
804             index = 0;
805         } else {
806             index++;
807         }
808     }
809
810     QAction *nextAction = switchActions.at(index);
811     nextAction->setChecked(true);
812     nextAction->trigger();
813
814     qDebug() << "shortcut: next" << switchMenu->title() << nextAction->text();
815 }
816
817 void ContextMenu::slotScale(int scale)
818 {
819     qDebug("scale: %d", scale);
820
821     parent->scaleForm(scale);
822 }
823
824 void ContextMenu::slotScaleShortcutPrev()
825 {
826     QList<QAction *> scaleActions = scaleGroup->actions();
827     if (scaleActions.count() < 2) {
828         return;
829     }
830
831     int index = 0;
832
833     QAction *action = scaleGroup->checkedAction();
834     if (action != NULL) {
835         index = scaleActions.indexOf(action);
836         if (index == 0) {
837             index = scaleActions.count() - 1;
838         } else {
839             index--;
840         }
841     }
842
843     QAction *prevAction = scaleActions.at(index);
844     prevAction->setChecked(true);
845     prevAction->trigger();
846
847     qDebug() << "shortcut: prev" << scaleMenu->title() << prevAction->text();
848 }
849
850 void ContextMenu::slotScaleShortcutNext()
851 {
852     QList<QAction *> scaleActions = scaleGroup->actions();
853     if (scaleActions.count() < 2) {
854         return;
855     }
856
857     int index = 0;
858
859     QAction *action = scaleGroup->checkedAction();
860     if (action != NULL) {
861         index = scaleActions.indexOf(action);
862         if (index == scaleActions.count() - 1) {
863             index = 0;
864         } else {
865             index++;
866         }
867     }
868
869     QAction *nextAction = scaleActions.at(index);
870     nextAction->setChecked(true);
871     nextAction->trigger();
872
873     qDebug() << "shortcut: next" << scaleMenu->title() << nextAction->text();
874 }
875
876 void ContextMenu::slotController(int index)
877 {
878     qDebug("controller: %d", index);
879
880     parent->openController(index,
881         parent->getUiState()->getConState()->getRecentlyDockPos());
882
883     if (infoDialog != NULL && infoDialog->isVisible() == true) {
884         /* update controller shortcut info */
885         infoDialog->updateShortcutTableItems();
886     }
887 }
888
889 void ContextMenu::slotCloseCon()
890 {
891     qDebug("controller: None");
892
893     parent->closeController();
894     parent->getUiState()->getConState()->setConFormIndex(-1);
895
896     if (infoDialog != NULL && infoDialog->isVisible() == true) {
897         /* update controller shortcut info */
898         infoDialog->updateShortcutTableItems();
899     }
900 }
901
902 void ContextMenu::slotConShortcutPrev()
903 {
904     QList<QAction *> conActions = controllerGroup->actions();
905     if (conActions.count() < 2) {
906         return;
907     }
908
909     int index = 0;
910
911     QAction *action = controllerGroup->checkedAction();
912     if (action != NULL) {
913         index = conActions.indexOf(action);
914         if (index == 0) {
915             index = conActions.count() - 1;
916         } else {
917             index--;
918         }
919     }
920
921     QAction *prevAction = conActions.at(index);
922     prevAction->setChecked(true);
923     prevAction->trigger();
924
925     qDebug() << "shortcut: prev" << controllerMenu->title() << prevAction->text();
926 }
927
928 void ContextMenu::slotConShortcutNext()
929 {
930     QList<QAction *> conActions = controllerGroup->actions();
931     if (conActions.count() < 2) {
932         return;
933     }
934
935     int index = 0;
936
937     QAction *action = controllerGroup->checkedAction();
938     if (action != NULL) {
939         index = conActions.indexOf(action);
940         if (index == conActions.count() - 1) {
941             index = 0;
942         } else {
943             index++;
944         }
945     }
946
947     QAction *nextAction = conActions.at(index);
948     qDebug() << "shortcut next:" << controllerMenu->title() <<
949         '<' << nextAction->text();
950
951     nextAction->setChecked(true);
952     nextAction->trigger();
953 }
954
955 void ContextMenu::slotShell()
956 {
957     qDebug("SDB shell");
958
959     const QString sdbPath = sdbHelper->getSdbPath();
960
961     QFileInfo sdbFileInfo(sdbPath);
962     if (sdbFileInfo.exists() == false) {
963         parent->showMsgBox(QMessageBox::Warning, MSG_SDB_NOT_EXIST + sdbPath);
964         return;
965     }
966
967     if (!is_sdb_daemon_initialized()) {
968         parent->showMsgBox(QMessageBox::Warning, MSG_SDB_NOT_READY);
969         return;
970     }
971
972     /* start command in a new process */
973     sdbHelper->openShell(vmName);
974 }
975
976 void ContextMenu::launchControlPanel(QString& command,
977         QStringList& arguments)
978 {
979     const char *https_proxy_addr = get_https_proxy_addr();
980     if (https_proxy_addr) {
981         char **proxy = g_strsplit(https_proxy_addr, ":", 2);
982         if (proxy[0] && proxy[1]) {
983             QString httpsProxyAddr = "-Dhttps.proxyHost=" + QString(proxy[0]);
984             QString httpsProxyPort = "-Dhttps.proxyPort=" + QString(proxy[1]);
985             if (httpsProxyAddr != NULL && httpsProxyPort != NULL) {
986                 arguments << httpsProxyAddr << httpsProxyPort;
987             }
988         }
989         g_strfreev(proxy);
990     }
991
992
993     QString loggingCommand = QString("launching ecp: \"" + command + "\"");
994
995     QStringList wrapArguments;
996     for (int i = 0; i < arguments.size(); ++i) {
997         QString wrapArgument = QString("\"" + arguments.at(i) + "\"");
998          wrapArguments << wrapArgument;
999          loggingCommand += " " + wrapArgument;
1000     }
1001
1002     qInfo() << loggingCommand;
1003
1004     QString workingDir = QFileInfo(command).canonicalPath();
1005 #ifndef CONFIG_WIN32
1006     try {
1007         QProcess::startDetached(command, arguments, workingDir);
1008     } catch (QString &error) {
1009         parent->showMsgBox(QMessageBox::Warning, MSG_INVALID_ECP_OPEN + error);
1010         return;
1011     }
1012 #else
1013     QString winArguments = QString("\"" + command +"\"");
1014     for (int i = 0; i < arguments.size(); ++i) {
1015         winArguments += " \"" + arguments.at(i) + "\"";
1016     }
1017
1018     PROCESS_INFORMATION pinfo;
1019
1020     STARTUPINFOW startupInfo = { sizeof(STARTUPINFO), 0, 0, 0,
1021         (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT,
1022         (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT,
1023         0, 0, 0, STARTF_USESHOWWINDOW, SW_HIDE, 0, 0, 0, 0, 0
1024     };
1025     bool success = CreateProcessW(0, (LPWSTR)winArguments.utf16(),
1026             0, 0, FALSE, CREATE_UNICODE_ENVIRONMENT | CREATE_NEW_CONSOLE, 0,
1027             workingDir.isEmpty() ? 0 : (LPCWSTR)workingDir.utf16(),
1028             &startupInfo, &pinfo);
1029
1030
1031     if (!success) {
1032         QString error = QString::number(GetLastError());
1033         qWarning() << qPrintable(QString("error occured during launching \
1034                     ECP: ") + error);
1035         parent->showMsgBox(QMessageBox::Warning, MSG_INVALID_ECP_OPEN + error);
1036     }
1037
1038     CloseHandle(pinfo.hThread);
1039     CloseHandle(pinfo.hProcess);
1040 #endif
1041 }
1042
1043 void ContextMenu::slotControlPanel()
1044 {
1045     qDebug("Control Panel");
1046
1047     QString command;
1048     QStringList arguments;
1049
1050     // check for new ECP
1051 #if defined(CONFIG_WIN32)
1052     QString tmpEcpCommand = QDir(QCoreApplication::applicationDirPath() +
1053             QDir::separator() + SDK_EMULATOR_TOOLS_BIN_PATH +
1054             SDK_ECP_FILE + ".cmd").absolutePath();
1055     QString ecpCommand = QDir::toNativeSeparators(tmpEcpCommand);
1056 #elif defined(CONFIG_LINUX)
1057     QString ecpCommand = QDir(QCoreApplication::applicationDirPath() +
1058             QDir::separator() + SDK_EMULATOR_TOOLS_BIN_PATH +
1059             SDK_ECP_FILE).absolutePath();
1060 #else
1061     QString ecpCommand = QDir(QCoreApplication::applicationDirPath() +
1062             QDir::separator() + SDK_EMULATOR_TOOLS_BIN_PATH +
1063             SDK_ECP_FILE + ".app").absolutePath();
1064 #endif
1065     if (QFileInfo(ecpCommand).exists()) {
1066 #if defined(CONFIG_DARWIN)
1067         // In mac os x, launch .app using "open" command
1068         // ex : open emulator-control-panel.app --args vm_name=... platform_version=...
1069         command = "open";
1070         arguments << ecpCommand << "--args";
1071 #else
1072         command = ecpCommand;
1073 #endif
1074         QString vmNameOpt = "vm_name=" + parent->getUiInfo()->getVmName();
1075         QString platformVersionOpt = "platform_version=" +
1076             QString::fromLocal8Bit(get_platform_version());
1077         QString profileOpt = "profile=" +
1078             QString::fromLocal8Bit(get_profile_name());
1079         QString basePortOpt =
1080             "base_port=" + QString::number(parent->getUiInfo()->getBasePort());
1081
1082         arguments << vmNameOpt << platformVersionOpt << profileOpt
1083             << basePortOpt;
1084
1085         // we have standalone command for ECP
1086         // we respect standalone command, so nothing to do
1087         launchControlPanel(command, arguments);
1088
1089         return;
1090     }
1091
1092     // check for old ECP
1093     QString oldJar = QDir(QCoreApplication::applicationDirPath() +
1094             QDir::separator() + SDK_EMULATOR_BIN_PATH +
1095             SDK_ECP_FILE_JAR).absolutePath();
1096     if (QFileInfo(oldJar).exists()) {
1097         // we do not have standalone command for ECP
1098         // we may have SWT based ECP
1099
1100         // find java path
1101         const char *path;
1102         get_java_path(&path);
1103
1104         if (path) {
1105             command = QString::fromLocal8Bit(path);
1106         } else {
1107             // can not enter here...
1108             parent->showMsgBox(QMessageBox::Warning, MSG_INVALID_JAVA_PATH);
1109             return;
1110         }
1111
1112 #if defined(__x86_64__) || defined(_WIN64)
1113         arguments << "-d64";
1114 #endif
1115 #ifdef CONFIG_DARWIN
1116         /* SWT Display must be created on main thread due to Cocoa restrictions */
1117         arguments << "-XstartOnFirstThread";
1118 #endif
1119         arguments << "-jar" << oldJar;
1120
1121         QString vmNameOpt = "vmname=" + parent->getUiInfo()->getVmName();
1122         QString profileOpt = "profile=" +
1123             QString::fromLocal8Bit(get_profile_name());
1124         QString basePortOpt = "base.port=" +
1125             QString::number(parent->getUiInfo()->getBasePort());
1126
1127         arguments << vmNameOpt << profileOpt << basePortOpt;
1128
1129         launchControlPanel(command, arguments);
1130
1131         return;
1132     }
1133
1134     // we can not launch ControlPanel
1135     parent->showMsgBox(QMessageBox::Warning, MSG_ECP_NOT_EXIST);
1136
1137     return;
1138 }
1139
1140 void ContextMenu::slotRequestScreenshot()
1141 {
1142     qDebug("request screenshot");
1143
1144     parent->capture();
1145 }
1146
1147 void ContextMenu::slotShowScreenshot(const QPixmap &screenshot)
1148 {
1149     qDebug("show screenshot");
1150
1151     if (screenshotDialog == NULL) {
1152         screenshotDialog = new ScreenShotDialog(parent);
1153     }
1154
1155     screenshotDialog->slotRefresh(screenshot);
1156     screenshotDialog->show();
1157
1158 #ifdef CONFIG_LINUX
1159     slotOnTop(parent->getUiState()->isOnTop());
1160 #endif
1161 }
1162
1163 void ContextMenu::slotHostKeyboard(bool on)
1164 {
1165     qDebug("host keyboard: %s", on? "on" : "off");
1166
1167     if (on) {
1168         do_hotplug(ATTACH_HOST_KEYBOARD, NULL, 0);
1169     } else {
1170         do_hotplug(DETACH_HOST_KEYBOARD, NULL, 0);
1171     }
1172 }
1173
1174 void ContextMenu::slotAbout()
1175 {
1176     qDebug("about");
1177
1178     if (aboutDialog == NULL) {
1179         aboutDialog = new AboutDialog((QWidget *)parent);
1180     }
1181
1182     aboutDialog->show();
1183
1184 #ifdef CONFIG_LINUX
1185     slotOnTop(parent->getUiState()->isOnTop());
1186 #endif
1187 }
1188
1189 void ContextMenu::slotDeviceReset()
1190 {
1191     qDebug("System reset request.");
1192     qemu_system_reset_request();
1193     qDebug("Done for system reset request.");
1194 }
1195
1196 void ContextMenu::slotSystemReset()
1197 {
1198     int result = QMessageBox::question(this, EMULATOR_TITLE,
1199         MSG_SYSTEM_RESET_POPUP, QMessageBox::Yes, QMessageBox::No | QMessageBox::Default);
1200
1201     if (result == QMessageBox::Yes) {
1202         qDebug() << "Reboot.";
1203
1204         send_shutdown_request(MENU_ACTION_REBOOT);
1205
1206         rebootTimer->start();
1207     } else {
1208         qDebug() << "cancelled to reboot.";
1209     }
1210 }
1211
1212 void ContextMenu::slotForceClose()
1213 {
1214     qDebug("force close");
1215
1216     parent->close();
1217 }
1218
1219 void ContextMenu::slotPwkeyRelease()
1220 {
1221     do_hw_key_event(KEY_RELEASED, HARD_KEY_POWER);
1222 }
1223
1224 void ContextMenu::slotClose()
1225 {
1226     qDebug("close");
1227
1228     do_hw_key_event(KEY_PRESSED, HARD_KEY_POWER);
1229
1230     longPressTimer->setInterval(CLOSE_POWER_KEY_INTERVAL);
1231     longPressTimer->setSingleShot(true);
1232     QObject::connect(longPressTimer, SIGNAL(timeout()), this, SLOT(slotPwkeyRelease()));
1233     longPressTimer->start();
1234 }
1235
1236 QSignalMapper *ContextMenu::getSwitchMapper()
1237 {
1238     return switchMapper;
1239 }
1240
1241 QSignalMapper *ContextMenu::getScaleMapper()
1242 {
1243     return scaleMapper;
1244 }
1245
1246 QSignalMapper *ContextMenu::getControllerMapper()
1247 {
1248     return controllerMapper;
1249 }
1250
1251 ContextMenu::~ContextMenu()
1252 {
1253     qDebug("destroy menu");
1254
1255     delete sdbHelper;
1256
1257     longPressTimer->stop();
1258
1259     rebootTimer->stop();
1260 }