Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Flatpak support #16

Merged
merged 55 commits into from
Aug 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
88c07bc
get list app flatpak
s384 Nov 21, 2023
b31fd58
check error list_inicio
s384 Nov 22, 2023
c33f132
Flatpak list
s384 Nov 22, 2023
3ec8394
Search work
s384 Nov 22, 2023
128dade
work select apps
s384 Nov 22, 2023
37d50e8
Install apps deb and flatpak
s384 Nov 23, 2023
eb9334e
Add Flatpak icon for Flatpak apps
xoascf Nov 23, 2023
849fab5
Get Flatpak app version
xoascf Nov 23, 2023
e3aa1f8
Add demoted actions, use version from git, cleanup
xoascf Nov 23, 2023
5163481
Demote Flatpak app installation
xoascf Nov 24, 2023
3e9ddf6
Demote Flatpak app listing
xoascf Nov 24, 2023
4d780c3
Simplify installed apps listing
xoascf Nov 24, 2023
ea57e33
Use lxml instead of bs4, UTF-8 encoding scraping
xoascf Nov 24, 2023
b843538
Create desktop-directories path after install
xoascf Nov 24, 2023
81d3d2b
Update svg.py
xoascf Nov 24, 2023
dd6624e
Use get_dl with JSON responses for Flatpak
xoascf Nov 24, 2023
93bf368
Make some links clickable
xoascf Nov 24, 2023
1fa12f3
Fix crashing when no network
xoascf Nov 24, 2023
e40fe8a
All links should open now
xoascf Nov 24, 2023
9ec79fc
Update translations
xoascf Nov 24, 2023
e319809
Add flatpak as .deb dependency
xoascf Nov 24, 2023
f8a25b4
Run flatpak commands as user
xoascf Nov 24, 2023
d24fd43
List apps installed deb and flatpak
s384 Nov 24, 2023
2b1c722
Add --dirty to git describe
xoascf Nov 29, 2023
b63cca8
Use --user for Flatpak
xoascf Nov 29, 2023
cdbbee3
Replace spaces with dashes in Flatpak names
xoascf Nov 29, 2023
995ad07
Use AppInfo class
xoascf Dec 1, 2023
af830e7
Fix searching within app description
xoascf Dec 1, 2023
f1b8b16
Remove language parameter
xoascf Dec 1, 2023
766c332
Update store.py
xoascf Dec 1, 2023
8cebf2b
delete unused variable contador_selected
s384 Dec 4, 2023
743d196
New design button change apps
s384 Feb 1, 2024
83c8585
Change debian svg by the official
s384 Feb 1, 2024
af891a8
Flatpak without text
s384 Feb 1, 2024
401105d
Create .editorconfig
xoascf Feb 3, 2024
b6697bd
Merge branch 'nightly' into flatpak
xoascf Feb 3, 2024
d086ed0
Ui btn uninstall
s384 Feb 15, 2024
c720566
Buttons in all cards
s384 Feb 27, 2024
b3cd7c2
Merge branch 'nightly' into flatpak
xoascf Mar 13, 2024
08c2642
Use 'with open' when writing files
xoascf Mar 13, 2024
5bcbe8c
Update pushButton text in cardg.py
xoascf Mar 13, 2024
3651331
Use built-in list for type hinting
xoascf Mar 13, 2024
4c429d0
Update demoted_actions.py
xoascf Mar 13, 2024
c917c04
Update debian.svg
xoascf Mar 13, 2024
1822995
Use new about window with credits effect
xoascf Mar 14, 2024
d53b1f3
Update about.py
xoascf Mar 14, 2024
331f25b
Add NoClickableStyle and ClickableList classes
xoascf Mar 14, 2024
61d1948
deleted meaningless variable
s384 Jun 6, 2024
f660ff0
Label version
s384 Jun 7, 2024
6b5e625
Method Uninstall app working
s384 Jun 10, 2024
347d37f
Card desgin when app is uninstalled
s384 Jun 11, 2024
0cda217
ProcessType by install and uninstall
s384 Jun 12, 2024
24605e5
Update scripts
xoascf Jun 12, 2024
b51213a
Merge branch 'nightly' into flatpak
xoascf Jun 12, 2024
62ae77e
Change buttons title bar
s384 Jun 28, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
root = true

[*]
end_of_line = lf

[*.py]
charset = utf-8
indent_style = tab
indent_size = 4
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
__pycache__
venv
virtualenv
.venv
.virtualenv
*.pyc
db.sqlite3
.idea
Expand Down
90 changes: 55 additions & 35 deletions deepinesStore/about.py
Original file line number Diff line number Diff line change
@@ -1,58 +1,78 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-

from PyQt5.Qt import Qt
from PyQt5 import QtWidgets, QtGui
from deepinesStore.core import tr, site, set_blur, get_app_icon
from deepinesStore.widgets import G, ContactListWidget, add_people_to_list
from PyQt5 import QtCore, QtGui, QtWidgets

authors = [G("Sebastian", "@SebTrujillo"), G("Amaro", "@xoascf")]
from deepinesStore.core import tr, get_app_icon, get_text_link, STORE_VERSION
from deepinesStore.widgets import G, add_people_to_list, LinkLabel, CreditsListWidget

design = [G("Freddy", "@Akibaillusion"), G("jhalo", "@jhalo"), G("André")]

people = [G("Car", "@Xhafas"),
G("Isaías", "@igatjens"), G("Jose", "@fenoll"), G("Hugo", "@geekmidget"),
G("Eli", "@RealAct"), G("Diego", "@s_d1112"), G("Filho", "@filhoarrais"), G("Bruno", "@bigbruno"),
G("Alvaro", "@G4SP3R"), G("Omi", "@peteromio"), G("Opik", "@Prophaniti"), G("Jose", "@jsiapodev"),
G("Jorge", "@seiyukaras"), G("N1coc4colA", "@n1coc4cola"), G("Oscar", "@oscararg"), G("Jorge", "@jotakenobi"),
G("Tomás", "@TomasWarynyca"), G("Edwinsiño", "@Shokatsuo"),
people = [G("Car", "@Xhafas"), G("Sebastian Trujillo", "@SebTrujillo"), G("Amaro Martínez", "@xoascf"),
G("Freddy", "@Akibaillusion"), G("jhalo", "@jhalo"),
G("Isaías Gätjens M", "@igatjens"), G("Jose Fenoll", "@fenoll"), G("Hugo Florentino", "@geekmidget"),
G("Eli", "@RealAct"), G("Diego", "@s_d1112"), G("Filho Arrais", "@filhoarrais"),
G("Alvaro Samudio", "@G4SP3R"), G("Omi", "@peteromio"), G("Opik", "@Prophaniti"), G("José Siapo", "@jsiapodev"),
G("Jorge Cabrera", "@seiyukaras"), G("N1coc4colA", "@n1coc4cola"), G("Oscar Ortiz", "@oscararg"), G("Jorge", "@jotakenobi"),
G("Tomás Warynyca", "@TomasWarynyca"), G("Edwinsiño C", "@Shokatsuo"),
]

class AboutDialog(QtWidgets.QDialog):
def __init__(self, parent=None):
super().__init__(parent)
self.resize(580, 480)
self.resize(380, 460)
icon = get_app_icon()
self.setWindowIcon(icon)
self.setModal(True)
self.setWindowFlag(QtCore.Qt.WindowContextHelpButtonHint, False)
self.setAutoFillBackground(True)
self.app_icon_btn = QtWidgets.QPushButton(self)
self.app_icon_btn.setEnabled(True)
self.app_icon_btn.setIconSize(QtCore.QSize(120, 120))
self.app_icon_btn.setFlat(True)
self.app_icon_btn.setFocusPolicy(QtCore.Qt.FocusPolicy.NoFocus)
self.app_icon_btn.setIcon(icon)
self.app_icon_btn.setStyleSheet("background-color: transparent;")

self.app_icon_btn.installEventFilter(self)
self.app_name_lbl = QtWidgets.QLabel(self)
self.version_lbl = QtWidgets.QLabel(self)
self.version_lbl.setAlignment(QtCore.Qt.AlignCenter)
self.web_lbl = LinkLabel(self)
self.web_lbl.setAlignment(QtCore.Qt.AlignCenter)
self.web_lbl.setTextInteractionFlags(QtCore.Qt.TextBrowserInteraction)
font = QtGui.QFont()
font.setBold(True)
font.setPointSize(10)
self.app_name_lbl.setFont(font)
self.app_name_lbl.setAlignment(QtCore.Qt.AlignCenter)
self.description_lbl = QtWidgets.QLabel(self)
font.setBold(False)
self.description_lbl.setFont(font)
self.description_lbl.setAlignment(QtCore.Qt.AlignCenter)

list_ppl = CreditsListWidget()
self.pplP = add_people_to_list(people, list_ppl)
fntLst = QtGui.QFont()
fntLst.setPointSize(11)
layout = QtWidgets.QHBoxLayout()
list_dev = ContactListWidget()
list_des = ContactListWidget()
list_ppl = ContactListWidget()
self.devP = add_people_to_list(authors, list_dev)
self.desP = add_people_to_list(design, list_des)
self.pplP = add_people_to_list(people, list_ppl)
self.devP.setFont(fntLst)
self.desP.setFont(fntLst)
self.pplP.setFont(fntLst)
layout.addWidget(self.devP)
layout.addWidget(self.desP)
layout.addWidget(self.pplP)
list_ppl.setFont(fntLst)

layout = QtWidgets.QVBoxLayout(self)
layout.addWidget(self.app_icon_btn)
layout.addWidget(self.app_name_lbl)
layout.addWidget(self.version_lbl)
layout.addWidget(list_ppl)
layout.addWidget(self.web_lbl)
layout.addWidget(self.description_lbl)
self.setLayout(layout)
self.setStyleSheet("background-color: rgba(20, 20, 20, 100)")
self.setAttribute(Qt.WA_TranslucentBackground)
self.retranslateUi(self)

def showEvent(self, event):
set_blur(self)
self.retranslateUi(self) # TODO: Add translator credits.
QtCore.QMetaObject.connectSlotsByName(self)

def __tr(self, txt, disambiguation=None, n=-1):
return tr(self, txt, disambiguation, n)

def retranslateUi(self, AboutDialog):
self.setWindowTitle(self.__tr("About"))
self.devP.setTitle(self.__tr("Authors"))
self.desP.setTitle(self.__tr("Design"))
self.pplP.setTitle(self.__tr("Collaborators"))
self.app_name_lbl.setText(AboutDialog.parent().windowTitle())
self.version_lbl.setText(self.__tr("Version {version}").format(version=STORE_VERSION))
self.web_lbl.setText(get_text_link("deepinenespañol.org"))
self.description_lbl.setText(self.__tr("The App Store of Deepin en Español"))
24 changes: 24 additions & 0 deletions deepinesStore/app_info.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
from enum import Enum


class AppType(Enum):
DEB_PACKAGE = 0
FLATPAK_APP = 1


class AppState(Enum):
SELECTED = 0
DEFAULT = 1
INSTALLED = 2
UNINSTALLED = 3


class AppInfo:
def __init__(self, name: str, id: str, description: str, version = "0", category = "otros", type=AppType.DEB_PACKAGE, state=AppState.DEFAULT):
self.name = name
self.id = id
self.description = description
self.version = version
self.category = category
self.state = state
self.type = type
39 changes: 14 additions & 25 deletions deepinesStore/cardg.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,10 @@
# -*- coding: utf-8 -*-

# UI Source 'gui/card.ui'

from PyQt5 import QtGui, QtWidgets
from PyQt5.QtCore import QMetaObject, QSize, Qt, pyqtSignal
from PyQt5.QtCore import QMetaObject, QSize, Qt


class QLabelClickable(QtWidgets.QLabel):

clicked = pyqtSignal()
def __init__(self, *args):
QtWidgets.QLabel.__init__(self, *args)
def mouseReleaseEvent(self, ev):
self.clicked.emit()
from deepinesStore.widgets import ClickableLabel


class Ui_Frame(object):
Expand All @@ -24,38 +16,36 @@ def setupUi(self, Frame):
self.verticalLayout = QtWidgets.QVBoxLayout(Frame)
self.verticalLayout.setContentsMargins(0, 0, 0, 0)
self.verticalLayout.setSpacing(0)
self.verticalLayout.setObjectName("verticalLayout")
self.image_app = QLabelClickable(Frame)
self.image_app = ClickableLabel(Frame)
self.image_app.setText("")
self.image_app.setScaledContents(True)
self.image_app.setAlignment(Qt.AlignCenter)
self.image_app.setCursor(QtGui.QCursor(Qt.PointingHandCursor))
self.image_app.setObjectName("image_app")
self.image_app.setStyleSheet("#image_app{margin-top: 10px;}")
self.verticalLayout.addWidget(self.image_app)
self.lbl_name_app = QLabelClickable(Frame)
self.lbl_name_app = ClickableLabel(Frame)
self.lbl_name_app.setStyleSheet("background-color: transparent;" "margin-top:5px;")
self.lbl_name_app.setText("")
self.lbl_name_app.setAlignment(Qt.AlignCenter)
self.lbl_name_app.setCursor(QtGui.QCursor(Qt.PointingHandCursor))
font = QtGui.QFont()
font.setFamily("Segoe UI Semibold")
font.setPointSize(11)
font.setItalic(False)
self.lbl_name_app.setFont(font)
self.lbl_name_app.setWordWrap(True)
self.lbl_name_app.setObjectName("lbl_name_app")
self.verticalLayout.addWidget(self.lbl_name_app)
self.btn_select_app = QLabelClickable(Frame)
self.lbl_version = ClickableLabel(Frame)
font = QtGui.QFont()
font.setFamily("Segoe UI Semibold")
font.setPointSize(9)
font.setItalic(False)
self.btn_select_app.setFont(font)
self.btn_select_app.setWordWrap(True)
self.btn_select_app.setAlignment(Qt.AlignCenter)
self.btn_select_app.setCursor(QtGui.QCursor(Qt.PointingHandCursor))
self.btn_select_app.setObjectName("btn_select_app")
self.lbl_version.setFont(font)
self.lbl_version.setWordWrap(True)
self.lbl_version.setAlignment(Qt.AlignCenter)
self.lbl_version.setObjectName("lbl_version")
self.verticalLayout.addWidget(self.lbl_version)
self.btn_select_app = QtWidgets.QPushButton(Frame)
self.btn_select_app.setObjectName(u"btn_select_app")
self.btn_select_app.setMinimumSize(QSize(100, 30))
self.verticalLayout.addWidget(self.btn_select_app)

self.retranslateUi(Frame)
Expand All @@ -66,5 +56,4 @@ def __tr(self, txt, disambiguation=None, n=-1):
return tr(self, txt, disambiguation, n)

def retranslateUi(self, Frame):
Frame.setWindowTitle(self.__tr("Card"))
self.btn_select_app.setText(self.__tr("Install"))
self.btn_select_app.setText(self.__tr("Select"))
75 changes: 58 additions & 17 deletions deepinesStore/core.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,18 @@
STORE_VERSION = '[VERSION]' # TODO: Use Git Hash as fallback.
from enum import Enum
from os import environ as env, name
import argparse
import json


def get_ver():
version = '[VERSION]'
if "VERSION" in version:
import subprocess
version = subprocess.check_output(["git", "describe", "--dirty"]).strip().decode("utf-8")
return version


STORE_VERSION = get_ver()
BASE_URI = 'https://repositorio.deepines.com'


Expand All @@ -15,38 +29,42 @@ def get_app_icon():
def get_dl(uri, params=None, **kwargs):
from requests import get
try:
return get(uri, params=params, **kwargs)
response = get(uri, params=params, **kwargs)
response.raise_for_status()
return response
except Exception as e:
print(f'DL ERROR: {type(e).__name__}, URI: {uri}')
from sys import stderr
print(f'DL ERROR: {type(e).__name__}, URI: {uri}', file=stderr)

class DummyResponse:
status_code = None
content = b''
text = '' # FIXME: Use some kind of fallback for this, a text file maybe?
text = ''
def json(self): return {}
return DummyResponse()


def basic_uri_join(base_uri, *args):
base_uri = base_uri.strip().rstrip('/')
relative_paths = [path.strip().lstrip('/') for path in args]
def uri_join(base_uri, *args):
base_uri = base_uri.rstrip('/')
relative_paths = list(map(lambda x: x.lstrip('/'), args))
return f"{base_uri}/{'/'.join(relative_paths)}"


def get_deepines_uri(rel_uri):
return basic_uri_join(BASE_URI, 'pub', 'deepines', rel_uri)
return uri_join(BASE_URI, 'pub', 'deepines', rel_uri)

def get_text_link(text, uri=None):
if uri is None:
if text.startswith("@"):
uri = f"https://t.me/{text[1:]}"
else:
uri = f"https://{text}"
return f"<a href='{uri}' style='text-decoration: none; color: #004EE5;'>{text}</a>"

def tr(m, txt, disambiguation=None, n=-1):
from PyQt5.QtCore import QCoreApplication
return QCoreApplication.translate(m.__class__.__name__, txt, disambiguation, n)


def site():
# FIXME: It copies the link, need to open browser instead.
from PyQt5.QtWidgets import QApplication
QApplication.clipboard().setText('https://deepinenespañol.org')


def set_blur(win):
import platform
if platform.system() == 'Windows':
Expand All @@ -57,5 +75,28 @@ def set_blur(win):


def write(b, to):
# wb should work with text and binary, keeps newlines.
open(to, 'wb').write(b.content)
with open(to, 'wb') as ftw:
ftw.write(b.content)


if name == 'nt':
try:
from ctypes import windll
windll.shell32.SetCurrentProcessExplicitAppUserModelID('Deepines Store')
except AttributeError:
# Not available?
pass

parser = argparse.ArgumentParser()
parser.add_argument("--env", help="Serialized user environment as JSON")
args = parser.parse_args()

default_env = env.copy()

if args.env:
new_env = json.loads(args.env)
default_env.update(new_env)

class ProcessType(Enum):
INSTALL = 0
UNINSTALL = 1
43 changes: 43 additions & 0 deletions deepinesStore/deb/get_apps_deb.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
from lxml import html
import re

from deepinesStore.app_info import AppInfo
from deepinesStore.core import get_deepines_uri, get_dl


def get_repo_url():
fallback_url = get_deepines_uri("/5/paquetes.html")
repo_file = "/etc/apt/sources.list.d/deepines.list"
try:
repo_text = open(repo_file).read()
url = re.search(
"(?P<url>https?://[^\s]+)", repo_text).group("url") + "paquetes.html"
return url
except:
return fallback_url


def fetch_list_app_deb(list_ignored: list[str]) -> list[AppInfo]:
repo_url = get_repo_url()
request = get_dl(repo_url, timeout=10)

if request.status_code == 200:
html_tree = html.fromstring(request.content.decode("utf-8"))
entries = html_tree.xpath('//tr')
deb_app_info = []

def from_cell(entry, class_name: str):
return entry.xpath(f'.//td[@class="{class_name}"]/text()')[0].strip()

for entry in entries:
app_title = from_cell(entry, 'package')
if app_title not in list_ignored:
app_info = AppInfo(app_title, app_title, from_cell(
entry, 'description'), from_cell(entry, 'version'), from_cell(entry, 'section'))
deb_app_info.append(app_info)

return deb_app_info
else:
print(
f"App list fetch request has failed with status code {request.status_code}")
return []
Loading