diff --git a/qml.qrc b/qml.qrc index f6d1235..7b2295a 100755 --- a/qml.qrc +++ b/qml.qrc @@ -1,8 +1,7 @@ qml/main.qml - qml/LauncherGridDelegate.qml - qml/PageView.qml - qml/LauncherGridView.qml + qml/GridItemDelegate.qml + qml/AllAppsView.qml diff --git a/qml/AllAppsView.qml b/qml/AllAppsView.qml new file mode 100644 index 0000000..3c0005b --- /dev/null +++ b/qml/AllAppsView.qml @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2021 CutefishOS. + * + * Author: Reoin Wong + * + * This program 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 3 of the License, or + * any later version. + * + * This program 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.12 +import QtQuick.Controls 2.12 +import QtQuick.Layouts 1.12 +import FishUI 1.0 as FishUI + +import Cutefish.Launcher 1.0 + +ListView { + id: control + + property bool searchMode: false + + property var sourceModel: launcherModel + property var modelCount: sourceModel.count + + property int iconSize: 128 + FishUI.Units.largeSpacing * 2 + property int cellWidth: iconSize + calcExtraSpacing(iconSize, control.width) + property int cellHeight: iconSize + calcExtraSpacing(iconSize, control.height) + + property int rows: control.width / control.cellWidth + property int columns: control.height / control.cellHeight + property int pageCount: control.rows * control.columns + + orientation: ListView.Horizontal + snapMode: ListView.SnapOneItem + model: Math.ceil(control.modelCount / control.pageCount) + + maximumFlickVelocity: 10000 + highlightMoveDuration: 100 + + preferredHighlightBegin: 0 + preferredHighlightEnd: 0 + highlightRangeMode: ListView.StrictlyEnforceRange + highlightFollowsCurrentItem: true + + cacheBuffer: control.width * control.count + boundsBehavior: Flickable.DragOverBounds + currentIndex: 0 + clip: true + + NumberAnimation on contentX { + id: scrollAnim + + duration: 300 + easing.type: Easing.InOutQuad + + onStopped: { + var index = control.indexAt(control.contentX + control.width / 2, + control.contentY + control.height / 2) + if (index === -1) + control.currentIndex = 0 + else + control.currentIndex = index + } + } + + MouseArea { + anchors.fill: parent + z: -1 + + onClicked: { + launcher.hideWindow() + } + + onWheel: { + if (wheel.angleDelta.y > 0) + scrollPreviousPage() + else + scrollNextPage() + } + } + + delegate: Flow { + id: _page + width: control.width + height: control.height + + readonly property int pageIndex: index + + move: Transition { + NumberAnimation { + properties: "x, y" + duration: 300 + easing.type: Easing.InOutQuad + } + } + + Repeater { + model: PageModel { + id: _pageModel + sourceModel: launcherModel + startIndex: control.pageCount * _page.pageIndex + limitCount: control.pageCount + } + + delegate: GridItemDelegate { + searchMode: control.searchMode + pageIndex: _page.pageIndex + pageCount: control.pageCount + width: control.cellWidth + height: control.cellHeight + } + } + } + + function calcExtraSpacing(cellSize, containerSize) { + var availableColumns = Math.floor(containerSize / cellSize) + var extraSpacing = 0 + if (availableColumns > 0) { + var allColumnSize = availableColumns * cellSize + var extraSpace = Math.max(containerSize - allColumnSize, 0) + extraSpacing = extraSpace / availableColumns + } + return Math.floor(extraSpacing) + } + + function scrollNextPage() { + if (scrollAnim.running) + return + + if (currentIndex < count - 1) { + scrollAnim.to = control.currentItem.x + control.width + scrollAnim.restart() + } + } + + function scrollPreviousPage() { + if (scrollAnim.running) + return + + if (currentIndex > 0) { + scrollAnim.to = control.currentItem.x - control.width + scrollAnim.restart() + } + } +} diff --git a/qml/LauncherGridDelegate.qml b/qml/GridItemDelegate.qml similarity index 87% rename from qml/LauncherGridDelegate.qml rename to qml/GridItemDelegate.qml index 1807cde..af90b9a 100755 --- a/qml/LauncherGridDelegate.qml +++ b/qml/GridItemDelegate.qml @@ -27,9 +27,13 @@ import Cutefish.Launcher 1.0 Item { id: control + property bool searchMode: false property bool dragStarted: false property var dragItemIndex: index + property int pageIndex: 0 + property int pageCount: 0 + Drag.active: iconMouseArea.drag.active Drag.dragType: Drag.Automatic Drag.supportedActions: Qt.MoveAction @@ -49,8 +53,16 @@ Item { enabled: true onContainsDragChanged: { - if (drag.source) - launcherModel.move(drag.source.dragItemIndex, control.dragItemIndex) + if (control.searchMode) + return + + if (drag.source) { + launcherModel.move(drag.source.dragItemIndex, + control.dragItemIndex, + control.pageIndex, + control.pageCount) + _pageModel.move(drag.source.dragItemIndex, control.dragItemIndex) + } } } @@ -98,10 +110,10 @@ Item { onTriggered: launcherModel.removeFromDock(model.appId) } - MenuItem { - text: qsTr("Uninstall") - onTriggered: {} - } + // MenuItem { + // text: qsTr("Uninstall") + // onTriggered: {} + // } function updateActions() { sendToDock.visible = launcher.dockAvailable() && !launcher.isPinedDock(model.appId) diff --git a/qml/LauncherGridView.qml b/qml/LauncherGridView.qml deleted file mode 100644 index e82b7ea..0000000 --- a/qml/LauncherGridView.qml +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2021 CutefishOS. - * - * Author: revenmartin - * - * This program 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 3 of the License, or - * any later version. - * - * This program 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.12 -import QtQuick.Window 2.12 -import FishUI 1.0 as FishUI -import Cutefish.Launcher 1.0 - -PageView { - id: control - - property int iconSize: 128 + FishUI.Units.largeSpacing * 2 - - property int cellWidth: { - var extraWidth = calcExtraSpacing(iconSize, control.width) - return iconSize + extraWidth - } - - property int cellHeight: { - var extraHeight = calcExtraSpacing(iconSize, control.height) - return iconSize + extraHeight - } - - columns: control.width / cellWidth - rows: control.height / cellHeight - - model: launcherModel - - delegate: Item { - width: cellWidth - height: cellHeight - - LauncherGridDelegate { - id: delegate - anchors.fill: parent - } - } - - function calcExtraSpacing(cellSize, containerSize) { - var availableColumns = Math.floor(containerSize / cellSize); - var extraSpacing = 0; - if (availableColumns > 0) { - var allColumnSize = availableColumns * cellSize; - var extraSpace = Math.max(containerSize - allColumnSize, 0); - extraSpacing = extraSpace / availableColumns; - } - return Math.floor(extraSpacing); - } -} diff --git a/qml/PageView.qml b/qml/PageView.qml deleted file mode 100644 index 2dd7834..0000000 --- a/qml/PageView.qml +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (C) 2021 CutefishOS. - * - * Author: revenmartin - * - * This program 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 3 of the License, or - * any later version. - * - * This program 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.12 -import Cutefish.Launcher 1.0 - -Item { - id: pagedGrid - - property var model - - property int rows - property int columns - - property Component delegate - - readonly property var count: model.count - - readonly property int pageCount: rows * columns - readonly property alias pages: pageView.count - property alias currentPage: pageView.currentIndex - - MouseArea { - anchors.fill: parent - propagateComposedEvents: true - - onWheel: { - if (wheel.angleDelta.y > 0) - pageView.decrementCurrentIndex(); - else - pageView.incrementCurrentIndex(); - } - } - - ListView { - id: pageView - anchors.fill: parent - - orientation: Qt.Horizontal - snapMode: ListView.SnapOneItem - highlightFollowsCurrentItem: true - highlightRangeMode: ListView.StrictlyEnforceRange - highlightMoveDuration: 500 - currentIndex: 0 - - maximumFlickVelocity: 9000 - - preferredHighlightBegin: 0 - preferredHighlightEnd: 0 - - cacheBuffer: pageView.width * pageView.count - boundsBehavior: Flickable.DragOverBounds - clip: true - -// // Blank area - MouseArea { - anchors.fill: parent - z: -1 - onClicked: launcher.hideWindow() - } - - model: Math.ceil(pagedGrid.count / pageCount) - delegate: pageDelegate - } - - Component { - id: pageDelegate - - Flow { - id: _page - width: pagedGrid.width - height: pagedGrid.height - // columns: pagedGrid.columns - - readonly property int pageIndex: index - -// move: Transition { -// NumberAnimation { -// duration: 300 -// easing.type: Easing.InOutQuad -// properties: "x,y" -// } -// } - - Repeater { - model: PageModel { - id: _pageModel - sourceModel: pagedGrid.model - startIndex: pageCount * pageIndex - limitCount: pageCount - } - - delegate: pagedGrid.delegate - } - } - } -} diff --git a/qml/main.qml b/qml/main.qml index 19245a2..3881820 100755 --- a/qml/main.qml +++ b/qml/main.qml @@ -38,6 +38,21 @@ Item { property real maxSpacing: horizontalSpacing > verticalSpacing ? horizontalSpacing : verticalSpacing property bool showed: launcher.showed + onShowedChanged: { + if (showed) + searchFieldAni.start() + } + + NumberAnimation { + id: searchFieldAni + from: 0.0 + to: 1.0 + target: textField + property: "opacity" + easing.type: Easing.InQuad + duration: 250 + } + // onShowedChanged: { // appViewOpacityAni.restart() // blurAnimation.restart() @@ -103,7 +118,7 @@ Item { fillMode: Image.PreserveAspectCrop asynchronous: false cache: false - smooth: false + smooth: true } FastBlur { @@ -214,6 +229,10 @@ Item { } } + Item { + height: 14 + } + Item { id: gridItem Layout.fillHeight: true @@ -222,12 +241,13 @@ Item { Keys.enabled: true Keys.forwardTo: appView - LauncherGridView { + AllAppsView { id: appView anchors.fill: parent anchors.leftMargin: gridItem.width * 0.1 anchors.rightMargin: gridItem.width * 0.1 Layout.alignment: Qt.AlignHCenter + searchMode: textField.text focus: true Keys.enabled: true @@ -262,9 +282,9 @@ Item { PageIndicator { id: pageIndicator - count: appView.pages - currentIndex: appView.currentPage - onCurrentIndexChanged: appView.currentPage = currentIndex + count: appView.count + currentIndex: appView.currentIndex + onCurrentIndexChanged: appView.currentIndex = currentIndex interactive: true spacing: FishUI.Units.largeSpacing Layout.alignment: Qt.AlignHCenter diff --git a/src/launcheritem.h b/src/launcheritem.h index 36636f8..7cacb20 100644 --- a/src/launcheritem.h +++ b/src/launcheritem.h @@ -25,10 +25,13 @@ class LauncherItem : public QObject { Q_OBJECT + Q_PROPERTY(QString fuke READ fuke CONSTANT) public: explicit LauncherItem(QObject *parent = nullptr); + Q_INVOKABLE QString fuke() { return "asd"; }; + QString id; QString name; QString genericName; diff --git a/src/launchermodel.cpp b/src/launchermodel.cpp index 35dc401..7b0be55 100755 --- a/src/launchermodel.cpp +++ b/src/launchermodel.cpp @@ -60,6 +60,14 @@ LauncherModel::LauncherModel(QObject *parent) connect(this, &QAbstractItemModel::rowsRemoved, this, &LauncherModel::countChanged); connect(this, &QAbstractItemModel::modelReset, this, &LauncherModel::countChanged); connect(this, &QAbstractItemModel::layoutChanged, this, &LauncherModel::countChanged); + + connect(this, &LauncherModel::refreshed, this, [=] { + beginResetModel(); + std::sort(m_items.begin(), m_items.end(), [=] (LauncherItem *a, LauncherItem *b) { + return a->name < b->name; + }); + endResetModel(); + }); } LauncherModel::~LauncherModel() @@ -240,19 +248,22 @@ int LauncherModel::indexFromAppId(const QString &appId) const return -1; } -void LauncherModel::move(int from, int to) +void LauncherModel::move(int from, int to, int page, int pageCount) { if (from == to) return; - m_items.move(from, to); + int newFrom = from + (page * pageCount); + int newTo = to + (page * pageCount); + + m_items.move(newFrom, newTo); - if (from < to) - beginMoveRows(QModelIndex(), from, from, QModelIndex(), to + 1); - else - beginMoveRows(QModelIndex(), from, from, QModelIndex(), to); +// if (from < to) +// beginMoveRows(QModelIndex(), from, from, QModelIndex(), to + 1); +// else +// beginMoveRows(QModelIndex(), from, from, QModelIndex(), to); - endMoveRows(); +// endMoveRows(); } bool LauncherModel::launch(const QString &path) diff --git a/src/launchermodel.h b/src/launchermodel.h index 38a3ed4..f5b25ba 100755 --- a/src/launchermodel.h +++ b/src/launchermodel.h @@ -73,7 +73,7 @@ public: Q_INVOKABLE QString getIconName(const QString &appId); Q_INVOKABLE int indexFromAppId(const QString &appId) const; - Q_INVOKABLE void move(int from, int to); + Q_INVOKABLE void move(int from, int to, int page, int pageCount); public Q_SLOTS: Q_INVOKABLE bool launch(const QString &path); diff --git a/src/main.cpp b/src/main.cpp index 6856ea2..ac21702 100755 --- a/src/main.cpp +++ b/src/main.cpp @@ -41,7 +41,8 @@ int main(int argc, char *argv[]) QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QByteArray uri = "Cutefish.Launcher"; - qmlRegisterUncreatableType(uri, 1, 0, "LauncherItem", "cannot init application"); + // qmlRegisterUncreatableType(uri, 1, 0, "LauncherItem", "cannot init application"); + qmlRegisterType(uri, 1, 0, "LauncherItem"); qmlRegisterType(uri, 1, 0, "LauncherModel"); qmlRegisterType(uri, 1, 0, "PageModel"); qmlRegisterType(uri, 1, 0, "IconItem"); @@ -55,7 +56,7 @@ int main(int argc, char *argv[]) QApplication app(argc, argv); app.setApplicationName(QStringLiteral("cutefish-launcher")); - QPixmapCache::setCacheLimit(1024 * 10); + // QPixmapCache::setCacheLimit(1024 * 10); // QCommandLineParser parser; // QCommandLineOption showOption(QStringLiteral("show"), "Show Launcher"); diff --git a/src/pagemodel.cpp b/src/pagemodel.cpp index 41f9f15..8f474d8 100755 --- a/src/pagemodel.cpp +++ b/src/pagemodel.cpp @@ -37,6 +37,19 @@ int PageModel::startIndex() const { return m_startIndex; } int PageModel::limitCount() const { return m_limitCount; } +void PageModel::move(int from, int to) +{ + if (from == to) + return; + + if (from < to) + beginMoveRows(QModelIndex(), from, from, QModelIndex(), to + 1); + else + beginMoveRows(QModelIndex(), from, from, QModelIndex(), to); + + endMoveRows(); +} + void PageModel::setStartIndex(int startIndex) { if (startIndex != m_startIndex) { diff --git a/src/pagemodel.h b/src/pagemodel.h index 4161a70..d2f4a84 100755 --- a/src/pagemodel.h +++ b/src/pagemodel.h @@ -39,6 +39,8 @@ public: int startIndex() const; int limitCount() const; + Q_INVOKABLE void move(int from, int to); + bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const; public Q_SLOTS: