updateallwindow.py 13.2 KB
Newer Older
Erdem Ersoy's avatar
Erdem Ersoy committed
1 2
#!/usr/bin/env python3
#
3
# Pardus Flatpak GUI update all window module
Erdem Ersoy's avatar
Erdem Ersoy committed
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
# Copyright (C) 2020 Erdem Ersoy
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

import gettext
import locale
import threading
import time
import gi
gi.require_version('Gtk', '3.0')
gi.require_version('GLib', '2.0')
gi.require_version('Flatpak', '1.0')
gi.require_version('Gio', '2.0')
from gi.repository import Gtk, GLib, Flatpak, Gio

locale.setlocale(locale.LC_ALL, "")
Erdem Ersoy's avatar
Erdem Ersoy committed
31
gettext.bindtextdomain("pardus-flatpak-gui", "/usr/share/locale/")
32
gettext.textdomain("pardus-flatpak-gui")
Erdem Ersoy's avatar
Erdem Ersoy committed
33
_ = gettext.gettext
Erdem Ersoy's avatar
Erdem Ersoy committed
34
gettext.install("pardus-flatpak-gui", "/usr/share/locale/")
Erdem Ersoy's avatar
Erdem Ersoy committed
35 36 37


class UpdateAllWindow(object):
38 39 40
    at_updating = False

    def __init__(self, application, flatpak_installation, tree_model, show_button):
Erdem Ersoy's avatar
Erdem Ersoy committed
41
        self.Application = application
42

43 44
        self.FlatpakInstallation = flatpak_installation
        self.RefsToUpdate = flatpak_installation.list_installed_refs_for_update(Gio.Cancellable.new())
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
        self.InstalledRefsList = self.FlatpakInstallation.list_installed_refs()
        self.FlatHubRefsList = self.FlatpakInstallation.list_remote_refs_sync(
            "flathub", Gio.Cancellable.new())
        self.NonInstalledRefsList = []

        for item in self.FlatHubRefsList:
            self.NonInstalledRefsList.append(item)
            for item_2 in self.InstalledRefsList:
                if item.get_name() == item_2.get_name() and \
                        item.get_arch() == item_2.get_arch() and \
                        item.get_branch() == item_2.get_branch():
                    if len(self.NonInstalledRefsList) != 0:
                        self.NonInstalledRefsList.pop(len(self.NonInstalledRefsList) - 1)
                    else:
                        self.NonInstalledRefsList = []

61 62 63 64 65 66 67 68 69 70 71 72
        self.FlatpakTransaction = \
            Flatpak.Transaction.new_for_installation(
                self.FlatpakInstallation,
                Gio.Cancellable.new())
        self.FlatpakTransaction.set_default_arch(Flatpak.get_default_arch())
        self.FlatpakTransaction.set_disable_dependencies(False)
        self.FlatpakTransaction.set_disable_prune(False)
        self.FlatpakTransaction.set_disable_related(False)
        self.FlatpakTransaction.set_disable_static_deltas(False)
        self.FlatpakTransaction.set_no_deploy(False)
        self.FlatpakTransaction.set_no_pull(False)
        for ref_to_update in self.RefsToUpdate:
73 74
            ref_str = ref_to_update.format_ref()
            self.FlatpakTransaction.add_update(ref_str, None, None)
75

76 77
        self.TreeModel = tree_model
        self.HeaderBarShowButton = show_button
Erdem Ersoy's avatar
Erdem Ersoy committed
78 79

        try:
Erdem Ersoy's avatar
Erdem Ersoy committed
80
            update_all_gui_file = "/usr/share/pardus/pardus-flatpak-gui/ui/actionwindow.glade"
81 82
            update_all_builder = Gtk.Builder.new_from_file(update_all_gui_file)
            update_all_builder.connect_signals(self)
Erdem Ersoy's avatar
Erdem Ersoy committed
83
        except GLib.GError:
84
            print(_("Error reading GUI file: ") + update_all_gui_file)
Erdem Ersoy's avatar
Erdem Ersoy committed
85 86
            raise

Erdem Ersoy's avatar
Erdem Ersoy committed
87 88
        self.UpdateAllCancellation = Gio.Cancellable.new()

89
        self.UpdateAllWindow = update_all_builder.get_object("ActionWindow")
Erdem Ersoy's avatar
Erdem Ersoy committed
90 91 92 93
        self.UpdateAllWindow.set_application(application)
        self.UpdateAllWindow.set_title(_("Updating All"))
        self.UpdateAllWindow.show()

94
        self.UpdateAllProgressBar = update_all_builder.get_object(
Erdem Ersoy's avatar
Erdem Ersoy committed
95 96 97 98
                                        "ActionProgressBar")
        self.ProgressBarValue = int(
            self.UpdateAllProgressBar.get_fraction() * 100)

