1
0
Fork 0
mirror of synced 2024-06-22 16:20:32 +12:00

List view (beta)

This commit is contained in:
Dummerle 2021-03-08 15:07:07 +01:00
parent 48d175b66c
commit fc1c8ec031
8 changed files with 619 additions and 21 deletions

View file

@ -1,10 +1,10 @@
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import QSize
from PyQt5.QtGui import QIcon, QFont
from PyQt5.QtWidgets import QTabWidget, QTabBar, QWidget, QToolButton, QWidgetAction, QMenu
from legendary.core import LegendaryCore
from Rare import style_path
from Rare.Components.Tabs.Account.AccountWidget import MiniWidget
from Rare.Components.Tabs.CloudSaves.CloudSaves import SyncSaves
from Rare.Components.Tabs.Downloads.DownloadTab import DownloadTab
from Rare.Components.Tabs.Games.GamesTab import GameTab
from Rare.Components.Tabs.Settings.SettingsTab import SettingsTab
@ -25,8 +25,8 @@ class TabWidget(QTabWidget):
self.game_list.default_widget.game_list.install_game.connect(lambda x: self.downloadTab.install_game(x))
# Commented, because it is not finished
#self.cloud_saves = SyncSaves(core)
#self.addTab(self.cloud_saves, "Cloud Saves")
# self.cloud_saves = SyncSaves(core)
# self.addTab(self.cloud_saves, "Cloud Saves")
# Space Tab
self.addTab(QWidget(), "")
@ -34,11 +34,11 @@ class TabWidget(QTabWidget):
self.account = QWidget()
self.addTab(self.account, "")
self.setTabEnabled(disabled_tab+1, False)
self.setTabEnabled(disabled_tab + 1, False)
# self.settings = SettingsTab(core)
self.addTab(self.settings, QIcon(style_path + "/Icons/settings.png"), None)
self.setIconSize(QSize(25, 25))
self.tabBar().setTabButton(3, self.tabBar().RightSide, TabButtonWidget(core))
def resizeEvent(self, event):
@ -51,6 +51,8 @@ class TabBar(QTabBar):
super(TabBar, self).__init__()
self._expanded = expanded
self.setObjectName("main_tab_bar")
self.setFont(QFont("Arial", 13))
# self.setContentsMargins(0,10,0,10)
def tabSizeHint(self, index):
size = super(TabBar, self).tabSizeHint(index)
@ -70,6 +72,7 @@ class TabButtonWidget(QToolButton):
self.setIcon(QIcon(style_path + "/Icons/account.png"))
self.setToolTip("Account")
self.setIconSize(QSize(25, 25))
self.setMenu(QMenu())
action = QWidgetAction(self)
action.setDefaultWidget(MiniWidget(core))

View file

