comparison Applications/Samples/SimpleViewer/SimpleViewerApplication.cpp @ 319:daa04d15192c am-2

new SimpleViewer sample that has been split in multiple files to be able to scale it
author am@osimis.io
date Thu, 11 Oct 2018 13:16:54 +0200
parents
children 56b2e47d3c0c
comparison
equal deleted inserted replaced
318:3a4ca166fafa 319:daa04d15192c
1 /**
2 * Stone of Orthanc
3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
4 * Department, University Hospital of Liege, Belgium
5 * Copyright (C) 2017-2018 Osimis S.A., Belgium
6 *
7 * This program is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU Affero General Public License
9 * as published by the Free Software Foundation, either version 3 of
10 * the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Affero General Public License for more details.
16 *
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 **/
20
21
22 #include "SimpleViewerApplication.h"
23
24 #if ORTHANC_ENABLE_QT==1
25 #include "Qt/SimpleViewerMainWindow.h"
26 #endif
27
28 #if ORTHANC_ENABLE_WASM==1
29 #include <Platforms/Wasm/WasmViewport.h>
30 #endif
31
32 namespace SimpleViewer {
33
34 void SimpleViewerApplication::Initialize(StoneApplicationContext* context,
35 IStatusBar& statusBar,
36 const boost::program_options::variables_map& parameters)
37 {
38 using namespace OrthancStone;
39
40 context_ = context;
41 statusBar_ = &statusBar;
42
43 {// initialize viewports and layout
44 mainLayout_ = new LayoutWidget("main-layout");
45 mainLayout_->SetPadding(10);
46 mainLayout_->SetBackgroundCleared(true);
47 mainLayout_->SetBackgroundColor(0, 0, 0);
48 mainLayout_->SetHorizontal();
49
50 thumbnailsLayout_ = new LayoutWidget("thumbnail-layout");
51 thumbnailsLayout_->SetPadding(10);
52 thumbnailsLayout_->SetBackgroundCleared(true);
53 thumbnailsLayout_->SetBackgroundColor(50, 50, 50);
54 thumbnailsLayout_->SetVertical();
55
56 mainWidget_ = new LayerWidget(IObserver::broker_, "main-viewport");
57 //mainWidget_->RegisterObserver(*this);
58
59 // hierarchy
60 mainLayout_->AddWidget(thumbnailsLayout_);
61 mainLayout_->AddWidget(mainWidget_);
62
63 orthancApiClient_.reset(new OrthancApiClient(IObserver::broker_, context_->GetWebService()));
64
65 // sources
66 smartLoader_.reset(new SmartLoader(IObserver::broker_, *orthancApiClient_));
67 smartLoader_->SetImageQuality(SliceImageQuality_FullPam);
68
69 mainLayout_->SetTransmitMouseOver(true);
70 mainWidgetInteractor_.reset(new MainWidgetInteractor(*this));
71 mainWidget_->SetInteractor(*mainWidgetInteractor_);
72 thumbnailInteractor_.reset(new ThumbnailInteractor(*this));
73 }
74
75 statusBar.SetMessage("Use the key \"s\" to reinitialize the layout");
76 statusBar.SetMessage("Use the key \"n\" to go to next image in the main viewport");
77
78
79 if (parameters.count("studyId") < 1)
80 {
81 LOG(WARNING) << "The study ID is missing, will take the first studyId found in Orthanc";
82 orthancApiClient_->GetJsonAsync("/studies", new Callable<SimpleViewerApplication, OrthancApiClient::JsonResponseReadyMessage>(*this, &SimpleViewerApplication::OnStudyListReceived));
83 }
84 else
85 {
86 SelectStudy(parameters["studyId"].as<std::string>());
87 }
88 }
89
90
91 void SimpleViewerApplication::DeclareStartupOptions(boost::program_options::options_description& options)
92 {
93 boost::program_options::options_description generic("Sample options");
94 generic.add_options()
95 ("studyId", boost::program_options::value<std::string>(),
96 "Orthanc ID of the study")
97 ;
98
99 options.add(generic);
100 }
101
102 void SimpleViewerApplication::OnStudyListReceived(const OrthancApiClient::JsonResponseReadyMessage& message)
103 {
104 const Json::Value& response = message.Response;
105
106 if (response.isArray() && response.size() > 1)
107 {
108 SelectStudy(response[0].asString());
109 }
110 }
111 void SimpleViewerApplication::OnStudyReceived(const OrthancApiClient::JsonResponseReadyMessage& message)
112 {
113 const Json::Value& response = message.Response;
114
115 if (response.isObject() && response["Series"].isArray())
116 {
117 for (size_t i=0; i < response["Series"].size(); i++)
118 {
119 orthancApiClient_->GetJsonAsync("/series/" + response["Series"][(int)i].asString(), new Callable<SimpleViewerApplication, OrthancApiClient::JsonResponseReadyMessage>(*this, &SimpleViewerApplication::OnSeriesReceived));
120 }
121 }
122 }
123
124 void SimpleViewerApplication::OnSeriesReceived(const OrthancApiClient::JsonResponseReadyMessage& message)
125 {
126 const Json::Value& response = message.Response;
127
128 if (response.isObject() && response["Instances"].isArray() && response["Instances"].size() > 0)
129 {
130 // keep track of all instances IDs
131 const std::string& seriesId = response["ID"].asString();
132 seriesTags_[seriesId] = response;
133 instancesIdsPerSeriesId_[seriesId] = std::vector<std::string>();
134 for (size_t i = 0; i < response["Instances"].size(); i++)
135 {
136 const std::string& instanceId = response["Instances"][static_cast<int>(i)].asString();
137 instancesIdsPerSeriesId_[seriesId].push_back(instanceId);
138 }
139
140 // load the first instance in the thumbnail
141 LoadThumbnailForSeries(seriesId, instancesIdsPerSeriesId_[seriesId][0]);
142
143 // if this is the first thumbnail loaded, load the first instance in the mainWidget
144 if (mainWidget_->GetLayerCount() == 0)
145 {
146 smartLoader_->SetFrameInWidget(*mainWidget_, 0, instancesIdsPerSeriesId_[seriesId][0], 0);
147 }
148 }
149 }
150
151 void SimpleViewerApplication::LoadThumbnailForSeries(const std::string& seriesId, const std::string& instanceId)
152 {
153 LOG(INFO) << "Loading thumbnail for series " << seriesId;
154 LayerWidget* thumbnailWidget = new LayerWidget(IObserver::broker_, "thumbnail-series-" + seriesId);
155 thumbnails_.push_back(thumbnailWidget);
156 thumbnailsLayout_->AddWidget(thumbnailWidget);
157 thumbnailWidget->RegisterObserverCallback(new Callable<SimpleViewerApplication, LayerWidget::GeometryChangedMessage>(*this, &SimpleViewerApplication::OnWidgetGeometryChanged));
158 smartLoader_->SetFrameInWidget(*thumbnailWidget, 0, instanceId, 0);
159 thumbnailWidget->SetInteractor(*thumbnailInteractor_);
160 }
161
162 void SimpleViewerApplication::SelectStudy(const std::string& studyId)
163 {
164 orthancApiClient_->GetJsonAsync("/studies/" + studyId, new Callable<SimpleViewerApplication, OrthancApiClient::JsonResponseReadyMessage>(*this, &SimpleViewerApplication::OnStudyReceived));
165 }
166
167 void SimpleViewerApplication::OnWidgetGeometryChanged(const LayerWidget::GeometryChangedMessage& message)
168 {
169 message.origin_.SetDefaultView();
170 }
171
172 void SimpleViewerApplication::SelectSeriesInMainViewport(const std::string& seriesId)
173 {
174 smartLoader_->SetFrameInWidget(*mainWidget_, 0, instancesIdsPerSeriesId_[seriesId][0], 0);
175 }
176
177
178
179 void SimpleViewerApplication::ExecuteCommand(ICommand& command)
180 {
181 statusBar_->SetMessage("received command: " + std::string(command.GetName()));
182 if (command.GetName() == "selectTool:circle-measure")
183 {
184 SelectTool(Tools_CircleMeasure);
185 }
186 else if (command.GetName() == "selectTool:line-measure")
187 {
188 SelectTool(Tools_LineMeasure);
189 }
190 else if (command.GetName() == "selectTool:crop")
191 {
192 SelectTool(Tools_Crop);
193 }
194 else if (command.GetName() == "selectTool:windowing")
195 {
196 SelectTool(Tools_Windowing);
197 }
198 else if (command.GetName() == "action:rotate")
199 {
200 ExecuteAction(Actions_Rotate);
201 }
202 else if (command.GetName() == "action:invert")
203 {
204 ExecuteAction(Actions_Invert);
205 }
206 else
207 {
208 command.Execute();
209 }
210 }
211
212 void SimpleViewerApplication::ExecuteAction(SimpleViewerApplication::Actions action)
213 {
214 // TODO
215 }
216
217 void SimpleViewerApplication::SelectTool(SimpleViewerApplication::Tools tool)
218 {
219 currentTool_ = tool;
220 }
221
222 #if ORTHANC_ENABLE_QT==1
223 QStoneMainWindow* SimpleViewerApplication::CreateQtMainWindow()
224 {
225 return new SimpleViewerMainWindow(dynamic_cast<OrthancStone::NativeStoneApplicationContext&>(*context_), *this);
226 }
227 #endif
228
229 #if ORTHANC_ENABLE_WASM==1
230 void SimpleViewerApplication::InitializeWasm() {
231
232 AttachWidgetToWasmViewport("canvasThumbnails", thumbnailsLayout_);
233 AttachWidgetToWasmViewport("canvasMain", mainWidget_);
234 }
235 #endif
236
237
238 }