Kaynağa Gözat

Merge branch 'dicom-queries' of github.com:commontk/CTK into dicom-queries

nherlambang 15 yıl önce
ebeveyn
işleme
43d853d417

+ 4 - 0
Applications/ctkDICOMViewer/ctkDICOMViewerMain.cpp

@@ -23,6 +23,7 @@
 #include <QTreeView>
 #include <QSettings>
 #include <QDir>
+#include <QResource>
 
 // CTK widget includes
 #include <ctkDICOMAppWidget.h>
@@ -46,6 +47,9 @@ int main(int argc, char** argv)
   app.setOrganizationDomain("commontk.org");
   app.setApplicationName("ctkDICOM");
 
+  // set up Qt resource files
+  QResource::registerResource("./Resources/ctkDICOMViewer.qrc");
+
   QSettings settings;
   QString databaseDirectory;
 

+ 1 - 1
CMakeLists.txt

@@ -332,7 +332,7 @@ SET(CTK_APPLICATIONS
   ctkDICOMDemoSCU:OFF
   ctkDICOMQuery:OFF
   ctkDICOMRetrieve:OFF
-  ctkDICOMViewer:ON
+  ctkDICOMViewer:OFF
   ctkExampleHost:OFF
   ctkExampleHostedApp:OFF
   ctkPluginBrowser:OFF

+ 10 - 4
Libs/DICOM/Core/ctkDICOMImage.cpp

@@ -67,6 +67,8 @@ ctkDICOMImage::ctkDICOMImage(DicomImage* dicomImage, QObject* parentValue): d_pt
   Q_UNUSED(parentValue);
   Q_D(ctkDICOMImage);
   d->DicomImage = dicomImage;
+  // select first window by default
+  d->DicomImage->setWindow(0);
 }
 
 //------------------------------------------------------------------------------
@@ -83,10 +85,14 @@ unsigned long ctkDICOMImage::frameCount() const
   }
   return 0;
 }