@ -1,9 +1,11 @@
from PyQt5.QtCore import Qt, pyqtSignal
from PyQt5.QtCore import Qt, pyqtSignal, QSettings
from PyQt5.QtWidgets import *
from legendary.core import LegendaryCore
from Rare.Components.Tabs.Games.GameWidgetInstalled import GameWidgetInstalled
from Rare.Components.Tabs.Games.GameWidgetListUninstalled import UninstalledGameWidget
from Rare.Components.Tabs.Games.GameWidgetUninstalled import GameWidgetUninstalled
from Rare.Components.Tabs.Games.InstalledListWidget import GameWidget
from Rare.utils.QtExtensions import FlowLayout
@ -20,22 +22,33 @@ class GameList(QScrollArea):
self.setWidgetResizable(True)
self.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.init_ui()
def init_ui(self):
self.settings = QSettings()
icon_view = self.settings.value("icon_view", True, bool)
self.init_ui(icon_view)
def init_ui(self, icon_view=True):
self.widget = QWidget()
self.widgets = []
self.layout = FlowLayout()
if icon_view:
self.layout = FlowLayout()
else:
self.layout = QVBoxLayout()
self.updates = []
# Installed Games
for game in sorted(self.core.get_installed_list(), key=lambda x: x.title):
widget = GameWidgetInstalled(self.core, game)
if icon_view:
widget = GameWidgetInstalled(self.core, game)
widget.show_info.connect(lambda app_name: self.show_game_info.emit(app_name))
else:
widget = GameWidget(game, self.core)
if widget.update_available:
self.updates.append(widget.game.app_name)
self.layout.addWidget(widget)
widget.update_list.connect(self.update_list)
widget.show_info.connect(lambda app_name: self.show_game_info.emit(app_name))
uninstalled_games = []
installed = [i.app_name for i in self.core.get_installed_list()]
@ -45,7 +58,10 @@ class GameList(QScrollArea):
uninstalled_games.append(game)
# add uninstalled to gui
for game in uninstalled_games:
widget = GameWidgetUninstalled(self.core, game)
if icon_view:
widget = GameWidgetUninstalled(self.core, game)
else:
widget = UninstalledGameWidget(self.core, game)
widget.install_game.connect(lambda options: self.install_game.emit(options))
self.layout.addWidget(widget)
self.widgets.append(widget)
@ -65,8 +81,9 @@ class GameList(QScrollArea):
for w in self.widgets:
w.setVisible(not i_o)
def update_list(self):
def update_list(self, icon_view=True):
print("Updating List")
self.settings.setValue("icon_view", icon_view)
self.setWidget(QWidget())
self.init_ui()
self.init_ui(icon_view)
self.update()

View file

@ -122,8 +122,3 @@ class Menu(QMenu):
self.addAction(self.tr("Game info"), lambda: self.action.emit("info"))
self.addAction(self.tr("Uninstall"), lambda: self.action.emit("uninstall"))
def info(self):
pass
def uninstall(self):
pass

View file

@ -0,0 +1,67 @@
import os
import subprocess
from logging import getLogger
from PyQt5.QtCore import QThread, pyqtSignal, QProcess, QSettings
from PyQt5.QtGui import QPixmap
from PyQt5.QtWidgets import QWidget, QLabel, QHBoxLayout, QVBoxLayout, QPushButton, QMessageBox
from legendary.core import LegendaryCore
from Rare.Components.Dialogs.InstallDialog import InstallDialog
logger = getLogger("Game")
class UninstalledGameWidget(QWidget):
install_game = pyqtSignal(dict)
def __init__(self, core: LegendaryCore, game):
super(UninstalledGameWidget, self).__init__()
self.title = game.app_title
self.app_name = game.app_name
self.version = game.app_version
self.layout = QHBoxLayout()
self.game = game
self.core = core
settings = QSettings()
IMAGE_DIR = settings.value("img_dir", os.path.expanduser("~/.cache/rare"), type=str)
if os.path.exists(f"{IMAGE_DIR}/{game.app_name}/UninstalledArt.png"):
pixmap = QPixmap(f"{IMAGE_DIR}/{game.app_name}/UninstalledArt.png")
pixmap = pixmap.scaled(120, 160)
self.image = QLabel()
self.image.setPixmap(pixmap)
self.layout.addWidget(self.image)
self.child_layout = QVBoxLayout()
self.title_label = QLabel(f"<h2>{self.title}</h2>")
self.app_name_label = QLabel(f"App Name: {self.app_name}")
self.version_label = QLabel(f"Version: {self.version}")
self.install_button = QPushButton(self.tr("Install"))
self.install_button.setFixedWidth(120)
self.install_button.clicked.connect(self.install)
self.child_layout.addWidget(self.title_label)
self.child_layout.addWidget(self.app_name_label)
self.child_layout.addWidget(self.version_label)
self.child_layout.addWidget(self.install_button)
self.child_layout.addStretch(1)
self.layout.addLayout(self.child_layout)
self.layout.addStretch(1)
self.setLayout(self.layout)
def install(self):
logger.info("Install " + self.game.app_title)
infos = InstallDialog().get_information()
if infos != 0:
path, max_workers = infos
self.install_game.emit({
"app_name": self.game.app_name,
"options": {
"path": path,
"max_workers": max_workers
}
})
# wait for update of legendary to get progress

View file

@ -1,3 +1,4 @@
from PyQt5.QtCore import QSettings
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QCheckBox, QLineEdit, QLabel, QPushButton, QStyle, \
QStackedLayout
@ -29,6 +30,7 @@ class Games(QWidget):
self.head_bar = GameListHeadBar()
self.head_bar.setObjectName("head_bar")
self.game_list = GameList(core)
self.head_bar.search_bar.textChanged.connect(
@ -41,6 +43,8 @@ class Games(QWidget):
self.layout.addWidget(self.head_bar)
self.layout.addWidget(self.game_list)
# self.layout.addStretch(1)
self.head_bar.view.stateChanged.connect(
lambda: self.game_list.update_list(not self.head_bar.view.isChecked()))
self.setLayout(self.layout)
@ -62,6 +66,7 @@ class GameListHeadBar(QWidget):
self.list_view = QLabel(self.tr("List view"))
self.layout.addWidget(self.list_view)
self.view = QCheckBox(self.tr("Icon view"))
self.view.setChecked(not QSettings().value("icon_view", True, bool))
self.layout.addWidget(self.view)
self.refresh_list = QPushButton()
self.refresh_list.setIcon(self.style().standardIcon(getattr(QStyle, "SP_BrowserReload"))) # Reload icon

View file

@ -0,0 +1,110 @@
import os
from logging import getLogger
from PyQt5.QtCore import QProcess, pyqtSignal, QSettings
from PyQt5.QtGui import QPixmap
from PyQt5.QtWidgets import QWidget, QHBoxLayout, QLabel, QPushButton, QStyle, QVBoxLayout
from legendary.core import LegendaryCore
from legendary.models.game import InstalledGame
from Rare.utils import LegendaryApi
logger = getLogger("GameWidget")
class GameWidget(QWidget):
proc: QProcess
signal = pyqtSignal(str)
update_list = pyqtSignal()
# TODO Repair
def __init__(self, game: InstalledGame, core: LegendaryCore):
super(GameWidget, self).__init__()
self.core = core
self.game = game
self.dev = core.get_game(self.game.app_name).metadata["developer"]
self.title = game.title
self.app_name = game.app_name
self.version = game.version
self.size = game.install_size
self.launch_params = game.launch_parameters
self.update_available = self.core.get_asset(self.game.app_name, True).build_version != game.version
settings = QSettings()
IMAGE_DIR = settings.value("img_dir", os.path.expanduser("~/.cache/rare"))
# self.dev =
self.game_running = False
self.layout = QHBoxLayout()
if os.path.exists(f"{IMAGE_DIR}/{game.app_name}/FinalArt.png"):
pixmap = QPixmap(f"{IMAGE_DIR}/{game.app_name}/FinalArt.png")
elif os.path.exists(f"{IMAGE_DIR}/{game.app_name}/DieselGameBoxTall.png"):
pixmap = QPixmap(f"{IMAGE_DIR}/{game.app_name}/DieselGameBoxTall.png")
elif os.path.exists(f"{IMAGE_DIR}/{game.app_name}/DieselGameBoxLogo.png"):
pixmap = QPixmap(f"{IMAGE_DIR}/{game.app_name}/DieselGameBoxLogo.png")
else:
logger.warning(f"No Image found: {self.game.title}")
pixmap = None
if pixmap:
pixmap = pixmap.scaled(180, 240)
self.image = QLabel()
self.image.setPixmap(pixmap)
self.layout.addWidget(self.image)
##Layout on the right
self.childLayout = QVBoxLayout()
play_icon = self.style().standardIcon(getattr(QStyle, 'SP_MediaPlay'))
settings_icon = self.style().standardIcon(getattr(QStyle, 'SP_DirIcon'))
self.title_widget = QLabel(f"<h1>{self.title}</h1>")
self.app_name_label = QLabel(self.app_name)
self.launch_button = QPushButton(play_icon, self.tr("Launch"))
self.launch_button.setObjectName("launch_game_button")
self.launch_button.setFixedWidth(120)
self.launch_button.clicked.connect(self.launch)
if os.name != "nt":
self.wine_rating = QLabel("Wine Rating: " + self.get_rating())
self.developer_label = QLabel(self.tr("Developer: ") + self.dev)
self.version_label = QLabel("Version: " + str(self.version))
self.size_label = QLabel(f"{self.tr('Installed size')}: {round(self.size / (1024 ** 3), 2)} GB")
self.childLayout.addWidget(self.title_widget)
self.childLayout.addWidget(self.launch_button)
self.childLayout.addWidget(self.app_name_label)
self.childLayout.addWidget(self.developer_label)
if os.name != "nt":
self.childLayout.addWidget(self.wine_rating)
self.childLayout.addWidget(self.version_label)
self.childLayout.addWidget(self.size_label)
self.childLayout.addStretch(1)
self.layout.addLayout(self.childLayout)
self.layout.addStretch(1)
self.setLayout(self.layout)
def launch(self, offline=False):
if not self.game_running:
logger.info("Launching " + self.game.title)
self.proc = LegendaryApi.launch_game(self.core, self.game.app_name, offline)
if not self.proc:
logger.error("Could not start process")
return
self.proc.finished.connect(self.finished)
self.launch_button.setText(self.tr("Game running"))
self.launch_button.setDisabled(True)
self.game_running = True
else:
self.launch_button.setText("Launch")
self.launch_button.setDisabled(False)
def finished(self, exit_code):
self.launch_button.setText("Launch")
logger.info(f"Game {self.title} finished with exit code {exit_code}")
self.game_running = False
def kill(self):
self.proc.terminate()
self.launch_button.setText("Launch")
self.game_running = False
logger.info("Killing Game")
def get_rating(self) -> str:
return "gold" # TODO

View file

@ -13,7 +13,7 @@ QTabBar{
QTabBar::tab#main_tab_bar {
border-bottom: none;
padding: 5px;
padding: 5px
}
QTabBar::tab:selected{
border-bottom: 2px solid white;

401
Rare/languages/de.ts Normal file
View file

@ -0,0 +1,401 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="de_DE">
<context>
<name>About</name>
<message>
<location filename="../Components/Tabs/Settings/About.py" line="12"/>
<source>Developer:</source>
<translation>Entwickler:</translation>
</message>
<message>
<location filename="../Components/Tabs/Settings/About.py" line="17"/>
<source>Legendary developer:</source>
<translation>Legendary Entwickler:</translation>
</message>
<message>
<location filename="../Components/Tabs/Settings/About.py" line="23"/>
<source>This is a beta version, so you can get bugs. If you get a bug, please report it by creating a Issue on &lt;a href=&apos;https://github.com/Dummerle/Rare/issues&apos;&gt;Github&lt;/a&gt;. You can also contact me on Discord (Dummerle#7419). If you have a feature request, please contact me</source>
<translation>Dies ist eine beta version, dementsprechend wird es Bugs geben. Wenn du einen bug findest, berichte mir davon, indem du einen Issue auf &lt;a href=&apos;https://github.com/Dummerle/Rare/issues&apos;&gt;Github&lt;/a&gt; erstellst oder du kontaktierst mich über Discord (Dummerle#7419). Auch wenn du gerne ein neues Feature haben möchtest, kontaktiere mich</translation>
</message>
</context>
<context>
<name>DownloadTab</name>
<message>
<location filename="../Components/Tabs/Downloads/DownloadTab.py" line="102"/>
<source>&lt;b&gt;WARNING&lt;/b&gt;: The progress bar is not implemented. It is normal, if there is no progress. The progress is visible in console, because Legendary prints output to console. A pull request is active to get output</source>
<translation>&lt;b&gt;Warnung&lt;/b&gt;: Die Anzeige ist noch nicht fertig. Es wird normal sein, wenn dort kein Fortschritt angezeigt wird. Dafür musst du in die Konsole schauen, da es in Legendary noch keine Möglichkeit gibt, die Ausgabe zu verarbeiten. Ein Pull Request ist eingereicht</translation>
</message>
<message>
<location filename="../Components/Tabs/Downloads/DownloadTab.py" line="109"/>
<source>No active Download</source>
<translation>Keine aktiven Downloads</translation>
</message>
<message>
<location filename="../Components/Tabs/Downloads/DownloadTab.py" line="120"/>
<source>No updates available</source>
<translation>Keine verfügbaren Updates</translation>
</message>
<message>
<location filename="../Components/Tabs/Downloads/DownloadTab.py" line="140"/>
<source>Download size is 0. Game already exists</source>
<translation>Downloadgröße ist 0. Spiel exitstiert bereits</translation>
</message>
<message>
<location filename="../Components/Tabs/Downloads/DownloadTab.py" line="158"/>
<source>Installation failed. See logs for more information</source>
<translation>Installation fehlgeschlagen. Siehe Log für mehr Informationen</translation>
</message>
<message>
<location filename="../Components/Tabs/Downloads/DownloadTab.py" line="171"/>
<source>Installation finished</source>
<translation>Installation abgeschlossen</translation>
</message>
<message>
<location filename="../Components/Tabs/Downloads/DownloadTab.py" line="172"/>
<source>Download of game </source>
<translation>Download des Spiels </translation>
</message>
<message>
<location filename="../Components/Tabs/Downloads/DownloadTab.py" line="176"/>
<source>Installing Game: No active download</source>
<translation>Zu installierendes Spiel: Kein aktiver Download</translation>
</message>
</context>
<context>
<name>GameListHeadBar</name>
<message>
<location filename="../Components/Tabs/Games/GamesTab.py" line="52"/>
<source>Installed only</source>
<translation>Nur installierte</translation>
</message>
<message>
<location filename="../Components/Tabs/Games/GamesTab.py" line="58"/>
<source>Search Game</source>
<translation>Spiel suchen</translation>
</message>
<message>
<location filename="../Components/Tabs/Games/GamesTab.py" line="62"/>
<source>List view</source>
<translation>Listenansicht</translation>
</message>
<message>
<location filename="../Components/Tabs/Games/GamesTab.py" line="64"/>
<source>Icon view</source>
<translation>Iconansicht</translation>
</message>
</context>
<context>
<name>GameWidgetInstalled</name>
<message>
<location filename="../Components/Tabs/Games/GameWidgetInstalled.py" line="35"/>
<source>Update available</source>
<translation>Update verfügbar</translation>
</message>
<message>
<location filename="../Components/Tabs/Games/GameWidgetInstalled.py" line="99"/>
<source>Game running</source>
<translation>Spiel läuft</translation>
</message>
<message>
<location filename="../Components/Tabs/Games/GameWidgetInstalled.py" line="108"/>
<source>Do you want to uninstall</source>
<translation>Möchtest du das Spiel deinstallieren: </translation>
</message>
</context>
<context>
<name>GameWidgetUninstalled</name>
<message>
<location filename="../Components/Tabs/Games/GameWidgetUninstalled.py" line="60"/>
<source>Install Game</source>
<translation>Spiel installieren</translation>
</message>
</context>
<context>
<name>ImportWidget</name>
<message>
<location filename="../Components/Dialogs/Login/ImportWidget.py" line="38"/>
<source>Appdata path: </source>
<translation>Appdata pfad: </translation>
</message>
</context>
<context>
<name>LaunchDialog</name>
<message>
<location filename="../Components/Launch/LaunchDialog.py" line="58"/>
<source>Launching Rare</source>
<translation>Starte Rare</translation>
</message>
<message>
<location filename="../Components/Launch/LaunchDialog.py" line="60"/>
<source>Logging in</source>
<translation>Einloggen</translation>
</message>
</context>
<context>
<name>LegendarySettings</name>
<message>
<location filename="../Components/Tabs/Settings/Legendary.py" line="18"/>
<source>Legendary settings</source>
<translation>Legendary Einstellungen</translation>
</message>
<message>
<location filename="../Components/Tabs/Settings/Legendary.py" line="27"/>
<source>Default installation directory</source>
<translation>Standard Installationsordner</translation>
</message>
<message>
<location filename="../Components/Tabs/Settings/Legendary.py" line="36"/>
<source>Max workers for Download (Less: slower download)(0: Default)</source>
<translation>Maximale Anzahl für Downloadprozesse (Weniger: Langsamer)(o: Default)</translation>
</message>
</context>
<context>
<name>LinuxSettings</name>
<message>
<location filename="../Components/Tabs/Settings/Linux.py" line="28"/>
<source>Default Wine Prefix</source>
<translation>Standard Wine Prefix</translation>
</message>
<message>
<location filename="../Components/Tabs/Settings/Linux.py" line="38"/>
<source>Default Wine executable</source>
<translation>Standard Wine zum ausführen</translation>
</message>
</context>
<context>
<name>LoginDialog</name>
<message>
<location filename="../Components/Dialogs/Login/LoginDialog.py" line="27"/>
<source>Select one option to Login</source>
<translation>Wähle eine Option zum einloggen</translation>
</message>
</context>
<context>
<name>Menu</name>
<message>
<location filename="../Components/Tabs/Games/GameWidgetInstalled.py" line="122"/>
<source>Game info</source>
<translation>Spielinformation</translation>
</message>
<message>
<location filename="../Components/Tabs/Games/GameWidgetInstalled.py" line="123"/>
<source>Uninstall</source>
<translation>Deinstallieren</translation>
</message>
</context>
<context>
<name>MiniWidget</name>
<message>
<location filename="../Components/Tabs/Account/AccountWidget.py" line="14"/>
<source>Logged in as </source>
<translation>Eingeloggt als </translation>
</message>
<message>
<location filename="../Components/Tabs/Account/AccountWidget.py" line="16"/>
<source>Account settings</source>
<translation>Accounteinstellungen</translation>
</message>
<message>
<location filename="../Components/Tabs/Account/AccountWidget.py" line="20"/>
<source>Logout</source>
<translation>Ausloggen</translation>
</message>
<message>
<location filename="../Components/Tabs/Account/AccountWidget.py" line="26"/>
<source>Do you really want to logout</source>
<translation>Möchtest du dich wirklich ausloggen</translation>
</message>
</context>
<context>
<name>PathEdit</name>
<message>
<location filename="../utils/QtExtensions.py" line="131"/>
<source>Select Path</source>
<translation>Wähle Pfad</translation>
</message>
<message>
<location filename="../utils/QtExtensions.py" line="144"/>
<source>Choose Path</source>
<translation>Wähle Pfad</translation>
</message>
</context>
<context>
<name>PathInputDialog</name>
<message>
<location filename="../Components/Dialogs/PathInputDialog.py" line="15"/>
<source>Select directory</source>
<translation>Wähle Ordner</translation>
</message>
</context>
<context>
<name>RareSettings</name>
<message>
<location filename="../Components/Tabs/Settings/Rare.py" line="19"/>
<source>Rare settings</source>
<translation>Rare Einstellungen</translation>
</message>
<message>
<location filename="../Components/Tabs/Settings/Rare.py" line="35"/>
<source>Image Directory</source>
<translation>Ordner für Bilder</translation>
</message>
<message>
<location filename="../Components/Tabs/Settings/Rare.py" line="68"/>
<source>Restart Application to activate changes</source>
<translation>Starte die App neu um die Änderungen zu aktivieren</translation>
</message>
</context>
<context>
<name>SyncSaves</name>
<message>
<location filename="../Components/Tabs/CloudSaves/CloudSaves.py" line="50"/>
<source>Cloud Saves</source>
<translation>Cloudspeicher</translation>
</message>
<message>
<location filename="../Components/Tabs/CloudSaves/CloudSaves.py" line="50"/>
<source>Found Saves for folowing Games</source>
<translation>Speicherstände für folgende Spiele gefunden</translation>
</message>
<message>
<location filename="../Components/Tabs/CloudSaves/CloudSaves.py" line="52"/>
<source>Sync all games</source>
<translation>Alle Spiele synchronisieren</translation>
</message>
<message>
<location filename="../Components/Tabs/CloudSaves/CloudSaves.py" line="62"/>
<source>No Games Found</source>
<translation>Keine Spiele gefunden</translation>
</message>
<message>
<location filename="../Components/Tabs/CloudSaves/CloudSaves.py" line="62"/>
<source>Your games don&apos;t support cloud save</source>
<translation>Deine Spiele unterstützen keine Cloudspeicherstände</translation>
</message>
<message>
<location filename="../Components/Tabs/CloudSaves/CloudSaves.py" line="89"/>
<source>Found no savepath</source>
<translation>Keinen Speicherort gefunden</translation>
</message>
<message>
<location filename="../Components/Tabs/CloudSaves/CloudSaves.py" line="89"/>
<source>No save path was found. Please select path or skip</source>
<translation>Kein Pfad zum speichern wurde gefunden. Wähle einen Pfad oder überspringe</translation>
</message>
</context>
<context>
<name>SyncWidget</name>
<message>
<location filename="../Components/Tabs/CloudSaves/SyncWidget.py" line="53"/>
<source>Path not found</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../Components/Tabs/CloudSaves/SyncWidget.py" line="67"/>
<source>Local Save date: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../Components/Tabs/CloudSaves/SyncWidget.py" line="70"/>
<source>No Local Save files</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../Components/Tabs/CloudSaves/SyncWidget.py" line="72"/>
<source>Cloud save date: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../Components/Tabs/CloudSaves/SyncWidget.py" line="74"/>
<source>No Cloud saves</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../Components/Tabs/CloudSaves/SyncWidget.py" line="78"/>
<source>Game is up to date</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../Components/Tabs/CloudSaves/SyncWidget.py" line="79"/>
<source>Upload anyway</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../Components/Tabs/CloudSaves/SyncWidget.py" line="80"/>
<source>Download anyway</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../Components/Tabs/CloudSaves/SyncWidget.py" line="82"/>
<source>Cloud save is newer</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../Components/Tabs/CloudSaves/SyncWidget.py" line="83"/>
<source>Download Cloud saves</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../Components/Tabs/CloudSaves/SyncWidget.py" line="87"/>
<source>Upload Saves</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../Components/Tabs/CloudSaves/SyncWidget.py" line="98"/>
<source>Local save is newer</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../Components/Tabs/CloudSaves/SyncWidget.py" line="99"/>
<source>Upload saves</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../Components/Tabs/CloudSaves/SyncWidget.py" line="103"/>
<source>Download saves</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../Components/Tabs/CloudSaves/SyncWidget.py" line="125"/>
<source>Change path</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../Components/Tabs/CloudSaves/SyncWidget.py" line="139"/>
<source>Uploading...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../Components/Tabs/CloudSaves/SyncWidget.py" line="147"/>
<source>Upload finished</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../Components/Tabs/CloudSaves/SyncWidget.py" line="155"/>
<source>Downloading...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../Components/Tabs/CloudSaves/SyncWidget.py" line="161"/>
<source>Download finished</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>TabWidget</name>
<message>
<location filename="../Components/TabWidget.py" line="21"/>
<source>Games</source>
<translation>Spiele</translation>
</message>
</context>
<context>
<name>UpdateWidget</name>
<message>
<location filename="../Components/Tabs/Downloads/DownloadTab.py" line="196"/>
<source>Update Game</source>
<translation>Spiel updaten</translation>
</message>
</context>
</TS>