Added Cubemap API Hub. Closes #9
|
Before Width: | Height: | Size: 656 KiB |
|
Before Width: | Height: | Size: 694 KiB |
|
Before Width: | Height: | Size: 703 KiB |
|
Before Width: | Height: | Size: 667 KiB |
|
Before Width: | Height: | Size: 672 KiB |
|
Before Width: | Height: | Size: 683 KiB |
@@ -1,13 +0,0 @@
|
|||||||
Author
|
|
||||||
======
|
|
||||||
|
|
||||||
This is the work of Emil Persson, aka Humus.
|
|
||||||
http://www.humus.name
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
License
|
|
||||||
=======
|
|
||||||
|
|
||||||
This work is licensed under a Creative Commons Attribution 3.0 Unported License.
|
|
||||||
http://creativecommons.org/licenses/by/3.0/
|
|
||||||
|
Before Width: | Height: | Size: 906 KiB |
|
Before Width: | Height: | Size: 1.3 MiB |
|
Before Width: | Height: | Size: 869 KiB |
|
Before Width: | Height: | Size: 1013 KiB |
|
Before Width: | Height: | Size: 595 KiB |
|
Before Width: | Height: | Size: 1022 KiB |
@@ -1,13 +0,0 @@
|
|||||||
Author
|
|
||||||
======
|
|
||||||
|
|
||||||
This is the work of Emil Persson, aka Humus.
|
|
||||||
http://www.humus.name
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
License
|
|
||||||
=======
|
|
||||||
|
|
||||||
This work is licensed under a Creative Commons Attribution 3.0 Unported License.
|
|
||||||
http://creativecommons.org/licenses/by/3.0/
|
|
||||||
|
Before Width: | Height: | Size: 1015 KiB |
|
Before Width: | Height: | Size: 1.5 MiB |
|
Before Width: | Height: | Size: 899 KiB |
|
Before Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 469 KiB |
|
Before Width: | Height: | Size: 1002 KiB |
@@ -1,13 +0,0 @@
|
|||||||
Author
|
|
||||||
======
|
|
||||||
|
|
||||||
This is the work of Emil Persson, aka Humus.
|
|
||||||
http://www.humus.name
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
License
|
|
||||||
=======
|
|
||||||
|
|
||||||
This work is licensed under a Creative Commons Attribution 3.0 Unported License.
|
|
||||||
http://creativecommons.org/licenses/by/3.0/
|
|
||||||
|
Before Width: | Height: | Size: 810 KiB |
|
Before Width: | Height: | Size: 821 KiB |
|
Before Width: | Height: | Size: 735 KiB |
|
Before Width: | Height: | Size: 812 KiB |
|
Before Width: | Height: | Size: 770 KiB |
|
Before Width: | Height: | Size: 865 KiB |
@@ -1,13 +0,0 @@
|
|||||||
Author
|
|
||||||
======
|
|
||||||
|
|
||||||
This is the work of Emil Persson, aka Humus.
|
|
||||||
http://www.humus.name
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
License
|
|
||||||
=======
|
|
||||||
|
|
||||||
This work is licensed under a Creative Commons Attribution 3.0 Unported License.
|
|
||||||
http://creativecommons.org/licenses/by/3.0/
|
|
||||||
|
Before Width: | Height: | Size: 730 KiB |
|
Before Width: | Height: | Size: 992 KiB |
|
Before Width: | Height: | Size: 729 KiB |
|
Before Width: | Height: | Size: 736 KiB |
|
Before Width: | Height: | Size: 491 KiB |
|
Before Width: | Height: | Size: 730 KiB |
@@ -1,13 +0,0 @@
|
|||||||
Author
|
|
||||||
======
|
|
||||||
|
|
||||||
This is the work of Emil Persson, aka Humus.
|
|
||||||
http://www.humus.name
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
License
|
|
||||||
=======
|
|
||||||
|
|
||||||
This work is licensed under a Creative Commons Attribution 3.0 Unported License.
|
|
||||||
http://creativecommons.org/licenses/by/3.0/
|
|
||||||
|
Before Width: | Height: | Size: 860 KiB |
|
Before Width: | Height: | Size: 699 KiB |
|
Before Width: | Height: | Size: 834 KiB |
|
Before Width: | Height: | Size: 796 KiB |
|
Before Width: | Height: | Size: 874 KiB |
|
Before Width: | Height: | Size: 913 KiB |
@@ -1,13 +0,0 @@
|
|||||||
Author
|
|
||||||
======
|
|
||||||
|
|
||||||
This is the work of Emil Persson, aka Humus.
|
|
||||||
http://www.humus.name
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
License
|
|
||||||
=======
|
|
||||||
|
|
||||||
This work is licensed under a Creative Commons Attribution 3.0 Unported License.
|
|
||||||
http://creativecommons.org/licenses/by/3.0/
|
|
||||||
|
Before Width: | Height: | Size: 708 KiB |
|
Before Width: | Height: | Size: 853 KiB |
|
Before Width: | Height: | Size: 942 KiB |
|
Before Width: | Height: | Size: 705 KiB |
|
Before Width: | Height: | Size: 368 KiB |
|
Before Width: | Height: | Size: 443 KiB |
@@ -1,13 +0,0 @@
|
|||||||
Author
|
|
||||||
======
|
|
||||||
|
|
||||||
This is the work of Emil Persson, aka Humus.
|
|
||||||
http://www.humus.name
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
License
|
|
||||||
=======
|
|
||||||
|
|
||||||
This work is licensed under a Creative Commons Attribution 3.0 Unported License.
|
|
||||||
http://creativecommons.org/licenses/by/3.0/
|
|
||||||
|
Before Width: | Height: | Size: 938 KiB |
|
Before Width: | Height: | Size: 997 KiB |
|
Before Width: | Height: | Size: 1009 KiB |
|
Before Width: | Height: | Size: 915 KiB |
|
Before Width: | Height: | Size: 537 KiB |
|
Before Width: | Height: | Size: 844 KiB |
@@ -1,13 +0,0 @@
|
|||||||
Author
|
|
||||||
======
|
|
||||||
|
|
||||||
This is the work of Emil Persson, aka Humus.
|
|
||||||
http://www.humus.name
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
License
|
|
||||||
=======
|
|
||||||
|
|
||||||
This work is licensed under a Creative Commons Attribution 3.0 Unported License.
|
|
||||||
http://creativecommons.org/licenses/by/3.0/
|
|
||||||
|
Before Width: | Height: | Size: 893 KiB |
|
Before Width: | Height: | Size: 714 KiB |
|
Before Width: | Height: | Size: 902 KiB |
|
Before Width: | Height: | Size: 879 KiB |
|
Before Width: | Height: | Size: 453 KiB |
|
Before Width: | Height: | Size: 812 KiB |
@@ -1,13 +0,0 @@
|
|||||||
Author
|
|
||||||
======
|
|
||||||
|
|
||||||
This is the work of Emil Persson, aka Humus.
|
|
||||||
http://www.humus.name
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
License
|
|
||||||
=======
|
|
||||||
|
|
||||||
This work is licensed under a Creative Commons Attribution 3.0 Unported License.
|
|
||||||
http://creativecommons.org/licenses/by/3.0/
|
|
||||||
|
Before Width: | Height: | Size: 1000 KiB |
|
Before Width: | Height: | Size: 710 KiB |
|
Before Width: | Height: | Size: 876 KiB |
|
Before Width: | Height: | Size: 854 KiB |
|
Before Width: | Height: | Size: 788 KiB |
|
Before Width: | Height: | Size: 900 KiB |
@@ -1,13 +0,0 @@
|
|||||||
Author
|
|
||||||
======
|
|
||||||
|
|
||||||
This is the work of Emil Persson, aka Humus.
|
|
||||||
http://www.humus.name
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
License
|
|
||||||
=======
|
|
||||||
|
|
||||||
This work is licensed under a Creative Commons Attribution 3.0 Unported License.
|
|
||||||
http://creativecommons.org/licenses/by/3.0/
|
|
||||||
|
Before Width: | Height: | Size: 1.2 MiB |
|
Before Width: | Height: | Size: 982 KiB |
|
Before Width: | Height: | Size: 1.2 MiB |
|
Before Width: | Height: | Size: 823 KiB |
|
Before Width: | Height: | Size: 1.3 MiB |
|
Before Width: | Height: | Size: 684 KiB |
@@ -1,13 +0,0 @@
|
|||||||
Author
|
|
||||||
======
|
|
||||||
|
|
||||||
This is the work of Emil Persson, aka Humus.
|
|
||||||
http://www.humus.name
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
License
|
|
||||||
=======
|
|
||||||
|
|
||||||
This work is licensed under a Creative Commons Attribution 3.0 Unported License.
|
|
||||||
http://creativecommons.org/licenses/by/3.0/
|
|
||||||
|
Before Width: | Height: | Size: 1012 KiB |
|
Before Width: | Height: | Size: 1.7 MiB |
|
Before Width: | Height: | Size: 840 KiB |
|
Before Width: | Height: | Size: 946 KiB |
|
Before Width: | Height: | Size: 205 KiB |
|
Before Width: | Height: | Size: 920 KiB |
@@ -1,13 +0,0 @@
|
|||||||
Author
|
|
||||||
======
|
|
||||||
|
|
||||||
This is the work of Emil Persson, aka Humus.
|
|
||||||
http://www.humus.name
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
License
|
|
||||||
=======
|
|
||||||
|
|
||||||
This work is licensed under a Creative Commons Attribution 3.0 Unported License.
|
|
||||||
http://creativecommons.org/licenses/by/3.0/
|
|
||||||
390
package/contents/ui/CubemapHub.qml
Normal file
@@ -0,0 +1,390 @@
|
|||||||
|
import QtQuick
|
||||||
|
import QtQuick.Controls
|
||||||
|
import QtQuick.Dialogs
|
||||||
|
import QtQuick.Layouts
|
||||||
|
|
||||||
|
import com.github.digitalartifex.komplex as Komplex
|
||||||
|
|
||||||
|
Item
|
||||||
|
{
|
||||||
|
property alias selectedFile: searchModel.lastSavedFile
|
||||||
|
|
||||||
|
id: mainItem
|
||||||
|
|
||||||
|
Komplex.CubemapSearchModel
|
||||||
|
{
|
||||||
|
id: searchModel
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout
|
||||||
|
{
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
RowLayout
|
||||||
|
{
|
||||||
|
Layout.fillHeight: false
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.margins: 6
|
||||||
|
|
||||||
|
TextField
|
||||||
|
{
|
||||||
|
Layout.preferredHeight: 32
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
id: searchField
|
||||||
|
placeholderText: "Search"
|
||||||
|
onEditingFinished: mainItem.updateSearch()
|
||||||
|
Keys.onPressed: (event) =>
|
||||||
|
{
|
||||||
|
if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter)
|
||||||
|
{
|
||||||
|
searchField.focus = false; // Unfocus the TextField
|
||||||
|
event.accepted = true; // Prevent further propagation of the key event
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Button
|
||||||
|
{
|
||||||
|
Layout.preferredHeight: 32
|
||||||
|
Layout.preferredWidth: 32
|
||||||
|
|
||||||
|
icon.name: "search-symbolic"
|
||||||
|
|
||||||
|
onClicked: mainItem.updateSearch()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component
|
||||||
|
{
|
||||||
|
id: highlight
|
||||||
|
Rectangle {
|
||||||
|
width: view.cellWidth; height: view.cellHeight
|
||||||
|
color: palette.highlight; radius: 5
|
||||||
|
x: view.currentItem.x
|
||||||
|
y: view.currentItem.y
|
||||||
|
Behavior on x { SpringAnimation { spring: 3; damping: 0.2 } }
|
||||||
|
Behavior on y { SpringAnimation { spring: 3; damping: 0.2 } }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle
|
||||||
|
{
|
||||||
|
Layout.fillHeight: true
|
||||||
|
Layout.fillWidth: true
|
||||||
|
color: palette.base
|
||||||
|
clip: true
|
||||||
|
|
||||||
|
RowLayout
|
||||||
|
{
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
GridView
|
||||||
|
{
|
||||||
|
// The standard size
|
||||||
|
property int idealCellHeight: 300
|
||||||
|
property int idealCellWidth: 300
|
||||||
|
cellWidth: width / Math.floor(width / idealCellWidth)
|
||||||
|
cellHeight: idealCellHeight
|
||||||
|
|
||||||
|
id: view
|
||||||
|
|
||||||
|
model: searchModel
|
||||||
|
highlight: highlight
|
||||||
|
highlightFollowsCurrentItem: false
|
||||||
|
|
||||||
|
Layout.fillHeight: true
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.margins: 6
|
||||||
|
|
||||||
|
delegate: Column
|
||||||
|
{
|
||||||
|
id: entry
|
||||||
|
|
||||||
|
leftPadding: Math.floor((width - thumbnailImage.width) / 2)
|
||||||
|
topPadding: 10
|
||||||
|
rightPadding: Math.floor((width - thumbnailImage.width) / 2)
|
||||||
|
bottomPadding: 10
|
||||||
|
width: view.cellWidth
|
||||||
|
|
||||||
|
required property string id
|
||||||
|
required property string name
|
||||||
|
required property string description
|
||||||
|
required property string thumbnail
|
||||||
|
required property int index
|
||||||
|
property int itemIndex: index
|
||||||
|
|
||||||
|
Image
|
||||||
|
{
|
||||||
|
width: 280
|
||||||
|
height: 200
|
||||||
|
id: thumbnailImage
|
||||||
|
source: parent.thumbnail//"https://api.artifex.services/v1/cubemaps/thumbnail/" + parent.id
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
|
||||||
|
MouseArea
|
||||||
|
{
|
||||||
|
z: 9000
|
||||||
|
anchors.fill: parent
|
||||||
|
onClicked: (mouse) => {
|
||||||
|
view.currentIndex = entry.itemIndex
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle
|
||||||
|
{
|
||||||
|
color: palette.base
|
||||||
|
anchors.fill: parent
|
||||||
|
visible: thumbnailImage.status === Image.Loading
|
||||||
|
|
||||||
|
RowLayout
|
||||||
|
{
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
BusyIndicator
|
||||||
|
{
|
||||||
|
Layout.alignment: Qt.AlignCenter
|
||||||
|
Layout.preferredHeight: 64
|
||||||
|
Layout.preferredWidth: 64
|
||||||
|
visible: running
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle
|
||||||
|
{
|
||||||
|
color: palette.dark
|
||||||
|
anchors.fill: parent
|
||||||
|
visible: thumbnailImage.status === Image.Error
|
||||||
|
|
||||||
|
Text
|
||||||
|
{
|
||||||
|
color: palette.text
|
||||||
|
anchors.centerIn: parent
|
||||||
|
text: qsTr("Error Loading Image")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Text
|
||||||
|
{
|
||||||
|
elide: Text.ElideRight
|
||||||
|
topPadding: 4
|
||||||
|
bottomPadding: 2
|
||||||
|
text: "<h3>" + name + "</h3>"
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
width: 280
|
||||||
|
color: palette.link
|
||||||
|
font.bold: true
|
||||||
|
}
|
||||||
|
Text
|
||||||
|
{
|
||||||
|
leftPadding: 8
|
||||||
|
rightPadding: 8
|
||||||
|
text: qsTr(description)
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
elide: Text.ElideRight
|
||||||
|
width: 280
|
||||||
|
color: palette.text
|
||||||
|
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
|
||||||
|
maximumLineCount: 2
|
||||||
|
font.italic: true
|
||||||
|
}
|
||||||
|
RowLayout
|
||||||
|
{
|
||||||
|
visible: parent.itemIndex === view.currentIndex
|
||||||
|
width: 280
|
||||||
|
Button
|
||||||
|
{
|
||||||
|
Layout.topMargin: 4
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
Layout.preferredHeight: 32
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: "Download"
|
||||||
|
|
||||||
|
icon.source: "./icons/download.svg"
|
||||||
|
icon.name: "download-symbolic"
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
progressDialog.id = entry.id
|
||||||
|
progressDialog.description = entry.description
|
||||||
|
progressDialog.name = entry.name
|
||||||
|
progressDialog.thumbnail = entry.thumbnail
|
||||||
|
progressDialog.open()
|
||||||
|
searchModel.download(entry.id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
populate: Transition
|
||||||
|
{
|
||||||
|
NumberAnimation { property: "opacity"; from: 0; to: 1; duration: 1000 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout
|
||||||
|
{
|
||||||
|
Layout.margins: 6
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
Button
|
||||||
|
{
|
||||||
|
text: "Previous"
|
||||||
|
enabled: searchModel.previousPage !== ""
|
||||||
|
onClicked: searchModel.back()
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout
|
||||||
|
{
|
||||||
|
Layout.margins: 6
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
Text
|
||||||
|
{
|
||||||
|
visible: searchModel.totalResults > 0
|
||||||
|
color: palette.text
|
||||||
|
text: (searchModel.currentOffset + 1) + "-" + (searchModel.resultsPerPage + searchModel.currentOffset) + " of " + searchModel.totalResults
|
||||||
|
}
|
||||||
|
|
||||||
|
Text
|
||||||
|
{
|
||||||
|
color: palette.text
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: "Page " + (searchModel.currentOffset / searchModel.resultsPerPage) + " of " + Math.ceil(searchModel.totalResults / searchModel.resultsPerPage)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Button
|
||||||
|
{
|
||||||
|
text: "Next"
|
||||||
|
enabled: searchModel.nextPage !== ""
|
||||||
|
onClicked: searchModel.next()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle
|
||||||
|
{
|
||||||
|
color: palette.base
|
||||||
|
width: mainItem.width
|
||||||
|
height: mainItem.height
|
||||||
|
visible: searchModel.status === Komplex.PexelsImageSearchModel.Searching
|
||||||
|
|
||||||
|
RowLayout
|
||||||
|
{
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
BusyIndicator
|
||||||
|
{
|
||||||
|
Layout.alignment: Qt.AlignCenter
|
||||||
|
Layout.preferredHeight: 128
|
||||||
|
Layout.preferredWidth: 128
|
||||||
|
visible: running
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Dialog
|
||||||
|
{
|
||||||
|
property string name
|
||||||
|
property string description
|
||||||
|
property string id
|
||||||
|
property string thumbnail
|
||||||
|
|
||||||
|
modal: Qt.WindowModal
|
||||||
|
width: 600
|
||||||
|
height: 420
|
||||||
|
|
||||||
|
anchors.centerIn: parent
|
||||||
|
clip: true
|
||||||
|
|
||||||
|
id: progressDialog
|
||||||
|
|
||||||
|
ColumnLayout
|
||||||
|
{
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
Image
|
||||||
|
{
|
||||||
|
Layout.fillHeight: true
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
fillMode: Image.PreserveAspectCrop
|
||||||
|
source: progressDialog.thumbnail
|
||||||
|
}
|
||||||
|
|
||||||
|
Text
|
||||||
|
{
|
||||||
|
text: "Downloading Cubemap..."
|
||||||
|
color: palette.text
|
||||||
|
}
|
||||||
|
|
||||||
|
ProgressBar
|
||||||
|
{
|
||||||
|
value: searchModel.downloadProgress
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredHeight: 6
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections
|
||||||
|
{
|
||||||
|
target: searchModel
|
||||||
|
function onDownloadFinished()
|
||||||
|
{
|
||||||
|
progressDialog.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Dialog
|
||||||
|
{
|
||||||
|
width: 420
|
||||||
|
height: 105
|
||||||
|
|
||||||
|
id: warningDialog
|
||||||
|
ColumnLayout
|
||||||
|
{
|
||||||
|
Text
|
||||||
|
{
|
||||||
|
id: header
|
||||||
|
text: "Installation Error"
|
||||||
|
font.pointSize: 14
|
||||||
|
color: palette.text
|
||||||
|
}
|
||||||
|
Text
|
||||||
|
{
|
||||||
|
id: informative
|
||||||
|
text: searchModel.statusMessage
|
||||||
|
font.pointSize: 10
|
||||||
|
color: palette.text
|
||||||
|
}
|
||||||
|
DialogButtonBox
|
||||||
|
{
|
||||||
|
Layout.alignment: Qt.AlignRight
|
||||||
|
standardButtons: DialogButtonBox.Ok
|
||||||
|
onAccepted: warningDialog.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections
|
||||||
|
{
|
||||||
|
target: searchModel
|
||||||
|
function onStatusChanged()
|
||||||
|
{
|
||||||
|
if(searchModel.status === Komplex.CubemapSearchModel.Error)
|
||||||
|
{
|
||||||
|
warningDialog.open();
|
||||||
|
progressDialog.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateSearch()
|
||||||
|
{
|
||||||
|
console.log(searchField.text)
|
||||||
|
searchModel.query = searchField.text
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -31,10 +31,11 @@ add_library(
|
|||||||
ShaderToyMetadata.h
|
ShaderToyMetadata.h
|
||||||
ShaderToySearchModel.h
|
ShaderToySearchModel.h
|
||||||
ShaderToySearchModel.cpp
|
ShaderToySearchModel.cpp
|
||||||
ShaderToyAPI.h
|
|
||||||
PexelsAPI.h
|
|
||||||
KomplexSearchModel.h
|
KomplexSearchModel.h
|
||||||
KomplexSearchModel.cpp
|
KomplexSearchModel.cpp
|
||||||
|
CubemapSearch.h
|
||||||
|
CubemapSearch.cpp
|
||||||
|
CubemapMetadata.h
|
||||||
)
|
)
|
||||||
|
|
||||||
qt_add_qml_module(
|
qt_add_qml_module(
|
||||||
@@ -66,10 +67,11 @@ qt_add_qml_module(
|
|||||||
ShaderToyMetadata.h
|
ShaderToyMetadata.h
|
||||||
ShaderToySearchModel.h
|
ShaderToySearchModel.h
|
||||||
ShaderToySearchModel.cpp
|
ShaderToySearchModel.cpp
|
||||||
ShaderToyAPI.h
|
|
||||||
PexelsAPI.h
|
|
||||||
KomplexSearchModel.h
|
KomplexSearchModel.h
|
||||||
KomplexSearchModel.cpp
|
KomplexSearchModel.cpp
|
||||||
|
CubemapSearch.h
|
||||||
|
CubemapSearch.cpp
|
||||||
|
CubemapMetadata.h
|
||||||
NO_GENERATE_PLUGIN_SOURCE
|
NO_GENERATE_PLUGIN_SOURCE
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
17
plugin/CubemapMetadata.h
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
#ifndef CUBEMAPMETADATA_H
|
||||||
|
#define CUBEMAPMETADATA_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QUrl>
|
||||||
|
|
||||||
|
#include "Komplex_global.h"
|
||||||
|
|
||||||
|
struct KOMPLEX_EXPORT CubemapMetadata
|
||||||
|
{
|
||||||
|
QString description;
|
||||||
|
QString id;
|
||||||
|
QString name;
|
||||||
|
QUrl thumbnail;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CUBEMAPMETADATA_H
|
||||||
440
plugin/CubemapSearch.cpp
Normal file
@@ -0,0 +1,440 @@
|
|||||||
|
#include "CubemapSearch.h"
|
||||||
|
|
||||||
|
CubemapSearchModel::CubemapSearchModel(QObject *parent) : QAbstractItemModel { parent }
|
||||||
|
{
|
||||||
|
m_networkManager.setAutoDeleteReplies(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
CubemapSearchModel::~CubemapSearchModel()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int CubemapSearchModel::rowCount(const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(parent)
|
||||||
|
return m_data.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant CubemapSearchModel::data(const QModelIndex &index, int role) const
|
||||||
|
{
|
||||||
|
if(index.row() < 0 || index.row() >= m_data.count())
|
||||||
|
return QVariant();
|
||||||
|
|
||||||
|
QVariant data;
|
||||||
|
|
||||||
|
switch (static_cast<DataRoles>(role)) {
|
||||||
|
case Description:
|
||||||
|
data = QVariant::fromValue<QString>(m_data[index.row()].description);
|
||||||
|
break;
|
||||||
|
case Name:
|
||||||
|
data = QVariant::fromValue<QString>(m_data[index.row()].name);
|
||||||
|
break;
|
||||||
|
case Thumbnail:
|
||||||
|
data = QVariant::fromValue<QUrl>(m_data[index.row()].thumbnail);
|
||||||
|
break;
|
||||||
|
case Id:
|
||||||
|
data = QVariant::fromValue<QString>(m_data[index.row()].id);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
QHash<int, QByteArray> CubemapSearchModel::roleNames() const
|
||||||
|
{
|
||||||
|
return m_dataRoles;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CubemapSearchModel::getSearchResults(QString url)
|
||||||
|
{
|
||||||
|
setStatus(Searching);
|
||||||
|
|
||||||
|
QNetworkRequest request;
|
||||||
|
request.setUrl(QUrl(url));
|
||||||
|
|
||||||
|
QNetworkReply *reply = m_networkManager.get(request);
|
||||||
|
|
||||||
|
QObject::connect
|
||||||
|
(
|
||||||
|
reply,
|
||||||
|
&QNetworkReply::finished,
|
||||||
|
this,
|
||||||
|
[this, reply]()
|
||||||
|
{
|
||||||
|
if(reply->error())
|
||||||
|
qWarning() << reply->errorString();
|
||||||
|
|
||||||
|
QByteArray data = reply->readAll();
|
||||||
|
QJsonParseError jsonError;
|
||||||
|
|
||||||
|
QJsonDocument document = QJsonDocument::fromJson(data, &jsonError);
|
||||||
|
|
||||||
|
if(jsonError.error != QJsonParseError::NoError)
|
||||||
|
{
|
||||||
|
qWarning() << jsonError.errorString();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonObject rootObject = document.object();
|
||||||
|
|
||||||
|
if(rootObject.contains(QStringLiteral("total_results")))
|
||||||
|
setTotalResults(rootObject[QStringLiteral("total_results")].toInt());
|
||||||
|
else
|
||||||
|
setTotalResults(0);
|
||||||
|
|
||||||
|
if(currentOffset() > 0)
|
||||||
|
{
|
||||||
|
setPreviousPage(
|
||||||
|
QStringLiteral("https://api.artifex.services/v1/cubemaps/search/%1/%2/%3").arg(
|
||||||
|
query(),
|
||||||
|
std::clamp(
|
||||||
|
currentOffset() - resultsPerPage(),
|
||||||
|
static_cast<quint64>(0),
|
||||||
|
totalResults() - resultsPerPage()
|
||||||
|
),
|
||||||
|
resultsPerPage()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
setPreviousPage(QString());
|
||||||
|
|
||||||
|
if((currentOffset() + resultsPerPage()) < totalResults())
|
||||||
|
{
|
||||||
|
setNextPage(
|
||||||
|
QStringLiteral("https://api.artifex.services/v1/cubemaps/search/%1/%2/%3").arg(
|
||||||
|
query(),
|
||||||
|
std::clamp(
|
||||||
|
currentOffset() + resultsPerPage(),
|
||||||
|
static_cast<quint64>(0),
|
||||||
|
totalResults() - resultsPerPage()
|
||||||
|
),
|
||||||
|
resultsPerPage()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
setNextPage(QString());
|
||||||
|
|
||||||
|
beginResetModel();
|
||||||
|
m_data.clear();
|
||||||
|
endResetModel();
|
||||||
|
|
||||||
|
if(rootObject.contains(QStringLiteral("results")) && rootObject[QStringLiteral("results")].isArray())
|
||||||
|
{
|
||||||
|
QJsonArray resultsArray = rootObject[QStringLiteral("results")].toArray();
|
||||||
|
|
||||||
|
beginInsertRows(QModelIndex(), 0, resultsArray.count() - 1);
|
||||||
|
|
||||||
|
for(const QJsonValue &resultRef : std::as_const(resultsArray))
|
||||||
|
{
|
||||||
|
if(!resultRef.isObject())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
QJsonObject resultObject = resultRef.toObject();
|
||||||
|
CubemapMetadata cubemap;
|
||||||
|
|
||||||
|
cubemap.description = resultObject[QStringLiteral("description")].toString();
|
||||||
|
cubemap.id = resultObject[QStringLiteral("id")].toString();
|
||||||
|
cubemap.name = resultObject[QStringLiteral("name")].toString();
|
||||||
|
cubemap.thumbnail = QUrl(QStringLiteral("https://api.artifex.services/v1/cubemaps/thumbnail/%1").arg(resultObject[QStringLiteral("id")].toString()));
|
||||||
|
|
||||||
|
m_data.append(cubemap);
|
||||||
|
}
|
||||||
|
|
||||||
|
endInsertRows();
|
||||||
|
}
|
||||||
|
|
||||||
|
setStatus(Idle);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
int CubemapSearchModel::status() const
|
||||||
|
{
|
||||||
|
return static_cast<int>(m_status);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CubemapSearchModel::setStatus(const int &status, const QString &message)
|
||||||
|
{
|
||||||
|
setStatusMessage(message);
|
||||||
|
|
||||||
|
if (m_status == static_cast<Status>(status))
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_status = static_cast<Status>(status);
|
||||||
|
Q_EMIT statusChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString CubemapSearchModel::statusMessage() const
|
||||||
|
{
|
||||||
|
return m_statusMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CubemapSearchModel::setStatusMessage(const QString &message)
|
||||||
|
{
|
||||||
|
if (m_statusMessage == message)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_statusMessage = message;
|
||||||
|
Q_EMIT statusMessageChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString CubemapSearchModel::lastSavedFile() const
|
||||||
|
{
|
||||||
|
return m_lastSavedFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CubemapSearchModel::setLastSavedFile(const QString &lastSavedFile)
|
||||||
|
{
|
||||||
|
if (m_lastSavedFile == lastSavedFile)
|
||||||
|
return;
|
||||||
|
m_lastSavedFile = lastSavedFile;
|
||||||
|
Q_EMIT lastSavedFileChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
qreal CubemapSearchModel::downloadProgress() const
|
||||||
|
{
|
||||||
|
return m_downloadProgress;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CubemapSearchModel::setDownloadProgress(qreal downloadProgress)
|
||||||
|
{
|
||||||
|
if (m_downloadProgress == downloadProgress)
|
||||||
|
return;
|
||||||
|
m_downloadProgress = downloadProgress;
|
||||||
|
Q_EMIT downloadProgressChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
quint64 CubemapSearchModel::currentOffset() const
|
||||||
|
{
|
||||||
|
return m_currentOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CubemapSearchModel::setCurrentOffset(quint64 currentPage)
|
||||||
|
{
|
||||||
|
if (m_currentOffset == currentPage)
|
||||||
|
return;
|
||||||
|
m_currentOffset = currentPage;
|
||||||
|
Q_EMIT currentOffsetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex CubemapSearchModel::index(int row, int column, const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(parent)
|
||||||
|
return createIndex(row, column, &m_data.at(row));
|
||||||
|
}
|
||||||
|
|
||||||
|
int CubemapSearchModel::columnCount(const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(parent)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex CubemapSearchModel::parent(const QModelIndex &index) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(index)
|
||||||
|
return QModelIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CubemapSearchModel::next()
|
||||||
|
{
|
||||||
|
if(m_nextPage.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
getSearchResults(m_nextPage);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CubemapSearchModel::back()
|
||||||
|
{
|
||||||
|
if(m_previousPage.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
getSearchResults(m_previousPage);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CubemapSearchModel::download(QString id)
|
||||||
|
{
|
||||||
|
QNetworkRequest request(QUrl(QStringLiteral("https://api.artifex.services/v1/cubemaps/item/%1").arg(id)));
|
||||||
|
QNetworkReply *reply = m_networkManager.get(request);
|
||||||
|
setStatus(Downloading);
|
||||||
|
|
||||||
|
QObject::connect
|
||||||
|
(
|
||||||
|
reply,
|
||||||
|
&QNetworkReply::finished,
|
||||||
|
this,
|
||||||
|
[this, reply, id]()
|
||||||
|
{
|
||||||
|
if(reply->error())
|
||||||
|
{
|
||||||
|
qWarning() << reply->errorString();
|
||||||
|
setStatus(Error, QStringLiteral("Could not download resource %1").arg(id));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray data = reply->readAll();
|
||||||
|
|
||||||
|
QString zipFileLocation = QStringLiteral("%1/.local/share/komplex/cubemaps/%2.zip").arg(QStandardPaths::writableLocation(QStandardPaths::HomeLocation), id);
|
||||||
|
QString fileLocation = QStringLiteral("%1/.local/share/komplex/cubemaps/%2").arg(QStandardPaths::writableLocation(QStandardPaths::HomeLocation), id);
|
||||||
|
QFile zipFile(zipFileLocation);
|
||||||
|
|
||||||
|
if(zipFile.exists())
|
||||||
|
zipFile.remove();
|
||||||
|
|
||||||
|
if(!zipFile.open(QFile::ReadWrite))
|
||||||
|
{
|
||||||
|
qWarning() << "Could not open cubemap file:" << zipFileLocation;
|
||||||
|
setStatus(Error, QStringLiteral("Could not open cubemap file"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
quint64 written = zipFile.write(data);
|
||||||
|
|
||||||
|
if(written != data.length())
|
||||||
|
{
|
||||||
|
zipFile.close();
|
||||||
|
|
||||||
|
qWarning() << "Could not write cubemap file:" << zipFileLocation;
|
||||||
|
setStatus(Error, QStringLiteral("Could not open write file"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
zipFile.close();
|
||||||
|
|
||||||
|
QStringList params {
|
||||||
|
zipFileLocation,
|
||||||
|
QStringLiteral("-d"),
|
||||||
|
fileLocation
|
||||||
|
};
|
||||||
|
|
||||||
|
QProcess process;
|
||||||
|
process.setProcessChannelMode(QProcess::MergedChannels);
|
||||||
|
|
||||||
|
process.start(QStringLiteral("unzip"), params);
|
||||||
|
|
||||||
|
if(!process.waitForStarted() || !process.waitForFinished())
|
||||||
|
{
|
||||||
|
QString message;
|
||||||
|
|
||||||
|
switch(process.error())
|
||||||
|
{
|
||||||
|
case QProcess::Crashed:
|
||||||
|
message = QStringLiteral("Unzip process crashed");
|
||||||
|
break;
|
||||||
|
case QProcess::FailedToStart:
|
||||||
|
message = QStringLiteral("Unzip process failed to start");
|
||||||
|
break;
|
||||||
|
case QProcess::Timedout:
|
||||||
|
message = QStringLiteral("Unzip process timedout");
|
||||||
|
break;
|
||||||
|
case QProcess::WriteError:
|
||||||
|
message = QStringLiteral("Unzip process crashed due to a write error");
|
||||||
|
break;
|
||||||
|
case QProcess::ReadError:
|
||||||
|
message = QStringLiteral("Unzip process crashed due to a read error");
|
||||||
|
break;
|
||||||
|
case QProcess::UnknownError:
|
||||||
|
default:
|
||||||
|
message = QStringLiteral("Unzip process crashed due to an unknown error");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
setStatus(Error, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
qWarning() << process.errorString() << process.readAllStandardOutput();// << command;
|
||||||
|
|
||||||
|
if(status() != Error)
|
||||||
|
{
|
||||||
|
setLastSavedFile(fileLocation);
|
||||||
|
|
||||||
|
Q_EMIT downloadFinished();
|
||||||
|
}
|
||||||
|
|
||||||
|
setStatus(Idle);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
QObject::connect
|
||||||
|
(
|
||||||
|
reply,
|
||||||
|
&QNetworkReply::downloadProgress,
|
||||||
|
this,
|
||||||
|
[this](qint64 received, qint64 total)
|
||||||
|
{
|
||||||
|
setDownloadProgress(static_cast<qreal>(received) / static_cast<qreal>(total));
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString CubemapSearchModel::previousPage() const
|
||||||
|
{
|
||||||
|
return m_previousPage;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CubemapSearchModel::setPreviousPage(const QString &previousPage)
|
||||||
|
{
|
||||||
|
if (m_previousPage == previousPage)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_previousPage = previousPage;
|
||||||
|
Q_EMIT previousPageChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString CubemapSearchModel::nextPage() const
|
||||||
|
{
|
||||||
|
return m_nextPage;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CubemapSearchModel::setNextPage(const QString &nextPage)
|
||||||
|
{
|
||||||
|
if (m_nextPage == nextPage)
|
||||||
|
return;
|
||||||
|
m_nextPage = nextPage;
|
||||||
|
Q_EMIT nextPageChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
quint64 CubemapSearchModel::totalResults() const
|
||||||
|
{
|
||||||
|
return m_totalResults;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CubemapSearchModel::setTotalResults(quint64 totalResults)
|
||||||
|
{
|
||||||
|
if (m_totalResults == totalResults)
|
||||||
|
return;
|
||||||
|
m_totalResults = totalResults;
|
||||||
|
Q_EMIT totalResultsChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
quint16 CubemapSearchModel::resultsPerPage() const
|
||||||
|
{
|
||||||
|
return m_resultsPerPage;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CubemapSearchModel::setResultsPerPage(quint16 resultsPerPage)
|
||||||
|
{
|
||||||
|
if (m_resultsPerPage == resultsPerPage)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_resultsPerPage = resultsPerPage;
|
||||||
|
Q_EMIT resultsPerPageChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString CubemapSearchModel::query() const
|
||||||
|
{
|
||||||
|
return m_query;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CubemapSearchModel::setQuery(const QString &query)
|
||||||
|
{
|
||||||
|
if (m_query == query)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_query = query;
|
||||||
|
Q_EMIT queryChanged();
|
||||||
|
|
||||||
|
getSearchResults(QStringLiteral("https://api.artifex.services/v1/cubemaps/search/%1/0/%2").arg(m_query).arg(m_resultsPerPage));
|
||||||
|
}
|
||||||
156
plugin/CubemapSearch.h
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
#ifndef CUBEMAPSEARCH_H
|
||||||
|
#define CUBEMAPSEARCH_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QCache>
|
||||||
|
#include <QFile>
|
||||||
|
#include <QProcess>
|
||||||
|
#include <QEventLoop>
|
||||||
|
#include <QStandardPaths>
|
||||||
|
#include <QQuickImageProvider>
|
||||||
|
#include <QNetworkAccessManager>
|
||||||
|
#include <QNetworkRequest>
|
||||||
|
#include <QNetworkReply>
|
||||||
|
#include <QAbstractItemModel>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QJsonParseError>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QJsonArray>
|
||||||
|
#include <QJsonValue>
|
||||||
|
|
||||||
|
#include "CubemapMetadata.h"
|
||||||
|
#include "Komplex_global.h"
|
||||||
|
|
||||||
|
class KOMPLEX_EXPORT CubemapSearchModel : public QAbstractItemModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
|
||||||
|
enum DataRoles
|
||||||
|
{
|
||||||
|
Description = Qt::UserRole + 1,
|
||||||
|
Id,
|
||||||
|
Name,
|
||||||
|
Thumbnail
|
||||||
|
};
|
||||||
|
Q_ENUM(DataRoles)
|
||||||
|
|
||||||
|
enum Status
|
||||||
|
{
|
||||||
|
Idle,
|
||||||
|
Searching,
|
||||||
|
Error,
|
||||||
|
Downloading
|
||||||
|
};
|
||||||
|
Q_ENUM(Status)
|
||||||
|
|
||||||
|
CubemapSearchModel(QObject *parent = nullptr);
|
||||||
|
~CubemapSearchModel();
|
||||||
|
|
||||||
|
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||||
|
|
||||||
|
QString query() const;
|
||||||
|
void setQuery(const QString &query);
|
||||||
|
|
||||||
|
quint16 resultsPerPage() const;
|
||||||
|
void setResultsPerPage(quint16 resultsPerPage);
|
||||||
|
|
||||||
|
quint64 totalResults() const;
|
||||||
|
void setTotalResults(quint64 totalResults);
|
||||||
|
|
||||||
|
QString nextPage() const;
|
||||||
|
void setNextPage(const QString &nextPage);
|
||||||
|
|
||||||
|
QString previousPage() const;
|
||||||
|
void setPreviousPage(const QString &previousPage);
|
||||||
|
|
||||||
|
quint64 currentOffset() const;
|
||||||
|
void setCurrentOffset(quint64 currentOffset);
|
||||||
|
|
||||||
|
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
QModelIndex parent(const QModelIndex &index) const override;
|
||||||
|
|
||||||
|
Q_INVOKABLE void next();
|
||||||
|
Q_INVOKABLE void back();
|
||||||
|
Q_INVOKABLE void download(QString id);
|
||||||
|
|
||||||
|
qreal downloadProgress() const;
|
||||||
|
void setDownloadProgress(qreal downloadProgress);
|
||||||
|
|
||||||
|
QString lastSavedFile() const;
|
||||||
|
void setLastSavedFile(const QString &lastSavedFile);
|
||||||
|
|
||||||
|
int status() const;
|
||||||
|
void setStatus(const int &status, const QString &message = QString());
|
||||||
|
QString statusMessage() const;
|
||||||
|
void setStatusMessage(const QString &message);
|
||||||
|
|
||||||
|
Q_SIGNALS:
|
||||||
|
void queryChanged();
|
||||||
|
void resultsPerPageChanged();
|
||||||
|
void totalResultsChanged();
|
||||||
|
void nextPageChanged();
|
||||||
|
void previousPageChanged();
|
||||||
|
void currentOffsetChanged();
|
||||||
|
void downloadProgressChanged();
|
||||||
|
void downloadFinished();
|
||||||
|
void lastSavedFileChanged();
|
||||||
|
void statusChanged();
|
||||||
|
void statusMessageChanged();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
QHash<int, QByteArray> roleNames() const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void getSearchResults(QString url);
|
||||||
|
|
||||||
|
QNetworkAccessManager m_networkManager;
|
||||||
|
QString m_query;
|
||||||
|
|
||||||
|
quint16 m_resultsPerPage = 9;
|
||||||
|
quint64 m_totalResults = 0;
|
||||||
|
quint64 m_currentOffset = 0;
|
||||||
|
qreal m_downloadProgress = 0;
|
||||||
|
QString m_nextPage;
|
||||||
|
QString m_previousPage;
|
||||||
|
QString m_lastSavedFile;
|
||||||
|
QString m_statusMessage;
|
||||||
|
|
||||||
|
QList<CubemapMetadata> m_data;
|
||||||
|
Status m_status = Status::Idle;
|
||||||
|
|
||||||
|
static inline const QHash<int, QByteArray> m_dataRoles =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
static_cast<int>(Description),
|
||||||
|
QByteArray("description")
|
||||||
|
},
|
||||||
|
{
|
||||||
|
static_cast<int>(Id),
|
||||||
|
QByteArray("id")
|
||||||
|
},
|
||||||
|
{
|
||||||
|
static_cast<int>(Name),
|
||||||
|
QByteArray("name")
|
||||||
|
},
|
||||||
|
{
|
||||||
|
static_cast<int>(Thumbnail),
|
||||||
|
QByteArray("thumbnail")
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Q_PROPERTY(QString query READ query WRITE setQuery NOTIFY queryChanged FINAL)
|
||||||
|
Q_PROPERTY(quint16 resultsPerPage READ resultsPerPage WRITE setResultsPerPage NOTIFY resultsPerPageChanged FINAL)
|
||||||
|
Q_PROPERTY(quint64 totalResults READ totalResults WRITE setTotalResults NOTIFY totalResultsChanged FINAL)
|
||||||
|
Q_PROPERTY(QString nextPage READ nextPage WRITE setNextPage NOTIFY nextPageChanged FINAL)
|
||||||
|
Q_PROPERTY(QString previousPage READ previousPage WRITE setPreviousPage NOTIFY previousPageChanged FINAL)
|
||||||
|
Q_PROPERTY(quint64 currentOffset READ currentOffset WRITE setCurrentOffset NOTIFY currentOffsetChanged FINAL)
|
||||||
|
Q_PROPERTY(qreal downloadProgress READ downloadProgress WRITE setDownloadProgress NOTIFY downloadProgressChanged FINAL)
|
||||||
|
Q_PROPERTY(QString lastSavedFile READ lastSavedFile WRITE setLastSavedFile NOTIFY lastSavedFileChanged FINAL)
|
||||||
|
Q_PROPERTY(int status READ status WRITE setStatus NOTIFY statusChanged FINAL)
|
||||||
|
Q_PROPERTY(QString statusMessage READ statusMessage WRITE setStatusMessage NOTIFY statusMessageChanged FINAL)
|
||||||
|
};
|
||||||
|
Q_DECLARE_METATYPE(CubemapSearchModel)
|
||||||
|
#endif // CUBEMAPSEARCH_H
|
||||||
@@ -7,6 +7,7 @@
|
|||||||
#include "ShaderPackModel.h"
|
#include "ShaderPackModel.h"
|
||||||
#include "PexelsVideoSearch.h"
|
#include "PexelsVideoSearch.h"
|
||||||
#include "PexelsImageSearch.h"
|
#include "PexelsImageSearch.h"
|
||||||
|
#include "CubemapSearch.h"
|
||||||
#include "ShaderToySearchModel.h"
|
#include "ShaderToySearchModel.h"
|
||||||
#include "GeometryProvider.h"
|
#include "GeometryProvider.h"
|
||||||
#include "KomplexSearchModel.h"
|
#include "KomplexSearchModel.h"
|
||||||
@@ -49,6 +50,7 @@ public:
|
|||||||
qmlRegisterType<PexelsVideoSearchModel>(uri, 1, 0, "PexelsVideoSearchModel");
|
qmlRegisterType<PexelsVideoSearchModel>(uri, 1, 0, "PexelsVideoSearchModel");
|
||||||
qmlRegisterType<PexelsImageSearchModel>(uri, 1, 0, "PexelsImageSearchModel");
|
qmlRegisterType<PexelsImageSearchModel>(uri, 1, 0, "PexelsImageSearchModel");
|
||||||
qmlRegisterType<KomplexSearchModel>(uri, 1, 0, "KomplexSearchModel");
|
qmlRegisterType<KomplexSearchModel>(uri, 1, 0, "KomplexSearchModel");
|
||||||
|
qmlRegisterType<CubemapSearchModel>(uri, 1, 0, "CubemapSearchModel");
|
||||||
}
|
}
|
||||||
|
|
||||||
void unregisterTypes() override
|
void unregisterTypes() override
|
||||||
|
|||||||
@@ -6,3 +6,4 @@ classname PexelsImageSearchModel
|
|||||||
classname PexelsVideoSearchModel
|
classname PexelsVideoSearchModel
|
||||||
classname ShaderToySearchModel
|
classname ShaderToySearchModel
|
||||||
classname KomplexSearchModel
|
classname KomplexSearchModel
|
||||||
|
classname CubemapSearchModel
|
||||||