Compare commits
No commits in common. "debian/latest" and "pristine-tar" have entirely different histories.
debian/lat
...
pristine-t
|
@ -1,145 +0,0 @@
|
|||
# Created by .ignore support plugin (hsz.mobi)
|
||||
### Python template
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
share/python-wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
MANIFEST
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.nox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
*.py,cover
|
||||
.hypothesis/
|
||||
.pytest_cache/
|
||||
cover/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
local_settings.py
|
||||
db.sqlite3
|
||||
db.sqlite3-journal
|
||||
|
||||
# Flask stuff:
|
||||
instance/
|
||||
.webassets-cache
|
||||
|
||||
# Scrapy stuff:
|
||||
.scrapy
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
.pybuilder/
|
||||
target/
|
||||
|
||||
# Jupyter Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# IPython
|
||||
profile_default/
|
||||
ipython_config.py
|
||||
|
||||
# pyenv
|
||||
# For a library or package, you might want to ignore these files since the code is
|
||||
# intended to run in multiple environments; otherwise, check them in:
|
||||
# .python-version
|
||||
|
||||
# pipenv
|
||||
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||
# install all needed dependencies.
|
||||
#Pipfile.lock
|
||||
|
||||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
|
||||
__pypackages__/
|
||||
|
||||
# Celery stuff
|
||||
celerybeat-schedule
|
||||
celerybeat.pid
|
||||
|
||||
# SageMath parsed files
|
||||
*.sage.py
|
||||
|
||||
# Environments
|
||||
.env
|
||||
.venv
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
env.bak/
|
||||
venv.bak/
|
||||
|
||||
# Spyder project settings
|
||||
.spyderproject
|
||||
.spyproject
|
||||
|
||||
# Rope project settings
|
||||
.ropeproject
|
||||
|
||||
# mkdocs documentation
|
||||
/site
|
||||
|
||||
# mypy
|
||||
.mypy_cache/
|
||||
.dmypy.json
|
||||
dmypy.json
|
||||
|
||||
# Pyre type checker
|
||||
.pyre/
|
||||
|
||||
# pytype static type analyzer
|
||||
.pytype/
|
||||
|
||||
# Cython debug symbols
|
||||
cython_debug/
|
||||
|
||||
/.idea
|
||||
/build
|
||||
/*.gresource
|
||||
*~
|
165
LICENSE
165
LICENSE
|
@ -1,165 +0,0 @@
|
|||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
||||
This version of the GNU Lesser General Public License incorporates
|
||||
the terms and conditions of version 3 of the GNU General Public
|
||||
License, supplemented by the additional permissions listed below.
|
||||
|
||||
0. Additional Definitions.
|
||||
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||
General Public License.
|
||||
|
||||
"The Library" refers to a covered work governed by this License,
|
||||
other than an Application or a Combined Work as defined below.
|
||||
|
||||
An "Application" is any work that makes use of an interface provided
|
||||
by the Library, but which is not otherwise based on the Library.
|
||||
Defining a subclass of a class defined by the Library is deemed a mode
|
||||
of using an interface provided by the Library.
|
||||
|
||||
A "Combined Work" is a work produced by combining or linking an
|
||||
Application with the Library. The particular version of the Library
|
||||
with which the Combined Work was made is also called the "Linked
|
||||
Version".
|
||||
|
||||
The "Minimal Corresponding Source" for a Combined Work means the
|
||||
Corresponding Source for the Combined Work, excluding any source code
|
||||
for portions of the Combined Work that, considered in isolation, are
|
||||
based on the Application, and not on the Linked Version.
|
||||
|
||||
The "Corresponding Application Code" for a Combined Work means the
|
||||
object code and/or source code for the Application, including any data
|
||||
and utility programs needed for reproducing the Combined Work from the
|
||||
Application, but excluding the System Libraries of the Combined Work.
|
||||
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
|
||||
You may convey a covered work under sections 3 and 4 of this License
|
||||
without being bound by section 3 of the GNU GPL.
|
||||
|
||||
2. Conveying Modified Versions.
|
||||
|
||||
If you modify a copy of the Library, and, in your modifications, a
|
||||
facility refers to a function or data to be supplied by an Application
|
||||
that uses the facility (other than as an argument passed when the
|
||||
facility is invoked), then you may convey a copy of the modified
|
||||
version:
|
||||
|
||||
a) under this License, provided that you make a good faith effort to
|
||||
ensure that, in the event an Application does not supply the
|
||||
function or data, the facility still operates, and performs
|
||||
whatever part of its purpose remains meaningful, or
|
||||
|
||||
b) under the GNU GPL, with none of the additional permissions of
|
||||
this License applicable to that copy.
|
||||
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
|
||||
The object code form of an Application may incorporate material from
|
||||
a header file that is part of the Library. You may convey such object
|
||||
code under terms of your choice, provided that, if the incorporated
|
||||
material is not limited to numerical parameters, data structure
|
||||
layouts and accessors, or small macros, inline functions and templates
|
||||
(ten or fewer lines in length), you do both of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the object code that the
|
||||
Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
4. Combined Works.
|
||||
|
||||
You may convey a Combined Work under terms of your choice that,
|
||||
taken together, effectively do not restrict modification of the
|
||||
portions of the Library contained in the Combined Work and reverse
|
||||
engineering for debugging such modifications, if you also do each of
|
||||
the following:
|
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that
|
||||
the Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
c) For a Combined Work that displays copyright notices during
|
||||
execution, include the copyright notice for the Library among
|
||||
these notices, as well as a reference directing the user to the
|
||||
copies of the GNU GPL and this license document.
|
||||
|
||||
d) Do one of the following:
|
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this
|
||||
License, and the Corresponding Application Code in a form
|
||||
suitable for, and under terms that permit, the user to
|
||||
recombine or relink the Application with a modified version of
|
||||
the Linked Version to produce a modified Combined Work, in the
|
||||
manner specified by section 6 of the GNU GPL for conveying
|
||||
Corresponding Source.
|
||||
|
||||
1) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (a) uses at run time
|
||||
a copy of the Library already present on the user's computer
|
||||
system, and (b) will operate properly with a modified version
|
||||
of the Library that is interface-compatible with the Linked
|
||||
Version.
|
||||
|
||||
e) Provide Installation Information, but only if you would otherwise
|
||||
be required to provide such information under section 6 of the
|
||||
GNU GPL, and only to the extent that such information is
|
||||
necessary to install and execute a modified version of the
|
||||
Combined Work produced by recombining or relinking the
|
||||
Application with a modified version of the Linked Version. (If
|
||||
you use option 4d0, the Installation Information must accompany
|
||||
the Minimal Corresponding Source and Corresponding Application
|
||||
Code. If you use option 4d1, you must provide the Installation
|
||||
Information in the manner specified by section 6 of the GNU GPL
|
||||
for conveying Corresponding Source.)
|
||||
|
||||
5. Combined Libraries.
|
||||
|
||||
You may place library facilities that are a work based on the
|
||||
Library side by side in a single library together with other library
|
||||
facilities that are not Applications and are not covered by this
|
||||
License, and convey such a combined library under terms of your
|
||||
choice, if you do both of the following:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based
|
||||
on the Library, uncombined with any other library facilities,
|
||||
conveyed under the terms of this License.
|
||||
|
||||
b) Give prominent notice with the combined library that part of it
|
||||
is a work based on the Library, and explaining where to find the
|
||||
accompanying uncombined form of the same work.
|
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the GNU Lesser General Public License from time to time. Such new
|
||||
versions will be similar in spirit to the present version, but may
|
||||
differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Library as you received it specifies that a certain numbered version
|
||||
of the GNU Lesser General Public License "or any later version"
|
||||
applies to it, you have the option of following the terms and
|
||||
conditions either of that published version or of any later version
|
||||
published by the Free Software Foundation. If the Library as you
|
||||
received it does not specify a version number of the GNU Lesser
|
||||
General Public License, you may choose any version of the GNU Lesser
|
||||
General Public License ever published by the Free Software Foundation.
|
||||
|
||||
If the Library as you received it specifies that a proxy can decide
|
||||
whether future versions of the GNU Lesser General Public License shall
|
||||
apply, that proxy's public statement of acceptance of any version is
|
||||
permanent authorization for you to choose that version for the
|
||||
Library.
|
21
README.md
21
README.md
|
@ -1,21 +0,0 @@
|
|||
Shipments
|
||||
=========
|
||||
|
||||
A python library and a GTK3 mobile/desktop application for tracking multiple shipments.
|
||||
|
||||
![Screenshot of the control application](https://brixitcdn.net/metainfo/shipments.png)
|
||||
|
||||
Supported carriers
|
||||
------------------
|
||||
|
||||
* UPS
|
||||
* PostNL
|
||||
|
||||
Installing
|
||||
----------
|
||||
|
||||
```shell-session
|
||||
$ meson build
|
||||
$ meson compile -C build
|
||||
$ sudo meson install -C build
|
||||
```
|
|
@ -1,18 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
from os import environ, path
|
||||
from subprocess import call
|
||||
|
||||
prefix = environ.get('MESON_INSTALL_PREFIX', '/usr/local')
|
||||
datadir = path.join(prefix, 'share')
|
||||
destdir = environ.get('DESTDIR', '')
|
||||
|
||||
if not destdir:
|
||||
print('Updating icon cache...')
|
||||
call(['gtk-update-icon-cache', '-qtf', path.join(datadir, 'icons', 'hicolor')])
|
||||
|
||||
print('Updating desktop database')
|
||||
call(['update-desktop-database', '-q', path.join(datadir, 'applications')])
|
||||
|
||||
print('Compiling GSettings schemas...')
|
||||
call(['glib-compile-schemas', path.join(datadir, 'glib-2.0', 'schemas')])
|
|
@ -1,10 +0,0 @@
|
|||
install_data('org.postmarketos.Shipments.desktop',
|
||||
install_dir: join_paths(get_option('datadir'), 'applications'),
|
||||
)
|
||||
|
||||
install_data(['org.postmarketos.Shipments.appdata.xml'],
|
||||
install_dir : get_option('datadir') / 'metainfo')
|
||||
|
||||
install_data('org.postmarketos.Shipments.svg',
|
||||
install_dir: join_paths(get_option('datadir'), 'icons/hicolor/scalable/apps')
|
||||
)
|
|
@ -1,39 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Copyright 2021 Martijn Braam -->
|
||||
<component type="desktop-application">
|
||||
<id>org.postmarketos.Shipments</id>
|
||||
<metadata_license>CC0-1.0</metadata_license>
|
||||
<project_license>GPL-3.0</project_license>
|
||||
<name>Shipments</name>
|
||||
<summary>Postal package tracking application</summary>
|
||||
<description>
|
||||
<p>
|
||||
Application to track your shipments. Supported carriers:
|
||||
</p>
|
||||
<ul>
|
||||
<li>UPS</li>
|
||||
<li>PostNL</li>
|
||||
</ul>
|
||||
</description>
|
||||
<launchable type="desktop-id">org.postmarketos.Shipments.desktop</launchable>
|
||||
<provides>
|
||||
<binary>shipments</binary>
|
||||
</provides>
|
||||
<screenshots>
|
||||
<screenshot type="default">
|
||||
<image>http://brixitcdn.net/metainfo/shipments.png</image>
|
||||
</screenshot>
|
||||
</screenshots>
|
||||
<url type="homepage">https://sr.ht/~martijnbraam/shipments</url>
|
||||
<url type="bugtracker">https://todo.sr.ht/~martijnbraam/shipments</url>
|
||||
<content_rating type="oars-1.1"/>
|
||||
<releases>
|
||||
<release version="0.1.0" date="2021-11-25">
|
||||
<description>
|
||||
<p>
|
||||
First release
|
||||
</p>
|
||||
</description>
|
||||
</release>
|
||||
</releases>
|
||||
</component>
|
|
@ -1,13 +0,0 @@
|
|||
[Desktop Entry]
|
||||
Name=Shipments
|
||||
Encoding=UTF-8
|
||||
Version=1.0
|
||||
Type=Application
|
||||
Terminal=false
|
||||
Exec=shipments
|
||||
GenericName=Shipments
|
||||
Icon=org.postmarketos.Shipments
|
||||
Categories=GTK;GNOME;Utility
|
||||
X-DBUS-ServiceName=org.postmarketos.Shipments
|
||||
StartupNotify=true
|
||||
X-Purism-FormFactor=Workstation;Mobile;
|
|
@ -1,274 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
viewBox="0 0 128 128"
|
||||
style="display:inline;enable-background:new"
|
||||
version="1.0"
|
||||
id="svg11300"
|
||||
height="128"
|
||||
width="128"
|
||||
sodipodi:docname="org.postmarketos.Shipments.svg"
|
||||
inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||
<sodipodi:namedview
|
||||
id="namedview46"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
showgrid="false"
|
||||
inkscape:zoom="3.3518142"
|
||||
inkscape:cx="75.332337"
|
||||
inkscape:cy="56.387373"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1043"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg11300" />
|
||||
<title
|
||||
id="title4162">Adwaita Icon Template</title>
|
||||
<defs
|
||||
id="defs3">
|
||||
<linearGradient
|
||||
gradientUnits="userSpaceOnUse"
|
||||
y2="268"
|
||||
x2="115.82323"
|
||||
y1="268"
|
||||
x1="11.823223"
|
||||
id="linearGradient1329"
|
||||
xlink:href="#linearGradient1357"
|
||||
gradientTransform="translate(0.176777,-172)" />
|
||||
<linearGradient
|
||||
id="linearGradient1357">
|
||||
<stop
|
||||
id="stop1345"
|
||||
offset="0"
|
||||
style="stop-color:#986a44;stop-opacity:1" />
|
||||
<stop
|
||||
style="stop-color:#cdab8f;stop-opacity:1"
|
||||
offset="0.02884588"
|
||||
id="stop1347" />
|
||||
<stop
|
||||
id="stop1349"
|
||||
offset="0.05769204"
|
||||
style="stop-color:#b5835a;stop-opacity:1" />
|
||||
<stop
|
||||
style="stop-color:#b5835a;stop-opacity:1"
|
||||
offset="0.94230765"
|
||||
id="stop1351" />
|
||||
<stop
|
||||
id="stop1353"
|
||||
offset="0.97133332"
|
||||
style="stop-color:#cdab8f;stop-opacity:1" />
|
||||
<stop
|
||||
id="stop1355"
|
||||
offset="1"
|
||||
style="stop-color:#986a44;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
y2="23"
|
||||
x2="60"
|
||||
y1="53.254841"
|
||||
x1="70.586235"
|
||||
gradientTransform="translate(0,170)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient1610"
|
||||
xlink:href="#linearGradient1656" />
|
||||
<linearGradient
|
||||
id="linearGradient1656">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop1652" />
|
||||
<stop
|
||||
style="stop-color:#deddda;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop1654" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
y2="268"
|
||||
x2="68"
|
||||
y1="268"
|
||||
x1="60"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient1612"
|
||||
xlink:href="#linearGradient1270" />
|
||||
<linearGradient
|
||||
id="linearGradient1270">
|
||||
<stop
|
||||
style="stop-color:#949390;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop1258" />
|
||||
<stop
|
||||
id="stop1260"
|
||||
offset="0.08333334"
|
||||
style="stop-color:#d5d3cf;stop-opacity:1" />
|
||||
<stop
|
||||
style="stop-color:#949390;stop-opacity:1;"
|
||||
offset="0.16666667"
|
||||
id="stop1262" />
|
||||
<stop
|
||||
id="stop1264"
|
||||
offset="0.83333331"
|
||||
style="stop-color:#949390;stop-opacity:1;" />
|
||||
<stop
|
||||
style="stop-color:#d5d3cf;stop-opacity:1"
|
||||
offset="0.91666669"
|
||||
id="stop1266" />
|
||||
<stop
|
||||
style="stop-color:#949390;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop1268" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<metadata
|
||||
id="metadata4">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>GNOME Design Team</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<dc:source />
|
||||
<cc:license
|
||||
rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
|
||||
<dc:title>Adwaita Icon Template</dc:title>
|
||||
<dc:subject>
|
||||
<rdf:Bag />
|
||||
</dc:subject>
|
||||
<dc:date />
|
||||
<dc:rights>
|
||||
<cc:Agent>
|
||||
<dc:title />
|
||||
</cc:Agent>
|
||||
</dc:rights>
|
||||
<dc:publisher>
|
||||
<cc:Agent>
|
||||
<dc:title />
|
||||
</cc:Agent>
|
||||
</dc:publisher>
|
||||
<dc:identifier />
|
||||
<dc:relation />
|
||||
<dc:language />
|
||||
<dc:coverage />
|
||||
<dc:description />
|
||||
<dc:contributor>
|
||||
<cc:Agent>
|
||||
<dc:title />
|
||||
</cc:Agent>
|
||||
</dc:contributor>
|
||||
</cc:Work>
|
||||
<cc:License
|
||||
rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Reproduction" />
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Distribution" />
|
||||
<cc:requires
|
||||
rdf:resource="http://creativecommons.org/ns#Notice" />
|
||||
<cc:requires
|
||||
rdf:resource="http://creativecommons.org/ns#Attribution" />
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
|
||||
<cc:requires
|
||||
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
|
||||
</cc:License>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<rect
|
||||
ry="8"
|
||||
rx="8"
|
||||
style="display:inline;fill:url(#linearGradient1329);fill-opacity:1;stroke:none;stroke-width:32;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:4, 2;stroke-dashoffset:0;stroke-opacity:1;enable-background:new"
|
||||
id="rect1000-3-4"
|
||||
width="104"
|
||||
height="76"
|
||||
x="12.176777"
|
||||
y="40" />
|
||||
<rect
|
||||
y="14"
|
||||
x="12.176777"
|
||||
height="68"
|
||||
width="104"
|
||||
id="rect1299"
|
||||
style="display:inline;opacity:0.1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:32;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:4, 2;stroke-dashoffset:0;stroke-opacity:1;enable-background:new"
|
||||
rx="8"
|
||||
ry="8" />
|
||||
<rect
|
||||
ry="8"
|
||||
rx="8"
|
||||
style="display:inline;fill:#cdab8f;fill-opacity:1;stroke:none;stroke-width:32;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:4, 2;stroke-dashoffset:0;stroke-opacity:1;enable-background:new"
|
||||
id="rect1000-3-9-7"
|
||||
width="104"
|
||||
height="68"
|
||||
x="12.176777"
|
||||
y="12" />
|
||||
<rect
|
||||
style="vector-effect:none;fill:#cdab8f;fill-opacity:1;stroke:none;stroke-width:1.5456;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal"
|
||||
id="rect1076-65"
|
||||
width="2"
|
||||
height="60"
|
||||
x="62.176777"
|
||||
y="20" />
|
||||
<rect
|
||||
style="display:inline;vector-effect:none;fill:#eadcd0;fill-opacity:1;stroke:none;stroke-width:1.64198;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;enable-background:new"
|
||||
id="rect1076-6-69"
|
||||
width="2"
|
||||
height="67.715858"
|
||||
x="64.176781"
|
||||
y="-80"
|
||||
transform="scale(1,-1)" />
|
||||
<rect
|
||||
style="display:inline;vector-effect:none;fill:#eadcd0;fill-opacity:1;stroke:none;stroke-width:5.16445;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;enable-background:new;opacity:0.46896701"
|
||||
id="rect1076-6-69-3"
|
||||
width="16.155928"
|
||||
height="82.927765"
|
||||
x="57.443939"
|
||||
y="-94.935814"
|
||||
transform="scale(1,-1)" />
|
||||
<path
|
||||
id="rect1236"
|
||||
d="m 16.177734,13.072266 c -0.754705,0.43517 -1.427824,0.989659 -2,1.638672 v 62.578124 c 0.572176,0.649013 1.245295,1.203502 2,1.638672 z"
|
||||
style="opacity:0.1;vector-effect:none;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal" />
|
||||
<path
|
||||
id="rect1236-3"
|
||||
d="m 112.17773,13.072266 v 65.855468 c 0.75493,-0.435507 1.42781,-0.991137 2,-1.640625 V 14.712891 c -0.57219,-0.649488 -1.24507,-1.205118 -2,-1.640625 z"
|
||||
style="display:inline;opacity:0.1;vector-effect:none;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;enable-background:new" />
|
||||
<rect
|
||||
style="opacity:1;fill:#ffffff"
|
||||
id="rect1531"
|
||||
width="31.375116"
|
||||
height="28.904648"
|
||||
x="20.846174"
|
||||
y="17.752518"
|
||||
ry="0.97895521" />
|
||||
<rect
|
||||
style="display:inline;fill:#bfbfbf;stroke-width:0.312841;enable-background:new"
|
||||
id="rect1531-6"
|
||||
width="7.0242472"
|
||||
height="12.63574"
|
||||
x="40.854221"
|
||||
y="20.975752"
|
||||
ry="0.42795277" />
|
||||
<rect
|
||||
style="display:inline;fill:#bfbfbf;stroke-width:0.312841;enable-background:new"
|
||||
id="rect1531-6-7"
|
||||
width="7.0242472"
|
||||
height="12.63574"
|
||||
x="31.829975"
|
||||
y="20.975752"
|
||||
ry="0.42795277" />
|
||||
</svg>
|
Before Width: | Height: | Size: 9.4 KiB |
|
@ -1,5 +0,0 @@
|
|||
shipments (0.1-1) unstable; urgency=medium
|
||||
|
||||
* Initial release
|
||||
|
||||
-- Maryjane <maryjane@disroot.org> Sat, 27 Nov 2021 15:34:26 +0100
|
|
@ -1,35 +0,0 @@
|
|||
Source: shipments
|
||||
Section: utils
|
||||
Priority: optional
|
||||
Maintainer: Maryjane <maryjane@disroot.org>
|
||||
Build-Depends:
|
||||
debhelper-compat (= 13),
|
||||
dh-python,
|
||||
python3-setuptools,
|
||||
python3-all,
|
||||
libgtk-3-dev,
|
||||
libhandy-1-dev,
|
||||
meson,
|
||||
Standards-Version: 4.5.1
|
||||
Homepage: https://git.sr.ht/~martijnbraam/shipments
|
||||
#Vcs-Browser: https://git.disroot.org/maryjane/shipments
|
||||
#Vcs-Git: https://git.disroot.org/maryjane.git
|
||||
#Testsuite: autopkgtest-pkg-python
|
||||
Rules-Requires-Root: no
|
||||
|
||||
Package: shipments
|
||||
Architecture: all
|
||||
Depends:
|
||||
gir1.2-handy-1,
|
||||
gir1.2-gtk-3.0,
|
||||
python3,
|
||||
python3-dateutil,
|
||||
python3-gi,
|
||||
python3-stdnum,
|
||||
python3-requests,
|
||||
${python3:Depends},
|
||||
${misc:Depends},
|
||||
Description: Tracking multiple shipments.
|
||||
A python library and a GTK3 mobile/desktop application
|
||||
for tracking multiple shipments.
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||
Upstream-Name: shipments
|
||||
Upstream-Contact: https://git.sr.ht/~martijnbraam/shipments
|
||||
Source: https://git.sr.ht/~martijnbraam/shipments
|
||||
|
||||
Files: *
|
||||
Copyright: 2021 Martijn Braan
|
||||
License: LGPL-3
|
||||
|
||||
Files: data/org.postmarketos.Shipments.appdata.xml
|
||||
Copyright: 2021 Martijn Braan
|
||||
License: CC0-1.0
|
||||
|
||||
Files: debian/*
|
||||
Copyright: 2021 Maryjane <maryjane@disroot.org>
|
||||
License: GPL-3+
|
||||
This package is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
.
|
||||
This package is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>
|
||||
.
|
||||
On Debian systems, the complete text of the GNU General
|
||||
Public License version 3 can be found in "/usr/share/common-licenses/GPL-3".
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
#!/usr/bin/make -f
|
||||
|
||||
export PYBUILD_NAME=shipments
|
||||
|
||||
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
|
||||
|
||||
%:
|
||||
dh $@ --buildsystem=meson --builddirectory=_build
|
||||
|
|
@ -1 +0,0 @@
|
|||
3.0 (quilt)
|
|
@ -1 +0,0 @@
|
|||
extend-diff-ignore = "^[^/]*[.]egg-info/"
|
12
meson.build
12
meson.build
|
@ -1,12 +0,0 @@
|
|||
project('shipments',
|
||||
version: '0.1.0',
|
||||
meson_version: '>= 0.50.0',
|
||||
default_options: ['warning_level=2'])
|
||||
|
||||
dependency('libhandy-1', version: '>=1.0.0')
|
||||
|
||||
subdir('data')
|
||||
subdir('shipments')
|
||||
subdir('shipments_gtk')
|
||||
|
||||
meson.add_install_script('build-aux/meson/postinstall.py')
|
|
@ -1,49 +0,0 @@
|
|||
import shipments.carrier as carriers
|
||||
|
||||
|
||||
def identify_tracking(code):
|
||||
options = []
|
||||
cs = get_carriers()
|
||||
for c in cs:
|
||||
definition = getattr(carriers, c)
|
||||
if definition.identify(code):
|
||||
extra = definition.get_requirements(code)
|
||||
options.append((c, cs[c], extra))
|
||||
return options
|
||||
|
||||
|
||||
def get_tracking_info(code, extra=None, carrier=None):
|
||||
options = []
|
||||
extra = extra if extra is not None else []
|
||||
for c in get_carriers():
|
||||
definition = getattr(carriers, c)
|
||||
if definition.identify(code):
|
||||
options.append(definition())
|
||||
|
||||
if len(options) == 0:
|
||||
return None
|
||||
elif len(options) > 1:
|
||||
return False
|
||||
instance = options[0]
|
||||
|
||||
return instance.get_info(code, extra)
|
||||
|
||||
|
||||
def get_carrier(carrier_code):
|
||||
if not hasattr(carriers, carrier_code):
|
||||
return None
|
||||
instance = getattr(carriers, carrier_code)()
|
||||
return instance
|
||||
|
||||
|
||||
def get_carriers():
|
||||
result = {}
|
||||
for cn, cls in carriers.__dict__.items():
|
||||
if cn.startswith('__'):
|
||||
continue
|
||||
if cn == 'Carrier':
|
||||
continue
|
||||
if not hasattr(cls, 'DISPLAYNAME'):
|
||||
continue
|
||||
result[cn] = cls.DISPLAYNAME
|
||||
return result
|
|
@ -1,203 +0,0 @@
|
|||
from datetime import datetime
|
||||
|
||||
import requests
|
||||
|
||||
from shipments.structs import PackageInfo, PackageEvent, StatusCategory, Address
|
||||
|
||||
|
||||
class Carrier:
|
||||
DISPLAYNAME = 'N/A'
|
||||
|
||||
@classmethod
|
||||
def identify(cls, code):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def get_requirements(cls, code):
|
||||
return []
|
||||
|
||||
def get_info(self, code, extra):
|
||||
pass
|
||||
|
||||
|
||||
class PostNL(Carrier):
|
||||
DISPLAYNAME = 'PostNL'
|
||||
|
||||
@classmethod
|
||||
def identify(cls, code):
|
||||
if code.startswith('3S'):
|
||||
if len(code) == 13:
|
||||
return True
|
||||
if code.startswith('KG'):
|
||||
if len(code) == 8:
|
||||
return True
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
def get_requirements(cls, code):
|
||||
return [
|
||||
('country', 'Destination country', 'country-alpha2:NL'),
|
||||
('postalcode', 'Postal code', 'text')
|
||||
]
|
||||
|
||||
def get_info(self, code, extra):
|
||||
if not 'country' in extra:
|
||||
raise ValueError("Missing 'country' in extra data")
|
||||
if not 'postalcode' in extra:
|
||||
raise ValueError("Missing 'postalcode' in extra data")
|
||||
country = extra['country'].upper()
|
||||
postalcode = extra['postalcode'].upper().replace(' ', '').replace('-', '')
|
||||
url = f'https://jouw.postnl.nl/track-and-trace/api/trackAndTrace/{code}-{country}-{postalcode}?language=en'
|
||||
response = requests.get(url)
|
||||
data = response.json()
|
||||
|
||||
data = data['colli'][code]
|
||||
|
||||
result = PackageInfo(code, 'PostNL')
|
||||
result.carrier_name = 'PostNL'
|
||||
result.status = 'Label created'
|
||||
result.status_category = StatusCategory.LABEL_CREATED
|
||||
if data['isDelivered']:
|
||||
result.status = 'Delivered'
|
||||
result.status_category = StatusCategory.DELIVERED
|
||||
result.description = data['description']
|
||||
|
||||
for event in data['observations']:
|
||||
stamp = datetime.fromisoformat(event['observationDate'])
|
||||
e = PackageEvent(stamp, '', event['description'])
|
||||
result.events.append(e)
|
||||
|
||||
r = Address()
|
||||
r.name = data['recipient']['names']['companyName']
|
||||
r.attention = data['recipient']['names']['personName']
|
||||
r.address1 = data['recipient']['address']['street'] + ' ' + data['recipient']['address']['houseNumber']
|
||||
if data['recipient']['address']['houseNumberSuffix']:
|
||||
r.address1 += ' ' + data['recipient']['address']['houseNumberSuffix']
|
||||
r.postalcode = data['recipient']['address']['postalCode']
|
||||
r.city = data['recipient']['address']['town']
|
||||
r.country = data['recipient']['address']['country']
|
||||
result.destination = r
|
||||
|
||||
s = Address()
|
||||
s.name = data['sender']['names']['companyName']
|
||||
s.attention = data['sender']['names']['personName']
|
||||
s.address1 = data['sender']['address']['street'] + ' ' + data['sender']['address']['houseNumber']
|
||||
if data['sender']['address']['houseNumberSuffix']:
|
||||
s.address1 += ' ' + data['sender']['address']['houseNumberSuffix']
|
||||
|
||||
s.postalcode = data['sender']['address']['postalCode']
|
||||
s.city = data['sender']['address']['town']
|
||||
s.country = data['sender']['address']['country']
|
||||
result.origin = s
|
||||
|
||||
try:
|
||||
result.weight = int(data['details']['dimensions']['weight'])
|
||||
except:
|
||||
pass
|
||||
return result
|
||||
|
||||
|
||||
class UPS(Carrier):
|
||||
DISPLAYNAME = 'UPS'
|
||||
|
||||
@classmethod
|
||||
def identify(cls, code):
|
||||
if not code.startswith('1Z'):
|
||||
return False
|
||||
|
||||
a = 0
|
||||
b = 0
|
||||
x = True
|
||||
for char in code[2:-1]:
|
||||
if char.isdigit():
|
||||
num = int(char)
|
||||
else:
|
||||
num = (ord(char) - 63) % 10
|
||||
if x:
|
||||
a += int(num)
|
||||
else:
|
||||
b += int(num) * 2
|
||||
x = not x
|
||||
s = (a + b) % 10
|
||||
calculated = 10 - s
|
||||
if code[-1].isdigit():
|
||||
check = int(code[-1])
|
||||
else:
|
||||
check = (ord(code[-1]) - 63) % 10
|
||||
|
||||
return calculated == check
|
||||
|
||||
def get_info(self, code, extra):
|
||||
session = requests.Session()
|
||||
user_url = 'https://www.ups.com/track'
|
||||
response = session.get(user_url)
|
||||
token = response.cookies['X-XSRF-TOKEN-ST']
|
||||
url = 'https://www.ups.com/track/api/Track/GetStatus'
|
||||
request_data = {
|
||||
'Locale': 'en_US',
|
||||
'Requester': 'st/trackdetails',
|
||||
'TrackingNumber': [code]
|
||||
}
|
||||
response = session.post(url, json=request_data, headers={
|
||||
'Content-Type': 'Application/Json',
|
||||
'Referer': 'https://www.ups.com/track',
|
||||
'DNT': '1',
|
||||
'User-Agent': 'Mozilla/5.0',
|
||||
'X-Requested-With': 'XMLHttpRequest',
|
||||
"Accept": "application/json, text/plain, */*",
|
||||
'X-XSRF-TOKEN': token
|
||||
})
|
||||
payload = response.json()
|
||||
details = payload['trackDetails'][0]
|
||||
result = PackageInfo(code, 'UPS')
|
||||
result.carrier_name = 'UPS'
|
||||
result.status = details['packageStatus']
|
||||
result.status_category = StatusCategory.LABEL_CREATED
|
||||
if details['progressBarType'] == 'InTransit':
|
||||
result.status_category = StatusCategory.IN_TRANSIT
|
||||
elif details['progressBarType'] == 'Delivered':
|
||||
result.status_category = StatusCategory.DELIVERED
|
||||
|
||||
for event in details['shipmentProgressActivities']:
|
||||
better_time = event['time'].replace('.M.', 'M').zfill(8)
|
||||
dt = event['date'] + ' ' + better_time
|
||||
pdt = datetime.strptime(dt, '%m/%d/%Y %I:%M %p')
|
||||
label = 'No details'
|
||||
if event['actCode'] == 'MP':
|
||||
label = 'Label created'
|
||||
elif event['actCode'] == 'OF':
|
||||
label = 'Out for delivery'
|
||||
if event['milestoneName'] is not None and 'name' in event['milestoneName']:
|
||||
label = event['milestoneName']['name']
|
||||
elif 'activityScan' in event and event['activityScan'] is not None:
|
||||
label = event['activityScan']
|
||||
e = PackageEvent(pdt, event['location'], label)
|
||||
result.events.append(e)
|
||||
|
||||
if details['shipToAddress'] is not None:
|
||||
a = details['shipToAddress']
|
||||
sa = Address()
|
||||
sa.name = a['companyName']
|
||||
sa.attention = a['attentionName']
|
||||
sa.address1 = a['streetAddress1']
|
||||
sa.address2 = a['streetAddress2']
|
||||
sa.address3 = a['streetAddress3']
|
||||
sa.postalcode = a['zipCode']
|
||||
sa.city = a['city']
|
||||
sa.state = (a['state'] + ' ' + a['province']).strip()
|
||||
sa.country = a['country']
|
||||
result.destination = sa
|
||||
|
||||
if details['additionalInformation'] is not None:
|
||||
ai = details['additionalInformation']
|
||||
if 'weight' in ai:
|
||||
weight = ai['weight']
|
||||
unit = ai['weightUnit']
|
||||
if unit == 'KGS': # WTF ups, that's not how you write it
|
||||
result.weight = int(float(weight) * 1000)
|
||||
if 'serviceInformation' in ai and ai['serviceInformation'] is not None:
|
||||
result.service = ai['serviceInformation']['serviceName'].replace('®', '')
|
||||
|
||||
if 'leftAt' in details and details['leftAt'] is not None and details['leftAt'] != '':
|
||||
result.delivery_note = details['leftAt']
|
||||
return result
|
|
@ -1,10 +0,0 @@
|
|||
pkgdatadir = join_paths(get_option('prefix'), get_option('datadir'), meson.project_name())
|
||||
moduledir = join_paths(pkgdatadir, 'shipments')
|
||||
|
||||
sources = [
|
||||
'__init__.py',
|
||||
'carrier.py',
|
||||
'structs.py',
|
||||
]
|
||||
|
||||
install_data(sources, install_dir: moduledir)
|
|
@ -1,75 +0,0 @@
|
|||
import enum
|
||||
|
||||
|
||||
class StatusCategory(enum.Enum):
|
||||
LABEL_CREATED = 0
|
||||
IN_TRANSIT = 1
|
||||
DELIVERED = 2
|
||||
|
||||
|
||||
class Address:
|
||||
def __init__(self):
|
||||
self.name = None
|
||||
self.attention = None
|
||||
self.address1 = None
|
||||
self.address2 = None
|
||||
self.address3 = None
|
||||
self.city = None
|
||||
self.state = None
|
||||
self.postalcode = None
|
||||
self.country = None
|
||||
|
||||
def __str__(self):
|
||||
res = ''
|
||||
if self.name and self.name != '':
|
||||
res += self.name + '\n'
|
||||
if self.attention and self.attention != '':
|
||||
res += self.attention + '\n'
|
||||
if self.address1 and self.address1 != '':
|
||||
res += self.address1 + '\n'
|
||||
if self.address2 and self.address2 != '':
|
||||
res += self.address2 + '\n'
|
||||
if self.address3 and self.address3 != '':
|
||||
res += self.address3 + '\n'
|
||||
if self.postalcode and self.postalcode != '':
|
||||
res += self.postalcode + ' '
|
||||
if self.city and self.city != '':
|
||||
res += self.city + '\n'
|
||||
if self.state and self.state != '':
|
||||
res += self.state + '\n'
|
||||
if self.country and self.country != '':
|
||||
res += self.country
|
||||
return res
|
||||
|
||||
|
||||
class PackageInfo:
|
||||
def __init__(self, code, carrier):
|
||||
self.code = code
|
||||
self.carrier = carrier
|
||||
self.carrier_name = None
|
||||
|
||||
self.status = None
|
||||
self.status_category = None
|
||||
self.events = []
|
||||
|
||||
# Note from the delivering company about location
|
||||
self.delivery_note = None
|
||||
|
||||
# Description of package contents from sender
|
||||
self.description = None
|
||||
|
||||
self.destination = None
|
||||
self.origin = None
|
||||
|
||||
self.weight = None
|
||||
self.service = None
|
||||
|
||||
|
||||
class PackageEvent:
|
||||
def __init__(self, timestamp, location, label):
|
||||
self.timestamp = timestamp
|
||||
self.location = location
|
||||
self.label = label
|
||||
|
||||
def __repr__(self):
|
||||
return f'<event {self.timestamp} {self.label} @ {self.location}>'
|
Binary file not shown.
|
@ -0,0 +1 @@
|
|||
476db39afc861e3ecfc68903703cb711a404b371
|
|
@ -1,46 +0,0 @@
|
|||
import argparse
|
||||
import os
|
||||
import gi
|
||||
|
||||
from shipments_gtk.window import ShipmentsWindow
|
||||
|
||||
gi.require_version('Gtk', '3.0')
|
||||
from gi.repository import Gtk, Gio
|
||||
|
||||
gi.require_version('Handy', '1')
|
||||
from gi.repository import Handy
|
||||
|
||||
|
||||
class ShipmentsApplication(Gtk.Application):
|
||||
def __init__(self, application_id, flags, args, version):
|
||||
Gtk.Application.__init__(self, application_id=application_id, flags=flags)
|
||||
self.connect("activate", self.new_window)
|
||||
self.args = args
|
||||
self.version = version
|
||||
|
||||
def new_window(self, *args):
|
||||
ShipmentsWindow(self, self.args, self.version)
|
||||
|
||||
|
||||
def main(version):
|
||||
Handy.init()
|
||||
|
||||
parser = argparse.ArgumentParser(description="Shipment tracker")
|
||||
args = parser.parse_args()
|
||||
|
||||
if os.path.isfile('shipments_gtk/shipments.gresource'):
|
||||
print("Using resources from cwd/shipments_gtk")
|
||||
resource = Gio.resource_load("shipments.gresource")
|
||||
Gio.Resource._register(resource)
|
||||
elif os.path.isfile('shipments.gresource'):
|
||||
print("Using resources from cwd")
|
||||
resource = Gio.resource_load("shipments.gresource")
|
||||
Gio.Resource._register(resource)
|
||||
|
||||
app = ShipmentsApplication("org.postmarketos.Shipments", Gio.ApplicationFlags.FLAGS_NONE, args=args,
|
||||
version=version)
|
||||
app.run()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main('development')
|
|
@ -1,265 +0,0 @@
|
|||
_dataset = [
|
||||
("AW", "ABW", "Aruba"),
|
||||
("AF", "AFG", "Islamic Republic of Afghanistan"),
|
||||
("AO", "AGO", "Republic of Angola"),
|
||||
("AI", "AIA", "Anguilla"),
|
||||
("AX", "ALA", "Åland Islands"),
|
||||
("AL", "ALB", "Republic of Albania"),
|
||||
("AD", "AND", "Principality of Andorra"),
|
||||
("AE", "ARE", "United Arab Emirates"),
|
||||
("AR", "ARG", "Argentine Republic"),
|
||||
("AM", "ARM", "Republic of Armenia"),
|
||||
("AS", "ASM", "American Samoa"),
|
||||
("AQ", "ATA", "Antarctica"),
|
||||
("TF", "ATF", "French Southern Territories"),
|
||||
("AG", "ATG", "Antigua and Barbuda"),
|
||||
("AU", "AUS", "Australia"),
|
||||
("AT", "AUT", "Republic of Austria"),
|
||||
("AZ", "AZE", "Republic of Azerbaijan"),
|
||||
("BI", "BDI", "Republic of Burundi"),
|
||||
("BE", "BEL", "Kingdom of Belgium"),
|
||||
("BJ", "BEN", "Republic of Benin"),
|
||||
("BQ", "BES", "Bonaire, Sint Eustatius and Saba"),
|
||||
("BF", "BFA", "Burkina Faso"),
|
||||
("BD", "BGD", "People's Republic of Bangladesh"),
|
||||
("BG", "BGR", "Republic of Bulgaria"),
|
||||
("BH", "BHR", "Kingdom of Bahrain"),
|
||||
("BS", "BHS", "Commonwealth of the Bahamas"),
|
||||
("BA", "BIH", "Republic of Bosnia and Herzegovina"),
|
||||
("BL", "BLM", "Saint Barthélemy"),
|
||||
("BY", "BLR", "Republic of Belarus"),
|
||||
("BZ", "BLZ", "Belize"),
|
||||
("BM", "BMU", "Bermuda"),
|
||||
("BO", "BOL", "Plurinational State of Bolivia"),
|
||||
("BR", "BRA", "Federative Republic of Brazil"),
|
||||
("BB", "BRB", "Barbados"),
|
||||
("BN", "BRN", "Brunei Darussalam"),
|
||||
("BT", "BTN", "Kingdom of Bhutan"),
|
||||
("BV", "BVT", "Bouvet Island"),
|
||||
("BW", "BWA", "Republic of Botswana"),
|
||||
("CF", "CAF", "Central African Republic"),
|
||||
("CA", "CAN", "Canada"),
|
||||
("CC", "CCK", "Cocos (Keeling) Islands"),
|
||||
("CH", "CHE", "Swiss Confederation"),
|
||||
("CL", "CHL", "Republic of Chile"),
|
||||
("CN", "CHN", "People's Republic of China"),
|
||||
("CI", "CIV", "Republic of Côte d'Ivoire"),
|
||||
("CM", "CMR", "Republic of Cameroon"),
|
||||
("CD", "COD", "Congo, The Democratic Republic of the"),
|
||||
("CG", "COG", "Republic of the Congo"),
|
||||
("CK", "COK", "Cook Islands"),
|
||||
("CO", "COL", "Republic of Colombia"),
|
||||
("KM", "COM", "Union of the Comoros"),
|
||||
("CV", "CPV", "Republic of Cabo Verde"),
|
||||
("CR", "CRI", "Republic of Costa Rica"),
|
||||
("CU", "CUB", "Republic of Cuba"),
|
||||
("CW", "CUW", "Curaçao"),
|
||||
("CX", "CXR", "Christmas Island"),
|
||||
("KY", "CYM", "Cayman Islands"),
|
||||
("CY", "CYP", "Republic of Cyprus"),
|
||||
("CZ", "CZE", "Czech Republic"),
|
||||
("DE", "DEU", "Federal Republic of Germany"),
|
||||
("DJ", "DJI", "Republic of Djibouti"),
|
||||
("DM", "DMA", "Commonwealth of Dominica"),
|
||||
("DK", "DNK", "Kingdom of Denmark"),
|
||||
("DO", "DOM", "Dominican Republic"),
|
||||
("DZ", "DZA", "People's Democratic Republic of Algeria"),
|
||||
("EC", "ECU", "Republic of Ecuador"),
|
||||
("EG", "EGY", "Arab Republic of Egypt"),
|
||||
("ER", "ERI", "the State of Eritrea"),
|
||||
("EH", "ESH", "Western Sahara"),
|
||||
("ES", "ESP", "Kingdom of Spain"),
|
||||
("EE", "EST", "Republic of Estonia"),
|
||||
("ET", "ETH", "Federal Democratic Republic of Ethiopia"),
|
||||
("FI", "FIN", "Republic of Finland"),
|
||||
("FJ", "FJI", "Republic of Fiji"),
|
||||
("FK", "FLK", "Falkland Islands (Malvinas)"),
|
||||
("FR", "FRA", "French Republic"),
|
||||
("FO", "FRO", "Faroe Islands"),
|
||||
("FM", "FSM", "Federated States of Micronesia"),
|
||||
("GA", "GAB", "Gabonese Republic"),
|
||||
("GB", "GBR", "United Kingdom of Great Britain and Northern Ireland"),
|
||||
("GE", "GEO", "Georgia"),
|
||||
("GG", "GGY", "Guernsey"),
|
||||
("GH", "GHA", "Republic of Ghana"),
|
||||
("GI", "GIB", "Gibraltar"),
|
||||
("GN", "GIN", "Republic of Guinea"),
|
||||
("GP", "GLP", "Guadeloupe"),
|
||||
("GM", "GMB", "Republic of the Gambia"),
|
||||
("GW", "GNB", "Republic of Guinea-Bissau"),
|
||||
("GQ", "GNQ", "Republic of Equatorial Guinea"),
|
||||
("GR", "GRC", "Hellenic Republic"),
|
||||
("GD", "GRD", "Grenada"),
|
||||
("GL", "GRL", "Greenland"),
|
||||
("GT", "GTM", "Republic of Guatemala"),
|
||||
("GF", "GUF", "French Guiana"),
|
||||
("GU", "GUM", "Guam"),
|
||||
("GY", "GUY", "Republic of Guyana"),
|
||||
("HK", "HKG", "Hong Kong Special Administrative Region of China"),
|
||||
("HM", "HMD", "Heard Island and McDonald Islands"),
|
||||
("HN", "HND", "Republic of Honduras"),
|
||||
("HR", "HRV", "Republic of Croatia"),
|
||||
("HT", "HTI", "Republic of Haiti"),
|
||||
("HU", "HUN", "Hungary"),
|
||||
("ID", "IDN", "Republic of Indonesia"),
|
||||
("IM", "IMN", "Isle of Man"),
|
||||
("IN", "IND", "Republic of India"),
|
||||
("IO", "IOT", "British Indian Ocean Territory"),
|
||||
("IE", "IRL", "Ireland"),
|
||||
("IR", "IRN", "Islamic Republic of Iran"),
|
||||
("IQ", "IRQ", "Republic of Iraq"),
|
||||
("IS", "ISL", "Republic of Iceland"),
|
||||
("IL", "ISR", "State of Israel"),
|
||||
("IT", "ITA", "Italian Republic"),
|
||||
("JM", "JAM", "Jamaica"),
|
||||
("JE", "JEY", "Jersey"),
|
||||
("JO", "JOR", "Hashemite Kingdom of Jordan"),
|
||||
("JP", "JPN", "Japan"),
|
||||
("KZ", "KAZ", "Republic of Kazakhstan"),
|
||||
("KE", "KEN", "Republic of Kenya"),
|
||||
("KG", "KGZ", "Kyrgyz Republic"),
|
||||
("KH", "KHM", "Kingdom of Cambodia"),
|
||||
("KI", "KIR", "Republic of Kiribati"),
|
||||
("KN", "KNA", "Saint Kitts and Nevis"),
|
||||
("KR", "KOR", "Korea, Republic of"),
|
||||
("KW", "KWT", "State of Kuwait"),
|
||||
("LA", "LAO", "Lao People's Democratic Republic"),
|
||||
("LB", "LBN", "Lebanese Republic"),
|
||||
("LR", "LBR", "Republic of Liberia"),
|
||||
("LY", "LBY", "Libya"),
|
||||
("LC", "LCA", "Saint Lucia"),
|
||||
("LI", "LIE", "Principality of Liechtenstein"),
|
||||
("LK", "LKA", "Democratic Socialist Republic of Sri Lanka"),
|
||||
("LS", "LSO", "Kingdom of Lesotho"),
|
||||
("LT", "LTU", "Republic of Lithuania"),
|
||||
("LU", "LUX", "Grand Duchy of Luxembourg"),
|
||||
("LV", "LVA", "Republic of Latvia"),
|
||||
("MO", "MAC", "Macao Special Administrative Region of China"),
|
||||
("MF", "MAF", "Saint Martin (French part)"),
|
||||
("MA", "MAR", "Kingdom of Morocco"),
|
||||
("MC", "MCO", "Principality of Monaco"),
|
||||
("MD", "MDA", "Republic of Moldova"),
|
||||
("MG", "MDG", "Republic of Madagascar"),
|
||||
("MV", "MDV", "Republic of Maldives"),
|
||||
("MX", "MEX", "United Mexican States"),
|
||||
("MH", "MHL", "Republic of the Marshall Islands"),
|
||||
("MK", "MKD", "Republic of North Macedonia"),
|
||||
("ML", "MLI", "Republic of Mali"),
|
||||
("MT", "MLT", "Republic of Malta"),
|
||||
("MM", "MMR", "Republic of Myanmar"),
|
||||
("ME", "MNE", "Montenegro"),
|
||||
("MN", "MNG", "Mongolia"),
|
||||
("MP", "MNP", "Commonwealth of the Northern Mariana Islands"),
|
||||
("MZ", "MOZ", "Republic of Mozambique"),
|
||||
("MR", "MRT", "Islamic Republic of Mauritania"),
|
||||
("MS", "MSR", "Montserrat"),
|
||||
("MQ", "MTQ", "Martinique"),
|
||||
("MU", "MUS", "Republic of Mauritius"),
|
||||
("MW", "MWI", "Republic of Malawi"),
|
||||
("MY", "MYS", "Malaysia"),
|
||||
("YT", "MYT", "Mayotte"),
|
||||
("NA", "NAM", "Republic of Namibia"),
|
||||
("NC", "NCL", "New Caledonia"),
|
||||
("NE", "NER", "Republic of the Niger"),
|
||||
("NF", "NFK", "Norfolk Island"),
|
||||
("NG", "NGA", "Federal Republic of Nigeria"),
|
||||
("NI", "NIC", "Republic of Nicaragua"),
|
||||
("NU", "NIU", "Niue"),
|
||||
("NL", "NLD", "Kingdom of the Netherlands"),
|
||||
("NO", "NOR", "Kingdom of Norway"),
|
||||
("NP", "NPL", "Federal Democratic Republic of Nepal"),
|
||||
("NR", "NRU", "Republic of Nauru"),
|
||||
("NZ", "NZL", "New Zealand"),
|
||||
("OM", "OMN", "Sultanate of Oman"),
|
||||
("PK", "PAK", "Islamic Republic of Pakistan"),
|
||||
("PA", "PAN", "Republic of Panama"),
|
||||
("PN", "PCN", "Pitcairn"),
|
||||
("PE", "PER", "Republic of Peru"),
|
||||
("PH", "PHL", "Republic of the Philippines"),
|
||||
("PW", "PLW", "Republic of Palau"),
|
||||
("PG", "PNG", "Independent State of Papua New Guinea"),
|
||||
("PL", "POL", "Republic of Poland"),
|
||||
("PR", "PRI", "Puerto Rico"),
|
||||
("KP", "PRK", "Democratic People's Republic of Korea"),
|
||||
("PT", "PRT", "Portuguese Republic"),
|
||||
("PY", "PRY", "Republic of Paraguay"),
|
||||
("PS", "PSE", "the State of Palestine"),
|
||||
("PF", "PYF", "French Polynesia"),
|
||||
("QA", "QAT", "State of Qatar"),
|
||||
("RE", "REU", "Réunion"),
|
||||
("RO", "ROU", "Romania"),
|
||||
("RU", "RUS", "Russian Federation"),
|
||||
("RW", "RWA", "Rwandese Republic"),
|
||||
("SA", "SAU", "Kingdom of Saudi Arabia"),
|
||||
("SD", "SDN", "Republic of the Sudan"),
|
||||
("SN", "SEN", "Republic of Senegal"),
|
||||
("SG", "SGP", "Republic of Singapore"),
|
||||
("GS", "SGS", "South Georgia and the South Sandwich Islands"),
|
||||
("SH", "SHN", "Saint Helena, Ascension and Tristan da Cunha"),
|
||||
("SJ", "SJM", "Svalbard and Jan Mayen"),
|
||||
("SB", "SLB", "Solomon Islands"),
|
||||
("SL", "SLE", "Republic of Sierra Leone"),
|
||||
("SV", "SLV", "Republic of El Salvador"),
|
||||
("SM", "SMR", "Republic of San Marino"),
|
||||
("SO", "SOM", "Federal Republic of Somalia"),
|
||||
("PM", "SPM", "Saint Pierre and Miquelon"),
|
||||
("RS", "SRB", "Republic of Serbia"),
|
||||
("SS", "SSD", "Republic of South Sudan"),
|
||||
("ST", "STP", "Democratic Republic of Sao Tome and Principe"),
|
||||
("SR", "SUR", "Republic of Suriname"),
|
||||
("SK", "SVK", "Slovak Republic"),
|
||||
("SI", "SVN", "Republic of Slovenia"),
|
||||
("SE", "SWE", "Kingdom of Sweden"),
|
||||
("SZ", "SWZ", "Kingdom of Eswatini"),
|
||||
("SX", "SXM", "Sint Maarten (Dutch part)"),
|
||||
("SC", "SYC", "Republic of Seychelles"),
|
||||
("SY", "SYR", "Syrian Arab Republic"),
|
||||
("TC", "TCA", "Turks and Caicos Islands"),
|
||||
("TD", "TCD", "Republic of Chad"),
|
||||
("TG", "TGO", "Togolese Republic"),
|
||||
("TH", "THA", "Kingdom of Thailand"),
|
||||
("TJ", "TJK", "Republic of Tajikistan"),
|
||||
("TK", "TKL", "Tokelau"),
|
||||
("TM", "TKM", "Turkmenistan"),
|
||||
("TL", "TLS", "Democratic Republic of Timor-Leste"),
|
||||
("TO", "TON", "Kingdom of Tonga"),
|
||||
("TT", "TTO", "Republic of Trinidad and Tobago"),
|
||||
("TN", "TUN", "Republic of Tunisia"),
|
||||
("TR", "TUR", "Republic of Turkey"),
|
||||
("TV", "TUV", "Tuvalu"),
|
||||
("TW", "TWN", "Taiwan, Province of China"),
|
||||
("TZ", "TZA", "United Republic of Tanzania"),
|
||||
("UG", "UGA", "Republic of Uganda"),
|
||||
("UA", "UKR", "Ukraine"),
|
||||
("UM", "UMI", "United States Minor Outlying Islands"),
|
||||
("UY", "URY", "Eastern Republic of Uruguay"),
|
||||
("US", "USA", "United States of America"),
|
||||
("UZ", "UZB", "Republic of Uzbekistan"),
|
||||
("VA", "VAT", "Holy See (Vatican City State)"),
|
||||
("VC", "VCT", "Saint Vincent and the Grenadines"),
|
||||
("VE", "VEN", "Bolivarian Republic of Venezuela"),
|
||||
("VG", "VGB", "British Virgin Islands"),
|
||||
("VI", "VIR", "Virgin Islands of the United States"),
|
||||
("VN", "VNM", "Socialist Republic of Viet Nam"),
|
||||
("VU", "VUT", "Republic of Vanuatu"),
|
||||
("WF", "WLF", "Wallis and Futuna"),
|
||||
("WS", "WSM", "Independent State of Samoa"),
|
||||
("YE", "YEM", "Republic of Yemen"),
|
||||
("ZA", "ZAF", "Republic of South Africa"),
|
||||
("ZM", "ZMB", "Republic of Zambia"),
|
||||
("ZW", "ZWE", "Republic of Zimbabwe"),
|
||||
]
|
||||
|
||||
|
||||
def get_countries_alpha2():
|
||||
res = {}
|
||||
for line in _dataset:
|
||||
res[line[0]] = line[2]
|
||||
return res
|
||||
|
||||
|
||||
def get_countries_alpha3():
|
||||
res = {}
|
||||
for line in _dataset:
|
||||
res[line[1]] = line[2]
|
||||
return res
|
|
@ -1,35 +0,0 @@
|
|||
pkgdatadir = join_paths(get_option('prefix'), get_option('datadir'), meson.project_name())
|
||||
moduledir = join_paths(pkgdatadir, 'shipments_gtk')
|
||||
gnome = import('gnome')
|
||||
|
||||
gnome.compile_resources('shipments',
|
||||
'shipments.gresource.xml',
|
||||
gresource_bundle: true,
|
||||
install: true,
|
||||
install_dir: pkgdatadir,
|
||||
)
|
||||
|
||||
python = import('python')
|
||||
|
||||
conf = configuration_data()
|
||||
conf.set('PYTHON', python.find_installation('python3').path())
|
||||
conf.set('VERSION', meson.project_version())
|
||||
conf.set('localedir', join_paths(get_option('prefix'), get_option('localedir')))
|
||||
conf.set('pkgdatadir', pkgdatadir)
|
||||
|
||||
configure_file(
|
||||
input: 'shipments.in',
|
||||
output: 'shipments',
|
||||
configuration: conf,
|
||||
install: true,
|
||||
install_dir: get_option('bindir')
|
||||
)
|
||||
|
||||
sources = [
|
||||
'__init__.py',
|
||||
'__main__.py',
|
||||
'window.py',
|
||||
'lookup.py',
|
||||
]
|
||||
|
||||
install_data(sources, install_dir: moduledir)
|
Binary file not shown.
|
@ -1,7 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<gresources>
|
||||
<gresource prefix="/org/postmarketos/Shipments">
|
||||
<file>ui/shipments.glade</file>
|
||||
<file>ui/style.css</file>
|
||||
</gresource>
|
||||
</gresources>
|
|
@ -1,22 +0,0 @@
|
|||
#!@PYTHON@
|
||||
|
||||
import os
|
||||
import sys
|
||||
import signal
|
||||
import gettext
|
||||
|
||||
VERSION = '@VERSION@'
|
||||
pkgdatadir = '@pkgdatadir@'
|
||||
localedir = '@localedir@'
|
||||
|
||||
sys.path.insert(1, pkgdatadir)
|
||||
signal.signal(signal.SIGINT, signal.SIG_DFL)
|
||||
|
||||
if __name__ == '__main__':
|
||||
import gi
|
||||
from gi.repository import Gio
|
||||
resource = Gio.Resource.load(os.path.join(pkgdatadir, 'shipments.gresource'))
|
||||
resource._register()
|
||||
|
||||
from shipments_gtk import __main__
|
||||
sys.exit(__main__.main(VERSION))
|
|
@ -1,989 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.38.2 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.24"/>
|
||||
<requires lib="libhandy" version="1.0"/>
|
||||
<object class="GtkPopoverMenu" id="mainmenu">
|
||||
<property name="can-focus">False</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkModelButton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="action-name">app.delete</property>
|
||||
<property name="text" translatable="yes">Delete package</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkModelButton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="action-name">app.refresh</property>
|
||||
<property name="text" translatable="yes">Refresh package</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSeparator">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkModelButton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="action-name">app.about</property>
|
||||
<property name="text" translatable="yes">About</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="submenu">main</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<object class="HdyApplicationWindow" id="window">
|
||||
<property name="can-focus">False</property>
|
||||
<property name="default-width">1000</property>
|
||||
<property name="default-height">562</property>
|
||||
<signal name="destroy" handler="on_main_window_destroy" swapped="no"/>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="HdyTitleBar">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<child>
|
||||
<object class="HdyLeaflet" id="topleaflet">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="hhomogeneous-folded">False</property>
|
||||
<property name="vhomogeneous-folded">False</property>
|
||||
<child>
|
||||
<object class="HdyHeaderBar" id="headerbar_side">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="show-close-button">True</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="add">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="action-name">app.add</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="icon-name">value-increase-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="spacing">4</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="searchbutton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="action-name">app.search</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="icon-name">edit-find-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="pack-type">end</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="name">sidebar</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSeparator">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<style>
|
||||
<class name="sidebar"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="HdyHeaderBar" id="headerbar_main">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="title" translatable="yes">Shipments</property>
|
||||
<property name="show-close-button">True</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="back">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<signal name="clicked" handler="on_back_clicked" swapped="no"/>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="icon-name">go-previous-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSpinner" id="spinner">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="margin-left">10</property>
|
||||
<property name="margin-right">10</property>
|
||||
<property name="margin-start">10</property>
|
||||
<property name="margin-end">10</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="spacing">4</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="refresh">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="action-name">app.refresh</property>
|
||||
<property name="always-show-image">True</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="icon-name">view-refresh-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkMenuButton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="focus-on-click">False</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="popover">mainmenu</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="icon-name">open-menu-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="pack-type">end</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="name">content</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="HdyLeaflet" id="leaflet">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="hhomogeneous-folded">False</property>
|
||||
<property name="vhomogeneous-folded">False</property>
|
||||
<signal name="notify::folded" handler="on_leaflet_change" swapped="no"/>
|
||||
<signal name="notify::visible-child" handler="on_leaflet_change" swapped="no"/>
|
||||
<child>
|
||||
<object class="GtkBox" id="sidebar">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkRevealer" id="searchrevealer">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="transition-type">none</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkSearchEntry" id="searchbox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="margin-start">10</property>
|
||||
<property name="margin-end">10</property>
|
||||
<property name="margin-top">6</property>
|
||||
<property name="margin-bottom">6</property>
|
||||
<property name="primary-icon-name">edit-find-symbolic</property>
|
||||
<property name="primary-icon-activatable">False</property>
|
||||
<property name="primary-icon-sensitive">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="hscrollbar-policy">never</property>
|
||||
<child>
|
||||
<object class="GtkViewport">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="shadow-type">none</property>
|
||||
<child>
|
||||
<object class="GtkListBox" id="packagelist">
|
||||
<property name="width-request">200</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<signal name="row-activated" handler="on_row_activated" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="name">sidebar</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSeparator">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<style>
|
||||
<class name="sidebar"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkStack" id="mainstack">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="hexpand">True</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="nopackages">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkEventBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="margin-top">16</property>
|
||||
<property name="margin-bottom">16</property>
|
||||
<property name="label" translatable="yes">No packages tracked yet</property>
|
||||
<property name="wrap">True</property>
|
||||
<style>
|
||||
<class name="heading"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="label" translatable="yes">Use the add feature to track a package</property>
|
||||
<property name="wrap">True</property>
|
||||
<style>
|
||||
<class name="dim-label"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEventBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="name">nopackages</property>
|
||||
<property name="title" translatable="yes">nopackages</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="package">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<child>
|
||||
<object class="GtkViewport">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="shadow-type">none</property>
|
||||
<child>
|
||||
<object class="HdyClamp">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="maximum-size">1200</property>
|
||||
<property name="tightening-threshold">600</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="margin-start">10</property>
|
||||
<property name="margin-end">10</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="margin-top">16</property>
|
||||
<child>
|
||||
<object class="GtkStack" id="label_stack">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="margin-end">8</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="package_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">Package label</property>
|
||||
<property name="wrap">True</property>
|
||||
<style>
|
||||
<class name="heading"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="name">label</property>
|
||||
<property name="title" translatable="yes">page0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="package_label_entry">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<signal name="activate" handler="on_label_activate" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="name">entry</property>
|
||||
<property name="title" translatable="yes">page1</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkToggleButton" id="package_label_edit">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<signal name="toggled" handler="on_label_edit_toggle" swapped="no"/>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="margin-start">5</property>
|
||||
<property name="margin-end">5</property>
|
||||
<property name="margin-top">5</property>
|
||||
<property name="margin-bottom">5</property>
|
||||
<property name="icon-name">document-edit-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
<style>
|
||||
<class name="circular"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="package_code">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="margin-top">3</property>
|
||||
<property name="margin-bottom">8</property>
|
||||
<property name="label" translatable="yes">packagecode</property>
|
||||
<property name="wrap">True</property>
|
||||
<property name="wrap-mode">word-char</property>
|
||||
<property name="selectable">True</property>
|
||||
<style>
|
||||
<class name="dim-label"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkFlowBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="column-spacing">10</property>
|
||||
<property name="min-children-per-line">1</property>
|
||||
<property name="max-children-per-line">2</property>
|
||||
<property name="selection-mode">none</property>
|
||||
<child>
|
||||
<object class="GtkFlowBoxChild">
|
||||
<property name="width-request">100</property>
|
||||
<property name="height-request">80</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<child>
|
||||
<object class="GtkFrame">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="label-xalign">0</property>
|
||||
<property name="shadow-type">in</property>
|
||||
<child>
|
||||
<!-- n-columns=2 n-rows=10 -->
|
||||
<object class="GtkGrid">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="margin-start">8</property>
|
||||
<property name="margin-end">8</property>
|
||||
<property name="margin-top">8</property>
|
||||
<property name="margin-bottom">8</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="row-spacing">4</property>
|
||||
<property name="column-spacing">8</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="halign">end</property>
|
||||
<property name="label" translatable="yes">Courier</property>
|
||||
<style>
|
||||
<class name="dim-label"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">0</property>
|
||||
<property name="top-attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="package_courier">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">n/a</property>
|
||||
<property name="wrap">True</property>
|
||||
<property name="selectable">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">1</property>
|
||||
<property name="top-attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="halign">end</property>
|
||||
<property name="label" translatable="yes">Status</property>
|
||||
<style>
|
||||
<class name="dim-label"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">0</property>
|
||||
<property name="top-attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="package_status">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">n/a</property>
|
||||
<property name="wrap">True</property>
|
||||
<property name="selectable">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">1</property>
|
||||
<property name="top-attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="halign">end</property>
|
||||
<property name="label" translatable="yes">Note</property>
|
||||
<style>
|
||||
<class name="dim-label"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">0</property>
|
||||
<property name="top-attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="package_delivery_note">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">n/a</property>
|
||||
<property name="wrap">True</property>
|
||||
<property name="selectable">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">1</property>
|
||||
<property name="top-attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="halign">end</property>
|
||||
<property name="label" translatable="yes">Description</property>
|
||||
<style>
|
||||
<class name="dim-label"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">0</property>
|
||||
<property name="top-attach">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="package_description">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">n/a</property>
|
||||
<property name="wrap">True</property>
|
||||
<property name="selectable">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">1</property>
|
||||
<property name="top-attach">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSeparator">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="margin-top">8</property>
|
||||
<property name="margin-bottom">8</property>
|
||||
<property name="hexpand">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">0</property>
|
||||
<property name="top-attach">3</property>
|
||||
<property name="width">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="halign">end</property>
|
||||
<property name="label" translatable="yes">Weight</property>
|
||||
<style>
|
||||
<class name="dim-label"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">0</property>
|
||||
<property name="top-attach">5</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="package_weight">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">n/a</property>
|
||||
<property name="wrap">True</property>
|
||||
<property name="selectable">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">1</property>
|
||||
<property name="top-attach">5</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSeparator">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="margin-top">8</property>
|
||||
<property name="margin-bottom">8</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">0</property>
|
||||
<property name="top-attach">6</property>
|
||||
<property name="width">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="halign">end</property>
|
||||
<property name="label" translatable="yes">Recipient</property>
|
||||
<style>
|
||||
<class name="dim-label"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">0</property>
|
||||
<property name="top-attach">7</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="package_recipient">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">n/a</property>
|
||||
<property name="wrap">True</property>
|
||||
<property name="selectable">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">1</property>
|
||||
<property name="top-attach">7</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="halign">end</property>
|
||||
<property name="label" translatable="yes">Sender</property>
|
||||
<style>
|
||||
<class name="dim-label"/>
|
||||
</style>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">0</property>
|
||||
<property name="top-attach">9</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="package_sender">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">n/a</property>
|
||||
<property name="wrap">True</property>
|
||||
<property name="selectable">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">1</property>
|
||||
<property name="top-attach">9</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSeparator">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="margin-top">8</property>
|
||||
<property name="margin-bottom">8</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">0</property>
|
||||
<property name="top-attach">8</property>
|
||||
<property name="width">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child type="label_item">
|
||||
<placeholder/>
|
||||
</child>
|
||||
<style>
|
||||
<class name="view"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkFlowBoxChild">
|
||||
<property name="width-request">100</property>
|
||||
<property name="height-request">80</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<child>
|
||||
<object class="GtkFrame">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="label-xalign">0</property>
|
||||
<property name="shadow-type">in</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="package_events">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child type="label_item">
|
||||
<placeholder/>
|
||||
</child>
|
||||
<style>
|
||||
<class name="view"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="name">package</property>
|
||||
<property name="title" translatable="yes">package</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="name">content</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<object class="HdyHeaderGroup">
|
||||
<headerbars>
|
||||
<headerbar name="headerbar_side"/>
|
||||
<headerbar name="headerbar_main"/>
|
||||
</headerbars>
|
||||
</object>
|
||||
<object class="GtkSizeGroup" id="main_size">
|
||||
<widgets>
|
||||
<widget name="headerbar_main"/>
|
||||
<widget name="mainstack"/>
|
||||
</widgets>
|
||||
</object>
|
||||
<object class="GtkSizeGroup" id="sidebar_size">
|
||||
<widgets>
|
||||
<widget name="headerbar_side"/>
|
||||
<widget name="sidebar"/>
|
||||
</widgets>
|
||||
</object>
|
||||
</interface>
|
|
@ -1,488 +0,0 @@
|
|||
import json
|
||||
import os
|
||||
|
||||
import gi
|
||||
import shipments
|
||||
from shipments.structs import StatusCategory
|
||||
from shipments_gtk.lookup import get_countries_alpha2
|
||||
|
||||
gi.require_version('Gtk', '3.0')
|
||||
from gi.repository import Gtk, GLib, GObject, Gio, Gdk, GLib
|
||||
|
||||
gi.require_version('Handy', '1')
|
||||
from gi.repository import Handy
|
||||
|
||||
|
||||
class NewPackageDialog(Gtk.Dialog):
|
||||
def __init__(self, parent):
|
||||
super().__init__(title="Add package", transient_for=parent, flags=0)
|
||||
self.add_buttons(
|
||||
Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OK, Gtk.ResponseType.OK
|
||||
)
|
||||
|
||||
label = Gtk.Label("Enter the tracking code for the package you wish to track.", xalign=0.0)
|
||||
label.set_line_wrap(True)
|
||||
label.set_margin_top(16)
|
||||
label.set_margin_bottom(4)
|
||||
label.set_margin_start(10)
|
||||
label.set_margin_end(10)
|
||||
|
||||
self.code = Gtk.Entry()
|
||||
self.code.set_margin_start(10)
|
||||
self.code.set_margin_end(10)
|
||||
self.code.connect('changed', self.on_guess)
|
||||
|
||||
label2 = Gtk.Label("Select the courier", xalign=0.0)
|
||||
label2.set_margin_top(16)
|
||||
label2.set_margin_bottom(4)
|
||||
label2.set_margin_start(10)
|
||||
label2.set_margin_end(10)
|
||||
|
||||
dataset = shipments.get_carriers()
|
||||
self.carrier = Gtk.ComboBoxText()
|
||||
self.carrier.set_entry_text_column(0)
|
||||
self.lut = {}
|
||||
for i, carrier in enumerate(dataset):
|
||||
self.carrier.append_text(dataset[carrier])
|
||||
self.lut[carrier] = i
|
||||
self.carrier.set_margin_start(10)
|
||||
self.carrier.set_margin_end(10)
|
||||
self.carrier.set_margin_bottom(16)
|
||||
self.carrier.connect('changed', self.on_carrier_change)
|
||||
|
||||
box = self.get_content_area()
|
||||
box.add(label)
|
||||
box.add(self.code)
|
||||
box.add(label2)
|
||||
box.add(self.carrier)
|
||||
self.extrabox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
|
||||
box.add(self.extrabox)
|
||||
self.show_all()
|
||||
|
||||
def on_guess(self, *args):
|
||||
code = self.code.get_text()
|
||||
if len(code) > 2:
|
||||
guesses = shipments.identify_tracking(code)
|
||||
if len(guesses) == 1:
|
||||
self.set_carier(guesses[0])
|
||||
elif len(guesses) == 0:
|
||||
pass
|
||||
else:
|
||||
self.set_carier(guesses[0])
|
||||
|
||||
def set_carier(self, option):
|
||||
self.carrier.set_active(self.lut[option[0]])
|
||||
|
||||
def on_carrier_change(self, *args):
|
||||
for child in self.extrabox:
|
||||
self.extrabox.remove(child)
|
||||
|
||||
carrier = shipments.get_carrier(self.carrier.get_active_text())
|
||||
|
||||
extra_data = carrier.get_requirements(self.code.get_text())
|
||||
for fieldname, fieldlabel, fieldtype in extra_data:
|
||||
part = fieldtype.split(':', maxsplit=1)
|
||||
default = None
|
||||
if len(part) > 1:
|
||||
fieldtype = part[0]
|
||||
default = part[1]
|
||||
control = None
|
||||
if fieldtype == 'text':
|
||||
control = Gtk.Entry()
|
||||
elif fieldtype == 'country-alpha2':
|
||||
control = Gtk.ComboBoxText()
|
||||
index = None
|
||||
for i, cc in enumerate(get_countries_alpha2()):
|
||||
control.append_text(cc)
|
||||
if cc == default:
|
||||
index = i
|
||||
if index is not None:
|
||||
control.set_active(index)
|
||||
|
||||
if control is not None:
|
||||
label = Gtk.Label(fieldlabel, xalign=0.0)
|
||||
label.set_line_wrap(True)
|
||||
label.set_margin_top(16)
|
||||
label.set_margin_bottom(4)
|
||||
label.set_margin_start(10)
|
||||
label.set_margin_end(10)
|
||||
|
||||
control.set_margin_start(10)
|
||||
control.set_margin_end(10)
|
||||
control.fieldname = fieldname
|
||||
|
||||
self.extrabox.add(label)
|
||||
self.extrabox.add(control)
|
||||
self.extrabox.show_all()
|
||||
|
||||
|
||||
class ShipmentsWindow:
|
||||
def __init__(self, application, args, version):
|
||||
self.application = application
|
||||
self.args = args
|
||||
self.version = version
|
||||
|
||||
Handy.init()
|
||||
|
||||
builder = Gtk.Builder()
|
||||
builder.add_from_resource('/org/postmarketos/Shipments/ui/shipments.glade')
|
||||
builder.connect_signals(self)
|
||||
css = Gio.resources_lookup_data("/org/postmarketos/Shipments/ui/style.css", 0)
|
||||
self.provider = Gtk.CssProvider()
|
||||
self.provider.load_from_data(css.get_data())
|
||||
|
||||
self.provider = Gtk.CssProvider()
|
||||
self.provider.load_from_data(css.get_data())
|
||||
|
||||
self.window = builder.get_object("window")
|
||||
self.window.set_application(self.application)
|
||||
self.mainstack = builder.get_object("mainstack")
|
||||
|
||||
self.packagelist = builder.get_object("packagelist")
|
||||
self.package_label = builder.get_object("package_label")
|
||||
self.package_code = builder.get_object("package_code")
|
||||
self.package_courier = builder.get_object("package_courier")
|
||||
self.package_status = builder.get_object("package_status")
|
||||
self.package_events = builder.get_object("package_events")
|
||||
self.package_delivery_note = builder.get_object("package_delivery_note")
|
||||
self.package_description = builder.get_object("package_description")
|
||||
self.package_weight = builder.get_object("package_weight")
|
||||
self.package_recipient = builder.get_object("package_recipient")
|
||||
self.package_sender = builder.get_object("package_sender")
|
||||
self.refresh = builder.get_object("refresh")
|
||||
self.searchrevealer = builder.get_object("searchrevealer")
|
||||
self.searchbox = builder.get_object("searchbox")
|
||||
self.leaflet = builder.get_object("leaflet")
|
||||
self.topleaflet = builder.get_object("topleaflet")
|
||||
self.back = builder.get_object("back")
|
||||
|
||||
self.label_stack = builder.get_object("label_stack")
|
||||
self.package_label_entry = builder.get_object("package_label_entry")
|
||||
self.package_label_edit = builder.get_object("package_label_edit")
|
||||
|
||||
# self.hamburgermenu = builder.get_object("hamburgermenu")
|
||||
|
||||
self.apply_css(self.window, self.provider)
|
||||
|
||||
self.action_refresh = None
|
||||
self.action_delete = None
|
||||
self.init_actions()
|
||||
|
||||
xdg_data_home = os.path.expanduser(os.getenv('XDG_DATA_HOME', '~/.local/share'))
|
||||
self.db_path = os.path.join(xdg_data_home, 'shipments/shipments.json')
|
||||
self.packages = []
|
||||
self.current_package = None
|
||||
self.db_load()
|
||||
|
||||
if len(self.packages) > 0:
|
||||
self.show_package(self.packages[0]['code'])
|
||||
else:
|
||||
self.db_save()
|
||||
|
||||
self.window.show()
|
||||
|
||||
Gtk.main()
|
||||
|
||||
def apply_css(self, widget, provider):
|
||||
Gtk.StyleContext.add_provider(widget.get_style_context(),
|
||||
provider,
|
||||
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
|
||||
|
||||
if isinstance(widget, Gtk.Container):
|
||||
widget.forall(self.apply_css, provider)
|
||||
|
||||
def init_actions(self):
|
||||
action = Gio.SimpleAction.new("about", None)
|
||||
action.connect("activate", self.on_about)
|
||||
self.application.add_action(action)
|
||||
|
||||
action = Gio.SimpleAction.new("add", None)
|
||||
action.connect("activate", self.on_add)
|
||||
self.application.add_action(action)
|
||||
|
||||
action = Gio.SimpleAction.new("refresh", None)
|
||||
action.connect("activate", self.on_refresh)
|
||||
self.application.add_action(action)
|
||||
self.action_refresh = action
|
||||
|
||||
action = Gio.SimpleAction.new("search", None)
|
||||
action.connect("activate", self.on_search)
|
||||
self.application.add_action(action)
|
||||
|
||||
action = Gio.SimpleAction.new("delete", None)
|
||||
action.connect("activate", self.on_delete)
|
||||
self.application.add_action(action)
|
||||
self.action_delete = action
|
||||
|
||||
def db_load(self):
|
||||
if not os.path.isfile(self.db_path):
|
||||
return
|
||||
with open(self.db_path) as handle:
|
||||
self.packages = json.loads(handle.read())
|
||||
self.rebuild_list()
|
||||
|
||||
def db_save(self):
|
||||
if not os.path.isdir(os.path.dirname(self.db_path)):
|
||||
os.makedirs(os.path.dirname(self.db_path))
|
||||
|
||||
encoded = json.dumps(self.packages)
|
||||
with open(self.db_path, 'w') as handle:
|
||||
handle.write(encoded)
|
||||
|
||||
def on_main_window_destroy(self, widget):
|
||||
Gtk.main_quit()
|
||||
|
||||
def rebuild_list(self):
|
||||
for child in self.packagelist:
|
||||
self.packagelist.remove(child)
|
||||
|
||||
self.action_delete.set_enabled(len(self.packages) > 0)
|
||||
self.action_refresh.set_enabled(len(self.packages) > 0)
|
||||
|
||||
for package in self.packages:
|
||||
box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
|
||||
label = Gtk.Label(label=package['label'], xalign=0.0)
|
||||
box.add(label)
|
||||
code = Gtk.Label(label=package['status'], xalign=0.0)
|
||||
code.get_style_context().add_class('dim-label')
|
||||
box.add(code)
|
||||
box.set_margin_top(8)
|
||||
box.set_margin_bottom(8)
|
||||
box.set_margin_start(10)
|
||||
box.set_margin_end(10)
|
||||
row = Gtk.ListBoxRow()
|
||||
row.add(box)
|
||||
row.label = package['label']
|
||||
row.code = package['code']
|
||||
self.packagelist.add(row)
|
||||
self.packagelist.show_all()
|
||||
|
||||
def show_package(self, code):
|
||||
self.mainstack.set_visible_child_name('package')
|
||||
self.current_package = code
|
||||
|
||||
for package in self.packages:
|
||||
if package['code'] == code:
|
||||
break
|
||||
else:
|
||||
raise ValueError('Package not found')
|
||||
|
||||
self.package_label.set_text(package['label'])
|
||||
self.package_code.set_text(package['code'])
|
||||
self.package_status.set_text(package['status'])
|
||||
self.package_courier.set_text(package['courier_display'])
|
||||
self.package_delivery_note.set_text(package['note'] if package['note'] is not None else 'n/a')
|
||||
self.package_description.set_text(package['description'] if package['description'] is not None else '')
|
||||
if package['weight']:
|
||||
self.package_weight.set_text(str(package['weight'] / 1000) + ' Kg')
|
||||
else:
|
||||
self.package_weight.set_text('')
|
||||
self.package_recipient.set_text(package['recipient'] if package['recipient'] is not None else 'n/a')
|
||||
self.package_sender.set_text(package['sender'] if package['sender'] is not None else 'n/a')
|
||||
|
||||
for child in self.package_events:
|
||||
self.package_events.remove(child)
|
||||
|
||||
for event in package['events']:
|
||||
status = Gtk.Label(event['label'], xalign=0.0)
|
||||
location = Gtk.Label(event['location'], xalign=0.0)
|
||||
location.get_style_context().add_class('dim-label')
|
||||
timestamp = Gtk.Label(event['timestamp'].replace('T', ' ')[:-3], xalign=0.0)
|
||||
timestamp.get_style_context().add_class('dim-label')
|
||||
|
||||
status.set_margin_top(8)
|
||||
status.set_margin_bottom(4)
|
||||
status.set_margin_start(8)
|
||||
status.set_margin_end(8)
|
||||
status.set_line_wrap(True)
|
||||
|
||||
location.set_margin_bottom(8)
|
||||
location.set_margin_start(8)
|
||||
location.set_margin_end(8)
|
||||
|
||||
timestamp.set_margin_bottom(8)
|
||||
timestamp.set_margin_start(8)
|
||||
timestamp.set_margin_end(8)
|
||||
|
||||
sep = Gtk.Separator()
|
||||
box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
|
||||
box.add(status)
|
||||
box2 = Gtk.Box()
|
||||
box.add(box2)
|
||||
box.add(sep)
|
||||
box2.add(location)
|
||||
box2.pack_end(timestamp, 0, 0, 0)
|
||||
self.package_events.add(box)
|
||||
self.package_events.show_all()
|
||||
|
||||
def refresh_package(self, code):
|
||||
for i, package in enumerate(self.packages):
|
||||
if package['code'] == code:
|
||||
break
|
||||
else:
|
||||
raise ValueError('Package not found')
|
||||
|
||||
print("Refreshing index {}".format(i))
|
||||
extra = self.packages[i]['extra']
|
||||
info = shipments.get_tracking_info(code, extra, package['courier'])
|
||||
self.packages[i]['status'] = info.status
|
||||
self.packages[i]['courier_display'] = info.carrier_name
|
||||
self.packages[i]['events'] = []
|
||||
self.packages[i]['status_category'] = info.status_category.value
|
||||
self.packages[i]['note'] = info.delivery_note
|
||||
self.packages[i]['description'] = info.description
|
||||
self.packages[i]['weight'] = info.weight
|
||||
|
||||
for event in info.events:
|
||||
self.packages[i]['events'].append({
|
||||
'timestamp': event.timestamp.isoformat(),
|
||||
'location': event.location,
|
||||
'label': event.label
|
||||
})
|
||||
|
||||
if info.destination is not None:
|
||||
self.packages[i]['recipient'] = str(info.destination)
|
||||
else:
|
||||
self.packages[i]['recipient'] = None
|
||||
if info.origin is not None:
|
||||
self.packages[i]['sender'] = str(info.origin)
|
||||
else:
|
||||
self.packages[i]['sender'] = None
|
||||
|
||||
self.db_save()
|
||||
self.rebuild_list()
|
||||
|
||||
def on_about(self, *args):
|
||||
dialog = Gtk.AboutDialog(transient_for=self.window)
|
||||
dialog.set_logo_icon_name('org.postmarketos.Shipments')
|
||||
dialog.set_program_name('Shipments')
|
||||
dialog.set_version(self.version)
|
||||
dialog.set_website('https://git.sr.ht/~martijnbraam/shipments')
|
||||
dialog.set_authors(['Martijn Braam'])
|
||||
gtk_version = '{}.{}.{}'.format(Gtk.get_major_version(),
|
||||
Gtk.get_minor_version(), Gtk.get_micro_version())
|
||||
comment = "Postal package tracking application\n\n"
|
||||
comment += 'Gtk: {}'.format(gtk_version)
|
||||
dialog.set_comments(comment)
|
||||
text = "Distributed under the GNU GPL(v3) license.\n"
|
||||
dialog.set_license(text)
|
||||
dialog.run()
|
||||
dialog.destroy()
|
||||
|
||||
def on_refresh(self, action, *args):
|
||||
action.set_enabled(False)
|
||||
self.refresh_package(self.current_package)
|
||||
action.set_enabled(True)
|
||||
self.show_package(self.current_package)
|
||||
|
||||
def on_add(self, action, *args):
|
||||
dialog = NewPackageDialog(self.window)
|
||||
response = dialog.run()
|
||||
|
||||
if response == Gtk.ResponseType.OK:
|
||||
code = dialog.code.get_text()
|
||||
carrier_name = dialog.carrier.get_active_text()
|
||||
|
||||
carrierlist = shipments.get_carriers()
|
||||
for carrier_code in carrierlist:
|
||||
if carrierlist[carrier_code] == carrier_name:
|
||||
break
|
||||
else:
|
||||
raise ValueError("Carrier code unknown")
|
||||
|
||||
extra = {}
|
||||
for control in dialog.extrabox:
|
||||
if hasattr(control, 'fieldname'):
|
||||
if isinstance(control, Gtk.Entry):
|
||||
extra[control.fieldname] = control.get_text()
|
||||
elif isinstance(control, Gtk.ComboBoxText):
|
||||
extra[control.fieldname] = control.get_active_text()
|
||||
else:
|
||||
print(control)
|
||||
|
||||
print(f"Adding tracking {code} from {carrier_code}")
|
||||
print("Extra data: ", extra)
|
||||
for package in self.packages:
|
||||
if package['code'] == code:
|
||||
print("Code already exists in database, ignoring")
|
||||
return
|
||||
|
||||
self.packages.append({
|
||||
'label': code,
|
||||
'code': code,
|
||||
'courier': carrier_code,
|
||||
'extra': extra,
|
||||
'courier_display': carrier_name,
|
||||
'status': 'unknown',
|
||||
'status_category': StatusCategory.LABEL_CREATED.value,
|
||||
'note': '',
|
||||
'description': '',
|
||||
'weight': '',
|
||||
'recipient': '',
|
||||
'sender': '',
|
||||
'events': []
|
||||
})
|
||||
self.db_save()
|
||||
self.db_load()
|
||||
|
||||
dialog.destroy()
|
||||
|
||||
def on_search(self, action, *args):
|
||||
self.searchrevealer.set_reveal_child(True)
|
||||
self.searchbox.grab_focus()
|
||||
|
||||
def on_row_activated(self, widget, row):
|
||||
if self.packagelist.get_selection_mode() == Gtk.SelectionMode.NONE:
|
||||
self.packagelist.set_selection_mode(Gtk.SelectionMode.SINGLE)
|
||||
self.packagelist.select_row(row)
|
||||
self.show_package(row.code)
|
||||
self.leaflet.set_visible_child_name('content')
|
||||
|
||||
if self.leaflet.get_folded():
|
||||
self.packagelist.unselect_row(row)
|
||||
|
||||
def on_leaflet_change(self, *args):
|
||||
self.topleaflet.set_visible_child_name(self.leaflet.get_visible_child_name())
|
||||
self.back.set_visible(self.leaflet.get_folded())
|
||||
|
||||
def on_back_clicked(self, *args):
|
||||
self.leaflet.set_visible_child_name('sidebar')
|
||||
|
||||
def on_label_edit_toggle(self, widget, *args):
|
||||
view = 'entry' if widget.get_active() else 'label'
|
||||
if widget.get_active():
|
||||
self.package_label_entry.set_text(self.package_label.get_text())
|
||||
self.package_label_entry.grab_focus()
|
||||
self.label_stack.set_visible_child_name(view)
|
||||
|
||||
def on_label_activate(self, widget, *args):
|
||||
new_label = widget.get_text()
|
||||
for i, package in enumerate(self.packages):
|
||||
if package['code'] == self.current_package:
|
||||
break
|
||||
else:
|
||||
raise ValueError('Package not found')
|
||||
|
||||
self.packages[i]['label'] = new_label
|
||||
|
||||
self.db_save()
|
||||
self.rebuild_list()
|
||||
self.package_label.set_text(new_label)
|
||||
self.package_label_edit.set_active(False)
|
||||
|
||||
def on_delete(self, *args):
|
||||
for i, package in enumerate(self.packages):
|
||||
if package['code'] == self.current_package:
|
||||
break
|
||||
else:
|
||||
raise ValueError('Package not found')
|
||||
|
||||
del self.packages[i]
|
||||
|
||||
self.db_save()
|
||||
self.rebuild_list()
|
||||
|
||||
if len(self.packages) > 0:
|
||||
self.show_package(self.packages[0]['code'])
|
||||
else:
|
||||
self.mainstack.set_visible_child_name('nopackages')
|
Loading…
Reference in New Issue