Skip to content

Commit

Permalink
Merge branch 'master' into 1065-dicom-follow-links
Browse files Browse the repository at this point in the history
  • Loading branch information
pieper authored Feb 10, 2023
2 parents 65104cd + 2daac1c commit 6825a5a
Show file tree
Hide file tree
Showing 8 changed files with 141 additions and 43 deletions.
46 changes: 36 additions & 10 deletions Libs/DICOM/Widgets/Resources/UI/ctkDICOMObjectListWidget.ui
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>442</width>
<height>311</height>
<height>514</height>
</rect>
</property>
<property name="windowTitle">
Expand Down Expand Up @@ -51,8 +51,8 @@
</layout>
</item>
<item>
<widget class="ctkSliderWidget" name="fileSliderWidget" native="true">
<property name="decimals" stdset="0">
<widget class="ctkSliderWidget" name="fileSliderWidget">
<property name="decimals">
<number>0</number>
</property>
</widget>
Expand Down Expand Up @@ -106,20 +106,46 @@
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2"/>
</item>
<item>
<widget class="QTreeView" name="dcmObjectTreeView">
<property name="toolTip">
<string>Double-click to show DICOM tag definition.</string>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<property name="topMargin">
<number>0</number>
</property>
</widget>
<item>
<widget class="QTreeView" name="dcmObjectTreeView">
<property name="toolTip">
<string>Double-click to show DICOM tag definition.</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="thumbnailLabel">
<property name="text">
<string>Thumbnail</string>
</property>
</widget>
</item>
<item>
<widget class="ctkExpandButton" name="showThumbnailButton">
<property name="toolTip">
<string>Show image thumbnail</string>
</property>
<property name="mirrorOnExpand">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>ctkExpandButton</class>
<extends>QToolButton</extends>
<header>ctkExpandButton.h</header>
</customwidget>
<customwidget>
<class>ctkSearchBox</class>
<extends>QLineEdit</extends>
Expand Down
5 changes: 5 additions & 0 deletions Libs/DICOM/Widgets/ctkDICOMBrowser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <QCloseEvent>
#include <QComboBox>
#include <QDebug>
#include <QDesktopWidget>
#include <QDialogButtonBox>
#include <QFile>
#include <QFileInfo>
Expand Down Expand Up @@ -105,6 +106,10 @@ class ctkDICOMMetadataDialog : public QDialog
if (!savedGeometry.isEmpty())
{
this->restoreGeometry(savedGeometry);
if (this->isMaximized())
{
this->setGeometry(QApplication::desktop()->availableGeometry(this));
}
}
}

Expand Down
54 changes: 51 additions & 3 deletions Libs/DICOM/Widgets/ctkDICOMObjectListWidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,14 @@

// ctkDICOMWidgets includes
#include "ctkDICOMObjectListWidget.h"
#include "ctkDICOMThumbnailGenerator.h"
#include "ui_ctkDICOMObjectListWidget.h"

// Qt includes
#include <QApplication>
#include <QClipboard>
#include <QDesktopServices>
#include <QImage>
#include <QSortFilterProxyModel>
#include <QString>
#include <QStringList>
Expand Down Expand Up @@ -101,6 +103,7 @@ class ctkDICOMObjectListWidgetPrivate: public Ui_ctkDICOMObjectListWidget
ctkDICOMObjectModel* dicomObjectModel;
qRecursiveTreeProxyFilter* filterModel;
QString filterExpression;
bool thumbnailVisible{true};
};

//----------------------------------------------------------------------------
Expand Down Expand Up @@ -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&)),
Expand All @@ -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)));
}

//----------------------------------------------------------------------------
Expand All @@ -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);
Expand Down Expand Up @@ -307,7 +314,19 @@ void ctkDICOMObjectListWidget::updateWidget()
d->currentFile = d->fileList[static_cast<int>(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()
Expand Down Expand Up @@ -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;
}
4 changes: 4 additions & 0 deletions Libs/DICOM/Widgets/ctkDICOMObjectListWidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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<ctkDICOMObjectListWidgetPrivate> d_ptr;

Expand All @@ -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&);
Expand Down
36 changes: 32 additions & 4 deletions Libs/DICOM/Widgets/ctkDICOMThumbnailGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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);
}
6 changes: 6 additions & 0 deletions Libs/DICOM/Widgets/ctkDICOMThumbnailGenerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
28 changes: 6 additions & 22 deletions Libs/Widgets/ctkExpandButton.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ class ctkExpandButtonPrivate
bool mirrorOnExpand;
QPixmap defaultPixmap;
Qt::Orientation orientation;
Qt::LayoutDirection direction;
};

//-----------------------------------------------------------------------------
Expand All @@ -45,7 +44,6 @@ ctkExpandButtonPrivate::ctkExpandButtonPrivate(ctkExpandButton &object)
{
this->mirrorOnExpand = false;
this->orientation = Qt::Horizontal;
this->direction = Qt::LeftToRight;
}

//-----------------------------------------------------------------------------
Expand All @@ -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()));
}

//-----------------------------------------------------------------------------
Expand All @@ -80,7 +80,7 @@ void ctkExpandButton::setMirrorOnExpand(bool newBehavior)
{
Q_D(ctkExpandButton);
d->mirrorOnExpand = newBehavior;
this->updateIcon(d->direction);
this->updateIcon();
}

//-----------------------------------------------------------------------------
Expand Down Expand Up @@ -115,7 +115,7 @@ void ctkExpandButton::setOrientation(Qt::Orientation newOrientation)
QStyle::SP_ToolBarVerticalExtensionButton, &opt);
d->orientation = Qt::Vertical;
}
this->updateIcon(d->direction);
this->updateIcon();
}

//-----------------------------------------------------------------------------
Expand All @@ -126,36 +126,20 @@ 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
{
QImage mirrorImage =
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();
}
5 changes: 1 addition & 4 deletions Libs/Widgets/ctkExpandButton.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<ctkExpandButtonPrivate> d_ptr;
Expand Down

0 comments on commit 6825a5a

Please sign in to comment.