Merge pull request #11546 from vladest/tablet_home_paginate

Tablet home paginate
This commit is contained in:
Ryan Downe Karpf 2018-01-03 18:12:32 -08:00 committed by GitHub
commit eada0b1ff7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 271 additions and 42 deletions

View file

@ -23,11 +23,26 @@ Item {
property double sortOrder: 100
property int stableOrder: 0
property var tabletRoot;
property var flickable: null
property var gridView: null
property int buttonIndex: -1
width: 129
height: 129
signal clicked()
Connections {
target: flickable
onMovingChanged: {
//when flick/move started, and hover is on, clean hove state
if (flickable.moving && tabletButton.state.indexOf("hover") !== -1) {
tabletButton.state = (tabletButton.isActive) ? "active state" : "base state";
}
}
}
function changeProperty(key, value) {
tabletButton[key] = value;
}
@ -121,8 +136,10 @@ Item {
anchors.fill: parent
hoverEnabled: true
enabled: true
preventStealing: true
preventStealing: false
onClicked: {
gridView.currentIndex = buttonIndex
if (tabletButton.inDebugMode) {
if (tabletButton.isActive) {
tabletButton.isActive = false;
@ -130,12 +147,15 @@ Item {
tabletButton.isActive = true;
}
}
tabletButton.clicked();
if (tabletRoot) {
Tablet.playSound(TabletEnums.ButtonClick);
}
}
onEntered: {
gridView.currentIndex = buttonIndex
tabletButton.isEntered = true;
Tablet.playSound(TabletEnums.ButtonHover);

View file

@ -1,7 +1,10 @@
import QtQuick 2.5
import QtQuick 2.7
import QtQuick.Controls 2.2
import QtGraphicalEffects 1.0
import QtQuick.Layouts 1.3
import TabletScriptingInterface 1.0
import "."
import "../../styles-uit"
import "../audio" as HifiAudio
@ -10,7 +13,11 @@ Item {
id: tablet
objectName: "tablet"
property var tabletProxy: Tablet.getTablet("com.highfidelity.interface.tablet.system");
property var currentGridItems: null
focus: true
Rectangle {
id: bgTopBar
height: 90
@ -85,7 +92,6 @@ Item {
Rectangle {
id: bgMain
clip: true
gradient: Gradient {
GradientStop {
position: 0
@ -102,55 +108,186 @@ Item {
anchors.left: parent.left
anchors.top: bgTopBar.bottom
GridView {
id: flickable
anchors.top: parent.top
anchors.topMargin: 15
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
width: cellWidth * 3
cellHeight: 145
cellWidth: 145
model: tabletProxy.buttons
delegate: Item {
width: flickable.cellWidth
height: flickable.cellHeight
property var proxy: modelData
TabletButton {
id: tabletButton
anchors.centerIn: parent
onClicked: modelData.clicked()
state: wrapper.GridView.isCurrentItem ? "hover state" : "base state"
SwipeView {
id: swipeView
clip: false
currentIndex: -1
property int previousIndex: -1
Repeater {
id: pageRepeater
model: Math.ceil(tabletProxy.buttons.rowCount() / TabletEnums.ButtonsOnPage)
onItemAdded: {
item.proxyModel.sourceModel = tabletProxy.buttons;
item.proxyModel.pageIndex = index;
}
Connections {
target: modelData;
onPropertiesChanged: {
updateProperties();
delegate: Item {
id: page
property TabletButtonsProxyModel proxyModel: TabletButtonsProxyModel {}
GridView {
id: gridView
keyNavigationEnabled: false
highlightFollowsCurrentItem: false
property int previousGridIndex: -1
anchors {
fill: parent
topMargin: 20
leftMargin: 30
rightMargin: 30
bottomMargin: 0
}
function setButtonState(buttonIndex, buttonstate) {
if (buttonIndex < 0 || gridView.contentItem === undefined
|| gridView.contentItem.children.length - 1 < buttonIndex) {
return;
}
var itemat = gridView.contentItem.children[buttonIndex].children[0];
if (itemat.isActive) {
itemat.state = "active state";
} else {
itemat.state = buttonstate;
}
}
onCurrentIndexChanged: {
setButtonState(previousGridIndex, "base state");
setButtonState(currentIndex, "hover state");
previousGridIndex = currentIndex
}
cellWidth: width/3
cellHeight: cellWidth
flow: GridView.LeftToRight
model: page.proxyModel
delegate: Item {
id: wrapper
width: gridView.cellWidth
height: gridView.cellHeight
property var proxy: modelData
TabletButton {
id: tabletButton
anchors.centerIn: parent
gridView: wrapper.GridView.view
buttonIndex: page.proxyModel.buttonIndex(uuid);
flickable: swipeView.contentItem;
onClicked: modelData.clicked()
}
Connections {
target: modelData;
onPropertiesChanged: {
updateProperties();
}
}
Component.onCompleted: updateProperties()
function updateProperties() {
var keys = Object.keys(modelData.properties).forEach(function (key) {
if (tabletButton[key] !== modelData.properties[key]) {
tabletButton[key] = modelData.properties[key];
}
});
}
}
}
}
}
Component.onCompleted: updateProperties()
function updateProperties() {
var keys = Object.keys(modelData.properties).forEach(function (key) {
if (tabletButton[key] !== modelData.properties[key]) {
tabletButton[key] = modelData.properties[key];
}
});
onCurrentIndexChanged: {
if (swipeView.currentIndex < 0
|| swipeView.itemAt(swipeView.currentIndex) === null
|| swipeView.itemAt(swipeView.currentIndex).children[0] === null) {
return;
}
currentGridItems = swipeView.itemAt(swipeView.currentIndex).children[0];
currentGridItems.currentIndex = (previousIndex > swipeView.currentIndex ? currentGridItems.count - 1 : 0);
previousIndex = currentIndex;
}
hoverEnabled: true
anchors {
left: parent.left
right: parent.right
top: parent.top
bottom: pageIndicator.top
}
}
PageIndicator {
id: pageIndicator
currentIndex: swipeView.currentIndex
delegate: Item {
width: 15
height: 15
Rectangle {
anchors.centerIn: parent
opacity: index === pageIndicator.currentIndex ? 0.95 : 0.45
implicitWidth: index === pageIndicator.currentIndex ? 15 : 10
implicitHeight: implicitWidth
radius: width/2
color: "white"
Behavior on opacity {
OpacityAnimator {
duration: 100
}
}
}
}
interactive: false
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
count: swipeView.count
}
}
Component.onCompleted: {
focus = true;
forceActiveFocus();
}
Keys.onRightPressed: {
if (!currentGridItems) {
return;
}
var index = currentGridItems.currentIndex;
currentGridItems.moveCurrentIndexRight();
if (index === currentGridItems.count - 1 && index === currentGridItems.currentIndex) {
if (swipeView.currentIndex < swipeView.count - 1) {
swipeView.incrementCurrentIndex();
}
}
}
Keys.onRightPressed: flickable.moveCurrentIndexRight();
Keys.onLeftPressed: flickable.moveCurrentIndexLeft();
Keys.onDownPressed: flickable.moveCurrentIndexDown();
Keys.onUpPressed: flickable.moveCurrentIndexUp();
Keys.onLeftPressed: {
if (!currentGridItems) {
return;
}
var index = currentGridItems.currentIndex;
currentGridItems.moveCurrentIndexLeft();
if (index === 0 && index === currentGridItems.currentIndex) {
if (swipeView.currentIndex > 0) {
swipeView.decrementCurrentIndex();
}
}
}
Keys.onDownPressed: currentGridItems.moveCurrentIndexDown();
Keys.onUpPressed: currentGridItems.moveCurrentIndexUp();
Keys.onReturnPressed: {
if (flickable.currentItem) {
flickable.currentItem.proxy.clicked();
if (currentGridItems.currentItem) {
currentGridItems.currentItem.proxy.clicked();
if (tabletRoot) {
tabletRoot.playButtonClickSound();
}

View file

@ -92,8 +92,48 @@ void TabletButtonListModel::removeButton(TabletButtonProxy* button) {
endResetModel();
}
TabletButtonsProxyModel::TabletButtonsProxyModel(QObject *parent)
: QSortFilterProxyModel(parent) {
}
int TabletButtonsProxyModel::pageIndex() const {
return _pageIndex;
}
int TabletButtonsProxyModel::buttonIndex(const QString &uuid) {
if (!sourceModel() || _pageIndex < 0) {
return -1;
}
TabletButtonListModel* model = static_cast<TabletButtonListModel*>(sourceModel());
for (int i = 0; i < model->rowCount(); i++) {
TabletButtonProxy* bproxy = model->data(model->index(i), ButtonProxyRole).value<TabletButtonProxy*>();
if (bproxy && bproxy->getUuid().toString().contains(uuid)) {
return i - (_pageIndex*TabletScriptingInterface::ButtonsOnPage);
}
}
return -1;
}
void TabletButtonsProxyModel::setPageIndex(int pageIndex)
{
if (_pageIndex == pageIndex)
return;
_pageIndex = pageIndex;
invalidateFilter();
emit pageIndexChanged(_pageIndex);
}
bool TabletButtonsProxyModel::filterAcceptsRow(int sourceRow,
const QModelIndex &sourceParent) const {
Q_UNUSED(sourceParent);
return (sourceRow >= _pageIndex*TabletScriptingInterface::ButtonsOnPage
&& sourceRow < (_pageIndex + 1)*TabletScriptingInterface::ButtonsOnPage);
}
TabletScriptingInterface::TabletScriptingInterface() {
qmlRegisterType<TabletScriptingInterface>("TabletScriptingInterface", 1, 0, "TabletEnums");
qmlRegisterType<TabletButtonsProxyModel>("TabletScriptingInterface", 1, 0, "TabletButtonsProxyModel");
}
TabletScriptingInterface::~TabletScriptingInterface() {
@ -769,6 +809,7 @@ void TabletProxy::sendToQml(const QVariant& msg) {
}
OffscreenQmlSurface* TabletProxy::getTabletSurface() {
return _qmlOffscreenSurface;
}

View file

@ -16,6 +16,7 @@
#include <QtCore/QUuid>
#include <QtCore/QVariant>
#include <QtCore/QAbstractListModel>
#include <QSortFilterProxyModel>
#include <QtScript/QScriptValue>
#include <QtScript/QScriptEngine>
@ -46,6 +47,10 @@ public:
enum TabletAudioEvents { ButtonClick, ButtonHover, TabletOpen, TabletHandsIn, TabletHandsOut, Last};
Q_ENUM(TabletAudioEvents)
//Different useful constants
enum TabletConstants { ButtonsColumnsOnPage = 3, ButtonsRowsOnPage = 4, ButtonsOnPage = 12 };
Q_ENUM(TabletConstants)
TabletScriptingInterface();
virtual ~TabletScriptingInterface();
static const QString QML;
@ -118,6 +123,31 @@ protected:
Q_DECLARE_METATYPE(TabletButtonListModel*);
class TabletButtonsProxyModel : public QSortFilterProxyModel
{
Q_OBJECT
Q_PROPERTY(int pageIndex READ pageIndex WRITE setPageIndex NOTIFY pageIndexChanged)
public:
TabletButtonsProxyModel(QObject* parent = 0);
int pageIndex() const;
Q_INVOKABLE int buttonIndex(const QString& uuid);
public slots:
void setPageIndex(int pageIndex);
signals:
void pageIndexChanged(int pageIndex);
protected:
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override;
private:
int _pageIndex { -1 };
};
Q_DECLARE_METATYPE(TabletButtonsProxyModel*);
/**jsdoc
* @class TabletProxy
* @property name {string} READ_ONLY: name of this tablet
@ -234,6 +264,7 @@ public:
QQuickItem* getQmlMenu() const;
TabletButtonListModel* getButtons() { return &_buttons; }
signals:
/**jsdoc
* Signaled when this tablet receives an event from the html/js embedded in the tablet