mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-23 14:19:46 -06:00
Move DolphinQt2 to DolphinQt
This commit is contained in:
22
Source/Core/DolphinQt/QtUtils/ActionHelper.h
Normal file
22
Source/Core/DolphinQt/QtUtils/ActionHelper.h
Normal file
@ -0,0 +1,22 @@
|
||||
// Copyright 2017 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QAction>
|
||||
#include <QKeySequence>
|
||||
#include <QString>
|
||||
|
||||
// Since we have to support Qt < 5.6, we need our own implementation of addAction(QString&
|
||||
// text,QObject*,PointerToMemberFunction);
|
||||
template <typename ParentClass, typename RecieverClass, typename Func>
|
||||
QAction* AddAction(ParentClass* parent, const QString& text, const RecieverClass* receiver,
|
||||
Func slot, const QKeySequence& shortcut = 0)
|
||||
{
|
||||
QAction* action = parent->addAction(text);
|
||||
action->setShortcut(shortcut);
|
||||
action->connect(action, &QAction::triggered, receiver, slot);
|
||||
|
||||
return action;
|
||||
}
|
45
Source/Core/DolphinQt/QtUtils/AspectRatioWidget.cpp
Normal file
45
Source/Core/DolphinQt/QtUtils/AspectRatioWidget.cpp
Normal file
@ -0,0 +1,45 @@
|
||||
// Copyright 2018 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
// Based on:
|
||||
// https://stackoverflow.com/questions/30005540/keeping-the-aspect-ratio-of-a-sub-classed-qwidget-during-resize
|
||||
|
||||
#include "DolphinQt/QtUtils/AspectRatioWidget.h"
|
||||
|
||||
#include <QBoxLayout>
|
||||
#include <QResizeEvent>
|
||||
|
||||
AspectRatioWidget::AspectRatioWidget(QWidget* widget, float width, float height, QWidget* parent)
|
||||
: QWidget(parent), m_ar_width(width), m_ar_height(height)
|
||||
{
|
||||
m_layout = new QBoxLayout(QBoxLayout::LeftToRight, this);
|
||||
|
||||
// add spacer, then your widget, then spacer
|
||||
m_layout->addItem(new QSpacerItem(0, 0));
|
||||
m_layout->addWidget(widget);
|
||||
m_layout->addItem(new QSpacerItem(0, 0));
|
||||
}
|
||||
|
||||
void AspectRatioWidget::resizeEvent(QResizeEvent* event)
|
||||
{
|
||||
float aspect_ratio = static_cast<float>(event->size().width()) / event->size().height();
|
||||
int widget_stretch, outer_stretch;
|
||||
|
||||
if (aspect_ratio > (m_ar_width / m_ar_height)) // too wide
|
||||
{
|
||||
m_layout->setDirection(QBoxLayout::LeftToRight);
|
||||
widget_stretch = height() * (m_ar_width / m_ar_height); // i.e., my width
|
||||
outer_stretch = (width() - widget_stretch) / 2 + 0.5;
|
||||
}
|
||||
else // too tall
|
||||
{
|
||||
m_layout->setDirection(QBoxLayout::TopToBottom);
|
||||
widget_stretch = width() * (m_ar_height / m_ar_width); // i.e., my height
|
||||
outer_stretch = (height() - widget_stretch) / 2 + 0.5;
|
||||
}
|
||||
|
||||
m_layout->setStretch(0, outer_stretch);
|
||||
m_layout->setStretch(1, widget_stretch);
|
||||
m_layout->setStretch(2, outer_stretch);
|
||||
}
|
22
Source/Core/DolphinQt/QtUtils/AspectRatioWidget.h
Normal file
22
Source/Core/DolphinQt/QtUtils/AspectRatioWidget.h
Normal file
@ -0,0 +1,22 @@
|
||||
// Copyright 2018 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class QBoxLayout;
|
||||
|
||||
class AspectRatioWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AspectRatioWidget(QWidget* widget, float width, float height, QWidget* parent = nullptr);
|
||||
void resizeEvent(QResizeEvent* event) override;
|
||||
|
||||
private:
|
||||
QBoxLayout* m_layout;
|
||||
float m_ar_width;
|
||||
float m_ar_height;
|
||||
};
|
21
Source/Core/DolphinQt/QtUtils/BlockUserInputFilter.cpp
Normal file
21
Source/Core/DolphinQt/QtUtils/BlockUserInputFilter.cpp
Normal file
@ -0,0 +1,21 @@
|
||||
// Copyright 2017 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "DolphinQt/QtUtils/BlockUserInputFilter.h"
|
||||
|
||||
#include <QEvent>
|
||||
|
||||
BlockUserInputFilter* BlockUserInputFilter::Instance()
|
||||
{
|
||||
static BlockUserInputFilter s_block_user_input_filter;
|
||||
return &s_block_user_input_filter;
|
||||
}
|
||||
|
||||
bool BlockUserInputFilter::eventFilter(QObject* object, QEvent* event)
|
||||
{
|
||||
const QEvent::Type event_type = event->type();
|
||||
return event_type == QEvent::KeyPress || event_type == QEvent::KeyRelease ||
|
||||
event_type == QEvent::MouseButtonPress || event_type == QEvent::MouseButtonRelease ||
|
||||
event_type == QEvent::MouseButtonDblClick;
|
||||
}
|
20
Source/Core/DolphinQt/QtUtils/BlockUserInputFilter.h
Normal file
20
Source/Core/DolphinQt/QtUtils/BlockUserInputFilter.h
Normal file
@ -0,0 +1,20 @@
|
||||
// Copyright 2017 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
|
||||
class QEvent;
|
||||
|
||||
class BlockUserInputFilter : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
static BlockUserInputFilter* Instance();
|
||||
|
||||
private:
|
||||
BlockUserInputFilter() = default;
|
||||
bool eventFilter(QObject* object, QEvent* event) override;
|
||||
};
|
15
Source/Core/DolphinQt/QtUtils/DoubleClickEventFilter.cpp
Normal file
15
Source/Core/DolphinQt/QtUtils/DoubleClickEventFilter.cpp
Normal file
@ -0,0 +1,15 @@
|
||||
// Copyright 2017 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <QEvent>
|
||||
|
||||
#include "DolphinQt/QtUtils/DoubleClickEventFilter.h"
|
||||
|
||||
bool DoubleClickEventFilter::eventFilter(QObject* object, QEvent* event)
|
||||
{
|
||||
if (event->type() == QEvent::MouseButtonDblClick)
|
||||
emit doubleClicked();
|
||||
|
||||
return false;
|
||||
}
|
17
Source/Core/DolphinQt/QtUtils/DoubleClickEventFilter.h
Normal file
17
Source/Core/DolphinQt/QtUtils/DoubleClickEventFilter.h
Normal file
@ -0,0 +1,17 @@
|
||||
// Copyright 2017 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
|
||||
class DoubleClickEventFilter : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
signals:
|
||||
void doubleClicked();
|
||||
|
||||
private:
|
||||
bool eventFilter(QObject* object, QEvent* event) override;
|
||||
};
|
40
Source/Core/DolphinQt/QtUtils/ElidedButton.cpp
Normal file
40
Source/Core/DolphinQt/QtUtils/ElidedButton.cpp
Normal file
@ -0,0 +1,40 @@
|
||||
// Copyright 2017 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "DolphinQt/QtUtils/ElidedButton.h"
|
||||
|
||||
#include <QFontMetrics>
|
||||
#include <QStyleOptionButton>
|
||||
#include <QStylePainter>
|
||||
|
||||
ElidedButton::ElidedButton(const QString& text, Qt::TextElideMode elide_mode)
|
||||
: QPushButton(text, nullptr), m_elide_mode{elide_mode}
|
||||
{
|
||||
}
|
||||
|
||||
Qt::TextElideMode ElidedButton::elideMode() const
|
||||
{
|
||||
return m_elide_mode;
|
||||
}
|
||||
|
||||
void ElidedButton::setElideMode(Qt::TextElideMode elide_mode)
|
||||
{
|
||||
if (elide_mode == m_elide_mode)
|
||||
return;
|
||||
|
||||
m_elide_mode = elide_mode;
|
||||
repaint();
|
||||
}
|
||||
|
||||
void ElidedButton::paintEvent(QPaintEvent* event)
|
||||
{
|
||||
QStyleOptionButton option;
|
||||
initStyleOption(&option);
|
||||
|
||||
option.text = fontMetrics().elidedText(
|
||||
text(), m_elide_mode,
|
||||
style()->subElementRect(QStyle::SE_PushButtonContents, &option, this).width());
|
||||
|
||||
QStylePainter{this}.drawControl(QStyle::CE_PushButton, option);
|
||||
}
|
21
Source/Core/DolphinQt/QtUtils/ElidedButton.h
Normal file
21
Source/Core/DolphinQt/QtUtils/ElidedButton.h
Normal file
@ -0,0 +1,21 @@
|
||||
// Copyright 2017 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QPushButton>
|
||||
|
||||
class ElidedButton : public QPushButton
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ElidedButton(const QString& text = QStringLiteral(""),
|
||||
Qt::TextElideMode elide_mode = Qt::ElideRight);
|
||||
Qt::TextElideMode elideMode() const;
|
||||
void setElideMode(Qt::TextElideMode elide_mode);
|
||||
|
||||
private:
|
||||
void paintEvent(QPaintEvent* event) override;
|
||||
Qt::TextElideMode m_elide_mode;
|
||||
};
|
33
Source/Core/DolphinQt/QtUtils/ImageConverter.cpp
Normal file
33
Source/Core/DolphinQt/QtUtils/ImageConverter.cpp
Normal file
@ -0,0 +1,33 @@
|
||||
// Copyright 2018 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "DolphinQt/QtUtils/ImageConverter.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <QPixmap>
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "UICommon/GameFile.h"
|
||||
|
||||
QPixmap ToQPixmap(const UICommon::GameBanner& banner)
|
||||
{
|
||||
return ToQPixmap(banner.buffer, banner.width, banner.height);
|
||||
}
|
||||
|
||||
QPixmap ToQPixmap(const std::vector<u32>& buffer, int width, int height)
|
||||
{
|
||||
QImage image(width, height, QImage::Format_RGB888);
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
for (int x = 0; x < width; x++)
|
||||
{
|
||||
const u32 color = buffer[y * width + x];
|
||||
image.setPixel(
|
||||
x, y, qRgb((color & 0xFF0000) >> 16, (color & 0x00FF00) >> 8, (color & 0x0000FF) >> 0));
|
||||
}
|
||||
}
|
||||
|
||||
return QPixmap::fromImage(image);
|
||||
}
|
19
Source/Core/DolphinQt/QtUtils/ImageConverter.h
Normal file
19
Source/Core/DolphinQt/QtUtils/ImageConverter.h
Normal file
@ -0,0 +1,19 @@
|
||||
// Copyright 2018 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
|
||||
class QPixmap;
|
||||
|
||||
namespace UICommon
|
||||
{
|
||||
struct GameBanner;
|
||||
}
|
||||
|
||||
QPixmap ToQPixmap(const UICommon::GameBanner& banner);
|
||||
QPixmap ToQPixmap(const std::vector<u32>& buffer, int width, int height);
|
20
Source/Core/DolphinQt/QtUtils/QueueOnObject.h
Normal file
20
Source/Core/DolphinQt/QtUtils/QueueOnObject.h
Normal file
@ -0,0 +1,20 @@
|
||||
// Copyright 2017 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <utility>
|
||||
|
||||
// QWidget and subclasses are not thread-safe! However, Qt's signal-slot connection mechanism will
|
||||
// invoke slots/functions on the correct thread for any object. We can (ab)use this to queue up
|
||||
// arbitrary code from non-GUI threads. For more information, see:
|
||||
// https://stackoverflow.com/questions/21646467/
|
||||
|
||||
template <typename T, typename F>
|
||||
static void QueueOnObject(T* obj, F&& func)
|
||||
{
|
||||
QObject src;
|
||||
QObject::connect(&src, &QObject::destroyed, obj, std::forward<F>(func), Qt::QueuedConnection);
|
||||
}
|
77
Source/Core/DolphinQt/QtUtils/RunOnObject.h
Normal file
77
Source/Core/DolphinQt/QtUtils/RunOnObject.h
Normal file
@ -0,0 +1,77 @@
|
||||
// Copyright 2017 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QEvent>
|
||||
#include <QPointer>
|
||||
#include <QThread>
|
||||
#include <optional>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "Common/Event.h"
|
||||
#include "DolphinQt/QtUtils/QueueOnObject.h"
|
||||
|
||||
class QObject;
|
||||
|
||||
// QWidget and subclasses are not thread-safe! This helper takes arbitrary code from any thread,
|
||||
// safely runs it on the appropriate GUI thread, waits for it to finish, and returns the result.
|
||||
//
|
||||
// If the target object is destructed before the code gets to run, the QPointer will be nulled and
|
||||
// the function will return nullopt.
|
||||
|
||||
template <typename F>
|
||||
auto RunOnObject(QObject* object, F&& functor)
|
||||
{
|
||||
using OptionalResultT = std::optional<std::result_of_t<F()>>;
|
||||
|
||||
// If we queue up a functor on the current thread, it won't run until we return to the event loop,
|
||||
// which means waiting for it to finish will never complete. Instead, run it immediately.
|
||||
if (object->thread() == QThread::currentThread())
|
||||
return OptionalResultT(functor());
|
||||
|
||||
class FnInvokeEvent : public QEvent
|
||||
{
|
||||
public:
|
||||
FnInvokeEvent(F&& functor, QObject* obj, Common::Event& event, OptionalResultT& result)
|
||||
: QEvent(QEvent::None), m_func(std::move(functor)), m_obj(obj), m_event(event),
|
||||
m_result(result)
|
||||
{
|
||||
}
|
||||
|
||||
~FnInvokeEvent()
|
||||
{
|
||||
if (m_obj)
|
||||
{
|
||||
m_result = m_func();
|
||||
}
|
||||
else
|
||||
{
|
||||
// is already nullopt
|
||||
}
|
||||
m_event.Set();
|
||||
}
|
||||
|
||||
private:
|
||||
F m_func;
|
||||
QPointer<QObject> m_obj;
|
||||
Common::Event& m_event;
|
||||
OptionalResultT& m_result;
|
||||
};
|
||||
|
||||
Common::Event event{};
|
||||
OptionalResultT result = std::nullopt;
|
||||
QCoreApplication::postEvent(object,
|
||||
new FnInvokeEvent(std::forward<F>(functor), object, event, result));
|
||||
event.Wait();
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename Base, typename Type, typename Receiver>
|
||||
auto RunOnObject(Receiver* obj, Type Base::*func)
|
||||
{
|
||||
return RunOnObject(obj, [obj, func] { return (obj->*func)(); });
|
||||
}
|
55
Source/Core/DolphinQt/QtUtils/SignalDaemon.cpp
Normal file
55
Source/Core/DolphinQt/QtUtils/SignalDaemon.cpp
Normal file
@ -0,0 +1,55 @@
|
||||
// Copyright 2018 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "DolphinQt/QtUtils/SignalDaemon.h"
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <QSocketNotifier>
|
||||
|
||||
int SignalDaemon::s_sigterm_fd[2];
|
||||
|
||||
static constexpr char message[] =
|
||||
"\nA signal was received. A second signal will force Dolphin to stop.\n";
|
||||
|
||||
SignalDaemon::SignalDaemon(QObject* parent) : QObject(parent)
|
||||
{
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, s_sigterm_fd))
|
||||
qFatal("Couldn't create TERM socketpair");
|
||||
|
||||
m_term = new QSocketNotifier(s_sigterm_fd[1], QSocketNotifier::Read, this);
|
||||
connect(m_term, &QSocketNotifier::activated, this, &SignalDaemon::OnNotifierActivated);
|
||||
}
|
||||
|
||||
SignalDaemon::~SignalDaemon()
|
||||
{
|
||||
close(s_sigterm_fd[0]);
|
||||
close(s_sigterm_fd[1]);
|
||||
}
|
||||
|
||||
void SignalDaemon::OnNotifierActivated()
|
||||
{
|
||||
m_term->setEnabled(false);
|
||||
|
||||
char tmp;
|
||||
if (read(s_sigterm_fd[1], &tmp, sizeof(char)))
|
||||
{
|
||||
}
|
||||
|
||||
m_term->setEnabled(true);
|
||||
|
||||
emit InterruptReceived();
|
||||
}
|
||||
|
||||
void SignalDaemon::HandleInterrupt(int)
|
||||
{
|
||||
write(STDERR_FILENO, message, sizeof(message));
|
||||
|
||||
char a = 1;
|
||||
if (write(s_sigterm_fd[0], &a, sizeof(a)))
|
||||
{
|
||||
}
|
||||
}
|
31
Source/Core/DolphinQt/QtUtils/SignalDaemon.h
Normal file
31
Source/Core/DolphinQt/QtUtils/SignalDaemon.h
Normal file
@ -0,0 +1,31 @@
|
||||
// Copyright 2018 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
|
||||
class QSocketNotifier;
|
||||
|
||||
// Loosely based on https://doc.qt.io/qt-5.9/unix-signals.html
|
||||
class SignalDaemon : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SignalDaemon(QObject* parent);
|
||||
~SignalDaemon();
|
||||
|
||||
static void HandleInterrupt(int);
|
||||
|
||||
signals:
|
||||
void InterruptReceived();
|
||||
|
||||
private:
|
||||
void OnNotifierActivated();
|
||||
|
||||
static int s_sigterm_fd[2];
|
||||
|
||||
QSocketNotifier* m_term;
|
||||
};
|
94
Source/Core/DolphinQt/QtUtils/WinIconHelper.cpp
Normal file
94
Source/Core/DolphinQt/QtUtils/WinIconHelper.cpp
Normal file
@ -0,0 +1,94 @@
|
||||
// Copyright 2018 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "DolphinQt/QtUtils/WinIconHelper.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
// The following code is adapted from qpixmap_win.cpp (c) The Qt Company Ltd. (https://qt.io)
|
||||
// Licensed under the GNU GPL v3
|
||||
static inline BITMAPINFO GetBMI(int width, int height, bool topToBottom)
|
||||
{
|
||||
BITMAPINFO bmi = {};
|
||||
auto& bih = bmi.bmiHeader;
|
||||
|
||||
bih.biSize = sizeof(BITMAPINFOHEADER);
|
||||
bih.biWidth = width;
|
||||
bih.biHeight = topToBottom ? -height : height;
|
||||
bih.biPlanes = 1;
|
||||
bih.biBitCount = 32;
|
||||
bih.biCompression = BI_RGB;
|
||||
bih.biSizeImage = width * height * 4;
|
||||
|
||||
return bmi;
|
||||
}
|
||||
|
||||
static QPixmap PixmapFromHICON(HICON icon)
|
||||
{
|
||||
HDC screenDevice = GetDC(0);
|
||||
HDC hdc = CreateCompatibleDC(screenDevice);
|
||||
ReleaseDC(0, screenDevice);
|
||||
ICONINFO iconinfo;
|
||||
const bool result = GetIconInfo(icon, &iconinfo); // x and y Hotspot describes the icon center
|
||||
if (!result)
|
||||
{
|
||||
qErrnoWarning("QPixmap::fromWinHICON(), failed to GetIconInfo()");
|
||||
DeleteDC(hdc);
|
||||
return QPixmap();
|
||||
}
|
||||
const int w = iconinfo.xHotspot * 2;
|
||||
const int h = iconinfo.yHotspot * 2;
|
||||
BITMAPINFO bitmapInfo = GetBMI(w, h, false);
|
||||
DWORD* bits;
|
||||
HBITMAP winBitmap = CreateDIBSection(hdc, &bitmapInfo, DIB_RGB_COLORS, (VOID**)&bits, NULL, 0);
|
||||
HGDIOBJ oldhdc = reinterpret_cast<HBITMAP>(SelectObject(hdc, winBitmap));
|
||||
DrawIconEx(hdc, 0, 0, icon, iconinfo.xHotspot * 2, iconinfo.yHotspot * 2, 0, 0, DI_NORMAL);
|
||||
|
||||
QImage image(w, h, QImage::Format_ARGB32_Premultiplied);
|
||||
if (image.isNull())
|
||||
return {};
|
||||
|
||||
BITMAPINFO bmi = GetBMI(w, h, true);
|
||||
|
||||
QScopedArrayPointer<uchar> data(new uchar[bmi.bmiHeader.biSizeImage]);
|
||||
if (!GetDIBits(hdc, winBitmap, 0, h, data.data(), &bmi, DIB_RGB_COLORS))
|
||||
return {};
|
||||
|
||||
for (int y = 0; y < image.height(); ++y)
|
||||
{
|
||||
void* dest = static_cast<void*>(image.scanLine(y));
|
||||
const void* src = data.data() + y * image.bytesPerLine();
|
||||
memcpy(dest, src, image.bytesPerLine());
|
||||
}
|
||||
|
||||
// dispose resources created by iconinfo call
|
||||
DeleteObject(iconinfo.hbmMask);
|
||||
DeleteObject(iconinfo.hbmColor);
|
||||
SelectObject(hdc, oldhdc); // restore state
|
||||
DeleteObject(winBitmap);
|
||||
DeleteDC(hdc);
|
||||
return QPixmap::fromImage(image);
|
||||
}
|
||||
|
||||
QIcon WinIconHelper::GetNativeIcon()
|
||||
{
|
||||
QIcon icon;
|
||||
for (int size : {16, 32, 48, 256})
|
||||
{
|
||||
HANDLE h = LoadImageW(GetModuleHandleW(nullptr), L"\"DOLPHIN\"", IMAGE_ICON, size, size,
|
||||
LR_CREATEDIBSECTION);
|
||||
|
||||
if (h && h != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
auto* icon_handle = static_cast<HICON>(h);
|
||||
icon.addPixmap(PixmapFromHICON(icon_handle));
|
||||
}
|
||||
}
|
||||
|
||||
return icon;
|
||||
}
|
||||
|
||||
#endif
|
16
Source/Core/DolphinQt/QtUtils/WinIconHelper.h
Normal file
16
Source/Core/DolphinQt/QtUtils/WinIconHelper.h
Normal file
@ -0,0 +1,16 @@
|
||||
// Copyright 2018 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include <QIcon>
|
||||
|
||||
namespace WinIconHelper
|
||||
{
|
||||
QIcon GetNativeIcon();
|
||||
};
|
||||
|
||||
#endif
|
@ -0,0 +1,19 @@
|
||||
// Copyright 2017 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <QEvent>
|
||||
#include <QObject>
|
||||
|
||||
#include "DolphinQt/QtUtils/WindowActivationEventFilter.h"
|
||||
|
||||
bool WindowActivationEventFilter::eventFilter(QObject* object, QEvent* event)
|
||||
{
|
||||
if (event->type() == QEvent::WindowDeactivate)
|
||||
emit windowDeactivated();
|
||||
|
||||
if (event->type() == QEvent::WindowActivate)
|
||||
emit windowActivated();
|
||||
|
||||
return false;
|
||||
}
|
18
Source/Core/DolphinQt/QtUtils/WindowActivationEventFilter.h
Normal file
18
Source/Core/DolphinQt/QtUtils/WindowActivationEventFilter.h
Normal file
@ -0,0 +1,18 @@
|
||||
// Copyright 2017 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
|
||||
class WindowActivationEventFilter : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
signals:
|
||||
void windowActivated();
|
||||
void windowDeactivated();
|
||||
|
||||
private:
|
||||
bool eventFilter(QObject* object, QEvent* event) override;
|
||||
};
|
63
Source/Core/DolphinQt/QtUtils/WrapInScrollArea.cpp
Normal file
63
Source/Core/DolphinQt/QtUtils/WrapInScrollArea.cpp
Normal file
@ -0,0 +1,63 @@
|
||||
// Copyright 2018 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "DolphinQt/QtUtils/WrapInScrollArea.h"
|
||||
|
||||
#include <QFrame>
|
||||
#include <QLayout>
|
||||
#include <QPalette>
|
||||
#include <QScrollArea>
|
||||
#include <QVBoxLayout>
|
||||
#include <QWidget>
|
||||
|
||||
QWidget* GetWrappedWidget(QWidget* wrapped_widget, QWidget* to_resize, int margin_width,
|
||||
int margin_height)
|
||||
{
|
||||
auto* scroll = new QScrollArea;
|
||||
scroll->setWidget(wrapped_widget);
|
||||
scroll->setWidgetResizable(true);
|
||||
scroll->setFrameStyle(QFrame::NoFrame);
|
||||
|
||||
if (to_resize != nullptr)
|
||||
{
|
||||
// For some reason width() is bigger than it needs to be.
|
||||
auto min_size = wrapped_widget->minimumSizeHint();
|
||||
int recommended_width = min_size.width() + margin_width;
|
||||
int recommended_height = min_size.height() + margin_height;
|
||||
|
||||
to_resize->resize(std::max(recommended_width, to_resize->width()),
|
||||
std::max(recommended_height, to_resize->height()));
|
||||
}
|
||||
|
||||
#if defined(_WIN32) || defined(__APPLE__)
|
||||
// Transparency can cause unwanted side-effects on OSes other than Windows / macOS
|
||||
|
||||
// Make sure the background color stays consistent with the parent widget
|
||||
QPalette p = wrapped_widget->palette();
|
||||
|
||||
p.setColor(QPalette::Window, QColor(0, 0, 0, 0));
|
||||
|
||||
wrapped_widget->setPalette(p);
|
||||
scroll->setPalette(p);
|
||||
#endif
|
||||
|
||||
return scroll;
|
||||
}
|
||||
|
||||
void WrapInScrollArea(QWidget* parent, QLayout* wrapped_layout, QWidget* to_resize)
|
||||
{
|
||||
if (to_resize == nullptr)
|
||||
to_resize = parent;
|
||||
|
||||
auto* widget = new QWidget;
|
||||
widget->setLayout(wrapped_layout);
|
||||
|
||||
auto* scroll_area = GetWrappedWidget(widget, to_resize, 0, 0);
|
||||
|
||||
auto* scroll_layout = new QVBoxLayout;
|
||||
scroll_layout->addWidget(scroll_area);
|
||||
scroll_layout->setMargin(0);
|
||||
|
||||
parent->setLayout(scroll_layout);
|
||||
}
|
14
Source/Core/DolphinQt/QtUtils/WrapInScrollArea.h
Normal file
14
Source/Core/DolphinQt/QtUtils/WrapInScrollArea.h
Normal file
@ -0,0 +1,14 @@
|
||||
// Copyright 2018 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
class QLayout;
|
||||
class QWidget;
|
||||
|
||||
QWidget* GetWrappedWidget(QWidget* wrapped_widget, QWidget* to_resize = nullptr,
|
||||
int margin_width = 50, int margin_height = 50);
|
||||
|
||||
// Wrap wrapped_layout in a QScrollArea and fill the parent widget with it
|
||||
void WrapInScrollArea(QWidget* parent, QLayout* wrapped_layout, QWidget* to_resize = nullptr);
|
Reference in New Issue
Block a user