mirror of
https://github.com/overte-org/overte.git
synced 2025-04-26 01:56:22 +02:00
semicolons and whitespace per coding standard
This commit is contained in:
parent
a715a694f0
commit
632cdc1b38
1 changed files with 409 additions and 407 deletions
|
@ -21,45 +21,46 @@ import "../controls-uit" as HifiControls
|
||||||
// references HMD, Users, UserActivityLogger from root context
|
// references HMD, Users, UserActivityLogger from root context
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: pal
|
id: pal;
|
||||||
// Size
|
// Size
|
||||||
width: parent.width
|
width: parent.width;
|
||||||
height: parent.height
|
height: parent.height;
|
||||||
// Style
|
// Style
|
||||||
color: "#E3E3E3"
|
color: "#E3E3E3";
|
||||||
// Properties
|
// Properties
|
||||||
property int myCardHeight: 90
|
property int myCardHeight: 90;
|
||||||
property int rowHeight: 70
|
property int rowHeight: 70;
|
||||||
property int actionButtonWidth: 55
|
property int actionButtonWidth: 55;
|
||||||
property int actionButtonAllowance: actionButtonWidth * 2
|
property int actionButtonAllowance: actionButtonWidth * 2;
|
||||||
property int minNameCardWidth: palContainer.width - (actionButtonAllowance * 2) - 4 - hifi.dimensions.scrollbarBackgroundWidth
|
property int minNameCardWidth: palContainer.width - (actionButtonAllowance * 2) - 4 - hifi.dimensions.scrollbarBackgroundWidth;
|
||||||
property int nameCardWidth: minNameCardWidth + (iAmAdmin ? 0 : actionButtonAllowance)
|
property int nameCardWidth: minNameCardWidth + (iAmAdmin ? 0 : actionButtonAllowance);
|
||||||
property var myData: ({displayName: "", userName: "", audioLevel: 0.0, avgAudioLevel: 0.0, admin: true}) // valid dummy until set
|
property var myData: ({displayName: "", userName: "", audioLevel: 0.0, avgAudioLevel: 0.0, admin: true}); // valid dummy until set
|
||||||
property var ignored: ({}); // Keep a local list of ignored avatars & their data. Necessary because HashMap is slow to respond after ignoring.
|
property var ignored: ({}); // Keep a local list of ignored avatars & their data. Necessary because HashMap is slow to respond after ignoring.
|
||||||
property var userModelData: [] // This simple list is essentially a mirror of the userModel listModel without all the extra complexities.
|
property var userModelData: []; // This simple list is essentially a mirror of the userModel listModel without all the extra complexities.
|
||||||
property bool iAmAdmin: false
|
property bool iAmAdmin: false;
|
||||||
|
|
||||||
HifiConstants { id: hifi }
|
HifiConstants { id: hifi; }
|
||||||
|
|
||||||
// The letterbox used for popup messages
|
// The letterbox used for popup messages
|
||||||
LetterboxMessage {
|
LetterboxMessage {
|
||||||
id: letterboxMessage
|
|
||||||
z: 999 // Force the popup on top of everything else
|
id: letterboxMessage;
|
||||||
|
z: 999; // Force the popup on top of everything else
|
||||||
}
|
}
|
||||||
function letterbox(headerGlyph, headerText, message) {
|
function letterbox(headerGlyph, headerText, message) {
|
||||||
letterboxMessage.headerGlyph = headerGlyph
|
letterboxMessage.headerGlyph = headerGlyph;
|
||||||
letterboxMessage.headerText = headerText
|
letterboxMessage.headerText = headerText;
|
||||||
letterboxMessage.text = message
|
letterboxMessage.text = message;
|
||||||
letterboxMessage.visible = true
|
letterboxMessage.visible = true;
|
||||||
letterboxMessage.popupRadius = 0
|
letterboxMessage.popupRadius = 0;
|
||||||
}
|
}
|
||||||
Settings {
|
Settings {
|
||||||
id: settings
|
id: settings;
|
||||||
category: "pal"
|
category: "pal";
|
||||||
property bool filtered: false
|
property bool filtered: false;
|
||||||
property int nearDistance: 30
|
property int nearDistance: 30;
|
||||||
property int sortIndicatorColumn: 1
|
property int sortIndicatorColumn: 1;
|
||||||
property int sortIndicatorOrder: Qt.AscendingOrder
|
property int sortIndicatorOrder: Qt.AscendingOrder;
|
||||||
}
|
}
|
||||||
function refreshWithFilter() {
|
function refreshWithFilter() {
|
||||||
// We should just be able to set settings.filtered to filter.checked, but see #3249, so send to .js for saving.
|
// We should just be able to set settings.filtered to filter.checked, but see #3249, so send to .js for saving.
|
||||||
|
@ -68,418 +69,418 @@ Rectangle {
|
||||||
|
|
||||||
// This is the container for the PAL
|
// This is the container for the PAL
|
||||||
Rectangle {
|
Rectangle {
|
||||||
property bool punctuationMode: false
|
property bool punctuationMode: false;
|
||||||
id: palContainer
|
id: palContainer;
|
||||||
// Size
|
// Size
|
||||||
width: pal.width - 10
|
width: pal.width - 10;
|
||||||
height: pal.height - 10
|
height: pal.height - 10;
|
||||||
// Style
|
// Style
|
||||||
color: pal.color
|
color: pal.color;
|
||||||
// Anchors
|
// Anchors
|
||||||
anchors.centerIn: pal
|
anchors.centerIn: pal;
|
||||||
// Properties
|
// Properties
|
||||||
radius: hifi.dimensions.borderRadius
|
radius: hifi.dimensions.borderRadius;
|
||||||
|
|
||||||
// This contains the current user's NameCard and will contain other information in the future
|
// This contains the current user's NameCard and will contain other information in the future
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: myInfo
|
id: myInfo;
|
||||||
// Size
|
|
||||||
width: palContainer.width
|
|
||||||
height: myCardHeight
|
|
||||||
// Style
|
|
||||||
color: pal.color
|
|
||||||
// Anchors
|
|
||||||
anchors.top: palContainer.top
|
|
||||||
// Properties
|
|
||||||
radius: hifi.dimensions.borderRadius
|
|
||||||
// This NameCard refers to the current user's NameCard (the one above the table)
|
|
||||||
NameCard {
|
|
||||||
id: myCard
|
|
||||||
// Properties
|
|
||||||
displayName: myData.displayName
|
|
||||||
userName: myData.userName
|
|
||||||
audioLevel: myData.audioLevel
|
|
||||||
avgAudioLevel: myData.avgAudioLevel
|
|
||||||
isMyCard: true
|
|
||||||
// Size
|
// Size
|
||||||
width: minNameCardWidth
|
width: palContainer.width;
|
||||||
height: parent.height
|
height: myCardHeight;
|
||||||
// Anchors
|
|
||||||
anchors.left: parent.left
|
|
||||||
}
|
|
||||||
Row {
|
|
||||||
HifiControls.CheckBox {
|
|
||||||
id: filter
|
|
||||||
checked: settings.filtered
|
|
||||||
text: "in view"
|
|
||||||
boxSize: reload.height * 0.70
|
|
||||||
onCheckedChanged: refreshWithFilter()
|
|
||||||
}
|
|
||||||
HifiControls.GlyphButton {
|
|
||||||
id: reload
|
|
||||||
glyph: hifi.glyphs.reload
|
|
||||||
width: reload.height
|
|
||||||
onClicked: refreshWithFilter()
|
|
||||||
}
|
|
||||||
spacing: 50
|
|
||||||
anchors {
|
|
||||||
right: parent.right
|
|
||||||
top: parent.top
|
|
||||||
topMargin: 10
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Rectangles used to cover up rounded edges on bottom of MyInfo Rectangle
|
|
||||||
Rectangle {
|
|
||||||
color: pal.color
|
|
||||||
width: palContainer.width
|
|
||||||
height: 10
|
|
||||||
anchors.top: myInfo.bottom
|
|
||||||
anchors.left: parent.left
|
|
||||||
}
|
|
||||||
Rectangle {
|
|
||||||
color: pal.color
|
|
||||||
width: palContainer.width
|
|
||||||
height: 10
|
|
||||||
anchors.bottom: table.top
|
|
||||||
anchors.left: parent.left
|
|
||||||
}
|
|
||||||
// Rectangle that houses "ADMIN" string
|
|
||||||
Rectangle {
|
|
||||||
id: adminTab
|
|
||||||
// Size
|
|
||||||
width: 2*actionButtonWidth + hifi.dimensions.scrollbarBackgroundWidth + 2
|
|
||||||
height: 40
|
|
||||||
// Anchors
|
|
||||||
anchors.bottom: myInfo.bottom
|
|
||||||
anchors.bottomMargin: -10
|
|
||||||
anchors.right: myInfo.right
|
|
||||||
// Properties
|
|
||||||
visible: iAmAdmin
|
|
||||||
// Style
|
|
||||||
color: hifi.colors.tableRowLightEven
|
|
||||||
radius: hifi.dimensions.borderRadius
|
|
||||||
border.color: hifi.colors.lightGrayText
|
|
||||||
border.width: 2
|
|
||||||
// "ADMIN" text
|
|
||||||
RalewaySemiBold {
|
|
||||||
id: adminTabText
|
|
||||||
text: "ADMIN"
|
|
||||||
// Text size
|
|
||||||
size: hifi.fontSizes.tableHeading + 2
|
|
||||||
// Anchors
|
|
||||||
anchors.top: parent.top
|
|
||||||
anchors.topMargin: 8
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.rightMargin: hifi.dimensions.scrollbarBackgroundWidth
|
|
||||||
// Style
|
// Style
|
||||||
font.capitalization: Font.AllUppercase
|
color: pal.color;
|
||||||
color: hifi.colors.redHighlight
|
// Anchors
|
||||||
// Alignment
|
anchors.top: palContainer.top;
|
||||||
horizontalAlignment: Text.AlignHCenter
|
// Properties
|
||||||
verticalAlignment: Text.AlignTop
|
radius: hifi.dimensions.borderRadius;
|
||||||
}
|
// This NameCard refers to the current user's NameCard (the one above the table)
|
||||||
}
|
|
||||||
// This TableView refers to the table (below the current user's NameCard)
|
|
||||||
HifiControls.Table {
|
|
||||||
id: table
|
|
||||||
// Size
|
|
||||||
height: palContainer.height - myInfo.height - 4
|
|
||||||
width: palContainer.width - 4
|
|
||||||
// Anchors
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.top: myInfo.bottom
|
|
||||||
// Properties
|
|
||||||
centerHeaderText: true
|
|
||||||
sortIndicatorVisible: true
|
|
||||||
headerVisible: true
|
|
||||||
sortIndicatorColumn: settings.sortIndicatorColumn
|
|
||||||
sortIndicatorOrder: settings.sortIndicatorOrder
|
|
||||||
onSortIndicatorColumnChanged: {
|
|
||||||
settings.sortIndicatorColumn = sortIndicatorColumn
|
|
||||||
sortModel()
|
|
||||||
}
|
|
||||||
onSortIndicatorOrderChanged: {
|
|
||||||
settings.sortIndicatorOrder = sortIndicatorOrder
|
|
||||||
sortModel()
|
|
||||||
}
|
|
||||||
|
|
||||||
TableViewColumn {
|
|
||||||
role: "avgAudioLevel"
|
|
||||||
title: "LOUD"
|
|
||||||
width: actionButtonWidth
|
|
||||||
movable: false
|
|
||||||
resizable: false
|
|
||||||
}
|
|
||||||
|
|
||||||
TableViewColumn {
|
|
||||||
id: displayNameHeader
|
|
||||||
role: "displayName"
|
|
||||||
title: table.rowCount + (table.rowCount === 1 ? " NAME" : " NAMES")
|
|
||||||
width: nameCardWidth
|
|
||||||
movable: false
|
|
||||||
resizable: false
|
|
||||||
}
|
|
||||||
TableViewColumn {
|
|
||||||
role: "ignore"
|
|
||||||
title: "IGNORE"
|
|
||||||
width: actionButtonWidth
|
|
||||||
movable: false
|
|
||||||
resizable: false
|
|
||||||
}
|
|
||||||
TableViewColumn {
|
|
||||||
visible: iAmAdmin
|
|
||||||
role: "mute"
|
|
||||||
title: "SILENCE"
|
|
||||||
width: actionButtonWidth
|
|
||||||
movable: false
|
|
||||||
resizable: false
|
|
||||||
}
|
|
||||||
TableViewColumn {
|
|
||||||
visible: iAmAdmin
|
|
||||||
role: "kick"
|
|
||||||
title: "BAN"
|
|
||||||
width: actionButtonWidth
|
|
||||||
movable: false
|
|
||||||
resizable: false
|
|
||||||
}
|
|
||||||
model: ListModel {
|
|
||||||
id: userModel
|
|
||||||
}
|
|
||||||
|
|
||||||
// This Rectangle refers to each Row in the table.
|
|
||||||
rowDelegate: Rectangle { // The only way I know to specify a row height.
|
|
||||||
// Size
|
|
||||||
height: styleData.selected ? rowHeight : rowHeight - 15
|
|
||||||
color: styleData.selected
|
|
||||||
? hifi.colors.orangeHighlight
|
|
||||||
: styleData.alternate ? hifi.colors.tableRowLightEven : hifi.colors.tableRowLightOdd
|
|
||||||
}
|
|
||||||
|
|
||||||
// This Item refers to the contents of each Cell
|
|
||||||
itemDelegate: Item {
|
|
||||||
id: itemCell
|
|
||||||
property bool isCheckBox: styleData.role === "personalMute" || styleData.role === "ignore"
|
|
||||||
property bool isButton: styleData.role === "mute" || styleData.role === "kick"
|
|
||||||
property bool isAvgAudio: styleData.role === "avgAudioLevel"
|
|
||||||
|
|
||||||
// This NameCard refers to the cell that contains an avatar's
|
|
||||||
// DisplayName and UserName
|
|
||||||
NameCard {
|
NameCard {
|
||||||
id: nameCard
|
id: myCard;
|
||||||
// Properties
|
// Properties
|
||||||
displayName: styleData.value
|
displayName: myData.displayName;
|
||||||
userName: model ? model.userName : ""
|
userName: myData.userName;
|
||||||
audioLevel: model ? model.audioLevel : 0.0
|
audioLevel: myData.audioLevel;
|
||||||
avgAudioLevel: model ? model.avgAudioLevel : 0.0
|
avgAudioLevel: myData.avgAudioLevel;
|
||||||
visible: !isCheckBox && !isButton && !isAvgAudio
|
isMyCard: true;
|
||||||
uuid: model ? model.sessionId : ""
|
|
||||||
selected: styleData.selected
|
|
||||||
isAdmin: model && model.admin
|
|
||||||
// Size
|
// Size
|
||||||
width: nameCardWidth
|
width: minNameCardWidth;
|
||||||
height: parent.height
|
height: parent.height;
|
||||||
// Anchors
|
// Anchors
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left;
|
||||||
}
|
}
|
||||||
HifiControls.GlyphButton {
|
Row {
|
||||||
function getGlyph() {
|
HifiControls.CheckBox {
|
||||||
var fileName = "vol_";
|
id: filter;
|
||||||
if (model && model.personalMute) {
|
checked: settings.filtered;
|
||||||
fileName += "x_";
|
text: "in view";
|
||||||
}
|
boxSize: reload.height * 0.70;
|
||||||
fileName += (4.0*(model ? model.avgAudioLevel : 0.0)).toFixed(0);
|
onCheckedChanged: refreshWithFilter();
|
||||||
return hifi.glyphs[fileName];
|
|
||||||
}
|
}
|
||||||
id: avgAudioVolume
|
HifiControls.GlyphButton {
|
||||||
visible: isAvgAudio
|
id: reload;
|
||||||
glyph: getGlyph()
|
glyph: hifi.glyphs.reload;
|
||||||
width: 32
|
width: reload.height;
|
||||||
size: height
|
onClicked: refreshWithFilter();
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
onClicked: {
|
|
||||||
// cannot change mute status when ignoring
|
|
||||||
if (!model["ignore"]) {
|
|
||||||
var newValue = !model["personalMute"];
|
|
||||||
userModel.setProperty(model.userIndex, "personalMute", newValue)
|
|
||||||
userModelData[model.userIndex]["personalMute"] = newValue // Defensive programming
|
|
||||||
Users["personalMute"](model.sessionId, newValue)
|
|
||||||
UserActivityLogger["palAction"](newValue ? "personalMute" : "un-personalMute", model.sessionId)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
spacing: 50;
|
||||||
|
anchors {
|
||||||
|
right: parent.right;
|
||||||
|
top: parent.top;
|
||||||
|
topMargin: 10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Rectangles used to cover up rounded edges on bottom of MyInfo Rectangle
|
||||||
|
Rectangle {
|
||||||
|
color: pal.color;
|
||||||
|
width: palContainer.width;
|
||||||
|
height: 10;
|
||||||
|
anchors.top: myInfo.bottom;
|
||||||
|
anchors.left: parent.left;
|
||||||
|
}
|
||||||
|
Rectangle {
|
||||||
|
color: pal.color;
|
||||||
|
width: palContainer.width;
|
||||||
|
height: 10;
|
||||||
|
anchors.bottom: table.top;
|
||||||
|
anchors.left: parent.left;
|
||||||
|
}
|
||||||
|
// Rectangle that houses "ADMIN" string
|
||||||
|
Rectangle {
|
||||||
|
id: adminTab;
|
||||||
|
// Size
|
||||||
|
width: 2*actionButtonWidth + hifi.dimensions.scrollbarBackgroundWidth + 2;
|
||||||
|
height: 40;
|
||||||
|
// Anchors
|
||||||
|
anchors.bottom: myInfo.bottom;
|
||||||
|
anchors.bottomMargin: -10;
|
||||||
|
anchors.right: myInfo.right;
|
||||||
|
// Properties
|
||||||
|
visible: iAmAdmin;
|
||||||
|
// Style
|
||||||
|
color: hifi.colors.tableRowLightEven;
|
||||||
|
radius: hifi.dimensions.borderRadius;
|
||||||
|
border.color: hifi.colors.lightGrayText;
|
||||||
|
border.width: 2;
|
||||||
|
// "ADMIN" text
|
||||||
|
RalewaySemiBold {
|
||||||
|
id: adminTabText;
|
||||||
|
text: "ADMIN";
|
||||||
|
// Text size
|
||||||
|
size: hifi.fontSizes.tableHeading + 2;
|
||||||
|
// Anchors
|
||||||
|
anchors.top: parent.top;
|
||||||
|
anchors.topMargin: 8;
|
||||||
|
anchors.left: parent.left;
|
||||||
|
anchors.right: parent.right;
|
||||||
|
anchors.rightMargin: hifi.dimensions.scrollbarBackgroundWidth;
|
||||||
|
// Style
|
||||||
|
font.capitalization: Font.AllUppercase;
|
||||||
|
color: hifi.colors.redHighlight;
|
||||||
|
// Alignment
|
||||||
|
horizontalAlignment: Text.AlignHCenter;
|
||||||
|
verticalAlignment: Text.AlignTop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// This TableView refers to the table (below the current user's NameCard)
|
||||||
|
HifiControls.Table {
|
||||||
|
id: table;
|
||||||
|
// Size
|
||||||
|
height: palContainer.height - myInfo.height - 4;
|
||||||
|
width: palContainer.width - 4;
|
||||||
|
// Anchors
|
||||||
|
anchors.left: parent.left;
|
||||||
|
anchors.top: myInfo.bottom;
|
||||||
|
// Properties
|
||||||
|
centerHeaderText: true;
|
||||||
|
sortIndicatorVisible: true;
|
||||||
|
headerVisible: true;
|
||||||
|
sortIndicatorColumn: settings.sortIndicatorColumn;
|
||||||
|
sortIndicatorOrder: settings.sortIndicatorOrder;
|
||||||
|
onSortIndicatorColumnChanged: {
|
||||||
|
settings.sortIndicatorColumn = sortIndicatorColumn;
|
||||||
|
sortModel();
|
||||||
|
}
|
||||||
|
onSortIndicatorOrderChanged: {
|
||||||
|
settings.sortIndicatorOrder = sortIndicatorOrder;
|
||||||
|
sortModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
// This CheckBox belongs in the columns that contain the stateful action buttons ("Mute" & "Ignore" for now)
|
TableViewColumn {
|
||||||
// KNOWN BUG with the Checkboxes: When clicking in the center of the sorting header, the checkbox
|
role: "avgAudioLevel";
|
||||||
// will appear in the "hovered" state. Hovering over the checkbox will fix it.
|
title: "LOUD";
|
||||||
// Clicking on the sides of the sorting header doesn't cause this problem.
|
width: actionButtonWidth;
|
||||||
// I'm guessing this is a QT bug and not anything I can fix. I spent too long trying to work around it...
|
movable: false;
|
||||||
// I'm just going to leave the minor visual bug in.
|
resizable: false;
|
||||||
HifiControls.CheckBox {
|
|
||||||
id: actionCheckBox
|
|
||||||
visible: isCheckBox
|
|
||||||
anchors.centerIn: parent
|
|
||||||
checked: model ? model[styleData.role] : false
|
|
||||||
// If this is a "Personal Mute" checkbox, disable the checkbox if the "Ignore" checkbox is checked.
|
|
||||||
enabled: !(styleData.role === "personalMute" && (model ? model["ignore"] : true))
|
|
||||||
boxSize: 24
|
|
||||||
onClicked: {
|
|
||||||
var newValue = !model[styleData.role]
|
|
||||||
userModel.setProperty(model.userIndex, styleData.role, newValue)
|
|
||||||
userModelData[model.userIndex][styleData.role] = newValue // Defensive programming
|
|
||||||
Users[styleData.role](model.sessionId, newValue)
|
|
||||||
UserActivityLogger["palAction"](newValue ? styleData.role : "un-" + styleData.role, model.sessionId)
|
|
||||||
if (styleData.role === "ignore") {
|
|
||||||
userModel.setProperty(model.userIndex, "personalMute", newValue)
|
|
||||||
userModelData[model.userIndex]["personalMute"] = newValue // Defensive programming
|
|
||||||
if (newValue) {
|
|
||||||
ignored[model.sessionId] = userModelData[model.userIndex]
|
|
||||||
} else {
|
|
||||||
delete ignored[model.sessionId]
|
|
||||||
}
|
|
||||||
avgAudioVolume.glyph = avgAudioVolume.getGlyph()
|
|
||||||
}
|
|
||||||
// http://doc.qt.io/qt-5/qtqml-syntax-propertybinding.html#creating-property-bindings-from-javascript
|
|
||||||
// I'm using an explicit binding here because clicking a checkbox breaks the implicit binding as set by
|
|
||||||
// "checked:" statement above.
|
|
||||||
checked = Qt.binding(function() { return (model[styleData.role])})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This Button belongs in the columns that contain the stateless action buttons ("Silence" & "Ban" for now)
|
TableViewColumn {
|
||||||
HifiControls.Button {
|
id: displayNameHeader;
|
||||||
id: actionButton
|
role: "displayName";
|
||||||
color: 2 // Red
|
title: table.rowCount + (table.rowCount === 1 ? " NAME" : " NAMES");
|
||||||
visible: isButton
|
width: nameCardWidth;
|
||||||
anchors.centerIn: parent
|
movable: false;
|
||||||
width: 32
|
resizable: false;
|
||||||
height: 32
|
}
|
||||||
onClicked: {
|
TableViewColumn {
|
||||||
Users[styleData.role](model.sessionId)
|
role: "ignore";
|
||||||
UserActivityLogger["palAction"](styleData.role, model.sessionId)
|
title: "IGNORE";
|
||||||
if (styleData.role === "kick") {
|
width: actionButtonWidth;
|
||||||
userModelData.splice(model.userIndex, 1)
|
movable: false;
|
||||||
userModel.remove(model.userIndex) // after changing userModelData, b/c ListModel can frob the data
|
resizable: false;
|
||||||
}
|
}
|
||||||
}
|
TableViewColumn {
|
||||||
// muted/error glyphs
|
visible: iAmAdmin;
|
||||||
HiFiGlyphs {
|
role: "mute";
|
||||||
text: (styleData.role === "kick") ? hifi.glyphs.error : hifi.glyphs.muted
|
title: "SILENCE";
|
||||||
|
width: actionButtonWidth;
|
||||||
|
movable: false;
|
||||||
|
resizable: false;
|
||||||
|
}
|
||||||
|
TableViewColumn {
|
||||||
|
visible: iAmAdmin;
|
||||||
|
role: "kick";
|
||||||
|
title: "BAN";
|
||||||
|
width: actionButtonWidth;
|
||||||
|
movable: false;
|
||||||
|
resizable: false;
|
||||||
|
}
|
||||||
|
model: ListModel {
|
||||||
|
id: userModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This Rectangle refers to each Row in the table.
|
||||||
|
rowDelegate: Rectangle { // The only way I know to specify a row height.
|
||||||
|
// Size
|
||||||
|
height: styleData.selected ? rowHeight : rowHeight - 15;
|
||||||
|
color: styleData.selected
|
||||||
|
? hifi.colors.orangeHighlight
|
||||||
|
: styleData.alternate ? hifi.colors.tableRowLightEven : hifi.colors.tableRowLightOdd;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This Item refers to the contents of each Cell
|
||||||
|
itemDelegate: Item {
|
||||||
|
id: itemCell;
|
||||||
|
property bool isCheckBox: styleData.role === "personalMute" || styleData.role === "ignore";
|
||||||
|
property bool isButton: styleData.role === "mute" || styleData.role === "kick";
|
||||||
|
property bool isAvgAudio: styleData.role === "avgAudioLevel";
|
||||||
|
|
||||||
|
// This NameCard refers to the cell that contains an avatar's
|
||||||
|
// DisplayName and UserName
|
||||||
|
NameCard {
|
||||||
|
id: nameCard;
|
||||||
|
// Properties
|
||||||
|
displayName: styleData.value;
|
||||||
|
userName: model ? model.userName : "";
|
||||||
|
audioLevel: model ? model.audioLevel : 0.0;
|
||||||
|
avgAudioLevel: model ? model.avgAudioLevel : 0.0;
|
||||||
|
visible: !isCheckBox && !isButton && !isAvgAudio;
|
||||||
|
uuid: model ? model.sessionId : "";
|
||||||
|
selected: styleData.selected;
|
||||||
|
isAdmin: model && model.admin;
|
||||||
// Size
|
// Size
|
||||||
size: parent.height*1.3
|
width: nameCardWidth;
|
||||||
|
height: parent.height;
|
||||||
// Anchors
|
// Anchors
|
||||||
anchors.fill: parent
|
anchors.left: parent.left;
|
||||||
// Style
|
}
|
||||||
horizontalAlignment: Text.AlignHCenter
|
HifiControls.GlyphButton {
|
||||||
color: enabled ? hifi.buttons.textColor[actionButton.color]
|
function getGlyph() {
|
||||||
: hifi.buttons.disabledTextColor[actionButton.colorScheme]
|
var fileName = "vol_";
|
||||||
|
if (model && model.personalMute) {
|
||||||
|
fileName += "x_";
|
||||||
|
}
|
||||||
|
fileName += (4.0*(model ? model.avgAudioLevel : 0.0)).toFixed(0);
|
||||||
|
return hifi.glyphs[fileName];
|
||||||
|
}
|
||||||
|
id: avgAudioVolume;
|
||||||
|
visible: isAvgAudio;
|
||||||
|
glyph: getGlyph();
|
||||||
|
width: 32;
|
||||||
|
size: height;
|
||||||
|
anchors.verticalCenter: parent.verticalCenter;
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter;
|
||||||
|
onClicked: {
|
||||||
|
// cannot change mute status when ignoring
|
||||||
|
if (!model["ignore"]) {
|
||||||
|
var newValue = !model["personalMute"];
|
||||||
|
userModel.setProperty(model.userIndex, "personalMute", newValue);
|
||||||
|
userModelData[model.userIndex]["personalMute"] = newValue; // Defensive programming
|
||||||
|
Users["personalMute"](model.sessionId, newValue);
|
||||||
|
UserActivityLogger["palAction"](newValue ? "personalMute" : "un-personalMute", model.sessionId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This CheckBox belongs in the columns that contain the stateful action buttons ("Mute" & "Ignore" for now)
|
||||||
|
// KNOWN BUG with the Checkboxes: When clicking in the center of the sorting header, the checkbox
|
||||||
|
// will appear in the "hovered" state. Hovering over the checkbox will fix it.
|
||||||
|
// Clicking on the sides of the sorting header doesn't cause this problem.
|
||||||
|
// I'm guessing this is a QT bug and not anything I can fix. I spent too long trying to work around it...
|
||||||
|
// I'm just going to leave the minor visual bug in.
|
||||||
|
HifiControls.CheckBox {
|
||||||
|
id: actionCheckBox;
|
||||||
|
visible: isCheckBox;
|
||||||
|
anchors.centerIn: parent;
|
||||||
|
checked: model ? model[styleData.role] : false;
|
||||||
|
// If this is a "Personal Mute" checkbox, disable the checkbox if the "Ignore" checkbox is checked.
|
||||||
|
enabled: !(styleData.role === "personalMute" && (model ? model["ignore"] : true));
|
||||||
|
boxSize: 24;
|
||||||
|
onClicked: {
|
||||||
|
var newValue = !model[styleData.role];
|
||||||
|
userModel.setProperty(model.userIndex, styleData.role, newValue);
|
||||||
|
userModelData[model.userIndex][styleData.role] = newValue; // Defensive programming
|
||||||
|
Users[styleData.role](model.sessionId, newValue);
|
||||||
|
UserActivityLogger["palAction"](newValue ? styleData.role : "un-" + styleData.role, model.sessionId);
|
||||||
|
if (styleData.role === "ignore") {
|
||||||
|
userModel.setProperty(model.userIndex, "personalMute", newValue);
|
||||||
|
userModelData[model.userIndex]["personalMute"] = newValue; // Defensive programming
|
||||||
|
if (newValue) {
|
||||||
|
ignored[model.sessionId] = userModelData[model.userIndex];
|
||||||
|
} else {
|
||||||
|
delete ignored[model.sessionId];
|
||||||
|
}
|
||||||
|
avgAudioVolume.glyph = avgAudioVolume.getGlyph();
|
||||||
|
}
|
||||||
|
// http://doc.qt.io/qt-5/qtqml-syntax-propertybinding.html#creating-property-bindings-from-javascript
|
||||||
|
// I'm using an explicit binding here because clicking a checkbox breaks the implicit binding as set by
|
||||||
|
// "checked:" statement above.
|
||||||
|
checked = Qt.binding(function() { return (model[styleData.role])});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This Button belongs in the columns that contain the stateless action buttons ("Silence" & "Ban" for now)
|
||||||
|
HifiControls.Button {
|
||||||
|
id: actionButton;
|
||||||
|
color: 2; // Red
|
||||||
|
visible: isButton;
|
||||||
|
anchors.centerIn: parent;
|
||||||
|
width: 32;
|
||||||
|
height: 32;
|
||||||
|
onClicked: {
|
||||||
|
Users[styleData.role](model.sessionId);
|
||||||
|
UserActivityLogger["palAction"](styleData.role, model.sessionId);
|
||||||
|
if (styleData.role === "kick") {
|
||||||
|
userModelData.splice(model.userIndex, 1);
|
||||||
|
userModel.remove(model.userIndex); // after changing userModelData, b/c ListModel can frob the data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// muted/error glyphs
|
||||||
|
HiFiGlyphs {
|
||||||
|
text: (styleData.role === "kick") ? hifi.glyphs.error : hifi.glyphs.muted;
|
||||||
|
// Size
|
||||||
|
size: parent.height*1.3;
|
||||||
|
// Anchors
|
||||||
|
anchors.fill: parent;
|
||||||
|
// Style
|
||||||
|
horizontalAlignment: Text.AlignHCenter;
|
||||||
|
color: enabled ? hifi.buttons.textColor[actionButton.color]
|
||||||
|
: hifi.buttons.disabledTextColor[actionButton.colorScheme];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Separator between user and admin functions
|
// Separator between user and admin functions
|
||||||
Rectangle {
|
Rectangle {
|
||||||
// Size
|
// Size
|
||||||
width: 2
|
width: 2;
|
||||||
height: table.height
|
height: table.height;
|
||||||
// Anchors
|
// Anchors
|
||||||
anchors.left: adminTab.left
|
anchors.left: adminTab.left;
|
||||||
anchors.top: table.top
|
anchors.top: table.top;
|
||||||
// Properties
|
// Properties
|
||||||
visible: iAmAdmin
|
visible: iAmAdmin;
|
||||||
color: hifi.colors.lightGrayText
|
color: hifi.colors.lightGrayText;
|
||||||
}
|
|
||||||
TextMetrics {
|
|
||||||
id: displayNameHeaderMetrics
|
|
||||||
text: displayNameHeader.title
|
|
||||||
// font: displayNameHeader.font // was this always undefined? giving error now...
|
|
||||||
}
|
|
||||||
// This Rectangle refers to the [?] popup button next to "NAMES"
|
|
||||||
Rectangle {
|
|
||||||
color: hifi.colors.tableBackgroundLight
|
|
||||||
width: 20
|
|
||||||
height: hifi.dimensions.tableHeaderHeight - 2
|
|
||||||
anchors.left: table.left
|
|
||||||
anchors.top: table.top
|
|
||||||
anchors.topMargin: 1
|
|
||||||
anchors.leftMargin: actionButtonWidth + nameCardWidth/2 + displayNameHeaderMetrics.width/2 + 6
|
|
||||||
RalewayRegular {
|
|
||||||
id: helpText
|
|
||||||
text: "[?]"
|
|
||||||
size: hifi.fontSizes.tableHeading + 2
|
|
||||||
font.capitalization: Font.AllUppercase
|
|
||||||
color: hifi.colors.darkGray
|
|
||||||
horizontalAlignment: Text.AlignHCenter
|
|
||||||
verticalAlignment: Text.AlignVCenter
|
|
||||||
anchors.fill: parent
|
|
||||||
}
|
}
|
||||||
MouseArea {
|
TextMetrics {
|
||||||
anchors.fill: parent
|
id: displayNameHeaderMetrics;
|
||||||
acceptedButtons: Qt.LeftButton
|
text: displayNameHeader.title;
|
||||||
hoverEnabled: true
|
// font: displayNameHeader.font // was this always undefined? giving error now...
|
||||||
onClicked: letterbox(hifi.glyphs.question,
|
|
||||||
"Display Names",
|
|
||||||
"Bold names in the list are <b>avatar display names</b>.<br>" +
|
|
||||||
"If a display name isn't set, a unique <b>session display name</b> is assigned." +
|
|
||||||
"<br><br>Administrators of this domain can also see the <b>username</b> or <b>machine ID</b> associated with each avatar present.")
|
|
||||||
onEntered: helpText.color = hifi.colors.baseGrayHighlight
|
|
||||||
onExited: helpText.color = hifi.colors.darkGray
|
|
||||||
}
|
}
|
||||||
}
|
// This Rectangle refers to the [?] popup button next to "NAMES"
|
||||||
// This Rectangle refers to the [?] popup button next to "ADMIN"
|
Rectangle {
|
||||||
Rectangle {
|
color: hifi.colors.tableBackgroundLight;
|
||||||
visible: iAmAdmin
|
width: 20;
|
||||||
color: adminTab.color
|
height: hifi.dimensions.tableHeaderHeight - 2;
|
||||||
width: 20
|
anchors.left: table.left;
|
||||||
height: 28
|
anchors.top: table.top;
|
||||||
anchors.right: adminTab.right
|
anchors.topMargin: 1;
|
||||||
anchors.rightMargin: 10 + hifi.dimensions.scrollbarBackgroundWidth
|
anchors.leftMargin: actionButtonWidth + nameCardWidth/2 + displayNameHeaderMetrics.width/2 + 6;
|
||||||
anchors.top: adminTab.top
|
RalewayRegular {
|
||||||
anchors.topMargin: 2
|
id: helpText;
|
||||||
RalewayRegular {
|
text: "[?]";
|
||||||
id: adminHelpText
|
size: hifi.fontSizes.tableHeading + 2;
|
||||||
text: "[?]"
|
font.capitalization: Font.AllUppercase;
|
||||||
size: hifi.fontSizes.tableHeading + 2
|
color: hifi.colors.darkGray;
|
||||||
font.capitalization: Font.AllUppercase
|
horizontalAlignment: Text.AlignHCenter;
|
||||||
color: hifi.colors.redHighlight
|
verticalAlignment: Text.AlignVCenter;
|
||||||
horizontalAlignment: Text.AlignHCenter
|
anchors.fill: parent;
|
||||||
verticalAlignment: Text.AlignVCenter
|
}
|
||||||
anchors.fill: parent
|
MouseArea {
|
||||||
|
anchors.fill: parent;
|
||||||
|
acceptedButtons: Qt.LeftButton;
|
||||||
|
hoverEnabled: true;
|
||||||
|
onClicked: letterbox(hifi.glyphs.question,
|
||||||
|
"Display Names",
|
||||||
|
"Bold names in the list are <b>avatar display names</b>.<br>" +
|
||||||
|
"If a display name isn't set, a unique <b>session display name</b> is assigned." +
|
||||||
|
"<br><br>Administrators of this domain can also see the <b>username</b> or <b>machine ID</b> associated with each avatar present.");
|
||||||
|
onEntered: helpText.color = hifi.colors.baseGrayHighlight;
|
||||||
|
onExited: helpText.color = hifi.colors.darkGray;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
MouseArea {
|
// This Rectangle refers to the [?] popup button next to "ADMIN"
|
||||||
anchors.fill: parent
|
Rectangle {
|
||||||
acceptedButtons: Qt.LeftButton
|
visible: iAmAdmin;
|
||||||
hoverEnabled: true
|
color: adminTab.color;
|
||||||
onClicked: letterbox(hifi.glyphs.question,
|
width: 20;
|
||||||
"Admin Actions",
|
height: 28;
|
||||||
"<b>Silence</b> mutes a user's microphone. Silenced users can unmute themselves by clicking "UNMUTE" on their toolbar.<br><br>" +
|
anchors.right: adminTab.right;
|
||||||
"<b>Ban</b> removes a user from this domain and prevents them from returning. Admins can un-ban users from the Sandbox Domain Settings page.")
|
anchors.rightMargin: 10 + hifi.dimensions.scrollbarBackgroundWidth;
|
||||||
onEntered: adminHelpText.color = "#94132e"
|
anchors.top: adminTab.top;
|
||||||
onExited: adminHelpText.color = hifi.colors.redHighlight
|
anchors.topMargin: 2;
|
||||||
|
RalewayRegular {
|
||||||
|
id: adminHelpText;
|
||||||
|
text: "[?]";
|
||||||
|
size: hifi.fontSizes.tableHeading + 2;
|
||||||
|
font.capitalization: Font.AllUppercase;
|
||||||
|
color: hifi.colors.redHighlight;
|
||||||
|
horizontalAlignment: Text.AlignHCenter;
|
||||||
|
verticalAlignment: Text.AlignVCenter;
|
||||||
|
anchors.fill: parent;
|
||||||
|
}
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent;
|
||||||
|
acceptedButtons: Qt.LeftButton;
|
||||||
|
hoverEnabled: true;
|
||||||
|
onClicked: letterbox(hifi.glyphs.question,
|
||||||
|
"Admin Actions",
|
||||||
|
"<b>Silence</b> mutes a user's microphone. Silenced users can unmute themselves by clicking "UNMUTE" on their toolbar.<br><br>" +
|
||||||
|
"<b>Ban</b> removes a user from this domain and prevents them from returning. Admins can un-ban users from the Sandbox Domain Settings page.");
|
||||||
|
onEntered: adminHelpText.color = "#94132e";
|
||||||
|
onExited: adminHelpText.color = hifi.colors.redHighlight;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
HifiControls.Keyboard {
|
HifiControls.Keyboard {
|
||||||
id: keyboard
|
id: keyboard;
|
||||||
raised: myCard.currentlyEditingDisplayName && HMD.active
|
raised: myCard.currentlyEditingDisplayName && HMD.active;
|
||||||
numeric: parent.punctuationMode
|
numeric: parent.punctuationMode;
|
||||||
anchors {
|
anchors {
|
||||||
bottom: parent.bottom
|
bottom: parent.bottom;
|
||||||
left: parent.left
|
left: parent.left;
|
||||||
right: parent.right
|
right: parent.right;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Timer used when selecting table rows that aren't yet present in the model
|
// Timer used when selecting table rows that aren't yet present in the model
|
||||||
// (i.e. when selecting avatars using edit.js or sphere overlays)
|
// (i.e. when selecting avatars using edit.js or sphere overlays)
|
||||||
Timer {
|
Timer {
|
||||||
property bool selected // Selected or deselected?
|
property bool selected; // Selected or deselected?
|
||||||
property int userIndex // The userIndex of the avatar we want to select
|
property int userIndex; // The userIndex of the avatar we want to select
|
||||||
id: selectionTimer
|
id: selectionTimer;
|
||||||
onTriggered: {
|
onTriggered: {
|
||||||
if (selected) {
|
if (selected) {
|
||||||
table.selection.clear(); // for now, no multi-select
|
table.selection.clear(); // for now, no multi-select
|
||||||
|
@ -610,7 +611,8 @@ Rectangle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function sortModel() {
|
function sortModel() {
|
||||||
var sortProperty = table.getColumn(table.sortIndicatorColumn).role;
|
var column = table.getColumn(table.sortIndicatorColumn);
|
||||||
|
var sortProperty = column ? column.role : "displayName";
|
||||||
var before = (table.sortIndicatorOrder === Qt.AscendingOrder) ? -1 : 1;
|
var before = (table.sortIndicatorOrder === Qt.AscendingOrder) ? -1 : 1;
|
||||||
var after = -1 * before;
|
var after = -1 * before;
|
||||||
userModelData.sort(function (a, b) {
|
userModelData.sort(function (a, b) {
|
||||||
|
@ -645,7 +647,7 @@ Rectangle {
|
||||||
pal.sendToScript({method: 'selected', params: userIds});
|
pal.sendToScript({method: 'selected', params: userIds});
|
||||||
}
|
}
|
||||||
Connections {
|
Connections {
|
||||||
target: table.selection
|
target: table.selection;
|
||||||
onSelectionChanged: pal.noticeSelection()
|
onSelectionChanged: pal.noticeSelection();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue