Merge lp:~zeller-benjamin/qtcreator-plugin-ubuntu/snapcraft-step2 into lp:qtcreator-plugin-ubuntu

Proposed by Benjamin Zeller
Status: Needs review
Proposed branch: lp:~zeller-benjamin/qtcreator-plugin-ubuntu/snapcraft-step2
Merge into: lp:qtcreator-plugin-ubuntu
Prerequisite: lp:~zeller-benjamin/qtcreator-plugin-ubuntu/publishcompileinfo
Diff against target: 3433 lines (+2806/-145)
45 files modified
UbuntuPlugin.pro (+4/-2)
share/qtcreator/templates/wizards/ubuntu/snap-qtquick-app-qmake/appName.pro (+0/-32)
share/qtcreator/templates/wizards/ubuntu/snap-qtquick-app-qmake/appName/appName.pro (+2/-19)
share/qtcreator/templates/wizards/ubuntu/snap-qtquick-app-qmake/snapcraft.yaml (+10/-4)
share/qtcreator/templates/wizards/ubuntu/snap-qtquick-app-qmake/wizard.json (+8/-13)
share/qtcreator/ubuntu/scripts/qtc_desktop_snaprunner.py (+90/-0)
share/qtcreator/ubuntu/scripts/run_snapcraft.py (+51/-0)
src/ubuntu/UbuntuProject.mimetypes.xml (+5/-0)
src/ubuntu/clicktoolchain.cpp (+21/-1)
src/ubuntu/clicktoolchain.h (+1/-0)
src/ubuntu/snap/project/snapcraftbuildconfiguration.cpp (+44/-0)
src/ubuntu/snap/project/snapcraftbuildconfiguration.h (+33/-0)
src/ubuntu/snap/project/snapcraftbuildconfigurationfactory.cpp (+154/-0)
src/ubuntu/snap/project/snapcraftbuildconfigurationfactory.h (+44/-0)
src/ubuntu/snap/project/snapcraftbuildstepfactory.cpp (+65/-0)
src/ubuntu/snap/project/snapcraftbuildstepfactory.h (+25/-0)
src/ubuntu/snap/project/snapcraftproject.cpp (+214/-0)
src/ubuntu/snap/project/snapcraftproject.h (+102/-0)
src/ubuntu/snap/project/snapcraftprojectfile.cpp (+42/-0)
src/ubuntu/snap/project/snapcraftprojectfile.h (+48/-0)
src/ubuntu/snap/project/snapcraftprojectmanager.cpp (+64/-0)
src/ubuntu/snap/project/snapcraftprojectmanager.h (+40/-0)
src/ubuntu/snap/project/snapcraftprojectnode.cpp (+517/-0)
src/ubuntu/snap/project/snapcraftprojectnode.h (+136/-0)
src/ubuntu/snap/project/snapcraftrsyncstep.cpp (+51/-0)
src/ubuntu/snap/project/snapcraftrsyncstep.h (+31/-0)
src/ubuntu/snap/project/snapcraftstep.cpp (+139/-0)
src/ubuntu/snap/project/snapcraftstep.h (+50/-0)
src/ubuntu/snap/project/snaprunconfiguration.cpp (+273/-0)
src/ubuntu/snap/project/snaprunconfiguration.h (+94/-0)
src/ubuntu/snap/project/snaprunconfigurationfactory.cpp (+85/-0)
src/ubuntu/snap/project/snaprunconfigurationfactory.h (+31/-0)
src/ubuntu/snap/settings/snapcraftkitinformation.cpp (+114/-0)
src/ubuntu/snap/settings/snapcraftkitinformation.h (+59/-0)
src/ubuntu/snap/snap.pri (+31/-0)
src/ubuntu/snap/snapcraftpackagestep.cpp (+1/-1)
src/ubuntu/ubuntuclicktool.cpp (+5/-0)
src/ubuntu/ubuntuclicktool.h (+1/-0)
src/ubuntu/ubuntuconstants.h (+22/-13)
src/ubuntu/ubuntujsextension.cpp (+11/-0)
src/ubuntu/ubuntujsextension.h (+1/-0)
src/ubuntu/ubuntukitmanager.cpp (+4/-1)
src/ubuntu/ubuntuplugin.cpp (+27/-3)
src/ubuntu/ubuntuversion.cpp (+43/-45)
src/ubuntu/ubuntuversion.h (+13/-11)
To merge this branch: bzr merge lp:~zeller-benjamin/qtcreator-plugin-ubuntu/snapcraft-step2
Reviewer Review Type Date Requested Status
ubuntu-sdk-build-bot continuous-integration Needs Fixing
Zoltan Balogh Pending
Review via email: mp+307947@code.launchpad.net

Commit message

Implementing Part2 of the snapcraft plan

Description of the change

Implementing Part2 of the snapcraft plan

To post a comment you must log in.
Revision history for this message
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote :
review: Needs Fixing (continuous-integration)
486. By Benjamin Zeller

- Superuser check
- Less messages when opening a project

Revision history for this message
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote :
review: Needs Fixing (continuous-integration)
487. By Benjamin Zeller

Compile on trusty

Revision history for this message
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote :
review: Needs Fixing (continuous-integration)

Unmerged revisions

487. By Benjamin Zeller

Compile on trusty

486. By Benjamin Zeller

- Superuser check
- Less messages when opening a project

485. By Benjamin Zeller

add devmode switch

484. By Benjamin Zeller

Send errors to the TaskHub

483. By Benjamin Zeller

Allow local execution of snapcraft projects.

482. By Benjamin Zeller

Support building in Ubuntu Containers

481. By Benjamin Zeller

Migrate snapcraft template to use the snapcraft project type

480. By Benjamin Zeller

Fix mimetype file

479. By Benjamin Zeller

some polishing

478. By Benjamin Zeller

