From 93b24e060f223126fdb1facdd39177ba8a726828 Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Fri, 6 Oct 2017 09:55:43 -0400 Subject: Add a new testing utility for trying out QML files --- src-qt5/src-qml/test/main.cpp | 27 +++++++++++++++++++++++++++ src-qt5/src-qml/test/test.pro | 5 +++++ 2 files changed, 32 insertions(+) create mode 100644 src-qt5/src-qml/test/main.cpp create mode 100644 src-qt5/src-qml/test/test.pro (limited to 'src-qt5/src-qml/test') diff --git a/src-qt5/src-qml/test/main.cpp b/src-qt5/src-qml/test/main.cpp new file mode 100644 index 00000000..eabe7dc5 --- /dev/null +++ b/src-qt5/src-qml/test/main.cpp @@ -0,0 +1,27 @@ +#include +#include +#include + +int main(int argc, char** argv){ + QString QMLFile; + for(int i=1; i Date: Mon, 9 Oct 2017 10:53:54 -0400 Subject: Add a few test QML files which work to the src-qml directory. --- src-qt5/src-qml/test/test.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src-qt5/src-qml/test') diff --git a/src-qt5/src-qml/test/test.pro b/src-qt5/src-qml/test/test.pro index 4470adea..41d7d2a2 100644 --- a/src-qt5/src-qml/test/test.pro +++ b/src-qt5/src-qml/test/test.pro @@ -1,4 +1,4 @@ -QT = core gui widgets quick quickwidgets +QT = core gui widgets quick quickwidgets qml TARGET = test -- cgit From 7f013d766723468f4c4785411dcf5d42694cec3b Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Tue, 10 Oct 2017 10:24:50 -0400 Subject: Fix up the QML test routine a bit, and add a couple works-in-progress for a new firefly screensaver. --- src-qt5/src-qml/test/main.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src-qt5/src-qml/test') diff --git a/src-qt5/src-qml/test/main.cpp b/src-qt5/src-qml/test/main.cpp index eabe7dc5..e65c599f 100644 --- a/src-qt5/src-qml/test/main.cpp +++ b/src-qt5/src-qml/test/main.cpp @@ -1,6 +1,6 @@ #include #include -#include +#include int main(int argc, char** argv){ QString QMLFile; @@ -14,7 +14,8 @@ int main(int argc, char** argv){ } QApplication A(argc,argv); qDebug() << "Creating base widget"; - QQuickWidget base; + QQuickView base; + base.setResizeMode(QQuickView::SizeRootObjectToView); qDebug() << "Resize base widget"; base.resize(1024,768); qDebug() << "Load QML File:" << QMLFile; -- cgit From 27992c407e1d67b14c7d20aa378193d5590b1d52 Mon Sep 17 00:00:00 2001 From: Ken Moore Date: Fri, 13 Oct 2017 14:00:14 -0400 Subject: Another checkpoint commit - almost ready to start running tests with QML for the desktop background/wallpapers --- src-qt5/src-qml/test/CPUGaugeStyle.qml | 156 +++++++++++++++++++++++++++++++++ src-qt5/src-qml/test/Clock.qml | 101 +++++++++++++++++++++ src-qt5/src-qml/test/ListData.h | 41 +++++++++ src-qt5/src-qml/test/ListTest.qml | 19 ++++ src-qt5/src-qml/test/test-basic.qml | 48 ++++++++++ src-qt5/src-qml/test/test-cpugauge.qml | 108 +++++++++++++++++++++++ src-qt5/src-qml/test/testlist.cpp | 37 ++++++++ src-qt5/src-qml/test/testlist.pro | 7 ++ 8 files changed, 517 insertions(+) create mode 100644 src-qt5/src-qml/test/CPUGaugeStyle.qml create mode 100644 src-qt5/src-qml/test/Clock.qml create mode 100644 src-qt5/src-qml/test/ListData.h create mode 100644 src-qt5/src-qml/test/ListTest.qml create mode 100644 src-qt5/src-qml/test/test-basic.qml create mode 100644 src-qt5/src-qml/test/test-cpugauge.qml create mode 100644 src-qt5/src-qml/test/testlist.cpp create mode 100644 src-qt5/src-qml/test/testlist.pro (limited to 'src-qt5/src-qml/test') diff --git a/src-qt5/src-qml/test/CPUGaugeStyle.qml b/src-qt5/src-qml/test/CPUGaugeStyle.qml new file mode 100644 index 00000000..4728d136 --- /dev/null +++ b/src-qt5/src-qml/test/CPUGaugeStyle.qml @@ -0,0 +1,156 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, 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 The Qt Company Ltd 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." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.2 +import QtQuick.Controls.Styles 1.4 + +CircularGaugeStyle { + id: cpugauge + tickmarkInset: toPixels(0.04) + minorTickmarkInset: tickmarkInset + labelStepSize: 20 + labelInset: toPixels(0.23) + + property real xCenter: outerRadius + property real yCenter: outerRadius + property real needleLength: outerRadius - tickmarkInset * 1.25 + property real needleTipWidth: toPixels(0.02) + property real needleBaseWidth: toPixels(0.06) + property bool halfGauge: false + + function toPixels(percentage) { + return percentage * outerRadius; + } + + function degToRad(degrees) { + return degrees * (Math.PI / 180); + } + + function radToDeg(radians) { + return radians * (180 / Math.PI); + } + + function paintBackground(ctx) { + if (halfGauge) { + ctx.beginPath(); + ctx.rect(0, 0, ctx.canvas.width, ctx.canvas.height / 2); + ctx.clip(); + } + + ctx.beginPath(); + ctx.fillStyle = "black"; + ctx.ellipse(0, 0, ctx.canvas.width, ctx.canvas.height); + ctx.fill(); + + ctx.beginPath(); + ctx.lineWidth = tickmarkInset; + ctx.strokeStyle = "black"; + ctx.arc(xCenter, yCenter, outerRadius - ctx.lineWidth / 2, outerRadius - ctx.lineWidth / 2, 0, Math.PI * 2); + ctx.stroke(); + + ctx.beginPath(); + ctx.lineWidth = tickmarkInset / 2; + ctx.strokeStyle = "#222"; + ctx.arc(xCenter, yCenter, outerRadius - ctx.lineWidth / 2, outerRadius - ctx.lineWidth / 2, 0, Math.PI * 2); + ctx.stroke(); + + ctx.beginPath(); + var gradient = ctx.createRadialGradient(xCenter, yCenter, outerRadius * 0.8, xCenter, yCenter, outerRadius); + gradient.addColorStop(0, Qt.rgba(1, 1, 1, 0)); + gradient.addColorStop(0.7, Qt.rgba(1, 1, 1, 0.13)); + gradient.addColorStop(1, Qt.rgba(1, 1, 1, 1)); + ctx.fillStyle = gradient; + ctx.arc(xCenter, yCenter, outerRadius - tickmarkInset, outerRadius - tickmarkInset, 0, Math.PI * 2); + ctx.fill(); + } + + background: Canvas { + onPaint: { + var ctx = getContext("2d"); + ctx.reset(); + paintBackground(ctx); + } + + } + + needle: Canvas { + implicitWidth: needleBaseWidth + implicitHeight: needleLength + + property real xCenter: width / 2 + property real yCenter: height / 2 + + onPaint: { + var ctx = getContext("2d"); + ctx.reset(); + + ctx.beginPath(); + ctx.moveTo(xCenter, height); + ctx.lineTo(xCenter - needleBaseWidth / 2, height - needleBaseWidth / 2); + ctx.lineTo(xCenter - needleTipWidth / 2, 0); + ctx.lineTo(xCenter, yCenter - needleLength); + ctx.lineTo(xCenter, 0); + ctx.closePath(); + ctx.fillStyle = Qt.rgba(0.66, 0, 0, 0.66); + ctx.fill(); + + ctx.beginPath(); + ctx.moveTo(xCenter, height) + ctx.lineTo(width, height - needleBaseWidth / 2); + ctx.lineTo(xCenter + needleTipWidth / 2, 0); + ctx.lineTo(xCenter, 0); + ctx.closePath(); + ctx.fillStyle = Qt.lighter(Qt.rgba(0.66, 0, 0, 0.66)); + ctx.fill(); + } + } + + foreground: null +} diff --git a/src-qt5/src-qml/test/Clock.qml b/src-qt5/src-qml/test/Clock.qml new file mode 100644 index 00000000..685346cb --- /dev/null +++ b/src-qt5/src-qml/test/Clock.qml @@ -0,0 +1,101 @@ +import QtQuick 2.0 +import QtGraphicalEffects 1.0 + +Item { + id : clock + width: { + if (ListView.view && ListView.view.width >= 400) + return ListView.view.width / Math.floor(ListView.view.width / 400.0); + else + return 400; + } + + height: { + if (ListView.view && ListView.view.height >= 440) + return ListView.view.height; + else + return 440; + } + + property alias city: cityLabel.text + property int hours + property int minutes + property int seconds + property real shift + property bool night: false + property bool internationalTime: true //Unset for local time + + function timeChanged() { + var date = new Date; + hours = internationalTime ? date.getUTCHours() + Math.floor(clock.shift) : date.getHours() + night = ( hours < 7 || hours > 19 ) + minutes = internationalTime ? date.getUTCMinutes() + ((clock.shift % 1) * 60) : date.getMinutes() + seconds = date.getUTCSeconds(); + } + + Timer { + interval: 100; running: true; repeat: true; + onTriggered: clock.timeChanged() + } + + Item { + anchors.centerIn: parent + width: 200; height: 240 + Rectangle { anchors.fill: parent; color: "#80ff0000"; border.color: "red"; } + + Image { id: background; source: "clock.png"; visible: clock.night == false } + Image { source: "clock-night.png"; visible: clock.night == true } + + Image { + x: 92.5; y: 27 + source: "hour.png" + transform: Rotation { + id: hourRotation + origin.x: 7.5; origin.y: 73; + angle: (clock.hours * 30) + (clock.minutes * 0.5) + Behavior on angle { + SpringAnimation { spring: 2; damping: 0.2; modulus: 360 } + } + } + } + + Image { + x: 93.5; y: 17 + source: "minute.png" + transform: Rotation { + id: minuteRotation + origin.x: 6.5; origin.y: 83; + angle: clock.minutes * 6 + Behavior on angle { + SpringAnimation { spring: 2; damping: 0.2; modulus: 360 } + } + } + } + + Image { + x: 97.5; y: 20 + source: "second.png" + transform: Rotation { + id: secondRotation + origin.x: 2.5; origin.y: 80; + angle: clock.seconds * 6 + Behavior on angle { + SpringAnimation { spring: 2; damping: 0.2; modulus: 360 } + } + } + } + + Image { + anchors.centerIn: background; source: "center.png" + } + + Text { + id: cityLabel + y: 210; anchors.horizontalCenter: parent.horizontalCenter + color: "white" + font.family: "Helvetica" + font.bold: true; font.pixelSize: 16 + style: Text.Raised; styleColor: "black" + } + } +} diff --git a/src-qt5/src-qml/test/ListData.h b/src-qt5/src-qml/test/ListData.h new file mode 100644 index 00000000..7dd6f6e2 --- /dev/null +++ b/src-qt5/src-qml/test/ListData.h @@ -0,0 +1,41 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +class ListData : public QObject{ + Q_OBJECT + Q_PROPERTY(QList list READ list NOTIFY listchanged); +signals: + void listchanged(); + +private: + QStringList m_list; + //QTimer *timer; + //bool increasing; + +private slots: + void changeList(){ + /*if(m_list.isEmpty()){ increasing = true; } + else if(m_list.length() == 5){ increasing = false; } + if(increasing){ m_list << "Text - "+QString::number( m_list.length()+1 ); } + else{ m_list.takeAt(m_list.count()-1); } + emit listchanged();*/ + } + +public: + ListData() : QObject(){ + /*increasing = true; + timer = new QTimer(this); + timer->setInterval(1000); + timer->setSingleShot(false); + connect(timer, SIGNAL(timeout()), this, SLOT(changeList()) ); + timer->start();*/ + } + + QList list() { return QApplication::screens(); } //m_list; } +}; diff --git a/src-qt5/src-qml/test/ListTest.qml b/src-qt5/src-qml/test/ListTest.qml new file mode 100644 index 00000000..e6b6ba35 --- /dev/null +++ b/src-qt5/src-qml/test/ListTest.qml @@ -0,0 +1,19 @@ +import QtQuick 2.2 +import QtQuick.Layouts 1.3 + +Rectangle { + id: canvas + color: "black" + + ColumnLayout{ + anchors.fill: canvas + + Repeater{ + model: cppdata.list + Text{ + color: "white" + text: modelData + } + } + } //end row layout +} diff --git a/src-qt5/src-qml/test/test-basic.qml b/src-qt5/src-qml/test/test-basic.qml new file mode 100644 index 00000000..5d21ae41 --- /dev/null +++ b/src-qt5/src-qml/test/test-basic.qml @@ -0,0 +1,48 @@ +import QtQuick 2.0 +import "." as QML + +Rectangle { + id: root + width: 800; height: 600 + color: "#646464" + + ListView { + id: clockview + anchors.fill: parent + orientation: ListView.Horizontal + cacheBuffer: 2000 + snapMode: ListView.SnapOneItem + highlightRangeMode: ListView.ApplyRange + + delegate: QML.Clock { city: cityName; shift: timeShift } + model: ListModel { + ListElement { cityName: "New York"; timeShift: -4 } + ListElement { cityName: "London"; timeShift: 0 } + ListElement { cityName: "Oslo"; timeShift: 1 } + ListElement { cityName: "Mumbai"; timeShift: 5.5 } + ListElement { cityName: "Tokyo"; timeShift: 9 } + ListElement { cityName: "Brisbane"; timeShift: 10 } + ListElement { cityName: "Los Angeles"; timeShift: -8 } + } + } + + Image { + anchors.left: parent.left + anchors.bottom: parent.bottom + anchors.margins: 10 + source: "content/arrow.png" + rotation: -90 + opacity: clockview.atXBeginning ? 0 : 0.5 + Behavior on opacity { NumberAnimation { duration: 500 } } + } + + Image { + anchors.right: parent.right + anchors.bottom: parent.bottom + anchors.margins: 10 + source: "content/arrow.png" + rotation: 90 + opacity: clockview.atXEnd ? 0 : 0.5 + Behavior on opacity { NumberAnimation { duration: 500 } } + } +} diff --git a/src-qt5/src-qml/test/test-cpugauge.qml b/src-qt5/src-qml/test/test-cpugauge.qml new file mode 100644 index 00000000..1151c435 --- /dev/null +++ b/src-qt5/src-qml/test/test-cpugauge.qml @@ -0,0 +1,108 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, 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 The Qt Company Ltd 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." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.2 +import QtQuick.Window 2.1 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 +import QtQuick.Extras 1.4 + +import "." as QML + +Rectangle{ + id: rootwindow + visible: true + width: 800 + height: 600 + + color: "#161616" + property alias cpu: cpu + + Item { + id: container + anchors.fill: parent + property real diff: 5.1 + + Row { + id: gaugeRow + spacing: container.width * 0.02 + anchors.centerIn: parent + + CircularGauge { + id: cpu + width: height + height: container.height * 0.9 - gaugeRow.spacing + value: 0 + maximumValue: 100 + anchors.verticalCenter: parent.verticalCenter + + style: QML.CPUGaugeStyle {} + + } + + function updatevalue() { + if( container.diff >0 && cpu.value > (100-container.diff) ){ + cpu.value = 100; + container.diff = 0 - container.diff + } else if( container.diff <0 && cpu.value <(0-container.diff) ){ + cpu.value = 0; + container.diff = 0 - container.diff + } else { + cpu.value = cpu.value + container.diff + } + } + + Timer { + interval: 100; running: true; repeat: true; + onTriggered: gaugeRow.updatevalue() + } + } + } +} diff --git a/src-qt5/src-qml/test/testlist.cpp b/src-qt5/src-qml/test/testlist.cpp new file mode 100644 index 00000000..cc54c501 --- /dev/null +++ b/src-qt5/src-qml/test/testlist.cpp @@ -0,0 +1,37 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ListData.h" + +int main(int argc, char** argv){ + QString QMLFile; + for(int i=1; irootContext()->setContextProperty("cppdata", &data); + qDebug() << "Load QML File:" << QMLFile; + base.setSource(QUrl::fromLocalFile(QMLFile)); + qDebug() << "Start Event loop"; + base.show(); + int ret = A.exec(); + qDebug() << " - Finished"; + return ret; +} diff --git a/src-qt5/src-qml/test/testlist.pro b/src-qt5/src-qml/test/testlist.pro new file mode 100644 index 00000000..69c7bc23 --- /dev/null +++ b/src-qt5/src-qml/test/testlist.pro @@ -0,0 +1,7 @@ +QT = core gui widgets quick quickwidgets qml + +TARGET = test + +SOURCES += testlist.cpp + +HEADERS += ListData.h -- cgit From 769f269c83a2b9a6bcc6407380fe8c55e30b2476 Mon Sep 17 00:00:00 2001 From: ZackaryWelch Date: Mon, 23 Oct 2017 20:49:43 -0400 Subject: Added some test qml file for the video screensaver --- src-qt5/src-qml/test/File.qml | 21 ++++++++++++++++++ src-qt5/src-qml/test/Video.qml | 50 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) create mode 100644 src-qt5/src-qml/test/File.qml create mode 100644 src-qt5/src-qml/test/Video.qml (limited to 'src-qt5/src-qml/test') diff --git a/src-qt5/src-qml/test/File.qml b/src-qt5/src-qml/test/File.qml new file mode 100644 index 00000000..4713a454 --- /dev/null +++ b/src-qt5/src-qml/test/File.qml @@ -0,0 +1,21 @@ +import QtQuick 2.0 +import Qt.labs.folderlistmodel 2.1 + +ListView { + width: 200; height: 400 + + + FolderListModel { + id: folderModel + folder: "/usr/local/videos" + } + + Component { + id: fileDelegate + Text { text: fileName } + } + + model: folderModel + delegate: fileDelegate + Component.onCompleted: { console.log(folderModel.count) } +} diff --git a/src-qt5/src-qml/test/Video.qml b/src-qt5/src-qml/test/Video.qml new file mode 100644 index 00000000..e7d0626d --- /dev/null +++ b/src-qt5/src-qml/test/Video.qml @@ -0,0 +1,50 @@ +import QtQuick 2.0 +import QtMultimedia 5.7 +import QtQuick.Window 2.2 +import Qt.labs.folderlistmodel 2.1 + +Rectangle { + //width: Screen.width + //height: Screen.height + width: 800 + height: 600 + color: "black" + + FolderListModel { + id: folderModel + folder: "/usr/local/videos" + } + + Repeater { + model: folderModel + Component { + Item { + Component.onCompleted: { playlist.addItem(fileURL) } + } + } + } + + Playlist { + id: playlist + playbackMode: Playlist.Random + PlaylistItem { source: "/" } + onError: { console.log("ERROR") } + } + + MediaPlayer { + id: player + autoPlay: true + playlist: playlist + } + + VideoOutput { + id: videoOutput + source: player + anchors.fill: parent + } + + Component.onCompleted: { + playlist.shuffle() + console.log(playlist.itemCount) + } +} -- cgit