CustusX  20.03-rc1
An IGT application
cxImportWidget.cpp
Go to the documentation of this file.
1 /*=========================================================================
2 This file is part of CustusX, an Image Guided Therapy Application.
3 
4 Copyright (c) SINTEF Department of Medical Technology.
5 All rights reserved.
6 
7 CustusX is released under a BSD 3-Clause license.
8 
9 See Lisence.txt (https://github.com/SINTEFMedtek/CustusX/blob/master/License.txt) for details.
10 =========================================================================*/
11 
12 #include "cxImportWidget.h"
13 
14 #include <QTreeWidgetItem>
15 
16 #include <QFileDialog>
17 #include <QPushButton>
18 #include <QLabel>
19 #include <QTableWidget>
20 #include <QHeaderView>
21 #include <QApplication>
22 #include <QDesktopWidget>
23 #include <QStackedWidget>
24 #include "cxForwardDeclarations.h"
26 #include "cxVisServices.h"
27 #include "cxLogger.h"
28 #include "cxPatientModelService.h"
29 #include "cxProfile.h"
30 #include "cxImportDataTypeWidget.h"
32 #include "cxImage.h"
33 #include "cxMesh.h"
34 #include "cxPointMetric.h"
35 
36 namespace cx
37 {
38 /*
39  * TODOS:
40  * * implement coordinate system guess
41  * * implement parent guess
42  * * implement auto RAS to LPS conversion
43  */
44 
46  BaseWidget(NULL, "import_widget", "Import"),
47  mSelectedIndexInTable(0),
48  mFileManager(filemanager),
49  mVisServices(services)
50 {
51  //see https://wiki.qt.io/How_to_Use_QTableWidget
52  mTableWidget = new QTableWidget();
53  mTableWidget->setRowCount(0);
54  mTableWidget->setColumnCount(3);
55  mTableHeader<<""<<"Status"<<"Filename";
56  mTableWidget->setHorizontalHeaderLabels(mTableHeader);
57  mTableWidget->horizontalHeader()->setStretchLastSection(true);
58  mTableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
59  mTableWidget->verticalHeader()->setVisible(false);
60  mTableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
61  mTableWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
62  mTableWidget->setSelectionMode(QAbstractItemView::SingleSelection);
63  mTableWidget->setShowGrid(false);
64  mTableWidget->setStyleSheet("QTableView {selection-background-color: #ACCEF7;}");
65  mTableWidget->setGeometry(QApplication::desktop()->screenGeometry());
66  connect(mTableWidget, &QTableWidget::currentCellChanged, this, &ImportWidget::tableItemSelected);
67 
68  mStackedWidget = new QStackedWidget;
69 
70  mTopLayout = new QVBoxLayout();
71  this->setLayout(mTopLayout);
72  QPushButton *addMoreFilesButton = new QPushButton("Add more files...");
73  QHBoxLayout *buttonLayout = new QHBoxLayout();
74  QPushButton *importButton = new QPushButton("Import");
75  QPushButton *cancelButton = new QPushButton("Cancel");
76  buttonLayout->addWidget(importButton);
77  buttonLayout->addWidget(cancelButton);
78  buttonLayout->addStretch();
79  mTopLayout->addWidget(addMoreFilesButton);
80  mTopLayout->addWidget(new QLabel("Supports: "+this->generateFileTypeFilter()));
81  mTopLayout->addWidget(mTableWidget);
82  mTopLayout->addWidget(mStackedWidget);
83  mTopLayout->addStretch();
84  mTopLayout->addLayout(buttonLayout);
85 
86  connect(addMoreFilesButton, &QPushButton::clicked, this, &ImportWidget::addMoreFilesButtonClicked);
87  connect(importButton, &QPushButton::clicked, this, &ImportWidget::importButtonClicked);
88  connect(cancelButton, &QPushButton::clicked, this, &ImportWidget::cancelButtonClicked);
89  connect(this, &ImportWidget::finishedImporting, this, &ImportWidget::cleanUpAfterImport);
90 
91  QAction* addMoreFilesButtonClickedAction = new QAction("AddMoreFilesButtonClickedAction", this);
92  this->addAction(addMoreFilesButtonClickedAction);
93  connect(addMoreFilesButtonClickedAction, &QAction::triggered, this, &ImportWidget::addMoreFilesButtonClicked);
94 }
95 
96 int ImportWidget::insertDataIntoTable(QString fullfilename, std::vector<DataPtr> data)
97 {
98  int newRowIndex = mTableWidget->rowCount();
99  mTableWidget->setRowCount(newRowIndex+1);
100  mTableWidget->selectRow(mSelectedIndexInTable);
101  QString status;
102  bool allDataOk = true;
103  for(unsigned i=0; i<data.size(); ++i)
104  {
105  if(!data[i])
106  allDataOk = false;
107  }
108  status = allDataOk ? "ok" : "error";
109  QFileInfo fileInfo(fullfilename);
110  QString filename = fileInfo.fileName();
111 
112  QIcon trashcan(":/icons/open_icon_library/edit-delete-2.png");
113  QPushButton *removeButton = new QPushButton(trashcan,"");
114  connect(removeButton, &QPushButton::clicked, this, &ImportWidget::removeRowFromTableAndRemoveFilenameFromImportList);
115 
116  mTableWidget->setCellWidget(newRowIndex, 0, removeButton);
117  mTableWidget->setItem(newRowIndex, 1, new QTableWidgetItem(status));
118  QTableWidgetItem *filenameItem = new QTableWidgetItem(filename);
119  filenameItem->setData(Qt::ToolTipRole, fullfilename);
120  mTableWidget->setItem(newRowIndex, 2, filenameItem);
121 
122  return newRowIndex;
123 }
124 
125 int ImportWidget::findRowIndexContainingButton(QPushButton *button) const
126 {
127  int retval = -1;
128  for(int i=0; i<mTableWidget->rowCount(); ++i)
129  {
130  int buttonColoumn = 0;
131  QTableWidgetItem *item = mTableWidget->item(i,buttonColoumn);
132  QWidget *cellWidget = mTableWidget->cellWidget(i,buttonColoumn);
133  if(button == cellWidget)
134  retval = i;
135  }
136  return retval;
137 }
138 
139 void ImportWidget::addMoreFilesButtonClicked()
140 {
141  QStringList filenames = this->openFileBrowserForSelectingFiles();
142 
143  ImportDataTypeWidget *widget = NULL;
144  foreach (QString filename, filenames)
145  {
146  mFileNames.push_back(filename);
147 
148  std::vector<DataPtr> newData = mFileManager->read(filename);
149  int index = this->insertDataIntoTable(filename, newData);
150 
151  widget = new ImportDataTypeWidget(this, mVisServices, newData, mParentCandidates, filename);
152  mStackedWidget->insertWidget(index, widget);
153 
154  mNotImportedData.insert(mNotImportedData.end(), newData.begin(), newData.end());//Update mNotImportedData with new data
155  }
156 
157  this->generateParentCandidates();
158 }
159 
160 void ImportWidget::importButtonClicked()
161 {
162  emit readyToImport();
163  emit finishedImporting();
164 
165  mVisServices->session()->save();//AutoSave
166 }
167 
168 void ImportWidget::cancelButtonClicked()
169 {
170  emit finishedImporting();
171 }
172 
173 void ImportWidget::removeWidget(QWidget *widget)
174 {
175  mTopLayout->removeWidget(widget);
176  widget->deleteLater();
177 }
178 
179 void ImportWidget::removeRowFromTableAndRemoveFilenameFromImportList()
180 {
181  QPushButton *button = qobject_cast<QPushButton*>(QObject::sender());
182  int rowindex = this->findRowIndexContainingButton(button);
183  int filenamecoloumn = 2;
184  QString fullfilename = mTableWidget->item(rowindex, filenamecoloumn)->data(Qt::ToolTipRole).toString();
185  if(rowindex != -1)
186  mTableWidget->removeRow(rowindex);
187  int numberOfRemovedEntries = mFileNames.removeAll(fullfilename);
188 
189  QWidget *widgetToRemove = mStackedWidget->widget(rowindex);
190  mStackedWidget->removeWidget(widgetToRemove);
191 }
192 
193 void ImportWidget::tableItemSelected(int currentRow, int currentColumn, int previousRow, int previousColumn)
194 {
195  if(currentRow == mSelectedIndexInTable)
196  return;
197 
198  mStackedWidget->setCurrentIndex(currentRow);
199  mSelectedIndexInTable = currentRow;
200 }
201 
202 void ImportWidget::cleanUpAfterImport()
203 {
204  //clear data
205  //mData.clear();
206  mFileNames.clear();
207 
208  //reset table
209  mTableWidget->clear();
210  mTableWidget->setRowCount(0);
211  mTableWidget->setHorizontalHeaderLabels(mTableHeader);
212  //clear the stacked widget
213  for(int i=mStackedWidget->count()-1; i>=0; --i)
214  {
215  QWidget *widgetToRemove = mStackedWidget->widget(i);
216  mStackedWidget->removeWidget(widgetToRemove);
217  delete widgetToRemove;
218  }
219 }
220 
221 QStringList ImportWidget::openFileBrowserForSelectingFiles()
222 {
223  QString file_type_filter = generateFileTypeFilter();
224 
225  QStringList fileName = QFileDialog::getOpenFileNames(this->parentWidget(), QString(tr("Select data file(s) for import")), profile()->getSessionRootFolder(), tr(file_type_filter.toStdString().c_str()));
226  if (fileName.empty())
227  {
228  report("Import canceled");
229  }
230 
231  return fileName;
232 
233 }
234 
235 QString ImportWidget::generateFileTypeFilter() const
236 {
237  QString file_type_filter;
238  std::vector<FileReaderWriterServicePtr> mesh_readers = mVisServices->file()->getImportersForDataType(Mesh::getTypeName());
239  std::vector<FileReaderWriterServicePtr> image_readers = mVisServices->file()->getImportersForDataType(Image::getTypeName());
240  std::vector<FileReaderWriterServicePtr> point_metric_readers = mVisServices->file()->getImportersForDataType(PointMetric::getTypeName());
241  std::vector<FileReaderWriterServicePtr> readers;
242  readers.insert( readers.end(), mesh_readers.begin(), mesh_readers.end() );
243  readers.insert( readers.end(), image_readers.begin(), image_readers.end() );
244  readers.insert( readers.end(), point_metric_readers.begin(), point_metric_readers.end() );
245 
246  file_type_filter = "Image/Mesh/PointMetrics (";
247  for(unsigned i=0; i<readers.size(); ++i)
248  {
249  QString suffix = readers[i]->getFileSuffix();
250  if(!suffix.isEmpty())
251  file_type_filter.append("*."+suffix+" ");
252  }
253  while(file_type_filter.endsWith( ' ' ))
254  file_type_filter.chop(1);
255  file_type_filter.append(")");
256 
257  return file_type_filter;
258 }
259 
260 void ImportWidget::generateParentCandidates()
261 {
262  for(unsigned i=0; i<mNotImportedData.size(); ++i)
263  {
264  if(mNotImportedData[i]->getType() != PointMetric::getTypeName())
265  mParentCandidates.push_back(mNotImportedData[i]);
266  }
267  std::map<QString, DataPtr> loadedData = mVisServices->patient()->getDatas();
268  std::map<QString, DataPtr>::iterator it = loadedData.begin();
269  for(; it!=loadedData.end(); ++it)
270  {
271  mParentCandidates.push_back(it->second);
272  }
274 }
275 
276 
277 }
cxResource_EXPORT ProfilePtr profile()
Definition: cxProfile.cpp:160
boost::shared_ptr< class FileManagerService > FileManagerServicePtr
ImportWidget(FileManagerServicePtr filemanager, VisServicesPtr services)
boost::shared_ptr< class VisServices > VisServicesPtr
Definition: cxMainWindow.h:40
static QString getTypeName()
Definition: cxImage.h:126
void parentCandidatesUpdated()
Interface for QWidget which handles widgets uniformly for the system.
Definition: cxBaseWidget.h:88
void report(QString msg)
Definition: cxLogger.cpp:69
static QString getTypeName()
Definition: cxPointMetric.h:58
void finishedImporting()
static QString getTypeName()
Definition: cxMesh.h:67
Namespace for all CustusX production code.