diff --git a/Libs/DICOM/Widgets/Resources/UI/ctkDICOMObjectListWidget.ui b/Libs/DICOM/Widgets/Resources/UI/ctkDICOMObjectListWidget.ui
index 29020c49a1..07f4235181 100644
--- a/Libs/DICOM/Widgets/Resources/UI/ctkDICOMObjectListWidget.ui
+++ b/Libs/DICOM/Widgets/Resources/UI/ctkDICOMObjectListWidget.ui
@@ -7,7 +7,7 @@
0
0
442
- 311
+ 514
@@ -51,8 +51,8 @@
-
-
-
+
+
0
@@ -106,20 +106,46 @@
-
-
-
- -
-
-
- Double-click to show DICOM tag definition.
+
+
+ 0
-
+
-
+
+
+ Double-click to show DICOM tag definition.
+
+
+
+ -
+
+
+ Thumbnail
+
+
+
+ -
+
+
+ Show image thumbnail
+
+
+ true
+
+
+
+
+
+ ctkExpandButton
+ QToolButton
+
+
ctkSearchBox
QLineEdit
diff --git a/Libs/DICOM/Widgets/ctkDICOMBrowser.cpp b/Libs/DICOM/Widgets/ctkDICOMBrowser.cpp
index 8d958eef09..65b7c1e951 100644
--- a/Libs/DICOM/Widgets/ctkDICOMBrowser.cpp
+++ b/Libs/DICOM/Widgets/ctkDICOMBrowser.cpp
@@ -26,6 +26,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -105,6 +106,10 @@ class ctkDICOMMetadataDialog : public QDialog
if (!savedGeometry.isEmpty())
{
this->restoreGeometry(savedGeometry);
+ if (this->isMaximized())
+ {
+ this->setGeometry(QApplication::desktop()->availableGeometry(this));
+ }
}
}
diff --git a/Libs/DICOM/Widgets/ctkDICOMObjectListWidget.cpp b/Libs/DICOM/Widgets/ctkDICOMObjectListWidget.cpp
index 99304ea20c..1648031e4a 100644
--- a/Libs/DICOM/Widgets/ctkDICOMObjectListWidget.cpp
+++ b/Libs/DICOM/Widgets/ctkDICOMObjectListWidget.cpp
@@ -20,12 +20,14 @@
// ctkDICOMWidgets includes
#include "ctkDICOMObjectListWidget.h"
+#include "ctkDICOMThumbnailGenerator.h"
#include "ui_ctkDICOMObjectListWidget.h"
// Qt includes
#include
#include
#include
+#include
#include
#include
#include
@@ -101,6 +103,7 @@ class ctkDICOMObjectListWidgetPrivate: public Ui_ctkDICOMObjectListWidget
ctkDICOMObjectModel* dicomObjectModel;
qRecursiveTreeProxyFilter* filterModel;
QString filterExpression;
+ bool thumbnailVisible{true};
};
//----------------------------------------------------------------------------
@@ -212,6 +215,9 @@ ctkDICOMObjectListWidget::ctkDICOMObjectListWidget(QWidget* _parent):Superclass(
d->fileSliderWidget->setMinimum(1);
d->fileSliderWidget->setPageStep(1);
+ d->showThumbnailButton->setChecked(d->thumbnailVisible);
+ d->thumbnailLabel->setVisible(d->thumbnailVisible);
+
d->currentPathLabel->setTextInteractionFlags(Qt::TextSelectableByMouse);
connect(d->fileSliderWidget, SIGNAL(valueChanged(double)), this, SLOT(updateWidget()));
connect(d->dcmObjectTreeView, SIGNAL(doubleClicked(const QModelIndex&)),
@@ -225,6 +231,8 @@ ctkDICOMObjectListWidget::ctkDICOMObjectListWidget(QWidget* _parent):Superclass(
QObject::connect(d->metadataSearchBox, SIGNAL(textChanged(QString)), this, SLOT(setFilterExpression(QString)));
QObject::connect(d->metadataSearchBox, SIGNAL(textChanged(QString)), this, SLOT(onFilterChanged()));
+
+ QObject::connect(d->showThumbnailButton, SIGNAL(toggled(bool)), this, SLOT(setThumbnailVisible(bool)));
}
//----------------------------------------------------------------------------
@@ -250,10 +258,9 @@ void ctkDICOMObjectListWidget::setFileList(const QStringList& fileList)
if (d->fileList.size() > 0)
{
d->currentFile = d->fileList[0];
-
- d->populateDICOMObjectTreeView(d->currentFile);
d->fileSliderWidget->setMaximum(fileList.size());
d->fileSliderWidget->setSuffix(QString(" / %1").arg(fileList.size()));
+ this->updateWidget();
for (int columnIndex = 0; columnIndex < d->dicomObjectModel->columnCount(); ++columnIndex)
{
d->dcmObjectTreeView->resizeColumnToContents(columnIndex);
@@ -307,7 +314,19 @@ void ctkDICOMObjectListWidget::updateWidget()
d->currentFile = d->fileList[static_cast(d->fileSliderWidget->value())-1];
d->setPathLabel(d->currentFile);
d->populateDICOMObjectTreeView(d->currentFile);
- }
+
+ if (this->isThumbnailVisible())
+ {
+ // only update the thumbnail if visible for better update performance
+ ctkDICOMThumbnailGenerator thumbnailGenerator;
+ QImage thumbnailImage;
+ if (!thumbnailGenerator.generateThumbnail(d->currentFile, thumbnailImage))
+ {
+ thumbnailGenerator.generateBlankThumbnail(thumbnailImage);
+ }
+ d->thumbnailLabel->setPixmap(QPixmap::fromImage(thumbnailImage));
+ }
+}
// --------------------------------------------------------------------------
void ctkDICOMObjectListWidget::copyPath()
@@ -406,3 +425,32 @@ QString ctkDICOMObjectListWidget::filterExpression()
Q_D(ctkDICOMObjectListWidget);
return d->filterExpression;
}
+
+//------------------------------------------------------------------------------
+void ctkDICOMObjectListWidget::setThumbnailVisible(bool visible)
+{
+ Q_D(ctkDICOMObjectListWidget);
+ if (visible == d->thumbnailVisible)
+ {
+ // no change
+ return;
+ }
+ d->thumbnailVisible = visible;
+
+ QSignalBlocker blocker(d->showThumbnailButton);
+ d->showThumbnailButton->setChecked(visible);
+
+ d->thumbnailLabel->setVisible(visible);
+ if (visible)
+ {
+ // Previously the thumbnail was not visible, so it was not updated. Update it now.
+ this->updateWidget();
+ }
+}
+
+//------------------------------------------------------------------------------
+bool ctkDICOMObjectListWidget::isThumbnailVisible()const
+{
+ Q_D(const ctkDICOMObjectListWidget);
+ return d->thumbnailVisible;
+}
diff --git a/Libs/DICOM/Widgets/ctkDICOMObjectListWidget.h b/Libs/DICOM/Widgets/ctkDICOMObjectListWidget.h
index 5e96592d19..b7bd501451 100644
--- a/Libs/DICOM/Widgets/ctkDICOMObjectListWidget.h
+++ b/Libs/DICOM/Widgets/ctkDICOMObjectListWidget.h
@@ -36,6 +36,7 @@ class CTK_DICOM_WIDGETS_EXPORT ctkDICOMObjectListWidget : public QWidget
Q_PROPERTY(QString currentFile READ currentFile WRITE setCurrentFile)
Q_PROPERTY(QStringList fileList READ fileList WRITE setFileList)
Q_PROPERTY(QString filterExpression READ filterExpression WRITE setFilterExpression)
+ Q_PROPERTY(bool thumbnailVisible READ isThumbnailVisible WRITE setThumbnailVisible)
public:
typedef QWidget Superclass;
@@ -58,6 +59,8 @@ class CTK_DICOM_WIDGETS_EXPORT ctkDICOMObjectListWidget : public QWidget
/// Open DICOM tag definition in a web browser
void openLookupUrl(QString tag);
+ bool isThumbnailVisible()const;
+
protected:
QScopedPointer d_ptr;
@@ -72,6 +75,7 @@ public Q_SLOTS:
void setCurrentFile(const QString& newFileName);
void setFileList(const QStringList& fileList);
void setFilterExpression(const QString& expr);
+ void setThumbnailVisible(bool visible);
protected Q_SLOTS:
void itemDoubleClicked(const QModelIndex&);
diff --git a/Libs/DICOM/Widgets/ctkDICOMThumbnailGenerator.cpp b/Libs/DICOM/Widgets/ctkDICOMThumbnailGenerator.cpp
index 2c0a07cbe8..3439f3d1b0 100644
--- a/Libs/DICOM/Widgets/ctkDICOMThumbnailGenerator.cpp
+++ b/Libs/DICOM/Widgets/ctkDICOMThumbnailGenerator.cpp
@@ -123,11 +123,10 @@ void ctkDICOMThumbnailGenerator::setSmoothResize(bool on)
}
//------------------------------------------------------------------------------
-bool ctkDICOMThumbnailGenerator::generateThumbnail(DicomImage *dcmImage, const QString &path)
+bool ctkDICOMThumbnailGenerator::generateThumbnail(DicomImage *dcmImage, QImage& image)
{
Q_D(ctkDICOMThumbnailGenerator);
- QImage image;
// Check whether we have a valid image
EI_Status result = dcmImage->getStatus();
if (result != EIS_Normal)
@@ -184,14 +183,43 @@ bool ctkDICOMThumbnailGenerator::generateThumbnail(DicomImage *dcmImage, const Q
return false;
}
}
- image.scaled( d->Width, d->Height, Qt::KeepAspectRatio,
- (d->SmoothResize ? Qt::SmoothTransformation : Qt::FastTransformation) ).save(path,"PNG");
+ image = image.scaled( d->Width, d->Height, Qt::KeepAspectRatio,
+ (d->SmoothResize ? Qt::SmoothTransformation : Qt::FastTransformation) );
return true;
}
+//------------------------------------------------------------------------------
+bool ctkDICOMThumbnailGenerator::generateThumbnail(DicomImage *dcmImage, const QString &path)
+{
+ QImage image;
+ if (this->generateThumbnail(dcmImage, image))
+ {
+ return image.save(path,"PNG");
+ }
+ return false;
+}
+
+//------------------------------------------------------------------------------
+bool ctkDICOMThumbnailGenerator::generateThumbnail(const QString dcmImagePath, QImage& image)
+{
+ DicomImage dcmImage(QDir::toNativeSeparators(dcmImagePath).toUtf8());
+ return this->generateThumbnail(&dcmImage, image);
+}
+
//------------------------------------------------------------------------------
bool ctkDICOMThumbnailGenerator::generateThumbnail(const QString dcmImagePath, const QString& thumbnailPath)
{
DicomImage dcmImage(QDir::toNativeSeparators(dcmImagePath).toUtf8());
return this->generateThumbnail(&dcmImage, thumbnailPath);
}
+
+//------------------------------------------------------------------------------
+void ctkDICOMThumbnailGenerator::generateBlankThumbnail(QImage& image)
+{
+ Q_D(ctkDICOMThumbnailGenerator);
+ if (image.width() != d->Width || image.height() != d->Height)
+ {
+ image = QImage(d->Width, d->Height, QImage::Format_RGB32);
+ }
+ image.fill(Qt::darkGray);
+}
diff --git a/Libs/DICOM/Widgets/ctkDICOMThumbnailGenerator.h b/Libs/DICOM/Widgets/ctkDICOMThumbnailGenerator.h
index e556e14250..61c1aa3aaf 100644
--- a/Libs/DICOM/Widgets/ctkDICOMThumbnailGenerator.h
+++ b/Libs/DICOM/Widgets/ctkDICOMThumbnailGenerator.h
@@ -47,8 +47,14 @@ class CTK_DICOM_WIDGETS_EXPORT ctkDICOMThumbnailGenerator : public ctkDICOMAbstr
virtual bool generateThumbnail(DicomImage* dcmImage, const QString& path);
+ Q_INVOKABLE bool generateThumbnail(DicomImage *dcmImage, QImage& image);
+ Q_INVOKABLE bool generateThumbnail(const QString dcmImagePath, QImage& image);
Q_INVOKABLE bool generateThumbnail(const QString dcmImagePath, const QString& thumbnailPath);
+ /// Generate a blank thumbnail image (currently a solid gray box of the requested thumbnail size).
+ /// It can be used as a placeholder for invalid images or duringan image is loaded.
+ Q_INVOKABLE void generateBlankThumbnail(QImage& image);
+
/// Set thumbnail width
void setWidth(int width);
/// Get thumbnail width
diff --git a/Libs/Widgets/ctkExpandButton.cpp b/Libs/Widgets/ctkExpandButton.cpp
index 7eea69c9cd..7d46c65df4 100644
--- a/Libs/Widgets/ctkExpandButton.cpp
+++ b/Libs/Widgets/ctkExpandButton.cpp
@@ -36,7 +36,6 @@ class ctkExpandButtonPrivate
bool mirrorOnExpand;
QPixmap defaultPixmap;
Qt::Orientation orientation;
- Qt::LayoutDirection direction;
};
//-----------------------------------------------------------------------------
@@ -45,7 +44,6 @@ ctkExpandButtonPrivate::ctkExpandButtonPrivate(ctkExpandButton &object)
{
this->mirrorOnExpand = false;
this->orientation = Qt::Horizontal;
- this->direction = Qt::LeftToRight;
}
//-----------------------------------------------------------------------------
@@ -56,6 +54,8 @@ void ctkExpandButtonPrivate::init()
q->setOrientation(Qt::Horizontal);
q->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum);
q->setCheckable(true);
+
+ QObject::connect(q, SIGNAL(toggled(bool)), q, SLOT(updateIcon()));
}
//-----------------------------------------------------------------------------
@@ -80,7 +80,7 @@ void ctkExpandButton::setMirrorOnExpand(bool newBehavior)
{
Q_D(ctkExpandButton);
d->mirrorOnExpand = newBehavior;
- this->updateIcon(d->direction);
+ this->updateIcon();
}
//-----------------------------------------------------------------------------
@@ -115,7 +115,7 @@ void ctkExpandButton::setOrientation(Qt::Orientation newOrientation)
QStyle::SP_ToolBarVerticalExtensionButton, &opt);
d->orientation = Qt::Vertical;
}
- this->updateIcon(d->direction);
+ this->updateIcon();
}
//-----------------------------------------------------------------------------
@@ -126,15 +126,14 @@ Qt::Orientation ctkExpandButton::orientation() const
}
//-----------------------------------------------------------------------------
-void ctkExpandButton::updateIcon(Qt::LayoutDirection newDirection)
+void ctkExpandButton::updateIcon()
{
Q_D(ctkExpandButton);
// If the orientation is vertical, UpToBottom is LeftToRight and
// BottomToUp is RightToLeft. Rotate 90' clockwise.
- if(newDirection == Qt::LeftToRight)
+ if(!d->mirrorOnExpand || !this->isChecked())
{
this->setIcon(QIcon(d->defaultPixmap));
- d->direction = Qt::LeftToRight;
}
else
{
@@ -142,20 +141,5 @@ void ctkExpandButton::updateIcon(Qt::LayoutDirection newDirection)
d->defaultPixmap.toImage().mirrored(d->orientation == Qt::Horizontal,
d->orientation == Qt::Vertical);
this->setIcon(QIcon(QPixmap::fromImage(mirrorImage)));
- d->direction = Qt::RightToLeft;
}
}
-
-//-----------------------------------------------------------------------------
-void ctkExpandButton::nextCheckState()
-{
- Q_D(ctkExpandButton);
- if (d->mirrorOnExpand)
- {
- Qt::LayoutDirection newDirection =
- this->isChecked() ? Qt::LeftToRight : Qt::RightToLeft;
- this->updateIcon(newDirection);
- }
-
- return this->Superclass::nextCheckState();
-}
diff --git a/Libs/Widgets/ctkExpandButton.h b/Libs/Widgets/ctkExpandButton.h
index c7c05d89ae..51e2a10982 100644
--- a/Libs/Widgets/ctkExpandButton.h
+++ b/Libs/Widgets/ctkExpandButton.h
@@ -62,10 +62,7 @@ class CTK_WIDGETS_EXPORT ctkExpandButton
virtual QSize sizeHint() const;
private Q_SLOTS:
- void updateIcon(Qt::LayoutDirection newDirection);
-
-protected:
- virtual void nextCheckState();
+ void updateIcon();
protected:
QScopedPointer d_ptr;