mirror of
https://github.com/moonlight-stream/moonlight-qt.git
synced 2025-07-01 23:35:55 +00:00
WIP Quick GUI work
This commit is contained in:
parent
6a3b95a4b1
commit
3a7d3c807e
@ -57,7 +57,8 @@ SOURCES += \
|
||||
streaming/input.cpp \
|
||||
streaming/session.cpp \
|
||||
streaming/audio.cpp \
|
||||
streaming/video.cpp
|
||||
streaming/video.cpp \
|
||||
gui/computermodel.cpp
|
||||
|
||||
HEADERS += \
|
||||
utils.h \
|
||||
@ -68,7 +69,8 @@ HEADERS += \
|
||||
backend/boxartmanager.h \
|
||||
settings/streamingpreferences.h \
|
||||
streaming/input.hpp \
|
||||
streaming/session.hpp
|
||||
streaming/session.hpp \
|
||||
gui/computermodel.h
|
||||
|
||||
RESOURCES += \
|
||||
resources.qrc \
|
||||
|
@ -199,7 +199,7 @@ QVector<QString> NvComputer::uniqueAddresses()
|
||||
}
|
||||
|
||||
// We must have at least 1 address
|
||||
Q_ASSERT(uniqueAddressList.count() != 0);
|
||||
Q_ASSERT(!uniqueAddressList.isEmpty());
|
||||
|
||||
return uniqueAddressList;
|
||||
}
|
||||
|
83
app/gui/PcView.qml
Normal file
83
app/gui/PcView.qml
Normal file
@ -0,0 +1,83 @@
|
||||
import QtQuick 2.9
|
||||
import QtQuick.Controls 2.2
|
||||
|
||||
import ComputerModel 1.0
|
||||
|
||||
Frame {
|
||||
GridView {
|
||||
anchors.fill: parent
|
||||
cellWidth: 200; cellHeight: 300;
|
||||
focus: true
|
||||
|
||||
model: ComputerModel {}
|
||||
|
||||
delegate: Item {
|
||||
width: 300; height: 300;
|
||||
|
||||
Image {
|
||||
id: pcIcon
|
||||
y: 10; anchors.horizontalCenter: parent.horizontalCenter;
|
||||
source: {
|
||||
model.addPc ? "ic_add_to_queue_white_48px.svg" : "ic_tv_white_48px.svg"
|
||||
}
|
||||
sourceSize {
|
||||
width: 200
|
||||
height: 200
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
id: pcNameText
|
||||
text: model.name
|
||||
color: "white"
|
||||
|
||||
width: parent.width
|
||||
anchors.top: pcIcon.bottom
|
||||
minimumPointSize: 12
|
||||
font.pointSize: 36
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
fontSizeMode: Text.HorizontalFit
|
||||
}
|
||||
|
||||
Text {
|
||||
function getStatusText(model)
|
||||
{
|
||||
if (model.online) {
|
||||
var text = "<font color=\"green\">Online</font>"
|
||||
text += "<font color=\"white\"> - </font>"
|
||||
if (model.paired) {
|
||||
text += "<font color=\"skyblue\">Paired</font>"
|
||||
}
|
||||
else if (model.busy) {
|
||||
text += "<font color=\"red\">Busy</font>"
|
||||
}
|
||||
else {
|
||||
text += "<font color=\"red\">Not Paired</font>"
|
||||
}
|
||||
return text
|
||||
}
|
||||
else {
|
||||
return "<font color=\"red\">Offline</font>";
|
||||
}
|
||||
}
|
||||
|
||||
id: pcPairedText
|
||||
text: getStatusText(model)
|
||||
|
||||
width: parent.width
|
||||
anchors.top: pcNameText.bottom
|
||||
minimumPointSize: 12
|
||||
font.pointSize: 36
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
fontSizeMode: Text.HorizontalFit
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
parent.GridView.view.currentIndex = index
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
94
app/gui/computermodel.cpp
Normal file
94
app/gui/computermodel.cpp
Normal file
@ -0,0 +1,94 @@
|
||||
#include "computermodel.h"
|
||||
|
||||
ComputerModel::ComputerModel(QObject* object)
|
||||
: QAbstractListModel(object)
|
||||
{
|
||||
connect(&m_ComputerManager, &ComputerManager::computerStateChanged,
|
||||
this, &ComputerModel::handleComputerStateChanged);
|
||||
|
||||
m_Computers = m_ComputerManager.getComputers();
|
||||
m_ComputerManager.startPolling();
|
||||
}
|
||||
|
||||
QVariant ComputerModel::data(const QModelIndex& index, int role) const
|
||||
{
|
||||
if (!index.isValid()) {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
if (index.row() == m_Computers.count()) {
|
||||
// We insert a synthetic item at the end for the Add PC option
|
||||
switch (role) {
|
||||
case NameRole:
|
||||
return "Add PC";
|
||||
case AddPcRole:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (index.row() > m_Computers.count()) {
|
||||
qWarning() << "Index out of bounds: " << index.row();
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
NvComputer* computer = m_Computers[index.row()];
|
||||
QReadLocker lock(&computer->lock);
|
||||
|
||||
switch (role) {
|
||||
case NameRole:
|
||||
return computer->name;
|
||||
case OnlineRole:
|
||||
return computer->state == NvComputer::CS_ONLINE;
|
||||
case PairedRole:
|
||||
return computer->state == NvComputer::PS_PAIRED;
|
||||
case BusyRole:
|
||||
return computer->currentGameId != 0;
|
||||
case AddPcRole:
|
||||
return false;
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
int ComputerModel::rowCount(const QModelIndex& parent) const
|
||||
{
|
||||
// We should not return a count for valid index values,
|
||||
// only the parent (which will not have a "valid" index).
|
||||
if (parent.isValid()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Add PC placeholder counts as 1
|
||||
return m_Computers.count() + 1;
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> ComputerModel::roleNames() const
|
||||
{
|
||||
QHash<int, QByteArray> names;
|
||||
|
||||
names[NameRole] = "name";
|
||||
names[OnlineRole] = "online";
|
||||
names[PairedRole] = "paired";
|
||||
names[BusyRole] = "busy";
|
||||
|
||||
return names;
|
||||
}
|
||||
|
||||
void ComputerModel::handleComputerStateChanged(NvComputer* computer)
|
||||
{
|
||||
// If this is an existing computer, we can report the data changed
|
||||
int index = m_Computers.indexOf(computer);
|
||||
if (index >= 0) {
|
||||
// Let the view know that this specific computer changed
|
||||
emit dataChanged(createIndex(index, 0), createIndex(index, 0));
|
||||
}
|
||||
else {
|
||||
// This is a new PC that will be inserted at the end
|
||||
beginInsertRows(QModelIndex(), m_Computers.count(), m_Computers.count());
|
||||
m_Computers.append(computer);
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
// Our view of the world must be in sync with ComputerManager's
|
||||
Q_ASSERT(m_Computers.count() == m_ComputerManager.getComputers().count());
|
||||
}
|
||||
|
31
app/gui/computermodel.h
Normal file
31
app/gui/computermodel.h
Normal file
@ -0,0 +1,31 @@
|
||||
#include "backend/computermanager.h"
|
||||
|
||||
#include <QAbstractListModel>
|
||||
|
||||
class ComputerModel : public QAbstractListModel
|
||||
{
|
||||
enum Roles
|
||||
{
|
||||
NameRole = Qt::UserRole,
|
||||
OnlineRole,
|
||||
PairedRole,
|
||||
BusyRole,
|
||||
AddPcRole
|
||||
};
|
||||
|
||||
public:
|
||||
ComputerModel(QObject* object = nullptr);
|
||||
|
||||
QVariant data(const QModelIndex &index, int role) const override;
|
||||
|
||||
int rowCount(const QModelIndex &parent) const override;
|
||||
|
||||
virtual QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
private slots:
|
||||
void handleComputerStateChanged(NvComputer* computer);
|
||||
|
||||
private:
|
||||
QVector<NvComputer*> m_Computers;
|
||||
ComputerManager m_ComputerManager;
|
||||
};
|
Before Width: | Height: | Size: 313 B After Width: | Height: | Size: 313 B |
Before Width: | Height: | Size: 273 B After Width: | Height: | Size: 273 B |
@ -7,59 +7,8 @@ ApplicationWindow {
|
||||
width: 640
|
||||
height: 480
|
||||
title: qsTr("Stack")
|
||||
color: "#333333"
|
||||
|
||||
header: ToolBar {
|
||||
contentHeight: toolButton.implicitHeight
|
||||
|
||||
ToolButton {
|
||||
id: toolButton
|
||||
text: stackView.depth > 1 ? "\u25C0" : "\u2630"
|
||||
font.pixelSize: Qt.application.font.pixelSize * 1.6
|
||||
onClicked: {
|
||||
if (stackView.depth > 1) {
|
||||
stackView.pop()
|
||||
} else {
|
||||
drawer.open()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
text: stackView.currentItem.title
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
}
|
||||
|
||||
Drawer {
|
||||
id: drawer
|
||||
width: window.width * 0.66
|
||||
height: window.height
|
||||
|
||||
Column {
|
||||
anchors.fill: parent
|
||||
|
||||
ItemDelegate {
|
||||
text: qsTr("Page 1")
|
||||
width: parent.width
|
||||
onClicked: {
|
||||
stackView.push("Page1Form.ui.qml")
|
||||
drawer.close()
|
||||
}
|
||||
}
|
||||
ItemDelegate {
|
||||
text: qsTr("Page 2")
|
||||
width: parent.width
|
||||
onClicked: {
|
||||
stackView.push("Page2Form.ui.qml")
|
||||
drawer.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StackView {
|
||||
id: stackView
|
||||
initialItem: "HomeForm.ui.qml"
|
||||
anchors.fill: parent
|
||||
PcView {
|
||||
}
|
||||
}
|
||||
|
@ -3,4 +3,4 @@
|
||||
; http://doc.qt.io/qt-5/qtquickcontrols2-configuration.html
|
||||
|
||||
[Controls]
|
||||
Style=Imagine
|
||||
Style=Material
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include <QGuiApplication>
|
||||
#include <QQmlApplicationEngine>
|
||||
|
||||
#include "backend/nvhttp.h"
|
||||
#include "gui/computermodel.h"
|
||||
|
||||
// Don't let SDL hook our main function, since Qt is already
|
||||
// doing the same thing
|
||||
@ -26,6 +26,9 @@ int main(int argc, char *argv[])
|
||||
|
||||
QGuiApplication app(argc, argv);
|
||||
|
||||
// Register our C++ types for QML
|
||||
qmlRegisterType<ComputerModel>("ComputerModel", 1, 0, "ComputerModel");
|
||||
|
||||
// Load the main.qml file
|
||||
QQmlApplicationEngine engine;
|
||||
engine.load(QUrl(QStringLiteral("qrc:/gui/main.qml")));
|
||||
|
@ -2,5 +2,8 @@
|
||||
<qresource prefix="/">
|
||||
<file>gui/main.qml</file>
|
||||
<file>gui/qtquickcontrols2.conf</file>
|
||||
<file>gui/PcView.qml</file>
|
||||
<file>gui/ic_tv_white_48px.svg</file>
|
||||
<file>gui/ic_add_to_queue_white_48px.svg</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
@ -1,10 +1,8 @@
|
||||
<RCC>
|
||||
<qresource prefix="/">
|
||||
<file>res/icon128.png</file>
|
||||
<file>res/ic_add_to_queue_white_48px.svg</file>
|
||||
<file>res/ic_remove_circle_outline_white_48px.svg</file>
|
||||
<file>res/ic_remove_from_queue_white_48px.svg</file>
|
||||
<file>res/ic_tv_white_48px.svg</file>
|
||||
<file>res/ic_videogame_asset_white_48px.svg</file>
|
||||
<file>res/no_app_image.png</file>
|
||||
</qresource>
|
||||
|
Loading…
x
Reference in New Issue
Block a user