Added buttons list mutex protection. Reworked keyboard tablet navigation. no more double selections

This commit is contained in:
vladest 2017-12-11 17:50:16 +01:00
parent 3aaf666295
commit cc78fc1f53
4 changed files with 145 additions and 54 deletions

View file

@ -12,6 +12,11 @@ Item {
property int rowIndex: 6 // by default property int rowIndex: 6 // by default
property int columnIndex: 1 // point to 'go to location' property int columnIndex: 1 // point to 'go to location'
property int count: 0 property int count: 0
readonly property int buttonsOnPage: 12
readonly property int buttonsRowsOnPage: 4
readonly property int buttonsColumnsOnPage: 3
focus: true
Timer { Timer {
id: gridsRecreateTimer id: gridsRecreateTimer
@ -42,11 +47,12 @@ Item {
var button = tabletButtons[buttonIndex] var button = tabletButtons[buttonIndex]
if (button !== null) { if (button !== null) {
var grid = swipeView.itemAt(swipeView.count - 1); var grid = swipeView.itemAt(swipeView.count - 1);
if (grid === null || grid.children[0].children.length === 12) { if (grid === null || grid.children[0].children.length === buttonsOnPage) {
grid = pageComponent.createObject(swipeView); grid = pageComponent.createObject(swipeView);
} }
button.row = Math.floor(grid.children[0].children.length / buttonsColumnsOnPage);
button.column = grid.children[0].children.length % buttonsColumnsOnPage;
//reparent to actual grid //reparent to actual grid
button.parent = grid.children[0] button.parent = grid.children[0]
grid.children[0].children.push(button); grid.children[0].children.push(button);
} }
@ -236,6 +242,11 @@ Item {
id: swipeView id: swipeView
clip: false clip: false
currentIndex: pageIndicator.currentIndex currentIndex: pageIndicator.currentIndex
onCurrentIndexChanged: {
rowIndex = 0
columnIndex = 0
}
hoverEnabled: true hoverEnabled: true
anchors { anchors {
left: parent.left left: parent.left
@ -266,15 +277,6 @@ Item {
} }
} }
} }
MouseArea {
anchors.fill: parent
enabled: false //disabled by default
onClicked: {
if (index !== swipeView.currentIndex) {
swipeView.currentIndex = index
}
}
}
} }
interactive: false interactive: false
@ -284,75 +286,135 @@ Item {
} }
} }
function getPage(row, column) { function setCurrentItemState(state) {
var pageIndex = Math.floor((row + column) / 12) var index = rowIndex*buttonsColumnsOnPage + columnIndex;
var index = (row + column) % 12 var currentGridItems = swipeView.currentItem.children[0].children
var page = swipeView.itemAt(pageIndex).children[0] if (currentGridItems !== null && index >= 0 && index < currentGridItems.length) {
return { page: page, index: index, pageIndex: pageIndex } if (currentGridItems[index].isActive) {
currentGridItems[index].state = "active state";
} else {
currentGridItems[index].state = state;
}
}
} }
function setCurrentItemState(state) { function previousPage() {
var index = rowIndex + columnIndex; setCurrentItemState("base state");
if (index >= 0 && index <= count ) { var currentPage = swipeView.currentIndex
var grid = getPage(rowIndex, columnIndex) currentPage = currentPage - 1
grid.page.children[grid.index].state = state; if (currentPage < 0) {
swipeView.currentIndex = grid.pageIndex currentPage = swipeView.count - 1
} }
swipeView.currentIndex = currentPage
}
function nextPage() {
setCurrentItemState("base state");
var currentPage = swipeView.currentIndex
currentPage = currentPage + 1
if (currentPage >= swipeView.count) {
currentPage = 0
}
swipeView.currentIndex = currentPage
} }
function nextItem() { function nextItem() {
setCurrentItemState("base state"); setCurrentItemState("base state");
var nextColumnIndex = (columnIndex + 3 + 1) % 3; var currentGridItems = swipeView.currentItem.children[0].children
var nextIndex = rowIndex + nextColumnIndex; var nextColumnIndex = columnIndex + 1;
if(nextIndex < count) { var index = rowIndex*buttonsColumnsOnPage + nextColumnIndex;
columnIndex = nextColumnIndex; if(index >= currentGridItems.length || nextColumnIndex >= buttonsColumnsOnPage) {
}; nextColumnIndex = 0;
}
columnIndex = nextColumnIndex;
setCurrentItemState("hover state"); setCurrentItemState("hover state");
} }
function previousItem() { function previousItem() {
setCurrentItemState("base state"); setCurrentItemState("base state");
var prevIndex = (columnIndex + 3 - 1) % 3; var column = columnIndex
if((rowIndex + prevIndex) < count){ column = column - 1;
columnIndex = prevIndex;
if (column < 0 ) {
column = buttonsColumnsOnPage - 1;
var index = rowIndex*buttonsColumnsOnPage + column;
var currentGridItems = swipeView.currentItem.children[0].children
while(index >= currentGridItems.length) {
column = column - 1
index = rowIndex*buttonsColumnsOnPage + column;
}
} }
columnIndex = column
setCurrentItemState("hover state"); setCurrentItemState("hover state");
} }
function upItem() { function upItem() {
setCurrentItemState("base state"); setCurrentItemState("base state");
rowIndex = rowIndex - 3; var row = rowIndex
if (rowIndex < 0 ) { row = row - 1;
rowIndex = (count - (count % 3));
var index = rowIndex + columnIndex; if (row < 0 ) {
if(index > count) { row = buttonsRowsOnPage - 1;
rowIndex = rowIndex - 3; var index = row*buttonsColumnsOnPage + columnIndex;
var currentGridItems = swipeView.currentItem.children[0].children
while(index >= currentGridItems.length) {
row = row - 1
index = row*buttonsColumnsOnPage + columnIndex;
} }
} }
rowIndex = row
setCurrentItemState("hover state"); setCurrentItemState("hover state");
} }
function downItem() { function downItem() {
setCurrentItemState("base state"); setCurrentItemState("base state");
rowIndex = rowIndex + 3; rowIndex = rowIndex + 1;
var index = rowIndex + columnIndex; var currentGridItems = swipeView.currentItem.children[0].children
if (index > count ) { var index = rowIndex*buttonsColumnsOnPage + columnIndex;
if (index >= currentGridItems.length) {
rowIndex = 0; rowIndex = 0;
} }
setCurrentItemState("hover state"); setCurrentItemState("hover state");
} }
function selectItem() { function selectItem() {
var grid = getPage(rowIndex, columnIndex) var index = rowIndex*buttonsColumnsOnPage + columnIndex;
grid.page.children[grid.index].clicked(); var currentGridItems = swipeView.currentItem.children[0].children
if (tabletRoot) { if (currentGridItems !== null && index >= 0 && index < currentGridItems.length) {
tabletRoot.playButtonClickSound(); currentGridItems[index].clicked();
if (tabletRoot) {
tabletRoot.playButtonClickSound();
}
} }
} }
Keys.onRightPressed: nextItem(); Keys.onRightPressed: {
Keys.onLeftPressed: previousItem(); if (event.modifiers & Qt.ShiftModifier) {
Keys.onDownPressed: downItem(); nextPage();
Keys.onUpPressed: upItem(); } else {
nextItem();
}
}
Keys.onLeftPressed: {
if (event.modifiers & Qt.ShiftModifier) {
previousPage();
} else {
previousItem();
}
}
Keys.onDownPressed: {
if (event.modifiers & Qt.ShiftModifier) {
nextPage();
} else {
downItem();
}
}
Keys.onUpPressed: {
if (event.modifiers & Qt.ShiftModifier) {
previousPage();
} else {
upItem();
}
}
Keys.onReturnPressed: selectItem(); Keys.onReturnPressed: selectItem();
} }

