mirror of
https://github.com/Nheko-Reborn/nheko.git
synced 2024-11-23 19:38:48 +03:00
Basic running app on qt6
This commit is contained in:
parent
8c66945be9
commit
7303275793
27 changed files with 152 additions and 260 deletions
|
@ -196,14 +196,15 @@ endif()
|
|||
#
|
||||
# Discover Qt dependencies.
|
||||
#
|
||||
find_package(Qt5 5.15 COMPONENTS Core Widgets LinguistTools Concurrent Svg Multimedia Qml QuickControls2 QuickWidgets REQUIRED)
|
||||
find_package(Qt5QuickCompiler)
|
||||
find_package(Qt5DBus)
|
||||
find_package(Qt6 6.2 COMPONENTS Core Widgets LinguistTools Svg Multimedia Qml QuickControls2 REQUIRED)
|
||||
#find_package(Qt5QuickCompiler)
|
||||
find_package(Qt6DBus)
|
||||
|
||||
if (USE_BUNDLED_QTKEYCHAIN)
|
||||
include(FetchContent)
|
||||
set(BUILD_WITH_QT6 ON)
|
||||
FetchContent_Declare(
|
||||
qt5keychain
|
||||
qt6keychain
|
||||
GIT_REPOSITORY https://github.com/frankosterfeld/qtkeychain.git
|
||||
GIT_TAG v0.13.1
|
||||
)
|
||||
|
@ -213,13 +214,13 @@ if (USE_BUNDLED_QTKEYCHAIN)
|
|||
set(QTKEYCHAIN_STATIC ON CACHE INTERNAL "")
|
||||
endif()
|
||||
set(BUILD_TEST_APPLICATION OFF CACHE INTERNAL "")
|
||||
FetchContent_MakeAvailable(qt5keychain)
|
||||
FetchContent_MakeAvailable(qt6keychain)
|
||||
else()
|
||||
find_package(Qt5Keychain REQUIRED)
|
||||
find_package(Qt6Keychain REQUIRED)
|
||||
endif()
|
||||
|
||||
if (APPLE)
|
||||
find_package(Qt5MacExtras REQUIRED)
|
||||
find_package(Qt6MacExtras REQUIRED)
|
||||
endif(APPLE)
|
||||
|
||||
if (Qt5Widgets_FOUND)
|
||||
|
@ -505,7 +506,7 @@ if (NOT APPLE AND NOT WIN32)
|
|||
add_compile_definitions(NHEKO_DBUS_SYS)
|
||||
endif()
|
||||
|
||||
qt5_wrap_cpp(MOC_HEADERS
|
||||
qt_wrap_cpp(MOC_HEADERS
|
||||
# Dialogs
|
||||
src/dialogs/FallbackAuth.h
|
||||
src/dialogs/ReCaptcha.h
|
||||
|
@ -645,7 +646,7 @@ elseif(WIN32)
|
|||
target_compile_options(nheko PUBLIC "/Zc:__cplusplus")
|
||||
endif()
|
||||
else()
|
||||
target_link_libraries (nheko PRIVATE Qt5::DBus)
|
||||
target_link_libraries (nheko PRIVATE Qt::DBus)
|
||||
if (FLATPAK)
|
||||
target_compile_definitions(nheko PRIVATE NHEKO_FLATPAK)
|
||||
endif()
|
||||
|
@ -654,21 +655,19 @@ target_include_directories(nheko PRIVATE src includes third_party/blurhash third
|
|||
|
||||
# Fixup bundled keychain include dirs
|
||||
if (USE_BUNDLED_QTKEYCHAIN)
|
||||
target_include_directories(nheko PRIVATE ${qt5keychain_SOURCE_DIR} ${qt5keychain_BINARY_DIR})
|
||||
target_include_directories(nheko PRIVATE ${qt6keychain_SOURCE_DIR} ${qt6keychain_BINARY_DIR})
|
||||
endif()
|
||||
|
||||
target_link_libraries(nheko PRIVATE
|
||||
MatrixClient::MatrixClient
|
||||
cmark::cmark
|
||||
spdlog::spdlog
|
||||
Qt5::Widgets
|
||||
Qt5::Svg
|
||||
Qt5::Concurrent
|
||||
Qt5::Multimedia
|
||||
Qt5::Qml
|
||||
Qt5::QuickControls2
|
||||
Qt5::QuickWidgets
|
||||
qt5keychain
|
||||
Qt::Widgets
|
||||
Qt::Svg
|
||||
Qt::Multimedia
|
||||
Qt::Qml
|
||||
Qt::QuickControls2
|
||||
qt6keychain
|
||||
nlohmann_json::nlohmann_json
|
||||
lmdbxx::lmdbxx
|
||||
liblmdb::lmdb
|
||||
|
|
|
@ -4,9 +4,10 @@
|
|||
|
||||
file(GLOB LANG_TS_SRC "${CMAKE_CURRENT_SOURCE_DIR}/resources/langs/*.ts")
|
||||
|
||||
qt5_add_translation(QM_SRC ${LANG_TS_SRC})
|
||||
qt5_create_translation(${QM_SRC})
|
||||
qt_add_translation(QM_SRC ${LANG_TS_SRC})
|
||||
qt_create_translation(${QM_SRC})
|
||||
add_custom_target(LANG_QRC ALL DEPENDS ${QM_SRC})
|
||||
set_target_properties(LANG_QRC PROPERTIES QT_RESOURCE_PREFIX /)
|
||||
|
||||
# Generate a qrc file for the translations
|
||||
set(_qrc ${CMAKE_CURRENT_BINARY_DIR}/translations.qrc)
|
||||
|
@ -20,9 +21,9 @@ if(NOT EXISTS ${_qrc})
|
|||
file(APPEND ${_qrc} " </qresource>\n</RCC>\n")
|
||||
endif()
|
||||
|
||||
qt5_add_resources(LANG_QRC ${_qrc})
|
||||
qt_add_resources(LANG_QRC ${_qrc})
|
||||
if(Qt5QuickCompiler_FOUND AND COMPILE_QML)
|
||||
qtquick_compiler_add_resources(QRC resources/res.qrc)
|
||||
else()
|
||||
qt5_add_resources(QRC resources/res.qrc)
|
||||
qt_add_resources(QRC resources/res.qrc)
|
||||
endif()
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
import QtGraphicalEffects 1.0
|
||||
//import QtGraphicalEffects 1.0
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Window 2.2
|
||||
import im.nheko 1.0
|
||||
|
@ -120,13 +120,13 @@ Item {
|
|||
}
|
||||
]
|
||||
|
||||
FastBlur {
|
||||
id: blur
|
||||
//FastBlur {
|
||||
// id: blur
|
||||
|
||||
anchors.fill: parent
|
||||
source: timelineRoot
|
||||
radius: 50
|
||||
}
|
||||
// anchors.fill: parent
|
||||
// source: timelineRoot
|
||||
// radius: 50
|
||||
//}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,26 @@ import im.nheko.EmojiModel 1.0
|
|||
Pane {
|
||||
id: timelineRoot
|
||||
|
||||
palette: Nheko.colors
|
||||
palette {
|
||||
windowText: "#caccd1"
|
||||
button: "white"
|
||||
light: "#caccd1"
|
||||
dark: "#3c464d"
|
||||
mid: "#202228"
|
||||
text: "#caccd1"
|
||||
brightText: "#f4f5f8"
|
||||
base: "#202228"
|
||||
window: "#2d3139"
|
||||
|
||||
alternateBase: "#2d3139"
|
||||
highlight: "#38a3d8"
|
||||
highlightedText: "#f4f5f8"
|
||||
toolTipBase: base
|
||||
toolTipText: text
|
||||
link: "#38a3d8"
|
||||
buttonText: "#828284"
|
||||
|
||||
}
|
||||
background: null
|
||||
padding: 0
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
import QtGraphicalEffects 1.12
|
||||
//import QtGraphicalEffects 1.12
|
||||
import QtQuick 2.9
|
||||
import QtQuick.Controls 2.5
|
||||
import QtQuick.Layouts 1.2
|
||||
|
@ -19,16 +19,16 @@ Button {
|
|||
|
||||
property string iconImage: ""
|
||||
|
||||
DropShadow {
|
||||
anchors.fill: control.background
|
||||
horizontalOffset: 3
|
||||
verticalOffset: 3
|
||||
radius: 8
|
||||
samples: 17
|
||||
cached: true
|
||||
color: "#80000000"
|
||||
source: control.background
|
||||
}
|
||||
//DropShadow {
|
||||
// anchors.fill: control.background
|
||||
// horizontalOffset: 3
|
||||
// verticalOffset: 3
|
||||
// radius: 8
|
||||
// samples: 17
|
||||
// cached: true
|
||||
// color: "#80000000"
|
||||
// source: control.background
|
||||
//}
|
||||
|
||||
contentItem: RowLayout {
|
||||
spacing: 0
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
import "../"
|
||||
import "../ui/media"
|
||||
import QtMultimedia 5.15
|
||||
import QtMultimedia
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
|
@ -36,13 +36,13 @@ Item {
|
|||
MxcMedia {
|
||||
id: mxcmedia
|
||||
|
||||
// TODO: Show error in overlay or so?
|
||||
onError: console.log(error)
|
||||
roomm: room
|
||||
// desiredVolume is a float from 0.0 -> 1.0, MediaPlayer volume is an int from 0 to 100
|
||||
// this value automatically gets clamped for us between these two values.
|
||||
volume: mediaControls.desiredVolume * 100
|
||||
|
||||
audioOutput: AudioOutput {
|
||||
muted: mediaControls.muted
|
||||
volume: mediaControls.desiredVolume
|
||||
}
|
||||
videoOutput: videoOutput
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
|
@ -69,8 +69,7 @@ Item {
|
|||
clip: true
|
||||
anchors.fill: parent
|
||||
fillMode: VideoOutput.PreserveAspectFit
|
||||
source: mxcmedia
|
||||
flushMode: VideoOutput.FirstFrame
|
||||
//flushMode: VideoOutput.FirstFrame
|
||||
orientation: mxcmedia.orientation
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
import "../"
|
||||
import QtGraphicalEffects 1.0
|
||||
import QtQuick 2.9
|
||||
import QtQuick.Controls 2.3
|
||||
import QtQuick.Layouts 1.3
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
import "../"
|
||||
import QtGraphicalEffects 1.0
|
||||
import QtQuick 2.9
|
||||
import QtQuick.Controls 2.3
|
||||
import QtQuick.Layouts 1.3
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
import QtGraphicalEffects 1.0
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
import "./animations"
|
||||
import QtGraphicalEffects 1.12
|
||||
//import QtGraphicalEffects 1.12
|
||||
import QtQuick 2.12
|
||||
|
||||
Item {
|
||||
|
@ -140,17 +140,17 @@ Item {
|
|||
|
||||
}
|
||||
|
||||
Glow {
|
||||
anchors.fill: row
|
||||
radius: 14
|
||||
samples: 17
|
||||
color: spinner.foreground
|
||||
source: row
|
||||
//Glow {
|
||||
// anchors.fill: row
|
||||
// radius: 14
|
||||
// samples: 17
|
||||
// color: spinner.foreground
|
||||
// source: row
|
||||
|
||||
transform: Matrix4x4 {
|
||||
matrix: Qt.matrix4x4(Math.cos(spinner.a), -Math.sin(spinner.a), 0, 0, 0, Math.cos(spinner.a), 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)
|
||||
}
|
||||
// transform: Matrix4x4 {
|
||||
// matrix: Qt.matrix4x4(Math.cos(spinner.a), -Math.sin(spinner.a), 0, 0, 0, Math.cos(spinner.a), 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)
|
||||
// }
|
||||
|
||||
}
|
||||
//}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
import QtGraphicalEffects 1.12
|
||||
import QtQuick 2.12
|
||||
|
||||
SequentialAnimation {
|
||||
|
|
|
@ -4040,7 +4040,8 @@ Cache::displayName(const QString &room_id, const QString &user_id)
|
|||
static bool
|
||||
isDisplaynameSafe(const std::string &s)
|
||||
{
|
||||
for (QChar c : QString::fromStdString(s).toStdU32String()) {
|
||||
for (uint32_t cc : QString::fromStdString(s).toStdU32String()) {
|
||||
auto c = QChar(cc);
|
||||
if (c.isPrint() && !c.isSpace())
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ CompletionProxyModel::CompletionProxyModel(QAbstractItemModel *model,
|
|||
finder.toNextBoundary();
|
||||
auto end = finder.position();
|
||||
|
||||
auto ref = str.midRef(start, end - start).trimmed();
|
||||
auto ref = QStringView(str).mid(start, end - start).trimmed();
|
||||
if (!ref.isEmpty())
|
||||
trie_.insert(ref.toUcs4(), i);
|
||||
} while (finder.position() < str.size());
|
||||
|
|
|
@ -78,11 +78,12 @@ public slots:
|
|||
if (queryStart != -1) {
|
||||
id_ = id.left(queryStart);
|
||||
auto query = id.mid(queryStart + 1);
|
||||
auto queryBits = query.splitRef('&');
|
||||
auto queryBits = QStringView(query).split('&');
|
||||
|
||||
for (const auto &b : queryBits) {
|
||||
if (b.startsWith(QStringView(u"radius="))) {
|
||||
radius = b.mid(7).toDouble();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1373,7 +1373,6 @@ UserSettingsModel::data(const QModelIndex &index, int role) const
|
|||
l.push_back(QString::fromStdString(d));
|
||||
return l;
|
||||
};
|
||||
static QFontDatabase fontDb;
|
||||
|
||||
switch (index.row()) {
|
||||
case Theme:
|
||||
|
@ -1393,9 +1392,9 @@ UserSettingsModel::data(const QModelIndex &index, int role) const
|
|||
i->camera().toStdString(), i->cameraResolution().toStdString()));
|
||||
|
||||
case Font:
|
||||
return fontDb.families();
|
||||
return QFontDatabase::families();
|
||||
case EmojiFont:
|
||||
return fontDb.families(QFontDatabase::WritingSystem::Symbol);
|
||||
return QFontDatabase::families(QFontDatabase::WritingSystem::Symbol);
|
||||
case Ringtone:
|
||||
QStringList l{
|
||||
QStringLiteral("Mute"),
|
||||
|
@ -1438,8 +1437,6 @@ UserSettingsModel::data(const QModelIndex &index, int role) const
|
|||
bool
|
||||
UserSettingsModel::setData(const QModelIndex &index, const QVariant &value, int role)
|
||||
{
|
||||
static QFontDatabase fontDb;
|
||||
|
||||
auto i = UserSettings::instance();
|
||||
if (role == Value) {
|
||||
switch (index.row()) {
|
||||
|
@ -1464,7 +1461,7 @@ UserSettingsModel::setData(const QModelIndex &index, const QVariant &value, int
|
|||
return false;
|
||||
}
|
||||
case ScaleFactor: {
|
||||
if (value.canConvert(QMetaType::Double)) {
|
||||
if (value.canConvert(QMetaType::fromType<double>())) {
|
||||
utils::setScaleFactor(static_cast<float>(value.toDouble()));
|
||||
return true;
|
||||
} else
|
||||
|
@ -1548,7 +1545,7 @@ UserSettingsModel::setData(const QModelIndex &index, const QVariant &value, int
|
|||
return false;
|
||||
}
|
||||
case TimelineMaxWidth: {
|
||||
if (value.canConvert(QMetaType::Int)) {
|
||||
if (value.canConvert(QMetaType::fromType<int>())) {
|
||||
i->setTimelineMaxWidth(value.toInt());
|
||||
return true;
|
||||
} else
|
||||
|
@ -1619,7 +1616,7 @@ UserSettingsModel::setData(const QModelIndex &index, const QVariant &value, int
|
|||
return false;
|
||||
}
|
||||
case PrivacyScreenTimeout: {
|
||||
if (value.canConvert(QMetaType::Int)) {
|
||||
if (value.canConvert(QMetaType::fromType<int>())) {
|
||||
i->setPrivacyScreenTimeout(value.toInt());
|
||||
return true;
|
||||
} else
|
||||
|
@ -1633,7 +1630,7 @@ UserSettingsModel::setData(const QModelIndex &index, const QVariant &value, int
|
|||
return false;
|
||||
}
|
||||
case FontSize: {
|
||||
if (value.canConvert(QMetaType::Double)) {
|
||||
if (value.canConvert(QMetaType::fromType<double>())) {
|
||||
i->setFontSize(value.toDouble());
|
||||
return true;
|
||||
} else
|
||||
|
@ -1641,7 +1638,7 @@ UserSettingsModel::setData(const QModelIndex &index, const QVariant &value, int
|
|||
}
|
||||
case Font: {
|
||||
if (value.userType() == QMetaType::Int) {
|
||||
i->setFontFamily(fontDb.families().at(value.toInt()));
|
||||
i->setFontFamily(QFontDatabase::families().at(value.toInt()));
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
|
@ -1649,7 +1646,7 @@ UserSettingsModel::setData(const QModelIndex &index, const QVariant &value, int
|
|||
case EmojiFont: {
|
||||
if (value.userType() == QMetaType::Int) {
|
||||
i->setEmojiFontFamily(
|
||||
fontDb.families(QFontDatabase::WritingSystem::Symbol).at(value.toInt()));
|
||||
QFontDatabase::families(QFontDatabase::WritingSystem::Symbol).at(value.toInt()));
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
|
|
|
@ -268,7 +268,8 @@ utils::firstChar(const QString &input)
|
|||
return QString::fromUcs4(&c, 1).toUpper();
|
||||
}
|
||||
|
||||
return QString::fromUcs4(&input.toUcs4().at(0), 1).toUpper();
|
||||
auto c = static_cast<char32_t>(input.toUcs4().at(0));
|
||||
return QString::fromUcs4(&c, 1).toUpper();
|
||||
}
|
||||
|
||||
QString
|
||||
|
|
10
src/main.cpp
10
src/main.cpp
|
@ -152,8 +152,6 @@ main(int argc, char *argv[])
|
|||
QCoreApplication::setApplicationVersion(nheko::version);
|
||||
QCoreApplication::setOrganizationName(QStringLiteral("nheko"));
|
||||
QCoreApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
|
||||
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
|
||||
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
||||
|
||||
// this needs to be after setting the application name. Or how would we find our settings
|
||||
// file then?
|
||||
|
@ -287,15 +285,15 @@ main(int argc, char *argv[])
|
|||
QLocale::setDefault(QLocale(QLocale::English, QLocale::UnitedKingdom));
|
||||
|
||||
QTranslator qtTranslator;
|
||||
qtTranslator.load(QLocale(),
|
||||
if(qtTranslator.load(QLocale(),
|
||||
QStringLiteral("qt"),
|
||||
QStringLiteral("_"),
|
||||
QLibraryInfo::location(QLibraryInfo::TranslationsPath));
|
||||
QLibraryInfo::path(QLibraryInfo::TranslationsPath)))
|
||||
app.installTranslator(&qtTranslator);
|
||||
|
||||
QTranslator appTranslator;
|
||||
appTranslator.load(
|
||||
QLocale(), QStringLiteral("nheko"), QStringLiteral("_"), QStringLiteral(":/translations"));
|
||||
if(appTranslator.load(
|
||||
QLocale(), QStringLiteral("nheko"), QStringLiteral("_"), QStringLiteral(":/translations")))
|
||||
app.installTranslator(&appTranslator);
|
||||
|
||||
MainWindow w;
|
||||
|
|
|
@ -78,13 +78,13 @@ DelegateChooser::appendChoice(QQmlListProperty<DelegateChoice> *p, DelegateChoic
|
|||
dc->choices_.append(c);
|
||||
}
|
||||
|
||||
int
|
||||
qsizetype
|
||||
DelegateChooser::choiceCount(QQmlListProperty<DelegateChoice> *p)
|
||||
{
|
||||
return static_cast<DelegateChooser *>(p->object)->choices_.count();
|
||||
}
|
||||
DelegateChoice *
|
||||
DelegateChooser::choice(QQmlListProperty<DelegateChoice> *p, int index)
|
||||
DelegateChooser::choice(QQmlListProperty<DelegateChoice> *p, qsizetype index)
|
||||
{
|
||||
return static_cast<DelegateChooser *>(p->object)->choices_.at(index);
|
||||
}
|
||||
|
|
|
@ -86,7 +86,7 @@ private:
|
|||
DelegateIncubator incubator{*this};
|
||||
|
||||
static void appendChoice(QQmlListProperty<DelegateChoice> *, DelegateChoice *);
|
||||
static int choiceCount(QQmlListProperty<DelegateChoice> *);
|
||||
static DelegateChoice *choice(QQmlListProperty<DelegateChoice> *, int index);
|
||||
static qsizetype choiceCount(QQmlListProperty<DelegateChoice> *);
|
||||
static DelegateChoice *choice(QQmlListProperty<DelegateChoice> *, qsizetype index);
|
||||
static void clearChoices(QQmlListProperty<DelegateChoice> *);
|
||||
};
|
||||
|
|
|
@ -5,12 +5,14 @@
|
|||
|
||||
#include "InputBar.h"
|
||||
|
||||
#include <QVideoSink>
|
||||
#include <QBuffer>
|
||||
#include <QClipboard>
|
||||
#include <QDropEvent>
|
||||
#include <QFileDialog>
|
||||
#include <QGuiApplication>
|
||||
#include <QInputMethod>
|
||||
#include <QVideoFrame>
|
||||
#include <QMediaMetaData>
|
||||
#include <QMediaPlayer>
|
||||
#include <QMimeData>
|
||||
|
@ -52,55 +54,6 @@ MediaUpload::thumbnailDataUrl() const
|
|||
return QString("data:image/png;base64,") + base64;
|
||||
}
|
||||
|
||||
bool
|
||||
InputVideoSurface::present(const QVideoFrame &frame)
|
||||
{
|
||||
QImage::Format format = QVideoFrame::imageFormatFromPixelFormat(frame.pixelFormat());
|
||||
|
||||
if (format == QImage::Format_Invalid) {
|
||||
emit newImage({});
|
||||
return false;
|
||||
} else {
|
||||
QVideoFrame frametodraw(frame);
|
||||
|
||||
if (!frametodraw.map(QAbstractVideoBuffer::ReadOnly)) {
|
||||
emit newImage({});
|
||||
return false;
|
||||
}
|
||||
|
||||
// this is a shallow operation. it just refer the frame buffer
|
||||
QImage image(qAsConst(frametodraw).bits(),
|
||||
frametodraw.width(),
|
||||
frametodraw.height(),
|
||||
frametodraw.bytesPerLine(),
|
||||
format);
|
||||
image.detach();
|
||||
|
||||
frametodraw.unmap();
|
||||
|
||||
emit newImage(std::move(image));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
QList<QVideoFrame::PixelFormat>
|
||||
InputVideoSurface::supportedPixelFormats(QAbstractVideoBuffer::HandleType type) const
|
||||
{
|
||||
if (type == QAbstractVideoBuffer::NoHandle) {
|
||||
return {
|
||||
QVideoFrame::Format_ARGB32,
|
||||
QVideoFrame::Format_ARGB32_Premultiplied,
|
||||
QVideoFrame::Format_RGB24,
|
||||
QVideoFrame::Format_BGR24,
|
||||
QVideoFrame::Format_RGB32,
|
||||
QVideoFrame::Format_RGB565,
|
||||
QVideoFrame::Format_RGB555,
|
||||
};
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
InputBar::paste(bool fromMouse)
|
||||
{
|
||||
|
@ -371,7 +324,7 @@ InputBar::message(const QString &msg, MarkdownOverride useMarkdown, bool rainbow
|
|||
|
||||
QString body;
|
||||
bool firstLine = true;
|
||||
auto lines = related.quoted_body.splitRef(u'\n');
|
||||
auto lines = QStringView(related.quoted_body).split(u'\n');
|
||||
for (auto line : qAsConst(lines)) {
|
||||
if (firstLine) {
|
||||
firstLine = false;
|
||||
|
@ -799,21 +752,22 @@ MediaUpload::MediaUpload(std::unique_ptr<QIODevice> source_,
|
|||
blurhash_ =
|
||||
QString::fromStdString(blurhash::encode(data_.data(), img.width(), img.height(), 4, 3));
|
||||
} else if (mimeClass_ == u"video" || mimeClass_ == u"audio") {
|
||||
auto mediaPlayer = new QMediaPlayer(
|
||||
this,
|
||||
mimeClass_ == u"video" ? QFlags{QMediaPlayer::VideoSurface} : QMediaPlayer::Flags{});
|
||||
mediaPlayer->setMuted(true);
|
||||
auto mediaPlayer = new QMediaPlayer(this);
|
||||
|
||||
mediaPlayer->setAudioOutput(nullptr);
|
||||
|
||||
if (mimeClass_ == u"video") {
|
||||
auto newSurface = new InputVideoSurface(this);
|
||||
auto newSurface = new QVideoSink(this);
|
||||
connect(
|
||||
newSurface, &InputVideoSurface::newImage, this, [this, mediaPlayer](QImage img) {
|
||||
newSurface, &QVideoSink::videoFrameChanged, this, [this, mediaPlayer](const QVideoFrame& frame) {
|
||||
QImage img = frame.toImage();
|
||||
|
||||
if (img.size().isEmpty())
|
||||
return;
|
||||
|
||||
mediaPlayer->stop();
|
||||
|
||||
auto orientation = mediaPlayer->metaData(QMediaMetaData::Orientation).toInt();
|
||||
auto orientation = mediaPlayer->metaData().value(QMediaMetaData::Orientation).toInt();
|
||||
if (orientation == 90 || orientation == 270 || orientation == 180) {
|
||||
img =
|
||||
img.transformed(QTransform().rotate(orientation), Qt::SmoothTransformation);
|
||||
|
@ -844,11 +798,11 @@ MediaUpload::MediaUpload(std::unique_ptr<QIODevice> source_,
|
|||
}
|
||||
|
||||
connect(mediaPlayer,
|
||||
qOverload<QMediaPlayer::Error>(&QMediaPlayer::error),
|
||||
&QMediaPlayer::error,
|
||||
this,
|
||||
[mediaPlayer](QMediaPlayer::Error error) {
|
||||
[mediaPlayer]() {
|
||||
nhlog::ui()->debug("Media player error {} and errorStr {}",
|
||||
error,
|
||||
mediaPlayer->error(),
|
||||
mediaPlayer->errorString().toStdString());
|
||||
});
|
||||
connect(mediaPlayer,
|
||||
|
@ -858,18 +812,18 @@ MediaUpload::MediaUpload(std::unique_ptr<QIODevice> source_,
|
|||
"Media player status {} and error {}", status, mediaPlayer->error());
|
||||
});
|
||||
connect(mediaPlayer,
|
||||
qOverload<const QString &, const QVariant &>(&QMediaPlayer::metaDataChanged),
|
||||
[this, mediaPlayer](QString t, QVariant) {
|
||||
nhlog::ui()->debug("Got metadata {}", t.toStdString());
|
||||
&QMediaPlayer::metaDataChanged,
|
||||
[this, mediaPlayer]() {
|
||||
nhlog::ui()->debug("Got metadata");
|
||||
|
||||
if (mediaPlayer->duration() > 0)
|
||||
this->duration_ = mediaPlayer->duration();
|
||||
|
||||
auto dimensions = mediaPlayer->metaData(QMediaMetaData::Resolution).toSize();
|
||||
auto dimensions = mediaPlayer->metaData().value(QMediaMetaData::Resolution).toSize();
|
||||
if (!dimensions.isEmpty()) {
|
||||
dimensions_ = dimensions;
|
||||
auto orientation =
|
||||
mediaPlayer->metaData(QMediaMetaData::Orientation).toInt();
|
||||
mediaPlayer->metaData().value(QMediaMetaData::Orientation).toInt();
|
||||
if (orientation == 90 || orientation == 270) {
|
||||
dimensions_.transpose();
|
||||
}
|
||||
|
@ -886,8 +840,8 @@ MediaUpload::MediaUpload(std::unique_ptr<QIODevice> source_,
|
|||
|
||||
auto originalFile = qobject_cast<QFile *>(source.get());
|
||||
|
||||
mediaPlayer->setMedia(
|
||||
QMediaContent(originalFile ? originalFile->fileName() : originalFilename_), source.get());
|
||||
mediaPlayer->setSourceDevice(
|
||||
source.get(), QUrl(originalFile ? originalFile->fileName() : originalFilename_) );
|
||||
|
||||
mediaPlayer->play();
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <QAbstractVideoSurface>
|
||||
#include <QIODevice>
|
||||
#include <QImage>
|
||||
#include <QObject>
|
||||
|
@ -32,24 +31,6 @@ enum class MarkdownOverride
|
|||
OFF,
|
||||
};
|
||||
|
||||
class InputVideoSurface : public QAbstractVideoSurface
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
InputVideoSurface(QObject *parent)
|
||||
: QAbstractVideoSurface(parent)
|
||||
{}
|
||||
|
||||
bool present(const QVideoFrame &frame) override;
|
||||
|
||||
QList<QVideoFrame::PixelFormat>
|
||||
supportedPixelFormats(QAbstractVideoBuffer::HandleType type) const override;
|
||||
|
||||
signals:
|
||||
void newImage(QImage img);
|
||||
};
|
||||
|
||||
class MediaUpload : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
|
|
@ -272,7 +272,7 @@ TimelineViewManager::saveMedia(QString mxcUrl)
|
|||
{
|
||||
const QString downloadsFolder =
|
||||
QStandardPaths::writableLocation(QStandardPaths::DownloadLocation);
|
||||
const QString openLocation = downloadsFolder + "/" + mxcUrl.splitRef(u'/').constLast();
|
||||
const QString openLocation = downloadsFolder + "/" + mxcUrl.split(u'/').constLast();
|
||||
|
||||
const QString filename = QFileDialog::getSaveFileName(nullptr, {}, openLocation);
|
||||
|
||||
|
|
|
@ -148,9 +148,9 @@ MxcAnimatedImage::startDownload()
|
|||
}
|
||||
|
||||
void
|
||||
MxcAnimatedImage::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
|
||||
MxcAnimatedImage::geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry)
|
||||
{
|
||||
QQuickItem::geometryChanged(newGeometry, oldGeometry);
|
||||
QQuickItem::geometryChange(newGeometry, oldGeometry);
|
||||
|
||||
if (newGeometry.size() != oldGeometry.size()) {
|
||||
if (height() != 0 && width() != 0)
|
||||
|
|
|
@ -60,7 +60,7 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override;
|
||||
void geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry) override;
|
||||
QSGNode *updatePaintNode(QSGNode *oldNode,
|
||||
QQuickItem::UpdatePaintNodeData *updatePaintNodeData) override;
|
||||
|
||||
|
|
|
@ -9,17 +9,11 @@
|
|||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QMediaMetaData>
|
||||
#include <QMediaObject>
|
||||
#include <QMediaPlayer>
|
||||
#include <QMimeDatabase>
|
||||
#include <QStandardPaths>
|
||||
#include <QUrl>
|
||||
|
||||
#if defined(Q_OS_MACOS)
|
||||
// TODO (red_sky): Remove for Qt6. See other ifdef below
|
||||
#include <QTemporaryFile>
|
||||
#endif
|
||||
|
||||
#include "EventAccessors.h"
|
||||
#include "Logging.h"
|
||||
#include "MatrixClient.h"
|
||||
|
@ -31,44 +25,27 @@ MxcMediaProxy::MxcMediaProxy(QObject *parent)
|
|||
connect(this, &MxcMediaProxy::eventIdChanged, &MxcMediaProxy::startDownload);
|
||||
connect(this, &MxcMediaProxy::roomChanged, &MxcMediaProxy::startDownload);
|
||||
connect(this,
|
||||
qOverload<QMediaPlayer::Error>(&MxcMediaProxy::error),
|
||||
[this](QMediaPlayer::Error error) {
|
||||
&MxcMediaProxy::error,
|
||||
[this]() {
|
||||
nhlog::ui()->info("Media player error {} and errorStr {}",
|
||||
error,
|
||||
error(),
|
||||
this->errorString().toStdString());
|
||||
});
|
||||
connect(this, &MxcMediaProxy::mediaStatusChanged, [this](QMediaPlayer::MediaStatus status) {
|
||||
nhlog::ui()->info("Media player status {} and error {}", status, this->error());
|
||||
});
|
||||
connect(this,
|
||||
qOverload<const QString &, const QVariant &>(&MxcMediaProxy::metaDataChanged),
|
||||
[this](QString t, QVariant) {
|
||||
if (t == QMediaMetaData::Orientation)
|
||||
&MxcMediaProxy::metaDataChanged,
|
||||
[this]() {
|
||||
emit orientationChanged();
|
||||
});
|
||||
}
|
||||
void
|
||||
MxcMediaProxy::setVideoSurface(QAbstractVideoSurface *surface)
|
||||
{
|
||||
if (surface != m_surface) {
|
||||
qDebug() << "Changing surface";
|
||||
m_surface = surface;
|
||||
setVideoOutput(m_surface);
|
||||
emit videoSurfaceChanged();
|
||||
}
|
||||
}
|
||||
|
||||
QAbstractVideoSurface *
|
||||
MxcMediaProxy::getVideoSurface()
|
||||
{
|
||||
return m_surface;
|
||||
}
|
||||
|
||||
int
|
||||
MxcMediaProxy::orientation() const
|
||||
{
|
||||
nhlog::ui()->debug("metadata: {}", availableMetaData().join(QStringLiteral(",")).toStdString());
|
||||
auto orientation = metaData(QMediaMetaData::Orientation).toInt();
|
||||
//nhlog::ui()->debug("metadata: {}", metaData().
|
||||
auto orientation = metaData().value(QMediaMetaData::Orientation).toInt();
|
||||
nhlog::ui()->debug("Video orientation: {}", orientation);
|
||||
return orientation;
|
||||
}
|
||||
|
@ -129,34 +106,10 @@ MxcMediaProxy::startDownload()
|
|||
buffer.open(QIODevice::ReadOnly);
|
||||
buffer.reset();
|
||||
|
||||
QTimer::singleShot(0, this, [this, filename, suffix, encryptionInfo] {
|
||||
#if defined(Q_OS_MACOS)
|
||||
if (encryptionInfo) {
|
||||
// macOS has issues reading from a buffer in setMedia for whatever reason.
|
||||
// Instead, write the buffer to a temporary file and read from that.
|
||||
// This should be fixed in Qt6, so update this when we do that!
|
||||
// TODO: REMOVE IN QT6
|
||||
QTemporaryFile tempFile;
|
||||
tempFile.setFileTemplate(tempFile.fileTemplate() + QLatin1Char('.') + suffix);
|
||||
tempFile.open();
|
||||
tempFile.write(buffer.data());
|
||||
tempFile.close();
|
||||
nhlog::ui()->debug("Playing media from temp buffer file: {}. Remove in QT6!",
|
||||
filename.filePath().toStdString());
|
||||
this->setMedia(QUrl::fromLocalFile(tempFile.fileName()));
|
||||
} else {
|
||||
QTimer::singleShot(0, this, [this, filename] {
|
||||
nhlog::ui()->info(
|
||||
"Playing buffer with size: {}, {}", buffer.bytesAvailable(), buffer.isOpen());
|
||||
this->setMedia(QUrl::fromLocalFile(filename.filePath()));
|
||||
}
|
||||
#else
|
||||
Q_UNUSED(suffix)
|
||||
Q_UNUSED(encryptionInfo)
|
||||
|
||||
nhlog::ui()->info(
|
||||
"Playing buffer with size: {}, {}", buffer.bytesAvailable(), buffer.isOpen());
|
||||
this->setMedia(QMediaContent(filename.fileName()), &buffer);
|
||||
#endif
|
||||
this->setSourceDevice( &buffer, QUrl(filename.fileName()));
|
||||
emit loadedChanged();
|
||||
});
|
||||
};
|
||||
|
|
|
@ -5,14 +5,14 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <QAbstractVideoSurface>
|
||||
#include <QVideoSink>
|
||||
#include <QBuffer>
|
||||
#include <QMediaContent>
|
||||
#include <QMediaPlayer>
|
||||
#include <QObject>
|
||||
#include <QPointer>
|
||||
#include <QString>
|
||||
|
||||
#include "timeline/TimelineModel.h"
|
||||
#include "Logging.h"
|
||||
|
||||
class TimelineModel;
|
||||
|
@ -24,8 +24,6 @@ class MxcMediaProxy : public QMediaPlayer
|
|||
Q_OBJECT
|
||||
Q_PROPERTY(TimelineModel *roomm READ room WRITE setRoom NOTIFY roomChanged REQUIRED)
|
||||
Q_PROPERTY(QString eventId READ eventId WRITE setEventId NOTIFY eventIdChanged)
|
||||
Q_PROPERTY(QAbstractVideoSurface *videoSurface READ getVideoSurface WRITE setVideoSurface NOTIFY
|
||||
videoSurfaceChanged)
|
||||
Q_PROPERTY(bool loaded READ loaded NOTIFY loadedChanged)
|
||||
Q_PROPERTY(int orientation READ orientation NOTIFY orientationChanged)
|
||||
|
||||
|
@ -45,8 +43,6 @@ public:
|
|||
room_ = room;
|
||||
emit roomChanged();
|
||||
}
|
||||
void setVideoSurface(QAbstractVideoSurface *surface);
|
||||
QAbstractVideoSurface *getVideoSurface();
|
||||
|
||||
int orientation() const;
|
||||
|
||||
|
@ -54,10 +50,9 @@ signals:
|
|||
void roomChanged();
|
||||
void eventIdChanged();
|
||||
void loadedChanged();
|
||||
void newBuffer(QMediaContent, QIODevice *buf);
|
||||
void newBuffer(QUrl, QIODevice *buf);
|
||||
|
||||
void orientationChanged();
|
||||
void videoSurfaceChanged();
|
||||
|
||||
private slots:
|
||||
void startDownload();
|
||||
|
@ -67,5 +62,5 @@ private:
|
|||
QString eventId_;
|
||||
QString filename_;
|
||||
QBuffer buffer;
|
||||
QAbstractVideoSurface *m_surface = nullptr;
|
||||
QObject *m_surface = nullptr;
|
||||
};
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
#include <cstdlib>
|
||||
#include <memory>
|
||||
|
||||
#include <QMediaPlaylist>
|
||||
#include <QUrl>
|
||||
|
||||
#include "Cache.h"
|
||||
|
@ -144,11 +143,11 @@ CallManager::CallManager(QObject *parent)
|
|||
});
|
||||
|
||||
connect(&player_,
|
||||
QOverload<QMediaPlayer::Error>::of(&QMediaPlayer::error),
|
||||
&QMediaPlayer::error,
|
||||
this,
|
||||
[this](QMediaPlayer::Error error) {
|
||||
[this]() {
|
||||
stopRingtone();
|
||||
switch (error) {
|
||||
switch (player_.error()) {
|
||||
case QMediaPlayer::FormatError:
|
||||
case QMediaPlayer::ResourceError:
|
||||
nhlog::ui()->error("WebRTC: valid ringtone file not found");
|
||||
|
@ -497,19 +496,17 @@ CallManager::retrieveTurnServer()
|
|||
void
|
||||
CallManager::playRingtone(const QUrl &ringtone, bool repeat)
|
||||
{
|
||||
static QMediaPlaylist playlist;
|
||||
playlist.clear();
|
||||
playlist.setPlaybackMode(repeat ? QMediaPlaylist::CurrentItemInLoop
|
||||
: QMediaPlaylist::CurrentItemOnce);
|
||||
playlist.addMedia(ringtone);
|
||||
player_.setVolume(100);
|
||||
player_.setPlaylist(&playlist);
|
||||
player_.setLoops(repeat ? QMediaPlayer::Infinite :
|
||||
1);
|
||||
player_.setSource(ringtone);
|
||||
//player_.audioOutput()->setVolume(100);
|
||||
player_.play();
|
||||
}
|
||||
|
||||
void
|
||||
CallManager::stopRingtone()
|
||||
{
|
||||
player_.setPlaylist(nullptr);
|
||||
player_.stop();
|
||||
}
|
||||
|
||||
QStringList
|
||||
|
|
Loading…
Reference in a new issue