UI/Qt: Add tab hover previews
Show a delayed preview popup when hovering background tabs. Build the thumbnail from the cached front or backup WebContent bitmap so chrome does not need a fresh screenshot request or WebContent repaint on hover. Tie the popup to the tab hover lifecycle and hide it on current-tab hovers, tab presses, drags, layout changes, and tab strip exits.
This commit is contained in:
parent
9e2a820884
commit
7b6e94a445
4 changed files with 344 additions and 0 deletions
301
UI/Qt/TabBar.cpp
301
UI/Qt/TabBar.cpp
|
|
@ -16,6 +16,7 @@
|
|||
# include <UI/Qt/MacWindow.h>
|
||||
#endif
|
||||
#include <UI/Qt/Menu.h>
|
||||
#include <UI/Qt/StringUtils.h>
|
||||
#include <UI/Qt/Tab.h>
|
||||
#include <UI/Qt/TabBar.h>
|
||||
#include <UI/Qt/WindowControlButton.h>
|
||||
|
|
@ -31,7 +32,11 @@
|
|||
#include <QEasingCurve>
|
||||
#include <QEvent>
|
||||
#include <QFontMetrics>
|
||||
#include <QFrame>
|
||||
#include <QGraphicsDropShadowEffect>
|
||||
#include <QHBoxLayout>
|
||||
#include <QHelpEvent>
|
||||
#include <QLabel>
|
||||
#include <QLayoutItem>
|
||||
#include <QLinearGradient>
|
||||
#include <QMimeData>
|
||||
|
|
@ -40,9 +45,11 @@
|
|||
#include <QPainter>
|
||||
#include <QPainterPath>
|
||||
#include <QPixmap>
|
||||
#include <QScreen>
|
||||
#include <QStyle>
|
||||
#include <QTimer>
|
||||
#include <QToolButton>
|
||||
#include <QToolTip>
|
||||
#include <QVBoxLayout>
|
||||
#include <QVariant>
|
||||
#include <QVariantAnimation>
|
||||
|
|
@ -71,6 +78,11 @@ static constexpr int TAB_CARD_SHAPE_VERTICAL_INSET = 3;
|
|||
static constexpr int HORIZONTAL_NEW_TAB_BUTTON_SHAPE_SIZE = 32;
|
||||
static constexpr int TAB_CONTENT_HORIZONTAL_INSET = 8;
|
||||
static constexpr int VERTICAL_TABS_HOVER_COLLAPSE_POLL_INTERVAL_MS = 250;
|
||||
static constexpr int TAB_PREVIEW_HOVER_DELAY_MS = 350;
|
||||
static constexpr int TAB_PREVIEW_THUMBNAIL_WIDTH = 320;
|
||||
static constexpr int TAB_PREVIEW_THUMBNAIL_HEIGHT = 180;
|
||||
static constexpr int TAB_PREVIEW_SHADOW_MARGIN = 12;
|
||||
static constexpr int TAB_PREVIEW_CARD_GAP = 6;
|
||||
static constexpr int TAB_BUTTON_SIZE = 22;
|
||||
static constexpr int TAB_ICON_SIZE = 16;
|
||||
static constexpr int COLLAPSED_VERTICAL_TAB_BUTTON_SIZE = 16;
|
||||
|
|
@ -305,6 +317,159 @@ private:
|
|||
TabBar& m_tab_bar;
|
||||
};
|
||||
|
||||
class TabPreviewThumbnail final : public QWidget {
|
||||
public:
|
||||
explicit TabPreviewThumbnail(QWidget* parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
setFixedSize(TAB_PREVIEW_THUMBNAIL_WIDTH, TAB_PREVIEW_THUMBNAIL_HEIGHT);
|
||||
}
|
||||
|
||||
void set_colors(QColor background, QColor border)
|
||||
{
|
||||
m_background = background;
|
||||
m_border = border;
|
||||
update();
|
||||
}
|
||||
|
||||
void set_pixmap(QPixmap pixmap)
|
||||
{
|
||||
m_pixmap = AK::move(pixmap);
|
||||
update();
|
||||
}
|
||||
|
||||
private:
|
||||
virtual void paintEvent(QPaintEvent*) override
|
||||
{
|
||||
QPainter painter(this);
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
|
||||
auto outer_rect = rect();
|
||||
outer_rect.adjust(0, 0, -1, -1);
|
||||
|
||||
QPainterPath outer_path;
|
||||
outer_path.addRoundedRect(outer_rect, 7, 7);
|
||||
painter.fillPath(outer_path, m_background);
|
||||
|
||||
if (!m_pixmap.isNull()) {
|
||||
auto image_rect = rect().adjusted(1, 1, -1, -1);
|
||||
QPainterPath image_path;
|
||||
image_path.addRoundedRect(image_rect, 6, 6);
|
||||
|
||||
painter.save();
|
||||
painter.setClipPath(image_path);
|
||||
|
||||
auto x = image_rect.x() + (image_rect.width() - m_pixmap.width()) / 2;
|
||||
auto y = image_rect.y() + (image_rect.height() - m_pixmap.height()) / 2;
|
||||
painter.drawPixmap(x, y, m_pixmap);
|
||||
painter.restore();
|
||||
}
|
||||
|
||||
painter.setPen(m_border);
|
||||
painter.drawPath(outer_path);
|
||||
}
|
||||
|
||||
QColor m_background;
|
||||
QColor m_border;
|
||||
QPixmap m_pixmap;
|
||||
};
|
||||
|
||||
class TabPreviewPopup final : public QWidget {
|
||||
public:
|
||||
explicit TabPreviewPopup(QWidget* parent)
|
||||
: QWidget(parent, Qt::ToolTip | Qt::FramelessWindowHint | Qt::NoDropShadowWindowHint)
|
||||
{
|
||||
setAttribute(Qt::WA_TranslucentBackground);
|
||||
setAttribute(Qt::WA_ShowWithoutActivating);
|
||||
|
||||
auto* outer_layout = new QVBoxLayout(this);
|
||||
outer_layout->setContentsMargins(TAB_PREVIEW_SHADOW_MARGIN, TAB_PREVIEW_SHADOW_MARGIN, TAB_PREVIEW_SHADOW_MARGIN, TAB_PREVIEW_SHADOW_MARGIN);
|
||||
outer_layout->setSpacing(0);
|
||||
|
||||
m_card = new QFrame(this);
|
||||
m_card->setObjectName("LadybirdTabPreviewCard");
|
||||
|
||||
auto* shadow = new QGraphicsDropShadowEffect(m_card);
|
||||
shadow->setBlurRadius(28);
|
||||
shadow->setOffset(0, 8);
|
||||
shadow->setColor(QColor(0, 0, 0, 92));
|
||||
m_card->setGraphicsEffect(shadow);
|
||||
|
||||
auto* card_layout = new QVBoxLayout(m_card);
|
||||
card_layout->setContentsMargins(10, 10, 10, 10);
|
||||
card_layout->setSpacing(8);
|
||||
|
||||
m_thumbnail = new TabPreviewThumbnail(m_card);
|
||||
|
||||
m_title_label = new QLabel(m_card);
|
||||
m_title_label->setObjectName("LadybirdTabPreviewTitle");
|
||||
m_title_label->setFixedWidth(TAB_PREVIEW_THUMBNAIL_WIDTH);
|
||||
m_title_label->setTextFormat(Qt::PlainText);
|
||||
|
||||
m_url_label = new QLabel(m_card);
|
||||
m_url_label->setObjectName("LadybirdTabPreviewURL");
|
||||
m_url_label->setFixedWidth(TAB_PREVIEW_THUMBNAIL_WIDTH);
|
||||
m_url_label->setTextFormat(Qt::PlainText);
|
||||
|
||||
card_layout->addWidget(m_thumbnail);
|
||||
card_layout->addWidget(m_title_label);
|
||||
card_layout->addWidget(m_url_label);
|
||||
outer_layout->addWidget(m_card);
|
||||
}
|
||||
|
||||
void set_preview(QPalette const& palette, QString title, QString url, QPixmap const& thumbnail)
|
||||
{
|
||||
update_chrome_style(palette);
|
||||
|
||||
if (title.trimmed().isEmpty())
|
||||
title = "Untitled";
|
||||
|
||||
QFontMetrics title_metrics(m_title_label->font());
|
||||
QFontMetrics url_metrics(m_url_label->font());
|
||||
|
||||
m_thumbnail->set_pixmap(thumbnail);
|
||||
m_title_label->setText(title_metrics.elidedText(title, Qt::ElideRight, TAB_PREVIEW_THUMBNAIL_WIDTH));
|
||||
m_url_label->setText(url_metrics.elidedText(url, Qt::ElideMiddle, TAB_PREVIEW_THUMBNAIL_WIDTH));
|
||||
adjustSize();
|
||||
}
|
||||
|
||||
private:
|
||||
void update_chrome_style(QPalette const& palette)
|
||||
{
|
||||
auto card_background = ChromeStyle::style_sheet_color(ChromeStyle::chrome_surface(palette));
|
||||
auto thumbnail_background = ChromeStyle::chrome_surface_recessed(palette);
|
||||
auto border_color = ChromeStyle::chrome_control_border(palette);
|
||||
auto border = ChromeStyle::style_sheet_color(border_color);
|
||||
auto text = ChromeStyle::style_sheet_color(ChromeStyle::chrome_text(palette));
|
||||
auto muted_text = ChromeStyle::style_sheet_color(ChromeStyle::chrome_muted_text(palette));
|
||||
|
||||
m_thumbnail->set_colors(thumbnail_background, border_color);
|
||||
|
||||
setStyleSheet(qformatted(R"(
|
||||
QFrame#LadybirdTabPreviewCard {{
|
||||
background: {};
|
||||
border: 1px solid {};
|
||||
border-radius: 10px;
|
||||
}}
|
||||
|
||||
QLabel#LadybirdTabPreviewTitle {{
|
||||
color: {};
|
||||
font-weight: 600;
|
||||
}}
|
||||
|
||||
QLabel#LadybirdTabPreviewURL {{
|
||||
color: {};
|
||||
}}
|
||||
)",
|
||||
card_background, border, text, muted_text));
|
||||
}
|
||||
|
||||
QFrame* m_card { nullptr };
|
||||
TabPreviewThumbnail* m_thumbnail { nullptr };
|
||||
QLabel* m_title_label { nullptr };
|
||||
QLabel* m_url_label { nullptr };
|
||||
};
|
||||
|
||||
TabBar::TabBar(TabWidget* tab_widget)
|
||||
: QTabBar(tab_widget)
|
||||
, m_tab_widget(tab_widget)
|
||||
|
|
@ -316,6 +481,13 @@ TabBar::TabBar(TabWidget* tab_widget)
|
|||
setMinimumHeight(39);
|
||||
recreate_icons();
|
||||
|
||||
m_tab_preview_timer = new QTimer(this);
|
||||
m_tab_preview_timer->setInterval(TAB_PREVIEW_HOVER_DELAY_MS);
|
||||
m_tab_preview_timer->setSingleShot(true);
|
||||
connect(m_tab_preview_timer, &QTimer::timeout, this, &TabBar::show_tab_preview);
|
||||
|
||||
m_tab_preview_popup = new TabPreviewPopup(this);
|
||||
|
||||
m_hover_animation = new QVariantAnimation(this);
|
||||
m_hover_animation->setDuration(120);
|
||||
m_hover_animation->setEasingCurve(QEasingCurve::OutCubic);
|
||||
|
|
@ -328,6 +500,7 @@ TabBar::TabBar(TabWidget* tab_widget)
|
|||
m_hover_animation_tab_index = -1;
|
||||
});
|
||||
connect(this, &QTabBar::currentChanged, this, [this](int index) {
|
||||
hide_tab_preview();
|
||||
ensure_tab_visible(index);
|
||||
update_tab_button_geometry();
|
||||
});
|
||||
|
|
@ -418,6 +591,7 @@ QSize TabBar::tabSizeHint(int index) const
|
|||
|
||||
void TabBar::resizeEvent(QResizeEvent* event)
|
||||
{
|
||||
hide_tab_preview();
|
||||
QTabBar::resizeEvent(event);
|
||||
set_vertical_scroll_offset(m_vertical_scroll_offset);
|
||||
ensure_tab_visible(currentIndex());
|
||||
|
|
@ -426,11 +600,30 @@ void TabBar::resizeEvent(QResizeEvent* event)
|
|||
|
||||
void TabBar::tabLayoutChange()
|
||||
{
|
||||
hide_tab_preview();
|
||||
QTabBar::tabLayoutChange();
|
||||
set_vertical_scroll_offset(m_vertical_scroll_offset);
|
||||
update_tab_button_geometry();
|
||||
}
|
||||
|
||||
bool TabBar::event(QEvent* event)
|
||||
{
|
||||
if (event->type() == QEvent::ToolTip) {
|
||||
auto* help_event = static_cast<QHelpEvent*>(event);
|
||||
auto hovered_tab = tab_index_at(help_event->pos());
|
||||
if (hovered_tab >= 0 && hovered_tab != currentIndex()) {
|
||||
if (auto* tab = m_tab_widget ? m_tab_widget->tab(hovered_tab) : nullptr) {
|
||||
if (tab->view().tab_preview_pixmap({ TAB_PREVIEW_THUMBNAIL_WIDTH, TAB_PREVIEW_THUMBNAIL_HEIGHT }).has_value()) {
|
||||
event->accept();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return QTabBar::event(event);
|
||||
}
|
||||
|
||||
void TabBar::paintEvent(QPaintEvent*)
|
||||
{
|
||||
QPainter painter(this);
|
||||
|
|
@ -594,6 +787,7 @@ void TabBar::dragEnterEvent(QDragEnterEvent* event)
|
|||
|
||||
void TabBar::dragLeaveEvent(QDragLeaveEvent* event)
|
||||
{
|
||||
hide_tab_preview();
|
||||
m_drop_indicator_index = -1;
|
||||
update();
|
||||
QTabBar::dragLeaveEvent(event);
|
||||
|
|
@ -618,6 +812,7 @@ void TabBar::dragMoveEvent(QDragMoveEvent* event)
|
|||
|
||||
void TabBar::dropEvent(QDropEvent* event)
|
||||
{
|
||||
hide_tab_preview();
|
||||
if (!m_tab_widget || !s_active_tab_drag_source || !event->mimeData()->hasFormat(LADYBIRD_TAB_MIME_TYPE)) {
|
||||
event->ignore();
|
||||
return;
|
||||
|
|
@ -655,6 +850,7 @@ bool TabBar::eventFilter(QObject* watched, QEvent* event)
|
|||
|
||||
void TabBar::mousePressEvent(QMouseEvent* event)
|
||||
{
|
||||
hide_tab_preview();
|
||||
auto pressed_tab = tab_index_at(event->pos());
|
||||
m_pressed_tab = (m_tab_widget && pressed_tab >= 0) ? m_tab_widget->tab(pressed_tab) : nullptr;
|
||||
|
||||
|
|
@ -714,6 +910,7 @@ void TabBar::mouseMoveEvent(QMouseEvent* event)
|
|||
|
||||
void TabBar::leaveEvent(QEvent* event)
|
||||
{
|
||||
hide_tab_preview();
|
||||
set_hovered_tab_index(-1);
|
||||
QTabBar::leaveEvent(event);
|
||||
}
|
||||
|
|
@ -828,6 +1025,8 @@ QPixmap TabBar::render_tab_drag_pixmap(int index) const
|
|||
|
||||
void TabBar::start_tab_drag(int index)
|
||||
{
|
||||
hide_tab_preview();
|
||||
|
||||
if (!m_tab_widget)
|
||||
return;
|
||||
|
||||
|
|
@ -892,6 +1091,107 @@ void TabBar::start_hover_animation(int tab_index, qreal target_progress)
|
|||
m_hover_animation->start();
|
||||
}
|
||||
|
||||
void TabBar::schedule_tab_preview(int index)
|
||||
{
|
||||
if (!m_tab_preview_timer || !m_tab_preview_popup)
|
||||
return;
|
||||
|
||||
if (!m_tab_widget || index < 0 || index == currentIndex() || index >= count() || m_pressed_tab) {
|
||||
hide_tab_preview();
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_tab_preview_index == index && m_tab_preview_popup->isVisible())
|
||||
return;
|
||||
|
||||
m_tab_preview_index = index;
|
||||
m_tab_preview_popup->hide();
|
||||
QToolTip::hideText();
|
||||
m_tab_preview_timer->start();
|
||||
}
|
||||
|
||||
void TabBar::show_tab_preview()
|
||||
{
|
||||
if (!m_tab_widget || !m_tab_preview_popup)
|
||||
return;
|
||||
|
||||
auto index = m_tab_preview_index;
|
||||
if (index < 0 || index != m_hovered_tab_index || index == currentIndex() || index >= count()) {
|
||||
hide_tab_preview();
|
||||
return;
|
||||
}
|
||||
|
||||
auto* tab = m_tab_widget->tab(index);
|
||||
if (!tab) {
|
||||
hide_tab_preview();
|
||||
return;
|
||||
}
|
||||
|
||||
auto thumbnail = tab->view().tab_preview_pixmap({ TAB_PREVIEW_THUMBNAIL_WIDTH, TAB_PREVIEW_THUMBNAIL_HEIGHT });
|
||||
if (!thumbnail.has_value()) {
|
||||
hide_tab_preview();
|
||||
return;
|
||||
}
|
||||
|
||||
m_tab_preview_popup->set_preview(palette(), tab->title(), qstring_from_ak_string(tab->view().url().serialize()), *thumbnail);
|
||||
m_tab_preview_popup->move(tab_preview_position_for(index, m_tab_preview_popup->sizeHint()));
|
||||
m_tab_preview_popup->show();
|
||||
m_tab_preview_popup->raise();
|
||||
}
|
||||
|
||||
void TabBar::hide_tab_preview()
|
||||
{
|
||||
if (m_tab_preview_timer)
|
||||
m_tab_preview_timer->stop();
|
||||
|
||||
m_tab_preview_index = -1;
|
||||
|
||||
if (m_tab_preview_popup)
|
||||
m_tab_preview_popup->hide();
|
||||
}
|
||||
|
||||
QPoint TabBar::tab_preview_position_for(int index, QSize const& popup_size) const
|
||||
{
|
||||
auto tab_rect = visual_tab_rect(index);
|
||||
auto screen = QGuiApplication::screenAt(mapToGlobal(tab_rect.center()));
|
||||
if (!screen)
|
||||
screen = window()->screen();
|
||||
if (!screen)
|
||||
screen = QGuiApplication::primaryScreen();
|
||||
auto available_geometry = screen ? screen->availableGeometry() : QRect {};
|
||||
|
||||
QPoint position;
|
||||
if (tab_layout() == TabLayout::Horizontal) {
|
||||
position = mapToGlobal(QPoint {
|
||||
tab_rect.center().x() - popup_size.width() / 2,
|
||||
tab_rect.bottom() + TAB_PREVIEW_CARD_GAP - TAB_PREVIEW_SHADOW_MARGIN,
|
||||
});
|
||||
|
||||
if (position.y() + popup_size.height() > available_geometry.bottom())
|
||||
position.setY(mapToGlobal(QPoint { 0, tab_rect.top() }).y() - popup_size.height() - TAB_PREVIEW_CARD_GAP + TAB_PREVIEW_SHADOW_MARGIN);
|
||||
} else {
|
||||
position = mapToGlobal(QPoint {
|
||||
tab_rect.right() + TAB_PREVIEW_CARD_GAP - TAB_PREVIEW_SHADOW_MARGIN,
|
||||
tab_rect.center().y() - popup_size.height() / 2,
|
||||
});
|
||||
|
||||
if (position.x() + popup_size.width() > available_geometry.right())
|
||||
position.setX(mapToGlobal(QPoint { tab_rect.left(), 0 }).x() - popup_size.width() - TAB_PREVIEW_CARD_GAP + TAB_PREVIEW_SHADOW_MARGIN);
|
||||
}
|
||||
|
||||
auto minimum_x = available_geometry.left() + TAB_PREVIEW_CARD_GAP - TAB_PREVIEW_SHADOW_MARGIN;
|
||||
auto maximum_x = available_geometry.right() - popup_size.width() - TAB_PREVIEW_CARD_GAP + TAB_PREVIEW_SHADOW_MARGIN;
|
||||
if (minimum_x <= maximum_x)
|
||||
position.setX(clamp(position.x(), minimum_x, maximum_x));
|
||||
|
||||
auto minimum_y = available_geometry.top() + TAB_PREVIEW_CARD_GAP - TAB_PREVIEW_SHADOW_MARGIN;
|
||||
auto maximum_y = available_geometry.bottom() - popup_size.height() - TAB_PREVIEW_CARD_GAP + TAB_PREVIEW_SHADOW_MARGIN;
|
||||
if (minimum_y <= maximum_y)
|
||||
position.setY(clamp(position.y(), minimum_y, maximum_y));
|
||||
|
||||
return position;
|
||||
}
|
||||
|
||||
QRect TabBar::visual_tab_rect(int index) const
|
||||
{
|
||||
if (tab_layout() == TabLayout::Horizontal)
|
||||
|
|
@ -971,6 +1271,7 @@ void TabBar::set_hovered_tab_index(int index)
|
|||
m_hovered_tab_index = index;
|
||||
update_tab_button_geometry();
|
||||
start_hover_animation(index >= 0 ? index : previous_hovered_tab, index >= 0 ? 1.0 : 0.0);
|
||||
schedule_tab_preview(index);
|
||||
update();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ class QWheelEvent;
|
|||
namespace Ladybird {
|
||||
|
||||
class Tab;
|
||||
class TabPreviewPopup;
|
||||
class TabWidget;
|
||||
|
||||
enum class TabLayout : u8 {
|
||||
|
|
@ -66,6 +67,7 @@ private:
|
|||
virtual void resizeEvent(QResizeEvent*) override;
|
||||
virtual void tabLayoutChange() override;
|
||||
|
||||
virtual bool event(QEvent*) override;
|
||||
virtual void paintEvent(QPaintEvent*) override;
|
||||
virtual void contextMenuEvent(QContextMenuEvent* event) override;
|
||||
virtual void dragEnterEvent(QDragEnterEvent*) override;
|
||||
|
|
@ -87,6 +89,10 @@ private:
|
|||
bool start_window_move();
|
||||
void start_tab_drag(int index);
|
||||
void start_hover_animation(int tab_index, qreal target_progress);
|
||||
void schedule_tab_preview(int index);
|
||||
void show_tab_preview();
|
||||
void hide_tab_preview();
|
||||
QPoint tab_preview_position_for(int index, QSize const& popup_size) const;
|
||||
|
||||
QRect visual_tab_rect(int index) const;
|
||||
int tab_index_at(QPoint const&) const;
|
||||
|
|
@ -113,6 +119,9 @@ private:
|
|||
QPointer<Tab> m_pressed_tab;
|
||||
QPoint m_position_in_selected_tab_while_dragging;
|
||||
QPoint m_drag_start_position;
|
||||
QTimer* m_tab_preview_timer { nullptr };
|
||||
TabPreviewPopup* m_tab_preview_popup { nullptr };
|
||||
int m_tab_preview_index { -1 };
|
||||
};
|
||||
|
||||
class TabWidget final : public QWidget {
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@
|
|||
#include <QPaintEvent>
|
||||
#include <QPainter>
|
||||
#include <QPalette>
|
||||
#include <QPixmap>
|
||||
#include <QScrollBar>
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)
|
||||
# include <QStyleHints>
|
||||
|
|
@ -707,6 +708,37 @@ void WebContentView::paintEvent(QPaintEvent*)
|
|||
}
|
||||
#endif
|
||||
|
||||
Optional<QPixmap> WebContentView::tab_preview_pixmap(QSize const& maximum_size) const
|
||||
{
|
||||
auto paintable = current_paintable();
|
||||
if (!paintable.has_value())
|
||||
return {};
|
||||
|
||||
auto const* bitmap = paintable->shared_image_buffer->bitmap().ptr();
|
||||
if (!bitmap)
|
||||
return {};
|
||||
|
||||
auto width = min(bitmap->width(), paintable->bitmap_size.width());
|
||||
auto height = min(bitmap->height(), paintable->bitmap_size.height());
|
||||
if (width <= 0 || height <= 0 || maximum_size.isEmpty())
|
||||
return {};
|
||||
|
||||
QImage image(bitmap->scanline_u8(0), bitmap->width(), bitmap->height(), bitmap->pitch(), QImage::Format_RGB32);
|
||||
auto snapshot = image.copy(0, 0, width, height);
|
||||
if (snapshot.isNull())
|
||||
return {};
|
||||
|
||||
auto preview_size = snapshot.size().scaled(maximum_size, Qt::KeepAspectRatio);
|
||||
if (preview_size.isEmpty())
|
||||
return {};
|
||||
|
||||
auto preview = QPixmap::fromImage(snapshot).scaled(preview_size, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
if (preview.isNull())
|
||||
return {};
|
||||
|
||||
return preview;
|
||||
}
|
||||
|
||||
void WebContentView::resizeEvent(QResizeEvent* event)
|
||||
{
|
||||
WebContentViewBase::resizeEvent(event);
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
#include <LibWebView/ViewImplementation.h>
|
||||
|
||||
#include <QMenu>
|
||||
#include <QPixmap>
|
||||
#include <QTimer>
|
||||
#include <QUrl>
|
||||
|
||||
|
|
@ -87,6 +88,7 @@ public:
|
|||
Dark,
|
||||
};
|
||||
void update_palette(PaletteMode = PaletteMode::Default);
|
||||
Optional<QPixmap> tab_preview_pixmap(QSize const& maximum_size) const;
|
||||
|
||||
using ViewImplementation::client;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue