RetroShare/retroshare-gui/src/gui/gxschannels/GxsChannelPostThumbnail.cpp

207 lines
6.7 KiB
C++
Raw Normal View History

2020-08-26 16:29:49 -04:00
/*******************************************************************************
* retroshare-gui/src/gui/gxschannels/GxsChannelPostThumbnail.cpp *
* *
* Copyright 2020 by Retroshare Team <retroshare.project@gmail.com> *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Affero General Public License for more details. *
* *
* You should have received a copy of the GNU Affero General Public License *
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
* *
*******************************************************************************/
#include <QWheelEvent>
2020-08-27 12:53:39 -04:00
#include <QDateTime>
2020-08-26 16:29:49 -04:00
#include "gui/common/FilesDefs.h"
#include "gui/gxschannels/GxsChannelPostThumbnail.h"
2020-08-27 12:53:39 -04:00
ChannelPostThumbnailView::ChannelPostThumbnailView(const RsGxsChannelPost& post,uint32_t flags,QWidget *parent)
: QWidget(parent),mFlags(flags)
2020-08-26 16:29:49 -04:00
{
// now fill the data
2020-08-27 12:53:39 -04:00
init(post);
2020-08-26 16:29:49 -04:00
}
2020-08-27 12:53:39 -04:00
ChannelPostThumbnailView::ChannelPostThumbnailView(QWidget *parent,uint32_t flags)
: QWidget(parent),mFlags(flags)
2020-08-26 16:29:49 -04:00
{
2020-08-27 12:53:39 -04:00
init(RsGxsChannelPost());
2020-08-26 16:29:49 -04:00
}
ChannelPostThumbnailView::~ChannelPostThumbnailView()
{
2020-08-27 12:53:39 -04:00
delete mPostImage;
2020-08-26 16:29:49 -04:00
}
2020-08-27 12:53:39 -04:00
void ChannelPostThumbnailView::init(const RsGxsChannelPost& post)
2020-08-26 16:29:49 -04:00
{
2020-08-27 12:53:39 -04:00
QString msg = QString::fromUtf8(post.mMeta.mMsgName.c_str());
bool is_msg_new = IS_MSG_UNREAD(post.mMeta.mMsgStatus) || IS_MSG_NEW(post.mMeta.mMsgStatus);
QPixmap thumbnail;
if(post.mThumbnail.mSize > 0)
GxsIdDetails::loadPixmapFromData(post.mThumbnail.mData, post.mThumbnail.mSize, thumbnail,GxsIdDetails::ORIGINAL);
else if(post.mMeta.mPublishTs > 0) // this is for testing that the post is not an empty post (happens at the end of the last row)
thumbnail = FilesDefs::getPixmapFromQtResourcePath(CHAN_DEFAULT_IMAGE);
mPostImage = new ZoomableLabel(this);
mPostImage->setEnableZoom(mFlags & FLAG_ALLOW_PAN);
mPostImage->setScaledContents(true);
mPostImage->setPicture(thumbnail);
if(mFlags & FLAG_ALLOW_PAN)
mPostImage->setToolTip(tr("Use mouse to center and zoom into the image"));
2020-08-27 16:04:09 -04:00
QVBoxLayout *layout = new QVBoxLayout(this);
2020-08-27 12:53:39 -04:00
2020-08-27 16:04:09 -04:00
layout->addWidget(mPostImage);
2020-08-26 16:29:49 -04:00
2020-08-27 16:04:09 -04:00
setSizePolicy(QSizePolicy::Maximum,QSizePolicy::Maximum);
2020-08-26 16:29:49 -04:00
2020-08-27 16:04:09 -04:00
QFontMetricsF fm(font());
int W = THUMBNAIL_OVERSAMPLE_FACTOR * THUMBNAIL_W * fm.height() ;
int H = THUMBNAIL_OVERSAMPLE_FACTOR * THUMBNAIL_H * fm.height() ;
2020-08-27 12:53:39 -04:00
2020-08-27 16:04:09 -04:00
mPostImage->setFixedSize(W,H);
2020-08-27 12:53:39 -04:00
2020-08-27 16:04:09 -04:00
if(mFlags & FLAG_SHOW_TEXT)
2020-08-27 12:53:39 -04:00
{
2020-08-27 16:04:09 -04:00
mPostTitle = new QLabel(this);
2020-08-27 12:53:39 -04:00
layout->addWidget(mPostTitle);
QString ss = (msg.length() > 30)? (msg.left(30)+"..."):msg;
2020-08-26 16:29:49 -04:00
2020-08-27 12:53:39 -04:00
mPostTitle->setText(ss);
2020-08-26 16:29:49 -04:00
2020-08-27 12:53:39 -04:00
QFont font = mPostTitle->font();
2020-08-26 16:29:49 -04:00
if(is_msg_new)
{
2020-08-27 12:53:39 -04:00
font.setBold(true);
mPostTitle->setFont(font);
2020-08-26 16:29:49 -04:00
}
2020-08-27 12:53:39 -04:00
mPostTitle->setMaximumWidth(W);
mPostTitle->setWordWrap(true);
}
2020-08-26 16:29:49 -04:00
2020-08-27 16:04:09 -04:00
setLayout(layout);
2020-08-27 12:53:39 -04:00
adjustSize();
update();
2020-08-26 16:29:49 -04:00
}
void ZoomableLabel::mouseMoveEvent(QMouseEvent *me)
{
2020-08-27 12:53:39 -04:00
if(!mZoomEnabled)
return;
2020-08-26 16:29:49 -04:00
float new_center_x = mCenterX - (me->x() - mLastX);
float new_center_y = mCenterY - (me->y() - mLastY);
mLastX = me->x();
mLastY = me->y();
if(new_center_x - 0.5 * width()*mZoomFactor < 0) return;
if(new_center_y - 0.5 *height()*mZoomFactor < 0) return;
if(new_center_x + 0.5 * width()*mZoomFactor >= mFullImage.width()) return;
if(new_center_y + 0.5 *height()*mZoomFactor >=mFullImage.height()) return;
mCenterX = new_center_x;
mCenterY = new_center_y;
updateView();
}
void ZoomableLabel::mousePressEvent(QMouseEvent *me)
{
mMoving = true;
mLastX = me->x();
mLastY = me->y();
}
void ZoomableLabel::mouseReleaseEvent(QMouseEvent *)
{
mMoving = false;
}
void ZoomableLabel::wheelEvent(QWheelEvent *me)
{
2020-08-27 12:53:39 -04:00
if(!mZoomEnabled)
return;
2020-08-26 16:29:49 -04:00
float new_zoom_factor = (me->delta() > 0)?(mZoomFactor*1.05):(mZoomFactor/1.05);
float new_center_x = mCenterX;
float new_center_y = mCenterY;
// Try to find centerX and centerY so that the crop does not overlap the original image
float min_x = 0.5 * width()*new_zoom_factor;
float max_x = mFullImage.width() - 0.5 * width()*new_zoom_factor;
float min_y = 0.5 * height()*new_zoom_factor;
float max_y = mFullImage.height() - 0.5 * height()*new_zoom_factor;
if(min_x >= max_x) return;
if(min_y >= max_y) return;
if(new_center_x < min_x) new_center_x = min_x;
if(new_center_y < min_y) new_center_y = min_y;
if(new_center_x > max_x) new_center_x = max_x;
if(new_center_y > max_y) new_center_y = max_y;
mZoomFactor = new_zoom_factor;
mCenterX = new_center_x;
mCenterY = new_center_y;
updateView();
}
QPixmap ZoomableLabel::extractCroppedScaledPicture() const
{
QRect rect(mCenterX - 0.5 * width()*mZoomFactor, mCenterY - 0.5 * height()*mZoomFactor, width()*mZoomFactor, height()*mZoomFactor);
QPixmap pix = mFullImage.copy(rect).scaledToHeight(height(),Qt::SmoothTransformation);
return pix;
}
void ZoomableLabel::setPicture(const QPixmap& pix)
{
mFullImage = pix;
mCenterX = pix.width()/2.0;
mCenterY = pix.height()/2.0;
updateView();
}
void ZoomableLabel::resizeEvent(QResizeEvent *e)
{
QLabel::resizeEvent(e);
updateView();
}
void ZoomableLabel::updateView()
{
// The new image will be cropped from the original image, using the following rules:
// - first the cropped image size is computed
// - then center is calculated so that
// - the original center is preferred
// - if the crop overlaps the image border, the center is moved.
QRect rect(mCenterX - 0.5 * width()*mZoomFactor, mCenterY - 0.5 * height()*mZoomFactor, width()*mZoomFactor, height()*mZoomFactor);
QLabel::setPixmap(mFullImage.copy(rect));
}