Commit 52e6e7d1 authored by librebob's avatar librebob

initial commit.

parents
*.qmlc
*.pyc
designs/
libs/
/__pycache__
*.db
s.py
import QtQuick 2.6
import QtQuick.Controls 2.4
import QtQuick.Controls.Material 2.4
import QtQuick.Layouts 1.11
import Example 1.0
// signal messageReceived(string person, string notice)
Page {
id: libraryView
property color bg : '#202228'
property color sel: '#4d84c7'
property color hl: '#314661'
property color fg: '#2d3139'
property color tc: '#caccd1'
background: Rectangle {
anchors.fill: parent
color: bg
}
header: ToolBar {
id: toolBar
RowLayout {
spacing: 0
anchors.fill: parent
TextField {
placeholderText: 'Search...'
// background: Rectangle {
// anchors.fill: parent
// color: 'red'
// implicitWidth: 200
// }
Layout.fillHeight: true
}
Label {
background: Rectangle {
anchors.fill: parent
color: fg
}
color: tc
text: "Library"
elide: Label.ElideRight
horizontalAlignment: Qt.AlignHCenter
verticalAlignment: Qt.AlignVCenter
Layout.fillWidth: true
Layout.fillHeight: true
}
ToolButton {
contentItem: Text {
text: qsTr("")
color: tc
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
background: Rectangle {
anchors.fill: parent
color: fg
implicitWidth: 40
implicitHeight: 40
}
// Layout.fillWidth: true
Layout.fillHeight: true
// onClicked: menu.open()
}
// ToolButton {
// text: qsTr("‹")
// onClicked: stack.pop()
// }
}
}
ListView {
id: listView
anchors.top: parent.top
anchors.bottom: parent.bottom
model: library.games
width: 200
ScrollBar.vertical: ScrollBar { }
boundsBehavior: Flickable.StopAtBounds
delegate: Component {
id: delegateComponent
Rectangle {
anchors.left: parent.left
anchors.right: parent.right
height: 40
id: rect
border.color: bg
border.width: 1
// color: Qt.rgba(Math.random(),Math.random(),Math.random(),1)
MouseArea {
anchors.fill: parent
onClicked: {
window.indexUpdated(index)
listView.currentIndex = index
// stackView.push(gameView)
// currentItem.color = '#4d84c7';
// listView.currentItem.color = '#4d84c7';
// console.log(listView.currentItem)
// console.log(rect.GridView.isCurrentItem)
// console.log(ListView.isCurrentItem)
// console.log(listView.isCurrentItem)
// console.log(delegateComponent.GridView.isCurrentItem)
// console.log(delegateComponent.isCurrentItem)
}
id: itemMouseArea
hoverEnabled: true
}
// color:
color: ListView.isCurrentItem ? sel : itemMouseArea.containsMouse ? hl : fg
Image {
id: gameIcon
// anchors.horizontalCenter: parent.horizontalCenter
// anchors.verticalCenter: parent.verticalCenter
anchors.top: parent.top
anchors.bottom: parent.bottom
fillMode: Image.PreserveAspectFit
source: icon
}
Text {
// anchors.horizontalCenter: parent.horizontalCenter
color: tc
clip: true
width: parent.width
anchors.bottom: parent.bottom
// wrapMode: Text.WordWrap
text: name
// horizontalAlignment: Text.AlignHCenter
leftPadding: gameIcon.width + 2
bottomPadding: 2
}
}
}
}
ScrollView {
anchors.left: listView.right
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.top: parent.top
Column {
// anchors.fill: parent
Row {
anchors.right: parent.right
anchors.left: parent.left
padding: 40
spacing: 40
Image {
width: 128
height: 128
// anchors.horizontalCenter: parent.horizontalCenter
// anchors.verticalCenter: parent.verticalCenter
// anchors.left: parent.right
// anchors.bottom: parent.bottom
fillMode: Image.PreserveAspectFit
source: library.currentGame.icon
}
Column {
Text {
color: tc
// fontSizeMode: Text.HorizontalFit
text: library.currentGame.name
font.pixelSize: 56
horizontalAlignment: Text.AlignLeft
}
Text {
color: tc
text: library.currentGame.id
font.pixelSize: 16
// leftPadding: 4
horizontalAlignment: Text.AlignLeft
}
Row {
spacing: 5
topPadding: 4
Button {
text: 'Install'
visible: !library.currentGame.installed
onClicked: {
window.installGame(library.currentGame.id)
}
}
Button {
text: 'Play'
enabled: !library.currentGame.playing
onClicked: {
window.playGame(library.currentGame.id)
}
background: Rectangle {
implicitWidth: 100
implicitHeight: 40
color: library.currentGame.playing ? 'lightgreen' : 'lightblue'
}
visible: library.currentGame.installed
}
Button {
text: 'Uninstall'
visible: library.currentGame.installed
onClicked: {
window.uninstallGame()
}
background: Rectangle {
implicitWidth: 100
implicitHeight: 40
MouseArea {
id: uninstallMouseArea
anchors.fill: parent
hoverEnabled: true
}
color: uninstallMouseArea.containsMouse ? 'lightcoral' : '#e0e0e0'
}
}
}
}
}
// ScrollView {
// height: 400
// width: parent.width
// TextArea {
// width: parent.width
// color: "ghostwhite"
// readOnly: true
// text: library.log
//
// background: Rectangle {
// anchors.fill: parent
// color: "darkslategrey"
//
// }
// }
// }
}
}
}
import signal
import io
import datetime
from sys import argv
from PyQt5.QtCore import QObject, QTimer, pyqtProperty, pyqtSignal, QThread
from PyQt5.QtGui import QGuiApplication
from PyQt5.QtQml import QQmlListProperty, QQmlApplicationEngine, qmlRegisterType, qmlRegisterSingletonType
from peewee import SqliteDatabase
from peewee import DoesNotExist
# Local imports
import appstream
from threads import PlayThread
from threads import InstallThread
from models import GameRecord, db
class Game(QObject):
idChanged = pyqtSignal()
nameChanged = pyqtSignal()
iconChanged = pyqtSignal()
logsChanged = pyqtSignal()
refChanged = pyqtSignal()
playingChanged = pyqtSignal()
installedChanged = pyqtSignal()
installingChanged = pyqtSignal()
def __init__(self, id='', name='', icon='', ref='', installed=False, *args, **kwargs):
super().__init__(*args, **kwargs)
# Persisted values
self._id = id
self._name = name
self._icon = icon
self._ref = ref
self._installed = installed
# Dynamic values
self._playing = False
self._installing = False
@pyqtProperty('QString', notify=idChanged)
def id(self):
return self._id
@id.setter
def id(self, id):
if id != self._id:
self._id = id
self.idChanged.emit()
@pyqtProperty('QString', notify=nameChanged)
def name(self):
return self._name
@name.setter
def name(self, name):
if name != self._name:
self._name = name
self.nameChanged.emit()
@pyqtProperty('QString', notify=iconChanged)
def icon(self):
return self._icon
@icon.setter
def icon(self, icon):
if icon != self._icon:
self._icon = icon
self.iconChanged.emit()
@pyqtProperty('QString', notify=refChanged)
def ref(self):
return self._ref
@ref.setter
def ref(self, ref):
if ref != self._ref:
self._ref = ref
self.refChanged.emit()
@pyqtProperty(bool, notify=playingChanged)
def playing(self):
return self._playing
@playing.setter
def playing(self, playing):
self._playing = playing
self.playingChanged.emit()
@pyqtProperty(bool, notify=installedChanged)
def installed(self):
return self._installed
@installed.setter
def installed(self, installed):
self._installed = installed
self.installedChanged.emit()
@pyqtProperty(bool, notify=installingChanged)
def installing(self):
return self._installing
@installing.setter
def installing(self, installing):
self._installing = installing
self.installingChanged.emit()
class Library(QObject):
libraryChanged = pyqtSignal()
currentGameChanged = pyqtSignal()
logChanged = pyqtSignal()
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._games = []
self._currentGame = Game()
self._log = ''
self._threads = []
stream = appstream.Store()
stream.from_file('/var/lib/flatpak/appstream/flathub/x86_64/active/appstream.xml.gz')
for component in stream.get_components():
if component.project_license and not 'LicenseRef-proprietary' in component.project_license:
if 'Game' in component.categories:
try:
gr = GameRecord.get(GameRecord.id == component.id)
except DoesNotExist:
gr = None
self.appendGame(Game(component.id, component.name, self.getIcon(component.icons), component.bundle['value'], gr.installed if gr else False))
self._currentGame = self._games[0]
def getIcon(self, icons):
cached_icon = icons['cached'][0]
if cached_icon['height'] == '128':
return '/var/lib/flatpak/appstream/flathub/x86_64/active/icons/128x128/' + cached_icon['value']
elif cached_icon['height'] == '64':
return '/var/lib/flatpak/appstream/flathub/x86_64/active/icons/64x64/' + cached_icon['value']
def findById(self, game_id):
for game in self.games:
if game.id == game_id:
return game
return None
@pyqtProperty(Game, notify=currentGameChanged)
def currentGame(self):
return self._currentGame
@currentGame.setter
def currentGame(self, game):
if game != self._currentGame:
self._currentGame = game
self.currentGameChanged.emit()
@pyqtProperty(str, notify=logChanged)
def log(self):
return self._log
@log.setter
def log(self, data):
if data:
self._log += data
self.logChanged.emit()
@pyqtProperty(QQmlListProperty, notify=libraryChanged)
def games(self):
return QQmlListProperty(Game, self, self._games)
@games.setter
def games(self, games):
if games != self._games:
self._games = games
self.libraryChanged.emit()
def appendGame(self, game):
self._games.append(game)
self.libraryChanged.emit()
def indexUpdated(self, index):
self.currentGame = self._games[index]
def installGame(self, game_id):
self._currentGame.installing = True
installThread = InstallThread(self._currentGame.ref)
installThread.outputChanged.connect(self.updateLog)
installThread.finished.connect(self.installFinished)
installThread.start()
self._threads.append(installThread)
def installFinished(self):
self._currentGame.installing = False
self._currentGame.installed = True
(GameRecord.replace(
id=self._currentGame.id,
installed=self._currentGame.installed,
modified_date=datetime.datetime.now()
).execute())
self._log = '';
self.logChanged.emit()
def playGame(self, game_id):
self._currentGame.playing = True
playThread = PlayThread(self._currentGame.ref)
playThread.finished.connect(self.stopGame)
playThread.start()
self._threads.append(playThread)
print('run game')
def stopGame(self):
self._currentGame.playing = False
print('stop game')
# def logClear(self):
def updateLog(self, data):
print(data)
self.log = data
# class Loader():
def main():
signal.signal(signal.SIGINT, signal.SIG_DFL)
print('Press Ctrl+C')
db.connect()
db.create_tables([GameRecord], safe=True)
app = QGuiApplication(argv)
qmlRegisterType(Game, 'Example', 1, 0, 'Game')
qmlRegisterType(Library, 'Example', 1, 0, 'Library')
# qmlRegisterSingletonType()
library = Library()
engine = QQmlApplicationEngine()
engine.rootContext().setContextProperty('library', library)
engine.load('main.qml')
engine.rootObjects()[0].indexUpdated.connect(library.indexUpdated)
engine.rootObjects()[0].installGame.connect(library.installGame)
engine.rootObjects()[0].playGame.connect(library.playGame)
exit(app.exec_())
if __name__ == '__main__':
main()
import QtQuick 2.6
import QtQuick.Controls 2.4
import QtQuick.Layouts 1.11
import Example 1.0
// property Item item0: Library
// property alias libview: Library
ApplicationWindow {
id: window
signal indexUpdated(int index)
signal installGame(string id)
signal playGame(string id)
width: 1000
height: 700
visible: true
// property Component gameView: GameView{}
property Component libraryView: LibraryView{}
StackView {
id: stackView
anchors.fill: parent
initialItem: libraryView
}
}
from peewee import *
import datetime
db = SqliteDatabase('store.db')
class BaseModel(Model):
class Meta:
database = db
class GameRecord(BaseModel):
id = CharField(unique=True)
installed = BooleanField(default=False)
created_date = DateTimeField(default=datetime.datetime.now)
modified_date = DateTimeField()
import io
from PyQt5.QtCore import pyqtSignal, QThread
from subprocess import Popen, PIPE
from time import sleep
class InstallThread(QThread):
outputChanged = pyqtSignal('QString')
def __init__(self, game_id, game_ref):
QThread.__init__(self)
self._game_id = game_id
self._game_ref = game_ref
def __del__(self):
self.wait()
def run(self):
process = Popen(['flatpak', 'install', 'flathub', self._game_ref, '-y'], stdout=PIPE, stderr=PIPE)
for output in io.TextIOWrapper(process.stdout, encoding="utf-8"):
self.outputChanged.emit(output)
for output in io.TextIOWrapper(process.stderr, encoding="utf-8"):
self.outputChanged.emit(output)
sleep(1)
class PlayThread(QThread):
def __init__(self, game_id, game_ref):
QThread.__init__(self)
self._game_id = game_id
self._game_ref = game_ref
def __del__(self):
self.wait()
def run(self):
process = Popen(['flatpak', 'run', self._game_ref], stdout=PIPE, stderr=PIPE)
process.wait()
sleep(1)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment