diff --git a/data/io.github.giantpinkrobots.varia.desktop.in b/data/io.github.giantpinkrobots.varia.desktop.in index 9611c19..0196148 100644 --- a/data/io.github.giantpinkrobots.varia.desktop.in +++ b/data/io.github.giantpinkrobots.varia.desktop.in @@ -1,12 +1,12 @@ [Desktop Entry] # Translators: Do NOT translate or localize the application name. Name=Varia -Comment=Download files quickly and efficiently +Comment=Download files and torrents quickly Exec=varia Icon=io.github.giantpinkrobots.varia Terminal=false Type=Application Categories=Network # Translators: These are search terms to find this application. Do NOT translate or localize the semicolons. The list MUST also end with a semicolon. -Keywords=varia;aria;download;manager; +Keywords=varia;aria;download;manager;torrent; StartupNotify=true diff --git a/data/io.github.giantpinkrobots.varia.metainfo.xml.in b/data/io.github.giantpinkrobots.varia.metainfo.xml.in index 88bb9b7..bd9cb12 100644 --- a/data/io.github.giantpinkrobots.varia.metainfo.xml.in +++ b/data/io.github.giantpinkrobots.varia.metainfo.xml.in @@ -1,7 +1,7 @@ Varia -Download files quickly and efficiently +Download files and torrents io.github.giantpinkrobots.varia FSFAP @@ -27,14 +27,20 @@ fr_FR zh_TW nb_NO +ja_JP + +#75A3DC +#242424 + +

-Varia is a download manager for all your download needs. It can download multiple files at once very quickly with aria2. +Varia is a download manager for all your download needs. It can download regular files and torrents, and do it very quickly.

-Varia utilizes GTK4 and Libadwaita to provide a easy to use interface that integrates well with the GNOME desktop. +Using Varia is very easy and straightforward, and with its aria2 backend it can potentially increase the speed of your downloads. It can integrate with Firefox or Chrome/ium through a browser extension, configured to your liking, and even support a remote aria2 instance on another computer.

@@ -53,12 +59,11 @@ Varia utilizes GTK4 and Libadwaita to provide a easy to use interface that integ - + -

- Support for Firefox and Chromium extension.

-

- Initial torrenting support.

-

- Remote mode that allows connection to a remote aria2 instance.

-

- Background mode that allows the window to be hidden while still downloading.

+

- Shutdown after completion option added.

+

- Update to GNOME 46 and Libadwaita 1.5.

+

- Japanese language support.

- Bug fixes and adjustments.