-
-QPixmap ctkDICOMImage::getPixmap(int frame)
+DicomImage* ctkDICOMImage::getDicomImage() const
 {
-  Q_D(ctkDICOMImage);
+  Q_D(const ctkDICOMImage);
+  return d->DicomImage;
+}
+QPixmap ctkDICOMImage::getPixmap(int frame) const
+{
+  Q_D(const ctkDICOMImage);
 
   // this way of converting the dicom image to a qpixmap was adopted from some code from
   // the DCMTK forum, posted by Joerg Riesmayer, see http://forum.dcmtk.org/viewtopic.php?t=120
@@ -105,7 +111,7 @@ QPixmap ctkDICOMImage::getPixmap(int frame)
     buffer.resize(length);
 
     /* copy PGM header to buffer */
-    d->DicomImage->setWindow(0);
+
     if (d->DicomImage->getOutputData(static_cast<void *>(buffer.data() + offset), length - offset, 8, frame))
     {
       if (!pixmap.loadFromData(buffer, "PGM", Qt::AvoidDither))

+ 2 - 1
Libs/DICOM/Core/ctkDICOMImage.h

@@ -37,7 +37,8 @@ class CTK_DICOM_CORE_EXPORT ctkDICOMImage : public QObject
 public:
   explicit ctkDICOMImage(DicomImage* dicomImage, QObject* parent = 0);
   virtual ~ctkDICOMImage();
-  QPixmap getPixmap(int frame = 0);
+  DicomImage* getDicomImage() const;
+  QPixmap getPixmap(int frame = 0) const;
   unsigned long frameCount() const;
   Q_PROPERTY(unsigned long frameCount READ frameCount);
 

+ 39 - 1
Libs/DICOM/Core/ctkDICOMQuery.cpp

@@ -64,6 +64,7 @@ public:
   QString CalledAETitle;
   QString Host;
   int Port;
+  QMap<QString,QVariant> Filters;
   DcmSCU SCU;
   DcmDataset* query;
   QStringList StudyInstanceUIDList;
@@ -147,7 +148,16 @@ int ctkDICOMQuery::port()
   Q_D(ctkDICOMQuery);
   return d->Port;
 }
-
+void ctkDICOMQuery::setFilters ( QMap<QString,QVariant> filters ) 
+{
+  Q_D(ctkDICOMQuery);
+  d->Filters = filters;
+}
+QMap<QString,QVariant> ctkDICOMQuery::filters()
+{
+  Q_D(ctkDICOMQuery);
+  return d->Filters;
+}
 
 
 //------------------------------------------------------------------------------
@@ -214,6 +224,34 @@ void ctkDICOMQuery::query(ctkDICOMDatabase& database )
 
   d->query->putAndInsertString ( DCM_QueryRetrieveLevel, "STUDY" );
 
+  foreach( QString key, d->Filters.keys() )
+  {
+    if ( key == QString("Name") )
+    {
+      // make the filter a wildcard in dicom style
+      d->query->putAndInsertString( DCM_PatientsName,
+        (QString("*") + d->Filters[key].toString() + QString("*")).toAscii().data());
+    }
+    if ( key == QString("Study") )
+    {
+      // make the filter a wildcard in dicom style
+      d->query->putAndInsertString( DCM_StudyDescription,
+        (QString("*") + d->Filters[key].toString() + QString("*")).toAscii().data());
+    }
+    if ( key == QString("Series") )
+    {
+      // make the filter a wildcard in dicom style
+      d->query->putAndInsertString( DCM_SeriesDescription,
+        (QString("*") + d->Filters[key].toString() + QString("*")).toAscii().data());
+    }
+    if ( key == QString("ID") )
+    {
+      // make the filter a wildcard in dicom style
+      d->query->putAndInsertString( DCM_PatientID,
+        (QString("*") + d->Filters[key].toString() + QString("*")).toAscii().data());
+    }
+  }
+
   FINDResponses *responses = new FINDResponses();
 
   Uint16 presentationContex = 0;

+ 12 - 1
Libs/DICOM/Core/ctkDICOMQuery.h

@@ -23,6 +23,8 @@
 
 // Qt includes 
 #include <QObject>
+#include <QMap>
+#include <QString>
 #include <QSqlDatabase>
 
 // CTK includes
@@ -38,6 +40,7 @@ class CTK_DICOM_CORE_EXPORT ctkDICOMQuery : public QObject
   Q_PROPERTY(QString callingAETitle READ callingAETitle WRITE setCallingAETitle);
   Q_PROPERTY(QString calledAETitle READ calledAETitle WRITE setCallingAETitle);
   Q_PROPERTY(int port READ port WRITE setPort);
+
 public:
   explicit ctkDICOMQuery();
   virtual ~ctkDICOMQuery();
@@ -55,9 +58,17 @@ public:
   /// Query a remote DICOM Image Store SCP
   void query(ctkDICOMDatabase& database);
 
-  // Add a StudyInstanceUID to be queried
+  /// Add a StudyInstanceUID to be queried
   void addStudyInstanceUID ( QString StudyInstanceUID );
 
+  ///
+  // Filters are keyword/value pairs as generated by
+  // the ctkDICOMWidgets in a human readable (and editable)
+  // format.  The Query is responsible for converting these
+  // into the appropriate dicom syntax for the C-Find
+  void setFilters(QMap<QString,QVariant>);
+  QMap<QString,QVariant> filters();
+
 protected:
   QScopedPointer<ctkDICOMQueryPrivate> d_ptr;
 

+ 4 - 0
Libs/DICOM/Widgets/CMakeLists.txt

@@ -25,6 +25,8 @@ SET(KIT_SRCS
   ctkDICOMAppWidget.h
   ctkDICOMThumbnailWidget.cpp
   ctkDICOMThumbnailWidget.h
+  ctkDICOMThumbnailListWidget.cpp
+  ctkDICOMThumbnailListWidget.h
   )
 
 # Headers that should run through moc
@@ -34,6 +36,7 @@ SET(KIT_MOC_SRCS
   ctkDICOMServerNodeWidget.h
   ctkDICOMAppWidget.h
   ctkDICOMThumbnailWidget.h
+  ctkDICOMThumbnailListWidget.h
   )
 
 # UI files - includes new widgets
@@ -45,6 +48,7 @@ SET(KIT_UI_FORMS
   Resources/UI/ctkDICOMQueryWidget.ui
   Resources/UI/ctkDICOMAppWidget.ui
   Resources/UI/ctkDICOMThumbnailWidget.ui
+  Resources/UI/ctkDICOMThumbnailListWidget.ui
 )
 
 # Resources

+ 13 - 4
Libs/DICOM/Widgets/Resources/UI/ctkDICOMAppWidget.ui

@@ -7,7 +7,7 @@
     <x>0</x>
     <y>0</y>
     <width>739</width>
-    <height>547</height>
+    <height>638</height>
    </rect>
   </property>
   <property name="sizePolicy">
@@ -108,7 +108,7 @@
     <item>
      <layout class="QHBoxLayout" name="viewerLayout">
       <item>
-       <widget class="QWidget" name="thumbnailsWidget" native="true">
+       <widget class="ctkDICOMThumbnailListWidget" name="thumbnailsWidget" native="true">
         <property name="minimumSize">
          <size>
           <width>0</width>
@@ -121,8 +121,8 @@
        <widget class="QWidget" name="previewWidget" native="true">
         <property name="minimumSize">
          <size>
-          <width>0</width>
-          <height>200</height>
+          <width>256</width>
+          <height>256</height>
          </size>
         </property>
        </widget>
@@ -152,6 +152,9 @@
    <property name="windowTitle">
     <string>toolBar</string>
    </property>
+   <property name="floatable">
+    <bool>true</bool>
+   </property>
    <attribute name="toolBarArea">
     <enum>TopToolBarArea</enum>
    </attribute>
@@ -203,6 +206,12 @@
     <signal>directoryChanged(QString)</signal>
    </slots>
   </customwidget>
+  <customwidget>
+   <class>ctkDICOMThumbnailListWidget</class>
+   <extends>QWidget</extends>
+   <header>ctkDICOMThumbnailListWidget.h</header>
+   <container>1</container>
+  </customwidget>
  </customwidgets>
  <resources/>
  <connections>

+ 4 - 4
Libs/DICOM/Widgets/Resources/UI/ctkDICOMQueryWidget.ui

@@ -42,7 +42,7 @@
         </attribute>
         <layout class="QVBoxLayout" name="verticalLayout_7">
          <item>
-          <widget class="QLineEdit" name="NameSearch"/>
+          <widget class="QLineEdit" name="nameSearch"/>
          </item>
         </layout>
        </widget>
@@ -55,7 +55,7 @@
         </attribute>
         <layout class="QVBoxLayout" name="verticalLayout_8">
          <item>
-          <widget class="QLineEdit" name="StudySearch"/>
+          <widget class="QLineEdit" name="studySearch"/>
          </item>
         </layout>
        </widget>
@@ -68,7 +68,7 @@
         </attribute>
         <layout class="QVBoxLayout" name="verticalLayout_9">
          <item>
-          <widget class="QLineEdit" name="SeriesSearch"/>
+          <widget class="QLineEdit" name="seriesSearch"/>
          </item>
         </layout>
        </widget>
@@ -81,7 +81,7 @@
         </attribute>
         <layout class="QVBoxLayout" name="verticalLayout_10">
          <item>
-          <widget class="QLineEdit" name="IDSearch"/>
+          <widget class="QLineEdit" name="idSearch"/>
          </item>
         </layout>
        </widget>

+ 42 - 3
Libs/DICOM/Widgets/Resources/UI/ctkDICOMThumbnailWidget.ui

@@ -6,14 +6,53 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>566</width>
-    <height>294</height>
+    <width>128</width>
+    <height>158</height>
    </rect>
   </property>
   <property name="windowTitle">
    <string>Form</string>
   </property>
-  <layout class="QVBoxLayout" name="verticalLayout_2"/>
+  <property name="styleSheet">
+   <string notr="true">background-color:white</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout_2">
+   <item>
+    <widget class="QLabel" name="textLabel">
+     <property name="minimumSize">
+      <size>
+       <width>0</width>
+       <height>24</height>
+      </size>
+     </property>
+     <property name="text">
+      <string/>
+     </property>
+     <property name="scaledContents">
+      <bool>false</bool>
+     </property>
+     <property name="alignment">
+      <set>Qt::AlignCenter</set>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QLabel" name="pixmapLabel">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+       <horstretch>128</horstretch>
+       <verstretch>128</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="text">
+      <string/>
+     </property>
+     <property name="alignment">
+      <set>Qt::AlignCenter</set>
+     </property>
+    </widget>
+   </item>
+  </layout>
  </widget>
  <resources/>
  <connections/>

+ 27 - 3
Libs/DICOM/Widgets/ctkDICOMAppWidget.cpp

@@ -3,6 +3,7 @@
 #include <QTabBar>
 #include <QSettings>
 #include <QAction>
+#include <QModelIndex>
 
 // ctkDICOMWidgets includes
 #include "ctkDICOMDatabase.h"
@@ -13,6 +14,7 @@
 #include "ctkDirectoryButton.h"
 #include "ctkDICOMQueryRetrieveWidget.h"
 
+
 //logger
 #include <ctkLogger.h>
 static ctkLogger logger("org.commontk.DICOM.Widgets.ctkDICOMAppWidget");
@@ -40,10 +42,21 @@ ctkDICOMAppWidget::ctkDICOMAppWidget(QWidget* _parent):Superclass(_parent),
   Q_D(ctkDICOMAppWidget);  
 
   d->setupUi(this);
+  
+  //Set toolbar button style
+  d->toolBar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
 
   d->queryRetrieveWidget = new ctkDICOMQueryRetrieveWidget();
-
   connect(d->directoryButton, SIGNAL(directoryChanged(const QString&)), this, SLOT(onDatabaseDirectoryChanged(const QString&)));
+
+  //Set thumbnails width in thumbnail widget
+  d->thumbnailsWidget->setThumbnailWidth(128);
+  //Test add thumbnails
+  d->thumbnailsWidget->addTestThumbnail();
+
+  //connect signal and slots
+  connect(d->treeView, SIGNAL(clicked(const QModelIndex&)), this, SLOT(onDICOMModelSelected(const QModelIndex &)));
+  connect(d->thumbnailsWidget, SIGNAL(selected(const ctkDICOMThumbnailWidget&)), this, SLOT(onThumbnailSelected(const ctkDICOMThumbnailWidget&)));
 }
 
 //----------------------------------------------------------------------------
@@ -57,7 +70,7 @@ ctkDICOMAppWidget::~ctkDICOMAppWidget()
 //----------------------------------------------------------------------------
 void ctkDICOMAppWidget::onDatabaseDirectoryChanged(const QString& directory)
 {
-  Q_D(ctkDICOMAppWidget);  
+  //Q_D(ctkDICOMAppWidget);  
 
   QSettings settings;
   settings.setValue("DatabaseDirectory", directory);
@@ -68,7 +81,7 @@ void ctkDICOMAppWidget::onDatabaseDirectoryChanged(const QString& directory)
 
 void ctkDICOMAppWidget::onAddToDatabase()
 {
-  Q_D(ctkDICOMAppWidget);
+  //Q_D(ctkDICOMAppWidget);
 
   //d->
 }
@@ -88,3 +101,14 @@ void ctkDICOMAppWidget::onQuery(){
   d->queryRetrieveWidget->show();
   d->queryRetrieveWidget->raise();
 }
+
+void ctkDICOMAppWidget::onDICOMModelSelected(const QModelIndex& index){
+  Q_D(ctkDICOMAppWidget);
+
+  //TODO: update thumbnails and previewer
+  d->thumbnailsWidget->setModelIndex(index);
+}
+
+void ctkDICOMAppWidget::onThumbnailSelected(const ctkDICOMThumbnailWidget& widget){
+  //TODO: update previewer
+}

+ 5 - 0
Libs/DICOM/Widgets/ctkDICOMAppWidget.h

@@ -26,7 +26,9 @@
 
 #include "ctkDICOMWidgetsExport.h"
 
+class QModelIndex;
 class ctkDICOMAppWidgetPrivate;
+class ctkDICOMThumbnailWidget;
 
 class CTK_DICOM_WIDGETS_EXPORT ctkDICOMAppWidget : public QMainWindow
 {
@@ -40,6 +42,9 @@ public slots:
     void onDatabaseDirectoryChanged(const QString& directory);
     void onAddToDatabase();
 
+    void onDICOMModelSelected(const QModelIndex& index);
+    void onThumbnailSelected(const ctkDICOMThumbnailWidget& widget);
+
     void onImport();
     void onExport();
     void onQuery();

+ 5 - 5
Libs/DICOM/Widgets/ctkDICOMQueryRetrieveWidget.cpp

@@ -88,13 +88,13 @@ void ctkDICOMQueryRetrieveWidget::processQuery()
   QStringList serverNodes = d->serverNodeWidget->nodes();
   foreach (QString server, serverNodes)
   {
-    QMap<QString, QString> parameters = d->serverNodeWidget->nodeParameters(server);
-    if ( parameters["CheckState"] == QVariant(Qt::Checked).toString() )
+    QMap<QString, QVariant> parameters = d->serverNodeWidget->nodeParameters(server);
+    if ( parameters["CheckState"] == Qt::Checked )
     {
       d->queries[server] = new ctkDICOMQuery;
       d->queries[server]->setCallingAETitle(d->serverNodeWidget->callingAETitle());
-      d->queries[server]->setCalledAETitle(parameters["AETitle"]);
-      d->queries[server]->setHost(parameters["Address"]);
+      d->queries[server]->setCalledAETitle(parameters["AETitle"].toString());
+      d->queries[server]->setHost(parameters["Address"].toString());
       d->queries[server]->setPort(parameters["Port"].toInt());
       // TODO: add interface to ctkDICOMQuery for specifying query params
       // for now, query for everything
@@ -106,7 +106,7 @@ void ctkDICOMQueryRetrieveWidget::processQuery()
       }
       catch (std::exception e)
       {
-        logger.error ( "Query error: " + parameters["Name"] );
+        logger.error ( "Query error: " + parameters["Name"].toString() );
       }
     }
   }

+ 9 - 12
Libs/DICOM/Widgets/ctkDICOMQueryWidget.cpp

@@ -37,19 +37,16 @@ ctkDICOMQueryWidget::~ctkDICOMQueryWidget()
 
 
 //----------------------------------------------------------------------------
-void ctkDICOMQueryWidget::populateQuery(/*ctkDICOMQuery &query*/)
+QMap<QString,QVariant> ctkDICOMQueryWidget::parameters()
 {
   Q_D(ctkDICOMQueryWidget);
-  if ( d->CT->isChecked() )
-  {
-    std::cerr << "CT\n";
-    //query.addModality( "CT" );
-  }
-
-  if ( d->MR->isChecked() )
-  {
-    std::cerr << "MR\n";
-    //query.addModality( "CT" );
-  }
 
+  QMap<QString,QVariant> parameters;
+
+  parameters["Name"] = d->nameSearch->text();
+  parameters["Study"] = d->studySearch->text();
+  parameters["Series"] = d->seriesSearch->text();
+  parameters["ID"] = d->idSearch->text();
+
+  return parameters;
 }

+ 2 - 2
Libs/DICOM/Widgets/ctkDICOMQueryWidget.h

@@ -35,8 +35,8 @@ public:
   explicit ctkDICOMQueryWidget(QWidget* parent=0);
   virtual ~ctkDICOMQueryWidget();
   
-  /// set properties of query based on current widget state
-  void populateQuery (/*ctkDICOMQuery &query*/);
+  /// return map of field names and values
+  QMap<QString,QVariant> parameters();
 
 protected:
   QScopedPointer<ctkDICOMQueryWidgetPrivate> d_ptr;

+ 3 - 3
Libs/DICOM/Widgets/ctkDICOMServerNodeWidget.cpp

@@ -213,11 +213,11 @@ QStringList ctkDICOMServerNodeWidget::nodes()
 }
 
 //----------------------------------------------------------------------------
-QMap<QString, QString> ctkDICOMServerNodeWidget::nodeParameters(QString &node)
+QMap<QString, QVariant> ctkDICOMServerNodeWidget::nodeParameters(QString &node)
 {
   Q_D(ctkDICOMServerNodeWidget);
 
-  QMap<QString, QString> parameters;
+  QMap<QString, QVariant> parameters;
   int count = d->nodeTable->rowCount();
   QStringList keys;
   keys << "Name" << "AETitle" << "Address" << "Port";
@@ -231,7 +231,7 @@ QMap<QString, QString> ctkDICOMServerNodeWidget::nodeParameters(QString &node)
         {
           parameters[keys.at(k)] = d->nodeTable->item(row,k)->text();
         }
-        parameters["CheckState"] = QVariant(d->nodeTable->item(row,0)->checkState()).toString();
+        parameters["CheckState"] = d->nodeTable->item(row,0)->checkState();
       }
     }
   }

+ 1 - 1
Libs/DICOM/Widgets/ctkDICOMServerNodeWidget.h

@@ -42,7 +42,7 @@ public:
 
   QString callingAETitle();
   QStringList nodes();
-  QMap<QString,QString> nodeParameters(QString &node);
+  QMap<QString,QVariant> nodeParameters(QString &node);
 
 public slots:
   void addNode ();

