2
* Copyright 2013 Canonical Ltd.
4
* This program is free software; you can redistribute it and/or modify
5
* it under the terms of the GNU Lesser General Public License as published by
6
* the Free Software Foundation; version 2.1.
8
* This program is distributed in the hope that it will be useful,
9
* but WITHOUT ANY WARRANTY; without even the implied warranty of
10
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
* GNU Lesser General Public License for more details.
13
* You should have received a copy of the GNU Lesser General Public License
14
* along with this program. If not, see <http://www.gnu.org/licenses/>.
16
* Author: Juhapekka Piiroinen <juhapekka.piiroinen@canonical.com>
19
#include "ubuntumenu.h"
20
#include "ubuntushared.h"
21
#include "ubuntuconstants.h"
22
#include "ubuntudeviceswidget.h"
24
#include <coreplugin/icore.h>
25
#include <coreplugin/icontext.h>
26
#include <coreplugin/actionmanager/command.h>
27
#include <coreplugin/actionmanager/actioncontainer.h>
28
#include <coreplugin/coreconstants.h>
29
#include <coreplugin/messagemanager.h>
30
#include <qt4projectmanager/qt4projectmanagerconstants.h>
31
#include <projectexplorer/projectexplorer.h>
32
#include <projectexplorer/project.h>
33
#include <projectexplorer/buildmanager.h>
34
#include <projectexplorer/compileoutputwindow.h>
35
#include <projectexplorer/iprojectmanager.h>
36
#include <utils/qtcprocess.h>
38
#include <QProcessEnvironment>
41
#include <QInputDialog>
43
#include <QMessageBox>
45
#include <QJsonObject>
48
using namespace Ubuntu;
49
using namespace Ubuntu::Internal;
51
UbuntuMenu::UbuntuMenu(QObject *parent) :
54
m_obj = getMenuJSON();
56
connect(&m_ubuntuProcess,SIGNAL(message(QString)),this,SLOT(onMessage(QString)));
57
connect(&m_ubuntuProcess,SIGNAL(finished(QString,int)),this,SLOT(onFinished(QString,int)));
58
connect(&m_ubuntuProcess,SIGNAL(started(QString)),this,SLOT(onStarted(QString)));
59
connect(&m_ubuntuProcess,SIGNAL(error(QString)),this,SLOT(onError(QString)));
61
connect(ProjectExplorer::ProjectExplorerPlugin::instance(),SIGNAL(updateRunActions()),this,SLOT(slotUpdateActions()));
62
connect(UbuntuDevicesWidget::instance(),SIGNAL(updateDeviceActions()),this,SLOT(slotUpdateActions()));
66
void UbuntuMenu::slotUpdateActions() {
67
ProjectExplorer::ProjectExplorerPlugin* projectExplorerInstance = ProjectExplorer::ProjectExplorerPlugin::instance();
68
ProjectExplorer::Project* startupProject = projectExplorerInstance->startupProject();
69
bool isQmlProject = false;
70
bool isQmakeProject = false;
71
bool isUbuntuProject = false;
72
bool isCordovaProject = false;
75
isQmlProject = (startupProject->projectManager()->mimeType() == QLatin1String("application/x-qmlproject"));
76
isQmakeProject = (startupProject->projectManager()->mimeType() == QLatin1String("application/vnd.nokia.qt.qmakeprofile"));
77
isCordovaProject = (startupProject->projectManager()->mimeType() == QLatin1String("application/x-cordovaproject"));
78
isUbuntuProject = (startupProject->projectManager()->mimeType() == QLatin1String(Constants::UBUNTUPROJECT_MIMETYPE));
81
//bool canRun = projectExplorerInstance->canRun(startupProject,ProjectExplorer::NormalRunMode);
82
bool projectOpen = (startupProject!=NULL);
83
bool deviceDetected = UbuntuDevicesWidget::instance()->deviceDetected();
85
foreach(QAction* act, m_actions) {
86
bool requiresDevice = act->property(Constants::UBUNTU_MENUJSON_DEVICEREQUIRED).toBool();
87
bool requiresProject = act->property(Constants::UBUNTU_MENUJSON_PROJECTREQUIRED).toBool();
88
bool requiresQmlProject = act->property(Constants::UBUNTU_MENUJSON_QMLPROJECTREQUIRED).toBool();
89
bool requiresCordovaProject = act->property(Constants::UBUNTU_MENUJSON_CORDOVAPROJECTREQUIRED).toBool();
90
bool requiresQmakeProject = act->property(Constants::UBUNTU_MENUJSON_QMAKEPROJECTREQUIRED).toBool();
91
bool requiresUbuntuProject = act->property(Constants::UBUNTU_MENUJSON_UBUNTUPROJECTREQUIRED).toBool();
92
bool actionEnabled = ( (requiresQmakeProject ? isQmakeProject : true) && (requiresQmlProject ? isQmlProject : true) && (requiresDevice ? deviceDetected : true) && (requiresProject ? projectOpen : true) && (requiresUbuntuProject ? isUbuntuProject : true) && (requiresCordovaProject ? isCordovaProject : true));
94
act->setEnabled( actionEnabled );
98
void UbuntuMenu::onStarted(QString cmd) {
99
printToOutputPane(QString::fromLatin1("Started %0").arg(cmd));
102
void UbuntuMenu::onMessage(QString msg) {
103
printToOutputPane(msg);
106
void UbuntuMenu::onError(QString msg) {
107
printToOutputPane(QString::fromLatin1("%0").arg(msg));
110
void UbuntuMenu::onFinished(QString cmd, int code) {
111
printToOutputPane(QString::fromLatin1("%0 finished with code %1").arg(cmd).arg(code));
114
QString UbuntuMenu::menuPath(QString fileName) {
115
return Constants::UBUNTU_MENUPATH + fileName;
118
QJsonDocument UbuntuMenu::getMenuJSON() {
121
if (readFile(menuPath(QLatin1String(Constants::UBUNTU_MENUJSON)),&contents, &errorMsg) == false) {
122
qDebug() << __PRETTY_FUNCTION__ << errorMsg;
124
QJsonParseError error;
125
QJsonDocument retval = QJsonDocument::fromJson(contents,&error);
126
if (error.error != QJsonParseError::NoError) {
127
qDebug() << error.errorString();
132
void UbuntuMenu::parseMenu(QJsonObject obj, Core::ActionContainer*& parent, const Core::Id &group) {
133
if (obj.contains(QLatin1String(Constants::UBUNTU_MENUJSON_SUBMENU))) {
134
QString menuName, menuId;
135
if (obj.contains(QLatin1String(Constants::UBUNTU_MENUJSON_NAME))) {
136
menuName = obj.value(QLatin1String(Constants::UBUNTU_MENUJSON_NAME)).toString();
138
if (obj.contains(QLatin1String(Constants::UBUNTU_MENUJSON_ID))) {
139
menuId = obj.value(QLatin1String(Constants::UBUNTU_MENUJSON_ID)).toString();
141
Core::ActionContainer *actionContainer = Core::ActionManager::createMenu(Core::Id(menuId));
142
actionContainer->menu()->setTitle(menuName);
143
actionContainer->menu()->setObjectName(menuId);
145
QJsonValue submenu = obj.value(QLatin1String(Constants::UBUNTU_MENUJSON_SUBMENU));
146
if (submenu.isArray()) {
147
QJsonArray submenuArray = submenu.toArray();
148
for (int idx=0; idx<submenuArray.size(); idx++) {
149
QJsonValue subMenuItem = submenuArray.at(idx);
150
if (subMenuItem.isObject()) {
151
parseMenu(subMenuItem.toObject(),actionContainer);
156
if (parent == NULL) {
157
parent = actionContainer;
159
parent->addMenu(actionContainer,group);
161
} else if (obj.contains(QLatin1String(Constants::UBUNTU_MENUJSON_ACTIONS))) {
164
QString actionKeySequence;
165
QString actionWorkingDirectory;
166
bool actionProjectRequired = false;
167
bool actionDeviceRequired = false;
168
bool actionQmlProjectRequired = false;
169
bool actionQmakeProjectRequired = false;
170
bool actionUbuntuProjectRequired = false;
171
bool actionSaveRequired = false;
173
if (obj.contains(QLatin1String(Constants::UBUNTU_MENUJSON_NAME))) {
174
actionName = obj.value(QLatin1String(Constants::UBUNTU_MENUJSON_NAME)).toString();
176
if (obj.contains(QLatin1String(Constants::UBUNTU_MENUJSON_ID))) {
177
actionId = obj.value(QLatin1String(Constants::UBUNTU_MENUJSON_ID)).toString();
179
if (obj.contains(QLatin1String(Constants::UBUNTU_MENUJSON_KEYSEQUENCE))) {
180
actionKeySequence = obj.value(QLatin1String(Constants::UBUNTU_MENUJSON_KEYSEQUENCE)).toString();
182
if (obj.contains(QLatin1String(Constants::UBUNTU_MENUJSON_WORKINGDIRECTORY))) {
183
actionWorkingDirectory = obj.value(QLatin1String(Constants::UBUNTU_MENUJSON_WORKINGDIRECTORY)).toString();
185
if (obj.contains(QLatin1String(Constants::UBUNTU_MENUJSON_PROJECTREQUIRED))) {
186
actionProjectRequired = obj.value(QLatin1String(Constants::UBUNTU_MENUJSON_PROJECTREQUIRED)).toBool();
188
if (obj.contains(QLatin1String(Constants::UBUNTU_MENUJSON_DEVICEREQUIRED))) {
189
actionDeviceRequired = obj.value(QLatin1String(Constants::UBUNTU_MENUJSON_DEVICEREQUIRED)).toBool();
191
if (obj.contains(QLatin1String(Constants::UBUNTU_MENUJSON_QMLPROJECTREQUIRED))) {
192
actionQmlProjectRequired = obj.value(QLatin1String(Constants::UBUNTU_MENUJSON_QMLPROJECTREQUIRED)).toBool();
194
if (obj.contains(QLatin1String(Constants::UBUNTU_MENUJSON_QMAKEPROJECTREQUIRED))) {
195
actionQmakeProjectRequired = obj.value(QLatin1String(Constants::UBUNTU_MENUJSON_QMAKEPROJECTREQUIRED)).toBool();
198
if (obj.contains(QLatin1String(Constants::UBUNTU_MENUJSON_UBUNTUPROJECTREQUIRED))) {
199
actionUbuntuProjectRequired = obj.value(QLatin1String(Constants::UBUNTU_MENUJSON_UBUNTUPROJECTREQUIRED)).toBool();
202
if (obj.contains(QLatin1String(Constants::UBUNTU_MENUJSON_SAVEREQUIRED))) {
203
actionSaveRequired = obj.value(QLatin1String(Constants::UBUNTU_MENUJSON_SAVEREQUIRED)).toBool();
206
if (obj.contains(QLatin1String(Constants::UBUNTU_MENUJSON_ACTIONS)) && obj.value(QLatin1String(Constants::UBUNTU_MENUJSON_ACTIONS)).isArray()) {
208
QJsonValue actions = obj.value(QLatin1String(Constants::UBUNTU_MENUJSON_ACTIONS));
209
if (actions.isArray()) {
210
QJsonArray actionsArray = actions.toArray();
211
QJsonValueList actionsList;
212
for (int idx=0; idx<actionsArray.size(); idx++) {
213
QJsonValue actionItem = actionsArray.at(idx);
214
actionsList.append(actionItem);
216
m_commandMap.insert(actionName,actionsList);
220
QAction *act= new QAction(actionName, this);
221
act->setObjectName(actionId);
223
Core::Command *cmd = Core::ActionManager::registerAction(act, Core::Id(actionId), Core::Context(Core::Constants::C_GLOBAL));
224
if (actionKeySequence.isEmpty() == false) {
225
cmd->setDefaultKeySequence(QKeySequence(actionKeySequence));
227
if (actionWorkingDirectory.isEmpty() == false) {
228
act->setProperty(Constants::UBUNTU_MENUJSON_WORKINGDIRECTORY,actionWorkingDirectory);
231
act->setProperty(Constants::UBUNTU_MENUJSON_PROJECTREQUIRED,actionProjectRequired);
232
act->setProperty(Constants::UBUNTU_MENUJSON_DEVICEREQUIRED,actionDeviceRequired);
233
act->setProperty(Constants::UBUNTU_MENUJSON_QMAKEPROJECTREQUIRED,actionQmakeProjectRequired);
234
act->setProperty(Constants::UBUNTU_MENUJSON_QMLPROJECTREQUIRED,actionQmlProjectRequired);
235
act->setProperty(Constants::UBUNTU_MENUJSON_UBUNTUPROJECTREQUIRED,actionUbuntuProjectRequired);
236
act->setProperty(Constants::UBUNTU_MENUJSON_SAVEREQUIRED,actionSaveRequired);
238
connect(act, SIGNAL(triggered()), this, SLOT(menuItemTriggered()));
239
m_actions.append(act);
241
if (parent == NULL) {
242
qWarning() << "No menu defined";
244
parent->addAction(cmd,group);
250
void UbuntuMenu::menuItemTriggered() {
251
QAction* act = qobject_cast<QAction*>(sender());
254
// if we are executing something now, then kill it!
255
if (m_ubuntuProcess.state() != QProcess::NotRunning) {
256
m_ubuntuProcess.stop();
259
QVariant projectRequired = act->property(Constants::UBUNTU_MENUJSON_PROJECTREQUIRED);
260
ProjectExplorer::Project* project = NULL;
262
if (projectRequired.isValid() && projectRequired.toBool() == true) {
263
project = ProjectExplorer::ProjectExplorerPlugin::instance()->startupProject();
265
if (project == NULL) {
266
QMessageBox::information(Core::ICore::mainWindow(),QLatin1String(Constants::UBUNTU_DIALOG_NO_PROJECTOPEN_TITLE),QLatin1String(Constants::UBUNTU_DIALOG_NO_PROJECTOPEN_TEXT));
271
QVariant saveModifiedFilesRequired = act->property(Constants::UBUNTU_MENUJSON_SAVEREQUIRED);
272
if (saveModifiedFilesRequired.isValid() && saveModifiedFilesRequired.toBool()==true) {
273
ProjectExplorer::ProjectExplorerPlugin::instance()->saveModifiedFiles();
276
if (m_commandMap.contains(act->text())) {
277
QJsonValueList actions = m_commandMap.value(act->text());
280
bool bQueryOk = false;
283
for (int idx=0; idx < actions.size(); idx++) {
284
QJsonValue value = actions.at(idx);
285
if (value.isObject()) {
286
QJsonObject obj = value.toObject();
288
// check if the object is a querydialog
289
if (obj.contains(QLatin1String(Constants::UBUNTU_MENUJSON_QUERYDIALOG))) {
290
QJsonValue queryDialog = obj.value(QLatin1String(Constants::UBUNTU_MENUJSON_QUERYDIALOG));
291
if (queryDialog.isObject()) {
292
QJsonObject queryDialogObj = queryDialog.toObject();
293
QString queryDialogTitle;
294
QString queryDialogMessage;
295
QString queryDialogValue;
297
if (queryDialogObj.contains(QLatin1String(Constants::UBUNTU_MENUJSON_TITLE))) {
298
queryDialogTitle = queryDialogObj.value(QLatin1String(Constants::UBUNTU_MENUJSON_TITLE)).toString();
301
if (queryDialogObj.contains(QLatin1String(Constants::UBUNTU_MENUJSON_MESSAGE))) {
302
queryDialogMessage = queryDialogObj.value(QLatin1String(Constants::UBUNTU_MENUJSON_MESSAGE)).toString();
305
if (queryDialogObj.contains(QLatin1String(Constants::UBUNTU_MENUJSON_VALUE))) {
306
queryDialogValue = queryDialogObj.value(QLatin1String(Constants::UBUNTU_MENUJSON_VALUE)).toString();
309
queryData = QInputDialog::getText(Core::ICore::mainWindow(), queryDialogTitle,
310
queryDialogMessage, QLineEdit::Normal,
311
queryDialogValue, &bQueryOk);
313
// raise a flag that there is query data available for future actions
316
// if user has cancelled
317
if (bQueryOk == false) {
319
m_ubuntuProcess.clear();
323
// check if messageDialog
324
} else if (obj.contains(QLatin1String(Constants::UBUNTU_MENUJSON_MESSAGEDIALOG))) {
325
QJsonValue messageDialog = obj.value(QLatin1String(Constants::UBUNTU_MENUJSON_MESSAGEDIALOG));
326
if (messageDialog.isObject()) {
327
QJsonObject messageDialogObj = messageDialog.toObject();
328
QString messageDialogTitle;
329
QString messageDialogMessage;
331
if (messageDialogObj.contains(QLatin1String(Constants::UBUNTU_MENUJSON_TITLE))) {
332
messageDialogTitle = messageDialogObj.value(QLatin1String(Constants::UBUNTU_MENUJSON_TITLE)).toString();
335
if (messageDialogObj.contains(QLatin1String(Constants::UBUNTU_MENUJSON_MESSAGE))) {
336
messageDialogMessage = messageDialogObj.value(QLatin1String(Constants::UBUNTU_MENUJSON_MESSAGE)).toString();
339
QMessageBox::information(Core::ICore::mainWindow(), messageDialogTitle,
340
messageDialogMessage);
344
} else if (value.isString()) {
345
QString command = value.toString();
346
QString workingDirectory;
350
QString projectDirectory = project->projectDirectory();
351
QString displayName = project->displayName();
352
QString folderName = QFileInfo(projectDirectory).baseName();
353
QStringList projectFiles = project->files(ProjectExplorer::Project::AllFiles);
355
QString workingDirectoryData = act->property(Constants::UBUNTU_MENUJSON_WORKINGDIRECTORY).toString();
356
if (workingDirectoryData.isEmpty() == false) {
357
workingDirectory = workingDirectoryData.arg(projectDirectory);
359
workingDirectory = projectDirectory;
361
command = command.replace(QLatin1String(Constants::UBUNTU_ACTION_PROJECTDIRECTORY),projectDirectory);
362
command = command.replace(QLatin1String(Constants::UBUNTU_ACTION_FOLDERNAME),folderName);
363
command = command.replace(QLatin1String(Constants::UBUNTU_ACTION_DISPLAYNAME),displayName);
364
command = command.replace(QLatin1String(Constants::UBUNTU_ACTION_PROJECTFILES),projectFiles.join(QLatin1String(" ")));
367
command = command.replace(QLatin1String(Constants::UBUNTU_ACTION_SHAREDIRECTORY),Constants::UBUNTU_SHAREPATH);
368
command = command.replace(QLatin1String(Constants::UBUNTU_ACTION_SCRIPTDIRECTORY),Constants::UBUNTU_SCRIPTPATH);
369
command = command.replace(QLatin1String(Constants::UBUNTU_ACTION_SERIALNUMBER),UbuntuDevicesWidget::instance()->serialNumber());
371
if (bQuery && bQueryOk) {
372
command = QString(command).arg(queryData);
376
cmdList << command << workingDirectory;
377
m_ubuntuProcess.append(cmdList);
380
m_ubuntuProcess.start(act->text());
382
qWarning() << __PRETTY_FUNCTION__ << "No actions defined in map";
385
qWarning() << __PRETTY_FUNCTION__ << "Could not cast to action";
389
void UbuntuMenu::initialize() {
390
if (m_obj.isObject()) {
391
QJsonObject tmp = m_obj.object();
393
foreach (QString key, tmp.keys()) {
394
if (tmp.contains(key)) {
395
QJsonObject obj = tmp.value(key).toObject();
397
Core::ActionContainer *actionContainer = NULL;
399
if (obj.contains(QLatin1String(Constants::UBUNTU_MENUJSON_PARENT))) {
400
QString parentValue = obj.value(QLatin1String(Constants::UBUNTU_MENUJSON_PARENT)).toString();
401
if (parentValue == QLatin1String(Constants::UBUNTU_MENUJSON_PARENT_TOOLS)) actionContainer = Core::ActionManager::actionContainer(Core::Constants::M_TOOLS);
402
else if (parentValue == QLatin1String(Constants::UBUNTU_MENUJSON_PARENT_EDIT)) actionContainer = Core::ActionManager::actionContainer(Core::Constants::M_EDIT);
403
else if (parentValue == QLatin1String(Constants::UBUNTU_MENUJSON_PARENT_HELP)) actionContainer = Core::ActionManager::actionContainer(Core::Constants::M_HELP);
404
else if (parentValue == QLatin1String(Constants::UBUNTU_MENUJSON_PARENT_WINDOW)) actionContainer = Core::ActionManager::actionContainer(Core::Constants::M_WINDOW);
405
else if (parentValue == QLatin1String(Constants::UBUNTU_MENUJSON_PARENT_FILE)) actionContainer = Core::ActionManager::actionContainer(Core::Constants::M_FILE);
406
else if (parentValue == QLatin1String(Constants::UBUNTU_MENUJSON_PARENT_BUILD)) actionContainer = Core::ActionManager::actionContainer(ProjectExplorer::Constants::M_BUILDPROJECT);
407
else if (parentValue == QLatin1String(Constants::UBUNTU_MENUJSON_PARENT_TOP)) actionContainer = Core::ActionManager::actionContainer(Core::Constants::MENU_BAR);
408
else actionContainer = Core::ActionManager::actionContainer(Core::Id(parentValue));
410
actionContainer = Core::ActionManager::actionContainer(Core::Constants::M_TOOLS);
414
if (obj.contains(QLatin1String(Constants::UBUNTU_MENUJSON_GROUP))) {
415
group = obj.value(QLatin1String(Constants::UBUNTU_MENUJSON_GROUP)).toString();
419
if (!group.isEmpty()) {
420
groupId = Core::Id(group);
422
parseMenu(obj,actionContainer,groupId);
426
qDebug() << "json is not valid";