Przeglądaj źródła

Fix ctkDICOMobjectListWidget memory leak and other enahancements

* Replaced QSlider with ctkSliderWidget

* Added copy file path to the clipboard.

* changed the order of columns in dicom table to: Tag, Attribute, value, VR, Length

* Double-click on tag table item would open the browser and search the tag in dicomlookup.com

* other stylistic changes and code refactoring.
Alireza Mehrtash 11 lat temu
rodzic
commit
f4be487de6

+ 12 - 11
Libs/DICOM/Core/ctkDICOMObjectModel.cpp

@@ -78,10 +78,10 @@ void ctkDICOMObjectModelPrivate::init()
   Q_Q(ctkDICOMObjectModel);
   QStringList horizontalHeaderLabels;
   horizontalHeaderLabels.append( QString("Tag"));
-  horizontalHeaderLabels.append( QString("Tag HEX"));
+  horizontalHeaderLabels.append( QString("Attribute"));
+  horizontalHeaderLabels.append( QString("Value"));
   horizontalHeaderLabels.append( QString("VR"));
   horizontalHeaderLabels.append( QString("Length"));
-  horizontalHeaderLabels.append( QString("Value"));
   q->setHorizontalHeaderLabels(horizontalHeaderLabels);
 }
 
@@ -234,14 +234,14 @@ QStandardItem* ctkDICOMObjectModelPrivate::populateModelRow(const QString& tagNa
   // Insert items
   QList<QStandardItem *> modelRow;
 
-  modelRow.append( tagItem);
   modelRow.append( tagHexItem);
+  modelRow.append( tagItem);
+  modelRow.append( valItem);
   modelRow.append( VRItem);
   modelRow.append( lengthItem);
-  modelRow.append( valItem);
   parent->appendRow( modelRow);
 
-  return tagItem;
+  return tagHexItem;
 }
 
 //------------------------------------------------------------------------------
@@ -254,11 +254,6 @@ ctkDICOMObjectModel::ctkDICOMObjectModel(QObject* parentObject)
 }
 
 //------------------------------------------------------------------------------
-ctkDICOMObjectModel::ctkDICOMObjectModel(const ctkDICOMObjectModel& other)
-{
-}
-
-//------------------------------------------------------------------------------
 ctkDICOMObjectModel::~ctkDICOMObjectModel()
 {
 }
@@ -275,6 +270,12 @@ void ctkDICOMObjectModel::setFile(const QString &fileName)
     }
 
   DcmDataset *dataset = d->fileFormat.getDataset();
-  d->rootItem = ctkDICOMObjectModel::invisibleRootItem();
+  d->rootItem = this->invisibleRootItem();
+
+  if(d->rootItem->hasChildren())
+    {
+    d->rootItem->removeRows(0, d->rootItem->rowCount());
+    }
+
   d->itemInsert( dataset, d->rootItem);
 }

+ 69 - 27
Libs/DICOM/Widgets/Resources/UI/ctkDICOMObjectListWidget.ui

@@ -6,50 +6,92 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>359</width>
-    <height>225</height>
+    <width>312</width>
+    <height>206</height>
    </rect>
   </property>
   <property name="windowTitle">
    <string>Form</string>
   </property>
-  <layout class="QGridLayout" name="gridLayout">
-   <item row="0" column="0">
-    <layout class="QFormLayout" name="formLayout">
-     <property name="fieldGrowthPolicy">
-      <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
-     </property>
-     <item row="1" column="0">
-      <widget class="QLabel" name="label">
-       <property name="text">
-        <string>File Path:</string>
-       </property>
-      </widget>
-     </item>
-     <item row="1" column="1">
-      <widget class="QLineEdit" name="currentPathLineEdit"/>
-     </item>
-    </layout>
-   </item>
-   <item row="1" column="0">
+  <layout class="QVBoxLayout" name="verticalLayout_2">
+   <item>
     <layout class="QVBoxLayout" name="verticalLayout">
-     <property name="bottomMargin">
-      <number>0</number>
-     </property>
      <item>
