mirror of
https://invent.kde.org/marcoa/shift-shell.git
synced 2026-04-26 14:23:09 +00:00
folio: Refactor and implement support for proper drag & drop
This refactors the homescreen state object to isolate drag & drop from swipe states, allowing for using proper system-level drag & drop for delegate movement. This then ports the new applet list to use it.
This commit is contained in:
parent
1250180c45
commit
4c76f55b5c
16 changed files with 901 additions and 787 deletions
|
|
@ -9,6 +9,7 @@ plasma_add_applet(org.kde.plasma.mobile.homescreen.folio
|
||||||
qml/AppDrawerGrid.qml
|
qml/AppDrawerGrid.qml
|
||||||
qml/AppDrawerHeader.qml
|
qml/AppDrawerHeader.qml
|
||||||
qml/DelegateDragItem.qml
|
qml/DelegateDragItem.qml
|
||||||
|
qml/DelegateDropArea.qml
|
||||||
qml/FavouritesBar.qml
|
qml/FavouritesBar.qml
|
||||||
qml/FolderView.qml
|
qml/FolderView.qml
|
||||||
qml/FolderViewTitle.qml
|
qml/FolderViewTitle.qml
|
||||||
|
|
@ -65,6 +66,7 @@ ecm_target_qml_sources(org.kde.plasma.mobile.homescreen.folio SOURCES
|
||||||
)
|
)
|
||||||
|
|
||||||
ecm_target_qml_sources(org.kde.plasma.mobile.homescreen.folio SOURCES
|
ecm_target_qml_sources(org.kde.plasma.mobile.homescreen.folio SOURCES
|
||||||
|
qml/settings/AppletListDelegate.qml
|
||||||
qml/settings/AppletListViewer.qml
|
qml/settings/AppletListViewer.qml
|
||||||
qml/settings/SettingsButton.qml
|
qml/settings/SettingsButton.qml
|
||||||
qml/settings/SettingsComponent.qml
|
qml/settings/SettingsComponent.qml
|
||||||
|
|
|
||||||
|
|
@ -175,12 +175,9 @@ DragState::DragState(HomeScreenState *state, HomeScreen *parent)
|
||||||
connect(m_state, &HomeScreenState::delegateDragFromFavouritesStarted, this, &DragState::onDelegateDragFromFavouritesStarted);
|
connect(m_state, &HomeScreenState::delegateDragFromFavouritesStarted, this, &DragState::onDelegateDragFromFavouritesStarted);
|
||||||
connect(m_state, &HomeScreenState::delegateDragFromFolderStarted, this, &DragState::onDelegateDragFromFolderStarted);
|
connect(m_state, &HomeScreenState::delegateDragFromFolderStarted, this, &DragState::onDelegateDragFromFolderStarted);
|
||||||
connect(m_state, &HomeScreenState::delegateDragFromWidgetListStarted, this, &DragState::onDelegateDragFromWidgetListStarted);
|
connect(m_state, &HomeScreenState::delegateDragFromWidgetListStarted, this, &DragState::onDelegateDragFromWidgetListStarted);
|
||||||
connect(m_state, &HomeScreenState::swipeStateChanged, this, [this]() {
|
connect(m_state, &HomeScreenState::delegateDragStarted, this, &DragState::onDelegateDraggingStarted);
|
||||||
if (m_state->swipeState() == HomeScreenState::DraggingDelegate) {
|
connect(m_state, &HomeScreenState::delegateDragDropped, this, &DragState::onDelegateDropped);
|
||||||
onDelegateDraggingStarted();
|
connect(m_state, &HomeScreenState::delegateDragCancelled, this, &DragState::onDelegateDraggingCancelled);
|
||||||
}
|
|
||||||
});
|
|
||||||
connect(m_state, &HomeScreenState::delegateDragEnded, this, &DragState::onDelegateDropped);
|
|
||||||
|
|
||||||
connect(m_state, &HomeScreenState::pageNumChanged, this, [this]() {
|
connect(m_state, &HomeScreenState::pageNumChanged, this, [this]() {
|
||||||
m_candidateDropPosition->setPageRow(m_state->currentPage());
|
m_candidateDropPosition->setPageRow(m_state->currentPage());
|
||||||
|
|
@ -546,19 +543,8 @@ void DragState::onDelegateDropped()
|
||||||
// add dropped delegate
|
// add dropped delegate
|
||||||
bool success = createDropPositionDelegate();
|
bool success = createDropPositionDelegate();
|
||||||
|
|
||||||
// delete empty pages at the end if they exist
|
// Cleanup timers and state
|
||||||
// (it can be created if user drags app to new page, but doesn't place it there)
|
dragStopCleanup();
|
||||||
m_homeScreen->pageListModel()->deleteEmptyPagesAtEnd();
|
|
||||||
|
|
||||||
// clear ghost position if there is one
|
|
||||||
m_homeScreen->favouritesModel()->deleteGhostEntry();
|
|
||||||
|
|
||||||
// reset timers
|
|
||||||
m_folderInsertBetweenTimer->stop();
|
|
||||||
m_changeFolderPageTimer->stop();
|
|
||||||
m_leaveFolderTimer->stop();
|
|
||||||
m_changePageTimer->stop();
|
|
||||||
m_favouritesInsertBetweenTimer->stop();
|
|
||||||
|
|
||||||
// emit corresponding signal
|
// emit corresponding signal
|
||||||
// -> if we couldn't drop a new delegate at a spot, emit newDelegateDropAbandoned()
|
// -> if we couldn't drop a new delegate at a spot, emit newDelegateDropAbandoned()
|
||||||
|
|
@ -570,6 +556,41 @@ void DragState::onDelegateDropped()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DragState::onDelegateDraggingCancelled()
|
||||||
|
{
|
||||||
|
if (!m_dropDelegate) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cleanup timers and state
|
||||||
|
dragStopCleanup();
|
||||||
|
|
||||||
|
if (m_startPosition->location() == DelegateDragPosition::WidgetList || m_startPosition->location() == DelegateDragPosition::AppDrawer) {
|
||||||
|
// If this is a new delegate, it's abandoned
|
||||||
|
Q_EMIT newDelegateDropAbandoned();
|
||||||
|
} else {
|
||||||
|
// If it's an existing delegate, it simply goes back to its original position
|
||||||
|
Q_EMIT delegateDroppedAndPlaced();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DragState::dragStopCleanup()
|
||||||
|
{
|
||||||
|
// Delete empty pages at the end if they exist
|
||||||
|
// (it can be created if user drags app to new page, but doesn't place it there)
|
||||||
|
m_homeScreen->pageListModel()->deleteEmptyPagesAtEnd();
|
||||||
|
|
||||||
|
// Clear ghost position if there is one
|
||||||
|
m_homeScreen->favouritesModel()->deleteGhostEntry();
|
||||||
|
|
||||||
|
// Reset timers
|
||||||
|
m_folderInsertBetweenTimer->stop();
|
||||||
|
m_changeFolderPageTimer->stop();
|
||||||
|
m_leaveFolderTimer->stop();
|
||||||
|
m_changePageTimer->stop();
|
||||||
|
m_favouritesInsertBetweenTimer->stop();
|
||||||
|
}
|
||||||
|
|
||||||
void DragState::onLeaveCurrentFolder()
|
void DragState::onLeaveCurrentFolder()
|
||||||
{
|
{
|
||||||
if (!m_state) {
|
if (!m_state) {
|
||||||
|
|
@ -589,7 +610,7 @@ void DragState::onLeaveCurrentFolder()
|
||||||
|
|
||||||
void DragState::onChangePageTimerFinished()
|
void DragState::onChangePageTimerFinished()
|
||||||
{
|
{
|
||||||
if (!m_state || (m_state->swipeState() != HomeScreenState::DraggingDelegate)) {
|
if (!m_state || !m_state->isDraggingDelegate()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -624,7 +645,7 @@ void DragState::onChangePageTimerFinished()
|
||||||
|
|
||||||
void DragState::onOpenFolderTimerFinished()
|
void DragState::onOpenFolderTimerFinished()
|
||||||
{
|
{
|
||||||
if (!m_state || m_state->swipeState() != HomeScreenState::DraggingDelegate || m_state->viewState() != HomeScreenState::PageView
|
if (!m_state || !m_state->isDraggingDelegate() || m_state->viewState() != HomeScreenState::PageView
|
||||||
|| (m_candidateDropPosition->location() != DelegateDragPosition::Pages && m_candidateDropPosition->location() != DelegateDragPosition::Favourites)) {
|
|| (m_candidateDropPosition->location() != DelegateDragPosition::Pages && m_candidateDropPosition->location() != DelegateDragPosition::Favourites)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -672,7 +693,7 @@ void DragState::onOpenFolderTimerFinished()
|
||||||
|
|
||||||
void DragState::onLeaveFolderTimerFinished()
|
void DragState::onLeaveFolderTimerFinished()
|
||||||
{
|
{
|
||||||
if (!m_state || (m_state->swipeState() != HomeScreenState::DraggingDelegate) || !m_state->currentFolder()) {
|
if (!m_state || !m_state->isDraggingDelegate() || !m_state->currentFolder()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -684,7 +705,7 @@ void DragState::onLeaveFolderTimerFinished()
|
||||||
|
|
||||||
void DragState::onChangeFolderPageTimerFinished()
|
void DragState::onChangeFolderPageTimerFinished()
|
||||||
{
|
{
|
||||||
if (!m_state || (m_state->swipeState() != HomeScreenState::DraggingDelegate) || !m_state->currentFolder()) {
|
if (!m_state || !m_state->isDraggingDelegate() || !m_state->currentFolder()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -720,7 +741,7 @@ void DragState::onChangeFolderPageTimerFinished()
|
||||||
|
|
||||||
void DragState::onFolderInsertBetweenTimerFinished()
|
void DragState::onFolderInsertBetweenTimerFinished()
|
||||||
{
|
{
|
||||||
if (!m_state || (m_state->swipeState() != HomeScreenState::DraggingDelegate) || !m_state->currentFolder()) {
|
if (!m_state || !m_state->isDraggingDelegate() || !m_state->currentFolder()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -118,6 +118,7 @@ private Q_SLOTS:
|
||||||
void onDelegateDragFromFolderStarted(FolioApplicationFolder *folder, int position);
|
void onDelegateDragFromFolderStarted(FolioApplicationFolder *folder, int position);
|
||||||
void onDelegateDragFromWidgetListStarted(QString appletPluginId);
|
void onDelegateDragFromWidgetListStarted(QString appletPluginId);
|
||||||
void onDelegateDropped();
|
void onDelegateDropped();
|
||||||
|
void onDelegateDraggingCancelled();
|
||||||
|
|
||||||
void onLeaveCurrentFolder();
|
void onLeaveCurrentFolder();
|
||||||
|
|
||||||
|
|
@ -129,6 +130,9 @@ private Q_SLOTS:
|
||||||
void onFavouritesInsertBetweenTimerFinished();
|
void onFavouritesInsertBetweenTimerFinished();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// Cleanup after a drag event (stop timers etc.)
|
||||||
|
void dragStopCleanup();
|
||||||
|
|
||||||
// deletes the delegate at m_startPosition
|
// deletes the delegate at m_startPosition
|
||||||
void deleteStartPositionDelegate();
|
void deleteStartPositionDelegate();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -195,6 +195,7 @@ void HomeScreenState::setSwipeState(SwipeState swipeState)
|
||||||
if (swipeState != m_swipeState) {
|
if (swipeState != m_swipeState) {
|
||||||
m_swipeState = swipeState;
|
m_swipeState = swipeState;
|
||||||
Q_EMIT swipeStateChanged();
|
Q_EMIT swipeStateChanged();
|
||||||
|
Q_EMIT isDraggingDelegateChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -692,6 +693,11 @@ int HomeScreenState::currentFolderPage()
|
||||||
return m_folderPageNum;
|
return m_folderPageNum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool HomeScreenState::isDraggingDelegate()
|
||||||
|
{
|
||||||
|
return m_dragDropActive || m_swipeState == SwipeState::DraggingDelegate;
|
||||||
|
}
|
||||||
|
|
||||||
FolioDelegate *HomeScreenState::getPageDelegateAt(int page, int row, int column)
|
FolioDelegate *HomeScreenState::getPageDelegateAt(int page, int row, int column)
|
||||||
{
|
{
|
||||||
PageModel *pageModel = m_homeScreen->pageListModel()->getPage(page);
|
PageModel *pageModel = m_homeScreen->pageListModel()->getPage(page);
|
||||||
|
|
@ -905,6 +911,7 @@ void HomeScreenState::startDelegateAppDrawerDrag(qreal startX, qreal startY, qre
|
||||||
// we start dragging the delegate immediately from the app drawer, because we don't have a context menu to deal with!
|
// we start dragging the delegate immediately from the app drawer, because we don't have a context menu to deal with!
|
||||||
// NOTE: this has to happen after delegateDragFromAppDrawerStarted, because slots for that expect SwipeState::AwaitingDraggingDelegate
|
// NOTE: this has to happen after delegateDragFromAppDrawerStarted, because slots for that expect SwipeState::AwaitingDraggingDelegate
|
||||||
setSwipeState(SwipeState::DraggingDelegate);
|
setSwipeState(SwipeState::DraggingDelegate);
|
||||||
|
Q_EMIT delegateDragStarted();
|
||||||
}
|
}
|
||||||
|
|
||||||
void HomeScreenState::startDelegateFolderDrag(qreal startX,
|
void HomeScreenState::startDelegateFolderDrag(qreal startX,
|
||||||
|
|
@ -922,10 +929,6 @@ void HomeScreenState::startDelegateWidgetListDrag(qreal startX, qreal startY, qr
|
||||||
{
|
{
|
||||||
startDelegateDrag(startX, startY, pointerOffsetX, pointerOffsetY);
|
startDelegateDrag(startX, startY, pointerOffsetX, pointerOffsetY);
|
||||||
Q_EMIT delegateDragFromWidgetListStarted(appletPluginId);
|
Q_EMIT delegateDragFromWidgetListStarted(appletPluginId);
|
||||||
|
|
||||||
// we start dragging the delegate immediately from the app drawer, because we don't have a context menu to deal with!
|
|
||||||
// NOTE: this has to happen after delegateDragFromAppDrawerStarted, because slots for that expect SwipeState::AwaitingDraggingDelegate
|
|
||||||
setSwipeState(SwipeState::DraggingDelegate);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void HomeScreenState::cancelDelegateDrag()
|
void HomeScreenState::cancelDelegateDrag()
|
||||||
|
|
@ -991,7 +994,7 @@ void HomeScreenState::swipeEnded()
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SwipeState::DraggingDelegate:
|
case SwipeState::DraggingDelegate:
|
||||||
Q_EMIT delegateDragEnded();
|
Q_EMIT delegateDragDropped();
|
||||||
break;
|
break;
|
||||||
case SwipeState::AwaitingDraggingDelegate:
|
case SwipeState::AwaitingDraggingDelegate:
|
||||||
case SwipeState::DeterminingSwipeType:
|
case SwipeState::DeterminingSwipeType:
|
||||||
|
|
@ -1003,6 +1006,45 @@ void HomeScreenState::swipeEnded()
|
||||||
setSwipeState(SwipeState::None);
|
setSwipeState(SwipeState::None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HomeScreenState::dragStart()
|
||||||
|
{
|
||||||
|
// Cancel AwaitingDraggingDelegate
|
||||||
|
swipeEnded();
|
||||||
|
|
||||||
|
m_dragDropActive = true;
|
||||||
|
Q_EMIT delegateDragStarted();
|
||||||
|
Q_EMIT isDraggingDelegateChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void HomeScreenState::dragMove(qreal deltaX, qreal deltaY)
|
||||||
|
{
|
||||||
|
if (!m_dragDropActive) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setDelegateDragX(m_delegateDragX + deltaX);
|
||||||
|
setDelegateDragY(m_delegateDragY + deltaY);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HomeScreenState::dragDrop()
|
||||||
|
{
|
||||||
|
if (!m_dragDropActive) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_dragDropActive = false;
|
||||||
|
Q_EMIT delegateDragDropped();
|
||||||
|
Q_EMIT isDraggingDelegateChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void HomeScreenState::dragCancel()
|
||||||
|
{
|
||||||
|
if (!m_dragDropActive) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_dragDropActive = false;
|
||||||
|
Q_EMIT delegateDragCancelled();
|
||||||
|
Q_EMIT isDraggingDelegateChanged();
|
||||||
|
}
|
||||||
|
|
||||||
void HomeScreenState::swipeCancelled()
|
void HomeScreenState::swipeCancelled()
|
||||||
{
|
{
|
||||||
setSwipeState(SwipeState::None);
|
setSwipeState(SwipeState::None);
|
||||||
|
|
@ -1038,6 +1080,7 @@ void HomeScreenState::swipeMoved(qreal totalDeltaX, qreal totalDeltaY, qreal del
|
||||||
break;
|
break;
|
||||||
case SwipeState::AwaitingDraggingDelegate:
|
case SwipeState::AwaitingDraggingDelegate:
|
||||||
setSwipeState(SwipeState::DraggingDelegate);
|
setSwipeState(SwipeState::DraggingDelegate);
|
||||||
|
Q_EMIT delegateDragStarted();
|
||||||
break;
|
break;
|
||||||
case SwipeState::DraggingDelegate:
|
case SwipeState::DraggingDelegate:
|
||||||
setDelegateDragX(m_delegateDragX + deltaX);
|
setDelegateDragX(m_delegateDragX + deltaX);
|
||||||
|
|
|
||||||
|
|
@ -80,6 +80,8 @@ class HomeScreenState : public QObject
|
||||||
Q_PROPERTY(int currentPage READ currentPage NOTIFY pageNumChanged)
|
Q_PROPERTY(int currentPage READ currentPage NOTIFY pageNumChanged)
|
||||||
Q_PROPERTY(int currentFolderPage READ currentFolderPage NOTIFY folderPageNumChanged)
|
Q_PROPERTY(int currentFolderPage READ currentFolderPage NOTIFY folderPageNumChanged)
|
||||||
|
|
||||||
|
Q_PROPERTY(bool isDraggingDelegate READ isDraggingDelegate NOTIFY isDraggingDelegateChanged)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum SwipeState {
|
enum SwipeState {
|
||||||
None,
|
None,
|
||||||
|
|
@ -258,6 +260,9 @@ public:
|
||||||
|
|
||||||
int currentFolderPage();
|
int currentFolderPage();
|
||||||
|
|
||||||
|
// Whether something is being dragged (either from SwipeArea or Drag & Drop)
|
||||||
|
bool isDraggingDelegate();
|
||||||
|
|
||||||
// QML helpers
|
// QML helpers
|
||||||
Q_INVOKABLE FolioDelegate *getPageDelegateAt(int page, int row, int column);
|
Q_INVOKABLE FolioDelegate *getPageDelegateAt(int page, int row, int column);
|
||||||
Q_INVOKABLE FolioDelegate *getFavouritesDelegateAt(int position);
|
Q_INVOKABLE FolioDelegate *getFavouritesDelegateAt(int position);
|
||||||
|
|
@ -305,7 +310,9 @@ Q_SIGNALS:
|
||||||
void searchWidgetYChanged();
|
void searchWidgetYChanged();
|
||||||
void delegateDragXChanged();
|
void delegateDragXChanged();
|
||||||
void delegateDragYChanged();
|
void delegateDragYChanged();
|
||||||
void delegateDragEnded();
|
void delegateDragStarted();
|
||||||
|
void delegateDragDropped();
|
||||||
|
void delegateDragCancelled();
|
||||||
void delegateDragFromPageStarted(int page, int row, int column);
|
void delegateDragFromPageStarted(int page, int row, int column);
|
||||||
void delegateDragFromFavouritesStarted(int position);
|
void delegateDragFromFavouritesStarted(int position);
|
||||||
void delegateDragFromAppDrawerStarted(QString storageId);
|
void delegateDragFromAppDrawerStarted(QString storageId);
|
||||||
|
|
@ -313,6 +320,7 @@ Q_SIGNALS:
|
||||||
void delegateDragFromWidgetListStarted(QString appletPluginId);
|
void delegateDragFromWidgetListStarted(QString appletPluginId);
|
||||||
void pageNumChanged();
|
void pageNumChanged();
|
||||||
void folderPageNumChanged();
|
void folderPageNumChanged();
|
||||||
|
void isDraggingDelegateChanged();
|
||||||
|
|
||||||
void leftCurrentFolder();
|
void leftCurrentFolder();
|
||||||
void folderAboutToOpen(qreal x, qreal y); // the position on the screen where the delegate is at, for animations
|
void folderAboutToOpen(qreal x, qreal y); // the position on the screen where the delegate is at, for animations
|
||||||
|
|
@ -347,6 +355,12 @@ public Q_SLOTS:
|
||||||
void swipeCancelled();
|
void swipeCancelled();
|
||||||
void swipeMoved(qreal totalDeltaX, qreal totalDeltaY, qreal deltaX, qreal deltaY);
|
void swipeMoved(qreal totalDeltaX, qreal totalDeltaY, qreal deltaX, qreal deltaY);
|
||||||
|
|
||||||
|
// from DropArea
|
||||||
|
void dragStart();
|
||||||
|
void dragMove(qreal deltaX, qreal deltaY);
|
||||||
|
void dragDrop();
|
||||||
|
void dragCancel();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setViewState(ViewState viewState);
|
void setViewState(ViewState viewState);
|
||||||
void setSwipeState(SwipeState swipeState);
|
void setSwipeState(SwipeState swipeState);
|
||||||
|
|
@ -410,6 +424,7 @@ private:
|
||||||
qreal m_delegateDragY{0};
|
qreal m_delegateDragY{0};
|
||||||
qreal m_delegateDragPointerOffsetX{0};
|
qreal m_delegateDragPointerOffsetX{0};
|
||||||
qreal m_delegateDragPointerOffsetY{0};
|
qreal m_delegateDragPointerOffsetY{0};
|
||||||
|
bool m_dragDropActive{false};
|
||||||
|
|
||||||
int m_pageNum{0};
|
int m_pageNum{0};
|
||||||
int m_folderPageNum{0};
|
int m_folderPageNum{0};
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,8 @@ import org.kde.plasma.private.mobileshell as MobileShell
|
||||||
|
|
||||||
import "./delegate"
|
import "./delegate"
|
||||||
|
|
||||||
|
// Placeholder item that the user sees as they drag app/folder delegates around.
|
||||||
|
// See WidgetDragItem for the equivalent for widgets.
|
||||||
Item {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
property Folio.HomeScreen folio
|
property Folio.HomeScreen folio
|
||||||
|
|
@ -75,15 +77,16 @@ Item {
|
||||||
property var delegateDroppedOn: null
|
property var delegateDroppedOn: null
|
||||||
|
|
||||||
// reset and show drag item
|
// reset and show drag item
|
||||||
function onSwipeStateChanged() {
|
function onDelegateDragStarted() {
|
||||||
if (folio.HomeScreenState.swipeState === Folio.HomeScreenState.DraggingDelegate && !isWidgetDrag) {
|
if (isWidgetDrag) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
root.scale = 1.0;
|
root.scale = 1.0;
|
||||||
root.visible = true;
|
root.visible = true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// save the existing delegate at the spot (this is called before the delegate is dropped)
|
// save the existing delegate at the spot (this is called before the delegate is dropped)
|
||||||
function onDelegateDragEnded() {
|
function onDelegateDragDropped() {
|
||||||
if (root.isWidgetDrag) {
|
if (root.isWidgetDrag) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -103,6 +106,7 @@ Item {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
|
|
|
||||||
57
containments/homescreens/folio/qml/DelegateDropArea.qml
Normal file
57
containments/homescreens/folio/qml/DelegateDropArea.qml
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
// SPDX-FileCopyrightText: 2025 Devin Lin <devin@kde.org>
|
||||||
|
// SPDX-License-Identifier: LGPL-2.0-or-later
|
||||||
|
|
||||||
|
import QtQuick
|
||||||
|
|
||||||
|
import plasma.applet.org.kde.plasma.mobile.homescreen.folio as Folio
|
||||||
|
|
||||||
|
DropArea {
|
||||||
|
id: root
|
||||||
|
property Folio.HomeScreen folio
|
||||||
|
property Folio.HomeScreenState homeScreenState: folio.HomeScreenState
|
||||||
|
|
||||||
|
keys: ["text/x-plasmoidservicename"]
|
||||||
|
|
||||||
|
property real prevX
|
||||||
|
property real prevY
|
||||||
|
|
||||||
|
onEntered: (drag) => {
|
||||||
|
drag.accept();
|
||||||
|
const widthOffset = folio.HomeScreenState.pageCellWidth / 2;
|
||||||
|
const heightOffset = folio.HomeScreenState.pageCellHeight / 2;
|
||||||
|
|
||||||
|
homeScreenState.startDelegateWidgetListDrag(
|
||||||
|
drag.x - widthOffset,
|
||||||
|
drag.y - heightOffset,
|
||||||
|
widthOffset,
|
||||||
|
heightOffset,
|
||||||
|
drag.getDataAsString("text/x-plasmoidservicename")
|
||||||
|
);
|
||||||
|
|
||||||
|
homeScreenState.dragStart();
|
||||||
|
prevX = drag.x;
|
||||||
|
prevY = drag.y;
|
||||||
|
}
|
||||||
|
onDropped: (drop) => {
|
||||||
|
drop.accept();
|
||||||
|
dropWaitTimer.restart();
|
||||||
|
}
|
||||||
|
onExited: {
|
||||||
|
homeScreenState.dragCancel();
|
||||||
|
}
|
||||||
|
onPositionChanged: (drag) => {
|
||||||
|
drag.accept();
|
||||||
|
homeScreenState.dragMove(drag.x - prevX, drag.y - prevY);
|
||||||
|
prevX = drag.x;
|
||||||
|
prevY = drag.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
// HACK: Seems to crash otherwise, Qt bug?
|
||||||
|
Timer {
|
||||||
|
id: dropWaitTimer
|
||||||
|
interval: 10
|
||||||
|
onTriggered: {
|
||||||
|
homeScreenState.dragDrop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -66,7 +66,7 @@ MouseArea {
|
||||||
readonly property var dragState: folio.HomeScreenState.dragState
|
readonly property var dragState: folio.HomeScreenState.dragState
|
||||||
readonly property bool isDropPositionThis: dragState.candidateDropPosition.location === Folio.DelegateDragPosition.Favourites &&
|
readonly property bool isDropPositionThis: dragState.candidateDropPosition.location === Folio.DelegateDragPosition.Favourites &&
|
||||||
dragState.candidateDropPosition.favouritesPosition === delegate.index
|
dragState.candidateDropPosition.favouritesPosition === delegate.index
|
||||||
readonly property bool isAppHoveredOver: folio.HomeScreenState.swipeState === Folio.HomeScreenState.DraggingDelegate &&
|
readonly property bool isAppHoveredOver: folio.HomeScreenState.isDraggingDelegate &&
|
||||||
dragState.dropDelegate &&
|
dragState.dropDelegate &&
|
||||||
dragState.dropDelegate.type === Folio.FolioDelegate.Application &&
|
dragState.dropDelegate.type === Folio.FolioDelegate.Application &&
|
||||||
isDropPositionThis
|
isDropPositionThis
|
||||||
|
|
@ -178,7 +178,7 @@ MouseArea {
|
||||||
shadow: true
|
shadow: true
|
||||||
|
|
||||||
turnToFolder: delegate.isAppHoveredOver
|
turnToFolder: delegate.isAppHoveredOver
|
||||||
turnToFolderAnimEnabled: folio.HomeScreenState.swipeState === Folio.HomeScreenState.DraggingDelegate
|
turnToFolderAnimEnabled: folio.HomeScreenState.isDraggingDelegate
|
||||||
|
|
||||||
// do not show if the drop animation is running to this delegate
|
// do not show if the drop animation is running to this delegate
|
||||||
visible: !(root.homeScreen.dropAnimationRunning && delegate.isDropPositionThis)
|
visible: !(root.homeScreen.dropAnimationRunning && delegate.isDropPositionThis)
|
||||||
|
|
@ -221,12 +221,10 @@ MouseArea {
|
||||||
Connections {
|
Connections {
|
||||||
target: folio.HomeScreenState
|
target: folio.HomeScreenState
|
||||||
|
|
||||||
function onSwipeStateChanged() {
|
function onDelegateDragStarted() {
|
||||||
if (folio.HomeScreenState.swipeState === Folio.HomeScreenState.DraggingDelegate) {
|
|
||||||
contextMenu.close();
|
contextMenu.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
actions: [
|
actions: [
|
||||||
Kirigami.Action {
|
Kirigami.Action {
|
||||||
|
|
@ -298,12 +296,10 @@ MouseArea {
|
||||||
Connections {
|
Connections {
|
||||||
target: folio.HomeScreenState
|
target: folio.HomeScreenState
|
||||||
|
|
||||||
function onSwipeStateChanged() {
|
function onDelegateDragStarted() {
|
||||||
if (folio.HomeScreenState.swipeState === Folio.HomeScreenState.DraggingDelegate) {
|
|
||||||
contextMenu.close();
|
contextMenu.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
actions: [
|
actions: [
|
||||||
Kirigami.Action {
|
Kirigami.Action {
|
||||||
|
|
|
||||||
|
|
@ -326,7 +326,7 @@ Folio.DelegateTouchArea {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
||||||
sourceComponent: {
|
sourceComponent: {
|
||||||
if (delegate.delegateModel.type === Folio.FolioDelegate.Application) {
|
if (delegate.delegateModel && delegate.delegateModel.type === Folio.FolioDelegate.Application) {
|
||||||
return appComponent;
|
return appComponent;
|
||||||
} else {
|
} else {
|
||||||
return noneComponent;
|
return noneComponent;
|
||||||
|
|
@ -391,12 +391,10 @@ Folio.DelegateTouchArea {
|
||||||
Connections {
|
Connections {
|
||||||
target: folio.HomeScreenState
|
target: folio.HomeScreenState
|
||||||
|
|
||||||
function onSwipeStateChanged() {
|
function onDelegateDragStarted() {
|
||||||
if (folio.HomeScreenState.swipeState === Folio.HomeScreenState.DraggingDelegate) {
|
|
||||||
contextMenu.close();
|
contextMenu.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
actions: [
|
actions: [
|
||||||
Kirigami.Action {
|
Kirigami.Action {
|
||||||
|
|
|
||||||
|
|
@ -117,13 +117,20 @@ Item {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// area that can be swiped
|
// Drag and drop area
|
||||||
|
DelegateDropArea {
|
||||||
|
id: dropArea
|
||||||
|
folio: root.folio
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
// Area that can be swiped
|
||||||
MobileShell.SwipeArea {
|
MobileShell.SwipeArea {
|
||||||
id: swipeArea
|
id: swipeArea
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
||||||
interactive: root.interactive &&
|
interactive: root.interactive &&
|
||||||
settingsLoader.homeScreenInteractive &&
|
settings.homeScreenInteractive &&
|
||||||
|
!dropArea.containsDrag &&
|
||||||
(appDrawer.flickable.atYBeginning || // there are cases where contentY > 0 but atYBeginning is true
|
(appDrawer.flickable.atYBeginning || // there are cases where contentY > 0 but atYBeginning is true
|
||||||
appDrawer.flickable.contentY <= 10 ||
|
appDrawer.flickable.contentY <= 10 ||
|
||||||
// disable the swipe area when we are swiping in the app drawer, and not in drag-and-drop
|
// disable the swipe area when we are swiping in the app drawer, and not in drag-and-drop
|
||||||
|
|
@ -160,35 +167,23 @@ Item {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Loader {
|
SettingsComponent {
|
||||||
id: settingsLoader
|
id: settings
|
||||||
asynchronous: true
|
folio: root.folio
|
||||||
active: true
|
homeScreen: root
|
||||||
|
settingsModeHomeScreenScale: root.settingsModeHomeScreenScale
|
||||||
|
|
||||||
// Don't anchor, since we set y
|
// Don't anchor, since we set y
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: parent.height
|
height: parent.height
|
||||||
opacity: folio.HomeScreenState.settingsOpenProgress
|
opacity: folio.HomeScreenState.settingsOpenProgress
|
||||||
|
visible: opacity > 0
|
||||||
|
|
||||||
// move the settings out of the way if it is not visible
|
|
||||||
// NOTE: we do this instead of setting visible to false, because
|
|
||||||
// it doesn't mess with widget drag and drop
|
|
||||||
y: (opacity > 0) ? 0 : parent.height
|
|
||||||
z: 1
|
z: 1
|
||||||
|
|
||||||
readonly property bool homeScreenInteractive: item ? item.homeScreenInteractive : true
|
|
||||||
|
|
||||||
sourceComponent: SettingsComponent {
|
|
||||||
id: settings
|
|
||||||
folio: root.folio
|
|
||||||
|
|
||||||
bottomMargin: root.bottomMargin
|
bottomMargin: root.bottomMargin
|
||||||
leftMargin: root.leftMargin
|
leftMargin: root.leftMargin
|
||||||
rightMargin: root.rightMargin
|
rightMargin: root.rightMargin
|
||||||
|
|
||||||
settingsModeHomeScreenScale: root.settingsModeHomeScreenScale
|
|
||||||
homeScreen: root
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
|
|
@ -610,4 +605,5 @@ Item {
|
||||||
anchors.rightMargin: root.rightMargin
|
anchors.rightMargin: root.rightMargin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -124,7 +124,7 @@ Item {
|
||||||
property bool dropDelegateIsWidget: dropDelegate && dropDelegate.type === Folio.FolioDelegate.Widget
|
property bool dropDelegateIsWidget: dropDelegate && dropDelegate.type === Folio.FolioDelegate.Widget
|
||||||
|
|
||||||
// only show if it is an empty spot on this page
|
// only show if it is an empty spot on this page
|
||||||
visible: folio.HomeScreenState.swipeState === Folio.HomeScreenState.DraggingDelegate &&
|
visible: folio.HomeScreenState.isDraggingDelegate &&
|
||||||
dropPosition.location === Folio.DelegateDragPosition.Pages &&
|
dropPosition.location === Folio.DelegateDragPosition.Pages &&
|
||||||
dropPosition.page === root.pageNum &&
|
dropPosition.page === root.pageNum &&
|
||||||
!dropDelegateIsWidget &&
|
!dropDelegateIsWidget &&
|
||||||
|
|
@ -145,7 +145,7 @@ Item {
|
||||||
property bool dropDelegateIsWidget: dropDelegate && dropDelegate.type === Folio.FolioDelegate.Widget
|
property bool dropDelegateIsWidget: dropDelegate && dropDelegate.type === Folio.FolioDelegate.Widget
|
||||||
|
|
||||||
// only show if the widget can be placed here
|
// only show if the widget can be placed here
|
||||||
visible: folio.HomeScreenState.swipeState === Folio.HomeScreenState.DraggingDelegate &&
|
visible: folio.HomeScreenState.isDraggingDelegate &&
|
||||||
dropPosition.location === Folio.DelegateDragPosition.Pages &&
|
dropPosition.location === Folio.DelegateDragPosition.Pages &&
|
||||||
dropPosition.page === root.pageNum &&
|
dropPosition.page === root.pageNum &&
|
||||||
dropDelegateIsWidget &&
|
dropDelegateIsWidget &&
|
||||||
|
|
@ -180,7 +180,7 @@ Item {
|
||||||
dragState.candidateDropPosition.pageRow === delegate.pageDelegate.row &&
|
dragState.candidateDropPosition.pageRow === delegate.pageDelegate.row &&
|
||||||
dragState.candidateDropPosition.pageColumn === delegate.pageDelegate.column
|
dragState.candidateDropPosition.pageColumn === delegate.pageDelegate.column
|
||||||
|
|
||||||
property bool isAppHoveredOver: folio.HomeScreenState.swipeState === Folio.HomeScreenState.DraggingDelegate &&
|
property bool isAppHoveredOver: folio.HomeScreenState.isDraggingDelegate &&
|
||||||
dragState.dropDelegate &&
|
dragState.dropDelegate &&
|
||||||
dragState.dropDelegate.type === Folio.FolioDelegate.Application &&
|
dragState.dropDelegate.type === Folio.FolioDelegate.Application &&
|
||||||
isDropPositionThis
|
isDropPositionThis
|
||||||
|
|
@ -274,7 +274,7 @@ Item {
|
||||||
name: folio.FolioSettings.showPagesAppLabels ? delegate.pageDelegate.application.name : ""
|
name: folio.FolioSettings.showPagesAppLabels ? delegate.pageDelegate.application.name : ""
|
||||||
application: delegate.pageDelegate.application
|
application: delegate.pageDelegate.application
|
||||||
turnToFolder: delegate.isAppHoveredOver
|
turnToFolder: delegate.isAppHoveredOver
|
||||||
turnToFolderAnimEnabled: folio.HomeScreenState.swipeState === Folio.HomeScreenState.DraggingDelegate
|
turnToFolderAnimEnabled: folio.HomeScreenState.isDraggingDelegate
|
||||||
|
|
||||||
implicitWidth: folio.HomeScreenState.pageCellWidth
|
implicitWidth: folio.HomeScreenState.pageCellWidth
|
||||||
implicitHeight: folio.HomeScreenState.pageCellHeight
|
implicitHeight: folio.HomeScreenState.pageCellHeight
|
||||||
|
|
@ -323,12 +323,10 @@ Item {
|
||||||
Connections {
|
Connections {
|
||||||
target: folio.HomeScreenState
|
target: folio.HomeScreenState
|
||||||
|
|
||||||
function onSwipeStateChanged() {
|
function onDelegateDragStarted() {
|
||||||
if (folio.HomeScreenState.swipeState === Folio.HomeScreenState.DraggingDelegate) {
|
|
||||||
contextMenu.close();
|
contextMenu.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
actions: [
|
actions: [
|
||||||
Kirigami.Action {
|
Kirigami.Action {
|
||||||
|
|
@ -409,12 +407,10 @@ Item {
|
||||||
Connections {
|
Connections {
|
||||||
target: folio.HomeScreenState
|
target: folio.HomeScreenState
|
||||||
|
|
||||||
function onSwipeStateChanged() {
|
function onDelegateDragStarted() {
|
||||||
if (folio.HomeScreenState.swipeState === Folio.HomeScreenState.DraggingDelegate) {
|
|
||||||
contextMenu.close();
|
contextMenu.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
actions: [
|
actions: [
|
||||||
Kirigami.Action {
|
Kirigami.Action {
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,8 @@ import plasma.applet.org.kde.plasma.mobile.homescreen.folio as Folio
|
||||||
import './delegate'
|
import './delegate'
|
||||||
import './private'
|
import './private'
|
||||||
|
|
||||||
|
// Placeholder item that the user sees as they drag widgets around.
|
||||||
|
// See DelegateDragItem for the equivalent for app delegates.
|
||||||
Item {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
property Folio.HomeScreen folio
|
property Folio.HomeScreen folio
|
||||||
|
|
@ -25,7 +27,9 @@ Item {
|
||||||
|
|
||||||
property Folio.FolioWidget widget
|
property Folio.FolioWidget widget
|
||||||
|
|
||||||
readonly property bool isWidgetDelegate: folio.HomeScreenState.dragState.dropDelegate && folio.HomeScreenState.dragState.dropDelegate.type === Folio.FolioDelegate.Widget
|
readonly property bool isWidgetDelegate: folio.HomeScreenState.dragState.dropDelegate
|
||||||
|
&& folio.HomeScreenState.dragState.dropDelegate.type === Folio.FolioDelegate.Widget
|
||||||
|
&& folio.HomeScreenState.dragState.dropDelegate.widget.visualApplet
|
||||||
readonly property bool dropAnimationRunning: dragXAnim.running || dragYAnim.running
|
readonly property bool dropAnimationRunning: dragXAnim.running || dragYAnim.running
|
||||||
|
|
||||||
visible: false
|
visible: false
|
||||||
|
|
@ -74,15 +78,14 @@ Item {
|
||||||
id: stateWatcher
|
id: stateWatcher
|
||||||
target: folio.HomeScreenState
|
target: folio.HomeScreenState
|
||||||
|
|
||||||
function onSwipeStateChanged() {
|
function onDelegateDragStarted() {
|
||||||
if (folio.HomeScreenState.swipeState === Folio.HomeScreenState.DraggingDelegate &&
|
if (!root.isWidgetDelegate) {
|
||||||
folio.HomeScreenState.dragState.dropDelegate &&
|
return;
|
||||||
folio.HomeScreenState.dragState.dropDelegate.type === Folio.FolioDelegate.Widget) {
|
}
|
||||||
|
|
||||||
root.startDrag(folio.HomeScreenState.dragState.dropDelegate.widget);
|
root.startDrag(folio.HomeScreenState.dragState.dropDelegate.widget);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: folio.HomeScreenState.dragState
|
target: folio.HomeScreenState.dragState
|
||||||
|
|
|
||||||
|
|
@ -91,13 +91,11 @@ Item {
|
||||||
target: folio.HomeScreenState
|
target: folio.HomeScreenState
|
||||||
|
|
||||||
// if we are starting drag-and-drop, close the menu immediately
|
// if we are starting drag-and-drop, close the menu immediately
|
||||||
function onSwipeStateChanged() {
|
function onDelegateDragStarted() {
|
||||||
if (folio.HomeScreenState.swipeState === Folio.HomeScreenState.DraggingDelegate) {
|
|
||||||
configOverlay.animClose();
|
configOverlay.animClose();
|
||||||
root.closed();
|
root.closed();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// the config overlay
|
// the config overlay
|
||||||
FastBlur {
|
FastBlur {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,136 @@
|
||||||
|
// SPDX-FileCopyrightText: 2023-2025 Devin Lin <devin@kde.org>
|
||||||
|
// SPDX-License-Identifier: LGPL-2.0-or-later
|
||||||
|
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import QtQuick.Controls as QQC2
|
||||||
|
|
||||||
|
import org.kde.kirigami as Kirigami
|
||||||
|
import org.kde.plasma.plasmoid
|
||||||
|
import org.kde.plasma.extras 2.0 as PlasmaExtras
|
||||||
|
import org.kde.plasma.private.shell 2.0
|
||||||
|
import plasma.applet.org.kde.plasma.mobile.homescreen.folio as Folio
|
||||||
|
import org.kde.plasma.components 3.0 as PC3
|
||||||
|
import org.kde.plasma.private.mobileshell as MobileShell
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: delegate
|
||||||
|
property Folio.HomeScreen folio
|
||||||
|
|
||||||
|
readonly property string pluginName: model.pluginName
|
||||||
|
|
||||||
|
property real zoomScale: (model.isSupported && mouseArea.pressed) ? 0.8 : 1
|
||||||
|
transform: Scale {
|
||||||
|
origin.x: delegate.width / 2;
|
||||||
|
origin.y: delegate.height / 2;
|
||||||
|
xScale: delegate.zoomScale
|
||||||
|
yScale: delegate.zoomScale
|
||||||
|
}
|
||||||
|
|
||||||
|
Behavior on zoomScale { NumberAnimation { duration: 80 } }
|
||||||
|
|
||||||
|
// Placeholder item used for implement drag & drop
|
||||||
|
Item {
|
||||||
|
id: draggable
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
Drag.hotSpot.x: iconWidget.width / 2
|
||||||
|
Drag.hotSpot.y: iconWidget.height / 2
|
||||||
|
Drag.mimeData: { "text/x-plasmoidservicename": pluginName }
|
||||||
|
Drag.dragType: Drag.Automatic
|
||||||
|
Drag.onDragFinished: {
|
||||||
|
root.requestClose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MobileShell.HapticsEffect {
|
||||||
|
id: haptics
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: mouseArea
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
cursorShape: model.isSupported ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||||
|
hoverEnabled: true
|
||||||
|
|
||||||
|
onPressAndHold: {
|
||||||
|
if (!model.isSupported) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
haptics.buttonVibrate();
|
||||||
|
iconWidget.grabToImage(function(result) {
|
||||||
|
// Start drag & drop
|
||||||
|
folio.HomeScreenState.closeSettingsView();
|
||||||
|
draggable.Drag.imageSource = result.url;
|
||||||
|
draggable.Drag.active = true;
|
||||||
|
root.requestClose();
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: background
|
||||||
|
color: Qt.rgba(255, 255, 255, 0.3)
|
||||||
|
visible: model.isSupported && mouseArea.containsMouse
|
||||||
|
radius: Kirigami.Units.cornerRadius
|
||||||
|
anchors.fill: parent
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: Kirigami.Units.largeSpacing
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: iconWidget
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.maximumWidth: delegate.width
|
||||||
|
Layout.preferredHeight: Kirigami.Units.iconSizes.large
|
||||||
|
Layout.preferredWidth: Kirigami.Units.iconSizes.large
|
||||||
|
Layout.alignment: Qt.AlignBottom
|
||||||
|
|
||||||
|
Kirigami.Icon {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
source: model.decoration
|
||||||
|
visible: model.screenshot == ""
|
||||||
|
implicitWidth: Kirigami.Units.iconSizes.large
|
||||||
|
implicitHeight: Kirigami.Units.iconSizes.large
|
||||||
|
}
|
||||||
|
Image {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
fillMode: Image.PreserveAspectFit
|
||||||
|
source: model.screenshot
|
||||||
|
width: Kirigami.Units.iconSizes.large
|
||||||
|
height: Kirigami.Units.iconSizes.large
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PC3.Label {
|
||||||
|
id: heading
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.maximumWidth: delegate.width
|
||||||
|
Layout.alignment: Qt.AlignCenter
|
||||||
|
text: model.name
|
||||||
|
elide: Text.ElideRight
|
||||||
|
wrapMode: Text.Wrap
|
||||||
|
maximumLineCount: 2
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
font.weight: Font.Bold
|
||||||
|
}
|
||||||
|
|
||||||
|
PC3.Label {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.maximumWidth: delegate.width
|
||||||
|
Layout.alignment: Qt.AlignTop
|
||||||
|
// otherwise causes binding loop due to the way the Plasma sets the height
|
||||||
|
height: implicitHeight
|
||||||
|
text: model.isSupported ? model.description : model.unsupportedMessage
|
||||||
|
font.pointSize: Kirigami.Theme.smallFont.pointSize
|
||||||
|
wrapMode: Text.Wrap
|
||||||
|
elide: Text.ElideRight
|
||||||
|
maximumLineCount: heading.lineCount === 1 ? 3 : 2
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -19,28 +19,27 @@ import org.kde.plasma.private.mobileshell as MobileShell
|
||||||
import '../delegate'
|
import '../delegate'
|
||||||
import '../private'
|
import '../private'
|
||||||
|
|
||||||
MouseArea {
|
Loader {
|
||||||
id: root
|
id: root
|
||||||
property Folio.HomeScreen folio
|
property Folio.HomeScreen folio
|
||||||
|
|
||||||
property var homeScreen
|
property var homeScreen
|
||||||
|
|
||||||
signal requestClose()
|
active: false
|
||||||
onClicked: root.requestClose()
|
|
||||||
|
function requestClose() {
|
||||||
|
active = false;
|
||||||
|
}
|
||||||
|
|
||||||
Kirigami.Theme.inherit: false
|
Kirigami.Theme.inherit: false
|
||||||
Kirigami.Theme.colorSet: Kirigami.Theme.Complementary
|
Kirigami.Theme.colorSet: Kirigami.Theme.Complementary
|
||||||
|
|
||||||
MobileShell.HapticsEffect {
|
sourceComponent: Item {
|
||||||
id: haptics
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
color: Qt.rgba(0, 0, 0, 0.7)
|
color: Qt.rgba(0, 0, 0, 0.7)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PlasmaExtras.ModelContextMenu {
|
PlasmaExtras.ModelContextMenu {
|
||||||
id: getWidgetsDialog
|
id: getWidgetsDialog
|
||||||
visualParent: getWidgetsButton
|
visualParent: getWidgetsButton
|
||||||
|
|
@ -109,7 +108,6 @@ MouseArea {
|
||||||
|
|
||||||
model: widgetExplorer.widgetsModel
|
model: widgetExplorer.widgetsModel
|
||||||
|
|
||||||
readonly property real maxCellWidth: Kirigami.Units.gridUnit * 20
|
|
||||||
readonly property real intendedCellWidth: Kirigami.Units.gridUnit * 8
|
readonly property real intendedCellWidth: Kirigami.Units.gridUnit * 8
|
||||||
readonly property int columns: Math.min(5, (width - leftMargin - rightMargin) / intendedCellWidth)
|
readonly property int columns: Math.min(5, (width - leftMargin - rightMargin) / intendedCellWidth)
|
||||||
|
|
||||||
|
|
@ -120,117 +118,10 @@ MouseArea {
|
||||||
leftMargin: horizontalMargin
|
leftMargin: horizontalMargin
|
||||||
rightMargin: horizontalMargin
|
rightMargin: horizontalMargin
|
||||||
|
|
||||||
MouseArea {
|
delegate: AppletListDelegate {
|
||||||
z: -1
|
folio: root.folio
|
||||||
anchors.fill: parent
|
|
||||||
onClicked: root.requestClose()
|
|
||||||
}
|
|
||||||
|
|
||||||
delegate: MouseArea {
|
|
||||||
id: delegate
|
|
||||||
width: gridView.cellWidth
|
width: gridView.cellWidth
|
||||||
height: gridView.cellHeight
|
height: gridView.cellHeight
|
||||||
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
hoverEnabled: true
|
|
||||||
|
|
||||||
property real zoomScale: pressed ? 0.8 : 1
|
|
||||||
transform: Scale {
|
|
||||||
origin.x: delegate.width / 2;
|
|
||||||
origin.y: delegate.height / 2;
|
|
||||||
xScale: delegate.zoomScale
|
|
||||||
yScale: delegate.zoomScale
|
|
||||||
}
|
|
||||||
|
|
||||||
Behavior on zoomScale { NumberAnimation { duration: 80 } }
|
|
||||||
|
|
||||||
readonly property string pluginName: model.pluginName
|
|
||||||
|
|
||||||
onPressAndHold: {
|
|
||||||
if (!model.isSupported) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
root.requestClose();
|
|
||||||
folio.HomeScreenState.closeSettingsView();
|
|
||||||
haptics.buttonVibrate();
|
|
||||||
|
|
||||||
let mappedCoords = root.homeScreen.prepareStartDelegateDrag(null, delegate, true);
|
|
||||||
const widthOffset = folio.HomeScreenState.pageCellWidth / 2;
|
|
||||||
const heightOffset = folio.HomeScreenState.pageCellHeight / 2;
|
|
||||||
|
|
||||||
folio.HomeScreenState.startDelegateWidgetListDrag(
|
|
||||||
mappedCoords.x + mouseX - widthOffset,
|
|
||||||
mappedCoords.y + mouseY - heightOffset,
|
|
||||||
widthOffset,
|
|
||||||
heightOffset,
|
|
||||||
pluginName
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: background
|
|
||||||
color: Qt.rgba(255, 255, 255, 0.3)
|
|
||||||
visible: delegate.containsMouse
|
|
||||||
radius: Kirigami.Units.cornerRadius
|
|
||||||
anchors.fill: parent
|
|
||||||
}
|
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.margins: Kirigami.Units.largeSpacing
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: iconWidget
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.maximumWidth: delegate.width
|
|
||||||
Layout.preferredHeight: Kirigami.Units.iconSizes.large
|
|
||||||
Layout.preferredWidth: Kirigami.Units.iconSizes.large
|
|
||||||
Layout.alignment: Qt.AlignBottom
|
|
||||||
|
|
||||||
Kirigami.Icon {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
source: model.decoration
|
|
||||||
visible: model.screenshot == ""
|
|
||||||
implicitWidth: Kirigami.Units.iconSizes.large
|
|
||||||
implicitHeight: Kirigami.Units.iconSizes.large
|
|
||||||
}
|
|
||||||
Image {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
fillMode: Image.PreserveAspectFit
|
|
||||||
source: model.screenshot
|
|
||||||
width: Kirigami.Units.iconSizes.large
|
|
||||||
height: Kirigami.Units.iconSizes.large
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PC3.Label {
|
|
||||||
id: heading
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.maximumWidth: delegate.width
|
|
||||||
Layout.alignment: Qt.AlignCenter
|
|
||||||
text: model.name
|
|
||||||
elide: Text.ElideRight
|
|
||||||
wrapMode: Text.Wrap
|
|
||||||
maximumLineCount: 2
|
|
||||||
horizontalAlignment: Text.AlignHCenter
|
|
||||||
font.weight: Font.Bold
|
|
||||||
}
|
|
||||||
|
|
||||||
PC3.Label {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.maximumWidth: delegate.width
|
|
||||||
Layout.alignment: Qt.AlignTop
|
|
||||||
// otherwise causes binding loop due to the way the Plasma sets the height
|
|
||||||
height: implicitHeight
|
|
||||||
text: model.isSupported ? model.description : model.unsupportedMessage
|
|
||||||
font.pointSize: Kirigami.Theme.smallFont.pointSize
|
|
||||||
wrapMode: Text.Wrap
|
|
||||||
elide: Text.ElideRight
|
|
||||||
maximumLineCount: heading.lineCount === 1 ? 3 : 2
|
|
||||||
horizontalAlignment: Text.AlignHCenter
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -246,4 +137,5 @@ MouseArea {
|
||||||
|
|
||||||
onShouldClose: root.requestClose()
|
onShouldClose: root.requestClose()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,23 +21,12 @@ Item {
|
||||||
property var homeScreen
|
property var homeScreen
|
||||||
property real settingsModeHomeScreenScale
|
property real settingsModeHomeScreenScale
|
||||||
|
|
||||||
readonly property bool homeScreenInteractive: !appletListViewerLoader.active
|
readonly property bool homeScreenInteractive: !appletListViewer.active
|
||||||
|
|
||||||
property real bottomMargin: 0
|
property real bottomMargin: 0
|
||||||
property real leftMargin: 0
|
property real leftMargin: 0
|
||||||
property real rightMargin: 0
|
property real rightMargin: 0
|
||||||
|
|
||||||
Connections {
|
|
||||||
target: folio.HomeScreenState
|
|
||||||
|
|
||||||
// Close applet viewer when settings view closes
|
|
||||||
function onViewStateChanged() {
|
|
||||||
if (folio.HomeScreenState.viewState !== Folio.HomeScreenState.SettingsView) {
|
|
||||||
appletListViewerLoader.requestClose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
id: closeSettings
|
id: closeSettings
|
||||||
|
|
||||||
|
|
@ -84,7 +73,7 @@ Item {
|
||||||
iconName: 'widget-alternatives'
|
iconName: 'widget-alternatives'
|
||||||
textLabel: i18n("Widgets")
|
textLabel: i18n("Widgets")
|
||||||
onClicked: {
|
onClicked: {
|
||||||
appletListViewerLoader.active = true;
|
appletListViewer.active = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -157,49 +146,13 @@ Item {
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
Loader {
|
AppletListViewer {
|
||||||
id: appletListViewerLoader
|
|
||||||
asynchronous: true
|
|
||||||
active: false
|
|
||||||
|
|
||||||
signal requestClose()
|
|
||||||
onRequestClose: item?.requestClose()
|
|
||||||
|
|
||||||
width: parent.width
|
|
||||||
height: parent.height
|
|
||||||
|
|
||||||
opacity: status == Loader.Ready ? 1 : 0
|
|
||||||
// move the settings out of the way if it is not visible
|
|
||||||
// NOTE: we do this instead of setting visible to false, because
|
|
||||||
// it doesn't mess with widget drag and drop
|
|
||||||
y: (opacity > 0) ? 0 : parent.height
|
|
||||||
|
|
||||||
Behavior on opacity {
|
|
||||||
NumberAnimation { duration: Kirigami.Units.shortDuration }
|
|
||||||
}
|
|
||||||
|
|
||||||
sourceComponent: AppletListViewer {
|
|
||||||
id: appletListViewer
|
id: appletListViewer
|
||||||
folio: root.folio
|
|
||||||
|
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: parent.height
|
height: parent.height
|
||||||
|
|
||||||
onRequestClose: parent.active = false
|
folio: root.folio
|
||||||
|
|
||||||
homeScreen: root.homeScreen
|
homeScreen: root.homeScreen
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
PC3.BusyIndicator {
|
|
||||||
id: appletListLoadingIndicator
|
|
||||||
anchors.centerIn: parent
|
|
||||||
visible: appletListViewerLoader.status === Loader.Loading
|
|
||||||
|
|
||||||
implicitHeight: Kirigami.Units.iconSizes.huge
|
|
||||||
implicitWidth: Kirigami.Units.iconSizes.huge
|
|
||||||
|
|
||||||
Kirigami.Theme.inherit: false
|
|
||||||
Kirigami.Theme.colorSet: Kirigami.Theme.Complementary
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue