diff --git a/StickIcon.qml b/StickIcon.qml new file mode 100644 index 000000000..e69de29bb diff --git a/app/view/positioner.cpp b/app/view/positioner.cpp index ad372ac1d..8123b7b6d 100644 --- a/app/view/positioner.cpp +++ b/app/view/positioner.cpp @@ -115,6 +115,18 @@ void Positioner::init() connect(this, &Positioner::showDockAfterScreenChangeFinished, this, &Positioner::updateInLocationAnimation); connect(this, &Positioner::showDockAfterMovingToLayoutFinished, this, &Positioner::updateInLocationAnimation); + connect(this, &Positioner::isStickedOnTopEdgeChanged, this, [&]() { + if (m_view->formFactor() == Plasma::Types::Vertical) { + syncGeometry(); + } + }); + + connect(this, &Positioner::isStickedOnBottomEdgeChanged, this, [&]() { + if (m_view->formFactor() == Plasma::Types::Vertical) { + syncGeometry(); + } + }); + connect(m_view, &QQuickWindow::xChanged, this, &Positioner::validateDockGeometry); connect(m_view, &QQuickWindow::yChanged, this, &Positioner::validateDockGeometry); connect(m_view, &QQuickWindow::widthChanged, this, &Positioner::validateDockGeometry); @@ -390,13 +402,26 @@ void Positioner::syncGeometry() Latte::Types::WindowsCanCover, Latte::Types::WindowsAlwaysCover}); - QList edges({Plasma::Types::TopEdge, - Plasma::Types::BottomEdge}); + QList edges; + + if (m_isStickedOnTopEdge && m_isStickedOnBottomEdge) { + //! dont send an empty edges array because that means include all screen edges in calculations + edges << Plasma::Types::Floating; + } else { + if (!m_isStickedOnTopEdge) { + edges << Plasma::Types::TopEdge; + } + + if (!m_isStickedOnBottomEdge) { + edges << Plasma::Types::BottomEdge; + } + } freeRegion = latteCorona->availableScreenRegionWithCriteria(fixedScreen, layoutName, modes, edges); maximumRect = maximumNormalGeometry(); QRegion availableRegion = freeRegion.intersected(maximumRect); + availableScreenRect = freeRegion.intersected(maximumRect).boundingRect(); float area = 0; @@ -745,6 +770,36 @@ void Positioner::setInSlideAnimation(bool active) emit inSlideAnimationChanged(); } +bool Positioner::isStickedOnTopEdge() const +{ + return m_isStickedOnTopEdge; +} + +void Positioner::setIsStickedOnTopEdge(bool sticked) +{ + if (m_isStickedOnTopEdge == sticked) { + return; + } + + m_isStickedOnTopEdge = sticked; + emit isStickedOnTopEdgeChanged(); +} + +bool Positioner::isStickedOnBottomEdge() const +{ + return m_isStickedOnBottomEdge; +} + +void Positioner::setIsStickedOnBottomEdge(bool sticked) +{ + if (m_isStickedOnBottomEdge == sticked) { + return; + } + + m_isStickedOnBottomEdge = sticked; + emit isStickedOnBottomEdgeChanged(); +} + void Positioner::updateInLocationAnimation() { bool inLocationAnimation = ((m_goToLocation != Plasma::Types::Floating) || (m_moveToLayout != "") || m_goToScreen); diff --git a/app/view/positioner.h b/app/view/positioner.h index ce96e0501..a749da79f 100644 --- a/app/view/positioner.h +++ b/app/view/positioner.h @@ -51,6 +51,9 @@ class Positioner: public QObject Q_PROPERTY(bool inLocationAnimation READ inLocationAnimation NOTIFY inLocationAnimationChanged) Q_PROPERTY(bool inSlideAnimation READ inSlideAnimation WRITE setInSlideAnimation NOTIFY inSlideAnimationChanged) + Q_PROPERTY(bool isStickedOnTopEdge READ isStickedOnTopEdge WRITE setIsStickedOnTopEdge NOTIFY isStickedOnTopEdgeChanged) + Q_PROPERTY(bool isStickedOnBottomEdge READ isStickedOnBottomEdge WRITE setIsStickedOnBottomEdge NOTIFY isStickedOnBottomEdgeChanged) + Q_PROPERTY(int currentScreenId READ currentScreenId NOTIFY currentScreenChanged) //! animating window slide Q_PROPERTY(int slideOffset READ slideOffset WRITE setSlideOffset NOTIFY slideOffsetChanged) @@ -71,6 +74,12 @@ public: bool inSlideAnimation() const; void setInSlideAnimation(bool active); + bool isStickedOnTopEdge() const; + void setIsStickedOnTopEdge(bool sticked); + + bool isStickedOnBottomEdge() const; + void setIsStickedOnBottomEdge(bool sticked); + void setScreenToFollow(QScreen *scr, bool updateScreenId = true); void reconsiderScreen(); @@ -108,6 +117,8 @@ signals: void onHideWindowsForSlidingOut(); void inLocationAnimationChanged(); void inSlideAnimationChanged(); + void isStickedOnTopEdgeChanged(); + void isStickedOnBottomEdgeChanged(); private slots: void screenChanged(QScreen *screen); @@ -129,6 +140,9 @@ private: bool m_inLocationAnimation{false}; bool m_inSlideAnimation{false}; + bool m_isStickedOnTopEdge{false}; + bool m_isStickedOnBottomEdge{false}; + int m_slideOffset{0}; //! it is used in order to enforce X11 to never miss window geometry diff --git a/app/view/settings/primaryconfigview.cpp b/app/view/settings/primaryconfigview.cpp index 1c05c0772..983ec3d37 100644 --- a/app/view/settings/primaryconfigview.cpp +++ b/app/view/settings/primaryconfigview.cpp @@ -87,6 +87,8 @@ PrimaryConfigView::PrimaryConfigView(Plasma::Containment *containment, Latte::Vi connect(this, &PrimaryConfigView::complexityChanged, this, &PrimaryConfigView::updateShowInlineProperties); connect(this, &PrimaryConfigView::complexityChanged, this, &PrimaryConfigView::syncGeometry); + connect(this, &PrimaryConfigView::complexityChanged, m_latteView, &Latte::View::settingsLevelChanged); + connect(this, &QQuickView::statusChanged, [&](QQuickView::Status status) { if (status == QQuickView::Ready) { updateEffects(); @@ -104,6 +106,7 @@ PrimaryConfigView::PrimaryConfigView(Plasma::Containment *containment, Latte::Vi syncGeometry(); syncSlideEffect(); }); + connections << connect(m_latteView->visibility(), &VisibilityManager::modeChanged, this, &PrimaryConfigView::syncGeometry); connections << connect(containment, &Plasma::Containment::immutabilityChanged, this, &PrimaryConfigView::immutabilityChanged); @@ -149,6 +152,8 @@ void PrimaryConfigView::init() m_originalMode = m_latteView->visibility()->mode(); loadConfig(); + //! inform view about the current settings level + emit m_latteView->settingsLevelChanged(); setDefaultAlphaBuffer(true); setColor(Qt::transparent); diff --git a/app/view/view.cpp b/app/view/view.cpp index 5fe5ff8b3..f44919993 100644 --- a/app/view/view.cpp +++ b/app/view/view.cpp @@ -871,6 +871,19 @@ void View::setScreenEdgeMargin(int margin) emit screenEdgeMarginChanged(); } +int View::settingsLevel() const +{ + if (m_configView) { + auto configView = qobject_cast(m_configView); + + if (configView) { + return (int)configView->complexity(); + } + } + + return (int)Latte::Types::BasicSettings; +} + int View::fontPixelSize() const { return m_fontPixelSize; diff --git a/app/view/view.h b/app/view/view.h index 2ace6c26c..743d126ba 100644 --- a/app/view/view.h +++ b/app/view/view.h @@ -102,6 +102,7 @@ class View : public PlasmaQuick::ContainmentView Q_PROPERTY(int normalThickness READ normalThickness WRITE setNormalThickness NOTIFY normalThicknessChanged) Q_PROPERTY(int offset READ offset WRITE setOffset NOTIFY offsetChanged) Q_PROPERTY(int screenEdgeMargin READ screenEdgeMargin WRITE setScreenEdgeMargin NOTIFY screenEdgeMarginChanged) + Q_PROPERTY(int settingsLevel READ settingsLevel NOTIFY settingsLevelChanged) Q_PROPERTY(float maxLength READ maxLength WRITE setMaxLength NOTIFY maxLengthChanged) @@ -189,6 +190,8 @@ public: int alignment() const; void setAlignment(int alignment); + int settingsLevel() const; + QRect absoluteGeometry() const; QRect screenGeometry() const; @@ -288,6 +291,7 @@ signals: void offsetChanged(); void onPrimaryChanged(); void positionerChanged(); + void settingsLevelChanged(); void screenEdgeMarginChanged(); void screenEdgeMarginEnabledChanged(); void screenGeometryChanged(); diff --git a/containment/package/contents/config/main.xml b/containment/package/contents/config/main.xml index 7a3651ba8..e46cd76f5 100644 --- a/containment/package/contents/config/main.xml +++ b/containment/package/contents/config/main.xml @@ -69,6 +69,14 @@ -1 + + false + + + + false + + false diff --git a/containment/package/contents/ui/VisibilityManager.qml b/containment/package/contents/ui/VisibilityManager.qml index 62da82d84..cee47d210 100644 --- a/containment/package/contents/ui/VisibilityManager.qml +++ b/containment/package/contents/ui/VisibilityManager.qml @@ -287,6 +287,21 @@ Item{ } } + //! View::Positioner bindings + Binding{ + target: latteView && latteView.positioner ? latteView.positioner : null + property: "isStickedOnTopEdge" + when: latteView && latteView.positioner + value: plasmoid.configuration.isStickedOnTopEdge + } + + Binding{ + target: latteView && latteView.positioner ? latteView.positioner : null + property: "isStickedOnBottomEdge" + when: latteView && latteView.positioner + value: plasmoid.configuration.isStickedOnBottomEdge + } + //! View::WindowsTracker bindings Binding{ target: latteView && latteView.windowsTracker ? latteView.windowsTracker : null diff --git a/containment/package/contents/ui/editmode/HeaderSettings.qml b/containment/package/contents/ui/editmode/HeaderSettings.qml index f3e2df261..1bab2aee8 100644 --- a/containment/package/contents/ui/editmode/HeaderSettings.qml +++ b/containment/package/contents/ui/editmode/HeaderSettings.qml @@ -33,10 +33,10 @@ Item { width: plasmoid.formFactor === PlasmaCore.Types.Horizontal ? parent.width : parent.height height: thickness - readonly property bool containsMouse: rearrangeBtn.containsMouse + readonly property bool containsMouse: rearrangeBtn.containsMouse || stickOnBottomBtn.containsMouse || stickOnTopBtn.containsMouse readonly property int thickness: rearrangeBtn.implicitHeight - readonly property string tooltip: rearrangeBtn.tooltip + readonly property bool inExpertSettingsMode: latteView && (latteView.settingsLevel === Latte.Types.ExpertSettings) rotation: { if (plasmoid.formFactor === PlasmaCore.Types.Horizontal) { @@ -74,6 +74,46 @@ Item { } } + SettingsControls.Button{ + id: stickOnTopBtn + visible: root.isVertical && inExpertSettingsMode + + text: i18n("Stick On Top"); + tooltip: i18n("Stick maximum available space at top screen edge and ignore any top docks or panels") + checked: plasmoid.configuration.isStickedOnTopEdge + iconPositionReversed: (plasmoid.location === PlasmaCore.Types.RightEdge) + + icon: SettingsControls.StickIcon{} + + onPressedChanged: { + if (pressed) { + plasmoid.configuration.isStickedOnTopEdge = !plasmoid.configuration.isStickedOnTopEdge; + } + } + + states: [ + State { + name: "generalEdge" + when: (plasmoid.location !== PlasmaCore.Types.RightEdge) + + AnchorChanges { + target: stickOnTopBtn + anchors{ top:parent.top; bottom:undefined; left:parent.left; right:undefined; horizontalCenter:undefined; verticalCenter:undefined} + } + }, + State { + name: "rightEdge" + when: (plasmoid.location === PlasmaCore.Types.RightEdge) + + AnchorChanges { + target: stickOnTopBtn + anchors{ top:parent.top; bottom:undefined; left:undefined; right:parent.right; horizontalCenter:undefined; verticalCenter:undefined} + } + } + ] + } + + SettingsControls.Button{ id: rearrangeBtn anchors.horizontalCenter: parent.horizontalCenter @@ -81,38 +121,10 @@ Item { text: i18n("Rearrange and configure your widgets") tooltip: i18n("Feel free to move around your widgets and configure them from their tooltips") - reverseIcon: plasmoid.location === PlasmaCore.Types.RightEdge - - textColor: containsMouse ? colorizerManager.buttonTextColor : settingsRoot.textColor - backgroundColor: containsMouse ? hoveredBackground : normalBackground// "transparent" - checkedTextColor: colorizerManager.buttonTextColor - checkedBackgroundColor: colorizerManager.buttonFocusColor - checked: root.inConfigureAppletsMode - hoveredExternal: rearrangeTooltipBtn.hovered + iconPositionReversed: plasmoid.location === PlasmaCore.Types.RightEdge - property color normalBackground: Qt.rgba(colorizerManager.buttonHoverColor.r, - colorizerManager.buttonHoverColor.g, - colorizerManager.buttonHoverColor.b, - 0.3) - - property color hoveredBackground: Qt.rgba(colorizerManager.buttonHoverColor.r, - colorizerManager.buttonHoverColor.g, - colorizerManager.buttonHoverColor.b, - 0.7) - - onPressed: { - if (Latte.WindowSystem.compositingActive) { - plasmoid.configuration.inConfigureAppletsMode = !plasmoid.configuration.inConfigureAppletsMode; - } - } - } - - PlasmaComponents.Button { - id: rearrangeTooltipBtn - anchors.fill: rearrangeBtn - opacity: 0 - tooltip: headerSettings.tooltip + icon: SettingsControls.RearrangeIcon{} onPressedChanged: { if (Latte.WindowSystem.compositingActive && pressed) { @@ -120,4 +132,43 @@ Item { } } } + + SettingsControls.Button{ + id: stickOnBottomBtn + visible: root.isVertical && inExpertSettingsMode + + text: i18n("Stick On Bottom"); + tooltip: i18n("Stick maximum available space at top screen edge and ignore any bottom docks or panels") + checked: plasmoid.configuration.isStickedOnBottomEdge + iconPositionReversed: (plasmoid.location !== PlasmaCore.Types.RightEdge) + + icon: SettingsControls.StickIcon{} + + onPressedChanged: { + if (pressed) { + plasmoid.configuration.isStickedOnBottomEdge = !plasmoid.configuration.isStickedOnBottomEdge; + } + } + + states: [ + State { + name: "generalEdge" + when: (plasmoid.location !== PlasmaCore.Types.RightEdge) + + AnchorChanges { + target: stickOnBottomBtn + anchors{ top:parent.top; bottom:undefined; left:undefined; right:parent.right; horizontalCenter:undefined; verticalCenter:undefined} + } + }, + State { + name: "rightEdge" + when: (plasmoid.location === PlasmaCore.Types.RightEdge) + + AnchorChanges { + target: stickOnBottomBtn + anchors{ top:parent.top; bottom:undefined; left:parent.left; right:undefined; horizontalCenter:undefined; verticalCenter:undefined} + } + } + ] + } } diff --git a/containment/package/contents/ui/editmode/controls/Button.qml b/containment/package/contents/ui/editmode/controls/Button.qml index e4d7e6d63..9e71da76f 100644 --- a/containment/package/contents/ui/editmode/controls/Button.qml +++ b/containment/package/contents/ui/editmode/controls/Button.qml @@ -32,71 +32,84 @@ Item{ width: visibleButton.width height: visibleButton.height - signal pressed(); + signal pressedChanged(bool pressed); property bool checked: false - property bool hoveredExternal: false - property bool reverseIcon: false + + property bool iconPositionReversed: false property string text: "Default Text" property string tooltip: "" - readonly property bool containsMouse: buttonMouseArea.containsMouse || hoveredExternal + readonly property bool containsMouse: tooltipBtn.hovered readonly property int implicitHeight: visibleButton.height readonly property color appliedTextColor: checked ? checkedTextColor : textColor readonly property color appliedBackgroundColor: checked ? checkedBackgroundColor : backgroundColor - property color textColor: "white" - property color backgroundColor: "black" - property color checkedTextColor: "black" - property color checkedBackgroundColor: "white" + readonly property color textColor: containsMouse ? colorizerManager.buttonTextColor : settingsRoot.textColor + readonly property color backgroundColor: containsMouse ? hoveredBackground : normalBackground// "transparent" + readonly property color checkedTextColor: colorizerManager.buttonTextColor + readonly property color checkedBackgroundColor: colorizerManager.buttonFocusColor - Rectangle { - id: visibleButton - width: buttonRow.width + 4 * margin - height: buttonRow.height + 2 * margin - radius: 2 - color: appliedBackgroundColor - // border.width: 1 - // border.color: checked ? appliedBackgroundColor : appliedTextColor + readonly property color normalBackground: Qt.rgba(colorizerManager.buttonHoverColor.r, + colorizerManager.buttonHoverColor.g, + colorizerManager.buttonHoverColor.b, + 0.3) - readonly property int margin: units.smallSpacing + readonly property color hoveredBackground: Qt.rgba(colorizerManager.buttonHoverColor.r, + colorizerManager.buttonHoverColor.g, + colorizerManager.buttonHoverColor.b, + 0.7) - RowLayout{ - id: buttonRow - anchors.centerIn: parent - spacing: units.smallSpacing - layoutDirection: reverseIcon ? Qt.RightToLeft : Qt.LeftToRight + property Component icon - RearrangeIcon{ - width: height - height: textLbl.implicitHeight - iconColor: button.appliedTextColor - } + Item{ + id: visibleButtonRoot + width: visibleButton.width + height: visibleButton.height - PlasmaComponents.Label{ - id: textLbl - text: button.text - color: button.appliedTextColor + Rectangle { + id: visibleButton + width: buttonRow.width + 4 * margin + height: buttonRow.height + 2 * margin + radius: 2 + color: appliedBackgroundColor + // border.width: 1 + // border.color: checked ? appliedBackgroundColor : appliedTextColor + + readonly property int margin: units.smallSpacing + + RowLayout{ + id: buttonRow + anchors.centerIn: parent + spacing: units.smallSpacing + layoutDirection: iconPositionReversed ? Qt.RightToLeft : Qt.LeftToRight + + Loader { + width: height + height: textLbl.implicitHeight + active: button.icon + sourceComponent: button.icon + visible: active + + readonly property color iconColor: button.appliedTextColor + } + + PlasmaComponents.Label{ + id: textLbl + text: button.text + color: button.appliedTextColor + } } } - - /* Rectangle { - anchors.topMargin: 1 - anchors.top: buttonRow.bottom - anchors.horizontalCenter: buttonRow.horizontalCenter - width: visibleButton.width - height: 1 - color: button.appliedTextColor - visible: buttonMouseArea.containsMouse - }*/ } - MouseArea{ - id: buttonMouseArea - anchors.fill: visibleButton - hoverEnabled: true + PlasmaComponents.Button { + id: tooltipBtn + anchors.fill: visibleButtonRoot + opacity: 0 + tooltip: button.tooltip - onClicked: button.pressed(); + onPressedChanged: button.pressedChanged(pressed) } } diff --git a/containment/package/contents/ui/editmode/controls/GraphicIcon.qml b/containment/package/contents/ui/editmode/controls/GraphicIcon.qml new file mode 100644 index 000000000..2449cbf94 --- /dev/null +++ b/containment/package/contents/ui/editmode/controls/GraphicIcon.qml @@ -0,0 +1,25 @@ +/* +* Copyright 2020 Michail Vourlakos +* +* 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 . +*/ + +import QtQuick 2.7 + +Item{ + readonly property int margin: 2 + readonly property color iconColor: parent.iconColor +} diff --git a/containment/package/contents/ui/editmode/controls/RearrangeIcon.qml b/containment/package/contents/ui/editmode/controls/RearrangeIcon.qml index 12f0b4b34..4a209880a 100644 --- a/containment/package/contents/ui/editmode/controls/RearrangeIcon.qml +++ b/containment/package/contents/ui/editmode/controls/RearrangeIcon.qml @@ -18,18 +18,8 @@ */ import QtQuick 2.7 -import QtGraphicalEffects 1.0 - -import org.kde.plasma.plasmoid 2.0 -import org.kde.plasma.core 2.0 as PlasmaCore -import org.kde.plasma.components 2.0 as PlasmaComponents - -import org.kde.latte 0.2 as Latte - - -Item{ - property color iconColor: "red" +GraphicIcon{ readonly property int itemLength: 0.22*width Rectangle { diff --git a/containment/package/contents/ui/editmode/controls/StickIcon.qml b/containment/package/contents/ui/editmode/controls/StickIcon.qml new file mode 100644 index 000000000..4a1c315b2 --- /dev/null +++ b/containment/package/contents/ui/editmode/controls/StickIcon.qml @@ -0,0 +1,42 @@ +/* +* Copyright 2019 Michail Vourlakos +* +* 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 . +*/ + +import QtQuick 2.7 + +import org.kde.plasma.plasmoid 2.0 +import org.kde.plasma.core 2.0 as PlasmaCore + +GraphicIcon{ + readonly property int itemLength: 0.22*width + + Rectangle { + anchors.fill: parent + anchors.margins: parent.margin * 2 + color: "transparent" + + Rectangle{ + id: circle + anchors.centerIn: parent + width: parent.width + height: parent.height + radius: width/2 + color: iconColor + } + } +}