fix #186,drop shadowedImage and use Latte IconItem
parent
d50b5523cf
commit
68fc389067
@ -1,168 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016 Smith AR <audoban@openmailbox.org>
|
||||
* Michail Vourlakos <mvourlakos@gmail.com>
|
||||
*
|
||||
* This file is part of Latte-Dock
|
||||
*
|
||||
* Latte-Dock 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 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* Latte-Dock 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import QtQuick 2.0
|
||||
import QtGraphicalEffects 1.0
|
||||
|
||||
import org.kde.plasma.core 2.0 as PlasmaCore
|
||||
import org.kde.plasma.components 2.0 as PlasmaComponents
|
||||
|
||||
import org.kde.kquickcontrolsaddons 2.0 as KQuickControlAddons
|
||||
import org.kde.latte 0.1 as Latte
|
||||
|
||||
Component {
|
||||
id: imageBufferingComponent
|
||||
Item {
|
||||
id: yourImageWithLoadedIconContainer
|
||||
anchors.fill: parent
|
||||
|
||||
visible: false
|
||||
|
||||
property QtObject imageTimer
|
||||
|
||||
function updateImage(){
|
||||
if(!imageTimer)
|
||||
imageTimer = tttTimer.createObject(iconImage);
|
||||
else{
|
||||
imageTimer.loop = 1;
|
||||
imageTimer.restart();
|
||||
}
|
||||
}
|
||||
|
||||
Item{
|
||||
id:fixedIcon
|
||||
|
||||
width: root.iconSize + 2*shadowImageNoActive.radius
|
||||
height: width
|
||||
|
||||
visible:false
|
||||
|
||||
//KQuickControlAddons.QIconItem{
|
||||
Latte.IconItem{
|
||||
id: iconImage
|
||||
|
||||
width: root.iconSize
|
||||
height: width
|
||||
anchors.centerIn: parent
|
||||
|
||||
source: decoration //icon: decoration
|
||||
//state: KQuickControlAddons.QIconItem.DefaultState
|
||||
|
||||
enabled: true
|
||||
visible: true
|
||||
|
||||
smooth: true
|
||||
// onIconChanged: updateBuffers();
|
||||
|
||||
property int counter: 0
|
||||
|
||||
function updateBuffers(){
|
||||
if((index !== -1) &&(!centralItem.toBeDestroyed) &&(!mainItemContainer.delayingRemove)){
|
||||
if(root.initializationStep){
|
||||
root.initializationStep = false;
|
||||
}
|
||||
|
||||
centralItem.firstDrawed = true;
|
||||
// counter++;
|
||||
// console.log(counter);
|
||||
|
||||
if(shadowedImage && shadowedImage.source)
|
||||
shadowedImage.source.destroy();
|
||||
|
||||
|
||||
if(root.enableShadows == true){
|
||||
shadowImageNoActive.grabToImage(function(result) {
|
||||
shadowedImage.source = result.url
|
||||
result.destroy();
|
||||
}, Qt.size(fixedIcon.width,fixedIcon.height) );
|
||||
}
|
||||
else{
|
||||
fixedIcon.grabToImage(function(result) {
|
||||
shadowedImage.source = result.url;
|
||||
result.destroy();
|
||||
}, Qt.size(fixedIcon.width,fixedIcon.height) );
|
||||
}
|
||||
|
||||
mainItemContainer.buffersAreReady = true;
|
||||
if(!root.initializatedBuffers)
|
||||
root.noInitCreatedBuffers++;
|
||||
|
||||
iconImageBuffer.opacity = 1;
|
||||
}
|
||||
}
|
||||
|
||||
Component{
|
||||
id:tttTimer
|
||||
|
||||
Timer{
|
||||
id:ttt
|
||||
repeat: true
|
||||
interval: loop <= 1 ? centralItem.shadowInterval : 2500
|
||||
|
||||
property int loop: 0;
|
||||
|
||||
onTriggered: {
|
||||
iconImage.updateBuffers();
|
||||
|
||||
loop++;
|
||||
|
||||
// console.log(loop+' - '+interval);
|
||||
if(loop > 2)
|
||||
ttt.destroy(300);
|
||||
}
|
||||
|
||||
Component.onCompleted: ttt.start();
|
||||
}// end of timer
|
||||
|
||||
}//end of component of timer
|
||||
|
||||
Component.onCompleted: {
|
||||
yourImageWithLoadedIconContainer.updateImage();
|
||||
}
|
||||
|
||||
Component.onDestruction: {
|
||||
if(yourImageWithLoadedIconContainer.imageTimer)
|
||||
yourImageWithLoadedIconContainer.imageTimer.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DropShadow {
|
||||
id:shadowImageNoActive
|
||||
visible: false
|
||||
width: fixedIcon.width
|
||||
height: fixedIcon.height
|
||||
anchors.centerIn: fixedIcon
|
||||
|
||||
radius: centralItem.shadowSize
|
||||
samples: 2 * radius
|
||||
color: "#ff080808"
|
||||
source: fixedIcon
|
||||
|
||||
verticalOffset: 2
|
||||
}
|
||||
|
||||
Component.onDestruction: {
|
||||
if(yourImageWithLoadedIconContainer.imageTimer)
|
||||
yourImageWithLoadedIconContainer.imageTimer.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,438 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016 Smith AR <audoban@openmailbox.org>
|
||||
* Michail Vourlakos <mvourlakos@gmail.com>
|
||||
*
|
||||
* This file is part of Latte-Dock
|
||||
*
|
||||
* Latte-Dock 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 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* Latte-Dock 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import QtQuick 2.0
|
||||
import QtQuick.Layouts 1.1
|
||||
import QtGraphicalEffects 1.0
|
||||
|
||||
import org.kde.plasma.core 2.0 as PlasmaCore
|
||||
import org.kde.plasma.components 2.0 as PlasmaComponents
|
||||
import org.kde.plasma.extras 2.0 as PlasmaExtras
|
||||
import org.kde.kquickcontrolsaddons 2.0 as KQuickControlsAddons
|
||||
|
||||
//Column {
|
||||
MouseArea{
|
||||
id: tooltipContentItem
|
||||
hoverEnabled: true
|
||||
|
||||
property Item toolTip
|
||||
property var parentIndex
|
||||
property var titles
|
||||
property var windows
|
||||
property string mainText
|
||||
property string subText
|
||||
property variant icon
|
||||
property url launcherUrl
|
||||
property bool group: windows ? (windows.length > 1) : false
|
||||
|
||||
readonly property int thumbnailWidth: units.gridUnit * 15
|
||||
readonly property int thumbnailHeight: units.gridUnit * 10
|
||||
|
||||
property int preferredTextWidth: theme.mSize(theme.defaultFont).width * 30
|
||||
property int _s: units.largeSpacing / 2
|
||||
|
||||
Layout.minimumWidth: Math.max(thumbnailWidth, windowRow.width, appLabelRow.width) + _s
|
||||
Layout.minimumHeight: childrenRect.height
|
||||
Layout.maximumWidth: Layout.minimumWidth
|
||||
Layout.maximumHeight: Layout.minimumHeight
|
||||
|
||||
onContainsMouseChanged: {
|
||||
checkMouseInside();
|
||||
}
|
||||
|
||||
function checkMouseInside(){
|
||||
var isInside = containsMouse || windowRow.containsMouse();
|
||||
if (isInside){
|
||||
toolTipDelegate.currentItem = parentIndex;
|
||||
}
|
||||
else{
|
||||
root.disableRestoreZoom = false;
|
||||
toolTipDelegate.currentItem = -1;
|
||||
checkListHovered.restart();
|
||||
}
|
||||
}
|
||||
|
||||
states: State {
|
||||
when: mpris2Source.hasPlayer
|
||||
|
||||
PropertyChanges {
|
||||
target: thumbnailSourceItem
|
||||
opacity: 0 // cannot set visible to false or else WindowThumbnail won't provide thumbnail
|
||||
}
|
||||
PropertyChanges {
|
||||
target: playerControlsOpacityMask
|
||||
visible: true
|
||||
source: thumbnailSourceItem
|
||||
maskSource: playerControlsShadowMask
|
||||
}
|
||||
PropertyChanges {
|
||||
target: playerControlsRow
|
||||
visible: mpris2Source.hasPlayer
|
||||
}
|
||||
}
|
||||
|
||||
PlasmaCore.DataSource {
|
||||
id: mpris2Source
|
||||
readonly property string current: {
|
||||
var desktopFileName = launcherUrl.toString().split('/').pop().replace(".desktop", "")
|
||||
|
||||
for (var i = 0, length = sources.length; i < length; ++i) {
|
||||
var source = sources[i];
|
||||
var sourceData = data[source];
|
||||
|
||||
if (sourceData && sourceData.DesktopEntry === desktopFileName) {
|
||||
return source
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
readonly property bool hasPlayer: !!current
|
||||
|
||||
readonly property bool playing: hasPlayer && data[current].PlaybackStatus === "Playing"
|
||||
readonly property bool canControl: hasPlayer && data[current].CanControl
|
||||
readonly property bool canGoBack: hasPlayer && data[current].CanGoPrevious
|
||||
readonly property bool canGoNext: hasPlayer && data[current].CanGoNext
|
||||
readonly property bool canRaise: hasPlayer && data[current].CanRaise
|
||||
|
||||
readonly property var currentMetadata: hasPlayer ? data[current].Metadata : ({})
|
||||
|
||||
readonly property string track: {
|
||||
var xesamTitle = currentMetadata["xesam:title"]
|
||||
if (xesamTitle) {
|
||||
return xesamTitle
|
||||
}
|
||||
// if no track title is given, print out the file name
|
||||
var xesamUrl = currentMetadata["xesam:url"] ? currentMetadata["xesam:url"].toString() : ""
|
||||
if (!xesamUrl) {
|
||||
return ""
|
||||
}
|
||||
var lastSlashPos = xesamUrl.lastIndexOf('/')
|
||||
if (lastSlashPos < 0) {
|
||||
return ""
|
||||
}
|
||||
var lastUrlPart = xesamUrl.substring(lastSlashPos + 1)
|
||||
return decodeURIComponent(lastUrlPart)
|
||||
}
|
||||
readonly property string artist: currentMetadata["xesam:artist"] || ""
|
||||
readonly property string albumArt: currentMetadata["mpris:artUrl"] || ""
|
||||
|
||||
function goPrevious() {
|
||||
startOperation("Previous")
|
||||
}
|
||||
|
||||
function goNext() {
|
||||
startOperation("Next")
|
||||
}
|
||||
|
||||
function playPause() {
|
||||
startOperation("PlayPause")
|
||||
}
|
||||
|
||||
function raise() {
|
||||
startOperation("Raise")
|
||||
}
|
||||
|
||||
function startOperation(op) {
|
||||
var service = mpris2Source.serviceForSource(current)
|
||||
var operation = service.operationDescription(op)
|
||||
return service.startOperationCall(operation)
|
||||
}
|
||||
|
||||
engine: "mpris2"
|
||||
connectedSources: sources
|
||||
}
|
||||
|
||||
Column{
|
||||
spacing: _s
|
||||
|
||||
Item {
|
||||
id: thumbnailContainer
|
||||
width: Math.max(tooltipContentItem.width, windowRow.width)
|
||||
height: albumArtImage.available ? albumArtImage.height :
|
||||
raisePlayerArea.visible ? raisePlayerArea.height :
|
||||
windowRow.height
|
||||
|
||||
Item {
|
||||
id: thumbnailSourceItem
|
||||
anchors.fill: parent
|
||||
|
||||
PlasmaExtras.ScrollArea {
|
||||
id: scrollArea
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
width: Math.max(windowRow.width, thumbnailWidth)
|
||||
height: parent.height
|
||||
|
||||
visible: !albumArtImage.available
|
||||
|
||||
verticalScrollBarPolicy: Qt.ScrollBarAlwaysOff
|
||||
horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff
|
||||
|
||||
Component.onCompleted: {
|
||||
flickableItem.interactive = Qt.binding(function() {
|
||||
return contentItem.width > viewport.width;
|
||||
});
|
||||
}
|
||||
|
||||
Row {
|
||||
id: windowRow
|
||||
width: childrenRect.width
|
||||
height: childrenRect.height
|
||||
spacing: units.largeSpacing
|
||||
|
||||
Repeater {
|
||||
model: (root.showPreviews && !albumArtImage.available)
|
||||
|| !windowSystem.compositingActive ? windows : null
|
||||
|
||||
Column{
|
||||
PlasmaCore.WindowThumbnail {
|
||||
id: windowThumbnail
|
||||
|
||||
width: thumbnailWidth
|
||||
height: thumbnailHeight
|
||||
|
||||
winId: modelData
|
||||
|
||||
ToolTipWindowMouseArea {
|
||||
anchors.fill: parent
|
||||
modelIndex: tasksModel.makeModelIndex(parentIndex, group ? index : -1)
|
||||
winId: modelData
|
||||
thumbnailItem: parent
|
||||
}
|
||||
}
|
||||
|
||||
PlasmaComponents.Label{
|
||||
text: titles && titles[index] ? titles[index] : ""
|
||||
wrapMode: Text.Wrap
|
||||
font.italic: true
|
||||
elide: Text.ElideRight
|
||||
opacity: 0.7
|
||||
textFormat: Text.PlainText
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
|
||||
width: thumbnailWidth
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function containsMouse(){
|
||||
for(var i=0; i<children.length-1; ++i){
|
||||
if(children[i].children[0].containsMouse)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Image {
|
||||
id: albumArtImage
|
||||
// also Image.Loading to prevent loading thumbnails just because the album art takes a split second to load
|
||||
readonly property bool available: status === Image.Ready || status === Image.Loading
|
||||
|
||||
anchors.centerIn: parent
|
||||
width: parent.width
|
||||
height: thumbnailHeight
|
||||
sourceSize: Qt.size(thumbnailWidth, thumbnailHeight)
|
||||
asynchronous: true
|
||||
source: mpris2Source.albumArt
|
||||
fillMode: Image.PreserveAspectCrop
|
||||
visible: available
|
||||
|
||||
ToolTipWindowMouseArea {
|
||||
id: albumMouseArea
|
||||
|
||||
anchors.fill: parent
|
||||
modelIndex: tasksModel.makeModelIndex(parentIndex)//, group ? (index ? index : -1) : -1)
|
||||
winId: windows != undefined ? (windows[0] || 0) : 0
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: raisePlayerArea
|
||||
anchors.centerIn: parent
|
||||
width: thumbnailWidth
|
||||
height: thumbnailHeight
|
||||
|
||||
// if there's no window associated with this task, we might still be able to raise the player
|
||||
visible: windows == undefined || !windows[0] && mpris2Source.canRaise
|
||||
onClicked: mpris2Source.raise()
|
||||
|
||||
PlasmaCore.IconItem {
|
||||
anchors.fill: parent
|
||||
source: icon
|
||||
animated: false
|
||||
usesPlasmaTheme: false
|
||||
visible: !albumArtImage.available
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: playerControlsShadowMask
|
||||
anchors.fill: thumbnailSourceItem
|
||||
visible: false // OpacityMask would render it
|
||||
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: parent.height - playerControlsRow.height
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.bottom: parent.bottom
|
||||
width: parent.width
|
||||
height: playerControlsRow.height
|
||||
opacity: 0.2
|
||||
}
|
||||
}
|
||||
|
||||
OpacityMask {
|
||||
id: playerControlsOpacityMask
|
||||
anchors.fill: thumbnailSourceItem
|
||||
visible: false
|
||||
}
|
||||
|
||||
// prevent accidental click-through when a control is disabled
|
||||
MouseArea {
|
||||
anchors.fill: playerControlsRow
|
||||
enabled: playerControlsRow.visible
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
id: playerControlsRow
|
||||
anchors {
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
bottom: thumbnailSourceItem.bottom
|
||||
}
|
||||
width: thumbnailWidth
|
||||
spacing: 0
|
||||
enabled: mpris2Source.canControl
|
||||
visible: false
|
||||
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
spacing: 0
|
||||
|
||||
PlasmaExtras.Heading {
|
||||
Layout.fillWidth: true
|
||||
level: 4
|
||||
wrapMode: Text.NoWrap
|
||||
elide: Text.ElideRight
|
||||
text: mpris2Source.track || ""
|
||||
}
|
||||
|
||||
PlasmaExtras.Heading {
|
||||
Layout.fillWidth: true
|
||||
level: 5
|
||||
wrapMode: Text.NoWrap
|
||||
elide: Text.ElideRight
|
||||
text: mpris2Source.artist || ""
|
||||
}
|
||||
}
|
||||
|
||||
PlasmaComponents.ToolButton {
|
||||
enabled: mpris2Source.canGoBack
|
||||
iconName: "media-skip-backward"
|
||||
tooltip: i18nc("Go to previous song", "Previous")
|
||||
Accessible.name: tooltip
|
||||
onClicked: mpris2Source.goPrevious()
|
||||
}
|
||||
|
||||
PlasmaComponents.ToolButton {
|
||||
Layout.fillHeight: true
|
||||
Layout.preferredWidth: height // make this button bigger
|
||||
iconName: mpris2Source.playing ? "media-playback-pause" : "media-playback-start"
|
||||
tooltip: mpris2Source.playing ? i18nc("Pause player", "Pause") : i18nc("Start player", "Play")
|
||||
Accessible.name: tooltip
|
||||
onClicked: mpris2Source.playPause()
|
||||
}
|
||||
|
||||
PlasmaComponents.ToolButton {
|
||||
enabled: mpris2Source.canGoNext
|
||||
iconName: "media-skip-forward"
|
||||
tooltip: i18nc("Go to next song", "Next")
|
||||
Accessible.name: tooltip
|
||||
onClicked: mpris2Source.goNext()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
id: appLabelRow
|
||||
width: childrenRect.width + _s
|
||||
height: childrenRect.height + units.largeSpacing
|
||||
spacing: units.largeSpacing
|
||||
|
||||
Item {
|
||||
id: imageContainer
|
||||
width: tooltipIcon.width
|
||||
height: tooltipIcon.height
|
||||
y: _s
|
||||
|
||||
PlasmaCore.IconItem {
|
||||
id: tooltipIcon
|
||||
x: _s
|
||||
width: units.iconSizes.desktop
|
||||
height: width
|
||||
animated: false
|
||||
usesPlasmaTheme: false
|
||||
source: icon
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
id: mainColumn
|
||||
y: _s
|
||||
|
||||
//This instance is purely for metrics
|
||||
PlasmaExtras.Heading {
|
||||
id: tooltipMaintextPlaceholder
|
||||
visible: false
|
||||
level: 3
|
||||
text: mainText
|
||||
textFormat: Text.PlainText
|
||||
}
|
||||
PlasmaExtras.Heading {
|
||||
id: tooltipMaintext
|
||||
level: 3
|
||||
width: Math.min(tooltipMaintextPlaceholder.width, preferredTextWidth)
|
||||
//width: 400
|
||||
elide: Text.ElideRight
|
||||
text: mainText
|
||||
textFormat: Text.PlainText
|
||||
}
|
||||
PlasmaComponents.Label {
|
||||
id: tooltipSubtext
|
||||
width: tooltipContentItem.preferredTextWidth
|
||||
height: Math.min(theme.mSize(theme.defaultFont), contentHeight)
|
||||
wrapMode: Text.WordWrap
|
||||
text: subText
|
||||
textFormat: Text.PlainText
|
||||
opacity: 0.5
|
||||
visible: text !== ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue