~ubuntu-core-dev/software-properties/main

« back to all changes in this revision

Viewing changes to src/gnome-software-properties.in

  • Committer: Michael Vogt
  • Date: 2005-11-15 13:18:07 UTC
  • Revision ID: egon@top-20051115131807-12fada324eb74180
* initial revision (after accidently killing it)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/python2.4
 
2
# gnome-software-properties.in - edit /etc/apt/sources.list
 
3
#  
 
4
#  Copyright (c) 2004 Canonical
 
5
#                2004 Michiel Sikkes
 
6
#  
 
7
#  Author: Michiel Sikkes <michiel@eyesopened.nl>
 
8
#          Michael Vogt <mvo@debian.org>
 
9
 
10
#  This program is free software; you can redistribute it and/or 
 
11
#  modify it under the terms of the GNU General Public License as 
 
12
#  published by the Free Software Foundation; either version 2 of the
 
13
#  License, or (at your option) any later version.
 
14
 
15
#  This program is distributed in the hope that it will be useful,
 
16
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
17
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
18
#  GNU General Public License for more details.
 
19
 
20
#  You should have received a copy of the GNU General Public License
 
21
#  along with this program; if not, write to the Free Software
 
22
#  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 
23
#  USA
 
24
 
 
25
import pygtk
 
26
import sys
 
27
pygtk.require('2.0')
 
28
import gtk
 
29
import gtk.glade
 
30
import gconf
 
31
import gobject
 
32
import os
 
33
import gettext
 
34
import re
 
35
import string
 
36
import time
 
37
import tempfile
 
38
import subprocess
 
39
from optparse import OptionParser
 
40
import apt_pkg
 
41
        
 
42
sys.path.append("@prefix@/share/update-manager/python")
 
43
 
 
44
import aptsources
 
45
import dialog_add
 
46
import dialog_edit
 
47
import dialog_apt_key
 
48
from dialog_settings import dialog_settings
 
49
import shutil
 
50
 
 
51
 
 
52
(LIST_MARKUP, LIST_ENABLED, LIST_ENTRY_OBJ) = range(3)
 
53
 
 
54
class SoftwareConfigurator:
 
55
    
 
56
  def on_button_ok_clicked(self, widget, data):
 
57
    #self.save_periodic_config(periodicAptConfFile)
 
58
    
 
59
    location = "/etc/apt/sources.list"
 
60
    #backup first
 
61
    shutil.copy(location,location+".save")
 
62
    # write
 
63
    self.sourceslist.save(location)
 
64
 
 
65
    # write the source.list first, even if dirty=False, because
 
66
    # e.g. CD-ROM add does not set dirty variable even if it adds
 
67
    # something to the sources.list (but no reload needed)
 
68
    if self.dirty == False:
 
69
      gtk.main_quit()
 
70
      sys.exit(0)
 
71
    
 
72
    primary = "<span weight=\"bold\" size=\"larger\">" + _("Repositories "
 
73
              "changed") + "</span>"
 
74
    secondary = _("The repository information has changes. A backup copy of "
 
75
                  "your sources.list is stored in %s.save. "
 
76
                  "\n\n"
 
77
                  "You need to reload the package list from the servers "
 
78
                  "for your changes to take effect. Do you want to do this "
 
79
                  "now?") % location
 
80
    dialog = gtk.MessageDialog(self.main_window,gtk.DIALOG_MODAL,
 
81
                               gtk.MESSAGE_INFO,gtk.BUTTONS_YES_NO,"")
 
82
    dialog.set_markup(primary);
 
83
    dialog.format_secondary_text(secondary);
 
84
    #textview = gtk.TextView()
 
85
    #textview.set_editable(gtk.FALSE)
 
86
    #textbuffer = textview.get_buffer()
 
87
    #f = os.popen("/usr/bin/diff -u %s.save %s" % (location,location))
 
88
    #diff = f.read()
 
89
    #textbuffer.set_text(diff)
 
90
    #if f.close() != None:
 
91
    #  win = gtk.ScrolledWindow()
 
92
    #  win.set_policy(gtk.POLICY_AUTOMATIC,gtk.POLICY_AUTOMATIC)
 
93
    #  win.add(textview)
 
94
    #  win.set_size_request(400,300)
 
95
    #  win.show()
 
96
    #  dialog.vbox.pack_start(child = win, padding = 6)
 
97
    #  textview.show()
 
98
    res = dialog.run()
 
99
    dialog.destroy()
 
100
    if res == gtk.RESPONSE_YES:
 
101
      self.main_window.hide()
 
102
      # we are in "no-update" mode, this is used when the calling application
 
103
      # wants to deal with this itself
 
104
      if options.no_update:
 
105
        gtk.main_quit()
 
106
        sys.exit(1)
 
107
      child = subprocess.Popen(["/usr/sbin/synaptic", "--update-at-startup",
 
108
                                "--hide-main-window","--non-interactive"],
 
109
                               close_fds=True)
 
110
      # wait for the child to finish
 
111
      while child.poll() == None:
 
112
        time.sleep(0.05)
 
113
        while gtk.events_pending():
 
114
          gtk.main_iteration()
 
115
        gtk.main_quit()
 
116
        sys.exit(1)
 
117
    gtk.main_quit()
 
118
    sys.exit(0)
 
119
 
 
120
  def on_button_edit_clicked(self, widget, data):
 
121
    selection = self.sourceslist_view.get_selection()
 
122
    (model, iter) = selection.get_selected()
 
123
    source_entry = model.get_value(iter, LIST_ENTRY_OBJ)
 
124
    edit = dialog_edit.dialog_edit(self.main_window,self.sourceslist,
 
125
                                   source_entry)
 
126
    if edit.run() == gtk.RESPONSE_OK:
 
127
      self.reloadsources(self.sourceslist,self.matcher)
 
128
      self.dirty = True
 
129
 
 
130
  def on_sourceslist_selection_changed(self, selection, data):
 
131
    (model, iter) = selection.get_selected()
 
132
    if iter != None:
 
133
      self.button_del.set_sensitive(True)
 
134
      self.button_edit.set_sensitive(True)
 
135
    else:
 
136
      self.button_del.set_sensitive(False)
 
137
      self.button_edit.set_sensitive(False)
 
138
 
 
139
  #def on_sourceslist_row_activated(self, treeview, path, column, data):
 
140
  #  #print "on_row_activated()"
 
141
  #  model = treeview.get_model()
 
142
  #  source_entry = model.get_value(model.get_iter(path), LIST_ENTRY_OBJ)
 
143
  #  edit = dialog_edit.dialog_edit(self.main_window,self.sourceslist,
 
144
  #                                 source_entry)
 
145
  #  edit.run()
 
146
  #  self.reloadsources(self.sourceslist,self.matcher)
 
147
 
 
148
  def on_button_remove_clicked(self, widget, data):
 
149
    selection = self.sourceslist_view.get_selection()
 
150
    (model,a_iter) = selection.get_selected()
 
151
    if a_iter == None:
 
152
      return
 
153
    source = model.get_value(a_iter, LIST_ENTRY_OBJ)
 
154
    self.sourceslist.remove(source)
 
155
    self.reloadsources(self.sourceslist,self.matcher)
 
156
    self.dirty=True
 
157
 
 
158
  def on_button_add_clicked(self, widget, data):
 
159
    add = dialog_add.dialog_add(self.main_window,self.sourceslist)
 
160
    if add.run() == gtk.RESPONSE_OK:
 
161
      self.reloadsources(self.sourceslist,self.matcher)
 
162
      self.dirty=True
 
163
 
 
164
  def on_button_settings_clicked(self, widget, data):
 
165
    settings = dialog_settings(self.main_window, self.gladexml)
 
166
    settings.run()
 
167
    self.show_disabled = self.gconfclient.get_bool("/apps/gnome-software-properties/show_disabled")
 
168
    self.c_enabled.set_property("visible", self.show_disabled)
 
169
    self.reloadsources(self.sourceslist, self.matcher)
 
170
 
 
171
  def on_button_add_cdrom_clicked(self, widget, data):
 
172
    tmp = tempfile.NamedTemporaryFile()
 
173
    cmd = ["/usr/sbin/synaptic", "--hide-main-window",  "--non-interactive",
 
174
           "-o","Dir::Etc::sourcelist=%s" % tmp.name,"--ask-cdrom" ]
 
175
    self.main_window.set_sensitive(False)
 
176
    proc = subprocess.Popen(cmd)
 
177
    # wait for process to finish
 
178
    while proc.poll() == None:
 
179
      while gtk.events_pending():
 
180
        gtk.main_iteration()
 
181
      time.sleep(0.05)
 
182
    self.main_window.set_sensitive(True)
 
183
    # read tmp file with source name
 
184
    line = ""
 
185
    for x in open(tmp.name):
 
186
      line = x
 
187
    if line != "":
 
188
      self.sourceslist.list.append(aptsources.SourceEntry(line))
 
189
      self.reloadsources(self.sourceslist,self.matcher)
 
190
      #self.dirty=True # no need here
 
191
 
 
192
  def on_button_authentication_clicked(self, widget, data):
 
193
    auth = dialog_apt_key.dialog_apt_key(self.main_window)
 
194
    auth.run()
 
195
 
 
196
  def reloadsources(self, sourceslist, matcher):
 
197
    #self.meta = meta_data()
 
198
    self.sourcesstore.clear()
 
199
    for source in sourceslist.list:
 
200
      if source.invalid or (source.disabled and not self.show_disabled):
 
201
        continue
 
202
      (a_type,dist,comps) = matcher.match(source)
 
203
      contents = ""
 
204
      if source.comment != "":
 
205
        contents += "<i>%s</i>\n\n" % (source.comment)
 
206
      contents +="<big><b>%s </b></big> (%s) <small>\n%s</small>" % (dist,a_type, comps)
 
207
      iter = self.sourcesstore.append([contents, not source.disabled, source])
 
208
 
 
209
  def show_help(self, widget, data):
 
210
    print "self.show_help() called"
 
211
 
 
212
  # toggled on/off a source in the listview
 
213
  def toggled_enabled(self, renderer, path_string):
 
214
    iter = self.sourcesstore.get_iter_from_string(path_string)
 
215
    source = self.sourcesstore.get_value(iter, LIST_ENTRY_OBJ)
 
216
    self.dirty=True
 
217
    if self.sourcesstore.get_value(iter, LIST_ENABLED):
 
218
      self.sourcesstore.set_value(iter, LIST_ENABLED, False)
 
219
      source.set_enabled(False)
 
220
    else:
 
221
      self.sourcesstore.set_value(iter, LIST_ENABLED, True)
 
222
      source.set_enabled(True)
 
223
 
 
224
  def __init__(self):
 
225
    self.gconfclient = gconf.client_get_default()
 
226
 
 
227
    if os.path.exists("../data/gnome-software-properties.glade"):
 
228
      self.gladexml = gtk.glade.XML("../data/gnome-software-properties.glade")
 
229
    else:
 
230
      self.gladexml = gtk.glade.XML("@prefix@/share/update-manager/gnome-software-properties.glade")
 
231
 
 
232
    # do we show disabled sources?
 
233
    self.show_disabled = self.gconfclient.get_bool("/apps/gnome-software-properties/show_disabled")
 
234
    self.main_window = self.gladexml.get_widget("SoftwareConfigurator")
 
235
    # button on the right
 
236
    self.gladexml.signal_connect("on_button_edit_clicked",
 
237
                                 self.on_button_edit_clicked, None)
 
238
    self.button_edit = self.gladexml.get_widget("button_edit")
 
239
    self.button_del = self.gladexml.get_widget("button_remove")
 
240
 
 
241
    # Gets the treeview and creates a store for it.
 
242
    self.sourceslist_view = self.gladexml.get_widget("sourceslist")
 
243
    self.sourcesstore = gtk.ListStore(str, bool,gobject.TYPE_PYOBJECT)
 
244
    self.sourceslist_view.set_model(self.sourcesstore)
 
245
    #self.gladexml.signal_connect("on_sourceslist_row_activated",
 
246
    #                             self.on_sourceslist_row_activated, None)
 
247
    self.sourceslist_view.get_selection().connect("changed", self.on_sourceslist_selection_changed, None)
 
248
 
 
249
    # was something modified
 
250
    self.dirty=False
 
251
 
 
252
    # Create columns and append them.
 