99 100
        self.UpdateAllLabel = update_all_builder.get_object("ActionLabel")
        self.UpdateAllTextBuffer = update_all_builder.get_object(
Erdem Ersoy's avatar
Erdem Ersoy committed
101 102 103 104 105 106 107
                                       "ActionTextBuffer")

        self.UpdateAllTextBuffer.set_text("\0", -1)
        self.StatusText = _("Updating...")
        self.UpdateAllLabel.set_text(self.StatusText)
        self.UpdateAllTextBuffer.set_text(self.StatusText)

108 109
        self.handler_id = self.FlatpakTransaction.connect(
            "new-operation",
110
            self.update_all_progress_callback)
111 112
        self.handler_id_2 = self.FlatpakTransaction.connect(
            "operation-done",
113
            self.update_all_progress_callback_done)
114 115
        self.handler_id_error = self.FlatpakTransaction.connect(
            "operation-error",
116 117 118 119 120 121 122 123 124
            self.update_all_progress_callback_error)

        self.UpdateAllThread = threading.Thread(
                           target=self.update_all,
                           args=())
        self.UpdateAllThread.start()
        GLib.threads_init()

    def update_all(self):
Erdem Ersoy's avatar
Erdem Ersoy committed
125
        handler_id_cancel = self.UpdateAllCancellation.connect(self.cancellation_callback, None)
126
        try:
Erdem Ersoy's avatar
Erdem Ersoy committed
127
            self.FlatpakTransaction.run(self.UpdateAllCancellation)
128
        except GLib.Error:
129 130
            status_text = _("Error at updating!")
            self.StatusText = self.StatusText + "\n" + status_text
131
            GLib.idle_add(self.UpdateAllLabel.set_text,
132
                          status_text,
133 134 135 136
                          priority=GLib.PRIORITY_DEFAULT)
            GLib.idle_add(self.UpdateAllTextBuffer.set_text,
                          self.StatusText,
                          priority=GLib.PRIORITY_DEFAULT)
Erdem Ersoy's avatar
Erdem Ersoy committed
137 138 139
            self.disconnect_handlers(handler_id_cancel)
            UpdateAllWindow.at_updating = False
            return None
140
        else:
141
            status_text = _("Updating completed!")
142
            self.StatusText = self.StatusText + "\n" + status_text
143
            GLib.idle_add(self.UpdateAllLabel.set_text,
144
                          status_text,
145 146 147 148
                          priority=GLib.PRIORITY_DEFAULT)
            GLib.idle_add(self.UpdateAllTextBuffer.set_text,
                          self.StatusText,
                          priority=GLib.PRIORITY_DEFAULT)
Erdem Ersoy's avatar
Erdem Ersoy committed
149
        self.disconnect_handlers(handler_id_cancel)
150 151
        time.sleep(0.5)

152 153 154 155 156 157 158 159 160 161 162 163
        UpdateAllWindow.at_updating = False

        if self.HeaderBarShowButton.get_active():
            GLib.idle_add(self.HeaderBarShowButton.set_active,
                          False,
                          priority=GLib.PRIORITY_DEFAULT)
            time.sleep(0.2)

            GLib.idle_add(self.HeaderBarShowButton.set_active,
                          True,
                          priority=GLib.PRIORITY_DEFAULT)

164 165 166
    def update_all_progress_callback(self, transaction, operation, progress):
        ref_to_update = Flatpak.Ref.parse(operation.get_ref())
        ref_to_update_real_name = ref_to_update.get_name()
167
        operation_type = operation.get_operation_type()
Erdem Ersoy's avatar
Erdem Ersoy committed
168

169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
        if operation_type == Flatpak.TransactionOperationType.UPDATE:
            status_text = _("Updating: ") + ref_to_update_real_name
            self.StatusText = self.StatusText + "\n" + status_text
            GLib.idle_add(self.UpdateAllLabel.set_text,
                          status_text,
                          priority=GLib.PRIORITY_DEFAULT)
            GLib.idle_add(self.UpdateAllTextBuffer.set_text,
                          self.StatusText,
                          priority=GLib.PRIORITY_DEFAULT)
        elif operation_type == Flatpak.TransactionOperationType.INSTALL:
            status_text = _("Installing: ") + ref_to_update_real_name
            self.StatusText = self.StatusText + "\n" + status_text
            GLib.idle_add(self.UpdateAllLabel.set_text,
                          status_text,
                          priority=GLib.PRIORITY_DEFAULT)
            GLib.idle_add(self.UpdateAllTextBuffer.set_text,
                          self.StatusText,
                          priority=GLib.PRIORITY_DEFAULT)
187

188
        self.TransactionProgress = progress  # FIXME: Fix PyCharm warning
189 190 191
        self.TransactionProgress.set_update_frequency(200)
        self.handler_id_progress = self.TransactionProgress.connect(
            "changed",
192
            self.progress_bar_update)  # FIXME: Fix PyCharm warning
193

194
    def update_all_progress_callback_done(self, transaction, operation, commit, result):  # FIXME: Test and review
