mirror of
https://github.com/RetroShare/RetroShare.git
synced 2025-12-18 10:02:41 -05:00
added possibility to change the aspect ratio of thumbnails and replaced image warping by largest centered cropping
This commit is contained in:
parent
bebc9f2863
commit
af16659783
5 changed files with 93 additions and 26 deletions
|
|
@ -24,6 +24,8 @@
|
||||||
#include "gui/common/FilesDefs.h"
|
#include "gui/common/FilesDefs.h"
|
||||||
#include "gui/gxschannels/GxsChannelPostThumbnail.h"
|
#include "gui/gxschannels/GxsChannelPostThumbnail.h"
|
||||||
|
|
||||||
|
const float ChannelPostThumbnailView::DEFAULT_SIZE_IN_FONT_HEIGHT = 5.0;
|
||||||
|
|
||||||
ChannelPostThumbnailView::ChannelPostThumbnailView(const RsGxsChannelPost& post,uint32_t flags,QWidget *parent)
|
ChannelPostThumbnailView::ChannelPostThumbnailView(const RsGxsChannelPost& post,uint32_t flags,QWidget *parent)
|
||||||
: QWidget(parent),mPostTitle(nullptr),mFlags(flags), mAspectRatio(ASPECT_RATIO_2_3)
|
: QWidget(parent),mPostTitle(nullptr),mFlags(flags), mAspectRatio(ASPECT_RATIO_2_3)
|
||||||
{
|
{
|
||||||
|
|
@ -115,8 +117,6 @@ void ChannelPostThumbnailView::init(const RsGxsChannelPost& post)
|
||||||
|
|
||||||
layout->addWidget(mPostImage);
|
layout->addWidget(mPostImage);
|
||||||
|
|
||||||
setSizePolicy(QSizePolicy::Maximum,QSizePolicy::Maximum);
|
|
||||||
|
|
||||||
QFontMetricsF fm(font());
|
QFontMetricsF fm(font());
|
||||||
int W = THUMBNAIL_OVERSAMPLE_FACTOR * thumbnail_w() * fm.height() ;
|
int W = THUMBNAIL_OVERSAMPLE_FACTOR * thumbnail_w() * fm.height() ;
|
||||||
int H = THUMBNAIL_OVERSAMPLE_FACTOR * thumbnail_h() * fm.height() ;
|
int H = THUMBNAIL_OVERSAMPLE_FACTOR * thumbnail_h() * fm.height() ;
|
||||||
|
|
@ -134,31 +134,56 @@ void ChannelPostThumbnailView::init(const RsGxsChannelPost& post)
|
||||||
|
|
||||||
QFont font = mPostTitle->font();
|
QFont font = mPostTitle->font();
|
||||||
|
|
||||||
|
font.setPointSizeF(DEFAULT_SIZE_IN_FONT_HEIGHT / 5.0 * font.pointSizeF());
|
||||||
|
|
||||||
if(is_msg_new)
|
if(is_msg_new)
|
||||||
{
|
|
||||||
font.setBold(true);
|
font.setBold(true);
|
||||||
mPostTitle->setFont(font);
|
|
||||||
}
|
mPostTitle->setFont(font);
|
||||||
|
|
||||||
mPostTitle->setMaximumWidth(W);
|
mPostTitle->setMaximumWidth(W);
|
||||||
|
mPostTitle->setMaximumHeight(3*fm.height());
|
||||||
mPostTitle->setWordWrap(true);
|
mPostTitle->setWordWrap(true);
|
||||||
|
mPostTitle->adjustSize();
|
||||||
|
|
||||||
|
setMinimumHeight(H + mPostTitle->height() + 0.5*fm.height());
|
||||||
|
setMaximumHeight(H + mPostTitle->height() + 0.5*fm.height());
|
||||||
}
|
}
|
||||||
|
setSizePolicy(QSizePolicy::MinimumExpanding,QSizePolicy::MinimumExpanding);
|
||||||
|
|
||||||
|
layout->addStretch();
|
||||||
|
|
||||||
setLayout(layout);
|
setLayout(layout);
|
||||||
adjustSize();
|
adjustSize();
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QSize ChannelPostThumbnailView::actualSize() const
|
||||||
|
{
|
||||||
|
QFontMetricsF fm(font());
|
||||||
|
|
||||||
|
if(mPostTitle != nullptr)
|
||||||
|
{
|
||||||
|
QMargins cm = layout()->contentsMargins();
|
||||||
|
|
||||||
|
return QSize(width(),
|
||||||
|
mPostTitle->height() + mPostImage->height() + 0.5*fm.height()
|
||||||
|
+ cm.top() + cm.bottom() + layout()->spacing());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return size();
|
||||||
|
}
|
||||||
|
|
||||||
float ChannelPostThumbnailView::thumbnail_w() const
|
float ChannelPostThumbnailView::thumbnail_w() const
|
||||||
{
|
{
|
||||||
switch(mAspectRatio)
|
switch(mAspectRatio)
|
||||||
{
|
{
|
||||||
default:
|
default:
|
||||||
case ASPECT_RATIO_1_1:
|
case ASPECT_RATIO_1_1:
|
||||||
case ASPECT_RATIO_UNKNOWN: return 5;
|
case ASPECT_RATIO_UNKNOWN: return DEFAULT_SIZE_IN_FONT_HEIGHT;
|
||||||
|
|
||||||
case ASPECT_RATIO_2_3: return 4;
|
case ASPECT_RATIO_2_3: return DEFAULT_SIZE_IN_FONT_HEIGHT;
|
||||||
case ASPECT_RATIO_16_9: return 5 * 16.0/9.0;
|
case ASPECT_RATIO_16_9: return DEFAULT_SIZE_IN_FONT_HEIGHT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
float ChannelPostThumbnailView::thumbnail_h() const
|
float ChannelPostThumbnailView::thumbnail_h() const
|
||||||
|
|
@ -167,17 +192,17 @@ float ChannelPostThumbnailView::thumbnail_h() const
|
||||||
{
|
{
|
||||||
default:
|
default:
|
||||||
case ASPECT_RATIO_1_1:
|
case ASPECT_RATIO_1_1:
|
||||||
case ASPECT_RATIO_UNKNOWN: return 5;
|
case ASPECT_RATIO_UNKNOWN: return DEFAULT_SIZE_IN_FONT_HEIGHT;
|
||||||
|
|
||||||
case ASPECT_RATIO_2_3: return 6;
|
case ASPECT_RATIO_2_3: return DEFAULT_SIZE_IN_FONT_HEIGHT * 3.0/2.0;
|
||||||
case ASPECT_RATIO_16_9: return 5;
|
case ASPECT_RATIO_16_9: return DEFAULT_SIZE_IN_FONT_HEIGHT * 9.0/16.0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZoomableLabel::reset()
|
void ZoomableLabel::reset()
|
||||||
{
|
{
|
||||||
mCenterX = mFullImage.width()/2.0;
|
mCenterX = mFullImage.width()/2.0;
|
||||||
mCenterX = mFullImage.height()/2.0;
|
mCenterY = mFullImage.height()/2.0;
|
||||||
mZoomFactor = 1.0/std::max(width() / (float)mFullImage.width(), height()/(float)mFullImage.height());
|
mZoomFactor = 1.0/std::max(width() / (float)mFullImage.width(), height()/(float)mFullImage.height());
|
||||||
|
|
||||||
updateView();
|
updateView();
|
||||||
|
|
@ -257,9 +282,7 @@ void ZoomableLabel::setPicture(const QPixmap& pix)
|
||||||
{
|
{
|
||||||
mFullImage = pix;
|
mFullImage = pix;
|
||||||
|
|
||||||
mCenterX = pix.width()/2.0;
|
reset();
|
||||||
mCenterY = pix.height()/2.0;
|
|
||||||
|
|
||||||
updateView();
|
updateView();
|
||||||
}
|
}
|
||||||
void ZoomableLabel::resizeEvent(QResizeEvent *e)
|
void ZoomableLabel::resizeEvent(QResizeEvent *e)
|
||||||
|
|
|
||||||
|
|
@ -78,7 +78,7 @@ public:
|
||||||
} AspectRatio;
|
} AspectRatio;
|
||||||
|
|
||||||
// This variable determines the zoom factor on the text below thumbnails. 2.0 is mostly correct for all screen.
|
// This variable determines the zoom factor on the text below thumbnails. 2.0 is mostly correct for all screen.
|
||||||
static constexpr float THUMBNAIL_OVERSAMPLE_FACTOR = 2.0;
|
static constexpr float THUMBNAIL_OVERSAMPLE_FACTOR = 2.0;
|
||||||
|
|
||||||
static constexpr uint32_t FLAG_NONE = 0x00;
|
static constexpr uint32_t FLAG_NONE = 0x00;
|
||||||
static constexpr uint32_t FLAG_SHOW_TEXT = 0x01;
|
static constexpr uint32_t FLAG_SHOW_TEXT = 0x01;
|
||||||
|
|
@ -102,7 +102,15 @@ public:
|
||||||
QPixmap getCroppedScaledPicture() const { return mPostImage->extractCroppedScaledPicture() ; }
|
QPixmap getCroppedScaledPicture() const { return mPostImage->extractCroppedScaledPicture() ; }
|
||||||
|
|
||||||
void setText(const QString& s);
|
void setText(const QString& s);
|
||||||
|
|
||||||
|
// This is used to allow to render the widget into a pixmap without the white space that Qt adds vertically. There is *no way* apparently
|
||||||
|
// to get rid of that bloody space. It depends on the aspect ratio of the image and it only shows up when the text label is shown.
|
||||||
|
// The label however has a correct size. It seems that Qt doesn't like widgets with horizontal aspect ratio and forces the size accordingly.
|
||||||
|
|
||||||
|
QSize actualSize() const ;
|
||||||
private:
|
private:
|
||||||
|
static const float DEFAULT_SIZE_IN_FONT_HEIGHT ;
|
||||||
|
|
||||||
float thumbnail_w() const;
|
float thumbnail_w() const;
|
||||||
float thumbnail_h() const;
|
float thumbnail_h() const;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -106,6 +106,10 @@ void ChannelPostDelegate::zoom(bool zoom_or_unzoom)
|
||||||
mZoom = 2.0;
|
mZoom = 2.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ChannelPostDelegate::setAspectRatio(ChannelPostThumbnailView::AspectRatio r)
|
||||||
|
{
|
||||||
|
mAspectRatio = r;
|
||||||
|
}
|
||||||
void ChannelPostDelegate::paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const
|
void ChannelPostDelegate::paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const
|
||||||
{
|
{
|
||||||
// prepare
|
// prepare
|
||||||
|
|
@ -119,10 +123,13 @@ void ChannelPostDelegate::paint(QPainter * painter, const QStyleOptionViewItem &
|
||||||
|
|
||||||
if(mUseGrid || index.column()==0)
|
if(mUseGrid || index.column()==0)
|
||||||
{
|
{
|
||||||
// Draw a thumnail
|
// Draw a thumbnail
|
||||||
|
|
||||||
uint32_t flags = (mUseGrid)?(ChannelPostThumbnailView::FLAG_SHOW_TEXT):0;
|
uint32_t flags = (mUseGrid)?(ChannelPostThumbnailView::FLAG_SHOW_TEXT):0;
|
||||||
ChannelPostThumbnailView w(post,flags);
|
ChannelPostThumbnailView w(post,flags);
|
||||||
|
w.setAspectRatio(mAspectRatio);
|
||||||
|
w.updateGeometry();
|
||||||
|
w.adjustSize();
|
||||||
|
|
||||||
QPixmap pixmap(w.size());
|
QPixmap pixmap(w.size());
|
||||||
|
|
||||||
|
|
@ -133,6 +140,19 @@ void ChannelPostDelegate::paint(QPainter * painter, const QStyleOptionViewItem &
|
||||||
|
|
||||||
w.render(&pixmap,QPoint(),QRegion(),QWidget::DrawChildren );// draw the widgets, not the background
|
w.render(&pixmap,QPoint(),QRegion(),QWidget::DrawChildren );// draw the widgets, not the background
|
||||||
|
|
||||||
|
// We extract from the pixmap the part of the widget that we want. Saddly enough, Qt adds some white space
|
||||||
|
// below the widget and there is no way to control that.
|
||||||
|
|
||||||
|
pixmap = pixmap.copy(QRect(0,0,w.actualSize().width(),w.actualSize().height()));
|
||||||
|
|
||||||
|
if(index.row()==0 && index.column()==0)
|
||||||
|
{
|
||||||
|
QFile file("yourFile.png");
|
||||||
|
file.open(QIODevice::WriteOnly);
|
||||||
|
pixmap.save(&file, "PNG");
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
|
||||||
if(mUseGrid || index.column()==0)
|
if(mUseGrid || index.column()==0)
|
||||||
{
|
{
|
||||||
if(mZoom != 1.0)
|
if(mZoom != 1.0)
|
||||||
|
|
@ -143,15 +163,12 @@ void ChannelPostDelegate::paint(QPainter * painter, const QStyleOptionViewItem &
|
||||||
QPainter p(&pixmap);
|
QPainter p(&pixmap);
|
||||||
QFontMetricsF fm(option.font);
|
QFontMetricsF fm(option.font);
|
||||||
|
|
||||||
if(mUseGrid)
|
p.drawPixmap(mZoom*QPoint(0.1*fm.height(),-3.6*fm.height()),FilesDefs::getPixmapFromQtResourcePath(STAR_OVERLAY_IMAGE).scaled(mZoom*7*fm.height(),mZoom*7*fm.height(),Qt::KeepAspectRatio,Qt::SmoothTransformation));
|
||||||
p.drawPixmap(mZoom*QPoint(6.2*fm.height(),6.9*fm.height()),FilesDefs::getPixmapFromQtResourcePath(STAR_OVERLAY_IMAGE).scaled(mZoom*7*fm.height(),mZoom*7*fm.height(),Qt::KeepAspectRatio,Qt::SmoothTransformation));
|
|
||||||
else
|
|
||||||
p.drawPixmap(mZoom*QPoint(6.3*fm.height(),-3.7*fm.height()),FilesDefs::getPixmapFromQtResourcePath(STAR_OVERLAY_IMAGE).scaled(mZoom*7*fm.height(),mZoom*7*fm.height(),Qt::KeepAspectRatio,Qt::SmoothTransformation));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
painter->drawPixmap(option.rect.topLeft(),
|
painter->drawPixmap(option.rect.topLeft(),
|
||||||
pixmap.scaled(option.rect.width(),option.rect.width()*w.height()/(float)w.width(),Qt::IgnoreAspectRatio,Qt::SmoothTransformation));
|
pixmap.scaled(option.rect.width(),option.rect.width()*pixmap.height()/(float)pixmap.width(),Qt::IgnoreAspectRatio,Qt::SmoothTransformation));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -188,12 +205,25 @@ QSize ChannelPostDelegate::sizeHint(const QStyleOptionViewItem& option, const QM
|
||||||
|
|
||||||
QFontMetricsF fm(option.font);
|
QFontMetricsF fm(option.font);
|
||||||
|
|
||||||
uint32_t size_diff = mUseGrid?0:(2*fm.height());
|
RsGxsChannelPost post = index.data(Qt::UserRole).value<RsGxsChannelPost>() ;
|
||||||
|
uint32_t flags = (mUseGrid)?(ChannelPostThumbnailView::FLAG_SHOW_TEXT):0;
|
||||||
|
|
||||||
|
ChannelPostThumbnailView w(post,flags);
|
||||||
|
w.setAspectRatio(mAspectRatio);
|
||||||
|
w.updateGeometry();
|
||||||
|
w.adjustSize();
|
||||||
|
|
||||||
|
//std::cerr << "w.size(): " << w.width() << " x " << w.height() << ". Actual size: " << w.actualSize().width() << " x " << w.actualSize().height() << std::endl;
|
||||||
|
|
||||||
|
float aspect_ratio = w.actualSize().height()/(float)w.actualSize().width();
|
||||||
|
|
||||||
|
float cell_width = mZoom*COLUMN_SIZE_FONT_FACTOR_W*fm.height();
|
||||||
|
float cell_height = mZoom*COLUMN_SIZE_FONT_FACTOR_W*fm.height()*aspect_ratio;
|
||||||
|
|
||||||
if(mUseGrid || index.column()==0)
|
if(mUseGrid || index.column()==0)
|
||||||
return QSize(mZoom*COLUMN_SIZE_FONT_FACTOR_W*fm.height(),mZoom*COLUMN_SIZE_FONT_FACTOR_H*fm.height()-size_diff);
|
return QSize(cell_width,cell_height);
|
||||||
else
|
else
|
||||||
return QSize(option.rect.width()-mZoom*COLUMN_SIZE_FONT_FACTOR_W*fm.height(),mZoom*COLUMN_SIZE_FONT_FACTOR_H*fm.height()-size_diff);
|
return QSize(option.rect.width()-cell_width,cell_height);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChannelPostDelegate::setWidgetGrid(bool use_grid)
|
void ChannelPostDelegate::setWidgetGrid(bool use_grid)
|
||||||
|
|
@ -305,6 +335,8 @@ GxsChannelPostsWidgetWithModel::GxsChannelPostsWidgetWithModel(const RsGxsGroupI
|
||||||
ui->postsTree->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);// more beautiful if we scroll at pixel level
|
ui->postsTree->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);// more beautiful if we scroll at pixel level
|
||||||
ui->postsTree->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
|
ui->postsTree->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
|
||||||
|
|
||||||
|
mChannelPostsDelegate->setAspectRatio(ChannelPostThumbnailView::ASPECT_RATIO_16_9);
|
||||||
|
|
||||||
connect(ui->postsTree,SIGNAL(zoomRequested(bool)),this,SLOT(updateZoomFactor(bool)));
|
connect(ui->postsTree,SIGNAL(zoomRequested(bool)),this,SLOT(updateZoomFactor(bool)));
|
||||||
|
|
||||||
ui->channelPostFiles_TV->setModel(mChannelPostFilesModel = new RsGxsChannelPostFilesModel(this));
|
ui->channelPostFiles_TV->setModel(mChannelPostFilesModel = new RsGxsChannelPostFilesModel(this));
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,8 @@
|
||||||
#include "gui/gxs/GxsMessageFramePostWidget.h"
|
#include "gui/gxs/GxsMessageFramePostWidget.h"
|
||||||
#include "gui/feeds/FeedHolder.h"
|
#include "gui/feeds/FeedHolder.h"
|
||||||
|
|
||||||
|
#include "GxsChannelPostThumbnail.h"
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class GxsChannelPostsWidgetWithModel;
|
class GxsChannelPostsWidgetWithModel;
|
||||||
}
|
}
|
||||||
|
|
@ -69,6 +71,7 @@ class ChannelPostDelegate: public QAbstractItemDelegate
|
||||||
int cellSize(int col, const QFont& font, uint32_t parent_width) const;
|
int cellSize(int col, const QFont& font, uint32_t parent_width) const;
|
||||||
void zoom(bool zoom_or_unzoom) ;
|
void zoom(bool zoom_or_unzoom) ;
|
||||||
void setWidgetGrid(bool use_grid) ;
|
void setWidgetGrid(bool use_grid) ;
|
||||||
|
void setAspectRatio(ChannelPostThumbnailView::AspectRatio r) ;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr float IMAGE_MARGIN_FACTOR = 1.0;
|
static constexpr float IMAGE_MARGIN_FACTOR = 1.0;
|
||||||
|
|
@ -78,6 +81,7 @@ class ChannelPostDelegate: public QAbstractItemDelegate
|
||||||
|
|
||||||
float mZoom; // zoom factor for the whole thumbnail
|
float mZoom; // zoom factor for the whole thumbnail
|
||||||
bool mUseGrid; // wether we use the grid widget or the list widget
|
bool mUseGrid; // wether we use the grid widget or the list widget
|
||||||
|
ChannelPostThumbnailView::AspectRatio mAspectRatio;
|
||||||
};
|
};
|
||||||
|
|
||||||
class GxsChannelPostsWidgetWithModel: public GxsMessageFrameWidget
|
class GxsChannelPostsWidgetWithModel: public GxsMessageFrameWidget
|
||||||
|
|
|
||||||
|
|
@ -181,7 +181,7 @@
|
||||||
<item>
|
<item>
|
||||||
<widget class="QTabWidget" name="channel_TW">
|
<widget class="QTabWidget" name="channel_TW">
|
||||||
<property name="currentIndex">
|
<property name="currentIndex">
|
||||||
<number>0</number>
|
<number>1</number>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="tab_3">
|
<widget class="QWidget" name="tab_3">
|
||||||
<attribute name="title">
|
<attribute name="title">
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue