I have made the following changes intended for : CE:Apps / qmlgallery Please review and accept or decline. BOSS has already run some checks on this request. See the "Messages from BOSS" section below.
https://build.pub.meego.com//request/show/6314 Thank You, faenil [This message was auto-generated] --- Request # 6314: Messages from BOSS: State: review at 2012-08-29T01:27:29 by bossbot Reviews: accepted by bossbot : Prechecks succeeded. new for CE-maintainers : Please replace this text with a review and approve/reject the review (not the SR). BOSS will take care of the rest Changes: submit: home:faenil:branches:CE:Apps / qmlgallery -> CE:Apps / qmlgallery changes files: -------------- --- qmlgallery.changes +++ qmlgallery.changes @@ -0,0 +1,6 @@ +* Wed Aug 29 2012 Andrea Bernabei <[email protected]> - 0.0.9 +- Fixes NEMO#260: Feature: videos to the gallery +- Fixes NEMO#412: Add possibility to show only videos or only pictures +- Fixes NEMO#400: Rotating photos is printing extra messages to .xsession-errors +- Fixes .desktop file (part of NEMO#407) + old: ---- 0001-NEMO-363-Use-single-instance-invoker-to-launch.patch qmlgallery-0.0.8.tar.bz2 new: ---- qmlgallery-0.0.9.tar.bz2 spec files: ----------- --- qmlgallery.spec +++ qmlgallery.spec @@ -1,6 +1,6 @@ # # Do NOT Edit the Auto-generated Part! -# Generated by: spectacle version 0.25 +# Generated by: spectacle version 0.24 # Name: qmlgallery @@ -9,20 +9,20 @@ # << macros Summary: Photo Gallery for Nemo -Version: 0.0.8 +Version: 0.0.9 Release: 1 Group: Applications/System License: BSD URL: https://github.com/nemomobile/qmlgallery Source0: %{name}-%{version}.tar.bz2 Source100: qmlgallery.yaml -Patch0: 0001-NEMO-363-Use-single-instance-invoker-to-launch.patch Requires: libdeclarative-gallery Requires: nemo-qml-plugins-thumbnailer BuildRequires: pkgconfig(QtCore) >= 4.7.0 BuildRequires: pkgconfig(QtDeclarative) BuildRequires: pkgconfig(QtGui) BuildRequires: pkgconfig(qdeclarative-boostable) +BuildRequires: pkgconfig(QtOpenGL) BuildRequires: desktop-file-utils Provides: meego-handset-video > 0.2.5 Obsoletes: meego-handset-video <= 0.2.5 @@ -32,10 +32,8 @@ %prep -%setup -q -n %{name} +%setup -q -n %{name}-%{version} -# 0001-NEMO-363-Use-single-instance-invoker-to-launch.patch -%patch0 -p1 # >> setup # << setup other changes: -------------- ++++++ qmlgallery-0.0.8.tar.bz2 -> qmlgallery-0.0.9.tar.bz2 --- images +++ images +(directory) Binary files images/DefaultVideoThumbnail.jpg added Binary files images/GridVideoThumbnail.jpg added --- main.cpp +++ main.cpp @@ -36,6 +36,7 @@ #include <QDeclarativeContext> #include <QDebug> #include <QDir> +#include <QGLWidget> #ifdef HAS_BOOSTER #include <applauncherd/MDeclarativeCache> #endif @@ -58,6 +59,13 @@ view = &stackView; #endif + //NOTE: if we don't use a QGLWidget as viewport, the gallery lags once we load a video + //(you get the warning "QGLWindowSurface: Using plain widget as window surface QGLWindowSurface") + //and it won't stop lagging until you exit the app, in fact it seems the QGraphicsVideoItem + //used to play the video is never destroyed + QGLWidget *renderer = new QGLWidget(); + view->setViewport(renderer); + bool isFullscreen = false; QStringList arguments = application->arguments(); for (int i = 0; i < arguments.count(); ++i) { --- qml/FileTypeChoiceDialog.qml +++ qml/FileTypeChoiceDialog.qml @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2012 Andrea Bernabei <[email protected]> + * + * You may use this file under the terms of the BSD license as follows: + * + * "Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Nemo Mobile nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." + */ +import QtQuick 1.1 +import com.nokia.meego 1.0 + +SelectionDialog { + id: mediaTypeFilterDialog + titleText: "Choose file type" + model: ListModel { + ListElement {name: "Videos only"} + ListElement {name: "Images only"} + ListElement {name: "Both"} + } + + //we show Both videos and photos by default, + //and we don't destroy this Dialog once it's created, so we don't need to check the current filtering status + selectedIndex: 2 + + onSelectedIndexChanged: { + switch(model.get(selectedIndex).name) { + case "Videos only": + var vidFilter = gallery.createFilter(gallery, "videosfilter", "GalleryStartsWithFilter", "mimeType", "video/") + gallery.assignNewDestroyCurrent(vidFilter) + break; + case "Images only": + var imgFilter = gallery.createFilter(gallery, "imagesfilter", "GalleryStartsWithFilter", "mimeType", "image/") + gallery.assignNewDestroyCurrent(imgFilter) + break; + case "Both": + var videoFilter = gallery.createFilter(gallery, "videosfilter", "GalleryStartsWithFilter", "mimeType", "video/") + var imageFilter = gallery.createFilter(gallery, "imagesfilter", "GalleryStartsWithFilter", "mimeType", "image/") + var bothFilter = gallery.createFiltersArray(gallery, "arraysFilter", "GalleryFilterUnion", [videoFilter, imageFilter]) + gallery.assignNewDestroyCurrent(bothFilter) + break; + } + } +} --- qml/ImageContainer.qml +++ qml/ImageContainer.qml @@ -31,17 +31,20 @@ import QtQuick 1.1 import com.nokia.meego 1.0 +import QtMobility.gallery 1.1 Item { id: imgContainer - property int index: -1 + property variant imgController: imageController + property bool isVideo: galleryModel.isVideo(index) + + //used inside ImagePage's imgFlickable to get the bounding rectangle of the image + property alias image: img + width: imgController.imgContainerWidth height: imgController.imgContainerHeight - //This item has to be child of the controller - property variant imgController: parent - function resetZoom() { //resetting all variables related to pinch-to-zoom img.scale = 1 @@ -56,7 +59,7 @@ anchors.fill: imgContainer //Disable the pincharea if the listview is scrolling, to avoid problems - enabled: !imgController.moving + enabled: (!imgController.moving && !isVideo) pinch.target: img pinch.maximumScale: 5 pinch.dragAxis: Pinch.NoDrag @@ -211,22 +214,26 @@ Image { id: img - - //For Harmattan/Nemo ( THIS PART HAS TO BE FIXED , THE IMAGE IS NOT SCALED TO FILL THE SCREEN ATM) - property real imgRatio: galleryModel.get(index).width / galleryModel.get(index).height - property bool fitsVertically: imgRatio < (imgContainer.width / imgContainer.height) width: (fitsVertically) ? (imgController.height * imgRatio) : imgController.width height: (fitsVertically) ? (imgController.height) : (imgController.width / imgRatio) - //For Simulator: - //width: 480 - //fillMode: Image.PreserveAspectFit + property int imgWidth: isVideo ? videoThumbnailSize : (info.available ? info.metaData.width : -1) + property int imgHeight: isVideo ? videoThumbnailSize : (info.available ? info.metaData.height : -1) + property real imgRatio: imgWidth / imgHeight + property bool fitsVertically: imgRatio < (imgContainer.width / imgContainer.height) + + //DocumentGalleryItem automatically recognizes the rootType of the file + DocumentGalleryItem { + id: info + item: galleryModel.get(index).itemId + autoUpdate: true + properties: ["width", "height", "url"] + } transformOrigin: Item.TopLeft asynchronous: true - source: galleryModel.get(index).url - sourceSize.width: 2000 - sourceSize.height: 2000 + source: isVideo ? "qrc:/images/DefaultVideoThumbnail.jpg" : galleryModel.get(index).url + sourceSize.width: 1200 //Disable ListView scrolling if you're zooming onScaleChanged: { @@ -237,22 +244,14 @@ MouseArea { anchors.fill: parent - Timer { - id: doubleClickTimer - interval: 350 - } - - // onDoubleClicked seems broken on-device with all of the flickable/pincharea here onClicked: { - if (doubleClickTimer.running) resetZoom() - else doubleClickTimer.start() + if (!isVideo) { + if (imgController.doubleClickTimer.running) resetZoom() + else imgController.doubleClickTimer.start() + } } } } - } - } - - } --- qml/ImagePage.qml +++ qml/ImagePage.qml @@ -61,10 +61,24 @@ //number of pixel you have to move before the Pinch Area is disabled property real pinchThreshold: 3 property alias flickAreaEnabled: imgFlickable.enabled + property variant doubleClickTimer: timer + property int doubleClickInterval: 350 + property int videoThumbnailSize: 480 + //This property forces the middle item to be visible on screen by keeping the leftMost item at x = leftMostOptimalX + //You have to set it to FALSE when you want to want to modify leftMost's x property, and set it back to true + //to be sure that the middle item will be the one centered on screen. + //(e.g. this is what flickTo NumberAnimation does) + property bool keepMiddleItemAligned: true onWidthChanged: { - middle.resetZoom() - alignToCenter() + if (!middle.isVideo) + middle.resetZoom() + } + + function showVideoPlayer() { + appWindow.pageStack.push(Qt.resolvedUrl("VideoPlayer.qml"), + {videoSource: galleryModel.get(middle.index).url, imgController: imageController}, + true) } function modulus(a, b) { @@ -72,8 +86,10 @@ else return a % b } - function alignToCenter() { - leftMost.x = leftMostOptimalX + function isInside(x, y, rect) { + var rectAbsolute = rect.mapToItem(imageController, rect.x, rect.y) + return ((x > rectAbsolute.x) && (x < rectAbsolute.x + rect.width) && + (y > rectAbsolute.y) && (y < rectAbsolute.y + rect.height)) } function swapLeftMost() { @@ -89,7 +105,7 @@ rightMiddle = rightMost rightMost = oldLeftMost //set the index (relative to galleryModel) of the image which has to be loaded by the shifted image container - rightMost.index = modulus(middle.index + 2, imageController.galleryModel.count); + rightMost.index = modulus(middle.index + 2, galleryModel.count); } function swapRightMost() { @@ -103,7 +119,7 @@ middle = leftMiddle leftMiddle = leftMost leftMost = oldRightMost - leftMost.index = modulus(middle.index - 2, imageController.galleryModel.count); + leftMost.index = modulus(middle.index - 2, galleryModel.count); } NumberAnimation { @@ -114,49 +130,64 @@ to: flickToX; duration: 300; easing.type: Easing.OutQuad + onStarted: keepMiddleItemAligned = false onCompleted: { if (Math.abs(to - from) > swipeThreshold) { if (from > to ) swapLeftMost() else swapRightMost() - //center flickable view, this allows endless scrolling - alignToCenter() } + keepMiddleItemAligned = true //This should be the only way the view can stop moving, so we set moving to false moving = false } } - //create items and position them in a row, - // ------ImageContainer must be child of the images controller ----- + //This is to keep the middle item visible on screen. + //Read the comment above the definition of keepMiddleItemAligned to know more + Binding { + target: leftMost + value: leftMostOptimalX + property: "x" + when: keepMiddleItemAligned + } + ImageContainer { id: one; - x: leftMostOptimalX; index: modulus(visibleIndex - 2, galleryModel.count) + x: leftMostOptimalX } + ImageContainer { id: two anchors.left: one.right index: modulus(visibleIndex - 1, galleryModel.count) } + ImageContainer { id: three anchors.left: two.right index: visibleIndex } + ImageContainer { id: four anchors.left: three.right index: modulus (visibleIndex + 1, galleryModel.count) } + ImageContainer { id: five anchors.left: four.right index: modulus (visibleIndex + 2, galleryModel.count) } + Timer { + id: timer + interval: doubleClickInterval + } MouseArea { id: imgFlickable @@ -164,6 +195,21 @@ property bool pressedForClick: false + //HACK: this mousarea is disabled when the image is zoomed, and the mousearea inside the imageContainer's img is disabled when zoom factor is 1, + //so we have to get the doubleClick event here when the zoom factor is 1, and inside imageContainer's img when the image is zoomed. + //This is due to the high number of mouse areas (pincharea, flickable, multiple mouseareas) available in the same view + //Adding another MouseArea to handle this only made things worse + //comment added by faenil + onClicked: { + if (!imageController.moving && isInside(mouse.x, mouse.y, middle.image)) { + if (!middle.isVideo) { + if (doubleClickTimer.running) {} //TODO: IMPLEMENT ZOOM-IN VIA DOUBLECLICK INSIDE THE CURLY BRACKETS + else doubleClickTimer.start() + } + else showVideoPlayer() + } + } + onPressed: { firstPressX = mouseX pressX = mouseX @@ -210,6 +256,7 @@ flickTo.start() } } + Menu { id: pageMenu MenuLayout { @@ -222,6 +269,7 @@ } } } + ToolBarLayout { id: imgTools ToolIcon { --- qml/MainPage.qml +++ qml/MainPage.qml @@ -47,9 +47,15 @@ anchors.fill: parent onClicked: appWindow.pageStack.push(Qt.resolvedUrl("ImagePage.qml"), {visibleIndex: index, galleryModel: gallery} ) } + } } + Loader { + id: typeChoiceLoader + anchors.fill: parent + } + ToolBarLayout { id: mainTools ToolIcon { @@ -66,6 +72,13 @@ text: "Slideshow" onClicked: appWindow.pageStack.push(Qt.resolvedUrl("ImageSlideshowPage.qml"), {visibleIndex: 0, galleryModel: gallery}) } + MenuItem { + text: "Change type of shown files" + onClicked: { + typeChoiceLoader.source = Qt.resolvedUrl("FileTypeChoiceDialog.qml") + typeChoiceLoader.item.open() + } + } } } --- qml/VideoPlayer.qml +++ qml/VideoPlayer.qml @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2012 Andrea Bernabei <[email protected]> + * + * You may use this file under the terms of the BSD license as follows: + * + * "Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Nemo Mobile nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." + */ + +import QtQuick 1.1 +import com.nokia.meego 1.0 +import QtMultimediaKit 1.1 + +Page { + id: videoContainer + + tools: videoTools + orientationLock: PageOrientation.LockLandscape + + property alias videoSource: videoItem.source + + //force fullscreen = false, until we find a way to make the controls appear + //on top of the video without flickering and slowdown + Component.onCompleted: appWindow.fullscreen = false + + Video { + id: videoItem + anchors.fill: parent + fillMode: Video.PreserveAspectFit + + //autoLoad: true doesn't seem to be working + Component.onCompleted: play() + + MouseArea { + anchors.fill: parent + onClicked: !parent.paused ? parent.pause() : parent.play() + } + } + + ToolBarLayout { + id: videoTools + + ToolIcon { + platformIconId: "toolbar-back" + anchors.left: (parent === undefined) ? undefined : parent.left + onClicked: { + //Stopping the video wasn't enough, it would cause flickering + videoItem.source = "" + appWindow.pageStack.pop() + } + } + } + +} --- qml/api/GalleryDelegate.qml +++ qml/api/GalleryDelegate.qml @@ -32,6 +32,7 @@ import QtQuick 1.1 Image { + id: del width: GridView.view.thumbnailSize height: GridView.view.thumbnailSize @@ -39,6 +40,7 @@ // end hack asynchronous: true - source: "image://nemoThumbnail/" + url + //index is -1 when filters the model is reinitialized (e.g. filters change) so we have to treat that case too + source: (index == -1) ? "" : (GridView.view.model.isVideo(index) ? "qrc:/images/GridVideoThumbnail.jpg" : "image://nemoThumbnail/" + url) } --- qml/api/GalleryModel.qml +++ qml/api/GalleryModel.qml @@ -28,13 +28,57 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." */ - +import QtQuick 1.1 import QtMobility.gallery 1.1 DocumentGalleryModel { id: gallery + Component.onCompleted: { + //set default filter: show both videos and images + var videoFilter = createFilter(gallery, "videosfilter", "GalleryStartsWithFilter", "mimeType", "video/") + var imageFilter = createFilter(gallery, "imagesfilter", "GalleryStartsWithFilter", "mimeType", "image/") + var array = [videoFilter, imageFilter] + gallery.filter = createFiltersArray(gallery, "arraysFilter", "GalleryFilterUnion", array) + } + + //destroying the old filter before the new one is assigned makes the gallery model misbehave! + function assignNewDestroyCurrent(newFilter) { + var old = gallery.filter + gallery.filter = newFilter + old.destroy() + } + + //this is to create single filters dynamically + function createFilter(parentItem, name, filterType, keyToFilter, value){ + var myFilter = Qt.createQmlObject('import QtMobility.gallery 1.1;' + filterType + '{property: "' +keyToFilter + '"; value: "' + value + '" }', + parentItem, name); + return myFilter + } + + //this is to create group filters, such as union and intersection ones + function createFiltersArray(parentItem, name, filterType, filtersArray){ + var myFilter = Qt.createQmlObject('import QtMobility.gallery 1.1;' + filterType + '{ }', + parentItem, name); + myFilter.filters = filtersArray + return myFilter + } + + //this is to know if the item at index "index" is a video + function isVideo(index) { + //elements have index == -1 when the gallery model is being rebuilt (e.g. filters are changed) + //In that case, we must not access model data + //NOTE: this will still return a value, best thing would be to add a check in the other components + //every time before using this method! + if (index !== -1) + { + var mimeString = get(index).mimeType.toString() + return (mimeString.substring(0,5) === "video") + } + } + autoUpdate: true - rootType: DocumentGallery.Image - properties: [ "url", "width", "height" ] + rootType: DocumentGallery.File + + properties: [ "url", "mimeType" ] } --- qml/api/GalleryView.qml +++ qml/api/GalleryView.qml @@ -50,7 +50,6 @@ // Ideally, this would use (padding*(itemsPerRow-1)), but GridView's // behavior on cellWidth requires the rightmost item to have padding. thumbnailSize = Math.floor((width - padding * itemsPerRow) / itemsPerRow) - console.log("XXX: Thumb size is " + thumbnailSize) } Component.onCompleted: updateThumbnailSize() @@ -83,7 +82,7 @@ visible: parent.model.count == 0 && parent.model.progress == 1.0 - text: parent.model.filter == null ? "No images yet..." : "No matching images found..." + text: "No elements found..." color: "lightgrey" font.pointSize: 26 horizontalAlignment: Text.AlignHCenter --- qml/main.qml +++ qml/main.qml @@ -47,14 +47,4 @@ Component.onCompleted: { theme.inverted = true } - - /*Menu { - id: myMenu - visualParent: pageStack - MenuLayout { - MenuItem { text: qsTr("Open image") - onClicked: appWindow.pageStack.push(imagepage) - } - } - }*/ } --- qmlgallery.desktop +++ qmlgallery.desktop @@ -1,10 +1,9 @@ [Desktop Entry] -Encoding=UTF-8 Version=1.0 Type=Application Terminal=false Name=Gallery -Exec=/opt/qmlgallery/bin/qmlgallery +Exec=invoker -s --type=d /usr/bin/qmlgallery -fullscreen Icon=icons-Applications-photos X-Window-Icon= X-HildonDesk-ShowInToolbar=true --- qmlgallery.pro +++ qmlgallery.pro @@ -1,5 +1,5 @@ PROJECT_NAME = qmlgallery -QT += declarative +QT += declarative opengl # qml API we provide qml_api.files = qml/api/* @@ -9,6 +9,10 @@ target.path = $$INSTALL_ROOT/usr/bin INSTALLS += target +desktop.files = $${PROJECT_NAME}.desktop +desktop.path = $$INSTALL_ROOT/usr/share/applications +INSTALLS += desktop + RESOURCES += res.qrc SOURCES += main.cpp --- res.qrc +++ res.qrc @@ -1,9 +1,13 @@ <RCC> - <qresource> + <qresource prefix="/"> <file>qml/ImageContainer.qml</file> <file>qml/ImagePage.qml</file> <file>qml/MainPage.qml</file> <file>qml/main.qml</file> <file>qml/ImageSlideshowPage.qml</file> + <file>qml/VideoPlayer.qml</file> + <file>images/DefaultVideoThumbnail.jpg</file> + <file>images/GridVideoThumbnail.jpg</file> + <file>qml/FileTypeChoiceDialog.qml</file> </qresource> </RCC> ++++++ qmlgallery.yaml --- qmlgallery.yaml +++ qmlgallery.yaml @@ -1,14 +1,12 @@ Name: qmlgallery Summary: Photo Gallery for Nemo -Version: 0.0.8 +Version: 0.0.9 Release: 1 Group: Applications/System License: BSD URL: https://github.com/nemomobile/qmlgallery Sources: - "%{name}-%{version}.tar.bz2" -Patches: - - 0001-NEMO-363-Use-single-instance-invoker-to-launch.patch Description: Photo Gallery application using Qt Quick for Nemo Mobile. Configure: none Builder: qmake @@ -32,6 +30,7 @@ - QtDeclarative - QtGui - qdeclarative-boostable + - QtOpenGL Requires: - libdeclarative-gallery - nemo-qml-plugins-thumbnailer ++++++ deleted files: --- 0001-NEMO-363-Use-single-instance-invoker-to-launch.patch
