1
# DistUpgradeViewGtk.py
3
# Copyright (c) 2004-2006 Canonical
5
# Author: Michael Vogt <michael.vogt@ubuntu.com>
7
# This program is free software; you can redistribute it and/or
8
# modify it under the terms of the GNU General Public License as
9
# published by the Free Software Foundation; either version 2 of the
10
# License, or (at your option) any later version.
12
# This program is distributed in the hope that it will be useful,
13
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
17
# You should have received a copy of the GNU General Public License
18
# along with this program; if not, write to the Free Software
19
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22
from __future__ import absolute_import, print_function
42
from .DistUpgradeApport import run_apport, apport_crash
44
from .DistUpgradeView import DistUpgradeView, FuzzyTimeToStr, InstallProgress, AcquireProgress
45
from .SimpleGtkbuilderApp import SimpleGtkbuilderApp
48
from .DistUpgradeGettext import gettext as _
50
gobject.threads_init()
53
return unicode(str, 'latin1').encode('utf-8')
55
class GtkCdromProgressAdapter(apt.progress.base.CdromProgress):
56
""" Report the cdrom add progress
57
Subclass this class to implement cdrom add progress reporting
59
def __init__(self, parent):
60
self.status = parent.label_status
61
self.progress = parent.progressbar_cache
63
def update(self, text, step):
64
""" update is called regularly so that the gui can be redrawn """
66
self.status.set_text(text)
67
self.progress.set_fraction(step/float(self.totalSteps))
68
while gtk.events_pending():
70
def ask_cdrom_name(self):
72
def change_cdrom(self):
75
class GtkOpProgress(apt.progress.base.OpProgress):
76
def __init__(self, progressbar):
77
self.progressbar = progressbar
78
#self.progressbar.set_pulse_step(0.01)
79
#self.progressbar.pulse()
82
def update(self, percent):
84
# self.progressbar.set_fraction(1)
86
# self.progressbar.pulse()
87
new_fraction = percent/100.0
88
if abs(self.fraction-new_fraction) > 0.1:
89
self.fraction = new_fraction
90
self.progressbar.set_fraction(self.fraction)
91
while gtk.events_pending():
95
self.progressbar.set_text(" ")
98
class GtkAcquireProgressAdapter(AcquireProgress):
99
# FIXME: we really should have some sort of "we are at step"
101
# FIXME2: we need to thing about mediaCheck here too
102
def __init__(self, parent):
103
super(GtkAcquireProgressAdapter, self).__init__()
104
# if this is set to false the download will cancel
105
self.status = parent.label_status
106
self.progress = parent.progressbar_cache
108
self.canceled = False
109
self.button_cancel = parent.button_fetch_cancel
110
self.button_cancel.connect('clicked', self.cancelClicked)
111
def cancelClicked(self, widget):
112
logging.debug("cancelClicked")
114
def media_change(self, medium, drive):
115
#print("mediaChange %s %s" % (medium, drive))
116
msg = _("Please insert '%s' into the drive '%s'") % (medium,drive)
117
dialog = gtk.MessageDialog(parent=self.parent.window_main,
118
flags=gtk.DIALOG_MODAL,
119
type=gtk.MESSAGE_QUESTION,
120
buttons=gtk.BUTTONS_OK_CANCEL)
121
dialog.set_markup(msg)
125
if res == gtk.RESPONSE_OK:
129
#logging.debug("start")
130
super(GtkAcquireProgressAdapter, self).start()
131
self.progress.set_fraction(0)
133
self.button_cancel.show()
135
#logging.debug("stop")
136
self.progress.set_text(" ")
137
self.status.set_text(_("Fetching is complete"))
138
self.button_cancel.hide()
139
def pulse(self, owner):
140
super(GtkAcquireProgressAdapter, self).pulse(owner)
141
# only update if there is a noticable change
142
if abs(self.percent-self.progress.get_fraction()*100.0) > 0.1:
143
self.progress.set_fraction(self.percent/100.0)
144
currentItem = self.current_items + 1
145
if currentItem > self.total_items:
146
currentItem = self.total_items
147
if self.current_cps > 0:
148
self.status.set_text(_("Fetching file %li of %li at %sB/s") % (
149
currentItem, self.total_items,
150
apt_pkg.size_to_str(self.current_cps)))
151
self.progress.set_text(_("About %s remaining") % FuzzyTimeToStr(
154
self.status.set_text(_("Fetching file %li of %li") % (
155
currentItem, self.total_items))
156
self.progress.set_text(" ")
157
while gtk.events_pending():
159
return (not self.canceled)
161
class GtkInstallProgressAdapter(InstallProgress):
162
# timeout with no status change when the terminal is expanded
164
TIMEOUT_TERMINAL_ACTIVITY = 240
166
def __init__(self,parent):
167
InstallProgress.__init__(self)
169
self.label_status = parent.label_status
170
self.progress = parent.progressbar_cache
171
self.expander = parent.expander_terminal
172
self.term = parent._term
173
self.term.connect("child-exited", self.child_exited)
175
# setup the child waiting
176
# some options for dpkg to make it die less easily
177
apt_pkg.config.set("DPkg::StopOnError","False")
179
def start_update(self):
180
InstallProgress.start_update(self)
181
self.finished = False
182
# FIXME: add support for the timeout
183
# of the terminal (to display something useful then)
184
# -> longer term, move this code into python-apt
185
self.label_status.set_text(_("Applying changes"))
186
self.progress.set_fraction(0.0)
187
self.progress.set_text(" ")
188
self.expander.set_sensitive(True)
190
# if no libgtk2-perl is installed show the terminal
191
frontend= os.environ.get("DEBIAN_FRONTEND") or "gnome"
192
if frontend == "gnome" and self._cache:
193
if (not "libgtk2-perl" in self._cache or
194
not self._cache["libgtk2-perl"].is_installed):
196
self.expander.set_expanded(True)
197
self.env = ["VTE_PTY_KEEP_FD=%s"% self.writefd,
198
"APT_LISTCHANGES_FRONTEND=none"]
199
if not os.environ.has_key("DEBIAN_FRONTEND"):
200
self.env.append("DEBIAN_FRONTEND=%s" % frontend)
201
# do a bit of time-keeping
202
self.start_time = 0.0
204
self.last_activity = 0.0
206
def error(self, pkg, errormsg):
207
InstallProgress.error(self, pkg, errormsg)
208
logging.error("got an error from dpkg for pkg: '%s': '%s'" % (pkg, errormsg))
209
# we do not report followup errors from earlier failures
210
if gettext.dgettext('dpkg', "dependency problems - leaving unconfigured") in errormsg:
213
#self.expander_terminal.set_expanded(True)
214
self.parent.dialog_error.set_transient_for(self.parent.window_main)
215
summary = _("Could not install '%s'") % pkg
216
msg = _("The upgrade will continue but the '%s' package may not "
217
"be in a working state. Please consider submitting a "
218
"bug report about it.") % pkg
219
markup="<big><b>%s</b></big>\n\n%s" % (summary, msg)
220
self.parent.dialog_error.realize()
221
self.parent.dialog_error.set_title("")
222
self.parent.dialog_error.window.set_functions(gtk.gdk.FUNC_MOVE)
223
self.parent.label_error.set_markup(markup)
224
self.parent.textview_error.get_buffer().set_text(utf8(errormsg))
225
self.parent.scroll_error.show()
226
self.parent.dialog_error.run()
227
self.parent.dialog_error.hide()
229
def conffile(self, current, new):
230
logging.debug("got a conffile-prompt from dpkg for file: '%s'" % current)
232
#self.expander.set_expanded(True)
233
prim = _("Replace the customized configuration file\n'%s'?") % current
234
sec = _("You will lose any changes you have made to this "
235
"configuration file if you choose to replace it with "
237
markup = "<span weight=\"bold\" size=\"larger\">%s </span> \n\n%s" % (prim, sec)
238
self.parent.label_conffile.set_markup(markup)
239
self.parent.dialog_conffile.set_title("")
240
self.parent.dialog_conffile.set_transient_for(self.parent.window_main)
242
# workaround silly dpkg
243
if not os.path.exists(current):
244
current = current+".dpkg-dist"
247
if os.path.exists("/usr/bin/diff"):
248
cmd = ["/usr/bin/diff", "-u", current, new]
249
diff = utf8(subprocess.Popen(cmd, stdout=subprocess.PIPE).communicate()[0])
250
self.parent.textview_conffile.get_buffer().set_text(diff)
252
self.parent.textview_conffile.get_buffer().set_text(_("The 'diff' command was not found"))
253
res = self.parent.dialog_conffile.run()
254
self.parent.dialog_conffile.hide()
255
self.time_ui += time.time() - start
256
# if replace, send this to the terminal
257
if res == gtk.RESPONSE_YES:
258
self.term.feed_child("y\n", -1)
260
self.term.feed_child("n\n", -1)
263
pid = self.term.forkpty(envv=self.env)
265
# WORKAROUND for broken feisty vte where envv does not work)
267
(key, value) = env.split("=")
268
os.environ[key] = value
269
# force dpkg terminal messages untranslated for better bug
270
# duplication detection
271
os.environ["DPKG_UNTRANSLATED_MESSAGES"] = "1"
272
# HACK to work around bug in python/vte and unregister the logging
273
# atexit func in the child
274
sys.exitfunc = lambda: True
277
def status_change(self, pkg, percent, status):
278
# start the timer when the first package changes its status
279
if self.start_time == 0.0:
280
#print("setting start time to %s" % self.start_time)
281
self.start_time = time.time()
282
# only update if there is a noticable change
283
if abs(percent-self.progress.get_fraction()*100.0) > 0.1:
284
self.progress.set_fraction(float(percent)/100.0)
285
self.label_status.set_text(status.strip())
286
# start showing when we gathered some data
288
self.last_activity = time.time()
289
self.activity_timeout_reported = False
290
delta = self.last_activity - self.start_time
291
# time wasted in conffile questions (or other ui activity)
292
delta -= self.time_ui
293
time_per_percent = (float(delta)/percent)
294
eta = (100.0 - percent) * time_per_percent
295
# only show if we have some sensible data (60sec < eta < 2days)
296
if eta > 61.0 and eta < (60*60*24*2):
297
self.progress.set_text(_("About %s remaining") % FuzzyTimeToStr(eta))
299
self.progress.set_text(" ")
300
# 2 == WEBKIT_LOAD_FINISHED - the enums is not exposed via python
301
if (self.parent._webkit_view and
302
self.parent._webkit_view.get_property("load-status") == 2):
303
self.parent._webkit_view.execute_script('progress("%s")' % percent)
305
def child_exited(self, term):
306
# we need to capture the full status here (not only the WEXITSTATUS)
307
self.apt_status = term.get_child_exit_status()
310
def wait_child(self):
311
while not self.finished:
312
self.update_interface()
313
return self.apt_status
315
def finish_update(self):
316
self.label_status.set_text("")
318
def update_interface(self):
319
InstallProgress.update_interface(self)
320
# check if we haven't started yet with packages, pulse then
321
if self.start_time == 0.0:
322
self.progress.pulse()
324
# check about terminal activity
325
if self.last_activity > 0 and \
326
(self.last_activity + self.TIMEOUT_TERMINAL_ACTIVITY) < time.time():
327
if not self.activity_timeout_reported:
328
logging.warning("no activity on terminal for %s seconds (%s)" % (self.TIMEOUT_TERMINAL_ACTIVITY, self.label_status.get_text()))
329
self.activity_timeout_reported = True
330
self.parent.expander_terminal.set_expanded(True)
332
while gtk.events_pending():
336
class DistUpgradeVteTerminal(object):
337
def __init__(self, parent, term):
340
def call(self, cmd, hidden=False):
341
def wait_for_child(widget):
342
#print("wait for child finished")
345
self.term.connect("child-exited", wait_for_child)
346
self.parent.expander_terminal.set_sensitive(True)
348
self.parent.expander_terminal.set_expanded(True)
349
self.finished = False
350
pid = self.term.fork_command(command=cmd[0],argv=cmd)
354
while not self.finished:
355
while gtk.events_pending():
360
class HtmlView(object):
361
def __init__(self, webkit_view):
362
self._webkit_view = webkit_view
364
if not self._webkit_view:
366
self._webkit_view.open(url)
367
self._webkit_view.connect("load-finished", self._on_load_finished)
369
self._webkit_view.show()
371
self._webkit_view.hide()
372
def _on_load_finished(self, view, frame):
375
class DistUpgradeViewGtk(DistUpgradeView,SimpleGtkbuilderApp):
376
" gtk frontend of the distUpgrade tool "
377
def __init__(self, datadir=None, logdir=None):
378
DistUpgradeView.__init__(self)
381
localedir=os.path.join(os.getcwd(),"mo")
384
localedir="/usr/share/locale/"
385
gladedir=os.path.join(datadir, "gtkbuilder")
387
# check if we have a display etc
391
locale.bindtextdomain("update-manager",localedir)
392
gettext.textdomain("update-manager")
393
except Exception as e:
394
logging.warning("Error setting locales (%s)" % e)
396
icons = gtk.icon_theme_get_default()
398
gtk.window_set_default_icon(icons.load_icon("system-software-update", 32, 0))
399
except gobject.GError as e:
400
logging.debug("error setting default icon, ignoring (%s)" % e)
402
SimpleGtkbuilderApp.__init__(self,
403
gladedir+"/DistUpgrade.ui",
406
self.create_terminal()
408
self.prev_step = 0 # keep a record of the latest step
409
# we don't use this currently
410
#self.window_main.set_keep_above(True)
411
self.icontheme = gtk.icon_theme_get_default()
412
# we keep a reference pngloader around so that its in memory
413
# -> this avoid the issue that during the dapper->edgy upgrade
414
# the loaders move from /usr/lib/gtk/2.4.0/loaders to 2.10.0
415
self.pngloader = gtk.gdk.PixbufLoader("png")
417
self.svgloader = gtk.gdk.PixbufLoader("svg")
418
self.svgloader.close()
419
except gobject.GError as e:
420
logging.debug("svg pixbuf loader failed (%s)" % e)
424
self._webkit_view = webkit.WebView()
425
self.vbox_main.pack_end(self._webkit_view)
427
logging.exception("html widget")
428
self._webkit_view = None
429
self.window_main.realize()
430
self.window_main.window.set_functions(gtk.gdk.FUNC_MOVE)
431
self._opCacheProgress = GtkOpProgress(self.progressbar_cache)
432
self._acquireProgress = GtkAcquireProgressAdapter(self)
433
self._cdromProgress = GtkCdromProgressAdapter(self)
434
self._installProgress = GtkInstallProgressAdapter(self)
436
self.details_list = gtk.TreeStore(gobject.TYPE_STRING)
437
column = gtk.TreeViewColumn("")
438
render = gtk.CellRendererText()
439
column.pack_start(render, True)
440
column.add_attribute(render, "markup", 0)
441
self.treeview_details.append_column(column)
442
self.details_list.set_sort_column_id(0, gtk.SORT_ASCENDING)
443
self.treeview_details.set_model(self.details_list)
444
# Use italic style in the status labels
445
attrlist=pango.AttrList()
446
#attr = pango.AttrStyle(pango.STYLE_ITALIC, 0, -1)
447
attr = pango.AttrScale(pango.SCALE_SMALL, 0, -1)
448
attrlist.insert(attr)
449
self.label_status.set_property("attributes", attrlist)
450
# reasonable fault handler
451
sys.excepthook = self._handleException
453
def _handleException(self, type, value, tb):
454
# we handle the exception here, hand it to apport and run the
455
# apport gui manually after it because we kill u-m during the upgrade
456
# to prevent it from poping up for reboot notifications or FF restart
457
# notifications or somesuch
459
lines = traceback.format_exception(type, value, tb)
460
logging.error("not handled expection:\n%s" % "\n".join(lines))
461
# we can't be sure that apport will run in the middle of a upgrade
462
# so we still show a error message here
463
apport_crash(type, value, tb)
465
self.error(_("A fatal error occurred"),
466
_("Please report this as a bug (if you haven't already) and include the "
467
"files /var/log/dist-upgrade/main.log and "
468
"/var/log/dist-upgrade/apt.log "
469
"in your report. The upgrade has aborted.\n"
470
"Your original sources.list was saved in "
471
"/etc/apt/sources.list.distUpgrade."),
475
def getTerminal(self):
476
return DistUpgradeVteTerminal(self, self._term)
477
def getHtmlView(self):
478
return HtmlView(self._webkit_view)
480
def _key_press_handler(self, widget, keyev):
481
# user pressed ctrl-c
482
if len(keyev.string) == 1 and ord(keyev.string) == 3:
483
summary = _("Ctrl-c pressed")
484
msg = _("This will abort the operation and may leave the system "
485
"in a broken state. Are you sure you want to do that?")
486
res = self.askYesNoQuestion(summary, msg)
487
logging.warning("ctrl-c press detected, user decided to pass it "
492
def create_terminal(self):
493
" helper to create a vte terminal "
494
self._term = vte.Terminal()
495
self._term.connect("key-press-event", self._key_press_handler)
496
self._term.set_font_from_string("monospace 10")
497
self._term.connect("contents-changed", self._term_content_changed)
498
self._terminal_lines = []
499
self.hbox_custom.pack_start(self._term)
501
self.vscrollbar_terminal = gtk.VScrollbar()
502
self.vscrollbar_terminal.show()
503
self.hbox_custom.pack_start(self.vscrollbar_terminal)
504
self.vscrollbar_terminal.set_adjustment(self._term.get_adjustment())
506
self._terminal_log = open(os.path.join(self.logdir,"term.log"),"w")
508
# if something goes wrong (permission denied etc), use stdout
509
self._terminal_log = sys.stdout
512
def _term_content_changed(self, term):
513
" called when the *visible* part of the terminal changes "
514
# get the current visible text,
515
current_text = self._term.get_text(lambda a,b,c,d: True)
516
# see what we have currently and only print stuff that wasn't
519
for line in current_text.split("\n"):
520
new_lines.append(line)
521
if not line in self._terminal_lines:
522
self._terminal_log.write(line+"\n")
524
self._terminal_log.flush()
526
logging.exception("flush()")
527
self._terminal_lines = new_lines
528
def getAcquireProgress(self):
529
return self._acquireProgress
530
def getInstallProgress(self, cache):
531
self._installProgress._cache = cache
532
return self._installProgress
533
def getOpCacheProgress(self):
534
return self._opCacheProgress
535
def getCdromProgress(self):
536
return self._cdromProgress
537
def updateStatus(self, msg):
538
self.label_status.set_text("%s" % msg)
539
def hideStep(self, step):
540
image = getattr(self,"image_step%i" % step)
541
label = getattr(self,"label_step%i" % step)
542
#arrow = getattr(self,"arrow_step%i" % step)
545
def showStep(self, step):
546
image = getattr(self,"image_step%i" % step)
547
label = getattr(self,"label_step%i" % step)
551
size = gtk.ICON_SIZE_MENU
552
step = self.prev_step
554
image = getattr(self,"image_step%i" % step)
555
arrow = getattr(self,"arrow_step%i" % step)
556
image.set_from_stock(gtk.STOCK_CANCEL, size)
559
def setStep(self, step):
560
if self.icontheme.rescan_if_needed():
561
logging.debug("icon theme changed, re-reading")
562
# first update the "previous" step as completed
563
size = gtk.ICON_SIZE_MENU
564
attrlist=pango.AttrList()
566
image = getattr(self,"image_step%i" % self.prev_step)
567
label = getattr(self,"label_step%i" % self.prev_step)
568
arrow = getattr(self,"arrow_step%i" % self.prev_step)
569
label.set_property("attributes",attrlist)
570
image.set_from_stock(gtk.STOCK_APPLY, size)
573
self.prev_step = step
574
# show the an arrow for the current step and make the label bold
575
image = getattr(self,"image_step%i" % step)
576
label = getattr(self,"label_step%i" % step)
577
arrow = getattr(self,"arrow_step%i" % step)
578
# check if that step was not hidden with hideStep()
579
if not label.get_property("visible"):
583
attr = pango.AttrWeight(pango.WEIGHT_BOLD, 0, -1)
584
attrlist.insert(attr)
585
label.set_property("attributes",attrlist)
587
def information(self, summary, msg, extended_msg=None):
588
self.dialog_information.set_title("")
589
self.dialog_information.set_transient_for(self.window_main)
590
msg = "<big><b>%s</b></big>\n\n%s" % (summary,msg)
591
self.label_information.set_markup(msg)
592
if extended_msg != None:
593
buffer = self.textview_information.get_buffer()
594
buffer.set_text(extended_msg)
595
self.scroll_information.show()
597
self.scroll_information.hide()
598
self.dialog_information.realize()
599
self.dialog_information.window.set_functions(gtk.gdk.FUNC_MOVE)
600
self.dialog_information.run()
601
self.dialog_information.hide()
602
while gtk.events_pending():
605
def error(self, summary, msg, extended_msg=None):
606
self.dialog_error.set_title("")
607
self.dialog_error.set_transient_for(self.window_main)
608
#self.expander_terminal.set_expanded(True)
609
msg="<big><b>%s</b></big>\n\n%s" % (summary, msg)
610
self.label_error.set_markup(msg)
611
if extended_msg != None:
612
buffer = self.textview_error.get_buffer()
613
buffer.set_text(extended_msg)
614
self.scroll_error.show()
616
self.scroll_error.hide()
617
self.dialog_error.realize()
618
self.dialog_error.window.set_functions(gtk.gdk.FUNC_MOVE)
619
self.dialog_error.run()
620
self.dialog_error.hide()
623
def confirmChanges(self, summary, changes, demotions, downloadSize,
624
actions=None, removal_bold=True):
625
# FIXME: add a whitelist here for packages that we expect to be
626
# removed (how to calc this automatically?)
627
if not DistUpgradeView.confirmChanges(self, summary, changes,
628
demotions, downloadSize):
631
self.confirmChangesMessage += "\n\n<b>%s</b>" % \
632
_("To prevent data loss close all open "
633
"applications and documents.")
636
self.button_cancel_changes.set_use_stock(False)
637
self.button_cancel_changes.set_use_underline(True)
638
self.button_cancel_changes.set_label(actions[0])
639
self.button_confirm_changes.set_label(actions[1])
641
self.label_summary.set_markup("<big><b>%s</b></big>" % summary)
642
self.label_changes.set_markup(self.confirmChangesMessage)
643
# fill in the details
644
self.details_list.clear()
645
for (parent_text, details_list) in (
646
( _("No longer supported by Canonical (%s)"), self.demotions),
647
( _("<b>Downgrade (%s)</b>"), self.toDowngrade),
648
( _("Remove (%s)"), self.toRemove),
649
( _("No longer needed (%s)"), self.toRemoveAuto),
650
( _("Install (%s)"), self.toInstall),
651
( _("Upgrade (%s)"), self.toUpgrade),
654
node = self.details_list.append(None,
655
[parent_text % len(details_list)])
656
for pkg in details_list:
657
self.details_list.append(node, ["<b>%s</b> - %s" % (
658
pkg.name, glib.markup_escape_text(pkg.summary))])
660
self.dialog_changes.realize()
661
self.dialog_changes.set_transient_for(self.window_main)
662
self.dialog_changes.set_title("")
663
self.dialog_changes.window.set_functions(gtk.gdk.FUNC_MOVE|
665
res = self.dialog_changes.run()
666
self.dialog_changes.hide()
667
if res == gtk.RESPONSE_YES:
671
def askYesNoQuestion(self, summary, msg, default='No'):
672
msg = "<big><b>%s</b></big>\n\n%s" % (summary,msg)
673
dialog = gtk.MessageDialog(parent=self.window_main,
674
flags=gtk.DIALOG_MODAL,
675
type=gtk.MESSAGE_QUESTION,
676
buttons=gtk.BUTTONS_YES_NO)
679
dialog.set_default_response(gtk.RESPONSE_NO)
681
dialog.set_default_response(gtk.RESPONSE_YES)
682
dialog.set_markup(msg)
685
if res == gtk.RESPONSE_YES:
689
def confirmRestart(self):
690
self.dialog_restart.set_transient_for(self.window_main)
691
self.dialog_restart.set_title("")
692
self.dialog_restart.realize()
693
self.dialog_restart.window.set_functions(gtk.gdk.FUNC_MOVE)
694
res = self.dialog_restart.run()
695
self.dialog_restart.hide()
696
if res == gtk.RESPONSE_YES:
700
def processEvents(self):
701
while gtk.events_pending():
704
def pulseProgress(self, finished=False):
705
self.progressbar_cache.pulse()
707
self.progressbar_cache.set_fraction(1.0)
709
def on_window_main_delete_event(self, widget, event):
710
self.dialog_cancel.set_transient_for(self.window_main)
711
self.dialog_cancel.set_title("")
712
self.dialog_cancel.realize()
713
self.dialog_cancel.window.set_functions(gtk.gdk.FUNC_MOVE)
714
res = self.dialog_cancel.run()
715
self.dialog_cancel.hide()
716
if res == gtk.RESPONSE_CANCEL:
720
if __name__ == "__main__":
722
view = DistUpgradeViewGtk()
723
fp = GtkAcquireProgressAdapter(view)
724
ip = GtkInstallProgressAdapter(view)
727
for pkg in sys.argv[1:]:
728
if cache[pkg].is_installed:
729
cache[pkg].mark_delete()
731
cache[pkg].mark_install()
737
ip.conffile("TODO","TODO~")
738
view.getTerminal().call(["dpkg","--configure","-a"])
739
#view.getTerminal().call(["ls","-R","/usr"])
740
view.error("short","long",
741
"asfds afsdj af asdf asdf asf dsa fadsf asdf as fasf sextended\n"
742
"asfds afsdj af asdf asdf asf dsa fadsf asdf as fasf sextended\n"
743
"asfds afsdj af asdf asdf asf dsa fadsf asdf as fasf sextended\n"
744
"asfds afsdj af asdf asdf asf dsa fadsf asdf as fasf sextended\n"
745
"asfds afsdj af asdf asdf asf dsa fadsf asdf as fasf sextended\n"
746
"asfds afsdj af asdf asdf asf dsa fadsf asdf as fasf sextended\n"
747
"asfds afsdj af asdf asdf asf dsa fadsf asdf as fasf sextended\n"
749
view.confirmChanges("xx",[], 100)