195 196
        self.TransactionProgress.disconnect(self.handler_id_progress)

197 198 199 200 201 202 203
        operation_ref = Flatpak.Ref.parse(operation.get_ref())
        operation_ref_real_name = operation_ref.get_name()
        operation_ref_arch = operation_ref.get_arch()
        operation_ref_branch = operation_ref.get_branch()
        for updated_ref in self.RefsToUpdate:
            if updated_ref.get_name() == operation_ref_real_name and \
               updated_ref.get_arch() == operation_ref_arch and \
204 205
               updated_ref.get_branch() == operation_ref_branch and \
               updated_ref.get_kind() == Flatpak.RefKind.APP:
206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
                updated_ref_real_name = updated_ref.get_name()
                updated_ref_arch = updated_ref.get_arch()
                updated_ref_branch = updated_ref.get_branch()
                updated_ref_remote = "flathub"

                installed_size = updated_ref.get_installed_size()
                installed_size_mib = installed_size / 1048576
                installed_size_mib_str = \
                    f"{installed_size_mib:.2f}" + " MiB"

                download_size_mib_str = ""
                name = updated_ref.get_appdata_name()

                tree_iter = self.TreeModel.get_model().get_iter_first()
                while tree_iter:
221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240
                    real_name = self.TreeModel.get_value(tree_iter, 0)
                    arch = self.TreeModel.get_value(tree_iter, 1)
                    branch = self.TreeModel.get_value(tree_iter, 2)
                    if real_name == updated_ref_real_name and \
                       arch == updated_ref_arch and \
                       branch == updated_ref_branch:
                        GLib.idle_add(self.TreeModel.set_row,
                                      tree_iter, [updated_ref_real_name,
                                                  updated_ref_arch,
                                                  updated_ref_branch,
                                                  updated_ref_remote,
                                                  installed_size_mib_str,
                                                  download_size_mib_str,
                                                  name],
                                      priority=GLib.PRIORITY_DEFAULT)
                        time.sleep(0.2)

                        self.TreeModel.refilter()
                        time.sleep(0.3)
                    tree_iter = self.TreeModel.iter_next(tree_iter)
241

242 243 244
    def update_all_progress_callback_error(self, transaction, operation, error, details):
        ref_to_update_all = Flatpak.Ref.parse(operation.get_ref())
        ref_to_update_all_real_name = ref_to_update_all.get_name()
245
        operation_type = operation.get_operation_type()
246

247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264
        if operation_type == Flatpak.TransactionOperationType.UPDATE:
            status_text = _("Not updated: ") + ref_to_update_all_real_name
            self.StatusText = self.StatusText + "\n" + status_text
            GLib.idle_add(self.UpdateAllLabel.set_text,
                          status_text,
                          priority=GLib.PRIORITY_DEFAULT)
            GLib.idle_add(self.UpdateAllTextBuffer.set_text,
                          self.StatusText,
                          priority=GLib.PRIORITY_DEFAULT)
        elif operation_type == Flatpak.TransactionOperationType.INSTALL:
            status_text = _("Not installed: ") + ref_to_update_all_real_name
            self.StatusText = self.StatusText + "\n" + status_text
            GLib.idle_add(self.UpdateAllLabel.set_text,
                          status_text,
                          priority=GLib.PRIORITY_DEFAULT)
            GLib.idle_add(self.UpdateAllTextBuffer.set_text,
                          self.StatusText,
                          priority=GLib.PRIORITY_DEFAULT)
265 266 267

        return True

268
    def progress_bar_update(self, transaction_progress):
269 270 271
        GLib.idle_add(self.UpdateAllProgressBar.set_fraction,
                      float(transaction_progress.get_progress()) / 100.0,
                      priority=GLib.PRIORITY_DEFAULT)
Erdem Ersoy's avatar
Erdem Ersoy committed
272

Erdem Ersoy's avatar
Erdem Ersoy committed
273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288
    def cancellation_callback(self, *data):
        status_text = _("Updating canceled!")
        self.StatusText = self.StatusText + "\n" + status_text
        GLib.idle_add(self.UpdateAllLabel.set_text,
                      status_text,
                      priority=GLib.PRIORITY_DEFAULT)
        GLib.idle_add(self.UpdateAllTextBuffer.set_text,
                      self.StatusText,
                      priority=GLib.PRIORITY_DEFAULT)

    def disconnect_handlers(self, handler_id_cancel):
        self.UpdateAllCancellation.disconnect(handler_id_cancel)
        self.FlatpakTransaction.disconnect(self.handler_id)
        self.FlatpakTransaction.disconnect(self.handler_id_2)
        self.FlatpakTransaction.disconnect(self.handler_id_error)

289
    def on_delete_action_window(self, widget, event):
Erdem Ersoy's avatar
Erdem Ersoy committed
290
        self.UpdateAllCancellation.cancel()
291
        widget.hide_on_delete()