diff --git a/Packages/ohif-viewerbase/client/lib/studyLoadingListener.js b/Packages/ohif-viewerbase/client/lib/studyLoadingListener.js index 86bfa56a7..adbe1b6de 100644 --- a/Packages/ohif-viewerbase/client/lib/studyLoadingListener.js +++ b/Packages/ohif-viewerbase/client/lib/studyLoadingListener.js @@ -19,6 +19,14 @@ class BaseLoadingListener { delete Session.keys.progressSessionId; } + startListening() { + throw new Error('`startListening` must be implemented by child clases'); + } + + stopListening() { + throw new Error('`stopListening` must be implemented by child clases'); + } + destroy() { this.stopListening(); this._clearSession(); @@ -26,7 +34,7 @@ class BaseLoadingListener { static getNewId() { const timeSlice = (new Date()).getTime().toString().slice(-8); - const randomNumber = parseInt(Math.random() * 1000000000000); + const randomNumber = parseInt(Math.random() * 1000000000); return timeSlice.toString() + randomNumber.toString(); } @@ -35,6 +43,69 @@ class BaseLoadingListener { class DICOMFileLoadingListener extends BaseLoadingListener { constructor(stack) { super(stack); + this.dataSetUrls = this._getDataSetUrls(stack); + } + + _getImageLoadProgressEventName() { + return 'CornerstoneImageLoadProgress.' + this.id; + } + + startListening() { + const imageLoadProgressEventName = this._getImageLoadProgressEventName(); + + this.stopListening(); + + $(cornerstone).on(imageLoadProgressEventName, (e, eventData) => { + this._imageLoadProgressEventHandle(e, eventData); + }); + } + + stopListening() { + const imageLoadProgressEventName = this._getImageLoadProgressEventName(); + $(cornerstone).off(imageLoadProgressEventName); + } + + _imageLoadProgressEventHandle(e, eventData) { + var dataSetUrl = this._getDataSetUrl(eventData.imageId); + + if (!this.dataSetUrls.has(dataSetUrl)) { + return; + } + + this._triggerProgress(eventData); + } + + _triggerProgress(eventData) { + const progressSessionId = this._getProgressSessionId(); + + Session.set(progressSessionId, { + percentComplete: eventData.percentComplete, + bytesLoaded: eventData.loaded, + bytesTotal: eventData.total + }); + } + + _getDataSetUrl(imageId) { + // Remove "frame=999&" from the imageId + imageId = imageId.replace(/frame=\d+&?/i, ''); + + // Remove the last "&" like in "dicomweb:...&serverId=GQGpJcb4CnYDdu53q&" + imageId = imageId.replace(/&$/, ""); + + return imageId; + } + + _getDataSetUrls(stack) { + const dataSetUrls = new Set(); + const imageIds = stack.imageIds; + const length = stack.imageIds.length; + + for (let i = 0; i < length; i++) { + const dataSetUrl = this._getDataSetUrl(imageIds[i]); + dataSetUrls.add(dataSetUrl); + } + + return dataSetUrls; } } @@ -45,17 +116,17 @@ class StackLoadingListener extends BaseLoadingListener { this.loadedImageIds = []; } - getImageLoadedEventName() { + _getImageLoadedEventName() { return 'CornerstoneImageLoaded.' + this.id; } - getImageCachePromiseRemoveEventName() { + _getImageCachePromiseRemoveEventName() { return 'CornerstoneImageCachePromiseRemoved.' + this.id; } startListening() { - const imageLoadedEventName = this.getImageLoadedEventName(); - const imageCachePromiseRemovedEventName = this.getImageCachePromiseRemoveEventName(); + const imageLoadedEventName = this._getImageLoadedEventName(); + const imageCachePromiseRemovedEventName = this._getImageCachePromiseRemoveEventName(); this.stopListening(); @@ -69,21 +140,17 @@ class StackLoadingListener extends BaseLoadingListener { } stopListening() { - const imageLoadedEventName = this.getImageLoadedEventName(); - const imageCachePromiseRemovedEventName = this.getImageCachePromiseRemoveEventName(); + const imageLoadedEventName = this._getImageLoadedEventName(); + const imageCachePromiseRemovedEventName = this._getImageCachePromiseRemoveEventName(); $(cornerstone).off(imageLoadedEventName); $(cornerstone).off(imageCachePromiseRemovedEventName); } - _hasImageId(imageId) { - return this.stack.imageIds.indexOf(imageId) !== -1; - } - _moveImageId(imageId, srcImageIds, dstImageIds) { const imageIdIndex = srcImageIds.indexOf(imageId); - if(imageIdIndex === -1) { + if (imageIdIndex === -1) { return; } @@ -106,7 +173,7 @@ class StackLoadingListener extends BaseLoadingListener { const loadedImagesCount = this.loadedImageIds.length; const remainingImagesCount = this.remainingImageIds.length; const totalImagesCount = loadedImagesCount + remainingImagesCount; - const percentComplete = loadedImagesCount / (totalImagesCount); + const percentComplete = Math.round(loadedImagesCount / totalImagesCount * 100); const progressSessionId = this._getProgressSessionId(); Session.set(progressSessionId, { @@ -123,11 +190,11 @@ class StudyLoadingListener { this.listeners = {}; } - addStack(stack) { + addStack(stack, options) { const displaySetInstanceUid = stack.displaySetInstanceUid; if (!this.listeners[displaySetInstanceUid]) { - listener = this._createListener(stack); + listener = this._createListener(stack, options); if (listener) { this.listeners[displaySetInstanceUid] = listener; } @@ -137,16 +204,18 @@ class StudyLoadingListener { addStudy(study) { study.displaySets.forEach(displaySet => { const stack = OHIF.viewerbase.stackManager.findOrCreateStack(study, displaySet); - this.addStack(stack); + this.addStack(stack, { + isMultiFrame: displaySet.isMultiFrame + }); }); } addStudies(studies) { - if(!studies || !studies.length) { + if (!studies || !studies.length) { return; } - for(let i = 0; i < studies.length; i++) { + for (let i = 0; i < studies.length; i++) { this.addStudy(studies[i]); } } @@ -155,20 +224,22 @@ class StudyLoadingListener { const displaySetInstanceUids = Object.keys(this.listeners); const length = displaySetInstanceUids.length; - for(let i = 0; i < length; i++) { + for (let i = 0; i < length; i++) { const displaySetInstanceUid = displaySetInstanceUids[i]; const displaySet = this.listeners[displaySetInstanceUid] displaySet.destroy(); } - this.listener = {}; + this.listeners = {}; } - _createListener(stack) { + _createListener(stack, options) { const schema = this._getSchema(stack); - if(schema === 'wadors') { - return new StackLoadingListener(stack); + if ((schema === 'wadors') || !options.isMultiFrame) { + return new StackLoadingListener(stack) + } else if ((schema === 'dicomweb') || (schema === 'wadouri')) { + return new DICOMFileLoadingListener(stack); } } @@ -179,6 +250,7 @@ class StudyLoadingListener { } } +// Singleton const studyLoadingListener = new StudyLoadingListener(); export { studyLoadingListener }; \ No newline at end of file