From 1de3f3f9614943fb976bbda12b823e8453d2c197 Mon Sep 17 00:00:00 2001 From: Davide Punzo Date: Thu, 11 Jan 2024 15:18:03 +0100 Subject: [PATCH] ENH: Apply Andras' feedback --- .../Widgets/ctkDICOMSeriesItemWidget.cpp | 129 +++++++++++++----- .../Widgets/ctkDICOMVisualBrowserWidget.cpp | 14 +- .../Widgets/Resources/UI/ctkThumbnailLabel.ui | 16 ++- Libs/Widgets/ctkThumbnailLabel.cpp | 38 +++--- Libs/Widgets/ctkThumbnailLabel.h | 5 +- 5 files changed, 132 insertions(+), 70 deletions(-) diff --git a/Libs/DICOM/Widgets/ctkDICOMSeriesItemWidget.cpp b/Libs/DICOM/Widgets/ctkDICOMSeriesItemWidget.cpp index 2775937e43..1add8fd988 100644 --- a/Libs/DICOM/Widgets/ctkDICOMSeriesItemWidget.cpp +++ b/Libs/DICOM/Widgets/ctkDICOMSeriesItemWidget.cpp @@ -24,6 +24,7 @@ //Qt includes #include #include +#include #include #include #include @@ -32,6 +33,7 @@ // CTK includes #include +#include // ctkDICOMCore includes #include "ctkDICOMDatabase.h" @@ -63,8 +65,10 @@ class ctkDICOMSeriesItemWidgetPrivate: public Ui_ctkDICOMSeriesItemWidget void drawModalityThumbnail(); void drawThumbnail(const QString& file, int numberOfFrames); void drawTextWithShadow(QPainter *painter, - const QRect &r, - int flags, + const QFont &font, + const int &x, + const int &y, + const Qt::Alignment &alignment, const QString &text); void updateThumbnailProgressBar(); @@ -131,6 +135,7 @@ void ctkDICOMSeriesItemWidgetPrivate::init() this->setupUi(q); this->SeriesThumbnail->setTransformationMode(Qt::TransformationMode::SmoothTransformation); + this->SeriesThumbnail->textPushButton()->setElideMode(Qt::ElideRight); } //---------------------------------------------------------------------------- @@ -320,15 +325,16 @@ void ctkDICOMSeriesItemWidgetPrivate::createThumbnail(ctkJobDetail td) //---------------------------------------------------------------------------- void ctkDICOMSeriesItemWidgetPrivate::drawModalityThumbnail() { - Q_Q(ctkDICOMSeriesItemWidget); if (!this->DicomDatabase) { logger.error("drawThumbnail failed, no DICOM Database has been set. \n"); return; } - int margin = 10; - int fontSize = 40; + int textSize = 40; + QFont font = this->SeriesThumbnail->font(); + font.setBold(true); + font.setPixelSize(textSize); QPixmap resultPixmap(this->ThumbnailSize, this->ThumbnailSize); resultPixmap.fill(Qt::transparent); @@ -339,15 +345,16 @@ void ctkDICOMSeriesItemWidgetPrivate::drawModalityThumbnail() QImage thumbnailImage; QPainter painter; - QColor backgroundColor = q->palette().color(QPalette::Normal, QPalette::Window); + QColor backgroundColor = this->SeriesThumbnail->palette().color(QPalette::Normal, QPalette::Window); thumbnailGenerator.generateBlankThumbnail(thumbnailImage, backgroundColor); resultPixmap = QPixmap::fromImage(thumbnailImage); if (painter.begin(&resultPixmap)) { painter.setRenderHint(QPainter::Antialiasing); QRect rect = resultPixmap.rect(); - painter.setFont(QFont("Arial", fontSize, QFont::Bold)); - this->drawTextWithShadow(&painter, rect.adjusted(margin, margin, margin, margin), Qt::AlignCenter, this->Modality); + int x = int(rect.width() * 0.5); + int y = int(rect.height() * 0.5); + this->drawTextWithShadow(&painter, font, x, y, Qt::AlignCenter, this->Modality); painter.end(); } @@ -357,21 +364,18 @@ void ctkDICOMSeriesItemWidgetPrivate::drawModalityThumbnail() //---------------------------------------------------------------------------- void ctkDICOMSeriesItemWidgetPrivate::drawThumbnail(const QString &file, int numberOfFrames) { - Q_Q(ctkDICOMSeriesItemWidget); if (!this->DicomDatabase) { logger.error("drawThumbnail failed, no DICOM Database has been set. \n"); return; } - int margin = 10; - int fontSize = 12; - if (!this->SeriesThumbnail->text().isEmpty()) - { - margin = 5; - fontSize = 14; - } - + int margin = 5; + int iconSize = 48; + int textSize = 20; + QFont font = this->SeriesThumbnail->font(); + font.setBold(true); + font.setPixelSize(textSize); QPixmap resultPixmap(this->ThumbnailSize, this->ThumbnailSize); resultPixmap.fill(Qt::transparent); ctkDICOMThumbnailGenerator thumbnailGenerator; @@ -387,7 +391,7 @@ void ctkDICOMSeriesItemWidgetPrivate::drawThumbnail(const QString &file, int num thumbnailGenerated = false; emptyThumbnailGenerated = true; this->isThumbnailDocument = true; - QColor backgroundColor = q->palette().color(QPalette::Normal, QPalette::Window); + QColor backgroundColor = this->SeriesThumbnail->palette().color(QPalette::Normal, QPalette::Window); thumbnailGenerator.generateBlankThumbnail(this->ThumbnailImage, backgroundColor); resultPixmap = QPixmap::fromImage(this->ThumbnailImage); if (painter.begin(&resultPixmap)) @@ -406,18 +410,18 @@ void ctkDICOMSeriesItemWidgetPrivate::drawThumbnail(const QString &file, int num { painter.setRenderHint(QPainter::Antialiasing); QRect rect = resultPixmap.rect(); - painter.setFont(QFont("Arial", fontSize, QFont::Bold)); - int x = int((rect.width() / 2) - (this->ThumbnailImage.rect().width() / 2)); - int y = int((rect.height() / 2) - (this->ThumbnailImage.rect().height() / 2)); + painter.setFont(font); + int x = int((rect.width() * 0.5) - (this->ThumbnailImage.rect().width() * 0.5)); + int y = int((rect.height() * 0.5) - (this->ThumbnailImage.rect().height() * 0.5)); painter.drawPixmap(x, y, QPixmap::fromImage(this->ThumbnailImage)); - QString topLeft = ctkDICOMSeriesItemWidget::tr("Series: %1\n%2").arg(this->SeriesNumber).arg(this->Modality); - this->drawTextWithShadow(&painter, rect.adjusted(margin, margin, margin, margin), Qt::AlignTop | Qt::AlignLeft, topLeft); - QString bottomLeft = ctkDICOMSeriesItemWidget::tr("N.frames: %1").arg(numberOfFrames); - this->drawTextWithShadow(&painter, rect.adjusted(margin, -margin, margin, -margin), Qt::AlignBottom | Qt::AlignLeft, bottomLeft); + + QString topLeftString = ctkDICOMSeriesItemWidget::tr("Series: %1\n%2").arg(this->SeriesNumber).arg(this->Modality); + this->drawTextWithShadow(&painter, font, margin, margin, Qt::AlignTop | Qt::AlignLeft, topLeftString); QString rows = this->DicomDatabase->instanceValue(this->CentralFrameSOPInstanceUID, "0028,0010"); QString columns = this->DicomDatabase->instanceValue(this->CentralFrameSOPInstanceUID, "0028,0011"); - QString bottomRight = rows + "x" + columns; - this->drawTextWithShadow(&painter, rect.adjusted(-margin, -margin, -margin, -margin), Qt::AlignBottom | Qt::AlignRight, bottomRight); + QString bottomLeftString = rows + "x" + columns + "x" + QString::number(numberOfFrames); + this->drawTextWithShadow(&painter, font, margin, rect.height() - margin, + Qt::AlignBottom | Qt::AlignLeft, bottomLeftString); QSvgRenderer renderer; if (this->IsCloud) @@ -441,7 +445,7 @@ void ctkDICOMSeriesItemWidgetPrivate::drawThumbnail(const QString &file, int num } QPoint topRight = rect.topRight(); - QRectF bounds(topRight.x() - 48 - margin, topRight.y() + margin, 48, 48); + QRectF bounds(topRight.x() - iconSize - margin, topRight.y() + margin, iconSize, iconSize); renderer.render(&painter, bounds); painter.end(); } @@ -455,16 +459,66 @@ void ctkDICOMSeriesItemWidgetPrivate::drawThumbnail(const QString &file, int num //---------------------------------------------------------------------------- void ctkDICOMSeriesItemWidgetPrivate::drawTextWithShadow(QPainter *painter, - const QRect &r, - int flags, const - QString &text) + const QFont &font, + const int &x, + const int &y, + const Qt::Alignment &alignment, + const QString &text) { - painter->setPen(Qt::darkGray); - painter->drawText(r.adjusted(1, 1, 1, 1), flags, text); - painter->setPen(QColor(Qt::gray)); - painter->drawText(r.adjusted(2, 2, 2, 2), flags, text); - painter->setPen(QPen(QColor(41, 121, 255))); - painter->drawText(r, flags, text); + QColor textColor(60, 164, 255, 225); + QGraphicsDropShadowEffect* dropShadowEffect = new QGraphicsDropShadowEffect; + dropShadowEffect->setXOffset(1); + dropShadowEffect->setYOffset(1); + dropShadowEffect->setBlurRadius(1); + dropShadowEffect->setColor(Qt::gray); + QLabel textLabel; + QPalette palette = textLabel.palette(); + palette.setColor(QPalette::WindowText, textColor); + textLabel.setPalette(palette); + textLabel.setFont(font); + textLabel.setGraphicsEffect(dropShadowEffect); + textLabel.setText(text); + QPixmap textPixMap = textLabel.grab(); + QRect rect = textPixMap.rect(); + int textWidth = rect.width(); + int textHeight = rect.height(); + + if (alignment == Qt::AlignCenter) + { + painter->drawPixmap(x - textWidth * 0.5, y - textHeight * 0.5, textPixMap); + } + else if (alignment == (Qt::AlignTop | Qt::AlignLeft)) + { + painter->drawPixmap(x, y, textPixMap); + } + else if (alignment == Qt::AlignTop) + { + painter->drawPixmap(x - textWidth * 0.5, y, textPixMap); + } + else if (alignment == (Qt::AlignTop | Qt::AlignRight)) + { + painter->drawPixmap(x - textWidth, y, textPixMap); + } + else if (alignment == (Qt::AlignHCenter | Qt::AlignLeft)) + { + painter->drawPixmap(x, y - textHeight * 0.5, textPixMap); + } + else if (alignment == (Qt::AlignHCenter | Qt::AlignRight)) + { + painter->drawPixmap(x - textWidth, y - textHeight * 0.5, textPixMap); + } + else if (alignment == (Qt::AlignBottom | Qt::AlignLeft)) + { + painter->drawPixmap(x, y - textHeight, textPixMap); + } + else if (alignment == Qt::AlignBottom) + { + painter->drawPixmap(x - textWidth * 0.5, y - textHeight, textPixMap); + } + else if (alignment == (Qt::AlignBottom | Qt::AlignRight)) + { + painter->drawPixmap(x - textWidth, y - textHeight, textPixMap); + } } //---------------------------------------------------------------------------- @@ -600,6 +654,7 @@ void ctkDICOMSeriesItemWidget::setSeriesDescription(const QString& seriesDescrip { Q_D(ctkDICOMSeriesItemWidget); d->SeriesThumbnail->setText(seriesDescription); + d->SeriesThumbnail->textPushButton()->setToolTip(seriesDescription); } //------------------------------------------------------------------------------ diff --git a/Libs/DICOM/Widgets/ctkDICOMVisualBrowserWidget.cpp b/Libs/DICOM/Widgets/ctkDICOMVisualBrowserWidget.cpp index c102a29108..c787fa198d 100644 --- a/Libs/DICOM/Widgets/ctkDICOMVisualBrowserWidget.cpp +++ b/Libs/DICOM/Widgets/ctkDICOMVisualBrowserWidget.cpp @@ -714,7 +714,7 @@ void ctkDICOMVisualBrowserWidgetPrivate::setBackgroundColorToFilterWidgets(bool QColor color = Qt::yellow; if (visualDICOMBrowserColor.lightnessF() < 0.5) { - color.setRgb(60, 164, 255);; + color.setRgb(60, 164, 255); } this->setBackgroundColorToWidget(color, this->FilteringPatientIDSearchBox); this->setBackgroundColorToWidget(color, this->FilteringPatientNameSearchBox); @@ -2514,7 +2514,7 @@ void ctkDICOMVisualBrowserWidget::showPatientContextMenu(const QPoint &point) QAction *metadataAction = new QAction(metadataString, patientMenu); patientMenu->addAction(metadataAction); - QString deleteString = tr("Delete patient"); + QString deleteString = tr("Delete patient from local database"); QAction *deleteAction = new QAction(deleteString, patientMenu); patientMenu->addAction(deleteAction); deleteAction->setVisible(this->isDeleteActionVisible()); @@ -2607,8 +2607,8 @@ void ctkDICOMVisualBrowserWidget::showStudyContextMenu(const QPoint &point) QAction *metadataAction = new QAction(metadataString, studyMenu); studyMenu->addAction(metadataAction); - QString deleteString = numberOfSelectedStudies == 1 ? tr("Delete study") : - tr("Delete %1 studies").arg(numberOfSelectedStudies); + QString deleteString = numberOfSelectedStudies == 1 ? tr("Delete study from local database") : + tr("Delete %1 studies from local database").arg(numberOfSelectedStudies); QAction *deleteAction = new QAction(deleteString, studyMenu); studyMenu->addAction(deleteAction); deleteAction->setVisible(this->isDeleteActionVisible()); @@ -2708,8 +2708,8 @@ void ctkDICOMVisualBrowserWidget::showSeriesContextMenu(const QPoint &point) QAction *metadataAction = new QAction(metadataString, seriesMenu); seriesMenu->addAction(metadataAction); - QString deleteString = numberOfSelectedSeries == 1 ? tr("Delete series") : - tr("Delete %1 series").arg(numberOfSelectedSeries); + QString deleteString = numberOfSelectedSeries == 1 ? tr("Delete series from local database") : + tr("Delete %1 series from local database").arg(numberOfSelectedSeries); QAction *deleteAction = new QAction(deleteString, seriesMenu); seriesMenu->addAction(deleteAction); deleteAction->setVisible(this->isDeleteActionVisible()); @@ -2783,7 +2783,7 @@ void ctkDICOMVisualBrowserWidget::onPatientsTabMenuToolButtonClicked() } patientMenu->addSeparator(); - QString deleteString = tr("Delete all Patients"); + QString deleteString = tr("Delete all Patients from local database"); QAction *deleteAction = new QAction(deleteString, patientMenu); deleteAction->setIcon(QIcon(":Icons/delete.svg")); patientMenu->addAction(deleteAction); diff --git a/Libs/Widgets/Resources/UI/ctkThumbnailLabel.ui b/Libs/Widgets/Resources/UI/ctkThumbnailLabel.ui index abb2bf3810..2e911bc58d 100644 --- a/Libs/Widgets/Resources/UI/ctkThumbnailLabel.ui +++ b/Libs/Widgets/Resources/UI/ctkThumbnailLabel.ui @@ -119,14 +119,24 @@ - - - Qt::AlignCenter + + + false + + + true + + + ctkPushButton + QPushButton +
ctkPushButton.h
+
+
diff --git a/Libs/Widgets/ctkThumbnailLabel.cpp b/Libs/Widgets/ctkThumbnailLabel.cpp index cce96b9369..b7f1fd746c 100644 --- a/Libs/Widgets/ctkThumbnailLabel.cpp +++ b/Libs/Widgets/ctkThumbnailLabel.cpp @@ -93,27 +93,27 @@ void ctkThumbnailLabelPrivate::setupUi(QWidget* widget) //---------------------------------------------------------------------------- void ctkThumbnailLabelPrivate::updateThumbnail() -{ +{ Q_Q(ctkThumbnailLabel); QSize size = q->size(); - if (this->TextLabel->isVisible()) + if (this->TextPushButton->isVisible()) { if (this->TextPosition & Qt::AlignTop) { - size.setHeight(size.height() - this->TextLabel->height()); + size.setHeight(size.height() - this->TextPushButton->height()); } else if (this->TextPosition & Qt::AlignBottom) { - size.setHeight(size.height() - this->TextLabel->height()); + size.setHeight(size.height() - this->TextPushButton->height()); } else if (this->TextPosition & Qt::AlignLeft) { - size.setWidth(size.width() - this->TextLabel->width()); + size.setWidth(size.width() - this->TextPushButton->width()); } else if (this->TextPosition & Qt::AlignRight) { - size.setWidth(size.width() - this->TextLabel->width()); + size.setWidth(size.width() - this->TextPushButton->width()); } } @@ -148,18 +148,16 @@ ctkThumbnailLabel::~ctkThumbnailLabel() } //---------------------------------------------------------------------------- -QLabel* ctkThumbnailLabel::textLabel() +ctkPushButton* ctkThumbnailLabel::textPushButton() { Q_D(ctkThumbnailLabel); - - return d->TextLabel; + return d->TextPushButton; } //---------------------------------------------------------------------------- QFrame *ctkThumbnailLabel::pixmapFrame() { Q_D(ctkThumbnailLabel); - return d->PixmapFrame; } @@ -167,7 +165,6 @@ QFrame *ctkThumbnailLabel::pixmapFrame() QLabel* ctkThumbnailLabel::pixmapLabel() { Q_D(ctkThumbnailLabel); - return d->PixmapLabel; } @@ -175,7 +172,6 @@ QLabel* ctkThumbnailLabel::pixmapLabel() QProgressBar *ctkThumbnailLabel::operationProgressBar() { Q_D(ctkThumbnailLabel); - return d->OperationProgressBar; } @@ -184,8 +180,8 @@ void ctkThumbnailLabel::setText(const QString &text) { Q_D(ctkThumbnailLabel); - d->TextLabel->setText(text); - d->TextLabel->setVisible(!text.isEmpty() && + d->TextPushButton->setText(text); + d->TextPushButton->setVisible(!text.isEmpty() && ! (d->TextPosition & Qt::AlignHCenter && d->TextPosition & Qt::AlignVCenter) ); } @@ -194,7 +190,7 @@ void ctkThumbnailLabel::setText(const QString &text) QString ctkThumbnailLabel::text()const { Q_D(const ctkThumbnailLabel); - return d->TextLabel->text(); + return d->TextPushButton->text(); } //---------------------------------------------------------------------------- @@ -205,7 +201,7 @@ void ctkThumbnailLabel::setTextPosition(const Qt::Alignment& position) int textIndex = -1; for (textIndex = 0; textIndex < this->layout()->count(); ++textIndex) { - if (this->layout()->itemAt(textIndex)->widget() == d->TextLabel) + if (this->layout()->itemAt(textIndex)->widget() == d->TextPushButton) { break; } @@ -243,11 +239,11 @@ void ctkThumbnailLabel::setTextPosition(const Qt::Alignment& position) } if (row == 1 && col == 1) { - d->TextLabel->setVisible(false); + d->TextPushButton->setVisible(false); } else { - gridLayout->addWidget(d->TextLabel,row, col); + gridLayout->addWidget(d->TextPushButton,row, col); } } @@ -353,10 +349,10 @@ QColor ctkThumbnailLabel::selectedColor()const QSize ctkThumbnailLabel::minimumSizeHint()const { Q_D(const ctkThumbnailLabel); - if (d->TextLabel->isVisibleTo(const_cast(this)) && - !d->TextLabel->text().isEmpty()) + if (d->TextPushButton->isVisibleTo(const_cast(this)) && + !d->TextPushButton->text().isEmpty()) { - return d->TextLabel->minimumSizeHint(); + return d->TextPushButton->minimumSizeHint(); } return QSize(); } diff --git a/Libs/Widgets/ctkThumbnailLabel.h b/Libs/Widgets/ctkThumbnailLabel.h index fd9aa3db0d..584188c8c3 100644 --- a/Libs/Widgets/ctkThumbnailLabel.h +++ b/Libs/Widgets/ctkThumbnailLabel.h @@ -21,12 +21,13 @@ #ifndef __ctkThumbnailLabel_h #define __ctkThumbnailLabel_h -// Qt includes +// Qt includes #include #include #include "ctkWidgetsExport.h" +class ctkPushButton; class ctkThumbnailLabelPrivate; class QFrame; @@ -70,7 +71,7 @@ class CTK_WIDGETS_EXPORT ctkThumbnailLabel : public QWidget explicit ctkThumbnailLabel(QWidget* parent=0); virtual ~ctkThumbnailLabel(); - Q_INVOKABLE QLabel* textLabel(); + Q_INVOKABLE ctkPushButton* textPushButton(); Q_INVOKABLE QFrame* pixmapFrame(); Q_INVOKABLE QLabel* pixmapLabel(); Q_INVOKABLE QProgressBar* operationProgressBar();