Merge from master

This commit is contained in:
Olivier Prat 2018-11-08 09:14:42 +01:00
commit 9d5dcec0a0
550 changed files with 15682 additions and 16323 deletions

View file

@ -66,7 +66,7 @@ if (ANDROID)
set(GLES_OPTION ON)
set(PLATFORM_QT_COMPONENTS AndroidExtras WebView)
else ()
set(PLATFORM_QT_COMPONENTS WebEngine WebEngineWidgets)
set(PLATFORM_QT_COMPONENTS WebEngine)
endif ()
if (USE_GLES AND (NOT ANDROID))

View file

@ -541,7 +541,7 @@ void AvatarMixer::handleRequestsDomainListDataPacket(QSharedPointer<ReceivedMess
// ...For those nodes, reset the lastBroadcastTime to 0
// so that the AvatarMixer will send Identity data to us
[&](const SharedNodePointer& node) {
nodeData->setLastBroadcastTime(node->getUUID(), 0);
nodeData->setLastBroadcastTime(node->getLocalID(), 0);
nodeData->resetSentTraitData(node->getLocalID());
}
);
@ -565,7 +565,8 @@ void AvatarMixer::handleAvatarIdentityPacket(QSharedPointer<ReceivedMessage> mes
// parse the identity packet and update the change timestamp if appropriate
bool identityChanged = false;
bool displayNameChanged = false;
avatar.processAvatarIdentity(message->getMessage(), identityChanged, displayNameChanged);
QDataStream avatarIdentityStream(message->getMessage());
avatar.processAvatarIdentity(avatarIdentityStream, identityChanged, displayNameChanged);
if (identityChanged) {
QMutexLocker nodeDataLocker(&nodeData->getMutex());
@ -637,7 +638,7 @@ void AvatarMixer::handleNodeIgnoreRequestPacket(QSharedPointer<ReceivedMessage>
// Reset the lastBroadcastTime for the ignored avatar to 0
// so the AvatarMixer knows it'll have to send identity data about the ignored avatar
// to the ignorer if the ignorer unignores.
nodeData->setLastBroadcastTime(ignoredUUID, 0);
nodeData->setLastBroadcastTime(ignoredNode->getLocalID(), 0);
nodeData->resetSentTraitData(ignoredNode->getLocalID());
}
@ -647,7 +648,7 @@ void AvatarMixer::handleNodeIgnoreRequestPacket(QSharedPointer<ReceivedMessage>
// to the ignored if the ignorer unignores.
AvatarMixerClientData* ignoredNodeData = reinterpret_cast<AvatarMixerClientData*>(ignoredNode->getLinkedData());
if (ignoredNodeData) {
ignoredNodeData->setLastBroadcastTime(senderNode->getUUID(), 0);
ignoredNodeData->setLastBroadcastTime(senderNode->getLocalID(), 0);
ignoredNodeData->resetSentTraitData(senderNode->getLocalID());
}
}

View file

@ -26,20 +26,20 @@ AvatarMixerClientData::AvatarMixerClientData(const QUuid& nodeID, Node::LocalID
_avatar->setID(nodeID);
}
uint64_t AvatarMixerClientData::getLastOtherAvatarEncodeTime(QUuid otherAvatar) const {
std::unordered_map<QUuid, uint64_t>::const_iterator itr = _lastOtherAvatarEncodeTime.find(otherAvatar);
uint64_t AvatarMixerClientData::getLastOtherAvatarEncodeTime(NLPacket::LocalID otherAvatar) const {
const auto itr = _lastOtherAvatarEncodeTime.find(otherAvatar);
if (itr != _lastOtherAvatarEncodeTime.end()) {
return itr->second;
}
return 0;
}
void AvatarMixerClientData::setLastOtherAvatarEncodeTime(const QUuid& otherAvatar, uint64_t time) {
std::unordered_map<QUuid, uint64_t>::iterator itr = _lastOtherAvatarEncodeTime.find(otherAvatar);
void AvatarMixerClientData::setLastOtherAvatarEncodeTime(NLPacket::LocalID otherAvatar, uint64_t time) {
auto itr = _lastOtherAvatarEncodeTime.find(otherAvatar);
if (itr != _lastOtherAvatarEncodeTime.end()) {
itr->second = time;
} else {
_lastOtherAvatarEncodeTime.emplace(std::pair<QUuid, uint64_t>(otherAvatar, time));
_lastOtherAvatarEncodeTime.emplace(std::pair<NLPacket::LocalID, uint64_t>(otherAvatar, time));
}
}
@ -220,7 +220,7 @@ void AvatarMixerClientData::checkSkeletonURLAgainstWhitelist(const SlaveSharedDa
}
}
uint64_t AvatarMixerClientData::getLastBroadcastTime(const QUuid& nodeUUID) const {
uint64_t AvatarMixerClientData::getLastBroadcastTime(NLPacket::LocalID nodeUUID) const {
// return the matching PacketSequenceNumber, or the default if we don't have it
auto nodeMatch = _lastBroadcastTimes.find(nodeUUID);
if (nodeMatch != _lastBroadcastTimes.end()) {
@ -229,9 +229,9 @@ uint64_t AvatarMixerClientData::getLastBroadcastTime(const QUuid& nodeUUID) cons
return 0;
}
uint16_t AvatarMixerClientData::getLastBroadcastSequenceNumber(const QUuid& nodeUUID) const {
uint16_t AvatarMixerClientData::getLastBroadcastSequenceNumber(NLPacket::LocalID nodeID) const {
// return the matching PacketSequenceNumber, or the default if we don't have it
auto nodeMatch = _lastBroadcastSequenceNumbers.find(nodeUUID);
auto nodeMatch = _lastBroadcastSequenceNumbers.find(nodeID);
if (nodeMatch != _lastBroadcastSequenceNumbers.end()) {
return nodeMatch->second;
}
@ -252,7 +252,7 @@ void AvatarMixerClientData::ignoreOther(const Node* self, const Node* other) {
} else {
killPacket->writePrimitive(KillAvatarReason::YourAvatarEnteredTheirBubble);
}
setLastBroadcastTime(other->getUUID(), 0);
setLastBroadcastTime(other->getLocalID(), 0);
resetSentTraitData(other->getLocalID());
@ -331,9 +331,9 @@ AvatarMixerClientData::TraitsCheckTimestamp AvatarMixerClientData::getLastOtherA
}
}
void AvatarMixerClientData::cleanupKilledNode(const QUuid& nodeUUID, Node::LocalID nodeLocalID) {
removeLastBroadcastSequenceNumber(nodeUUID);
removeLastBroadcastTime(nodeUUID);
void AvatarMixerClientData::cleanupKilledNode(const QUuid&, Node::LocalID nodeLocalID) {
removeLastBroadcastSequenceNumber(nodeLocalID);
removeLastBroadcastTime(nodeLocalID);
_lastSentTraitsTimestamps.erase(nodeLocalID);
_sentTraitVersions.erase(nodeLocalID);
}

View file

@ -49,17 +49,16 @@ public:
const AvatarData* getConstAvatarData() const { return _avatar.get(); }
AvatarSharedPointer getAvatarSharedPointer() const { return _avatar; }
uint16_t getLastBroadcastSequenceNumber(NLPacket::LocalID nodeID) const;
void setLastBroadcastSequenceNumber(NLPacket::LocalID nodeID, uint16_t sequenceNumber)
{ _lastBroadcastSequenceNumbers[nodeID] = sequenceNumber; }
Q_INVOKABLE void removeLastBroadcastSequenceNumber(NLPacket::LocalID nodeID) { _lastBroadcastSequenceNumbers.erase(nodeID); }
bool isIgnoreRadiusEnabled() const { return _isIgnoreRadiusEnabled; }
void setIsIgnoreRadiusEnabled(bool enabled) { _isIgnoreRadiusEnabled = enabled; }
uint16_t getLastBroadcastSequenceNumber(const QUuid& nodeUUID) const;
void setLastBroadcastSequenceNumber(const QUuid& nodeUUID, uint16_t sequenceNumber)
{ _lastBroadcastSequenceNumbers[nodeUUID] = sequenceNumber; }
Q_INVOKABLE void removeLastBroadcastSequenceNumber(const QUuid& nodeUUID) { _lastBroadcastSequenceNumbers.erase(nodeUUID); }
uint64_t getLastBroadcastTime(const QUuid& nodeUUID) const;
void setLastBroadcastTime(const QUuid& nodeUUID, uint64_t broadcastTime) { _lastBroadcastTimes[nodeUUID] = broadcastTime; }
Q_INVOKABLE void removeLastBroadcastTime(const QUuid& nodeUUID) { _lastBroadcastTimes.erase(nodeUUID); }
uint64_t getLastBroadcastTime(NLPacket::LocalID nodeUUID) const;
void setLastBroadcastTime(NLPacket::LocalID nodeUUID, uint64_t broadcastTime) { _lastBroadcastTimes[nodeUUID] = broadcastTime; }
Q_INVOKABLE void removeLastBroadcastTime(NLPacket::LocalID nodeUUID) { _lastBroadcastTimes.erase(nodeUUID); }
Q_INVOKABLE void cleanupKilledNode(const QUuid& nodeUUID, Node::LocalID nodeLocalID);
@ -93,7 +92,7 @@ public:
void loadJSONStats(QJsonObject& jsonObject) const;
glm::vec3 getPosition() const { return _avatar ? _avatar->getWorldPosition() : glm::vec3(0); }
glm::vec3 getPosition() const { return _avatar ? _avatar->getClientGlobalPosition() : glm::vec3(0); }
bool isRadiusIgnoring(const QUuid& other) const;
void addToRadiusIgnoringSet(const QUuid& other);
void removeFromRadiusIgnoringSet(const QUuid& other);
@ -114,10 +113,10 @@ public:
const ConicalViewFrustums& getViewFrustums() const { return _currentViewFrustums; }
uint64_t getLastOtherAvatarEncodeTime(QUuid otherAvatar) const;
void setLastOtherAvatarEncodeTime(const QUuid& otherAvatar, uint64_t time);
uint64_t getLastOtherAvatarEncodeTime(NLPacket::LocalID otherAvatar) const;
void setLastOtherAvatarEncodeTime(NLPacket::LocalID otherAvatar, uint64_t time);
QVector<JointData>& getLastOtherAvatarSentJoints(QUuid otherAvatar) { return _lastOtherAvatarSentJoints[otherAvatar]; }
QVector<JointData>& getLastOtherAvatarSentJoints(NLPacket::LocalID otherAvatar) { return _lastOtherAvatarSentJoints[otherAvatar]; }
void queuePacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer node);
int processPackets(const SlaveSharedData& slaveSharedData); // returns number of packets processed
@ -150,13 +149,13 @@ private:
AvatarSharedPointer _avatar { new AvatarData() };
uint16_t _lastReceivedSequenceNumber { 0 };
std::unordered_map<QUuid, uint16_t> _lastBroadcastSequenceNumbers;
std::unordered_map<QUuid, uint64_t> _lastBroadcastTimes;
std::unordered_map<NLPacket::LocalID, uint16_t> _lastBroadcastSequenceNumbers;
std::unordered_map<NLPacket::LocalID, uint64_t> _lastBroadcastTimes;
// this is a map of the last time we encoded an "other" avatar for
// sending to "this" node
std::unordered_map<QUuid, uint64_t> _lastOtherAvatarEncodeTime;
std::unordered_map<QUuid, QVector<JointData>> _lastOtherAvatarSentJoints;
std::unordered_map<NLPacket::LocalID, uint64_t> _lastOtherAvatarEncodeTime;
std::unordered_map<NLPacket::LocalID, QVector<JointData>> _lastOtherAvatarSentJoints;
uint64_t _identityChangeTimestamp;
bool _avatarSessionDisplayNameMustChange{ true };

View file

@ -68,13 +68,11 @@ void AvatarMixerSlave::processIncomingPackets(const SharedNodePointer& node) {
_stats.processIncomingPacketsElapsedTime += (end - start);
}
int AvatarMixerSlave::sendIdentityPacket(const AvatarMixerClientData* nodeData, const SharedNodePointer& destinationNode) {
if (destinationNode->getType() == NodeType::Agent && !destinationNode->isUpstream()) {
int AvatarMixerSlave::sendIdentityPacket(NLPacketList& packetList, const AvatarMixerClientData* nodeData, const Node& destinationNode) {
if (destinationNode.getType() == NodeType::Agent && !destinationNode.isUpstream()) {
QByteArray individualData = nodeData->getConstAvatarData()->identityByteArray();
individualData.replace(0, NUM_BYTES_RFC4122_UUID, nodeData->getNodeID().toRfc4122()); // FIXME, this looks suspicious
auto identityPackets = NLPacketList::create(PacketType::AvatarIdentity, QByteArray(), true, true);
identityPackets->write(individualData);
DependencyManager::get<NodeList>()->sendPacketList(std::move(identityPackets), *destinationNode);
packetList.write(individualData);
_stats.numIdentityPackets++;
return individualData.size();
} else {
@ -247,12 +245,12 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node)
// reset the internal state for correct random number distribution
distribution.reset();
// Estimate number to sort on number sent last frame (with min. of 20).
const int numToSendEst = std::max(int(nodeData->getNumAvatarsSentLastFrame() * 2.5f), 20);
// reset the number of sent avatars
nodeData->resetNumAvatarsSentLastFrame();
// keep a counter of the number of considered avatars
int numOtherAvatars = 0;
// keep track of outbound data rate specifically for avatar data
int numAvatarDataBytes = 0;
int identityBytesSent = 0;
@ -261,7 +259,6 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node)
// max number of avatarBytes per frame
int maxAvatarBytesPerFrame = int(_maxKbpsPerNode * BYTES_PER_KILOBIT / AVATAR_MIXER_BROADCAST_FRAMES_PER_SECOND);
// keep track of the number of other avatars held back in this frame
int numAvatarsHeldBack = 0;
@ -279,10 +276,6 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node)
int minimumBytesPerAvatar = PALIsOpen ? AvatarDataPacket::AVATAR_HAS_FLAGS_SIZE + NUM_BYTES_RFC4122_UUID +
sizeof(AvatarDataPacket::AvatarGlobalPosition) + sizeof(AvatarDataPacket::AudioLoudness) : 0;
// setup a PacketList for the avatarPackets
auto avatarPacketList = NLPacketList::create(PacketType::BulkAvatarData);
static auto maxAvatarDataBytes = avatarPacketList->getMaxSegmentSize() - NUM_BYTES_RFC4122_UUID;
// compute node bounding box
const float MY_AVATAR_BUBBLE_EXPANSION_FACTOR = 4.0f; // magic number determined emperically
AABox nodeBox = computeBubbleBox(avatar, MY_AVATAR_BUBBLE_EXPANSION_FACTOR);
@ -350,8 +343,7 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node)
// Don't bother with these checks if the other avatar has their bubble enabled and we're gettingAnyIgnored
if (nodeData->isIgnoreRadiusEnabled() || (avatarClientNodeData->isIgnoreRadiusEnabled() && !getsAnyIgnored)) {
// Perform the collision check between the two bounding boxes
const float OTHER_AVATAR_BUBBLE_EXPANSION_FACTOR = 2.4f; // magic number determined empirically
AABox otherNodeBox = computeBubbleBox(avatarClientNodeData->getAvatar(), OTHER_AVATAR_BUBBLE_EXPANSION_FACTOR);
AABox otherNodeBox = avatarClientNodeData->getAvatar().getDefaultBubbleBox();
if (nodeBox.touches(otherNodeBox)) {
nodeData->ignoreOther(destinationNode, avatarNode);
shouldIgnore = !getsAnyIgnored;
@ -364,7 +356,7 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node)
}
if (!shouldIgnore) {
AvatarDataSequenceNumber lastSeqToReceiver = nodeData->getLastBroadcastSequenceNumber(avatarNode->getUUID());
AvatarDataSequenceNumber lastSeqToReceiver = nodeData->getLastBroadcastSequenceNumber(avatarNode->getLocalID());
AvatarDataSequenceNumber lastSeqFromSender = avatarClientNodeData->getLastReceivedSequenceNumber();
// FIXME - This code does appear to be working. But it seems brittle.
@ -396,7 +388,7 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node)
if (!shouldIgnore) {
// sort this one for later
const AvatarData* avatarNodeData = avatarClientNodeData->getConstAvatarData();
auto lastEncodeTime = nodeData->getLastOtherAvatarEncodeTime(avatarNodeData->getSessionUUID());
auto lastEncodeTime = nodeData->getLastOtherAvatarEncodeTime(avatarNode->getLocalID());
sortedAvatars.push(SortableAvatar(avatarNodeData, avatarNode, lastEncodeTime));
}
@ -406,8 +398,13 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node)
int remainingAvatars = (int)sortedAvatars.size();
auto traitsPacketList = NLPacketList::create(PacketType::BulkAvatarTraits, QByteArray(), true, true);
auto avatarPacket = NLPacket::create(PacketType::BulkAvatarData);
const int avatarPacketCapacity = avatarPacket->getPayloadCapacity();
int avatarSpaceAvailable = avatarPacketCapacity;
int numPacketsSent = 0;
auto identityPacketList = NLPacketList::create(PacketType::AvatarIdentity, QByteArray(), true, true);
const auto& sortedAvatarVector = sortedAvatars.getSortedVector();
const auto& sortedAvatarVector = sortedAvatars.getSortedVector(numToSendEst);
for (const auto& sortedAvatar : sortedAvatarVector) {
const Node* otherNode = sortedAvatar.getNode();
auto lastEncodeForOther = sortedAvatar.getTimestamp();
@ -432,21 +429,9 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node)
auto startAvatarDataPacking = chrono::high_resolution_clock::now();
++numOtherAvatars;
const AvatarMixerClientData* otherNodeData = reinterpret_cast<const AvatarMixerClientData*>(otherNode->getLinkedData());
const AvatarData* otherAvatar = otherNodeData->getConstAvatarData();
// If the time that the mixer sent AVATAR DATA about Avatar B to Avatar A is BEFORE OR EQUAL TO
// the time that Avatar B flagged an IDENTITY DATA change, send IDENTITY DATA about Avatar B to Avatar A.
if (otherAvatar->hasProcessedFirstIdentity()
&& nodeData->getLastBroadcastTime(otherNode->getUUID()) <= otherNodeData->getIdentityChangeTimestamp()) {
identityBytesSent += sendIdentityPacket(otherNodeData, node);
// remember the last time we sent identity details about this other node to the receiver
nodeData->setLastBroadcastTime(otherNode->getUUID(), usecTimestampNow());
}
// Typically all out-of-view avatars but such avatars' priorities will rise with time:
bool isLowerPriority = sortedAvatar.getPriority() <= OUT_OF_VIEW_THRESHOLD;
@ -456,71 +441,56 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node)
} else if (!overBudget) {
detail = distribution(generator) < AVATAR_SEND_FULL_UPDATE_RATIO ? AvatarData::SendAllData : AvatarData::CullSmallData;
nodeData->incrementAvatarInView();
}
bool includeThisAvatar = true;
QVector<JointData>& lastSentJointsForOther = nodeData->getLastOtherAvatarSentJoints(otherNode->getUUID());
// If the time that the mixer sent AVATAR DATA about Avatar B to Avatar A is BEFORE OR EQUAL TO
// the time that Avatar B flagged an IDENTITY DATA change, send IDENTITY DATA about Avatar B to Avatar A.
if (otherAvatar->hasProcessedFirstIdentity()
&& nodeData->getLastBroadcastTime(otherNode->getLocalID()) <= otherNodeData->getIdentityChangeTimestamp()) {
identityBytesSent += sendIdentityPacket(*identityPacketList, otherNodeData, *destinationNode);
lastSentJointsForOther.resize(otherAvatar->getJointCount());
bool distanceAdjust = true;
glm::vec3 viewerPosition = myPosition;
AvatarDataPacket::HasFlags hasFlagsOut; // the result of the toByteArray
bool dropFaceTracking = false;
auto startSerialize = chrono::high_resolution_clock::now();
QByteArray bytes = otherAvatar->toByteArray(detail, lastEncodeForOther, lastSentJointsForOther,
hasFlagsOut, dropFaceTracking, distanceAdjust, viewerPosition,
&lastSentJointsForOther);
auto endSerialize = chrono::high_resolution_clock::now();
_stats.toByteArrayElapsedTime +=
(quint64) chrono::duration_cast<chrono::microseconds>(endSerialize - startSerialize).count();
if (bytes.size() > maxAvatarDataBytes) {
qCWarning(avatars) << "otherAvatar.toByteArray() for" << otherNode->getUUID()
<< "resulted in very large buffer of" << bytes.size() << "bytes - dropping facial data";
dropFaceTracking = true; // first try dropping the facial data
bytes = otherAvatar->toByteArray(detail, lastEncodeForOther, lastSentJointsForOther,
hasFlagsOut, dropFaceTracking, distanceAdjust, viewerPosition, &lastSentJointsForOther);
if (bytes.size() > maxAvatarDataBytes) {
qCWarning(avatars) << "otherAvatar.toByteArray() for" << otherNode->getUUID()
<< "without facial data resulted in very large buffer of" << bytes.size()
<< "bytes - reducing to MinimumData";
bytes = otherAvatar->toByteArray(AvatarData::MinimumData, lastEncodeForOther, lastSentJointsForOther,
hasFlagsOut, dropFaceTracking, distanceAdjust, viewerPosition, &lastSentJointsForOther);
if (bytes.size() > maxAvatarDataBytes) {
qCWarning(avatars) << "otherAvatar.toByteArray() for" << otherNode->getUUID()
<< "MinimumData resulted in very large buffer of" << bytes.size()
<< "bytes - refusing to send avatar";
includeThisAvatar = false;
}
// remember the last time we sent identity details about this other node to the receiver
nodeData->setLastBroadcastTime(otherNode->getLocalID(), usecTimestampNow());
}
}
if (includeThisAvatar) {
// start a new segment in the PacketList for this avatar
avatarPacketList->startSegment();
numAvatarDataBytes += avatarPacketList->write(otherNode->getUUID().toRfc4122());
numAvatarDataBytes += avatarPacketList->write(bytes);
avatarPacketList->endSegment();
QVector<JointData>& lastSentJointsForOther = nodeData->getLastOtherAvatarSentJoints(otherNode->getLocalID());
if (detail != AvatarData::NoData) {
_stats.numOthersIncluded++;
const bool distanceAdjust = true;
const bool dropFaceTracking = false;
AvatarDataPacket::SendStatus sendStatus;
sendStatus.sendUUID = true;
// increment the number of avatars sent to this reciever
nodeData->incrementNumAvatarsSentLastFrame();
do {
auto startSerialize = chrono::high_resolution_clock::now();
QByteArray bytes = otherAvatar->toByteArray(detail, lastEncodeForOther, lastSentJointsForOther,
sendStatus, dropFaceTracking, distanceAdjust, myPosition,
&lastSentJointsForOther, avatarSpaceAvailable);
auto endSerialize = chrono::high_resolution_clock::now();
_stats.toByteArrayElapsedTime +=
(quint64)chrono::duration_cast<chrono::microseconds>(endSerialize - startSerialize).count();
// set the last sent sequence number for this sender on the receiver
nodeData->setLastBroadcastSequenceNumber(otherNode->getUUID(),
otherNodeData->getLastReceivedSequenceNumber());
nodeData->setLastOtherAvatarEncodeTime(otherNode->getUUID(), usecTimestampNow());
avatarPacket->write(bytes);
avatarSpaceAvailable -= bytes.size();
numAvatarDataBytes += bytes.size();
if (!sendStatus || avatarSpaceAvailable < (int)AvatarDataPacket::MIN_BULK_PACKET_SIZE) {
// Weren't able to fit everything.
nodeList->sendPacket(std::move(avatarPacket), *destinationNode);
++numPacketsSent;
avatarPacket = NLPacket::create(PacketType::BulkAvatarData);
avatarSpaceAvailable = avatarPacketCapacity;
}
} else {
// TODO? this avatar is not included now, and will probably not be included next frame.
// It would be nice if we could tweak its future sort priority to put it at the back of the list.
} while (!sendStatus);
if (detail != AvatarData::NoData) {
_stats.numOthersIncluded++;
// increment the number of avatars sent to this receiver
nodeData->incrementNumAvatarsSentLastFrame();
// set the last sent sequence number for this sender on the receiver
nodeData->setLastBroadcastSequenceNumber(otherNode->getLocalID(),
otherNodeData->getLastReceivedSequenceNumber());
nodeData->setLastOtherAvatarEncodeTime(otherNode->getLocalID(), usecTimestampNow());
}
auto endAvatarDataPacking = chrono::high_resolution_clock::now();
@ -532,17 +502,21 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node)
remainingAvatars--;
}
if (nodeData->getNumAvatarsSentLastFrame() > numToSendEst) {
qCWarning(avatars) << "More avatars sent than upper estimate" << nodeData->getNumAvatarsSentLastFrame()
<< " / " << numToSendEst;
}
quint64 startPacketSending = usecTimestampNow();
// close the current packet so that we're always sending something
avatarPacketList->closeCurrentPacket(true);
if (avatarPacket->getPayloadSize() != 0) {
nodeList->sendPacket(std::move(avatarPacket), *destinationNode);
++numPacketsSent;
}
_stats.numPacketsSent += (int)avatarPacketList->getNumPackets();
_stats.numPacketsSent += numPacketsSent;
_stats.numBytesSent += numAvatarDataBytes;
// send the avatar data PacketList
nodeList->sendPacketList(std::move(avatarPacketList), *destinationNode);
// record the bytes sent for other avatar data in the AvatarMixerClientData
nodeData->recordSentAvatarData(numAvatarDataBytes);
@ -554,6 +528,12 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node)
nodeList->sendPacketList(std::move(traitsPacketList), *destinationNode);
}
// Send any AvatarIdentity packets:
identityPacketList->closeCurrentPacket();
if (identityBytesSent > 0) {
nodeList->sendPacketList(std::move(identityPacketList), *destinationNode);
}
// record the number of avatars held back this frame
nodeData->recordNumOtherAvatarStarves(numAvatarsHeldBack);
nodeData->recordNumOtherAvatarSkips(numAvatarsWithSkippedFrames);
@ -599,20 +579,20 @@ void AvatarMixerSlave::broadcastAvatarDataToDownstreamMixer(const SharedNodePoin
// so we always send a full update for this avatar
quint64 start = usecTimestampNow();
AvatarDataPacket::HasFlags flagsOut;
AvatarDataPacket::SendStatus sendStatus;
QVector<JointData> emptyLastJointSendData { otherAvatar->getJointCount() };
QByteArray avatarByteArray = otherAvatar->toByteArray(AvatarData::SendAllData, 0, emptyLastJointSendData,
flagsOut, false, false, glm::vec3(0), nullptr);
sendStatus, false, false, glm::vec3(0), nullptr, 0);
quint64 end = usecTimestampNow();
_stats.toByteArrayElapsedTime += (end - start);
auto lastBroadcastTime = nodeData->getLastBroadcastTime(agentNode->getUUID());
auto lastBroadcastTime = nodeData->getLastBroadcastTime(agentNode->getLocalID());
if (lastBroadcastTime <= agentNodeData->getIdentityChangeTimestamp()
|| (start - lastBroadcastTime) >= REBROADCAST_IDENTITY_TO_DOWNSTREAM_EVERY_US) {
sendReplicatedIdentityPacket(*agentNode, agentNodeData, *node);
nodeData->setLastBroadcastTime(agentNode->getUUID(), start);
nodeData->setLastBroadcastTime(agentNode->getLocalID(), start);
}
// figure out how large our avatar byte array can be to fit in the packet list
@ -630,14 +610,14 @@ void AvatarMixerSlave::broadcastAvatarDataToDownstreamMixer(const SharedNodePoin
<< "-" << avatarByteArray.size() << "bytes";
avatarByteArray = otherAvatar->toByteArray(AvatarData::SendAllData, 0, emptyLastJointSendData,
flagsOut, true, false, glm::vec3(0), nullptr);
sendStatus, true, false, glm::vec3(0), nullptr, 0);
if (avatarByteArray.size() > maxAvatarByteArraySize) {
qCWarning(avatars) << "Replicated avatar data without facial data still too large for"
<< otherAvatar->getSessionUUID() << "-" << avatarByteArray.size() << "bytes";
avatarByteArray = otherAvatar->toByteArray(AvatarData::MinimumData, 0, emptyLastJointSendData,
flagsOut, true, false, glm::vec3(0), nullptr);
sendStatus, true, false, glm::vec3(0), nullptr, 0);
}
}
@ -646,7 +626,7 @@ void AvatarMixerSlave::broadcastAvatarDataToDownstreamMixer(const SharedNodePoin
nodeData->incrementNumAvatarsSentLastFrame();
// set the last sent sequence number for this sender on the receiver
nodeData->setLastBroadcastSequenceNumber(agentNode->getUUID(),
nodeData->setLastBroadcastSequenceNumber(agentNode->getLocalID(),
agentNodeData->getLastReceivedSequenceNumber());
// increment the number of avatars sent to this reciever

View file

@ -101,7 +101,7 @@ public:
void harvestStats(AvatarMixerSlaveStats& stats);
private:
int sendIdentityPacket(const AvatarMixerClientData* nodeData, const SharedNodePointer& destinationNode);
int sendIdentityPacket(NLPacketList& packet, const AvatarMixerClientData* nodeData, const Node& destinationNode);
int sendReplicatedIdentityPacket(const Node& agentNode, const AvatarMixerClientData* nodeData, const Node& destinationNode);
qint64 addChangedTraitsToBulkPacket(AvatarMixerClientData* listeningNodeData,

View file

@ -69,10 +69,10 @@ void ScriptableAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) {
AvatarData::setSkeletonModelURL(skeletonModelURL);
}
static AnimPose composeAnimPose(const FBXJoint& fbxJoint, const glm::quat rotation, const glm::vec3 translation) {
static AnimPose composeAnimPose(const HFMJoint& joint, const glm::quat rotation, const glm::vec3 translation) {
glm::mat4 translationMat = glm::translate(translation);
glm::mat4 rotationMat = glm::mat4_cast(fbxJoint.preRotation * rotation * fbxJoint.postRotation);
glm::mat4 finalMat = translationMat * fbxJoint.preTransform * rotationMat * fbxJoint.postTransform;
glm::mat4 rotationMat = glm::mat4_cast(joint.preRotation * rotation * joint.postRotation);
glm::mat4 finalMat = translationMat * joint.preTransform * rotationMat * joint.postTransform;
return AnimPose(finalMat);
}
@ -84,7 +84,7 @@ void ScriptableAvatar::update(float deltatime) {
// Run animation
if (_animation && _animation->isLoaded() && _animation->getFrames().size() > 0 && !_bind.isNull() && _bind->isLoaded()) {
if (!_animSkeleton) {
_animSkeleton = std::make_shared<AnimSkeleton>(_bind->getGeometry());
_animSkeleton = std::make_shared<AnimSkeleton>(_bind->getHFMModel());
}
float currentFrame = _animationDetails.currentFrame + deltatime * _animationDetails.fps;
if (_animationDetails.loop || currentFrame < _animationDetails.lastFrame) {
@ -93,7 +93,7 @@ void ScriptableAvatar::update(float deltatime) {
}
_animationDetails.currentFrame = currentFrame;
const QVector<FBXJoint>& modelJoints = _bind->getGeometry().joints;
const QVector<HFMJoint>& modelJoints = _bind->getHFMModel().joints;
QStringList animationJointNames = _animation->getJointNames();
const int nJoints = modelJoints.size();
@ -102,8 +102,8 @@ void ScriptableAvatar::update(float deltatime) {
}
const int frameCount = _animation->getFrames().size();
const FBXAnimationFrame& floorFrame = _animation->getFrames().at((int)glm::floor(currentFrame) % frameCount);
const FBXAnimationFrame& ceilFrame = _animation->getFrames().at((int)glm::ceil(currentFrame) % frameCount);
const HFMAnimationFrame& floorFrame = _animation->getFrames().at((int)glm::floor(currentFrame) % frameCount);
const HFMAnimationFrame& ceilFrame = _animation->getFrames().at((int)glm::ceil(currentFrame) % frameCount);
const float frameFraction = glm::fract(currentFrame);
std::vector<AnimPose> poses = _animSkeleton->getRelativeDefaultPoses();
@ -113,7 +113,7 @@ void ScriptableAvatar::update(float deltatime) {
const QString& name = animationJointNames[i];
// As long as we need the model preRotations anyway, let's get the jointIndex from the bind skeleton rather than
// trusting the .fst (which is sometimes not updated to match changes to .fbx).
int mapping = _bind->getGeometry().getJointIndex(name);
int mapping = _bind->getHFMModel().getJointIndex(name);
if (mapping != -1 && !_maskedJoints.contains(name)) {
AnimPose floorPose = composeAnimPose(modelJoints[mapping], floorFrame.rotations[i], floorFrame.translations[i] * UNIT_SCALE);

View file

@ -1,7 +1,7 @@
import QtQuick 2.5
import "../../qml/controls-uit"
import "../../qml/styles-uit"
import controlsUit 1.0
import stylesUit 1.0
Item {
id: menu

View file

@ -1,7 +1,7 @@
import QtQuick 2.5
import "../../qml/controls-uit"
import "../../qml/styles-uit"
import controlsUit 1.0
import stylesUit 1.0
Item {
id: root

View file

@ -1,7 +1,7 @@
import QtQuick 2.5
import "../../qml/controls-uit"
import "../../qml/styles-uit"
import controlsUit 1.0
import stylesUit 1.0
import "../../qml/dialogs"
QtObject {

View file

@ -0,0 +1,140 @@
{
"version": "1.1",
"root": {
"id": "userAnimStateMachine",
"type": "stateMachine",
"data": {
"currentState": "idleAnim",
"states": [
{
"id": "idleAnim",
"interpTarget": 6,
"interpDuration": 6,
"transitions": [
{ "var": "postTransitAnim", "state": "postTransitAnim" },
{ "var": "preTransitAnim", "state": "preTransitAnim" }
]
},
{
"id": "preTransitAnim",
"interpTarget": 6,
"interpDuration": 6,
"transitions": [
{ "var": "idleAnim", "state": "idleAnim" },
{ "var": "transitAnim", "state": "transitAnim" }
]
},
{
"id": "transitAnim",
"interpTarget": 6,
"interpDuration": 6,
"transitions": [
{ "var": "preTransitAnim", "state": "preTransitAnim" },
{ "var": "postTransitAnim", "state": "postTransitAnim" }
]
},
{
"id": "postTransitAnim",
"interpTarget": 6,
"interpDuration": 6,
"transitions": [
{ "var": "transitAnim", "state": "transitAnim" },
{ "var": "idleAnim", "state": "idleAnim" }
]
},
{
"id": "userAnimA",
"interpTarget": 6,
"interpDuration": 6,
"transitions": [
{ "var": "idleAnim", "state": "idleAnim" },
{ "var": "userAnimB", "state": "userAnimB" }
]
},
{
"id": "userAnimB",
"interpTarget": 6,
"interpDuration": 6,
"transitions": [
{ "var": "idleAnim", "state": "idleAnim" },
{ "var": "userAnimA", "state": "userAnimA" }
]
}
]
},
"children": [
{
"id": "idleAnim",
"type": "clip",
"data": {
"url": "qrc:///avatar/animations/idle.fbx",
"startFrame": 0.0,
"endFrame": 90.0,
"timeScale": 1.0,
"loopFlag": true
},
"children": []
},
{
"id": "preTransitAnim",
"type": "clip",
"data": {
"url": "https://hifi-content.s3.amazonaws.com/luis/test_scripts/transitApp/animations/teleport01_warp.fbx",
"startFrame": 0.0,
"endFrame": 10.0,
"timeScale": 1.0,
"loopFlag": false
},
"children": []
},
{
"id": "transitAnim",
"type": "clip",
"data": {
"url": "https://hifi-content.s3.amazonaws.com/luis/test_scripts/transitApp/animations/teleport01_warp.fbx",
"startFrame": 11.0,
"endFrame": 11.0,
"timeScale": 1.0,
"loopFlag": true
},
"children": []
},
{
"id": "postTransitAnim",
"type": "clip",
"data": {
"url": "https://hifi-content.s3.amazonaws.com/luis/test_scripts/transitApp/animations/teleport01_warp.fbx",
"startFrame": 22.0,
"endFrame": 49.0,
"timeScale": 1.0,
"loopFlag": false
},
"children": []
},
{
"id": "userAnimA",
"type": "clip",
"data": {
"url": "qrc:///avatar/animations/idle.fbx",
"startFrame": 0.0,
"endFrame": 90.0,
"timeScale": 1.0,
"loopFlag": true
},
"children": []
},
{
"id": "userAnimB",
"type": "clip",
"data": {
"url": "qrc:///avatar/animations/idle.fbx",
"startFrame": 0.0,
"endFrame": 90.0,
"timeScale": 1.0,
"loopFlag": true
},
"children": []
}
]
}
}

View file

@ -51,32 +51,34 @@
{ "from": "Vive.RSCenter", "to": "Standard.RightPrimaryThumb" },
{ "from": "Vive.RightApplicationMenu", "to": "Standard.RightSecondaryThumb" },
{ "from": "Vive.LeftHand", "to": "Standard.LeftHand"},
{ "from": "Vive.RightHand", "to": "Standard.RightHand"},
{ "from": "Vive.LeftHand", "to": "Standard.LeftHand" },
{ "from": "Vive.RightHand", "to": "Standard.RightHand" },
{ "from": "Vive.Head", "to" : "Standard.Head" },
{
"from": "Vive.LeftFoot", "to" : "Standard.LeftFoot",
"filters" : [{"type" : "exponentialSmoothing", "rotation" : 0.15, "translation": 0.3}]
"filters" : [{"type" : "exponentialSmoothing", "rotation" : 0.15, "translation": 0.15}]
},
{
"from": "Vive.RightFoot", "to" : "Standard.RightFoot",
"filters" : [{"type" : "exponentialSmoothing", "rotation" : 0.15, "translation": 0.3}]
"filters" : [{"type" : "exponentialSmoothing", "rotation" : 0.15, "translation": 0.15}]
},
{
"from": "Vive.Hips", "to" : "Standard.Hips",
"filters" : [{"type" : "exponentialSmoothing", "rotation" : 0.15, "translation": 0.3}]
"filters" : [{"type" : "exponentialSmoothing", "rotation" : 0.15, "translation": 0.15}]
},
{
"from": "Vive.Spine2", "to" : "Standard.Spine2",
"filters" : [{"type" : "exponentialSmoothing", "rotation" : 0.15, "translation": 0.3}]
"filters" : [{"type" : "exponentialSmoothing", "rotation" : 0.15, "translation": 0.15}]
},
{
"from": "Vive.RightArm", "to" : "Standard.RightArm",
"filters" : [{"type" : "exponentialSmoothing", "rotation" : 0.15, "translation": 0.15}]
},
{
"from": "Vive.LeftArm", "to" : "Standard.LeftArm",
"filters" : [{"type" : "exponentialSmoothing", "rotation" : 0.15, "translation": 0.15}]
},
{ "from": "Vive.Head", "to" : "Standard.Head"},
{ "from": "Vive.RightArm", "to" : "Standard.RightArm" },
{ "from": "Vive.LeftArm", "to" : "Standard.LeftArm" },
{ "from": "Vive.TrackedObject00", "to" : "Standard.TrackedObject00" },
{ "from": "Vive.TrackedObject01", "to" : "Standard.TrackedObject01" },

View file

@ -0,0 +1,4 @@
<svg width="22" height="26" fill="none" version="1.1" viewBox="0 0 22 26" xmlns="http://www.w3.org/2000/svg">
<path d="M1 7L11 1L21 7M1 7L11 13M1 7V19L11 25M11 13L21 7M11 13V25M21 7V19L11 25" stroke="#000" stroke-linejoin="round" stroke-width="2"/>
<circle class="st1" cx="19.407" cy="2.5881" r="2.5846" fill="#ef3b4e" stroke-width=".24043"/>
</svg>

After

Width:  |  Height:  |  Size: 356 B

View file

@ -0,0 +1,3 @@
<svg width="22" height="26" viewBox="0 0 22 26" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M1 7L11 1L21 7M1 7L11 13M1 7V19L11 25M11 13L21 7M11 13V25M21 7V19L11 25" stroke="black" stroke-width="2" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 243 B

View file

@ -0,0 +1,4 @@
<svg width="22" height="26" fill="none" version="1.1" viewBox="0 0 22 26" xmlns="http://www.w3.org/2000/svg">
<path d="M1 7L11 1L21 7M1 7L11 13M1 7V19L11 25M11 13L21 7M11 13V25M21 7V19L11 25" stroke="#fff" stroke-linejoin="round" stroke-width="2"/>
<circle class="st1" cx="19.41" cy="2.5828" r="2.5846" fill="#ef3b4e" stroke-width=".24043"/>
</svg>

After

Width:  |  Height:  |  Size: 355 B

View file

@ -0,0 +1,3 @@
<svg width="22" height="26" viewBox="0 0 22 26" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M1 7L11 1L21 7M1 7L11 13M1 7V19L11 25M11 13L21 7M11 13V25M21 7V19L11 25" stroke="white" stroke-width="2" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 243 B

View file

@ -1,6 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" x="0px" y="0px" viewBox="0 0 96 96" style="enable-background:new 0 0 96 96;" xml:space="preserve">
<style type="text/css">
.st1{fill:#EF3B4E;}
</style>
<circle class="st1" cx="84.6" cy="11.5" r="10.75"/>
<g><path d="M2.4,70.5c0,6.1,4.9,11,11,11H76c6.1,0,11-4.9,11-11V59.6c3.7-0.7,6.6-3.9,6.6-7.9v-7.5c0-3.9-2.8-7.2-6.6-7.9V25.5 c0-6.1-4.9-11-11-11H13.4c-6.1,0-11,4.9-11,11V70.5z M87.6,51.8c0,1.1-0.9,2-2,2H72.2c-2.8,0-5-2.2-5-5v-1.5c0-2.8,2.2-5,5-5h13.3 c1.1,0,2,0.9,2,2V51.8z M8.4,25.5c0-2.8,2.2-5,5-5H76c2.8,0,5,2.2,5,5v10.7h-8.7c-6.1,0-11,4.9-11,11v1.5c0,6.1,4.9,11,11,11H81 v10.7c0,2.8-2.2,5-5,5H13.4c-2.8,0-5-2.2-5-5V25.5z"></path></g></svg>

Before

Width:  |  Height:  |  Size: 755 B

View file

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" x="0px" y="0px" viewBox="0 0 96 96" style="enable-background:new 0 0 96 96;" xml:space="preserve"><g><path d="M2.4,70.5c0,6.1,4.9,11,11,11H76c6.1,0,11-4.9,11-11V59.6c3.7-0.7,6.6-3.9,6.6-7.9v-7.5c0-3.9-2.8-7.2-6.6-7.9V25.5 c0-6.1-4.9-11-11-11H13.4c-6.1,0-11,4.9-11,11V70.5z M87.6,51.8c0,1.1-0.9,2-2,2H72.2c-2.8,0-5-2.2-5-5v-1.5c0-2.8,2.2-5,5-5h13.3 c1.1,0,2,0.9,2,2V51.8z M8.4,25.5c0-2.8,2.2-5,5-5H76c2.8,0,5,2.2,5,5v10.7h-8.7c-6.1,0-11,4.9-11,11v1.5c0,6.1,4.9,11,11,11H81 v10.7c0,2.8-2.2,5-5,5H13.4c-2.8,0-5-2.2-5-5V25.5z"></path></g></svg>

Before

Width:  |  Height:  |  Size: 643 B

View file

@ -1,16 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 96 96" style="enable-background:new 0 0 96 96;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FFFFFF;}
.st1{fill:#EF3B4E;}
</style>
<circle class="st1" cx="84.6" cy="11.5" r="10.75"/>
<g>
<path class="st0" d="M2.4,70.5c0,6.1,4.9,11,11,11H76c6.1,0,11-4.9,11-11V59.6c3.7-0.7,6.6-3.9,6.6-7.9v-7.5c0-3.9-2.8-7.2-6.6-7.9
V25.5c0-6.1-4.9-11-11-11H13.4c-6.1,0-11,4.9-11,11C2.4,25.5,2.4,70.5,2.4,70.5z M87.6,51.8c0,1.1-0.9,2-2,2H72.2c-2.8,0-5-2.2-5-5
v-1.5c0-2.8,2.2-5,5-5h13.3c1.1,0,2,0.9,2,2L87.6,51.8L87.6,51.8z M8.4,25.5c0-2.8,2.2-5,5-5H76c2.8,0,5,2.2,5,5v10.7h-8.7
c-6.1,0-11,4.9-11,11v1.5c0,6.1,4.9,11,11,11H81v10.7c0,2.8-2.2,5-5,5H13.4c-2.8,0-5-2.2-5-5V25.5z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 984 B

View file

@ -1,14 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 96 96" style="enable-background:new 0 0 96 96;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FFFFFF;}
</style>
<g>
<path class="st0" d="M2.4,70.5c0,6.1,4.9,11,11,11H76c6.1,0,11-4.9,11-11V59.6c3.7-0.7,6.6-3.9,6.6-7.9v-7.5c0-3.9-2.8-7.2-6.6-7.9
V25.5c0-6.1-4.9-11-11-11H13.4c-6.1,0-11,4.9-11,11C2.4,25.5,2.4,70.5,2.4,70.5z M87.6,51.8c0,1.1-0.9,2-2,2H72.2c-2.8,0-5-2.2-5-5
v-1.5c0-2.8,2.2-5,5-5h13.3c1.1,0,2,0.9,2,2L87.6,51.8L87.6,51.8z M8.4,25.5c0-2.8,2.2-5,5-5H76c2.8,0,5,2.2,5,5v10.7h-8.7
c-6.1,0-11,4.9-11,11v1.5c0,6.1,4.9,11,11,11H81v10.7c0,2.8-2.2,5-5,5H13.4c-2.8,0-5-2.2-5-5V25.5z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 909 B

View file

@ -10,6 +10,7 @@ Item {
property int modality: Qt.NonModal
implicitHeight: row.height
implicitWidth: row.width
visible: false
Component.onCompleted: {
stats.parentChanged.connect(fill);

View file

@ -10,8 +10,8 @@
import QtQuick 2.5
import QtQuick.Controls 1.4
import "styles-uit"
import "controls-uit" as HifiControlsUit
import stylesUit 1.0
import controlsUit 1.0 as HifiControlsUit
Item {
id: root

View file

@ -2,9 +2,9 @@ import QtQuick 2.5
import QtWebChannel 1.0
import QtWebEngine 1.5
import "controls-uit"
import controlsUit 1.0
import "styles" as HifiStyles
import "styles-uit"
import stylesUit 1.0
import "windows"
ScrollingWindow {

View file

@ -10,8 +10,8 @@
import QtQuick 2.5
import QtQuick.Controls 1.4
import "styles-uit"
import "controls-uit" as HifiControls
import stylesUit 1.0
import controlsUit 1.0 as HifiControls
Item {
id: root

View file

@ -11,7 +11,7 @@
import QtQuick 2.5
import Hifi 1.0 as Hifi
import "controls-uit"
import controlsUit 1.0
import "windows" as Windows
Windows.ScrollingWindow {

View file

@ -12,9 +12,9 @@ import QtQuick 2.3
import "windows" as Windows
import "controls"
import "controls-uit" as Controls
import controlsUit 1.0 as Controls
import "styles"
import "styles-uit"
import stylesUit 1.0
Windows.Window {
id: root;

View file

@ -11,8 +11,8 @@
import Hifi 1.0
import QtQuick 2.4
import "controls-uit"
import "styles-uit"
import controlsUit 1.0
import stylesUit 1.0
import "windows"
import "LoginDialog"

View file

@ -13,8 +13,8 @@ import QtQuick 2.4
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4 as OriginalStyles
import "../../controls-uit"
import "../../styles-uit"
import controlsUit 1.0
import stylesUit 1.0
Item {
id: linkAccountBody

View file

@ -13,8 +13,8 @@ import QtQuick 2.4
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4 as OriginalStyles
import "../../controls-uit"
import "../../styles-uit"
import controlsUit 1.0
import stylesUit 1.0
Item {
id: signupBody

View file

@ -12,8 +12,8 @@ import Hifi 1.0
import QtQuick 2.4
import QtQuick.Controls.Styles 1.4 as OriginalStyles
import "../controls-uit"
import "../styles-uit"
import controlsUit 1.0
import stylesUit 1.0
Item {
id: completeProfileBody

View file

@ -13,8 +13,9 @@ import QtQuick 2.7
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4 as OriginalStyles
import "../controls-uit"
import "../styles-uit"
import controlsUit 1.0
import stylesUit 1.0
Item {
id: linkAccountBody
clip: true
@ -96,7 +97,7 @@ Item {
topMargin: hifi.dimensions.contentSpacing.y
}
text: qsTr("Sign in to High Fidelity to make friends, get HFC, and buy interesting things on the Marketplace!")
text: qsTr("Sign in to High Fidelity to make friends, get HFC, and get interesting things on the Marketplace!")
width: parent.width
wrapMode: Text.WordWrap
lineHeight: 1
@ -136,7 +137,7 @@ Item {
TextField {
id: usernameField
text: Settings.getValue("wallet/savedUsername", "");
text: Settings.getValue("keepMeLoggedIn/savedUsername", "");
width: parent.width
focus: true
placeholderText: "Username or Email"
@ -165,7 +166,7 @@ Item {
root.text = "";
}
Component.onCompleted: {
var savedUsername = Settings.getValue("wallet/savedUsername", "");
var savedUsername = Settings.getValue("keepMeLoggedIn/savedUsername", "");
usernameField.text = savedUsername === "Unknown user" ? "" : savedUsername;
}
}
@ -239,7 +240,10 @@ Item {
}
Keys.onReturnPressed: linkAccountBody.login()
Keys.onReturnPressed: {
Settings.setValue("keepMeLoggedIn/savedUsername", usernameField.text);
linkAccountBody.login();
}
}
InfoItem {
@ -263,21 +267,21 @@ Item {
CheckBox {
id: autoLogoutCheckbox
checked: !Settings.getValue("wallet/autoLogout", true)
text: "Keep me signed in"
checked: Settings.getValue("keepMeLoggedIn", false)
text: "Keep me logged in"
boxSize: 20;
labelFontSize: 15
color: hifi.colors.black
onCheckedChanged: {
Settings.setValue("wallet/autoLogout", !checked);
Settings.setValue("keepMeLoggedIn", checked);
if (checked) {
Settings.setValue("wallet/savedUsername", Account.username);
Settings.setValue("keepMeLoggedIn/savedUsername", usernameField.text);
} else {
Settings.setValue("wallet/savedUsername", "");
Settings.setValue("keepMeLoggedIn/savedUsername", "");
}
}
Component.onDestruction: {
Settings.setValue("wallet/autoLogout", !checked);
Settings.setValue("keepMeLoggedIn", checked);
}
}
@ -289,7 +293,10 @@ Item {
text: qsTr(loginDialog.isSteamRunning() ? "Link Account" : "Log in")
color: hifi.buttons.blue
onClicked: linkAccountBody.login()
onClicked: {
Settings.setValue("keepMeLoggedIn/savedUsername", usernameField.text);
linkAccountBody.login();
}
}
}
@ -403,6 +410,7 @@ Item {
case Qt.Key_Enter:
case Qt.Key_Return:
event.accepted = true
Settings.setValue("keepMeLoggedIn/savedUsername", usernameField.text);
linkAccountBody.login()
break
}

View file

@ -12,8 +12,8 @@ import Hifi 1.0
import QtQuick 2.7
import QtQuick.Controls.Styles 1.4 as OriginalStyles
import "../controls-uit"
import "../styles-uit"
import controlsUit 1.0
import stylesUit 1.0
Item {
id: signInBody

View file

@ -12,8 +12,8 @@ import Hifi 1.0
import QtQuick 2.7
import QtQuick.Controls 1.4
import "../controls-uit"
import "../styles-uit"
import controlsUit 1.0
import stylesUit 1.0
Item {
id: signupBody

View file

@ -12,8 +12,8 @@ import Hifi 1.0
import QtQuick 2.4
import QtQuick.Controls 1.4
import "../controls-uit"
import "../styles-uit"
import controlsUit 1.0
import stylesUit 1.0
Item {
id: usernameCollisionBody

View file

@ -11,8 +11,8 @@
import Hifi 1.0
import QtQuick 2.4
import "../controls-uit"
import "../styles-uit"
import controlsUit 1.0
import stylesUit 1.0
Item {
id: welcomeBody

View file

@ -13,8 +13,8 @@ import QtWebEngine 1.1
import QtWebChannel 1.0
import "windows" as Windows
import "controls-uit" as Controls
import "styles-uit"
import controlsUit 1.0 as Controls
import stylesUit 1.0
Windows.ScrollingWindow {
id: root

View file

@ -2,9 +2,9 @@ import QtQuick 2.3
import "windows" as Windows
import "controls"
import "controls-uit" as Controls
import controlsUit 1.0 as Controls
import "styles"
import "styles-uit"
import stylesUit 1.0
Windows.Window {
id: root

View file

@ -3,9 +3,9 @@ import QtWebChannel 1.0
import QtWebEngine 1.5
import "controls"
import "controls-uit" as HifiControls
import controlsUit 1.0 as HifiControls
import "styles" as HifiStyles
import "styles-uit"
import stylesUit 1.0
import "windows"
Item {

View file

@ -4,9 +4,9 @@ import QtQuick.Controls 1.3
import QtQuick.Controls.Styles 1.3
import QtGraphicalEffects 1.0
import "controls-uit"
import controlsUit 1.0
import "styles" as HifiStyles
import "styles-uit"
import stylesUit 1.0
import "windows"
ScrollingWindow {

View file

@ -1,170 +1,4 @@
//
// AttachmentsTable.qml
//
// Created by David Rowe on 18 Feb 2016
// Copyright 2016 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import controlsUit 1.0
import QtQuick 2.5
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import QtQuick.XmlListModel 2.0
import "../styles-uit"
import "../controls-uit" as HifiControls
import "../windows"
import "../hifi/models"
TableView {
id: tableView
property int colorScheme: hifi.colorSchemes.light
readonly property bool isLightColorScheme: colorScheme == hifi.colorSchemes.light
model: S3Model{}
Rectangle {
anchors.fill: parent
visible: tableView.model.status !== XmlListModel.Ready
color: hifi.colors.darkGray0
BusyIndicator {
anchors.centerIn: parent
width: 48; height: 48
running: true
}
}
headerDelegate: Rectangle {
height: hifi.dimensions.tableHeaderHeight
color: hifi.colors.darkGray
border.width: 0.5
border.color: hifi.colors.baseGrayHighlight
RalewayRegular {
id: textHeader
size: hifi.fontSizes.tableHeading
color: hifi.colors.lightGrayText
text: styleData.value
anchors {
horizontalCenter: parent.horizontalCenter
verticalCenter: parent.verticalCenter
}
}
}
// Use rectangle to draw border with rounded corners.
Rectangle {
color: "#00000000"
anchors { fill: parent; margins: -2 }
radius: hifi.dimensions.borderRadius
border.color: hifi.colors.baseGrayHighlight
border.width: 3
}
anchors.margins: 2 // Shrink TableView to lie within border.
backgroundVisible: true
horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff
verticalScrollBarPolicy: Qt.ScrollBarAsNeeded
style: TableViewStyle {
// Needed in order for rows to keep displaying rows after end of table entries.
backgroundColor: parent.isLightColorScheme ? hifi.colors.tableRowLightEven : hifi.colors.tableRowDarkEven
alternateBackgroundColor: parent.isLightColorScheme ? hifi.colors.tableRowLightOdd : hifi.colors.tableRowDarkOdd
handle: Item {
id: scrollbarHandle
implicitWidth: 6
Rectangle {
anchors {
fill: parent
leftMargin: 2 // Move it right
rightMargin: -2 // ""
topMargin: 3 // Shrink vertically
bottomMargin: 3 // ""
}
radius: 3
color: hifi.colors.tableScrollHandleDark
}
}
scrollBarBackground: Item {
implicitWidth: 10
Rectangle {
anchors {
fill: parent
margins: -1 // Expand
}
color: hifi.colors.baseGrayHighlight
}
Rectangle {
anchors {
fill: parent
margins: 1 // Shrink
}
radius: 4
color: hifi.colors.tableScrollBackgroundDark
}
}
incrementControl: Item {
visible: false
}
decrementControl: Item {
visible: false
}
}
rowDelegate: Rectangle {
height: hifi.dimensions.tableRowHeight
color: styleData.selected
? hifi.colors.primaryHighlight
: tableView.isLightColorScheme
? (styleData.alternate ? hifi.colors.tableRowLightEven : hifi.colors.tableRowLightOdd)
: (styleData.alternate ? hifi.colors.tableRowDarkEven : hifi.colors.tableRowDarkOdd)
}
itemDelegate: Item {
anchors {
left: parent ? parent.left : undefined
leftMargin: hifi.dimensions.tablePadding
right: parent ? parent.right : undefined
rightMargin: hifi.dimensions.tablePadding
}
FiraSansSemiBold {
id: textItem
text: styleData.value
size: hifi.fontSizes.tableText
color: colorScheme == hifi.colorSchemes.light
? (styleData.selected ? hifi.colors.black : hifi.colors.baseGrayHighlight)
: (styleData.selected ? hifi.colors.black : hifi.colors.lightGrayText)
anchors {
horizontalCenter: parent.horizontalCenter
verticalCenter: parent.verticalCenter
}
}
}
TableViewColumn {
role: "name"
title: "NAME"
width: parent.width *0.3
horizontalAlignment: Text.AlignHCenter
}
TableViewColumn {
role: "size"
title: "SIZE"
width: parent.width *0.2
horizontalAlignment: Text.AlignHCenter
}
TableViewColumn {
role: "modified"
title: "LAST MODIFIED"
width: parent.width *0.5
horizontalAlignment: Text.AlignHCenter
}
}
AttachmentsTable {
}

View file

@ -1,38 +1,4 @@
//
// WebView.qml
//
// Created by Bradley Austin Davis on 12 Jan 2016
// Copyright 2016 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import controlsUit 1.0
import QtQuick 2.7
import QtWebEngine 1.5
WebEngineView {
id: root
Component.onCompleted: {
console.log("Connecting JS messaging to Hifi Logging")
// Ensure the JS from the web-engine makes it to our logging
root.javaScriptConsoleMessage.connect(function(level, message, lineNumber, sourceID) {
console.log("Web Window JS message: " + sourceID + " " + lineNumber + " " + message);
});
}
onLoadingChanged: {
// Required to support clicking on "hifi://" links
if (WebEngineView.LoadStartedStatus == loadRequest.status) {
var url = loadRequest.url.toString();
if (urlHandler.canHandleUrl(url)) {
if (urlHandler.handleUrl(url)) {
root.stop();
}
}
}
}
WebSpinner { }
}
BaseWebView {
}

View file

@ -1,122 +1,4 @@
//
// Button.qml
//
// Created by David Rowe on 16 Feb 2016
// Copyright 2016 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import controlsUit 1.0
import QtQuick 2.7
import QtQuick.Controls 2.3 as Original
import TabletScriptingInterface 1.0
import "../styles-uit"
Original.Button {
id: control;
property int color: 0
property int colorScheme: hifi.colorSchemes.light
property int fontSize: hifi.fontSizes.buttonLabel
property int radius: hifi.buttons.radius
property alias implicitTextWidth: buttonText.implicitWidth
property string buttonGlyph: "";
property int fontCapitalization: Font.AllUppercase
width: hifi.dimensions.buttonWidth
height: hifi.dimensions.controlLineHeight
HifiConstants { id: hifi }
onHoveredChanged: {
if (hovered) {
Tablet.playSound(TabletEnums.ButtonHover);
}
}
onFocusChanged: {
if (focus) {
Tablet.playSound(TabletEnums.ButtonHover);
}
}
onClicked: {
Tablet.playSound(TabletEnums.ButtonClick);
}
background: Rectangle {
radius: control.radius
border.width: (control.color === hifi.buttons.none ||
(control.color === hifi.buttons.noneBorderless && control.hovered) ||
(control.color === hifi.buttons.noneBorderlessWhite && control.hovered) ||
(control.color === hifi.buttons.noneBorderlessGray && control.hovered)) ? 1 : 0;
border.color: control.color === hifi.buttons.noneBorderless ? hifi.colors.blueHighlight :
(control.color === hifi.buttons.noneBorderlessGray ? hifi.colors.baseGray : hifi.colors.white);
gradient: Gradient {
GradientStop {
position: 0.2
color: {
if (!control.enabled) {
hifi.buttons.disabledColorStart[control.colorScheme]
} else if (control.pressed) {
hifi.buttons.pressedColor[control.color]
} else if (control.hovered) {
hifi.buttons.hoveredColor[control.color]
} else {
hifi.buttons.colorStart[control.color]
}
}
}
GradientStop {
position: 1.0
color: {
if (!control.enabled) {
hifi.buttons.disabledColorFinish[control.colorScheme]
} else if (control.pressed) {
hifi.buttons.pressedColor[control.color]
} else if (control.hovered) {
hifi.buttons.hoveredColor[control.color]
} else {
hifi.buttons.colorFinish[control.color]
}
}
}
}
}
contentItem: Item {
HiFiGlyphs {
id: buttonGlyph;
visible: control.buttonGlyph !== "";
text: control.buttonGlyph === "" ? hifi.glyphs.question : control.buttonGlyph;
// Size
size: 34;
// Anchors
anchors.right: buttonText.left;
anchors.top: parent.top;
anchors.bottom: parent.bottom;
// Style
color: enabled ? hifi.buttons.textColor[control.color]
: hifi.buttons.disabledTextColor[control.colorScheme];
// Alignment
horizontalAlignment: Text.AlignHCenter;
verticalAlignment: Text.AlignVCenter;
}
RalewayBold {
id: buttonText;
anchors.centerIn: parent;
font.capitalization: control.fontCapitalization
color: enabled ? hifi.buttons.textColor[control.color]
: hifi.buttons.disabledTextColor[control.colorScheme]
size: control.fontSize
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
text: control.text
}
}
Button {
}

View file

@ -1,121 +1,4 @@
//
// CheckBox.qml
//
// Created by David Rowe on 26 Feb 2016
// Copyright 2016 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import controlsUit 1.0
import QtQuick 2.2
import QtQuick.Controls 2.2 as Original
import "../styles-uit"
import TabletScriptingInterface 1.0
Original.CheckBox {
id: checkBox
property int colorScheme: hifi.colorSchemes.light
property string color: hifi.colors.lightGrayText
readonly property bool isLightColorScheme: colorScheme == hifi.colorSchemes.light
property bool isRedCheck: false
property int boxSize: 14
property int boxRadius: 3
property bool wrap: true;
readonly property int checkSize: Math.max(boxSize - 8, 10)
readonly property int checkRadius: 2
property string labelFontFamily: "Raleway"
property int labelFontSize: 14;
property int labelFontWeight: Font.DemiBold;
focusPolicy: Qt.ClickFocus
hoverEnabled: true
onClicked: {
Tablet.playSound(TabletEnums.ButtonClick);
}
onHoveredChanged: {
if (hovered) {
Tablet.playSound(TabletEnums.ButtonHover);
}
}
indicator: Rectangle {
id: box
implicitWidth: boxSize
implicitHeight: boxSize
radius: boxRadius
y: parent.height / 2 - height / 2
border.width: 1
border.color: pressed || hovered
? hifi.colors.checkboxCheckedBorder
: (checkBox.isLightColorScheme ? hifi.colors.checkboxLightFinish : hifi.colors.checkboxDarkFinish)
gradient: Gradient {
GradientStop {
position: 0.2
color: pressed || hovered
? (checkBox.isLightColorScheme ? hifi.colors.checkboxChecked : hifi.colors.checkboxLightStart)
: (checkBox.isLightColorScheme ? hifi.colors.checkboxLightStart : hifi.colors.checkboxDarkStart)
}
GradientStop {
position: 1.0
color: pressed || hovered
? (checkBox.isLightColorScheme ? hifi.colors.checkboxChecked : hifi.colors.checkboxLightFinish)
: (checkBox.isLightColorScheme ? hifi.colors.checkboxLightFinish : hifi.colors.checkboxDarkFinish)
}
}
Rectangle {
visible: pressed || hovered
anchors.centerIn: parent
id: innerBox
width: checkSize - 4
height: width
radius: checkRadius
color: hifi.colors.checkboxCheckedBorder
}
Rectangle {
id: check
width: checkSize
height: checkSize
radius: checkRadius
anchors.centerIn: parent
color: isRedCheck ? hifi.colors.checkboxCheckedRed : hifi.colors.checkboxChecked
border.width: 2
border.color: isRedCheck? hifi.colors.checkboxCheckedBorderRed : hifi.colors.checkboxCheckedBorder
visible: checked && !pressed || !checked && pressed
}
Rectangle {
id: disabledOverlay
visible: !enabled
width: boxSize
height: boxSize
radius: boxRadius
border.width: 1
border.color: hifi.colors.baseGrayHighlight
color: hifi.colors.baseGrayHighlight
opacity: 0.5
}
}
contentItem: Label {
text: checkBox.text
color: checkBox.color
font.family: checkBox.labelFontFamily;
font.pixelSize: checkBox.labelFontSize;
font.weight: checkBox.labelFontWeight;
x: 2
verticalAlignment: Text.AlignVCenter
wrapMode: checkBox.wrap ? Text.Wrap : Text.NoWrap
elide: checkBox.wrap ? Text.ElideNone : Text.ElideRight
enabled: checkBox.enabled
leftPadding: checkBox.indicator.width + checkBox.spacing
}
CheckBox {
}

View file

@ -1,125 +1,4 @@
//
// CheckBox2.qml
//
// Created by Vlad Stelmahovsky on 10 Aug 2017
// Copyright 2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import QtQuick 2.7
import QtQuick.Controls 2.2
import "../styles-uit"
import "../controls-uit" as HiFiControls
import TabletScriptingInterface 1.0
CheckBox {
id: checkBox
HifiConstants { id: hifi; }
padding: 0
leftPadding: 0
property int colorScheme: hifi.colorSchemes.light
property string color: hifi.colors.lightGrayText
readonly property bool isLightColorScheme: colorScheme === hifi.colorSchemes.light
property bool isRedCheck: false
property bool isRound: false
property int boxSize: 14
property int boxRadius: isRound ? boxSize : 3
property bool wrap: true;
readonly property int checkSize: Math.max(boxSize - 8, 10)
readonly property int checkRadius: isRound ? checkSize / 2 : 2
focusPolicy: Qt.ClickFocus
hoverEnabled: true
onClicked: {
Tablet.playSound(TabletEnums.ButtonClick);
}
onHoveredChanged: {
if (hovered) {
Tablet.playSound(TabletEnums.ButtonHover);
}
}
indicator: Rectangle {
id: box
implicitWidth: boxSize
implicitHeight: boxSize
radius: boxRadius
x: checkBox.leftPadding
y: parent.height / 2 - height / 2
border.width: 1
border.color: pressed || hovered
? hifi.colors.checkboxCheckedBorder
: (checkBox.isLightColorScheme ? hifi.colors.checkboxLightFinish : hifi.colors.checkboxDarkFinish)
gradient: Gradient {
GradientStop {
position: 0.2
color: pressed || hovered
? (checkBox.isLightColorScheme ? hifi.colors.checkboxChecked : hifi.colors.checkboxLightStart)
: (checkBox.isLightColorScheme ? hifi.colors.checkboxLightStart : hifi.colors.checkboxDarkStart)
}
GradientStop {
position: 1.0
color: pressed || hovered
? (checkBox.isLightColorScheme ? hifi.colors.checkboxChecked : hifi.colors.checkboxLightFinish)
: (checkBox.isLightColorScheme ? hifi.colors.checkboxLightFinish : hifi.colors.checkboxDarkFinish)
}
}
Rectangle {
visible: pressed || hovered
anchors.centerIn: parent
id: innerBox
width: checkSize - 4
height: width
radius: checkRadius
color: hifi.colors.checkboxCheckedBorder
}
Rectangle {
id: check
width: checkSize
height: checkSize
radius: checkRadius
anchors.centerIn: parent
color: isRedCheck ? hifi.colors.checkboxCheckedRed : hifi.colors.checkboxChecked
border.width: 2
border.color: isRedCheck? hifi.colors.checkboxCheckedBorderRed : hifi.colors.checkboxCheckedBorder
visible: checked && !pressed || !checked && pressed
}
Rectangle {
id: disabledOverlay
visible: !enabled
width: boxSize
height: boxSize
radius: boxRadius
border.width: 1
border.color: hifi.colors.baseGrayHighlight
color: hifi.colors.baseGrayHighlight
opacity: 0.5
}
}
contentItem: Text {
id: root
font.pixelSize: hifi.fontSizes.inputLabel
font.family: "Raleway"
font.weight: Font.DemiBold
text: checkBox.text
color: checkBox.color
x: 2
wrapMode: checkBox.wrap ? Text.Wrap : Text.NoWrap
elide: checkBox.wrap ? Text.ElideNone : Text.ElideRight
enabled: checkBox.enabled
verticalAlignment: Text.AlignVCenter
leftPadding: checkBox.indicator.width + checkBox.spacing
}
}
import controlsUit 1.0
CheckBoxQQC2 {
}

View file

@ -1,191 +1,4 @@
//
// ComboBox.qml
//
// Created by Bradley Austin David on 27 Jan 2016
// Copyright 2016 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import controlsUit 1.0
import QtQuick 2.7
import QtQuick.Controls 2.2
import "../styles-uit"
import "../controls-uit" as HifiControls
FocusScope {
id: root
HifiConstants { id: hifi }
property alias model: comboBox.model;
property alias editable: comboBox.editable
property alias comboBox: comboBox
readonly property alias currentText: comboBox.currentText;
property alias currentIndex: comboBox.currentIndex;
property int currentHighLightedIndex: comboBox.currentIndex;
property int dropdownHeight: 480
property int colorScheme: hifi.colorSchemes.light
readonly property bool isLightColorScheme: colorScheme == hifi.colorSchemes.light
property string label: ""
property real controlHeight: height + (comboBoxLabel.visible ? comboBoxLabel.height + comboBoxLabel.anchors.bottomMargin : 0)
readonly property ComboBox control: comboBox
property bool isDesktop: true
signal accepted();
implicitHeight: comboBox.height;
focus: true
ComboBox {
id: comboBox
anchors.fill: parent
hoverEnabled: true
visible: true
height: hifi.fontSizes.textFieldInput + 13 // Match height of TextField control.
function previousItem() { root.currentHighLightedIndex = (root.currentHighLightedIndex + comboBox.count - 1) % comboBox.count; }
function nextItem() { root.currentHighLightedIndex = (root.currentHighLightedIndex + comboBox.count + 1) % comboBox.count; }
function selectCurrentItem() { root.currentIndex = root.currentHighLightedIndex; close(); /*hideList();*/ }
function selectSpecificItem(index) { root.currentIndex = index; close();/*hideList();*/ }
Keys.onUpPressed: previousItem();
Keys.onDownPressed: nextItem();
Keys.onSpacePressed: selectCurrentItem();
Keys.onRightPressed: selectCurrentItem();
Keys.onReturnPressed: selectCurrentItem();
background: Rectangle {
gradient: Gradient {
GradientStop {
position: 0.2
color: comboBox.popup.visible
? (isLightColorScheme ? hifi.colors.dropDownPressedLight : hifi.colors.dropDownPressedDark)
: (isLightColorScheme ? hifi.colors.dropDownLightStart : hifi.colors.dropDownDarkStart)
}
GradientStop {
position: 1.0
color: comboBox.popup.visible
? (isLightColorScheme ? hifi.colors.dropDownPressedLight : hifi.colors.dropDownPressedDark)
: (isLightColorScheme ? hifi.colors.dropDownLightFinish : hifi.colors.dropDownDarkFinish)
}
}
}
indicator: Item {
id: dropIcon
anchors { right: parent.right; verticalCenter: parent.verticalCenter }
height: root.height
width: height
Rectangle {
width: 1
height: parent.height
anchors.top: parent.top
anchors.left: parent.left
color: isLightColorScheme ? hifi.colors.faintGray : hifi.colors.baseGray
}
HiFiGlyphs {
anchors { top: parent.top; topMargin: -11; horizontalCenter: parent.horizontalCenter }
size: hifi.dimensions.spinnerSize
text: hifi.glyphs.caratDn
color: comboBox.hovered || comboBox.popup.visible ? hifi.colors.baseGray : (isLightColorScheme ? hifi.colors.lightGray : hifi.colors.lightGrayText)
}
}
contentItem: FiraSansSemiBold {
id: textField
anchors {
left: parent.left
leftMargin: hifi.dimensions.textPadding
verticalCenter: parent.verticalCenter
}
size: hifi.fontSizes.textFieldInput
text: comboBox.displayText ? comboBox.displayText : comboBox.currentText
elide: Text.ElideRight
color: comboBox.hovered || comboBox.popup.visible ? hifi.colors.baseGray : (isLightColorScheme ? hifi.colors.lightGray : hifi.colors.lightGrayText )
}
delegate: ItemDelegate {
id: itemDelegate
hoverEnabled: true
width: root.width + 4
height: popupText.implicitHeight * 1.4
highlighted: root.currentHighLightedIndex == index
onHoveredChanged: {
if (hovered) {
root.currentHighLightedIndex = index
}
}
background: Rectangle {
color: itemDelegate.highlighted ? hifi.colors.primaryHighlight
: (isLightColorScheme ? hifi.colors.dropDownPressedLight
: hifi.colors.dropDownPressedDark)
}
contentItem: FiraSansSemiBold {
id: popupText
anchors.left: parent.left
anchors.leftMargin: hifi.dimensions.textPadding
anchors.verticalCenter: parent.verticalCenter
text: comboBox.model[index] ? comboBox.model[index]
: (comboBox.model.get && comboBox.model.get(index).text ?
comboBox.model.get(index).text : "")
size: hifi.fontSizes.textFieldInput
color: hifi.colors.baseGray
}
}
popup: Popup {
y: comboBox.height - 1
width: comboBox.width
implicitHeight: listView.contentHeight > dropdownHeight ? dropdownHeight
: listView.contentHeight
padding: 0
topPadding: 1
onClosed: {
root.accepted()
}
contentItem: ListView {
id: listView
clip: true
model: comboBox.popup.visible ? comboBox.delegateModel : null
currentIndex: root.currentHighLightedIndex
delegate: comboBox.delegate
ScrollBar.vertical: HifiControls.ScrollBar {
id: scrollbar
parent: listView
policy: ScrollBar.AsNeeded
visible: size < 1.0
}
}
background: Rectangle {
color: hifi.colors.baseGray
}
}
}
function textAt(index) {
return comboBox.textAt(index);
}
HifiControls.Label {
id: comboBoxLabel
text: root.label
colorScheme: root.colorScheme
anchors.left: parent.left
anchors.bottom: parent.top
anchors.bottomMargin: 4
visible: label != ""
}
Component.onCompleted: {
isDesktop = (typeof desktop !== "undefined");
}
ComboBox {
}

View file

@ -1,138 +1,4 @@
//
// ContentSection.qml
//
// Created by David Rowe on 16 Feb 2016
// Copyright 2016 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import controlsUit 1.0
import QtQuick 2.5
import QtGraphicalEffects 1.0
import "../styles-uit"
Column {
property string name: "Content Section"
property bool isFirst: false
property bool isCollapsible: false // Set at creation.
property bool isCollapsed: false
spacing: 0 // Defer spacing decisions to individual controls.
anchors {
left: parent.left
leftMargin: hifi.dimensions.contentMargin.x
right: parent.right
rightMargin: hifi.dimensions.contentMargin.x
}
function toggleCollapsed() {
if (isCollapsible) {
isCollapsed = !isCollapsed;
for (var i = 1; i < children.length; i++) {
children[i].visible = !isCollapsed;
}
}
}
Item {
id: sectionName
anchors.left: parent.left
anchors.right: parent.right
height: leadingSpace.height + topBar.height + heading.height + bottomBar.height
Item {
id: leadingSpace
width: 1
height: isFirst ? 7 : 0
anchors.top: parent.top
}
Item {
id: topBar
visible: !isFirst
height: visible ? 2 : 0
anchors.top: leadingSpace.bottom
Rectangle {
id: shadow
width: frame.width
height: 1
color: hifi.colors.baseGrayShadow
x: -hifi.dimensions.contentMargin.x
}
Rectangle {
width: frame.width
height: 1
color: hifi.colors.baseGrayHighlight
x: -hifi.dimensions.contentMargin.x
anchors.top: shadow.bottom
}
}
Item {
id: heading
anchors {
left: parent.left
right: parent.right
top: topBar.bottom
}
height: isCollapsible ? 36 : 28
RalewayRegular {
id: title
anchors {
left: parent.left
top: parent.top
topMargin: 12
}
size: hifi.fontSizes.sectionName
font.capitalization: Font.AllUppercase
text: name
color: hifi.colors.lightGrayText
}
HiFiGlyphs {
anchors {
top: title.top
topMargin: -9
right: parent.right
rightMargin: -4
}
size: hifi.fontSizes.disclosureButton
text: isCollapsed ? hifi.glyphs.disclosureButtonExpand : hifi.glyphs.disclosureButtonCollapse
color: hifi.colors.lightGrayText
visible: isCollapsible
}
MouseArea {
// Events are propogated so that any active control is defocused.
anchors.fill: parent
propagateComposedEvents: true
onPressed: {
toggleCollapsed();
mouse.accepted = false;
}
}
}
LinearGradient {
id: bottomBar
visible: desktop.gradientsSupported && isCollapsible
width: frame.width
height: visible ? 4 : 0
x: -hifi.dimensions.contentMargin.x
anchors.top: heading.bottom
start: Qt.point(0, 0)
end: Qt.point(0, 4)
gradient: Gradient {
GradientStop { position: 0.0; color: hifi.colors.darkGray }
GradientStop { position: 1.0; color: hifi.colors.baseGray } // Equivalent of darkGray0 over baseGray background.
}
cached: true
}
}
ContentSection {
}

View file

@ -1,321 +1,4 @@
//
// FilterBar.qml
//
// Created by Zach Fox on 17 Feb 2018-03-12
// Copyright 2018 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import controlsUit 1.0
import QtQuick 2.9
import QtQuick.Controls 2.2
import QtGraphicalEffects 1.0
import "../styles-uit"
import "../controls-uit" as HifiControls
Item {
id: root;
property int colorScheme: hifi.colorSchemes.light
readonly property bool isLightColorScheme: colorScheme == hifi.colorSchemes.light
readonly property bool isFaintGrayColorScheme: colorScheme == hifi.colorSchemes.faintGray
property bool error: false;
property alias textFieldHeight: textField.height;
property string placeholderText;
property alias dropdownHeight: dropdownContainer.height;
property alias text: textField.text;
property alias primaryFilterChoices: filterBarModel;
property int primaryFilter_index: -1;
property string primaryFilter_filterName: "";
property string primaryFilter_displayName: "";
signal accepted;
onPrimaryFilter_indexChanged: {
if (primaryFilter_index === -1) {
primaryFilter_filterName = "";
primaryFilter_displayName = "";
} else {
primaryFilter_filterName = filterBarModel.get(primaryFilter_index).filterName;
primaryFilter_displayName = filterBarModel.get(primaryFilter_index).displayName;
}
}
TextField {
id: textField;
anchors.top: parent.top;
anchors.right: parent.right;
anchors.left: parent.left;
font.family: "Fira Sans"
font.pixelSize: hifi.fontSizes.textFieldInput;
placeholderText: root.primaryFilter_index === -1 ? root.placeholderText : "";
TextMetrics {
id: primaryFilterTextMetrics;
font.family: "FiraSans Regular";
font.pixelSize: hifi.fontSizes.textFieldInput;
font.capitalization: Font.AllUppercase;
text: root.primaryFilter_displayName;
}
// workaround for https://bugreports.qt.io/browse/QTBUG-49297
Keys.onPressed: {
switch (event.key) {
case Qt.Key_Return:
case Qt.Key_Enter:
event.accepted = true;
// emit accepted signal manually
if (acceptableInput) {
root.accepted();
root.forceActiveFocus();
}
break;
case Qt.Key_Backspace:
if (textField.text === "") {
primaryFilter_index = -1;
}
break;
}
}
onAccepted: {
root.forceActiveFocus();
}
onActiveFocusChanged: {
if (!activeFocus) {
dropdownContainer.visible = false;
}
}
color: {
if (isLightColorScheme) {
if (textField.activeFocus) {
hifi.colors.black
} else {
hifi.colors.lightGray
}
} else if (isFaintGrayColorScheme) {
if (textField.activeFocus) {
hifi.colors.black
} else {
hifi.colors.lightGray
}
} else {
if (textField.activeFocus) {
hifi.colors.white
} else {
hifi.colors.lightGrayText
}
}
}
background: Rectangle {
id: mainFilterBarRectangle;
color: {
if (isLightColorScheme) {
if (textField.activeFocus) {
hifi.colors.white
} else {
hifi.colors.textFieldLightBackground
}
} else if (isFaintGrayColorScheme) {
if (textField.activeFocus) {
hifi.colors.white
} else {
hifi.colors.faintGray50
}
} else {
if (textField.activeFocus) {
hifi.colors.black
} else {
hifi.colors.baseGrayShadow
}
}
}
border.color: textField.error ? hifi.colors.redHighlight :
(textField.activeFocus ? hifi.colors.primaryHighlight : (isFaintGrayColorScheme ? hifi.colors.lightGrayText : hifi.colors.lightGray))
border.width: 1
radius: 4
Item {
id: searchButtonContainer;
anchors.left: parent.left;
anchors.verticalCenter: parent.verticalCenter;
height: parent.height;
width: 42;
// Search icon
HiFiGlyphs {
id: searchIcon;
text: hifi.glyphs.search
color: textField.color
size: 40;
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
width: paintedWidth;
}
// Carat
HiFiGlyphs {
text: hifi.glyphs.caratDn;
color: textField.color;
size: 40;
anchors.left: parent.left;
anchors.leftMargin: 15;
width: paintedWidth;
}
MouseArea {
anchors.fill: parent;
onClicked: {
textField.forceActiveFocus();
dropdownContainer.visible = !dropdownContainer.visible;
}
}
}
Rectangle {
z: 999;
id: primaryFilterContainer;
color: textField.activeFocus ? hifi.colors.faintGray : hifi.colors.white;
width: primaryFilterTextMetrics.tightBoundingRect.width + 14;
height: parent.height - 8;
anchors.verticalCenter: parent.verticalCenter;
anchors.left: searchButtonContainer.right;
anchors.leftMargin: 4;
visible: primaryFilterText.text !== "";
radius: height/2;
FiraSansRegular {
id: primaryFilterText;
text: root.primaryFilter_displayName;
anchors.fill: parent;
color: textField.activeFocus ? hifi.colors.black : hifi.colors.lightGray;
horizontalAlignment: Text.AlignHCenter;
verticalAlignment: Text.AlignVCenter;
size: hifi.fontSizes.textFieldInput;
font.capitalization: Font.AllUppercase;
}
MouseArea {
anchors.fill: parent;
onClicked: {
textField.forceActiveFocus();
}
}
}
// "Clear" button
HiFiGlyphs {
text: hifi.glyphs.error
color: textField.color
size: 40
anchors.right: parent.right
anchors.rightMargin: hifi.dimensions.textPadding - 2
anchors.verticalCenter: parent.verticalCenter
visible: root.text !== "" || root.primaryFilter_index !== -1;
MouseArea {
anchors.fill: parent;
onClicked: {
root.text = "";
root.primaryFilter_index = -1;
dropdownContainer.visible = false;
textField.forceActiveFocus();
}
}
}
}
selectedTextColor: hifi.colors.black
selectionColor: hifi.colors.primaryHighlight
leftPadding: 44 + (root.primaryFilter_index === -1 ? 0 : primaryFilterTextMetrics.tightBoundingRect.width + 20);
rightPadding: 44;
}
Rectangle {
id: dropdownContainer;
visible: false;
height: 50 * filterBarModel.count;
width: parent.width;
anchors.top: textField.bottom;
anchors.left: parent.left;
anchors.right: parent.right;
color: hifi.colors.white;
ListModel {
id: filterBarModel;
}
ListView {
id: dropdownListView;
interactive: false;
anchors.fill: parent;
model: filterBarModel;
delegate: Rectangle {
id: dropDownButton;
color: hifi.colors.white;
width: parent.width;
height: 50;
RalewaySemiBold {
id: dropDownButtonText;
text: model.displayName;
anchors.fill: parent;
anchors.leftMargin: 12;
color: hifi.colors.baseGray;
horizontalAlignment: Text.AlignLeft;
verticalAlignment: Text.AlignVCenter;
size: 18;
}
MouseArea {
anchors.fill: parent;
hoverEnabled: true;
propagateComposedEvents: false;
onEntered: {
dropDownButton.color = hifi.colors.blueHighlight;
}
onExited: {
dropDownButton.color = hifi.colors.white;
}
onClicked: {
textField.forceActiveFocus();
root.primaryFilter_index = index;
dropdownContainer.visible = false;
}
}
}
}
}
DropShadow {
anchors.fill: dropdownContainer;
horizontalOffset: 0;
verticalOffset: 4;
radius: 4.0;
samples: 9
color: Qt.rgba(0, 0, 0, 0.25);
source: dropdownContainer;
visible: dropdownContainer.visible;
}
function changeFilterByDisplayName(name) {
for (var i = 0; i < filterBarModel.count; i++) {
if (filterBarModel.get(i).displayName === name) {
root.primaryFilter_index = i;
return;
}
}
console.log("Passed displayName not found in filterBarModel! primaryFilter unchanged.");
}
FilterBar {
}

View file

@ -1,91 +1,4 @@
//
// GlyphButton.qml
//
// Created by Clement on 3/7/16
// Copyright 2016 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import controlsUit 1.0
import QtQuick 2.7
import QtQuick.Controls 2.2 as Original
import TabletScriptingInterface 1.0
import "../styles-uit"
Original.Button {
id: control
property int color: 0
property int colorScheme: hifi.colorSchemes.light
property string glyph: ""
property int size: 32
width: 120
height: 28
onHoveredChanged: {
if (hovered) {
Tablet.playSound(TabletEnums.ButtonHover);
}
}
onFocusChanged: {
if (focus) {
Tablet.playSound(TabletEnums.ButtonHover);
}
}
onClicked: {
Tablet.playSound(TabletEnums.ButtonClick);
}
background: Rectangle {
radius: hifi.buttons.radius
gradient: Gradient {
GradientStop {
position: 0.2
color: {
if (!control.enabled) {
hifi.buttons.disabledColorStart[control.colorScheme]
} else if (control.pressed) {
hifi.buttons.pressedColor[control.color]
} else if (control.hovered) {
hifi.buttons.hoveredColor[control.color]
} else if (!control.hovered && control.focus) {
hifi.buttons.focusedColor[control.color]
} else {
hifi.buttons.colorStart[control.color]
}
}
}
GradientStop {
position: 1.0
color: {
if (!control.enabled) {
hifi.buttons.disabledColorFinish[control.colorScheme]
} else if (control.pressed) {
hifi.buttons.pressedColor[control.color]
} else if (control.hovered) {
hifi.buttons.hoveredColor[control.color]
} else if (!control.hovered && control.focus) {
hifi.buttons.focusedColor[control.color]
} else {
hifi.buttons.colorFinish[control.color]
}
}
}
}
}
contentItem: HiFiGlyphs {
color: enabled ? hifi.buttons.textColor[control.color]
: hifi.buttons.disabledTextColor[control.colorScheme]
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
text: control.glyph
size: control.size
}
GlyphButton {
}

View file

@ -1,18 +1,4 @@
//
// HorizontalRule.qml
//
// Created by Clement on 7/18/16
// Copyright 2016 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import controlsUit 1.0
import QtQuick 2.5
Rectangle {
anchors.left: parent.left
anchors.right: parent.right
height: 1
color: hifi.colors.lightGray
HorizontalRule {
}

View file

@ -1,21 +1,4 @@
//
// HorizontalSpacer.qml
//
// Created by Clement on 7/18/16
// Copyright 2016 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import controlsUit 1.0
import QtQuick 2.5
import "../styles-uit"
Item {
id: root
property alias size: root.width
width: hifi.dimensions.controlInterlineHeight
height: 1 // Must be non-zero
HorizontalSpacer {
}

View file

@ -1,63 +1,4 @@
//
// ImageMessageBox.qml
//
// Created by Dante Ruiz on 7/5/2017
// Copyright 2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import QtQuick 2.5
import "../styles-uit"
Item {
id: imageBox
visible: false
anchors.fill: parent
property alias source: image.source
property alias imageWidth: image.width
property alias imageHeight: image.height
Rectangle {
anchors.fill: parent
color: "black"
opacity: 0.3
}
Image {
id: image
anchors.centerIn: parent
HiFiGlyphs {
id: closeGlyphButton
text: hifi.glyphs.close
size: 25
anchors {
top: parent.top
topMargin: 15
right: parent.right
rightMargin: 15
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
onEntered: {
parent.text = hifi.glyphs.closeInverted;
}
onExited: {
parent.text = hifi.glyphs.close;
}
onClicked: {
imageBox.visible = false;
}
}
}
}
import controlsUit 1.0
ImageMessageBox {
}

View file

@ -1,185 +1,4 @@
import QtQuick 2.0
import TabletScriptingInterface 1.0
import controlsUit 1.0
Item {
id: keyItem
width: 45
height: 50
property int contentPadding: 4
property string glyph: "a"
property bool toggle: false // does this button have the toggle behaivor?
property bool toggled: false // is this button currently toggled?
property alias mouseArea: mouseArea1
property alias fontFamily: letter.font.family;
property alias fontPixelSize: letter.font.pixelSize
property alias verticalAlignment: letter.verticalAlignment
property alias letterAnchors: letter.anchors
function resetToggledMode(mode) {
toggled = mode;
if (toggled) {
state = "mouseDepressed";
} else {
state = "";
}
}
MouseArea {
id: mouseArea1
width: 36
anchors.fill: parent
hoverEnabled: true
onCanceled: {
if (toggled) {
keyItem.state = "mouseDepressed";
} else {
keyItem.state = "";
}
}
onContainsMouseChanged: {
if (containsMouse) {
Tablet.playSound(TabletEnums.ButtonHover);
}
}
onDoubleClicked: {
mouse.accepted = true;
}
property var _HAPTIC_STRENGTH: 0.1;
property var _HAPTIC_DURATION: 3.0;
property var leftHand: 0;
property var rightHand: 1;
onEntered: {
keyItem.state = "mouseOver";
var globalPosition = keyItem.mapToGlobal(mouseArea1.mouseX, mouseArea1.mouseY);
var pointerID = Web3DOverlay.deviceIdByTouchPoint(globalPosition.x, globalPosition.y);
if (Pointers.isLeftHand(pointerID)) {
Controller.triggerHapticPulse(_HAPTIC_STRENGTH, _HAPTIC_DURATION, leftHand);
} else if (Pointers.isRightHand(pointerID)) {
Controller.triggerHapticPulse(_HAPTIC_STRENGTH, _HAPTIC_DURATION, rightHand);
}
}
onExited: {
if (toggled) {
keyItem.state = "mouseDepressed";
} else {
keyItem.state = "";
}
}
onPressed: {
keyItem.state = "mouseClicked";
mouse.accepted = true;
}
onReleased: {
if (containsMouse) {
Tablet.playSound(TabletEnums.ButtonClick);
webEntity.synthesizeKeyPress(glyph);
webEntity.synthesizeKeyPress(glyph, mirrorText);
if (toggle) {
toggled = !toggled;
}
keyItem.state = "mouseOver";
} else {
if (toggled) {
keyItem.state = "mouseDepressed";
} else {
keyItem.state = "";
}
}
mouse.accepted = true;
}
}
Rectangle {
id: roundedRect
width: 30
color: "#121212"
radius: 2
border.color: "#00000000"
anchors.fill: parent
anchors.margins: contentPadding
}
Text {
id: letter
y: 6
width: 50
color: "#ffffff"
text: glyph
style: Text.Normal
font.family: "Tahoma"
anchors.right: parent.right
anchors.rightMargin: 0
anchors.left: parent.left
anchors.leftMargin: 0
anchors.bottom: parent.bottom
anchors.bottomMargin: 0
anchors.top: parent.top
anchors.topMargin: 8
horizontalAlignment: Text.AlignHCenter
font.pixelSize: 28
}
states: [
State {
name: "mouseOver"
PropertyChanges {
target: roundedRect
color: "#121212"
radius: 3
border.width: 2
border.color: "#00b4ef"
}
PropertyChanges {
target: letter
color: "#00b4ef"
style: Text.Normal
}
},
State {
name: "mouseClicked"
PropertyChanges {
target: roundedRect
color: "#1080b8"
border.width: 2
border.color: "#00b4ef"
}
PropertyChanges {
target: letter
color: "#121212"
styleColor: "#00000000"
style: Text.Normal
}
},
State {
name: "mouseDepressed"
PropertyChanges {
target: roundedRect
color: "#0578b1"
border.width: 0
}
PropertyChanges {
target: letter
color: "#121212"
styleColor: "#00000000"
style: Text.Normal
}
}
]
Key {
}

View file

@ -1,354 +1,4 @@
//
// FileDialog.qml
//
// Created by Anthony Thibault on 31 Oct 2016
// Copyright 2016 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import controlsUit 1.0
import QtQuick 2.7
import QtGraphicalEffects 1.0
import "."
Rectangle {
id: keyboardBase
objectName: "keyboard"
anchors.left: parent.left
anchors.right: parent.right
color: "#252525"
property bool raised: false
property bool numeric: false
readonly property int keyboardRowHeight: 50
readonly property int keyboardWidth: 480
readonly property int keyboardHeight: 200
readonly property int mirrorTextHeight: keyboardRowHeight
property bool password: false
property alias mirroredText: mirrorText.text
property bool showMirrorText: true
readonly property int raisedHeight: keyboardHeight + (showMirrorText ? keyboardRowHeight : 0)
height: enabled && raised ? raisedHeight : 0
visible: enabled && raised
property bool shiftMode: false
property bool numericShiftMode: false
onRaisedChanged: {
mirroredText = "";
}
function resetShiftMode(mode) {
shiftMode = mode;
shiftKey.resetToggledMode(mode);
}
function toUpper(str) {
if (str === ",") {
return "<";
} else if (str === ".") {
return ">";
} else if (str === "/") {
return "?";
} else if (str === "-") {
return "_";
} else {
return str.toUpperCase(str);
}
}
function toLower(str) {
if (str === "<") {
return ",";
} else if (str === ">") {
return ".";
} else if (str === "?") {
return "/";
} else if (str === "_") {
return "-";
} else {
return str.toLowerCase(str);
}
}
function forEachKey(func) {
var i, j;
for (i = 0; i < columnAlpha.children.length; i++) {
var row = columnAlpha.children[i];
for (j = 0; j < row.children.length; j++) {
var key = row.children[j];
func(key);
}
}
}
onShiftModeChanged: {
forEachKey(function (key) {
if (/[a-z-_]/i.test(key.glyph)) {
if (shiftMode) {
key.glyph = keyboardBase.toUpper(key.glyph);
} else {
key.glyph = keyboardBase.toLower(key.glyph);
}
}
});
}
function alphaKeyClickedHandler(mouseArea) {
// reset shift mode to false after first keypress
if (shiftMode) {
resetShiftMode(false);
}
}
Component.onCompleted: {
// hook up callbacks to every ascii key
forEachKey(function (key) {
if (/^[a-z]+$/i.test(key.glyph)) {
key.mouseArea.onClicked.connect(alphaKeyClickedHandler);
}
});
}
Rectangle {
height: showMirrorText ? mirrorTextHeight : 0
width: keyboardWidth
color: "#252525"
anchors.horizontalCenter: parent.horizontalCenter
TextInput {
id: mirrorText
visible: showMirrorText
font.family: "Fira Sans"
font.pixelSize: 20
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
color: "#00B4EF";
anchors.left: parent.left
anchors.leftMargin: 10
anchors.right: parent.right
anchors.top: parent.top
anchors.bottom: parent.bottom
wrapMode: Text.WordWrap
readOnly: false // we need this to allow control to accept QKeyEvent
selectByMouse: false
echoMode: password ? TextInput.Password : TextInput.Normal
Keys.onPressed: {
if (event.key == Qt.Key_Return || event.key == Qt.Key_Space) {
mirrorText.text = "";
event.accepted = true;
}
}
MouseArea { // ... and we need this mouse area to prevent mirrorText from getting mouse events to ensure it will never get focus
anchors.fill: parent
}
}
}
Rectangle {
id: keyboardRect
y: showMirrorText ? mirrorTextHeight : 0
width: keyboardWidth
height: keyboardHeight
color: "#252525"
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
anchors.bottomMargin: 0
Column {
id: columnAlpha
width: keyboardWidth
height: keyboardHeight
visible: !numeric
Row {
width: keyboardWidth
height: keyboardRowHeight
anchors.left: parent.left
anchors.leftMargin: 4
Key { width: 43; glyph: "q"; }
Key { width: 43; glyph: "w"; }
Key { width: 43; glyph: "e"; }
Key { width: 43; glyph: "r"; }
Key { width: 43; glyph: "t"; }
Key { width: 43; glyph: "y"; }
Key { width: 43; glyph: "u"; }
Key { width: 43; glyph: "i"; }
Key { width: 43; glyph: "o"; }
Key { width: 43; glyph: "p"; }
Key { width: 43; glyph: "←"; }
}
Row {
width: keyboardWidth
height: keyboardRowHeight
anchors.left: parent.left
anchors.leftMargin: 20
Key { width: 43; glyph: "a"; }
Key { width: 43; glyph: "s"; }
Key { width: 43; glyph: "d"; }
Key { width: 43; glyph: "f"; }
Key { width: 43; glyph: "g"; }
Key { width: 43; glyph: "h"; }
Key { width: 43; glyph: "j"; }
Key { width: 43; glyph: "k"; }
Key { width: 43; glyph: "l"; }
Key { width: 70; glyph: "⏎"; }
}
Row {
width: keyboardWidth
height: keyboardRowHeight
anchors.left: parent.left
anchors.leftMargin: 4
Key {
id: shiftKey
width: 43
glyph: "⇪"
toggle: true
onToggledChanged: shiftMode = toggled
}
Key { width: 43; glyph: "z"; }
Key { width: 43; glyph: "x"; }
Key { width: 43; glyph: "c"; }
Key { width: 43; glyph: "v"; }
Key { width: 43; glyph: "b"; }
Key { width: 43; glyph: "n"; }
Key { width: 43; glyph: "m"; }
Key { width: 43; glyph: "-"; }
Key { width: 43; glyph: "/"; }
Key { width: 43; glyph: "?"; }
}
Row {
width: keyboardWidth
height: keyboardRowHeight
anchors.left: parent.left
anchors.leftMargin: 4
Key {
width: 70
glyph: "123"
mouseArea.onClicked: keyboardBase.parent.punctuationMode = true
}
Key { width: 231; glyph: " "; }
Key { width: 43; glyph: ","; }
Key { width: 43; glyph: "."; }
Key {
fontFamily: "hifi-glyphs";
fontPixelSize: 48;
letterAnchors.topMargin: -4;
verticalAlignment: Text.AlignVCenter;
width: 86; glyph: "\ue02b";
}
}
}
Column {
id: columnNumeric
width: keyboardWidth
height: keyboardHeight
visible: numeric
Row {
width: keyboardWidth
height: keyboardRowHeight
anchors.left: parent.left
anchors.leftMargin: 4
Key { width: 43; glyph: "1"; }
Key { width: 43; glyph: "2"; }
Key { width: 43; glyph: "3"; }
Key { width: 43; glyph: "4"; }
Key { width: 43; glyph: "5"; }
Key { width: 43; glyph: "6"; }
Key { width: 43; glyph: "7"; }
Key { width: 43; glyph: "8"; }
Key { width: 43; glyph: "9"; }
Key { width: 43; glyph: "0"; }
Key { width: 43; glyph: "←"; }
}
Row {
width: keyboardWidth
height: keyboardRowHeight
anchors.left: parent.left
anchors.leftMargin: 4
Key { width: 43; glyph: "!"; }
Key { width: 43; glyph: "@"; }
Key { width: 43; glyph: "#"; }
Key { width: 43; glyph: "$"; }
Key { width: 43; glyph: "%"; }
Key { width: 43; glyph: "^"; }
Key { width: 43; glyph: "&"; }
Key { width: 43; glyph: "*"; }
Key { width: 43; glyph: "("; }
Key { width: 43; glyph: ")"; }
Key { width: 43; glyph: "⏎"; }
}
Row {
width: keyboardWidth
height: keyboardRowHeight
anchors.left: parent.left
anchors.leftMargin: 4
Key {
id: numericShiftKey
width: 43
glyph: "\u21E8"
toggle: true
onToggledChanged: numericShiftMode = toggled
}
Key { width: 43; glyph: numericShiftMode ? "`" : "+"; }
Key { width: 43; glyph: numericShiftMode ? "~" : "-"; }
Key { width: 43; glyph: numericShiftMode ? "\u00A3" : "="; }
Key { width: 43; glyph: numericShiftMode ? "\u20AC" : ";"; }
Key { width: 43; glyph: numericShiftMode ? "\u00A5" : ":"; }
Key { width: 43; glyph: numericShiftMode ? "<" : "'"; }
Key { width: 43; glyph: numericShiftMode ? ">" : "\""; }
Key { width: 43; glyph: numericShiftMode ? "[" : "{"; }
Key { width: 43; glyph: numericShiftMode ? "]" : "}"; }
Key { width: 43; glyph: numericShiftMode ? "\\" : "|"; }
}
Row {
width: keyboardWidth
height: keyboardRowHeight
anchors.left: parent.left
anchors.leftMargin: 4
Key {
width: 70
glyph: "abc"
mouseArea.onClicked: keyboardBase.parent.punctuationMode = false
}
Key { width: 231; glyph: " "; }
Key { width: 43; glyph: ","; }
Key { width: 43; glyph: "."; }
Key {
fontFamily: "hifi-glyphs";
fontPixelSize: 48;
letterAnchors.topMargin: -4;
verticalAlignment: Text.AlignVCenter;
width: 86; glyph: "\ue02b";
}
}
}
}
Keyboard {
}

View file

@ -1,35 +1,4 @@
//
// Label.qml
//
// Created by David Rowe on 26 Feb 2016
// Copyright 2016 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import controlsUit 1.0
import QtQuick 2.7
import "../styles-uit"
RalewaySemiBold {
HifiConstants { id: hifi }
property int colorScheme: hifi.colorSchemes.light
size: hifi.fontSizes.inputLabel
color: {
if (colorScheme === hifi.colorSchemes.dark) {
if (enabled) {
hifi.colors.lightGrayText
} else {
hifi.colors.baseGrayHighlight
}
} else {
if (enabled) {
hifi.colors.lightGray
} else {
hifi.colors.lightGrayText
}
}
}
Label {
}

View file

@ -1,41 +1,4 @@
//
// QueuedButton.qml
// -- original Button.qml + signal timer workaround --ht
// Created by David Rowe on 16 Feb 2016
// Copyright 2016 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import controlsUit 1.0
import QtQuick 2.5
import "../styles-uit"
import "." as HifiControls
HifiControls.Button {
// FIXME: THIS WORKAROUND MIGRATED/CONSOLIDATED FROM RUNNINGSCRIPTS.QML
// For some reason trigginer an API that enters
// an internal event loop directly from the button clicked
// trigger below causes the appliction to behave oddly.
// Most likely because the button onClicked handling is never
// completed until the function returns.
// FIXME find a better way of handling the input dialogs that
// doesn't trigger this.
// NOTE: dialogs that need to use this workaround can connect via
// onQueuedClicked: ...
// instead of:
// onClicked: ...
signal clickedQueued()
Timer {
id: fromTimer
interval: 5
repeat: false
running: false
onTriggered: clickedQueued()
}
onClicked: fromTimer.running = true
QueuedButton {
}

View file

@ -1,93 +1,4 @@
//
// RadioButton.qml
//
// Created by Cain Kilgore on 20th July 2017
// Copyright 2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import controlsUit 1.0
import QtQuick 2.5
import QtQuick.Controls 2.2 as Original
import "../styles-uit"
import "../controls-uit" as HifiControls
import TabletScriptingInterface 1.0
Original.RadioButton {
id: radioButton
HifiConstants { id: hifi }
hoverEnabled: true
property int colorScheme: hifi.colorSchemes.light
readonly property bool isLightColorScheme: colorScheme == hifi.colorSchemes.light
property real letterSpacing: 1
property int fontSize: hifi.fontSizes.inputLabel
property int boxSize: defaultBoxSize
property real scaleFactor: boxSize / defaultBoxSize
readonly property int defaultBoxSize: 14
readonly property int boxRadius: 3 * scaleFactor
readonly property int checkSize: 10 * scaleFactor
readonly property int checkRadius: 2 * scaleFactor
readonly property int indicatorRadius: 7 * scaleFactor
onClicked: {
Tablet.playSound(TabletEnums.ButtonClick);
}
onHoveredChanged: {
if (hovered) {
Tablet.playSound(TabletEnums.ButtonHover);
}
}
indicator: Rectangle {
id: box
width: boxSize
height: boxSize
radius: indicatorRadius
x: radioButton.leftPadding
y: parent.height / 2 - height / 2
gradient: Gradient {
GradientStop {
position: 0.2
color: pressed || hovered
? (radioButton.isLightColorScheme ? hifi.colors.checkboxDarkStart : hifi.colors.checkboxLightStart)
: (radioButton.isLightColorScheme ? hifi.colors.checkboxLightStart : hifi.colors.checkboxDarkStart)
}
GradientStop {
position: 1.0
color: pressed || hovered
? (radioButton.isLightColorScheme ? hifi.colors.checkboxDarkFinish : hifi.colors.checkboxLightFinish)
: (radioButton.isLightColorScheme ? hifi.colors.checkboxLightFinish : hifi.colors.checkboxDarkFinish)
}
}
Rectangle {
id: check
width: checkSize
height: checkSize
radius: indicatorRadius
anchors.centerIn: parent
color: "#00B4EF"
border.width: 1
border.color: "#36CDFF"
visible: checked && !pressed || !checked && pressed
}
}
contentItem: RalewaySemiBold {
text: radioButton.text
size: radioButton.fontSize
font.letterSpacing: letterSpacing
color: isLightColorScheme ? hifi.colors.lightGray : hifi.colors.lightGrayText
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
leftPadding: radioButton.indicator.width + radioButton.spacing
}
RadioButton {
}

View file

@ -1,41 +1,4 @@
//
// ScrollBar.qml
//
// Created by Vlad Stelmahovsky on 27 Nov 2017
// Copyright 2016 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import QtQuick 2.7
import QtQuick.Controls 2.2
import "../styles-uit"
import controlsUit 1.0
ScrollBar {
visible: size < 1.0
HifiConstants { id: hifi }
property int colorScheme: hifi.colorSchemes.light
readonly property bool isLightColorScheme: colorScheme == hifi.colorSchemes.light
background: Item {
implicitWidth: hifi.dimensions.scrollbarBackgroundWidth
Rectangle {
anchors { fill: parent; topMargin: 3; bottomMargin: 3 }
radius: hifi.dimensions.scrollbarHandleWidth/2
color: isLightColorScheme ? hifi.colors.tableScrollBackgroundLight
: hifi.colors.tableScrollBackgroundDark
}
}
contentItem: Item {
implicitWidth: hifi.dimensions.scrollbarHandleWidth
Rectangle {
anchors { fill: parent; topMargin: 1; bottomMargin: 1 }
radius: hifi.dimensions.scrollbarHandleWidth/2
color: isLightColorScheme ? hifi.colors.tableScrollHandleLight : hifi.colors.tableScrollHandleDark
}
}
}

View file

@ -1,44 +1,4 @@
//
// Separator.qml
//
// Created by Zach Fox on 2017-06-06
// Copyright 2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import controlsUit 1.0
import QtQuick 2.5
import "../styles-uit"
Item {
property int colorScheme: 0;
readonly property var topColor: [ hifi.colors.baseGrayShadow, hifi.colors.faintGray, "#89858C" ];
readonly property var bottomColor: [ hifi.colors.baseGrayHighlight, hifi.colors.faintGray, "#89858C" ];
// Size
height: colorScheme === 0 ? 2 : 1;
Rectangle {
// Size
width: parent.width;
height: 1;
// Anchors
anchors.left: parent.left;
anchors.bottom: parent.bottom;
// Style
color: topColor[colorScheme];
}
Rectangle {
visible: colorScheme === 0;
// Size
width: parent.width;
height: 1;
// Anchors
anchors.left: parent.left;
anchors.bottom: parent.bottom;
anchors.bottomMargin: -height;
// Style
color: bottomColor[colorScheme];
}
Separator {
}

View file

@ -1,98 +1,4 @@
//
// Slider.qml
//
// Created by David Rowe on 27 Feb 2016
// Copyright 2016 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import QtQuick 2.7
import QtQuick.Controls 2.2
import "../styles-uit"
import "../controls-uit" as HifiControls
import controlsUit 1.0
Slider {
id: slider
property int colorScheme: hifi.colorSchemes.light
readonly property bool isLightColorScheme: colorScheme == hifi.colorSchemes.light
property string label: ""
property real controlHeight: height + (sliderLabel.visible ? sliderLabel.height + sliderLabel.anchors.bottomMargin : 0)
property alias minimumValue: slider.from
property alias maximumValue: slider.to
property alias step: slider.stepSize
property bool tickmarksEnabled: false
height: hifi.fontSizes.textFieldInput + 14 // Match height of TextField control.
y: sliderLabel.visible ? sliderLabel.height + sliderLabel.anchors.bottomMargin : 0
background: Rectangle {
x: slider.leftPadding
y: slider.topPadding + slider.availableHeight / 2 - height / 2
implicitWidth: 50
implicitHeight: hifi.dimensions.sliderGrooveHeight
width: slider.availableWidth
height: implicitHeight
radius: height / 2
color: isLightColorScheme ? hifi.colors.sliderGutterLight : hifi.colors.sliderGutterDark
Rectangle {
width: slider.visualPosition * parent.width
height: parent.height
radius: height / 2
gradient: Gradient {
GradientStop { position: 0.0; color: hifi.colors.blueAccent }
GradientStop { position: 1.0; color: hifi.colors.primaryHighlight }
}
}
}
handle: Rectangle {
x: slider.leftPadding + slider.visualPosition * (slider.availableWidth - width)
y: slider.topPadding + slider.availableHeight / 2 - height / 2
implicitWidth: hifi.dimensions.sliderHandleSize
implicitHeight: hifi.dimensions.sliderHandleSize
radius: height / 2
border.width: 1
border.color: isLightColorScheme ? hifi.colors.sliderBorderLight : hifi.colors.sliderBorderDark
gradient: Gradient {
GradientStop {
position: 0.0
color: pressed || hovered
? (isLightColorScheme ? hifi.colors.sliderDarkStart : hifi.colors.sliderLightStart )
: (isLightColorScheme ? hifi.colors.sliderLightStart : hifi.colors.sliderDarkStart )
}
GradientStop {
position: 1.0
color: pressed || hovered
? (isLightColorScheme ? hifi.colors.sliderDarkFinish : hifi.colors.sliderLightFinish )
: (isLightColorScheme ? hifi.colors.sliderLightFinish : hifi.colors.sliderDarkFinish )
}
}
Rectangle {
height: parent.height - 2
width: height
radius: height / 2
anchors.centerIn: parent
color: hifi.colors.transparent
border.width: 1
border.color: hifi.colors.black
}
}
HifiControls.Label {
id: sliderLabel
text: slider.label
colorScheme: slider.colorScheme
anchors.left: parent.left
anchors.bottom: parent.top
anchors.bottomMargin: 2
visible: label != ""
}
}
}

View file

@ -1,185 +1,4 @@
//
// SpinBox.qml
//
// Created by David Rowe on 26 Feb 2016
// Copyright 2016 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import QtQuick 2.7
import QtQuick.Controls 2.2
import "../styles-uit"
import "../controls-uit" as HifiControls
import controlsUit 1.0
SpinBox {
id: spinBox
HifiConstants {
id: hifi
}
inputMethodHints: Qt.ImhFormattedNumbersOnly
property int colorScheme: hifi.colorSchemes.light
readonly property bool isLightColorScheme: colorScheme === hifi.colorSchemes.light
property string label: ""
property string suffix: ""
property string labelInside: ""
property color colorLabelInside: hifi.colors.white
property color backgroundColor: isLightColorScheme
? (spinBox.activeFocus ? hifi.colors.white : hifi.colors.lightGray)
: (spinBox.activeFocus ? hifi.colors.black : hifi.colors.baseGrayShadow)
property real controlHeight: height + (spinBoxLabel.visible ? spinBoxLabel.height + spinBoxLabel.anchors.bottomMargin : 0)
property int decimals: 2;
property real factor: Math.pow(10, decimals)
property real minimumValue: 0.0
property real maximumValue: 0.0
property real realValue: 0.0
property real realFrom: minimumValue
property real realTo: maximumValue
property real realStepSize: 1.0
signal editingFinished()
implicitHeight: height
implicitWidth: width
editable: true
padding: 0
leftPadding: 0
rightPadding: padding + (up.indicator ? up.indicator.width : 0)
topPadding: 0
bottomPadding: 0
locale: Qt.locale("en_US")
onValueModified: realValue = value/factor
onValueChanged: realValue = value/factor
onRealValueChanged: {
var newValue = Math.round(realValue*factor);
if(value != newValue) {
value = newValue;
}
}
stepSize: realStepSize*factor
to : realTo*factor
from : realFrom*factor
font.family: "Fira Sans SemiBold"
font.pixelSize: hifi.fontSizes.textFieldInput
height: hifi.fontSizes.textFieldInput + 13 // Match height of TextField control.
y: spinBoxLabel.visible ? spinBoxLabel.height + spinBoxLabel.anchors.bottomMargin : 0
background: Rectangle {
color: backgroundColor
border.color: spinBoxLabelInside.visible ? spinBoxLabelInside.color : hifi.colors.primaryHighlight
border.width: spinBox.activeFocus ? spinBoxLabelInside.visible ? 2 : 1 : 0
}
validator: DoubleValidator {
bottom: Math.min(spinBox.from, spinBox.to)
top: Math.max(spinBox.from, spinBox.to)
}
textFromValue: function(value, locale) {
return parseFloat(value/factor).toFixed(decimals);
}
valueFromText: function(text, locale) {
return Number.fromLocaleString(locale, text)*factor;
}
contentItem: TextInput {
z: 2
color: isLightColorScheme
? (spinBox.activeFocus ? hifi.colors.black : hifi.colors.lightGray)
: (spinBox.activeFocus ? hifi.colors.white : hifi.colors.lightGrayText)
selectedTextColor: hifi.colors.black
selectionColor: hifi.colors.primaryHighlight
text: spinBox.textFromValue(spinBox.value, spinBox.locale) + suffix
inputMethodHints: spinBox.inputMethodHints
validator: spinBox.validator
verticalAlignment: Qt.AlignVCenter
leftPadding: spinBoxLabelInside.visible ? 30 : hifi.dimensions.textPadding
//rightPadding: hifi.dimensions.spinnerSize
width: spinBox.width - hifi.dimensions.spinnerSize
onEditingFinished: spinBox.editingFinished()
}
up.indicator: Item {
x: spinBox.width - implicitWidth - 5
y: 1
clip: true
implicitHeight: spinBox.implicitHeight/2
implicitWidth: spinBox.implicitHeight/2
HiFiGlyphs {
anchors.centerIn: parent
text: hifi.glyphs.caratUp
size: hifi.dimensions.spinnerSize
color: spinBox.up.pressed || spinBox.up.hovered ? (isLightColorScheme ? hifi.colors.black : hifi.colors.white) : hifi.colors.gray
}
}
up.onPressedChanged: {
if(value) {
spinBox.forceActiveFocus();
}
}
down.indicator: Item {
x: spinBox.width - implicitWidth - 5
y: spinBox.implicitHeight/2
clip: true
implicitHeight: spinBox.implicitHeight/2
implicitWidth: spinBox.implicitHeight/2
HiFiGlyphs {
anchors.centerIn: parent
text: hifi.glyphs.caratDn
size: hifi.dimensions.spinnerSize
color: spinBox.down.pressed || spinBox.down.hovered ? (isLightColorScheme ? hifi.colors.black : hifi.colors.white) : hifi.colors.gray
}
}
down.onPressedChanged: {
if(value) {
spinBox.forceActiveFocus();
}
}
HifiControls.Label {
id: spinBoxLabel
text: spinBox.label
colorScheme: spinBox.colorScheme
anchors.left: parent.left
anchors.bottom: parent.top
anchors.bottomMargin: 4
visible: label != ""
}
HifiControls.Label {
id: spinBoxLabelInside
text: spinBox.labelInside
anchors.left: parent.left
anchors.leftMargin: 10
font.bold: true
anchors.verticalCenter: parent.verticalCenter
color: spinBox.colorLabelInside
visible: spinBox.labelInside != ""
}
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.NoButton
onWheel: {
if (wheel.angleDelta.y > 0)
value += stepSize
else
value -= stepSize
}
}
}

View file

@ -1,160 +1,4 @@
//
// Switch.qml
//
// Created by Zach Fox on 2017-06-06
// Copyright 2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import controlsUit 1.0
import QtQuick 2.7
import QtQuick.Controls 2.2 as Original
import "../styles-uit"
Item {
id: rootSwitch;
property int colorScheme: hifi.colorSchemes.light;
readonly property bool isLightColorScheme: colorScheme == hifi.colorSchemes.light;
property int switchWidth: 70;
readonly property int switchRadius: height/2;
property string labelTextOff: "";
property string labelGlyphOffText: "";
property int labelGlyphOffSize: 32;
property string labelTextOn: "";
property string labelGlyphOnText: "";
property int labelGlyphOnSize: 32;
property alias checked: originalSwitch.checked;
signal onCheckedChanged;
signal clicked;
Original.Switch {
id: originalSwitch;
focusPolicy: Qt.ClickFocus
anchors.top: rootSwitch.top;
anchors.left: rootSwitch.left;
anchors.leftMargin: rootSwitch.width/2 - rootSwitch.switchWidth/2;
onCheckedChanged: rootSwitch.onCheckedChanged();
onClicked: rootSwitch.clicked();
hoverEnabled: true
topPadding: 3;
leftPadding: 3;
rightPadding: 3;
bottomPadding: 3;
onHoveredChanged: {
if (hovered) {
switchHandle.color = hifi.colors.blueHighlight;
} else {
switchHandle.color = hifi.colors.lightGray;
}
}
background: Rectangle {
color: "#252525";
implicitWidth: rootSwitch.switchWidth;
implicitHeight: rootSwitch.height;
radius: rootSwitch.switchRadius;
}
indicator: Rectangle {
id: switchHandle;
implicitWidth: rootSwitch.height - originalSwitch.topPadding - originalSwitch.bottomPadding;
implicitHeight: implicitWidth;
radius: implicitWidth/2;
border.color: hifi.colors.lightGrayText;
color: hifi.colors.lightGray;
//x: originalSwitch.leftPadding
x: Math.max(0, Math.min(parent.width - width, originalSwitch.visualPosition * parent.width - (width / 2)))
y: parent.height / 2 - height / 2
Behavior on x {
enabled: !originalSwitch.down
SmoothedAnimation { velocity: 200 }
}
}
}
// OFF Label
Item {
anchors.right: originalSwitch.left;
anchors.rightMargin: 10;
anchors.top: rootSwitch.top;
height: rootSwitch.height;
RalewaySemiBold {
id: labelOff;
text: labelTextOff;
size: hifi.fontSizes.inputLabel;
color: originalSwitch.checked ? hifi.colors.lightGrayText : "#FFFFFF";
anchors.top: parent.top;
anchors.right: parent.right;
width: paintedWidth;
height: parent.height;
verticalAlignment: Text.AlignVCenter;
}
HiFiGlyphs {
id: labelGlyphOff;
text: labelGlyphOffText;
size: labelGlyphOffSize;
color: labelOff.color;
anchors.top: parent.top;
anchors.topMargin: 2;
anchors.right: labelOff.left;
anchors.rightMargin: 4;
}
MouseArea {
anchors.top: parent.top;
anchors.bottom: parent.bottom;
anchors.left: labelGlyphOff.left;
anchors.right: labelOff.right;
onClicked: {
originalSwitch.checked = false;
}
}
}
// ON Label
Item {
anchors.left: originalSwitch.right;
anchors.leftMargin: 10;
anchors.top: rootSwitch.top;
height: rootSwitch.height;
RalewaySemiBold {
id: labelOn;
text: labelTextOn;
size: hifi.fontSizes.inputLabel;
color: originalSwitch.checked ? "#FFFFFF" : hifi.colors.lightGrayText;
anchors.top: parent.top;
anchors.left: parent.left;
width: paintedWidth;
height: parent.height;
verticalAlignment: Text.AlignVCenter;
}
HiFiGlyphs {
id: labelGlyphOn;
text: labelGlyphOnText;
size: labelGlyphOnSize;
color: labelOn.color;
anchors.top: parent.top;
anchors.left: labelOn.right;
}
MouseArea {
anchors.top: parent.top;
anchors.bottom: parent.bottom;
anchors.left: labelOn.left;
anchors.right: labelGlyphOn.right;
onClicked: {
originalSwitch.checked = true;
}
}
}
Switch {
}

View file

@ -1,165 +1,4 @@
//
// Table.qml
//
// Created by David Rowe on 18 Feb 2016
// Copyright 2016 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import controlsUit 1.0
import QtQuick 2.5
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import QtQuick.Controls 2.3 as QQC2
import "../styles-uit"
TableView {
id: tableView
property int colorScheme: hifi.colorSchemes.light
readonly property bool isLightColorScheme: colorScheme == hifi.colorSchemes.light
property bool expandSelectedRow: false
property bool centerHeaderText: false
readonly property real headerSpacing: 3 //spacing between sort indicator and table header title
property var titlePaintedPos: [] // storing extra data position behind painted
// title text and sort indicatorin table's header
signal titlePaintedPosSignal(int column) //signal that extradata position gets changed
model: ListModel { }
Component.onCompleted: {
if (flickableItem !== null && flickableItem !== undefined) {
tableView.flickableItem.QQC2.ScrollBar.vertical = scrollbar
}
}
QQC2.ScrollBar {
id: scrollbar
parent: tableView.flickableItem
policy: QQC2.ScrollBar.AsNeeded
orientation: Qt.Vertical
visible: size < 1.0
topPadding: tableView.headerVisible ? hifi.dimensions.tableHeaderHeight + 1 : 1
anchors.top: tableView.top
anchors.left: tableView.right
anchors.bottom: tableView.bottom
background: Item {
implicitWidth: hifi.dimensions.scrollbarBackgroundWidth
Rectangle {
anchors {
fill: parent;
topMargin: tableView.headerVisible ? hifi.dimensions.tableHeaderHeight : 0
}
color: isLightColorScheme ? hifi.colors.tableScrollBackgroundLight
: hifi.colors.tableScrollBackgroundDark
}
}
contentItem: Item {
implicitWidth: hifi.dimensions.scrollbarHandleWidth
Rectangle {
anchors.fill: parent
radius: (width - 4)/2
color: isLightColorScheme ? hifi.colors.tableScrollHandleLight : hifi.colors.tableScrollHandleDark
}
}
}
headerVisible: false
headerDelegate: Rectangle {
height: hifi.dimensions.tableHeaderHeight
color: isLightColorScheme ? hifi.colors.tableBackgroundLight : hifi.colors.tableBackgroundDark
RalewayRegular {
id: titleText
x: centerHeaderText ? (parent.width - paintedWidth -
((sortIndicatorVisible &&
sortIndicatorColumn === styleData.column) ?
(titleSort.paintedWidth / 5 + tableView.headerSpacing) : 0)) / 2 :
hifi.dimensions.tablePadding
text: styleData.value
size: hifi.fontSizes.tableHeading
font.capitalization: Font.AllUppercase
color: hifi.colors.baseGrayHighlight
horizontalAlignment: (centerHeaderText ? Text.AlignHCenter : Text.AlignLeft)
anchors.verticalCenter: parent.verticalCenter
}
//actual image of sort indicator in glyph font only 20% of real font size
//i.e. if the charachter size set to 60 pixels, actual image is 12 pixels
HiFiGlyphs {
id: titleSort
text: sortIndicatorOrder == Qt.AscendingOrder ? hifi.glyphs.caratUp : hifi.glyphs.caratDn
color: hifi.colors.darkGray
opacity: 0.6;
size: hifi.fontSizes.tableHeadingIcon
anchors.verticalCenter: titleText.verticalCenter
anchors.left: titleText.right
anchors.leftMargin: -(hifi.fontSizes.tableHeadingIcon / 2.5) + tableView.headerSpacing
visible: sortIndicatorVisible && sortIndicatorColumn === styleData.column
onXChanged: {
titlePaintedPos[styleData.column] = titleText.x + titleText.paintedWidth +
paintedWidth / 5 + tableView.headerSpacing*2
titlePaintedPosSignal(styleData.column)
}
}
Rectangle {
width: 1
anchors {
left: parent.left
top: parent.top
topMargin: 1
bottom: parent.bottom
bottomMargin: 2
}
color: isLightColorScheme ? hifi.colors.lightGrayText : hifi.colors.baseGrayHighlight
visible: styleData.column > 0
}
Rectangle {
height: 1
anchors {
left: parent.left
right: parent.right
bottom: parent.bottom
}
color: isLightColorScheme ? hifi.colors.lightGrayText : hifi.colors.baseGrayHighlight
}
}
// Use rectangle to draw border with rounded corners.
frameVisible: false
Rectangle {
color: "#00000000"
anchors { fill: parent; margins: -2 }
border.color: isLightColorScheme ? hifi.colors.lightGrayText : hifi.colors.baseGrayHighlight
border.width: 2
}
anchors.margins: 2 // Shrink TableView to lie within border.
backgroundVisible: true
horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff
verticalScrollBarPolicy: Qt.ScrollBarAlwaysOff
style: TableViewStyle {
// Needed in order for rows to keep displaying rows after end of table entries.
backgroundColor: tableView.isLightColorScheme ? hifi.colors.tableBackgroundLight : hifi.colors.tableBackgroundDark
alternateBackgroundColor: tableView.isLightColorScheme ? hifi.colors.tableRowLightOdd : hifi.colors.tableRowDarkOdd
padding.top: headerVisible ? hifi.dimensions.tableHeaderHeight: 0
}
rowDelegate: Rectangle {
height: (styleData.selected && expandSelectedRow ? 1.8 : 1) * hifi.dimensions.tableRowHeight
color: styleData.selected
? hifi.colors.primaryHighlight
: tableView.isLightColorScheme
? (styleData.alternate ? hifi.colors.tableRowLightEven : hifi.colors.tableRowLightOdd)
: (styleData.alternate ? hifi.colors.tableRowDarkEven : hifi.colors.tableRowDarkOdd)
}
Table {
}

View file

@ -1,138 +1,4 @@
//
// ContentSection.qml
//
// Created by Dante Ruiz on 13 Feb 2017
// Copyright 2016 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import controlsUit 1.0
import QtQuick 2.5
import QtGraphicalEffects 1.0
import "../styles-uit"
Column {
property string name: "Content Section"
property bool isFirst: false
property bool isCollapsible: false // Set at creation.
property bool isCollapsed: false
spacing: 0 // Defer spacing decisions to individual controls.
anchors {
left: parent.left
leftMargin: hifi.dimensions.contentMargin.x
right: parent.right
rightMargin: hifi.dimensions.contentMargin.x
}
function toggleCollapsed() {
if (isCollapsible) {
isCollapsed = !isCollapsed;
for (var i = 1; i < children.length; i++) {
children[i].visible = !isCollapsed;
}
}
}
Item {
id: sectionName
anchors.left: parent.left
anchors.right: parent.right
height: leadingSpace.height + topBar.height + heading.height + bottomBar.height
Item {
id: leadingSpace
width: 1
height: isFirst ? 7 : 0
anchors.top: parent.top
}
Item {
id: topBar
visible: !isFirst
height: visible ? 2 : 0
anchors.top: leadingSpace.bottom
Rectangle {
id: shadow
width: 480
height: 1
color: hifi.colors.baseGrayShadow
x: -hifi.dimensions.contentMargin.x
}
Rectangle {
width: 480
height: 1
color: hifi.colors.baseGrayHighlight
x: -hifi.dimensions.contentMargin.x
anchors.top: shadow.bottom
}
}
Item {
id: heading
anchors {
left: parent.left
right: parent.right
top: topBar.bottom
}
height: isCollapsible ? 36 : 28
RalewayRegular {
id: title
anchors {
left: parent.left
top: parent.top
topMargin: 12
}
size: hifi.fontSizes.sectionName
font.capitalization: Font.AllUppercase
text: name
color: hifi.colors.lightGrayText
}
HiFiGlyphs {
anchors {
top: title.top
topMargin: -9
right: parent.right
rightMargin: -4
}
size: hifi.fontSizes.disclosureButton
text: isCollapsed ? hifi.glyphs.disclosureButtonExpand : hifi.glyphs.disclosureButtonCollapse
color: hifi.colors.lightGrayText
visible: isCollapsible
}
MouseArea {
// Events are propogated so that any active control is defocused.
anchors.fill: parent
propagateComposedEvents: true
onPressed: {
toggleCollapsed();
mouse.accepted = false;
}
}
}
LinearGradient {
id: bottomBar
visible: false
width: 480
height: visible ? 4 : 0
x: -hifi.dimensions.contentMargin.x
anchors.top: heading.bottom
start: Qt.point(0, 0)
end: Qt.point(0, 4)
gradient: Gradient {
GradientStop { position: 0.0; color: hifi.colors.darkGray }
GradientStop { position: 1.0; color: hifi.colors.baseGray } // Equivalent of darkGray0 over baseGray background.
}
cached: true
}
}
TabletContentSection {
}

View file

@ -1,34 +1,4 @@
//
// TabletHeader.qml
//
// Created by David Rowe on 11 Mar 2017.
// Copyright 2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html
//
import controlsUit 1.0
import QtQuick 2.5
import "../styles-uit"
Rectangle {
property string title: ""
HifiConstants { id: hifi }
height: hifi.dimensions.tabletMenuHeader
z: 100
color: hifi.colors.darkGray
RalewayBold {
text: title
size: 26
color: hifi.colors.white
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: hifi.dimensions.contentMargin.x
}
TabletHeader {
}

View file

@ -1,65 +1,4 @@
//
// TextField.qml
//
// Created by David Rowe on 21 Apr 2016
// Copyright 2016 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import controlsUit 1.0
import QtQuick 2.5
import "../styles-uit"
import "../controls-uit" as HifiControls
Item {
property string icon: ""
property int iconSize: 30
property string text: ""
property int colorScheme: hifi.colorSchemes.light
readonly property bool isLightColorScheme: colorScheme == hifi.colorSchemes.light
signal clicked()
height: Math.max(glyph.visible ? glyph.height - 4 : 0, string.visible ? string.height : 0)
width: glyph.width + string.anchors.leftMargin + string.width
HiFiGlyphs {
id: glyph
anchors.left: parent.left
anchors.top: parent.top
anchors.topMargin: -2
text: parent.icon
size: parent.iconSize
color: isLightColorScheme
? (mouseArea.containsMouse ? hifi.colors.baseGrayHighlight : hifi.colors.lightGray)
: (mouseArea.containsMouse ? hifi.colors.faintGray : hifi.colors.lightGrayText)
visible: text !== ""
width: visible ? implicitWidth : 0
}
RalewaySemiBold {
id: string
anchors {
left: glyph.visible ? glyph.right : parent.left
leftMargin: visible && glyph.visible ? hifi.dimensions.contentSpacing.x : 0
verticalCenter: glyph.visible ? glyph.verticalCenter : undefined
}
text: parent.text
size: hifi.fontSizes.inputLabel
color: isLightColorScheme
? (mouseArea.containsMouse ? hifi.colors.baseGrayHighlight : hifi.colors.lightGray)
: (mouseArea.containsMouse ? hifi.colors.faintGray : hifi.colors.lightGrayText)
font.underline: true;
visible: text !== ""
}
MouseArea {
id: mouseArea
anchors.fill: parent
hoverEnabled: true
onClicked: parent.clicked()
}
TextAction {
}

View file

@ -1,23 +1,4 @@
//
// TextEdit.qml
//
// Created by Bradley Austin Davis on 24 Apr 2015
// Copyright 2015 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import QtQuick 2.5
import "../styles-uit"
import controlsUit 1.0
TextEdit {
property real size: 32
font.family: "Raleway"
font.weight: Font.DemiBold
font.pointSize: size
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignLeft
}

View file

@ -1,180 +1,4 @@
//
// TextField.qml
//
// Created by David Rowe on 17 Feb 2016
// Copyright 2016 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import QtQuick 2.5
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import "../styles-uit"
import "../controls-uit" as HifiControls
import controlsUit 1.0
TextField {
id: textField
property int colorScheme: hifi.colorSchemes.light
readonly property bool isLightColorScheme: colorScheme == hifi.colorSchemes.light
readonly property bool isFaintGrayColorScheme: colorScheme == hifi.colorSchemes.faintGray
property bool isSearchField: false
property string label: ""
property real controlHeight: height + (textFieldLabel.visible ? textFieldLabel.height + 1 : 0)
property bool hasDefocusedBorder: true;
property bool hasRoundedBorder: false
property int roundedBorderRadius: 4
property bool error: false;
property bool hasClearButton: false;
property string leftPermanentGlyph: "";
property string centerPlaceholderGlyph: "";
placeholderText: textField.placeholderText
font.family: "Fira Sans"
font.pixelSize: hifi.fontSizes.textFieldInput
height: implicitHeight + 3 // Make surrounding box higher so that highlight is vertically centered.
property alias textFieldLabel: textFieldLabel
y: textFieldLabel.visible ? textFieldLabel.height + textFieldLabel.anchors.bottomMargin : 0
// workaround for https://bugreports.qt.io/browse/QTBUG-49297
Keys.onPressed: {
switch (event.key) {
case Qt.Key_Return:
case Qt.Key_Enter:
event.accepted = true;
// emit accepted signal manually
if (acceptableInput) {
accepted();
}
}
}
style: TextFieldStyle {
id: style;
textColor: {
if (isLightColorScheme) {
if (textField.activeFocus) {
hifi.colors.black
} else {
hifi.colors.lightGray
}
} else if (isFaintGrayColorScheme) {
if (textField.activeFocus) {
hifi.colors.black
} else {
hifi.colors.lightGray
}
} else {
if (textField.activeFocus) {
hifi.colors.white
} else {
hifi.colors.lightGrayText
}
}
}
background: Rectangle {
color: {
if (isLightColorScheme) {
if (textField.activeFocus) {
hifi.colors.white
} else {
hifi.colors.textFieldLightBackground
}
} else if (isFaintGrayColorScheme) {
if (textField.activeFocus) {
hifi.colors.white
} else {
hifi.colors.faintGray50
}
} else {
if (textField.activeFocus) {
hifi.colors.black
} else {
hifi.colors.baseGrayShadow
}
}
}
border.color: textField.error ? hifi.colors.redHighlight :
(textField.activeFocus ? hifi.colors.primaryHighlight : (hasDefocusedBorder ? (isFaintGrayColorScheme ? hifi.colors.lightGrayText : hifi.colors.lightGray) : color))
border.width: textField.activeFocus || hasRoundedBorder || textField.error ? 1 : 0
radius: isSearchField ? textField.height / 2 : (hasRoundedBorder ? roundedBorderRadius : 0)
HiFiGlyphs {
text: textField.leftPermanentGlyph;
color: textColor;
size: hifi.fontSizes.textFieldSearchIcon;
anchors.left: parent.left;
anchors.verticalCenter: parent.verticalCenter;
anchors.leftMargin: hifi.dimensions.textPadding - 2;
visible: text;
}
HiFiGlyphs {
text: textField.centerPlaceholderGlyph;
color: textColor;
size: parent.height;
anchors.horizontalCenter: parent.horizontalCenter;
anchors.verticalCenter: parent.verticalCenter;
visible: text && !textField.focus && textField.text === "";
}
HiFiGlyphs {
text: hifi.glyphs.search
color: textColor
size: hifi.fontSizes.textFieldSearchIcon
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
anchors.leftMargin: hifi.dimensions.textPadding - 2
visible: isSearchField
}
HiFiGlyphs {
text: hifi.glyphs.error
color: textColor
size: 40
anchors.right: parent.right
anchors.rightMargin: hifi.dimensions.textPadding - 2
anchors.verticalCenter: parent.verticalCenter
visible: hasClearButton && textField.text !== "";
MouseArea {
anchors.fill: parent;
onClicked: {
textField.text = "";
}
}
}
}
placeholderTextColor: isFaintGrayColorScheme ? hifi.colors.lightGrayText : hifi.colors.lightGray
selectedTextColor: hifi.colors.black
selectionColor: hifi.colors.primaryHighlight
padding.left: hasRoundedBorder ? textField.height / 2 : ((isSearchField || textField.leftPermanentGlyph !== "") ? textField.height - 2 : 0) + hifi.dimensions.textPadding
padding.right: (hasClearButton ? textField.height - 2 : 0) + hifi.dimensions.textPadding
}
HifiControls.Label {
id: textFieldLabel
text: textField.label
colorScheme: textField.colorScheme
anchors.left: parent.left
Binding on anchors.right {
when: textField.right
value: textField.right
}
Binding on wrapMode {
when: textField.right
value: Text.WordWrap
}
anchors.bottom: parent.top
anchors.bottomMargin: 3
visible: label != ""
}
}

View file

@ -1,51 +1,4 @@
//
// ToolTip.qml
//
// Created by Clement on 9/12/17
// Copyright 2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import controlsUit 1.0
import QtQuick 2.5
Item {
property string toolTip
property bool showToolTip: false
Rectangle {
id: toolTipRectangle
anchors.right: parent.right
width: toolTipText.width + 4
height: toolTipText.height + 4
opacity: (toolTip != "" && showToolTip) ? 1 : 0
color: "#ffffaa"
border.color: "#0a0a0a"
Text {
id: toolTipText
text: toolTip
color: "black"
anchors.centerIn: parent
}
Behavior on opacity {
PropertyAnimation {
easing.type: Easing.InOutQuad
duration: 250
}
}
}
MouseArea {
id: mouseArea
anchors.fill: parent
onEntered: showTimer.start()
onExited: { showToolTip = false; showTimer.stop(); }
hoverEnabled: true
}
Timer {
id: showTimer
interval: 250
onTriggered: { showToolTip = true; }
}
}
ToolTip {
}

View file

@ -1,205 +1,4 @@
//
// Tree.qml
//
// Created by David Rowe on 17 Feb 2016
// Copyright 2016 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import controlsUit 1.0
import QtQml.Models 2.2
import QtQuick 2.7
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import QtQuick.Controls 2.2 as QQC2
import "../styles-uit"
TreeView {
id: treeView
property var treeModel: ListModel { }
property bool centerHeaderText: false
property int colorScheme: hifi.colorSchemes.light
readonly property bool isLightColorScheme: colorScheme == hifi.colorSchemes.light
property var modifyEl: function(index, data) { return false; }
model: treeModel
selection: ItemSelectionModel {
id: selectionModel
model: treeModel
}
anchors { left: parent.left; right: parent.right }
headerVisible: false
Component.onCompleted: {
if (flickableItem !== null && flickableItem !== undefined) {
treeView.flickableItem.QQC2.ScrollBar.vertical = scrollbar
}
}
QQC2.ScrollBar {
id: scrollbar
parent: treeView.flickableItem
policy: QQC2.ScrollBar.AsNeeded
orientation: Qt.Vertical
visible: size < 1.0
topPadding: treeView.headerVisible ? hifi.dimensions.tableHeaderHeight + 1 : 1
anchors.top: treeView.top
anchors.left: treeView.right
anchors.bottom: treeView.bottom
background: Item {
implicitWidth: hifi.dimensions.scrollbarBackgroundWidth
Rectangle {
anchors {
fill: parent;
topMargin: treeView.headerVisible ? hifi.dimensions.tableHeaderHeight: 0
}
color: isLightColorScheme ? hifi.colors.tableScrollBackgroundLight
: hifi.colors.tableScrollBackgroundDark
}
}
contentItem: Item {
implicitWidth: hifi.dimensions.scrollbarHandleWidth
Rectangle {
anchors.fill: parent
radius: (width - 4)/2
color: isLightColorScheme ? hifi.colors.tableScrollHandleLight : hifi.colors.tableScrollHandleDark
}
}
}
// Use rectangle to draw border with rounded corners.
frameVisible: false
Rectangle {
color: "#00000000"
anchors.fill: parent
radius: hifi.dimensions.borderRadius
border.color: isLightColorScheme ? hifi.colors.lightGrayText : hifi.colors.baseGrayHighlight
border.width: 2
anchors.margins: -2
}
anchors.margins: 2 // Shrink TreeView to lie within border.
backgroundVisible: true
horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff
verticalScrollBarPolicy: Qt.ScrollBarAlwaysOff
style: TreeViewStyle {
// Needed in order for rows to keep displaying rows after end of table entries.
backgroundColor: parent.isLightColorScheme ? hifi.colors.tableRowLightEven : hifi.colors.tableRowDarkEven
alternateBackgroundColor: parent.isLightColorScheme ? hifi.colors.tableRowLightOdd : hifi.colors.tableRowDarkOdd
headerDelegate: Rectangle {
height: hifi.dimensions.tableHeaderHeight
color: isLightColorScheme ? hifi.colors.tableBackgroundLight : hifi.colors.tableBackgroundDark
RalewayRegular {
id: titleText
text: styleData.value
size: hifi.fontSizes.tableHeading
font.capitalization: Font.AllUppercase
color: hifi.colors.baseGrayHighlight
horizontalAlignment: (centerHeaderText ? Text.AlignHCenter : Text.AlignLeft)
elide: Text.ElideRight
anchors {
left: parent.left
leftMargin: hifi.dimensions.tablePadding
right: sortIndicatorVisible && sortIndicatorColumn === styleData.column ? titleSort.left : parent.right
rightMargin: hifi.dimensions.tablePadding
verticalCenter: parent.verticalCenter
}
}
HiFiGlyphs {
id: titleSort
text: sortIndicatorOrder == Qt.AscendingOrder ? hifi.glyphs.caratUp : hifi.glyphs.caratDn
color: isLightColorScheme ? hifi.colors.darkGray : hifi.colors.baseGrayHighlight
opacity: 0.6;
size: hifi.fontSizes.tableHeadingIcon
anchors {
right: parent.right
verticalCenter: titleText.verticalCenter
}
visible: sortIndicatorVisible && sortIndicatorColumn === styleData.column
}
Rectangle {
width: 1
anchors {
left: parent.left
top: parent.top
topMargin: 1
bottom: parent.bottom
bottomMargin: 2
}
color: isLightColorScheme ? hifi.colors.lightGrayText : hifi.colors.baseGrayHighlight
visible: styleData.column > 0
}
Rectangle {
height: 1
anchors {
left: parent.left
right: parent.right
bottom: parent.bottom
}
color: isLightColorScheme ? hifi.colors.lightGrayText : hifi.colors.baseGrayHighlight
}
}
branchDelegate: HiFiGlyphs {
text: styleData.isExpanded ? hifi.glyphs.caratDn : hifi.glyphs.caratR
size: hifi.fontSizes.carat
color: colorScheme == hifi.colorSchemes.light
? (styleData.selected ? hifi.colors.black : hifi.colors.baseGrayHighlight)
: (styleData.selected ? hifi.colors.black : hifi.colors.lightGrayText)
anchors {
left: parent ? parent.left : undefined
leftMargin: hifi.dimensions.tablePadding / 2
}
}
}
rowDelegate: Rectangle {
height: hifi.dimensions.tableRowHeight
color: styleData.selected
? hifi.colors.primaryHighlight
: treeView.isLightColorScheme
? (styleData.alternate ? hifi.colors.tableRowLightEven : hifi.colors.tableRowLightOdd)
: (styleData.alternate ? hifi.colors.tableRowDarkEven : hifi.colors.tableRowDarkOdd)
}
itemDelegate: FiraSansSemiBold {
anchors {
left: parent ? parent.left : undefined
leftMargin: (2 + styleData.depth) * hifi.dimensions.tablePadding
right: parent ? parent.right : undefined
rightMargin: hifi.dimensions.tablePadding
verticalCenter: parent ? parent.verticalCenter : undefined
}
text: styleData.value
size: hifi.fontSizes.tableText
color: colorScheme == hifi.colorSchemes.light
? (styleData.selected ? hifi.colors.black : hifi.colors.baseGrayHighlight)
: (styleData.selected ? hifi.colors.black : hifi.colors.lightGrayText)
elide: Text.ElideRight
}
Item {
id: unfocusHelper
visible: false
}
onDoubleClicked: isExpanded(index) ? collapse(index) : expand(index)
Tree {
}

View file

@ -1,21 +1,4 @@
//
// VerticalSpacer.qml
//
// Created by David Rowe on 16 Feb 2016
// Copyright 2016 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import controlsUit 1.0
import QtQuick 2.5
import "../styles-uit"
Item {
id: root
property alias size: root.height
width: 1 // Must be non-zero
height: hifi.dimensions.controlInterlineHeight
VerticalSpacer {
}

View file

@ -1,40 +1,4 @@
//
// GlyphButton.qml
//
// Created by Vlad Stelmahovsky on 2017-06-21
// Copyright 2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import controlsUit 1.0
import QtQuick 2.5
import QtQuick.Controls 2.2 as Original
import "../styles-uit"
Original.Button {
id: control
property int colorScheme: hifi.colorSchemes.light
property string glyph: ""
property int size: 32
//colors
readonly property color normalColor: "#AFAFAF"
readonly property color hoverColor: "#00B4EF"
readonly property color clickedColor: "#FFFFFF"
readonly property color disabledColor: "#575757"
background: Item {}
contentItem: HiFiGlyphs {
color: control.enabled ? (control.pressed ? control.clickedColor :
(control.hovered ? control.hoverColor : control.normalColor)) :
control.disabledColor
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
text: control.glyph
size: control.size
}
WebGlyphButton {
}

View file

@ -1,24 +1,4 @@
//
// WebSpinner.qml
//
// Created by David Rowe on 23 May 2017
// Copyright 2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import controlsUit 1.0
import QtQuick 2.5
import QtWebEngine 1.5
AnimatedImage {
property WebEngineView webview: parent
source: "../../icons/loader-snake-64-w.gif"
visible: webview.loading && /^(http.*|)$/i.test(webview.url.toString())
playing: visible
z: 10000
anchors {
horizontalCenter: parent.horizontalCenter
verticalCenter: parent.verticalCenter
}
WebSpinner {
}

View file

@ -1,21 +1,4 @@
//
// WebView.qml
//
// Created by Bradley Austin Davis on 12 Jan 2016
// Copyright 2016 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import controlsUit 1.0
import QtQuick 2.5
import "."
BaseWebView {
onNewViewRequested: {
// Load dialog via OffscreenUi so that JavaScript EventBridge is available.
var browser = OffscreenUi.load("Browser.qml");
request.openIn(browser.webView);
browser.webView.forceActiveFocus();
}
WebView {
}

View file

@ -0,0 +1 @@
this folder exists purely for compatibility reasons and might be deleted in future! please consider using 'import controlsUit 1.0' instead of including this folder

View file

@ -3,7 +3,6 @@ import QtQuick.Controls 2.2 as Original
import "."
import "../styles"
import "../controls-uit"
Original.Button {
id: control

View file

@ -4,7 +4,7 @@ import QtWebChannel 1.0
import QtQuick.Controls 2.2
import "../styles-uit" as StylesUIt
import stylesUit 1.0 as StylesUIt
Item {
id: flick

View file

@ -10,7 +10,7 @@
import Hifi 1.0
import QtQuick 2.4
import "../styles-uit"
import stylesUit 1.0
Rectangle {
property alias text: label.text

View file

@ -1,5 +1,5 @@
import QtQuick 2.7
import "../controls-uit" as HiFiControls
import controlsUit 1.0 as HiFiControls
Item {
id: root

View file

@ -1,8 +1,8 @@
import QtQuick 2.7
import QtWebEngine 1.5
import "../controls-uit" as HiFiControls
import controlsUit 1.0 as HiFiControls
import "../styles" as HifiStyles
import "../styles-uit"
import stylesUit 1.0
Item {
id: root

View file

@ -1,5 +1,5 @@
import QtQuick 2.7
import "../controls-uit" as HiFiControls
import controlsUit 1.0 as HiFiControls
Item {
width: parent !== null ? parent.width : undefined

View file

@ -1,6 +1,6 @@
//
// ImageButton.qml
// interface/resources/qml/controls-uit
// interface/resources/qml/controlsUit
//
// Created by Gabriel Calero & Cristian Duarte on 12 Oct 2017
// Copyright 2017 High Fidelity, Inc.
@ -11,7 +11,7 @@
import QtQuick 2.5
import QtQuick.Layouts 1.3
import "../styles-uit" as HifiStyles
import "../stylesUit" as HifiStyles
Item {
id: button
@ -79,4 +79,4 @@ Item {
}
}
]
}
}

View file

@ -0,0 +1,170 @@
//
// AttachmentsTable.qml
//
// Created by David Rowe on 18 Feb 2016
// Copyright 2016 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import QtQuick 2.5
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import QtQuick.XmlListModel 2.0
import "../stylesUit"
import "." as HifiControls
import "../windows"
import "../hifi/models"
TableView {
id: tableView
property int colorScheme: hifi.colorSchemes.light
readonly property bool isLightColorScheme: colorScheme == hifi.colorSchemes.light
model: S3Model{}
Rectangle {
anchors.fill: parent
visible: tableView.model.status !== XmlListModel.Ready
color: hifi.colors.darkGray0
BusyIndicator {
anchors.centerIn: parent
width: 48; height: 48
running: true
}
}
headerDelegate: Rectangle {
height: hifi.dimensions.tableHeaderHeight
color: hifi.colors.darkGray
border.width: 0.5
border.color: hifi.colors.baseGrayHighlight
RalewayRegular {
id: textHeader
size: hifi.fontSizes.tableHeading
color: hifi.colors.lightGrayText
text: styleData.value
anchors {
horizontalCenter: parent.horizontalCenter
verticalCenter: parent.verticalCenter
}
}
}
// Use rectangle to draw border with rounded corners.
Rectangle {
color: "#00000000"
anchors { fill: parent; margins: -2 }
radius: hifi.dimensions.borderRadius
border.color: hifi.colors.baseGrayHighlight
border.width: 3
}
anchors.margins: 2 // Shrink TableView to lie within border.
backgroundVisible: true
horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff
verticalScrollBarPolicy: Qt.ScrollBarAsNeeded
style: TableViewStyle {
// Needed in order for rows to keep displaying rows after end of table entries.
backgroundColor: parent.isLightColorScheme ? hifi.colors.tableRowLightEven : hifi.colors.tableRowDarkEven
alternateBackgroundColor: parent.isLightColorScheme ? hifi.colors.tableRowLightOdd : hifi.colors.tableRowDarkOdd
handle: Item {
id: scrollbarHandle
implicitWidth: 6
Rectangle {
anchors {
fill: parent
leftMargin: 2 // Move it right
rightMargin: -2 // ""
topMargin: 3 // Shrink vertically
bottomMargin: 3 // ""
}
radius: 3
color: hifi.colors.tableScrollHandleDark
}
}
scrollBarBackground: Item {
implicitWidth: 10
Rectangle {
anchors {
fill: parent
margins: -1 // Expand
}
color: hifi.colors.baseGrayHighlight
}
Rectangle {
anchors {
fill: parent
margins: 1 // Shrink
}
radius: 4
color: hifi.colors.tableScrollBackgroundDark
}
}
incrementControl: Item {
visible: false
}
decrementControl: Item {
visible: false
}
}
rowDelegate: Rectangle {
height: hifi.dimensions.tableRowHeight
color: styleData.selected
? hifi.colors.primaryHighlight
: tableView.isLightColorScheme
? (styleData.alternate ? hifi.colors.tableRowLightEven : hifi.colors.tableRowLightOdd)
: (styleData.alternate ? hifi.colors.tableRowDarkEven : hifi.colors.tableRowDarkOdd)
}
itemDelegate: Item {
anchors {
left: parent ? parent.left : undefined
leftMargin: hifi.dimensions.tablePadding
right: parent ? parent.right : undefined
rightMargin: hifi.dimensions.tablePadding
}
FiraSansSemiBold {
id: textItem
text: styleData.value
size: hifi.fontSizes.tableText
color: colorScheme == hifi.colorSchemes.light
? (styleData.selected ? hifi.colors.black : hifi.colors.baseGrayHighlight)
: (styleData.selected ? hifi.colors.black : hifi.colors.lightGrayText)
anchors {
horizontalCenter: parent.horizontalCenter
verticalCenter: parent.verticalCenter
}
}
}
TableViewColumn {
role: "name"
title: "NAME"
width: parent.width *0.3
horizontalAlignment: Text.AlignHCenter
}
TableViewColumn {
role: "size"
title: "SIZE"
width: parent.width *0.2
horizontalAlignment: Text.AlignHCenter
}
TableViewColumn {
role: "modified"
title: "LAST MODIFIED"
width: parent.width *0.5
horizontalAlignment: Text.AlignHCenter
}
}

View file

@ -0,0 +1,38 @@
//
// WebView.qml
//
// Created by Bradley Austin Davis on 12 Jan 2016
// Copyright 2016 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import QtQuick 2.7
import QtWebEngine 1.5
WebEngineView {
id: root
Component.onCompleted: {
console.log("Connecting JS messaging to Hifi Logging")
// Ensure the JS from the web-engine makes it to our logging
root.javaScriptConsoleMessage.connect(function(level, message, lineNumber, sourceID) {
console.log("Web Window JS message: " + sourceID + " " + lineNumber + " " + message);
});
}
onLoadingChanged: {
// Required to support clicking on "hifi://" links
if (WebEngineView.LoadStartedStatus == loadRequest.status) {
var url = loadRequest.url.toString();
if (urlHandler.canHandleUrl(url)) {
if (urlHandler.handleUrl(url)) {
root.stop();
}
}
}
}
WebSpinner { }
}

View file

@ -0,0 +1,122 @@
//
// Button.qml
//
// Created by David Rowe on 16 Feb 2016
// Copyright 2016 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import QtQuick 2.7
import QtQuick.Controls 2.3 as Original
import TabletScriptingInterface 1.0
import "../stylesUit"
Original.Button {
id: control;
property int color: 0
property int colorScheme: hifi.colorSchemes.light
property int fontSize: hifi.fontSizes.buttonLabel
property int radius: hifi.buttons.radius
property alias implicitTextWidth: buttonText.implicitWidth
property string buttonGlyph: "";
property int fontCapitalization: Font.AllUppercase
width: hifi.dimensions.buttonWidth
height: hifi.dimensions.controlLineHeight
HifiConstants { id: hifi }
onHoveredChanged: {
if (hovered) {
Tablet.playSound(TabletEnums.ButtonHover);
}
}
onFocusChanged: {
if (focus) {
Tablet.playSound(TabletEnums.ButtonHover);
}
}
onClicked: {
Tablet.playSound(TabletEnums.ButtonClick);
}
background: Rectangle {
radius: control.radius
border.width: (control.color === hifi.buttons.none ||
(control.color === hifi.buttons.noneBorderless && control.hovered) ||
(control.color === hifi.buttons.noneBorderlessWhite && control.hovered) ||
(control.color === hifi.buttons.noneBorderlessGray && control.hovered)) ? 1 : 0;
border.color: control.color === hifi.buttons.noneBorderless ? hifi.colors.blueHighlight :
(control.color === hifi.buttons.noneBorderlessGray ? hifi.colors.baseGray : hifi.colors.white);
gradient: Gradient {
GradientStop {
position: 0.2
color: {
if (!control.enabled) {
hifi.buttons.disabledColorStart[control.colorScheme]
} else if (control.pressed) {
hifi.buttons.pressedColor[control.color]
} else if (control.hovered) {
hifi.buttons.hoveredColor[control.color]
} else {
hifi.buttons.colorStart[control.color]
}
}
}
GradientStop {
position: 1.0
color: {
if (!control.enabled) {
hifi.buttons.disabledColorFinish[control.colorScheme]
} else if (control.pressed) {
hifi.buttons.pressedColor[control.color]
} else if (control.hovered) {
hifi.buttons.hoveredColor[control.color]
} else {
hifi.buttons.colorFinish[control.color]
}
}
}
}
}
contentItem: Item {
HiFiGlyphs {
id: buttonGlyph;
visible: control.buttonGlyph !== "";
text: control.buttonGlyph === "" ? hifi.glyphs.question : control.buttonGlyph;
// Size
size: 34;
// Anchors
anchors.right: buttonText.left;
anchors.top: parent.top;
anchors.bottom: parent.bottom;
// Style
color: enabled ? hifi.buttons.textColor[control.color]
: hifi.buttons.disabledTextColor[control.colorScheme];
// Alignment
horizontalAlignment: Text.AlignHCenter;
verticalAlignment: Text.AlignVCenter;
}
RalewayBold {
id: buttonText;
anchors.centerIn: parent;
font.capitalization: control.fontCapitalization
color: enabled ? hifi.buttons.textColor[control.color]
: hifi.buttons.disabledTextColor[control.colorScheme]
size: control.fontSize
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
text: control.text
}
}
}

View file

@ -0,0 +1,121 @@
//
// CheckBox.qml
//
// Created by David Rowe on 26 Feb 2016
// Copyright 2016 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import QtQuick 2.2
import QtQuick.Controls 2.2 as Original
import "../stylesUit"
import TabletScriptingInterface 1.0
Original.CheckBox {
id: checkBox
property int colorScheme: hifi.colorSchemes.light
property string color: hifi.colors.lightGrayText
readonly property bool isLightColorScheme: colorScheme == hifi.colorSchemes.light
property bool isRedCheck: false
property int boxSize: 14
property int boxRadius: 3
property bool wrap: true;
readonly property int checkSize: Math.max(boxSize - 8, 10)
readonly property int checkRadius: 2
property string labelFontFamily: "Raleway"
property int labelFontSize: 14;
property int labelFontWeight: Font.DemiBold;
focusPolicy: Qt.ClickFocus
hoverEnabled: true
onClicked: {
Tablet.playSound(TabletEnums.ButtonClick);
}
onHoveredChanged: {
if (hovered) {
Tablet.playSound(TabletEnums.ButtonHover);
}
}
indicator: Rectangle {
id: box
implicitWidth: boxSize
implicitHeight: boxSize
radius: boxRadius
y: parent.height / 2 - height / 2
border.width: 1
border.color: pressed || hovered
? hifi.colors.checkboxCheckedBorder
: (checkBox.isLightColorScheme ? hifi.colors.checkboxLightFinish : hifi.colors.checkboxDarkFinish)
gradient: Gradient {
GradientStop {
position: 0.2
color: pressed || hovered
? (checkBox.isLightColorScheme ? hifi.colors.checkboxChecked : hifi.colors.checkboxLightStart)
: (checkBox.isLightColorScheme ? hifi.colors.checkboxLightStart : hifi.colors.checkboxDarkStart)
}
GradientStop {
position: 1.0
color: pressed || hovered
? (checkBox.isLightColorScheme ? hifi.colors.checkboxChecked : hifi.colors.checkboxLightFinish)
: (checkBox.isLightColorScheme ? hifi.colors.checkboxLightFinish : hifi.colors.checkboxDarkFinish)
}
}
Rectangle {
visible: pressed || hovered
anchors.centerIn: parent
id: innerBox
width: checkSize - 4
height: width
radius: checkRadius
color: hifi.colors.checkboxCheckedBorder
}
Rectangle {
id: check
width: checkSize
height: checkSize
radius: checkRadius
anchors.centerIn: parent
color: isRedCheck ? hifi.colors.checkboxCheckedRed : hifi.colors.checkboxChecked
border.width: 2
border.color: isRedCheck? hifi.colors.checkboxCheckedBorderRed : hifi.colors.checkboxCheckedBorder
visible: checked && !pressed || !checked && pressed
}
Rectangle {
id: disabledOverlay
visible: !enabled
width: boxSize
height: boxSize
radius: boxRadius
border.width: 1
border.color: hifi.colors.baseGrayHighlight
color: hifi.colors.baseGrayHighlight
opacity: 0.5
}
}
contentItem: Label {
text: checkBox.text
color: checkBox.color
font.family: checkBox.labelFontFamily;
font.pixelSize: checkBox.labelFontSize;
font.weight: checkBox.labelFontWeight;
x: 2
verticalAlignment: Text.AlignVCenter
wrapMode: checkBox.wrap ? Text.Wrap : Text.NoWrap
elide: checkBox.wrap ? Text.ElideNone : Text.ElideRight
enabled: checkBox.enabled
leftPadding: checkBox.indicator.width + checkBox.spacing
}
}

View file

@ -0,0 +1,125 @@
//
// CheckBox2.qml
//
// Created by Vlad Stelmahovsky on 10 Aug 2017
// Copyright 2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import QtQuick 2.7
import QtQuick.Controls 2.2
import "../stylesUit"
import "." as HiFiControls
import TabletScriptingInterface 1.0
CheckBox {
id: checkBox
HifiConstants { id: hifi; }
padding: 0
leftPadding: 0
property int colorScheme: hifi.colorSchemes.light
property string color: hifi.colors.lightGrayText
readonly property bool isLightColorScheme: colorScheme === hifi.colorSchemes.light
property bool isRedCheck: false
property bool isRound: false
property int boxSize: 14
property int boxRadius: isRound ? boxSize : 3
property bool wrap: true;
readonly property int checkSize: Math.max(boxSize - 8, 10)
readonly property int checkRadius: isRound ? checkSize / 2 : 2
focusPolicy: Qt.ClickFocus
hoverEnabled: true
onClicked: {
Tablet.playSound(TabletEnums.ButtonClick);
}
onHoveredChanged: {
if (hovered) {
Tablet.playSound(TabletEnums.ButtonHover);
}
}
indicator: Rectangle {
id: box
implicitWidth: boxSize
implicitHeight: boxSize
radius: boxRadius
x: checkBox.leftPadding
y: parent.height / 2 - height / 2
border.width: 1
border.color: pressed || hovered
? hifi.colors.checkboxCheckedBorder
: (checkBox.isLightColorScheme ? hifi.colors.checkboxLightFinish : hifi.colors.checkboxDarkFinish)
gradient: Gradient {
GradientStop {
position: 0.2
color: pressed || hovered
? (checkBox.isLightColorScheme ? hifi.colors.checkboxChecked : hifi.colors.checkboxLightStart)
: (checkBox.isLightColorScheme ? hifi.colors.checkboxLightStart : hifi.colors.checkboxDarkStart)
}
GradientStop {
position: 1.0
color: pressed || hovered
? (checkBox.isLightColorScheme ? hifi.colors.checkboxChecked : hifi.colors.checkboxLightFinish)
: (checkBox.isLightColorScheme ? hifi.colors.checkboxLightFinish : hifi.colors.checkboxDarkFinish)
}
}
Rectangle {
visible: pressed || hovered
anchors.centerIn: parent
id: innerBox
width: checkSize - 4
height: width
radius: checkRadius
color: hifi.colors.checkboxCheckedBorder
}
Rectangle {
id: check
width: checkSize
height: checkSize
radius: checkRadius
anchors.centerIn: parent
color: isRedCheck ? hifi.colors.checkboxCheckedRed : hifi.colors.checkboxChecked
border.width: 2
border.color: isRedCheck? hifi.colors.checkboxCheckedBorderRed : hifi.colors.checkboxCheckedBorder
visible: checked && !pressed || !checked && pressed
}
Rectangle {
id: disabledOverlay
visible: !enabled
width: boxSize
height: boxSize
radius: boxRadius
border.width: 1
border.color: hifi.colors.baseGrayHighlight
color: hifi.colors.baseGrayHighlight
opacity: 0.5
}
}
contentItem: Text {
id: root
font.pixelSize: hifi.fontSizes.inputLabel
font.family: "Raleway"
font.weight: Font.DemiBold
text: checkBox.text
color: checkBox.color
x: 2
wrapMode: checkBox.wrap ? Text.Wrap : Text.NoWrap
elide: checkBox.wrap ? Text.ElideNone : Text.ElideRight
enabled: checkBox.enabled
verticalAlignment: Text.AlignVCenter
leftPadding: checkBox.indicator.width + checkBox.spacing
}
}

View file

@ -0,0 +1,191 @@
//
// ComboBox.qml
//
// Created by Bradley Austin David on 27 Jan 2016
// Copyright 2016 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import QtQuick 2.7
import QtQuick.Controls 2.2
import "../stylesUit"
import "." as HifiControls
FocusScope {
id: root
HifiConstants { id: hifi }
property alias model: comboBox.model;
property alias editable: comboBox.editable
property alias comboBox: comboBox
readonly property alias currentText: comboBox.currentText;
property alias currentIndex: comboBox.currentIndex;
property int currentHighLightedIndex: comboBox.currentIndex;
property int dropdownHeight: 480
property int colorScheme: hifi.colorSchemes.light
readonly property bool isLightColorScheme: colorScheme == hifi.colorSchemes.light
property string label: ""
property real controlHeight: height + (comboBoxLabel.visible ? comboBoxLabel.height + comboBoxLabel.anchors.bottomMargin : 0)
readonly property ComboBox control: comboBox
property bool isDesktop: true
signal accepted();
implicitHeight: comboBox.height;
focus: true
ComboBox {
id: comboBox
anchors.fill: parent
hoverEnabled: true
visible: true
height: hifi.fontSizes.textFieldInput + 13 // Match height of TextField control.
function previousItem() { root.currentHighLightedIndex = (root.currentHighLightedIndex + comboBox.count - 1) % comboBox.count; }
function nextItem() { root.currentHighLightedIndex = (root.currentHighLightedIndex + comboBox.count + 1) % comboBox.count; }
function selectCurrentItem() { root.currentIndex = root.currentHighLightedIndex; close(); /*hideList();*/ }
function selectSpecificItem(index) { root.currentIndex = index; close();/*hideList();*/ }
Keys.onUpPressed: previousItem();
Keys.onDownPressed: nextItem();
Keys.onSpacePressed: selectCurrentItem();
Keys.onRightPressed: selectCurrentItem();
Keys.onReturnPressed: selectCurrentItem();
background: Rectangle {
gradient: Gradient {
GradientStop {
position: 0.2
color: comboBox.popup.visible
? (isLightColorScheme ? hifi.colors.dropDownPressedLight : hifi.colors.dropDownPressedDark)
: (isLightColorScheme ? hifi.colors.dropDownLightStart : hifi.colors.dropDownDarkStart)
}
GradientStop {
position: 1.0
color: comboBox.popup.visible
? (isLightColorScheme ? hifi.colors.dropDownPressedLight : hifi.colors.dropDownPressedDark)
: (isLightColorScheme ? hifi.colors.dropDownLightFinish : hifi.colors.dropDownDarkFinish)
}
}
}
indicator: Item {
id: dropIcon
anchors { right: parent.right; verticalCenter: parent.verticalCenter }
height: root.height
width: height
Rectangle {
width: 1
height: parent.height
anchors.top: parent.top
anchors.left: parent.left
color: isLightColorScheme ? hifi.colors.faintGray : hifi.colors.baseGray
}
HiFiGlyphs {
anchors { top: parent.top; topMargin: -11; horizontalCenter: parent.horizontalCenter }
size: hifi.dimensions.spinnerSize
text: hifi.glyphs.caratDn
color: comboBox.hovered || comboBox.popup.visible ? hifi.colors.baseGray : (isLightColorScheme ? hifi.colors.lightGray : hifi.colors.lightGrayText)
}
}
contentItem: FiraSansSemiBold {
id: textField
anchors {
left: parent.left
leftMargin: hifi.dimensions.textPadding
verticalCenter: parent.verticalCenter
}
size: hifi.fontSizes.textFieldInput
text: comboBox.displayText ? comboBox.displayText : comboBox.currentText
elide: Text.ElideRight
color: comboBox.hovered || comboBox.popup.visible ? hifi.colors.baseGray : (isLightColorScheme ? hifi.colors.lightGray : hifi.colors.lightGrayText )
}
delegate: ItemDelegate {
id: itemDelegate
hoverEnabled: true
width: root.width + 4
height: popupText.implicitHeight * 1.4
highlighted: root.currentHighLightedIndex == index
onHoveredChanged: {
if (hovered) {
root.currentHighLightedIndex = index
}
}
background: Rectangle {
color: itemDelegate.highlighted ? hifi.colors.primaryHighlight
: (isLightColorScheme ? hifi.colors.dropDownPressedLight
: hifi.colors.dropDownPressedDark)
}
contentItem: FiraSansSemiBold {
id: popupText
anchors.left: parent.left
anchors.leftMargin: hifi.dimensions.textPadding
anchors.verticalCenter: parent.verticalCenter
text: comboBox.model[index] ? comboBox.model[index]
: (comboBox.model.get && comboBox.model.get(index).text ?
comboBox.model.get(index).text : "")
size: hifi.fontSizes.textFieldInput
color: hifi.colors.baseGray
}
}
popup: Popup {
y: comboBox.height - 1
width: comboBox.width
implicitHeight: listView.contentHeight > dropdownHeight ? dropdownHeight
: listView.contentHeight
padding: 0
topPadding: 1
onClosed: {
root.accepted()
}
contentItem: ListView {
id: listView
clip: true
model: comboBox.popup.visible ? comboBox.delegateModel : null
currentIndex: root.currentHighLightedIndex
delegate: comboBox.delegate
ScrollBar.vertical: HifiControls.ScrollBar {
id: scrollbar
parent: listView
policy: ScrollBar.AsNeeded
visible: size < 1.0
}
}
background: Rectangle {
color: hifi.colors.baseGray
}
}
}
function textAt(index) {
return comboBox.textAt(index);
}
HifiControls.Label {
id: comboBoxLabel
text: root.label
colorScheme: root.colorScheme
anchors.left: parent.left
anchors.bottom: parent.top
anchors.bottomMargin: 4
visible: label != ""
}
Component.onCompleted: {
isDesktop = (typeof desktop !== "undefined");
}
}

View file

@ -0,0 +1,138 @@
//
// ContentSection.qml
//
// Created by David Rowe on 16 Feb 2016
// Copyright 2016 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import QtQuick 2.5
import QtGraphicalEffects 1.0
import "../stylesUit"
Column {
property string name: "Content Section"
property bool isFirst: false
property bool isCollapsible: false // Set at creation.
property bool isCollapsed: false
spacing: 0 // Defer spacing decisions to individual controls.
anchors {
left: parent.left
leftMargin: hifi.dimensions.contentMargin.x
right: parent.right
rightMargin: hifi.dimensions.contentMargin.x
}
function toggleCollapsed() {
if (isCollapsible) {
isCollapsed = !isCollapsed;
for (var i = 1; i < children.length; i++) {
children[i].visible = !isCollapsed;
}
}
}
Item {
id: sectionName
anchors.left: parent.left
anchors.right: parent.right
height: leadingSpace.height + topBar.height + heading.height + bottomBar.height
Item {
id: leadingSpace
width: 1
height: isFirst ? 7 : 0
anchors.top: parent.top
}
Item {
id: topBar
visible: !isFirst
height: visible ? 2 : 0
anchors.top: leadingSpace.bottom
Rectangle {
id: shadow
width: frame.width
height: 1
color: hifi.colors.baseGrayShadow
x: -hifi.dimensions.contentMargin.x
}
Rectangle {
width: frame.width
height: 1
color: hifi.colors.baseGrayHighlight
x: -hifi.dimensions.contentMargin.x
anchors.top: shadow.bottom
}
}
Item {
id: heading
anchors {
left: parent.left
right: parent.right
top: topBar.bottom
}
height: isCollapsible ? 36 : 28
RalewayRegular {
id: title
anchors {
left: parent.left
top: parent.top
topMargin: 12
}
size: hifi.fontSizes.sectionName
font.capitalization: Font.AllUppercase
text: name
color: hifi.colors.lightGrayText
}
HiFiGlyphs {
anchors {
top: title.top
topMargin: -9
right: parent.right
rightMargin: -4
}
size: hifi.fontSizes.disclosureButton
text: isCollapsed ? hifi.glyphs.disclosureButtonExpand : hifi.glyphs.disclosureButtonCollapse
color: hifi.colors.lightGrayText
visible: isCollapsible
}
MouseArea {
// Events are propogated so that any active control is defocused.
anchors.fill: parent
propagateComposedEvents: true
onPressed: {
toggleCollapsed();
mouse.accepted = false;
}
}
}
LinearGradient {
id: bottomBar
visible: desktop.gradientsSupported && isCollapsible
width: frame.width
height: visible ? 4 : 0
x: -hifi.dimensions.contentMargin.x
anchors.top: heading.bottom
start: Qt.point(0, 0)
end: Qt.point(0, 4)
gradient: Gradient {
GradientStop { position: 0.0; color: hifi.colors.darkGray }
GradientStop { position: 1.0; color: hifi.colors.baseGray } // Equivalent of darkGray0 over baseGray background.
}
cached: true
}
}
}

View file

@ -0,0 +1,333 @@
//
// FilterBar.qml
//
// Created by Zach Fox on 17 Feb 2018-03-12
// Copyright 2018 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import QtQuick 2.9
import QtQuick.Controls 2.2
import QtGraphicalEffects 1.0
import "../stylesUit"
import "." as HifiControls
Item {
id: root;
property int colorScheme: hifi.colorSchemes.light
readonly property bool isLightColorScheme: colorScheme == hifi.colorSchemes.light
readonly property bool isFaintGrayColorScheme: colorScheme == hifi.colorSchemes.faintGray
property bool error: false;
property alias textFieldHeight: textField.height;
property string placeholderText;
property alias dropdownHeight: dropdownContainer.height;
property alias text: textField.text;
property alias primaryFilterChoices: filterBarModel;
property int primaryFilter_index: -1;
property string primaryFilter_filterName: "";
property string primaryFilter_displayName: "";
signal accepted;
onPrimaryFilter_indexChanged: {
if (primaryFilter_index === -1) {
primaryFilter_filterName = "";
primaryFilter_displayName = "";
} else {
primaryFilter_filterName = filterBarModel.get(primaryFilter_index).filterName;
primaryFilter_displayName = filterBarModel.get(primaryFilter_index).displayName;
}
}
TextField {
id: textField;
anchors.top: parent.top;
anchors.right: parent.right;
anchors.left: parent.left;
font.family: "Fira Sans"
font.pixelSize: hifi.fontSizes.textFieldInput;
placeholderText: root.primaryFilter_index === -1 ? root.placeholderText : "";
TextMetrics {
id: primaryFilterTextMetrics;
font.family: "FiraSans Regular";
font.pixelSize: hifi.fontSizes.textFieldInput;
font.capitalization: Font.AllUppercase;
text: root.primaryFilter_displayName;
}
// workaround for https://bugreports.qt.io/browse/QTBUG-49297
Keys.onPressed: {
switch (event.key) {
case Qt.Key_Return:
case Qt.Key_Enter:
event.accepted = true;
// emit accepted signal manually
if (acceptableInput) {
root.accepted();
root.forceActiveFocus();
}
break;
case Qt.Key_Backspace:
if (textField.text === "") {
primaryFilter_index = -1;
}
break;
}
}
onAccepted: {
root.forceActiveFocus();
}
onActiveFocusChanged: {
if (!activeFocus) {
dropdownContainer.visible = false;
}
}
color: {
if (isLightColorScheme) {
if (textField.activeFocus) {
hifi.colors.black
} else {
hifi.colors.lightGray
}
} else if (isFaintGrayColorScheme) {
if (textField.activeFocus) {
hifi.colors.black
} else {
hifi.colors.lightGray
}
} else {
if (textField.activeFocus) {
hifi.colors.white
} else {
hifi.colors.lightGrayText
}
}
}
background: Rectangle {
id: mainFilterBarRectangle;
color: {
if (isLightColorScheme) {
if (textField.activeFocus) {
hifi.colors.white
} else {
hifi.colors.textFieldLightBackground
}
} else if (isFaintGrayColorScheme) {
if (textField.activeFocus) {
hifi.colors.white
} else {
hifi.colors.faintGray50
}
} else {
if (textField.activeFocus) {
hifi.colors.black
} else {
hifi.colors.baseGrayShadow
}
}
}
border.color: textField.error ? hifi.colors.redHighlight :
(textField.activeFocus ? hifi.colors.primaryHighlight : (isFaintGrayColorScheme ? hifi.colors.lightGrayText : hifi.colors.lightGray))
border.width: 1
radius: 4
Item {
id: searchButtonContainer;
anchors.left: parent.left;
anchors.verticalCenter: parent.verticalCenter;
height: parent.height;
width: 42;
// Search icon
HiFiGlyphs {
id: searchIcon;
text: hifi.glyphs.search
color: textField.color
size: 40;
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
width: paintedWidth;
}
// Carat
HiFiGlyphs {
text: hifi.glyphs.caratDn;
color: textField.color;
size: 40;
anchors.left: parent.left;
anchors.leftMargin: 15;
width: paintedWidth;
}
MouseArea {
anchors.fill: parent;
onClicked: {
textField.forceActiveFocus();
dropdownContainer.visible = !dropdownContainer.visible;
}
}
}
Rectangle {
z: 999;
id: primaryFilterContainer;
color: textField.activeFocus ? hifi.colors.faintGray : hifi.colors.white;
width: primaryFilterTextMetrics.tightBoundingRect.width + 14;
height: parent.height - 8;
anchors.verticalCenter: parent.verticalCenter;
anchors.left: searchButtonContainer.right;
anchors.leftMargin: 4;
visible: primaryFilterText.text !== "";
radius: height/2;
FiraSansRegular {
id: primaryFilterText;
text: root.primaryFilter_displayName;
anchors.fill: parent;
color: textField.activeFocus ? hifi.colors.black : hifi.colors.lightGray;
horizontalAlignment: Text.AlignHCenter;
verticalAlignment: Text.AlignVCenter;
size: hifi.fontSizes.textFieldInput;
font.capitalization: Font.AllUppercase;
}
MouseArea {
anchors.fill: parent;
onClicked: {
textField.forceActiveFocus();
}
}
}
// "Clear" button
HiFiGlyphs {
text: hifi.glyphs.error
color: textField.color
size: 40
anchors.right: parent.right
anchors.rightMargin: hifi.dimensions.textPadding - 2
anchors.verticalCenter: parent.verticalCenter
visible: root.text !== "" || root.primaryFilter_index !== -1;
MouseArea {
anchors.fill: parent;
onClicked: {
root.text = "";
root.primaryFilter_index = -1;
dropdownContainer.visible = false;
textField.forceActiveFocus();
}
}
}
}
selectedTextColor: hifi.colors.black
selectionColor: hifi.colors.primaryHighlight
leftPadding: 44 + (root.primaryFilter_index === -1 ? 0 : primaryFilterTextMetrics.tightBoundingRect.width + 20);
rightPadding: 44;
}
Rectangle {
id: dropdownContainer;
visible: false;
height: 50 * filterBarModel.count;
width: parent.width;
anchors.top: textField.bottom;
anchors.left: parent.left;
anchors.right: parent.right;
color: hifi.colors.white;
ListModel {
id: filterBarModel;
}
ListView {
id: dropdownListView;
interactive: false;
anchors.fill: parent;
model: filterBarModel;
delegate: Item {
width: parent.width;
height: 50;
Rectangle {
id: dropDownButton;
color: hifi.colors.white;
width: parent.width;
height: 50;
visible: true;
RalewaySemiBold {
id: dropDownButtonText;
text: model.displayName;
anchors.fill: parent;
anchors.topMargin: 2;
anchors.leftMargin: 12;
color: hifi.colors.baseGray;
horizontalAlignment: Text.AlignLeft;
verticalAlignment: Text.AlignVCenter;
size: 18;
}
MouseArea {
anchors.fill: parent;
hoverEnabled: true;
propagateComposedEvents: false;
onEntered: {
dropDownButton.color = hifi.colors.blueHighlight;
}
onExited: {
dropDownButton.color = hifi.colors.white;
}
onClicked: {
textField.forceActiveFocus();
root.primaryFilter_index = index;
dropdownContainer.visible = false;
}
}
}
Rectangle {
height: 2;
width: parent.width;
color: hifi.colors.lightGray;
visible: model.separator
}
}
}
}
DropShadow {
anchors.fill: dropdownContainer;
horizontalOffset: 0;
verticalOffset: 4;
radius: 4.0;
samples: 9
color: Qt.rgba(0, 0, 0, 0.25);
source: dropdownContainer;
visible: dropdownContainer.visible;
}
function changeFilterByDisplayName(name) {
for (var i = 0; i < filterBarModel.count; i++) {
if (filterBarModel.get(i).displayName === name) {
root.primaryFilter_index = i;
return;
}
}
console.log("Passed displayName not found in filterBarModel! primaryFilter unchanged.");
}
}

View file

@ -0,0 +1,91 @@
//
// GlyphButton.qml
//
// Created by Clement on 3/7/16
// Copyright 2016 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import QtQuick 2.7
import QtQuick.Controls 2.2 as Original
import TabletScriptingInterface 1.0
import "../stylesUit"
Original.Button {
id: control
property int color: 0
property int colorScheme: hifi.colorSchemes.light
property string glyph: ""
property int size: 32
width: 120
height: 28
onHoveredChanged: {
if (hovered) {
Tablet.playSound(TabletEnums.ButtonHover);
}
}
onFocusChanged: {
if (focus) {
Tablet.playSound(TabletEnums.ButtonHover);
}
}
onClicked: {
Tablet.playSound(TabletEnums.ButtonClick);
}
background: Rectangle {
radius: hifi.buttons.radius
gradient: Gradient {
GradientStop {
position: 0.2
color: {
if (!control.enabled) {
hifi.buttons.disabledColorStart[control.colorScheme]
} else if (control.pressed) {
hifi.buttons.pressedColor[control.color]
} else if (control.hovered) {
hifi.buttons.hoveredColor[control.color]
} else if (!control.hovered && control.focus) {
hifi.buttons.focusedColor[control.color]
} else {
hifi.buttons.colorStart[control.color]
}
}
}
GradientStop {
position: 1.0
color: {
if (!control.enabled) {
hifi.buttons.disabledColorFinish[control.colorScheme]
} else if (control.pressed) {
hifi.buttons.pressedColor[control.color]
} else if (control.hovered) {
hifi.buttons.hoveredColor[control.color]
} else if (!control.hovered && control.focus) {
hifi.buttons.focusedColor[control.color]
} else {
hifi.buttons.colorFinish[control.color]
}
}
}
}
}
contentItem: HiFiGlyphs {
color: enabled ? hifi.buttons.textColor[control.color]
: hifi.buttons.disabledTextColor[control.colorScheme]
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
text: control.glyph
size: control.size
}
}

View file

@ -0,0 +1,18 @@
//
// HorizontalRule.qml
//
// Created by Clement on 7/18/16
// Copyright 2016 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import QtQuick 2.5
Rectangle {
anchors.left: parent.left
anchors.right: parent.right
height: 1
color: hifi.colors.lightGray
}

View file

@ -0,0 +1,21 @@
//
// HorizontalSpacer.qml
//
// Created by Clement on 7/18/16
// Copyright 2016 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import QtQuick 2.5
import "../stylesUit"
Item {
id: root
property alias size: root.width
width: hifi.dimensions.controlInterlineHeight
height: 1 // Must be non-zero
}

View file

@ -0,0 +1,63 @@
//
// ImageMessageBox.qml
//
// Created by Dante Ruiz on 7/5/2017
// Copyright 2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import QtQuick 2.5
import "../stylesUit"
Item {
id: imageBox
visible: false
anchors.fill: parent
property alias source: image.source
property alias imageWidth: image.width
property alias imageHeight: image.height
Rectangle {
anchors.fill: parent
color: "black"
opacity: 0.3
}
Image {
id: image
anchors.centerIn: parent
HiFiGlyphs {
id: closeGlyphButton
text: hifi.glyphs.close
size: 25
anchors {
top: parent.top
topMargin: 15
right: parent.right
rightMargin: 15
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
onEntered: {
parent.text = hifi.glyphs.closeInverted;
}
onExited: {
parent.text = hifi.glyphs.close;
}
onClicked: {
imageBox.visible = false;
}
}
}
}
}

View file

@ -0,0 +1,185 @@
import QtQuick 2.0
import TabletScriptingInterface 1.0
Item {
id: keyItem
width: 45
height: 50
property int contentPadding: 4
property string glyph: "a"
property bool toggle: false // does this button have the toggle behaivor?
property bool toggled: false // is this button currently toggled?
property alias mouseArea: mouseArea1
property alias fontFamily: letter.font.family;
property alias fontPixelSize: letter.font.pixelSize
property alias verticalAlignment: letter.verticalAlignment
property alias letterAnchors: letter.anchors
function resetToggledMode(mode) {
toggled = mode;
if (toggled) {
state = "mouseDepressed";
} else {
state = "";
}
}
MouseArea {
id: mouseArea1
width: 36
anchors.fill: parent
hoverEnabled: true
onCanceled: {
if (toggled) {
keyItem.state = "mouseDepressed";
} else {
keyItem.state = "";
}
}
onContainsMouseChanged: {
if (containsMouse) {
Tablet.playSound(TabletEnums.ButtonHover);
}
}
onDoubleClicked: {
mouse.accepted = true;
}
property var _HAPTIC_STRENGTH: 0.1;
property var _HAPTIC_DURATION: 3.0;
property var leftHand: 0;
property var rightHand: 1;
onEntered: {
keyItem.state = "mouseOver";
var globalPosition = keyItem.mapToGlobal(mouseArea1.mouseX, mouseArea1.mouseY);
var pointerID = Web3DOverlay.deviceIdByTouchPoint(globalPosition.x, globalPosition.y);
if (Pointers.isLeftHand(pointerID)) {
Controller.triggerHapticPulse(_HAPTIC_STRENGTH, _HAPTIC_DURATION, leftHand);
} else if (Pointers.isRightHand(pointerID)) {
Controller.triggerHapticPulse(_HAPTIC_STRENGTH, _HAPTIC_DURATION, rightHand);
}
}
onExited: {
if (toggled) {
keyItem.state = "mouseDepressed";
} else {
keyItem.state = "";
}
}
onPressed: {
keyItem.state = "mouseClicked";
mouse.accepted = true;
}
onReleased: {
if (containsMouse) {
Tablet.playSound(TabletEnums.ButtonClick);
webEntity.synthesizeKeyPress(glyph);
webEntity.synthesizeKeyPress(glyph, mirrorText);
if (toggle) {
toggled = !toggled;
}
keyItem.state = "mouseOver";
} else {
if (toggled) {
keyItem.state = "mouseDepressed";
} else {
keyItem.state = "";
}
}
mouse.accepted = true;
}
}
Rectangle {
id: roundedRect
width: 30
color: "#121212"
radius: 2
border.color: "#00000000"
anchors.fill: parent
anchors.margins: contentPadding
}
Text {
id: letter
y: 6
width: 50
color: "#ffffff"
text: glyph
style: Text.Normal
font.family: "Tahoma"
anchors.right: parent.right
anchors.rightMargin: 0
anchors.left: parent.left
anchors.leftMargin: 0
anchors.bottom: parent.bottom
anchors.bottomMargin: 0
anchors.top: parent.top
anchors.topMargin: 8
horizontalAlignment: Text.AlignHCenter
font.pixelSize: 28
}
states: [
State {
name: "mouseOver"
PropertyChanges {
target: roundedRect
color: "#121212"
radius: 3
border.width: 2
border.color: "#00b4ef"
}
PropertyChanges {
target: letter
color: "#00b4ef"
style: Text.Normal
}
},
State {
name: "mouseClicked"
PropertyChanges {
target: roundedRect
color: "#1080b8"
border.width: 2
border.color: "#00b4ef"
}
PropertyChanges {
target: letter
color: "#121212"
styleColor: "#00000000"
style: Text.Normal
}
},
State {
name: "mouseDepressed"
PropertyChanges {
target: roundedRect
color: "#0578b1"
border.width: 0
}
PropertyChanges {
target: letter
color: "#121212"
styleColor: "#00000000"
style: Text.Normal
}
}
]
}

View file

@ -0,0 +1,354 @@
//
// FileDialog.qml
//
// Created by Anthony Thibault on 31 Oct 2016
// Copyright 2016 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import QtQuick 2.7
import QtGraphicalEffects 1.0
import "."
Rectangle {
id: keyboardBase
objectName: "keyboard"
anchors.left: parent.left
anchors.right: parent.right
color: "#252525"
property bool raised: false
property bool numeric: false
readonly property int keyboardRowHeight: 50
readonly property int keyboardWidth: 480
readonly property int keyboardHeight: 200
readonly property int mirrorTextHeight: keyboardRowHeight
property bool password: false
property alias mirroredText: mirrorText.text
property bool showMirrorText: true
readonly property int raisedHeight: keyboardHeight + (showMirrorText ? keyboardRowHeight : 0)
height: enabled && raised ? raisedHeight : 0
visible: enabled && raised
property bool shiftMode: false
property bool numericShiftMode: false
onRaisedChanged: {
mirroredText = "";
}
function resetShiftMode(mode) {
shiftMode = mode;
shiftKey.resetToggledMode(mode);
}
function toUpper(str) {
if (str === ",") {
return "<";
} else if (str === ".") {
return ">";
} else if (str === "/") {
return "?";
} else if (str === "-") {
return "_";
} else {
return str.toUpperCase(str);
}
}
function toLower(str) {
if (str === "<") {
return ",";
} else if (str === ">") {
return ".";
} else if (str === "?") {
return "/";
} else if (str === "_") {
return "-";
} else {
return str.toLowerCase(str);
}
}
function forEachKey(func) {
var i, j;
for (i = 0; i < columnAlpha.children.length; i++) {
var row = columnAlpha.children[i];
for (j = 0; j < row.children.length; j++) {
var key = row.children[j];
func(key);
}
}
}
onShiftModeChanged: {
forEachKey(function (key) {
if (/[a-z-_]/i.test(key.glyph)) {
if (shiftMode) {
key.glyph = keyboardBase.toUpper(key.glyph);
} else {
key.glyph = keyboardBase.toLower(key.glyph);
}
}
});
}
function alphaKeyClickedHandler(mouseArea) {
// reset shift mode to false after first keypress
if (shiftMode) {
resetShiftMode(false);
}
}
Component.onCompleted: {
// hook up callbacks to every ascii key
forEachKey(function (key) {
if (/^[a-z]+$/i.test(key.glyph)) {
key.mouseArea.onClicked.connect(alphaKeyClickedHandler);
}
});
}
Rectangle {
height: showMirrorText ? mirrorTextHeight : 0
width: keyboardWidth
color: "#252525"
anchors.horizontalCenter: parent.horizontalCenter
TextInput {
id: mirrorText
visible: showMirrorText
font.family: "Fira Sans"
font.pixelSize: 20
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
color: "#00B4EF";
anchors.left: parent.left
anchors.leftMargin: 10
anchors.right: parent.right
anchors.top: parent.top
anchors.bottom: parent.bottom
wrapMode: Text.WordWrap
readOnly: false // we need this to allow control to accept QKeyEvent
selectByMouse: false
echoMode: password ? TextInput.Password : TextInput.Normal
Keys.onPressed: {
if (event.key == Qt.Key_Return || event.key == Qt.Key_Space) {
mirrorText.text = "";
event.accepted = true;
}
}
MouseArea { // ... and we need this mouse area to prevent mirrorText from getting mouse events to ensure it will never get focus
anchors.fill: parent
}
}
}
Rectangle {
id: keyboardRect
y: showMirrorText ? mirrorTextHeight : 0
width: keyboardWidth
height: keyboardHeight
color: "#252525"
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
anchors.bottomMargin: 0
Column {
id: columnAlpha
width: keyboardWidth
height: keyboardHeight
visible: !numeric
Row {
width: keyboardWidth
height: keyboardRowHeight
anchors.left: parent.left
anchors.leftMargin: 4
Key { width: 43; glyph: "q"; }
Key { width: 43; glyph: "w"; }
Key { width: 43; glyph: "e"; }
Key { width: 43; glyph: "r"; }
Key { width: 43; glyph: "t"; }
Key { width: 43; glyph: "y"; }
Key { width: 43; glyph: "u"; }
Key { width: 43; glyph: "i"; }
Key { width: 43; glyph: "o"; }
Key { width: 43; glyph: "p"; }
Key { width: 43; glyph: "←"; }
}
Row {
width: keyboardWidth
height: keyboardRowHeight
anchors.left: parent.left
anchors.leftMargin: 20
Key { width: 43; glyph: "a"; }
Key { width: 43; glyph: "s"; }
Key { width: 43; glyph: "d"; }
Key { width: 43; glyph: "f"; }
Key { width: 43; glyph: "g"; }
Key { width: 43; glyph: "h"; }
Key { width: 43; glyph: "j"; }
Key { width: 43; glyph: "k"; }
Key { width: 43; glyph: "l"; }
Key { width: 70; glyph: "⏎"; }
}
Row {
width: keyboardWidth
height: keyboardRowHeight
anchors.left: parent.left
anchors.leftMargin: 4
Key {
id: shiftKey
width: 43
glyph: "⇪"
toggle: true
onToggledChanged: shiftMode = toggled
}
Key { width: 43; glyph: "z"; }
Key { width: 43; glyph: "x"; }
Key { width: 43; glyph: "c"; }
Key { width: 43; glyph: "v"; }
Key { width: 43; glyph: "b"; }
Key { width: 43; glyph: "n"; }
Key { width: 43; glyph: "m"; }
Key { width: 43; glyph: "-"; }
Key { width: 43; glyph: "/"; }
Key { width: 43; glyph: "?"; }
}
Row {
width: keyboardWidth
height: keyboardRowHeight
anchors.left: parent.left
anchors.leftMargin: 4
Key {
width: 70
glyph: "123"
mouseArea.onClicked: keyboardBase.parent.punctuationMode = true
}
Key { width: 231; glyph: " "; }
Key { width: 43; glyph: ","; }
Key { width: 43; glyph: "."; }
Key {
fontFamily: "hifi-glyphs";
fontPixelSize: 48;
letterAnchors.topMargin: -4;
verticalAlignment: Text.AlignVCenter;
width: 86; glyph: "\ue02b";
}
}
}
Column {
id: columnNumeric
width: keyboardWidth
height: keyboardHeight
visible: numeric
Row {
width: keyboardWidth
height: keyboardRowHeight
anchors.left: parent.left
anchors.leftMargin: 4
Key { width: 43; glyph: "1"; }
Key { width: 43; glyph: "2"; }
Key { width: 43; glyph: "3"; }
Key { width: 43; glyph: "4"; }
Key { width: 43; glyph: "5"; }
Key { width: 43; glyph: "6"; }
Key { width: 43; glyph: "7"; }
Key { width: 43; glyph: "8"; }
Key { width: 43; glyph: "9"; }
Key { width: 43; glyph: "0"; }
Key { width: 43; glyph: "←"; }
}
Row {
width: keyboardWidth
height: keyboardRowHeight
anchors.left: parent.left
anchors.leftMargin: 4
Key { width: 43; glyph: "!"; }
Key { width: 43; glyph: "@"; }
Key { width: 43; glyph: "#"; }
Key { width: 43; glyph: "$"; }
Key { width: 43; glyph: "%"; }
Key { width: 43; glyph: "^"; }
Key { width: 43; glyph: "&"; }
Key { width: 43; glyph: "*"; }
Key { width: 43; glyph: "("; }
Key { width: 43; glyph: ")"; }
Key { width: 43; glyph: "⏎"; }
}
Row {
width: keyboardWidth
height: keyboardRowHeight
anchors.left: parent.left
anchors.leftMargin: 4
Key {
id: numericShiftKey
width: 43
glyph: "\u21E8"
toggle: true
onToggledChanged: numericShiftMode = toggled
}
Key { width: 43; glyph: numericShiftMode ? "`" : "+"; }
Key { width: 43; glyph: numericShiftMode ? "~" : "-"; }
Key { width: 43; glyph: numericShiftMode ? "\u00A3" : "="; }
Key { width: 43; glyph: numericShiftMode ? "\u20AC" : ";"; }
Key { width: 43; glyph: numericShiftMode ? "\u00A5" : ":"; }
Key { width: 43; glyph: numericShiftMode ? "<" : "'"; }
Key { width: 43; glyph: numericShiftMode ? ">" : "\""; }
Key { width: 43; glyph: numericShiftMode ? "[" : "{"; }
Key { width: 43; glyph: numericShiftMode ? "]" : "}"; }
Key { width: 43; glyph: numericShiftMode ? "\\" : "|"; }
}
Row {
width: keyboardWidth
height: keyboardRowHeight
anchors.left: parent.left
anchors.leftMargin: 4
Key {
width: 70
glyph: "abc"
mouseArea.onClicked: keyboardBase.parent.punctuationMode = false
}
Key { width: 231; glyph: " "; }
Key { width: 43; glyph: ","; }
Key { width: 43; glyph: "."; }
Key {
fontFamily: "hifi-glyphs";
fontPixelSize: 48;
letterAnchors.topMargin: -4;
verticalAlignment: Text.AlignVCenter;
width: 86; glyph: "\ue02b";
}
}
}
}
}

View file

@ -0,0 +1,35 @@
//
// Label.qml
//
// Created by David Rowe on 26 Feb 2016
// Copyright 2016 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import QtQuick 2.7
import "../stylesUit"
RalewaySemiBold {
HifiConstants { id: hifi }
property int colorScheme: hifi.colorSchemes.light
size: hifi.fontSizes.inputLabel
color: {
if (colorScheme === hifi.colorSchemes.dark) {
if (enabled) {
hifi.colors.lightGrayText
} else {
hifi.colors.baseGrayHighlight
}
} else {
if (enabled) {
hifi.colors.lightGray
} else {
hifi.colors.lightGrayText
}
}
}
}

View file

@ -0,0 +1,41 @@
//
// QueuedButton.qml
// -- original Button.qml + signal timer workaround --ht
// Created by David Rowe on 16 Feb 2016
// Copyright 2016 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import QtQuick 2.5
import "../stylesUit"
import "." as HifiControls
HifiControls.Button {
// FIXME: THIS WORKAROUND MIGRATED/CONSOLIDATED FROM RUNNINGSCRIPTS.QML
// For some reason trigginer an API that enters
// an internal event loop directly from the button clicked
// trigger below causes the appliction to behave oddly.
// Most likely because the button onClicked handling is never
// completed until the function returns.
// FIXME find a better way of handling the input dialogs that
// doesn't trigger this.
// NOTE: dialogs that need to use this workaround can connect via
// onQueuedClicked: ...
// instead of:
// onClicked: ...
signal clickedQueued()
Timer {
id: fromTimer
interval: 5
repeat: false
running: false
onTriggered: clickedQueued()
}
onClicked: fromTimer.running = true
}

View file

@ -0,0 +1,93 @@
//
// RadioButton.qml
//
// Created by Cain Kilgore on 20th July 2017
// Copyright 2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import QtQuick 2.5
import QtQuick.Controls 2.2 as Original
import "../stylesUit"
import "." as HifiControls
import TabletScriptingInterface 1.0
Original.RadioButton {
id: radioButton
HifiConstants { id: hifi }
hoverEnabled: true
property int colorScheme: hifi.colorSchemes.light
readonly property bool isLightColorScheme: colorScheme == hifi.colorSchemes.light
property real letterSpacing: 1
property int fontSize: hifi.fontSizes.inputLabel
property int boxSize: defaultBoxSize
property real scaleFactor: boxSize / defaultBoxSize
readonly property int defaultBoxSize: 14
readonly property int boxRadius: 3 * scaleFactor
readonly property int checkSize: 10 * scaleFactor
readonly property int checkRadius: 2 * scaleFactor
readonly property int indicatorRadius: 7 * scaleFactor
onClicked: {
Tablet.playSound(TabletEnums.ButtonClick);
}
onHoveredChanged: {
if (hovered) {
Tablet.playSound(TabletEnums.ButtonHover);
}
}
indicator: Rectangle {
id: box
width: boxSize
height: boxSize
radius: indicatorRadius
x: radioButton.leftPadding
y: parent.height / 2 - height / 2
gradient: Gradient {
GradientStop {
position: 0.2
color: pressed || hovered
? (radioButton.isLightColorScheme ? hifi.colors.checkboxDarkStart : hifi.colors.checkboxLightStart)
: (radioButton.isLightColorScheme ? hifi.colors.checkboxLightStart : hifi.colors.checkboxDarkStart)
}
GradientStop {
position: 1.0
color: pressed || hovered
? (radioButton.isLightColorScheme ? hifi.colors.checkboxDarkFinish : hifi.colors.checkboxLightFinish)
: (radioButton.isLightColorScheme ? hifi.colors.checkboxLightFinish : hifi.colors.checkboxDarkFinish)
}
}
Rectangle {
id: check
width: checkSize
height: checkSize
radius: indicatorRadius
anchors.centerIn: parent
color: "#00B4EF"
border.width: 1
border.color: "#36CDFF"
visible: checked && !pressed || !checked && pressed
}
}
contentItem: RalewaySemiBold {
text: radioButton.text
size: radioButton.fontSize
font.letterSpacing: letterSpacing
color: isLightColorScheme ? hifi.colors.lightGray : hifi.colors.lightGrayText
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
leftPadding: radioButton.indicator.width + radioButton.spacing
}
}

View file

@ -0,0 +1,41 @@
//
// ScrollBar.qml
//
// Created by Vlad Stelmahovsky on 27 Nov 2017
// Copyright 2016 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import QtQuick 2.7
import QtQuick.Controls 2.2
import "../stylesUit"
ScrollBar {
visible: size < 1.0
HifiConstants { id: hifi }
property int colorScheme: hifi.colorSchemes.light
readonly property bool isLightColorScheme: colorScheme == hifi.colorSchemes.light
background: Item {
implicitWidth: hifi.dimensions.scrollbarBackgroundWidth
Rectangle {
anchors { fill: parent; topMargin: 3; bottomMargin: 3 }
radius: hifi.dimensions.scrollbarHandleWidth/2
color: isLightColorScheme ? hifi.colors.tableScrollBackgroundLight
: hifi.colors.tableScrollBackgroundDark
}
}
contentItem: Item {
implicitWidth: hifi.dimensions.scrollbarHandleWidth
Rectangle {
anchors { fill: parent; topMargin: 1; bottomMargin: 1 }
radius: hifi.dimensions.scrollbarHandleWidth/2
color: isLightColorScheme ? hifi.colors.tableScrollHandleLight : hifi.colors.tableScrollHandleDark
}
}
}

View file

@ -0,0 +1,44 @@
//
// Separator.qml
//
// Created by Zach Fox on 2017-06-06
// Copyright 2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import QtQuick 2.5
import "../stylesUit"
Item {
property int colorScheme: 0;
readonly property var topColor: [ hifi.colors.baseGrayShadow, hifi.colors.faintGray, "#89858C" ];
readonly property var bottomColor: [ hifi.colors.baseGrayHighlight, hifi.colors.faintGray, "#89858C" ];
// Size
height: colorScheme === 0 ? 2 : 1;
Rectangle {
// Size
width: parent.width;
height: 1;
// Anchors
anchors.left: parent.left;
anchors.bottom: parent.bottom;
// Style
color: topColor[colorScheme];
}
Rectangle {
visible: colorScheme === 0;
// Size
width: parent.width;
height: 1;
// Anchors
anchors.left: parent.left;
anchors.bottom: parent.bottom;
anchors.bottomMargin: -height;
// Style
color: bottomColor[colorScheme];
}
}

Some files were not shown because too many files have changed in this diff Show more