uninstallwindow.py 12.4 KB
Newer Older
Erdem Ersoy's avatar
Erdem Ersoy committed
1 2
#!/usr/bin/env python3
#
3
# Pardus Flatpak GUI uninstall from file 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 UninstallWindow(object):
38
    def __init__(self, application, flatpak_installation, real_name, arch, branch,
39 40
                 tree_model, tree_iter, selection, search_filter, show_button,
                 button_not_pressed_already):
Erdem Ersoy's avatar
Erdem Ersoy committed
41 42
        self.Application = application

43 44 45 46
        self.RealName = real_name
        self.Arch = arch
        self.Branch = branch
        self.RefFormat = "app/" + self.RealName + "/" + self.Arch + "/" + self.Branch
Erdem Ersoy's avatar
Erdem Ersoy committed
47

48
        self.FlatpakInstallation = flatpak_installation
Erdem Ersoy's avatar
Erdem Ersoy committed
49 50 51 52
        self.FlatpakTransaction = \
            Flatpak.Transaction.new_for_installation(
                self.FlatpakInstallation,
                Gio.Cancellable.new())
53
        self.FlatpakTransaction.set_default_arch(self.Arch)
Erdem Ersoy's avatar
Erdem Ersoy committed
54 55 56 57 58 59
        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)
60
        self.FlatpakTransaction.add_uninstall(self.RefFormat)
Erdem Ersoy's avatar
Erdem Ersoy committed
61

62 63 64 65
        self.TreeModel = tree_model
        self.TreeIter = tree_iter
        self.Selection = selection
        self.SearchFilter = search_filter
66
        self.HeaderBarShowButton = show_button
67
        self.ButtonNotPressedAlready = button_not_pressed_already
Erdem Ersoy's avatar
Erdem Ersoy committed
68

69 70
        self.FlatHubRefs = self.FlatpakInstallation.list_remote_refs_sync("flathub", Gio.Cancellable.new())

71 72 73 74 75
        self.handler_id = self.FlatpakTransaction.connect(
            "new-operation",
            self.uninstall_progress_callback)
        self.handler_id_2 = self.FlatpakTransaction.connect(
            "operation-done",
76
            self.uninstall_progress_callback_done)
77 78 79
        self.handler_id_error = self.FlatpakTransaction.connect(
            "operation-error",
            self.uninstall_progress_callback_error)
Erdem Ersoy's avatar
Erdem Ersoy committed
80 81

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

Erdem Ersoy's avatar
Erdem Ersoy committed
89 90
        self.UninstallCancellation = Gio.Cancellable.new()

91 92
        self.UninstallWindow = uninstall_builder.get_object("ActionWindow")
        self.UninstallWindow.set_application(self.Application)
93
        self.UninstallWindow.set_title(_("Uninstalling..."))
Erdem Ersoy's avatar
Erdem Ersoy committed
94 95
        self.UninstallWindow.show()

96 97 98
        self.UninstallButtonCancel = uninstall_builder.get_object("ActionButtonCancel")
        self.UninstallButtonCancel.set_sensitive(True)

99
        self.UninstallProgressBar = uninstall_builder.get_object(
Erdem Ersoy's avatar
Erdem Ersoy committed
100 101 102 103
                                        "ActionProgressBar")
        self.ProgressBarValue = int(
            self.UninstallProgressBar.get_fraction() * 100)

104 105
        self.UninstallLabel = uninstall_builder.get_object("ActionLabel")
        self.UninstallTextBuffer = uninstall_builder.get_object(
Erdem Ersoy's avatar
Erdem Ersoy committed
106 107 108
                                       "ActionTextBuffer")

        self.UninstallTextBuffer.set_text("\0", -1)
109
        self.StatusText = _("Uninstalling...")
Erdem Ersoy's avatar
Erdem Ersoy committed
110 111 112 113
        self.UninstallLabel.set_text(self.StatusText)
        self.UninstallTextBuffer.set_text(self.StatusText)

        self.UninstallThread = threading.Thread(
114
                           target=self.uninstall,
Erdem Ersoy's avatar
Erdem Ersoy committed
115 116 117 118
                           args=())
        self.UninstallThread.start()
        GLib.threads_init()

119
    def uninstall(self):
120 121 122 123 124
        GLib.idle_add(self.Selection.unselect_all,
                      data=None,
                      priority=GLib.PRIORITY_DEFAULT)
        time.sleep(0.2)