253
    cr = gtk.CellRendererToggle()
 
254
    cr.set_property("activatable", True)
 
255
    cr.set_property("xpad", 10)
 
256
    cr.set_property("ypad", 10)
 
257
    cr.connect("toggled", self.toggled_enabled)
 
258
    self.c_enabled = gtk.TreeViewColumn("Enabled", cr, active=LIST_ENABLED)
 
259
    self.sourceslist_view.append_column(self.c_enabled)
 
260
    self.c_enabled.set_property("visible", self.show_disabled)
 
261
 
 
262
    tr = gtk.CellRendererText()
 
263
    tr.set_property("xpad", 10)
 
264
    tr.set_property("ypad", 10)
 
265
    c0 = gtk.TreeViewColumn("Entry", tr, markup=LIST_MARKUP)
 
266
    self.sourceslist_view.append_column(c0)
 
267
 
 
268
    self.sourceslist = aptsources.SourcesList("@sysconfdir@/apt/sources.list")
 
269
    self.matcher = aptsources.SourceEntryMatcher()
 
270
    # Empty and fill the sources store.
 
271
    self.reloadsources(self.sourceslist,self.matcher)
 
272
 
 
273
    self.main_window = self.gladexml.get_widget("SoftwareConfigurator")
 
274
    self.main_window.connect("delete_event", lambda widget,ev: gtk.main_quit())
 
275
 
 
276
    okbutton = self.gladexml.get_widget("button_ok")
 
277
    okbutton.connect("clicked", self.on_button_ok_clicked, None)
 
278
 
 
279
    cancelbutton = self.gladexml.get_widget("button_cancel")
 
280
    cancelbutton.connect("clicked", lambda w,v: gtk.main_quit(), None)
 
281
 
 
282
    self.gladexml.signal_connect("on_button_add_clicked", self.on_button_add_clicked, None)
 
283
    self.gladexml.signal_connect("on_button_add_cdrom_clicked", self.on_button_add_cdrom_clicked, None)
 
284
    self.gladexml.signal_connect("on_button_remove_clicked", self.on_button_remove_clicked, None)
 
285
    self.gladexml.signal_connect("on_button_authentication_clicked", self.on_button_authentication_clicked, None)
 
286
 
 
287
    # settings
 
288
    self.gladexml.signal_connect("on_button_settings_clicked", self.on_button_settings_clicked, None)
 
289
 
 
290
    self.main_window.show()
 
291
    if options.toplevel != None:
 
292
      # don't show the add-cdrom button for now
 
293
      # FIXME: on the long run interface with apt-pkg/cdrom.h
 
294
      b = self.gladexml.get_widget("button_add_cdrom")
 
295
      b.hide()
 
296
      toplevel = gtk.gdk.window_foreign_new(int(options.toplevel))
 
297
      self.main_window.window.set_transient_for(toplevel)
 
298
 
 
299
      
 
300
    # init the config
 
301
    apt_pkg.InitConfig()
 
302
 
 
303
  def main(self):
 
304
    gtk.main()
 
305
 
 
306
 
 
307
if __name__ == "__main__":
 
308
  APP="update-manager"
 
309
  DIR="@prefix@/share/locale"
 
310
  gettext.bindtextdomain(APP, DIR)
 
311
  gettext.textdomain(APP)
 
312
  gtk.glade.bindtextdomain(APP, DIR)
 
313
  gtk.glade.textdomain(APP)
 
314
  _ = gettext.gettext
 
315
  #print "Software Configurator started..."
 
316
 
 
317
  # add option parser
 
318
  parser = OptionParser()
 
319
  parser.add_option("-n", "--no-update", action="store_true",
 
320
                    dest="no_update", default=False,
 
321
                    help="No update on repository change (usefull if called "\
 
322
                         "from a external program).")
 
323
  parser.add_option("-t", "--toplevel", 
 
324
                    action="store", type="string", dest="toplevel",
 
325
                    help="Set x-window-id of the toplevel parent for the "\
 
326
                         "dialog (usefull for embedding)")
 
327
  
 
328
 
 
329
  (options, args) = parser.parse_args()
 
330
  ui = SoftwareConfigurator()
 
331
  ui.main()
 
332
  #print "Software Configurator ended..."