# HG changeset patch # User Benjamin Golinvaux # Date 1553009347 -3600 # Node ID 7428c5dfa5dfa54b7fe1196d994ccbba4c2fd6ee # Parent 9d124a81c34ab91bc64078bebbe74bd328194f72 Initial commit non working app diff -r 9d124a81c34a -r 7428c5dfa5df Applications/Samples/CtPetDoseStructFusion/AppStatus.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Applications/Samples/CtPetDoseStructFusion/AppStatus.h Tue Mar 19 16:29:07 2019 +0100 @@ -0,0 +1,27 @@ +#pragma once + +#include + + +namespace CtPetDoseStructFusion +{ + struct AppStatus + { + std::string patientId; + std::string studyDescription; + std::string currentSeriesIdInMainViewport; + // note: if you add members here, update the serialization code below and deserialization in ct-dose-struct-fusion.ts -> onAppStatusUpdated() + + + AppStatus() + { + } + + void ToJson(Json::Value &output) const + { + output["patientId"] = patientId; + output["studyDescription"] = studyDescription; + output["currentSeriesIdInMainViewport"] = currentSeriesIdInMainViewport; + } + }; +} diff -r 9d124a81c34a -r 7428c5dfa5df Applications/Samples/CtPetDoseStructFusion/CMakeLists.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Applications/Samples/CtPetDoseStructFusion/CMakeLists.txt Tue Mar 19 16:29:07 2019 +0100 @@ -0,0 +1,145 @@ +cmake_minimum_required(VERSION 2.8.3) +project(CtPetDoseStructFusion) + +include(../../../Resources/CMake/OrthancStoneParameters.cmake) + +if (OPENSSL_NO_CAPIENG) +add_definitions(-DOPENSSL_NO_CAPIENG=1) +endif() + +set(ENABLE_SDL OFF CACHE BOOL "Target SDL Native application") +set(ENABLE_QT OFF CACHE BOOL "Target Qt Native application") +set(ENABLE_WASM OFF CACHE BOOL "Target WASM application") + +if (ENABLE_WASM) + ##################################################################### + ## Configuration of the Emscripten compiler for WebAssembly target + ##################################################################### + + set(WASM_FLAGS "-s WASM=1") + set(WASM_FLAGS "${WASM_FLAGS} -s STRICT=1") # drops support for all deprecated build options + set(WASM_FLAGS "${WASM_FLAGS} -s FILESYSTEM=1") # if we don't include it, gen_uuid.c fails to build because srand, getpid(), ... are not defined + set(WASM_FLAGS "${WASM_FLAGS} -s DISABLE_EXCEPTION_CATCHING=0") # actually enable exception catching + set(WASM_FLAGS "${WASM_FLAGS} -s ERROR_ON_MISSING_LIBRARIES=1") + + if (CMAKE_BUILD_TYPE MATCHES DEBUG) + set(WASM_FLAGS "${WASM_FLAGS} -g4") # generate debug information + set(WASM_FLAGS "${WASM_FLAGS} -s ASSERTIONS=2") # more runtime checks + else() + set(WASM_FLAGS "${WASM_FLAGS} -Os") # optimize for web (speed and size) + endif() + + set(WASM_MODULE_NAME "StoneFrameworkModule" CACHE STRING "Name of the WebAssembly module") + + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WASM_FLAGS}") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WASM_FLAGS}") + + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${WASM_FLAGS}") # not always clear which flags are for the compiler and which one are for the linker -> pass them all to the linker too + + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --js-library ${STONE_SOURCES_DIR}/Platforms/Wasm/WasmWebService.js") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --js-library ${STONE_SOURCES_DIR}/Platforms/Wasm/WasmDelayedCallExecutor.js") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --js-library ${STONE_SOURCES_DIR}/Platforms/Wasm/default-library.js") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s EXTRA_EXPORTED_RUNTIME_METHODS='[\"ccall\", \"cwrap\"]'") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s EXPORT_NAME='\"${WASM_MODULE_NAME}\"'") + +# +-------------------------------+ +# | Commented for now! | +# +-------------------------------+ + # set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s ALLOW_MEMORY_GROWTH=1") + # set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s TOTAL_MEMORY=536870912") + # set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s TOTAL_STACK=128000000") + + add_definitions(-DORTHANC_ENABLE_WASM=1) + set(ORTHANC_SANDBOXED ON) + +elseif (ENABLE_QT OR ENABLE_SDL) + + set(ENABLE_NATIVE ON) + set(ORTHANC_SANDBOXED OFF) + set(ENABLE_CRYPTO_OPTIONS ON) + set(ENABLE_GOOGLE_TEST ON) + set(ENABLE_WEB_CLIENT ON) + +endif() + +##################################################################### +## Configuration for Orthanc +##################################################################### + +if (ORTHANC_STONE_VERSION STREQUAL "mainline") + set(ORTHANC_FRAMEWORK_VERSION "mainline") + set(ORTHANC_FRAMEWORK_DEFAULT_SOURCE "hg") +else() + set(ORTHANC_FRAMEWORK_VERSION "1.4.1") + set(ORTHANC_FRAMEWORK_DEFAULT_SOURCE "web") +endif() + +set(ORTHANC_FRAMEWORK_SOURCE "${ORTHANC_FRAMEWORK_DEFAULT_SOURCE}" CACHE STRING "Source of the Orthanc source code (can be \"hg\", \"archive\", \"web\" or \"path\")") +set(ORTHANC_FRAMEWORK_ARCHIVE "" CACHE STRING "Path to the Orthanc archive, if ORTHANC_FRAMEWORK_SOURCE is \"archive\"") +set(ORTHANC_FRAMEWORK_ROOT "" CACHE STRING "Path to the Orthanc source directory, if ORTHANC_FRAMEWORK_SOURCE is \"path\"") + +##################################################################### +## Build a static library containing the Orthanc Stone framework +##################################################################### + + +LIST(APPEND ORTHANC_BOOST_COMPONENTS program_options) + +include(../../Resources/CMake/OrthancStoneConfiguration.cmake) + +add_library(OrthancStone STATIC + ${ORTHANC_STONE_SOURCES} + ) + +##################################################################### +## Build the CDSF applications +##################################################################### + +if (ENABLE_QT OR ENABLE_WASM) + if (ENABLE_QT) + list(APPEND CDSF_APPLICATION_SOURCES + ${ORTHANC_STONE_ROOT}/Applications/Samples/CtPetDoseStructFusion/Qt/CtPetDoseStructFusionMainWindow.cpp + ${ORTHANC_STONE_ROOT}/Applications/Samples/CtPetDoseStructFusion/Qt/CtPetDoseStructFusionMainWindow.ui + ${ORTHANC_STONE_ROOT}/Applications/Samples/CtPetDoseStructFusion/Qt/mainQt.cpp + ) + + ORTHANC_QT_WRAP_UI(CDSF_APPLICATION_SOURCES + ${ORTHANC_STONE_ROOT}/Applications/Samples/CtPetDoseStructFusion/Qt/CtPetDoseStructFusionMainWindow.ui + ) + + ORTHANC_QT_WRAP_CPP(CDSF_APPLICATION_SOURCES + ${ORTHANC_STONE_ROOT}/Applications/Samples/CtPetDoseStructFusion/Qt/CtPetDoseStructFusionMainWindow.h + ) + + elseif (ENABLE_WASM) + list(APPEND CDSF_APPLICATION_SOURCES + ${ORTHANC_STONE_ROOT}/Applications/Samples/CtPetDoseStructFusion/Wasm/mainWasm.cpp + ${ORTHANC_STONE_ROOT}/Applications/Samples/CtPetDoseStructFusion/Wasm/CtPetDoseStructFusionWasmApplicationAdapter.cpp + ${ORTHANC_STONE_ROOT}/Applications/Samples/CtPetDoseStructFusion/Wasm/CtPetDoseStructFusionWasmApplicationAdapter.h + ${STONE_WASM_SOURCES} + ) + endif() + + add_executable(CtPetDoseStructFusionApplication + ${ORTHANC_STONE_ROOT}/Applications/Samples/CtPetDoseStructFusion/AppStatus.h + ${ORTHANC_STONE_ROOT}/Applications/Samples/CtPetDoseStructFusion/MainWidgetInteractor.cpp + ${ORTHANC_STONE_ROOT}/Applications/Samples/CtPetDoseStructFusion/MainWidgetInteractor.h + ${ORTHANC_STONE_ROOT}/Applications/Samples/CtPetDoseStructFusion/Messages.h + ${ORTHANC_STONE_ROOT}/Applications/Samples/CtPetDoseStructFusion/CtPetDoseStructFusionApplication.cpp + ${ORTHANC_STONE_ROOT}/Applications/Samples/CtPetDoseStructFusion/CtPetDoseStructFusionApplication.h + ${ORTHANC_STONE_ROOT}/Applications/Samples/CtPetDoseStructFusion/ThumbnailInteractor.cpp + ${ORTHANC_STONE_ROOT}/Applications/Samples/CtPetDoseStructFusion/ThumbnailInteractor.h + ${CDSF_APPLICATION_SOURCES} + ) + target_link_libraries(CtPetDoseStructFusionApplication OrthancStone) + +endif() + + + + + + + + + diff -r 9d124a81c34a -r 7428c5dfa5df Applications/Samples/CtPetDoseStructFusion/CtPetDoseStructFusionApplication.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Applications/Samples/CtPetDoseStructFusion/CtPetDoseStructFusionApplication.cpp Tue Mar 19 16:29:07 2019 +0100 @@ -0,0 +1,239 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2019 Osimis S.A., Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + **/ + + +#include "CtPetDoseStructFusionApplication.h" + +#if ORTHANC_ENABLE_QT == 1 +# include "Qt/CtPetDoseStructFusionMainWindow.h" +#endif + +#if ORTHANC_ENABLE_WASM == 1 +# include +#endif + +namespace CtPetDoseStructFusion +{ + + void CtPetDoseStructFusionApplication::Initialize(StoneApplicationContext* context, + IStatusBar& statusBar, + const boost::program_options::variables_map& parameters) + { + using namespace OrthancStone; + + context_ = context; + statusBar_ = &statusBar; + + {// initialize viewports and layout + mainLayout_ = new LayoutWidget("main-layout"); + mainLayout_->SetPadding(10); + mainLayout_->SetBackgroundCleared(true); + mainLayout_->SetBackgroundColor(0, 0, 0); + mainLayout_->SetHorizontal(); + + thumbnailsLayout_ = new LayoutWidget("thumbnail-layout"); + thumbnailsLayout_->SetPadding(10); + thumbnailsLayout_->SetBackgroundCleared(true); + thumbnailsLayout_->SetBackgroundColor(50, 50, 50); + thumbnailsLayout_->SetVertical(); + + mainWidget_ = new SliceViewerWidget(IObserver::GetBroker(), "main-viewport"); + //mainWidget_->RegisterObserver(*this); + + // hierarchy + mainLayout_->AddWidget(thumbnailsLayout_); + mainLayout_->AddWidget(mainWidget_); + + // sources + smartLoader_.reset(new SmartLoader(IObserver::GetBroker(), context->GetOrthancApiClient())); + smartLoader_->SetImageQuality(SliceImageQuality_FullPam); + + mainLayout_->SetTransmitMouseOver(true); + mainWidgetInteractor_.reset(new MainWidgetInteractor(*this)); + mainWidget_->SetInteractor(*mainWidgetInteractor_); + thumbnailInteractor_.reset(new ThumbnailInteractor(*this)); + } + + statusBar.SetMessage("Use the key \"s\" to reinitialize the layout"); + statusBar.SetMessage("Use the key \"n\" to go to next image in the main viewport"); + +#if TODO_BGO_CDSF + if (parameters.count("studyId") < 1) + { + LOG(WARNING) << "The study ID is missing, will take the first studyId found in Orthanc"; + context->GetOrthancApiClient().GetJsonAsync("/studies", new Callable(*this, &CtPetDoseStructFusionApplication::OnStudyListReceived)); + } + else + { + SelectStudy(parameters["studyId"].as()); + } +#endif +// TODO_BGO_CDSF + } + + + void CtPetDoseStructFusionApplication::DeclareStartupOptions(boost::program_options::options_description& options) + { + boost::program_options::options_description generic("Sample options"); +#if TODO_BGO_CDSF + generic.add_options() + ("studyId", boost::program_options::value(), + "Orthanc ID of the study") + ; + + options.add(generic); +#endif + } + + void CtPetDoseStructFusionApplication::OnStudyListReceived(const OrthancApiClient::JsonResponseReadyMessage& message) + { + const Json::Value& response = message.GetJson(); + + if (response.isArray() && + response.size() >= 1) + { + SelectStudy(response[0].asString()); + } + } + void CtPetDoseStructFusionApplication::OnStudyReceived(const OrthancApiClient::JsonResponseReadyMessage& message) + { + const Json::Value& response = message.GetJson(); + + if (response.isObject() && response["Series"].isArray()) + { + for (size_t i=0; i < response["Series"].size(); i++) + { + context_->GetOrthancApiClient().GetJsonAsync( + "/series/" + response["Series"][(int)i].asString(), + new Callable< + CtPetDoseStructFusionApplication + , OrthancApiClient::JsonResponseReadyMessage>( + *this, + &CtPetDoseStructFusionApplication::OnSeriesReceived + ) + ); + } + } + } + + void CtPetDoseStructFusionApplication::OnSeriesReceived(const OrthancApiClient::JsonResponseReadyMessage& message) + { + const Json::Value& response = message.GetJson(); + + if (response.isObject() && + response["Instances"].isArray() && + response["Instances"].size() > 0) + { + // keep track of all instances IDs + const std::string& seriesId = response["ID"].asString(); + seriesTags_[seriesId] = response; + instancesIdsPerSeriesId_[seriesId] = std::vector(); + for (size_t i = 0; i < response["Instances"].size(); i++) + { + const std::string& instanceId = response["Instances"][static_cast(i)].asString(); + instancesIdsPerSeriesId_[seriesId].push_back(instanceId); + } + + // load the first instance in the thumbnail + LoadThumbnailForSeries(seriesId, instancesIdsPerSeriesId_[seriesId][0]); + + // if this is the first thumbnail loaded, load the first instance in the mainWidget + if (mainWidget_->GetLayerCount() == 0) + { + smartLoader_->SetFrameInWidget(*mainWidget_, 0, instancesIdsPerSeriesId_[seriesId][0], 0); + } + } + } + + void CtPetDoseStructFusionApplication::LoadThumbnailForSeries(const std::string& seriesId, const std::string& instanceId) + { + LOG(INFO) << "Loading thumbnail for series " << seriesId; + + SliceViewerWidget* thumbnailWidget = + new SliceViewerWidget(IObserver::GetBroker(), "thumbnail-series-" + seriesId); + thumbnails_.push_back(thumbnailWidget); + thumbnailsLayout_->AddWidget(thumbnailWidget); + + thumbnailWidget->RegisterObserverCallback( + new Callable + (*this, &CtPetDoseStructFusionApplication::OnWidgetGeometryChanged)); + + smartLoader_->SetFrameInWidget(*thumbnailWidget, 0, instanceId, 0); + thumbnailWidget->SetInteractor(*thumbnailInteractor_); + } + + void CtPetDoseStructFusionApplication::SelectStudy(const std::string& studyId) + { + context_->GetOrthancApiClient().GetJsonAsync("/studies/" + studyId, new Callable(*this, &CtPetDoseStructFusionApplication::OnStudyReceived)); + } + + void CtPetDoseStructFusionApplication::OnWidgetGeometryChanged(const SliceViewerWidget::GeometryChangedMessage& message) + { + // TODO: The "const_cast" could probably be replaced by "mainWidget_" + const_cast(message.GetOrigin()).FitContent(); + } + + void CtPetDoseStructFusionApplication::SelectSeriesInMainViewport(const std::string& seriesId) + { + smartLoader_->SetFrameInWidget(*mainWidget_, 0, instancesIdsPerSeriesId_[seriesId][0], 0); + } + + bool CtPetDoseStructFusionApplication::Handle(const StoneSampleCommands::SelectTool& value) ORTHANC_OVERRIDE + { + currentTool_ = value.tool; + return true; + } + + bool CtPetDoseStructFusionApplication::Handle(const StoneSampleCommands::Action& value) ORTHANC_OVERRIDE + { + switch (value.type) + { + case ActionType_Invert: + // TODO + break; + case ActionType_UndoCrop: + // TODO + break; + case ActionType_Rotate: + // TODO + break; + default: + throw std::runtime_error("Action type not supported"); + } + return true; + } + +#if ORTHANC_ENABLE_QT==1 + QStoneMainWindow* CtPetDoseStructFusionApplication::CreateQtMainWindow() + { + return new CtPetDoseStructFusionMainWindow(dynamic_cast(*context_), *this); + } +#endif + +#if ORTHANC_ENABLE_WASM==1 + void CtPetDoseStructFusionApplication::InitializeWasm() { + + AttachWidgetToWasmViewport("canvasThumbnails", thumbnailsLayout_); + AttachWidgetToWasmViewport("canvasMain", mainWidget_); + } +#endif + + +} diff -r 9d124a81c34a -r 7428c5dfa5df Applications/Samples/CtPetDoseStructFusion/CtPetDoseStructFusionApplication.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Applications/Samples/CtPetDoseStructFusion/CtPetDoseStructFusionApplication.h Tue Mar 19 16:29:07 2019 +0100 @@ -0,0 +1,170 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2019 Osimis S.A., Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + **/ + + +#pragma once + + /* + This header contains the command definitions for the sample applications + */ +#include "Applications/Samples/StoneSampleCommands_generated.hpp" +using namespace StoneSampleCommands; + +#include "Applications/IStoneApplication.h" + +#include "Framework/Layers/CircleMeasureTracker.h" +#include "Framework/Layers/LineMeasureTracker.h" +#include "Framework/Widgets/SliceViewerWidget.h" +#include "Framework/Widgets/LayoutWidget.h" +#include "Framework/Messages/IObserver.h" +#include "Framework/SmartLoader.h" + +#if ORTHANC_ENABLE_WASM==1 +#include "Platforms/Wasm/WasmPlatformApplicationAdapter.h" +#include "Platforms/Wasm/Defaults.h" +#endif + +#if ORTHANC_ENABLE_QT==1 +#include "Qt/CtPetDoseStructFusionMainWindow.h" +#endif + +#include +#include + +#include "ThumbnailInteractor.h" +#include "MainWidgetInteractor.h" +#include "AppStatus.h" +#include "Messages.h" + +using namespace OrthancStone; + + +namespace CtPetDoseStructFusion +{ + + class CtPetDoseStructFusionApplication + : public IStoneApplication + , public IObserver + , public IObservable + , public StoneSampleCommands::IHandler + { + public: + + struct StatusUpdatedMessage : public BaseMessage + { + const AppStatus& status_; + + StatusUpdatedMessage(const AppStatus& status) + : BaseMessage(), + status_(status) + { + } + }; + + private: + Tool currentTool_; + + std::auto_ptr mainWidgetInteractor_; + std::auto_ptr thumbnailInteractor_; + LayoutWidget* mainLayout_; + LayoutWidget* thumbnailsLayout_; + SliceViewerWidget* mainWidget_; + std::vector thumbnails_; + std::map > instancesIdsPerSeriesId_; + std::map seriesTags_; + unsigned int currentInstanceIndex_; + OrthancStone::WidgetViewport* wasmViewport1_; + OrthancStone::WidgetViewport* wasmViewport2_; + + IStatusBar* statusBar_; + std::auto_ptr smartLoader_; + + Orthanc::Font font_; + + public: + CtPetDoseStructFusionApplication(MessageBroker& broker) : + IObserver(broker), + IObservable(broker), + currentTool_(StoneSampleCommands::Tool_LineMeasure), + mainLayout_(NULL), + currentInstanceIndex_(0), + wasmViewport1_(NULL), + wasmViewport2_(NULL) + { + font_.LoadFromResource(Orthanc::EmbeddedResources::FONT_UBUNTU_MONO_BOLD_16); + } + + virtual void Finalize() {} + virtual IWidget* GetCentralWidget() {return mainLayout_;} + + virtual void DeclareStartupOptions(boost::program_options::options_description& options); + virtual void Initialize(StoneApplicationContext* context, + IStatusBar& statusBar, + const boost::program_options::variables_map& parameters); + + void OnStudyListReceived(const OrthancApiClient::JsonResponseReadyMessage& message); + + void OnStudyReceived(const OrthancApiClient::JsonResponseReadyMessage& message); + + void OnSeriesReceived(const OrthancApiClient::JsonResponseReadyMessage& message); + + void LoadThumbnailForSeries(const std::string& seriesId, const std::string& instanceId); + + void SelectStudy(const std::string& studyId); + + void OnWidgetGeometryChanged(const SliceViewerWidget::GeometryChangedMessage& message); + + void SelectSeriesInMainViewport(const std::string& seriesId); + + + Tool GetCurrentTool() const + { + return currentTool_; + } + + const Orthanc::Font& GetFont() const + { + return font_; + } + + // ExecuteAction method was empty (its body was a single "TODO" comment) + virtual bool Handle(const SelectTool& value) ORTHANC_OVERRIDE; + virtual bool Handle(const Action& value) ORTHANC_OVERRIDE; + + template + bool ExecuteCommand(const T& cmd) + { + std::string cmdStr = StoneSampleCommands::StoneSerialize(cmd); + return StoneSampleCommands::StoneDispatchToHandler(cmdStr, this); + } + + virtual std::string GetTitle() const {return "CtPetDoseStructFusion";} + +#if ORTHANC_ENABLE_WASM==1 + virtual void InitializeWasm(); +#endif + +#if ORTHANC_ENABLE_QT==1 + virtual QStoneMainWindow* CreateQtMainWindow(); +#endif + }; + + +} diff -r 9d124a81c34a -r 7428c5dfa5df Applications/Samples/CtPetDoseStructFusion/MainWidgetInteractor.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Applications/Samples/CtPetDoseStructFusion/MainWidgetInteractor.cpp Tue Mar 19 16:29:07 2019 +0100 @@ -0,0 +1,111 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2019 Osimis S.A., Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + **/ + +#include "MainWidgetInteractor.h" + +#include "CtPetDoseStructFusionApplication.h" + +namespace CtPetDoseStructFusion { + + IWorldSceneMouseTracker* MainWidgetInteractor::CreateMouseTracker(WorldSceneWidget& widget, + const ViewportGeometry& view, + MouseButton button, + KeyboardModifiers modifiers, + int viewportX, + int viewportY, + double x, + double y, + IStatusBar* statusBar, + const std::vector& displayTouches) + { + if (button == MouseButton_Left) + { + if (application_.GetCurrentTool() == Tool_LineMeasure) + { + return new LineMeasureTracker(statusBar, dynamic_cast(widget).GetSlice(), + x, y, 255, 0, 0, application_.GetFont()); + } + else if (application_.GetCurrentTool() == Tool_CircleMeasure) + { + return new CircleMeasureTracker(statusBar, dynamic_cast(widget).GetSlice(), + x, y, 255, 0, 0, application_.GetFont()); + } + else if (application_.GetCurrentTool() == Tool_Crop) + { + // TODO + } + else if (application_.GetCurrentTool() == Tool_Windowing) + { + // TODO + } + else if (application_.GetCurrentTool() == Tool_Zoom) + { + // TODO + } + else if (application_.GetCurrentTool() == Tool_Pan) + { + // TODO + } + } + return NULL; + } + + void MainWidgetInteractor::MouseOver(CairoContext& context, + WorldSceneWidget& widget, + const ViewportGeometry& view, + double x, + double y, + IStatusBar* statusBar) + { + if (statusBar != NULL) + { + Vector p = dynamic_cast(widget).GetSlice().MapSliceToWorldCoordinates(x, y); + + char buf[64]; + sprintf(buf, "X = %.02f Y = %.02f Z = %.02f (in cm)", + p[0] / 10.0, p[1] / 10.0, p[2] / 10.0); + statusBar->SetMessage(buf); + } + } + + void MainWidgetInteractor::MouseWheel(WorldSceneWidget& widget, + MouseWheelDirection direction, + KeyboardModifiers modifiers, + IStatusBar* statusBar) + { + } + + void MainWidgetInteractor::KeyPressed(WorldSceneWidget& widget, + KeyboardKeys key, + char keyChar, + KeyboardModifiers modifiers, + IStatusBar* statusBar) + { + switch (keyChar) + { + case 's': + widget.FitContent(); + break; + + default: + break; + } + } +} diff -r 9d124a81c34a -r 7428c5dfa5df Applications/Samples/CtPetDoseStructFusion/MainWidgetInteractor.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Applications/Samples/CtPetDoseStructFusion/MainWidgetInteractor.h Tue Mar 19 16:29:07 2019 +0100 @@ -0,0 +1,76 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2019 Osimis S.A., Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + **/ + +#pragma once + +#include "Framework/Widgets/IWorldSceneInteractor.h" + +using namespace OrthancStone; + +namespace CtPetDoseStructFusion { + + class CtPetDoseStructFusionApplication; + + class MainWidgetInteractor : public IWorldSceneInteractor + { + private: + CtPetDoseStructFusionApplication& application_; + + public: + MainWidgetInteractor(CtPetDoseStructFusionApplication& application) : + application_(application) + { + } + + /** + WorldSceneWidget: + */ + virtual IWorldSceneMouseTracker* CreateMouseTracker(WorldSceneWidget& widget, + const ViewportGeometry& view, + MouseButton button, + KeyboardModifiers modifiers, + int viewportX, + int viewportY, + double x, + double y, + IStatusBar* statusBar, + const std::vector& displayTouches); + + virtual void MouseOver(CairoContext& context, + WorldSceneWidget& widget, + const ViewportGeometry& view, + double x, + double y, + IStatusBar* statusBar); + + virtual void MouseWheel(WorldSceneWidget& widget, + MouseWheelDirection direction, + KeyboardModifiers modifiers, + IStatusBar* statusBar); + + virtual void KeyPressed(WorldSceneWidget& widget, + KeyboardKeys key, + char keyChar, + KeyboardModifiers modifiers, + IStatusBar* statusBar); + }; + + +} diff -r 9d124a81c34a -r 7428c5dfa5df Applications/Samples/CtPetDoseStructFusion/Messages.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Applications/Samples/CtPetDoseStructFusion/Messages.h Tue Mar 19 16:29:07 2019 +0100 @@ -0,0 +1,10 @@ +#pragma once + +namespace CtPetDoseStructFusion +{ + enum CtPetDoseStructFusionMessageType + { + CtPetDoseStructFusionMessageType_First = OrthancStone::MessageType_CustomMessage, + CtPetDoseStructFusionMessageType_AppStatusUpdated + }; +} diff -r 9d124a81c34a -r 7428c5dfa5df Applications/Samples/CtPetDoseStructFusion/Qt/CtPetDoseStructFusionMainWindow.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Applications/Samples/CtPetDoseStructFusion/Qt/CtPetDoseStructFusionMainWindow.cpp Tue Mar 19 16:29:07 2019 +0100 @@ -0,0 +1,110 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2019 Osimis S.A., Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + **/ + +#include "CtPetDoseStructFusionMainWindow.h" + +/** + * Don't use "ui_MainWindow.h" instead of below, as + * this makes CMake unable to detect when the UI file changes. + **/ +#include +#include "../CtPetDoseStructFusionApplication.h" + + +namespace CtPetDoseStructFusion +{ + + template + bool ExecuteCommand(U* handler, const T& command) + { + std::string serializedCommand = StoneSerialize(command); + StoneDispatchToHandler(serializedCommand, handler); + } + + CtPetDoseStructFusionMainWindow::CtPetDoseStructFusionMainWindow( + OrthancStone::NativeStoneApplicationContext& context, + CtPetDoseStructFusionApplication& stoneApplication, + QWidget *parent) : + QStoneMainWindow(context, parent), + ui_(new Ui::CtPetDoseStructFusionMainWindow), + stoneApplication_(stoneApplication) + { + ui_->setupUi(this); + SetCentralStoneWidget(*ui_->cairoCentralWidget); + +#if QT_VERSION >= 0x050000 + connect(ui_->toolButtonCrop, &QToolButton::clicked, this, &CtPetDoseStructFusionMainWindow::cropClicked); + connect(ui_->pushButtonUndoCrop, &QToolButton::clicked, this, &CtPetDoseStructFusionMainWindow::undoCropClicked); + connect(ui_->toolButtonLine, &QToolButton::clicked, this, &CtPetDoseStructFusionMainWindow::lineClicked); + connect(ui_->toolButtonCircle, &QToolButton::clicked, this, &CtPetDoseStructFusionMainWindow::circleClicked); + connect(ui_->toolButtonWindowing, &QToolButton::clicked, this, &CtPetDoseStructFusionMainWindow::windowingClicked); + connect(ui_->pushButtonRotate, &QPushButton::clicked, this, &CtPetDoseStructFusionMainWindow::rotateClicked); + connect(ui_->pushButtonInvert, &QPushButton::clicked, this, &CtPetDoseStructFusionMainWindow::invertClicked); +#else + connect(ui_->toolButtonCrop, SIGNAL(clicked()), this, SLOT(cropClicked())); + connect(ui_->toolButtonLine, SIGNAL(clicked()), this, SLOT(lineClicked())); + connect(ui_->toolButtonCircle, SIGNAL(clicked()), this, SLOT(circleClicked())); + connect(ui_->toolButtonWindowing, SIGNAL(clicked()), this, SLOT(windowingClicked())); + connect(ui_->pushButtonUndoCrop, SIGNAL(clicked()), this, SLOT(undoCropClicked())); + connect(ui_->pushButtonRotate, SIGNAL(clicked()), this, SLOT(rotateClicked())); + connect(ui_->pushButtonInvert, SIGNAL(clicked()), this, SLOT(invertClicked())); +#endif + } + + CtPetDoseStructFusionMainWindow::~CtPetDoseStructFusionMainWindow() + { + delete ui_; + } + + void CtPetDoseStructFusionMainWindow::cropClicked() + { + stoneApplication_.ExecuteCommand(SelectTool(Tool_Crop)); + } + + void CtPetDoseStructFusionMainWindow::undoCropClicked() + { + stoneApplication_.ExecuteCommand(Action(ActionType_UndoCrop)); + } + + void CtPetDoseStructFusionMainWindow::lineClicked() + { + stoneApplication_.ExecuteCommand(SelectTool(Tool_LineMeasure)); + } + + void CtPetDoseStructFusionMainWindow::circleClicked() + { + stoneApplication_.ExecuteCommand(SelectTool(Tool_CircleMeasure)); + } + + void CtPetDoseStructFusionMainWindow::windowingClicked() + { + stoneApplication_.ExecuteCommand(SelectTool(Tool_Windowing)); + } + + void CtPetDoseStructFusionMainWindow::rotateClicked() + { + stoneApplication_.ExecuteCommand(Action(ActionType_Rotate)); + } + + void CtPetDoseStructFusionMainWindow::invertClicked() + { + stoneApplication_.ExecuteCommand(Action(ActionType_Invert)); + } +} diff -r 9d124a81c34a -r 7428c5dfa5df Applications/Samples/CtPetDoseStructFusion/Qt/CtPetDoseStructFusionMainWindow.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Applications/Samples/CtPetDoseStructFusion/Qt/CtPetDoseStructFusionMainWindow.h Tue Mar 19 16:29:07 2019 +0100 @@ -0,0 +1,57 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2019 Osimis S.A., Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + **/ +#pragma once + +#include +#include + +namespace Ui +{ + class CtPetDoseStructFusionMainWindow; +} + +using namespace OrthancStone; + +namespace CtPetDoseStructFusion +{ + class CtPetDoseStructFusionApplication; + + class CtPetDoseStructFusionMainWindow : public QStoneMainWindow + { + Q_OBJECT + + private: + Ui::CtPetDoseStructFusionMainWindow* ui_; + CtPetDoseStructFusionApplication& stoneApplication_; + + public: + explicit CtPetDoseStructFusionMainWindow(OrthancStone::NativeStoneApplicationContext& context, CtPetDoseStructFusionApplication& stoneApplication, QWidget *parent = 0); + ~CtPetDoseStructFusionMainWindow(); + + private slots: + void cropClicked(); + void undoCropClicked(); + void rotateClicked(); + void windowingClicked(); + void lineClicked(); + void circleClicked(); + void invertClicked(); + }; +} diff -r 9d124a81c34a -r 7428c5dfa5df Applications/Samples/CtPetDoseStructFusion/Qt/CtPetDoseStructFusionMainWindow.ui --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Applications/Samples/CtPetDoseStructFusion/Qt/CtPetDoseStructFusionMainWindow.ui Tue Mar 19 16:29:07 2019 +0100 @@ -0,0 +1,151 @@ + + + CtPetDoseStructFusionMainWindow + + + + 0 + 0 + 903 + 634 + + + + + 500 + 300 + + + + + 500 + 300 + + + + Stone of Orthanc + + + Qt::LeftToRight + + + + + 0 + 0 + + + + Qt::LeftToRight + + + + QLayout::SetDefaultConstraint + + + + + + 0 + 500 + + + + + + + + + 0 + 100 + + + + + 16777215 + 100 + + + + + + + windowing + + + + + + + crop + + + + + + + undo crop + + + + + + + line + + + + + + + circle + + + + + + + rotate + + + + + + + invert + + + + + + + + + + + + 0 + 0 + 903 + 22 + + + + + Test + + + + + + + + + QCairoWidget + QGraphicsView +
QCairoWidget.h
+
+
+ + +
diff -r 9d124a81c34a -r 7428c5dfa5df Applications/Samples/CtPetDoseStructFusion/Qt/mainQt.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Applications/Samples/CtPetDoseStructFusion/Qt/mainQt.cpp Tue Mar 19 16:29:07 2019 +0100 @@ -0,0 +1,14 @@ +#include "Applications/Qt/QtStoneApplicationRunner.h" + +#include "../CtPetDoseStructFusionApplication.h" +#include "Framework/Messages/MessageBroker.h" + + +int main(int argc, char* argv[]) +{ + OrthancStone::MessageBroker broker; + CtPetDoseStructFusion::CtPetDoseStructFusionApplication stoneApplication(broker); + + OrthancStone::QtStoneApplicationRunner qtAppRunner(broker, stoneApplication); + return qtAppRunner.Execute(argc, argv); +} diff -r 9d124a81c34a -r 7428c5dfa5df Applications/Samples/CtPetDoseStructFusion/ThumbnailInteractor.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Applications/Samples/CtPetDoseStructFusion/ThumbnailInteractor.cpp Tue Mar 19 16:29:07 2019 +0100 @@ -0,0 +1,46 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2019 Osimis S.A., Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + **/ + +#include "ThumbnailInteractor.h" + +#include "CtPetDoseStructFusionApplication.h" + +namespace CtPetDoseStructFusion { + + IWorldSceneMouseTracker* ThumbnailInteractor::CreateMouseTracker(WorldSceneWidget& widget, + const ViewportGeometry& view, + MouseButton button, + KeyboardModifiers modifiers, + int viewportX, + int viewportY, + double x, + double y, + IStatusBar* statusBar, + const std::vector& displayTouches) + { + if (button == MouseButton_Left) + { + statusBar->SetMessage("selected thumbnail " + widget.GetName()); + std::string seriesId = widget.GetName().substr(strlen("thumbnail-series-")); + application_.SelectSeriesInMainViewport(seriesId); + } + return NULL; + } +} diff -r 9d124a81c34a -r 7428c5dfa5df Applications/Samples/CtPetDoseStructFusion/ThumbnailInteractor.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Applications/Samples/CtPetDoseStructFusion/ThumbnailInteractor.h Tue Mar 19 16:29:07 2019 +0100 @@ -0,0 +1,77 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2019 Osimis S.A., Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + **/ + + +#pragma once + +#include "Framework/Widgets/IWorldSceneInteractor.h" + +using namespace OrthancStone; + +namespace CtPetDoseStructFusion { + + class CtPetDoseStructFusionApplication; + + class ThumbnailInteractor : public IWorldSceneInteractor + { + private: + CtPetDoseStructFusionApplication& application_; + public: + ThumbnailInteractor(CtPetDoseStructFusionApplication& application) : + application_(application) + { + } + + virtual IWorldSceneMouseTracker* CreateMouseTracker(WorldSceneWidget& widget, + const ViewportGeometry& view, + MouseButton button, + KeyboardModifiers modifiers, + int viewportX, + int viewportY, + double x, + double y, + IStatusBar* statusBar, + const std::vector& displayTouches); + + virtual void MouseOver(CairoContext& context, + WorldSceneWidget& widget, + const ViewportGeometry& view, + double x, + double y, + IStatusBar* statusBar) + {} + + virtual void MouseWheel(WorldSceneWidget& widget, + MouseWheelDirection direction, + KeyboardModifiers modifiers, + IStatusBar* statusBar) + {} + + virtual void KeyPressed(WorldSceneWidget& widget, + KeyboardKeys key, + char keyChar, + KeyboardModifiers modifiers, + IStatusBar* statusBar) + {} + + }; + + +} diff -r 9d124a81c34a -r 7428c5dfa5df Applications/Samples/CtPetDoseStructFusion/Wasm/CtPetDoseStructFusionWasmApplicationAdapter.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Applications/Samples/CtPetDoseStructFusion/Wasm/CtPetDoseStructFusionWasmApplicationAdapter.cpp Tue Mar 19 16:29:07 2019 +0100 @@ -0,0 +1,51 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2019 Osimis S.A., Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + **/ + +#include "CtPetDoseStructFusionWasmApplicationAdapter.h" + +namespace CtPetDoseStructFusion +{ + + CtPetDoseStructFusionWasmApplicationAdapter::CtPetDoseStructFusionWasmApplicationAdapter(MessageBroker &broker, CtPetDoseStructFusionApplication &application) + : WasmPlatformApplicationAdapter(broker, application), + viewerApplication_(application) + { + application.RegisterObserverCallback(new Callable(*this, &CtPetDoseStructFusionWasmApplicationAdapter::OnStatusUpdated)); + } + + void CtPetDoseStructFusionWasmApplicationAdapter::OnStatusUpdated(const CtPetDoseStructFusionApplication::StatusUpdatedMessage &message) + { + Json::Value statusJson; + message.status_.ToJson(statusJson); + + Json::Value event; + event["event"] = "appStatusUpdated"; + event["data"] = statusJson; + + Json::StreamWriterBuilder builder; + std::unique_ptr writer(builder.newStreamWriter()); + std::ostringstream outputStr; + + writer->write(event, &outputStr); + + NotifyStatusUpdateFromCppToWebWithString(outputStr.str()); + } + +} // namespace CtPetDoseStructFusion \ No newline at end of file diff -r 9d124a81c34a -r 7428c5dfa5df Applications/Samples/CtPetDoseStructFusion/Wasm/CtPetDoseStructFusionWasmApplicationAdapter.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Applications/Samples/CtPetDoseStructFusion/Wasm/CtPetDoseStructFusionWasmApplicationAdapter.h Tue Mar 19 16:29:07 2019 +0100 @@ -0,0 +1,43 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2019 Osimis S.A., Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + **/ + +#pragma once + +#include +#include +#include + +#include "../CtPetDoseStructFusionApplication.h" + +namespace CtPetDoseStructFusion { + + class CtPetDoseStructFusionWasmApplicationAdapter : public WasmPlatformApplicationAdapter + { + CtPetDoseStructFusionApplication& viewerApplication_; + + public: + CtPetDoseStructFusionWasmApplicationAdapter(MessageBroker& broker, CtPetDoseStructFusionApplication& application); + + private: + void OnStatusUpdated(const CtPetDoseStructFusionApplication::StatusUpdatedMessage& message); + + }; + +} \ No newline at end of file diff -r 9d124a81c34a -r 7428c5dfa5df Applications/Samples/CtPetDoseStructFusion/Wasm/ct-pet-dose-struct-fusion.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Applications/Samples/CtPetDoseStructFusion/Wasm/ct-pet-dose-struct-fusion.html Tue Mar 19 16:29:07 2019 +0100 @@ -0,0 +1,43 @@ + + + + + + + + + + + + Simple Viewer + + + + +
+
+ +
+
+ +
+
+
+ + + + + + + + + +
+ + + + \ No newline at end of file diff -r 9d124a81c34a -r 7428c5dfa5df Applications/Samples/CtPetDoseStructFusion/Wasm/ct-pet-dose-struct-fusion.ts --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Applications/Samples/CtPetDoseStructFusion/Wasm/ct-pet-dose-struct-fusion.ts Tue Mar 19 16:29:07 2019 +0100 @@ -0,0 +1,81 @@ +import wasmApplicationRunner = require('../../../../Platforms/Wasm/wasm-application-runner'); + +wasmApplicationRunner.InitializeWasmApplication("OrthancStoneCtPetDoseStructFusion", "/orthanc"); + +function SelectTool(toolName: string) { + var command = { + command: "selectTool:" + toolName, + commandType: "generic-no-arg-command", + args: { + } + }; + wasmApplicationRunner.SendCommandToStoneApplication(JSON.stringify(command)); +} + +function PerformAction(actionName: string) { + var command = { + command: "action:" + actionName, + commandType: "generic-no-arg-command", + args: { + } + }; + wasmApplicationRunner.SendCommandToStoneApplication(JSON.stringify(command)); +} + +class CtPetDoseStructFusionUI { + + private _labelPatientId: HTMLSpanElement; + private _labelStudyDescription: HTMLSpanElement; + + public constructor() { + // install "SelectTool" handlers + document.querySelectorAll("[tool-selector]").forEach((e) => { + (e as HTMLButtonElement).addEventListener("click", () => { + SelectTool(e.attributes["tool-selector"].value); + }); + }); + + // install "PerformAction" handlers + document.querySelectorAll("[action-trigger]").forEach((e) => { + (e as HTMLButtonElement).addEventListener("click", () => { + PerformAction(e.attributes["action-trigger"].value); + }); + }); + + // connect all ui elements to members + this._labelPatientId = document.getElementById("label-patient-id") as HTMLSpanElement; + this._labelStudyDescription = document.getElementById("label-study-description") as HTMLSpanElement; + } + + public onAppStatusUpdated(status: any) { + this._labelPatientId.innerText = status["patientId"]; + this._labelStudyDescription.innerText = status["studyDescription"]; + // this.highlighThumbnail(status["currentInstanceIdInMainViewport"]); + } + +} + +var ui = new CtPetDoseStructFusionUI(); + +// this method is called "from the C++ code" when the StoneApplication is updated. +// it can be used to update the UI of the application +function UpdateWebApplicationWithString(statusUpdateMessageString: string) { + console.log("updating web application with string: ", statusUpdateMessageString); + let statusUpdateMessage = JSON.parse(statusUpdateMessageString); + + if ("event" in statusUpdateMessage) { + let eventName = statusUpdateMessage["event"]; + if (eventName == "appStatusUpdated") { + ui.onAppStatusUpdated(statusUpdateMessage["data"]); + } + } +} + +function UpdateWebApplicationWithSerializedMessage(statusUpdateMessageString: string) { + console.log("updating web application with serialized message: ", statusUpdateMessageString); + console.log(""); +} + +// make it available to other js scripts in the application +( window).UpdateWebApplicationWithString = UpdateWebApplicationWithString; +( window).UpdateWebApplicationWithSerializedMessage = UpdateWebApplicationWithSerializedMessage; diff -r 9d124a81c34a -r 7428c5dfa5df Applications/Samples/CtPetDoseStructFusion/Wasm/mainWasm.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Applications/Samples/CtPetDoseStructFusion/Wasm/mainWasm.cpp Tue Mar 19 16:29:07 2019 +0100 @@ -0,0 +1,38 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2019 Osimis S.A., Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + **/ + +#include "Platforms/Wasm/WasmWebService.h" +#include "Platforms/Wasm/WasmViewport.h" + +#include + +#include "../CtPetDoseStructFusionApplication.h" +#include "CtPetDoseStructFusionWasmApplicationAdapter.h" + + +OrthancStone::IStoneApplication* CreateUserApplication(OrthancStone::MessageBroker& broker) { + + return new CtPetDoseStructFusion::CtPetDoseStructFusionApplication(broker); +} + +OrthancStone::WasmPlatformApplicationAdapter* CreateWasmApplicationAdapter(OrthancStone::MessageBroker& broker, IStoneApplication* application) +{ + return new CtPetDoseStructFusion::CtPetDoseStructFusionWasmApplicationAdapter(broker, *(dynamic_cast(application))); +} diff -r 9d124a81c34a -r 7428c5dfa5df Applications/Samples/CtPetDoseStructFusion/Wasm/styles.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Applications/Samples/CtPetDoseStructFusion/Wasm/styles.css Tue Mar 19 16:29:07 2019 +0100 @@ -0,0 +1,54 @@ +html, body { + width: 100%; + height: 100%; + margin: 0px; + border: 0; + overflow: hidden; /* Disable scrollbars */ + display: block; /* No floating content on sides */ + background-color: black; + color: white; + font-family: Arial, Helvetica, sans-serif; +} + +canvas { + left:0px; + top:0px; +} + +#canvas-group { + padding:5px; + background-color: grey; +} + +#status-group { + padding:5px; +} + +#worklist-group { + padding:5px; +} + +.vsol-button { + height: 40px; +} + +#thumbnails-group ul li { + display: inline; + list-style: none; +} + +.thumbnail { + width: 100px; + height: 100px; + padding: 3px; +} + +.thumbnail-selected { + border-width: 1px; + border-color: red; + border-style: solid; +} + +#template-thumbnail-li { + display: none !important; +} \ No newline at end of file diff -r 9d124a81c34a -r 7428c5dfa5df Applications/Samples/CtPetDoseStructFusion/Wasm/tsconfig-ct-pet-dose-struct-fusion.json --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Applications/Samples/CtPetDoseStructFusion/Wasm/tsconfig-ct-pet-dose-struct-fusion.json Tue Mar 19 16:29:07 2019 +0100 @@ -0,0 +1,9 @@ +{ + "extends" : "../../Web/tsconfig-samples", + "compilerOptions": { + }, + "include" : [ + "ct-dose-struct-fusion.ts", + "../../build-wasm/ApplicationCommands_generated.ts" + ] +}