View file

@ -24,6 +24,10 @@ Item {
property int stableOrder: 0 property int stableOrder: 0
property var tabletRoot; property var tabletRoot;
property var flickable: null property var flickable: null
property int row: -1
property int column: -1
width: 129 width: 129
height: 129 height: 129
@ -135,6 +139,7 @@ Item {
preventStealing: false preventStealing: false
onClicked: { onClicked: {
console.log("Tablet Button Clicked!"); console.log("Tablet Button Clicked!");
tablet.setCurrentItemState("base state");
if (tabletButton.inDebugMode) { if (tabletButton.inDebugMode) {
if (tabletButton.isActive) { if (tabletButton.isActive) {
tabletButton.isActive = false; tabletButton.isActive = false;
@ -142,6 +147,9 @@ Item {
tabletButton.isActive = true; tabletButton.isActive = true;
} }
} }
tablet.rowIndex = tabletButton.row
tablet.columnIndex = tabletButton.column
tabletButton.clicked(); tabletButton.clicked();
if (tabletRoot) { if (tabletRoot) {
tabletInterface.playSound(TabletEnums.ButtonClick); tabletInterface.playSound(TabletEnums.ButtonClick);
@ -149,6 +157,7 @@ Item {
} }
onEntered: { onEntered: {
tablet.setCurrentItemState("base state");
tabletButton.isEntered = true; tabletButton.isEntered = true;
tabletInterface.playSound(TabletEnums.ButtonHover); tabletInterface.playSound(TabletEnums.ButtonHover);
@ -157,6 +166,8 @@ Item {
} else { } else {
tabletButton.state = "hover state"; tabletButton.state = "hover state";
} }
tablet.rowIndex = tabletButton.row
tablet.columnIndex = tabletButton.column
} }
onExited: { onExited: {
tabletButton.isEntered = false; tabletButton.isEntered = false;

View file

@ -716,7 +716,11 @@ TabletButtonProxy* TabletProxy::addButton(const QVariant& properties) {
} }
auto tabletButtonProxy = QSharedPointer<TabletButtonProxy>(new TabletButtonProxy(properties.toMap())); auto tabletButtonProxy = QSharedPointer<TabletButtonProxy>(new TabletButtonProxy(properties.toMap()));
_tabletButtonProxies.push_back(tabletButtonProxy); {
QMutexLocker locker(&_tabletButtonsListMutex);
_tabletButtonProxies.push_back(tabletButtonProxy);
}
if (!_toolbarMode && _qmlTabletRoot) { if (!_toolbarMode && _qmlTabletRoot) {
auto tablet = getQmlTablet(); auto tablet = getQmlTablet();
if (tablet) { if (tablet) {
@ -764,7 +768,10 @@ void TabletProxy::removeButton(TabletButtonProxy* tabletButtonProxy) {
return; return;
} }
buttonProxy = *iter; buttonProxy = *iter;
_tabletButtonProxies.erase(iter); {
QMutexLocker locker(&_tabletButtonsListMutex);
_tabletButtonProxies.erase(iter);
}
} }
if (!_toolbarMode && _qmlTabletRoot) { if (!_toolbarMode && _qmlTabletRoot) {
@ -813,8 +820,12 @@ void TabletProxy::addButtonsToHomeScreen() {
if (!tablet || _toolbarMode) { if (!tablet || _toolbarMode) {
return; return;
} }
for (auto& buttonProxy : _tabletButtonProxies) {
addButtonProxyToQmlTablet(tablet, buttonProxy.data()); {
QMutexLocker locker(&_tabletButtonsListMutex);
for (auto& buttonProxy : _tabletButtonProxies) {
addButtonProxyToQmlTablet(tablet, buttonProxy.data());
}
} }
auto loader = _qmlTabletRoot->findChild<QQuickItem*>("loader"); auto loader = _qmlTabletRoot->findChild<QQuickItem*>("loader");
QObject::disconnect(loader, SIGNAL(loaded()), this, SLOT(addButtonsToHomeScreen())); QObject::disconnect(loader, SIGNAL(loaded()), this, SLOT(addButtonsToHomeScreen()));
@ -841,9 +852,12 @@ void TabletProxy::desktopWindowClosed() {
void TabletProxy::addButtonsToToolbar() { void TabletProxy::addButtonsToToolbar() {
Q_ASSERT(QThread::currentThread() == thread()); Q_ASSERT(QThread::currentThread() == thread());
ToolbarProxy* toolbarProxy = DependencyManager::get<TabletScriptingInterface>()->getSystemToolbarProxy(); ToolbarProxy* toolbarProxy = DependencyManager::get<TabletScriptingInterface>()->getSystemToolbarProxy();
for (auto& buttonProxy : _tabletButtonProxies) { {
// copy properties from tablet button proxy to toolbar button proxy. QMutexLocker locker(&_tabletButtonsListMutex);
buttonProxy->setToolbarButtonProxy(toolbarProxy->addButton(buttonProxy->getProperties())); for (auto& buttonProxy : _tabletButtonProxies) {
// copy properties from tablet button proxy to toolbar button proxy.
buttonProxy->setToolbarButtonProxy(toolbarProxy->addButton(buttonProxy->getProperties()));
}
} }
// make the toolbar visible // make the toolbar visible
@ -902,11 +916,14 @@ QQuickItem* TabletProxy::getQmlMenu() const {
QList<QObject *> TabletProxy::getButtonsList() const { QList<QObject *> TabletProxy::getButtonsList() const {
QList<QObject *> buttonsList; QList<QObject *> buttonsList;
QMutexLocker locker(&_tabletButtonsListMutex);
for (auto& buttonProxy : _tabletButtonProxies) { for (auto& buttonProxy : _tabletButtonProxies) {
if (buttonProxy->getQmlButton()) { if (buttonProxy->getQmlButton()) {
buttonsList.append(buttonProxy->getQmlButton()); buttonsList.append(buttonProxy->getQmlButton());
} }
} }
return buttonsList; return buttonsList;
} }

View file

@ -270,6 +270,7 @@ protected:
std::pair<QVariant, bool> _initialWebPathParams; std::pair<QVariant, bool> _initialWebPathParams;
bool _landscape { false }; bool _landscape { false };
bool _showRunningScripts { false }; bool _showRunningScripts { false };
mutable QMutex _tabletButtonsListMutex;
}; };
Q_DECLARE_METATYPE(TabletProxy*); Q_DECLARE_METATYPE(TabletProxy*);