- Added buildsteps
- Added buildconfiguration
- For now rsync the whole project to the build dir
- Wrap snapcraft call so "clean" is called always

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'UbuntuPlugin.pro'
2--- UbuntuPlugin.pro 2016-09-22 15:50:17 +0000
3+++ UbuntuPlugin.pro 2016-11-16 10:23:00 +0000
4@@ -52,7 +52,7 @@
5 src/ubuntu/ubuntuproject.cpp \
6 src/ubuntu/ubuntuprojectfile.cpp \
7 src/ubuntu/ubuntuprojectnode.cpp \
8- #src/ubuntu/ubuntuversion.cpp \
9+ src/ubuntu/ubuntuversion.cpp \
10 #src/ubuntu/ubuntufeatureprovider.cpp \
11 #src/ubuntu/ubuntuversionmanager.cpp \
12 src/ubuntu/ubuntupackagingmode.cpp \
13@@ -123,7 +123,7 @@
14 src/ubuntu/ubuntuproject.h \
15 src/ubuntu/ubuntuprojectfile.h \
16 src/ubuntu/ubuntuprojectnode.h \
17- #src/ubuntu/ubuntuversion.h \
18+ src/ubuntu/ubuntuversion.h \
19 #src/ubuntu/ubuntufeatureprovider.h \
20 #src/ubuntu/ubuntuversionmanager.h \
21 src/ubuntu/ubuntupackagingmode.h \
22@@ -220,6 +220,8 @@
23 src/ubuntu/device/remote/ubuntudirectuploadstep.h \
24 src/ubuntu/device/remote/ubuntudeploystepfactory.h
25
26+include(src/ubuntu/snap/snap.pri)
27+
28
29 FORMS += \
30 src/ubuntu/device/remote/ubunturemoterunconfigurationwidget.ui \
31
32=== removed file 'share/qtcreator/templates/wizards/ubuntu/snap-qtquick-app-qmake/appName.pro'
33--- share/qtcreator/templates/wizards/ubuntu/snap-qtquick-app-qmake/appName.pro 2016-09-22 15:32:42 +0000
34+++ share/qtcreator/templates/wizards/ubuntu/snap-qtquick-app-qmake/appName.pro 1970-01-01 00:00:00 +0000
35@@ -1,32 +0,0 @@
36-# This is the basic qmake template for the Ubuntu-SDK
37-# it handles creation and installation of the manifest
38-# file and takes care of subprojects
39-TEMPLATE = subdirs
40-
41-SUBDIRS += %{ProjectNameL}
42-
43-# enables/disabled the extra targets to build a snapcraft package
44-# also tells the IDE this is a snapcraft project
45-CONFIG += snapcraft
46-
47-snapcraft {
48-
49- SNAPCRAFT_FILE=snapcraft.yaml
50-
51- #the Ubuntu SDK IDE uses the snap target to create the package
52- snappy.target = snap
53- snappy.commands = cd $$OUT_PWD
54- snappy.commands += && rm -rf \'$$OUT_PWD/snap-deploy\'
55- snappy.commands += && make INSTALL_ROOT=$$OUT_PWD/snap-deploy install
56- snappy.commands += && cd $$OUT_PWD/snap-deploy
57- snappy.commands += && snapcraft
58-
59- OTHER_FILES+=$$SNAPCRAFT_FILE
60- QMAKE_EXTRA_TARGETS += snappy
61-
62- packaging.files = $$SNAPCRAFT_FILE
63- packaging.path = /
64-
65- INSTALLS+=packaging
66-}
67-
68
69=== modified file 'share/qtcreator/templates/wizards/ubuntu/snap-qtquick-app-qmake/appName/appName.pro'
70--- share/qtcreator/templates/wizards/ubuntu/snap-qtquick-app-qmake/appName/appName.pro 2016-09-22 15:32:42 +0000
71+++ share/qtcreator/templates/wizards/ubuntu/snap-qtquick-app-qmake/appName/appName.pro 2016-11-16 10:23:00 +0000
72@@ -16,33 +16,16 @@
73
74 CONF_FILES += %{ProjectNameL}.png
75
76-AP_TEST_FILES += tests/autopilot/run \
77- $$files(tests/*.py,true)
78-
79 #show all the files in QtCreator
80 OTHER_FILES += $${CONF_FILES} \
81 $${QML_FILES} \
82- $${AP_TEST_FILES} \
83 %{ProjectNameL}.desktop \
84 %{ProjectNameL}.wrapper
85
86 snapcraft {
87- #specify where the config files are installed to
88- config_files.path = /setup/gui
89- config_files.files += $${CONF_FILES}
90- INSTALLS+=config_files
91-
92- #install the desktop file
93- desktop_file.path = /setup/gui
94- desktop_file.files = $$PWD/%{ProjectNameL}.desktop
95- desktop_file.CONFIG += no_check_exist
96- INSTALLS+=desktop_file
97-
98- # Default rules for deployment.
99-
100 wrapper.files = %{ProjectNameL}.wrapper
101- wrapper.path = /deploy/bin
102+ wrapper.path = /bin
103
104- target.path = /deploy/bin
105+ target.path = /bin
106 INSTALLS+=target wrapper
107 }
108
109=== added directory 'share/qtcreator/templates/wizards/ubuntu/snap-qtquick-app-qmake/setup'
110=== added directory 'share/qtcreator/templates/wizards/ubuntu/snap-qtquick-app-qmake/setup/gui'
111=== renamed file 'share/qtcreator/templates/wizards/ubuntu/snap-qtquick-app-qmake/appName/appName.desktop' => 'share/qtcreator/templates/wizards/ubuntu/snap-qtquick-app-qmake/setup/gui/appName.desktop'
112=== renamed file 'share/qtcreator/templates/wizards/ubuntu/snap-qtquick-app-qmake/appName/appName.png' => 'share/qtcreator/templates/wizards/ubuntu/snap-qtquick-app-qmake/setup/gui/appName.png'
113=== modified file 'share/qtcreator/templates/wizards/ubuntu/snap-qtquick-app-qmake/snapcraft.yaml'
114--- share/qtcreator/templates/wizards/ubuntu/snap-qtquick-app-qmake/snapcraft.yaml 2016-09-22 15:32:42 +0000
115+++ share/qtcreator/templates/wizards/ubuntu/snap-qtquick-app-qmake/snapcraft.yaml 2016-11-16 10:23:00 +0000
116@@ -11,13 +11,19 @@
117
118 parts:
119 %{ProjectNameL}:
120- plugin: dump
121- source: deploy/
122+ plugin: qmake
123+ source: %{ProjectNameL}/
124+ qt-version: qt5
125+ options: ["CONFIG+=snapcraft"]
126+ project-files: [%{ProjectNameL}.pro]
127+ build-packages:
128+ - build-essential
129+ - qtbase5-dev
130+ - qt5-qmake
131 stage-packages:
132 - ubuntu-sdk-libs
133 - qtubuntu-desktop
134 - qtmir-desktop
135 - mir-graphics-drivers-desktop
136-
137-
138+ after: [qt5conf]
139
140
141=== modified file 'share/qtcreator/templates/wizards/ubuntu/snap-qtquick-app-qmake/wizard.json'
142--- share/qtcreator/templates/wizards/ubuntu/snap-qtquick-app-qmake/wizard.json 2016-09-22 15:32:42 +0000
143+++ share/qtcreator/templates/wizards/ubuntu/snap-qtquick-app-qmake/wizard.json 2016-11-16 10:23:00 +0000
144@@ -1,17 +1,17 @@
145 {
146 "version": 1,
147- "supportedProjectTypes": [ "Qt4ProjectManager.Qt4Project" ],
148+ "supportedProjectTypes": [ "SnapcraftProjectManager.SnapcraftProject" ],
149 "id": "A.QtQuick Snappy Application",
150 "category": "B.Snapcraft",
151 "trDescription": "Creates a experimental C++ Ubuntu snappy application project with a sample UI containing a Label and a Button.",
152 "trDisplayName": "QtQuick App with QML Ubuntu UI",
153 "trDisplayCategory": "Snapcraft",
154 "icon": "../share/ubuntu.png",
155- "enabled": "%{JS: [ %{Plugins} ].indexOf('QmakeProjectManager') >= 0}",
156+ "enabled": "%{JS: [ %{Plugins} ].indexOf('Ubuntu') >= 0 && Ubuntu.supportsSnappy()}",
157
158 "options":
159 [
160- { "key": "ProjectFile", "value": "%{JS: Util.fileName('%{ProjectDirectory}/%{ProjectName}', 'pro')}" },
161+ { "key": "ProjectFile", "value": "%{JS: Util.fileName('%{ProjectDirectory}/snapcraft','yaml')}" },
162 { "key": "ProjectNameL", "value": "%{JS: \"%{ProjectName}\".toLowerCase()}" },
163 { "key": "CppFileName", "value": "%{JS: 'main.' + Util.preferredSuffix('text/x-c++src')}" },
164 { "key": "IsTopLevelProject", "value": "%{JS: !'%{Exists:ProjectExplorer.Profile.Ids}'}" }
165@@ -62,15 +62,10 @@
166 "data":
167 [
168 {
169- "source": "appName.pro",
170- "target": "%{ProjectFile}",
171+ "source": "snapcraft.yaml",
172 "openAsProject": true
173 },
174 {
175- "source": "snapcraft.yaml",
176- "openInEditor": true
177- },
178- {
179 "source": "appName/main.cpp",
180 "target": "%{ProjectDirectory}/%{ProjectNameL}/%{CppFileName}",
181 "openInEditor": true
182@@ -81,12 +76,12 @@
183 "openInEditor": true
184 },
185 {
186- "source": "appName/appName.desktop",
187- "target": "%{ProjectDirectory}/%{ProjectNameL}/%{ProjectNameL}.desktop"
188+ "source": "setup/gui/appName.desktop",
189+ "target": "%{ProjectDirectory}/setup/gui/%{ProjectNameL}.desktop"
190 },
191 {
192- "source": "appName/appName.png",
193- "target": "%{ProjectDirectory}/%{ProjectNameL}/%{ProjectNameL}.png"
194+ "source": "setup/gui/appName.png",
195+ "target": "%{ProjectDirectory}/setup/gui/%{ProjectNameL}.png"
196 },
197 {
198 "source": "appName/appName.pro",
199
200=== added file 'share/qtcreator/ubuntu/scripts/qtc_desktop_snaprunner.py'
201--- share/qtcreator/ubuntu/scripts/qtc_desktop_snaprunner.py 1970-01-01 00:00:00 +0000
202+++ share/qtcreator/ubuntu/scripts/qtc_desktop_snaprunner.py 2016-11-16 10:23:00 +0000
203@@ -0,0 +1,90 @@
204+#!/usr/bin/python3
205+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
206+#
207+# QTC device applauncher
208+# Copyright (C) 2014 Canonical
209+#
210+# This program is free software: you can redistribute it and/or modify
211+# it under the terms of the GNU General Public License as published by
212+# the Free Software Foundation, either version 3 of the License, or
213+# (at your option) any later version.
214+#
215+# This program is distributed in the hope that it will be useful,
216+# but WITHOUT ANY WARRANTY; without even the implied warranty of
217+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
218+# GNU General Public License for more details.
219+#
220+# You should have received a copy of the GNU General Public License
221+# along with this program. If not, see <http://www.gnu.org/licenses/>.
222+#
223+# Author: Benjamin Zeller <benjamin.zeller@canonical.com>
224+
225+import os
226+import os.path
227+import subprocess
228+import argparse
229+import signal
230+import sys
231+
232+# register options to the argument parser
233+parser = argparse.ArgumentParser(description="SDK snap launcher")
234+parser.add_argument('snap_package',action="store")
235+parser.add_argument('snap_command',action='store')
236+parser.add_argument('--devmode' ,action='store_true')
237+
238+options, args = parser.parse_known_args()
239+
240+if not os.path.isfile(options.snap_package):
241+ print("Snap file does not exist")
242+ sys.exit(1)
243+
244+#parse the package name which should be application_version_arch.snap
245+app_info = os.path.basename(options.snap_package)[:-5].split("_")
246+if len(app_info) != 3:
247+ print("The snap package name is invalid", file=sys.stderr)
248+ sys.exit(1)
249+
250+#flush all descriptors
251+sys.stdout.flush()
252+sys.stderr.flush()
253+
254+#ok lets install the snap package
255+snaparg = ["snap", "install", options.snap_package, "--dangerous"]
256+if options.devmode:
257+ print("Enabling devmode\n")
258+ snaparg += ["--devmode"]
259+ret = subprocess.call(snaparg, stdout=sys.stdout, stderr=sys.stderr)
260+if ret != 0:
261+ sys.exit(ret)
262+
263+#flush all descriptors
264+sys.stdout.flush()
265+sys.stderr.flush()
266+
267+#this will contain the actual subprocess object
268+proc = None
269+stopped = False
270+def signalHandler(signum, frame):
271+ print('Signal handler called with signal', signum)
272+ if proc is not None:
273+ proc.kill()
274+ else:
275+ stopped = True
276+
277+signal.signal(signal.SIGINT, signalHandler)
278+signal.signal(signal.SIGTERM, signalHandler)
279+signal.signal(signal.SIGHUP, signalHandler)
280+
281+#start the actual app
282+print("Command args are: "+str(args)+"\n")
283+if not stopped:
284+ proc = subprocess.Popen(["snap", "run", app_info[0]+"."+options.snap_command]+args, stdout=sys.stdout, stderr=sys.stderr)
285+ ret = proc.wait()
286+
287+#flush all descriptors
288+sys.stdout.flush()
289+sys.stderr.flush()
290+
291+subprocess.call(["snap", "remove", app_info[0]], stdout=sys.stdout, stderr=sys.stderr)
292+
293+sys.exit(ret)
294
295=== added file 'share/qtcreator/ubuntu/scripts/run_snapcraft.py'
296--- share/qtcreator/ubuntu/scripts/run_snapcraft.py 1970-01-01 00:00:00 +0000
297+++ share/qtcreator/ubuntu/scripts/run_snapcraft.py 2016-11-16 10:23:00 +0000
298@@ -0,0 +1,51 @@
299+#!/usr/bin/python3
300+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
301+#
302+# QTC device applauncher
303+# Copyright (C) 2014 Canonical
304+#
305+# This program is free software: you can redistribute it and/or modify
306+# it under the terms of the GNU General Public License as published by
307+# the Free Software Foundation, either version 3 of the License, or
308+# (at your option) any later version.
309+#
310+# This program is distributed in the hope that it will be useful,
311+# but WITHOUT ANY WARRANTY; without even the implied warranty of
312+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
313+# GNU General Public License for more details.
314+#
315+# You should have received a copy of the GNU General Public License
316+# along with this program. If not, see <http://www.gnu.org/licenses/>.
317+#
318+# Author: Benjamin Zeller <benjamin.zeller@canonical.com>
319+
320+import os
321+import sys
322+import shutil
323+import subprocess
324+from optparse import OptionParser
325+
326+parser = OptionParser(usage="usage: %prog [options] lp:branch")
327+parser.add_option(
328+ "-s", "--snapcraft", dest="snapcraft")
329+options, args = parser.parse_args()
330+
331+if options.snapcraft is None:
332+ options.snapcraft = shutil.which("snapcraft")
333+
334+if options.snapcraft is None:
335+ parser.error("Snapcraft not found.")
336+
337+if not os.path.isfile(options.snapcraft) or not os.access(options.snapcraft, os.X_OK):
338+ parser.error("-s must specify a executable file.")
339+
340+print("Using snapcraft from :"+options.snapcraft)
341+
342+sys.stdout.flush()
343+sys.stderr.flush()
344+
345+ret = subprocess.call([options.snapcraft, "clean"])
346+if ret != 0:
347+ sys.exit(ret)
348+
349+sys.exit(subprocess.call([options.snapcraft]+args))
350
351=== modified file 'src/ubuntu/UbuntuProject.mimetypes.xml'
352--- src/ubuntu/UbuntuProject.mimetypes.xml 2015-03-06 15:02:08 +0000
353+++ src/ubuntu/UbuntuProject.mimetypes.xml 2016-11-16 10:23:00 +0000
354@@ -17,4 +17,9 @@
355 <sub-class-of type="application/json"/>
356 <glob pattern="manifest.json*"/>
357 </mime-type>
358+ <mime-type type="application/x-snapcraft">
359+ <comment>Snapcraft project file</comment>
360+ <sub-class-of type="application/x-yaml"/>
361+ <glob pattern="snapcraft.yaml"/>
362+ </mime-type>
363 </mime-info>
364
365=== modified file 'src/ubuntu/clicktoolchain.cpp'
366--- src/ubuntu/clicktoolchain.cpp 2016-09-22 13:17:48 +0000
367+++ src/ubuntu/clicktoolchain.cpp 2016-11-16 10:23:00 +0000
368@@ -62,6 +62,11 @@
369 ProjectExplorer::Abi::GenericLinuxFlavor,
370 ProjectExplorer::Abi::ElfFormat,
371 64));
372+ map.insert(QLatin1String("arm64") , ProjectExplorer::Abi(ProjectExplorer::Abi::ArmArchitecture,
373+ ProjectExplorer::Abi::LinuxOS,
374+ ProjectExplorer::Abi::GenericLinuxFlavor,
375+ ProjectExplorer::Abi::ElfFormat,
376+ 64));
377 return map;
378 }
379
380@@ -130,6 +135,15 @@
381 return clickArchitectures[arch];
382 }
383
384+QString ClickToolChain::abiToArchitectureName(const ProjectExplorer::Abi &abi)
385+{
386+ for (auto i = clickArchitectures.constBegin(); i != clickArchitectures.constEnd(); i++){
387+ if (i.value() == abi)
388+ return i.key();
389+ }
390+ return QString("unknown");
391+}
392+
393 QList<QString> ClickToolChain::supportedArchitectures()
394 {
395 return clickArchitectures.keys();
396@@ -158,7 +172,13 @@
397 {
398 switch(abi.architecture()) {
399 case ProjectExplorer::Abi::ArmArchitecture:
400- return QLatin1String("arm-linux-gnueabihf");
401+ switch(abi.wordWidth())
402+ {
403+ case 32:
404+ return QLatin1String("arm-linux-gnueabihf");
405+ case 64:
406+ return QLatin1String("aarch64-linux-gnu");
407+ }
408 break;
409 case ProjectExplorer::Abi::X86Architecture:
410 switch(abi.wordWidth())
411
412=== modified file 'src/ubuntu/clicktoolchain.h'
413--- src/ubuntu/clicktoolchain.h 2016-09-22 13:17:48 +0000
414+++ src/ubuntu/clicktoolchain.h 2016-11-16 10:23:00 +0000
415@@ -50,6 +50,7 @@
416 const UbuntuClickTool::Target &clickTarget () const;
417
418 static ProjectExplorer::Abi architectureNameToAbi ( const QString &arch );
419+ static QString abiToArchitectureName ( const ProjectExplorer::Abi &abi );
420 static QList<QString> supportedArchitectures ();
421
422 QString remoteCompilerCommand () const;
423
424=== added directory 'src/ubuntu/snap/project'
425=== added file 'src/ubuntu/snap/project/snapcraftbuildconfiguration.cpp'
426--- src/ubuntu/snap/project/snapcraftbuildconfiguration.cpp 1970-01-01 00:00:00 +0000
427+++ src/ubuntu/snap/project/snapcraftbuildconfiguration.cpp 2016-11-16 10:23:00 +0000
428@@ -0,0 +1,44 @@
429+#include "snapcraftbuildconfiguration.h"
430+
431+#include <ubuntu/ubuntuconstants.h>
432+#include <QDebug>
433+
434+namespace Ubuntu {
435+namespace Internal {
436+
437+SnapcraftBuildConfiguration::SnapcraftBuildConfiguration(ProjectExplorer::Target *target)
438+ : ProjectExplorer::BuildConfiguration(target, Constants::SNAPCRAFT_BUILDCONFIGURATION_ID)
439+{
440+
441+}
442+
443+SnapcraftBuildConfiguration::SnapcraftBuildConfiguration(ProjectExplorer::Target *target, ProjectExplorer::BuildConfiguration *source)
444+ : ProjectExplorer::BuildConfiguration(target, source)
445+{
446+
447+}
448+
449+bool SnapcraftBuildConfiguration::fromMap(const QVariantMap &map)
450+{
451+ return ProjectExplorer::BuildConfiguration::fromMap(map);
452+}
453+
454+QVariantMap SnapcraftBuildConfiguration::toMap() const
455+{
456+ QVariantMap data = ProjectExplorer::BuildConfiguration::toMap();
457+ qDebug()<<"Storing ID: "<<ProjectExplorer::idFromMap(data);
458+ return data;
459+}
460+
461+ProjectExplorer::NamedWidget *SnapcraftBuildConfiguration::createConfigWidget()
462+{
463+ return nullptr;
464+}
465+
466+ProjectExplorer::BuildConfiguration::BuildType SnapcraftBuildConfiguration::buildType() const
467+{
468+ return ProjectExplorer::BuildConfiguration::Unknown;
469+}
470+
471+} // namespace Internal
472+} // namespace Ubuntu
473
474=== added file 'src/ubuntu/snap/project/snapcraftbuildconfiguration.h'
475--- src/ubuntu/snap/project/snapcraftbuildconfiguration.h 1970-01-01 00:00:00 +0000
476+++ src/ubuntu/snap/project/snapcraftbuildconfiguration.h 2016-11-16 10:23:00 +0000
477@@ -0,0 +1,33 @@
478+#ifndef UBUNTU_INTERNAL_SNAPCRAFTBUILDCONFIGURATION_H
479+#define UBUNTU_INTERNAL_SNAPCRAFTBUILDCONFIGURATION_H
480+
481+#include <projectexplorer/buildconfiguration.h>
482+
483+namespace Ubuntu {
484+namespace Internal {
485+
486+class SnapcraftBuildConfigurationFactory;
487+
488+class SnapcraftBuildConfiguration : public ProjectExplorer::BuildConfiguration
489+{
490+ Q_OBJECT
491+
492+public:
493+ friend class SnapcraftBuildConfigurationFactory;
494+ // ProjectConfiguration interface
495+ virtual bool fromMap(const QVariantMap &map) override;
496+ virtual QVariantMap toMap() const override;
497+
498+ // BuildConfiguration interface
499+ virtual ProjectExplorer::NamedWidget *createConfigWidget() override;
500+ virtual BuildType buildType() const override;
501+
502+protected:
503+ SnapcraftBuildConfiguration(ProjectExplorer::Target *target);
504+ SnapcraftBuildConfiguration(ProjectExplorer::Target *target, BuildConfiguration *source);
505+};
506+
507+} // namespace Internal
508+} // namespace Ubuntu
509+
510+#endif // UBUNTU_INTERNAL_SNAPCRAFTBUILDCONFIGURATION_H
511
512=== added file 'src/ubuntu/snap/project/snapcraftbuildconfigurationfactory.cpp'
513--- src/ubuntu/snap/project/snapcraftbuildconfigurationfactory.cpp 1970-01-01 00:00:00 +0000
514+++ src/ubuntu/snap/project/snapcraftbuildconfigurationfactory.cpp 2016-11-16 10:23:00 +0000
515@@ -0,0 +1,154 @@
516+#include "snapcraftbuildconfigurationfactory.h"
517+
518+#include "snapcraftproject.h"
519+#include "snapcraftbuildconfiguration.h"
520+#include "snapcraftrsyncstep.h"
521+#include "snapcraftstep.h"
522+#include <ubuntu/ubuntuconstants.h>
523+
524+#include <projectexplorer/target.h>
525+#include <projectexplorer/kit.h>
526+#include <projectexplorer/projectmacroexpander.h>
527+#include <projectexplorer/projectexplorerconstants.h>
528+#include <projectexplorer/buildsteplist.h>
529+#include <projectexplorer/kitinformation.h>
530+
531+#include <coreplugin/documentmanager.h>
532+#include <utils/mimetypes/mimedatabase.h>
533+#include <utils/qtcassert.h>
534+
535+namespace Ubuntu {
536+namespace Internal {
537+
538+SnapcraftBuildInfo::SnapcraftBuildInfo(const SnapcraftBuildConfigurationFactory *factory)
539+ :ProjectExplorer::BuildInfo(factory)
540+{
541+
542+}
543+
544+SnapcraftBuildConfigurationFactory::SnapcraftBuildConfigurationFactory()
545+{
546+
547+}
548+
549+QList<ProjectExplorer::BuildInfo *> SnapcraftBuildConfigurationFactory::availableBuilds(const ProjectExplorer::Target *parent) const
550+{
551+ if (qobject_cast<SnapcraftProject *>(parent->project()))
552+ return {};
553+
554+ //restrict this to local devices type kits for now
555+ if (ProjectExplorer::DeviceKitInformation::deviceId(parent->kit()) != ProjectExplorer::Constants::DESKTOP_DEVICE_ID)
556+ return {};
557+
558+ QList<ProjectExplorer::BuildInfo *> infoList;
559+ ProjectExplorer::BuildInfo *info = createBuildInfo(parent->kit(), parent->project()->projectFilePath().toString());
560+ if (info)
561+ infoList << info;
562+
563+ return infoList;
564+}
565+
566+int SnapcraftBuildConfigurationFactory::priority(const ProjectExplorer::Target *) const
567+{
568+ return 0;
569+}
570+
571+int SnapcraftBuildConfigurationFactory::priority(const ProjectExplorer::Kit *, const QString &) const
572+{
573+ return 0;
574+}
575+
576+QList<ProjectExplorer::BuildInfo *> SnapcraftBuildConfigurationFactory::availableSetups(const ProjectExplorer::Kit *k, const QString &projectPath) const
577+{
578+ Utils::MimeDatabase db;
579+
580+ //restrict this to local devices type kits for now
581+ if (ProjectExplorer::DeviceKitInformation::deviceId(k) != ProjectExplorer::Constants::DESKTOP_DEVICE_ID)
582+ return {};
583+
584+ auto mimeType = db.mimeTypeForFile(projectPath);
585+ if (!mimeType.matchesName(Constants::SNAPCRAFT_PROJECT_MIMETYPE))
586+ return {};
587+
588+ QList<ProjectExplorer::BuildInfo *> infoList;
589+ ProjectExplorer::BuildInfo *info = createBuildInfo(k, projectPath);
590+ if (info)
591+ infoList << info;
592+
593+ return infoList;
594+}
595+
596+ProjectExplorer::BuildConfiguration *SnapcraftBuildConfigurationFactory::create(ProjectExplorer::Target *parent, const ProjectExplorer::BuildInfo *info) const
597+{
598+ SnapcraftBuildConfiguration *conf = new SnapcraftBuildConfiguration(parent);
599+
600+ conf->setDisplayName(info->displayName);
601+ conf->setBuildDirectory(info->buildDirectory);
602+
603+ ProjectExplorer::BuildStepList *bs = conf->stepList(ProjectExplorer::Constants::BUILDSTEPS_BUILD);
604+ bs->insertStep(0, new SnapcraftRsyncStep(bs));
605+ bs->insertStep(1, new SnapcraftStep(bs));
606+
607+ return conf;
608+}
609+
610+bool SnapcraftBuildConfigurationFactory::canRestore(const ProjectExplorer::Target *, const QVariantMap &map) const
611+{
612+ return (ProjectExplorer::idFromMap(map) == Constants::SNAPCRAFT_BUILDCONFIGURATION_ID);
613+}
614+
615+ProjectExplorer::BuildConfiguration *SnapcraftBuildConfigurationFactory::restore(ProjectExplorer::Target *parent, const QVariantMap &map)
616+{
617+ QTC_ASSERT(parent, return nullptr);
618+ SnapcraftBuildConfiguration *conf = new SnapcraftBuildConfiguration(parent);
619+ if (conf->fromMap(map))
620+ return conf;
621+
622+ delete conf;
623+ return nullptr;
624+}
625+
626+bool SnapcraftBuildConfigurationFactory::canClone(const ProjectExplorer::Target *parent, ProjectExplorer::BuildConfiguration *product) const
627+{
628+ QTC_ASSERT(parent, return false);
629+ QTC_ASSERT(product, return false);
630+ return (product->id() == Constants::SNAPCRAFT_BUILDCONFIGURATION_ID);
631+}
632+
633+ProjectExplorer::BuildConfiguration *SnapcraftBuildConfigurationFactory::clone(ProjectExplorer::Target *parent, ProjectExplorer::BuildConfiguration *product)
634+{
635+ QTC_ASSERT(parent, return nullptr);
636+ QTC_ASSERT(product, return nullptr);
637+
638+ SnapcraftBuildConfiguration *conf = new SnapcraftBuildConfiguration(parent, product);
639+ return conf;
640+}
641+
642+ProjectExplorer::BuildInfo *SnapcraftBuildConfigurationFactory::createBuildInfo(const ProjectExplorer::Kit *k, const QString &projectPath) const
643+{
644+ SnapcraftBuildInfo *build = new SnapcraftBuildInfo(this);
645+ build->buildType = ProjectExplorer::BuildConfiguration::Release;
646+ build->typeName = tr("Build");
647+ build->kitId = k->id();
648+ build->displayName = ProjectExplorer::BuildConfiguration::buildTypeName(build->buildType);
649+ build->buildDirectory = shadowBuildDirectory(k, projectPath);
650+ return {build};
651+}
652+
653+Utils::FileName SnapcraftBuildConfigurationFactory::shadowBuildDirectory(const ProjectExplorer::Kit *k, const QString &projectPath) const
654+{
655+
656+ Utils::FileName projectDir = ProjectExplorer::Project::projectDirectory(Utils::FileName::fromString(projectPath));
657+ const QString projectName = projectDir.fileName();
658+
659+ ProjectExplorer::ProjectMacroExpander expander(projectPath, projectName,
660+ k, tr("build"),
661+ ProjectExplorer::BuildConfiguration::Release);
662+
663+ QString buildPath = expander.expand(Core::DocumentManager::buildDirectory());
664+ return Utils::FileName::fromString(QDir::cleanPath(QDir(projectDir.toString()).absoluteFilePath(buildPath)));
665+}
666+
667+
668+} // namespace Internal
669+} // namespace Ubuntu
670
671=== added file 'src/ubuntu/snap/project/snapcraftbuildconfigurationfactory.h'
672--- src/ubuntu/snap/project/snapcraftbuildconfigurationfactory.h 1970-01-01 00:00:00 +0000
673+++ src/ubuntu/snap/project/snapcraftbuildconfigurationfactory.h 2016-11-16 10:23:00 +0000
674@@ -0,0 +1,44 @@
675+#ifndef UBUNTU_INTERNAL_SNAPCRAFTBUILDCONFIGURATIONFACTORY_H
676+#define UBUNTU_INTERNAL_SNAPCRAFTBUILDCONFIGURATIONFACTORY_H
677+
678+#include <projectexplorer/buildconfiguration.h>
679+#include <projectexplorer/buildinfo.h>
680+
681+namespace Ubuntu {
682+namespace Internal {
683+
684+class SnapcraftBuildConfigurationFactory;
685+
686+class SnapcraftBuildInfo : public ProjectExplorer::BuildInfo
687+{
688+public:
689+ SnapcraftBuildInfo(const SnapcraftBuildConfigurationFactory *factory);
690+};
691+
692+class SnapcraftBuildConfigurationFactory : public ProjectExplorer::IBuildConfigurationFactory
693+{
694+public:
695+ SnapcraftBuildConfigurationFactory();
696+
697+ // IBuildConfigurationFactory interface
698+ virtual QList<ProjectExplorer::BuildInfo *> availableBuilds(const ProjectExplorer::Target *parent) const override;
699+
700+ virtual int priority(const ProjectExplorer::Target *parent) const override;
701+ virtual int priority(const ProjectExplorer::Kit *k, const QString &projectPath) const override;
702+
703+ virtual QList<ProjectExplorer::BuildInfo *> availableSetups(const ProjectExplorer::Kit *k, const QString &projectPath) const override;
704+ virtual ProjectExplorer::BuildConfiguration *create(ProjectExplorer::Target *parent, const ProjectExplorer::BuildInfo *info) const override;
705+ virtual bool canRestore(const ProjectExplorer::Target *parent, const QVariantMap &map) const override;
706+ virtual ProjectExplorer::BuildConfiguration *restore(ProjectExplorer::Target *parent, const QVariantMap &map) override;
707+ virtual bool canClone(const ProjectExplorer::Target *parent, ProjectExplorer::BuildConfiguration *product) const override;
708+ virtual ProjectExplorer::BuildConfiguration *clone(ProjectExplorer::Target *parent, ProjectExplorer::BuildConfiguration *product) override;
709+
710+private:
711+ ProjectExplorer::BuildInfo *createBuildInfo (const ProjectExplorer::Kit *k, const QString &projectPath) const;
712+ Utils::FileName shadowBuildDirectory(const ProjectExplorer::Kit *k, const QString &projectPath) const;
713+};
714+
715+} // namespace Internal
716+} // namespace Ubuntu
717+
718+#endif // UBUNTU_INTERNAL_SNAPCRAFTBUILDCONFIGURATIONFACTORY_H
719
720=== added file 'src/ubuntu/snap/project/snapcraftbuildstepfactory.cpp'
721--- src/ubuntu/snap/project/snapcraftbuildstepfactory.cpp 1970-01-01 00:00:00 +0000
722+++ src/ubuntu/snap/project/snapcraftbuildstepfactory.cpp 2016-11-16 10:23:00 +0000
723@@ -0,0 +1,65 @@
724+#include "snapcraftbuildstepfactory.h"
725+#include "snapcraftrsyncstep.h"
726+#include "snapcraftstep.h"
727+#include "snapcraftproject.h"
728+
729+#include <ubuntu/ubuntuconstants.h>
730+
731+#include <projectexplorer/projectexplorerconstants.h>
732+#include <projectexplorer/buildsteplist.h>
733+#include <projectexplorer/target.h>
734+#include <utils/algorithm.h>
735+
736+namespace Ubuntu {
737+namespace Internal {
738+
739+SnapcraftBuildStepFactory::SnapcraftBuildStepFactory(QObject *parent) : ProjectExplorer::IBuildStepFactory (parent)
740+{
741+
742+}
743+
744+QList<ProjectExplorer::BuildStepInfo> SnapcraftBuildStepFactory::availableSteps(ProjectExplorer::BuildStepList *parent) const
745+{
746+ if (parent->id() != ProjectExplorer::Constants::BUILDSTEPS_BUILD)
747+ return {};
748+
749+ if (!parent->target() || !qobject_cast<SnapcraftProject *>(parent->target()->project()))
750+ return {};
751+
752+ return {
753+ ProjectExplorer::BuildStepInfo(Constants::SNAPCRAFT_RSYNCBUILSSTEP_ID, tr("Prepare build")),
754+ ProjectExplorer::BuildStepInfo(Constants::SNAPCRAFT_BUILDSTEP_ID, tr("Snapcraft"))
755+ };
756+}
757+
758+ProjectExplorer::BuildStep *SnapcraftBuildStepFactory::create(ProjectExplorer::BuildStepList *parent, Core::Id id)
759+{
760+ if (!Utils::contains(availableSteps(parent), [&id](const ProjectExplorer::BuildStepInfo &step){return id == step.id;}))
761+ return nullptr;
762+
763+ if (id == Constants::SNAPCRAFT_RSYNCBUILSSTEP_ID) {
764+ return new SnapcraftRsyncStep(parent);
765+ } else if (id == Constants::SNAPCRAFT_BUILDSTEP_ID) {
766+ return new SnapcraftStep(parent);
767+ }
768+
769+ return nullptr;
770+}
771+
772+ProjectExplorer::BuildStep *SnapcraftBuildStepFactory::clone(ProjectExplorer::BuildStepList *parent, ProjectExplorer::BuildStep *product)
773+{
774+ Core::Id id = product->id();
775+ if (!Utils::contains(availableSteps(parent), [&id](const ProjectExplorer::BuildStepInfo &step){return id == step.id;}))
776+ return nullptr;
777+
778+ if (id == Constants::SNAPCRAFT_RSYNCBUILSSTEP_ID) {
779+ return new SnapcraftRsyncStep(parent, static_cast<SnapcraftRsyncStep *>(product));
780+ } else if (id == Constants::SNAPCRAFT_BUILDSTEP_ID) {
781+ return new SnapcraftStep(parent, static_cast<SnapcraftStep *>(product));
782+ }
783+
784+ return nullptr;
785+}
786+
787+} // namespace Internal
788+} // namespace Ubuntu
789
790=== added file 'src/ubuntu/snap/project/snapcraftbuildstepfactory.h'
791--- src/ubuntu/snap/project/snapcraftbuildstepfactory.h 1970-01-01 00:00:00 +0000
792+++ src/ubuntu/snap/project/snapcraftbuildstepfactory.h 2016-11-16 10:23:00 +0000
793@@ -0,0 +1,25 @@
794+#ifndef UBUNTU_INTERNAL_SNAPCRAFTBUILDSTEPFACTORY_H
795+#define UBUNTU_INTERNAL_SNAPCRAFTBUILDSTEPFACTORY_H
796+
797+#include <projectexplorer/buildstep.h>
798+
799+namespace Ubuntu {
800+namespace Internal {
801+
802+class SnapcraftBuildStepFactory : public ProjectExplorer::IBuildStepFactory
803+{
804+ Q_OBJECT
805+public:
806+ SnapcraftBuildStepFactory(QObject *parent = nullptr);
807+
808+ // IBuildStepFactory interface
809+public:
810+ virtual QList<ProjectExplorer::BuildStepInfo> availableSteps(ProjectExplorer::BuildStepList *parent) const override;
811+ virtual ProjectExplorer::BuildStep *create(ProjectExplorer::BuildStepList *parent, Core::Id id) override;
812+ virtual ProjectExplorer::BuildStep *clone(ProjectExplorer::BuildStepList *parent, ProjectExplorer::BuildStep *product) override;
813+};
814+
815+} // namespace Internal
816+} // namespace Ubuntu
817+
818+#endif // UBUNTU_INTERNAL_SNAPCRAFTBUILDSTEPFACTORY_H
819
820=== added file 'src/ubuntu/snap/project/snapcraftproject.cpp'
821--- src/ubuntu/snap/project/snapcraftproject.cpp 1970-01-01 00:00:00 +0000
822+++ src/ubuntu/snap/project/snapcraftproject.cpp 2016-11-16 10:23:00 +0000
823@@ -0,0 +1,214 @@
824+/*
825+ * Copyright 2016 Canonical Ltd.
826+ *
827+ * This program is free software; you can redistribute it and/or modify
828+ * it under the terms of the GNU Lesser General Public License as published by
829+ * the Free Software Foundation; version 2.1.
830+ *
831+ * This program is distributed in the hope that it will be useful,
832+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
833+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
834+ * GNU Lesser General Public License for more details.
835+ *
836+ * You should have received a copy of the GNU Lesser General Public License
837+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
838+ *
839+ * Author: Benjamin Zeller <benjamin.zeller@canonical.com>
840+ */
841+
842+#include "snapcraftproject.h"
843+#include "snapcraftprojectnode.h"
844+
845+#include <coreplugin/modemanager.h>
846+#include <coreplugin/icontext.h>
847+#include <coreplugin/documentmanager.h>
848+#include <projectexplorer/projectexplorerconstants.h>
849+#include <projectexplorer/kitinformation.h>
850+#include <projectexplorer/toolchain.h>
851+#include <projectexplorer/projectmacroexpander.h>
852+#include <projectexplorer/projectexplorerconstants.h>
853+#include <projectexplorer/taskhub.h>
854+#include <qmljs/qmljssimplereader.h>
855+#include <qtsupport/qtkitinformation.h>
856+#include <qtsupport/qtsupportconstants.h>
857+
858+#pragma GCC diagnostic push
859+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
860+#include <yaml-cpp/yaml.h>
861+#pragma GCC diagnostic pop
862+
863+
864+using namespace Ubuntu;
865+using namespace Ubuntu::Internal;
866+
867+enum {
868+ debug = 0
869+};
870+
871+SnapcraftProject::SnapcraftProject(SnapcraftProjectManager *manager, const Utils::FileName &fileName)
872+ : m_manager(manager),
873+ m_fileName(fileName),
874+ m_watcher(new QFileSystemWatcher)
875+{
876+
877+ setId(Constants::SNAPCRAFT_PROJECT_ID);
878+
879+ setProjectContext(Core::Context(Constants::SNAPCRAFT_PROJECT_PROJECTCONTEXT));
880+
881+
882+ m_file = QPointer<SnapcraftProjectFile>(new SnapcraftProjectFile());
883+ Core::DocumentManager::addDocument(m_file.data(), true);
884+ setDocument(m_file.data());
885+
886+ m_file->setFilePath(fileName);
887+
888+ m_rootNode = QSharedPointer<SnapcraftProjectNode>(new SnapcraftProjectNode(this, fileName, &m_watcher));
889+
890+ ProjectExplorer::FileNode *projectFileNode = new ProjectExplorer::FileNode(fileName, ProjectExplorer::ProjectFileType, false);
891+ m_rootNode->addFileNodes({projectFileNode});
892+
893+ connect(m_file.data(), &SnapcraftProjectFile::changed, this, &SnapcraftProject::asyncUpdate);
894+
895+ //we show magic directories that are not listed in the snapcraft.yaml file, therefore we need to watch the directory
896+ //if one of those is changed or removed
897+ m_watcher.addPath(projectDirectory().toFileInfo().absoluteFilePath());
898+ connect(&m_watcher, &QFileSystemWatcher::directoryChanged, this, &SnapcraftProject::maybeUpdate);
899+
900+ QMetaObject::invokeMethod(this, "asyncUpdate", Qt::QueuedConnection);
901+}
902+
903+QString SnapcraftProject::displayName() const {
904+ return m_rootNode->displayName();
905+}
906+
907+ProjectExplorer::IProjectManager *SnapcraftProject::projectManager() const {
908+ return m_manager;
909+}
910+
911+ProjectExplorer::ProjectNode *SnapcraftProject::rootProjectNode() const {
912+ return m_rootNode.data();
913+}
914+
915+QStringList SnapcraftProject::files(FilesMode) const {
916+ QStringList files;
917+ //enumChild(projectDir(), files);
918+ return files;
919+}
920+
921+bool SnapcraftProject::supportsKit(ProjectExplorer::Kit *, QString *) const
922+{
923+#if 0
924+ UbuntuKitMatcher matcher;
925+ if (!matcher.matches(k)) {
926+ if(errorMessage)
927+ *errorMessage = tr("Only Desktop and Ubuntu Kits are supported");
928+ return false;
929+ }
930+#endif
931+ return true;
932+}
933+
934+bool SnapcraftProject::needsConfiguration() const
935+{
936+ return targets().size() == 0;
937+}
938+
939+bool SnapcraftProject::requiresTargetPanel() const
940+{
941+ return true;
942+}
943+
944+QString SnapcraftProject::shadowBuildDirectory(const QString &proFilePath
945+ , const ProjectExplorer::Kit *k
946+ , const QString &suffix
947+ , const ProjectExplorer::BuildConfiguration::BuildType buildType)
948+{
949+ if (proFilePath.isEmpty())
950+ return QString();
951+
952+ QFileInfo info(proFilePath);
953+
954+ QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(k);
955+ if (version)
956+ return info.absolutePath();
957+
958+ const QString projectName = QFileInfo(proFilePath).completeBaseName();
959+ ProjectExplorer::ProjectMacroExpander expander(proFilePath, projectName, k, suffix, buildType);
960+ QDir projectDir = QDir(projectDirectory(Utils::FileName::fromString(proFilePath)).toString());
961+ QString buildPath = expander.expand(Core::DocumentManager::buildDirectory());
962+ return QDir::cleanPath(projectDir.absoluteFilePath(buildPath));
963+}
964+
965+void SnapcraftProject::asyncUpdate()
966+{
967+ if(debug) qDebug()<<"Syncing from yaml";
968+
969+ QString oldDisplayName = displayName();
970+
971+ try {
972+ YAML::Node yaml = YAML::LoadFile(m_fileName.toString().toStdString());
973+ if (!m_rootNode->syncFromYAMLNode(yaml)) {
974+ ProjectExplorer::TaskHub::addTask(ProjectExplorer::Task::Error,
975+ QString::fromLatin1("Error while parsing snapcraft.yaml: file is invalid"),
976+ ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM,
977+ projectFilePath());
978+ }
979+
980+ QStringList commandList;
981+
982+ try {
983+ YAML::Node commands = yaml["apps"];
984+ if (!commands.IsMap()) {
985+ ProjectExplorer::TaskHub::addTask(ProjectExplorer::Task::Error,
986+ QString::fromLatin1("Error while parsing snapcraft.yaml: apps is not a map"),
987+ ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM,
988+ projectFilePath());
989+ } else {
990+ for (auto it = commands.begin(); it != commands.end(); ++it) {
991+ if(!it->second.IsMap() || it->second["daemon"])
992+ continue;
993+
994+ commandList << QString::fromStdString(it->first.as<std::string>());
995+ }
996+ }
997+
998+ if(yaml["version"]) {
999+ QString snapVer = QString::fromStdString(yaml["version"].as<std::string>());
1000+ if (snapVer != m_snapVersion) {
1001+ if(debug) qDebug()<<"Snap version is"<<snapVer;
1002+ m_snapVersion = snapVer;
1003+ emit snapVersionChanged();
1004+ }
1005+ }
1006+
1007+ } catch (const YAML::Exception &e) {
1008+ ProjectExplorer::TaskHub::addTask(ProjectExplorer::Task::Error,
1009+ QString::fromLatin1("Error while parsing the command list: %1").arg(QString::fromLatin1(e.what())),
1010+ ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM,
1011+ projectFilePath(),
1012+ e.mark.line);
1013+ }
1014+
1015+ if (m_commands != commandList) {
1016+ m_commands = commandList;
1017+ emit commandListChanged(m_commands);
1018+ }
1019+
1020+ } catch (const YAML::Exception &e) {
1021+ ProjectExplorer::TaskHub::addTask(ProjectExplorer::Task::Error,
1022+ QString::fromLatin1("Error while parsing the project file: %1").arg(QString::fromLatin1(e.what())),
1023+ ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM,
1024+ projectFilePath(),
1025+ e.mark.line);
1026+ }
1027+
1028+ if (oldDisplayName != displayName())
1029+ emit displayNameChanged();
1030+}
1031+
1032+void SnapcraftProject::maybeUpdate(const QString &pathChanged)
1033+{
1034+ if (QFileInfo(pathChanged) == projectDirectory().toFileInfo()) {
1035+ asyncUpdate();
1036+ }
1037+}
1038
1039=== added file 'src/ubuntu/snap/project/snapcraftproject.h'
1040--- src/ubuntu/snap/project/snapcraftproject.h 1970-01-01 00:00:00 +0000
1041+++ src/ubuntu/snap/project/snapcraftproject.h 2016-11-16 10:23:00 +0000
1042@@ -0,0 +1,102 @@
1043+/*
1044+ * Copyright 2016 Canonical Ltd.
1045+ *
1046+ * This program is free software; you can redistribute it and/or modify
1047+ * it under the terms of the GNU Lesser General Public License as published by
1048+ * the Free Software Foundation; version 2.1.
1049+ *
1050+ * This program is distributed in the hope that it will be useful,
1051+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1052+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1053+ * GNU Lesser General Public License for more details.
1054+ *
1055+ * You should have received a copy of the GNU Lesser General Public License
1056+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1057+ *
1058+ * Author: Benjamin Zeller <benjamin.zeller@canonical.com>
1059+ */
1060+
1061+#ifndef SNAPCRAFTPROJECT_H
1062+#define SNAPCRAFTPROJECT_H
1063+
1064+#include "snapcraftprojectmanager.h"
1065+#include "snapcraftprojectfile.h"
1066+
1067+#include <ubuntu/ubuntuconstants.h>
1068+
1069+#include <projectexplorer/buildconfiguration.h>
1070+#include <projectexplorer/projectnodes.h>
1071+#include <projectexplorer/project.h>
1072+
1073+#include <QPointer>
1074+#include <QFileSystemWatcher>
1075+
1076+#include <yaml-cpp/node/node.h>
1077+
1078+namespace Ubuntu {
1079+namespace Internal {
1080+
1081+class UbuntuProjectManager;
1082+class SnapcraftProjectNode;
1083+
1084+class SnapcraftProject : public ProjectExplorer::Project
1085+{
1086+ Q_OBJECT
1087+
1088+public:
1089+ SnapcraftProject(SnapcraftProjectManager *manager, const Utils::FileName &fileName);
1090+
1091+ QString displayName() const override;
1092+ QString snapVersion() const{
1093+ return m_snapVersion;
1094+ }
1095+
1096+ ProjectExplorer::IProjectManager *projectManager() const override;
1097+
1098+ ProjectExplorer::ProjectNode *rootProjectNode() const override;
1099+ QStringList files(FilesMode fileMode) const override;
1100+
1101+ QDir projectDir() const {
1102+ return projectDirectory().toString();
1103+ }
1104+
1105+ QString filesFileName() const {
1106+ return m_fileName.toString();
1107+ }
1108+
1109+ QStringList commands () const {
1110+ return m_commands;
1111+ }
1112+
1113+ // Project interface
1114+ bool supportsKit(ProjectExplorer::Kit *k, QString *errorMessage) const override;
1115+ bool needsConfiguration() const override;
1116+ bool requiresTargetPanel() const override;
1117+
1118+ static QString shadowBuildDirectory(const QString &proFilePath, const ProjectExplorer::Kit *k,
1119+ const QString &suffix = QString(),
1120+ const ProjectExplorer::BuildConfiguration::BuildType buildType = ProjectExplorer::BuildConfiguration::Unknown);
1121+
1122+protected slots:
1123+ void asyncUpdate ();
1124+ void maybeUpdate (const QString &pathChanged);
1125+
1126+signals:
1127+ void commandListChanged (const QStringList &commands);
1128+ void snapVersionChanged ();
1129+
1130+private:
1131+ SnapcraftProjectManager *m_manager;
1132+ QString m_projectName;
1133+ QStringList m_commands;
1134+ QString m_snapVersion;
1135+ QPointer<SnapcraftProjectFile> m_file;
1136+
1137+ Utils::FileName m_fileName;
1138+ QSharedPointer<SnapcraftProjectNode> m_rootNode;
1139+ QFileSystemWatcher m_watcher;
1140+};
1141+}
1142+}
1143+
1144+#endif // SNAPCRAFTPROJECT_H
1145
1146=== added file 'src/ubuntu/snap/project/snapcraftprojectfile.cpp'
1147--- src/ubuntu/snap/project/snapcraftprojectfile.cpp 1970-01-01 00:00:00 +0000
1148+++ src/ubuntu/snap/project/snapcraftprojectfile.cpp 2016-11-16 10:23:00 +0000
1149@@ -0,0 +1,42 @@
1150+/*
1151+ * Copyright 2016 Canonical Ltd.
1152+ *
1153+ * This program is free software; you can redistribute it and/or modify
1154+ * it under the terms of the GNU Lesser General Public License as published by
1155+ * the Free Software Foundation; version 2.1.
1156+ *
1157+ * This program is distributed in the hope that it will be useful,
1158+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1159+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1160+ * GNU Lesser General Public License for more details.
1161+ *
1162+ * You should have received a copy of the GNU Lesser General Public License
1163+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1164+ *
1165+ * Author: Benjamin Zeller <benjamin.zeller@canonical.com>
1166+ */
1167+
1168+#include "snapcraftprojectfile.h"
1169+
1170+using namespace Ubuntu::Internal;
1171+
1172+SnapcraftProjectFile::SnapcraftProjectFile(Core::Id id)
1173+ : TextEditor::TextDocument(id)
1174+{
1175+}
1176+
1177+Core::IDocument::ReloadBehavior SnapcraftProjectFile::reloadBehavior(Core::IDocument::ChangeTrigger state, Core::IDocument::ChangeType type) const
1178+{
1179+ Q_UNUSED(state)
1180+ Q_UNUSED(type)
1181+ return BehaviorSilent;
1182+}
1183+
1184+bool SnapcraftProjectFile::reload(QString *errorString, Core::IDocument::ReloadFlag flag, Core::IDocument::ChangeType type)
1185+{
1186+ if (type != TypePermissions) {
1187+ emit changed();
1188+ }
1189+
1190+ return TextDocument::reload(errorString, flag, type);
1191+}
1192
1193=== added file 'src/ubuntu/snap/project/snapcraftprojectfile.h'
1194--- src/ubuntu/snap/project/snapcraftprojectfile.h 1970-01-01 00:00:00 +0000
1195+++ src/ubuntu/snap/project/snapcraftprojectfile.h 2016-11-16 10:23:00 +0000
1196@@ -0,0 +1,48 @@
1197+/*
1198+ * Copyright 2016 Canonical Ltd.
1199+ *
1200+ * This program is free software; you can redistribute it and/or modify
1201+ * it under the terms of the GNU Lesser General Public License as published by
1202+ * the Free Software Foundation; version 2.1.
1203+ *
1204+ * This program is distributed in the hope that it will be useful,
1205+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1206+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1207+ * GNU Lesser General Public License for more details.
1208+ *
1209+ * You should have received a copy of the GNU Lesser General Public License
1210+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1211+ *
1212+ * Author: Benjamin Zeller <benjamin.zeller@canonical.com>
1213+ */
1214+
1215+#ifndef SNAPCRAFTPROJECTFILE_H
1216+#define SNAPCRAFTPROJECTFILE_H
1217+
1218+#include <QObject>
1219+#include <ubuntu/ubuntuconstants.h>
1220+
1221+#include <texteditor/textdocument.h>
1222+#include <utils/fileutils.h>
1223+
1224+namespace Ubuntu {
1225+namespace Internal {
1226+class SnapcraftProject;
1227+class SnapcraftProjectFile : public TextEditor::TextDocument
1228+{
1229+ Q_OBJECT
1230+public:
1231+ SnapcraftProjectFile(Core::Id id = Core::Id());
1232+
1233+ // IDocument interface
1234+ virtual ReloadBehavior reloadBehavior(ChangeTrigger state, ChangeType type) const override;
1235+ virtual bool reload(QString *errorString, ReloadFlag flag, ChangeType type) override;
1236+
1237+signals:
1238+ void changed ();
1239+
1240+};
1241+}
1242+}
1243+
1244+#endif // SNAPCRAFTPROJECTFILE_H
1245
1246=== added file 'src/ubuntu/snap/project/snapcraftprojectmanager.cpp'
1247--- src/ubuntu/snap/project/snapcraftprojectmanager.cpp 1970-01-01 00:00:00 +0000
1248+++ src/ubuntu/snap/project/snapcraftprojectmanager.cpp 2016-11-16 10:23:00 +0000
1249@@ -0,0 +1,64 @@
1250+/*
1251+ * Copyright 2016 Canonical Ltd.
1252+ *
1253+ * This program is free software; you can redistribute it and/or modify
1254+ * it under the terms of the GNU Lesser General Public License as published by
1255+ * the Free Software Foundation; version 2.1.
1256+ *
1257+ * This program is distributed in the hope that it will be useful,
1258+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1259+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1260+ * GNU Lesser General Public License for more details.
1261+ *
1262+ * You should have received a copy of the GNU Lesser General Public License
1263+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1264+ *
1265+ * Author: Benjamin Zeller <benjamin.zeller@canonical.com>
1266+ */
1267+
1268+#include "snapcraftprojectmanager.h"
1269+#include "snapcraftproject.h"
1270+
1271+#include <ubuntu/ubuntuconstants.h>
1272+
1273+#include <projectexplorer/session.h>
1274+#include <coreplugin/idocument.h>
1275+#include <utils/fileutils.h>
1276+
1277+#include <QFileInfo>
1278+
1279+
1280+namespace Ubuntu {
1281+namespace Internal {
1282+
1283+SnapcraftProjectManager::SnapcraftProjectManager()
1284+{
1285+
1286+}
1287+
1288+QString SnapcraftProjectManager::mimeType() const
1289+{
1290+ return QLatin1String(Constants::SNAPCRAFT_PROJECT_MIMETYPE);
1291+}
1292+
1293+ProjectExplorer::Project *SnapcraftProjectManager::openProject(const QString &fileName, QString *errorString)
1294+{
1295+ QFileInfo fileInfo(fileName);
1296+
1297+ foreach (ProjectExplorer::Project *pi, ProjectExplorer::SessionManager::projects()) {
1298+ if (fileName == pi->document()->filePath().toString()) {
1299+ if (errorString)
1300+ *errorString = tr("Failed opening project '%1': Project already open") .arg(QDir::toNativeSeparators(fileName));
1301+ return 0;
1302+ }
1303+ }
1304+
1305+ if (fileInfo.isFile())
1306+ return new SnapcraftProject(this, Utils::FileName(fileInfo));
1307+
1308+ *errorString = tr("Failed opening project '%1': Project file is not a file").arg(QDir::toNativeSeparators(fileName));
1309+ return 0;
1310+}
1311+
1312+} // namespace Internal
1313+} // namespace Ubuntu
1314
1315=== added file 'src/ubuntu/snap/project/snapcraftprojectmanager.h'
1316--- src/ubuntu/snap/project/snapcraftprojectmanager.h 1970-01-01 00:00:00 +0000
1317+++ src/ubuntu/snap/project/snapcraftprojectmanager.h 2016-11-16 10:23:00 +0000
1318@@ -0,0 +1,40 @@
1319+/*
1320+ * Copyright 2016 Canonical Ltd.
1321+ *
1322+ * This program is free software; you can redistribute it and/or modify
1323+ * it under the terms of the GNU Lesser General Public License as published by
1324+ * the Free Software Foundation; version 2.1.
1325+ *
1326+ * This program is distributed in the hope that it will be useful,
1327+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1328+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1329+ * GNU Lesser General Public License for more details.
1330+ *
1331+ * You should have received a copy of the GNU Lesser General Public License
1332+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1333+ *
1334+ * Author: Benjamin Zeller <benjamin.zeller@canonical.com>
1335+ */
1336+
1337+#ifndef UBUNTU_INTERNAL_SNAPCRAFTPROJECTMANAGER_H
1338+#define UBUNTU_INTERNAL_SNAPCRAFTPROJECTMANAGER_H
1339+
1340+#include <projectexplorer/iprojectmanager.h>
1341+
1342+namespace Ubuntu {
1343+namespace Internal {
1344+
1345+class SnapcraftProjectManager : public ProjectExplorer::IProjectManager
1346+{
1347+public:
1348+ SnapcraftProjectManager();
1349+
1350+ // IProjectManager interface
1351+ virtual QString mimeType() const override;
1352+ virtual ProjectExplorer::Project *openProject(const QString &fileName, QString *errorString) override;
1353+};
1354+
1355+} // namespace Internal
1356+} // namespace Ubuntu
1357+
1358+#endif // UBUNTU_INTERNAL_SNAPCRAFTPROJECTMANAGER_H
1359
1360=== added file 'src/ubuntu/snap/project/snapcraftprojectnode.cpp'
1361--- src/ubuntu/snap/project/snapcraftprojectnode.cpp 1970-01-01 00:00:00 +0000
1362+++ src/ubuntu/snap/project/snapcraftprojectnode.cpp 2016-11-16 10:23:00 +0000
1363@@ -0,0 +1,517 @@
1364+/*
1365+ * Copyright 2016 Canonical Ltd.
1366+ *
1367+ * This program is free software; you can redistribute it and/or modify
1368+ * it under the terms of the GNU Lesser General Public License as published by
1369+ * the Free Software Foundation; version 2.1.
1370+ *
1371+ * This program is distributed in the hope that it will be useful,
1372+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1373+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1374+ * GNU Lesser General Public License for more details.
1375+ *
1376+ * You should have received a copy of the GNU Lesser General Public License
1377+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1378+ *
1379+ * Author: Benjamin Zeller <benjamin.zeller@canonical.com>
1380+ */
1381+
1382+#include "snapcraftprojectnode.h"
1383+#include "snapcraftproject.h"
1384+
1385+#include <projectexplorer/nodesvisitor.h>
1386+#include <projectexplorer/projectexplorerconstants.h>
1387+#include <projectexplorer/taskhub.h>
1388+#include <coreplugin/fileiconprovider.h>
1389+#include <ubuntu/ubuntuconstants.h>
1390+
1391+#include <QFileInfo>
1392+#include <QDir>
1393+#include <QTimer>
1394+#include <QFileSystemWatcher>
1395+
1396+#pragma GCC diagnostic push
1397+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
1398+#include <yaml-cpp/yaml.h>
1399+#pragma GCC diagnostic pop
1400+
1401+namespace Ubuntu {
1402+namespace Internal {
1403+
1404+enum {
1405+ debug = 0
1406+};
1407+
1408+
1409+static QIcon generateIcon(const QString &overlay) {
1410+ const QSize desiredSize = QSize(16, 16);
1411+
1412+ const QPixmap overlayPixmap(overlay);
1413+ const QIcon overlayIcon(overlayPixmap.scaled(12, 12));
1414+ const QPixmap pixmap
1415+ = Core::FileIconProvider::overlayIcon(QStyle::SP_DirIcon, overlayIcon, desiredSize);
1416+
1417+ QIcon result;
1418+ result.addPixmap(pixmap);
1419+
1420+ return result;
1421+}
1422+
1423+static QIcon generateProjectIcon () {
1424+ static QIcon projectIcon;
1425+ if (projectIcon.isNull())
1426+ projectIcon = generateIcon(QString::fromLatin1(Constants::UBUNTU_ICON));
1427+
1428+ return projectIcon;
1429+}
1430+
1431+SnapcraftProjectNode::SnapcraftProjectNode(SnapcraftProject *rootProject, const Utils::FileName &projectFilePath, QFileSystemWatcher *watcher)
1432+ : ProjectExplorer::ProjectNode (projectFilePath),
1433+ m_rootProject(rootProject),
1434+ m_watcher(watcher)
1435+{
1436+ setDisplayName(projectFilePath.parentDir().toFileInfo().fileName());
1437+ setIcon(generateProjectIcon());
1438+}
1439+
1440+SnapcraftProjectNode::~SnapcraftProjectNode()
1441+{
1442+}
1443+
1444+bool SnapcraftProjectNode::syncFromYAMLNode(YAML::Node rootNode)
1445+{
1446+ if(debug) qDebug()<<"Sync from YAML node";
1447+ try {
1448+ QString displayName = QString::fromStdString(rootNode["name"].as<std::string>());
1449+ setDisplayName(displayName);
1450+
1451+ YAML::Node parts = rootNode["parts"];
1452+ if (!parts.IsMap()) {
1453+ ProjectExplorer::TaskHub::addTask(ProjectExplorer::Task::Error,
1454+ QString::fromLatin1("Error while parsing snapcraft.yaml: parts is not a map"),
1455+ ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM,
1456+ m_rootProject->projectFilePath());
1457+ return false;
1458+ }
1459+
1460+ QList<ProjectExplorer::FolderNode *> existingNodes = subFolderNodes();
1461+ QList<ProjectExplorer::FolderNode *> nodesToRemove;
1462+ QList<ProjectExplorer::FolderNode *> nodesToAdd;
1463+
1464+ QStringList partsFromYaml;
1465+ QStringList existingParts;
1466+
1467+ for (const auto &part : existingNodes) {
1468+ existingParts << part->displayName();
1469+ }
1470+
1471+ //iterate over the parts
1472+ for (auto it = parts.begin(); it != parts.end(); ++it) {
1473+
1474+ YAML::Node subProject = it->second;
1475+ QString partName = QString::fromStdString(it->first.as<std::string>());
1476+ //QString subType = QString::fromStdString(subProject["plugin"].as<std::string>());
1477+ QString source = QDir::cleanPath(QString::fromStdString(subProject["source"].as<std::string>()));
1478+
1479+ partsFromYaml << partName;
1480+
1481+ // We only show a part if it locally exists and is a directory
1482+ QString sourcePathName = QDir::cleanPath(filePath().parentDir().appendPath(source).toString());
1483+ Utils::FileName sourcePath = Utils::FileName::fromString(sourcePathName);
1484+ if (sourcePath.exists() && sourcePath.toFileInfo().isDir()) {
1485+
1486+ int idx = existingParts.indexOf(partName);
1487+ if (idx >= 0) {
1488+ //check if source is still the same
1489+ SnapcraftGenericPartNode *n = static_cast<SnapcraftGenericPartNode *>(existingNodes.at(idx));
1490+ if (n->filePath() == sourcePath)
1491+ continue;
1492+
1493+ nodesToRemove << n;
1494+ }
1495+
1496+ SnapcraftGenericPartNode *partNode = new SnapcraftGenericPartNode(partName, sourcePath, m_watcher);
1497+ nodesToAdd << partNode;
1498+ }
1499+ }
1500+
1501+
1502+ //snapcraft has magic directories, like setup, we want to show in the project tree
1503+ QStringList magicSnapcraftDirs{
1504+ QStringLiteral("setup")
1505+ };
1506+
1507+ for (const QString &magicDir: magicSnapcraftDirs) {
1508+ Utils::FileName dirPath = filePath().parentDir().appendPath(magicDir);
1509+ if (dirPath.exists()) {
1510+ partsFromYaml << magicDir;
1511+ if(!existingParts.contains(magicDir)) {
1512+ SnapcraftGenericPartNode *partNode = new SnapcraftGenericPartNode(magicDir, dirPath, m_watcher);
1513+ nodesToAdd << partNode;
1514+ }
1515+ }
1516+ }
1517+
1518+ QSet<QString> obsoleteParts = existingParts.toSet() - partsFromYaml.toSet();
1519+
1520+ if(debug) {
1521+ qDebug()<<"Parts in yaml"<<partsFromYaml;
1522+ qDebug()<<"Currently known parts"<<existingParts;
1523+ qDebug()<<"Parts now obsolete: "<<obsoleteParts;
1524+ }
1525+
1526+ for (const auto &part : obsoleteParts) {
1527+ int idx = existingParts.indexOf(part);
1528+ if (idx >= 0)
1529+ nodesToRemove << existingNodes.at(idx);
1530+ }
1531+
1532+ //remove old nodes
1533+ removeFolderNodes(nodesToRemove);
1534+ addFolderNodes(nodesToAdd);
1535+ } catch (const YAML::Exception &e) {
1536+ ProjectExplorer::TaskHub::addTask(ProjectExplorer::Task::Error,
1537+ QString::fromLatin1("Error while parsing snapcraft.yaml: %1").arg(QString::fromLatin1(e.what())),
1538+ ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM,
1539+ m_rootProject->projectFilePath(),
1540+ e.mark.line);
1541+ return false;
1542+ }
1543+
1544+ return true;
1545+}
1546+
1547+/*!
1548+ \class Ubuntu::Internal::SnapcraftGenericPartNode
1549+ \brief The SnapcraftGenericPartNode class
1550+ Fallback node if the subproject type can not be handled by the plugin directly
1551+ */
1552+
1553+static void enumChild(const QDir &dir, QSet<Utils::FileName> &dirs, QSet<Utils::FileName> &res) {
1554+ foreach (const QFileInfo &info, dir.entryInfoList(QDir::NoDotAndDotDot|QDir::Dirs|QDir::Files|QDir::Hidden)) {
1555+ if (info.isDir()) {
1556+ dirs << Utils::FileName(info);
1557+ enumChild(QDir(info.absoluteFilePath()), dirs, res);
1558+ } else {
1559+ res.insert(Utils::FileName(info));
1560+ }
1561+ }
1562+}
1563+
1564+SnapcraftGenericPartNode::SnapcraftGenericPartNode(const QString &partName, const Utils::FileName &folderPath, QFileSystemWatcher *watcher)
1565+ : ProjectExplorer::FolderNode (folderPath, ProjectExplorer::FolderNodeType, partName)
1566+ , m_watcher(watcher)
1567+{
1568+ scheduleProjectScan();
1569+
1570+ setIcon(generateProjectIcon());
1571+
1572+ if (watcher->addPath(folderPath.toString())) {
1573+ if(debug) qDebug()<<"Added"<<folderPath.toString()<<"to watcher";
1574+ } else {
1575+ if(debug) qDebug()<<"Failed to add"<<folderPath.toString()<<"to watcher";
1576+ }
1577+ m_watcherConnection = QObject::connect(watcher, &QFileSystemWatcher::directoryChanged, [this](const QString &path){
1578+ maybeScheduleProjectScan(path);
1579+ });
1580+}
1581+
1582+SnapcraftGenericPartNode::~SnapcraftGenericPartNode()
1583+{
1584+ //@BUG the watcher is still watching all the subdirs and files!
1585+ if (m_watcher) {
1586+ QString myPath = filePath().toFileInfo().absoluteFilePath();
1587+ QStringList watched = m_watcher->directories();
1588+ QStringList toRemove;
1589+ for(const QString &path: watched) {
1590+ if(path.startsWith(myPath))
1591+ toRemove << path;
1592+ }
1593+ m_watcher->removePaths(toRemove);
1594+ QObject::disconnect(m_watcherConnection);
1595+ }
1596+}
1597+
1598+void SnapcraftGenericPartNode::maybeScheduleProjectScan(const QString &changedPath)
1599+{
1600+ Utils::FileName changed = Utils::FileName::fromString(changedPath);
1601+ if (filePath().toFileInfo() == changed.toFileInfo())
1602+ scheduleProjectScan();
1603+}
1604+
1605+void SnapcraftGenericPartNode::scheduleProjectScan()
1606+{
1607+ if (m_scanning)
1608+ return;
1609+
1610+ if(debug) qDebug()<<"Scheduling Project scan";
1611+
1612+ m_scanning = true;
1613+
1614+ QTimer *rescanTimer = new QTimer();
1615+ rescanTimer->setSingleShot(true);
1616+ rescanTimer->start(0);
1617+ QObject::connect(rescanTimer, &QTimer::timeout, [this, rescanTimer](){
1618+ if(debug) qDebug()<<"Starting Project scan";
1619+ delete rescanTimer;
1620+ this->scanProjectDirectory();
1621+
1622+ m_scanning = false;
1623+ });
1624+}
1625+
1626+void SnapcraftGenericPartNode::removeFileNodes(const QList<Utils::FileName> &files)
1627+{
1628+ foreach(const Utils::FileName &f, files) {
1629+ if(f.toFileInfo().isDir())
1630+ continue;
1631+
1632+ FindFileNodesForFileVisitor vis(f);
1633+ this->accept(&vis);
1634+
1635+ for (ProjectExplorer::FileNode *node : vis.nodes()) {
1636+ node->parentFolderNode()->removeFileNodes({node});
1637+ }
1638+ }
1639+}
1640+
1641+void SnapcraftGenericPartNode::removeFolderNodes(QList<Utils::FileName> &dirs)
1642+{
1643+
1644+ qSort(dirs.begin(), dirs.end(),[](const Utils::FileName &a, const Utils::FileName &b){
1645+ return a.toFileInfo().absoluteFilePath() > b.toFileInfo().absoluteFilePath();
1646+ });
1647+
1648+ foreach(const Utils::FileName &f, dirs) {
1649+ FindNodesForFolderVisitor vis(f);
1650+ this->accept(&vis);
1651+
1652+ FindNodesForFolderVisitor visParent(f.parentDir());
1653+ this->accept(&visParent);
1654+
1655+ if(visParent.nodes().size()) {
1656+ m_watcher->removePath(f.toFileInfo().absoluteFilePath());
1657+ visParent.nodes()[0]->removeFolderNodes(vis.nodes());
1658+ }
1659+ }
1660+}
1661+
1662+QList<ProjectExplorer::ProjectAction> SnapcraftGenericPartNode::supportedActions(ProjectExplorer::Node *node) const
1663+{
1664+ static const QList<ProjectExplorer::ProjectAction> fileActions {
1665+ ProjectExplorer::ProjectAction::Rename,
1666+ ProjectExplorer::ProjectAction::RemoveFile
1667+ };
1668+ static const QList<ProjectExplorer::ProjectAction> folderActions {
1669+ ProjectExplorer::ProjectAction::AddNewFile,
1670+ ProjectExplorer::ProjectAction::RemoveFile
1671+ };
1672+ switch (node->nodeType()) {
1673+ case ProjectExplorer::FileNodeType:
1674+ return fileActions;
1675+ case ProjectExplorer::FolderNodeType:
1676+ case ProjectExplorer::ProjectNodeType:
1677+ return folderActions;
1678+ default:
1679+ return ProjectExplorer::FolderNode::supportedActions(node);
1680+ }
1681+}
1682+
1683+bool SnapcraftGenericPartNode::addFiles(const QStringList &, QStringList *)
1684+{
1685+ return true;
1686+}
1687+
1688+bool SnapcraftGenericPartNode::removeFiles(const QStringList &, QStringList *)
1689+{
1690+ return true;
1691+}
1692+
1693+bool SnapcraftGenericPartNode::deleteFiles(const QStringList &)
1694+{
1695+ return true;
1696+}
1697+
1698+void SnapcraftGenericPartNode::scanProjectDirectory()
1699+{
1700+ QSet<Utils::FileName> dirs;
1701+ QSet<Utils::FileName> files;
1702+ enumChild(QDir(filePath().toString()), dirs, files);
1703+
1704+ FindFilesAndDirsVisitor vis;
1705+ this->accept(&vis);
1706+
1707+ QSet<Utils::FileName> oldFiles = QSet<Utils::FileName>::fromList(vis.filePaths());
1708+ QSet<Utils::FileName> oldDirs = QSet<Utils::FileName>::fromList(vis.dirPaths());
1709+ QSet<Utils::FileName> newFiles(files);
1710+ QSet<Utils::FileName> newDirs(dirs);
1711+
1712+ QSet<Utils::FileName> filesToRemove = oldFiles - newFiles;
1713+ QSet<Utils::FileName> filesToAdd = newFiles - oldFiles;
1714+ QList<Utils::FileName> dirsToRemove = (oldDirs - newDirs).toList();
1715+ QSet<Utils::FileName> dirsToAdd = newDirs - oldDirs;
1716+
1717+ if(debug) {
1718+ qDebug()<<"Removing dirs " <<dirsToRemove;
1719+ qDebug()<<"Adding dirs " <<dirsToAdd;
1720+ qDebug()<<"Removing files" <<filesToRemove;
1721+ qDebug()<<"Adding files " <<filesToAdd;
1722+ }
1723+
1724+ removeFileNodes(filesToRemove.toList());
1725+ removeFolderNodes(dirsToRemove);
1726+
1727+ for (const Utils::FileName &dir : dirsToAdd) {
1728+ Utils::FileName relativeName = dir.relativeChildPath(filePath());
1729+ QStringList relativeNameList = relativeName.toUserOutput().split(QDir::separator());
1730+ createOrFindFolder(relativeNameList);
1731+ }
1732+
1733+ for (const Utils::FileName &file : filesToAdd) {
1734+ Utils::FileName folderPath = file.parentDir();
1735+
1736+ //do not show the project file twice
1737+ if (file == projectNode()->filePath())
1738+ continue;
1739+
1740+ ProjectExplorer::FolderNode *parentNode = nullptr;
1741+ if (folderPath == filePath()) {
1742+ parentNode = this;
1743+ } else {
1744+ Utils::FileName relativeName = folderPath.relativeChildPath(filePath());
1745+ QStringList relativeNameList = relativeName.toUserOutput().split(QDir::separator());
1746+ parentNode = createOrFindFolder(relativeNameList);
1747+ }
1748+
1749+ ProjectExplorer::FileNode *fNode = new ProjectExplorer::FileNode(file, ProjectExplorer::UnknownFileType, false);
1750+ parentNode->addFileNodes({fNode});
1751+ }
1752+}
1753+
1754+ProjectExplorer::FolderNode *SnapcraftGenericPartNode::createOrFindFolder(const QStringList &folder)
1755+{
1756+ QStringList watches;
1757+ ProjectExplorer::FolderNode *currFolder = this;
1758+
1759+ Utils::FileName currentPath = filePath();
1760+
1761+ for (const QString &folderName: folder) {
1762+
1763+ QList<ProjectExplorer::FolderNode *> subnodes = currFolder->subFolderNodes();
1764+ currentPath = currentPath.appendPath(folderName);
1765+
1766+ auto check = [&folderName](ProjectExplorer::FolderNode *f) {
1767+ return f->filePath().fileName() == folderName;
1768+ };
1769+
1770+ auto it = std::find_if(subnodes.begin(), subnodes.end(), check);
1771+
1772+ if (it != subnodes.end()) {
1773+ //node exists already
1774+ currFolder = *it;
1775+ continue;
1776+ }
1777+
1778+ //does not exist lets create a new one
1779+ ProjectExplorer::FolderNode *fNode = new SnapcraftGenericPartFolderNode(currentPath, ProjectExplorer::FolderNodeType, folderName);
1780+ currFolder->addFolderNodes({fNode});
1781+ currFolder = fNode;
1782+
1783+ watches << currentPath.toFileInfo().absoluteFilePath();
1784+ }
1785+
1786+ if (!watches.isEmpty())
1787+ m_watcher->addPaths(watches);
1788+
1789+ return currFolder;
1790+}
1791+
1792+Utils::FileNameList FindFilesAndDirsVisitor::filePaths() const
1793+{
1794+ return m_filePaths;
1795+}
1796+
1797+Utils::FileNameList FindFilesAndDirsVisitor::dirPaths() const
1798+{
1799+ return m_dirPaths;
1800+}
1801+
1802+void FindFilesAndDirsVisitor::visitProjectNode(ProjectExplorer::ProjectNode *projectNode)
1803+{
1804+ visitFolderNode(projectNode);
1805+}
1806+
1807+void FindFilesAndDirsVisitor::visitFolderNode(ProjectExplorer::FolderNode *folderNode)
1808+{
1809+ if (folderNode->nodeType() != ProjectExplorer::ProjectNodeType)
1810+ m_dirPaths.append(folderNode->filePath());
1811+
1812+ for (const ProjectExplorer::FileNode *fileNode : folderNode->fileNodes())
1813+ m_filePaths.append(fileNode->filePath());
1814+}
1815+
1816+FindFileNodesForFileVisitor::FindFileNodesForFileVisitor(const Utils::FileName &f)
1817+ : m_file(f)
1818+{
1819+
1820+}
1821+
1822+QList<ProjectExplorer::FileNode *> FindFileNodesForFileVisitor::nodes() const
1823+{
1824+ return m_nodes;
1825+}
1826+
1827+void FindFileNodesForFileVisitor::visitProjectNode(ProjectExplorer::ProjectNode *projectNode)
1828+{
1829+ visitFolderNode(projectNode);
1830+}
1831+
1832+void FindFileNodesForFileVisitor::visitFolderNode(ProjectExplorer::FolderNode *folderNode)
1833+{
1834+ for(auto fileNode: folderNode->fileNodes()) {
1835+ if (fileNode->filePath() == m_file)
1836+ m_nodes.append(fileNode);
1837+ }
1838+}
1839+
1840+FindNodesForFolderVisitor::FindNodesForFolderVisitor(const Utils::FileName &f)
1841+ : m_folder(f)
1842+{
1843+
1844+}
1845+
1846+QList<ProjectExplorer::FolderNode *> FindNodesForFolderVisitor::nodes() const
1847+{
1848+ return m_nodes;
1849+}
1850+
1851+void FindNodesForFolderVisitor::visitProjectNode(ProjectExplorer::ProjectNode *)
1852+{
1853+ return;
1854+}
1855+
1856+void FindNodesForFolderVisitor::visitFolderNode(ProjectExplorer::FolderNode *folderNode)
1857+{
1858+ if (m_folder == folderNode->filePath())
1859+ m_nodes.append(folderNode);
1860+}
1861+
1862+bool SnapcraftGenericPartFolderNode::addFiles(const QStringList &, QStringList *)
1863+{
1864+ return true;
1865+}
1866+
1867+bool SnapcraftGenericPartFolderNode::removeFiles(const QStringList &, QStringList *)
1868+{
1869+ return true;
1870+}
1871+
1872+bool SnapcraftGenericPartFolderNode::deleteFiles(const QStringList &)
1873+{
1874+ return true;
1875+}
1876+
1877+
1878+
1879+} // namespace Internal
1880+} // namespace Ubuntu
1881
1882=== added file 'src/ubuntu/snap/project/snapcraftprojectnode.h'
1883--- src/ubuntu/snap/project/snapcraftprojectnode.h 1970-01-01 00:00:00 +0000
1884+++ src/ubuntu/snap/project/snapcraftprojectnode.h 2016-11-16 10:23:00 +0000
1885@@ -0,0 +1,136 @@
1886+/*
1887+ * Copyright 2016 Canonical Ltd.
1888+ *
1889+ * This program is free software; you can redistribute it and/or modify
1890+ * it under the terms of the GNU Lesser General Public License as published by
1891+ * the Free Software Foundation; version 2.1.
1892+ *
1893+ * This program is distributed in the hope that it will be useful,
1894+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1895+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1896+ * GNU Lesser General Public License for more details.
1897+ *
1898+ * You should have received a copy of the GNU Lesser General Public License
1899+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1900+ *
1901+ * Author: Benjamin Zeller <benjamin.zeller@canonical.com>
1902+ */
1903+
1904+#ifndef UBUNTU_INTERNAL_SNAPCRAFTPROJECTNODE_H
1905+#define UBUNTU_INTERNAL_SNAPCRAFTPROJECTNODE_H
1906+
1907+#include <projectexplorer/projectnodes.h>
1908+#include <projectexplorer/nodesvisitor.h>
1909+#include <yaml-cpp/node/node.h>
1910+
1911+#include <QPointer>
1912+
1913+class QFileSystemWatcher;
1914+
1915+namespace Ubuntu {
1916+namespace Internal {
1917+
1918+class FindFilesAndDirsVisitor : public ProjectExplorer::NodesVisitor {
1919+public:
1920+ Utils::FileNameList filePaths() const;
1921+ Utils::FileNameList dirPaths() const;
1922+
1923+ void visitProjectNode(ProjectExplorer::ProjectNode *projectNode) override;
1924+ void visitFolderNode(ProjectExplorer::FolderNode *folderNode) override;
1925+
1926+private:
1927+ Utils::FileNameList m_filePaths;
1928+ Utils::FileNameList m_dirPaths;
1929+};
1930+
1931+class FindFileNodesForFileVisitor : public ProjectExplorer::NodesVisitor {
1932+
1933+public:
1934+ FindFileNodesForFileVisitor (const Utils::FileName &f);
1935+ QList<ProjectExplorer::FileNode *> nodes () const;
1936+
1937+ void visitProjectNode(ProjectExplorer::ProjectNode *projectNode) override;
1938+ void visitFolderNode(ProjectExplorer::FolderNode *folderNode) override;
1939+
1940+private:
1941+ Utils::FileName m_file;
1942+ QList<ProjectExplorer::FileNode *> m_nodes;
1943+};
1944+
1945+class FindNodesForFolderVisitor : public ProjectExplorer::NodesVisitor {
1946+
1947+public:
1948+ FindNodesForFolderVisitor (const Utils::FileName &f);
1949+ QList<ProjectExplorer::FolderNode *> nodes () const;
1950+
1951+ void visitProjectNode(ProjectExplorer::ProjectNode *projectNode) override;
1952+ void visitFolderNode(ProjectExplorer::FolderNode *folderNode) override;
1953+
1954+private:
1955+ Utils::FileName m_folder;
1956+ QList<ProjectExplorer::FolderNode *> m_nodes;
1957+};
1958+
1959+class SnapcraftProject;
1960+class SnapcraftGenericPartNode;
1961+
1962+class SnapcraftProjectNode : public ProjectExplorer::ProjectNode
1963+{
1964+public:
1965+ SnapcraftProjectNode(SnapcraftProject *rootProject, const Utils::FileName &projectFilePath, QFileSystemWatcher *watcher);
1966+ ~SnapcraftProjectNode();
1967+
1968+ bool syncFromYAMLNode(YAML::Node rootNode);
1969+
1970+private:
1971+ SnapcraftProject *m_rootProject = nullptr;
1972+ QPointer<QFileSystemWatcher> m_watcher;
1973+};
1974+
1975+class SnapcraftGenericPartFolderNode : public ProjectExplorer::FolderNode
1976+{
1977+public:
1978+
1979+ using ProjectExplorer::FolderNode::FolderNode;
1980+
1981+ // FolderNode interface
1982+ virtual bool addFiles(const QStringList &filePaths, QStringList *notAdded) override;
1983+ virtual bool removeFiles(const QStringList &filePaths, QStringList *notRemoved) override;
1984+ virtual bool deleteFiles(const QStringList &filePaths) override;
1985+};
1986+
1987+class SnapcraftGenericPartNode : public ProjectExplorer::FolderNode
1988+{
1989+public:
1990+ SnapcraftGenericPartNode(const QString &partName, const Utils::FileName &folderPath, QFileSystemWatcher *watcher);
1991+ ~SnapcraftGenericPartNode();
1992+
1993+ void maybeScheduleProjectScan(const QString &changedPath);
1994+ void scheduleProjectScan();
1995+
1996+ using ProjectExplorer::FolderNode::removeFileNodes;
1997+ void removeFileNodes (const QList<Utils::FileName> &files);
1998+
1999+ using ProjectExplorer::FolderNode::removeFolderNodes;
2000+ void removeFolderNodes (QList<Utils::FileName> &dirs);
2001+
2002+ // Node interface
2003+ virtual QList<ProjectExplorer::ProjectAction> supportedActions(ProjectExplorer::Node *node) const override;
2004+ virtual bool addFiles(const QStringList &filePaths, QStringList *notAdded) override;
2005+ virtual bool removeFiles(const QStringList &filePaths, QStringList *notRemoved) override;
2006+ virtual bool deleteFiles(const QStringList &filePaths) override;
2007+
2008+protected:
2009+ ProjectExplorer::FolderNode *createOrFindFolder (const QStringList &folder);
2010+ void scanProjectDirectory ();
2011+
2012+private:
2013+ bool m_scanning = false;
2014+ QMetaObject::Connection m_watcherConnection;
2015+ QPointer<QFileSystemWatcher> m_watcher;
2016+};
2017+
2018+} // namespace Internal
2019+} // namespace Ubuntu
2020+
2021+#endif // UBUNTU_INTERNAL_SNAPCRAFTPROJECTNODE_H
2022
2023=== added file 'src/ubuntu/snap/project/snapcraftrsyncstep.cpp'
2024--- src/ubuntu/snap/project/snapcraftrsyncstep.cpp 1970-01-01 00:00:00 +0000
2025+++ src/ubuntu/snap/project/snapcraftrsyncstep.cpp 2016-11-16 10:23:00 +0000
2026@@ -0,0 +1,51 @@
2027+#include "snapcraftrsyncstep.h"
2028+#include "snapcraftproject.h"
2029+#include "snapcraftbuildconfiguration.h"
2030+
2031+#include <ubuntu/ubuntuconstants.h>
2032+
2033+#include <projectexplorer/target.h>
2034+
2035+namespace Ubuntu {
2036+namespace Internal {
2037+
2038+SnapcraftRsyncStep::SnapcraftRsyncStep(ProjectExplorer::BuildStepList *bsl)
2039+ : ProjectExplorer::AbstractProcessStep(bsl, Constants::SNAPCRAFT_RSYNCBUILSSTEP_ID)
2040+{
2041+ setDefaultDisplayName(tr("Prepare build"));
2042+}
2043+
2044+SnapcraftRsyncStep::SnapcraftRsyncStep(ProjectExplorer::BuildStepList *bsl, SnapcraftRsyncStep *bs)
2045+ : ProjectExplorer::AbstractProcessStep(bsl, bs)
2046+{
2047+
2048+}
2049+
2050+bool SnapcraftRsyncStep::init(QList<const ProjectExplorer::BuildStep *> &)
2051+{
2052+ QString projectDir = target()->project()->projectDirectory().toString();
2053+
2054+ ProjectExplorer::BuildConfiguration *bc = target()->activeBuildConfiguration();
2055+ if(!bc)
2056+ return false;
2057+
2058+ ProjectExplorer::ProcessParameters *param = processParameters();
2059+ param->setWorkingDirectory(bc->buildDirectory().toUserOutput());
2060+ param->setCommand(QStringLiteral("rsync"));
2061+ param->setArguments(QString::fromLatin1("-a --delete \"%1/\" \"./\"")
2062+ .arg(QDir::cleanPath(projectDir)));
2063+ param->setMacroExpander(bc->macroExpander());
2064+ param->setEnvironment(bc->environment());
2065+
2066+ return true;
2067+}
2068+
2069+ProjectExplorer::BuildStepConfigWidget *SnapcraftRsyncStep::createConfigWidget()
2070+{
2071+ return new ProjectExplorer::SimpleBuildStepConfigWidget(this);
2072+}
2073+
2074+
2075+
2076+} // namespace Internal
2077+} // namespace Ubuntu
2078
2079=== added file 'src/ubuntu/snap/project/snapcraftrsyncstep.h'
2080--- src/ubuntu/snap/project/snapcraftrsyncstep.h 1970-01-01 00:00:00 +0000
2081+++ src/ubuntu/snap/project/snapcraftrsyncstep.h 2016-11-16 10:23:00 +0000
2082@@ -0,0 +1,31 @@
2083+#ifndef UBUNTU_INTERNAL_SNAPCRAFTRSYNCSTEP_H
2084+#define UBUNTU_INTERNAL_SNAPCRAFTRSYNCSTEP_H
2085+
2086+#include <projectexplorer/abstractprocessstep.h>
2087+
2088+namespace Ubuntu {
2089+namespace Internal {
2090+
2091+class SnapcraftBuildStepFactory;
2092+class SnapcraftBuildConfigurationFactory;
2093+
2094+class SnapcraftRsyncStep : public ProjectExplorer::AbstractProcessStep
2095+{
2096+ Q_OBJECT
2097+public:
2098+ friend class SnapcraftBuildStepFactory;
2099+ friend class SnapcraftBuildConfigurationFactory;
2100+
2101+ // BuildStep interface
2102+ virtual bool init(QList<const ProjectExplorer::BuildStep *> &earlierSteps) override;
2103+ virtual ProjectExplorer::BuildStepConfigWidget *createConfigWidget() override;
2104+
2105+protected:
2106+ SnapcraftRsyncStep(ProjectExplorer::BuildStepList *bsl);
2107+ SnapcraftRsyncStep(ProjectExplorer::BuildStepList *bsl, SnapcraftRsyncStep *bs);
2108+};
2109+
2110+} // namespace Internal
2111+} // namespace Ubuntu
2112+
2113+#endif // UBUNTU_INTERNAL_SNAPCRAFTRSYNCSTEP_H
2114
2115=== added file 'src/ubuntu/snap/project/snapcraftstep.cpp'
2116--- src/ubuntu/snap/project/snapcraftstep.cpp 1970-01-01 00:00:00 +0000
2117+++ src/ubuntu/snap/project/snapcraftstep.cpp 2016-11-16 10:23:00 +0000
2118@@ -0,0 +1,139 @@
2119+#include "snapcraftstep.h"
2120+#include "snapcraftproject.h"
2121+#include "snapcraftbuildconfiguration.h"
2122+
2123+#include <ubuntu/snap/settings/snapcraftkitinformation.h>
2124+#include <ubuntu/ubuntuconstants.h>
2125+#include <ubuntu/clicktoolchain.h>
2126+
2127+#include <projectexplorer/target.h>
2128+#include <utils/environment.h>
2129+
2130+#include <QRegularExpression>
2131+
2132+
2133+namespace Ubuntu {
2134+namespace Internal {
2135+
2136+static const char * PACKAGE_NAME_REGEX = "^Snapped ([\\S]+\\.snap)$";
2137+
2138+SnapcraftStep::SnapcraftStep(ProjectExplorer::BuildStepList *bsl)
2139+ : ProjectExplorer::AbstractProcessStep(bsl, Constants::SNAPCRAFT_BUILDSTEP_ID)
2140+{
2141+ setDefaultDisplayName(tr("Snapcraft"));
2142+
2143+ connect(qobject_cast<SnapcraftProject *>(target()->project()), &SnapcraftProject::snapVersionChanged,
2144+ this, &SnapcraftStep::packagePathChanged);
2145+ connect(qobject_cast<SnapcraftProject *>(target()->project()), &SnapcraftProject::displayNameChanged,
2146+ this, &SnapcraftStep::packagePathChanged);
2147+}
2148+
2149+SnapcraftStep::SnapcraftStep(ProjectExplorer::BuildStepList *bsl, SnapcraftStep *bs)
2150+ : ProjectExplorer::AbstractProcessStep(bsl, bs)
2151+{
2152+ connect(qobject_cast<SnapcraftProject *>(target()->project()), &SnapcraftProject::snapVersionChanged,
2153+ this, &SnapcraftStep::packagePathChanged);
2154+ connect(qobject_cast<SnapcraftProject *>(target()->project()), &SnapcraftProject::displayNameChanged,
2155+ this, &SnapcraftStep::packagePathChanged);
2156+}
2157+
2158+void SnapcraftStep::stdOutput(const QString &line)
2159+{
2160+ m_lastLine = line;
2161+ ProjectExplorer::AbstractProcessStep::stdOutput(line);
2162+}
2163+
2164+void SnapcraftStep::processStarted()
2165+{
2166+ m_packagePath.clear();
2167+ emit packagePathChanged();
2168+
2169+ ProjectExplorer::AbstractProcessStep::processStarted();
2170+}
2171+
2172+void SnapcraftStep::processFinished(int exitCode, QProcess::ExitStatus status)
2173+{
2174+ Utils::FileName newPackagePath;
2175+
2176+ ProjectExplorer::AbstractProcessStep::processFinished(exitCode, status);
2177+ if (status == QProcess::NormalExit && exitCode == 0) {
2178+ QRegularExpression exp((QLatin1String(PACKAGE_NAME_REGEX)));
2179+ QRegularExpressionMatch m = exp.match(m_lastLine);
2180+ if(m.hasMatch()) {
2181+ ProjectExplorer::BuildConfiguration *bc = target()->activeBuildConfiguration();
2182+ if(bc)
2183+ newPackagePath = bc->buildDirectory().appendPath(m.captured(1));
2184+ }
2185+ }
2186+
2187+ if (m_packagePath != newPackagePath) {
2188+ m_packagePath = newPackagePath;
2189+ emit packagePathChanged();
2190+ }
2191+}
2192+
2193+bool SnapcraftStep::processSucceeded(int exitCode, QProcess::ExitStatus status)
2194+{
2195+ if (!ProjectExplorer::AbstractProcessStep::processSucceeded(exitCode, status))
2196+ return false;
2197+
2198+ return m_packagePath.toFileInfo().exists();
2199+}
2200+
2201+bool SnapcraftStep::init(QList<const ProjectExplorer::BuildStep *> &)
2202+{
2203+ //QString projectDir = target()->project()->projectDirectory().toString();
2204+ ProjectExplorer::BuildConfiguration *bc = target()->activeBuildConfiguration();
2205+ if(!bc)
2206+ return false;
2207+
2208+ Utils::FileName snapcraftBin = Utils::FileName::fromString(Constants::UBUNTU_SCRIPTPATH);
2209+ snapcraftBin = snapcraftBin.appendPath(QString::fromLatin1("run_snapcraft.py"));
2210+
2211+ ProjectExplorer::ProcessParameters *param = processParameters();
2212+ param->setWorkingDirectory(bc->buildDirectory().toUserOutput());
2213+ param->setCommand(snapcraftBin.toUserOutput());
2214+ param->setArguments(QString::fromLatin1("-s '%1'").arg(snapcraftBin.toFileInfo().absoluteFilePath()));
2215+ param->setMacroExpander(bc->macroExpander());
2216+ param->setEnvironment(bc->environment());
2217+
2218+ return true;
2219+}
2220+
2221+ProjectExplorer::BuildStepConfigWidget *SnapcraftStep::createConfigWidget()
2222+{
2223+ return new ProjectExplorer::SimpleBuildStepConfigWidget(this);
2224+}
2225+
2226+Utils::FileName SnapcraftStep::snapcraftCommand() const
2227+{
2228+ Utils::Environment env = Utils::Environment::systemEnvironment();
2229+ Utils::FileName fallback = env.searchInPath(QStringLiteral("snapcraft"));
2230+ if (!target())
2231+ return fallback;
2232+
2233+ Utils::FileName bin = SnapcraftKitInformation::snapcraftPath(target()->kit());
2234+ if (!bin.exists())
2235+ return fallback;
2236+
2237+ return bin;
2238+}
2239+
2240+Utils::FileName SnapcraftStep::packagePath() const
2241+{
2242+ if (!m_packagePath.isEmpty())
2243+ return m_packagePath;
2244+
2245+ ProjectExplorer::BuildConfiguration *bc = target()->activeBuildConfiguration();
2246+ SnapcraftProject *pro = qobject_cast<SnapcraftProject *>(target()->project());
2247+ ProjectExplorer::ToolChain *tc = ProjectExplorer::ToolChainKitInformation::toolChain(target()->kit());
2248+ if(bc && pro && tc && !pro->displayName().isEmpty() && !pro->snapVersion().isEmpty())
2249+ return bc->buildDirectory().appendPath(QStringLiteral("%1_%2_%3.snap")
2250+ .arg(pro->displayName())
2251+ .arg(pro->snapVersion())
2252+ .arg(ClickToolChain::abiToArchitectureName(tc->targetAbi())));
2253+ return Utils::FileName();
2254+}
2255+
2256+} // namespace Internal
2257+} // namespace Ubuntu
2258
2259=== added file 'src/ubuntu/snap/project/snapcraftstep.h'
2260--- src/ubuntu/snap/project/snapcraftstep.h 1970-01-01 00:00:00 +0000
2261+++ src/ubuntu/snap/project/snapcraftstep.h 2016-11-16 10:23:00 +0000
2262@@ -0,0 +1,50 @@
2263+#ifndef UBUNTU_INTERNAL_SNAPCRAFTSTEP_H
2264+#define UBUNTU_INTERNAL_SNAPCRAFTSTEP_H
2265+
2266+#include <projectexplorer/abstractprocessstep.h>
2267+#include <utils/fileutils.h>
2268+
2269+namespace Ubuntu {
2270+namespace Internal {
2271+
2272+class SnapcraftBuildStepFactory;
2273+class SnapcraftBuildConfigurationFactory;
2274+
2275+class SnapcraftStep : public ProjectExplorer::AbstractProcessStep
2276+{
2277+ Q_OBJECT
2278+public:
2279+ friend class SnapcraftBuildStepFactory;
2280+ friend class SnapcraftBuildConfigurationFactory;
2281+
2282+ // BuildStep interface
2283+ virtual bool init(QList<const ProjectExplorer::BuildStep *> &earlierSteps) override;
2284+ virtual ProjectExplorer::BuildStepConfigWidget *createConfigWidget() override;
2285+
2286+ Utils::FileName snapcraftCommand () const;
2287+ Utils::FileName packagePath () const;
2288+
2289+signals:
2290+ void packagePathChanged ();
2291+
2292+protected:
2293+ SnapcraftStep(ProjectExplorer::BuildStepList *bsl);
2294+ SnapcraftStep(ProjectExplorer::BuildStepList *bsl, SnapcraftStep *bs);
2295+
2296+ // AbstractProcessStep interface
2297+ virtual void stdOutput(const QString &line);
2298+ virtual void processStarted() override;
2299+ virtual void processFinished(int exitCode, QProcess::ExitStatus status) override;
2300+ virtual bool processSucceeded(int exitCode, QProcess::ExitStatus status) override;
2301+
2302+
2303+
2304+private:
2305+ QString m_lastLine;
2306+ Utils::FileName m_packagePath;
2307+};
2308+
2309+} // namespace Internal
2310+} // namespace Ubuntu
2311+
2312+#endif // UBUNTU_INTERNAL_SNAPCRAFTSTEP_H
2313
2314=== added file 'src/ubuntu/snap/project/snaprunconfiguration.cpp'
2315--- src/ubuntu/snap/project/snaprunconfiguration.cpp 1970-01-01 00:00:00 +0000
2316+++ src/ubuntu/snap/project/snaprunconfiguration.cpp 2016-11-16 10:23:00 +0000
2317@@ -0,0 +1,273 @@
2318+#include "snaprunconfiguration.h"
2319+#include "snapcraftstep.h"
2320+#include "snapcraftproject.h"
2321+
2322+#include <ubuntu/ubuntuconstants.h>
2323+
2324+#include <projectexplorer/runnables.h>
2325+#include <projectexplorer/target.h>
2326+#include <projectexplorer/buildconfiguration.h>
2327+#include <projectexplorer/buildstep.h>
2328+#include <projectexplorer/buildsteplist.h>
2329+#include <projectexplorer/projectexplorerconstants.h>
2330+#include <projectexplorer/localenvironmentaspect.h>
2331+#include <projectexplorer/runconfigurationaspects.h>
2332+#include <utils/qtcprocess.h>
2333+#include <utils/pathchooser.h>
2334+
2335+#include <QFileInfo>
2336+#include <QFormLayout>
2337+#include <QComboBox>
2338+#include <QCheckBox>
2339+
2340+namespace Ubuntu {
2341+namespace Internal {
2342+
2343+const QString COMMAND_KEY = QStringLiteral("SnapProjectManager.SnapRunConfiguration.SnapCommand");
2344+const QString DEVMODE_KEY = QStringLiteral("SnapProjectManager.SnapRunConfiguration.SnapDevMode");
2345+const QString WORKINGDIRECTORYASPECT_ID = QStringLiteral("SnapProjectManager.SnapRunConfiguration.WorkingDirectoryAspect");
2346+const QString ARGUMENTASPECT_ID = QStringLiteral("SnapProjectManager.SnapRunConfiguration.ArgumentAspect");
2347+const QString TERMINALASPECT_ID = QStringLiteral("SnapProjectManager.SnapRunConfiguration.TerminalAspect");
2348+
2349+SnapRunConfiguration::SnapRunConfiguration(ProjectExplorer::Target *parent)
2350+ : ProjectExplorer::RunConfiguration(parent, Constants::SNAP_RUNCONFIGURATION_ID)
2351+ , m_useDevMode(true)
2352+ , m_workingDirectoryAspect(new ProjectExplorer::WorkingDirectoryAspect(this, WORKINGDIRECTORYASPECT_ID))
2353+ , m_argumentAspect(new ProjectExplorer::ArgumentsAspect(this, ARGUMENTASPECT_ID))
2354+ , m_terminalAspect(new ProjectExplorer::TerminalAspect(this, TERMINALASPECT_ID))
2355+ , m_localEnvironmentAspect(new ProjectExplorer::LocalEnvironmentAspect(this, ProjectExplorer::LocalEnvironmentAspect::BaseEnvironmentModifier()))
2356+{
2357+ m_terminalAspect->setRunMode(ProjectExplorer::ApplicationLauncher::Gui);
2358+
2359+ addExtraAspect(m_argumentAspect);
2360+ addExtraAspect(m_terminalAspect);
2361+ addExtraAspect(m_localEnvironmentAspect);
2362+ addExtraAspect(m_workingDirectoryAspect);
2363+
2364+ if(parent) {
2365+ SnapcraftProject *pro = qobject_cast<SnapcraftProject *>(parent->project());
2366+ if (pro) {
2367+ setDisplayName(pro->displayName());
2368+ QStringList comms = pro->commands();
2369+ if (comms.size())
2370+ m_command = comms.first();
2371+ }
2372+ m_workingDirectoryAspect->setDefaultWorkingDirectory(Utils::FileName::fromString(pro->projectDir().absolutePath()));
2373+ }
2374+
2375+ // Connect target signals
2376+ connect(this->target(), &ProjectExplorer::Target::activeBuildConfigurationChanged,
2377+ this, &SnapRunConfiguration::updateConfiguration);
2378+ updateConfiguration();
2379+}
2380+
2381+SnapRunConfiguration::SnapRunConfiguration(ProjectExplorer::Target *parent, SnapRunConfiguration *source)
2382+ : ProjectExplorer::RunConfiguration(parent, source),
2383+ m_command(source->m_command)
2384+{
2385+ // Connect target signals
2386+ connect(this->target(), &ProjectExplorer::Target::activeBuildConfigurationChanged,
2387+ this, &SnapRunConfiguration::updateConfiguration);
2388+ updateConfiguration();
2389+}
2390+
2391+QString SnapRunConfiguration::command() const
2392+{
2393+ return m_command;
2394+}
2395+
2396+void SnapRunConfiguration::setCommand(const QString &command)
2397+{
2398+ if (command != m_command) {
2399+ m_command = command;
2400+ emit enabledChanged();
2401+ }
2402+}
2403+
2404+bool SnapRunConfiguration::fromMap(const QVariantMap &map)
2405+{
2406+ if (!ProjectExplorer::RunConfiguration::fromMap(map))
2407+ return false;
2408+
2409+ m_command = map.value(COMMAND_KEY, QString()).toString();
2410+ m_useDevMode = map.value(DEVMODE_KEY, true).toBool();
2411+ return true;
2412+}
2413+
2414+QVariantMap SnapRunConfiguration::toMap() const
2415+{
2416+ QVariantMap map = ProjectExplorer::RunConfiguration::toMap();
2417+ map.insert(COMMAND_KEY, m_command);
2418+ map.insert(DEVMODE_KEY, m_useDevMode);
2419+ return map;
2420+}
2421+
2422+bool SnapRunConfiguration::isEnabled() const
2423+{
2424+ return !m_command.isEmpty();
2425+}
2426+
2427+QString SnapRunConfiguration::disabledReason() const
2428+{
2429+ return tr("Please select a command to run in the runconfiguration.");
2430+}
2431+
2432+QWidget *SnapRunConfiguration::createConfigurationWidget()
2433+{
2434+ return new SnapRunConfigurationWidget(this);
2435+}
2436+
2437+ProjectExplorer::Runnable SnapRunConfiguration::runnable() const
2438+{
2439+ SnapcraftStep *pckStep = activeSnapcraftStep();
2440+ if (!pckStep) {
2441+ return ProjectExplorer::Runnable();
2442+ }
2443+
2444+ Utils::FileName packagePath = pckStep->packagePath();
2445+ if(packagePath.isEmpty()) {
2446+ return ProjectExplorer::Runnable();
2447+ }
2448+
2449+ qDebug()<<"Going to run "<<packagePath.toUserOutput();
2450+
2451+ QStringList args{
2452+ packagePath.toUserOutput(),
2453+ m_command
2454+ };
2455+
2456+ if (m_useDevMode)
2457+ args.prepend(QStringLiteral("--devmode"));
2458+
2459+ ProjectExplorer::StandardRunnable r;
2460+ r.executable = Utils::FileName::fromString(Constants::UBUNTU_SCRIPTPATH).appendPath(QStringLiteral("qtc_desktop_snaprunner.py")).toString();;
2461+ r.workingDirectory = m_workingDirectoryAspect->workingDirectory().toString();
2462+ r.environment = m_localEnvironmentAspect->environment();
2463+ r.commandLineArguments = Utils::QtcProcess::joinArgs(args);
2464+ if (!m_argumentAspect->arguments().isEmpty()) {
2465+ r.commandLineArguments.append(QStringLiteral(" -- %1").arg(m_argumentAspect->arguments()));
2466+ }
2467+ return r;
2468+}
2469+
2470+SnapcraftStep *SnapRunConfiguration::activeSnapcraftStep() const
2471+{
2472+ ProjectExplorer::BuildConfiguration *buildConf = activeBuildConfiguration();
2473+ if(!buildConf)
2474+ return nullptr;
2475+
2476+ ProjectExplorer::BuildStepList *bsList = buildConf->stepList(ProjectExplorer::Constants::BUILDSTEPS_BUILD);
2477+ for(ProjectExplorer::BuildStep *currStep : bsList->steps()) {
2478+ SnapcraftStep *pckStep = qobject_cast<SnapcraftStep*>(currStep);
2479+ if(pckStep)
2480+ return pckStep;
2481+ }
2482+ return nullptr;
2483+}
2484+
2485+void SnapRunConfiguration::updateConfiguration()
2486+{
2487+ if(m_currBuildConfConn)
2488+ disconnect(m_currBuildConfConn);
2489+
2490+ m_currBuildConfConn = connect(activeSnapcraftStep(), &SnapcraftStep::packagePathChanged,
2491+ this, &ProjectExplorer::RunConfiguration::requestRunActionsUpdate);
2492+
2493+}
2494+
2495+bool SnapRunConfiguration::useDevMode() const
2496+{
2497+ return m_useDevMode;
2498+}
2499+
2500+void SnapRunConfiguration::setUseDevMode(bool useDevMode)
2501+{
2502+ m_useDevMode = useDevMode;
2503+}
2504+
2505+SnapRunConfigurationWidget::SnapRunConfigurationWidget(SnapRunConfiguration *config)
2506+ : QWidget (nullptr),
2507+ m_rc(config),
2508+ m_updating(false)
2509+{
2510+ QFormLayout *layout = new QFormLayout(this);
2511+ layout->setMargin(0);
2512+ layout->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow);
2513+
2514+ setLayout(layout);
2515+
2516+ m_commandsBox = new QComboBox(this);
2517+ updateComboBox();
2518+
2519+ connect(m_commandsBox, SIGNAL(currentIndexChanged(int)),
2520+ this, SLOT(commandSelected(int)));
2521+
2522+ int idx = m_commandsBox->findText(config->command());
2523+ if (idx >= 0)
2524+ m_commandsBox->setCurrentIndex(idx);
2525+
2526+ m_devmodeCheckBox = new QCheckBox(tr("Use devmode"), this);
2527+ m_devmodeCheckBox->setChecked(config->useDevMode());
2528+ connect(m_devmodeCheckBox, &QCheckBox::stateChanged,
2529+ this, &SnapRunConfigurationWidget::devModeStateChanged);
2530+
2531+ layout->addRow(tr("Command:"), m_commandsBox);
2532+ config->extraAspect<ProjectExplorer::ArgumentsAspect>()->addToMainConfigurationWidget(this, layout);
2533+ config->extraAspect<ProjectExplorer::WorkingDirectoryAspect>()->addToMainConfigurationWidget(this,layout);
2534+ config->extraAspect<ProjectExplorer::TerminalAspect>()->addToMainConfigurationWidget(this,layout);
2535+ layout->addRow(QStringLiteral(""), m_devmodeCheckBox);
2536+
2537+ if(config->target()) {
2538+ connect(qobject_cast<SnapcraftProject*>(config->target()->project()), &SnapcraftProject::commandListChanged,
2539+ this, &SnapRunConfigurationWidget::updateComboBox);
2540+ }
2541+}
2542+
2543+void SnapRunConfigurationWidget::updateComboBox()
2544+{
2545+ QString currItem = m_rc->command();
2546+
2547+ //TODO check if project is still loading, so we do not override something we need
2548+
2549+ m_updating = true;
2550+ m_commandsBox->clear();
2551+ m_commandsBox->addItem(QString());
2552+ if(m_rc && m_rc->target()) {
2553+ SnapcraftProject *pro = qobject_cast<SnapcraftProject *>(m_rc->target()->project());
2554+ if (pro) {
2555+ QStringList comms = pro->commands();
2556+ m_commandsBox->addItems(comms);
2557+ }
2558+ }
2559+ m_updating = false;
2560+
2561+ int idx = m_commandsBox->findText(currItem);
2562+ if (idx <= 0 && m_commandsBox->count() > 1)
2563+ m_commandsBox->setCurrentIndex(1);
2564+ else if (idx > 0)
2565+ m_commandsBox->setCurrentIndex(idx);
2566+ else
2567+ m_commandsBox->setCurrentIndex(0);
2568+}
2569+
2570+void SnapRunConfigurationWidget::devModeStateChanged(int state)
2571+{
2572+ if (state == Qt::Checked)
2573+ m_rc->setUseDevMode(true);
2574+ else
2575+ m_rc->setUseDevMode(false);
2576+}
2577+
2578+void SnapRunConfigurationWidget::commandSelected(const int index)
2579+{
2580+ if(m_updating)
2581+ return;
2582+
2583+ if(index == 0)
2584+ m_rc->setCommand(QString());
2585+ else
2586+ m_rc->setCommand(m_commandsBox->itemText(index));
2587+}
2588+
2589+} // namespace Internal
2590+} // namespace Ubuntu
2591
2592=== added file 'src/ubuntu/snap/project/snaprunconfiguration.h'
2593--- src/ubuntu/snap/project/snaprunconfiguration.h 1970-01-01 00:00:00 +0000
2594+++ src/ubuntu/snap/project/snaprunconfiguration.h 2016-11-16 10:23:00 +0000
2595@@ -0,0 +1,94 @@
2596+#ifndef UBUNTU_INTERNAL_SNAPRUNCONFIGURATION_H
2597+#define UBUNTU_INTERNAL_SNAPRUNCONFIGURATION_H
2598+
2599+#include "snaprunconfigurationfactory.h"
2600+
2601+#include <projectexplorer/runconfiguration.h>
2602+#include <utils/fileutils.h>
2603+
2604+#include <QStringList>
2605+
2606+class QComboBox;
2607+class QCheckBox;
2608+
2609+namespace Utils {
2610+ class PathChooser;
2611+}
2612+
2613+namespace ProjectExplorer {
2614+ class WorkingDirectoryAspect;
2615+ class ArgumentsAspect;
2616+ class TerminalAspect;
2617+ class LocalEnvironmentAspect;
2618+}
2619+
2620+namespace Ubuntu {
2621+namespace Internal {
2622+
2623+class SnapcraftStep;
2624+
2625+class SnapRunConfiguration : public ProjectExplorer::RunConfiguration
2626+{
2627+ Q_OBJECT
2628+ friend class SnapRunConfigurationFactory;
2629+protected:
2630+ SnapRunConfiguration(ProjectExplorer::Target *parent);
2631+ SnapRunConfiguration(ProjectExplorer::Target *parent, SnapRunConfiguration *source);
2632+
2633+public:
2634+
2635+ QString command () const;
2636+ void setCommand (const QString &command);
2637+
2638+ // ProjectConfiguration interface
2639+ virtual bool fromMap(const QVariantMap &map) override;
2640+ virtual QVariantMap toMap() const override;
2641+
2642+ // RunConfiguration interface
2643+ virtual bool isEnabled() const override;
2644+ virtual QString disabledReason() const override;
2645+ virtual QWidget *createConfigurationWidget() override;
2646+ virtual ProjectExplorer::Runnable runnable() const override;
2647+
2648+ bool useDevMode() const;
2649+ void setUseDevMode(bool useDevMode);
2650+
2651+private:
2652+ SnapcraftStep *activeSnapcraftStep() const;
2653+ void updateCommandList(const QStringList &commands);
2654+ void updateConfiguration();
2655+
2656+private:
2657+ QString m_command;
2658+ bool m_useDevMode;
2659+ QMetaObject::Connection m_currBuildConfConn;
2660+ ProjectExplorer::WorkingDirectoryAspect* m_workingDirectoryAspect;
2661+ ProjectExplorer::ArgumentsAspect* m_argumentAspect;
2662+ ProjectExplorer::TerminalAspect* m_terminalAspect;
2663+ ProjectExplorer::LocalEnvironmentAspect* m_localEnvironmentAspect;
2664+};
2665+
2666+class SnapRunConfigurationWidget : public QWidget
2667+{
2668+ Q_OBJECT
2669+public:
2670+ SnapRunConfigurationWidget(SnapRunConfiguration *config);
2671+
2672+protected:
2673+ void updateComboBox ();
2674+ void devModeStateChanged (int state);
2675+
2676+protected slots:
2677+ void commandSelected (const int index);
2678+
2679+private:
2680+ SnapRunConfiguration *m_rc;
2681+ QComboBox *m_commandsBox;
2682+ QCheckBox *m_devmodeCheckBox;
2683+ bool m_updating;
2684+};
2685+
2686+} // namespace Internal
2687+} // namespace Ubuntu
2688+
2689+#endif // UBUNTU_INTERNAL_SNAPRUNCONFIGURATION_H
2690
2691=== added file 'src/ubuntu/snap/project/snaprunconfigurationfactory.cpp'
2692--- src/ubuntu/snap/project/snaprunconfigurationfactory.cpp 1970-01-01 00:00:00 +0000
2693+++ src/ubuntu/snap/project/snaprunconfigurationfactory.cpp 2016-11-16 10:23:00 +0000
2694@@ -0,0 +1,85 @@
2695+#include "snaprunconfigurationfactory.h"
2696+#include "snaprunconfiguration.h"
2697+#include "snapcraftproject.h"
2698+
2699+#include <ubuntu/ubuntuconstants.h>
2700+#include <projectexplorer/target.h>
2701+
2702+#include <utils/qtcassert.h>
2703+
2704+namespace Ubuntu {
2705+namespace Internal {
2706+
2707+SnapRunConfigurationFactory::SnapRunConfigurationFactory()
2708+{
2709+ setObjectName(QStringLiteral("SnapRunConfigurationFactory"));
2710+}
2711+
2712+QList<Core::Id> SnapRunConfigurationFactory::availableCreationIds(ProjectExplorer::Target *parent,
2713+ ProjectExplorer::IRunConfigurationFactory::CreationMode mode) const
2714+{
2715+ Q_UNUSED(mode);
2716+
2717+ if (!parent)
2718+ return {};
2719+ if (!qobject_cast<SnapcraftProject *>(parent->project()))
2720+ return {};
2721+
2722+ return {
2723+ Constants::SNAP_RUNCONFIGURATION_ID
2724+ };
2725+}
2726+
2727+QString SnapRunConfigurationFactory::displayNameForId(Core::Id id) const
2728+{
2729+ if (id == Constants::SNAP_RUNCONFIGURATION_ID)
2730+ return tr("Snapcraft Runconfiguration");
2731+
2732+ return QString();
2733+}
2734+
2735+bool SnapRunConfigurationFactory::canCreate(ProjectExplorer::Target *parent, Core::Id id) const
2736+{
2737+ return availableCreationIds(parent, ProjectExplorer::IRunConfigurationFactory::AutoCreate).contains(id);
2738+}
2739+
2740+bool SnapRunConfigurationFactory::canRestore(ProjectExplorer::Target *parent, const QVariantMap &map) const
2741+{
2742+ return availableCreationIds(parent, ProjectExplorer::IRunConfigurationFactory::AutoCreate).contains(ProjectExplorer::idFromMap(map));
2743+}
2744+
2745+bool SnapRunConfigurationFactory::canClone(ProjectExplorer::Target *parent, ProjectExplorer::RunConfiguration *product) const
2746+{
2747+ return availableCreationIds(parent, ProjectExplorer::IRunConfigurationFactory::AutoCreate).contains(product->id());
2748+}
2749+
2750+ProjectExplorer::RunConfiguration *SnapRunConfigurationFactory::clone(ProjectExplorer::Target *parent, ProjectExplorer::RunConfiguration *product)
2751+{
2752+ QTC_ASSERT(canClone(parent, product), return nullptr);
2753+ return new SnapRunConfiguration(parent, static_cast<SnapRunConfiguration *>(product));
2754+}
2755+
2756+ProjectExplorer::RunConfiguration *SnapRunConfigurationFactory::doCreate(ProjectExplorer::Target *parent, Core::Id id)
2757+{
2758+ QTC_ASSERT(canCreate(parent, id), return nullptr);
2759+ if (id == Constants::SNAP_RUNCONFIGURATION_ID)
2760+ return new SnapRunConfiguration(parent);
2761+ return nullptr;
2762+}
2763+
2764+ProjectExplorer::RunConfiguration *SnapRunConfigurationFactory::doRestore(ProjectExplorer::Target *parent, const QVariantMap &map)
2765+{
2766+ QTC_ASSERT(canRestore(parent, map), return nullptr);
2767+
2768+ SnapRunConfiguration *conf = new SnapRunConfiguration(parent);
2769+ if (conf->fromMap(map))
2770+ return conf;
2771+
2772+ //something went wrong
2773+ delete conf;
2774+ return nullptr;
2775+
2776+}
2777+
2778+} // namespace Internal
2779+} // namespace Ubuntu
2780
2781=== added file 'src/ubuntu/snap/project/snaprunconfigurationfactory.h'
2782--- src/ubuntu/snap/project/snaprunconfigurationfactory.h 1970-01-01 00:00:00 +0000
2783+++ src/ubuntu/snap/project/snaprunconfigurationfactory.h 2016-11-16 10:23:00 +0000
2784@@ -0,0 +1,31 @@
2785+#ifndef UBUNTU_INTERNAL_SNAPRUNCONFIGURATIONFACTORY_H
2786+#define UBUNTU_INTERNAL_SNAPRUNCONFIGURATIONFACTORY_H
2787+
2788+#include <projectexplorer/runconfiguration.h>
2789+
2790+namespace Ubuntu {
2791+namespace Internal {
2792+
2793+class SnapRunConfigurationFactory : public ProjectExplorer::IRunConfigurationFactory
2794+{
2795+public:
2796+
2797+ SnapRunConfigurationFactory();
2798+
2799+ // IRunConfigurationFactory interface
2800+ virtual QList<Core::Id> availableCreationIds(ProjectExplorer::Target *parent, CreationMode mode) const override;
2801+ virtual QString displayNameForId(Core::Id id) const override;
2802+ virtual bool canCreate(ProjectExplorer::Target *parent, Core::Id id) const override;
2803+ virtual bool canRestore(ProjectExplorer::Target *parent, const QVariantMap &map) const override;
2804+ virtual bool canClone(ProjectExplorer::Target *parent, ProjectExplorer::RunConfiguration *product) const override;
2805+ virtual ProjectExplorer::RunConfiguration *clone(ProjectExplorer::Target *parent, ProjectExplorer::RunConfiguration *product) override;
2806+
2807+private:
2808+ virtual ProjectExplorer::RunConfiguration *doCreate(ProjectExplorer::Target *parent, Core::Id id) override;
2809+ virtual ProjectExplorer::RunConfiguration *doRestore(ProjectExplorer::Target *parent, const QVariantMap &map) override;
2810+};
2811+
2812+} // namespace Internal
2813+} // namespace Ubuntu
2814+
2815+#endif // UBUNTU_INTERNAL_SNAPRUNCONFIGURATIONFACTORY_H
2816
2817=== added directory 'src/ubuntu/snap/settings'
2818=== added file 'src/ubuntu/snap/settings/snapcraftkitinformation.cpp'
2819--- src/ubuntu/snap/settings/snapcraftkitinformation.cpp 1970-01-01 00:00:00 +0000
2820+++ src/ubuntu/snap/settings/snapcraftkitinformation.cpp 2016-11-16 10:23:00 +0000
2821@@ -0,0 +1,114 @@
2822+#include "snapcraftkitinformation.h"
2823+
2824+#include <projectexplorer/kit.h>
2825+
2826+#include <utils/environment.h>
2827+#include <utils/qtcassert.h>
2828+#include <utils/pathchooser.h>
2829+
2830+#include <QFileInfo>
2831+
2832+namespace Ubuntu {
2833+namespace Internal {
2834+
2835+static const char TOOL_ID[] = "SnapcraftProjectManager.SnapcraftKitInformation";
2836+
2837+SnapcraftKitInformation::SnapcraftKitInformation()
2838+{
2839+ setObjectName(QStringLiteral("SnapcraftKitInformation"));
2840+ setId(TOOL_ID);
2841+ setPriority(29000);
2842+}
2843+
2844+Utils::FileName SnapcraftKitInformation::snapcraftPath(const ProjectExplorer::Kit *k)
2845+{
2846+ return k->value(TOOL_ID, QVariant::fromValue<Utils::FileName>(Utils::FileName())).value<Utils::FileName>();
2847+}
2848+
2849+void SnapcraftKitInformation::setSnapcraftPath(ProjectExplorer::Kit *k, const Utils::FileName &snapcraft)
2850+{
2851+ if (snapcraft.toFileInfo().isExecutable()) {
2852+ k->setValue(TOOL_ID, QVariant::fromValue<Utils::FileName>(snapcraft));
2853+ }
2854+}
2855+
2856+QVariant SnapcraftKitInformation::defaultValue(const ProjectExplorer::Kit *) const
2857+{
2858+ Utils::Environment env = Utils::Environment::systemEnvironment();
2859+ return QVariant::fromValue<Utils::FileName>(env.searchInPath(QStringLiteral("snapcraft")));
2860+}
2861+
2862+QList<ProjectExplorer::Task> SnapcraftKitInformation::validate(const ProjectExplorer::Kit *) const
2863+{
2864+ return QList<ProjectExplorer::Task>();
2865+}
2866+
2867+ProjectExplorer::KitInformation::ItemList SnapcraftKitInformation::toUserOutput(const ProjectExplorer::Kit *k) const
2868+{
2869+ Utils::FileName snap = snapcraftPath(k);
2870+ return ItemList {
2871+ qMakePair(tr("Snapcraft"), snap.exists() ? snap.toUserOutput() : tr("Unconfigured"))
2872+ };
2873+}
2874+
2875+ProjectExplorer::KitConfigWidget *SnapcraftKitInformation::createConfigWidget(ProjectExplorer::Kit *kit) const
2876+{
2877+ return new SnapcraftKitInformationWidget(kit, this);
2878+}
2879+
2880+SnapcraftKitInformationWidget::SnapcraftKitInformationWidget(ProjectExplorer::Kit *kit, const ProjectExplorer::KitInformation *ki)
2881+ : ProjectExplorer::KitConfigWidget(kit, ki)
2882+ , m_chooser(new Utils::PathChooser)
2883+ , m_ignoreChange(false)
2884+{
2885+ m_chooser->setExpectedKind(Utils::PathChooser::ExistingCommand);
2886+ m_chooser->setFileName(SnapcraftKitInformation::snapcraftPath(kit));
2887+ connect(m_chooser, &Utils::PathChooser::pathChanged,
2888+ this, &SnapcraftKitInformationWidget::pathWasChanged);
2889+}
2890+
2891+SnapcraftKitInformationWidget::~SnapcraftKitInformationWidget()
2892+{
2893+ delete m_chooser;
2894+}
2895+
2896+QString SnapcraftKitInformationWidget::displayName() const
2897+{
2898+ return tr("Snapcraft");
2899+}
2900+
2901+void SnapcraftKitInformationWidget::makeReadOnly()
2902+{
2903+ m_chooser->setReadOnly(true);
2904+}
2905+
2906+void SnapcraftKitInformationWidget::refresh()
2907+{
2908+ if (!m_ignoreChange)
2909+ m_chooser->setPath(SnapcraftKitInformation::snapcraftPath(kit()).toUserOutput());
2910+}
2911+
2912+QWidget *SnapcraftKitInformationWidget::mainWidget() const
2913+{
2914+ return m_chooser->lineEdit();
2915+}
2916+
2917+QString SnapcraftKitInformationWidget::toolTip() const
2918+{
2919+ return tr("The snapcraft binary to use for this kit.");
2920+}
2921+
2922+QWidget *SnapcraftKitInformationWidget::buttonWidget() const
2923+{
2924+ return m_chooser->buttonAtIndex(0);
2925+}
2926+
2927+void SnapcraftKitInformationWidget::pathWasChanged()
2928+{
2929+ m_ignoreChange = true;
2930+ SnapcraftKitInformation::setSnapcraftPath(kit(), m_chooser->fileName());
2931+ m_ignoreChange = false;
2932+}
2933+
2934+} // namespace Internal
2935+} // namespace Ubuntu
2936
2937=== added file 'src/ubuntu/snap/settings/snapcraftkitinformation.h'
2938--- src/ubuntu/snap/settings/snapcraftkitinformation.h 1970-01-01 00:00:00 +0000
2939+++ src/ubuntu/snap/settings/snapcraftkitinformation.h 2016-11-16 10:23:00 +0000
2940@@ -0,0 +1,59 @@
2941+#ifndef UBUNTU_INTERNAL_SNAPCRAFTKITINFORMATION_H
2942+#define UBUNTU_INTERNAL_SNAPCRAFTKITINFORMATION_H
2943+
2944+#include <projectexplorer/kitconfigwidget.h>
2945+#include <projectexplorer/kitinformation.h>
2946+
2947+namespace Utils {
2948+class PathChooser;
2949+}
2950+
2951+namespace Ubuntu {
2952+namespace Internal {
2953+
2954+class SnapcraftKitInformation : public ProjectExplorer::KitInformation
2955+{
2956+ Q_OBJECT
2957+public:
2958+ SnapcraftKitInformation();
2959+
2960+ static Utils::FileName snapcraftPath (const ProjectExplorer::Kit *k);
2961+ static void setSnapcraftPath (ProjectExplorer::Kit *k, const Utils::FileName &snapcraft);
2962+
2963+ // KitInformation interface
2964+ virtual QVariant defaultValue(const ProjectExplorer::Kit *) const override;
2965+ virtual QList<ProjectExplorer::Task> validate(const ProjectExplorer::Kit *) const override;
2966+ virtual ItemList toUserOutput(const ProjectExplorer::Kit *) const override;
2967+ virtual ProjectExplorer::KitConfigWidget *createConfigWidget(ProjectExplorer::Kit *) const override;
2968+
2969+private:
2970+ Utils::FileName m_snapcraftPath;
2971+};
2972+
2973+class SnapcraftKitInformationWidget : public ProjectExplorer::KitConfigWidget
2974+{
2975+public:
2976+ SnapcraftKitInformationWidget(ProjectExplorer::Kit *kit, const ProjectExplorer::KitInformation *ki);
2977+ virtual ~SnapcraftKitInformationWidget();
2978+
2979+ // KitConfigWidget interface
2980+ virtual QString displayName() const override;
2981+ virtual void makeReadOnly() override;
2982+ virtual void refresh() override;
2983+ virtual QWidget *mainWidget() const override;
2984+ virtual QString toolTip() const override;
2985+ virtual QWidget *buttonWidget() const override;
2986+
2987+private:
2988+ void pathWasChanged();
2989+private:
2990+ Utils::PathChooser *m_chooser;
2991+ bool m_ignoreChange;
2992+
2993+
2994+};
2995+
2996+} // namespace Internal
2997+} // namespace Ubuntu
2998+
2999+#endif // UBUNTU_INTERNAL_SNAPCRAFTKITINFORMATION_H
3000
3001=== added file 'src/ubuntu/snap/snap.pri'
3002--- src/ubuntu/snap/snap.pri 1970-01-01 00:00:00 +0000
3003+++ src/ubuntu/snap/snap.pri 2016-11-16 10:23:00 +0000
3004@@ -0,0 +1,31 @@
3005+
3006+LIBS+=-lyaml-cpp
3007+
3008+SOURCES += \
3009+ $$PWD/project/snapcraftproject.cpp \
3010+ $$PWD/project/snapcraftprojectfile.cpp \
3011+ $$PWD/project/snapcraftprojectnode.cpp \
3012+ $$PWD/project/snapcraftprojectmanager.cpp \
3013+ $$PWD/project/snapcraftbuildconfigurationfactory.cpp \
3014+ $$PWD/project/snapcraftbuildconfiguration.cpp \
3015+ $$PWD/project/snapcraftrsyncstep.cpp \
3016+ $$PWD/project/snapcraftstep.cpp \
3017+ $$PWD/project/snapcraftbuildstepfactory.cpp \
3018+ $$PWD/settings/snapcraftkitinformation.cpp \
3019+ $$PWD/project/snaprunconfiguration.cpp \
3020+ $$PWD/project/snaprunconfigurationfactory.cpp
3021+
3022+HEADERS += \
3023+ $$PWD/project/snapcraftproject.h \
3024+ $$PWD/project/snapcraftprojectfile.h \
3025+ $$PWD/project/snapcraftprojectnode.h \
3026+ $$PWD/project/snapcraftprojectmanager.h \
3027+ $$PWD/project/snapcraftbuildconfigurationfactory.h \
3028+ $$PWD/project/snapcraftbuildconfiguration.h \
3029+ $$PWD/project/snapcraftrsyncstep.h \
3030+ $$PWD/project/snapcraftstep.h \
3031+ $$PWD/project/snapcraftbuildstepfactory.h \
3032+ $$PWD/settings/snapcraftkitinformation.h \
3033+ $$PWD/project/snaprunconfiguration.h \
3034+ $$PWD/project/snaprunconfigurationfactory.h
3035+
3036
3037=== modified file 'src/ubuntu/snap/snapcraftpackagestep.cpp'
3038--- src/ubuntu/snap/snapcraftpackagestep.cpp 2016-09-22 13:17:48 +0000
3039+++ src/ubuntu/snap/snapcraftpackagestep.cpp 2016-11-16 10:23:00 +0000
3040@@ -37,7 +37,7 @@
3041 namespace Ubuntu {
3042 namespace Internal {
3043
3044-const char * PACKAGE_NAME_REGEX = "^Snapped ([\\S]+\\.snap)$";
3045+static const char * PACKAGE_NAME_REGEX = "^Snapped ([\\S]+\\.snap)$";
3046
3047 SnapcraftPackageStep::SnapcraftPackageStep(ProjectExplorer::BuildStepList *bsl)
3048 : ProjectExplorer::BuildStep (bsl, Constants::UBUNTU_SNAP_PACKAGESTEP_ID)
3049
3050=== modified file 'src/ubuntu/ubuntuclicktool.cpp'
3051--- src/ubuntu/ubuntuclicktool.cpp 2016-08-18 06:42:19 +0000
3052+++ src/ubuntu/ubuntuclicktool.cpp 2016-11-16 10:23:00 +0000
3053@@ -471,6 +471,11 @@
3054 return UbuntuClickTool::findOrCreateToolWrapper(QStringLiteral("make"),target);
3055 }
3056
3057+Utils::FileName UbuntuClickTool::findOrCreateSnapcraftWrapper(const UbuntuClickTool::Target &target)
3058+{
3059+ return Utils::FileName::fromString(UbuntuClickTool::findOrCreateToolWrapper(QStringLiteral("snapcraft"),target));
3060+}
3061+
3062 QString UbuntuClickTool::mapIncludePathsForCMake(const ProjectExplorer::Kit *k, const QString &in)
3063 {
3064 if (in.isEmpty())
3065
3066=== modified file 'src/ubuntu/ubuntuclicktool.h'
3067--- src/ubuntu/ubuntuclicktool.h 2016-07-20 14:56:52 +0000
3068+++ src/ubuntu/ubuntuclicktool.h 2016-11-16 10:23:00 +0000
3069@@ -86,6 +86,7 @@
3070 static QString findOrCreateToolWrapper(const QString &tool, const UbuntuClickTool::Target &target);
3071 static QString findOrCreateQMakeWrapper(const UbuntuClickTool::Target &target);
3072 static QString findOrCreateMakeWrapper(const UbuntuClickTool::Target &target);
3073+ static Utils::FileName findOrCreateSnapcraftWrapper(const UbuntuClickTool::Target &target);
3074 static QString mapIncludePathsForCMake(const ProjectExplorer::Kit *k, const QString &in);
3075 static QString hostArchitecture ();
3076 static bool compatibleWithHostArchitecture (const QString &targetArch);
3077
3078=== modified file 'src/ubuntu/ubuntuconstants.h'
3079--- src/ubuntu/ubuntuconstants.h 2016-09-22 13:17:48 +0000
3080+++ src/ubuntu/ubuntuconstants.h 2016-11-16 10:23:00 +0000
3081@@ -260,23 +260,21 @@
3082 const char FEATURE_UBUNTU_TRUSTY[] = "Ubuntu.Wizards.FeatureUbuntuTrusty";
3083 const char FEATURE_UBUNTU_UTOPIC[] = "Ubuntu.Wizards.FeatureUbuntuUtopic";
3084
3085-const char DISTRIB_ID[] = "DISTRIB_ID=";
3086-const char DISTRIB_CODENAME[] = "DISTRIB_CODENAME=";
3087-const char DISTRIB_RELEASE[] = "DISTRIB_RELEASE=";
3088-const char DISTRIB_DESCRIPTION[] = "DISTRIB_DESCRIPTION=";
3089-const char LSB_RELEASE[] = "/etc/lsb-release";
3090-
3091-const char PRECISE[] = "precise";
3092-const char QUANTAL[] = "quantal";
3093-const char RARING[] = "raring";
3094-const char SAUCY[] = "saucy";
3095-const char TRUSTY[] = "trusty";
3096-const char UTOPIC[] = "utopic";
3097-
3098 const char PLATFORM_DESKTOP[] = "Desktop";
3099 const char PLATFORM_DESKTOP_DISPLAYNAME[] = "Ubuntu %0";
3100+
3101+const QString PRECISE (QStringLiteral("precise"));
3102+const QString QUANTAL (QStringLiteral("quantal"));
3103+const QString RARING (QStringLiteral("raring"));
3104+const QString SAUCY (QStringLiteral("saucy"));
3105+const QString TRUSTY (QStringLiteral("trusty"));
3106+const QString UTOPIC (QStringLiteral("utopic"));
3107+const QString VIVID (QStringLiteral("vivid"));
3108+const QString WILY (QStringLiteral("wily"));
3109 */
3110
3111+const QString XENIAL (QStringLiteral("xenial"));
3112+
3113 const char TASK_DEVICE_SCRIPT[] = "Ubuntu.Task.DeviceScript";
3114
3115 const char UBUNTU_SETTINGS_ICON[] = ":/ubuntu/images/ubuntu-32.png";
3116@@ -393,6 +391,17 @@
3117 const char CHROOT_UPDATE_LIST_SCRIPT[] = "%1/ubuntu/scripts/qtc_chroot_get_upgrades.py %2 %3";
3118
3119
3120+//Snapcraft
3121+const char SNAPCRAFT_PROJECT_MIMETYPE[] = "application/x-snapcraft";
3122+const char SNAPCRAFT_PROJECT_ID[ ] = "SnapcraftProjectManager.SnapcraftProject";
3123+const char SNAPCRAFT_PROJECT_PROJECTCONTEXT[] = "SnapcraftProject.ProjectContext";
3124+const char SNAPCRAFT_BUILDCONFIGURATION_ID[] = "SnapcraftProjectManager.SnapcraftBuildconfiguration.Id";
3125+const char SNAPCRAFT_RSYNCBUILSSTEP_ID[] = "SnapcraftProjectManager.SnapcraftRsyncStep.Id";
3126+const char SNAPCRAFT_BUILDSTEP_ID[] = "SnapcraftProjectManager.SnapcraftStep.Id";
3127+const char SNAP_RUNCONFIGURATION_ID[] = "SnapcraftProjectManager.SnapRunConfiguration.Id";
3128+
3129+
3130+
3131 } // namespace Ubuntu
3132 } // namespace Constants
3133
3134
3135=== modified file 'src/ubuntu/ubuntujsextension.cpp'
3136--- src/ubuntu/ubuntujsextension.cpp 2016-09-22 13:17:48 +0000
3137+++ src/ubuntu/ubuntujsextension.cpp 2016-11-16 10:23:00 +0000
3138@@ -15,8 +15,11 @@
3139 *
3140 * Author: Benjamin Zeller <benjamin.zeller@canonical.com>
3141 */
3142+
3143 #include "ubuntujsextension.h"
3144 #include <ubuntu/ubuntubzr.h>
3145+#include <ubuntu/ubuntuversion.h>
3146+#include <ubuntu/ubuntuconstants.h>
3147
3148 namespace Ubuntu {
3149 namespace Internal {
3150@@ -43,4 +46,12 @@
3151 return maintainer;
3152 }
3153
3154+bool UbuntuJsExtension::supportsSnappy() const
3155+{
3156+ UbuntuVersion *v = UbuntuVersion::instance();
3157+ if (v->isValid())
3158+ return v->supportsSnappy();
3159+ return false;
3160+}
3161+
3162 }}
3163
3164=== modified file 'src/ubuntu/ubuntujsextension.h'
3165--- src/ubuntu/ubuntujsextension.h 2016-09-22 13:17:48 +0000
3166+++ src/ubuntu/ubuntujsextension.h 2016-11-16 10:23:00 +0000
3167@@ -30,6 +30,7 @@
3168 explicit UbuntuJsExtension(QObject *parent = 0);
3169
3170 Q_INVOKABLE QString developerId() const;
3171+ Q_INVOKABLE bool supportsSnappy() const;
3172 };
3173
3174 }}
3175
3176=== modified file 'src/ubuntu/ubuntukitmanager.cpp'
3177--- src/ubuntu/ubuntukitmanager.cpp 2016-08-18 06:42:19 +0000
3178+++ src/ubuntu/ubuntukitmanager.cpp 2016-11-16 10:23:00 +0000
3179@@ -5,7 +5,8 @@
3180 #include "ubuntuclickdialog.h"
3181 #include "ubuntuqtversion.h"
3182 #include "settings.h"
3183-#include "device/container/containerdevice.h"
3184+#include <ubuntu/device/container/containerdevice.h>
3185+#include <ubuntu/snap/settings/snapcraftkitinformation.h>
3186
3187 #include <coreplugin/icore.h>
3188 #include <projectexplorer/kitmanager.h>
3189@@ -509,6 +510,8 @@
3190 ProjectExplorer::SysRootKitInformation::setSysRoot(k,Utils::FileName::fromString(UbuntuClickTool::targetBasePath(tc->clickTarget())));
3191 }
3192
3193+ SnapcraftKitInformation::setSnapcraftPath(k, UbuntuClickTool::findOrCreateSnapcraftWrapper(tc->clickTarget()));
3194+
3195 //make sure we point to a ubuntu device
3196 Core::Id devId = ProjectExplorer::DeviceTypeKitInformation::deviceTypeId(k);
3197 bool devValid = devId.isValid(); //invalid type
3198
3199=== modified file 'src/ubuntu/ubuntuplugin.cpp'
3200--- src/ubuntu/ubuntuplugin.cpp 2016-09-22 15:50:17 +0000
3201+++ src/ubuntu/ubuntuplugin.cpp 2016-11-16 10:23:00 +0000
3202@@ -52,6 +52,13 @@
3203 #include <ubuntu/wizards/ubuntuprojectapplicationwizard.h>
3204 #include <ubuntu/wizards/ubuntufirstrunwizard.h>
3205 #include <ubuntu/wizards/ubuntuprojectmigrationwizard.h>
3206+#include <ubuntu/ubuntuversion.h>
3207+
3208+#include <ubuntu/snap/project/snapcraftprojectmanager.h>
3209+#include <ubuntu/snap/project/snapcraftbuildconfigurationfactory.h>
3210+#include <ubuntu/snap/project/snapcraftbuildstepfactory.h>
3211+#include <ubuntu/snap/settings/snapcraftkitinformation.h>
3212+#include <ubuntu/snap/project/snaprunconfiguration.h>
3213
3214 #include "ubuntujsextension.h"
3215
3216@@ -84,6 +91,8 @@
3217
3218 #include <coreplugin/icore.h>
3219 #include <stdint.h>
3220+#include <unistd.h>
3221+#include <sys/types.h>
3222
3223
3224 using namespace Ubuntu;
3225@@ -116,6 +125,11 @@
3226 defaultFont.setFamily(QStringLiteral("Ubuntu"));
3227 defaultFont.setWeight(QFont::Light);
3228
3229+
3230+ if (::getuid() == 0) {
3231+ criticalError(tr("\nThe Ubuntu SDK can not be used as superuser."));
3232+ return false;
3233+ }
3234 if (QStandardPaths::findExecutable(QStringLiteral("lxc")).isEmpty()) {
3235 criticalError(tr("\nLxd is not installed properly.\nIt is required for the Ubuntu-SDK-IDE to work."));
3236 return false;
3237@@ -175,6 +189,16 @@
3238 addAutoReleasedObject(new UbuntuRemoteRunControlFactory);
3239 addAutoReleasedObject(new UbuntuLocalRunControlFactory);
3240
3241+
3242+ if (UbuntuVersion::instance()->supportsSnappy()) {
3243+ addAutoReleasedObject(new SnapcraftProjectManager);
3244+ addAutoReleasedObject(new SnapcraftBuildConfigurationFactory);
3245+ addAutoReleasedObject(new SnapcraftBuildStepFactory);
3246+ addAutoReleasedObject(new SnapRunConfigurationFactory);
3247+
3248+ ProjectExplorer::KitManager::registerKitInformation(new SnapcraftKitInformation);
3249+ }
3250+
3251 // Build support
3252 addAutoReleasedObject(new ClickToolChainFactory);
3253 addAutoReleasedObject(new UbuntuHtmlBuildConfigurationFactory);
3254@@ -379,6 +403,7 @@
3255
3256 while (!ok) {
3257 QProcess proc;
3258+ qDebug()<<"Running "<<Constants::UBUNTU_TARGET_TOOL;
3259 proc.setProgram(Constants::UBUNTU_TARGET_TOOL);
3260
3261 QStringList args{QStringLiteral("initialized")};
3262@@ -401,14 +426,13 @@
3263 case ERR_NO_ACCESS:
3264 //the tool tells us that we have no access to the LXD server
3265 criticalError(tr("The current user can not access the LXD server which is required for the Ubuntu SDK.\n"
3266- "Make sure the user is part of the lxd group and restart the IDE."));
3267+ "Make sure the user is part of the lxd group, relogin and restart the IDE."));
3268 break;
3269 case ERR_NO_BRIDGE:
3270 if (Settings::askForContainerSetup()) {
3271 QString text = tr("The container backend is not completely initialized.\n\n"
3272 "Create default configuration?\n"
3273- "Not setting up the container configuration will\nmake it impossible to run applications locally.\n\n"
3274- "Note: Will override existing LXD configurations."
3275+ "Not setting up the container configuration will\nmake it impossible to run applications locally."
3276 );
3277
3278 QMessageBox box(QMessageBox::Question, qApp->applicationName(),text, QMessageBox::Yes | QMessageBox::No | QMessageBox::Abort, Core::ICore::mainWindow());
3279
3280=== modified file 'src/ubuntu/ubuntuversion.cpp'
3281--- src/ubuntu/ubuntuversion.cpp 2014-05-27 15:53:25 +0000
3282+++ src/ubuntu/ubuntuversion.cpp 2016-11-16 10:23:00 +0000
3283@@ -21,61 +21,59 @@
3284 #include <QFile>
3285 #include <QStringList>
3286
3287-using namespace Ubuntu::Internal;
3288+namespace Ubuntu {
3289+namespace Internal {
3290+
3291+Q_GLOBAL_STATIC(UbuntuVersion, g_instance);
3292+
3293+const char DISTRIB_ID[] = "DISTRIB_ID=";
3294+const char DISTRIB_CODENAME[] = "DISTRIB_CODENAME=";
3295+const char DISTRIB_RELEASE[] = "DISTRIB_RELEASE=";
3296+const char DISTRIB_DESCRIPTION[] = "DISTRIB_DESCRIPTION=";
3297+const char LSB_RELEASE[] = "/etc/lsb-release";
3298
3299 UbuntuVersion::UbuntuVersion()
3300 {
3301-
3302-}
3303-
3304-Core::FeatureSet UbuntuVersion::features() {
3305- Core::FeatureSet retval;
3306-
3307- QString cName = codename();
3308- if (cName==QLatin1String(Constants::PRECISE)) {
3309- retval |= Core::FeatureSet(Constants::FEATURE_UBUNTU_PRECISE);
3310- } else if (cName==QLatin1String(Constants::QUANTAL)) {
3311- retval |= Core::FeatureSet(Constants::FEATURE_UBUNTU_QUANTAL);
3312- } else if (cName==QLatin1String(Constants::RARING)) {
3313- retval |= Core::FeatureSet(Constants::FEATURE_UBUNTU_RARING);
3314- } else if (cName==QLatin1String(Constants::SAUCY)) {
3315- retval |= Core::FeatureSet(Constants::FEATURE_UBUNTU_SAUCY);
3316- retval |= Core::FeatureSet(Constants::FEATURE_UNITY_SCOPE);
3317- } else if (cName==QLatin1String(Constants::TRUSTY)) {
3318- retval |= Core::FeatureSet(Constants::FEATURE_UBUNTU_TRUSTY);
3319- retval |= Core::FeatureSet(Constants::FEATURE_UNITY_SCOPE);
3320- } else if (cName==QLatin1String(Constants::UTOPIC)) {
3321- retval |= Core::FeatureSet(Constants::FEATURE_UBUNTU_UTOPIC);
3322- retval |= Core::FeatureSet(Constants::FEATURE_UNITY_SCOPE);
3323- }
3324- return retval;
3325-}
3326-
3327-UbuntuVersion *UbuntuVersion::fromLsbFile(const QString &fileName)
3328-{
3329- QFile lsbRelease(fileName);
3330+ initFromLsbFile();
3331+}
3332+
3333+bool UbuntuVersion::supportsSnappy() const
3334+{
3335+ if (m_valid)
3336+ return codename() == Constants::XENIAL;
3337+ return false;
3338+}
3339+
3340+UbuntuVersion *UbuntuVersion::instance()
3341+{
3342+ return g_instance();
3343+}
3344+
3345+void UbuntuVersion::initFromLsbFile()
3346+{
3347+ QFile lsbRelease(QString::fromLatin1(LSB_RELEASE));
3348 if (lsbRelease.open(QIODevice::ReadOnly)) {
3349 QByteArray data = lsbRelease.readAll();
3350 lsbRelease.close();
3351
3352- UbuntuVersion *ver = new UbuntuVersion;
3353-
3354 foreach(QString line, QString::fromLatin1(data).split(QLatin1String("\n"))) {
3355- if (line.startsWith(QLatin1String(Constants::DISTRIB_ID))) {
3356- ver->m_id = line.replace(QLatin1String(Constants::DISTRIB_ID),QLatin1String(""));
3357-
3358- } else if (line.startsWith(QLatin1String(Constants::DISTRIB_RELEASE))) {
3359- ver->m_release = line.replace(QLatin1String(Constants::DISTRIB_RELEASE),QLatin1String(""));
3360-
3361- } else if (line.startsWith(QLatin1String(Constants::DISTRIB_CODENAME))) {
3362- ver->m_codename = line.replace(QLatin1String(Constants::DISTRIB_CODENAME),QLatin1String(""));
3363-
3364- } else if (line.startsWith(QLatin1String(Constants::DISTRIB_DESCRIPTION))) {
3365- ver->m_description = line.replace(QLatin1String(Constants::DISTRIB_DESCRIPTION),QLatin1String(""));
3366+ if (line.startsWith(QLatin1String(DISTRIB_ID))) {
3367+ m_id = line.replace(QLatin1String(DISTRIB_ID),QLatin1String(""));
3368+
3369+ } else if (line.startsWith(QLatin1String(DISTRIB_RELEASE))) {
3370+ m_release = line.replace(QLatin1String(DISTRIB_RELEASE),QLatin1String(""));
3371+
3372+ } else if (line.startsWith(QLatin1String(DISTRIB_CODENAME))) {
3373+ m_codename = line.replace(QLatin1String(DISTRIB_CODENAME),QLatin1String(""));
3374+
3375+ } else if (line.startsWith(QLatin1String(DISTRIB_DESCRIPTION))) {
3376+ m_description = line.replace(QLatin1String(DISTRIB_DESCRIPTION),QLatin1String(""));
3377 }
3378 }
3379
3380- return ver;
3381+ m_valid = true;
3382 }
3383- return 0;
3384 }
3385+
3386+}}
3387+
3388
3389=== modified file 'src/ubuntu/ubuntuversion.h'
3390--- src/ubuntu/ubuntuversion.h 2014-05-27 15:53:25 +0000
3391+++ src/ubuntu/ubuntuversion.h 2016-11-16 10:23:00 +0000
3392@@ -27,28 +27,30 @@
3393 namespace Internal {
3394
3395
3396-class UbuntuVersion : public QObject
3397+class UbuntuVersion
3398 {
3399- Q_OBJECT
3400-
3401 public:
3402 explicit UbuntuVersion();
3403
3404 public slots:
3405- QString id() { return m_id; }
3406- QString release() { return m_release; }
3407- QString codename() { return m_codename; }
3408- QString description() { return m_description; }
3409-
3410- Core::FeatureSet features();
3411-
3412- static UbuntuVersion *fromLsbFile( const QString &fileName );
3413+ bool isValid () const { return m_valid; }
3414+ QString id() const { return m_id; }
3415+ QString release() const { return m_release; }
3416+ QString codename() const { return m_codename; }
3417+ QString description() const { return m_description; }
3418+ bool supportsSnappy () const;
3419+
3420+ static UbuntuVersion *instance( );
3421+
3422+protected:
3423+ void initFromLsbFile( );
3424
3425 protected:
3426 QString m_id;
3427 QString m_release;
3428 QString m_codename;
3429 QString m_description;
3430+ bool m_valid = false;
3431 };
3432 }
3433 }

Subscribers

People subscribed via source and target branches