Merge branch 'master' of https://github.com/highfidelity/hifi into flocking

This commit is contained in:
Philip Rosedale 2016-01-29 17:18:35 -08:00
commit ca459e0bd6
30 changed files with 626 additions and 487 deletions

View file

@ -680,11 +680,11 @@ void AudioMixer::domainSettingsRequestComplete() {
void AudioMixer::broadcastMixes() {
auto nodeList = DependencyManager::get<NodeList>();
int nextFrame = 0;
int64_t nextFrame = 0;
QElapsedTimer timer;
timer.start();
int usecToSleep = AudioConstants::NETWORK_FRAME_USECS;
int64_t usecToSleep = AudioConstants::NETWORK_FRAME_USECS;
const int TRAILING_AVERAGE_FRAMES = 100;
int framesSinceCutoffEvent = TRAILING_AVERAGE_FRAMES;
@ -826,12 +826,7 @@ void AudioMixer::broadcastMixes() {
break;
}
usecToSleep = (++nextFrame * AudioConstants::NETWORK_FRAME_USECS) - timer.nsecsElapsed() / 1000; // ns to us
if (usecToSleep > int(USECS_PER_SECOND)) {
qDebug() << "DANGER: amount to sleep is" << usecToSleep;
qDebug() << "NextFrame is" << nextFrame << "and timer nsecs elapsed is" << timer.nsecsElapsed();
}
usecToSleep = (++nextFrame * AudioConstants::NETWORK_FRAME_USECS) - (timer.nsecsElapsed() / 1000);
if (usecToSleep > 0) {
usleep(usecToSleep);

View file

@ -976,6 +976,175 @@
</div>
</div>
<div class="section-header text-section">
<label>Text</label>
</div>
<div class="text-section property">
<div class="label">Text Content</div>
<div class="value">
<input type="text" id="property-text-text">
</div>
</div>
<div class="text-section property">
<div class="label">Line Height</div>
<div class="value">
<input class="coord" type='number' id="property-text-line-height" min="0" step="0.005">
</div>
</div>
<div class="text-section property">
<div class="label">Text Color</div>
<div class="value">
<div class='color-picker' id="property-text-text-color"></div>
<div class="input-area">R <input class="coord" type='number' id="property-text-text-color-red"></div>
<div class="input-area">G <input class="coord" type='number' id="property-text-text-color-green"></div>
<div class="input-area">B <input class="coord" type='number' id="property-text-text-color-blue"></div>
</div>
</div>
<div class="text-section property">
<div class="label">Background Color</div>
<div class="value">
<div class='color-picker' id="property-text-background-color"></div>
<div class="input-area">R <input class="coord" type='number' id="property-text-background-color-red"></div>
<div class="input-area">G <input class="coord" type='number' id="property-text-background-color-green"></div>
<div class="input-area">B <input class="coord" type='number' id="property-text-background-color-blue"></div>
</div>
</div>
<div class="section-header zone-section">
<label>Zone</label>
</div>
<div class="zone-section property">
<span class="label">Stage Sun Model Enabled</span>
<span class="value">
<input type='checkbox' id="property-zone-stage-sun-model-enabled">
</span>
</div>
<div class="sub-section-header zone-section keyLight-section">
<label>KeyLight</label>
</div>
<div class="zone-section keyLight-section property">
<div class="label">Light Color</div>
<div class="value">
<div class='color-picker' id="property-zone-key-light-color"></div>
<div class="input-area">R <input class="coord" type='number' id="property-zone-key-light-color-red" min="0" max="255" step="1"></div>
<div class="input-area">G <input class="coord" type='number' id="property-zone-key-light-color-green" min="0" max="255" step="1"></div>
<div class="input-area">B <input class="coord" type='number' id="property-zone-key-light-color-blue" min="0" max="255" step="1"></div>
</div>
</div>
<div class="zone-section keyLight-section property">
<div class="label">Light Intensity</div>
<div class="value">
<input class="coord" type='number' id="property-zone-key-intensity" min="0" max="10" step="0.1">
</div>
</div>
<div class="zone-section keyLight-section property">
<div class="label">Light Direction</div>
<div class="value">
<div class="input-area">Pitch <input class="coord" type='number' id="property-zone-key-light-direction-x"></div>
<div class="input-area">Yaw <input class="coord" type='number' id="property-zone-key-light-direction-y"></div>
<div class="input-area">Roll <input class="coord" type='number' id="property-zone-key-light-direction-z"></div>
</div>
</div>
<div class="zone-section keyLight-section property">
<div class="label">Ambient Intensity</div>
<div class="value">
<input class="coord" type='number' id="property-zone-key-ambient-intensity" min="0" max="10" step="0.1">
</div>
</div>
<div class="zone-section keyLight-section property">
<div class="label">Ambient URL</div>
<div class="value">
<input type="text" id="property-zone-key-ambient-url" class="url">
</div>
</div>
<div class="sub-section-header zone-section stage-section">
<label>Stage</label>
</div>
<div class="zone-section stage-section property">
<div class="label">Stage Latitude</div>
<div class="value">
<input class="coord" type='number' id="property-zone-stage-latitude" min="-90" max="90" step="1">
</div>
</div>
<div class="zone-section stage-section property">
<div class="label">Stage Longitude</div>
<div class="value">
<input class="coord" type='number' id="property-zone-stage-longitude" min="-180" max="180" step="1">
</div>
</div>
<div class="zone-section stage-section property">
<div class="label">Stage Altitude</div>
<div class="value">
<input class="coord" type='number' id="property-zone-stage-altitude" step="1">
</div>
</div>
<div class="zone-section stage-section property">
<span class="label">Automatically calculate stage hour and day from location and clock.</span>
<span class="value">
<input type='checkbox' id="property-zone-stage-automatic-hour-day">
</span>
</div>
<div class="zone-section stage-section property">
<div class="label">Stage Day</div>
<div class="value">
<input class="coord" type='number' id="property-zone-stage-day" min="0" max="365" step="1">
</div>
</div>
<div class="zone-section stage-section property">
<div class="label">Stage Hour</div>
<div class="value">
<input class="coord" type='number' id="property-zone-stage-hour" min="0" max="24" step="0.5">
</div>
</div>
<div class="sub-section-header zone-section background-section">
<label>Background</label>
</div>
<div class="zone-section background-section property">
<div class="label">Background Mode</div>
<div class="value">
<select name="SelectBackgroundMode" id="property-zone-background-mode">
<option value='inherit'>Nothing</option>
<option value='skybox'>Skybox</option>
</select>
</div>
</div>
<div class="sub-section-header zone-section skybox-section">
<label>Skybox</label>
</div>
<div class="zone-section skybox-section property">
<div class="label">Skybox Color</div>
<div class="value">
<div class='color-picker' id="property-zone-skybox-color"></div>
<div class="input-area">R <input class="coord" type='number' id="property-zone-skybox-color-red"></div>
<div class="input-area">G <input class="coord" type='number' id="property-zone-skybox-color-green"></div>
<div class="input-area">B <input class="coord" type='number' id="property-zone-skybox-color-blue"></div>
</div>
</div>
<div class="zone-section skybox-section property">
<div class="label">Skybox URL</div>
<div class="value">
<input type="text" id="property-zone-skybox-url" class="url">
</div>
</div>
<div class="section-header web-section">
<label>Web</label>
</div>
@ -984,6 +1153,7 @@
<div class="label">Source URL</div>
<div class="value">
<input type="text" id="property-web-source-url" class="url">
</div>
</div>
@ -1364,41 +1534,7 @@
</div>
<div class="section-header text-section">
<label>Text</label>
</div>
<div class="text-section property">
<div class="label">Text Content</div>
<div class="value">
<input type="text" id="property-text-text">
</div>
</div>
<div class="text-section property">
<div class="label">Line Height</div>
<div class="value">
<input class="coord" type='number' id="property-text-line-height" min="0" step="0.005">
</div>
</div>
<div class="text-section property">
<div class="label">Text Color</div>
<div class="value">
<div class='color-picker' id="property-text-text-color"></div>
<div class="input-area">R <input class="coord" type='number' id="property-text-text-color-red"></div>
<div class="input-area">G <input class="coord" type='number' id="property-text-text-color-green"></div>
<div class="input-area">B <input class="coord" type='number' id="property-text-text-color-blue"></div>
</div>
</div>
<div class="text-section property">
<div class="label">Background Color</div>
<div class="value">
<div class='color-picker' id="property-text-background-color"></div>
<div class="input-area">R <input class="coord" type='number' id="property-text-background-color-red"></div>
<div class="input-area">G <input class="coord" type='number' id="property-text-background-color-green"></div>
<div class="input-area">B <input class="coord" type='number' id="property-text-background-color-blue"></div>
</div>
</div>
<div class="section-header light-section">
<label>Light</label>
@ -1437,141 +1573,6 @@
<input class="coord" type='number' id="property-light-cutoff">
</div>
</div>
<div class="section-header zone-section">
<label>Zone</label>
</div>
<div class="zone-section property">
<span class="label">Stage Sun Model Enabled</span>
<span class="value">
<input type='checkbox' id="property-zone-stage-sun-model-enabled">
</span>
</div>
<div class="sub-section-header zone-section keyLight-section">
<label>KeyLight</label>
</div>
<div class="zone-section keyLight-section property">
<div class="label">Light Color</div>
<div class="value">
<div class='color-picker' id="property-zone-key-light-color"></div>
<div class="input-area">R <input class="coord" type='number' id="property-zone-key-light-color-red" min="0" max="255" step="1"></div>
<div class="input-area">G <input class="coord" type='number' id="property-zone-key-light-color-green" min="0" max="255" step="1"></div>
<div class="input-area">B <input class="coord" type='number' id="property-zone-key-light-color-blue" min="0" max="255" step="1"></div>
</div>
</div>
<div class="zone-section keyLight-section property">
<div class="label">Light Intensity</div>
<div class="value">
<input class="coord" type='number' id="property-zone-key-intensity" min="0" max="10" step="0.1">
</div>
</div>
<div class="zone-section keyLight-section property">
<div class="label">Light Direction</div>
<div class="value">
<div class="input-area">Pitch <input class="coord" type='number' id="property-zone-key-light-direction-x"></div>
<div class="input-area">Yaw <input class="coord" type='number' id="property-zone-key-light-direction-y"></div>
<div class="input-area">Roll <input class="coord" type='number' id="property-zone-key-light-direction-z"></div>
</div>
</div>
<div class="zone-section keyLight-section property">
<div class="label">Ambient Intensity</div>
<div class="value">
<input class="coord" type='number' id="property-zone-key-ambient-intensity" min="0" max="10" step="0.1">
</div>
</div>
<div class="zone-section keyLight-section property">
<div class="label">Ambient URL</div>
<div class="value">
<input type="text" id="property-zone-key-ambient-url" class="url">
</div>
</div>
<div class="sub-section-header zone-section stage-section">
<label>Stage</label>
</div>
<div class="zone-section stage-section property">
<div class="label">Stage Latitude</div>
<div class="value">
<input class="coord" type='number' id="property-zone-stage-latitude" min="-90" max="90" step="1">
</div>
</div>
<div class="zone-section stage-section property">
<div class="label">Stage Longitude</div>
<div class="value">
<input class="coord" type='number' id="property-zone-stage-longitude" min="-180" max="180" step="1">
</div>
</div>
<div class="zone-section stage-section property">
<div class="label">Stage Altitude</div>
<div class="value">
<input class="coord" type='number' id="property-zone-stage-altitude" step="1">
</div>
</div>
<div class="zone-section stage-section property">
<span class="label">Automatically calculate stage hour and day from location and clock.</span>
<span class="value">
<input type='checkbox' id="property-zone-stage-automatic-hour-day">
</span>
</div>
<div class="zone-section stage-section property">
<div class="label">Stage Day</div>
<div class="value">
<input class="coord" type='number' id="property-zone-stage-day" min="0" max="365" step="1">
</div>
</div>
<div class="zone-section stage-section property">
<div class="label">Stage Hour</div>
<div class="value">
<input class="coord" type='number' id="property-zone-stage-hour" min="0" max="24" step="0.5">
</div>
</div>
<div class="sub-section-header zone-section background-section">
<label>Background</label>
</div>
<div class="zone-section background-section property">
<div class="label">Background Mode</div>
<div class="value">
<select name="SelectBackgroundMode" id="property-zone-background-mode">
<option value='inherit'>Nothing</option>
<option value='skybox'>Skybox</option>
</select>
</div>
</div>
<div class="sub-section-header zone-section skybox-section">
<label>Skybox</label>
</div>
<div class="zone-section skybox-section property">
<div class="label">Skybox Color</div>
<div class="value">
<div class='color-picker' id="property-zone-skybox-color"></div>
<div class="input-area">R <input class="coord" type='number' id="property-zone-skybox-color-red"></div>
<div class="input-area">G <input class="coord" type='number' id="property-zone-skybox-color-green"></div>
<div class="input-area">B <input class="coord" type='number' id="property-zone-skybox-color-blue"></div>
</div>
</div>
<div class="zone-section skybox-section property">
<div class="label">Skybox URL</div>
<div class="value">
<input type="text" id="property-zone-skybox-url" class="url">
</div>
</div>
</div>
</body>
</html>
</html>

View file

@ -145,7 +145,7 @@
"id": "rightHandGraspOpen",
"type": "clip",
"data": {
"url": "https://hifi-content.s3.amazonaws.com/ozan/dev/anim/hand_anims/hydra_pose_open_right.fbx",
"url": "http://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims_160127/hydra_pose_open_right.fbx",
"startFrame": 0.0,
"endFrame": 0.0,
"timeScale": 1.0,
@ -157,7 +157,7 @@
"id": "rightHandGraspClosed",
"type": "clip",
"data": {
"url": "https://hifi-content.s3.amazonaws.com/ozan/dev/anim/hand_anims/hydra_pose_closed_right.fbx",
"url": "http://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims_160127/hydra_pose_closed_right.fbx",
"startFrame": 0.0,
"endFrame": 0.0,
"timeScale": 1.0,
@ -205,7 +205,7 @@
"id": "leftHandGraspOpen",
"type": "clip",
"data": {
"url": "https://hifi-content.s3.amazonaws.com/ozan/dev/anim/hand_anims/hydra_pose_open_left.fbx",
"url": "http://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims_160127/hydra_pose_open_left.fbx",
"startFrame": 0.0,
"endFrame": 0.0,
"timeScale": 1.0,
@ -217,7 +217,7 @@
"id": "leftHandGraspClosed",
"type": "clip",
"data": {
"url": "https://hifi-content.s3.amazonaws.com/ozan/dev/anim/hand_anims/hydra_pose_closed_left.fbx",
"url": "http://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims_160127/hydra_pose_closed_left.fbx",
"startFrame": 10.0,
"endFrame": 10.0,
"timeScale": 1.0,
@ -420,7 +420,7 @@
"id": "idleStand",
"type": "clip",
"data": {
"url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/idle.fbx",
"url": "http://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims_160127/idle.fbx",
"startFrame": 0.0,
"endFrame": 90.0,
"timeScale": 1.0,
@ -432,7 +432,7 @@
"id": "idleTalk",
"type": "clip",
"data": {
"url": "http://hifi-public.s3.amazonaws.com/ozan/anim/talk/talk.fbx",
"url": "http://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims_160127/talk.fbx",
"startFrame": 0.0,
"endFrame": 801.0,
"timeScale": 1.0,
@ -457,7 +457,7 @@
"id": "walkFwdShort",
"type": "clip",
"data": {
"url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/walk_short_fwd.fbx",
"url": "http://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims_160127/walk_short_fwd.fbx",
"startFrame": 0.0,
"endFrame": 39.0,
"timeScale": 1.0,
@ -469,7 +469,7 @@
"id": "walkFwdNormal",
"type": "clip",
"data": {
"url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/walk_fwd.fbx",
"url": "http://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims_160127/walk_fwd.fbx",
"startFrame": 0.0,
"endFrame": 35.0,
"timeScale": 1.0,
@ -481,7 +481,7 @@
"id": "walkFwdRun",
"type": "clip",
"data": {
"url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/run_fwd.fbx",
"url": "http://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims_160127/run_fwd.fbx",
"startFrame": 0.0,
"endFrame": 21.0,
"timeScale": 1.0,
@ -495,7 +495,7 @@
"id": "idleToWalkFwd",
"type": "clip",
"data": {
"url": "http://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims/idle_to_walk.fbx",
"url": "http://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims_160127/idle_to_walk.fbx",
"startFrame": 1.0,
"endFrame": 19.0,
"timeScale": 1.0,
@ -518,7 +518,7 @@
"id": "walkBwdShort",
"type": "clip",
"data": {
"url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/walk_short_bwd.fbx",
"url": "http://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims_160127/walk_short_bwd.fbx",
"startFrame": 0.0,
"endFrame": 38.0,
"timeScale": 1.0,
@ -530,7 +530,7 @@
"id": "walkBwdNormal",
"type": "clip",
"data": {
"url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/walk_bwd.fbx",
"url": "http://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims_160127/walk_bwd.fbx",
"startFrame": 0.0,
"endFrame": 36.0,
"timeScale": 1.0,
@ -544,7 +544,7 @@
"id": "turnLeft",
"type": "clip",
"data": {
"url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/turn_left.fbx",
"url": "http://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims_160127/turn_left.fbx",
"startFrame": 0.0,
"endFrame": 28.0,
"timeScale": 1.0,
@ -556,7 +556,7 @@
"id": "turnRight",
"type": "clip",
"data": {
"url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/turn_right.fbx",
"url": "http://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims_160127/turn_right.fbx",
"startFrame": 0.0,
"endFrame": 30.0,
"timeScale": 1.0,
@ -579,7 +579,7 @@
"id": "strafeLeftShort",
"type": "clip",
"data": {
"url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/side_step_short_left.fbx",
"url": "http://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims_160127/side_step_short_left.fbx",
"startFrame": 0.0,
"endFrame": 28.0,
"timeScale": 1.0,
@ -591,7 +591,7 @@
"id": "strafeLeftNormal",
"type": "clip",
"data": {
"url": "http://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/side_step_left.fbx",
"url": "http://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims_160127/side_step_left.fbx",
"startFrame": 0.0,
"endFrame": 30.0,
"timeScale": 1.0,
@ -616,7 +616,7 @@
"id": "strafeRightShort",
"type": "clip",
"data": {
"url": "http://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/side_step_short_right.fbx",
"url": "http://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims_160127/side_step_short_right.fbx",
"startFrame": 0.0,
"endFrame": 28.0,
"timeScale": 1.0,
@ -628,7 +628,7 @@
"id": "strafeRightNormal",
"type": "clip",
"data": {
"url": "http://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/side_step_right.fbx",
"url": "http://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims_160127/side_step_right.fbx",
"startFrame": 0.0,
"endFrame": 30.0,
"timeScale": 1.0,
@ -642,7 +642,7 @@
"id": "awayIntro",
"type": "clip",
"data": {
"url": "https://hifi-public.s3.amazonaws.com/ozan/anim/kneel/kneel.fbx",
"url": "http://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims_160127/kneel.fbx",
"startFrame": 0.0,
"endFrame": 83.0,
"timeScale": 1.0,
@ -654,7 +654,7 @@
"id": "away",
"type": "clip",
"data": {
"url": "https://hifi-public.s3.amazonaws.com/ozan/anim/kneel/kneel.fbx",
"url": "http://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims_160127/kneel.fbx",
"startFrame": 83.0,
"endFrame": 84.0,
"timeScale": 1.0,
@ -666,7 +666,7 @@
"id": "awayOutro",
"type": "clip",
"data": {
"url": "https://hifi-public.s3.amazonaws.com/ozan/anim/kneel/kneel.fbx",
"url": "http://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims_160127/kneel.fbx",
"startFrame": 84.0,
"endFrame": 167.0,
"timeScale": 1.0,
@ -678,7 +678,7 @@
"id": "fly",
"type": "clip",
"data": {
"url": "https://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims/fly.fbx",
"url": "http://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims_160127/fly.fbx",
"startFrame": 1.0,
"endFrame": 80.0,
"timeScale": 1.0,
@ -700,7 +700,7 @@
"id": "userAnimA",
"type": "clip",
"data": {
"url": "http://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/idle.fbx",
"url": "http://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims_160127/idle.fbx",
"startFrame": 0.0,
"endFrame": 90.0,
"timeScale": 1.0,
@ -712,7 +712,7 @@
"id": "userAnimB",
"type": "clip",
"data": {
"url": "http://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/idle.fbx",
"url": "http://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims_160127/idle.fbx",
"startFrame": 0.0,
"endFrame": 90.0,
"timeScale": 1.0,

View file

@ -91,8 +91,10 @@ FocusScope {
id: popup
parent: desktop
anchors.fill: parent
z: desktop.zLevels.menu
visible: false
focus: true
MouseArea {
anchors.fill: parent
onClicked: hideList();
@ -116,7 +118,7 @@ FocusScope {
ListView {
id: listView
height: textView.height * count
height: textField.height * count * 1.4
model: root.model
highlight: Rectangle{
width: listView.currentItem ? listView.currentItem.width : 0

View file

@ -252,11 +252,17 @@ FocusScope {
return messageDialogBuilder.createObject(desktop, properties);
}
Component { id: queryDialogBuilder; QueryDialog { } }
function queryBox(properties) {
return queryDialogBuilder.createObject(desktop, properties);
Component { id: inputDialogBuilder; QueryDialog { } }
function inputDialog(properties) {
return inputDialogBuilder.createObject(desktop, properties);
}
Component { id: fileDialogBuilder; FileDialog { } }
function fileOpenDialog(properties) {
return fileDialogBuilder.createObject(desktop, properties);
}
MenuMouseHandler { id: menuPopperUpper }
function popupMenu(point) {
menuPopperUpper.popup(desktop, rootMenu.items, point);

View file

@ -12,6 +12,27 @@ import "fileDialog"
//FIXME implement shortcuts for favorite location
ModalWindow {
id: root
resizable: true
width: 640
height: 480
Settings {
category: "FileDialog"
property alias width: root.width
property alias height: root.height
property alias x: root.x
property alias y: root.y
}
// Set from OffscreenUi::getOpenFile()
property alias caption: root.title;
// Set from OffscreenUi::getOpenFile()
property alias dir: model.folder;
// Set from OffscreenUi::getOpenFile()
property alias filter: selectionType.filtersString;
// Set from OffscreenUi::getOpenFile()
property int options; // <-- FIXME unused
property bool selectDirectory: false;
property bool showHidden: false;
@ -19,17 +40,11 @@ ModalWindow {
property bool multiSelect: false;
// FIXME implement
property bool saveDialog: false;
property var helper: fileDialogHelper
property alias model: fileTableView.model
signal selectedFile(var file);
signal canceled();
resizable: true
width: 640
height: 480
property var helper: fileDialogHelper
property alias model: fileTableView.model
property alias filterModel: selectionType.model
property alias folder: model.folder
Rectangle {
anchors.fill: parent
@ -120,6 +135,7 @@ ModalWindow {
onDoubleClicked: navigateToRow(row);
model: FolderListModel {
id: model
nameFilters: selectionType.currentFilter
showDirsFirst: true
showDotAndDotDot: false
showFiles: !root.selectDirectory
@ -157,12 +173,10 @@ ModalWindow {
readOnly: true
}
ComboBox {
FileTypeSelection {
id: selectionType
anchors { bottom: buttonRow.top; bottomMargin: 8; right: parent.right; rightMargin: 8; left: buttonRow.left }
visible: !selectDirectory
model: ListModel { ListElement { text: "All Files (*.*)"; filter: "*.*" } }
// onCurrentIndexChanged: model.nameFilters = [ filterModel.get(currentIndex).filter ]
KeyNavigation.left: fileTableView
KeyNavigation.right: openButton
}

View file

@ -5,6 +5,7 @@ import QtQuick.Dialogs 1.2 as OriginalDialogs
import "../controls"
import "../styles"
import "../windows"
import "messageDialog"
// FIXME respect default button functionality
ModalWindow {
@ -126,126 +127,23 @@ ModalWindow {
onHeightChanged: d.resize(); onWidthChanged: d.resize();
layoutDirection: Qt.RightToLeft
anchors { bottom: details.top; right: parent.right; margins: d.spacing * 2; bottomMargin: 0 }
Button {
id: okButton
text: qsTr("OK")
focus: root.defaultButton === OriginalDialogs.StandardButton.Ok
onClicked: root.click(OriginalDialogs.StandardButton.Ok)
visible: root.buttons & OriginalDialogs.StandardButton.Ok
}
Button {
id: openButton
text: qsTr("Open")
focus: root.defaultButton === OriginalDialogs.StandardButton.Open
onClicked: root.click(OriginalDialogs.StandardButton.Open)
visible: root.buttons & OriginalDialogs.StandardButton.Open
}
Button {
id: saveButton
text: qsTr("Save")
focus: root.defaultButton === OriginalDialogs.StandardButton.Save
onClicked: root.click(OriginalDialogs.StandardButton.Save)
visible: root.buttons & OriginalDialogs.StandardButton.Save
}
Button {
id: saveAllButton
text: qsTr("Save All")
focus: root.defaultButton === OriginalDialogs.StandardButton.SaveAll
onClicked: root.click(OriginalDialogs.StandardButton.SaveAll)
visible: root.buttons & OriginalDialogs.StandardButton.SaveAll
}
Button {
id: retryButton
text: qsTr("Retry")
focus: root.defaultButton === OriginalDialogs.StandardButton.Retry
onClicked: root.click(OriginalDialogs.StandardButton.Retry)
visible: root.buttons & OriginalDialogs.StandardButton.Retry
}
Button {
id: ignoreButton
text: qsTr("Ignore")
focus: root.defaultButton === OriginalDialogs.StandardButton.Ignore
onClicked: root.click(OriginalDialogs.StandardButton.Ignore)
visible: root.buttons & OriginalDialogs.StandardButton.Ignore
}
Button {
id: applyButton
text: qsTr("Apply")
focus: root.defaultButton === OriginalDialogs.StandardButton.Apply
onClicked: root.click(OriginalDialogs.StandardButton.Apply)
visible: root.buttons & OriginalDialogs.StandardButton.Apply
}
Button {
id: yesButton
text: qsTr("Yes")
focus: root.defaultButton === OriginalDialogs.StandardButton.Yes
onClicked: root.click(OriginalDialogs.StandardButton.Yes)
visible: root.buttons & OriginalDialogs.StandardButton.Yes
}
Button {
id: yesAllButton
text: qsTr("Yes to All")
focus: root.defaultButton === OriginalDialogs.StandardButton.YesToAll
onClicked: root.click(OriginalDialogs.StandardButton.YesToAll)
visible: root.buttons & OriginalDialogs.StandardButton.YesToAll
}
Button {
id: noButton
text: qsTr("No")
focus: root.defaultButton === OriginalDialogs.StandardButton.No
onClicked: root.click(OriginalDialogs.StandardButton.No)
visible: root.buttons & OriginalDialogs.StandardButton.No
}
Button {
id: noAllButton
text: qsTr("No to All")
focus: root.defaultButton === OriginalDialogs.StandardButton.NoToAll
onClicked: root.click(OriginalDialogs.StandardButton.NoToAll)
visible: root.buttons & OriginalDialogs.StandardButton.NoToAll
}
Button {
id: discardButton
text: qsTr("Discard")
focus: root.defaultButton === OriginalDialogs.StandardButton.Discard
onClicked: root.click(OriginalDialogs.StandardButton.Discard)
visible: root.buttons & OriginalDialogs.StandardButton.Discard
}
Button {
id: resetButton
text: qsTr("Reset")
focus: root.defaultButton === OriginalDialogs.StandardButton.Reset
onClicked: root.click(OriginalDialogs.StandardButton.Reset)
visible: root.buttons & OriginalDialogs.StandardButton.Reset
}
Button {
id: restoreDefaultsButton
text: qsTr("Restore Defaults")
focus: root.defaultButton === OriginalDialogs.StandardButton.RestoreDefaults
onClicked: root.click(OriginalDialogs.StandardButton.RestoreDefaults)
visible: root.buttons & OriginalDialogs.StandardButton.RestoreDefaults
}
Button {
id: cancelButton
text: qsTr("Cancel")
focus: root.defaultButton === OriginalDialogs.StandardButton.Cancel
onClicked: root.click(OriginalDialogs.StandardButton.Cancel)
visible: root.buttons & OriginalDialogs.StandardButton.Cancel
}
Button {
id: abortButton
text: qsTr("Abort")
focus: root.defaultButton === OriginalDialogs.StandardButton.Abort
onClicked: root.click(OriginalDialogs.StandardButton.Abort)
visible: root.buttons & OriginalDialogs.StandardButton.Abort
}
Button {
id: closeButton
text: qsTr("Close")
focus: root.defaultButton === OriginalDialogs.StandardButton.Close
onClicked: root.click(OriginalDialogs.StandardButton.Close)
visible: root.buttons & OriginalDialogs.StandardButton.Close
}
MessageDialogButton { dialog: root; text: qsTr("OK"); button: OriginalDialogs.StandardButton.Ok; }
MessageDialogButton { dialog: root; text: qsTr("Open"); button: OriginalDialogs.StandardButton.Open; }
MessageDialogButton { dialog: root; text: qsTr("Save"); button: OriginalDialogs.StandardButton.Save; }
MessageDialogButton { dialog: root; text: qsTr("Save All"); button: OriginalDialogs.StandardButton.SaveAll; }
MessageDialogButton { dialog: root; text: qsTr("Retry"); button: OriginalDialogs.StandardButton.Retry; }
MessageDialogButton { dialog: root; text: qsTr("Ignore"); button: OriginalDialogs.StandardButton.Ignore; }
MessageDialogButton { dialog: root; text: qsTr("Apply"); button: OriginalDialogs.StandardButton.Apply; }
MessageDialogButton { dialog: root; text: qsTr("Yes"); button: OriginalDialogs.StandardButton.Yes; }
MessageDialogButton { dialog: root; text: qsTr("Yes to All"); button: OriginalDialogs.StandardButton.YesToAll; }
MessageDialogButton { dialog: root; text: qsTr("No"); button: OriginalDialogs.StandardButton.No; }
MessageDialogButton { dialog: root; text: qsTr("No to All"); button: OriginalDialogs.StandardButton.NoToAll; }
MessageDialogButton { dialog: root; text: qsTr("Discard"); button: OriginalDialogs.StandardButton.Discard; }
MessageDialogButton { dialog: root; text: qsTr("Reset"); button: OriginalDialogs.StandardButton.Reset; }
MessageDialogButton { dialog: root; text: qsTr("Restore Defaults"); button: OriginalDialogs.StandardButton.RestoreDefaults; }
MessageDialogButton { dialog: root; text: qsTr("Cancel"); button: OriginalDialogs.StandardButton.Cancel; }
MessageDialogButton { dialog: root; text: qsTr("Abort"); button: OriginalDialogs.StandardButton.Abort; }
MessageDialogButton { dialog: root; text: qsTr("Close"); button: OriginalDialogs.StandardButton.Close; }
Button {
id: moreButton
text: qsTr("Show Details...")
@ -253,13 +151,7 @@ ModalWindow {
}
visible: detailedText && detailedText.length > 0
}
Button {
id: helpButton
text: qsTr("Help")
focus: root.defaultButton === OriginalDialogs.StandardButton.Help
onClicked: root.click(OriginalDialogs.StandardButton.Help)
visible: root.buttons & OriginalDialogs.StandardButton.Help
}
MessageDialogButton { dialog: root; text: qsTr("Help"); button: OriginalDialogs.StandardButton.Help; }
}
Item {
@ -328,7 +220,7 @@ ModalWindow {
case Qt.Key_Enter:
case Qt.Key_Return:
event.accepted = true
root.click(OriginalDialogs.StandardButton.Ok)
root.click(root.defaultButton)
break
}
}

View file

@ -16,9 +16,17 @@ ModalWindow {
signal selected(var result);
signal canceled();
property alias result: textResult.text
property var items;
property alias label: mainTextContainer.text
property var result;
// FIXME not current honored
property var current;
// For text boxes
property alias placeholderText: textResult.placeholderText
property alias text: mainTextContainer.text
// For combo boxes
property bool editable: true;
Rectangle {
clip: true
@ -55,10 +63,20 @@ ModalWindow {
anchors { top: mainTextContainer.bottom; bottom: buttons.top; left: parent.left; right: parent.right; margins: d.spacing }
// FIXME make a text field type that can be bound to a history for autocompletion
TextField {
focus: true
id: textResult
focus: items ? false : true
visible: items ? false : true
anchors { left: parent.left; right: parent.right; verticalCenter: parent.verticalCenter }
}
VrControls.ComboBox {
id: comboBox
focus: items ? true : false
visible: items ? true : false
anchors { left: parent.left; right: parent.right; verticalCenter: parent.verticalCenter }
model: items ? items : []
}
}
Flow {
@ -86,6 +104,7 @@ ModalWindow {
text: qsTr("OK")
shortcut: Qt.Key_Return
onTriggered: {
root.result = items ? comboBox.currentText : textResult.text
root.selected(root.result);
root.destroy();
}

View file

@ -72,23 +72,6 @@ Window {
scripts.stopAllScripts();
}
Component {
id: fileDialogBuilder
FileDialog { }
}
function loadFromFile() {
var fileDialog = fileDialogBuilder.createObject(desktop, { filterModel: fileFilters });
fileDialog.canceled.connect(function(){
console.debug("Cancelled file open")
})
fileDialog.selectedFile.connect(function(file){
console.debug("Selected " + file)
scripts.loadOneScript(file);
})
}
Rectangle {
color: "white"
anchors.fill: parent
@ -123,26 +106,42 @@ Window {
}
ListView {
id: listView
clip: true
anchors { fill: parent; margins: 0 }
model: runningScriptsModel
delegate: Rectangle {
id: rectangle
clip: true
radius: 3
anchors { left: parent.left; right: parent.right }
height: scriptName.height + 12
color: index % 2 ? "#ddd" : "#eee"
height: scriptName.height + 12 + (ListView.isCurrentItem ? scriptName.height + 6 : 0)
color: ListView.isCurrentItem ? "#39f" :
index % 2 ? "#ddd" : "#eee"
Text {
anchors { left: parent.left; leftMargin: 4; verticalCenter: parent.verticalCenter }
id: scriptName
anchors { left: parent.left; leftMargin: 4; top: parent.top; topMargin:6 }
text: name
}
Text {
id: scriptUrl
anchors { left: scriptName.left; right: parent.right; rightMargin: 4; top: scriptName.bottom; topMargin: 6 }
text: url
elide: Text.ElideMiddle
}
MouseArea {
anchors.fill: parent
onClicked: listView.currentIndex = index
}
Row {
anchors.verticalCenter: parent.verticalCenter
anchors.verticalCenter: scriptName.verticalCenter
anchors.right: parent.right
anchors.rightMargin: 4
spacing: 4
@ -185,31 +184,38 @@ Window {
anchors.bottomMargin: 8
anchors.right: parent.right
// 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.
Timer {
id: asyncAction
interval: 50
repeat: false
running: false
onTriggered: ApplicationInterface.loadScriptURLDialog();
}
Button {
text: "from URL";
onClicked: {
focus = false;
asyncAction.running = true;
onClicked: fromUrlTimer.running = true;
// 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.
Timer {
id: fromUrlTimer
interval: 5
repeat: false
running: false
onTriggered: ApplicationInterface.loadScriptURLDialog();
}
}
Button {
text: "from Disk"
onClicked: loadFromFile();
onClicked: fromDiskTimer.running = true;
Timer {
id: fromDiskTimer
interval: 5
repeat: false
running: false
onTriggered: ApplicationInterface.loadDialog();
}
}
}

View file

@ -0,0 +1,27 @@
import QtQuick 2.5
import "../../controls" as VrControls
VrControls.ComboBox {
id: root
property string filtersString: "All Files (*.*)";
property var currentFilter: [ "*.*" ];
// Per http://doc.qt.io/qt-5/qfiledialog.html#getOpenFileName the string can contain
// multiple filters separated by semicolons
// ex: "Images (*.png *.xpm *.jpg);;Text files (*.txt);;XML files (*.xml)"
model: filtersString.split(';;');
enabled: model.length > 1
onCurrentTextChanged: {
var globRegex = /\((.*)\)$/
var globs = globRegex.exec(currentText);
if (!globs[1]) {
console.warn("Unable to parse filter " + currentText);
return;
}
currentFilter = globs[1].split(" ");
}
}

View file

@ -0,0 +1,12 @@
import QtQuick 2.5
import QtQuick.Controls 1.2
import QtQuick.Dialogs 1.2
Button {
property var dialog;
property int button: StandardButton.NoButton;
focus: dialog.defaultButton === button
onClicked: dialog.click(button)
visible: dialog.buttons & button
}

View file

@ -20,12 +20,8 @@ Frame {
Row {
id: controlsRow
anchors.right: parent.right
anchors.top: parent.top
anchors.rightMargin: iconSize
anchors.topMargin: iconSize / 2
anchors { right: parent.right; top: parent.top; rightMargin: iconSize; topMargin: iconSize / 2; }
spacing: iconSize / 4
FontAwesome {
visible: false
text: "\uf08d"
@ -54,6 +50,18 @@ Frame {
}
}
}
Text {
id: titleText
anchors { left: parent.left; leftMargin: iconSize; right: controlsRow.left; rightMargin: iconSize; top: parent.top; topMargin: iconSize / 2; }
text: window.title
elide: Text.ElideRight
font.bold: true
color: window.focus ? "white" : "gray"
style: Text.Outline;
styleColor: "black"
}
}
}

View file

@ -25,7 +25,7 @@ Item {
id: debugZ
visible: DebugQML
text: window ? "Z: " + window.z : ""
y: -height
y: window.height + 4
}
function deltaSize(dx, dy) {

View file

@ -13,5 +13,16 @@ Frame {
color: "#7f7f7f7f";
radius: 3;
}
Text {
y: -implicitHeight - iconSize / 2
text: window.title
elide: Text.ElideRight
font.bold: true
color: window.focus ? "white" : "gray"
style: Text.Outline;
styleColor: "black"
}
}

View file

@ -406,6 +406,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
_entityClipboard(new EntityTree()),
_lastQueriedTime(usecTimestampNow()),
_mirrorViewRect(QRect(MIRROR_VIEW_LEFT_PADDING, MIRROR_VIEW_TOP_PADDING, MIRROR_VIEW_WIDTH, MIRROR_VIEW_HEIGHT)),
_previousScriptLocation("LastScriptLocation", DESKTOP_LOCATION),
_fieldOfView("fieldOfView", DEFAULT_FIELD_OF_VIEW_DEGREES),
_scaleMirror(1.0f),
_rotateMirror(0.0f),
@ -4501,14 +4502,24 @@ void Application::domainSettingsReceived(const QJsonObject& domainSettingsObject
}
void Application::loadDialog() {
// To be migratd to QML
QString fileNameString = QFileDialog::getOpenFileName(
_glWidget, tr("Open Script"), "", tr("JavaScript Files (*.js)"));
if (!fileNameString.isEmpty()) {
auto scriptEngines = DependencyManager::get<ScriptEngines>();
QString fileNameString = OffscreenUi::getOpenFileName(
_glWidget, tr("Open Script"), getPreviousScriptLocation(), tr("JavaScript Files (*.js)"));
if (!fileNameString.isEmpty() && QFile(fileNameString).exists()) {
setPreviousScriptLocation(QFileInfo(fileNameString).absolutePath());
DependencyManager::get<ScriptEngines>()->loadScript(fileNameString, true, false, false, true); // Don't load from cache
}
}
QString Application::getPreviousScriptLocation() {
QString result = _previousScriptLocation.get();
return result;
}
void Application::setPreviousScriptLocation(const QString& location) {
_previousScriptLocation.set(location);
}
void Application::loadScriptURLDialog() {
auto newScript = OffscreenUi::getText(nullptr, "Open and Run Script", "Script URL");
if (!newScript.isEmpty()) {

View file

@ -103,6 +103,9 @@ public:
void postLambdaEvent(std::function<void()> f) override;
QString getPreviousScriptLocation();
void setPreviousScriptLocation(const QString& previousScriptLocation);
void initializeGL();
void initializeUi();
void paintGL();
@ -431,6 +434,7 @@ private:
Camera _mirrorCamera; // Cammera for mirror view
QRect _mirrorViewRect;
Setting::Handle<QString> _previousScriptLocation;
Setting::Handle<float> _fieldOfView;
float _scaleMirror;

View file

@ -20,12 +20,14 @@
#include <AddressManager.h>
#include <Application.h>
#include <OffscreenUi.h>
#include "MainWindow.h"
#include "Menu.h"
#include "InterfaceLogging.h"
#include "Bookmarks.h"
#include <QtQuick/QQuickWindow>
Bookmarks::Bookmarks() {
_bookmarksFilename = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/" + BOOKMARKS_FILENAME;
@ -104,18 +106,13 @@ void Bookmarks::setupMenus(Menu* menubar, MenuWrapper* menu) {
}
void Bookmarks::bookmarkLocation() {
QInputDialog bookmarkLocationDialog(qApp->getWindow());
bookmarkLocationDialog.setWindowTitle("Bookmark Location");
bookmarkLocationDialog.setLabelText("Name:");
bookmarkLocationDialog.setInputMode(QInputDialog::TextInput);
bookmarkLocationDialog.resize(400, 200);
if (bookmarkLocationDialog.exec() == QDialog::Rejected) {
bool ok = false;
auto bookmarkName = OffscreenUi::getText(nullptr, "Bookmark Location", "Name:", QLineEdit::Normal, QString(), &ok);
if (!ok) {
return;
}
QString bookmarkName = bookmarkLocationDialog.textValue().trimmed();
bookmarkName = bookmarkName.replace(QRegExp("(\r\n|[\r\n\t\v ])+"), " ");
bookmarkName = bookmarkName.trimmed().replace(QRegExp("(\r\n|[\r\n\t\v ])+"), " ");
if (bookmarkName.length() == 0) {
return;
}
@ -125,13 +122,14 @@ void Bookmarks::bookmarkLocation() {
Menu* menubar = Menu::getInstance();
if (contains(bookmarkName)) {
QMessageBox duplicateBookmarkMessage;
duplicateBookmarkMessage.setIcon(QMessageBox::Warning);
duplicateBookmarkMessage.setText("The bookmark name you entered already exists in your list.");
duplicateBookmarkMessage.setInformativeText("Would you like to overwrite it?");
duplicateBookmarkMessage.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
duplicateBookmarkMessage.setDefaultButton(QMessageBox::Yes);
if (duplicateBookmarkMessage.exec() == QMessageBox::No) {
auto offscreenUi = DependencyManager::get<OffscreenUi>();
auto duplicateBookmarkMessage = offscreenUi->createMessageBox(QMessageBox::Warning, "Duplicate Bookmark",
"The bookmark name you entered already exists in your list.",
QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
duplicateBookmarkMessage->setProperty("informativeText", "Would you like to overwrite it?");
auto result = offscreenUi->waitForMessageBoxResult(duplicateBookmarkMessage);
if (result != QMessageBox::Yes) {
return;
}
removeLocationFromMenu(menubar, bookmarkName);
@ -157,19 +155,13 @@ void Bookmarks::deleteBookmark() {
bookmarkList.append(menuItems[i]->text());
}
QInputDialog deleteBookmarkDialog(qApp->getWindow());
deleteBookmarkDialog.setWindowTitle("Delete Bookmark");
deleteBookmarkDialog.setLabelText("Select the bookmark to delete");
deleteBookmarkDialog.resize(400, 400);
deleteBookmarkDialog.setOption(QInputDialog::UseListViewForComboBoxItems);
deleteBookmarkDialog.setComboBoxItems(bookmarkList);
deleteBookmarkDialog.setOkButtonText("Delete");
if (deleteBookmarkDialog.exec() == QDialog::Rejected) {
bool ok = false;
auto bookmarkName = OffscreenUi::getItem(nullptr, "Delete Bookmark", "Select the bookmark to delete", bookmarkList, 0, false, &ok);
if (!ok) {
return;
}
QString bookmarkName = deleteBookmarkDialog.textValue().trimmed();
bookmarkName = bookmarkName.trimmed();
if (bookmarkName.length() == 0) {
return;
}

View file

@ -191,10 +191,10 @@ bool ScriptEditorWidget::save() {
bool ScriptEditorWidget::saveAs() {
auto scriptEngines = DependencyManager::get<ScriptEngines>();
QString fileName = QFileDialog::getSaveFileName(this, tr("Save script"),
scriptEngines->getPreviousScriptLocation(),
qApp->getPreviousScriptLocation(),
tr("JavaScript Files (*.js)"));
if (!fileName.isEmpty()) {
scriptEngines->setPreviousScriptLocation(fileName);
qApp->setPreviousScriptLocation(fileName);
return saveFile(fileName);
} else {
return false;

View file

@ -87,12 +87,11 @@ void ScriptEditorWindow::loadScriptMenu(const QString& scriptName) {
}
void ScriptEditorWindow::loadScriptClicked() {
auto scriptEngines = DependencyManager::get<ScriptEngines>();
QString scriptName = QFileDialog::getOpenFileName(this, tr("Interface"),
scriptEngines->getPreviousScriptLocation(),
qApp->getPreviousScriptLocation(),
tr("JavaScript Files (*.js)"));
if (!scriptName.isEmpty()) {
scriptEngines->setPreviousScriptLocation(scriptName);
qApp->setPreviousScriptLocation(scriptName);
addScriptEditorWidget("loading...")->loadFile(scriptName);
updateButtons();
}
@ -100,7 +99,7 @@ void ScriptEditorWindow::loadScriptClicked() {
void ScriptEditorWindow::loadMenuAboutToShow() {
_loadMenu->clear();
QStringList runningScripts = DependencyManager::get<ScriptEngines>()->getRunningScripts();;
QStringList runningScripts = DependencyManager::get<ScriptEngines>()->getRunningScripts();
if (runningScripts.count() > 0) {
QSignalMapper* signalMapper = new QSignalMapper(this);
foreach (const QString& runningScript, runningScripts) {

View file

@ -102,6 +102,11 @@ void AudioInjector::restart() {
// reset the current send offset to zero
_currentSendOffset = 0;
// reset state to start sending from beginning again
_nextFrame = 0;
_frameTimer->invalidate();
_hasSentFirstFrame = false;
// check our state to decide if we need extra handling for the restart request
if (_state == State::Finished) {
// we finished playing, need to reset state so we can get going again
@ -246,6 +251,11 @@ int64_t AudioInjector::injectNextFrame() {
}
}
if (!_frameTimer->isValid()) {
// in the case where we have been restarted, the frame timer will be invalid and we need to start it back over here
_frameTimer->restart();
}
int totalBytesLeftToCopy = (_options.stereo ? 2 : 1) * AudioConstants::NETWORK_FRAME_BYTES_PER_CHANNEL;
if (!_options.loop) {
// If we aren't looping, let's make sure we don't read past the end

View file

@ -79,6 +79,12 @@ void AudioInjectorManager::run() {
if (_injectors.size() > 0) {
// loop through the injectors in the map and send whatever frames need to go out
auto front = _injectors.top();
// create an InjectorQueue to hold injectors to be queued
// this allows us to call processEvents even if a single injector wants to be re-queued immediately
std::vector<TimeInjectorPointerPair> heldInjectors;
heldInjectors.reserve(_injectors.size());
while (_injectors.size() > 0 && front.first <= usecTimestampNow()) {
// either way we're popping this injector off - get a copy first
auto injector = front.second;
@ -89,8 +95,8 @@ void AudioInjectorManager::run() {
auto nextCallDelta = injector->injectNextFrame();
if (nextCallDelta >= 0 && !injector->isFinished()) {
// re-enqueue the injector with the correct timing
_injectors.emplace(usecTimestampNow() + nextCallDelta, injector);
// enqueue the injector with the correct timing in our holding queue
heldInjectors.emplace(heldInjectors.end(), usecTimestampNow() + nextCallDelta, injector);
}
}
@ -101,6 +107,12 @@ void AudioInjectorManager::run() {
break;
}
}
// if there are injectors in the holding queue, push them to our persistent queue now
while (!heldInjectors.empty()) {
_injectors.push(heldInjectors.back());
heldInjectors.pop_back();
}
}
} else {

View file

@ -490,6 +490,9 @@ void NodeList::processDomainServerList(QSharedPointer<ReceivedMessage> message)
// this is a packet from the domain server, reset the count of un-replied check-ins
_numNoReplyDomainCheckIns = 0;
// emit our signal so listeners know we just heard from the DS
emit receivedDomainServerList();
DependencyManager::get<NodeList>()->flagTimeForConnectionStep(LimitedNodeList::ConnectionStep::ReceiveDSList);
QDataStream packetStream(message->getMessage());

View file

@ -87,6 +87,7 @@ public slots:
signals:
void limitOfSilentDomainCheckInsReached();
void receivedDomainServerList();
private slots:
void stopKeepalivePingTimer();
void sendPendingDSPathQuery();

View file

@ -30,6 +30,10 @@ ThreadedAssignment::ThreadedAssignment(ReceivedMessage& message) :
connect(&_domainServerTimer, &QTimer::timeout, this, &ThreadedAssignment::checkInWithDomainServerOrExit);
_domainServerTimer.setInterval(DOMAIN_SERVER_CHECK_IN_MSECS);
// if the NL tells us we got a DS response, clear our member variable of queued check-ins
auto nodeList = DependencyManager::get<NodeList>();
connect(nodeList.data(), &NodeList::receivedDomainServerList, this, &ThreadedAssignment::clearQueuedCheckIns);
}
void ThreadedAssignment::setFinished(bool isFinished) {
@ -103,11 +107,18 @@ void ThreadedAssignment::sendStatsPacket() {
}
void ThreadedAssignment::checkInWithDomainServerOrExit() {
if (DependencyManager::get<NodeList>()->getNumNoReplyDomainCheckIns() == MAX_SILENT_DOMAIN_SERVER_CHECK_INS) {
// verify that the number of queued check-ins is not >= our max
// the number of queued check-ins is cleared anytime we get a response from the domain-server
if (_numQueuedCheckIns >= MAX_SILENT_DOMAIN_SERVER_CHECK_INS) {
qDebug() << "At least" << MAX_SILENT_DOMAIN_SERVER_CHECK_INS << "have been queued without a response from domain-server"
<< "Stopping the current assignment";
setFinished(true);
} else {
auto nodeList = DependencyManager::get<NodeList>();
QMetaObject::invokeMethod(nodeList.data(), "sendDomainServerCheckIn");
// increase the number of queued check ins
_numQueuedCheckIns++;
}
}

View file

@ -33,6 +33,7 @@ public slots:
virtual void run() = 0;
Q_INVOKABLE virtual void stop() { setFinished(true); }
virtual void sendStatsPacket();
void clearQueuedCheckIns() { _numQueuedCheckIns = 0; }
signals:
void finished();
@ -42,6 +43,7 @@ protected:
bool _isFinished;
QTimer _domainServerTimer;
QTimer _statsTimer;
int _numQueuedCheckIns { 0 };
protected slots:
void domainSettingsRequestFailed();

View file

@ -34,8 +34,7 @@ ScriptsModel& getScriptsModel() {
}
ScriptEngines::ScriptEngines()
: _scriptsLocationHandle("scriptsLocation", DESKTOP_LOCATION),
_previousScriptLocation("LastScriptLocation", DESKTOP_LOCATION)
: _scriptsLocationHandle("scriptsLocation", DESKTOP_LOCATION)
{
_scriptsModelFilter.setSourceModel(&_scriptsModel);
_scriptsModelFilter.sort(0, Qt::AscendingOrder);
@ -445,14 +444,3 @@ void ScriptEngines::onScriptEngineError(const QString& scriptFilename) {
qCDebug(scriptengine) << "Application::loadScript(), script failed to load...";
emit scriptLoadError(scriptFilename, "");
}
QString ScriptEngines::getPreviousScriptLocation() const {
return _previousScriptLocation.get();
}
void ScriptEngines::setPreviousScriptLocation(const QString& previousScriptLocation) {
if (_previousScriptLocation.get() != previousScriptLocation) {
_previousScriptLocation.set(previousScriptLocation);
emit previousScriptLocationChanged();
}
}

View file

@ -30,7 +30,6 @@ class ScriptEngines : public QObject, public Dependency {
Q_PROPERTY(ScriptsModel* scriptsModel READ scriptsModel CONSTANT)
Q_PROPERTY(ScriptsModelFilter* scriptsModelFilter READ scriptsModelFilter CONSTANT)
Q_PROPERTY(QString previousScriptLocation READ getPreviousScriptLocation WRITE setPreviousScriptLocation NOTIFY previousScriptLocationChanged)
public:
using ScriptInitializer = std::function<void(ScriptEngine*)>;
@ -48,9 +47,6 @@ public:
QStringList getRunningScripts();
ScriptEngine* getScriptEngine(const QString& scriptHash);
QString getPreviousScriptLocation() const;
void setPreviousScriptLocation(const QString& previousScriptLocation);
ScriptsModel* scriptsModel() { return &_scriptsModel; };
ScriptsModelFilter* scriptsModelFilter() { return &_scriptsModelFilter; };
@ -73,7 +69,6 @@ signals:
void scriptCountChanged();
void scriptsReloading();
void scriptLoadError(const QString& filename, const QString& error);
void previousScriptLocationChanged();
protected slots:
void onScriptFinished(const QString& fileNameString, ScriptEngine* engine);
@ -97,7 +92,6 @@ protected:
std::atomic<bool> _stoppingAllScripts { false };
std::list<ScriptInitializer> _scriptInitializers;
mutable Setting::Handle<QString> _scriptsLocationHandle;
mutable Setting::Handle<QString> _previousScriptLocation;
ScriptsModel _scriptsModel;
ScriptsModelFilter _scriptsModelFilter;
};

View file

@ -199,19 +199,7 @@ private slots:
}
};
QMessageBox::StandardButton OffscreenUi::messageBox(QMessageBox::Icon icon, const QString& title, const QString& text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton) {
if (QThread::currentThread() != thread()) {
QMessageBox::StandardButton result = QMessageBox::StandardButton::NoButton;
QMetaObject::invokeMethod(this, "messageBox", Qt::BlockingQueuedConnection,
Q_RETURN_ARG(QMessageBox::StandardButton, result),
Q_ARG(QMessageBox::Icon, icon),
Q_ARG(QString, title),
Q_ARG(QString, text),
Q_ARG(QMessageBox::StandardButtons, buttons),
Q_ARG(QMessageBox::StandardButton, defaultButton));
return result;
}
QQuickItem* OffscreenUi::createMessageBox(QMessageBox::Icon icon, const QString& title, const QString& text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton) {
QVariantMap map;
map.insert("title", title);
map.insert("text", text);
@ -225,12 +213,34 @@ QMessageBox::StandardButton OffscreenUi::messageBox(QMessageBox::Icon icon, cons
if (!invokeResult) {
qWarning() << "Failed to create message box";
return QMessageBox::StandardButton::NoButton;
return nullptr;
}
return qvariant_cast<QQuickItem*>(result);
}
QMessageBox::StandardButton OffscreenUi::waitForMessageBoxResult(QQuickItem* messageBox) {
if (!messageBox) {
return QMessageBox::NoButton;
}
QMessageBox::StandardButton resultButton = MessageBoxListener(qvariant_cast<QQuickItem*>(result)).waitForButtonResult();
qDebug() << "Message box got a result of " << resultButton;
return resultButton;
return MessageBoxListener(messageBox).waitForButtonResult();
}
QMessageBox::StandardButton OffscreenUi::messageBox(QMessageBox::Icon icon, const QString& title, const QString& text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton) {
if (QThread::currentThread() != thread()) {
QMessageBox::StandardButton result = QMessageBox::StandardButton::NoButton;
QMetaObject::invokeMethod(this, "messageBox", Qt::BlockingQueuedConnection,
Q_RETURN_ARG(QMessageBox::StandardButton, result),
Q_ARG(QMessageBox::Icon, icon),
Q_ARG(QString, title),
Q_ARG(QString, text),
Q_ARG(QMessageBox::StandardButtons, buttons),
Q_ARG(QMessageBox::StandardButton, defaultButton));
return result;
}
return waitForMessageBoxResult(createMessageBox(icon, title, text, buttons, defaultButton));
}
QMessageBox::StandardButton OffscreenUi::critical(const QString& title, const QString& text,
@ -273,6 +283,7 @@ private slots:
// FIXME many input parameters currently ignored
QString OffscreenUi::getText(void* ignored, const QString & title, const QString & label, QLineEdit::EchoMode mode, const QString & text, bool * ok, Qt::WindowFlags flags, Qt::InputMethodHints inputMethodHints) {
if (ok) { *ok = false; }
QVariant result = DependencyManager::get<OffscreenUi>()->inputDialog(title, label, text).toString();
if (ok && result.isValid()) {
*ok = true;
@ -280,35 +291,70 @@ QString OffscreenUi::getText(void* ignored, const QString & title, const QString
return result.toString();
}
// FIXME many input parameters currently ignored
QString OffscreenUi::getItem(void *ignored, const QString & title, const QString & label, const QStringList & items, int current, bool editable, bool * ok, Qt::WindowFlags flags, Qt::InputMethodHints inputMethodHints) {
if (ok) {
*ok = false;
}
QVariant OffscreenUi::inputDialog(const QString& query, const QString& placeholderText, const QString& currentValue) {
auto offscreenUi = DependencyManager::get<OffscreenUi>();
auto inputDialog = offscreenUi->createInputDialog(title, label, current);
if (!inputDialog) {
return QString();
}
inputDialog->setProperty("items", items);
inputDialog->setProperty("editable", editable);
QVariant result = offscreenUi->waitForInputDialogResult(inputDialog);
if (!result.isValid()) {
return QString();
}
if (ok) {
*ok = true;
}
return result.toString();
}
QVariant OffscreenUi::inputDialog(const QString& title, const QString& label, const QVariant& current) {
if (QThread::currentThread() != thread()) {
QVariant result;
QMetaObject::invokeMethod(this, "queryBox", Qt::BlockingQueuedConnection,
QMetaObject::invokeMethod(this, "inputDialog", Qt::BlockingQueuedConnection,
Q_RETURN_ARG(QVariant, result),
Q_ARG(QString, query),
Q_ARG(QString, placeholderText),
Q_ARG(QString, currentValue));
Q_ARG(QString, title),
Q_ARG(QString, label),
Q_ARG(QVariant, current));
return result;
}
return waitForInputDialogResult(createInputDialog(title, label, current));
}
QQuickItem* OffscreenUi::createInputDialog(const QString& title, const QString& label, const QVariant& current) {
QVariantMap map;
map.insert("text", query);
map.insert("placeholderText", placeholderText);
map.insert("result", currentValue);
map.insert("title", title);
map.insert("label", label);
map.insert("current", current);
QVariant result;
bool invokeResult = QMetaObject::invokeMethod(_desktop, "queryBox",
bool invokeResult = QMetaObject::invokeMethod(_desktop, "inputDialog",
Q_RETURN_ARG(QVariant, result),
Q_ARG(QVariant, QVariant::fromValue(map)));
if (!invokeResult) {
qWarning() << "Failed to create message box";
return QVariant();
return nullptr;
}
return InputDialogListener(qvariant_cast<QQuickItem*>(result)).waitForResult();
return qvariant_cast<QQuickItem*>(result);
}
QVariant OffscreenUi::waitForInputDialogResult(QQuickItem* inputDialog) {
if (!inputDialog) {
return QVariant();
}
return InputDialogListener(inputDialog).waitForResult();
}
bool OffscreenUi::navigationFocused() {
return offscreenFlags->isNavigationFocused();
@ -412,4 +458,66 @@ void OffscreenUi::toggleMenu(const QPoint& screenPosition) {
}
class FileDialogListener : public ModalDialogListener {
Q_OBJECT
friend class OffscreenUi;
FileDialogListener(QQuickItem* messageBox) : ModalDialogListener(messageBox) {
if (_finished) {
return;
}
connect(_dialog, SIGNAL(selectedFile(QVariant)), this, SLOT(onSelectedFile(QVariant)));
}
private slots:
void onSelectedFile(QVariant file) {
_result = file;
_finished = true;
disconnect(_dialog);
}
};
QString OffscreenUi::fileOpenDialog(const QString& caption, const QString& dir, const QString& filter, QString* selectedFilter, QFileDialog::Options options) {
if (QThread::currentThread() != thread()) {
QString result;
QMetaObject::invokeMethod(this, "fileOpenDialog", Qt::BlockingQueuedConnection,
Q_RETURN_ARG(QString, result),
Q_ARG(QString, caption),
Q_ARG(QString, dir),
Q_ARG(QString, filter),
Q_ARG(QString*, selectedFilter),
Q_ARG(QFileDialog::Options, options));
return result;
}
// FIXME support returning the selected filter... somehow?
QVariantMap map;
map.insert("caption", caption);
map.insert("dir", QUrl::fromLocalFile(dir));
map.insert("filter", filter);
map.insert("options", static_cast<int>(options));
QVariant buildDialogResult;
bool invokeResult = QMetaObject::invokeMethod(_desktop, "fileOpenDialog",
Q_RETURN_ARG(QVariant, buildDialogResult),
Q_ARG(QVariant, QVariant::fromValue(map)));
if (!invokeResult) {
qWarning() << "Failed to create file open dialog";
return QString();
}
QVariant result = FileDialogListener(qvariant_cast<QQuickItem*>(buildDialogResult)).waitForResult();
if (!result.isValid()) {
return QString();
}
qDebug() << result.toString();
return result.toUrl().toLocalFile();
}
QString OffscreenUi::getOpenFileName(void* ignored, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options) {
return DependencyManager::get<OffscreenUi>()->fileOpenDialog(caption, dir, filter, selectedFilter, options);
}
#include "OffscreenUi.moc"

View file

@ -42,6 +42,13 @@ public:
QQuickItem* getToolWindow();
// Message box compatibility
Q_INVOKABLE QMessageBox::StandardButton messageBox(QMessageBox::Icon icon, const QString& title, const QString& text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton);
// Must be called from the main thread
QQuickItem* createMessageBox(QMessageBox::Icon icon, const QString& title, const QString& text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton);
// Must be called from the main thread
QMessageBox::StandardButton waitForMessageBoxResult(QQuickItem* messageBox);
/// Same design as QMessageBox::critical(), will block, returns result
static QMessageBox::StandardButton critical(void* ignored, const QString& title, const QString& text,
QMessageBox::StandardButtons buttons = QMessageBox::Ok,
@ -80,18 +87,21 @@ public:
QMessageBox::StandardButtons buttons = QMessageBox::Ok,
QMessageBox::StandardButton defaultButton = QMessageBox::NoButton);
Q_INVOKABLE QMessageBox::StandardButton messageBox(QMessageBox::Icon icon, const QString& title, const QString& text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton);
Q_INVOKABLE QVariant inputDialog(const QString& query, const QString& placeholderText = QString(), const QString& currentValue = QString());
// FIXME implement
static QVariant query(const QString& query, const QString& placeholderText = QString(), const QString& currentValue = QString());
// FIXME implement
// file dialog compatibility
Q_INVOKABLE QString fileOpenDialog(const QString &caption = QString(), const QString &dir = QString(), const QString &filter = QString(), QString *selectedFilter = 0, QFileDialog::Options options = 0);
// Compatibility with QFileDialog::getOpenFileName
static QString getOpenFileName(void* ignored, const QString &caption = QString(), const QString &dir = QString(), const QString &filter = QString(), QString *selectedFilter = 0, QFileDialog::Options options = 0);
// input dialog compatibility
Q_INVOKABLE QVariant inputDialog(const QString& title, const QString& label = QString(), const QVariant& current = QVariant());
QQuickItem* createInputDialog(const QString& title, const QString& label, const QVariant& current);
QVariant waitForInputDialogResult(QQuickItem* inputDialog);
// Compatibility with QInputDialog::getText
static QString getText(void* ignored, const QString & title, const QString & label, QLineEdit::EchoMode mode = QLineEdit::Normal, const QString & text = QString(), bool * ok = 0, Qt::WindowFlags flags = 0, Qt::InputMethodHints inputMethodHints = Qt::ImhNone);
// Compatibility with QInputDialog::getItem
static QString getItem(void *ignored, const QString & title, const QString & label, const QStringList & items, int current = 0, bool editable = true, bool * ok = 0, Qt::WindowFlags flags = 0, Qt::InputMethodHints inputMethodHints = Qt::ImhNone);
private:
QQuickItem* _desktop { nullptr };

View file

@ -21,6 +21,7 @@ DISTFILES += \
../../interface/resources/qml/dialogs/*.qml \
../../interface/resources/qml/dialogs/fileDialog/*.qml \
../../interface/resources/qml/dialogs/preferences/*.qml \
../../interface/resources/qml/dialogs/messageDialog/*.qml \
../../interface/resources/qml/desktop/*.qml \
../../interface/resources/qml/menus/*.qml \
../../interface/resources/qml/styles/*.qml \