├── .editorconfig ├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── README.md ├── build-aux ├── cargo.sh ├── dist-vendor.sh ├── meson_post_install.py └── zypp.gui.Devel.json ├── data ├── additional.json ├── icons │ ├── country │ │ ├── armenia.png │ │ ├── australia.png │ │ ├── austria.png │ │ ├── belarus.png │ │ ├── belgium.png │ │ ├── brazil.png │ │ ├── bulgaria.png │ │ ├── canada.png │ │ ├── china.png │ │ ├── costa.rica.png │ │ ├── cyprus.png │ │ ├── czech.republic.png │ │ ├── denmark.png │ │ ├── ecuador.png │ │ ├── estonia.png │ │ ├── finland.png │ │ ├── france.png │ │ ├── germany.png │ │ ├── greece.png │ │ ├── hong.kong.png │ │ ├── hungary.png │ │ ├── india.png │ │ ├── indonesia.png │ │ ├── iran,islamic.republic.of.png │ │ ├── israel.png │ │ ├── italy.png │ │ ├── japan.png │ │ ├── kenya.png │ │ ├── korea,republic.of.png │ │ ├── latvia.png │ │ ├── malaysia.png │ │ ├── moldova.png │ │ ├── netherlands.png │ │ ├── new.zealand.png │ │ ├── norway.png │ │ ├── oman.png │ │ ├── poland.png │ │ ├── portugal.png │ │ ├── romania.png │ │ ├── russian.federation.png │ │ ├── singapore.png │ │ ├── slovakia.png │ │ ├── slovenia.png │ │ ├── south.africa.png │ │ ├── sweden.png │ │ ├── switzerland.png │ │ ├── taiwan.png │ │ ├── turkey.png │ │ ├── ukraine.png │ │ ├── united.kingdom.png │ │ ├── united.states.png │ │ ├── uruguay.png │ │ └── uzbekistan.png │ ├── meson.build │ ├── zypp.gui-symbolic.svg │ └── zypp.gui.svg ├── meson.build ├── mirror.json.in ├── resources │ ├── meson.build │ ├── resources.gresource.xml │ ├── screenshots │ │ ├── screenshot1.png │ │ ├── screenshot2.png │ │ ├── screenshot3.png │ │ ├── screenshot4.png │ │ ├── screenshot5.png │ │ ├── screenshot6.png │ │ ├── screenshot7.png │ │ └── screenshot8.png │ ├── style.css │ └── ui │ │ ├── additional_row.blp │ │ ├── list_row.blp │ │ ├── mirror_row.blp │ │ ├── mirror_window.blp │ │ ├── page_settings.blp │ │ ├── repo_add.blp │ │ ├── repo_row.blp │ │ ├── search_row.blp │ │ └── window.blp ├── zypp-gui-service.desktop.in ├── zypp.gui.desktop.in.in ├── zypp.gui.gschema.xml.in ├── zypp.gui.metainfo.xml.in.in ├── zypp.gui.policy.in.in └── zypp.gui.service.in ├── hooks └── pre-commit.hook ├── meson.build ├── meson_options.txt ├── mod_repo ├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── meson.build └── src │ ├── main.rs │ └── meson.build ├── packagekit_rs ├── .gitignore ├── Cargo.toml ├── packagekit-sys │ ├── Cargo.toml │ ├── build.rs │ ├── src │ │ └── lib.rs │ └── tests │ │ ├── abi.rs │ │ ├── constant.c │ │ ├── layout.c │ │ └── manual.h ├── src │ ├── auto │ │ └── enums.rs │ ├── client.rs │ ├── details.rs │ ├── lib.rs │ ├── package.rs │ ├── prelude.rs │ ├── progress.rs │ ├── results.rs │ ├── task.rs │ └── update_detail.rs └── tests │ └── packagekit.rs ├── po ├── LINGUAS ├── POTFILES.in └── meson.build ├── subprojects └── blueprint-compiler.wrap ├── tools └── get_mirror_data │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ ├── get.sh │ └── src │ ├── main.rs │ └── name_convert.rs └── zypp-gui ├── Cargo.toml ├── meson.build └── src ├── additional.rs ├── config.rs.in ├── list_row.rs ├── main.rs ├── meson.build ├── mirror.rs ├── mirror_row.rs ├── mirror_window.rs ├── notification.rs ├── package_meta.rs ├── packagekit.rs ├── page_settings.rs ├── repo_row.rs ├── search.rs ├── search_row.rs ├── util.rs ├── window.rs └── zypper.rs /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | [*] 3 | indent_style = space 4 | end_of_line = lf 5 | trim_trailing_whitespace = true 6 | insert_final_newline = true 7 | charset = utf-8 8 | 9 | [*.{build,css,doap,scss,ui,xml,xml.in,xml.in.in,yaml,yml}] 10 | indent_size = 2 11 | 12 | [*.{json,py,rs}] 13 | indent_size = 4 14 | 15 | [*.{c,h,h.in}] 16 | indent_size = 2 17 | max_line_length = 80 18 | 19 | [NEWS] 20 | indent_size = 2 21 | max_line_length = 72 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | build/ 3 | _build/ 4 | builddir/ 5 | build-aux/app 6 | build-aux/.flatpak-builder/ 7 | zypp-gui/src/config.rs 8 | *.ui.in~ 9 | *.ui~ 10 | .flatpak/ 11 | .cargo 12 | vendor/ 13 | 14 | /subprojects/blueprint-compiler 15 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = [ 3 | "zypp-gui", 4 | "mod_repo", 5 | ] 6 | 7 | default-members = [ 8 | "zypp-gui", 9 | ] 10 | 11 | resolver = "2" 12 | 13 | [workspace.package] 14 | version = "0.4.1" 15 | authors = ["Xiaoguang Wang "] 16 | edition = "2018" 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ZYPP GUI 2 | 3 | It's a GUI application working on openSUSE distro. Application runs as a daemon to monitor the system update. Application can update the system, search, install and remove the package, change the settings of repos. It achieves some functions of command zypper. 4 | 5 | zypp gui differs from GNOME software to: 6 | - support general openSUSE desktop environments instead of GNOME only 7 | 8 | zypp gui differs from YaST software management to: 9 | - support desktop integration (e.g. update detection and notification) 10 | 11 | ## Targets: 12 | - [x] Refresh the repos, download the packages, install the update. 13 | - [x] Search, install and remove the package. 14 | - [x] Offline update. 15 | - [x] Add and remove repos. 16 | - [x] Modify the repos. 17 | - [x] Add mirror repos. 18 | - [ ] Monitor the new release and update to the new release. 19 | 20 | ## Screenshot 21 | 22 | ![](./data/resources/screenshots/screenshot1.png) 23 | ![](./data/resources/screenshots/screenshot2.png) 24 | ![](./data/resources/screenshots/screenshot3.png) 25 | ![](./data/resources/screenshots/screenshot4.png) 26 | ![](./data/resources/screenshots/screenshot5.png) 27 | ![](./data/resources/screenshots/screenshot6.png) 28 | ![](./data/resources/screenshots/screenshot7.png) 29 | ![](./data/resources/screenshots/screenshot8.png) 30 | 31 | ## How to build: 32 | 33 | #### meson 34 | 1. Install dependences: 35 | ``` 36 | zypper in meson gcc cargo glib2-devel gtk4-devel systemd-devel libpackagekit-glib2-devel polkit-devel libadwaita-devel 37 | ``` 38 | 2. Compile: 39 | ``` 40 | meson --prefix /usr _builddir 41 | meson compile -C _builddir 42 | ``` 43 | 3. Install: 44 | ``` 45 | meson install -C _builddir 46 | ``` 47 | 48 | #### Open Build Service 49 | [OBS Link](https://build.opensuse.org/package/show/openSUSE:Factory/zypp-gui) 50 | -------------------------------------------------------------------------------- /build-aux/cargo.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | export MESON_BUILD_ROOT="$1" 4 | export MESON_SOURCE_ROOT="$2" 5 | export CARGO_TARGET_DIR="$MESON_BUILD_ROOT"/target 6 | export CARGO_HOME="$MESON_BUILD_ROOT"/cargo-home 7 | 8 | if [[ $4 = "Devel" ]] 9 | then 10 | echo "DEBUG MODE" 11 | cargo build --manifest-path \ 12 | "$MESON_SOURCE_ROOT"/$6/Cargo.toml && \ 13 | cp "$CARGO_TARGET_DIR"/debug/$5 $3 14 | else 15 | echo "RELEASE MODE" 16 | cargo build --manifest-path \ 17 | "$MESON_SOURCE_ROOT"/$6/Cargo.toml --release && \ 18 | cp "$CARGO_TARGET_DIR"/release/$5 $3 19 | fi 20 | 21 | -------------------------------------------------------------------------------- /build-aux/dist-vendor.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | export DIST="$1" 3 | export SOURCE_ROOT="$2" 4 | 5 | cd "$SOURCE_ROOT" 6 | mkdir "$DIST"/.cargo 7 | cargo vendor -s "$SOURCE_ROOT"/mod_repo/Cargo.toml | sed 's/^directory = ".*"/directory = "vendor"/g' > $DIST/.cargo/config 8 | # Move vendor into dist tarball directory 9 | cp -r vendor "$DIST" 10 | 11 | cd "$SOURCE_ROOT"/mod_repo 12 | mkdir "$DIST"/mod_repo/.cargo 13 | cargo vendor | sed 's/^directory = ".*"/directory = "vendor"/g' > $DIST/mod_repo/.cargo/config 14 | # Move vendor into dist tarball directory 15 | #cp -r vendor "$DIST" 16 | cp -r vendor "$DIST"/mod_repo/ 17 | -------------------------------------------------------------------------------- /build-aux/meson_post_install.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from os import environ, path 4 | from subprocess import call 5 | 6 | if not environ.get('DESTDIR', ''): 7 | PREFIX = environ.get('MESON_INSTALL_PREFIX', '/usr/local') 8 | DATA_DIR = path.join(PREFIX, 'share') 9 | print('Updating icon cache...') 10 | call(['gtk-update-icon-cache', '-qtf', path.join(DATA_DIR, 'icons/hicolor')]) 11 | print("Compiling new schemas...") 12 | call(["glib-compile-schemas", path.join(DATA_DIR, 'glib-2.0/schemas')]) 13 | print("Updating desktop database...") 14 | call(["update-desktop-database", path.join(DATA_DIR, 'applications')]) 15 | -------------------------------------------------------------------------------- /build-aux/zypp.gui.Devel.json: -------------------------------------------------------------------------------- 1 | { 2 | "app-id" : "zypp.gui.Devel", 3 | "runtime" : "org.gnome.Platform", 4 | "runtime-version" : "40", 5 | "sdk" : "org.gnome.Sdk", 6 | "sdk-extensions" : [ 7 | "org.freedesktop.Sdk.Extension.rust-stable" 8 | ], 9 | "command": "zypp-gui", 10 | "finish-args": [ 11 | "--socket=fallback-x11", 12 | "--socket=wayland", 13 | "--device=dri", 14 | "--env=RUST_LOG=zypp-gui=debug", 15 | "--env=G_MESSAGES_DEBUG=none" 16 | ], 17 | "build-options": { 18 | "append-path": "/usr/lib/sdk/rust-stable/bin", 19 | "build-args": ["--share=network"], 20 | "test-args": [ 21 | "--socket=x11", 22 | "--share=network" 23 | ], 24 | "env": { 25 | "RUST_BACKTRACE": "1" 26 | } 27 | }, 28 | "modules" : [ 29 | { 30 | "name" : "zypp-gui", 31 | "buildsystem" : "meson", 32 | "run-tests": true, 33 | "config-opts" : [ 34 | "-Dprofile=development" 35 | ], 36 | "sources" : [ 37 | { 38 | "type": "dir", 39 | "path": "../" 40 | } 41 | ] 42 | } 43 | ] 44 | } 45 | 46 | -------------------------------------------------------------------------------- /data/additional.json: -------------------------------------------------------------------------------- 1 | { 2 | "list": [ 3 | { 4 | "name": "packman", 5 | "url": "http://ftp.gwdg.de/pub/linux/misc/packman/suse/", 6 | "info": "Offers various additional packages for openSUSE, especially but not limited to multimedia related applications and libraries that are on the openSUSE Build Service application blacklist. It's the largest external repository of openSUSE packages. Packman is comprised of the following four repositories:\n\n* Essentials: provides codecs and audio and video player applications, to fulfill the most essential needs\n* Multimedia: contains many more multimedia related applications\n* Extra: additional non multimedia related applications, mostly network related\n* Games: obviously, games" 7 | } 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /data/icons/country/armenia.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwxg/zypp-gui/101b086d82e7de5641a5cb3c35f2474e214cb317/data/icons/country/armenia.png -------------------------------------------------------------------------------- /data/icons/country/australia.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwxg/zypp-gui/101b086d82e7de5641a5cb3c35f2474e214cb317/data/icons/country/australia.png -------------------------------------------------------------------------------- /data/icons/country/austria.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwxg/zypp-gui/101b086d82e7de5641a5cb3c35f2474e214cb317/data/icons/country/austria.png -------------------------------------------------------------------------------- /data/icons/country/belarus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwxg/zypp-gui/101b086d82e7de5641a5cb3c35f2474e214cb317/data/icons/country/belarus.png -------------------------------------------------------------------------------- /data/icons/country/belgium.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwxg/zypp-gui/101b086d82e7de5641a5cb3c35f2474e214cb317/data/icons/country/belgium.png -------------------------------------------------------------------------------- /data/icons/country/brazil.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwxg/zypp-gui/101b086d82e7de5641a5cb3c35f2474e214cb317/data/icons/country/brazil.png -------------------------------------------------------------------------------- /data/icons/country/bulgaria.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwxg/zypp-gui/101b086d82e7de5641a5cb3c35f2474e214cb317/data/icons/country/bulgaria.png -------------------------------------------------------------------------------- /data/icons/country/canada.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwxg/zypp-gui/101b086d82e7de5641a5cb3c35f2474e214cb317/data/icons/country/canada.png -------------------------------------------------------------------------------- /data/icons/country/china.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwxg/zypp-gui/101b086d82e7de5641a5cb3c35f2474e214cb317/data/icons/country/china.png -------------------------------------------------------------------------------- /data/icons/country/costa.rica.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwxg/zypp-gui/101b086d82e7de5641a5cb3c35f2474e214cb317/data/icons/country/costa.rica.png -------------------------------------------------------------------------------- /data/icons/country/cyprus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwxg/zypp-gui/101b086d82e7de5641a5cb3c35f2474e214cb317/data/icons/country/cyprus.png -------------------------------------------------------------------------------- /data/icons/country/czech.republic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwxg/zypp-gui/101b086d82e7de5641a5cb3c35f2474e214cb317/data/icons/country/czech.republic.png -------------------------------------------------------------------------------- /data/icons/country/denmark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwxg/zypp-gui/101b086d82e7de5641a5cb3c35f2474e214cb317/data/icons/country/denmark.png -------------------------------------------------------------------------------- /data/icons/country/ecuador.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwxg/zypp-gui/101b086d82e7de5641a5cb3c35f2474e214cb317/data/icons/country/ecuador.png -------------------------------------------------------------------------------- /data/icons/country/estonia.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwxg/zypp-gui/101b086d82e7de5641a5cb3c35f2474e214cb317/data/icons/country/estonia.png -------------------------------------------------------------------------------- /data/icons/country/finland.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwxg/zypp-gui/101b086d82e7de5641a5cb3c35f2474e214cb317/data/icons/country/finland.png -------------------------------------------------------------------------------- /data/icons/country/france.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwxg/zypp-gui/101b086d82e7de5641a5cb3c35f2474e214cb317/data/icons/country/france.png -------------------------------------------------------------------------------- /data/icons/country/germany.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwxg/zypp-gui/101b086d82e7de5641a5cb3c35f2474e214cb317/data/icons/country/germany.png -------------------------------------------------------------------------------- /data/icons/country/greece.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwxg/zypp-gui/101b086d82e7de5641a5cb3c35f2474e214cb317/data/icons/country/greece.png -------------------------------------------------------------------------------- /data/icons/country/hong.kong.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwxg/zypp-gui/101b086d82e7de5641a5cb3c35f2474e214cb317/data/icons/country/hong.kong.png -------------------------------------------------------------------------------- /data/icons/country/hungary.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwxg/zypp-gui/101b086d82e7de5641a5cb3c35f2474e214cb317/data/icons/country/hungary.png -------------------------------------------------------------------------------- /data/icons/country/india.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwxg/zypp-gui/101b086d82e7de5641a5cb3c35f2474e214cb317/data/icons/country/india.png -------------------------------------------------------------------------------- /data/icons/country/indonesia.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwxg/zypp-gui/101b086d82e7de5641a5cb3c35f2474e214cb317/data/icons/country/indonesia.png -------------------------------------------------------------------------------- /data/icons/country/iran,islamic.republic.of.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwxg/zypp-gui/101b086d82e7de5641a5cb3c35f2474e214cb317/data/icons/country/iran,islamic.republic.of.png -------------------------------------------------------------------------------- /data/icons/country/israel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwxg/zypp-gui/101b086d82e7de5641a5cb3c35f2474e214cb317/data/icons/country/israel.png -------------------------------------------------------------------------------- /data/icons/country/italy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwxg/zypp-gui/101b086d82e7de5641a5cb3c35f2474e214cb317/data/icons/country/italy.png -------------------------------------------------------------------------------- /data/icons/country/japan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwxg/zypp-gui/101b086d82e7de5641a5cb3c35f2474e214cb317/data/icons/country/japan.png -------------------------------------------------------------------------------- /data/icons/country/kenya.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwxg/zypp-gui/101b086d82e7de5641a5cb3c35f2474e214cb317/data/icons/country/kenya.png -------------------------------------------------------------------------------- /data/icons/country/korea,republic.of.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwxg/zypp-gui/101b086d82e7de5641a5cb3c35f2474e214cb317/data/icons/country/korea,republic.of.png -------------------------------------------------------------------------------- /data/icons/country/latvia.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwxg/zypp-gui/101b086d82e7de5641a5cb3c35f2474e214cb317/data/icons/country/latvia.png -------------------------------------------------------------------------------- /data/icons/country/malaysia.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwxg/zypp-gui/101b086d82e7de5641a5cb3c35f2474e214cb317/data/icons/country/malaysia.png -------------------------------------------------------------------------------- /data/icons/country/moldova.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwxg/zypp-gui/101b086d82e7de5641a5cb3c35f2474e214cb317/data/icons/country/moldova.png -------------------------------------------------------------------------------- /data/icons/country/netherlands.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwxg/zypp-gui/101b086d82e7de5641a5cb3c35f2474e214cb317/data/icons/country/netherlands.png -------------------------------------------------------------------------------- /data/icons/country/new.zealand.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwxg/zypp-gui/101b086d82e7de5641a5cb3c35f2474e214cb317/data/icons/country/new.zealand.png -------------------------------------------------------------------------------- /data/icons/country/norway.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwxg/zypp-gui/101b086d82e7de5641a5cb3c35f2474e214cb317/data/icons/country/norway.png -------------------------------------------------------------------------------- /data/icons/country/oman.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwxg/zypp-gui/101b086d82e7de5641a5cb3c35f2474e214cb317/data/icons/country/oman.png -------------------------------------------------------------------------------- /data/icons/country/poland.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwxg/zypp-gui/101b086d82e7de5641a5cb3c35f2474e214cb317/data/icons/country/poland.png -------------------------------------------------------------------------------- /data/icons/country/portugal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwxg/zypp-gui/101b086d82e7de5641a5cb3c35f2474e214cb317/data/icons/country/portugal.png -------------------------------------------------------------------------------- /data/icons/country/romania.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwxg/zypp-gui/101b086d82e7de5641a5cb3c35f2474e214cb317/data/icons/country/romania.png -------------------------------------------------------------------------------- /data/icons/country/russian.federation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwxg/zypp-gui/101b086d82e7de5641a5cb3c35f2474e214cb317/data/icons/country/russian.federation.png -------------------------------------------------------------------------------- /data/icons/country/singapore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwxg/zypp-gui/101b086d82e7de5641a5cb3c35f2474e214cb317/data/icons/country/singapore.png -------------------------------------------------------------------------------- /data/icons/country/slovakia.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwxg/zypp-gui/101b086d82e7de5641a5cb3c35f2474e214cb317/data/icons/country/slovakia.png -------------------------------------------------------------------------------- /data/icons/country/slovenia.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwxg/zypp-gui/101b086d82e7de5641a5cb3c35f2474e214cb317/data/icons/country/slovenia.png -------------------------------------------------------------------------------- /data/icons/country/south.africa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwxg/zypp-gui/101b086d82e7de5641a5cb3c35f2474e214cb317/data/icons/country/south.africa.png -------------------------------------------------------------------------------- /data/icons/country/sweden.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwxg/zypp-gui/101b086d82e7de5641a5cb3c35f2474e214cb317/data/icons/country/sweden.png -------------------------------------------------------------------------------- /data/icons/country/switzerland.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwxg/zypp-gui/101b086d82e7de5641a5cb3c35f2474e214cb317/data/icons/country/switzerland.png -------------------------------------------------------------------------------- /data/icons/country/taiwan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwxg/zypp-gui/101b086d82e7de5641a5cb3c35f2474e214cb317/data/icons/country/taiwan.png -------------------------------------------------------------------------------- /data/icons/country/turkey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwxg/zypp-gui/101b086d82e7de5641a5cb3c35f2474e214cb317/data/icons/country/turkey.png -------------------------------------------------------------------------------- /data/icons/country/ukraine.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwxg/zypp-gui/101b086d82e7de5641a5cb3c35f2474e214cb317/data/icons/country/ukraine.png -------------------------------------------------------------------------------- /data/icons/country/united.kingdom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwxg/zypp-gui/101b086d82e7de5641a5cb3c35f2474e214cb317/data/icons/country/united.kingdom.png -------------------------------------------------------------------------------- /data/icons/country/united.states.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwxg/zypp-gui/101b086d82e7de5641a5cb3c35f2474e214cb317/data/icons/country/united.states.png -------------------------------------------------------------------------------- /data/icons/country/uruguay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwxg/zypp-gui/101b086d82e7de5641a5cb3c35f2474e214cb317/data/icons/country/uruguay.png -------------------------------------------------------------------------------- /data/icons/country/uzbekistan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwxg/zypp-gui/101b086d82e7de5641a5cb3c35f2474e214cb317/data/icons/country/uzbekistan.png -------------------------------------------------------------------------------- /data/icons/meson.build: -------------------------------------------------------------------------------- 1 | install_data( 2 | '@0@.svg'.format(application_id), 3 | install_dir: iconsdir / 'hicolor' / 'scalable' / 'apps' 4 | ) 5 | 6 | install_data( 7 | '@0@-symbolic.svg'.format(base_id), 8 | install_dir: iconsdir / 'hicolor' / 'symbolic' / 'apps', 9 | rename: '@0@-symbolic.svg'.format(application_id) 10 | ) 11 | 12 | install_subdir( 13 | 'country', 14 | install_dir: iconsdir / 'hicolor' / '16x16' / 'places', 15 | strip_directory : true 16 | ) 17 | -------------------------------------------------------------------------------- /data/icons/zypp.gui-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 13 | 15 | 17 | 18 | 20 | image/svg+xml 21 | 23 | 24 | 25 | 26 | 27 | 31 | 35 | 41 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /data/icons/zypp.gui.svg: -------------------------------------------------------------------------------- 1 | 2 | 13 | 15 | 17 | 18 | 20 | image/svg+xml 21 | 23 | 24 | 25 | 26 | 27 | 31 | 35 | 41 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /data/meson.build: -------------------------------------------------------------------------------- 1 | subdir('icons') 2 | subdir('resources') 3 | # Desktop file 4 | desktop_conf = configuration_data() 5 | desktop_conf.set('icon', application_id) 6 | desktop_file = i18n.merge_file( 7 | type: 'desktop', 8 | input: configure_file( 9 | input: '@0@.desktop.in.in'.format(base_id), 10 | output: '@BASENAME@', 11 | configuration: desktop_conf 12 | ), 13 | output: '@0@.desktop'.format(application_id), 14 | po_dir: podir, 15 | install: true, 16 | install_dir: datadir / 'applications' 17 | ) 18 | # Validate Desktop file 19 | if desktop_file_validate.found() 20 | test( 21 | 'validate-desktop', 22 | desktop_file_validate, 23 | args: [ 24 | desktop_file.full_path() 25 | ], 26 | depends: desktop_file, 27 | ) 28 | endif 29 | 30 | # Appdata 31 | appdata_conf = configuration_data() 32 | appdata_conf.set('app-id', application_id) 33 | appdata_conf.set('gettext-package', gettext_package) 34 | appdata_file = i18n.merge_file( 35 | input: configure_file( 36 | input: '@0@.metainfo.xml.in.in'.format(base_id), 37 | output: '@BASENAME@', 38 | configuration: appdata_conf 39 | ), 40 | output: '@0@.metainfo.xml'.format(application_id), 41 | po_dir: podir, 42 | install: true, 43 | install_dir: datadir / 'metainfo' 44 | ) 45 | # Validate Appdata 46 | if appstream_util.found() 47 | test( 48 | 'validate-appdata', appstream_util, 49 | args: [ 50 | 'validate', '--nonet', appdata_file.full_path() 51 | ], 52 | depends: appdata_file, 53 | ) 54 | endif 55 | 56 | # GSchema 57 | gschema_conf = configuration_data() 58 | gschema_conf.set('app-id', application_id) 59 | gschema_conf.set('gettext-package', gettext_package) 60 | configure_file( 61 | input: '@0@.gschema.xml.in'.format(base_id), 62 | output: '@0@.gschema.xml'.format(application_id), 63 | configuration: gschema_conf, 64 | install: true, 65 | install_dir: datadir / 'glib-2.0' / 'schemas' 66 | ) 67 | 68 | # Validata GSchema 69 | if glib_compile_schemas.found() 70 | test( 71 | 'validate-gschema', glib_compile_schemas, 72 | args: [ 73 | '--strict', '--dry-run', meson.current_build_dir() 74 | ], 75 | ) 76 | endif 77 | 78 | # Policy file 79 | policy_conf = configuration_data() 80 | policy_conf.set('path', bindir) 81 | policy_conf.set('icon', application_id) 82 | policy_file = i18n.merge_file( 83 | input: configure_file( 84 | input: '@0@.policy.in.in'.format(base_id), 85 | output: '@BASENAME@', 86 | configuration: policy_conf 87 | ), 88 | output: '@0@.policy'.format(application_id), 89 | po_dir: podir, 90 | install: true, 91 | install_dir: datadir / 'polkit-1' / 'actions' 92 | ) 93 | 94 | # Service file 95 | service_conf = configuration_data() 96 | service_conf.set('app_id', application_id) 97 | service_conf.set('bindir', bindir) 98 | configure_file( 99 | input: '@0@.service.in'.format(base_id), 100 | output: '@0@.service'.format(application_id), 101 | configuration: service_conf, 102 | install: true, 103 | install_dir: datadir / 'dbus-1' / 'services' 104 | ) 105 | 106 | # Auto start Service file 107 | auto_conf = configuration_data() 108 | auto_conf.set('bindir', bindir) 109 | configure_file( 110 | input : 'zypp-gui-service.desktop.in', 111 | output : 'zypp-gui-service.desktop', 112 | configuration: auto_conf, 113 | install: true, 114 | install_dir: join_paths(get_option('sysconfdir'), 'xdg/autostart'), 115 | ) 116 | 117 | # Mirror sites data file 118 | mirror_conf = configuration_data() 119 | mirror_conf.set('bindir', bindir) 120 | configure_file( 121 | input : 'mirror.json.in', 122 | output : 'mirror.json', 123 | configuration: mirror_conf, 124 | install: true, 125 | install_dir: pkgdatadir, 126 | ) 127 | -------------------------------------------------------------------------------- /data/resources/meson.build: -------------------------------------------------------------------------------- 1 | blueprints = custom_target('blueprints', 2 | input: files( 3 | 'ui/additional_row.blp', 4 | 'ui/mirror_row.blp', 5 | 'ui/mirror_window.blp', 6 | 'ui/repo_add.blp', 7 | 'ui/repo_row.blp', 8 | 'ui/search_row.blp', 9 | 'ui/list_row.blp', 10 | 'ui/window.blp', 11 | 'ui/page_settings.blp', 12 | ), 13 | output: '.', 14 | command: [find_program('blueprint-compiler'), 'batch-compile', '@OUTPUT@', '@CURRENT_SOURCE_DIR@', '@INPUT@'], 15 | ) 16 | 17 | # Resources 18 | resources = gnome.compile_resources( 19 | 'resources', 20 | 'resources.gresource.xml', 21 | gresource_bundle: true, 22 | source_dir: meson.current_build_dir(), 23 | install: true, 24 | install_dir: pkgdatadir, 25 | dependencies: blueprints, 26 | ) 27 | 28 | -------------------------------------------------------------------------------- /data/resources/resources.gresource.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ui/window.ui 5 | ui/list_row.ui 6 | ui/repo_row.ui 7 | ui/search_row.ui 8 | ui/repo_add.ui 9 | ui/mirror_row.ui 10 | ui/mirror_window.ui 11 | ui/additional_row.ui 12 | ui/page_settings.ui 13 | 14 | style.css 15 | 16 | 17 | -------------------------------------------------------------------------------- /data/resources/screenshots/screenshot1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwxg/zypp-gui/101b086d82e7de5641a5cb3c35f2474e214cb317/data/resources/screenshots/screenshot1.png -------------------------------------------------------------------------------- /data/resources/screenshots/screenshot2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwxg/zypp-gui/101b086d82e7de5641a5cb3c35f2474e214cb317/data/resources/screenshots/screenshot2.png -------------------------------------------------------------------------------- /data/resources/screenshots/screenshot3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwxg/zypp-gui/101b086d82e7de5641a5cb3c35f2474e214cb317/data/resources/screenshots/screenshot3.png -------------------------------------------------------------------------------- /data/resources/screenshots/screenshot4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwxg/zypp-gui/101b086d82e7de5641a5cb3c35f2474e214cb317/data/resources/screenshots/screenshot4.png -------------------------------------------------------------------------------- /data/resources/screenshots/screenshot5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwxg/zypp-gui/101b086d82e7de5641a5cb3c35f2474e214cb317/data/resources/screenshots/screenshot5.png -------------------------------------------------------------------------------- /data/resources/screenshots/screenshot6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwxg/zypp-gui/101b086d82e7de5641a5cb3c35f2474e214cb317/data/resources/screenshots/screenshot6.png -------------------------------------------------------------------------------- /data/resources/screenshots/screenshot7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwxg/zypp-gui/101b086d82e7de5641a5cb3c35f2474e214cb317/data/resources/screenshots/screenshot7.png -------------------------------------------------------------------------------- /data/resources/screenshots/screenshot8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwxg/zypp-gui/101b086d82e7de5641a5cb3c35f2474e214cb317/data/resources/screenshots/screenshot8.png -------------------------------------------------------------------------------- /data/resources/style.css: -------------------------------------------------------------------------------- 1 | .repo-box{ 2 | border-color: #bbbbbb; 3 | border-radius: 8px; 4 | border-width: 1px; 5 | border-style: solid; 6 | } 7 | 8 | .mirror-box{ 9 | border-color: #bbbbbb; 10 | border-radius: 8px; 11 | border-width: 1px; 12 | border-style: solid; 13 | } 14 | 15 | .additional-box{ 16 | border-color: #bbbbbb; 17 | border-width: 1px; 18 | border-style: solid; 19 | } 20 | -------------------------------------------------------------------------------- /data/resources/ui/additional_row.blp: -------------------------------------------------------------------------------- 1 | using Gtk 4.0; 2 | using Adw 1; 3 | 4 | Adw.ExpanderRow additional_row { 5 | title: _("Repo"); 6 | 7 | styles [ 8 | "additional-box", 9 | ] 10 | 11 | [action] 12 | Button button_add { 13 | label: _("Add"); 14 | valign: center; 15 | 16 | styles [ 17 | "list-button", 18 | ] 19 | } 20 | 21 | Box { 22 | 23 | Label repo_info { 24 | halign: start; 25 | margin-start: 5; 26 | wrap: true; 27 | wrap-mode: word; 28 | label: _("info"); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /data/resources/ui/list_row.blp: -------------------------------------------------------------------------------- 1 | using Gtk 4.0; 2 | 3 | Box row { 4 | margin-start: 10; 5 | margin-end: 10; 6 | margin-top: 5; 7 | margin-bottom: 5; 8 | homogeneous: true; 9 | 10 | Label name { 11 | halign: start; 12 | xalign: 0; 13 | } 14 | 15 | Label version { 16 | halign: end; 17 | wrap: true; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /data/resources/ui/mirror_row.blp: -------------------------------------------------------------------------------- 1 | using Gtk 4.0; 2 | using Adw 1; 3 | 4 | Adw.ActionRow mirror_row { 5 | title: _("Hello"); 6 | activatable: true; 7 | 8 | Label { 9 | } 10 | 11 | Image { 12 | icon-name: "go-next-symbolic"; 13 | 14 | styles [ 15 | "dim-label", 16 | ] 17 | } 18 | 19 | styles [ 20 | "content", 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /data/resources/ui/mirror_window.blp: -------------------------------------------------------------------------------- 1 | using Gtk 4.0; 2 | 3 | Window mirror_window { 4 | title: _("Mirror Site"); 5 | 6 | Box { 7 | margin-start: 20; 8 | margin-end: 20; 9 | margin-top: 10; 10 | margin-bottom: 10; 11 | orientation: vertical; 12 | 13 | Box { 14 | margin-top: 5; 15 | margin-bottom: 5; 16 | 17 | Label country { 18 | halign: start; 19 | label: _("country"); 20 | } 21 | 22 | Label site { 23 | label: _("site"); 24 | } 25 | } 26 | 27 | Separator { 28 | } 29 | 30 | Label { 31 | halign: start; 32 | margin-end: 20; 33 | margin-top: 10; 34 | margin-bottom: 5; 35 | label: _("Url"); 36 | } 37 | 38 | Box connect_box { 39 | margin-top: 5; 40 | margin-bottom: 5; 41 | } 42 | 43 | Box { 44 | margin-top: 5; 45 | margin-bottom: 5; 46 | orientation: vertical; 47 | 48 | Label { 49 | halign: start; 50 | margin-bottom: 5; 51 | label: _("Distributions"); 52 | } 53 | 54 | Box distro_box { 55 | } 56 | } 57 | 58 | Button add { 59 | label: _("Add to repo"); 60 | receives-default: true; 61 | halign: end; 62 | margin-top: 10; 63 | margin-bottom: 5; 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /data/resources/ui/page_settings.blp: -------------------------------------------------------------------------------- 1 | using Gtk 4.0; 2 | using Adw 1; 3 | 4 | Adw.NavigationSplitView page_settings { 5 | sidebar: Adw.NavigationPage { 6 | title: _("Sidebar"); 7 | child: Adw.ToolbarView { 8 | [top] 9 | Adw.HeaderBar { 10 | title-widget: Adw.WindowTitle { 11 | title: _("Settings"); 12 | }; 13 | [start] 14 | Button button_deck_back { 15 | icon-name: "go-previous-symbolic"; 16 | } 17 | } 18 | StackSidebar { 19 | width-request: 100; 20 | vexpand: true; 21 | stack: setting_stack; 22 | styles [ "content", ] 23 | } 24 | }; 25 | }; 26 | 27 | content: Adw.NavigationPage { 28 | title: _("Content"); 29 | child: Adw.ToolbarView { 30 | [top] 31 | Adw.HeaderBar top_right_box { 32 | show-title: false; 33 | [start] 34 | Button repo_add { 35 | label: _("Add"); 36 | } 37 | } 38 | content: Stack setting_stack { 39 | vexpand: true; 40 | hexpand: true; 41 | StackPage { 42 | name: "Repo List"; 43 | title: _("Repo List"); 44 | child: 45 | ScrolledWindow repo_list { 46 | Viewport { 47 | Adw.Clamp { 48 | Box repo_box { 49 | orientation: vertical; 50 | homogeneous: true; 51 | spacing: 20; 52 | margin-bottom: 10; 53 | } 54 | } 55 | } 56 | }; 57 | } 58 | 59 | StackPage { 60 | name: "Mirrors"; 61 | title: _("Mirrors"); 62 | child: 63 | ScrolledWindow mirror { 64 | Viewport { 65 | Adw.Clamp { 66 | Box { 67 | orientation: vertical; 68 | Box mirror_page { 69 | orientation: vertical; 70 | 71 | Box { 72 | margin-top: 10; 73 | orientation: vertical; 74 | 75 | Label { 76 | halign: start; 77 | margin-top: 10; 78 | margin-bottom: 5; 79 | label: _("Asia"); 80 | } 81 | 82 | ListBox asia { 83 | selection-mode: none; 84 | styles [ "mirror-box", ] 85 | } 86 | } 87 | 88 | Box { 89 | margin-top: 10; 90 | orientation: vertical; 91 | 92 | Label { 93 | halign: start; 94 | margin-top: 10; 95 | margin-bottom: 5; 96 | label: _("Africa"); 97 | } 98 | 99 | ListBox africa { 100 | selection-mode: none; 101 | styles [ "mirror-box", ] 102 | } 103 | } 104 | 105 | Box { 106 | margin-top: 10; 107 | orientation: vertical; 108 | 109 | Label { 110 | halign: start; 111 | margin-top: 10; 112 | margin-bottom: 5; 113 | label: _("Europe"); 114 | } 115 | 116 | ListBox europe { 117 | selection-mode: none; 118 | styles [ "mirror-box", ] 119 | } 120 | } 121 | 122 | Box { 123 | margin-top: 10; 124 | orientation: vertical; 125 | 126 | Label { 127 | halign: start; 128 | margin-top: 10; 129 | margin-bottom: 5; 130 | label: _("North America"); 131 | } 132 | 133 | ListBox north_america { 134 | selection-mode: none; 135 | styles [ "mirror-box", ] 136 | } 137 | } 138 | 139 | Box { 140 | margin-top: 10; 141 | orientation: vertical; 142 | 143 | Label { 144 | halign: start; 145 | margin-top: 10; 146 | margin-bottom: 5; 147 | label: _("Oceania"); 148 | } 149 | 150 | ListBox oceania { 151 | selection-mode: none; 152 | styles [ "mirror-box", ] 153 | } 154 | } 155 | 156 | Box { 157 | margin-top: 10; 158 | orientation: vertical; 159 | 160 | Label { 161 | halign: start; 162 | margin-top: 10; 163 | margin-bottom: 5; 164 | label: _("South America"); 165 | } 166 | 167 | ListBox south_america { 168 | selection-mode: none; 169 | styles [ "mirror-box", ] 170 | } 171 | } 172 | } 173 | } 174 | } 175 | } 176 | } 177 | ; 178 | } 179 | 180 | StackPage { 181 | name: "Additional Repos"; 182 | title: _("Additional Repos"); 183 | child: 184 | ScrolledWindow additional_repo { 185 | 186 | Viewport { 187 | Adw.Clamp { 188 | Box { 189 | margin-start: 20; 190 | margin-end: 20; 191 | margin-top: 20; 192 | margin-bottom: 20; 193 | orientation: vertical; 194 | 195 | ListBox additional_page { 196 | } 197 | } 198 | } 199 | } 200 | }; 201 | } 202 | }; 203 | }; 204 | }; 205 | } 206 | -------------------------------------------------------------------------------- /data/resources/ui/repo_add.blp: -------------------------------------------------------------------------------- 1 | using Gtk 4.0; 2 | 3 | Window repo_add_window { 4 | default-width: 440; 5 | 6 | Box { 7 | margin-start: 20; 8 | margin-end: 20; 9 | margin-top: 10; 10 | margin-bottom: 10; 11 | orientation: vertical; 12 | 13 | Box { 14 | margin-top: 5; 15 | margin-bottom: 5; 16 | orientation: vertical; 17 | 18 | Label { 19 | halign: start; 20 | label: _("Name:"); 21 | } 22 | 23 | Entry repo_name { 24 | } 25 | } 26 | 27 | Box { 28 | margin-top: 5; 29 | margin-bottom: 5; 30 | orientation: vertical; 31 | 32 | Label { 33 | halign: start; 34 | label: _("Url:"); 35 | } 36 | 37 | Entry repo_url { 38 | } 39 | } 40 | 41 | Box { 42 | margin-top: 5; 43 | margin-bottom: 5; 44 | homogeneous: true; 45 | 46 | Button add_cancel { 47 | margin-end: 5; 48 | label: _("Cancel"); 49 | receives-default: true; 50 | } 51 | 52 | Button add_ok { 53 | margin-start: 5; 54 | label: _("OK"); 55 | receives-default: true; 56 | } 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /data/resources/ui/repo_row.blp: -------------------------------------------------------------------------------- 1 | using Gtk 4.0; 2 | using Adw 1; 3 | 4 | Adw.PreferencesGroup repo_row { 5 | title: _("repo name"); 6 | 7 | header-suffix: Button delete_button { 8 | child: Adw.ButtonContent { 9 | icon-name: "user-trash-symbolic"; 10 | }; 11 | 12 | styles [ 13 | "flat", 14 | ] 15 | }; 16 | 17 | Adw.SwitchRow enable_switch { 18 | title: _("Enable"); 19 | } 20 | 21 | Adw.SwitchRow refresh_button { 22 | title: _("Refresh"); 23 | } 24 | 25 | Adw.SpinRow priority_button { 26 | title: _("Priority"); 27 | 28 | adjustment: Adjustment { 29 | lower: 1; 30 | upper: 99; 31 | value: 90; 32 | page-increment: 10; 33 | step-increment: 1; 34 | }; 35 | } 36 | 37 | Adw.ActionRow url { 38 | title: _("repo url"); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /data/resources/ui/search_row.blp: -------------------------------------------------------------------------------- 1 | using Gtk 4.0; 2 | using Adw 1; 3 | 4 | Adw.ActionRow row { 5 | activatable: false; 6 | selectable: false; 7 | title: _("title"); 8 | subtitle: _("subtitle\nsecond line"); 9 | subtitle-lines: 2; 10 | 11 | Button operation_button { 12 | label: _("Install"); 13 | width-request: 100; 14 | receives-default: false; 15 | halign: end; 16 | valign: center; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /data/resources/ui/window.blp: -------------------------------------------------------------------------------- 1 | using Gtk 4.0; 2 | using Adw 1; 3 | 4 | Adw.ApplicationWindow window { 5 | vexpand: true; 6 | default-width: 800; 7 | default-height: 600; 8 | 9 | Adw.ViewStack viewstack { 10 | vexpand: true; 11 | 12 | Box page_update { 13 | vexpand: true; 14 | hexpand: true; 15 | orientation: vertical; 16 | 17 | Adw.HeaderBar headerbar1 { 18 | 19 | ToggleButton search_button { 20 | receives-default: true; 21 | 22 | Image { 23 | icon-name: "edit-find-symbolic"; 24 | } 25 | } 26 | 27 | Button button_settings { 28 | receives-default: true; 29 | 30 | Image { 31 | icon-name: "applications-system-symbolic"; 32 | } 33 | } 34 | } 35 | 36 | Revealer notification_bar { 37 | valign: start; 38 | 39 | Box notification_box { 40 | 41 | Label notification_label { 42 | label: _("Notification here."); 43 | wrap: true; 44 | } 45 | 46 | Button notification_button { 47 | receives-default: true; 48 | 49 | Image { 50 | icon-name: "window-close-symbolic"; 51 | } 52 | } 53 | 54 | styles [ 55 | "app-notification", 56 | ] 57 | } 58 | } 59 | 60 | Stack button_stack { 61 | 62 | Box update_button { 63 | homogeneous: true; 64 | margin-start: 20; 65 | margin-end: 20; 66 | margin-top: 10; 67 | margin-bottom: 10; 68 | 69 | Button cancel_button { 70 | label: _("Cancel"); 71 | receives-default: true; 72 | halign: start; 73 | } 74 | 75 | Box { 76 | halign: end; 77 | 78 | Button download_button { 79 | label: _("Download"); 80 | receives-default: true; 81 | margin-end: 10; 82 | } 83 | 84 | Button offline_update_button { 85 | label: _("Offline Update"); 86 | receives-default: true; 87 | margin-end: 10; 88 | margin-start: 10; 89 | } 90 | } 91 | } 92 | 93 | Adw.Clamp search_bar { 94 | 95 | Entry search_entry { 96 | margin-start: 40; 97 | margin-end: 40; 98 | margin-top: 5; 99 | margin-bottom: 5; 100 | primary-icon-name: "edit-find-symbolic"; 101 | primary-icon-activatable: false; 102 | primary-icon-sensitive: false; 103 | } 104 | } 105 | } 106 | 107 | Stack stack_box { 108 | margin-start: 20; 109 | margin-end: 20; 110 | vexpand: true; 111 | hexpand: true; 112 | 113 | ScrolledWindow stack_list { 114 | margin-bottom: 10; 115 | 116 | Viewport { 117 | 118 | Box { 119 | orientation: vertical; 120 | vexpand: true; 121 | hexpand: true; 122 | 123 | ListBox list_box { 124 | selection-mode: none; 125 | vexpand: true; 126 | hexpand: true; 127 | } 128 | } 129 | } 130 | } 131 | 132 | Box progress { 133 | valign: center; 134 | margin-start: 20; 135 | margin-end: 20; 136 | orientation: vertical; 137 | 138 | Label progress_label { 139 | valign: center; 140 | margin-bottom: 10; 141 | hexpand: true; 142 | justify: center; 143 | yalign: 0.5; 144 | } 145 | 146 | ProgressBar progress_bar { 147 | valign: center; 148 | margin-start: 20; 149 | margin-end: 20; 150 | ellipsize: middle; 151 | } 152 | } 153 | 154 | Adw.Clamp stack_label { 155 | 156 | Label label { 157 | label: _("No update."); 158 | use-markup: true; 159 | } 160 | } 161 | 162 | ScrolledWindow search_box { 163 | margin-bottom: 10; 164 | 165 | Viewport { 166 | 167 | Box { 168 | orientation: vertical; 169 | 170 | ListBox search_list_box { 171 | } 172 | } 173 | } 174 | } 175 | } 176 | } 177 | } 178 | } 179 | -------------------------------------------------------------------------------- /data/zypp-gui-service.desktop.in: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Type=Application 3 | Name=zypp gui 4 | Exec=@bindir@/zypp-gui --gapplication-service 5 | NotShowIn=Budgie 6 | NoDisplay=true 7 | -------------------------------------------------------------------------------- /data/zypp.gui.desktop.in.in: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Name=zypp gui 3 | Comment=Update, install and remove software 4 | Type=Application 5 | Exec=zypp-gui %U 6 | Terminal=false 7 | Categories=GTK; 8 | Keywords=GTK; 9 | # Translators: Do NOT translate or transliterate this text (this is an icon file name)! 10 | Icon=@icon@ 11 | StartupNotify=true 12 | DBusActivatable=true 13 | -------------------------------------------------------------------------------- /data/zypp.gui.gschema.xml.in: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /data/zypp.gui.metainfo.xml.in.in: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | @app-id@ 5 | CC0 6 | 7 | 8 | zypp gui 9 | Update, install and remove software on the computer 10 | 11 |

Application runs as a deamon to monitor the system update. When there is new update, update the system. Application can search, install and remove the package, configure the repos.

12 |
13 | 14 | 15 | /screenshots/screenshot1.png 16 | Main window 17 | 18 | 19 | http://github.com/sunwxg/zypp-gui 20 | http://github.com/sunwxg/zypp-gui/issues 21 | 22 | 23 | 24 | 25 | 26 | ModernToolkit 27 | HiDpiIcon 28 | 29 | Xiaoguang Wang 30 | sun.wxg@gmail.com 31 | @gettext-package@ 32 | @app-id@.desktop 33 |
34 | -------------------------------------------------------------------------------- /data/zypp.gui.policy.in.in: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | zypp gui 7 | https://github.com/sunwxg/zypp-gui/ 8 | @icon@ 9 | 10 | 11 | Get/Set repos settings 12 | Privileges are required to get/set repos settings 13 | 14 | auth_admin 15 | auth_admin 16 | auth_admin_keep 17 | 18 | @path@/mod-repo 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /data/zypp.gui.service.in: -------------------------------------------------------------------------------- 1 | [D-BUS Service] 2 | Name=@app_id@ 3 | Exec=@bindir@/zypp-gui --gapplication-service 4 | -------------------------------------------------------------------------------- /hooks/pre-commit.hook: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Source: https://gitlab.gnome.org/GNOME/fractal/blob/master/hooks/pre-commit.hook 3 | 4 | install_rustfmt() { 5 | if ! which rustup &> /dev/null; then 6 | curl https://sh.rustup.rs -sSf | sh -s -- -y 7 | export PATH=$PATH:$HOME/.cargo/bin 8 | if ! which rustup &> /dev/null; then 9 | echo "Failed to install rustup. Performing the commit without style checking." 10 | exit 0 11 | fi 12 | fi 13 | 14 | if ! rustup component list|grep rustfmt &> /dev/null; then 15 | echo "Installing rustfmt…" 16 | rustup component add rustfmt 17 | fi 18 | } 19 | 20 | if ! which cargo &> /dev/null || ! cargo fmt --help &> /dev/null; then 21 | echo "Unable to check code style, because rustfmt could not be run." 22 | 23 | if [ ! -t 1 ]; then 24 | # No input is possible 25 | echo "Performing commit." 26 | exit 0 27 | fi 28 | 29 | echo "" 30 | echo "y: Install rustfmt via rustup" 31 | echo "n: Don't install rustfmt and perform the commit" 32 | echo "Q: Don't install rustfmt and abort the commit" 33 | 34 | while true; do 35 | read -p "Install rustfmt via rustup? [y/n/Q]: " yn 36 | case $yn in 37 | [Yy]* ) install_rustfmt; break;; 38 | [Nn]* ) echo "Performing commit."; exit 0;; 39 | [Qq]* | "" ) echo "Aborting commit."; exit -1;; 40 | * ) echo "Invalid input";; 41 | esac 42 | done 43 | fi 44 | 45 | echo "--Checking style--" 46 | #cargo fmt --all -- --check 47 | cargo fmt --manifest-path zypp-gui/Cargo.toml -- --check 48 | if test $? != 0; then 49 | echo "--Checking style fail--" 50 | echo "Please fix the above issues, either manually or by running: cargo fmt --manifest-path zypp-gui/Cargo.toml" 51 | 52 | exit -1 53 | fi 54 | cargo fmt --manifest-path mod_repo/Cargo.toml -- --check 55 | if test $? != 0; then 56 | echo "--Checking style fail--" 57 | echo "Please fix the above issues, either manually or by running: cargo fmt --manifest-path mod_repo/Cargo.toml" 58 | 59 | exit -1 60 | fi 61 | cargo fmt --manifest-path packagekit_rs/Cargo.toml -- --check 62 | if test $? != 0; then 63 | echo "--Checking style fail--" 64 | echo "Please fix the above issues, either manually or by running: cargo fmt --manifest-path packagekit_rs/Cargo.toml" 65 | 66 | exit -1 67 | fi 68 | 69 | echo "--Checking style pass--" 70 | -------------------------------------------------------------------------------- /meson.build: -------------------------------------------------------------------------------- 1 | project( 2 | 'zypp-gui', 3 | 'rust', 4 | version: '0.4.1', 5 | meson_version: '>= 0.50', 6 | ) 7 | 8 | i18n = import('i18n') 9 | gnome = import('gnome') 10 | 11 | base_id = 'zypp.gui' 12 | 13 | dependency('glib-2.0', version: '>= 2.56') 14 | dependency('gio-2.0', version: '>= 2.56') 15 | dependency('gtk+-3.0', version: '>= 3.24.7') 16 | 17 | glib_compile_resources = find_program('glib-compile-resources', required: true) 18 | glib_compile_schemas = find_program('glib-compile-schemas', required: true) 19 | desktop_file_validate = find_program('desktop-file-validate', required: false) 20 | appstream_util = find_program('appstream-util', required: false) 21 | cargo = find_program('cargo', required: true) 22 | cargo_script = find_program('build-aux/cargo.sh') 23 | 24 | version = meson.project_version() 25 | version_array = version.split('.') 26 | major_version = version_array[0].to_int() 27 | minor_version = version_array[1].to_int() 28 | version_micro = version_array[2].to_int() 29 | 30 | prefix = get_option('prefix') 31 | bindir = prefix / get_option('bindir') 32 | localedir = prefix / get_option('localedir') 33 | 34 | datadir = prefix / get_option('datadir') 35 | pkgdatadir = datadir / meson.project_name() 36 | iconsdir = datadir / 'icons' 37 | podir = meson.source_root() / 'po' 38 | gettext_package = meson.project_name() 39 | 40 | if get_option('profile') == 'development' 41 | profile = 'Devel' 42 | vcs_tag = run_command('git', 'rev-parse', '--short', 'HEAD').stdout().strip() 43 | if vcs_tag == '' 44 | version_suffix = '-devel' 45 | else 46 | version_suffix = '-@0@'.format(vcs_tag) 47 | endif 48 | application_id = '@0@.@1@'.format(base_id, profile) 49 | else 50 | profile = '' 51 | version_suffix = '' 52 | application_id = base_id 53 | endif 54 | 55 | 56 | #meson.add_dist_script( 57 | #'build-aux/dist-vendor.sh', 58 | #meson.build_root() / 'meson-dist' / meson.project_name() + '-' + version, 59 | #meson.source_root() 60 | #) 61 | 62 | if get_option('profile') == 'development' 63 | # Setup pre-commit hook for ensuring coding style is always consistent 64 | message('Setting up git pre-commit hook..') 65 | run_command('cp', '-f', 'hooks/pre-commit.hook', '.git/hooks/pre-commit') 66 | endif 67 | 68 | if get_option('profile') == 'default' 69 | # Setup pre-commit hook for ensuring coding style is always consistent 70 | message('Setting up git pre-commit hook..') 71 | run_command('cp', '-f', 'hooks/pre-commit.hook', '.git/hooks/pre-commit') 72 | endif 73 | 74 | subdir('data') 75 | subdir('po') 76 | subdir('zypp-gui') 77 | subdir('mod_repo') 78 | 79 | meson.add_install_script('build-aux/meson_post_install.py') 80 | -------------------------------------------------------------------------------- /meson_options.txt: -------------------------------------------------------------------------------- 1 | option( 2 | 'profile', 3 | type: 'combo', 4 | choices: [ 5 | 'default', 6 | 'development' 7 | ], 8 | value: 'default', 9 | description: 'The build profile for zypp gui. One of "default" or "development".' 10 | ) 11 | -------------------------------------------------------------------------------- /mod_repo/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /mod_repo/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "ansi_term" 7 | version = "0.12.1" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" 10 | dependencies = [ 11 | "winapi", 12 | ] 13 | 14 | [[package]] 15 | name = "atty" 16 | version = "0.2.14" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" 19 | dependencies = [ 20 | "hermit-abi", 21 | "libc", 22 | "winapi", 23 | ] 24 | 25 | [[package]] 26 | name = "bitflags" 27 | version = "1.3.2" 28 | source = "registry+https://github.com/rust-lang/crates.io-index" 29 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 30 | 31 | [[package]] 32 | name = "clap" 33 | version = "2.34.0" 34 | source = "registry+https://github.com/rust-lang/crates.io-index" 35 | checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" 36 | dependencies = [ 37 | "ansi_term", 38 | "atty", 39 | "bitflags", 40 | "strsim", 41 | "textwrap", 42 | "unicode-width", 43 | "vec_map", 44 | ] 45 | 46 | [[package]] 47 | name = "hermit-abi" 48 | version = "0.1.19" 49 | source = "registry+https://github.com/rust-lang/crates.io-index" 50 | checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" 51 | dependencies = [ 52 | "libc", 53 | ] 54 | 55 | [[package]] 56 | name = "libc" 57 | version = "0.2.144" 58 | source = "registry+https://github.com/rust-lang/crates.io-index" 59 | checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1" 60 | 61 | [[package]] 62 | name = "mod-repo" 63 | version = "0.1.0" 64 | dependencies = [ 65 | "clap", 66 | ] 67 | 68 | [[package]] 69 | name = "strsim" 70 | version = "0.8.0" 71 | source = "registry+https://github.com/rust-lang/crates.io-index" 72 | checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" 73 | 74 | [[package]] 75 | name = "textwrap" 76 | version = "0.11.0" 77 | source = "registry+https://github.com/rust-lang/crates.io-index" 78 | checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" 79 | dependencies = [ 80 | "unicode-width", 81 | ] 82 | 83 | [[package]] 84 | name = "unicode-width" 85 | version = "0.1.10" 86 | source = "registry+https://github.com/rust-lang/crates.io-index" 87 | checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" 88 | 89 | [[package]] 90 | name = "vec_map" 91 | version = "0.8.2" 92 | source = "registry+https://github.com/rust-lang/crates.io-index" 93 | checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" 94 | 95 | [[package]] 96 | name = "winapi" 97 | version = "0.3.9" 98 | source = "registry+https://github.com/rust-lang/crates.io-index" 99 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 100 | dependencies = [ 101 | "winapi-i686-pc-windows-gnu", 102 | "winapi-x86_64-pc-windows-gnu", 103 | ] 104 | 105 | [[package]] 106 | name = "winapi-i686-pc-windows-gnu" 107 | version = "0.4.0" 108 | source = "registry+https://github.com/rust-lang/crates.io-index" 109 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 110 | 111 | [[package]] 112 | name = "winapi-x86_64-pc-windows-gnu" 113 | version = "0.4.0" 114 | source = "registry+https://github.com/rust-lang/crates.io-index" 115 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 116 | -------------------------------------------------------------------------------- /mod_repo/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "mod-repo" 3 | version = "0.1.0" 4 | authors = ["Xiaoguang Wang "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | clap = "2.34.0" 11 | -------------------------------------------------------------------------------- /mod_repo/meson.build: -------------------------------------------------------------------------------- 1 | subdir('src') 2 | -------------------------------------------------------------------------------- /mod_repo/src/main.rs: -------------------------------------------------------------------------------- 1 | extern crate clap; 2 | use clap::{App, Arg, ArgMatches, SubCommand}; 3 | use std::process::{exit, Command, Stdio}; 4 | 5 | fn main() { 6 | let matches = App::new("Modify the repo settings") 7 | .version("1.0") 8 | .arg( 9 | Arg::with_name("enable") 10 | .short("e") 11 | .long("enable") 12 | .help("Enable the repo"), 13 | ) 14 | .arg( 15 | Arg::with_name("disable") 16 | .short("d") 17 | .long("disable") 18 | .help("Disable the repo"), 19 | ) 20 | .arg( 21 | Arg::with_name("refresh") 22 | .short("f") 23 | .long("refresh") 24 | .help("Refresh the repo"), 25 | ) 26 | .arg( 27 | Arg::with_name("no-refresh") 28 | .short("F") 29 | .long("no-refresh") 30 | .help("Not refresh the repo"), 31 | ) 32 | .arg( 33 | Arg::with_name("priority") 34 | .short("p") 35 | .long("priority") 36 | .help("Priority of the repo") 37 | .takes_value(true), 38 | ) 39 | .arg( 40 | Arg::with_name("cpg") 41 | .short("g") 42 | .long("cpg") 43 | .help("CPG check"), 44 | ) 45 | .arg( 46 | Arg::with_name("no-cpg") 47 | .short("G") 48 | .long("no-cpg") 49 | .help("no CPG check"), 50 | ) 51 | .arg( 52 | Arg::with_name("repo") 53 | .help("repo id") 54 | //.required(true) 55 | .index(1), 56 | ) 57 | .subcommand( 58 | SubCommand::with_name("add") 59 | .about("Add repo") 60 | .arg( 61 | Arg::with_name("name") 62 | .short("n") 63 | .long("name") 64 | .help("repo name") 65 | .required(true) 66 | .takes_value(true), 67 | ) 68 | .arg( 69 | Arg::with_name("url") 70 | .short("u") 71 | .long("url") 72 | .help("repo url") 73 | .required(true) 74 | .takes_value(true), 75 | ), 76 | ) 77 | .subcommand( 78 | SubCommand::with_name("delete").about("Delete repo").arg( 79 | Arg::with_name("id") 80 | .short("i") 81 | .long("id") 82 | .help("repo id") 83 | .required(true) 84 | .takes_value(true), 85 | ), 86 | ) 87 | .get_matches(); 88 | 89 | if matches.is_present("add") { 90 | add_repo(matches); 91 | } else if matches.is_present("delete") { 92 | delete_repo(matches); 93 | } else { 94 | modify_repo(matches); 95 | } 96 | } 97 | 98 | fn modify_repo(matches: ArgMatches) { 99 | let mut args: Vec<&str> = vec![]; 100 | if matches.is_present("enable") { 101 | args.push("-e"); 102 | } else if matches.is_present("disable") { 103 | args.push("-d"); 104 | } else if matches.is_present("refresh") { 105 | args.push("-f"); 106 | } else if matches.is_present("no-refresh") { 107 | args.push("-F"); 108 | } else if matches.is_present("cpg") { 109 | args.push("-g"); 110 | } else if matches.is_present("no-cpg") { 111 | args.push("-G"); 112 | } else if matches.is_present("priority") { 113 | let value = matches.value_of("priority").unwrap(); 114 | args.push("-p"); 115 | args.push(value); 116 | } 117 | 118 | let id = matches.value_of("repo").unwrap(); 119 | args.push(id); 120 | 121 | let status = Command::new("zypper") 122 | .arg("mr") 123 | .args(args) 124 | .stdout(Stdio::piped()) 125 | .status() 126 | .expect("failed to execute zypper"); 127 | 128 | if status.success() { 129 | exit(0); 130 | } else { 131 | exit(1); 132 | } 133 | } 134 | 135 | fn add_repo(matches: ArgMatches) { 136 | let mut args: Vec<&str> = vec![]; 137 | let add_matches = matches.subcommand_matches("add").unwrap(); 138 | 139 | if add_matches.is_present("url") { 140 | let value = add_matches.value_of("url").unwrap(); 141 | args.push(value); 142 | } 143 | if add_matches.is_present("name") { 144 | let value = add_matches.value_of("name").unwrap(); 145 | args.push(value); 146 | } 147 | 148 | let status = Command::new("zypper") 149 | .arg("ar") 150 | .arg("-d") 151 | .arg("-f") 152 | .args(args) 153 | .stdout(Stdio::piped()) 154 | .status() 155 | .expect("failed to execute zypper"); 156 | 157 | if status.success() { 158 | exit(0); 159 | } else { 160 | exit(1); 161 | } 162 | } 163 | 164 | fn delete_repo(matches: ArgMatches) { 165 | let mut args: Vec<&str> = vec![]; 166 | let delete_matches = matches.subcommand_matches("delete").unwrap(); 167 | 168 | if delete_matches.is_present("id") { 169 | let value = delete_matches.value_of("id").unwrap(); 170 | args.push(value); 171 | } 172 | 173 | let status = Command::new("zypper") 174 | .arg("rr") 175 | .args(args) 176 | .stdout(Stdio::piped()) 177 | .status() 178 | .expect("failed to execute zypper"); 179 | 180 | if status.success() { 181 | exit(0); 182 | } else { 183 | exit(1); 184 | } 185 | } 186 | -------------------------------------------------------------------------------- /mod_repo/src/meson.build: -------------------------------------------------------------------------------- 1 | 2 | sources = files( 3 | 'main.rs', 4 | ) 5 | 6 | custom_target( 7 | 'cargo-build', 8 | build_by_default: true, 9 | input: sources, 10 | output: 'mod-repo', 11 | console: true, 12 | install: true, 13 | install_dir: bindir, 14 | command: [ 15 | cargo_script, 16 | meson.build_root(), 17 | meson.source_root(), 18 | '@OUTPUT@', 19 | profile, 20 | 'mod-repo', 21 | 'mod_repo', 22 | ] 23 | ) 24 | -------------------------------------------------------------------------------- /packagekit_rs/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | Cargo.lock 3 | -------------------------------------------------------------------------------- /packagekit_rs/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "packagekit_rs" 3 | version = "0.1.0" 4 | authors = ["Xiaoguang Wang "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | package-kit-glib-sys = { path = "./packagekit-sys", features = ["v1_1_13"] } 11 | gio = "0.20" 12 | gio-sys = "0.20" 13 | libc = "0.2.97" 14 | glib = "0.20" 15 | glib-sys = "0.20" 16 | gobject-sys = "0.20.9" 17 | -------------------------------------------------------------------------------- /packagekit_rs/packagekit-sys/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "package-kit-glib-sys" 3 | version = "0.1.0" 4 | links = "\"packagekit-glib2\"" 5 | edition = "2018" 6 | build = "build.rs" 7 | [package.metadata.system-deps.packagekit_glib2] 8 | name = "packagekit-glib2" 9 | version = "0.0" 10 | 11 | [package.metadata.system-deps.packagekit_glib2.v0_5] 12 | version = "0.5" 13 | 14 | [package.metadata.system-deps.packagekit_glib2.v0_5_2] 15 | version = "0.5.2" 16 | 17 | [package.metadata.system-deps.packagekit_glib2.v0_5_3] 18 | version = "0.5.3" 19 | 20 | [package.metadata.system-deps.packagekit_glib2.v0_5_4] 21 | version = "0.5.4" 22 | 23 | [package.metadata.system-deps.packagekit_glib2.v0_5_5] 24 | version = "0.5.5" 25 | 26 | [package.metadata.system-deps.packagekit_glib2.v0_6] 27 | version = "0.6" 28 | 29 | [package.metadata.system-deps.packagekit_glib2.v0_6_1] 30 | version = "0.6.1" 31 | 32 | [package.metadata.system-deps.packagekit_glib2.v0_6_2] 33 | version = "0.6.2" 34 | 35 | [package.metadata.system-deps.packagekit_glib2.v0_6_3] 36 | version = "0.6.3" 37 | 38 | [package.metadata.system-deps.packagekit_glib2.v0_6_4] 39 | version = "0.6.4" 40 | 41 | [package.metadata.system-deps.packagekit_glib2.v0_6_5] 42 | version = "0.6.5" 43 | 44 | [package.metadata.system-deps.packagekit_glib2.v0_6_10] 45 | version = "0.6.10" 46 | 47 | [package.metadata.system-deps.packagekit_glib2.v0_6_11] 48 | version = "0.6.11" 49 | 50 | [package.metadata.system-deps.packagekit_glib2.v0_6_13] 51 | version = "0.6.13" 52 | 53 | [package.metadata.system-deps.packagekit_glib2.v0_7_2] 54 | version = "0.7.2" 55 | 56 | [package.metadata.system-deps.packagekit_glib2.v0_7_5] 57 | version = "0.7.5" 58 | 59 | [package.metadata.system-deps.packagekit_glib2.v0_8] 60 | version = "0.8" 61 | 62 | [package.metadata.system-deps.packagekit_glib2.v0_8_1] 63 | version = "0.8.1" 64 | 65 | [package.metadata.system-deps.packagekit_glib2.v0_8_2] 66 | version = "0.8.2" 67 | 68 | [package.metadata.system-deps.packagekit_glib2.v0_8_6] 69 | version = "0.8.6" 70 | 71 | [package.metadata.system-deps.packagekit_glib2.v0_8_8] 72 | version = "0.8.8" 73 | 74 | [package.metadata.system-deps.packagekit_glib2.v0_8_11] 75 | version = "0.8.11" 76 | 77 | [package.metadata.system-deps.packagekit_glib2.v0_8_12] 78 | version = "0.8.12" 79 | 80 | [package.metadata.system-deps.packagekit_glib2.v0_8_14] 81 | version = "0.8.14" 82 | 83 | [package.metadata.system-deps.packagekit_glib2.v0_8_16] 84 | version = "0.8.16" 85 | 86 | [package.metadata.system-deps.packagekit_glib2.v0_8_17] 87 | version = "0.8.17" 88 | 89 | [package.metadata.system-deps.packagekit_glib2.v0_9_1] 90 | version = "0.9.1" 91 | 92 | [package.metadata.system-deps.packagekit_glib2.v0_9_5] 93 | version = "0.9.5" 94 | 95 | [package.metadata.system-deps.packagekit_glib2.v0_9_6] 96 | version = "0.9.6" 97 | 98 | [package.metadata.system-deps.packagekit_glib2.v1_0_2] 99 | version = "1.0.2" 100 | 101 | [package.metadata.system-deps.packagekit_glib2.v1_0_10] 102 | version = "1.0.10" 103 | 104 | [package.metadata.system-deps.packagekit_glib2.v1_0_12] 105 | version = "1.0.12" 106 | 107 | [package.metadata.system-deps.packagekit_glib2.v1_1_2] 108 | version = "1.1.2" 109 | 110 | [package.metadata.system-deps.packagekit_glib2.v1_1_8] 111 | version = "1.1.8" 112 | 113 | [package.metadata.system-deps.packagekit_glib2.v1_1_13] 114 | version = "1.1.13" 115 | [package.metadata.docs.rs] 116 | features = ["dox"] 117 | 118 | [lib] 119 | name = "package_kit_glib_sys" 120 | 121 | [dependencies] 122 | libc = "0.2.97" 123 | gio-sys = "0.20" 124 | glib-sys = "0.20" 125 | gobject-sys = "0.20" 126 | 127 | [build-dependencies] 128 | system-deps = "7" 129 | 130 | [dev-dependencies] 131 | #shell-words = "1.0.0" 132 | #tempfile = "3" 133 | 134 | [features] 135 | v0_5 = [] 136 | v0_5_2 = ["v0_5"] 137 | v0_5_3 = ["v0_5_2"] 138 | v0_5_4 = ["v0_5_3"] 139 | v0_5_5 = ["v0_5_4"] 140 | v0_6 = ["v0_5_5"] 141 | v0_6_1 = ["v0_6"] 142 | v0_6_2 = ["v0_6_1"] 143 | v0_6_3 = ["v0_6_2"] 144 | v0_6_4 = ["v0_6_3"] 145 | v0_6_5 = ["v0_6_4"] 146 | v0_6_10 = ["v0_6_5"] 147 | v0_6_11 = ["v0_6_10"] 148 | v0_6_13 = ["v0_6_11"] 149 | v0_7_2 = ["v0_6_13"] 150 | v0_7_5 = ["v0_7_2"] 151 | v0_8 = ["v0_7_5"] 152 | v0_8_1 = ["v0_8"] 153 | v0_8_2 = ["v0_8_1"] 154 | v0_8_6 = ["v0_8_2"] 155 | v0_8_8 = ["v0_8_6"] 156 | v0_8_11 = ["v0_8_8"] 157 | v0_8_12 = ["v0_8_11"] 158 | v0_8_14 = ["v0_8_12"] 159 | v0_8_16 = ["v0_8_14"] 160 | v0_8_17 = ["v0_8_16"] 161 | v0_9_1 = ["v0_8_17"] 162 | v0_9_5 = ["v0_9_1"] 163 | v0_9_6 = ["v0_9_5"] 164 | v1_0_2 = ["v0_9_6"] 165 | v1_0_10 = ["v1_0_2"] 166 | v1_0_12 = ["v1_0_10"] 167 | v1_1_2 = ["v1_0_12"] 168 | v1_1_8 = ["v1_1_2"] 169 | v1_1_13 = ["v1_1_8"] 170 | dox = [] 171 | -------------------------------------------------------------------------------- /packagekit_rs/packagekit-sys/build.rs: -------------------------------------------------------------------------------- 1 | // Generated by gir (https://github.com/gtk-rs/gir @ f3d92ad) 2 | // from /home/home/person/git_hub/gir-files (@ 7d95377) 3 | // DO NOT EDIT 4 | 5 | #[cfg(not(feature = "dox"))] 6 | use std::process; 7 | 8 | #[cfg(feature = "dox")] 9 | fn main() {} // prevent linking libraries to avoid documentation failure 10 | 11 | #[cfg(not(feature = "dox"))] 12 | fn main() { 13 | if let Err(s) = system_deps::Config::new().probe() { 14 | println!("cargo:warning={}", s); 15 | process::exit(1); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packagekit_rs/packagekit-sys/tests/layout.c: -------------------------------------------------------------------------------- 1 | // Generated by gir (https://github.com/gtk-rs/gir @ f3d92ad) 2 | // from /home/home/person/git_hub/gir-files (@ 7d95377) 3 | // DO NOT EDIT 4 | 5 | #include "manual.h" 6 | #include 7 | #include 8 | 9 | int main() { 10 | printf("%s;%zu;%zu\n", "PkAuthorizeEnum", sizeof(PkAuthorizeEnum), alignof(PkAuthorizeEnum)); 11 | printf("%s;%zu;%zu\n", "PkBitfield", sizeof(PkBitfield), alignof(PkBitfield)); 12 | printf("%s;%zu;%zu\n", "PkCategory", sizeof(PkCategory), alignof(PkCategory)); 13 | printf("%s;%zu;%zu\n", "PkCategoryClass", sizeof(PkCategoryClass), alignof(PkCategoryClass)); 14 | printf("%s;%zu;%zu\n", "PkClient", sizeof(PkClient), alignof(PkClient)); 15 | printf("%s;%zu;%zu\n", "PkClientClass", sizeof(PkClientClass), alignof(PkClientClass)); 16 | printf("%s;%zu;%zu\n", "PkClientError", sizeof(PkClientError), alignof(PkClientError)); 17 | printf("%s;%zu;%zu\n", "PkClientHelper", sizeof(PkClientHelper), alignof(PkClientHelper)); 18 | printf("%s;%zu;%zu\n", "PkClientHelperClass", sizeof(PkClientHelperClass), alignof(PkClientHelperClass)); 19 | printf("%s;%zu;%zu\n", "PkControl", sizeof(PkControl), alignof(PkControl)); 20 | printf("%s;%zu;%zu\n", "PkControlClass", sizeof(PkControlClass), alignof(PkControlClass)); 21 | printf("%s;%zu;%zu\n", "PkControlError", sizeof(PkControlError), alignof(PkControlError)); 22 | printf("%s;%zu;%zu\n", "PkDesktop", sizeof(PkDesktop), alignof(PkDesktop)); 23 | printf("%s;%zu;%zu\n", "PkDesktopClass", sizeof(PkDesktopClass), alignof(PkDesktopClass)); 24 | printf("%s;%zu;%zu\n", "PkDetails", sizeof(PkDetails), alignof(PkDetails)); 25 | printf("%s;%zu;%zu\n", "PkDetailsClass", sizeof(PkDetailsClass), alignof(PkDetailsClass)); 26 | printf("%s;%zu;%zu\n", "PkDistroUpgrade", sizeof(PkDistroUpgrade), alignof(PkDistroUpgrade)); 27 | printf("%s;%zu;%zu\n", "PkDistroUpgradeClass", sizeof(PkDistroUpgradeClass), alignof(PkDistroUpgradeClass)); 28 | printf("%s;%zu;%zu\n", "PkDistroUpgradeEnum", sizeof(PkDistroUpgradeEnum), alignof(PkDistroUpgradeEnum)); 29 | printf("%s;%zu;%zu\n", "PkEnumMatch", sizeof(PkEnumMatch), alignof(PkEnumMatch)); 30 | printf("%s;%zu;%zu\n", "PkError", sizeof(PkError), alignof(PkError)); 31 | printf("%s;%zu;%zu\n", "PkErrorClass", sizeof(PkErrorClass), alignof(PkErrorClass)); 32 | printf("%s;%zu;%zu\n", "PkErrorEnum", sizeof(PkErrorEnum), alignof(PkErrorEnum)); 33 | printf("%s;%zu;%zu\n", "PkEulaRequired", sizeof(PkEulaRequired), alignof(PkEulaRequired)); 34 | printf("%s;%zu;%zu\n", "PkEulaRequiredClass", sizeof(PkEulaRequiredClass), alignof(PkEulaRequiredClass)); 35 | printf("%s;%zu;%zu\n", "PkExitEnum", sizeof(PkExitEnum), alignof(PkExitEnum)); 36 | printf("%s;%zu;%zu\n", "PkFiles", sizeof(PkFiles), alignof(PkFiles)); 37 | printf("%s;%zu;%zu\n", "PkFilesClass", sizeof(PkFilesClass), alignof(PkFilesClass)); 38 | printf("%s;%zu;%zu\n", "PkFilterEnum", sizeof(PkFilterEnum), alignof(PkFilterEnum)); 39 | printf("%s;%zu;%zu\n", "PkGroupEnum", sizeof(PkGroupEnum), alignof(PkGroupEnum)); 40 | printf("%s;%zu;%zu\n", "PkInfoEnum", sizeof(PkInfoEnum), alignof(PkInfoEnum)); 41 | printf("%s;%zu;%zu\n", "PkItemProgress", sizeof(PkItemProgress), alignof(PkItemProgress)); 42 | printf("%s;%zu;%zu\n", "PkItemProgressClass", sizeof(PkItemProgressClass), alignof(PkItemProgressClass)); 43 | printf("%s;%zu;%zu\n", "PkMediaChangeRequired", sizeof(PkMediaChangeRequired), alignof(PkMediaChangeRequired)); 44 | printf("%s;%zu;%zu\n", "PkMediaChangeRequiredClass", sizeof(PkMediaChangeRequiredClass), alignof(PkMediaChangeRequiredClass)); 45 | printf("%s;%zu;%zu\n", "PkMediaTypeEnum", sizeof(PkMediaTypeEnum), alignof(PkMediaTypeEnum)); 46 | printf("%s;%zu;%zu\n", "PkNetworkEnum", sizeof(PkNetworkEnum), alignof(PkNetworkEnum)); 47 | printf("%s;%zu;%zu\n", "PkOfflineAction", sizeof(PkOfflineAction), alignof(PkOfflineAction)); 48 | printf("%s;%zu;%zu\n", "PkOfflineError", sizeof(PkOfflineError), alignof(PkOfflineError)); 49 | printf("%s;%zu;%zu\n", "PkPackage", sizeof(PkPackage), alignof(PkPackage)); 50 | printf("%s;%zu;%zu\n", "PkPackageClass", sizeof(PkPackageClass), alignof(PkPackageClass)); 51 | printf("%s;%zu;%zu\n", "PkPackageSack", sizeof(PkPackageSack), alignof(PkPackageSack)); 52 | printf("%s;%zu;%zu\n", "PkPackageSackClass", sizeof(PkPackageSackClass), alignof(PkPackageSackClass)); 53 | printf("%s;%zu;%zu\n", "PkPackageSackSortType", sizeof(PkPackageSackSortType), alignof(PkPackageSackSortType)); 54 | printf("%s;%zu;%zu\n", "PkProgress", sizeof(PkProgress), alignof(PkProgress)); 55 | printf("%s;%zu;%zu\n", "PkProgressClass", sizeof(PkProgressClass), alignof(PkProgressClass)); 56 | printf("%s;%zu;%zu\n", "PkProgressType", sizeof(PkProgressType), alignof(PkProgressType)); 57 | printf("%s;%zu;%zu\n", "PkRepoDetail", sizeof(PkRepoDetail), alignof(PkRepoDetail)); 58 | printf("%s;%zu;%zu\n", "PkRepoDetailClass", sizeof(PkRepoDetailClass), alignof(PkRepoDetailClass)); 59 | printf("%s;%zu;%zu\n", "PkRepoSignatureRequired", sizeof(PkRepoSignatureRequired), alignof(PkRepoSignatureRequired)); 60 | printf("%s;%zu;%zu\n", "PkRepoSignatureRequiredClass", sizeof(PkRepoSignatureRequiredClass), alignof(PkRepoSignatureRequiredClass)); 61 | printf("%s;%zu;%zu\n", "PkRequireRestart", sizeof(PkRequireRestart), alignof(PkRequireRestart)); 62 | printf("%s;%zu;%zu\n", "PkRequireRestartClass", sizeof(PkRequireRestartClass), alignof(PkRequireRestartClass)); 63 | printf("%s;%zu;%zu\n", "PkRestartEnum", sizeof(PkRestartEnum), alignof(PkRestartEnum)); 64 | printf("%s;%zu;%zu\n", "PkResults", sizeof(PkResults), alignof(PkResults)); 65 | printf("%s;%zu;%zu\n", "PkResultsClass", sizeof(PkResultsClass), alignof(PkResultsClass)); 66 | printf("%s;%zu;%zu\n", "PkRoleEnum", sizeof(PkRoleEnum), alignof(PkRoleEnum)); 67 | printf("%s;%zu;%zu\n", "PkSigTypeEnum", sizeof(PkSigTypeEnum), alignof(PkSigTypeEnum)); 68 | printf("%s;%zu;%zu\n", "PkSource", sizeof(PkSource), alignof(PkSource)); 69 | printf("%s;%zu;%zu\n", "PkSourceClass", sizeof(PkSourceClass), alignof(PkSourceClass)); 70 | printf("%s;%zu;%zu\n", "PkStatusEnum", sizeof(PkStatusEnum), alignof(PkStatusEnum)); 71 | printf("%s;%zu;%zu\n", "PkTask", sizeof(PkTask), alignof(PkTask)); 72 | printf("%s;%zu;%zu\n", "PkTaskClass", sizeof(PkTaskClass), alignof(PkTaskClass)); 73 | printf("%s;%zu;%zu\n", "PkTransactionFlagEnum", sizeof(PkTransactionFlagEnum), alignof(PkTransactionFlagEnum)); 74 | printf("%s;%zu;%zu\n", "PkTransactionList", sizeof(PkTransactionList), alignof(PkTransactionList)); 75 | printf("%s;%zu;%zu\n", "PkTransactionListClass", sizeof(PkTransactionListClass), alignof(PkTransactionListClass)); 76 | printf("%s;%zu;%zu\n", "PkTransactionPast", sizeof(PkTransactionPast), alignof(PkTransactionPast)); 77 | printf("%s;%zu;%zu\n", "PkTransactionPastClass", sizeof(PkTransactionPastClass), alignof(PkTransactionPastClass)); 78 | printf("%s;%zu;%zu\n", "PkUpdateDetail", sizeof(PkUpdateDetail), alignof(PkUpdateDetail)); 79 | printf("%s;%zu;%zu\n", "PkUpdateDetailClass", sizeof(PkUpdateDetailClass), alignof(PkUpdateDetailClass)); 80 | printf("%s;%zu;%zu\n", "PkUpdateStateEnum", sizeof(PkUpdateStateEnum), alignof(PkUpdateStateEnum)); 81 | printf("%s;%zu;%zu\n", "PkUpgradeKindEnum", sizeof(PkUpgradeKindEnum), alignof(PkUpgradeKindEnum)); 82 | return 0; 83 | } 84 | -------------------------------------------------------------------------------- /packagekit_rs/packagekit-sys/tests/manual.h: -------------------------------------------------------------------------------- 1 | // Feel free to edit this file, it won't be regenerated by gir generator unless removed. 2 | 3 | #include 4 | -------------------------------------------------------------------------------- /packagekit_rs/src/auto/enums.rs: -------------------------------------------------------------------------------- 1 | use glib::translate::*; 2 | use glib::StaticType; 3 | use glib::Type; 4 | use std::fmt; 5 | use package_kit_glib_sys::*; 6 | 7 | #[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone, Copy)] 8 | #[non_exhaustive] 9 | #[doc(alias = "PkProgressType")] 10 | pub enum ProgressType { 11 | #[doc(alias = "PK_PROGRESS_TYPE_PACKAGE_ID")] 12 | PackageId, 13 | #[doc(alias = "PK_PROGRESS_TYPE_TRANSACTION_ID")] 14 | TransactionId, 15 | #[doc(alias = "PK_PROGRESS_TYPE_PERCENTAGE")] 16 | Percentage, 17 | #[doc(alias = "PK_PROGRESS_TYPE_ALLOW_CANCEL")] 18 | AllowCancel, 19 | #[doc(alias = "PK_PROGRESS_TYPE_STATUS")] 20 | Status, 21 | #[doc(alias = "PK_PROGRESS_TYPE_ROLE")] 22 | Role, 23 | #[doc(alias = "PK_PROGRESS_TYPE_CALLER_ACTIVE")] 24 | CallerActive, 25 | #[doc(alias = "PK_PROGRESS_TYPE_ELAPSED_TIME")] 26 | ElapsedTime, 27 | #[doc(alias = "PK_PROGRESS_TYPE_REMAINING_TIME")] 28 | RemainingTime, 29 | #[doc(alias = "PK_PROGRESS_TYPE_SPEED")] 30 | Speed, 31 | #[doc(alias = "PK_PROGRESS_TYPE_DOWNLOAD_SIZE_REMAINING")] 32 | DownloadSizeRemaining, 33 | #[doc(alias = "PK_PROGRESS_TYPE_UID")] 34 | Uid, 35 | #[doc(alias = "PK_PROGRESS_TYPE_PACKAGE")] 36 | Package, 37 | #[doc(alias = "PK_PROGRESS_TYPE_ITEM_PROGRESS")] 38 | ItemProgress, 39 | #[doc(alias = "PK_PROGRESS_TYPE_TRANSACTION_FLAGS")] 40 | TransactionFlags, 41 | #[doc(alias = "PK_PROGRESS_TYPE_INVALID")] 42 | Invalid, 43 | #[doc(hidden)] 44 | __Unknown(i32), 45 | } 46 | 47 | impl fmt::Display for ProgressType { 48 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 49 | write!(f, "ProgressType::{}", match *self { 50 | Self::PackageId => "PackageId", 51 | Self::TransactionId => "TransactionId", 52 | Self::Percentage => "Percentage", 53 | Self::AllowCancel => "AllowCancel", 54 | Self::Status => "Status", 55 | Self::Role => "Role", 56 | Self::CallerActive => "CallerActive", 57 | Self::ElapsedTime => "ElapsedTime", 58 | Self::RemainingTime => "RemainingTime", 59 | Self::Speed => "Speed", 60 | Self::DownloadSizeRemaining => "DownloadSizeRemaining", 61 | Self::Uid => "Uid", 62 | Self::Package => "Package", 63 | Self::ItemProgress => "ItemProgress", 64 | Self::TransactionFlags => "TransactionFlags", 65 | Self::Invalid => "Invalid", 66 | _ => "Unknown", 67 | }) 68 | } 69 | } 70 | 71 | #[doc(hidden)] 72 | impl ToGlib for ProgressType { 73 | type GlibType = PkProgressType; 74 | 75 | fn to_glib(&self) -> PkProgressType { 76 | match *self { 77 | Self::PackageId => PK_PROGRESS_TYPE_PACKAGE_ID, 78 | Self::TransactionId => PK_PROGRESS_TYPE_TRANSACTION_ID, 79 | Self::Percentage => PK_PROGRESS_TYPE_PERCENTAGE, 80 | Self::AllowCancel => PK_PROGRESS_TYPE_ALLOW_CANCEL, 81 | Self::Status => PK_PROGRESS_TYPE_STATUS, 82 | Self::Role => PK_PROGRESS_TYPE_ROLE, 83 | Self::CallerActive => PK_PROGRESS_TYPE_CALLER_ACTIVE, 84 | Self::ElapsedTime => PK_PROGRESS_TYPE_ELAPSED_TIME, 85 | Self::RemainingTime => PK_PROGRESS_TYPE_REMAINING_TIME, 86 | Self::Speed => PK_PROGRESS_TYPE_SPEED, 87 | Self::DownloadSizeRemaining => PK_PROGRESS_TYPE_DOWNLOAD_SIZE_REMAINING, 88 | Self::Uid => PK_PROGRESS_TYPE_UID, 89 | Self::Package => PK_PROGRESS_TYPE_PACKAGE, 90 | Self::ItemProgress => PK_PROGRESS_TYPE_ITEM_PROGRESS, 91 | Self::TransactionFlags => PK_PROGRESS_TYPE_TRANSACTION_FLAGS, 92 | Self::Invalid => PK_PROGRESS_TYPE_INVALID, 93 | Self::__Unknown(value) => value, 94 | } 95 | } 96 | } 97 | 98 | #[doc(hidden)] 99 | impl FromGlib for ProgressType { 100 | fn from_glib(value: PkProgressType) -> Self { 101 | //skip_assert_initialized!(); 102 | match value { 103 | 0 => Self::PackageId, 104 | 1 => Self::TransactionId, 105 | 2 => Self::Percentage, 106 | 3 => Self::AllowCancel, 107 | 4 => Self::Status, 108 | 5 => Self::Role, 109 | 6 => Self::CallerActive, 110 | 7 => Self::ElapsedTime, 111 | 8 => Self::RemainingTime, 112 | 9 => Self::Speed, 113 | 10 => Self::DownloadSizeRemaining, 114 | 11 => Self::Uid, 115 | 12 => Self::Package, 116 | 13 => Self::ItemProgress, 117 | 14 => Self::TransactionFlags, 118 | 15 => Self::Invalid, 119 | value => Self::__Unknown(value), 120 | } 121 | } 122 | } 123 | 124 | impl StaticType for ProgressType { 125 | fn static_type() -> Type { 126 | unsafe { from_glib(pk_progress_type_get_type()) } 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /packagekit_rs/src/details.rs: -------------------------------------------------------------------------------- 1 | use glib; 2 | use glib::object::IsA; 3 | use glib::translate::*; 4 | 5 | use package_kit_glib_sys::*; 6 | 7 | glib::wrapper! { 8 | pub struct DetailsPk(Interface); 9 | 10 | match fn { 11 | type_ => || pk_details_get_type(), 12 | } 13 | } 14 | 15 | impl DetailsPk { 16 | #[doc(alias = "pk_details_new")] 17 | pub fn new() -> DetailsPk { 18 | unsafe { from_glib_full(pk_details_new()) } 19 | } 20 | } 21 | 22 | impl Default for DetailsPk { 23 | fn default() -> Self { 24 | Self::new() 25 | } 26 | } 27 | 28 | pub const NONE_DETAILS: Option<&DetailsPk> = None; 29 | 30 | pub trait DetailsPkExt: 'static { 31 | #[doc(alias = "pk_details_get_description")] 32 | fn description(&self) -> glib::GString; 33 | 34 | #[doc(alias = "pk_details_get_license")] 35 | fn license(&self) -> glib::GString; 36 | 37 | #[doc(alias = "pk_details_get_package_id")] 38 | fn package_id(&self) -> glib::GString; 39 | 40 | #[doc(alias = "pk_details_get_size")] 41 | fn size(&self) -> u64; 42 | 43 | #[doc(alias = "pk_details_get_summary")] 44 | fn summary(&self) -> glib::GString; 45 | 46 | #[doc(alias = "pk_details_get_url")] 47 | fn url(&self) -> glib::GString; 48 | } 49 | 50 | impl> DetailsPkExt for O { 51 | fn description(&self) -> glib::GString { 52 | unsafe { from_glib_none(pk_details_get_description(self.as_ref().to_glib_none().0)) } 53 | } 54 | 55 | fn license(&self) -> glib::GString { 56 | unsafe { from_glib_none(pk_details_get_license(self.as_ref().to_glib_none().0)) } 57 | } 58 | 59 | fn package_id(&self) -> glib::GString { 60 | unsafe { from_glib_none(pk_details_get_package_id(self.as_ref().to_glib_none().0)) } 61 | } 62 | 63 | fn size(&self) -> u64 { 64 | unsafe { pk_details_get_size(self.as_ref().to_glib_none().0) } 65 | } 66 | 67 | fn summary(&self) -> glib::GString { 68 | unsafe { from_glib_none(pk_details_get_summary(self.as_ref().to_glib_none().0)) } 69 | } 70 | 71 | fn url(&self) -> glib::GString { 72 | unsafe { from_glib_none(pk_details_get_url(self.as_ref().to_glib_none().0)) } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /packagekit_rs/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod prelude; 2 | 3 | pub mod results; 4 | pub use results::ResultsPk; 5 | pub use results::ResultsPkExt; 6 | 7 | pub mod package; 8 | pub use self::package::PackagePk; 9 | pub use self::package::PackagePkExt; 10 | 11 | pub mod details; 12 | pub use self::details::DetailsPk; 13 | pub use self::details::DetailsPkExt; 14 | 15 | pub mod update_detail; 16 | pub use self::update_detail::UpdateDetailPk; 17 | pub use self::update_detail::UpdateDetailPkExt; 18 | 19 | pub mod progress; 20 | pub use self::progress::ProgressPk; 21 | pub use self::progress::ProgressPkExt; 22 | 23 | pub mod client; 24 | pub use self::client::ClientPk; 25 | pub use self::client::ClientPkExt; 26 | 27 | pub mod task; 28 | pub use self::task::PkTaskExt; 29 | pub use self::task::TaskPk; 30 | 31 | pub use package_kit_glib_sys::{ 32 | pk_offline_get_prepared_ids, pk_offline_trigger, PK_OFFLINE_ACTION_REBOOT, 33 | PK_PROGRESS_TYPE_PERCENTAGE, PK_STATUS_ENUM_CLEANUP, PK_STATUS_ENUM_DOWNLOAD, 34 | PK_STATUS_ENUM_INSTALL, PK_STATUS_ENUM_REFRESH_CACHE, PK_STATUS_ENUM_REMOVE, 35 | PK_STATUS_ENUM_UPDATE, 36 | }; 37 | 38 | extern crate gio_sys; 39 | extern crate glib; 40 | -------------------------------------------------------------------------------- /packagekit_rs/src/package.rs: -------------------------------------------------------------------------------- 1 | use glib; 2 | use glib::object::IsA; 3 | use glib::translate::*; 4 | use libc::c_char; 5 | use std::fmt; 6 | 7 | use package_kit_glib_sys::*; 8 | 9 | glib::wrapper! { 10 | pub struct PackagePk(Interface); 11 | 12 | match fn { 13 | type_ => || pk_package_get_type(), 14 | } 15 | } 16 | 17 | impl PackagePk { 18 | #[doc(alias = "pk_package_new")] 19 | pub fn new() -> PackagePk { 20 | unsafe { from_glib_full(pk_package_new()) } 21 | } 22 | 23 | pub fn ids_to_string(package_ids: *mut *mut c_char) -> glib::GString { 24 | unsafe { from_glib_full(pk_package_ids_to_string(package_ids)) } 25 | } 26 | } 27 | 28 | impl Default for PackagePk { 29 | fn default() -> Self { 30 | Self::new() 31 | } 32 | } 33 | 34 | impl fmt::Display for PackagePk { 35 | #[inline] 36 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 37 | f.write_str(&PackagePkExt::name(self)) 38 | } 39 | } 40 | 41 | pub const NONE_PACKAGE: Option<&PackagePk> = None; 42 | 43 | pub trait PackagePkExt: 'static { 44 | fn name(&self) -> String; 45 | fn id(&self) -> String; 46 | fn info(&self) -> String; 47 | fn summary(&self) -> String; 48 | fn version(&self) -> String; 49 | fn data(&self) -> String; 50 | } 51 | 52 | impl> PackagePkExt for O { 53 | fn name(&self) -> String { 54 | unsafe { 55 | let s: glib::GString = 56 | from_glib_none(pk_package_get_name(self.as_ref().to_glib_none().0)); 57 | s.to_string() 58 | } 59 | } 60 | 61 | fn id(&self) -> String { 62 | unsafe { 63 | let s: glib::GString = 64 | from_glib_none(pk_package_get_id(self.as_ref().to_glib_none().0)); 65 | s.to_string() 66 | } 67 | } 68 | 69 | fn info(&self) -> String { 70 | unsafe { 71 | let info = pk_info_enum_to_string(pk_package_get_info(self.as_ref().to_glib_none().0)); 72 | let s: glib::GString = from_glib_none(info); 73 | s.to_string() 74 | } 75 | } 76 | 77 | fn summary(&self) -> String { 78 | unsafe { 79 | let s: glib::GString = 80 | from_glib_none(pk_package_get_summary(self.as_ref().to_glib_none().0)); 81 | s.to_string() 82 | } 83 | } 84 | 85 | fn version(&self) -> String { 86 | unsafe { 87 | let s: glib::GString = 88 | from_glib_none(pk_package_get_version(self.as_ref().to_glib_none().0)); 89 | s.to_string() 90 | } 91 | } 92 | 93 | fn data(&self) -> String { 94 | unsafe { 95 | let s: glib::GString = 96 | from_glib_none(pk_package_get_data(self.as_ref().to_glib_none().0)); 97 | s.to_string() 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /packagekit_rs/src/prelude.rs: -------------------------------------------------------------------------------- 1 | pub use crate::ClientPkExt; 2 | pub use crate::PackagePkExt; 3 | pub use crate::PkTaskExt; 4 | pub use crate::ProgressPkExt; 5 | pub use crate::ResultsPkExt; 6 | -------------------------------------------------------------------------------- /packagekit_rs/src/progress.rs: -------------------------------------------------------------------------------- 1 | use glib; 2 | use glib::object::IsA; 3 | use glib::translate::*; 4 | 5 | use crate::package::PackagePk; 6 | use package_kit_glib_sys::*; 7 | 8 | glib::wrapper! { 9 | pub struct ProgressPk(Interface); 10 | 11 | match fn { 12 | type_ => || pk_progress_get_type(), 13 | } 14 | } 15 | 16 | impl ProgressPk { 17 | #[doc(alias = "pk_progress_new")] 18 | pub fn new() -> ProgressPk { 19 | unsafe { from_glib_full(pk_progress_new()) } 20 | } 21 | } 22 | 23 | impl Default for ProgressPk { 24 | fn default() -> Self { 25 | Self::new() 26 | } 27 | } 28 | 29 | pub const NONE_PROGRESS: Option<&ProgressPk> = None; 30 | 31 | pub trait ProgressPkExt: 'static { 32 | fn package(&self) -> PackagePk; 33 | 34 | fn package_id(&self) -> glib::GString; 35 | 36 | fn percentage(&self) -> i32; 37 | 38 | fn status(&self) -> i32; 39 | 40 | fn transaction_id(&self) -> glib::GString; 41 | 42 | fn get_role(&self) -> glib::GString; 43 | 44 | fn get_item_package(&self) -> String; 45 | } 46 | 47 | impl> ProgressPkExt for O { 48 | fn package(&self) -> PackagePk { 49 | unsafe { from_glib_none(pk_progress_get_package(self.as_ref().to_glib_none().0)) } 50 | } 51 | 52 | fn package_id(&self) -> glib::GString { 53 | unsafe { from_glib_none(pk_progress_get_package_id(self.as_ref().to_glib_none().0)) } 54 | } 55 | 56 | fn percentage(&self) -> i32 { 57 | unsafe { pk_progress_get_percentage(self.as_ref().to_glib_none().0) } 58 | } 59 | 60 | fn status(&self) -> i32 { 61 | unsafe { pk_progress_get_status(self.as_ref().to_glib_none().0) } 62 | } 63 | 64 | fn transaction_id(&self) -> glib::GString { 65 | unsafe { 66 | from_glib_none(pk_progress_get_transaction_id( 67 | self.as_ref().to_glib_none().0, 68 | )) 69 | } 70 | } 71 | 72 | fn get_role(&self) -> glib::GString { 73 | unsafe { 74 | let role = pk_progress_get_role(self.as_ref().to_glib_none().0); 75 | from_glib_none(pk_role_enum_to_string(role)) 76 | } 77 | } 78 | 79 | fn get_item_package(&self) -> String { 80 | unsafe { 81 | let item_progress = pk_progress_get_item_progress(self.as_ref().to_glib_none().0); 82 | let id = pk_item_progress_get_package_id(item_progress); 83 | let s: glib::GString = from_glib_none(id); 84 | s.to_string() 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /packagekit_rs/src/results.rs: -------------------------------------------------------------------------------- 1 | use glib; 2 | use glib::object::IsA; 3 | use glib::translate::*; 4 | use libc::c_char; 5 | 6 | use crate::details::DetailsPk; 7 | use crate::package::PackagePk; 8 | use crate::update_detail::UpdateDetailPk; 9 | use package_kit_glib_sys::*; 10 | 11 | glib::wrapper! { 12 | pub struct ResultsPk(Interface); 13 | 14 | match fn { 15 | type_ => || pk_results_get_type(), 16 | } 17 | } 18 | 19 | impl ResultsPk { 20 | #[doc(alias = "pk_results_new")] 21 | pub fn new() -> ResultsPk { 22 | unsafe { from_glib_full(pk_results_new()) } 23 | } 24 | } 25 | 26 | impl Default for ResultsPk { 27 | fn default() -> Self { 28 | Self::new() 29 | } 30 | } 31 | 32 | pub const NONE_RESULTS: Option<&ResultsPk> = None; 33 | 34 | pub trait ResultsPkExt: 'static { 35 | fn package_array(&self) -> Vec; 36 | 37 | fn package_ids(&self) -> Option<*mut *mut c_char>; 38 | 39 | fn detail_array(&self) -> Vec; 40 | 41 | fn require_restart_len(&self) -> i32; 42 | 43 | fn require_restart_worst(&self) -> i32; 44 | } 45 | 46 | impl> ResultsPkExt for O { 47 | fn package_array(&self) -> Vec { 48 | unsafe { 49 | { 50 | let sack = pk_results_get_package_sack(self.as_ref().to_glib_none().0); 51 | pk_package_sack_sort(sack, PK_PACKAGE_SACK_SORT_TYPE_NAME); 52 | let array = pk_package_sack_get_array(sack); 53 | Vec::from_raw_parts( 54 | (*array).pdata as *mut PackagePk, 55 | (*array).len as usize, 56 | (*array).len as usize, 57 | ) 58 | } 59 | } 60 | } 61 | 62 | fn package_ids(&self) -> Option<*mut *mut c_char> { 63 | unsafe { 64 | let sack = pk_results_get_package_sack(self.as_ref().to_glib_none().0); 65 | if pk_package_sack_get_size(sack) == 0 { 66 | return None; 67 | } 68 | Some(pk_package_sack_get_ids(sack)) 69 | } 70 | } 71 | 72 | fn detail_array(&self) -> Vec { 73 | unsafe { 74 | { 75 | let array = pk_results_get_update_detail_array(self.as_ref().to_glib_none().0); 76 | Vec::from_raw_parts( 77 | (*array).pdata as *mut UpdateDetailPk, 78 | (*array).len as usize, 79 | (*array).len as usize, 80 | ) 81 | } 82 | } 83 | } 84 | 85 | fn require_restart_len(&self) -> i32 { 86 | unsafe { 87 | { 88 | let array = pk_results_get_require_restart_array(self.as_ref().to_glib_none().0); 89 | Vec::from_raw_parts( 90 | (*array).pdata as *mut DetailsPk, 91 | (*array).len as usize, 92 | (*array).len as usize, 93 | ) 94 | .len() as i32 95 | } 96 | } 97 | } 98 | 99 | fn require_restart_worst(&self) -> i32 { 100 | unsafe { pk_results_get_require_restart_worst(self.as_ref().to_glib_none().0) } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /packagekit_rs/src/task.rs: -------------------------------------------------------------------------------- 1 | use glib; 2 | use glib::object::IsA; 3 | use glib::translate::*; 4 | 5 | use package_kit_glib_sys::*; 6 | 7 | glib::wrapper! { 8 | pub struct TaskPk(Interface); 9 | 10 | match fn { 11 | type_ => || pk_task_get_type(), 12 | } 13 | } 14 | 15 | impl TaskPk { 16 | #[doc(alias = "pk_task_new")] 17 | pub fn new() -> TaskPk { 18 | unsafe { from_glib_full(pk_task_new()) } 19 | } 20 | } 21 | 22 | impl Default for TaskPk { 23 | fn default() -> Self { 24 | Self::new() 25 | } 26 | } 27 | 28 | pub const NONE_TASK: Option<&TaskPk> = None; 29 | 30 | pub trait PkTaskExt: 'static { 31 | #[doc(alias = "pk_task_install_packages_sync")] 32 | #[doc(alias = "pk_task_set_only_download")] 33 | fn set_only_download(&self, only_download: bool); 34 | 35 | fn set_simulate(&self, simulate: bool); 36 | } 37 | 38 | impl> PkTaskExt for O { 39 | fn set_only_download(&self, only_download: bool) { 40 | unsafe { 41 | pk_task_set_only_download(self.as_ref().to_glib_none().0, only_download as i32); 42 | } 43 | } 44 | 45 | fn set_simulate(&self, simulate: bool) { 46 | unsafe { 47 | pk_task_set_simulate(self.as_ref().to_glib_none().0, simulate as i32); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /packagekit_rs/src/update_detail.rs: -------------------------------------------------------------------------------- 1 | use glib; 2 | use glib::object::IsA; 3 | use glib::translate::*; 4 | 5 | use package_kit_glib_sys::*; 6 | 7 | glib::wrapper! { 8 | pub struct UpdateDetailPk(Interface); 9 | 10 | match fn { 11 | type_ => || pk_update_detail_get_type(), 12 | } 13 | } 14 | 15 | impl UpdateDetailPk { 16 | #[doc(alias = "pk_update_detail_new")] 17 | pub fn new() -> UpdateDetailPk { 18 | unsafe { from_glib_full(pk_update_detail_new()) } 19 | } 20 | } 21 | 22 | impl Default for UpdateDetailPk { 23 | fn default() -> Self { 24 | Self::new() 25 | } 26 | } 27 | 28 | pub const NONE_UPDATEDETAIL: Option<&UpdateDetailPk> = None; 29 | 30 | pub trait UpdateDetailPkExt: 'static { 31 | #[doc(alias = "get_obsoletes")] 32 | fn obsoletes(&self) -> Vec; 33 | 34 | #[doc(alias = "get_package_id")] 35 | fn package_id(&self) -> glib::GString; 36 | 37 | #[doc(alias = "get_update_text")] 38 | fn update_text(&self) -> glib::GString; 39 | 40 | #[doc(alias = "get_updated")] 41 | fn updated(&self) -> glib::GString; 42 | 43 | #[doc(alias = "get_restart")] 44 | fn restart(&self) -> i32; 45 | } 46 | 47 | impl> UpdateDetailPkExt for O { 48 | fn obsoletes(&self) -> Vec { 49 | unsafe { 50 | FromGlibPtrContainer::from_glib_none(pk_update_detail_get_obsoletes( 51 | self.as_ref().to_glib_none().0, 52 | )) 53 | } 54 | } 55 | 56 | fn package_id(&self) -> glib::GString { 57 | unsafe { 58 | from_glib_none(pk_update_detail_get_package_id( 59 | self.as_ref().to_glib_none().0, 60 | )) 61 | } 62 | } 63 | 64 | fn update_text(&self) -> glib::GString { 65 | unsafe { 66 | from_glib_none(pk_update_detail_get_update_text( 67 | self.as_ref().to_glib_none().0, 68 | )) 69 | } 70 | } 71 | 72 | fn updated(&self) -> glib::GString { 73 | unsafe { from_glib_none(pk_update_detail_get_updated(self.as_ref().to_glib_none().0)) } 74 | } 75 | 76 | fn restart(&self) -> i32 { 77 | unsafe { pk_update_detail_get_restart(self.as_ref().to_glib_none().0) as i32 } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /packagekit_rs/tests/packagekit.rs: -------------------------------------------------------------------------------- 1 | //use pk_rs::client; 2 | use packagekit_rs::*; 3 | 4 | #[test] 5 | fn client_new() { 6 | let _client = ClientPk::new(); 7 | } 8 | 9 | #[test] 10 | fn task_new() { 11 | let _task = Task::new(); 12 | } 13 | 14 | #[test] 15 | fn refresh_cache() { 16 | let client = ClientPk::new(); 17 | client.refresh_cache(true).expect("fail refresh cache"); 18 | } 19 | 20 | #[test] 21 | fn get_updates() { 22 | let client = ClientPk::new(); 23 | let result = client.get_updates(None).expect("fail updates"); 24 | let vecc = result.package_array(); 25 | assert!(vecc.len() > 0, "get 0 updates"); 26 | } 27 | 28 | #[test] 29 | fn get_packages() { 30 | let client = ClientPk::new(); 31 | let result = client.get_packages(None).expect("fail updates"); 32 | let vecc = result.package_array(); 33 | assert!(vecc.len() > 0, "get 0 packages"); 34 | } 35 | -------------------------------------------------------------------------------- /po/LINGUAS: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwxg/zypp-gui/101b086d82e7de5641a5cb3c35f2474e214cb317/po/LINGUAS -------------------------------------------------------------------------------- /po/POTFILES.in: -------------------------------------------------------------------------------- 1 | data/org.openSUSE.sofware.desktop.in.in 2 | data/org.openSUSE.sofware.gschema.xml.in 3 | data/org.openSUSE.sofware.metainfo.xml.in.in 4 | -------------------------------------------------------------------------------- /po/meson.build: -------------------------------------------------------------------------------- 1 | i18n.gettext(gettext_package, preset: 'glib') 2 | -------------------------------------------------------------------------------- /subprojects/blueprint-compiler.wrap: -------------------------------------------------------------------------------- 1 | [wrap-git] 2 | directory = blueprint-compiler 3 | url = https://gitlab.gnome.org/jwestman/blueprint-compiler.git 4 | revision = v0.6.0 5 | depth = 1 6 | 7 | [provide] 8 | program_names = blueprint-compiler -------------------------------------------------------------------------------- /tools/get_mirror_data/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /tools/get_mirror_data/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "ansi_term" 7 | version = "0.12.1" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" 10 | dependencies = [ 11 | "winapi", 12 | ] 13 | 14 | [[package]] 15 | name = "anyhow" 16 | version = "1.0.71" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" 19 | 20 | [[package]] 21 | name = "atty" 22 | version = "0.2.14" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" 25 | dependencies = [ 26 | "hermit-abi", 27 | "libc", 28 | "winapi", 29 | ] 30 | 31 | [[package]] 32 | name = "autocfg" 33 | version = "1.1.0" 34 | source = "registry+https://github.com/rust-lang/crates.io-index" 35 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 36 | 37 | [[package]] 38 | name = "bitflags" 39 | version = "1.3.2" 40 | source = "registry+https://github.com/rust-lang/crates.io-index" 41 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 42 | 43 | [[package]] 44 | name = "byteorder" 45 | version = "1.4.3" 46 | source = "registry+https://github.com/rust-lang/crates.io-index" 47 | checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" 48 | 49 | [[package]] 50 | name = "clap" 51 | version = "2.34.0" 52 | source = "registry+https://github.com/rust-lang/crates.io-index" 53 | checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" 54 | dependencies = [ 55 | "ansi_term", 56 | "atty", 57 | "bitflags", 58 | "strsim 0.8.0", 59 | "textwrap 0.11.0", 60 | "unicode-width", 61 | "vec_map", 62 | ] 63 | 64 | [[package]] 65 | name = "clap" 66 | version = "3.2.25" 67 | source = "registry+https://github.com/rust-lang/crates.io-index" 68 | checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" 69 | dependencies = [ 70 | "atty", 71 | "bitflags", 72 | "clap_lex", 73 | "indexmap", 74 | "strsim 0.10.0", 75 | "termcolor", 76 | "textwrap 0.16.0", 77 | ] 78 | 79 | [[package]] 80 | name = "clap_lex" 81 | version = "0.2.4" 82 | source = "registry+https://github.com/rust-lang/crates.io-index" 83 | checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" 84 | dependencies = [ 85 | "os_str_bytes", 86 | ] 87 | 88 | [[package]] 89 | name = "get_mirror_data" 90 | version = "0.1.0" 91 | dependencies = [ 92 | "clap 2.34.0", 93 | "mif", 94 | "minidom", 95 | "serde", 96 | "serde_json", 97 | ] 98 | 99 | [[package]] 100 | name = "hashbrown" 101 | version = "0.12.3" 102 | source = "registry+https://github.com/rust-lang/crates.io-index" 103 | checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" 104 | 105 | [[package]] 106 | name = "hermit-abi" 107 | version = "0.1.19" 108 | source = "registry+https://github.com/rust-lang/crates.io-index" 109 | checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" 110 | dependencies = [ 111 | "libc", 112 | ] 113 | 114 | [[package]] 115 | name = "indexmap" 116 | version = "1.9.3" 117 | source = "registry+https://github.com/rust-lang/crates.io-index" 118 | checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" 119 | dependencies = [ 120 | "autocfg", 121 | "hashbrown", 122 | "serde", 123 | ] 124 | 125 | [[package]] 126 | name = "itoa" 127 | version = "1.0.6" 128 | source = "registry+https://github.com/rust-lang/crates.io-index" 129 | checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" 130 | 131 | [[package]] 132 | name = "libc" 133 | version = "0.2.144" 134 | source = "registry+https://github.com/rust-lang/crates.io-index" 135 | checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1" 136 | 137 | [[package]] 138 | name = "memchr" 139 | version = "2.5.0" 140 | source = "registry+https://github.com/rust-lang/crates.io-index" 141 | checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" 142 | 143 | [[package]] 144 | name = "mif" 145 | version = "0.3.0" 146 | source = "registry+https://github.com/rust-lang/crates.io-index" 147 | checksum = "eb59e79bfe3b36442a85878d1df2fd48123041dd3b83e5586b60b0b7e0013a5e" 148 | dependencies = [ 149 | "anyhow", 150 | "byteorder", 151 | "clap 3.2.25", 152 | "indexmap", 153 | "num-traits", 154 | "serde", 155 | "thiserror", 156 | "toml", 157 | ] 158 | 159 | [[package]] 160 | name = "minidom" 161 | version = "0.13.0" 162 | source = "registry+https://github.com/rust-lang/crates.io-index" 163 | checksum = "332592c2149fc7dd40a64fc9ef6f0d65607284b474cef9817d1fc8c7e7b3608e" 164 | dependencies = [ 165 | "quick-xml", 166 | ] 167 | 168 | [[package]] 169 | name = "num-traits" 170 | version = "0.2.15" 171 | source = "registry+https://github.com/rust-lang/crates.io-index" 172 | checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" 173 | dependencies = [ 174 | "autocfg", 175 | ] 176 | 177 | [[package]] 178 | name = "os_str_bytes" 179 | version = "6.5.0" 180 | source = "registry+https://github.com/rust-lang/crates.io-index" 181 | checksum = "ceedf44fb00f2d1984b0bc98102627ce622e083e49a5bacdb3e514fa4238e267" 182 | 183 | [[package]] 184 | name = "proc-macro2" 185 | version = "1.0.58" 186 | source = "registry+https://github.com/rust-lang/crates.io-index" 187 | checksum = "fa1fb82fc0c281dd9671101b66b771ebbe1eaf967b96ac8740dcba4b70005ca8" 188 | dependencies = [ 189 | "unicode-ident", 190 | ] 191 | 192 | [[package]] 193 | name = "quick-xml" 194 | version = "0.20.0" 195 | source = "registry+https://github.com/rust-lang/crates.io-index" 196 | checksum = "26aab6b48e2590e4a64d1ed808749ba06257882b461d01ca71baeb747074a6dd" 197 | dependencies = [ 198 | "memchr", 199 | ] 200 | 201 | [[package]] 202 | name = "quote" 203 | version = "1.0.27" 204 | source = "registry+https://github.com/rust-lang/crates.io-index" 205 | checksum = "8f4f29d145265ec1c483c7c654450edde0bfe043d3938d6972630663356d9500" 206 | dependencies = [ 207 | "proc-macro2", 208 | ] 209 | 210 | [[package]] 211 | name = "ryu" 212 | version = "1.0.13" 213 | source = "registry+https://github.com/rust-lang/crates.io-index" 214 | checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" 215 | 216 | [[package]] 217 | name = "serde" 218 | version = "1.0.163" 219 | source = "registry+https://github.com/rust-lang/crates.io-index" 220 | checksum = "2113ab51b87a539ae008b5c6c02dc020ffa39afd2d83cffcb3f4eb2722cebec2" 221 | dependencies = [ 222 | "serde_derive", 223 | ] 224 | 225 | [[package]] 226 | name = "serde_derive" 227 | version = "1.0.163" 228 | source = "registry+https://github.com/rust-lang/crates.io-index" 229 | checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e" 230 | dependencies = [ 231 | "proc-macro2", 232 | "quote", 233 | "syn", 234 | ] 235 | 236 | [[package]] 237 | name = "serde_json" 238 | version = "1.0.96" 239 | source = "registry+https://github.com/rust-lang/crates.io-index" 240 | checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" 241 | dependencies = [ 242 | "itoa", 243 | "ryu", 244 | "serde", 245 | ] 246 | 247 | [[package]] 248 | name = "strsim" 249 | version = "0.8.0" 250 | source = "registry+https://github.com/rust-lang/crates.io-index" 251 | checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" 252 | 253 | [[package]] 254 | name = "strsim" 255 | version = "0.10.0" 256 | source = "registry+https://github.com/rust-lang/crates.io-index" 257 | checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" 258 | 259 | [[package]] 260 | name = "syn" 261 | version = "2.0.16" 262 | source = "registry+https://github.com/rust-lang/crates.io-index" 263 | checksum = "a6f671d4b5ffdb8eadec19c0ae67fe2639df8684bd7bc4b83d986b8db549cf01" 264 | dependencies = [ 265 | "proc-macro2", 266 | "quote", 267 | "unicode-ident", 268 | ] 269 | 270 | [[package]] 271 | name = "termcolor" 272 | version = "1.2.0" 273 | source = "registry+https://github.com/rust-lang/crates.io-index" 274 | checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" 275 | dependencies = [ 276 | "winapi-util", 277 | ] 278 | 279 | [[package]] 280 | name = "textwrap" 281 | version = "0.11.0" 282 | source = "registry+https://github.com/rust-lang/crates.io-index" 283 | checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" 284 | dependencies = [ 285 | "unicode-width", 286 | ] 287 | 288 | [[package]] 289 | name = "textwrap" 290 | version = "0.16.0" 291 | source = "registry+https://github.com/rust-lang/crates.io-index" 292 | checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" 293 | 294 | [[package]] 295 | name = "thiserror" 296 | version = "1.0.40" 297 | source = "registry+https://github.com/rust-lang/crates.io-index" 298 | checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" 299 | dependencies = [ 300 | "thiserror-impl", 301 | ] 302 | 303 | [[package]] 304 | name = "thiserror-impl" 305 | version = "1.0.40" 306 | source = "registry+https://github.com/rust-lang/crates.io-index" 307 | checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" 308 | dependencies = [ 309 | "proc-macro2", 310 | "quote", 311 | "syn", 312 | ] 313 | 314 | [[package]] 315 | name = "toml" 316 | version = "0.5.11" 317 | source = "registry+https://github.com/rust-lang/crates.io-index" 318 | checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" 319 | dependencies = [ 320 | "indexmap", 321 | "serde", 322 | ] 323 | 324 | [[package]] 325 | name = "unicode-ident" 326 | version = "1.0.8" 327 | source = "registry+https://github.com/rust-lang/crates.io-index" 328 | checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" 329 | 330 | [[package]] 331 | name = "unicode-width" 332 | version = "0.1.10" 333 | source = "registry+https://github.com/rust-lang/crates.io-index" 334 | checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" 335 | 336 | [[package]] 337 | name = "vec_map" 338 | version = "0.8.2" 339 | source = "registry+https://github.com/rust-lang/crates.io-index" 340 | checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" 341 | 342 | [[package]] 343 | name = "winapi" 344 | version = "0.3.9" 345 | source = "registry+https://github.com/rust-lang/crates.io-index" 346 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 347 | dependencies = [ 348 | "winapi-i686-pc-windows-gnu", 349 | "winapi-x86_64-pc-windows-gnu", 350 | ] 351 | 352 | [[package]] 353 | name = "winapi-i686-pc-windows-gnu" 354 | version = "0.4.0" 355 | source = "registry+https://github.com/rust-lang/crates.io-index" 356 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 357 | 358 | [[package]] 359 | name = "winapi-util" 360 | version = "0.1.5" 361 | source = "registry+https://github.com/rust-lang/crates.io-index" 362 | checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" 363 | dependencies = [ 364 | "winapi", 365 | ] 366 | 367 | [[package]] 368 | name = "winapi-x86_64-pc-windows-gnu" 369 | version = "0.4.0" 370 | source = "registry+https://github.com/rust-lang/crates.io-index" 371 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 372 | -------------------------------------------------------------------------------- /tools/get_mirror_data/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "get_mirror_data" 3 | version = "0.1.0" 4 | edition = "2018" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | clap = "2.34.0" 10 | mif = "0.3.0" 11 | minidom = "0.13.0" 12 | serde = "1.0.126" 13 | serde_json = "1.0.64" 14 | -------------------------------------------------------------------------------- /tools/get_mirror_data/get.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | wget https://mirrors.opensuse.org/ -O /dev/shm/mirror.html 4 | cat /dev/shm/mirror.html | ./target/debug/get_mirror_data $1 5 | -------------------------------------------------------------------------------- /tools/get_mirror_data/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | use std::io::prelude::*; 3 | use minidom::Element; 4 | use serde::{Deserialize, Serialize}; 5 | use clap::{App, Arg}; 6 | 7 | mod name_convert; 8 | use crate::name_convert::NAME_CONVERT; 9 | use crate::name_convert::COUNTRY_CONVERT; 10 | 11 | const NS: &'static str = "metadata/common"; 12 | const NSHEAD: &'static str = r#""#; 13 | const NSEND: &'static str = r#""#; 14 | 15 | #[derive(Serialize, Deserialize, Debug, Clone)] 16 | struct Data { 17 | asia: Vec, 18 | africa: Vec, 19 | europe: Vec, 20 | north_america: Vec, 21 | oceania: Vec, 22 | south_america: Vec, 23 | } 24 | 25 | #[derive(Serialize, Deserialize, Debug, Clone)] 26 | pub struct Site { 27 | pub country: String, 28 | pub name: String, 29 | pub http: String, 30 | pub rsync: String, 31 | pub ftp: String, 32 | } 33 | 34 | fn main() { 35 | let matches = App::new("Get openSUSE mirror site data") 36 | .version("1.0") 37 | .arg( 38 | Arg::with_name("number") 39 | .short("n") 40 | .long("number") 41 | .help("get the number of site"), 42 | ) 43 | .get_matches(); 44 | let mut print_number = false; 45 | if matches.is_present("number") { 46 | print_number = true; 47 | } 48 | 49 | let mut name_map: HashMap = HashMap::new(); 50 | for i in NAME_CONVERT { 51 | name_map.insert(i.0.to_string(), i.1.to_string()); 52 | } 53 | let mut country_map: HashMap = HashMap::new(); 54 | for i in COUNTRY_CONVERT { 55 | country_map.insert(i.0.to_string(), i.1.to_string()); 56 | } 57 | 58 | let mut buffer = String::new(); 59 | let _ = std::io::stdin().read_to_string(&mut buffer); 60 | 61 | let data = get_data(buffer); 62 | 63 | let root: Element = data.parse().unwrap(); 64 | 65 | let body = root.get_child("table",NS).unwrap() 66 | .get_child("tbody", NS).unwrap(); 67 | 68 | let mut _map: HashMap> = HashMap::new(); 69 | let mut _region: Vec = vec![]; 70 | let mut _region_name = String::new(); 71 | 72 | for c in body.children() { 73 | let (is_region, skip) = is_region(c); 74 | if is_region { 75 | if _region.len() > 0 { 76 | _map.insert(_region_name, _region); 77 | } 78 | _region_name = get_region(c); 79 | _region = vec![]; 80 | continue; 81 | } 82 | if skip { 83 | continue; 84 | } 85 | 86 | _region.push(get_site(c, name_map.clone(), country_map.clone())); 87 | } 88 | _map.insert(_region_name, _region); 89 | if print_number { 90 | for i in _map.clone() { 91 | println!("{} {}", i.0, i.1.len()); 92 | } 93 | } 94 | 95 | let result = Data { 96 | asia: _map.get("Asia:").unwrap().clone(), 97 | africa: _map.get("Africa:").unwrap().clone(), 98 | europe: _map.get("Europe:").unwrap().clone(), 99 | north_america: _map.get("North America:").unwrap().clone(), 100 | oceania: _map.get("Oceania:").unwrap().clone(), 101 | south_america: _map.get("South America:").unwrap().clone(), 102 | }; 103 | 104 | if !print_number { 105 | println!("{}", serde_json::to_string_pretty(&result).unwrap()); 106 | } 107 | } 108 | 109 | fn get_site(e: &Element, name_map: HashMap, country_map: HashMap) -> Site { 110 | let mut country = String::new(); 111 | let mut name = String::new(); 112 | let mut http = (String::new(), String::new()); 113 | let mut rsync = (String::new(), String::new()); 114 | let mut ftp = (String::new(), String::new()); 115 | 116 | for c1 in e.children() { 117 | if c1.is("td", NS) { 118 | for c2 in c1.children() { 119 | if c2.is("img", NS) { 120 | country = match country_map.get(c1.text().trim()) { 121 | Some(country) => country.to_string(), 122 | None => c1.text().trim().to_string(), 123 | }; 124 | } 125 | if c2.is("a", NS) { 126 | match c2.text().as_str() { 127 | "HTTP" => { http = ("HTTP".to_string(), c2.attr("href").unwrap().to_string()); }, 128 | "rsync" => { rsync = ("rsync".to_string(), c2.attr("href").unwrap().to_string()); }, 129 | "FTP" => { ftp = ("ftp".to_string(), c2.attr("href").unwrap().to_string()); }, 130 | _ => { 131 | name = match name_map.get(c2.text().as_str()) { 132 | Some(name) => name.to_string(), 133 | None => c2.text(), 134 | }; 135 | }, 136 | } 137 | } 138 | } 139 | } 140 | } 141 | 142 | let site = Site { 143 | country: country, 144 | name: name, 145 | http: http.1, 146 | rsync: rsync.1, 147 | ftp: ftp.1, 148 | }; 149 | site 150 | } 151 | 152 | fn is_region(e: &Element) -> (bool, bool) { 153 | let mut _ret = false; 154 | let mut _skip = false; 155 | for c1 in e.children() { 156 | if c1.is("td", NS) { 157 | match c1.attr("colspan") { 158 | Some(_) => { 159 | if c1.attr("colspan").unwrap() == "28" { 160 | _ret = true; 161 | } else if c1.attr("colspan").unwrap() == "6" { 162 | _skip = true; 163 | } 164 | }, 165 | None => {}, 166 | } 167 | } 168 | } 169 | (_ret, _skip) 170 | } 171 | 172 | fn get_region(e: &Element) -> String { 173 | let mut _region = String::new(); 174 | let td = e.get_child("td", NS).unwrap(); 175 | match td.attr("colspan") { 176 | Some(_) => { 177 | _region = td.text(); 178 | }, 179 | None => {}, 180 | } 181 | _region 182 | } 183 | 184 | fn get_data(buffer: String) -> String { 185 | let mut data = String::new(); 186 | data.push_str(NSHEAD); 187 | 188 | let mut _in_table = false; 189 | for line in buffer.lines() { 190 | if line.contains("") { 191 | _in_table = true; 192 | data.push_str(line); 193 | continue; 194 | } 195 | if line.contains("
") { 196 | _in_table = false; 197 | data.push_str(line); 198 | data.push_str(NSEND); 199 | continue; 200 | } 201 | 202 | if line.len() == 0 { 203 | continue; 204 | } 205 | if line.contains("radic") { 206 | continue; 207 | } 208 | 209 | if _in_table { 210 | data.push_str(line); 211 | } 212 | } 213 | 214 | data 215 | } 216 | -------------------------------------------------------------------------------- /tools/get_mirror_data/src/name_convert.rs: -------------------------------------------------------------------------------- 1 | pub static NAME_CONVERT:&'static [(&'static str, &'static str)] = &[ 2 | ("The Clarkson Open Source Institute (COSI)", 3 | "The.Clarkson.Open.Source.Institute"), 4 | ("SUSE Linux Products GmbH", 5 | "SUSE.Linux.Products.GmbH"), 6 | ("NAV Communications", 7 | "NAV.Communications"), 8 | ("IPHH - Internet Port Hamburg GmbH", 9 | "IPHH-Internet.Port.Hamburg.GmbH"), 10 | ("Lysator ACS", 11 | "Lysator.ACS"), 12 | ("RPM PBone Search", 13 | "RPM.PBone.Search"), 14 | ("Telkom / FOSS-ID - Free Open Source Software Untuk Semua", 15 | "Telkom.FOSS-ID"), 16 | ("RWTH Aachen University", 17 | "RWTH.Aachen.University"), 18 | ("Princeton University Mathematics", 19 | "Princeton.University.Mathematics"), 20 | ("TENET - Tertiary Education Network", 21 | "TENET-Tertiary.Education.Network"), 22 | ("AARNet - Australia's Research and Education Network", 23 | "AARNet-Australia"), 24 | ("Vectra", 25 | "Vectra"), 26 | ("IPACCT Ltd.", 27 | "IPACCT.Ltd"), 28 | ("LeadHosts", 29 | "LeadHosts"), 30 | ("UNINETT - Norwegian Research Network", 31 | "UNINETT-Norwegian.Research.Network"), 32 | ("NLUUG / Surfnet", 33 | "NLUUG.Surfnet"), 34 | ("University of Science and Technology of China", 35 | "University.of.Science.and.Technology.of.China"), 36 | ("Sultan Qaboos University", 37 | "Sultan.Qaboos.University"), 38 | ("23Media GmbH", 39 | "23Media.GmbH"), 40 | ("Novell Hungary", 41 | "Novell.Hungary"), 42 | ("Linux Kernel Archives (JP)", 43 | "Linux.Kernel.Archives.JP"), 44 | ("LiteServer", 45 | "LiteServer"), 46 | ("NetiX", 47 | "NetiX"), 48 | ("University of Maryland, College Park", 49 | "University.of.Maryland.College.Park"), 50 | ("Яндекс - Yandex", 51 | "Яндекс.Yandex"), 52 | ("JAIST - Japan Advanced Institute Of Science And Technology", 53 | "JAIST"), 54 | ("KLID - Commercial Linux Stakeholders In Denmark", 55 | "KLID-Denmark"), 56 | ("WPI ACM", 57 | "WPI.ACM"), 58 | ("RpmFind, Lyon", 59 | "RpmFind.Lyon"), 60 | ("Host.AG", 61 | "Host.AG"), 62 | ("Komunitas openSUSE Indonesia", 63 | "Komunitas.openSUSE.Indonesia"), 64 | ("Universidad de Costa Rica", 65 | "Universidad.de.Costa.Rica"), 66 | ("Federal University of Paraná, Center for Scientific Computing and Free Software (C3SL)", 67 | "Federal.University"), 68 | ("Esslingen University of Applied Sciences", 69 | "Esslingen.University.of.Applied.Sciences"), 70 | ("Technische Universität Ilmenau", 71 | "Technische.Universität.Ilmenau"), 72 | ("ITCenter of Isfahan University of Technology", 73 | "ITCenter.of.Isfahan.University"), 74 | ("National University of Singapore", 75 | "National.University.of.Singapore"), 76 | ("openSUSE Heroes - sponsored by QSC AG", 77 | "openSUSE.Heroes-sponsored.by.QSC.AG"), 78 | ("CHG - Scientific Center in Chernogolovka RAS", 79 | "CHG-Scientific.Center.in.Chernogolovka.RAS"), 80 | ("The Free Mirror Project", 81 | "Free.Mirror"), 82 | ("Georgia Institute of Technology", 83 | "Georgia.Institute.of.Technology"), 84 | ("Linux Foundation - Portland, Oregon, USA", 85 | "Linux.Foundation.Portland.Oregon.USA"), 86 | ("TDS Telecom", 87 | "TDS.Telecom"), 88 | ("Virginia Tech Transportation Institute", 89 | "Virginia.Tech.Transportation.Institute"), 90 | ("Intergrid", 91 | "Intergrid"), 92 | ("iiNet", 93 | "iiNet"), 94 | ("FSN . HU", 95 | "FSN.HU"), 96 | ("Kelompok Linux Arek Suroboyo", 97 | "Kelompok.Linux.Arek.Suroboyo"), 98 | ("Facultad de Derecho, Universidad de la República, Uruguay", 99 | "Facultad.de.Derecho"), 100 | ("KINDL&PARTNERI advokatni kancelar s.r.o.", 101 | "KINDL&PARTNERI.advokatni.kancelar.s.r.o."), 102 | ("Linux Kernel Archives (US West)", 103 | "Linux.Kernel.Archives.US.West"), 104 | ("Netspace Online Systems", 105 | "Netspace.Online.Systems"), 106 | ("Beijing Jiaotong University", 107 | "Beijing.Jiaotong.University"), 108 | ("Academic Computer Club", 109 | "Academic.Computer.Club"), 110 | ("Xgroup.si", 111 | "Xgroup.si"), 112 | ("Easy Lee", 113 | "Easy.Lee"), 114 | ("Telkom University", 115 | "Telkom.University"), 116 | ("Linux Kernel Archives (US East)", 117 | "Linux.Kernel.Archives.US.East"), 118 | ("University Of Kent - UK Mirror Service", 119 | "University.Of.Kent-UK.Mirror.Service"), 120 | ("GWDG - Gesellschaft für wissenschaftliche Datenverarbeitung mbH Göttingen", 121 | "GWDG"), 122 | ("Leaseweb", 123 | "Leaseweb"), 124 | ("iHost", 125 | "iHost"), 126 | ("CZLUG - Czech Linux Users' Group", 127 | "CZLUG-Czech.Linux.User.Group"), 128 | ("ia64-linux.org", 129 | "ia64-linux.org"), 130 | ("MGTS, RUE Beltelecom. ByFly ISP", 131 | "MGTS.RUE.Beltelecom.ByFly.ISP"), 132 | ("VDS Sunucu", 133 | "VDS.Sunucu"), 134 | ("Academic Computer Club Umeå University", 135 | "Academic.Computer.Club.Umeå.University"), 136 | ("Datto Inc.", 137 | "Datto.Inc."), 138 | ("Datacenter Uzinfocom", 139 | "Datacenter.Uzinfocom"), 140 | ("Beijing Foreign Studies University", 141 | "Beijing.Foreign.Studies.University"), 142 | ("Repo UGM", 143 | "Repo.UGM"), 144 | ("Hostsuisse (ENIDAN Technologies GmbH)", 145 | "Hostsuisse.ENIDAN.Technologies.GmbH"), 146 | ("dogado GmbH", 147 | "dogado.GmbH"), 148 | ("University of Waterloo Computer Science Club", 149 | "University.of.Waterloo"), 150 | ("University of Utah", 151 | "University.of.Utah"), 152 | ("Israel Internet Association (ISOC-IL)", 153 | "Israel.Internet.Association"), 154 | ("Linder Hard- und Software", 155 | "Linder.Hard-und.Software"), 156 | ("NCHC - National Center for High-Performance Computing", 157 | "NCHC"), 158 | ("CZ.NIC", 159 | "CZ.NIC"), 160 | ("Internode", 161 | "Internode"), 162 | ("TheoM’s Mirror Service", 163 | "TheoM’s.Mirror.Service"), 164 | ("NetEase", 165 | "NetEase"), 166 | ("Tsinghua University TUNA", 167 | "Tsinghua.University"), 168 | ("TWAREN - Taiwan Advance Research & Education Network", 169 | "TWAREN"), 170 | ("Coreix Ltd", 171 | "Coreix.Ltd"), 172 | ("Tomsk State Pedagogical University", 173 | "Tomsk.State.Pedagogical.University"), 174 | ("RNL - Técnico Lisboa", 175 | "RNL-Técnico.Lisboa"), 176 | ("ETTE.biz", 177 | "ETTE.biz"), 178 | ("ibiblio.org - the public's library and digital archive", 179 | "ibiblio.org"), 180 | ("University of Crete", 181 | "University.of.Crete"), 182 | ("Dalhousie University, Halifax NS", 183 | "Dalhousie.University"), 184 | ("Adfinis AG", 185 | "Adfinis.AG"), 186 | ("Julius Maximilian University of Würzburg", 187 | "Julius.Maximilian.University.of.Würzburg"), 188 | ("nxtHost.com", 189 | "nxtHost.com"), 190 | ("University of Bayreuth", 191 | "University.of.Bayreuth"), 192 | ("Purdue Linux Users Group", 193 | "Purdue.Linux.Users.Group"), 194 | ("Linux Kernel Archives (EU)", 195 | "Linux.Kernel.Archives.EU"), 196 | ("Consorcio Ecuatoriano para el Desarrollo de Internet Avanzado", 197 | "Consorcio.Ecuatoriano.para"), 198 | ("KDDI R&D Labs", 199 | "KDDI.R&D.Labs"), 200 | ("RIKEN's Institute & Centers", 201 | "RIKEN's.Institute&Centers"), 202 | ("Easyname GmbH", 203 | "Easyname.GmbH"), 204 | ("University of Erlangen-Nürnberg", 205 | "University.of.Erlangen-Nürnberg"), 206 | ("Schlund Technologies GmbH", 207 | "Schlund.Technologies.GmbH"), 208 | ("University of Kaiserslautern", 209 | "University.of.Kaiserslautern"), 210 | ("Alwyzon", 211 | "Alwyzon"), 212 | ("FedoraMD project", 213 | "FedoraMD.project"), 214 | ("BELNET - The network of knowledge", 215 | "BELNET-The.network.of.knowledge"), 216 | ("University of Cyprus, Library", 217 | "University.of.Cyprus.Library"), 218 | ("Technische Universität Chemnitz", 219 | "Technische.Universität.Chemnitz"), 220 | ("openSUSE Heroes", 221 | "openSUSE.Heroes"), 222 | ("Get Hosted Online", 223 | "Get.Hosted.Online"), 224 | ("Poznań Supercomputing and Networking Center", 225 | "Poznań.Supercomputing.and.Networking.Center"), 226 | ("http://sfo-korg-mirror.kernel.org/", 227 | "sfo-korg-mirror"), 228 | ("Siena College", 229 | "Siena.College"), 230 | ("KAIST - Korea Advanced Institute of Science and Technology", 231 | "KAIST"), 232 | ("Ucom LLC", 233 | "Ucom.LLC"), 234 | ("IP Serverone Solutions Sdn Bhd", 235 | "IP.Serverone.Solutions.Sdn.Bhd"), 236 | ("Linux Kullanicilari Dernegi, ULAKBIM", 237 | "Linux.Kullanicilari.Dernegi.ULAKBIM"), 238 | ("Rochester Institute of Technology - Research Computing", 239 | "Rochester.Institute.of.Technology"), 240 | ("Indiana University, Research Technologies Core Services", 241 | "Indiana.University"), 242 | ("Lanzhou University Open Source Society", 243 | "Lanzhou.University"), 244 | ("Silicon Hill, Student’s Union CTU", 245 | "Silicon.Hill.Student’s.Union.CTU"), 246 | ("Rainside", 247 | "Rainside"), 248 | ("University of Paderborn", 249 | "University.of.Paderborn"), 250 | ("Rotterdam University", 251 | "Rotterdam.University"), 252 | ("ICM - Interdisciplinary Center for Mathematical and Computational Modeling", 253 | "ICM"), 254 | ("Yuan Ze University", 255 | "Yuan.Ze.University"), 256 | ("Rackspace Hosting, Inc.", 257 | "Rackspace.Hosting.Inc."), 258 | ("Bernhard M. Wiedemann", 259 | "Bernhard.M.Wiedemann"), 260 | ("Harbin Institute of Technology Linux User Group", 261 | "Harbin.Institute.of.Technology"), 262 | ("eScience Center, Nanjing University", 263 | "eScience.Center,.Nanjing.University"), 264 | ("DEAC", 265 | "DEAC"), 266 | ("lagis Internet Serviceprovider", 267 | "lagis.Internet.Serviceprovider"), 268 | ("Liquid Telecom", 269 | "Liquid.Telecom"), 270 | ("UPC Česká republika", 271 | "UPC.Česká.republika"), 272 | ("GARR - The Italian Academic & Research Network", 273 | "GARR-The.Italian.Academic&Research.Network"), 274 | ("UNICAMP - University of Campinas", 275 | "UNICAMP"), 276 | ("Quantum Mirror", 277 | "Quantum.Mirror"), 278 | ("University of Oxford", 279 | "University.of.Oxford"), 280 | ("University of Leipzig", 281 | "University.of.Leipzig"), 282 | ("openSUSE", 283 | "openSUSE"), 284 | ("Binario Cloud / openSUSE Brasil", 285 | "Binario.Cloud"), 286 | ("EUserv Internet", 287 | "EUserv.Internet"), 288 | ("UFONE", 289 | "UFONE"), 290 | ("Shanghai Jiao Tong University Network Information Center", 291 | "Shanghai.Jiao.Tong.University"), 292 | ("Funet - Finnish University and Research Network", 293 | "Funet-Finnish.University.and.Research.Network"), 294 | ("Elion", 295 | "Elion"), 296 | ("Carsten Braun Software Solutions", 297 | "Carsten.Braun.Software.Solutions"), 298 | ("Dotsrc.org", 299 | "Dotsrc.org"), 300 | ("Free", 301 | "Free"), 302 | ("MUUG - Manitoba UNIX User Group", 303 | "MUUG"), 304 | ("Esto Internet", 305 | "Esto.Internet"), 306 | ("Ivan Barabash", 307 | "Ivan.Barabash"), 308 | ("Silicon Valley Web Hosting LLC", 309 | "Silicon.Valley.Web.Hosting.LLC"), 310 | ("standaloneInstaller.com", 311 | "standaloneInstaller.com"), 312 | ]; 313 | 314 | pub static COUNTRY_CONVERT:&'static [(&'static str, &'static str)] = &[ 315 | ("Hong Kong", 316 | "Hong.Kong"), 317 | ("Costa Rica", 318 | "Costa.Rica"), 319 | ("Czech Republic", 320 | "Czech.Republic"), 321 | ("Iran, Islamic Republic of", 322 | "Iran,Islamic.Republic.of"), 323 | ("Korea, Republic of", 324 | "Korea,Republic.of"), 325 | ("New Zealand", 326 | "New.Zealand"), 327 | ("Russian Federation", 328 | "Russian.Federation"), 329 | ("South Africa", 330 | "South.Africa"), 331 | ("United Kingdom", 332 | "United.Kingdom"), 333 | ("United States", 334 | "United.States"), 335 | ]; 336 | -------------------------------------------------------------------------------- /zypp-gui/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "zypp_gui" 3 | version = "0.4.1" 4 | authors = ["Xiaoguang Wang "] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | packagekit_rs = { path = "../packagekit_rs" } 9 | libc = "0.2.95" 10 | adw = { package = "libadwaita", version = "0.7", features = ["v1_4"] } 11 | polkit-sys = "0.1.0" 12 | zbus = "1.9.1" 13 | log = "0.4.14" 14 | env_logger = "0.8.4" 15 | gettext-rs = { version = "0.7", features = ["gettext-system"] } 16 | serde_json = "1.0.64" 17 | serde = { version = "1.0", features = ["derive"] } 18 | gtk = { version = "0.9", package = "gtk4" } 19 | gdk = { version = "0.9", package = "gdk4" } 20 | async-channel = "2.1.1" 21 | -------------------------------------------------------------------------------- /zypp-gui/meson.build: -------------------------------------------------------------------------------- 1 | subdir('src') 2 | -------------------------------------------------------------------------------- /zypp-gui/src/additional.rs: -------------------------------------------------------------------------------- 1 | use adw::prelude::*; 2 | use serde::{Deserialize, Serialize}; 3 | use std::fs::File; 4 | use std::io::prelude::*; 5 | use std::process::{Command, Stdio}; 6 | 7 | use crate::config; 8 | use crate::zypper::Zypper; 9 | 10 | enum SYSTEM { 11 | TW, 12 | LEAP, 13 | } 14 | 15 | #[derive(Serialize, Deserialize, Debug, Clone)] 16 | struct Data { 17 | list: Vec, 18 | } 19 | #[derive(Serialize, Deserialize, Debug, Clone)] 20 | struct Repo { 21 | name: String, 22 | url: String, 23 | info: String, 24 | } 25 | 26 | #[derive(Clone)] 27 | pub struct AdditionalRepo { 28 | data: Data, 29 | additional_page: gtk::ListBox, 30 | main_window: adw::ApplicationWindow, 31 | } 32 | 33 | impl AdditionalRepo { 34 | pub fn new(main_builder: >k::Builder, builder: >k::Builder) -> Self { 35 | let data = AdditionalRepo::read_data(); 36 | let additional_page: gtk::ListBox = builder.object("additional_page").unwrap(); 37 | let main_window: adw::ApplicationWindow = main_builder.object("window").unwrap(); 38 | 39 | let this = Self { 40 | data, 41 | additional_page, 42 | main_window, 43 | }; 44 | 45 | this.creat_row(); 46 | this 47 | } 48 | 49 | fn read_data() -> Data { 50 | let path = format!("{}/{}", config::PKGDATADIR, "additional.json"); 51 | let mut file = match File::open(path) { 52 | Ok(file) => file, 53 | Err(_) => return Data { list: vec![] }, 54 | }; 55 | let mut buffer = String::new(); 56 | file.read_to_string(&mut buffer).expect("read file fail"); 57 | let data: Data = match serde_json::from_str(&buffer) { 58 | Ok(data) => data, 59 | Err(_) => return Data { list: vec![] }, 60 | }; 61 | 62 | data 63 | } 64 | 65 | fn creat_row(&self) { 66 | for data in self.data.list.clone() { 67 | let builder = gtk::Builder::from_resource("/zypp/gui/ui/additional_row.ui"); 68 | let row: adw::ExpanderRow = builder.object("additional_row").unwrap(); 69 | let sub_row: gtk::Label = builder.object("repo_info").unwrap(); 70 | let button: gtk::Button = builder.object("button_add").unwrap(); 71 | row.set_title(&data.name); 72 | sub_row.set_markup(&data.info); 73 | 74 | let this = self.clone(); 75 | button.connect_clicked(move |_| { 76 | let url = match this.check_system() { 77 | SYSTEM::TW => { 78 | let url = format!("{}openSUSE_Tumbleweed/", data.url.clone()); 79 | url 80 | } 81 | SYSTEM::LEAP => { 82 | let url = format!("{}openSUSE_Leap_$releasever/", data.url.clone()); 83 | url 84 | } 85 | }; 86 | if this.check_url(url.clone()) { 87 | this.create_dialog("The repo has been added".to_string()); 88 | } else { 89 | Zypper::add_repo(data.name.clone(), url); 90 | } 91 | }); 92 | 93 | self.additional_page.append(&row.to_owned()); 94 | } 95 | } 96 | 97 | fn check_url(&self, url: String) -> bool { 98 | let status = Command::new("grep") 99 | .arg(url) 100 | .arg("-r") 101 | .arg("/etc/zypp/repos.d/") 102 | .stdout(Stdio::piped()) 103 | .status() 104 | .expect("failed to execute grep"); 105 | 106 | if status.success() { 107 | true 108 | } else { 109 | false 110 | } 111 | } 112 | 113 | fn create_dialog(&self, text: String) { 114 | let dialog = gtk::MessageDialog::new( 115 | Some(&self.main_window), 116 | gtk::DialogFlags::DESTROY_WITH_PARENT | gtk::DialogFlags::MODAL, 117 | gtk::MessageType::Error, 118 | gtk::ButtonsType::Cancel, 119 | &text, 120 | ); 121 | 122 | dialog.run_async(move |obj, _answer| { 123 | obj.close(); 124 | }); 125 | } 126 | 127 | fn check_system(&self) -> SYSTEM { 128 | let status = Command::new("grep") 129 | .arg("Tumbleweed") 130 | .arg("/etc/os-release") 131 | .stdout(Stdio::piped()) 132 | .status() 133 | .expect("failed to execute rpm"); 134 | 135 | if status.success() { 136 | SYSTEM::TW 137 | } else { 138 | SYSTEM::LEAP 139 | } 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /zypp-gui/src/config.rs.in: -------------------------------------------------------------------------------- 1 | pub const APP_ID: &str = @APP_ID@; 2 | pub const GETTEXT_PACKAGE: &str = @GETTEXT_PACKAGE@; 3 | pub const LOCALEDIR: &str = @LOCALEDIR@; 4 | pub const PKGDATADIR: &str = @PKGDATADIR@; 5 | pub const PROFILE: &str = @PROFILE@; 6 | pub const RESOURCES_FILE: &str = concat!(@PKGDATADIR@, "/resources.gresource"); 7 | pub const VERSION: &str = @VERSION@; 8 | -------------------------------------------------------------------------------- /zypp-gui/src/list_row.rs: -------------------------------------------------------------------------------- 1 | pub struct ListRow { 2 | row: gtk::Box, 3 | name: gtk::Label, 4 | version: gtk::Label, 5 | } 6 | 7 | impl ListRow { 8 | pub fn new() -> Self { 9 | let builder = gtk::Builder::from_resource("/zypp/gui/ui/list_row.ui"); 10 | let row: gtk::Box = builder.object("row").unwrap(); 11 | let name: gtk::Label = builder.object("name").unwrap(); 12 | let version: gtk::Label = builder.object("version").unwrap(); 13 | 14 | Self { 15 | row: row, 16 | name: name, 17 | version: version, 18 | } 19 | } 20 | 21 | pub fn row(&self) -> >k::Box { 22 | &self.row 23 | } 24 | 25 | pub fn set_name(&self, name: String) { 26 | self.name.set_label(&name.to_string()); 27 | } 28 | 29 | pub fn set_version(&self, version: String) { 30 | self.version.set_label(&version.to_string()); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /zypp-gui/src/main.rs: -------------------------------------------------------------------------------- 1 | mod additional; 2 | mod config; 3 | mod list_row; 4 | mod mirror; 5 | mod mirror_row; 6 | mod mirror_window; 7 | mod notification; 8 | mod package_meta; 9 | mod packagekit; 10 | mod page_settings; 11 | mod repo_row; 12 | mod search; 13 | mod search_row; 14 | mod util; 15 | mod window; 16 | mod zypper; 17 | 18 | use config::{GETTEXT_PACKAGE, LOCALEDIR, RESOURCES_FILE}; 19 | use gettextrs::*; 20 | use gtk::gio; 21 | use gtk::glib; 22 | use gtk::prelude::*; 23 | use log::info; 24 | 25 | use crate::packagekit::PackagekitState; 26 | use crate::window::Window; 27 | 28 | fn main() { 29 | env_logger::init(); 30 | 31 | // Prepare i18n 32 | setlocale(LocaleCategory::LcAll, ""); 33 | bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR).expect("Unable to bind the text domain"); 34 | textdomain(GETTEXT_PACKAGE).expect("Unable to switch to the text domain"); 35 | 36 | glib::set_application_name("zypp gui"); 37 | glib::set_prgname(Some("zypp-gui")); 38 | 39 | gtk::init().expect("Unable to start GTK4"); 40 | adw::init().expect("Unable to init adw"); 41 | 42 | let res = gio::Resource::load(RESOURCES_FILE).expect("Could not load gresource file"); 43 | gio::resources_register(&res); 44 | 45 | //setup_css(); 46 | let application = adw::Application::new(Some(config::APP_ID), Default::default()); 47 | application.connect_startup(|app| { 48 | build_ui(app); 49 | }); 50 | 51 | info!("zypp gui ({})", config::APP_ID); 52 | info!("Version: {} ({})", config::VERSION, config::PROFILE); 53 | application.run(); 54 | } 55 | 56 | fn build_ui(application: &adw::Application) { 57 | info!("startup"); 58 | let packagekit_state = PackagekitState::new(); 59 | let window = Window::new(packagekit_state, application.clone()); 60 | //let window = adw::ApplicationWindow::new(application); 61 | 62 | application.connect_activate(move |_| { 63 | info!("activate"); 64 | window.first_show(); 65 | window.window().show(); 66 | }); 67 | } 68 | 69 | //fn setup_css() { 70 | //let provider = gtk::CssProvider::new(); 71 | //provider.load_from_resource("/zypp/gui/style.css"); 72 | //if let Some(screen) = gdk::Screen::default() { 73 | //gtk::StyleContext::add_provider_for_screen( 74 | //&screen, 75 | //&provider, 76 | //gtk::STYLE_PROVIDER_PRIORITY_APPLICATION, 77 | //); 78 | //} 79 | //} 80 | -------------------------------------------------------------------------------- /zypp-gui/src/meson.build: -------------------------------------------------------------------------------- 1 | global_conf = configuration_data() 2 | global_conf.set_quoted('APP_ID', application_id) 3 | global_conf.set_quoted('PKGDATADIR', pkgdatadir) 4 | global_conf.set_quoted('PROFILE', profile) 5 | global_conf.set_quoted('VERSION', version + version_suffix) 6 | global_conf.set_quoted('GETTEXT_PACKAGE', gettext_package) 7 | global_conf.set_quoted('LOCALEDIR', localedir) 8 | config = configure_file( 9 | input: 'config.rs.in', 10 | output: 'config.rs', 11 | configuration: global_conf 12 | ) 13 | # Copy the config.rs output to the source directory. 14 | run_command( 15 | 'cp', 16 | meson.build_root() / 'zypp-gui' / 'src' / 'config.rs', 17 | meson.source_root() / 'zypp-gui' / 'src' / 'config.rs', 18 | check: true 19 | ) 20 | 21 | sources = files( 22 | 'config.rs', 23 | 'config.rs.in', 24 | 'list_row.rs', 25 | 'main.rs', 26 | 'mirror.rs', 27 | 'mirror_row.rs', 28 | 'mirror_window.rs', 29 | 'notification.rs', 30 | 'package_meta.rs', 31 | 'packagekit.rs', 32 | 'page_settings.rs', 33 | 'repo_row.rs', 34 | 'search.rs', 35 | 'search_row.rs', 36 | 'additional.rs', 37 | 'util.rs', 38 | 'window.rs', 39 | 'zypper.rs', 40 | ) 41 | 42 | custom_target( 43 | 'cargo-build', 44 | build_by_default: true, 45 | input: sources, 46 | output: meson.project_name(), 47 | console: true, 48 | install: true, 49 | install_dir: bindir, 50 | depends: resources, 51 | command: [ 52 | cargo_script, 53 | meson.build_root(), 54 | meson.source_root(), 55 | '@OUTPUT@', 56 | profile, 57 | 'zypp_gui', 58 | 'zypp-gui', 59 | ] 60 | ) 61 | -------------------------------------------------------------------------------- /zypp-gui/src/mirror.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | use std::fs::File; 3 | use std::io::prelude::*; 4 | 5 | use crate::config; 6 | use crate::mirror_row::MirrorRow; 7 | 8 | #[derive(Serialize, Deserialize, Debug, Clone)] 9 | struct Data { 10 | asia: Vec, 11 | africa: Vec, 12 | europe: Vec, 13 | north_america: Vec, 14 | oceania: Vec, 15 | south_america: Vec, 16 | } 17 | 18 | #[derive(Serialize, Deserialize, Debug, Clone)] 19 | pub struct Site { 20 | pub country: String, 21 | pub name: String, 22 | pub http: String, 23 | pub rsync: String, 24 | pub ftp: String, 25 | } 26 | 27 | #[derive(Clone)] 28 | pub struct MirrorSettings { 29 | data: Data, 30 | main_window: adw::ApplicationWindow, 31 | } 32 | 33 | impl MirrorSettings { 34 | pub fn new(main_builder: >k::Builder, builder: >k::Builder) -> Self { 35 | let data = MirrorSettings::read_data(); 36 | let main_window: adw::ApplicationWindow = main_builder.object("window").unwrap(); 37 | 38 | let mirror = Self { data, main_window }; 39 | 40 | mirror.creat_row(builder); 41 | mirror 42 | } 43 | 44 | fn read_data() -> Data { 45 | let path = format!("{}/{}", config::PKGDATADIR, "mirror.json"); 46 | let mut file = match File::open(path) { 47 | Ok(file) => file, 48 | Err(_) => { 49 | return Data { 50 | asia: vec![], 51 | africa: vec![], 52 | europe: vec![], 53 | north_america: vec![], 54 | oceania: vec![], 55 | south_america: vec![], 56 | } 57 | } 58 | }; 59 | let mut buffer = String::new(); 60 | file.read_to_string(&mut buffer).expect("read file fail"); 61 | 62 | let data: Data = match serde_json::from_str(&buffer) { 63 | Ok(data) => data, 64 | Err(_) => { 65 | return Data { 66 | asia: vec![], 67 | africa: vec![], 68 | europe: vec![], 69 | north_america: vec![], 70 | oceania: vec![], 71 | south_america: vec![], 72 | } 73 | } 74 | }; 75 | data 76 | } 77 | 78 | fn creat_row(&self, builder: >k::Builder) { 79 | { 80 | let list_box: gtk::ListBox = builder.object("asia").unwrap(); 81 | for site in self.data.asia.clone() { 82 | let row = MirrorRow::new(site, self.main_window.clone()); 83 | list_box.append(&row.row().to_owned()); 84 | } 85 | } 86 | { 87 | let list_box: gtk::ListBox = builder.object("africa").unwrap(); 88 | for site in self.data.africa.clone() { 89 | let row = MirrorRow::new(site, self.main_window.clone()); 90 | list_box.append(&row.row().to_owned()); 91 | } 92 | } 93 | { 94 | let list_box: gtk::ListBox = builder.object("europe").unwrap(); 95 | for site in self.data.europe.clone() { 96 | let row = MirrorRow::new(site, self.main_window.clone()); 97 | list_box.append(&row.row().to_owned()); 98 | } 99 | } 100 | { 101 | let list_box: gtk::ListBox = builder.object("north_america").unwrap(); 102 | for site in self.data.north_america.clone() { 103 | let row = MirrorRow::new(site, self.main_window.clone()); 104 | list_box.append(&row.row().to_owned()); 105 | } 106 | } 107 | { 108 | let list_box: gtk::ListBox = builder.object("oceania").unwrap(); 109 | for site in self.data.oceania.clone() { 110 | let row = MirrorRow::new(site, self.main_window.clone()); 111 | list_box.append(&row.row().to_owned()); 112 | } 113 | } 114 | { 115 | let list_box: gtk::ListBox = builder.object("south_america").unwrap(); 116 | for site in self.data.south_america.clone() { 117 | let row = MirrorRow::new(site, self.main_window.clone()); 118 | list_box.append(&row.row().to_owned()); 119 | } 120 | } 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /zypp-gui/src/mirror_row.rs: -------------------------------------------------------------------------------- 1 | use adw::prelude::*; 2 | 3 | use crate::mirror::Site; 4 | use crate::mirror_window::MirrorWindow; 5 | 6 | #[derive(Clone)] 7 | pub struct MirrorRow { 8 | row: adw::ActionRow, 9 | site: Site, 10 | main_window: adw::ApplicationWindow, 11 | } 12 | 13 | impl MirrorRow { 14 | pub fn new(site: Site, main_window: adw::ApplicationWindow) -> Self { 15 | let builder = gtk::Builder::from_resource("/zypp/gui/ui/mirror_row.ui"); 16 | let row: adw::ActionRow = builder.object("mirror_row").unwrap(); 17 | let title = format!("{} {}", site.country.clone(), site.name.clone()); 18 | row.set_title(title.as_str()); 19 | //row.set_icon_name(Some(site.country.to_lowercase().as_str())); 20 | 21 | let mirror_row = Self { 22 | row, 23 | site, 24 | main_window, 25 | }; 26 | 27 | mirror_row.row_button_connect(); 28 | mirror_row 29 | } 30 | 31 | pub fn row(&self) -> &adw::ActionRow { 32 | &self.row 33 | } 34 | 35 | fn row_button_connect(&self) { 36 | { 37 | let this = self.clone(); 38 | self.row.connect_activated(move |_| { 39 | let window = MirrorWindow::new(this.site.clone()); 40 | window.window().set_transient_for(Some(&this.main_window)); 41 | window.window().show(); 42 | }); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /zypp-gui/src/mirror_window.rs: -------------------------------------------------------------------------------- 1 | use gtk::prelude::*; 2 | use log::debug; 3 | use std::collections::HashMap; 4 | use std::thread; 5 | 6 | use crate::mirror::Site; 7 | use crate::zypper::Zypper; 8 | 9 | #[derive(Clone)] 10 | pub struct MirrorWindow { 11 | window: gtk::Window, 12 | site: Site, 13 | map: HashMap, 14 | radio_buttons: Vec, 15 | } 16 | 17 | impl MirrorWindow { 18 | pub fn new(site: Site) -> Self { 19 | let builder = gtk::Builder::from_resource("/zypp/gui/ui/mirror_window.ui"); 20 | let window: gtk::Window = builder.object("mirror_window").unwrap(); 21 | window.set_modal(true); 22 | 23 | let country: gtk::Label = builder.object("country").unwrap(); 24 | let site_label: gtk::Label = builder.object("site").unwrap(); 25 | country.set_text(&site.country); 26 | site_label.set_text(&site.name); 27 | 28 | let mut this = Self { 29 | window: window, 30 | site: site.clone(), 31 | map: HashMap::new(), 32 | radio_buttons: vec![], 33 | }; 34 | 35 | { 36 | let connect_box: gtk::Box = builder.object("connect_box").unwrap(); 37 | let mut list: Vec = vec![]; 38 | if site.http.len() != 0 { 39 | list.push("http".to_string()); 40 | this.map.insert("http".to_string(), site.http); 41 | }; 42 | if site.rsync.len() != 0 { 43 | list.push("rsync".to_string()); 44 | this.map.insert("rsync".to_string(), site.rsync); 45 | }; 46 | if site.ftp.len() != 0 { 47 | list.push("ftp".to_string()); 48 | this.map.insert("ftp".to_string(), site.ftp); 49 | }; 50 | this.add_radiobutton(connect_box, list.clone()); 51 | } 52 | 53 | { 54 | let distro_box: gtk::Box = builder.object("distro_box").unwrap(); 55 | let mut list: Vec = vec![]; 56 | for i in &["tw", "leap"] { 57 | list.push(i.to_string()); 58 | this.map.insert(i.to_string(), i.to_string()); 59 | } 60 | this.add_radiobutton(distro_box, list.clone()); 61 | } 62 | 63 | this.connect_signal(&builder); 64 | 65 | this 66 | } 67 | 68 | pub fn window(&self) -> >k::Window { 69 | &self.window 70 | } 71 | 72 | fn add_radiobutton(&mut self, button_box: gtk::Box, list: Vec) { 73 | if list.len() == 0 { 74 | return; 75 | } 76 | 77 | let first_button: gtk::ToggleButton = gtk::ToggleButton::with_mnemonic(&list[0]); 78 | first_button.set_widget_name(&list[0]); 79 | button_box.append(&first_button.to_owned()); 80 | self.radio_buttons.push(first_button.clone()); 81 | 82 | for i in 1..list.len() { 83 | let button: gtk::ToggleButton = gtk::ToggleButton::with_mnemonic(&list[i]); 84 | button.set_widget_name(&list[i]); 85 | button_box.append(&button.to_owned()); 86 | self.radio_buttons.push(button.clone()); 87 | } 88 | } 89 | 90 | fn connect_signal(&self, builder: >k::Builder) { 91 | let add_button: gtk::Button = builder.object("add").unwrap(); 92 | let this = self.clone(); 93 | let radio_buttons = self.radio_buttons.clone(); 94 | add_button.connect_clicked(move |_| { 95 | let mut _url = "".to_string(); 96 | let mut _distro = "".to_string(); 97 | for b in radio_buttons.clone() { 98 | if b.is_active() { 99 | if b.widget_name().contains("http") 100 | || b.widget_name().contains("ftp") 101 | || b.widget_name().contains("rsync") 102 | { 103 | let name: String = b.widget_name().to_string(); 104 | _url = this.map.get(&name).unwrap().to_string(); 105 | } else { 106 | let name: String = b.widget_name().to_string(); 107 | _distro = this.map.get(&name).unwrap().to_string(); 108 | } 109 | } 110 | } 111 | let list = this.get_repo_address_list(this.site.name.clone(), _url, _distro); 112 | debug!("These addresses will be added.\n{:?}", list); 113 | this.create_dialog(list); 114 | }); 115 | } 116 | 117 | fn get_repo_address_list( 118 | &self, 119 | name: String, 120 | url_in: String, 121 | distro: String, 122 | ) -> Vec<(String, String)> { 123 | let url = match url_in.strip_suffix("/") { 124 | Some(url) => url, 125 | _ => url_in.as_str(), 126 | }; 127 | let mut list = vec![]; 128 | if distro == "tw" { 129 | //repo-debug.repo: baseurl=http://download.opensuse.org/tumbleweed/repo/debug/ 130 | //repo-src-oss.repo: baseurl=http://download.opensuse.org/tumbleweed/repo/src-oss 131 | //repo-src-non-oss.repo:baseurl=http://download.opensuse.org/tumbleweed/repo/src-non-oss 132 | //repo-non-oss.repo: baseurl=http://download.opensuse.org/tumbleweed/repo/non-oss/ 133 | //repo-oss.repo: baseurl=http://download.opensuse.org/tumbleweed/repo/oss/ 134 | { 135 | let name = format!("{}-non-oss", name); 136 | let link = format!("{}/tumbleweed/repo/non-oss/", url); 137 | list.push((link, name)); 138 | } 139 | { 140 | let name = format!("{}-oss", name); 141 | let link = format!("{}/tumbleweed/repo/oss/", url); 142 | list.push((link, name)); 143 | } 144 | { 145 | let name = format!("{}-debug", name); 146 | let link = format!("{}/tumbleweed/repo/debug/", url); 147 | list.push((link, name)); 148 | } 149 | { 150 | let name = format!("{}-src-oss", name); 151 | let link = format!("{}/tumbleweed/repo/src-oss/", url); 152 | list.push((link, name)); 153 | } 154 | { 155 | let name = format!("{}-src-non-oss", name); 156 | let link = format!("{}/tumbleweed/repo/src-non-oss/", url); 157 | list.push((link, name)); 158 | } 159 | } else if distro.contains("leap") { 160 | //repo-debug-non-oss.repo:baseurl=http://download.opensuse.org/debug/distribution/leap/$releasever/repo/non-oss/ 161 | //repo-debug.repo:baseurl=http://download.opensuse.org/debug/distribution/leap/$releasever/repo/oss/ 162 | //repo-debug-update-non-oss.repo:baseurl=http://download.opensuse.org/debug/update/leap/$releasever/non-oss/ 163 | //repo-debug-update.repo:baseurl=http://download.opensuse.org/debug/update/leap/$releasever/oss/ 164 | //repo-non-oss.repo:baseurl=http://download.opensuse.org/distribution/leap/$releasever/repo/non-oss/ 165 | //repo-oss.repo:baseurl=http://download.opensuse.org/distribution/leap/$releasever/repo/oss/ 166 | //repo-source-non-oss.repo:baseurl=http://download.opensuse.org/source/distribution/leap/$releasever/repo/non-oss/ 167 | //repo-source.repo:baseurl=http://download.opensuse.org/source/distribution/leap/$releasever/repo/oss/ 168 | //repo-update-non-oss.repo:baseurl=http://download.opensuse.org/update/leap/$releasever/non-oss/ 169 | //repo-update.repo:baseurl=http://download.opensuse.org/update/leap/$releasever/oss/ 170 | 171 | { 172 | let name = format!("{}-non-oss", name); 173 | let link = format!("{}/distribution/leap/$releasever/repo/non-oss/", url); 174 | list.push((link, name)); 175 | } 176 | { 177 | let name = format!("{}-oss", name); 178 | let link = format!("{}/distribution/leap/$releasever/repo/oss/", url); 179 | list.push((link, name)); 180 | } 181 | { 182 | let name = format!("{}-update-non-oss", name); 183 | let link = format!("{}/update/leap/$releasever/non-oss/", url); 184 | list.push((link, name)); 185 | } 186 | { 187 | let name = format!("{}-update-oss", name); 188 | let link = format!("{}/update/leap/$releasever/oss/", url); 189 | list.push((link, name)); 190 | } 191 | } 192 | 193 | list 194 | } 195 | 196 | fn create_dialog(&self, list: Vec<(String, String)>) { 197 | let mut text = format!("These repos will be added:\n\n"); 198 | for i in list.clone() { 199 | text = format!("{}{}, {}\n", text, i.1, i.0); 200 | } 201 | 202 | let dialog = gtk::MessageDialog::new( 203 | Some(&self.window), 204 | gtk::DialogFlags::DESTROY_WITH_PARENT | gtk::DialogFlags::MODAL, 205 | gtk::MessageType::Error, 206 | gtk::ButtonsType::OkCancel, 207 | &text, 208 | ); 209 | 210 | let window = self.window.clone(); 211 | dialog.run_async(move |obj, _answer| { 212 | obj.close(); 213 | if _answer == gtk::ResponseType::Ok { 214 | let l = list.clone(); 215 | thread::spawn(move || { 216 | for i in l { 217 | Zypper::add_repo(i.1, i.0); 218 | } 219 | }); 220 | //&self.window.close(); 221 | window.close(); 222 | } 223 | }); 224 | } 225 | } 226 | -------------------------------------------------------------------------------- /zypp-gui/src/notification.rs: -------------------------------------------------------------------------------- 1 | use gettextrs::*; 2 | use gtk::prelude::*; 3 | 4 | #[derive(Clone)] 5 | pub struct Notification { 6 | notification_bar: gtk::Revealer, 7 | label: gtk::Label, 8 | } 9 | 10 | impl Notification { 11 | pub fn new(builder: >k::Builder) -> Self { 12 | let notification_bar: gtk::Revealer = builder.object("notification_bar").unwrap(); 13 | let label: gtk::Label = builder.object("notification_label").unwrap(); 14 | 15 | Self::signal_connect(&builder); 16 | 17 | Self { 18 | notification_bar, 19 | label, 20 | } 21 | } 22 | 23 | fn signal_connect(builder: >k::Builder) { 24 | let button: gtk::Button = builder.object("notification_button").unwrap(); 25 | let notification_bar: gtk::Revealer = builder.object("notification_bar").unwrap(); 26 | button.connect_clicked(move |_| { 27 | notification_bar.set_reveal_child(false); 28 | }); 29 | } 30 | 31 | pub fn set_label(&self, text: String) { 32 | self.label.set_text(&gettext(text.as_str())); 33 | self.notification_bar.set_reveal_child(true); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /zypp-gui/src/packagekit.rs: -------------------------------------------------------------------------------- 1 | use gtk::glib; 2 | use gtk::glib::translate::*; 3 | use libc::{c_char, c_int}; 4 | use log::debug; 5 | use std::cell::RefCell; 6 | use std::env; 7 | use std::process::{Command, Stdio}; 8 | use std::ptr; 9 | use std::rc::Rc; 10 | use zbus::{Connection, Message}; 11 | 12 | use crate::util::{PKmessage, PackageInfo}; 13 | use packagekit_rs::prelude::*; 14 | use packagekit_rs::{ 15 | pk_offline_get_prepared_ids, pk_offline_trigger, ClientPk, ProgressPk, ResultsPk, 16 | PK_OFFLINE_ACTION_REBOOT, PK_PROGRESS_TYPE_PERCENTAGE, PK_STATUS_ENUM_DOWNLOAD, 17 | PK_STATUS_ENUM_INSTALL, PK_STATUS_ENUM_REFRESH_CACHE, PK_STATUS_ENUM_REMOVE, 18 | }; 19 | 20 | #[derive(Clone)] 21 | pub struct PackagekitState { 22 | state: Rc>, 23 | } 24 | 25 | impl PackagekitState { 26 | pub fn new() -> Self { 27 | Self { 28 | state: Rc::new(RefCell::new(false)), 29 | } 30 | } 31 | 32 | pub fn set_busy(&self, s: bool) { 33 | *self.state.borrow_mut() = s; 34 | } 35 | 36 | pub fn busy(&self) -> bool { 37 | let state = self.state.borrow(); 38 | if *state { 39 | true 40 | } else { 41 | false 42 | } 43 | } 44 | } 45 | 46 | pub fn get_updates(sender: async_channel::Sender) { 47 | debug!("get updates start"); 48 | let client = ClientPk::new(); 49 | let sender1 = sender.clone(); 50 | let sender2 = sender.clone(); 51 | 52 | // Send update packages list 53 | { 54 | let closure = move |progress: &ProgressPk, progress_type: c_int| { 55 | if progress_type == PK_PROGRESS_TYPE_PERCENTAGE { 56 | sender1 57 | .send_blocking(PKmessage::Progress((progress.percentage(), None))) 58 | .expect("Couldn't send data to channel"); 59 | } 60 | }; 61 | 62 | let result: ResultsPk; 63 | match client.get_updates(Some(Box::new(closure)), None) { 64 | Ok(ret) => result = ret, 65 | Err(e) => { 66 | sender 67 | .send_blocking(PKmessage::Error(e.to_string())) 68 | .expect("Couldn't send data to channel"); 69 | sender.close(); 70 | return; 71 | } 72 | } 73 | 74 | let vecc = result.package_array(); 75 | if vecc.len() == 0 { 76 | debug!("get updates success: 0 packages"); 77 | sender 78 | .send_blocking(PKmessage::PackageListNew(vec![])) 79 | .expect("Couldn't send data to channel"); 80 | sender.close(); 81 | return; 82 | } 83 | 84 | let mut name_vec: Vec = vec![]; 85 | for pkg in vecc { 86 | name_vec.push(PackageInfo { 87 | name: pkg.name(), 88 | version_new: pkg.version(), 89 | version_current: "".to_string(), 90 | }); 91 | } 92 | debug!("get updates success"); 93 | sender 94 | .send_blocking(PKmessage::PackageListNew(name_vec)) 95 | .expect("Couldn't send data to channel"); 96 | } 97 | 98 | // Send installed packages list 99 | { 100 | let closure = move |progress: &ProgressPk, progress_type: c_int| { 101 | if progress_type == PK_PROGRESS_TYPE_PERCENTAGE { 102 | sender2 103 | .send_blocking(PKmessage::Progress((progress.percentage(), None))) 104 | .expect("Couldn't send data to channel"); 105 | } 106 | }; 107 | 108 | let result: ResultsPk; 109 | match client.get_packages(Some(Box::new(closure)), None) { 110 | Ok(ret) => result = ret, 111 | Err(e) => { 112 | sender 113 | .send_blocking(PKmessage::Error(e.to_string())) 114 | .expect("Couldn't send data to channel"); 115 | sender.close(); 116 | return; 117 | } 118 | } 119 | 120 | let vecc = result.package_array(); 121 | if vecc.len() == 0 { 122 | return; 123 | } 124 | let mut name_vec: Vec = vec![]; 125 | for pkg in vecc { 126 | name_vec.push(PackageInfo { 127 | name: pkg.name(), 128 | version_new: "".to_string(), 129 | version_current: pkg.version(), 130 | }); 131 | } 132 | debug!("get installed success"); 133 | sender 134 | .send_blocking(PKmessage::PackageListInstalled(name_vec)) 135 | .expect("Couldn't send data to channel"); 136 | sender.close(); 137 | } 138 | } 139 | 140 | pub fn download_updates(sender: async_channel::Sender) { 141 | debug!("download updates start"); 142 | let client = ClientPk::new(); 143 | let sender1 = sender.clone(); 144 | let closure = move |progress: &ProgressPk, progress_type: c_int| { 145 | if progress_type == PK_PROGRESS_TYPE_PERCENTAGE 146 | && progress.status() == PK_STATUS_ENUM_DOWNLOAD 147 | { 148 | sender1 149 | .send_blocking(PKmessage::Progress(( 150 | progress.percentage(), 151 | Some(progress.get_item_package()), 152 | ))) 153 | .expect("Couldn't send data to channel"); 154 | } 155 | }; 156 | 157 | let result: ResultsPk; 158 | match client.get_updates(None, None) { 159 | Ok(ret) => result = ret, 160 | Err(e) => { 161 | sender 162 | .send_blocking(PKmessage::Error(e.to_string())) 163 | .expect("Couldn't send data to channel"); 164 | sender.close(); 165 | return; 166 | } 167 | } 168 | 169 | let ids: *mut *mut c_char; 170 | match result.package_ids() { 171 | Some(ret) => ids = ret, 172 | None => { 173 | sender 174 | .send_blocking(PKmessage::Error("Update fail".to_string())) 175 | .expect("Couldn't send data to channel"); 176 | sender.close(); 177 | return; 178 | } 179 | } 180 | 181 | client.set_cache_age(60 * 60 * 24); 182 | match client.update_packages(ids, Some(Box::new(closure)), true) { 183 | Ok(_) => { 184 | debug!("download success"); 185 | sender 186 | .send_blocking(PKmessage::DownloadFinish) 187 | .expect("Couldn't send data to channel"); 188 | sender.close(); 189 | } 190 | Err(e) => { 191 | sender 192 | .send_blocking(PKmessage::Error(e.to_string())) 193 | .expect("Couldn't send data to channel"); 194 | sender.close(); 195 | return; 196 | } 197 | } 198 | } 199 | 200 | pub fn updates(sender: async_channel::Sender) { 201 | debug!("updates start"); 202 | let client = ClientPk::new(); 203 | let sender1 = sender.clone(); 204 | let closure = move |progress: &ProgressPk, progress_type: c_int| { 205 | if progress_type == PK_PROGRESS_TYPE_PERCENTAGE 206 | && progress.status() == PK_STATUS_ENUM_INSTALL 207 | { 208 | sender1 209 | .send_blocking(PKmessage::Progress(( 210 | progress.percentage(), 211 | Some(progress.get_item_package()), 212 | ))) 213 | .expect("Couldn't send data to channel"); 214 | } 215 | }; 216 | 217 | let result: ResultsPk; 218 | match client.get_updates(None, None) { 219 | Ok(ret) => result = ret, 220 | Err(e) => { 221 | sender 222 | .send_blocking(PKmessage::Error(e.to_string())) 223 | .expect("Couldn't send data to channel"); 224 | sender.close(); 225 | return; 226 | } 227 | } 228 | 229 | let ids: *mut *mut c_char; 230 | match result.package_ids() { 231 | Some(ret) => ids = ret, 232 | None => { 233 | sender 234 | .send_blocking(PKmessage::Error("Update fail".to_string())) 235 | .expect("Couldn't send data to channel"); 236 | sender.close(); 237 | return; 238 | } 239 | } 240 | 241 | match client.update_packages(ids, Some(Box::new(closure)), false) { 242 | Ok(_) => { 243 | debug!("update success"); 244 | sender 245 | .send_blocking(PKmessage::UpdateFinish) 246 | .expect("Couldn't send data to channel"); 247 | } 248 | Err(e) => { 249 | sender 250 | .send_blocking(PKmessage::Error(e.to_string())) 251 | .expect("Couldn't send data to channel"); 252 | sender.close(); 253 | return; 254 | } 255 | } 256 | } 257 | 258 | /* 259 | pub fn search_names(sender: glib::Sender, text: glib::GString) { 260 | debug!("search start"); 261 | let client = ClientPk::new(); 262 | let sender1 = sender.clone(); 263 | { 264 | let closure = move |progress: &ProgressPk, progress_type: c_int| { 265 | if progress_type == PK_PROGRESS_TYPE_PERCENTAGE 266 | && progress.status() == PK_STATUS_ENUM_REFRESH_CACHE 267 | { 268 | sender1 269 | .send(PKmessage::Progress((progress.percentage(), None))) 270 | .expect("Couldn't send data to channel"); 271 | } 272 | }; 273 | 274 | let names = [text.as_str()]; 275 | let result: ResultsPk; 276 | match client.search_names(&names, Some(Box::new(closure))) { 277 | Ok(ret) => result = ret, 278 | Err(e) => { 279 | sender 280 | .send(PKmessage::Error(e.to_string())) 281 | .expect("Couldn't send data to channel"); 282 | return; 283 | } 284 | } 285 | let vecc = result.package_array(); 286 | if vecc.len() == 0 { 287 | debug!("get search success: 0 packages"); 288 | sender 289 | .send(PKmessage::SearchListNew(vec![])) 290 | .expect("Couldn't send data to channel"); 291 | return; 292 | } 293 | let mut name_vec: Vec = vec![]; 294 | for pkg in vecc { 295 | name_vec.push(SearchInfo { 296 | name: pkg.name(), 297 | id: pkg.id(), 298 | summary: pkg.summary(), 299 | info: pkg.info(), 300 | }); 301 | } 302 | debug!("get search success"); 303 | sender 304 | .send(PKmessage::SearchListNew(name_vec)) 305 | .expect("Couldn't send data to channel"); 306 | } 307 | } 308 | */ 309 | 310 | pub fn install_packages(sender: async_channel::Sender, id: String) { 311 | debug!("install start"); 312 | let client = ClientPk::new(); 313 | let sender1 = sender.clone(); 314 | let closure = move |progress: &ProgressPk, progress_type: c_int| { 315 | if progress_type == PK_PROGRESS_TYPE_PERCENTAGE 316 | && (progress.status() == PK_STATUS_ENUM_INSTALL 317 | || progress.status() == PK_STATUS_ENUM_DOWNLOAD 318 | || progress.status() == PK_STATUS_ENUM_REFRESH_CACHE) 319 | { 320 | sender1 321 | .send_blocking(PKmessage::Progress((progress.percentage(), None))) 322 | .expect("Couldn't send data to channel"); 323 | } 324 | }; 325 | 326 | match client.install_packages(&[id.as_str()], Some(Box::new(closure))) { 327 | Ok(_) => { 328 | debug!("install success"); 329 | sender 330 | .send_blocking(PKmessage::InstallFinish) 331 | .expect("Couldn't send data to channel"); 332 | } 333 | Err(e) => { 334 | sender 335 | .send_blocking(PKmessage::Error(e.to_string())) 336 | .expect("Couldn't send data to channel"); 337 | sender.close(); 338 | return; 339 | } 340 | } 341 | } 342 | 343 | pub fn remove_packages(sender: async_channel::Sender, id: String) { 344 | debug!("remove start"); 345 | let client = ClientPk::new(); 346 | let sender1 = sender.clone(); 347 | let closure = move |progress: &ProgressPk, progress_type: c_int| { 348 | if progress_type == PK_PROGRESS_TYPE_PERCENTAGE 349 | && progress.status() == PK_STATUS_ENUM_REMOVE 350 | { 351 | sender1 352 | .send_blocking(PKmessage::Progress((progress.percentage(), None))) 353 | .expect("Couldn't send data to channel"); 354 | } 355 | }; 356 | 357 | match client.remove_packages(&[id.as_str()], Some(Box::new(closure))) { 358 | Ok(_) => { 359 | debug!("remove success"); 360 | sender 361 | .send_blocking(PKmessage::RemoveFinish) 362 | .expect("Couldn't send data to channel"); 363 | } 364 | Err(e) => { 365 | sender 366 | .send_blocking(PKmessage::Error(e.to_string())) 367 | .expect("Couldn't send data to channel"); 368 | sender.close(); 369 | return; 370 | } 371 | } 372 | } 373 | 374 | pub fn offline_update_trigger() -> Result { 375 | unsafe { 376 | let mut error = ptr::null_mut(); 377 | let ret = pk_offline_trigger(PK_OFFLINE_ACTION_REBOOT, ptr::null_mut(), &mut error); 378 | if error.is_null() { 379 | Ok(from_glib(ret)) 380 | } else { 381 | Err("Offline update trigger failed".to_string()) 382 | } 383 | } 384 | } 385 | 386 | pub fn offline_update_prepared() -> bool { 387 | unsafe { 388 | let mut error = ptr::null_mut(); 389 | let ret = pk_offline_get_prepared_ids(&mut error); 390 | 391 | if error.is_null() { 392 | let ids: *mut *mut c_char = ret; 393 | let v: Vec = FromGlibPtrContainer::from_glib_none(ids); 394 | if v.len() > 0 { 395 | return true; 396 | } 397 | return false; 398 | } else { 399 | return false; 400 | } 401 | } 402 | } 403 | 404 | pub fn do_reboot() { 405 | let desktop = match env::var("DESKTOP_SESSION") { 406 | Ok(d) => d, 407 | Err(_) => "none".to_string(), 408 | }; 409 | if desktop.contains("gnome") { 410 | do_reboot_gnome(); 411 | } else if desktop.contains("plasma") { 412 | do_reboot_kde(); 413 | } else { 414 | do_reboot_other(); 415 | } 416 | } 417 | 418 | fn do_reboot_gnome() { 419 | let conn = match Connection::new_session() { 420 | Ok(conn) => conn, 421 | Err(_) => return, 422 | }; 423 | let msg = Message::method( 424 | None, 425 | Some("org.gnome.SessionManager"), 426 | "/org/gnome/SessionManager", 427 | Some("org.gnome.SessionManager"), 428 | "Reboot", 429 | &(), 430 | ) 431 | .unwrap(); 432 | let _ret = match conn.send_message(msg) { 433 | Ok(ret) => ret, 434 | Err(_) => return, 435 | }; 436 | } 437 | 438 | fn do_reboot_other() { 439 | let conn = match Connection::new_system() { 440 | Ok(conn) => conn, 441 | Err(_) => return, 442 | }; 443 | let msg = Message::method( 444 | None, 445 | Some("org.freedesktop.login1"), 446 | "/org/freedesktop/login1", 447 | Some("org.freedesktop.login1.Manager"), 448 | "Reboot", 449 | &true, 450 | ) 451 | .unwrap(); 452 | let _ret = match conn.send_message(msg) { 453 | Ok(ret) => ret, 454 | Err(_) => return, 455 | }; 456 | } 457 | 458 | fn do_reboot_kde() { 459 | //qdbus org.kde.ksmserver /KSMServer org.kde.KSMServerInterface.logout -1 1 -1 460 | let _status = Command::new("qdbus-qt5") 461 | .arg("org.kde.ksmserver") 462 | .arg("/KSMServer") 463 | .arg("org.kde.KSMServerInterface.logout") 464 | .arg("-1") 465 | .arg("1") 466 | .arg("-1") 467 | .stdout(Stdio::piped()) 468 | .status() 469 | .expect("failed to execute rpm"); 470 | } 471 | -------------------------------------------------------------------------------- /zypp-gui/src/page_settings.rs: -------------------------------------------------------------------------------- 1 | use gtk::gio; 2 | use gtk::gio::prelude::*; 3 | use gtk::gio::File; 4 | use gtk::glib; 5 | use gtk::prelude::*; 6 | use log::debug; 7 | use std::collections::HashMap; 8 | use std::collections::HashSet; 9 | use std::thread; 10 | 11 | use crate::additional::AdditionalRepo; 12 | use crate::mirror::MirrorSettings; 13 | use crate::repo_row::RepoRow; 14 | use crate::zypper::{RepoInfo, Settings, Zypper}; 15 | 16 | #[derive(Clone)] 17 | pub struct PageSettings { 18 | pub widget: adw::NavigationSplitView, 19 | pub button_deck_back: gtk::Button, 20 | list: HashMap, 21 | list_box: gtk::Box, 22 | main_window: adw::ApplicationWindow, 23 | } 24 | 25 | impl PageSettings { 26 | pub fn new(main_builder: >k::Builder) -> Self { 27 | let builder = gtk::Builder::from_resource("/zypp/gui/ui/page_settings.ui"); 28 | let widget: adw::NavigationSplitView = builder.object("page_settings").unwrap(); 29 | let button_deck_back: gtk::Button = builder.object("button_deck_back").unwrap(); 30 | let list_box: gtk::Box = builder.object("repo_box").unwrap(); 31 | let main_window: adw::ApplicationWindow = main_builder.object("window").unwrap(); 32 | MirrorSettings::new(main_builder, &builder); 33 | AdditionalRepo::new(main_builder, &builder); 34 | 35 | let mut page_settings = Self { 36 | widget, 37 | button_deck_back, 38 | list: HashMap::new(), 39 | list_box, 40 | main_window, 41 | }; 42 | page_settings.button_connect(&builder); 43 | page_settings.build_repo_list(); 44 | page_settings.monitor_repo_dir(); 45 | 46 | page_settings 47 | } 48 | 49 | fn update_repo_list(&mut self) { 50 | let repo_list = match Zypper::get_repos() { 51 | Some(list) => list, 52 | None => vec![], 53 | }; 54 | 55 | //Add/Update repo row 56 | for info in repo_list.clone() { 57 | match self.find_in_list_box(info.clone()) { 58 | Some(_c) => {} 59 | None => { 60 | let list_box = self.list_box.clone(); 61 | let row = RepoRow::new(info.clone()); 62 | list_box.prepend(&row.row().to_owned()); 63 | self.list.insert(info.name.clone(), row.clone()); 64 | self.row_button_connect(&row, info.clone()); 65 | } 66 | }; 67 | } 68 | 69 | //Remove missing repo row 70 | let repo_names: HashSet = repo_list.iter().map(|repo| repo.name.clone()).collect(); 71 | let missing_repos: Vec = self 72 | .list 73 | .keys() 74 | .filter(|&name| !repo_names.contains(name)) 75 | .cloned() 76 | .collect(); 77 | 78 | for name in missing_repos { 79 | let list_box = self.list_box.clone(); 80 | list_box.remove(self.list.get(&name).expect("repo row").row()); 81 | self.list.remove(&name); 82 | } 83 | } 84 | 85 | fn find_in_list_box(&self, info: RepoInfo) -> Option<&RepoRow> { 86 | match self.list.get(&info.name) { 87 | Some(row) => { 88 | row.update(info); 89 | return Some(row); 90 | } 91 | None => return None, 92 | } 93 | } 94 | 95 | fn build_repo_list(&mut self) { 96 | let repo_list = match Zypper::get_repos() { 97 | Some(list) => list, 98 | None => vec![], 99 | }; 100 | let list_box = self.list_box.clone(); 101 | for info in repo_list { 102 | let row = RepoRow::new(info.clone()); 103 | list_box.prepend(&row.row().to_owned()); 104 | self.list.insert(info.name.clone(), row.clone()); 105 | self.row_button_connect(&row, info.clone()); 106 | } 107 | } 108 | 109 | fn row_button_connect(&self, row: &RepoRow, info: RepoInfo) { 110 | { 111 | let id = String::from(info.id.clone()); 112 | row.enable().connect_active_notify(move |switch| { 113 | Zypper::change_repo(id.clone(), Settings::Enable(switch.is_active())); 114 | }); 115 | } 116 | { 117 | let id = String::from(info.id.clone()); 118 | row.refresh().connect_active_notify(move |b| { 119 | Zypper::change_repo(id.clone(), Settings::Refresh(b.is_active())); 120 | }); 121 | } 122 | { 123 | let id = String::from(info.id.clone()); 124 | row.priority().connect_value_notify(move |b| { 125 | Zypper::change_repo(id.clone(), Settings::Priority(b.value() as i32)); 126 | }); 127 | } 128 | { 129 | let this = self.clone(); 130 | let id = String::from(info.id.clone()); 131 | row.delete().connect_clicked(move |_| { 132 | this.create_dialog(id.clone()); 133 | }); 134 | } 135 | } 136 | 137 | fn button_connect(&self, builder: >k::Builder) { 138 | { 139 | let stack: gtk::Stack = builder.object("setting_stack").unwrap(); 140 | let this: gtk::Stack = builder.object("setting_stack").unwrap(); 141 | let repo_add_button: gtk::Button = builder.object("repo_add").unwrap(); 142 | let top_right_box: adw::HeaderBar = builder.object("top_right_box").unwrap(); 143 | stack.connect_local("notify::visible-child", true, move |_| { 144 | if this.visible_child_name().unwrap() == "Repo List" { 145 | if repo_add_button.parent() == None { 146 | top_right_box.pack_start(&repo_add_button); 147 | } 148 | } else { 149 | if repo_add_button.parent() != None { 150 | top_right_box.remove(&repo_add_button); 151 | } 152 | } 153 | None 154 | }); 155 | } 156 | 157 | { 158 | let button: gtk::Button = builder.object("repo_add").unwrap(); 159 | let this = self.clone(); 160 | button.connect_clicked(move |_| { 161 | this.create_add_repo_window(); 162 | }); 163 | } 164 | } 165 | 166 | fn create_add_repo_window(&self) { 167 | let builder = gtk::Builder::from_resource("/zypp/gui/ui/repo_add.ui"); 168 | let window: gtk::Window = builder.object("repo_add_window").unwrap(); 169 | window.set_modal(true); 170 | window.set_transient_for(Some(&self.main_window)); 171 | 172 | let cancel: gtk::Button = builder.object("add_cancel").unwrap(); 173 | let w = window.clone(); 174 | cancel.connect_clicked(move |_| { 175 | w.close(); 176 | }); 177 | 178 | let name: gtk::Entry = builder.object("repo_name").unwrap(); 179 | let url: gtk::Entry = builder.object("repo_url").unwrap(); 180 | let ok: gtk::Button = builder.object("add_ok").unwrap(); 181 | let w = window.clone(); 182 | ok.connect_clicked(move |_| { 183 | let name = name.text(); 184 | let url = url.text(); 185 | if name.len() == 0 || url.len() == 0 { 186 | return; 187 | } 188 | Zypper::add_repo(name.to_string(), url.to_string()); 189 | w.close(); 190 | }); 191 | 192 | window.show(); 193 | } 194 | 195 | fn create_dialog(&self, id: String) { 196 | let dialog = gtk::MessageDialog::new( 197 | Some(&self.main_window), 198 | gtk::DialogFlags::DESTROY_WITH_PARENT | gtk::DialogFlags::MODAL, 199 | gtk::MessageType::Error, 200 | gtk::ButtonsType::OkCancel, 201 | "Do you want to delete this repo?", 202 | ); 203 | 204 | dialog.run_async(move |obj, answer| { 205 | obj.close(); 206 | if answer == gtk::ResponseType::Ok { 207 | Zypper::delete_repo(id.to_string()); 208 | } 209 | }); 210 | } 211 | 212 | fn monitor_repo_dir(&self) { 213 | let (tx, rx) = async_channel::bounded(1); 214 | 215 | thread::spawn(move || { 216 | let mainloop = glib::MainLoop::new(None, true); 217 | let path = std::path::Path::new("/etc/zypp/repos.d"); 218 | let file = File::for_path(path); 219 | let monitor = file 220 | .monitor( 221 | gio::FileMonitorFlags::SEND_MOVED, 222 | Some(&gio::Cancellable::new()), 223 | ) 224 | .unwrap(); 225 | monitor.connect_changed(move |_, _, _, event| { 226 | debug!("/etc/zypp/repos.d folder is changed: {:?}", event); 227 | if event == gio::FileMonitorEvent::Created 228 | || event == gio::FileMonitorEvent::Deleted 229 | || event == gio::FileMonitorEvent::ChangesDoneHint 230 | { 231 | let value = tx.clone(); 232 | glib::spawn_future_local(async move { 233 | value 234 | .send("repo changed") 235 | .await 236 | .expect("Couldn't send data to channel"); 237 | }); 238 | } 239 | }); 240 | mainloop.run(); 241 | }); 242 | 243 | let mut this = self.clone(); 244 | glib::spawn_future_local(async move { 245 | while let Ok(_) = rx.recv().await { 246 | this.update_repo_list(); 247 | } 248 | }); 249 | } 250 | } 251 | -------------------------------------------------------------------------------- /zypp-gui/src/repo_row.rs: -------------------------------------------------------------------------------- 1 | use crate::zypper::RepoInfo; 2 | use adw::prelude::*; 3 | 4 | #[derive(Clone)] 5 | pub struct RepoRow { 6 | row: adw::PreferencesGroup, 7 | enable: adw::SwitchRow, 8 | refresh: adw::SwitchRow, 9 | priority: adw::SpinRow, 10 | delete: gtk::Button, 11 | url: adw::ActionRow, 12 | } 13 | 14 | impl RepoRow { 15 | pub fn new(info: RepoInfo) -> Self { 16 | let builder = gtk::Builder::from_resource("/zypp/gui/ui/repo_row.ui"); 17 | let row: adw::PreferencesGroup = builder.object("repo_row").unwrap(); 18 | //let name: gtk::Label = builder.object("name").unwrap(); 19 | let enable: adw::SwitchRow = builder.object("enable_switch").unwrap(); 20 | let refresh: adw::SwitchRow = builder.object("refresh_button").unwrap(); 21 | let priority: adw::SpinRow = builder.object("priority_button").unwrap(); 22 | let url: adw::ActionRow = builder.object("url").unwrap(); 23 | let delete: gtk::Button = builder.object("delete_button").unwrap(); 24 | 25 | row.set_title(info.name.as_str()); 26 | enable.set_active(info.enable); 27 | refresh.set_active(info.refresh); 28 | priority.set_value(info.priority as f64); 29 | url.set_title(info.url.as_str()); 30 | 31 | Self { 32 | row: row, 33 | enable: enable, 34 | refresh: refresh, 35 | priority: priority, 36 | delete: delete, 37 | url: url, 38 | } 39 | } 40 | 41 | pub fn row(&self) -> &adw::PreferencesGroup { 42 | &self.row 43 | } 44 | 45 | pub fn enable(&self) -> &adw::SwitchRow { 46 | &self.enable 47 | } 48 | 49 | pub fn refresh(&self) -> &adw::SwitchRow { 50 | &self.refresh 51 | } 52 | 53 | pub fn priority(&self) -> &adw::SpinRow { 54 | &self.priority 55 | } 56 | 57 | pub fn delete(&self) -> >k::Button { 58 | &self.delete 59 | } 60 | 61 | pub fn update(&self, info: RepoInfo) { 62 | self.row.set_title(info.name.as_str()); 63 | self.enable.set_active(info.enable); 64 | self.refresh.set_active(info.refresh); 65 | self.priority.set_value(info.priority as f64); 66 | self.url.set_title(info.url.as_str()); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /zypp-gui/src/search.rs: -------------------------------------------------------------------------------- 1 | use gtk::glib; 2 | use gtk::prelude::*; 3 | use log::debug; 4 | use std::thread; 5 | 6 | use crate::notification; 7 | use crate::package_meta::PackageMeta; 8 | use crate::packagekit; 9 | use crate::packagekit::PackagekitState; 10 | use crate::search_row::SearchRow; 11 | use crate::util::{PKmessage, SearchInfo}; 12 | 13 | #[derive(Clone)] 14 | pub struct SearchPackage { 15 | search_entry: gtk::Entry, 16 | list_box: gtk::ListBox, 17 | stack_box: gtk::Stack, 18 | pub search_box: gtk::ScrolledWindow, 19 | progress_bar: gtk::ProgressBar, 20 | progress: gtk::Box, 21 | progress_label: gtk::Label, 22 | notification: notification::Notification, 23 | packagekit_state: PackagekitState, 24 | package_meta: PackageMeta, 25 | } 26 | 27 | impl SearchPackage { 28 | pub fn new( 29 | builder: >k::Builder, 30 | progress_bar: gtk::ProgressBar, 31 | progress: gtk::Box, 32 | progress_label: gtk::Label, 33 | notification: notification::Notification, 34 | packagekit_state: PackagekitState, 35 | ) -> Self { 36 | let search_entry: gtk::Entry = builder.object("search_entry").unwrap(); 37 | let list_box: gtk::ListBox = builder.object("search_list_box").unwrap(); 38 | let stack_box: gtk::Stack = builder.object("stack_box").unwrap(); 39 | let search_box: gtk::ScrolledWindow = builder.object("search_box").unwrap(); 40 | 41 | let package_meta = PackageMeta::new(); 42 | 43 | let search = Self { 44 | search_entry, 45 | list_box, 46 | stack_box, 47 | search_box, 48 | progress_bar, 49 | progress, 50 | progress_label, 51 | notification, 52 | packagekit_state, 53 | package_meta: package_meta, 54 | }; 55 | 56 | search.connect_signal(); 57 | search 58 | } 59 | 60 | fn connect_signal(&self) { 61 | let entry: gtk::Entry = self.search_entry.clone(); 62 | let this = self.clone(); 63 | entry.connect_activate(move |entry| { 64 | let text = entry.text(); 65 | if this.packagekit_state.busy() { 66 | return; 67 | } 68 | //this.packagekit_state.set_busy(true); 69 | //this.search_names(text); 70 | this.search_meta(text); 71 | }); 72 | } 73 | 74 | fn row_connect_signal(&self, button: >k::Button, info: SearchInfo) { 75 | let installed = info.info == "installed"; 76 | let id = info.id; 77 | let this = self.clone(); 78 | button.connect_clicked(move |_| { 79 | if this.packagekit_state.busy() { 80 | return; 81 | } 82 | this.packagekit_state.set_busy(true); 83 | if installed { 84 | this.remove_packages(id.clone()); 85 | } else { 86 | this.install_packages(id.clone()); 87 | } 88 | }); 89 | } 90 | 91 | pub fn update_package_meta(&self) { 92 | self.package_meta.update_data(); 93 | } 94 | 95 | fn update_list(&self, list: Vec) { 96 | self.clear_list(); 97 | let list_box = &self.list_box; 98 | for info in list { 99 | let row = SearchRow::new(info.clone()); 100 | self.row_connect_signal(row.button(), info.clone()); 101 | row.set_title(info.name); 102 | let v: Vec<&str> = info.id.split(';').collect(); 103 | let subtitle = format!("{} {} {}\n{}", v[1], v[2], v[3], info.summary); 104 | row.set_subtitle(subtitle); 105 | list_box.append(&row.row().to_owned()); 106 | } 107 | } 108 | 109 | fn clear_list(&self) { 110 | let list_box = &self.list_box; 111 | let mut child = match list_box.first_child() { 112 | Some(child) => child, 113 | None => return, 114 | }; 115 | loop { 116 | let next_child = child.next_sibling(); 117 | list_box.remove(&child); 118 | match next_child { 119 | Some(c) => { 120 | child = c; 121 | } 122 | None => break, 123 | }; 124 | } 125 | } 126 | 127 | fn update_search_list(&self, list: Vec) { 128 | self.packagekit_state.set_busy(false); 129 | self.update_list(list); 130 | self.stack_box.set_visible_child(&self.search_box); 131 | } 132 | 133 | fn update_progress(&self, percentage: i32) { 134 | self.stack_box.set_visible_child(&self.progress); 135 | self.progress_bar.set_fraction(percentage as f64 / 100.0); 136 | } 137 | 138 | fn update_progress_text(&self, text: Option) { 139 | let s = if text.is_some() { 140 | text.unwrap() 141 | } else { 142 | String::new() 143 | }; 144 | let v: Vec<&str> = s.split(';').collect(); 145 | if v.len() < 2 { 146 | self.progress_label.set_text(String::from("").as_str()); 147 | return; 148 | } 149 | let fmt = format!("{} {}", v[0], v[1]); 150 | self.progress_label.set_markup(fmt.as_str()); 151 | } 152 | 153 | fn show_notification(&self, text: String) { 154 | self.notification.set_label(text); 155 | self.update_search_list(vec![]); 156 | } 157 | 158 | /* 159 | fn search_names(&self, text: glib::GString) { 160 | let (tx, rx) = glib::MainContext::channel(glib::Priority::default()); 161 | 162 | thread::spawn(move || { 163 | packagekit::search_names(tx, text); 164 | }); 165 | 166 | let this = self.clone(); 167 | self.update_progress(0); 168 | rx.attach(None, move |message| { 169 | match message { 170 | PKmessage::SearchListNew(list) => { 171 | debug!("SearchFinish len={}", list.len()); 172 | this.update_search_list(list); 173 | } 174 | PKmessage::Progress((percentage, id)) => { 175 | this.update_progress(percentage); 176 | this.update_progress_text(id); 177 | } 178 | PKmessage::Error(text) => { 179 | this.show_notification(text); 180 | } 181 | _ => {} 182 | } 183 | glib::ControlFlow::Continue 184 | }); 185 | } 186 | */ 187 | 188 | fn search_meta(&self, text: glib::GString) { 189 | let list = self.package_meta.search(text.to_string()); 190 | debug!("SearchFinish len={}", list.len()); 191 | self.update_search_list(list); 192 | } 193 | 194 | fn install_packages(&self, id: String) { 195 | let (tx, rx) = async_channel::bounded(1); 196 | 197 | thread::spawn(move || { 198 | packagekit::install_packages(tx, id); 199 | }); 200 | 201 | let this = self.clone(); 202 | this.update_progress(0); 203 | glib::spawn_future_local(async move { 204 | while let Ok(message) = rx.recv().await { 205 | match message { 206 | PKmessage::InstallFinish => { 207 | debug!("InstallFinish"); 208 | this.update_search_list(vec![]); 209 | } 210 | PKmessage::Progress((percentage, id)) => { 211 | this.update_progress(percentage); 212 | this.update_progress_text(id); 213 | } 214 | PKmessage::Error(text) => { 215 | this.show_notification(text); 216 | this.update_search_list(vec![]); 217 | } 218 | _ => {} 219 | } 220 | } 221 | }); 222 | } 223 | 224 | fn remove_packages(&self, id: String) { 225 | let (tx, rx) = async_channel::bounded(1); 226 | 227 | thread::spawn(move || { 228 | packagekit::remove_packages(tx, id); 229 | }); 230 | 231 | let this = self.clone(); 232 | this.update_progress(0); 233 | glib::spawn_future_local(async move { 234 | while let Ok(message) = rx.recv().await { 235 | match message { 236 | PKmessage::RemoveFinish => { 237 | debug!("RemoveFinish"); 238 | this.update_search_list(vec![]); 239 | } 240 | PKmessage::Progress((percentage, id)) => { 241 | this.update_progress(percentage); 242 | this.update_progress_text(id); 243 | } 244 | PKmessage::Error(text) => { 245 | this.show_notification(text); 246 | this.update_search_list(vec![]); 247 | } 248 | _ => {} 249 | } 250 | } 251 | }); 252 | } 253 | } 254 | -------------------------------------------------------------------------------- /zypp-gui/src/search_row.rs: -------------------------------------------------------------------------------- 1 | use crate::util::SearchInfo; 2 | use adw::prelude::*; 3 | use gettextrs::*; 4 | 5 | pub struct SearchRow { 6 | row: adw::ActionRow, 7 | button: gtk::Button, 8 | } 9 | 10 | impl SearchRow { 11 | pub fn new(info: SearchInfo) -> Self { 12 | let builder = gtk::Builder::from_resource("/zypp/gui/ui/search_row.ui"); 13 | let row: adw::ActionRow = builder.object("row").unwrap(); 14 | let button: gtk::Button = builder.object("operation_button").unwrap(); 15 | if info.info == "installed" { 16 | button.set_label(&gettext("Remove")); 17 | } else { 18 | button.set_label(&gettext("Install")); 19 | } 20 | 21 | Self { 22 | row: row, 23 | button: button, 24 | } 25 | } 26 | 27 | pub fn row(&self) -> &adw::ActionRow { 28 | &self.row 29 | } 30 | 31 | pub fn button(&self) -> >k::Button { 32 | &self.button 33 | } 34 | 35 | pub fn set_title(&self, name: String) { 36 | self.row.set_title(&name.to_string()); 37 | } 38 | 39 | pub fn set_subtitle(&self, subtitle: String) { 40 | self.row.set_subtitle(&subtitle.to_string()); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /zypp-gui/src/util.rs: -------------------------------------------------------------------------------- 1 | use gettextrs::*; 2 | use std::fmt; 3 | 4 | pub enum PKmessage { 5 | PackageListNew(Vec), 6 | PackageListInstalled(Vec), 7 | Progress((i32, Option)), 8 | DownloadFinish, 9 | UpdateFinish, 10 | InstallFinish, 11 | RemoveFinish, 12 | Error(String), 13 | } 14 | 15 | #[derive(Clone)] 16 | pub struct PackageInfo { 17 | pub name: String, 18 | pub version_current: String, 19 | pub version_new: String, 20 | } 21 | 22 | #[derive(Clone)] 23 | pub struct SearchInfo { 24 | pub name: String, 25 | pub id: String, 26 | pub summary: String, 27 | pub info: String, 28 | } 29 | 30 | #[allow(dead_code)] 31 | #[derive(Clone, Debug)] 32 | pub enum ButtonState { 33 | Refresh, 34 | Refreshing, 35 | Download, 36 | Downloading, 37 | Update, 38 | Updating, 39 | RestartUpdate, 40 | } 41 | 42 | impl fmt::Display for ButtonState { 43 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 44 | match self { 45 | Self::Refresh => write!(f, "{}", &gettext("Refresh")), 46 | Self::Refreshing => write!(f, "{}", &gettext("Refreshing")), 47 | Self::Download => write!(f, "{}", &gettext("Download")), 48 | Self::Downloading => write!(f, "{}", &gettext("Downloading")), 49 | Self::Update => write!(f, "{}", &gettext("Update")), 50 | Self::Updating => write!(f, "{}", &gettext("Updating")), 51 | Self::RestartUpdate => write!(f, "{}", &gettext("Restart&Update")), 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /zypp-gui/src/zypper.rs: -------------------------------------------------------------------------------- 1 | use log::debug; 2 | use std::process::{Command, Stdio}; 3 | 4 | #[derive(Clone)] 5 | pub enum Settings { 6 | Enable(bool), 7 | Refresh(bool), 8 | Priority(i32), 9 | } 10 | 11 | #[derive(Clone, Debug)] 12 | #[allow(dead_code)] 13 | pub struct RepoInfo { 14 | pub id: String, 15 | pub alias: String, 16 | pub name: String, 17 | pub enable: bool, 18 | pub cpg: bool, 19 | pub refresh: bool, 20 | pub priority: i32, 21 | pub url: String, 22 | } 23 | 24 | pub struct Zypper {} 25 | 26 | impl Zypper { 27 | fn to_repoinfo(line: &str) -> RepoInfo { 28 | let r: Vec<&str> = line.split("|").collect(); 29 | let id = r[0].trim().to_string(); 30 | let alias = r[1].trim().to_string(); 31 | let name = r[2].trim().to_string(); 32 | let enable = if r[3].trim().to_string().contains("Yes") { 33 | true 34 | } else { 35 | false 36 | }; 37 | let cpg = if r[4].trim().to_string().contains("Yes") { 38 | true 39 | } else { 40 | false 41 | }; 42 | let refresh = if r[5].trim().to_string().contains("Yes") { 43 | true 44 | } else { 45 | false 46 | }; 47 | let priority = r[7].trim().to_string().parse::().unwrap(); 48 | let url = r[9].trim().to_string(); 49 | 50 | RepoInfo { 51 | id: id, 52 | alias: alias, 53 | name: name, 54 | enable: enable, 55 | cpg: cpg, 56 | refresh: refresh, 57 | priority: priority, 58 | url: url, 59 | } 60 | } 61 | 62 | pub fn get_repos() -> Option> { 63 | let process = Command::new("zypper") 64 | .arg("lr") 65 | .arg("-d") 66 | .stdout(Stdio::piped()) 67 | .output() 68 | .expect("failed to execute rpm"); 69 | 70 | let s = String::from_utf8_lossy(&process.stdout).to_string(); 71 | let v: Vec<&str> = s.split("\n").collect(); 72 | if v.len() < 3 { 73 | return None; 74 | } 75 | let mut repos: Vec = vec![]; 76 | for i in 2..v.len() - 1 { 77 | repos.push(Self::to_repoinfo(v[i])); 78 | } 79 | return Some(repos); 80 | } 81 | 82 | pub fn change_repo(id: String, settings: Settings) -> bool { 83 | let mut args: Vec<&str> = vec![]; 84 | let mut _value = String::new(); 85 | match settings { 86 | Settings::Enable(s) => args.push(if s { "-e" } else { "-d" }), 87 | Settings::Refresh(s) => args.push(if s { "-f" } else { "-F" }), 88 | Settings::Priority(s) => { 89 | args.push("-p"); 90 | _value = s.to_string(); 91 | args.push(&_value); 92 | } 93 | } 94 | 95 | let child = Command::new("pkexec") 96 | .arg("mod-repo") 97 | .args(args) 98 | .arg(id) 99 | .spawn() 100 | .expect("failed to run pkexec"); 101 | 102 | let output = child.wait_with_output().expect("fail to wait pkexec"); 103 | if !output.status.success() { 104 | debug!("pkexec fail"); 105 | return false; 106 | } else { 107 | return true; 108 | } 109 | } 110 | 111 | pub fn add_repo(name: String, url: String) -> bool { 112 | let child = Command::new("pkexec") 113 | .arg("mod-repo") 114 | .arg("add") 115 | .arg("--name") 116 | .arg(name) 117 | .arg("--url") 118 | .arg(url) 119 | .spawn() 120 | .expect("failed to run pkexec"); 121 | 122 | let output = child.wait_with_output().expect("fail to wait pkexec"); 123 | if !output.status.success() { 124 | debug!("pkexec fail"); 125 | return false; 126 | } else { 127 | return true; 128 | } 129 | } 130 | 131 | pub fn delete_repo(id: String) -> bool { 132 | let child = Command::new("pkexec") 133 | .arg("mod-repo") 134 | .arg("delete") 135 | .arg("--id") 136 | .arg(id) 137 | .spawn() 138 | .expect("failed to run pkexec"); 139 | 140 | let output = child.wait_with_output().expect("fail to wait pkexec"); 141 | if !output.status.success() { 142 | debug!("pkexec fail"); 143 | return false; 144 | } else { 145 | return true; 146 | } 147 | } 148 | } 149 | 150 | #[test] 151 | fn get_repos() { 152 | Zypper::get_repos(); 153 | } 154 | --------------------------------------------------------------------------------