413 lines
12 KiB
QML
413 lines
12 KiB
QML
/*
|
|
* Copyright 2015 Luca Beltrame <lbeltrame@kde.org>
|
|
*
|
|
* This file is part of Danbooru Client.
|
|
*
|
|
* Danbooru Client is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* Danbooru Client is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with Danbooru Client. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
import QtQuick 2.4
|
|
import QtQuick.Controls 1.3
|
|
import QtQuick.Dialogs 1.2
|
|
import QtQuick.Controls.Styles 1.3
|
|
import QtQuick.Layouts 1.1
|
|
|
|
|
|
import org.kde.kquickcontrolsaddons 2.0
|
|
import org.kde.kcoreaddons 1.0 as KCoreAddons
|
|
import org.kde.kio 1.0
|
|
|
|
import DanbooruClient 1.0
|
|
|
|
Rectangle {
|
|
id: rootObj
|
|
objectName: "rootObj"
|
|
width: 500
|
|
height: 500
|
|
|
|
property bool poolMode: false;
|
|
|
|
signal downloadFinished()
|
|
signal downloadRequested(url url, var tags)
|
|
signal downloadStarted()
|
|
signal fileInfo(url name, var tags)
|
|
|
|
|
|
KRun {
|
|
id: runner
|
|
}
|
|
|
|
onDownloadFinished: {
|
|
|
|
grid.opacity = 1
|
|
runningIndicator.running = false
|
|
|
|
if (danbooruModel.rowCount() == 0) {
|
|
warnLabel.visible = true
|
|
}
|
|
}
|
|
|
|
onDownloadStarted: {
|
|
warnLabel.visible = false
|
|
grid.opacity = 0.5
|
|
runningIndicator.running = true
|
|
}
|
|
|
|
BusyIndicator {
|
|
id: runningIndicator
|
|
z: 1
|
|
width: grid.cellWidth / 2
|
|
height: grid.cellHeight / 2
|
|
anchors.horizontalCenter: parent.horizontalCenter
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
running: false
|
|
}
|
|
|
|
Label {
|
|
id: warnLabel
|
|
z: 1
|
|
width: grid.cellWidth / 2
|
|
height: grid.cellHeight / 2
|
|
anchors.horizontalCenter: parent.horizontalCenter
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
visible: false
|
|
text: "No posts found."
|
|
|
|
}
|
|
|
|
Component {
|
|
id: highlight
|
|
Rectangle {
|
|
width: grid.cellWidth; height: grid.cellHeight
|
|
color: "lightsteelblue"; radius: 5
|
|
}
|
|
}
|
|
|
|
Component {
|
|
id: viewDelegate
|
|
Item {
|
|
|
|
width: grid.cellWidth
|
|
height: grid.cellHeight
|
|
|
|
Column {
|
|
id: postElement
|
|
anchors.fill: parent
|
|
|
|
QPixmapItem {
|
|
|
|
id: pixItem
|
|
pixmap: thumbPix
|
|
anchors.horizontalCenter: parent.horizontalCenter
|
|
smooth: true
|
|
fillMode: QPixmapItem.PreserveAspectFit
|
|
height: grid.cellHeight * 0.75
|
|
width: grid.cellWidth * 0.9
|
|
|
|
MouseArea {
|
|
id: mouseArea
|
|
anchors.fill: parent
|
|
height: parent.height
|
|
width: parent.width
|
|
|
|
//
|
|
|
|
hoverEnabled: true
|
|
|
|
onClicked: {
|
|
grid.currentIndex = index
|
|
rootObj.fileInfo(fileUrl, tags)
|
|
}
|
|
|
|
onDoubleClicked: {
|
|
imageOverlay.imageDoubleClicked(sampleUrl, tags)
|
|
}
|
|
|
|
onEntered: {
|
|
viewButton.opacity = 1
|
|
downloadButton.opacity = 1
|
|
}
|
|
|
|
onExited: {
|
|
viewButton.opacity = 0
|
|
downloadButton.opacity = 0
|
|
}
|
|
|
|
Button {
|
|
id: viewButton
|
|
iconName: "view-preview"
|
|
visible: opacity > 0
|
|
opacity: 0
|
|
tooltip: i18n("View in image viewer")
|
|
|
|
anchors.top: parent.top
|
|
anchors.left: parent.left
|
|
anchors.topMargin: (pixItem.height - pixItem.paintedHeight) / 2
|
|
anchors.leftMargin: (pixItem.width - pixItem.paintedWidth) / 2
|
|
|
|
height: pixItem.height * 0.15
|
|
width: pixItem.height * 0.15
|
|
z: 1
|
|
|
|
onClicked: {
|
|
runner.openUrl(fileUrl)
|
|
}
|
|
|
|
Behavior on opacity {
|
|
NumberAnimation {
|
|
duration: 200
|
|
}
|
|
}
|
|
}
|
|
|
|
Button {
|
|
|
|
id: downloadButton
|
|
iconName: "download"
|
|
visible: opacity > 0
|
|
opacity: 0
|
|
tooltip: i18n("Download image")
|
|
|
|
anchors.bottom: parent.bottom
|
|
anchors.left: parent.left
|
|
anchors.bottomMargin: (pixItem.height - pixItem.paintedHeight) / 2
|
|
anchors.leftMargin: (pixItem.width - pixItem.paintedWidth) / 2
|
|
|
|
height: pixItem.height * 0.15
|
|
width: pixItem.height * 0.15
|
|
z: 1
|
|
|
|
onClicked: {
|
|
rootObj.downloadRequested(fileUrl, tags)
|
|
}
|
|
|
|
Behavior on opacity {
|
|
NumberAnimation {
|
|
duration: 200
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Text {
|
|
id: sizeText
|
|
text: i18n("File size: %1", KCoreAddons.Format.formatByteSize(fileSize))
|
|
}
|
|
Text {
|
|
id: resolutionText
|
|
text: i18n("Resolution: %1 x %2", resolution.width, resolution.height)
|
|
}
|
|
|
|
Text {
|
|
id: ratingText
|
|
text: {
|
|
|
|
if (rating == DanbooruPost.Safe) {
|
|
return i18n("Rating: %1", "Safe")
|
|
} else if (rating == DanbooruPost.Questionable) {
|
|
return i18n("Rating: %1", "Questionable")
|
|
} else if (rating == DanbooruPost.Explicit) {
|
|
return i18n("Rating: %1", "Explicit")
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
ScrollView {
|
|
id: scrollView
|
|
anchors.fill: parent
|
|
GridView {
|
|
id: grid
|
|
cellWidth: 230
|
|
cellHeight: 230
|
|
|
|
flow: GridView.FlowLeftToRight
|
|
anchors.fill: parent
|
|
clip: true
|
|
|
|
highlight: highlight
|
|
highlightFollowsCurrentItem: true
|
|
snapMode: GridView.SnapToRow
|
|
|
|
model: danbooruModel
|
|
delegate: viewDelegate
|
|
focus: true
|
|
|
|
Component.onCompleted: { currentIndex = -1; forceActiveFocus()}
|
|
|
|
onAtYEndChanged: {
|
|
|
|
// Download only if at end, if there are posts, if
|
|
// we are not displaying a pool, if the option is set
|
|
// and if we're not already downloading something
|
|
|
|
if (grid.atYEnd && danbooruModel.rowCount() > 0 &&
|
|
!rootObj.poolMode &&
|
|
infiniteScroll &&
|
|
!runningIndicator.running) {
|
|
|
|
rootObj.downloadStarted()
|
|
danbooruService.nextPostPage();
|
|
}
|
|
}
|
|
|
|
add: Transition {
|
|
NumberAnimation { property: "opacity"; from: 0; to: 1; duration: 250}
|
|
}
|
|
|
|
Behavior on opacity {
|
|
NumberAnimation {
|
|
duration: 200
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
Image {
|
|
// This handles displaying the medium-resolution image as preview
|
|
signal imageDoubleClicked(url url, var tags)
|
|
|
|
id: imageOverlay
|
|
smooth: true
|
|
fillMode: QPixmapItem.PreserveAspectFit
|
|
height: rootObj.height * 0.9
|
|
width: rootObj.width * 0.9
|
|
anchors.horizontalCenter: parent.horizontalCenter
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
visible: width > 0
|
|
z: 1
|
|
|
|
Button {
|
|
id: closeButton
|
|
anchors.top: parent.top
|
|
anchors.right: imageOverlay.right
|
|
height: parent.paintedHeight * 0.05
|
|
width: parent.paintedHeight * 0.05
|
|
anchors.topMargin: (parent.height - parent.paintedHeight) / 2
|
|
anchors.leftMargin: (parent.width - parent.paintedWidth) / 2
|
|
iconName: "window-close"
|
|
visible: false
|
|
z: 2
|
|
tooltip: i18n("Click to close image preview")
|
|
|
|
onClicked: {
|
|
closeButton.visible = false
|
|
// shrinkAnimation.start()
|
|
imageOverlay.visible = false
|
|
overlayBox.visible = false
|
|
overlayText.visible = false
|
|
}
|
|
|
|
}
|
|
|
|
Rectangle {
|
|
|
|
id: overlayBox
|
|
color:"black"
|
|
|
|
anchors.bottom: parent.bottom
|
|
anchors.left: parent.left
|
|
anchors.bottomMargin: (parent.height - parent.paintedHeight) / 2
|
|
anchors.leftMargin: (parent.width - parent.paintedWidth) / 2
|
|
width: imageOverlay.paintedWidth
|
|
height: imageOverlay.paintedHeight * 0.05
|
|
opacity: 0.8
|
|
visible: false
|
|
|
|
Text {
|
|
id: overlayText
|
|
anchors.fill: parent
|
|
text: "" // FIXME
|
|
color: "white"
|
|
visible: false
|
|
}
|
|
}
|
|
|
|
Keys.onEscapePressed: {
|
|
closeButton.visible = false
|
|
imageOverlay.visible = false
|
|
}
|
|
|
|
onImageDoubleClicked: {
|
|
|
|
imageOverlay.visible = true
|
|
imageOverlay.source = url
|
|
closeButton.visible = true
|
|
if (tags.length < 10) {
|
|
overlayText.text = i18n("Tags: %1", tags.toString())
|
|
} else {
|
|
overlayText.text = i18n("Tags: %1", tags.slice(0, 10).join(", "))
|
|
}
|
|
}
|
|
|
|
onStatusChanged: {
|
|
|
|
if (imageOverlay.status == Image.Loading) {
|
|
rootObj.downloadStarted()
|
|
}
|
|
|
|
if (imageOverlay.status == Image.Ready) {
|
|
rootObj.downloadFinished()
|
|
// imageOverlay.visible = true
|
|
enlargeAnimation.start()
|
|
|
|
}
|
|
}
|
|
|
|
PropertyAnimation {
|
|
id: enlargeAnimation
|
|
target: imageOverlay
|
|
properties: "width"
|
|
from: 0
|
|
to: imageOverlay.paintedWidth
|
|
duration: 250
|
|
|
|
onRunningChanged: {
|
|
if (!enlargeAnimation.running) {
|
|
overlayBox.visible = true
|
|
overlayText.visible = true
|
|
|
|
if (imageOverlay.paintedWidth / imageOverlay.paintedHeight <= 1.6) {
|
|
overlayBox.height = imageOverlay.paintedHeight * 0.03
|
|
} else {
|
|
overlayBox.height = imageOverlay.paintedHeight * 0.05
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
PropertyAnimation {
|
|
id: shrinkAnimation
|
|
target: imageOverlay
|
|
properties: "width"
|
|
from: imageOverlay.paintedWidth
|
|
to: 0
|
|
duration: 250
|
|
onRunningChanged: {
|
|
if (!shrinkAnimation.running) {
|
|
imageOverlay.visible = false
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
}
|