diff --git a/io.github.giantpinkrobots.varia.json b/io.github.giantpinkrobots.varia.json index 41400a2..fa388b6 100644 --- a/io.github.giantpinkrobots.varia.json +++ b/io.github.giantpinkrobots.varia.json @@ -1,17 +1,18 @@ { "app-id" : "io.github.giantpinkrobots.varia", "runtime" : "org.gnome.Platform", - "runtime-version" : "45", + "runtime-version" : "46", "sdk" : "org.gnome.Sdk", "command" : "varia", - "//": "Justifications for the permissions: This program utilizes aria2c, and aria2c requires the networking permission and the xdg-download directory in order to download files.", + "//": "Justifications for the permissions: This program utilizes aria2c, and aria2c requires the networking permission and the xdg-download directory in order to download files. It also has a 'shut down once all downloads are completed' feature that requires access to org.freedesktop.login1.", "finish-args" : [ "--share=network", "--share=ipc", "--socket=fallback-x11", "--device=dri", "--socket=wayland", - "--filesystem=xdg-download" + "--filesystem=xdg-download", + "--system-talk-name=org.freedesktop.login1" ], "cleanup" : [ "/include", diff --git a/meson.build b/meson.build index 012b278..f81c75d 100644 --- a/meson.build +++ b/meson.build @@ -1,5 +1,5 @@ project('varia', - version: 'v2024.2.29-2', + version: 'v2024.3.20', meson_version: '>= 0.62.0', default_options: [ 'warning_level=2', 'werror=false', ], ) diff --git a/po/Varia.pot b/po/Varia.pot index cf2e1b0..88fe8ca 100644 --- a/po/Varia.pot +++ b/po/Varia.pot @@ -218,6 +218,21 @@ msgstr "" msgid "Browser Extension" msgstr "" +msgid "Shutdown on Completion" +msgstr "" + +msgid "Varia is about to shut down your computer." +msgstr "" + +msgid "Press Cancel to cancel and disable." +msgstr "" + +msgid "Cancel" +msgstr "" + +msgid "Warning" +msgstr "" + #: src/gtk/help-overlay.ui:11 msgctxt "shortcut window" msgid "General" diff --git a/po/tr.po b/po/tr.po index 1eea33d..96f7359 100644 --- a/po/tr.po +++ b/po/tr.po @@ -10,8 +10,8 @@ msgstr "" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2023-11-30 03:17+0300\n" "PO-Revision-Date: 2023-11-30 03:18+0300\n" -"Last-Translator: Sabri Ünal \n" -"Language-Team: Turkish \n" +"Last-Translator: Giant Pink Robots! \n" +"Language-Team: \n" "Language: tr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -222,6 +222,21 @@ msgstr "İndirmeler arka planda devam ediyor." msgid "Browser Extension" msgstr "Tarayıcı Uzantısı" +msgid "Shutdown on Completion" +msgstr "İndirmeler Bittiğinde Bilgisayarı Kapat" + +msgid "Varia is about to shut down your computer." +msgstr "Varia birazdan bilgisayarınızı kapatacak." + +msgid "Press Cancel to cancel and disable." +msgstr "İptal edip devre dışı bırakmak için Vazgeç'e basın." + +msgid "Cancel" +msgstr "Vazgeç" + +msgid "Warning" +msgstr "Uyarı" + #: src/gtk/help-overlay.ui:11 msgctxt "shortcut window" msgid "General" diff --git a/src/download/actionrow.py b/src/download/actionrow.py index 06af5e6..c2f0d95 100644 --- a/src/download/actionrow.py +++ b/src/download/actionrow.py @@ -49,6 +49,7 @@ def create_actionrow(self, filename): pause_button = Gtk.Button.new_from_icon_name("media-playback-pause-symbolic") pause_button.set_valign(Gtk.Align.CENTER) + pause_button.get_style_context().add_class("circular") pause_button.connect("clicked", on_pause_clicked, self, pause_button, download_item) self.pause_buttons.append(pause_button) @@ -56,6 +57,7 @@ def create_actionrow(self, filename): stop_button = Gtk.Button.new_from_icon_name("process-stop-symbolic") stop_button.set_valign(Gtk.Align.CENTER) + stop_button.get_style_context().add_class("circular") stop_button.connect("clicked", on_stop_clicked, self, download_item) button_box.append(stop_button) @@ -70,7 +72,7 @@ def create_actionrow(self, filename): box_2.append(progress_bar) self.download_list.append(download_item) - download_item.index = len(self.downloads)-1 + download_item.index = len(self.downloads) return [progress_bar, speed_label, self.pause_buttons[len(self.pause_buttons)-1], download_item, filename_label] @@ -94,10 +96,9 @@ def on_pause_clicked(button, self, pause_button, download_item): all_paused = True - for download_thread in self.downloads: - if (download_thread.download): - if (download_thread.download.is_paused) == False: - all_paused = False + for download_thread in self.downloads.copy(): + if (download_thread.download) and (download_thread.is_alive()) and (download_thread.download.is_paused == False): + all_paused = False if (all_paused == True): self.all_paused = True @@ -107,9 +108,9 @@ def on_pause_clicked(button, self, pause_button, download_item): def on_stop_clicked(button, self, download_item): index = download_item.index - download_thread = self.downloads[index+1] + download_thread = self.downloads[index] deletefiles = True - if ((download_thread.download.is_torrent) and (download_thread.download.seeder)): + if (download_thread.download) and ((download_thread.download.is_torrent) and (download_thread.download.seeder)): deletefiles = False try: download_thread.stop(deletefiles) diff --git a/src/download/listen.py b/src/download/listen.py index b34f03d..e91ecc0 100644 --- a/src/download/listen.py +++ b/src/download/listen.py @@ -2,31 +2,49 @@ import requests import json import gi -from gi.repository import GLib +gi.require_version('Gtk', '4.0') +gi.require_version('Adw', '1') +from gi.repository import Gtk, Adw, GLib, Gio from download.actionrow import create_actionrow from download.thread import DownloadThread import threading +import string +import random +import textwrap + +def listen_to_aria2(self, variaapp): + if not (self.terminating) and not (self.shutdown_dialog_raised): + currently_downloading = False -def listen_to_aria2(self): - if not self.terminating: for frontend_download_item in self.downloads.copy(): - if ( (frontend_download_item.download) and ( ((frontend_download_item.download.is_metadata) or (frontend_download_item.download.name.endswith(".torrent"))) and (frontend_download_item.download.is_complete) ) ): - frontend_download_item.cancelled = True - frontend_download_item.stop(True) - self.download_list.remove(frontend_download_item.actionrow) - self.downloads.remove(frontend_download_item) + if frontend_download_item.download: + if (frontend_download_item.is_alive()): + currently_downloading = True + if ( ((frontend_download_item.download.is_metadata) or (frontend_download_item.download.name.endswith(".torrent"))) and (frontend_download_item.download.is_complete) ): + frontend_download_item.cancelled = True + frontend_download_item.stop(True) + self.download_list.remove(frontend_download_item.actionrow) + self.downloads.remove(frontend_download_item) try: - downloads_in_frontend = set(download_item.download.info_hash for download_item in self.downloads.copy()) + downloads_in_frontend = set(download_item.download.gid for download_item in self.downloads.copy()) for download_item_to_be_added in self.api.get_downloads(): - if ((download_item_to_be_added.info_hash not in downloads_in_frontend) and (download_item_to_be_added.is_metadata == False) and (download_item_to_be_added.is_complete == False)): + if ((download_item_to_be_added.gid not in downloads_in_frontend) and (download_item_to_be_added.is_metadata == False) and (download_item_to_be_added.is_complete == False)): if not download_item_to_be_added.is_torrent: print('Download added directly to aria2c, adding it to the UI: ' + download_item_to_be_added.files[0].uris[0]["uri"]) add_download_to_ui(self, download_item_to_be_added) except: pass - GLib.timeout_add(2000, listen_to_aria2, self) + if currently_downloading == True: + self.shutdown_action.set_enabled(True) + else: + self.shutdown_action.set_enabled(False) + if (self.shutdown_dialog_raised == False) and (self.shutdown_mode == True): + self.shutdown_dialog_raised = True + raise_shutdown_dialog(self, variaapp) + + GLib.timeout_add(2000, listen_to_aria2, self, variaapp) def add_download_to_ui(self, download_item_to_be_added): if download_item_to_be_added.is_torrent: @@ -39,3 +57,39 @@ def add_download_to_ui(self, download_item_to_be_added): self.downloads.append(download_thread) download_thread.start() download_thread.pause_button.show() + +def raise_shutdown_dialog(variamain, variaapp): + while (True): + shutdown_id = ''.join(random.choices(string.ascii_lowercase + string.digits, k=10)) + if (shutdown_id != variamain.shutdown_id): + variamain.shutdown_id = shutdown_id + break + + notification = Gio.Notification.new(_("Warning")) + notification.set_body(_("Varia is about to shut down your computer.")) + variaapp.send_notification(None, notification) + + dialog = Adw.AlertDialog() + dialog.set_body(textwrap.fill(_("Varia is about to shut down your computer.") + " " + _("Press Cancel to cancel and disable."), 50)) + dialog.add_response("cancel", _("Cancel")) + dialog.set_default_response("cancel") + dialog.set_close_response("cancel") + dialog.connect("response", shutdown_dialog_cancel_pressed, variamain, variaapp) + dialog.present(variamain) + + GLib.timeout_add(30000, initiate_shutdown, variamain, shutdown_id) + +def shutdown_dialog_cancel_pressed(dialog, response_id, variamain, variaapp): + variamain.shutdown_dialog_raised = False + variamain.shutdown_mode = False + variamain.sidebar_remote_mode_label.set_text("") + GLib.timeout_add(2000, listen_to_aria2, variamain, variaapp) + +def initiate_shutdown(variamain, shutdown_id): + if (variamain.shutdown_dialog_raised == True) and (shutdown_id == variamain.shutdown_id): + bus = Gio.bus_get_sync(Gio.BusType.SYSTEM, None) + proxy = Gio.DBusProxy.new_sync(bus, Gio.DBusProxyFlags.NONE, None, + 'org.freedesktop.login1', '/org/freedesktop/login1', + 'org.freedesktop.login1.Manager', None) + proxy.call_sync('PowerOff', GLib.Variant('(b)', (True,)), Gio.DBusCallFlags.NONE, -1, None) + exit() diff --git a/src/initiate.py b/src/initiate.py index 32d62f1..f7f6d9b 100644 --- a/src/initiate.py +++ b/src/initiate.py @@ -64,7 +64,6 @@ def initiate(self): self.set_default_size(800, 600) self.set_size_request(650, 450) - self.set_titlebar(Gtk.Box()) self.total_download_speed = "" self.terminating = False @@ -73,11 +72,15 @@ def initiate(self): Gtk.Settings.get_default().set_property("gtk-icon-theme-name", "Adwaita") self.overlay_split_view = Adw.OverlaySplitView.new() - self.set_child(child=self.overlay_split_view) + self.set_content(self.overlay_split_view) self.downloads = [] self.pause_buttons = [] self.all_paused = False + self.shutdown_mode = False + self.shutdown_dialog_raised = False + self.shutdown_id = "" + def on_dialog_dismiss(dialog, response_id): dialog.destroy() diff --git a/src/variamain.py b/src/variamain.py index bb0bab3..8101287 100644 --- a/src/variamain.py +++ b/src/variamain.py @@ -1,4 +1,4 @@ -variaVersion = "v2024.2.29-2" +variaVersion = "v2024.3.20" import gi import sys @@ -22,11 +22,11 @@ from initiate import initiate from download.listen import listen_to_aria2 -class MainWindow(Gtk.Window): +class MainWindow(Adw.ApplicationWindow): def __init__(self, variaapp, appdir, appconf, aria2c_subprocess, *args, **kwargs): super().__init__(*args, **kwargs) self.set_hide_on_close(True) - self.connect('close-request', self.exitProgram, variaapp, False, True) + self.connect('close-request', self.exitProgram, variaapp, False) self.appdir = appdir self.appconf = appconf @@ -65,7 +65,7 @@ def __init__(self, variaapp, appdir, appconf, aria2c_subprocess, *args, **kwargs set_aria2c_download_simultaneous_amount(self) # Listen to aria2c: - thread = threading.Thread(target=listen_to_aria2(self)) + thread = threading.Thread(target=listen_to_aria2(self, variaapp)) thread.start() # Load incomplete downloads: @@ -230,7 +230,7 @@ def save_appconf(self): json.dump(self.appconf, f) print("Config saved") - def exitProgram(self, app, variaapp, background, show_exit_window): + def exitProgram(self, app, variaapp, background): if (background == True): self.hide() notification = Gio.Notification.new(_("Background Mode")) @@ -247,7 +247,8 @@ def exitProgram(self, app, variaapp, background, show_exit_window): self.pause_all("no") self.api.client.shutdown() - if (show_exit_window == True): + if (self.is_visible() == True): + self.hide() exiting_dialog = Adw.MessageDialog() exiting_dialog_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=25) exiting_dialog.set_child(exiting_dialog_box) @@ -289,7 +290,7 @@ def aria2c_exiting_check(self, app, counter, variaapp, exiting_dialog): def quit_action_received(self, variaapp): if (self.terminating == False): - self.exitProgram(variaapp, variaapp, False, False) + self.exitProgram(variaapp, variaapp, False) class MyApp(Adw.Application): def __init__(self, appdir, appconf, aria2c_subprocess, **kwargs): diff --git a/src/window/preferences.py b/src/window/preferences.py index 416ccc6..11ae21d 100644 --- a/src/window/preferences.py +++ b/src/window/preferences.py @@ -7,8 +7,7 @@ from download.communicate import set_speed_limit, set_aria2c_download_directory, set_aria2c_download_simultaneous_amount def show_preferences(button, self, app): - preferences = Adw.PreferencesWindow(transient_for=self) - preferences.set_search_enabled(False) + preferences = Adw.PreferencesDialog() page = Adw.PreferencesPage(title=_("Preferences")) preferences.add(page) @@ -248,7 +247,7 @@ def show_preferences(button, self, app): group_2.add(remote_aria2_expander_box) - preferences.present() + preferences.present(self) def speed_limit_text_filter(entry, self): text = entry.get_text() @@ -278,14 +277,12 @@ def on_download_directory_selected(dialog, result, self, prefswindow, actionrow) set_aria2c_download_directory(self) actionrow.set_subtitle(self.appconf["download_directory"]) except: - error_dialog = Adw.MessageDialog() + error_dialog = Adw.AlertDialog() error_dialog.set_body(_("Failed to open directory.")) error_dialog.add_response("ok", _("OK")) error_dialog.set_default_response("ok") error_dialog.set_close_response("ok") - error_dialog.set_transient_for(prefswindow) - error_dialog.connect("response", on_dialog_dismiss, self) - error_dialog.show() + error_dialog.present(prefswindow) def on_switch_speed_limit(switch, state, self, preferencesWindow): if state: @@ -382,14 +379,9 @@ def on_switch_remote(switch, state, self, preferencesWindow): restart_varia_dialog(preferencesWindow) def restart_varia_dialog(preferencesWindow): - dialog = Adw.MessageDialog() + dialog = Adw.AlertDialog() dialog.set_body(_("Please restart Varia to apply the change.")) dialog.add_response("ok", _("OK")) dialog.set_default_response("ok") dialog.set_close_response("ok") - dialog.set_transient_for(preferencesWindow) - dialog.connect("response", on_dialog_dismiss) - dialog.show() - -def on_dialog_dismiss(dialog, response_id): - dialog.destroy() + dialog.present(preferencesWindow) diff --git a/src/window/sidebar.py b/src/window/sidebar.py index 1cd9519..a56600a 100644 --- a/src/window/sidebar.py +++ b/src/window/sidebar.py @@ -5,6 +5,7 @@ gi.require_version('Adw', '1') from gi.repository import Gtk, Adw, GLib, Gio from gettext import gettext as _ +import textwrap from window.preferences import show_preferences from download.actionrow import on_download_clicked @@ -41,6 +42,11 @@ def window_create_sidebar(self, variaapp, DownloadThread, variaVersion): downloads_folder_action.connect("activate", show_about, self, variaVersion) variaapp.add_action(downloads_folder_action) + self.shutdown_action = Gio.SimpleAction.new("shutdown_on_completion", None) + self.shutdown_action.connect("activate", shutdown_on_completion, self) + self.shutdown_action.set_enabled(False) + variaapp.add_action(self.shutdown_action) + hamburger_menu_item_background = Gio.MenuItem.new(_("Background Mode"), "app.background_mode") if (os.name != 'nt'): hamburger_menu_model.append_item(hamburger_menu_item_background) @@ -51,6 +57,9 @@ def window_create_sidebar(self, variaapp, DownloadThread, variaVersion): hamburger_menu_item_open_downloads_folder = Gio.MenuItem.new(_("Open Download Folder"), "app.downloads_folder") hamburger_menu_model.append_item(hamburger_menu_item_open_downloads_folder) + hamburger_menu_item_shutdown = Gio.MenuItem.new(_("Shutdown on Completion"), "app.shutdown_on_completion") + hamburger_menu_model.append_item(hamburger_menu_item_shutdown) + hamburger_menu_item_about = Gio.MenuItem.new(_("About Varia"), "app.about") hamburger_menu_model.append_item(hamburger_menu_item_about) @@ -111,9 +120,10 @@ def window_create_sidebar(self, variaapp, DownloadThread, variaVersion): sidebar_expanding_box = Gtk.Box() Gtk.Widget.set_vexpand(sidebar_expanding_box, True) + self.sidebar_shutdown_mode_label = Gtk.Label() self.sidebar_remote_mode_label = Gtk.Label() if (self.appconf['remote'] == '1'): - self.sidebar_remote_mode_label.set_text(_("Remote Mode")) + self.sidebar_remote_mode_label.set_text(textwrap.fill(_("Remote Mode"), 23)) self.sidebar_speed_limited_label = Gtk.Label() sidebar_content_box.set_margin_start(6) @@ -131,6 +141,7 @@ def window_create_sidebar(self, variaapp, DownloadThread, variaVersion): sidebar_content_box.append(sidebar_separator) sidebar_content_box.append(sidebar_filter_buttons_box) sidebar_content_box.append(sidebar_expanding_box) + sidebar_content_box.append(self.sidebar_shutdown_mode_label) sidebar_content_box.append(self.sidebar_remote_mode_label) sidebar_content_box.append(self.sidebar_speed_limited_label) sidebar_box.append(sidebar_content_box) @@ -138,10 +149,10 @@ def window_create_sidebar(self, variaapp, DownloadThread, variaVersion): self.overlay_split_view.set_sidebar(sidebar_box) def background_mode(app, variaapp1, self, variaapp): - self.exitProgram(app=app, variaapp=variaapp, background=True, show_exit_window=True) + self.exitProgram(app=app, variaapp=variaapp, background=True) def show_about(app, variaapp, self, variaVersion): - dialog = Adw.AboutWindow(transient_for=self) + dialog = Adw.AboutDialog() dialog.set_application_name("Varia") dialog.set_version(variaVersion) dialog.set_developer_name("Giant Pink Robots!") @@ -156,26 +167,25 @@ def show_about(app, variaapp, self, variaVersion): dialog.set_application_icon("io.github.giantpinkrobots.varia") dialog.set_translator_credits(_("translator-credits")) dialog.set_artists(["Jakub Steiner"]) - dialog.set_release_notes_version("v2024.2.29-2") - dialog.set_release_notes('''

v2024.2.29:

-
  • Support for Firefox and Chromium extension.
  • -
  • Initial torrenting support.
  • -
  • Remote mode that allows connection to a remote aria2 instance.
  • -
  • Background mode that allows the window to be hidden while still downloading.
  • -
  • Bug fixes and adjustments.
-

v2024.2.29-1:

-
  • Hotfix: an error that prevented the app from running in the Flathub release.
  • -
  • German translation updates.
  • -
  • Dutch translation updates.
-

v2024.2.29-2:

-
  • Hotfix: an error in the browser extension integration.
  • -
  • Tiny UI adjustments.
  • -
  • Russian translation updates.
  • -
  • New Norwegian (Bokmål) translation.
''') - dialog.show() + dialog.set_release_notes_version("v2024.3.20") + dialog.set_release_notes('''

v2024.3.20:

+
  • Shutdown after completion option added.
  • +
  • Update to GNOME 46 and Libadwaita 1.5.
  • +
  • Japanese language support.
  • +
  • Bug fixes and adjustments.
''') + + dialog.present(self) def open_downloads_folder(self, app, variaapp, appconf): if (os.name == 'nt'): os.startfile(appconf["download_directory"]) else: subprocess.Popen(["xdg-open", appconf["download_directory"]]) + +def shutdown_on_completion(self, app, variaapp): + if (variaapp.shutdown_mode == False): + variaapp.shutdown_mode = True + variaapp.sidebar_remote_mode_label.set_text(textwrap.fill(_("Shutdown on Completion"), 23)) + else: + variaapp.shutdown_mode = False + variaapp.sidebar_remote_mode_label.set_text("")