Commit 66f62099 authored by Marco Martin's avatar Marco Martin
Browse files

Don't assume m_containment is there

The containment property is assigned from qml so it can be bull. Also, if this component is used in a plasmoid that can run also in normal applet mode (i.e. folderview) it will be null in that case.

if we don't have a containment assigned yet, just do nothing in the signal handlers as they are supposed to read and write from the containment config

BUG:436041
parent 770e9ab7
......@@ -45,11 +45,18 @@ AppletsLayout::AppletsLayout(QQuickItem *parent)
m_saveLayoutTimer->setInterval(100);
connect(m_layoutManager, &AbstractLayoutManager::layoutNeedsSaving, m_saveLayoutTimer, QOverload<>::of(&QTimer::start));
connect(m_saveLayoutTimer, &QTimer::timeout, this, [this]() {
// We can't assume m_containment to be valid: if we load in a plasmoid that can run also
// in "applet" mode, m_containment will never be valid
if (!m_containment) {
return;
}
// We can't save the layout during bootup, for performance reasons and to avoid race consitions as much as possible, so if we needto save and still starting up,
// don't actually savenow, but we will when Corona::startupCompleted is emitted
if (!m_configKey.isEmpty() && m_containment && m_containment->corona()->isStartupCompleted()) {
const QString serializedConfig = m_layoutManager->serializeLayout();
m_containment->config().writeEntry(m_configKey, serializedConfig);
m_containment->config().writeEntry(m_fallbackConfigKey, serializedConfig);
// FIXME: something more efficient
m_layoutManager->parseLayout(serializedConfig);
m_savedSize = size();
......@@ -57,44 +64,48 @@ AppletsLayout::AppletsLayout(QQuickItem *parent)
}
});
m_configKeyChangeTimer = new QTimer(this);
m_configKeyChangeTimer->setSingleShot(true);
m_configKeyChangeTimer->setInterval(100);
connect(m_configKeyChangeTimer, &QTimer::timeout, this, [this]() {
if (!m_configKey.isEmpty() && m_containment) {
m_layoutManager->parseLayout(m_containment->config().readEntry(m_configKey, ""));
if (width() > 0 && height() > 0) {
m_layoutChangeTimer = new QTimer(this);
m_layoutChangeTimer->setSingleShot(true);
m_layoutChangeTimer->setInterval(100);
connect(m_layoutChangeTimer, &QTimer::timeout, this, [this]() {
// We can't assume m_containment to be valid: if we load in a plasmoid that can run also
// in "applet" mode, m_containment will never be valid
if (!m_containment) {
return;
}
const QString &serializedConfig = m_containment->config().readEntry(m_configKey, "");
if ((m_layoutChanges & ConfigKeyChange) && !serializedConfig.isEmpty()) {
if (!m_configKey.isEmpty() && m_containment) {
m_layoutManager->parseLayout(serializedConfig);
if (width() > 0 && height() > 0) {
m_layoutManager->resetLayoutFromConfig();
m_savedSize = size();
}
}
} else if (m_layoutChanges & SizeChange) {
const QRect newGeom(x(), y(), width(), height());
// The size has been restored from the last one it has been saved: restore that exact same layout
if (newGeom.size() == m_savedSize) {
m_layoutManager->resetLayoutFromConfig();
m_savedSize = size();
// If the resize is consequence of a screen resolution change, queue a relayout maintaining the distance between screen edges
} else if (!m_geometryBeforeResolutionChange.isEmpty()) {
m_layoutManager->layoutGeometryChanged(newGeom, m_geometryBeforeResolutionChange);
m_geometryBeforeResolutionChange = QRectF();
// Heuristically relayout items only when the plasma startup is fully completed
} else {
polish();
}
}
m_layoutChanges = NoChange;
});
m_pressAndHoldTimer = new QTimer(this);
m_pressAndHoldTimer->setSingleShot(true);
connect(m_pressAndHoldTimer, &QTimer::timeout, this, [this]() {
setEditMode(true);
});
m_sizeSyncTimer = new QTimer(this);
m_sizeSyncTimer->setSingleShot(true);
m_sizeSyncTimer->setInterval(150);
connect(m_sizeSyncTimer, &QTimer::timeout, this, [this]() {
const QRect newGeom(x(), y(), width(), height());
// The size has been restored from the last one it has been saved: restore that exact same layout
if (newGeom.size() == m_savedSize) {
m_layoutManager->resetLayoutFromConfig();
// If the resize is consequence of a screen resolution change, queue a relayout maintaining the distance between screen edges
} else if (!m_geometryBeforeResolutionChange.isEmpty()) {
m_layoutManager->layoutGeometryChanged(newGeom, m_geometryBeforeResolutionChange);
m_geometryBeforeResolutionChange = QRectF();
// Heuristically relayout items only when the plasma startup is fully completed
} else {
polish();
}
});
}
AppletsLayout::~AppletsLayout()
......@@ -150,11 +161,30 @@ void AppletsLayout::setConfigKey(const QString &key)
m_configKey = key;
// Reloading everything from the new config is expansive, event compress it
m_configKeyChangeTimer->start();
m_layoutChanges |= ConfigKeyChange;
m_layoutChangeTimer->start();
emit configKeyChanged();
}
QString AppletsLayout::fallbackConfigKey() const
{
return m_fallbackConfigKey;
}
void AppletsLayout::setFallbackConfigKey(const QString &key)
{
if (m_fallbackConfigKey == key) {
return;
}
m_fallbackConfigKey = key;
emit fallbackConfigKeyChanged();
}
QJSValue AppletsLayout::acceptsAppletCallback() const
{
return m_acceptsAppletCallback;
......@@ -455,7 +485,8 @@ void AppletsLayout::geometryChanged(const QRectF &newGeometry, const QRectF &old
// Only do a layouting procedure if we received a valid size
if (!newGeometry.isEmpty()) {
m_sizeSyncTimer->start();
m_layoutChanges |= SizeChange;
m_layoutChangeTimer->start();
}
QQuickItem::geometryChanged(newGeometry, oldGeometry);
......@@ -475,7 +506,12 @@ void AppletsLayout::componentComplete()
}
if (!m_configKey.isEmpty()) {
m_layoutManager->parseLayout(m_containment->config().readEntry(m_configKey, ""));
const QString &serializedConfig = m_containment->config().readEntry(m_configKey, "");
if (!serializedConfig.isEmpty()) {
m_layoutManager->parseLayout(serializedConfig);
} else {
m_layoutManager->parseLayout(m_containment->config().readEntry(m_fallbackConfigKey, ""));
}
}
const QList<QObject *> appletObjects = m_containmentItem->property("applets").value<QList<QObject *>>();
......
......@@ -48,6 +48,11 @@ class AppletsLayout : public QQuickItem
Q_PROPERTY(QString configKey READ configKey WRITE setConfigKey NOTIFY configKeyChanged)
// A config key that can be used as fallback when loading and configKey is not found
// Is always a backup of the last used configKey. Useful when the configkey depends
// from the screen size and plasma starts on an "unexpected" size
Q_PROPERTY(QString fallbackConfigKey READ fallbackConfigKey WRITE setFallbackConfigKey NOTIFY fallbackConfigKeyChanged)
Q_PROPERTY(PlasmaQuick::AppletQuickItem *containment READ containment WRITE setContainment NOTIFY containmentChanged)
Q_PROPERTY(QJSValue acceptsAppletCallback READ acceptsAppletCallback WRITE setAcceptsAppletCallback NOTIFY acceptsAppletCallbackChanged)
......@@ -95,6 +100,13 @@ public:
};
Q_ENUM(EditModeCondition)
enum LayoutChange {
NoChange = 0,
SizeChange = 1,
ConfigKeyChange = 2
};
Q_DECLARE_FLAGS(LayoutChanges, LayoutChange)
AppletsLayout(QQuickItem *parent = nullptr);
~AppletsLayout();
......@@ -102,6 +114,9 @@ public:
QString configKey() const;
void setConfigKey(const QString &key);
QString fallbackConfigKey() const;
void setFallbackConfigKey(const QString &key);
PlasmaQuick::AppletQuickItem *containment() const;
void setContainment(PlasmaQuick::AppletQuickItem *containment);
......@@ -160,6 +175,7 @@ Q_SIGNALS:
void appletRefused(QObject *applet, int x, int y);
void configKeyChanged();
void fallbackConfigKeyChanged();
void containmentChanged();
void minimumItemWidthChanged();
void minimumItemHeightChanged();
......@@ -194,8 +210,10 @@ private:
AppletContainer *createContainerForApplet(PlasmaQuick::AppletQuickItem *appletItem);
QString m_configKey;
QString m_fallbackConfigKey;
QTimer *m_saveLayoutTimer;
QTimer *m_configKeyChangeTimer;
QTimer *m_layoutChangeTimer;
LayoutChanges m_layoutChanges = NoChange;
PlasmaQuick::AppletQuickItem *m_containmentItem = nullptr;
Plasma::Containment *m_containment = nullptr;
......@@ -207,7 +225,6 @@ private:
QPointer<QQuickItem> m_eventManagerToFilter;
QTimer *m_pressAndHoldTimer;
QTimer *m_sizeSyncTimer;
QJSValue m_acceptsAppletCallback;
......@@ -223,4 +240,7 @@ private:
QPointF m_mouseDownPosition = QPoint(-1, -1);
bool m_mouseDownWasEditMode = false;
bool m_editMode = false;
bool m_sizeSpecificLayouts = false;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(AppletsLayout::LayoutChanges)
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment