2
# gnome-software-properties.in - edit /etc/apt/sources.list
4
# Copyright (c) 2004 Canonical
7
# Author: Michiel Sikkes <michiel@eyesopened.nl>
8
# Michael Vogt <mvo@debian.org>
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.
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.
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
39
from optparse import OptionParser
42
sys.path.append("@prefix@/share/update-manager/python")
48
from dialog_settings import dialog_settings
52
(LIST_MARKUP, LIST_ENABLED, LIST_ENTRY_OBJ) = range(3)
54
class SoftwareConfigurator:
56
def on_button_ok_clicked(self, widget, data):
57
#self.save_periodic_config(periodicAptConfFile)
59
location = "/etc/apt/sources.list"
61
shutil.copy(location,location+".save")
63
self.sourceslist.save(location)
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:
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. "
77
"You need to reload the package list from the servers "
78
"for your changes to take effect. Do you want to do this "
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))
89
#textbuffer.set_text(diff)
90
#if f.close() != None:
91
# win = gtk.ScrolledWindow()
92
# win.set_policy(gtk.POLICY_AUTOMATIC,gtk.POLICY_AUTOMATIC)
94
# win.set_size_request(400,300)
96
# dialog.vbox.pack_start(child = win, padding = 6)
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:
107
child = subprocess.Popen(["/usr/sbin/synaptic", "--update-at-startup",
108
"--hide-main-window","--non-interactive"],
110
# wait for the child to finish
111
while child.poll() == None:
113
while gtk.events_pending():
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,
126
if edit.run() == gtk.RESPONSE_OK:
127
self.reloadsources(self.sourceslist,self.matcher)
130
def on_sourceslist_selection_changed(self, selection, data):
131
(model, iter) = selection.get_selected()
133
self.button_del.set_sensitive(True)
134
self.button_edit.set_sensitive(True)
136
self.button_del.set_sensitive(False)
137
self.button_edit.set_sensitive(False)
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,
146
# self.reloadsources(self.sourceslist,self.matcher)
148
def on_button_remove_clicked(self, widget, data):
149
selection = self.sourceslist_view.get_selection()
150
(model,a_iter) = selection.get_selected()
153
source = model.get_value(a_iter, LIST_ENTRY_OBJ)
154
self.sourceslist.remove(source)
155
self.reloadsources(self.sourceslist,self.matcher)
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)
164
def on_button_settings_clicked(self, widget, data):
165
settings = dialog_settings(self.main_window, self.gladexml)
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)
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():
182
self.main_window.set_sensitive(True)
183
# read tmp file with source name
185
for x in open(tmp.name):
188
self.sourceslist.list.append(aptsources.SourceEntry(line))
189
self.reloadsources(self.sourceslist,self.matcher)
190
#self.dirty=True # no need here
192
def on_button_authentication_clicked(self, widget, data):
193
auth = dialog_apt_key.dialog_apt_key(self.main_window)
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):
202
(a_type,dist,comps) = matcher.match(source)
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])
209
def show_help(self, widget, data):
210
print "self.show_help() called"
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)
217
if self.sourcesstore.get_value(iter, LIST_ENABLED):
218
self.sourcesstore.set_value(iter, LIST_ENABLED, False)
219
source.set_enabled(False)
221
self.sourcesstore.set_value(iter, LIST_ENABLED, True)
222
source.set_enabled(True)
225
self.gconfclient = gconf.client_get_default()
227
if os.path.exists("../data/gnome-software-properties.glade"):
228
self.gladexml = gtk.glade.XML("../data/gnome-software-properties.glade")
230
self.gladexml = gtk.glade.XML("@prefix@/share/update-manager/gnome-software-properties.glade")
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")
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)
249
# was something modified
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)
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)
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)
273
self.main_window = self.gladexml.get_widget("SoftwareConfigurator")
274
self.main_window.connect("delete_event", lambda widget,ev: gtk.main_quit())
276
okbutton = self.gladexml.get_widget("button_ok")
277
okbutton.connect("clicked", self.on_button_ok_clicked, None)
279
cancelbutton = self.gladexml.get_widget("button_cancel")
280
cancelbutton.connect("clicked", lambda w,v: gtk.main_quit(), None)
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)
288
self.gladexml.signal_connect("on_button_settings_clicked", self.on_button_settings_clicked, None)
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")
296
toplevel = gtk.gdk.window_foreign_new(int(options.toplevel))
297
self.main_window.window.set_transient_for(toplevel)
307
if __name__ == "__main__":
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)
315
#print "Software Configurator started..."
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)")
329
(options, args) = parser.parse_args()
330
ui = SoftwareConfigurator()
332
#print "Software Configurator ended..."