Browse Source

ENH: Added Copy metadata button to DICOM metadata widget (#727)

* ENH: Added Copy metadata button to DICOM metadata widget

Added "Copy metadata" button (next to "Copy path" button) in the DICOM metadata browser (ctkDICOMObjectListWidget) to copy all metadata to the clipboard.
It is useful for collecting information from users when they reporting DICOM loading errors.

Also added tooltip for the existing, very useful, but hard-to-discover feature: if user clicks on a tag then its definition is displayed at http://dicomlookup.com.

* ENH: Updated based on code review comments
Andras Lasso 8 years ago
parent
commit
253a54aef0

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

@@ -6,8 +6,8 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>312</width>
-    <height>206</height>
+    <width>486</width>
+    <height>297</height>
    </rect>
   </property>
   <property name="windowTitle">
@@ -20,18 +20,6 @@
       <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>
@@ -39,6 +27,12 @@
        </item>
        <item>
         <widget class="QLabel" name="currentPathLabel">
+         <property name="sizePolicy">
+          <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
+           <horstretch>0</horstretch>
+           <verstretch>0</verstretch>
+          </sizepolicy>
+         </property>
          <property name="text">
           <string/>
          </property>
@@ -46,18 +40,6 @@
        </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>
@@ -66,6 +48,13 @@
          </property>
         </widget>
        </item>
+       <item>
+        <widget class="QPushButton" name="copyMetadataPushButton">
+         <property name="text">
+          <string>Copy Metadata</string>
+         </property>
+        </widget>
+       </item>
       </layout>
      </item>
      <item>
@@ -79,7 +68,11 @@
       <layout class="QHBoxLayout" name="horizontalLayout_3"/>
      </item>
      <item>
-      <widget class="QTreeView" name="dcmObjectTreeView"/>
+      <widget class="QTreeView" name="dcmObjectTreeView">
+       <property name="toolTip">
+        <string>Double-click Tag to show its definition.</string>
+       </property>
+      </widget>
      </item>
     </layout>
    </item>

+ 63 - 2
Libs/DICOM/Widgets/ctkDICOMObjectListWidget.cpp

@@ -43,6 +43,7 @@ public:
   ~ctkDICOMObjectListWidgetPrivate();
   void populateDICOMObjectTreeView(const QString& fileName);
   void setPathLabel(const QString& currentFile);
+  QString dicomObjectModelAsString(QModelIndex parent = QModelIndex(), int indent = 0);
 
   QString currentFile;
   QStringList fileList;
@@ -76,6 +77,49 @@ void ctkDICOMObjectListWidgetPrivate::setPathLabel(const QString& currentFile)
   currentPathLabel->setText(currentFile);
 }
 
+// --------------------------------------------------------------------------
+QString ctkDICOMObjectListWidgetPrivate::dicomObjectModelAsString(QModelIndex parent /*=QModelIndex()*/, int indent /*=0*/)
+{
+  QString dump;
+  QString indentString(indent, '\t'); // add tab characters, (indent) number of times
+#ifdef WIN32
+  QString newLine = "\r\n";
+#else
+  QString newLine = "\n";
+#endif
+  for (int r = 0; r < this->dicomObjectModel->rowCount(parent); ++r)
+    {
+    dump += indentString;
+    for (int c = 0; c < this->dicomObjectModel->columnCount(); ++c)
+      {
+      QModelIndex index = this->dicomObjectModel->index(r, c, parent);
+      QString name = this->dicomObjectModel->data(index).toString();
+      if (c == 0)
+        {
+        // Replace round brackets by square brackets.
+        // If the text is copied into Excel, Excel would recognize tag (0008,0012)
+        // as a negative number (-80,012). Instead, [0008,0012] is displayed fine.
+        name.replace('(', '[');
+        name.replace(')', ']');
+        dump += name;
+        }
+      else
+        {
+        dump += "\t" + name;
+        }
+      
+      }
+    dump += newLine;
+    // here is your applicable code
+    QModelIndex index0 = this->dicomObjectModel->index(r, 0, parent);
+    if (this->dicomObjectModel->hasChildren(index0))
+      {
+      dump += dicomObjectModelAsString(index0, indent+1);
+      }
+    }
+  return dump;
+}
+
 //----------------------------------------------------------------------------
 // ctkDICOMObjectListWidget methods
 
@@ -95,6 +139,7 @@ ctkDICOMObjectListWidget::ctkDICOMObjectListWidget(QWidget* _parent):Superclass(
   connect(d->dcmObjectTreeView, SIGNAL(doubleClicked(const QModelIndex&))
                                ,this, SLOT(openLookupUrl(const QModelIndex&)));
   connect(d->copyPathPushButton , SIGNAL(clicked(bool)),this, SLOT(copyPath()));
+  connect(d->copyMetadataPushButton, SIGNAL(clicked(bool)), this, SLOT(copyMetadata()));
 }
 
 //----------------------------------------------------------------------------
@@ -116,11 +161,10 @@ void ctkDICOMObjectListWidget::setFileList(const QStringList& fileList)
 {
   Q_D(ctkDICOMObjectListWidget);
   d->fileList = fileList;
-  if (d-> fileList.size()> 0)
+  if (d->fileList.size() > 0)
     {
     d->currentFile = d->fileList[0];
     d->setPathLabel(d->currentFile );
-    d->currentPathLabel->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed);
     d->populateDICOMObjectTreeView(d->currentFile );
     d->fileSliderWidget->setMaximum(fileList.size()-1);
     }
@@ -167,3 +211,20 @@ void ctkDICOMObjectListWidget::copyPath()
   QClipboard *clipboard = QApplication::clipboard();
   clipboard->setText(d->currentFile);
 }
+
+// --------------------------------------------------------------------------
+
+QString ctkDICOMObjectListWidget::metadataAsText()
+{
+  Q_D(ctkDICOMObjectListWidget);
+  return d->dicomObjectModelAsString();
+}
+
+// --------------------------------------------------------------------------
+
+void ctkDICOMObjectListWidget::copyMetadata()
+{
+  Q_D(ctkDICOMObjectListWidget);
+  QClipboard *clipboard = QApplication::clipboard();
+  clipboard->setText(metadataAsText());
+}

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

@@ -44,6 +44,9 @@ public:
   QString currentFile();
   QStringList fileList();
 
+  /// Get metadata tree as plain text
+  QString metadataAsText();
+
 protected:
   QScopedPointer<ctkDICOMObjectListWidgetPrivate> d_ptr;
 
@@ -62,6 +65,7 @@ protected Q_SLOTS:
   void openLookupUrl(const QModelIndex&);
   void updateWidget();
   void copyPath();
+  void copyMetadata();
 };
 
 #endif