Erdem Ersoy's avatar
Erdem Ersoy committed
125
        handler_id_cancel = self.UninstallCancellation.connect(self.cancellation_callback, None)
Erdem Ersoy's avatar
Erdem Ersoy committed
126
        try:
Erdem Ersoy's avatar
Erdem Ersoy committed
127
            self.FlatpakTransaction.run(self.UninstallCancellation)
Erdem Ersoy's avatar
Erdem Ersoy committed
128
        except GLib.Error:
129 130
            status_text = _("Error at uninstalling!")
            self.StatusText = self.StatusText + "\n" + status_text
Erdem Ersoy's avatar
Erdem Ersoy committed
131
            GLib.idle_add(self.UninstallLabel.set_text,
132
                          status_text,
Erdem Ersoy's avatar
Erdem Ersoy committed
133 134 135 136
                          priority=GLib.PRIORITY_DEFAULT)
            GLib.idle_add(self.UninstallTextBuffer.set_text,
                          self.StatusText,
                          priority=GLib.PRIORITY_DEFAULT)
Erdem Ersoy's avatar
Erdem Ersoy committed
137 138 139
            self.disconnect_handlers(handler_id_cancel)
            UninstallWindow.at_uninstallation = False
            return None
Erdem Ersoy's avatar
Erdem Ersoy committed
140
        else:
141 142
            status_text = _("Uninstalling completed!")
            self.StatusText = self.StatusText + "\n" + status_text
Erdem Ersoy's avatar
Erdem Ersoy committed
143
            GLib.idle_add(self.UninstallLabel.set_text,
144
                          status_text,
Erdem Ersoy's avatar
Erdem Ersoy committed
145 146 147 148
                          priority=GLib.PRIORITY_DEFAULT)
            GLib.idle_add(self.UninstallTextBuffer.set_text,
                          self.StatusText,
                          priority=GLib.PRIORITY_DEFAULT)
149
        time.sleep(0.2)
Erdem Ersoy's avatar
Erdem Ersoy committed
150
        self.disconnect_handlers(handler_id_cancel)
151 152 153
        GLib.idle_add(self.UninstallButtonCancel.set_sensitive,
                      False,
                      priority=GLib.PRIORITY_DEFAULT)
Erdem Ersoy's avatar
Erdem Ersoy committed
154 155
        time.sleep(0.5)

156 157 158
        if self.ButtonNotPressedAlready:
            pass
        elif not self.HeaderBarShowButton.get_active():
159 160 161 162
            GLib.idle_add(self.HeaderBarShowButton.set_active,
                          True,
                          priority=GLib.PRIORITY_DEFAULT)
            time.sleep(0.2)
163

164 165 166 167
            GLib.idle_add(self.Selection.unselect_all,
                      data=None,
                      priority=GLib.PRIORITY_DEFAULT)

168 169 170
    def uninstall_progress_callback(self, transaction, operation, progress):
        ref_to_uninstall = Flatpak.Ref.parse(operation.get_ref())
        ref_to_uninstall_real_name = ref_to_uninstall.get_name()
171

172
        status_text = _("Uninstalling: ") + ref_to_uninstall_real_name
173
        self.StatusText = self.StatusText + "\n" + status_text
174
        GLib.idle_add(self.UninstallLabel.set_text,
175
                      status_text,
176 177 178 179
                      priority=GLib.PRIORITY_DEFAULT)
        GLib.idle_add(self.UninstallTextBuffer.set_text,
                      self.StatusText,
                      priority=GLib.PRIORITY_DEFAULT)
Erdem Ersoy's avatar
Erdem Ersoy committed
180

181
        self.TransactionProgress = progress  # FIXME: Fix PyCharm warning
Erdem Ersoy's avatar
Erdem Ersoy committed
182 183
        self.TransactionProgress.set_update_frequency(200)
        self.handler_id_progress = self.TransactionProgress.connect(
184 185
            "changed",
            self.progress_bar_update)  # FIXME: Fix PyCharm warning
Erdem Ersoy's avatar
Erdem Ersoy committed
186

187
    def uninstall_progress_callback_done(self, transaction, operation, commit, result):
Erdem Ersoy's avatar
Erdem Ersoy committed
188 189
        self.TransactionProgress.disconnect(self.handler_id_progress)