+ 48 - 36
Libs/DICOM/Widgets/ctkDICOMThumbnailListWidget.cpp

@@ -15,13 +15,20 @@
 class ctkDICOMThumbnailListWidgetPrivate: public Ui_ctkDICOMThumbnailListWidget
 {
 public:
-  ctkDICOMThumbnailListWidgetPrivate(){}
+  ctkDICOMThumbnailListWidgetPrivate(ctkDICOMThumbnailListWidget* parent): q_ptr(parent){
+    
+  }
 
+  void clearAllThumbnails();
+  void addThumbnail(ctkDICOMThumbnailWidget* widget);
   void rearrangeThumbnails();
 
   QList<ctkDICOMThumbnailWidget*> thumbnailList;
   int maxColumnNum;
   int thumbnailWidth;
+
+  ctkDICOMThumbnailListWidget* const q_ptr;
+  Q_DECLARE_PUBLIC(ctkDICOMThumbnailListWidget);
 };
 
 //----------------------------------------------------------------------------
@@ -39,7 +46,8 @@ void ctkDICOMThumbnailListWidgetPrivate::rearrangeThumbnails(){
   int row = 0;
   int column = 0;
   for(int i = 0; i < count; i++){
-    this->thumbnailLayout->addWidget(this->thumbnailList.at(i), row, column);
+    ctkDICOMThumbnailWidget* widget = this->thumbnailList.at(i);
+    this->thumbnailLayout->addWidget(widget, row, column);
     column++;
     if(column >= this->maxColumnNum){
       column = 0;
@@ -48,12 +56,35 @@ void ctkDICOMThumbnailListWidgetPrivate::rearrangeThumbnails(){
   }
 }
 
+void ctkDICOMThumbnailListWidgetPrivate::addThumbnail(ctkDICOMThumbnailWidget* widget){
+  Q_Q(ctkDICOMThumbnailListWidget);
+
+  if(widget == NULL)return;
+
+  this->thumbnailList.push_back(widget);
+
+  q->connect(widget, SIGNAL(selected(const ctkDICOMThumbnailWidget&)), q,  SIGNAL(selected(const ctkDICOMThumbnailWidget&)));
+}
+
+void ctkDICOMThumbnailListWidgetPrivate::clearAllThumbnails(){
+  int count = this->thumbnailList.count();
+
+  // clear all thumbnails from layout
+  for(int i = 0; i < count; i++){
+    QWidget* widget = this->thumbnailList.at(i);
+    this->thumbnailLayout->removeWidget(widget);
+    widget->deleteLater();
+  }
+
+  this->thumbnailList.clear();
+}
+
 //----------------------------------------------------------------------------
 // ctkDICOMThumbnailListWidget methods
 
 //----------------------------------------------------------------------------
 ctkDICOMThumbnailListWidget::ctkDICOMThumbnailListWidget(QWidget* _parent):Superclass(_parent), 
-  d_ptr(new ctkDICOMThumbnailListWidgetPrivate)
+									   d_ptr(new ctkDICOMThumbnailListWidgetPrivate(this))
 {
   Q_D(ctkDICOMThumbnailListWidget);
   
@@ -67,45 +98,19 @@ ctkDICOMThumbnailListWidget::~ctkDICOMThumbnailListWidget()
 {
 }
 
-void ctkDICOMThumbnailListWidget::clearThumbnail(){
+void ctkDICOMThumbnailListWidget::addTestThumbnail(int count){
   Q_D(ctkDICOMThumbnailListWidget);
-  
-  int count = d->thumbnailList.count();
-
-  // clear all thumbnails from layout
-  for(int i = 0; i < count; i++){
-    d->thumbnailLayout->removeWidget(d->thumbnailList.at(i));
-  }
-
-  d->thumbnailList.clear();
-}
-
-void ctkDICOMThumbnailListWidget::addThumbnail(ctkDICOMThumbnailWidget* widget){
-  Q_D(ctkDICOMThumbnailListWidget);
-  if(widget == NULL)return;
-
-  d->thumbnailList.push_back(widget);
-
-  int count = d->thumbnailList.count();
-
-  int lastRow = (count/d->maxColumnNum);
-  int lastColumn = (count%d->maxColumnNum);
-
-  int nextRow = (lastRow+((lastColumn+1)/d->maxColumnNum));
-  int nextColumn = (lastColumn+1)%d->maxColumnNum;
-
-  d->thumbnailLayout->addWidget(widget, nextRow, nextColumn);
-}
-
-void ctkDICOMThumbnailListWidget::addTestThumbnail(){
-  Q_D(ctkDICOMThumbnailListWidget);
-  for(int i = 0; i<11; i++){
+  for(int i = 0; i<count; i++){
     ctkDICOMThumbnailWidget* widget = new ctkDICOMThumbnailWidget(this);
+    QPixmap pixmap(64, 64);
+    pixmap.fill(Qt::blue);
     QString text("Thumbnail: ");
     widget->setMaximumWidth(d->thumbnailWidth);
     widget->setText(text);
-    this->addThumbnail(widget);
+    widget->setPixmap(pixmap);
+    d->addThumbnail(widget);
   }
+  d->rearrangeThumbnails();
 }
 
 void ctkDICOMThumbnailListWidget::setThumbnailWidth(int width){
@@ -124,3 +129,10 @@ void ctkDICOMThumbnailListWidget::resizeEvent ( QResizeEvent * event ){
   d->rearrangeThumbnails();
 }
 
+void ctkDICOMThumbnailListWidget::setModelIndex(const QModelIndex &index){
+  Q_D(ctkDICOMThumbnailListWidget);
+
+  d->clearAllThumbnails();
+  this->addTestThumbnail(index.model()->rowCount(index));
+  
+}

+ 8 - 7
Libs/DICOM/Widgets/ctkDICOMThumbnailListWidget.h

@@ -26,12 +26,13 @@
 
 #include "ctkDICOMWidgetsExport.h"
 
+class QModelIndex;
 class ctkDICOMThumbnailListWidgetPrivate;
-
 class ctkDICOMThumbnailWidget;
 
 class CTK_DICOM_WIDGETS_EXPORT ctkDICOMThumbnailListWidget : public QWidget
 {
+  Q_OBJECT
 public:
   typedef QWidget Superclass;
   explicit ctkDICOMThumbnailListWidget(QWidget* parent=0);
@@ -39,19 +40,19 @@ public:
 
   void setThumbnailWidth(int width);
 
-  void addTestThumbnail();
+  void addTestThumbnail(int count = 10);
+  void setModelIndex(const QModelIndex& index);
   
 protected:
   QScopedPointer<ctkDICOMThumbnailListWidgetPrivate> d_ptr;
 
-  void clearThumbnail();
-  void addThumbnail(ctkDICOMThumbnailWidget* widget);
-
-  virtual void resizeEvent(QResizeEvent * event);
-  
+  virtual void resizeEvent(QResizeEvent * event); 
 private:
   Q_DECLARE_PRIVATE(ctkDICOMThumbnailListWidget);
   Q_DISABLE_COPY(ctkDICOMThumbnailListWidget);
+
+signals:
+  void selected(const ctkDICOMThumbnailWidget& widget);
 };
 
 #endif

+ 15 - 0
Libs/DICOM/Widgets/ctkDICOMThumbnailWidget.cpp

@@ -35,3 +35,18 @@ ctkDICOMThumbnailWidget::~ctkDICOMThumbnailWidget()
 {
 }
 
+void ctkDICOMThumbnailWidget::setText(QString &text){
+  Q_D(ctkDICOMThumbnailWidget);
+
+  d->textLabel->setText(text);
+}
+
+void ctkDICOMThumbnailWidget::setPixmap(QPixmap &pixmap){
+  Q_D(ctkDICOMThumbnailWidget);
+
+  d->pixmapLabel->setPixmap(pixmap);
+}
+
+void ctkDICOMThumbnailWidget::mousePressEvent(QMouseEvent* event){
+  emit selected(*this);
+}

+ 9 - 0
Libs/DICOM/Widgets/ctkDICOMThumbnailWidget.h

@@ -30,17 +30,26 @@ class ctkDICOMThumbnailWidgetPrivate;
 
 class CTK_DICOM_WIDGETS_EXPORT ctkDICOMThumbnailWidget : public QWidget
 {
+  Q_OBJECT
 public:
   typedef QWidget Superclass;
   explicit ctkDICOMThumbnailWidget(QWidget* parent=0);
   virtual ~ctkDICOMThumbnailWidget();
+
+  void setText(QString& text);
+  void setPixmap(QPixmap& pixmap);
   
 protected:
   QScopedPointer<ctkDICOMThumbnailWidgetPrivate> d_ptr;
 
+  virtual void mousePressEvent(QMouseEvent* event);
+  
 private:
   Q_DECLARE_PRIVATE(ctkDICOMThumbnailWidget);
   Q_DISABLE_COPY(ctkDICOMThumbnailWidget);
+
+signals:
+  void selected(const ctkDICOMThumbnailWidget& widget);
 };
 
 #endif