checkpoint with PAL working.

This commit is contained in:
howard-stearns 2018-06-01 13:33:45 -07:00
parent e6ffb9a3e5
commit 29b09d64e6
4 changed files with 74 additions and 164 deletions

View file

@ -18,6 +18,7 @@ import Qt.labs.settings 1.0
import "../styles-uit"
import "../controls-uit" as HifiControlsUit
import "../controls" as HifiControls
import "models" as HifiModels
// references HMD, Users, UserActivityLogger from root context
@ -44,6 +45,28 @@ Rectangle {
property bool punctuationMode: false;
HifiConstants { id: hifi; }
RootHttpRequest { id: http; }
HifiModels.PSFListModel {
id: connectionsUserModel;
http: http;
endpoint: "/api/v1/users?filter=connections";
localSort: true;
property var sortColumn: connectionsTable.getColumn(connectionsTable.sortIndicatorColumn);
sortProperty: sortColumn ? sortColumn.role : "userName";
sortAscending: connectionsTable.sortIndicatorOrder === Qt.AscendingOrder;
itemsPerPage: 9;
listView: connectionsTable;
processPage: function (data) {
return data.users.map(function (user) {
return {
userName: user.username,
connection: user.connection,
profileUrl: user.images.thumbnail,
placeName: (user.location.root || user.location.domain || {}).name || ''
};
});
};
}
// The letterbox used for popup messages
LetterboxMessage {
@ -106,16 +129,6 @@ Rectangle {
});
return sessionIDs;
}
function getSelectedConnectionsUserNames() {
var userNames = [];
connectionsTable.selection.forEach(function (userIndex) {
var datum = connectionsUserModelData[userIndex];
if (datum) {
userNames.push(datum.userName);
}
});
return userNames;
}
function refreshNearbyWithFilter() {
// We should just be able to set settings.filtered to inViewCheckbox.checked, but see #3249, so send to .js for saving.
var userIds = getSelectedNearbySessionIDs();
@ -232,9 +245,7 @@ Rectangle {
anchors.fill: parent;
onClicked: {
if (activeTab != "connectionsTab") {
connectionsLoading.visible = false;
connectionsLoading.visible = true;
pal.sendToScript({method: 'refreshConnections'});
connectionsUserModel.getFirstPage();
}
activeTab = "connectionsTab";
connectionsHelpText.color = hifi.colors.blueAccent;
@ -258,11 +269,7 @@ Rectangle {
id: reloadConnections;
width: reloadConnections.height;
glyph: hifi.glyphs.reload;
onClicked: {
connectionsLoading.visible = false;
connectionsLoading.visible = true;
pal.sendToScript({method: 'refreshConnections'});
}
onClicked: connectionsUserModel.getFirstPage('delayRefresh');
}
}
// "CONNECTIONS" text
@ -702,7 +709,7 @@ Rectangle {
anchors.top: parent.top;
anchors.topMargin: 185;
anchors.horizontalCenter: parent.horizontalCenter;
visible: true;
visible: !connectionsUserModel.retrievedAtLeastOnePage;
onVisibleChanged: {
if (visible) {
connectionsTimeoutTimer.start();
@ -747,14 +754,6 @@ Rectangle {
headerVisible: true;
sortIndicatorColumn: settings.connectionsSortIndicatorColumn;
sortIndicatorOrder: settings.connectionsSortIndicatorOrder;
onSortIndicatorColumnChanged: {
settings.connectionsSortIndicatorColumn = sortIndicatorColumn;
sortConnectionsModel();
}
onSortIndicatorOrderChanged: {
settings.connectionsSortIndicatorOrder = sortIndicatorOrder;
sortConnectionsModel();
}
TableViewColumn {
id: connectionsUserNameHeader;
@ -779,8 +778,10 @@ Rectangle {
resizable: false;
}
model: ListModel {
id: connectionsUserModel;
model: connectionsUserModel.model;
Connections {
target: connectionsTable.flickableItem;
onAtYEndChanged: if (connectionsTable.flickableItem.atYEnd) { connectionsUserModel.getNextPage(); }
}
// This Rectangle refers to each Row in the connectionsTable.
@ -1130,16 +1131,6 @@ Rectangle {
sortModel();
reloadNearby.color = 0;
break;
case 'connections':
var data = message.params;
if (pal.debug) {
console.log('Got connection data: ', JSON.stringify(data));
}
connectionsUserModelData = data;
sortConnectionsModel();
connectionsLoading.visible = false;
connectionsRefreshProblemText.visible = false;
break;
case 'select':
var sessionIds = message.params[0];
var selected = message.params[1];
@ -1239,6 +1230,11 @@ Rectangle {
reloadNearby.color = 2;
}
break;
case 'inspectionCertificate_resetCert': // HRS FIXME what's this about?
break;
case 'http.response':
http.handleHttpResponse(message);
break;
default:
console.log('Unrecognized message:', JSON.stringify(message));
}
@ -1287,45 +1283,6 @@ Rectangle {
nearbyTable.positionViewAtRow(newSelectedIndexes[0], ListView.Beginning);
}
}
function sortConnectionsModel() {
var column = connectionsTable.getColumn(connectionsTable.sortIndicatorColumn);
var sortProperty = column ? column.role : "userName";
var before = (connectionsTable.sortIndicatorOrder === Qt.AscendingOrder) ? -1 : 1;
var after = -1 * before;
// get selection(s) before sorting
var selectedIDs = getSelectedConnectionsUserNames();
connectionsUserModelData.sort(function (a, b) {
var aValue = a[sortProperty].toString().toLowerCase(), bValue = b[sortProperty].toString().toLowerCase();
if (!aValue && !bValue) {
return 0;
} else if (!aValue) {
return after;
} else if (!bValue) {
return before;
}
switch (true) {
case (aValue < bValue): return before;
case (aValue > bValue): return after;
default: return 0;
}
});
connectionsTable.selection.clear();
connectionsUserModel.clear();
var userIndex = 0;
var newSelectedIndexes = [];
connectionsUserModelData.forEach(function (datum) {
datum.userIndex = userIndex++;
connectionsUserModel.append(datum);
if (selectedIDs.indexOf(datum.sessionId) != -1) {
newSelectedIndexes.push(datum.userIndex);
}
});
if (newSelectedIndexes.length > 0) {
connectionsTable.selection.select(newSelectedIndexes);
connectionsTable.positionViewAtRow(newSelectedIndexes[0], ListView.Beginning);
}
}
signal sendToScript(var message);
function noticeSelection() {
var userIds = [];

View file

@ -401,7 +401,6 @@ Item {
itemsPerPage: 8;
listView: connectionsList;
processPage: function (data) {
console.log("processPage", connectionsModel.listModelName, JSON.stringify(data));
return data.users;
};
searchFilter: filterBar.text;

View file

@ -25,15 +25,17 @@ Item {
// Parameters. Even if you override getPage, below, please set these for clarity and consistency, when applicable.
// E.g., your getPage function could refer to this sortKey, etc.
property string endpoint;
property string sortKey;
property string sortProperty; // Currently only handles sorting on one column, which fits with current needs and tables.
property bool sortAscending;
property string sortKey: !sortProperty ? '' : (sortProperty + "," + (sortAscending ? "asc" : "desc"));
property string searchFilter: "";
property string tagsFilter;
// QML fires the following changed handlers even when first instantiating the Item. So we need a guard against firing them too early.
property bool initialized: false;
Component.onCompleted: initialized = true;
onEndpointChanged: if (initialized) { getFirstPage(); }
onSortKeyChanged: if (initialized) { getFirstPage(); }
onEndpointChanged: if (initialized) { getFirstPage('delayClear'); }
onSortKeyChanged: if (initialized) { getFirstPage('delayClear'); }
onSearchFilterChanged: {
if (!initialized) { return; }
if (searchItemTest) {
@ -42,14 +44,15 @@ Item {
finalModel.append(filteredCopy);
debugView('after searchFilterChanged');
} else { // TODO: fancy timer against fast typing.
getFirstPage();
getFirstPage('delayClear');
}
}
onTagsFilterChanged: if (initialized) { getFirstPage(); }
onTagsFilterChanged: if (initialized) { getFirstPage('delayClear'); }
property int itemsPerPage: 100;
// If the endpoint doesn't do search, tags, sort, these functions can be supplied to do it here.
property var searchItemTest: null;
property bool localSort: false;
property var copyOfItems: [];
// State.
@ -92,21 +95,29 @@ Item {
return fail("Mismatched page, expected:" + currentPageToRetrieve);
}
processed = processPage(response.data || response);
if (response.total_pages && (response.total_pages === currentPageToRetrieve)) {
currentPageToRetrieve = -1;
}
if (searchItemTest) {
copyOfItems = copyOfItems.concat(processed);
if (searchFilter) {
processed = applySearchItemTest(processed);
}
}
if (localSort) {
copyOfItems = copyOfItems.concat(processed);
if (sortProperty) {
sortCopy(sortProperty, sortAscending);
processed = copyOfItems;
delayedClear = true; // see next conditional
}
}
if (delayedClear) {
finalModel.clear();
delayedClear = false;
}
finalModel.append(processed); // FIXME keep index steady, and apply any post sort
retrievedAtLeastOnePage = true;
if (response.total_pages && (response.total_pages === currentPageToRetrieve)) {
currentPageToRetrieve = -1;
}
debugView('after handlePage');
if (searchItemTest && searchFilter && listView && listView.atYEnd && (currentPageToRetrieve >= 0)) {
getNextPage(); // too fancy??
@ -185,85 +196,26 @@ Item {
id: finalModel;
}
// Used when sorting model data on the CLIENT
// Right now, there is no sorting done on the client for
// any users of PSFListModel, but that could very easily change.
property string sortColumnName: "";
property bool isSortingDescending: true;
property bool valuesAreNumerical: false;
function sortCopy(sortProperty, isAscending) {
console.debug('client sort', listModelName, sortProperty, isAscending, copyOfItems.length, 'items');
var before = isAscending ? -1 : 1;
var after = -1 * before;
function swap(a, b) {
if (a < b) {
move(a, b, 1);
move(b - 1, a, 1);
} else if (a > b) {
move(b, a, 1);
move(a - 1, b, 1);
}
}
function partition(begin, end, pivot) {
if (valuesAreNumerical) {
var piv = get(pivot)[sortColumnName];
swap(pivot, end - 1);
var store = begin;
var i;
for (i = begin; i < end - 1; ++i) {
var currentElement = get(i)[sortColumnName];
if (isSortingDescending) {
if (currentElement > piv) {
swap(store, i);
++store;
}
} else {
if (currentElement < piv) {
swap(store, i);
++store;
}
}
copyOfItems.sort(function (a, b) {
var aValue = a[sortProperty].toString().toLowerCase(),
bValue = b[sortProperty].toString().toLowerCase();
if (!aValue && !bValue) {
return 0;
} else if (!aValue) {
return after;
} else if (!bValue) {
return before;
}
swap(end - 1, store);
return store;
} else {
var piv = get(pivot)[sortColumnName].toLowerCase();
swap(pivot, end - 1);
var store = begin;
var i;
for (i = begin; i < end - 1; ++i) {
var currentElement = get(i)[sortColumnName].toLowerCase();
if (isSortingDescending) {
if (currentElement > piv) {
swap(store, i);
++store;
}
} else {
if (currentElement < piv) {
swap(store, i);
++store;
}
}
switch (true) {
case (aValue < bValue): return before;
case (aValue > bValue): return after;
default: return 0;
}
swap(end - 1, store);
return store;
}
}
function qsort(begin, end) {
if (end - 1 > begin) {
var pivot = begin + Math.floor(Math.random() * (end - begin));
pivot = partition(begin, end, pivot);
qsort(begin, pivot);
qsort(pivot + 1, end);
}
}
function quickSort() {
qsort(0, count)
});
}
}

View file

@ -317,6 +317,8 @@ function fromQml(message) { // messages are {method, params}, like json-rpc. See
}
);
break;
case 'http.request':
break; // Handled elsewhere.
default:
print('Unrecognized message from Pal.qml:', JSON.stringify(message));
}