190 191 192 193 194 195 196 197 198 199 200 201
        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 uninstalled_ref in self.FlatHubRefs:
            if uninstalled_ref.get_name() == operation_ref_real_name and \
               uninstalled_ref.get_arch() == operation_ref_arch and \
               uninstalled_ref.get_branch() == operation_ref_branch and \
               uninstalled_ref.get_kind() == Flatpak.RefKind.APP:
                uninstalled_ref_real_name = uninstalled_ref.get_name()
                uninstalled_ref_arch = uninstalled_ref.get_arch()
                uninstalled_ref_branch = uninstalled_ref.get_branch()
202
                uninstalled_ref_remote = "FlatHub"
203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238

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

                download_size = uninstalled_ref.get_download_size()
                download_size_mib = download_size / 1048576
                download_size_mib_str = f"{download_size_mib:.2f}" + " MiB"

                name = ""

                tree_model = self.TreeModel.get_model()
                tree_iter = tree_model.get_iter_first()
                while tree_iter:
                    real_name = tree_model.get_value(tree_iter, 0)
                    arch = tree_model.get_value(tree_iter, 1)
                    branch = tree_model.get_value(tree_iter, 2)
                    if real_name == uninstalled_ref_real_name and \
                       arch == uninstalled_ref_arch and \
                       branch == uninstalled_ref_branch:
                        GLib.idle_add(tree_model.set_row,
                                      tree_iter, [uninstalled_ref_real_name,
                                                  uninstalled_ref_arch,
                                                  uninstalled_ref_branch,
                                                  uninstalled_ref_remote,
                                                  installed_size_mib_str,
                                                  download_size_mib_str,
                                                  name],
                                      priority=GLib.PRIORITY_DEFAULT)
                        time.sleep(0.2)

                        tree_model.refilter()
                        time.sleep(0.3)
                    tree_iter = tree_model.iter_next(tree_iter)

239 240 241
    def uninstall_progress_callback_error(self, transaction, operation, error, details):
        ref_to_uninstall = Flatpak.Ref.parse(operation.get_ref())
        ref_to_uninstall_real_name = ref_to_uninstall.get_name()
242

243
        status_text = _("Not uninstalled: ") + ref_to_uninstall_real_name
244
        self.StatusText = self.StatusText + "\n" + status_text
245
        GLib.idle_add(self.UninstallLabel.set_text,
246
                      status_text,
247 248 249 250 251
                      priority=GLib.PRIORITY_DEFAULT)
        GLib.idle_add(self.UninstallTextBuffer.set_text,
                      self.StatusText,
                      priority=GLib.PRIORITY_DEFAULT)

252
        if ref_to_uninstall_real_name != self.RealName:
Erdem Ersoy's avatar
Erdem Ersoy committed
253 254 255 256
            return True
        else:
            return False

257
    def progress_bar_update(self, transaction_progress):
Erdem Ersoy's avatar
Erdem Ersoy committed
258
        GLib.idle_add(self.UninstallProgressBar.set_fraction,
Erdem Ersoy's avatar
Erdem Ersoy committed
259 260 261
                      float(transaction_progress.get_progress()) / 100.0,
                      priority=GLib.PRIORITY_DEFAULT)

Erdem Ersoy's avatar
Erdem Ersoy committed
262
    def cancellation_callback(self, *data):
Erdem Ersoy's avatar
Erdem Ersoy committed
263
        status_text = _("Uninstalling canceled!")
Erdem Ersoy's avatar
Erdem Ersoy committed
264 265 266 267 268 269 270 271 272 273 274 275 276 277
        self.StatusText = self.StatusText + "\n" + status_text
        GLib.idle_add(self.UninstallLabel.set_text,
                      status_text,
                      priority=GLib.PRIORITY_DEFAULT)
        GLib.idle_add(self.UninstallTextBuffer.set_text,
                      self.StatusText,
                      priority=GLib.PRIORITY_DEFAULT)

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

278
    def on_press_cancel(self, button):
Erdem Ersoy's avatar
Erdem Ersoy committed
279
        self.UninstallCancellation.cancel()
280 281
        self.UninstallWindow.hide_on_delete()

282
    def on_delete_action_window(self, widget, event):
Erdem Ersoy's avatar
Erdem Ersoy committed
283
        self.UninstallCancellation.cancel()
284
        widget.hide_on_delete()