-      <widget class="QSlider" name="fileSlider">
-       <property name="orientation">
-        <enum>Qt::Horizontal</enum>
+      <layout class="QHBoxLayout" name="horizontalLayout">
+       <item>
+        <widget class="QLabel" name="label">
+         <property name="minimumSize">
+          <size>
+           <width>70</width>
+           <height>0</height>
+          </size>
+         </property>
+         <property name="maximumSize">
+          <size>
+           <width>70</width>
+           <height>16777215</height>
+          </size>
+         </property>
+         <property name="text">
+          <string>File Path:</string>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QLabel" name="currentPathLabel">
+         <property name="text">
+          <string/>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QPushButton" name="copyPathPushButton">
+         <property name="minimumSize">
+          <size>
+           <width>100</width>
+           <height>0</height>
+          </size>
+         </property>
+         <property name="maximumSize">
+          <size>
+           <width>100</width>
+           <height>16777215</height>
+          </size>
+         </property>
+         <property name="toolTip">
+          <string>Copy the file full path to the clipboard.</string>
+         </property>
+         <property name="text">
+          <string>Copy Path</string>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </item>
+     <item>
+      <widget class="ctkSliderWidget" name="fileSliderWidget">
+       <property name="decimals">
+        <number>0</number>
        </property>
       </widget>
      </item>
      <item>
+      <layout class="QHBoxLayout" name="horizontalLayout_3"/>
+     </item>
+     <item>
       <widget class="QTreeView" name="dcmObjectTreeView"/>
      </item>
     </layout>
    </item>
   </layout>
  </widget>
+ <customwidgets>
+  <customwidget>
+   <class>ctkSliderWidget</class>
+   <extends>QWidget</extends>
+   <header>ctkSliderWidget.h</header>
+  </customwidget>
+ </customwidgets>
  <resources/>
  <connections/>
 </ui>

+ 53 - 22
Libs/DICOM/Widgets/ctkDICOMObjectListWidget.cpp

@@ -22,13 +22,13 @@
 #include "ctkDICOMObjectListWidget.h"
 #include "ui_ctkDICOMObjectListWidget.h"
 
-// STD includes
-#include <iostream>
-
 // Qt includes
+#include <QApplication>
+#include <QClipboard>
+#include <QDesktopServices>
 #include <QString>
 #include <QStringList>
-#include <QTimer>
+#include <QUrl>
 
 //CTK includes
 #include <ctkDICOMObjectModel.h>
@@ -42,9 +42,11 @@ public:
   ctkDICOMObjectListWidgetPrivate();
   ~ctkDICOMObjectListWidgetPrivate();
   void populateDICOMObjectTreeView(const QString& fileName);
+  void setPathLabel(const QString& currentFile);
 
   QString currentFile;
   QStringList fileList;
+  ctkDICOMObjectModel* dicomObjectModel;
 };
 
 //----------------------------------------------------------------------------
@@ -53,26 +55,27 @@ public:
 //----------------------------------------------------------------------------
 ctkDICOMObjectListWidgetPrivate::ctkDICOMObjectListWidgetPrivate()
 {
-
 }
 
 //----------------------------------------------------------------------------
 ctkDICOMObjectListWidgetPrivate::~ctkDICOMObjectListWidgetPrivate()
 {
-
 }
 
 //----------------------------------------------------------------------------
 void ctkDICOMObjectListWidgetPrivate::populateDICOMObjectTreeView(const QString& fileName)
 {
-  //TODO: Check memory management
-  ctkDICOMObjectModel* dcmObjModel = new ctkDICOMObjectModel;
-  dcmObjModel->setFile(fileName);
-  this->dcmObjectTreeView->reset();
-  this->dcmObjectTreeView->setModel(dcmObjModel);
+  this->dicomObjectModel->setFile(fileName);
+  this->dcmObjectTreeView->setModel(this->dicomObjectModel);
   this->dcmObjectTreeView->expandAll();
 }
 
+// --------------------------------------------------------------------------
+void ctkDICOMObjectListWidgetPrivate::setPathLabel(const QString& currentFile)
+{
+  currentPathLabel->setText(currentFile);
+}
+
 //----------------------------------------------------------------------------
 // ctkDICOMObjectListWidget methods
 
@@ -83,20 +86,29 @@ ctkDICOMObjectListWidget::ctkDICOMObjectListWidget(QWidget* _parent):Superclass(
   Q_D(ctkDICOMObjectListWidget);
 
   d->setupUi(this);
-  d->currentPathLineEdit->setReadOnly(true);
-  connect(d->fileSlider, SIGNAL(valueChanged(int)), this, SLOT(updateWidget()));
+  d->dicomObjectModel = new ctkDICOMObjectModel(this);
+
+  d->fileSliderWidget->setPageStep(1);
+
+  d->currentPathLabel->setTextInteractionFlags(Qt::TextSelectableByMouse);
+  connect(d->fileSliderWidget, SIGNAL(valueChanged(double)), this, SLOT(updateWidget()));
+  connect(d->dcmObjectTreeView, SIGNAL(doubleClicked(const QModelIndex&))
+                               ,this, SLOT(openLookupUrl(const QModelIndex&)));
+  connect(d->copyPathPushButton , SIGNAL(clicked(bool)),this, SLOT(copyPath()));
 }
 
 //----------------------------------------------------------------------------
 ctkDICOMObjectListWidget::~ctkDICOMObjectListWidget()
 {
+  Q_D(ctkDICOMObjectListWidget);
+  d->dicomObjectModel->deleteLater();
 }
 
 //----------------------------------------------------------------------------
 void ctkDICOMObjectListWidget::setCurrentFile(const QString& newFileName)
 {
   Q_D(ctkDICOMObjectListWidget);
-  d->currentPathLineEdit->setText(newFileName);
+  d->setPathLabel(newFileName);
 }
 
 // --------------------------------------------------------------------------
@@ -107,32 +119,51 @@ void ctkDICOMObjectListWidget::setFileList(const QStringList& fileList)
   if (d-> fileList.size()> 0)
     {
     d->currentFile = d->fileList[0];
-    d->currentPathLineEdit->setText(d->currentFile );
+    d->setPathLabel(d->currentFile );
+    d->currentPathLabel->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed);
     d->populateDICOMObjectTreeView(d->currentFile );
-    d->fileSlider->setMaximum(d->fileList.size()-1);
+    d->fileSliderWidget->setMaximum(fileList.size()-1);
     }
 }
-
 // --------------------------------------------------------------------------
 QString ctkDICOMObjectListWidget::currentFile()
 {
-  Q_D(const ctkDICOMObjectListWidget);
+  Q_D(ctkDICOMObjectListWidget);
   return d->currentFile;
 }
 
 // --------------------------------------------------------------------------
 QStringList ctkDICOMObjectListWidget::fileList()
 {
-  Q_D(const ctkDICOMObjectListWidget);
+  Q_D(ctkDICOMObjectListWidget);
   return d->fileList;
 }
+// --------------------------------------------------------------------------
 
+void ctkDICOMObjectListWidget::openLookupUrl(const QModelIndex& index)
+{
+  if (index.column() == 0)
+  {
+    QVariant  data = index.data();
+    QString lookupUrl = "http://dicomlookup.com/lookup.asp?sw=Tnumber&q="+data.toString();
+    QUrl url(lookupUrl);
+    QDesktopServices::openUrl(url);
+  }
+}
 // --------------------------------------------------------------------------
+
 void ctkDICOMObjectListWidget::updateWidget()
 {
   Q_D(ctkDICOMObjectListWidget);
-  int fileNumber = d->fileSlider->value();
-  d->currentFile = d->fileList[fileNumber];
-  d->currentPathLineEdit->setText(d->currentFile);
+  d->currentFile = d->fileList[static_cast<int>(d->fileSliderWidget->value())];
+  d->setPathLabel(d->currentFile);
   d->populateDICOMObjectTreeView(d->currentFile);
+ }
+// --------------------------------------------------------------------------
+
+void ctkDICOMObjectListWidget::copyPath()
+{
+  Q_D(ctkDICOMObjectListWidget);
+  QClipboard *clipboard = QApplication::clipboard();
+  clipboard->setText(d->currentFile);
 }

+ 4 - 0
Libs/DICOM/Widgets/ctkDICOMObjectListWidget.h

@@ -22,6 +22,7 @@
 #define __ctkDICOMObjectListWidget_h
 
 // Qt includes 
+#include <QItemSelection>
 #include <QWidget>
 
 #include "ctkDICOMWidgetsExport.h"
@@ -51,13 +52,16 @@ private:
   Q_DISABLE_COPY(ctkDICOMObjectListWidget);
 
 Q_SIGNALS:
+  void doubleClicked(const QModelIndex&);
 
 public Q_SLOTS:
   void setCurrentFile(const QString& newFileName);
   void setFileList(const QStringList& fileList);
 
 protected Q_SLOTS:
+  void openLookupUrl(const QModelIndex&);
   void updateWidget();
+  void copyPath();
 };
 
 #endif