feat: add styled progress bar
This commit is contained in:
parent
21b5972d46
commit
28a84a9611
6 changed files with 480 additions and 15 deletions
253
components/controls/StyledProgressBar.qml
Normal file
253
components/controls/StyledProgressBar.qml
Normal file
|
|
@ -0,0 +1,253 @@
|
||||||
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Templates
|
||||||
|
import Caelestia
|
||||||
|
import Caelestia.Components
|
||||||
|
import Caelestia.Config
|
||||||
|
import Caelestia.Internal
|
||||||
|
import qs.components
|
||||||
|
import qs.services
|
||||||
|
|
||||||
|
ProgressBar {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
enum IndeterminateAnimState {
|
||||||
|
Running,
|
||||||
|
Completing,
|
||||||
|
Stopped
|
||||||
|
}
|
||||||
|
|
||||||
|
property color fgColour: Colours.palette.m3primary
|
||||||
|
property color bgColour: Colours.palette.m3secondaryContainer
|
||||||
|
|
||||||
|
property bool wavy
|
||||||
|
property bool wavePaused
|
||||||
|
property int waveFrequency: 6
|
||||||
|
property real waveAmplitude: 0.5
|
||||||
|
property int waveDuration: 1000
|
||||||
|
property bool animateIndeterminate
|
||||||
|
|
||||||
|
property int indeterminateAnimState: StyledProgressBar.Stopped
|
||||||
|
|
||||||
|
function toBounds(startFrac: real, endFrac: real, gapSize: real): point {
|
||||||
|
startFrac = CUtils.clamp(startFrac, 0, 1);
|
||||||
|
endFrac = CUtils.clamp(endFrac, 0, 1);
|
||||||
|
|
||||||
|
// Ramp down gap size
|
||||||
|
const GAP_RAMP_DOWN_THRESHOLD = 0.01;
|
||||||
|
gapSize += height / 2;
|
||||||
|
const startGapSize = (gapSize * CUtils.clamp(startFrac, 0, GAP_RAMP_DOWN_THRESHOLD) / GAP_RAMP_DOWN_THRESHOLD);
|
||||||
|
const endGapSize = (gapSize * (1 - CUtils.clamp(endFrac, 1 - GAP_RAMP_DOWN_THRESHOLD, 1)) / GAP_RAMP_DOWN_THRESHOLD);
|
||||||
|
const start = width * startFrac + startGapSize;
|
||||||
|
const end = width * endFrac - endGapSize;
|
||||||
|
|
||||||
|
return start >= end ? Qt.point(0, 0) : Qt.point(start, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateIAnimState(): void {
|
||||||
|
if (indeterminate && animateIndeterminate) {
|
||||||
|
manager.completeEndProgress = 0;
|
||||||
|
indeterminateAnimState = StyledProgressBar.Running;
|
||||||
|
} else if (indeterminateAnimState === StyledProgressBar.Running) {
|
||||||
|
indeterminateAnimState = StyledProgressBar.Completing;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onIndeterminateChanged: updateIAnimState()
|
||||||
|
onAnimateIndeterminateChanged: updateIAnimState()
|
||||||
|
Component.onCompleted: updateIAnimState()
|
||||||
|
|
||||||
|
implicitWidth: 200
|
||||||
|
implicitHeight: 4
|
||||||
|
|
||||||
|
contentItem: Loader {
|
||||||
|
anchors.fill: parent
|
||||||
|
sourceComponent: root.indeterminate || root.indeterminateAnimState !== StyledProgressBar.Stopped ? indeterminateComp : determinateComp
|
||||||
|
}
|
||||||
|
|
||||||
|
LinearIndicatorManager {
|
||||||
|
id: manager
|
||||||
|
|
||||||
|
gap: Tokens.spacing.extraSmall
|
||||||
|
|
||||||
|
Anim on progress {
|
||||||
|
running: root.indeterminateAnimState !== StyledProgressBar.Stopped
|
||||||
|
from: 0
|
||||||
|
to: 1
|
||||||
|
duration: manager.duration
|
||||||
|
easing.type: Easing.Linear
|
||||||
|
loops: Animation.Infinite
|
||||||
|
}
|
||||||
|
|
||||||
|
Anim on completeEndProgress {
|
||||||
|
running: root.indeterminateAnimState === StyledProgressBar.Completing
|
||||||
|
to: 1
|
||||||
|
duration: manager.completeEndDuration
|
||||||
|
onFinished: {
|
||||||
|
if (root.indeterminateAnimState === StyledProgressBar.Completing)
|
||||||
|
root.indeterminateAnimState = StyledProgressBar.Stopped;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Behavior on value {
|
||||||
|
Anim {}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: determinateComp
|
||||||
|
|
||||||
|
Item {
|
||||||
|
Line {
|
||||||
|
id: remaining
|
||||||
|
|
||||||
|
anchors.right: parent.right
|
||||||
|
implicitWidth: parent.width - wave.implicitWidth - Tokens.spacing.extraSmall
|
||||||
|
}
|
||||||
|
|
||||||
|
Line {
|
||||||
|
property real implicitSize
|
||||||
|
|
||||||
|
Component.onCompleted: implicitSize = Qt.binding(() => parent.width * (1 - root.visualPosition) < parent.height ? parent.height : 4)
|
||||||
|
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.rightMargin: (parent.height - implicitHeight) / 2
|
||||||
|
|
||||||
|
implicitWidth: implicitSize
|
||||||
|
implicitHeight: implicitSize
|
||||||
|
|
||||||
|
radius: Tokens.rounding.full
|
||||||
|
color: root.fgColour
|
||||||
|
|
||||||
|
Behavior on implicitSize {
|
||||||
|
Anim {
|
||||||
|
type: Anim.FastSpatial
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Wave {
|
||||||
|
id: wave
|
||||||
|
|
||||||
|
readonly property real targetWidth: parent.width * root.visualPosition
|
||||||
|
|
||||||
|
anchors.left: parent.left
|
||||||
|
|
||||||
|
Anim on implicitWidth {
|
||||||
|
running: true
|
||||||
|
to: wave.targetWidth
|
||||||
|
onFinished: wave.implicitWidth = Qt.binding(() => wave.targetWidth)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: indeterminateComp
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: content
|
||||||
|
|
||||||
|
Line {
|
||||||
|
bounds: {
|
||||||
|
const i = manager.activeIndicators[0]; // qmllint disable unresolved-type
|
||||||
|
return i ? root.toBounds(0, i.startFraction, i.gapSize / 2) : Qt.point(0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Line {
|
||||||
|
bounds: {
|
||||||
|
const i = manager.activeIndicators[manager.activeIndicators.length - 1]; // qmllint disable unresolved-type
|
||||||
|
return i ? root.toBounds(i.endFraction, 1, i.gapSize / 2) : Qt.point(0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Instantiator {
|
||||||
|
model: Math.max(manager.activeIndicators.length, 1) - 1 // qmllint disable unresolved-type
|
||||||
|
|
||||||
|
delegate: Line {
|
||||||
|
required property int index
|
||||||
|
readonly property LinearIndicatorSegment cur: manager.activeIndicators[index] // qmllint disable unresolved-type
|
||||||
|
readonly property LinearIndicatorSegment next: manager.activeIndicators[index + 1 % manager.activeIndicators.length] // qmllint disable unresolved-type
|
||||||
|
|
||||||
|
bounds: root.toBounds(cur.endFraction, next.startFraction, cur.gapSize / 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
onObjectAdded: (_, obj) => content.data.push(obj)
|
||||||
|
onObjectRemoved: (_, obj) => {
|
||||||
|
const idx = content.data.indexOf(obj);
|
||||||
|
if (idx !== -1)
|
||||||
|
content.data.splice(idx, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Instantiator {
|
||||||
|
model: manager.activeIndicators // qmllint disable unresolved-type
|
||||||
|
|
||||||
|
delegate: Wave {
|
||||||
|
required property LinearIndicatorSegment modelData
|
||||||
|
readonly property point bounds: root.toBounds(modelData.startFraction, modelData.endFraction, modelData.gapSize / 2)
|
||||||
|
|
||||||
|
x: bounds.x
|
||||||
|
implicitWidth: bounds.y - bounds.x
|
||||||
|
|
||||||
|
color: root.fgColour
|
||||||
|
}
|
||||||
|
|
||||||
|
onObjectAdded: (_, obj) => content.data.push(obj)
|
||||||
|
onObjectRemoved: (_, obj) => {
|
||||||
|
const idx = content.data.indexOf(obj);
|
||||||
|
if (idx !== -1)
|
||||||
|
content.data.splice(idx, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
component Line: StyledRect {
|
||||||
|
property point bounds
|
||||||
|
|
||||||
|
x: bounds.x
|
||||||
|
implicitWidth: bounds.y - bounds.x
|
||||||
|
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
implicitHeight: parent.height
|
||||||
|
|
||||||
|
radius: Tokens.rounding.full
|
||||||
|
color: root.fgColour
|
||||||
|
}
|
||||||
|
|
||||||
|
component Wave: WavyLine {
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
implicitHeight: lineWidth * amplitudeMultiplier * 2 + lineWidth
|
||||||
|
|
||||||
|
lineWidth: parent.height
|
||||||
|
amplitudeMultiplier: root.wavy ? root.waveAmplitude : 0
|
||||||
|
frequency: root.waveFrequency
|
||||||
|
startX: x
|
||||||
|
fullLength: parent.width
|
||||||
|
color: root.fgColour
|
||||||
|
|
||||||
|
Anim on waveProgress {
|
||||||
|
running: true
|
||||||
|
paused: root.wavePaused
|
||||||
|
from: 0
|
||||||
|
to: 1
|
||||||
|
duration: root.waveDuration
|
||||||
|
easing.type: Easing.Linear
|
||||||
|
loops: Animation.Infinite
|
||||||
|
}
|
||||||
|
|
||||||
|
Behavior on amplitudeMultiplier {
|
||||||
|
Anim {
|
||||||
|
type: Anim.DefaultEffects
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Behavior on color {
|
||||||
|
CAnim {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,15 +1,16 @@
|
||||||
qml_module(caelestia-internal
|
qml_module(caelestia-internal
|
||||||
URI Caelestia.Internal
|
URI Caelestia.Internal
|
||||||
SOURCES
|
SOURCES
|
||||||
arcgauge.hpp arcgauge.cpp
|
arcgauge.cpp
|
||||||
cachingimagemanager.hpp cachingimagemanager.cpp
|
cachingimagemanager.cpp
|
||||||
circularbuffer.hpp circularbuffer.cpp
|
circularbuffer.cpp
|
||||||
circularindicatormanager.hpp circularindicatormanager.cpp
|
circularindicatormanager.cpp
|
||||||
hyprdevices.hpp hyprdevices.cpp
|
linearindicatormanager.cpp
|
||||||
hyprextras.hpp hyprextras.cpp
|
hyprdevices.cpp
|
||||||
logindmanager.hpp logindmanager.cpp
|
hyprextras.cpp
|
||||||
sparklineitem.hpp sparklineitem.cpp
|
logindmanager.cpp
|
||||||
visualiserbars.hpp visualiserbars.cpp
|
sparklineitem.cpp
|
||||||
|
visualiserbars.cpp
|
||||||
LIBRARIES
|
LIBRARIES
|
||||||
Qt::Gui
|
Qt::Gui
|
||||||
Qt::Quick
|
Qt::Quick
|
||||||
|
|
|
||||||
119
plugin/src/Caelestia/Internal/linearindicatormanager.cpp
Normal file
119
plugin/src/Caelestia/Internal/linearindicatormanager.cpp
Normal file
|
|
@ -0,0 +1,119 @@
|
||||||
|
#include "linearindicatormanager.hpp"
|
||||||
|
|
||||||
|
#include <qpoint.h>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
// See
|
||||||
|
// https://github.com/material-components/material-components-android/blob/master/lib/java/com/google/android/material/progressindicator/LinearIndeterminateDisjointAnimatorDelegate.java#L44-L46
|
||||||
|
constexpr int TOTAL_DURATION_IN_MS = 1800;
|
||||||
|
constexpr std::array DURATION_TO_MOVE_SEGMENT_ENDS = { 533, 567, 850, 750 };
|
||||||
|
constexpr std::array DELAY_TO_MOVE_SEGMENT_ENDS = { 1267, 1000, 333, 0 };
|
||||||
|
|
||||||
|
QEasingCurve curve(const QPointF& c1, const QPointF& c2) {
|
||||||
|
QEasingCurve curve(QEasingCurve::BezierSpline);
|
||||||
|
curve.addCubicBezierSegment(c1, c2, { 1.0, 1.0 });
|
||||||
|
return curve;
|
||||||
|
}
|
||||||
|
|
||||||
|
qreal getFractionInRange(qreal playtime, int start, int duration) {
|
||||||
|
const auto fraction = static_cast<qreal>(playtime - start) / duration;
|
||||||
|
return std::clamp(fraction, 0.0, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace caelestia::controls {
|
||||||
|
|
||||||
|
LinearIndicatorSegment::LinearIndicatorSegment(int gap, QObject* parent)
|
||||||
|
: QObject(parent)
|
||||||
|
, m_startFraction(0)
|
||||||
|
, m_endFraction(0)
|
||||||
|
, m_gapSize(gap) {}
|
||||||
|
|
||||||
|
qreal LinearIndicatorSegment::startFraction() const {
|
||||||
|
return m_startFraction;
|
||||||
|
}
|
||||||
|
|
||||||
|
qreal LinearIndicatorSegment::endFraction() const {
|
||||||
|
return m_endFraction;
|
||||||
|
}
|
||||||
|
|
||||||
|
int LinearIndicatorSegment::gapSize() const {
|
||||||
|
return m_gapSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
LinearIndicatorManager::LinearIndicatorManager(QObject* parent)
|
||||||
|
: QObject(parent)
|
||||||
|
, m_interpolators({
|
||||||
|
curve({ 0.2, 0.0 }, { 0.8, 1.0 }),
|
||||||
|
curve({ 0.4, 0.0 }, { 1.0, 1.0 }),
|
||||||
|
curve({ 0.0, 0.0 }, { 0.65, 1.0 }),
|
||||||
|
curve({ 0.1, 0.0 }, { 0.45, 1.0 }),
|
||||||
|
})
|
||||||
|
, m_progress(0)
|
||||||
|
, m_completeEndProgress(0)
|
||||||
|
, m_gap(4)
|
||||||
|
, m_activeIndicators({
|
||||||
|
new LinearIndicatorSegment(m_gap, this),
|
||||||
|
new LinearIndicatorSegment(m_gap, this),
|
||||||
|
}) {
|
||||||
|
for (auto el : m_activeIndicators)
|
||||||
|
QObject::connect(this, &LinearIndicatorManager::updated, el, &LinearIndicatorSegment::updated);
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<LinearIndicatorSegment*> LinearIndicatorManager::activeIndicators() const {
|
||||||
|
return { m_activeIndicators.cbegin(), m_activeIndicators.cend() };
|
||||||
|
}
|
||||||
|
|
||||||
|
qreal LinearIndicatorManager::progress() const {
|
||||||
|
return m_progress;
|
||||||
|
}
|
||||||
|
|
||||||
|
qreal LinearIndicatorManager::completeEndProgress() const {
|
||||||
|
return m_completeEndProgress;
|
||||||
|
}
|
||||||
|
|
||||||
|
int LinearIndicatorManager::gap() const {
|
||||||
|
return m_gap;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LinearIndicatorManager::setGap(int gap) {
|
||||||
|
m_gap = gap;
|
||||||
|
for (auto el : m_activeIndicators)
|
||||||
|
el->m_gapSize = m_gap;
|
||||||
|
update(m_progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
int LinearIndicatorManager::duration() const {
|
||||||
|
return TOTAL_DURATION_IN_MS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int LinearIndicatorManager::completeEndDuration() const {
|
||||||
|
return TOTAL_DURATION_IN_MS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LinearIndicatorManager::update(qreal progress) {
|
||||||
|
const auto playtime = progress * TOTAL_DURATION_IN_MS;
|
||||||
|
for (size_t i = 0; i < SEGMENTS; i++) {
|
||||||
|
const auto di = i * 2;
|
||||||
|
auto* const indicator = m_activeIndicators[i];
|
||||||
|
|
||||||
|
auto fraction = getFractionInRange(playtime, DELAY_TO_MOVE_SEGMENT_ENDS[di], DURATION_TO_MOVE_SEGMENT_ENDS[di]);
|
||||||
|
indicator->m_startFraction = std::clamp(m_interpolators[di].valueForProgress(fraction), 0.0, 1.0);
|
||||||
|
|
||||||
|
fraction =
|
||||||
|
getFractionInRange(playtime, DELAY_TO_MOVE_SEGMENT_ENDS[di + 1], DURATION_TO_MOVE_SEGMENT_ENDS[di + 1]);
|
||||||
|
indicator->m_endFraction = std::clamp(m_interpolators[di + 1].valueForProgress(fraction), 0.0, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_progress = progress;
|
||||||
|
emit updated();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LinearIndicatorManager::updateCompleteEndProgress(qreal progress) {
|
||||||
|
m_completeEndProgress = progress;
|
||||||
|
update(m_progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace caelestia::controls
|
||||||
86
plugin/src/Caelestia/Internal/linearindicatormanager.hpp
Normal file
86
plugin/src/Caelestia/Internal/linearindicatormanager.hpp
Normal file
|
|
@ -0,0 +1,86 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <qcolor.h>
|
||||||
|
#include <qeasingcurve.h>
|
||||||
|
#include <qobject.h>
|
||||||
|
#include <qqmlengine.h>
|
||||||
|
#include <qqmlintegration.h>
|
||||||
|
|
||||||
|
namespace caelestia::controls {
|
||||||
|
|
||||||
|
class LinearIndicatorManager;
|
||||||
|
|
||||||
|
class LinearIndicatorSegment : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
QML_ELEMENT
|
||||||
|
QML_UNCREATABLE("LinearIndicatorSegments can only be retrieved from a "
|
||||||
|
"LinearIndicatorManager.")
|
||||||
|
|
||||||
|
Q_PROPERTY(qreal startFraction READ startFraction NOTIFY updated FINAL)
|
||||||
|
Q_PROPERTY(qreal endFraction READ endFraction NOTIFY updated FINAL)
|
||||||
|
Q_PROPERTY(int gapSize READ gapSize NOTIFY updated FINAL)
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit LinearIndicatorSegment(int gap, QObject* parent = nullptr);
|
||||||
|
|
||||||
|
qreal startFraction() const;
|
||||||
|
qreal endFraction() const;
|
||||||
|
int gapSize() const;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void updated();
|
||||||
|
|
||||||
|
private:
|
||||||
|
qreal m_startFraction;
|
||||||
|
qreal m_endFraction;
|
||||||
|
int m_gapSize;
|
||||||
|
|
||||||
|
friend LinearIndicatorManager;
|
||||||
|
};
|
||||||
|
|
||||||
|
class LinearIndicatorManager : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
QML_ELEMENT
|
||||||
|
|
||||||
|
Q_PROPERTY(
|
||||||
|
QList<caelestia::controls::LinearIndicatorSegment*> activeIndicators READ activeIndicators CONSTANT FINAL)
|
||||||
|
|
||||||
|
Q_PROPERTY(qreal progress READ progress WRITE update NOTIFY updated FINAL)
|
||||||
|
Q_PROPERTY(qreal completeEndProgress READ completeEndProgress WRITE updateCompleteEndProgress NOTIFY updated FINAL)
|
||||||
|
Q_PROPERTY(int gap READ gap WRITE setGap NOTIFY updated FINAL)
|
||||||
|
|
||||||
|
Q_PROPERTY(qreal duration READ duration CONSTANT FINAL)
|
||||||
|
Q_PROPERTY(qreal completeEndDuration READ completeEndDuration CONSTANT FINAL)
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit LinearIndicatorManager(QObject* parent = nullptr);
|
||||||
|
|
||||||
|
QList<LinearIndicatorSegment*> activeIndicators() const;
|
||||||
|
|
||||||
|
qreal progress() const;
|
||||||
|
qreal completeEndProgress() const;
|
||||||
|
|
||||||
|
int gap() const;
|
||||||
|
void setGap(int gap);
|
||||||
|
|
||||||
|
int duration() const;
|
||||||
|
int completeEndDuration() const;
|
||||||
|
|
||||||
|
void update(qreal progress);
|
||||||
|
void updateCompleteEndProgress(qreal progress);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void updated();
|
||||||
|
|
||||||
|
private:
|
||||||
|
static constexpr int SEGMENTS = 2;
|
||||||
|
|
||||||
|
std::array<QEasingCurve, 4> m_interpolators;
|
||||||
|
qreal m_progress;
|
||||||
|
qreal m_completeEndProgress;
|
||||||
|
int m_gap;
|
||||||
|
|
||||||
|
std::array<LinearIndicatorSegment*, SEGMENTS> m_activeIndicators;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace caelestia::controls
|
||||||
|
|
@ -100,7 +100,7 @@ void CUtils::saveItem(QQuickItem* target, const QUrl& path, const QRect& rect, Q
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CUtils::copyFile(const QUrl& source, const QUrl& target, bool overwrite) const {
|
bool CUtils::copyFile(const QUrl& source, const QUrl& target, bool overwrite) {
|
||||||
if (!source.isLocalFile()) {
|
if (!source.isLocalFile()) {
|
||||||
qCWarning(lcCUtils) << "copyFile: source" << source << "is not a local file";
|
qCWarning(lcCUtils) << "copyFile: source" << source << "is not a local file";
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -120,7 +120,7 @@ bool CUtils::copyFile(const QUrl& source, const QUrl& target, bool overwrite) co
|
||||||
return QFile::copy(source.toLocalFile(), target.toLocalFile());
|
return QFile::copy(source.toLocalFile(), target.toLocalFile());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CUtils::deleteFile(const QUrl& path) const {
|
bool CUtils::deleteFile(const QUrl& path) {
|
||||||
if (!path.isLocalFile()) {
|
if (!path.isLocalFile()) {
|
||||||
qCWarning(lcCUtils) << "deleteFile: path" << path << "is not a local file";
|
qCWarning(lcCUtils) << "deleteFile: path" << path << "is not a local file";
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -129,7 +129,7 @@ bool CUtils::deleteFile(const QUrl& path) const {
|
||||||
return QFile::remove(path.toLocalFile());
|
return QFile::remove(path.toLocalFile());
|
||||||
}
|
}
|
||||||
|
|
||||||
QString CUtils::toLocalFile(const QUrl& url) const {
|
QString CUtils::toLocalFile(const QUrl& url) {
|
||||||
if (!url.isLocalFile()) {
|
if (!url.isLocalFile()) {
|
||||||
qCWarning(lcCUtils) << "toLocalFile: given url is not a local file" << url;
|
qCWarning(lcCUtils) << "toLocalFile: given url is not a local file" << url;
|
||||||
return QString();
|
return QString();
|
||||||
|
|
@ -138,4 +138,8 @@ QString CUtils::toLocalFile(const QUrl& url) const {
|
||||||
return url.toLocalFile();
|
return url.toLocalFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qreal CUtils::clamp(qreal value, qreal min, qreal max) {
|
||||||
|
return qBound(min, value, max);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace caelestia
|
} // namespace caelestia
|
||||||
|
|
|
||||||
|
|
@ -21,9 +21,11 @@ public:
|
||||||
Q_INVOKABLE void saveItem(QQuickItem* target, const QUrl& path, const QRect& rect, QJSValue onSaved, QJSValue onFailed);
|
Q_INVOKABLE void saveItem(QQuickItem* target, const QUrl& path, const QRect& rect, QJSValue onSaved, QJSValue onFailed);
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
Q_INVOKABLE bool copyFile(const QUrl& source, const QUrl& target, bool overwrite = true) const;
|
Q_INVOKABLE static bool copyFile(const QUrl& source, const QUrl& target, bool overwrite = true);
|
||||||
Q_INVOKABLE bool deleteFile(const QUrl& path) const;
|
Q_INVOKABLE static bool deleteFile(const QUrl& path);
|
||||||
Q_INVOKABLE QString toLocalFile(const QUrl& url) const;
|
Q_INVOKABLE static QString toLocalFile(const QUrl& url);
|
||||||
|
|
||||||
|
Q_INVOKABLE static qreal clamp(qreal value, qreal min, qreal max);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace caelestia
|
} // namespace caelestia
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue