source: projects/synaptic/trunk/gtk/rgmainwindow.cc.orig @ 280

Revision 280, 107.2 KB checked in by yasumichi, 15 years ago (diff)

first import

Line 
1/* rgmainwindow.cc - main window of the app
2 *
3 * Copyright (c) 2001-2003 Conectiva S/A
4 *               2002-2004 Michael Vogt <mvo@debian.org>
5 *               2004 Canonical 
6
7 * Author: Alfredo K. Kojima <kojima@conectiva.com.br>
8 *         Michael Vogt <mvo@debian.org>
9 *         Gustavo Niemeyer <niemeyer@conectiva.com>
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License as
13 * published by the Free Software Foundation; either version 2 of the
14 * License, or (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
24 * USA
25 */
26
27#include "config.h"
28
29#include <cassert>
30#include <stdio.h>
31#include <ctype.h>
32#include <glade/glade.h>
33#include <gtk/gtk.h>
34#include <gdk/gdk.h>
35#include <gdk/gdkkeysyms.h>
36#include <cmath>
37#include <algorithm>
38#include <fstream>
39
40#include <sys/types.h>
41#include <sys/wait.h>
42
43#include <apt-pkg/strutl.h>
44#include <apt-pkg/error.h>
45#include <apt-pkg/configuration.h>
46#include <pwd.h>
47
48#include "raptoptions.h"
49#include "rconfiguration.h"
50#include "rgmainwindow.h"
51#include "rgfindwindow.h"
52#include "rgfiltermanager.h"
53#include "rpackagefilter.h"
54#include "raptoptions.h"
55
56#include "rgrepositorywin.h"
57#include "rgpreferenceswindow.h"
58#include "rgaboutpanel.h"
59#include "rgsummarywindow.h"
60#include "rgchangeswindow.h"
61#include "rgcdscanner.h"
62#include "rgpkgcdrom.h"
63#include "rgsetoptwindow.h"
64
65#include "rgfetchprogress.h"
66#include "rgpkgdetails.h"
67#include "rgcacheprogress.h"
68#include "rguserdialog.h"
69#include "rginstallprogress.h"
70#include "rgdummyinstallprogress.h"
71#include "rgdebinstallprogress.h"
72#include "rgterminstallprogress.h"
73#include "rgmisc.h"
74#include "sections_trans.h"
75
76// icons and pixmaps
77#include "synaptic.xpm"
78
79#include "i18n.h"
80
81
82
83enum { WHAT_IT_DEPENDS_ON,
84   WHAT_DEPENDS_ON_IT,
85   WHAT_IT_WOULD_DEPEND_ON,
86   WHAT_IT_PROVIDES,
87   WHAT_IT_SUGGESTS
88};
89
90enum { DEP_NAME_COLUMN,         /* text */
91   DEP_IS_NOT_AVAILABLE,        /* foreground-set */
92   DEP_IS_NOT_AVAILABLE_COLOR,  /* foreground */
93   DEP_PKG_INFO
94};                              /* additional info (install
95                                   not installed) as text */
96
97void RGMainWindow::changeView(int view, string subView)
98{
99   //cout << "RGMainWindow::changeView()" << endl;
100   if(view >= N_PACKAGE_VIEWS) {
101      //cerr << "changeView called with invalid view NR: " << view << endl;
102      view=0;
103   }
104
105   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(_viewButtons[view]), TRUE);
106     
107   RPackage *pkg = selectedPackage();
108   _blockActions = TRUE;
109
110   _lister->setView(view);
111
112   refreshSubViewList();
113
114   if(!subView.empty()) {
115      GtkTreeSelection* selection;
116      GtkTreeModel *model;
117      GtkTreeIter iter;
118      char *str;
119
120      setInterfaceLocked(TRUE);
121      GtkWidget *view = glade_xml_get_widget(_gladeXML, "treeview_subviews");
122      model = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
123      selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
124      if(gtk_tree_model_get_iter_first(model, &iter)) {
125         do {
126            gtk_tree_model_get(model, &iter, 0, &str, -1);
127            if(strcoll(str,subView.c_str()) == 0) {
128               gtk_tree_selection_select_iter(selection, &iter);
129               break;
130            }
131         } while(gtk_tree_model_iter_next(model, &iter));
132      }
133      _lister->reapplyFilter();
134      refreshTable(pkg);
135      setInterfaceLocked(FALSE);     
136   }
137   _blockActions = FALSE;
138   setStatusText();
139}
140
141void RGMainWindow::refreshSubViewList()
142{
143   string selected = selectedSubView();
144
145   vector<string> subViews = _lister->getSubViews();
146
147   gchar *str = g_strdup_printf("<b>%s</b>", _("All"));
148   subViews.insert(subViews.begin(), str);
149   g_free(str);
150   setTreeList("treeview_subviews", subViews, true);
151
152   if(!selected.empty()) {
153      GtkTreeSelection *selection;
154      GtkTreeModel *model;
155      GtkTreeIter iter;
156      const char *str = NULL;
157
158      selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(_subViewList));
159      model = gtk_tree_view_get_model(GTK_TREE_VIEW(_subViewList));
160      PangoFontDescription *font = pango_font_description_from_string("Sans 9");
161      gtk_widget_modify_font(_subViewList, font);
162      bool ok =  gtk_tree_model_get_iter_first(model, &iter);
163      while(ok) {
164         gtk_tree_model_get(model, &iter, 0, &str, -1);
165         if(str && strcoll(str, selected.c_str()) == 0) {
166            gtk_tree_selection_select_iter(selection, &iter);
167            return;
168         }
169         ok = gtk_tree_model_iter_next(model, &iter);
170      }
171   } else {
172      // we auto set to "All" when we have gtk2.4 (without the list is
173      // too slow)
174      GtkTreeModel *model;
175      GtkTreeSelection *selection;
176      GtkTreeIter iter;
177
178      selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(_subViewList));
179      model = gtk_tree_view_get_model(GTK_TREE_VIEW(_subViewList));
180      gtk_tree_model_get_iter_first(model, &iter);
181      gtk_tree_selection_select_iter(selection, &iter);
182   }
183}
184
185
186RPackage *RGMainWindow::selectedPackage()
187{
188   if (_pkgList == NULL)
189      return NULL;
190
191   GtkTreeSelection *selection;
192   GtkTreeIter iter;
193   RPackage *pkg = NULL;
194   GList *li = NULL;
195   GList *list = NULL;
196
197   selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(_treeView));
198   list = gtk_tree_selection_get_selected_rows(selection, &_pkgList);
199   if (list == NULL) // Empty.
200      return NULL;
201
202   // We are only interessted in the last element
203   li = g_list_last(list);
204   gtk_tree_model_get_iter(_pkgList, &iter, (GtkTreePath *) (li->data));
205
206   gtk_tree_model_get(_pkgList, &iter, PKG_COLUMN, &pkg, -1);
207
208
209   // free the list
210   g_list_foreach(list, (void (*)(void *, void *))gtk_tree_path_free, NULL);
211   g_list_free(list);
212
213
214   return pkg;
215}
216
217string RGMainWindow::selectedSubView()
218{
219   GtkTreeSelection *selection;
220   GtkTreeModel *model;
221   GtkTreeIter iter;
222   gchar *subView = NULL;
223   static string ret = "(no selection)";
224
225   selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(_subViewList));
226   if (selection != NULL) {
227      if (gtk_tree_selection_get_selected(selection, &model, &iter)) {
228         gtk_tree_model_get(model, &iter, 0, &subView, -1);
229         
230         // check if first item is selected ("All")
231         gchar *str=gtk_tree_model_get_string_from_iter(model, &iter);
232         if(str[0] == '0' || subView == NULL)
233            ret = "";
234         else
235            ret = subView;
236         g_free(str);
237         g_free(subView);
238      }
239   }
240
241   return ret;
242}
243
244
245bool RGMainWindow::showErrors()
246{
247   return _userDialog->showErrors();
248}
249
250void RGMainWindow::notifyChange(RPackage *pkg)
251{
252   if (pkg != NULL)
253      refreshTable(pkg);
254
255   setStatusText();
256}
257
258void RGMainWindow::forgetNewPackages()
259{
260   int row = 0;
261   while (row < _lister->viewPackagesSize()) {
262      RPackage *elem = _lister->getViewPackage(row);
263      if (elem->getFlags() && RPackage::FNew)
264         elem->setNew(false);
265   }
266   _roptions->forgetNewPackages();
267}
268
269
270void RGMainWindow::refreshTable(RPackage *selectedPkg)
271{
272   //cout << "RGMainWindow::refreshTable(): " << selectedPkg << endl;
273
274   string selected = selectedSubView();
275   _lister->setSubView(utf8(selected.c_str()));
276
277   _pkgList = GTK_TREE_MODEL(gtk_pkg_list_new(_lister));
278   gtk_tree_view_set_model(GTK_TREE_VIEW(_treeView),
279                           GTK_TREE_MODEL(_pkgList));
280
281   gtk_adjustment_value_changed(
282         gtk_tree_view_get_hadjustment(GTK_TREE_VIEW(_treeView)));
283   gtk_adjustment_value_changed(
284         gtk_tree_view_get_vadjustment(GTK_TREE_VIEW(_treeView)));
285
286   // set selected pkg to be selected again
287   if(selectedPkg != NULL) {
288      GtkTreeIter iter;
289      RPackage *pkg;
290     
291      // make sure we have the keyboard focus after the refresh
292      gtk_widget_grab_focus(_treeView);
293
294      // find and select the pkg we are looking for
295      bool ok =  gtk_tree_model_get_iter_first(_pkgList, &iter);
296      while(ok) {
297         gtk_tree_model_get(_pkgList, &iter, PKG_COLUMN, &pkg, -1);
298         if(pkg == selectedPkg) {
299            GtkTreePath* path = gtk_tree_model_get_path(_pkgList, &iter);
300            gtk_tree_view_set_cursor(GTK_TREE_VIEW(_treeView), path,
301                                     NULL, false);
302            gtk_tree_path_free(path);
303            break;
304         }
305
306         ok = gtk_tree_model_iter_next(_pkgList, &iter);
307      }
308   }
309
310   setStatusText();
311}
312
313void RGMainWindow::updatePackageInfo(RPackage *pkg)
314{
315   if (_blockActions)
316      return;
317
318   //cout << "RGMainWindow::updatePackageInfo(): " << pkg << endl;
319
320   // set everything to non-sensitive (for both pkg != NULL && pkg == NULL)
321   gtk_widget_set_sensitive(_keepM, FALSE);
322   gtk_widget_set_sensitive(_installM, FALSE);
323   gtk_widget_set_sensitive(_reinstallM, FALSE);
324   gtk_widget_set_sensitive(_pkgupgradeM, FALSE);
325   gtk_widget_set_sensitive(_removeM, FALSE);
326   gtk_widget_set_sensitive(_purgeM, FALSE);
327   gtk_widget_set_sensitive(_pkgReconfigureM, FALSE);
328   gtk_widget_set_sensitive(_pkgHelpM, FALSE);
329   gtk_widget_set_sensitive(_pkginfo, FALSE);
330   gtk_widget_set_sensitive(_dl_changelogM, FALSE);
331   gtk_widget_set_sensitive(_detailsM, FALSE);
332   gtk_widget_set_sensitive(_propertiesB, FALSE);
333   gtk_widget_set_sensitive(_overrideVersionM, FALSE);
334   gtk_widget_set_sensitive(_pinM, FALSE);
335   gtk_text_buffer_set_text(_pkgCommonTextBuffer,
336                            _("No package is selected.\n"), -1);
337
338   setStatusText();
339
340   // return if no pkg is selected
341   if (!pkg)
342      return;
343
344//    cout <<   pkg->label() << endl;
345//    cout <<   pkg->component() << endl;
346//   cout << "trusted: " << pkg->isTrusted() << endl;
347 
348   // set menu according to pkg status
349   int flags = pkg->getFlags();
350
351   // changelog and properties are always visible
352   gtk_widget_set_sensitive(_dl_changelogM, TRUE);
353   gtk_widget_set_sensitive(_detailsM, TRUE);
354   gtk_widget_set_sensitive(_propertiesB, TRUE);
355   gtk_widget_set_sensitive(_pinM, TRUE);
356
357   // set info
358   gtk_widget_set_sensitive(_pkginfo, true);
359   RGPkgDetailsWindow::fillInValues(this, pkg);
360   // work around a stupid gtk-bug (see debian #279447)
361   gtk_widget_queue_resize(glade_xml_get_widget(_gladeXML,"viewport_pkginfo"));
362
363   if(_pkgDetails != NULL)
364      RGPkgDetailsWindow::fillInValues(_pkgDetails,pkg, true);
365
366   // Pin, if a pin is set, we skip all other checks and return
367   if( flags & RPackage::FPinned) {
368      _blockActions = TRUE;
369      gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(_pinM), true);
370      _blockActions = FALSE;
371      return;
372   } else {
373      _blockActions = TRUE;
374      gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(_pinM), false);
375      _blockActions = FALSE;
376   }
377
378   // enable unmark if a action is performed with the pkg
379   if((flags & RPackage::FInstall)   || (flags & RPackage::FNewInstall) ||
380      (flags & RPackage::FReInstall) || (flags & RPackage::FUpgrade) ||
381      (flags & RPackage::FDowngrade) || (flags & RPackage::FRemove) ||
382      (flags & RPackage::FPurge))
383      gtk_widget_set_sensitive(_keepM, TRUE);
384   // enable install if outdated or not insalled
385   if(!(flags & RPackage::FInstalled))
386      gtk_widget_set_sensitive(_installM, TRUE);
387   // enable reinstall if installed and installable and not outdated
388   if(flags & RPackage::FInstalled
389      && !(flags & RPackage::FNotInstallable)
390      && !(flags & RPackage::FOutdated))
391      gtk_widget_set_sensitive(_reinstallM, TRUE);
392   // enable upgrade is outdated
393   if(flags & RPackage::FOutdated)
394      gtk_widget_set_sensitive(_pkgupgradeM, TRUE);
395   // enable remove if package is installed
396   if(flags & RPackage::FInstalled)
397      gtk_widget_set_sensitive(_removeM, TRUE);
398
399   // enable purge if package is installed or has residual config
400   if(flags & RPackage::FInstalled || flags & RPackage::FResidualConfig)
401      gtk_widget_set_sensitive(_purgeM, TRUE);
402   // enable help if package is installed
403   if( flags & RPackage::FInstalled)
404      gtk_widget_set_sensitive(_pkgHelpM, TRUE);
405   // enable debconf if package is installed and depends on debconf
406   if( flags & RPackage::FInstalled && (pkg->dependsOn("debconf") ||
407                                        pkg->dependsOn("debconf-i18n")))
408       gtk_widget_set_sensitive(_pkgReconfigureM, TRUE);
409
410   if(pkg->getAvailableVersions().size() > 1)
411      gtk_widget_set_sensitive(_overrideVersionM, TRUE);
412
413   // set the "keep" menu icon according to the current status
414   GtkWidget *img;
415   if (!(flags & RPackage::FInstalled))
416      img = get_gtk_image("package-available");
417   else
418      img = get_gtk_image("package-installed-updated");
419   gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(_keepM), img);
420
421
422}
423
424
425// install a specific version
426void RGMainWindow::cbInstallFromVersion(GtkWidget *self, void *data)
427{
428   //cout << "RGMainWindow::cbInstallFromVersion()" << endl;
429
430   RGMainWindow *me = (RGMainWindow *) data;
431   RPackage *pkg = me->selectedPackage();
432   if(pkg == NULL)
433      return;
434
435   RGGladeUserDialog dia(me,"change_version");
436
437   GtkWidget *label = glade_xml_get_widget(dia.getGladeXML(),
438                                           "label_text");
439   gchar *str_name = g_strdup_printf(_("Select the version of %s that should be forced for installation"), pkg->name());
440   gchar *str = g_strdup_printf("<big><b>%s</b></big>\n\n%s", str_name,
441                                _("The package manager always selects the most applicable version available. If you force a different version from the default one, errors in the dependency handling can occur."));
442   gtk_label_set_markup(GTK_LABEL(label), str);
443   g_free(str_name);
444   g_free(str);
445   
446   GtkWidget *optionMenu = glade_xml_get_widget(dia.getGladeXML(),
447                                        "optionmenu_available_versions");
448
449   GtkWidget *menu = gtk_menu_new();
450   GtkWidget *item;
451
452   int canidateNr = 0;
453   vector<pair<string, string> > versions = pkg->getAvailableVersions();
454   for(unsigned int i=0;i<versions.size();i++) {
455      gchar *str = g_strdup_printf("%s (%s)",
456                                   versions[i].first.c_str(),
457                                   versions[i].second.c_str() );
458      item = gtk_menu_item_new_with_label(str);
459      if(versions[i].first == pkg->availableVersion())
460         canidateNr = i;
461      gtk_widget_show(item);
462      gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
463      //cout << "got: " << str << endl;
464      g_free(str);
465   }
466   gtk_option_menu_set_menu(GTK_OPTION_MENU(optionMenu), menu);
467   gtk_option_menu_set_history(GTK_OPTION_MENU(optionMenu), canidateNr);
468   if(!dia.run()) {
469      //cout << "cancel" << endl;
470      return;    // user clicked cancel
471   }
472
473   int nr = gtk_option_menu_get_history(GTK_OPTION_MENU(optionMenu));
474
475   pkg->setNotify(false);
476   // nr-1 here as we add a "do not override" to the option menu
477   pkg->setVersion(versions[nr].first.c_str());
478   me->pkgAction(PKG_INSTALL_FROM_VERSION);
479   
480
481   if (!(pkg->getFlags() & RPackage::FInstall))
482      pkg->unsetVersion();   // something went wrong
483
484   pkg->setNotify(true);
485}
486
487bool RGMainWindow::askStateChange(RPackageLister::pkgState state,
488                                  vector<RPackage *> exclude)
489{
490   vector<RPackage *> toKeep;
491   vector<RPackage *> toInstall;
492   vector<RPackage *> toReInstall;
493   vector<RPackage *> toUpgrade;
494   vector<RPackage *> toDowngrade;
495   vector<RPackage *> toRemove;
496   vector<RPackage *> notAuthenticated;
497
498   bool ask = _config->FindB("Synaptic::AskRelated", true);
499
500   // ask if the user really want this changes
501   bool changed = true;
502   if (ask && _lister->getStateChanges(state, toKeep, toInstall, toReInstall,
503                                       toUpgrade, toRemove, toDowngrade,
504                                       notAuthenticated, exclude)) {
505      RGChangesWindow changes(this);
506      changes.confirm(_lister, toKeep, toInstall, toReInstall,
507                      toUpgrade, toRemove, toDowngrade, notAuthenticated);
508      int res = gtk_dialog_run(GTK_DIALOG(changes.window()));
509      if( res != GTK_RESPONSE_OK) {
510         // canceled operation
511         _lister->restoreState(state);
512         // if a operation was canceled, we discard all errors from this
513         // operation too
514         _error->Discard();
515         changed = false;
516      }
517   }
518
519   return changed;
520}
521
522#if 0
523void RGMainWindow::installAllWeakDepends(RPackage *pkg,
524                                         pkgCache::Dep::DepType type)
525{
526   //cout << "RGMainWindow::installWeakDepends()" << endl;
527   if(pkg == NULL) return;
528   
529   vector<DepInformation> deps = pkg->enumDeps();
530   for(unsigned int i=0;i<deps.size();i++) {
531      if(deps[i].type == type) {
532         if(!deps[i].isVirtual) {
533            RPackage *newpkg = (RPackage *) _lister->getPackage(deps[i].name);
534            pkgInstallHelper(newpkg);
535         }
536      }
537   }
538}
539#endif
540
541void RGMainWindow::pkgAction(RGPkgAction action)
542{
543   GtkTreeSelection *selection;
544   GtkTreeIter iter;
545   GList *li, *list;
546
547   setInterfaceLocked(TRUE);
548   _blockActions = TRUE;
549
550   // get list of selected pkgs
551   selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(_treeView));
552   list = li = gtk_tree_selection_get_selected_rows(selection, &_pkgList);
553
554   // save pkg state
555   RPackageLister::pkgState state;
556   bool ask = _config->FindB("Synaptic::AskRelated", true);
557
558   // we always save the state (for undo)
559   _lister->saveState(state);
560   if (ask)
561      _lister->unregisterObserver(this);
562   _lister->notifyCachePreChange();
563
564   // We block notifications in setInstall() and friends, since it'd
565   // kill the algorithm in a long loop with many selected packages.
566   _lister->notifyPreChange(NULL);
567
568   // do the work
569   vector<RPackage *> exclude;
570   vector<RPackage *> instPkgs;
571   RPackage *pkg = NULL;
572
573   while (li != NULL) {
574      gtk_tree_model_get_iter(_pkgList, &iter, (GtkTreePath *) (li->data));
575      gtk_tree_model_get(_pkgList, &iter, PKG_COLUMN, &pkg, -1);
576      li = g_list_next(li);
577      if (pkg == NULL)
578         continue;
579
580      pkg->setNotify(false);
581
582      // needed for the stateChange
583      exclude.push_back(pkg);
584      /* do the dirty deed */
585      switch (action) {
586         case PKG_KEEP:        // keep
587            pkgKeepHelper(pkg);
588            break;
589         case PKG_INSTALL:     // install
590            instPkgs.push_back(pkg);
591            pkgInstallHelper(pkg, false);
592#if 0 // handled in the pkgCache now (where it belongs)
593            if(_config->FindB("Synaptic::UseRecommends", false)) {
594               installAllWeakDepends(pkg, pkgCache::Dep::Recommends);
595            }
596            if(_config->FindB("Synaptic::UseSuggests", false)) {
597               installAllWeakDepends(pkg, pkgCache::Dep::Suggests);
598            }
599#endif
600            break;
601         case PKG_INSTALL_FROM_VERSION:     // install with specific version
602            pkgInstallHelper(pkg, false);
603            break;
604         case PKG_REINSTALL:      // reinstall
605            instPkgs.push_back(pkg);
606            pkgInstallHelper(pkg, false, true);
607            break;
608         case PKG_DELETE:      // delete
609            pkgRemoveHelper(pkg);
610            break;
611         case PKG_PURGE:       // purge
612            pkgRemoveHelper(pkg, true);
613            break;
614         case PKG_DELETE_WITH_DEPS:
615            pkgRemoveHelper(pkg, true, true);
616            break;
617         default:
618            cout << "uh oh!!!!!!!!!" << endl;
619            break;
620      }
621
622      pkg->setNotify(true);
623   }
624
625   // Do it just once, otherwise it'd kill a long installation list.
626   if (!_lister->check())
627      _lister->fixBroken();
628
629   _lister->notifyPostChange(NULL);
630
631   _lister->notifyCachePostChange();
632
633   bool changed = askStateChange(state, exclude);
634
635   if (changed) {
636      bool failed=false;
637      // check for failed installs, if a installs fails, restore old state
638      // as the Fixer may do wired thinks when trying to resolve the problem
639      if (action == PKG_INSTALL) {
640         failed = checkForFailedInst(instPkgs);
641         if(failed)
642            _lister->restoreState(state);
643      }
644      // if everything is fine, save it as new undo state
645      if(!failed)
646         _lister->saveUndoState(state);
647   }
648
649   if (ask)
650      _lister->registerObserver(this);
651
652   g_list_foreach(list, (void (*)(void *, void *))gtk_tree_path_free, NULL);
653   g_list_free(list);
654
655   _blockActions = FALSE;
656   setInterfaceLocked(FALSE);
657   refreshTable(pkg);
658}
659
660bool RGMainWindow::checkForFailedInst(vector<RPackage *> instPkgs)
661{
662   string failedReason;
663   bool failed = false;
664   for (unsigned int i = 0; i < instPkgs.size(); i++) {
665      RPackage *pkg = instPkgs[i];
666      if (pkg == NULL)
667         continue;
668      if (!(pkg->getFlags() & RPackage::FInstall)) {
669         failed = true;
670         failedReason += string(pkg->name()) + ":\n";
671         failedReason += pkg->showWhyInstBroken();
672         failedReason += "\n";
673         pkg->setKeep();
674         pkg->unsetVersion();
675         _lister->notifyChange(pkg);
676      }
677   }
678   if (failed) {
679      RGGladeUserDialog dia(this,"unmet");
680      GtkWidget *tv = glade_xml_get_widget(dia.getGladeXML(),
681                                           "textview");
682      GtkTextBuffer *tb = gtk_text_view_get_buffer(GTK_TEXT_VIEW(tv));
683      gtk_text_buffer_set_text(tb, utf8(failedReason.c_str()), -1);
684      dia.run();
685      // we informaed the user about the problem, we can clear the
686      // apt error stack
687      // CHECKME: is this discard here really needed?
688      _error->Discard();
689   }
690     
691   return failed;
692}
693
694RGMainWindow::RGMainWindow(RPackageLister *packLister, string name)
695   : RGGladeWindow(NULL, name), _lister(packLister), _pkgList(0),
696     _treeView(0), _tasksWin(0), _iconLegendPanel(0), _pkgDetails(0),
697     _logView(0), _installProgress(0), _fetchProgress(0)
698{
699   assert(_win);
700
701   _blockActions = false;
702   _unsavedChanges = false;
703   _interfaceLocked = 0;
704
705   _lister->registerObserver(this);
706   _tooltips = gtk_tooltips_new();
707
708   _toolbarStyle = (GtkToolbarStyle) _config->FindI("Synaptic::ToolbarState",
709                                                    (int)GTK_TOOLBAR_BOTH);
710
711
712   buildInterface();
713   _userDialog = new RGUserDialog(this);
714
715   packLister->setUserDialog(_userDialog);
716
717   packLister->setProgressMeter(_cacheProgress);
718   _findWin = NULL;
719   _setOptWin = NULL;
720   _sourcesWin = NULL;
721   _configWin = NULL;
722   _aboutPanel = NULL;
723   _fmanagerWin = NULL;
724
725   GValue value = { 0, };
726   g_value_init(&value, G_TYPE_STRING);
727   g_object_get_property(G_OBJECT(gtk_settings_get_default()),
728                         "gtk-font-name", &value);
729   _config->Set("Volatile::orginalFontName", g_value_get_string(&value));
730   if (_config->FindB("Synaptic::useUserFont")) {
731      g_value_set_string(&value, _config->Find("Synaptic::FontName").c_str());
732      g_object_set_property(G_OBJECT(gtk_settings_get_default()),
733                            "gtk-font-name", &value);
734   }
735   g_value_unset(&value);
736
737   // apply the proxy settings
738   RGPreferencesWindow::applyProxySettings();
739}
740
741
742
743// needed for the buildTreeView function
744struct mysort {
745   bool operator() (const pair<int, GtkTreeViewColumn *> &x,
746                    const pair<int, GtkTreeViewColumn *> &y) {
747      return x.first < y.first;
748}};
749
750
751void RGMainWindow::buildTreeView()
752{
753   GtkCellRenderer *renderer;
754   GtkTreeViewColumn *column, *name_column = NULL;
755   GtkTreeSelection *selection;
756   vector<pair<int, GtkTreeViewColumn *> > all_columns;
757   int pos = 0;
758   bool visible;
759
760   // remove old tree columns
761   if (_treeView) {
762      GList *columns = gtk_tree_view_get_columns(GTK_TREE_VIEW(_treeView));
763      for (GList * li = g_list_first(columns); li != NULL;
764           li = g_list_next(li)) {
765         gtk_tree_view_remove_column(GTK_TREE_VIEW(_treeView),
766                                     GTK_TREE_VIEW_COLUMN(li->data));
767      }
768      // need to free the list here
769      g_list_free(columns);
770   }
771
772   _treeView = glade_xml_get_widget(_gladeXML, "treeview_packages");
773   assert(_treeView);
774   gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(_treeView),TRUE);
775
776   gtk_tree_view_set_search_column(GTK_TREE_VIEW(_treeView), NAME_COLUMN);
777   selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(_treeView));
778   gtk_tree_selection_set_mode(selection, GTK_SELECTION_MULTIPLE);
779
780   /* Status(pixmap) column */
781   pos = _config->FindI("Synaptic::statusColumnPos", 0);
782   visible = _config->FindI("Synaptic::statusColumnVisible", true);
783   if(visible) {
784      renderer = gtk_cell_renderer_pixbuf_new();
785      // TRANSLATORS: Column header for the column "Status" in the package list
786      column = gtk_tree_view_column_new_with_attributes(_("S"), renderer,
787                                                        "pixbuf",
788                                                        PIXMAP_COLUMN, NULL);
789      gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
790      gtk_tree_view_column_set_fixed_width(column, 20);
791      //gtk_tree_view_insert_column(GTK_TREE_VIEW(_treeView), column, pos);
792      gtk_tree_view_column_set_sort_column_id(column, COLOR_COLUMN);
793      all_columns.push_back(pair<int, GtkTreeViewColumn *>(pos, column));
794   }
795
796   /* supported(pixmap) column */
797   pos = _config->FindI("Synaptic::supportedColumnPos", 1);
798   visible = _config->FindI("Synaptic::supportedColumnVisible", true);
799   if(visible) {
800      renderer = gtk_cell_renderer_pixbuf_new();
801      column = gtk_tree_view_column_new_with_attributes(" ", renderer,
802                                                        "pixbuf",
803                                                        SUPPORTED_COLUMN,
804                                                        NULL);
805      gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
806      gtk_tree_view_column_set_fixed_width(column, 20);
807      //gtk_tree_view_insert_column(GTK_TREE_VIEW(_treeView), column, pos);
808      gtk_tree_view_column_set_sort_column_id(column, SUPPORTED_COLUMN);
809      all_columns.push_back(pair<int, GtkTreeViewColumn *>(pos, column));
810   }
811
812
813   /* Package name */
814   pos = _config->FindI("Synaptic::nameColumnPos", 2);
815   visible = _config->FindI("Synaptic::nameColumnVisible", true);
816   if (visible) {
817      renderer = gtk_cell_renderer_text_new();
818      gtk_cell_renderer_text_set_fixed_height_from_font(GTK_CELL_RENDERER_TEXT
819                                                        (renderer), 1);
820      name_column = column =
821         gtk_tree_view_column_new_with_attributes(_("Package"), renderer,
822                                                  "markup", NAME_COLUMN,
823                                                  //"text", NAME_COLUMN,
824                                                  "background-gdk",
825                                                  COLOR_COLUMN, NULL);
826      gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
827      gtk_tree_view_column_set_fixed_width(column, 200);
828
829      //gtk_tree_view_insert_column(GTK_TREE_VIEW(_treeView), column, pos);
830      all_columns.push_back(pair<int, GtkTreeViewColumn *>(pos, column));
831      gtk_tree_view_column_set_resizable(column, TRUE);
832      gtk_tree_view_column_set_sort_column_id(column, NAME_COLUMN);
833   }
834
835   // section
836   pos = _config->FindI("Synaptic::sectionColumnPos", 2);
837   visible = _config->FindI("Synaptic::sectionColumnVisible", false);
838   if (visible) {
839      renderer = gtk_cell_renderer_text_new();
840      gtk_cell_renderer_text_set_fixed_height_from_font(GTK_CELL_RENDERER_TEXT
841                                                        (renderer), 1);
842      column =
843         gtk_tree_view_column_new_with_attributes(_("Section"),
844                                                  renderer, "text",
845                                                  SECTION_COLUMN,
846                                                  "background-gdk",
847                                                  COLOR_COLUMN, NULL);
848      gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
849      gtk_tree_view_column_set_fixed_width(column, 130);
850      //gtk_tree_view_insert_column (GTK_TREE_VIEW(_treeView), column, pos);
851      all_columns.push_back(pair<int, GtkTreeViewColumn *>(pos, column));
852      gtk_tree_view_column_set_sort_column_id(column, SECTION_COLUMN);
853      gtk_tree_view_column_set_resizable(column, TRUE);
854   }
855
856   // component
857   pos = _config->FindI("Synaptic::componentColumnPos", 3);
858   visible = _config->FindI("Synaptic::componentColumnVisible", false);
859   if (visible) {
860      renderer = gtk_cell_renderer_text_new();
861      gtk_cell_renderer_text_set_fixed_height_from_font(GTK_CELL_RENDERER_TEXT
862                                                        (renderer), 1);
863      column =
864         gtk_tree_view_column_new_with_attributes(_("Component"),
865                                                  renderer, "text",
866                                                  COMPONENT_COLUMN,
867                                                  "background-gdk",
868                                                  COLOR_COLUMN, NULL);
869      gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
870      gtk_tree_view_column_set_fixed_width(column, 130);
871      //gtk_tree_view_insert_column (GTK_TREE_VIEW(_treeView), column, pos);
872      all_columns.push_back(pair<int, GtkTreeViewColumn *>(pos, column));
873      gtk_tree_view_column_set_sort_column_id(column, COMPONENT_COLUMN);
874      gtk_tree_view_column_set_resizable(column, TRUE);
875   }
876
877
878   /* Installed Version */
879   pos = _config->FindI("Synaptic::instVerColumnPos", 4);
880   visible = _config->FindI("Synaptic::instVerColumnVisible", true);
881   if (visible) {
882      renderer = gtk_cell_renderer_text_new();
883      gtk_cell_renderer_text_set_fixed_height_from_font(GTK_CELL_RENDERER_TEXT
884                                                        (renderer), 1);
885      column =
886         gtk_tree_view_column_new_with_attributes(_("Installed Version"),
887                                                  renderer, "text",
888                                                  INSTALLED_VERSION_COLUMN,
889                                                  "background-gdk",
890                                                  COLOR_COLUMN, NULL);
891      gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
892      gtk_tree_view_column_set_fixed_width(column, 130);
893      //gtk_tree_view_insert_column (GTK_TREE_VIEW(_treeView), column, pos);
894      all_columns.push_back(pair<int, GtkTreeViewColumn *>(pos, column));
895      gtk_tree_view_column_set_sort_column_id(column, INSTALLED_VERSION_COLUMN);
896      gtk_tree_view_column_set_resizable(column, TRUE);
897   }
898
899   /* Available Version */
900   pos = _config->FindI("Synaptic::availVerColumnPos", 5);
901   visible = _config->FindI("Synaptic::availVerColumnVisible", true);
902   if (visible) {
903      renderer = gtk_cell_renderer_text_new();
904      gtk_cell_renderer_text_set_fixed_height_from_font(GTK_CELL_RENDERER_TEXT
905                                                        (renderer), 1);
906      column =
907         gtk_tree_view_column_new_with_attributes(_("Latest Version"),
908                                                  renderer, "text",
909                                                  AVAILABLE_VERSION_COLUMN,
910                                                  "background-gdk",
911                                                  COLOR_COLUMN, NULL);
912      gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
913      gtk_tree_view_column_set_fixed_width(column, 130);
914      //gtk_tree_view_insert_column (GTK_TREE_VIEW (_treeView), column, pos);
915      all_columns.push_back(pair<int, GtkTreeViewColumn *>(pos, column));
916      gtk_tree_view_column_set_sort_column_id(column, AVAILABLE_VERSION_COLUMN);
917      gtk_tree_view_column_set_resizable(column, TRUE);
918   }
919   // installed size
920   pos = _config->FindI("Synaptic::instSizeColumnPos", 6);
921   visible = _config->FindI("Synaptic::instSizeColumnVisible", false);
922   if (visible) {
923      /* Installed size */
924      renderer = gtk_cell_renderer_text_new();
925      gtk_cell_renderer_text_set_fixed_height_from_font(GTK_CELL_RENDERER_TEXT
926                                                        (renderer), 1);
927      g_object_set(G_OBJECT(renderer), "xalign",1.0, "xpad", 10, NULL);
928      column = gtk_tree_view_column_new_with_attributes(_("Size"), renderer,
929                                                        "text",
930                                                        PKG_SIZE_COLUMN,
931                                                        "background-gdk",
932                                                        COLOR_COLUMN, NULL);
933      gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
934      gtk_tree_view_column_set_fixed_width(column, 80);
935      //gtk_tree_view_insert_column (GTK_TREE_VIEW(_treeView), column, pos);
936      all_columns.push_back(pair<int, GtkTreeViewColumn *>(pos, column));
937      gtk_tree_view_column_set_resizable(column, TRUE);
938      gtk_tree_view_column_set_sort_column_id(column, PKG_SIZE_COLUMN);
939   }
940
941   pos = _config->FindI("Synaptic::downloadSizeColumnPos", 7);
942   visible = _config->FindI("Synaptic::downloadSizeColumnVisible", false);
943   if (visible) {
944      /* Download size */
945      renderer = gtk_cell_renderer_text_new();
946      gtk_cell_renderer_text_set_fixed_height_from_font(GTK_CELL_RENDERER_TEXT
947                                                        (renderer), 1);
948      g_object_set(G_OBJECT(renderer), "xalign",1.0, "xpad", 10, NULL);
949      column = gtk_tree_view_column_new_with_attributes(_("Download"),
950                                                        renderer,"text",
951                                                        PKG_DOWNLOAD_SIZE_COLUMN,
952                                                        "background-gdk",
953                                                        COLOR_COLUMN, NULL);
954      gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
955      gtk_tree_view_column_set_fixed_width(column, 80);
956      //gtk_tree_view_insert_column (GTK_TREE_VIEW(_treeView), column, pos);
957      all_columns.push_back(pair<int, GtkTreeViewColumn *>(pos, column));
958      gtk_tree_view_column_set_resizable(column, TRUE);
959      gtk_tree_view_column_set_sort_column_id(column, PKG_DOWNLOAD_SIZE_COLUMN);
960   }
961
962
963   /* Description */
964   pos = _config->FindI("Synaptic::descrColumnPos", 8);
965   visible = _config->FindI("Synaptic::descrColumnVisible", true);
966   if (visible) {
967      renderer = gtk_cell_renderer_text_new();
968      gtk_cell_renderer_text_set_fixed_height_from_font(GTK_CELL_RENDERER_TEXT
969                                                        (renderer), 1);
970      column =
971         gtk_tree_view_column_new_with_attributes(_("Description"), renderer,
972                                                  "text", DESCR_COLUMN,
973                                                  "background-gdk",
974                                                  COLOR_COLUMN, NULL);
975      gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
976      gtk_tree_view_column_set_fixed_width(column, 500);
977      //gtk_tree_view_insert_column (GTK_TREE_VIEW (_treeView), column, pos);
978      all_columns.push_back(pair<int, GtkTreeViewColumn *>(pos, column));
979      gtk_tree_view_column_set_resizable(column, TRUE);
980   }
981   // now sort and insert in order
982   sort(all_columns.begin(), all_columns.end(), mysort());
983   for (unsigned int i = 0; i < all_columns.size(); i++) {
984      gtk_tree_view_append_column(GTK_TREE_VIEW(_treeView),
985                                  GTK_TREE_VIEW_COLUMN(all_columns[i].second));
986   }
987   // now set name column to expander column
988   if (name_column)
989      gtk_tree_view_set_expander_column(GTK_TREE_VIEW(_treeView), name_column);
990
991   g_object_set(G_OBJECT(_treeView),
992                "fixed_height_mode", TRUE,
993                NULL);
994
995   _pkgList = GTK_TREE_MODEL(gtk_pkg_list_new(_lister));
996   gtk_tree_view_set_model(GTK_TREE_VIEW(_treeView), _pkgList);
997   gtk_tree_view_set_search_column(GTK_TREE_VIEW(_treeView), NAME_COLUMN);
998}
999
1000void RGMainWindow::buildInterface()
1001{
1002   GtkWidget *img, *menuitem, *widget, *button;
1003
1004   // here is a pointer to rgmainwindow for every widget that needs it
1005   g_object_set_data(G_OBJECT(_win), "me", this);
1006
1007
1008   GdkPixbuf *icon = gdk_pixbuf_new_from_xpm_data((const char **)
1009                                                  synaptic_xpm);
1010   gtk_window_set_icon(GTK_WINDOW(_win), icon);
1011
1012   gtk_window_resize(GTK_WINDOW(_win),
1013                     _config->FindI("Synaptic::windowWidth", 800),
1014                     _config->FindI("Synaptic::windowHeight", 600));
1015   gtk_window_move(GTK_WINDOW(_win),
1016                   _config->FindI("Synaptic::windowX", 100),
1017                   _config->FindI("Synaptic::windowY", 100));
1018   if(_config->FindB("Synaptic::Maximized",false))
1019      gtk_window_maximize(GTK_WINDOW(_win));
1020   RGFlushInterface();
1021
1022
1023   glade_xml_signal_connect_data(_gladeXML,
1024                                 "on_about_activate",
1025                                 G_CALLBACK(cbShowAboutPanel), this);
1026
1027   glade_xml_signal_connect_data(_gladeXML,
1028                                 "on_introduction_activate",
1029                                 G_CALLBACK(cbShowWelcomeDialog), this);
1030
1031
1032   glade_xml_signal_connect_data(_gladeXML,
1033                                 "on_icon_legend_activate",
1034                                 G_CALLBACK(cbShowIconLegendPanel), this);
1035
1036   glade_xml_signal_connect_data(_gladeXML,
1037                                 "on_help_activate",
1038                                 G_CALLBACK(cbHelpAction), this);
1039
1040   glade_xml_signal_connect_data(_gladeXML,
1041                                 "on_update_packages",
1042                                 G_CALLBACK(cbUpdateClicked), this);
1043
1044   glade_xml_signal_connect_data(_gladeXML,
1045                                 "on_button_details_clicked",
1046                                 G_CALLBACK(cbDetailsWindow), this);
1047
1048   _propertiesB = glade_xml_get_widget(_gladeXML, "button_details");
1049   assert(_propertiesB);
1050   _upgradeB = glade_xml_get_widget(_gladeXML, "button_upgrade");
1051   _upgradeM = glade_xml_get_widget(_gladeXML, "upgrade1");
1052   glade_xml_signal_connect_data(_gladeXML,
1053                                 "on_upgrade_packages",
1054                                 G_CALLBACK(cbUpgradeClicked), this);
1055
1056   if (_config->FindB("Synaptic::NoUpgradeButtons", false) == true) {
1057      gtk_widget_hide(_upgradeB);
1058      widget = glade_xml_get_widget(_gladeXML, "alignment_upgrade");
1059      gtk_widget_hide(widget);
1060   }
1061
1062   _proceedB = glade_xml_get_widget(_gladeXML, "button_procceed");
1063   _proceedM = glade_xml_get_widget(_gladeXML, "menu_proceed");
1064   glade_xml_signal_connect_data(_gladeXML,
1065                                 "on_proceed_clicked",
1066                                 G_CALLBACK(cbProceedClicked), this);
1067
1068   _fixBrokenM = glade_xml_get_widget(_gladeXML, "fix_broken_packages");
1069   glade_xml_signal_connect_data(_gladeXML,
1070                                 "on_fix_broken_packages",
1071                                 G_CALLBACK(cbFixBrokenClicked), this);
1072
1073   glade_xml_signal_connect_data(_gladeXML,
1074                                 "on_preferences_activate",
1075                                 G_CALLBACK(cbShowConfigWindow), this);
1076
1077   glade_xml_signal_connect_data(_gladeXML,
1078                                 "on_set_option_activate",
1079                                 G_CALLBACK(cbShowSetOptWindow), this);
1080
1081   glade_xml_signal_connect_data(_gladeXML,
1082                                 "on_repositories_activate",
1083                                 G_CALLBACK(cbShowSourcesWindow), this);
1084
1085   glade_xml_signal_connect_data(_gladeXML,
1086                                 "on_exit_activate",
1087                                 G_CALLBACK(closeWin), this);
1088
1089   glade_xml_signal_connect_data(_gladeXML,
1090                                 "on_edit_filter_activate",
1091                                 G_CALLBACK(cbShowFilterManagerWindow), this);
1092
1093   glade_xml_signal_connect_data(_gladeXML,
1094                                 "on_button_pkghelp_clicked",
1095                                 G_CALLBACK(cbPkgHelpClicked), this);
1096   _pkgHelpM = glade_xml_get_widget(_gladeXML, "menu_documentation");
1097   assert(_pkgHelpM);
1098
1099   glade_xml_signal_connect_data(_gladeXML,
1100                                 "on_button_pkgreconfigure_clicked",
1101                                 G_CALLBACK(cbPkgReconfigureClicked), this);
1102   _pkgReconfigureM = glade_xml_get_widget(_gladeXML, "menu_configure");
1103   assert(_pkgReconfigureM);
1104
1105   glade_xml_signal_connect_data(_gladeXML,
1106                                 "on_search_name",
1107                                 G_CALLBACK(cbFindToolClicked), this);
1108
1109   glade_xml_signal_connect_data(_gladeXML,
1110                                 "on_undo1_activate",
1111                                 G_CALLBACK(cbUndoClicked), this);
1112
1113   glade_xml_signal_connect_data(_gladeXML,
1114                                 "on_redo1_activate",
1115                                 G_CALLBACK(cbRedoClicked), this);
1116
1117   glade_xml_signal_connect_data(_gladeXML,
1118                                 "on_clear_all_changes_activate",
1119                                 G_CALLBACK(cbClearAllChangesClicked), this);
1120
1121   glade_xml_signal_connect_data(_gladeXML,
1122                                 "on_tasks_activate",
1123                                 G_CALLBACK(cbTasksClicked), this);
1124
1125   glade_xml_signal_connect_data(_gladeXML,
1126                                 "on_open_activate",
1127                                 G_CALLBACK(cbOpenClicked), this);
1128
1129   glade_xml_signal_connect_data(_gladeXML,
1130                                 "on_save_activate",
1131                                 G_CALLBACK(cbSaveClicked), this);
1132
1133   glade_xml_signal_connect_data(_gladeXML,
1134                                 "on_view_commit_log_activate",
1135                                 G_CALLBACK(cbViewLogClicked), this);
1136
1137
1138   glade_xml_signal_connect_data(_gladeXML,
1139                                 "on_save_as_activate",
1140                                 G_CALLBACK(cbSaveAsClicked), this);
1141
1142   widget = _detailsM = glade_xml_get_widget(_gladeXML, "menu_details");
1143   assert(_detailsM);
1144   g_object_set_data(G_OBJECT(widget), "me", this);
1145
1146   widget = _keepM = glade_xml_get_widget(_gladeXML, "menu_keep");
1147   assert(_keepM);
1148   img = get_gtk_image("package-available");
1149   gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(widget), img);
1150   g_object_set_data(G_OBJECT(widget), "me", this);
1151
1152   widget = _installM = glade_xml_get_widget(_gladeXML, "menu_install");
1153   assert(_installM);
1154   img = get_gtk_image("package-install");
1155   gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(widget), img);
1156   g_object_set_data(G_OBJECT(widget), "me", this);
1157
1158   widget = _reinstallM = glade_xml_get_widget(_gladeXML, "menu_reinstall");
1159   assert(_reinstallM);
1160   img = get_gtk_image("package-reinstall");
1161   gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(widget), img);
1162   g_object_set_data(G_OBJECT(widget), "me", this);
1163
1164   widget = _pkgupgradeM = glade_xml_get_widget(_gladeXML, "menu_upgrade");
1165   assert(_upgradeM);
1166   img = get_gtk_image("package-upgrade");
1167   gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(widget), img);
1168   g_object_set_data(G_OBJECT(widget), "me", this);
1169
1170   widget = _removeM = glade_xml_get_widget(_gladeXML, "menu_remove");
1171   assert(_removeM);
1172   img = get_gtk_image("package-remove");
1173   gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(widget), img);
1174   g_object_set_data(G_OBJECT(widget), "me", this);
1175
1176   widget = _purgeM = glade_xml_get_widget(_gladeXML, "menu_purge");
1177   assert(_purgeM);
1178   img = get_gtk_image("package-purge");
1179   gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(widget), img);
1180   g_object_set_data(G_OBJECT(widget), "me", this);
1181
1182#if 0
1183   _remove_w_depsM = glade_xml_get_widget(_gladeXML, "menu_remove_with_deps");
1184   assert(_remove_w_depsM);
1185#endif
1186
1187   _dl_changelogM = glade_xml_get_widget(_gladeXML, "menu_download_changelog");
1188   assert(_dl_changelogM);
1189#ifdef HAVE_RPM
1190   gtk_widget_hide(_purgeM);
1191   gtk_widget_hide(_pkgReconfigureM);
1192   gtk_widget_hide(_pkgHelpM);
1193   gtk_widget_hide(_dl_changelogM);
1194   gtk_widget_hide(glade_xml_get_widget(_gladeXML,"menu_changelog_separator"));
1195   gtk_widget_hide(glade_xml_get_widget(_gladeXML,"separator_debian"));
1196#endif
1197   
1198   if(!FileExists(_config->Find("Synaptic::taskHelperProg","/usr/bin/tasksel")))
1199      gtk_widget_hide(glade_xml_get_widget(_gladeXML, "menu_tasks"));
1200
1201   // Workaround for a bug in libglade.
1202   button = glade_xml_get_widget(_gladeXML, "button_update");
1203   gtk_tool_item_set_tooltip(GTK_TOOL_ITEM(button), GTK_TOOLTIPS(_tooltips),
1204                             _("Reload the package information to become "
1205                               "informed about new, removed or upgraded "
1206                               "software packages."), "");
1207
1208   button = glade_xml_get_widget(_gladeXML, "button_upgrade");
1209   gtk_tool_item_set_tooltip(GTK_TOOL_ITEM(button), GTK_TOOLTIPS(_tooltips),
1210                        _("Mark all possible upgrades"), "");
1211
1212   button = glade_xml_get_widget(_gladeXML, "button_procceed");
1213   gtk_tool_item_set_tooltip(GTK_TOOL_ITEM(button), GTK_TOOLTIPS(_tooltips),
1214                        _("Apply all marked changes"), "");
1215
1216   _pkgCommonTextView = glade_xml_get_widget(_gladeXML, "text_descr");
1217   assert(_pkgCommonTextView);
1218   gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(_pkgCommonTextView),
1219                               GTK_WRAP_WORD);
1220   _pkgCommonTextBuffer = gtk_text_view_get_buffer(
1221                               GTK_TEXT_VIEW(_pkgCommonTextView));
1222
1223   glade_xml_signal_connect_data(_gladeXML,
1224                                 "on_menu_action_keep",
1225                                 G_CALLBACK(cbPkgAction),
1226                                 GINT_TO_POINTER(PKG_KEEP));
1227
1228   glade_xml_signal_connect_data(_gladeXML,
1229                                 "on_menu_action_install",
1230                                 G_CALLBACK(cbPkgAction),
1231                                 GINT_TO_POINTER(PKG_INSTALL));
1232   // callback same as for install
1233   widget = glade_xml_get_widget(_gladeXML, "menu_upgrade");
1234   assert(widget);
1235   g_object_set_data(G_OBJECT(widget), "me", this);
1236
1237   widget = glade_xml_get_widget(_gladeXML, "menu_reinstall");
1238   assert(widget);
1239   g_object_set_data(G_OBJECT(widget), "me", this);
1240   glade_xml_signal_connect_data(_gladeXML,
1241                                 "on_menu_action_reinstall",
1242                                 G_CALLBACK(cbPkgAction),
1243                                 GINT_TO_POINTER(PKG_REINSTALL));
1244   
1245   glade_xml_signal_connect_data(_gladeXML,
1246                                 "on_menu_action_delete",
1247                                 G_CALLBACK(cbPkgAction),
1248                                 GINT_TO_POINTER(PKG_DELETE));
1249#if 0
1250   widget = glade_xml_get_widget(_gladeXML, "menu_remove_with_deps");
1251   assert(widget);
1252   g_object_set_data(G_OBJECT(widget), "me", this);
1253   glade_xml_signal_connect_data(_gladeXML,
1254                                 "on_menu_action_delete_with_deps",
1255                                 G_CALLBACK(cbPkgAction),
1256                                 GINT_TO_POINTER(PKG_DELETE_WITH_DEPS));
1257#endif
1258
1259   widget = glade_xml_get_widget(_gladeXML, "menu_purge");
1260   assert(widget);
1261   glade_xml_signal_connect_data(_gladeXML,
1262                                 "on_menu_action_purge",
1263                                 G_CALLBACK(cbPkgAction),
1264                                 GINT_TO_POINTER(PKG_PURGE));
1265
1266   _pinM = glade_xml_get_widget(_gladeXML, "menu_hold");
1267   glade_xml_signal_connect_data(_gladeXML,
1268                                 "on_menu_pin",
1269                                 G_CALLBACK(cbMenuPinClicked), this);
1270
1271   _overrideVersionM = glade_xml_get_widget(_gladeXML,
1272                                            "menu_override_version");
1273   assert(_overrideVersionM);
1274   glade_xml_signal_connect_data(_gladeXML,
1275                                 "on_menu_override_version_activate",
1276                                 G_CALLBACK(cbInstallFromVersion), this);
1277
1278
1279   // only if pkg help is enabled
1280#ifndef SYNAPTIC_PKG_HOLD
1281   gtk_widget_hide(_pinM);
1282//    widget = glade_xml_get_widget(_gladeXML, "separator_hold");
1283//    if (widget != NULL)
1284//       gtk_widget_hide(widget);
1285#endif
1286
1287   _pkginfo = glade_xml_get_widget(_gladeXML, "notebook_pkginfo");
1288   assert(_pkginfo);
1289   GtkWidget *box = glade_xml_get_widget(_gladeXML, "vbox_pkgdescr");
1290   if(_config->FindB("Synaptic::ShowAllPkgInfoInMain", false)) {
1291      gtk_notebook_set_show_tabs(GTK_NOTEBOOK(_pkginfo), TRUE);
1292      gtk_container_set_border_width(GTK_CONTAINER(box), 12);
1293   } else {
1294      gtk_container_set_border_width(GTK_CONTAINER(box), 0);
1295   }
1296#ifndef HAVE_RPM
1297   gtk_widget_show(glade_xml_get_widget(_gladeXML,"scrolledwindow_filelist"));
1298#endif
1299
1300   _vpaned = glade_xml_get_widget(_gladeXML, "vpaned_main");
1301   assert(_vpaned);
1302   _hpaned = glade_xml_get_widget(_gladeXML, "hpaned_main");
1303   assert(_hpaned);
1304   // If the pane position is restored before the window is shown, it's
1305   // not restored in the same place as it was.
1306   if(!_config->FindB("Volatile::HideMainwindow", false))
1307      show();
1308   RGFlushInterface();
1309   gtk_paned_set_position(GTK_PANED(_vpaned),
1310                          _config->FindI("Synaptic::vpanedPos", 140));
1311   gtk_paned_set_position(GTK_PANED(_hpaned),
1312                          _config->FindI("Synaptic::hpanedPos", 200));
1313
1314
1315   // build the treeview
1316   buildTreeView();
1317
1318   g_signal_connect(G_OBJECT(_treeView), "button-press-event",
1319                    (GCallback) cbPackageListClicked, this);
1320
1321   GtkTreeSelection *select;
1322   select = gtk_tree_view_get_selection(GTK_TREE_VIEW(_treeView));
1323   //gtk_tree_selection_set_mode (select, GTK_SELECTION_MULTIPLE);
1324   g_signal_connect(G_OBJECT(select), "changed",
1325                    G_CALLBACK(cbSelectedRow), this);
1326   g_signal_connect(G_OBJECT(_treeView), "row-activated",
1327                    G_CALLBACK(cbPackageListRowActivated), this);
1328
1329   glade_xml_signal_connect_data(_gladeXML,
1330                                 "on_add_cdrom_activate",
1331                                 G_CALLBACK(cbAddCDROM), this);
1332
1333   glade_xml_signal_connect_data(_gladeXML,
1334                                 "on_download_changelog_activate",
1335                                 G_CALLBACK(cbChangelogDialog),
1336                                 this);
1337
1338   /* --------------------------------------------------------------- */
1339
1340   // toolbar menu code
1341   button = glade_xml_get_widget(_gladeXML, "menu_toolbar_pixmaps");
1342   gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(button), FALSE);
1343   g_object_set_data(G_OBJECT(button), "me", this);
1344   g_signal_connect(G_OBJECT(button),
1345                    "activate",
1346                    G_CALLBACK(cbMenuToolbarClicked),
1347                    GINT_TO_POINTER(GTK_TOOLBAR_ICONS));
1348   if (_toolbarStyle == GTK_TOOLBAR_ICONS)
1349      gtk_menu_item_activate(GTK_MENU_ITEM(button));
1350
1351   button = glade_xml_get_widget(_gladeXML, "menu_toolbar_text");
1352   gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(button), FALSE);
1353   g_object_set_data(G_OBJECT(button), "me", this);
1354   g_signal_connect(G_OBJECT(button),
1355                    "activate",
1356                    G_CALLBACK(cbMenuToolbarClicked),
1357                    GINT_TO_POINTER(GTK_TOOLBAR_TEXT));
1358   if (_toolbarStyle == GTK_TOOLBAR_TEXT)
1359      gtk_menu_item_activate(GTK_MENU_ITEM(button));
1360
1361   button = glade_xml_get_widget(_gladeXML, "menu_toolbar_both");
1362   gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(button), FALSE);
1363   g_object_set_data(G_OBJECT(button), "me", this);
1364   g_signal_connect(G_OBJECT(button),
1365                    "activate",
1366                    G_CALLBACK(cbMenuToolbarClicked),
1367                    GINT_TO_POINTER(GTK_TOOLBAR_BOTH));
1368   if (_toolbarStyle == GTK_TOOLBAR_BOTH)
1369      gtk_menu_item_activate(GTK_MENU_ITEM(button));
1370
1371   button = glade_xml_get_widget(_gladeXML, "menu_toolbar_beside");
1372   gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(button), FALSE);
1373   g_object_set_data(G_OBJECT(button), "me", this);
1374   g_signal_connect(G_OBJECT(button),
1375                    "activate",
1376                    G_CALLBACK(cbMenuToolbarClicked),
1377                    GINT_TO_POINTER(GTK_TOOLBAR_BOTH_HORIZ));
1378   if (_toolbarStyle == GTK_TOOLBAR_BOTH_HORIZ)
1379      gtk_menu_item_activate(GTK_MENU_ITEM(button));
1380
1381   button = glade_xml_get_widget(_gladeXML, "menu_toolbar_hide");
1382   gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(button), FALSE);
1383   g_object_set_data(G_OBJECT(button), "me", this);
1384   g_signal_connect(G_OBJECT(button),
1385                    "activate",
1386                    G_CALLBACK(cbMenuToolbarClicked),
1387                    GINT_TO_POINTER(TOOLBAR_HIDE));
1388   if (_toolbarStyle == TOOLBAR_HIDE)
1389      gtk_menu_item_activate(GTK_MENU_ITEM(button));
1390
1391   // build popup-menu
1392   _popupMenu = gtk_menu_new();
1393   menuitem = gtk_image_menu_item_new_with_label(_("Unmark"));
1394   img = gtk_image_new_from_stock(GTK_STOCK_APPLY, GTK_ICON_SIZE_MENU);
1395   gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), img);
1396   g_object_set_data(G_OBJECT(menuitem), "me", this);
1397   g_signal_connect(menuitem, "activate",
1398                    (GCallback) cbPkgAction, (void *)PKG_KEEP);
1399   gtk_menu_shell_append(GTK_MENU_SHELL(_popupMenu), menuitem);
1400
1401   menuitem = gtk_image_menu_item_new_with_label(_("Mark for Installation"));
1402   img = get_gtk_image("package-install");
1403   gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), img);
1404   g_object_set_data(G_OBJECT(menuitem), "me", this);
1405   g_signal_connect(menuitem, "activate",
1406                    (GCallback) cbPkgAction, (void *)PKG_INSTALL);
1407   gtk_menu_shell_append(GTK_MENU_SHELL(_popupMenu), menuitem);
1408
1409   menuitem = gtk_image_menu_item_new_with_label(_("Mark for Reinstallation"));
1410   img = get_gtk_image("package-reinstall");
1411   gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem),img);
1412   g_object_set_data(G_OBJECT(menuitem),"me",this);
1413   g_signal_connect(menuitem, "activate",
1414                    (GCallback) cbPkgAction, (void*)PKG_REINSTALL);
1415   gtk_menu_shell_append(GTK_MENU_SHELL(_popupMenu), menuitem);
1416
1417
1418   menuitem = gtk_image_menu_item_new_with_label(_("Mark for Upgrade"));
1419   img = get_gtk_image("package-upgrade");
1420   gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem),img);
1421   g_object_set_data(G_OBJECT(menuitem), "me", this);
1422   g_signal_connect(menuitem, "activate",
1423                    (GCallback) cbPkgAction, (void *)PKG_INSTALL);
1424   gtk_menu_shell_append(GTK_MENU_SHELL(_popupMenu), menuitem);
1425
1426   menuitem = gtk_image_menu_item_new_with_label(_("Mark for Removal"));
1427   img = get_gtk_image("package-remove");
1428   gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), img);
1429   g_object_set_data(G_OBJECT(menuitem), "me", this);
1430   g_signal_connect(menuitem, "activate",
1431                    (GCallback) cbPkgAction, (void *)PKG_DELETE);
1432   gtk_menu_shell_append(GTK_MENU_SHELL(_popupMenu), menuitem);
1433
1434
1435   menuitem = gtk_image_menu_item_new_with_label(_("Mark for Complete Removal"));
1436   img = get_gtk_image("package-purge");
1437   gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), img);
1438   g_object_set_data(G_OBJECT(menuitem), "me", this);
1439   g_signal_connect(menuitem, "activate",
1440                    (GCallback) cbPkgAction, (void *)PKG_PURGE);
1441   gtk_menu_shell_append(GTK_MENU_SHELL(_popupMenu), menuitem);
1442#ifdef HAVE_RPM
1443   gtk_widget_hide(menuitem);
1444#endif
1445
1446#if 0  // disabled for now
1447   menuitem = gtk_image_menu_item_new_with_label(_("Remove Including Orphaned Dependencies"));
1448   img = get_gtk_image("package-remove");
1449   gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), img);
1450   g_object_set_data(G_OBJECT(menuitem), "me", this);
1451   g_signal_connect(menuitem, "activate",
1452                    (GCallback) cbPkgAction,
1453                    (void *)PKG_DELETE_WITH_DEPS);
1454   gtk_menu_shell_append(GTK_MENU_SHELL(_popupMenu), menuitem);
1455
1456   menuitem = gtk_separator_menu_item_new();
1457   gtk_menu_shell_append(GTK_MENU_SHELL(_popupMenu), menuitem);
1458
1459   menuitem = gtk_check_menu_item_new_with_label(_("Hold Current Version"));
1460   g_object_set_data(G_OBJECT(menuitem), "me", this);
1461   g_signal_connect(menuitem, "activate", (GCallback) cbMenuPinClicked, this);
1462   gtk_menu_shell_append(GTK_MENU_SHELL(_popupMenu), menuitem);
1463#endif
1464
1465   menuitem = gtk_separator_menu_item_new ();
1466   gtk_menu_shell_append(GTK_MENU_SHELL(_popupMenu), menuitem);
1467
1468   menuitem = gtk_image_menu_item_new_with_label(_("Properties"));
1469   img = gtk_image_new_from_stock(GTK_STOCK_PROPERTIES,GTK_ICON_SIZE_MENU);
1470   gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), img);
1471   g_object_set_data(G_OBJECT(menuitem), "me", this);
1472   g_signal_connect(menuitem, "activate",
1473                    (GCallback) cbDetailsWindow, this);
1474   gtk_menu_shell_append(GTK_MENU_SHELL(_popupMenu), menuitem);
1475
1476#ifndef HAVE_RPM // recommends stuff
1477   menuitem = gtk_separator_menu_item_new ();
1478   gtk_menu_shell_append(GTK_MENU_SHELL(_popupMenu), menuitem);
1479
1480   menuitem = gtk_image_menu_item_new_with_label(_("Mark Recommended for Installation"));
1481   g_object_set_data(G_OBJECT(menuitem), "me", this);
1482   gtk_menu_shell_append(GTK_MENU_SHELL(_popupMenu), menuitem);
1483
1484   menuitem = gtk_image_menu_item_new_with_label(_("Mark Suggested for Installation"));
1485   g_object_set_data(G_OBJECT(menuitem), "me", this);
1486   gtk_menu_shell_append(GTK_MENU_SHELL(_popupMenu), menuitem);
1487#endif
1488
1489   gtk_widget_show(_popupMenu);
1490
1491   // attach progress bar
1492   _progressBar = glade_xml_get_widget(_gladeXML, "progressbar_main");
1493   assert(_progressBar);
1494   _statusL = glade_xml_get_widget(_gladeXML, "label_status");
1495   assert(_statusL);
1496
1497   gtk_misc_set_alignment(GTK_MISC(_statusL), 0.0f, 0.0f);
1498   gtk_widget_set_usize(GTK_WIDGET(_statusL), 100, -1);
1499   _cacheProgress = new RGCacheProgress(_progressBar, _statusL);
1500   assert(_cacheProgress);
1501
1502
1503   //FIXME/MAYBE: create this dynmaic?!?
1504   //    for (vector<string>::const_iterator I = views.begin();
1505   // I != views.end(); I++) {
1506   // item = gtk_radiobutton_new((char *)(*I).c_str());
1507   GtkWidget *w;
1508   glade_xml_signal_connect_data(_gladeXML,
1509                                 "on_radiobutton_section_toggled",
1510                                 (GCallback) cbChangedView, this);
1511   w=_viewButtons[PACKAGE_VIEW_SECTION] = glade_xml_get_widget(_gladeXML, "radiobutton_sections");
1512   g_object_set_data(G_OBJECT(w), "index",
1513                     GINT_TO_POINTER(PACKAGE_VIEW_SECTION));
1514   glade_xml_signal_connect_data(_gladeXML,
1515                                 "on_radiobutton_status_toggled",
1516                                 (GCallback) cbChangedView, this);
1517   w=_viewButtons[PACKAGE_VIEW_STATUS] = glade_xml_get_widget(_gladeXML, "radiobutton_status");
1518
1519   g_object_set_data(G_OBJECT(w), "index",
1520                     GINT_TO_POINTER(PACKAGE_VIEW_STATUS));
1521   glade_xml_signal_connect_data(_gladeXML,
1522                                 "on_radiobutton_custom_toggled",
1523                                 (GCallback) cbChangedView, this);
1524   w=_viewButtons[PACKAGE_VIEW_CUSTOM] = glade_xml_get_widget(_gladeXML, "radiobutton_custom");
1525   g_object_set_data(G_OBJECT(w), "index",
1526                     GINT_TO_POINTER(PACKAGE_VIEW_CUSTOM));
1527   glade_xml_signal_connect_data(_gladeXML,
1528                                 "on_radiobutton_find_toggled",
1529                                 (GCallback) cbChangedView, this);
1530   w=_viewButtons[PACKAGE_VIEW_SEARCH] = glade_xml_get_widget(_gladeXML, "radiobutton_find");
1531   g_object_set_data(G_OBJECT(w), "index",
1532                     GINT_TO_POINTER(PACKAGE_VIEW_SEARCH));
1533
1534   _subViewList = glade_xml_get_widget(_gladeXML, "treeview_subviews");
1535   assert(_subViewList);
1536   setTreeList("treeview_subviews", vector<string>(), true);
1537   // Setup the selection handler
1538   select = gtk_tree_view_get_selection(GTK_TREE_VIEW(_subViewList));
1539   gtk_tree_selection_set_mode(select, GTK_SELECTION_SINGLE);
1540   g_signal_connect(G_OBJECT(select), "changed",
1541                    G_CALLBACK(cbChangedSubView), this);
1542
1543   GtkBindingSet *binding_set = gtk_binding_set_find("GtkTreeView");
1544   gtk_binding_entry_add_signal(binding_set, GDK_s, GDK_CONTROL_MASK,
1545                                "start_interactive_search", 0);
1546
1547}
1548
1549
1550
1551
1552void RGMainWindow::pkgInstallHelper(RPackage *pkg, bool fixBroken,
1553                                    bool reInstall)
1554{
1555   if (pkg->availableVersion() != NULL)
1556      pkg->setInstall();
1557
1558   if(reInstall == true)
1559       pkg->setReInstall(true);
1560
1561   // check whether something broke
1562   if (fixBroken && !_lister->check())
1563      _lister->fixBroken();
1564}
1565
1566void RGMainWindow::pkgRemoveHelper(RPackage *pkg, bool purge, bool withDeps)
1567{
1568   if (pkg->getFlags() & RPackage::FImportant) {
1569      if (!_userDialog->confirm(_("Removing this package may render the "
1570                                  "system unusable.\n"
1571                                  "Are you sure you want to do that?"),
1572                                false)) {
1573         return;
1574      }
1575   }
1576   if (!withDeps)
1577      pkg->setRemove(purge);
1578   else
1579      pkg->setRemoveWithDeps(true, false);
1580}
1581
1582void RGMainWindow::pkgKeepHelper(RPackage *pkg)
1583{
1584   pkg->setKeep();
1585}
1586
1587
1588void RGMainWindow::setStatusText(char *text)
1589{
1590
1591   int listed, installed, broken;
1592   int toInstall, toReInstall, toRemove;
1593   double size;
1594
1595   _lister->getStats(installed, broken, toInstall, toReInstall, toRemove, size);
1596
1597   if (text) {
1598      gtk_label_set_text(GTK_LABEL(_statusL), text);
1599   } else {
1600      gchar *buffer;
1601      // we need to make this two strings for i18n reasons
1602      listed = _lister->viewPackagesSize();
1603      if (size < 0) {
1604         buffer =
1605            g_strdup_printf(_("%i packages listed, %i installed, %i broken. %i to install/upgrade, %i to remove; %s will be freed"),
1606                            listed, installed, broken, toInstall, toRemove,
1607                            SizeToStr(fabs(size)).c_str());
1608      } else if( size > 0) {
1609         buffer =
1610            g_strdup_printf(_
1611                            ("%i packages listed, %i installed, %i broken. %i to install/upgrade, %i to remove; %s will be used"),
1612                            listed, installed, broken, toInstall, toRemove,
1613                            SizeToStr(fabs(size)).c_str());
1614      } else {
1615         buffer =
1616            g_strdup_printf(_
1617                            ("%i packages listed, %i installed, %i broken. %i to install/upgrade, %i to remove"),
1618                            listed, installed, broken, toInstall, toRemove);
1619      }
1620      gtk_label_set_text(GTK_LABEL(_statusL), buffer);
1621      g_free(buffer);
1622   }
1623
1624   gtk_widget_set_sensitive(_upgradeB, _lister->upgradable());
1625   gtk_widget_set_sensitive(_upgradeM, _lister->upgradable());
1626
1627   gtk_widget_set_sensitive(_proceedB, (toInstall + toRemove) != 0);
1628   gtk_widget_set_sensitive(_proceedM, (toInstall + toRemove) != 0);
1629   _unsavedChanges = ((toInstall + toRemove) != 0);
1630
1631   gtk_widget_queue_draw(_statusL);
1632}
1633
1634
1635void RGMainWindow::saveState()
1636{
1637   if (_config->FindB("Volatile::NoStateSaving", false) == true)
1638      return;
1639   _config->Set("Synaptic::vpanedPos",
1640                gtk_paned_get_position(GTK_PANED(_vpaned)));
1641   _config->Set("Synaptic::hpanedPos",
1642                gtk_paned_get_position(GTK_PANED(_hpaned)));
1643   _config->Set("Synaptic::windowWidth", _win->allocation.width);
1644   _config->Set("Synaptic::windowHeight", _win->allocation.height);
1645   gint x, y;
1646   gtk_window_get_position(GTK_WINDOW(_win), &x, &y);
1647   _config->Set("Synaptic::windowX", x);
1648   _config->Set("Synaptic::windowY", y);
1649   _config->Set("Synaptic::ToolbarState", (int)_toolbarStyle);
1650   if(gdk_window_get_state(_win->window) & GDK_WINDOW_STATE_MAXIMIZED)
1651      _config->Set("Synaptic::Maximized", true);
1652   else
1653      _config->Set("Synaptic::Maximized", false);
1654
1655   if (!RWriteConfigFile(*_config)) {
1656      _error->Error(_("An error occurred while saving configurations."));
1657      _userDialog->showErrors();
1658   }
1659   if (!_roptions->store())
1660      cerr << "Internal Error: error storing raptoptions" << endl;
1661}
1662
1663bool RGMainWindow::restoreState()
1664{
1665
1666   // see if we have broken packages (might be better in some
1667   // RGMainWindow::preGuiStart funktion)
1668   int installed, broken, toInstall, toReInstall, toRemove;
1669   double sizeChange;
1670   _lister->getStats(installed, broken, toInstall, toReInstall, toRemove, sizeChange);
1671   if (broken > 0) {
1672      gchar *msg;
1673      msg = ngettext("You have %d broken package on your system!\n\n"
1674                        "Use the \"Broken\" filter to locate it.",
1675                        "You have %i broken packages on your system!\n\n"
1676                        "Use the \"Broken\" filter to locate them.", broken);
1677      msg = g_strdup_printf(msg, broken);
1678      _userDialog->warning(msg);
1679      g_free(msg);
1680   }
1681
1682   if(!_config->FindB("Volatile::Upgrade-Mode",false)) {
1683      int viewNr = _config->FindI("Synaptic::ViewMode", 0);
1684      changeView(viewNr);
1685
1686      // we auto set to "All" on startup when we have gtk2.4 (without
1687      // the list is too slow)
1688      GtkTreeModel *model;
1689      GtkTreeSelection *selection;
1690      GtkTreeIter iter;
1691
1692      selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(_subViewList));
1693      model = gtk_tree_view_get_model(GTK_TREE_VIEW(_subViewList));
1694      gtk_tree_model_get_iter_first(model, &iter);
1695      gtk_tree_selection_select_iter(selection, &iter);
1696   }
1697   updatePackageInfo(NULL);
1698   return true;
1699}
1700
1701
1702bool RGMainWindow::close()
1703{
1704   if (_interfaceLocked > 0)
1705      return true;
1706
1707   RGGladeUserDialog dia(this);
1708   if (_unsavedChanges == false || dia.run("quit")) {
1709      _error->Discard();
1710      saveState();
1711      showErrors();
1712      exit(0);
1713   }
1714   return true;
1715}
1716
1717
1718
1719void RGMainWindow::setInterfaceLocked(bool flag)
1720{
1721   if (flag) {
1722      _interfaceLocked++;
1723      if (_interfaceLocked > 1)
1724         return;
1725
1726      gtk_widget_set_sensitive(_win, FALSE);
1727      if(GTK_WIDGET_VISIBLE(_win))
1728         gdk_window_set_cursor(_win->window, _busyCursor);
1729   } else {
1730      assert(_interfaceLocked > 0);
1731
1732      _interfaceLocked--;
1733      if (_interfaceLocked > 0)
1734         return;
1735
1736      gtk_widget_set_sensitive(_win, TRUE);
1737      if(GTK_WIDGET_VISIBLE(_win))
1738         gdk_window_set_cursor(_win->window, NULL);
1739   }
1740
1741   // fast enough with the new fixed-height mode
1742   while (gtk_events_pending())
1743      gtk_main_iteration();
1744}
1745
1746void RGMainWindow::setTreeLocked(bool flag)
1747{
1748   if (flag == true) {
1749      updatePackageInfo(NULL);
1750      gtk_tree_view_set_model(GTK_TREE_VIEW(_treeView), NULL);
1751   } else {
1752      gtk_tree_view_set_model(GTK_TREE_VIEW(_treeView), _pkgList);
1753   }
1754}
1755
1756
1757
1758// --------------------------------------------------------------------------
1759// Callbacks
1760//
1761
1762void RGMainWindow::cbPkgAction(GtkWidget *self, void *data)
1763{
1764   RGMainWindow *me = (RGMainWindow *) g_object_get_data(G_OBJECT(self), "me");
1765   assert(me);
1766   me->pkgAction((RGPkgAction)GPOINTER_TO_INT(data));
1767}
1768
1769gboolean RGMainWindow::cbPackageListClicked(GtkWidget *treeview,
1770                                            GdkEventButton *event,
1771                                            gpointer data)
1772{
1773   //cout << "RGMainWindow::cbPackageListClicked()" << endl;
1774
1775   RGMainWindow *me = (RGMainWindow *) data;
1776   RPackage *pkg = NULL;
1777   GtkTreePath *path;
1778   GtkTreeViewColumn *column;
1779
1780   /* Single clicks only */
1781   if (event->type == GDK_BUTTON_PRESS) {
1782      GtkTreeSelection *selection;
1783      GtkTreeIter iter;
1784
1785      if(!(event->window == gtk_tree_view_get_bin_window(GTK_TREE_VIEW(treeview))))
1786         return false;
1787
1788      selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview));
1789      if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(treeview),
1790                                        (int)event->x, (int)event->y,
1791                                        &path, &column, NULL, NULL)) {
1792
1793         /* Check if it's either a right-button click, or a left-button
1794          * click on the status column. */
1795         if (!(event->button == 3 ||
1796               (event->button == 1 && strcmp(column->title, "S") == 0)))
1797            return false;
1798
1799         vector<RPackage *> selected_pkgs;
1800         GList *li = NULL;
1801
1802         // Treat click with CONTROL as additional selection
1803         if((event->state & GDK_CONTROL_MASK) != GDK_CONTROL_MASK
1804            && !gtk_tree_selection_path_is_selected(selection, path))
1805            gtk_tree_selection_unselect_all(selection);
1806         gtk_tree_selection_select_path(selection, path);
1807
1808         li = gtk_tree_selection_get_selected_rows(selection, &me->_pkgList);
1809         for (li = g_list_first(li); li != NULL; li = g_list_next(li)) {
1810            gtk_tree_model_get_iter(me->_pkgList, &iter,
1811                                    (GtkTreePath *) (li->data));
1812
1813            gtk_tree_model_get(me->_pkgList, &iter, PKG_COLUMN, &pkg, -1);
1814            if (pkg)
1815               selected_pkgs.push_back(pkg);
1816         }
1817
1818         cbTreeviewPopupMenu(treeview, event, me, selected_pkgs);
1819         return true;
1820      }
1821   }
1822
1823   return false;
1824}
1825
1826void RGMainWindow::cbChangelogDialog(GtkWidget *self, void *data)
1827{
1828   RGMainWindow *me = (RGMainWindow*)data;
1829
1830   RPackage *pkg = me->selectedPackage();
1831   if(pkg == NULL)
1832      return;
1833   
1834   me->setInterfaceLocked(TRUE);
1835   RGFetchProgress *status = new RGFetchProgress(me);;
1836   status->setDescription(_("Downloading changelog"),
1837                          _("The changelog contains information about the"
1838             " changes and closed bugs in each version of"
1839             " the package."));
1840   pkgAcquire fetcher(status);
1841   string filename = pkg->getChangelogFile(&fetcher);
1842   
1843   RGGladeUserDialog dia(me,"changelog");
1844
1845   // set title
1846   GtkWidget *win = glade_xml_get_widget(dia.getGladeXML(),
1847                                           "dialog_changelog");
1848   assert(win);
1849   // TRANSLATORS: Title of the changelog dialog - %s is the name of the package
1850   gchar *str = g_strdup_printf(_("%s Changelog"), pkg->name());
1851   gtk_window_set_title(GTK_WINDOW(win), str);
1852   g_free(str);
1853
1854
1855   // set changelog data
1856   GtkWidget *textview = glade_xml_get_widget(dia.getGladeXML(),
1857                                              "textview_changelog");
1858   assert(textview);
1859   GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview));
1860   GtkTextIter start,end;
1861   gtk_text_buffer_get_start_iter (buffer, &start);
1862   gtk_text_buffer_get_end_iter(buffer,&end);
1863   gtk_text_buffer_delete(buffer,&start,&end);
1864   
1865   ifstream in(filename.c_str());
1866   string s;
1867   while(getline(in, s)) {
1868      // no need to free str later, it is allocated in a static buffer
1869      const char *str = utf8(s.c_str());
1870      if(str!=NULL)
1871         gtk_text_buffer_insert_at_cursor(buffer, str, -1);
1872      gtk_text_buffer_insert_at_cursor(buffer, "\n", -1);
1873   }
1874   
1875   dia.run();
1876
1877   // clean up
1878   delete status;
1879   unlink(filename.c_str());
1880   me->setInterfaceLocked(FALSE);
1881}
1882
1883
1884void RGMainWindow::cbPackageListRowActivated(GtkTreeView *treeview,
1885                                             GtkTreePath *path,
1886                                             GtkTreeViewColumn *arg2,
1887                                             gpointer data)
1888{
1889   //cout << "RGMainWindow::cbPackageListRowActivated()" << endl;
1890   
1891   RGMainWindow *me = (RGMainWindow *) data;
1892   GtkTreeIter iter;
1893   RPackage *pkg = NULL;
1894
1895   if (!gtk_tree_model_get_iter(me->_pkgList, &iter, path))
1896      return;
1897
1898   gtk_tree_model_get(me->_pkgList, &iter, PKG_COLUMN, &pkg, -1);
1899   assert(pkg);
1900
1901   int flags = pkg->getFlags();
1902
1903   if(flags & RPackage::FPinned)
1904      return;
1905
1906   if (!(flags & RPackage::FInstalled)) {
1907      if (flags & RPackage::FKeep)
1908         me->pkgAction(PKG_INSTALL);
1909      else if (flags & RPackage::FInstall)
1910         me->pkgAction(PKG_DELETE);
1911   } else if (flags & RPackage::FOutdated) {
1912      if (flags & RPackage::FKeep)
1913         me->pkgAction(PKG_INSTALL);
1914      else if (flags & RPackage::FUpgrade)
1915         me->pkgAction(PKG_KEEP);
1916   }
1917
1918   gtk_tree_view_set_cursor(GTK_TREE_VIEW(me->_treeView), path, NULL, false);
1919
1920   me->setStatusText();
1921}
1922
1923void RGMainWindow::cbAddCDROM(GtkWidget *self, void *data)
1924{
1925   RGMainWindow *me = (RGMainWindow *) data;
1926   RGCDScanner scan(me, me->_userDialog);
1927   me->setInterfaceLocked(TRUE);
1928   bool updateCache = false;
1929   bool dontStop = true;
1930   while (dontStop) {
1931      if (scan.run() == false)
1932         me->showErrors();
1933      else
1934         updateCache = true;
1935      if(_config->FindB("APT::CDROM::NoMount", false))
1936         dontStop=false;
1937      else
1938         dontStop = me->_userDialog->confirm(_("Do you want to add another CD-ROM?"));
1939   }
1940   scan.hide();
1941   if (updateCache) {
1942      me->setTreeLocked(TRUE);
1943      me->_lister->openCache();
1944      me->setTreeLocked(FALSE);
1945      me->refreshTable(me->selectedPackage());
1946   }
1947   me->setInterfaceLocked(FALSE);
1948}
1949
1950
1951
1952void RGMainWindow::cbTasksClicked(GtkWidget *self, void *data)
1953{
1954   RGMainWindow *me = (RGMainWindow*)data;
1955
1956   me->setBusyCursor(true);
1957
1958   if (me->_tasksWin == NULL) {   
1959      me->_tasksWin = new RGTasksWin(me);
1960   }
1961   me->_tasksWin->show();
1962
1963   me->setBusyCursor(false);
1964}
1965
1966void RGMainWindow::cbOpenClicked(GtkWidget *self, void *data)
1967{
1968   //std::cout << "RGMainWindow::openClicked()" << endl;
1969   RGMainWindow *me = (RGMainWindow*)data;
1970
1971   GtkWidget *filesel;
1972   filesel = gtk_file_chooser_dialog_new(_("Open changes"),
1973                                         GTK_WINDOW(me->window()),
1974                                         GTK_FILE_CHOOSER_ACTION_OPEN,
1975                                         GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
1976                                         GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
1977                                         NULL);
1978   if(gtk_dialog_run(GTK_DIALOG(filesel)) == GTK_RESPONSE_ACCEPT) {
1979      const char *file;
1980      file = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(filesel));
1981      me->selectionsFilename = file;
1982
1983      ifstream in(file);
1984      if (!in != 0) {
1985         _error->Error(_("Can't read %s"), file);
1986         me->_userDialog->showErrors();
1987         return;
1988      }
1989      me->_lister->unregisterObserver(me);
1990      me->_lister->readSelections(in);
1991      me->_lister->registerObserver(me);
1992      me->setStatusText();
1993   }
1994   gtk_widget_destroy(filesel);
1995}
1996
1997void RGMainWindow::cbSaveClicked(GtkWidget *self, void *data)
1998{
1999   //std::cout << "RGMainWindow::saveClicked()" << endl;
2000   RGMainWindow *me = (RGMainWindow *) data;
2001
2002   if (me->selectionsFilename == "") {
2003      me->cbSaveAsClicked(self, data);
2004      return;
2005   }
2006
2007   ofstream out(me->selectionsFilename.c_str());
2008   if (!out != 0) {
2009      _error->Error(_("Can't write %s"), me->selectionsFilename.c_str());
2010      me->_userDialog->showErrors();
2011      return;
2012   }
2013
2014   me->_lister->unregisterObserver(me);
2015   me->_lister->writeSelections(out, me->saveFullState);
2016   me->_lister->registerObserver(me);
2017   me->setStatusText();
2018
2019}
2020
2021
2022void RGMainWindow::cbSaveAsClicked(GtkWidget *self, void *data)
2023{
2024   //std::cout << "RGMainWindow::saveAsClicked()" << endl;
2025   RGMainWindow *me = (RGMainWindow*)data;
2026
2027   GtkWidget *filesel;
2028   filesel = gtk_file_chooser_dialog_new(_("Open changes"),
2029                                         GTK_WINDOW(me->window()),
2030                                         GTK_FILE_CHOOSER_ACTION_SAVE,
2031                                         GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
2032                                         GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
2033                                         NULL);
2034   GtkWidget *checkButton =
2035      gtk_check_button_new_with_label(_("Save full state, not only changes"));
2036   gtk_file_chooser_set_extra_widget(GTK_FILE_CHOOSER(filesel), checkButton);
2037
2038   if(gtk_dialog_run(GTK_DIALOG(filesel)) == GTK_RESPONSE_ACCEPT) {
2039      const char *file;
2040      file = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(filesel));
2041      me->selectionsFilename = file;
2042      me->saveFullState =
2043         gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(checkButton));
2044      // now call save for the actual saving
2045      me->cbSaveClicked(self, me);
2046   }
2047   gtk_widget_destroy(filesel);
2048}
2049
2050
2051void RGMainWindow::cbShowConfigWindow(GtkWidget *self, void *data)
2052{
2053   RGMainWindow *me = (RGMainWindow *) data;
2054
2055   if (me->_configWin == NULL) {
2056      me->_configWin = new RGPreferencesWindow(me, me->_lister);
2057   }
2058
2059   me->_configWin->show();
2060}
2061
2062void RGMainWindow::cbShowSetOptWindow(GtkWidget *self, void *data)
2063{
2064   RGMainWindow *win = (RGMainWindow *) data;
2065
2066   if (win->_setOptWin == NULL)
2067      win->_setOptWin = new RGSetOptWindow(win);
2068
2069   win->_setOptWin->show();
2070}
2071
2072void RGMainWindow::cbDetailsWindow(GtkWidget *self, void *data)
2073{
2074   RGMainWindow *me = (RGMainWindow *) data;
2075   assert(data);
2076
2077   RPackage *pkg = me->selectedPackage();
2078   if (pkg == NULL)
2079      return;
2080
2081   if(me->_pkgDetails == NULL)
2082      me->_pkgDetails = new RGPkgDetailsWindow(me);
2083
2084   RGPkgDetailsWindow::fillInValues(me->_pkgDetails, pkg);
2085   me->_pkgDetails->show();
2086}
2087
2088// helper to hide the "please wait" message
2089static void plug_added(GtkWidget *sock, void *data)
2090{
2091   gtk_widget_show(sock);
2092   gtk_widget_hide(GTK_WIDGET(data));
2093}
2094
2095static gboolean kill_repos(GtkWidget *self, GdkEvent *event, void *data)
2096{
2097   GPid pid = *(GPid*)data;
2098   kill(pid, SIGQUIT);
2099   return TRUE;
2100}
2101
2102void RGMainWindow::cbShowSourcesWindow(GtkWidget *self, void *data)
2103{
2104   RGMainWindow *me = (RGMainWindow *) data;
2105
2106   // FIXME: make this all go into the repository window
2107   bool Changed = false;
2108   bool ForceReload = _config->FindB("Synaptic::UpdateAfterSrcChange",false);
2109   {
2110      if(!g_file_test("/usr/bin/gnome-software-properties",
2111                      G_FILE_TEST_IS_EXECUTABLE)
2112         || _config->FindB("Synaptic::dontUseGnomeSoftwareProperties", false))
2113      {
2114         RGRepositoryEditor w(me);
2115         Changed = w.Run();
2116      } else {
2117         // use gnome-software-properties window
2118         me->setInterfaceLocked(TRUE);
2119         ForceReload = true;
2120         GPid pid;
2121         int status;
2122         char *argv[5];
2123         GtkWidget *win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
2124         gtk_window_set_title(GTK_WINDOW(win), _("Repositories"));
2125         gtk_window_set_default_size(GTK_WINDOW(win),400,500);
2126         gtk_container_set_border_width(GTK_CONTAINER(win), 6);
2127         gtk_window_set_transient_for(GTK_WINDOW(win), GTK_WINDOW(me->_win));
2128         gtk_window_set_skip_taskbar_hint(GTK_WINDOW(win), TRUE);
2129         GtkWidget *vbox = gtk_vbox_new(FALSE, 12);
2130         gtk_container_add(GTK_CONTAINER(win), vbox);
2131         gtk_widget_show(vbox);
2132
2133         GtkWidget *label = gtk_label_new("");
2134         gtk_label_set_markup(GTK_LABEL(label),
2135                              _("<big><b>Building repository dialog</b></big>\n\n"
2136                                "Please wait."));
2137         gtk_box_pack_start_defaults(GTK_BOX(vbox), label);
2138         gtk_widget_show(label);
2139         
2140         GtkWidget *sock = gtk_socket_new();
2141         g_signal_connect(G_OBJECT(sock), "plug-added",
2142                          G_CALLBACK(plug_added),  label);
2143         gtk_box_pack_start_defaults(GTK_BOX(vbox), sock);
2144         
2145         argv[0] = "/usr/bin/gnome-software-properties";
2146         argv[1] = "-n";
2147         argv[2] = "-p";
2148         argv[3] = g_strdup_printf("%i", gtk_socket_get_id(GTK_SOCKET(sock)));
2149         argv[4] = NULL;
2150         
2151         g_spawn_async(NULL, argv, NULL,(GSpawnFlags)G_SPAWN_DO_NOT_REAP_CHILD,
2152                       NULL, NULL, &pid, NULL);
2153         // kill the child if the window is deleted
2154         g_signal_connect(G_OBJECT(win), "delete-event",
2155                          G_CALLBACK(kill_repos), &pid);
2156         gtk_widget_show_all(win);
2157         while(waitpid(pid, &status, WNOHANG) == 0) {
2158            usleep(50000);
2159            RGFlushInterface();
2160         }
2161         Changed = WEXITSTATUS(status);   
2162         gtk_widget_destroy(win);
2163         me->setInterfaceLocked(FALSE);
2164      }
2165   }
2166   RGFlushInterface();
2167
2168   // auto update after repostitory change
2169   if (Changed == true && ForceReload) {
2170      me->cbUpdateClicked(NULL, data);
2171   } else if(Changed == true &&
2172             _config->FindB("Synaptic::AskForUpdateAfterSrcChange",true)) {
2173      // ask for update after repo change
2174      GtkWidget *cb, *dialog;
2175      dialog = gtk_message_dialog_new (GTK_WINDOW(me->window()),
2176                                       GTK_DIALOG_DESTROY_WITH_PARENT,
2177                                       GTK_MESSAGE_INFO,
2178                                       GTK_BUTTONS_CLOSE,
2179                                       _("Repositories changed"));
2180      // TRANSLATORS: this message appears when the user added/removed
2181      // a repostiory (sources.list entry) a reload (apt-get udpate) is
2182      // needed then
2183      gchar *msgstr = _("The repository information "
2184                        "has changed. "
2185                        "You have to click on the "
2186                        "\"Reload\" button for your changes to "
2187                        "take effect");
2188#if GTK_CHECK_VERSION(2,6,0)
2189      gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),
2190                                               msgstr);
2191#else
2192      gtk_message_dialog_set_markup(GTK_MESSAGE_DIALOG(dialog), msgstr);
2193#endif
2194      cb = gtk_check_button_new_with_label(_("Never show this message again"));
2195      gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(dialog)->vbox),cb);
2196      gtk_widget_show(cb);
2197      gtk_dialog_run (GTK_DIALOG (dialog));
2198      if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cb))) {
2199            _config->Set("Synaptic::AskForUpdateAfterSrcChange", false);
2200      }
2201      gtk_widget_destroy (dialog);
2202   }
2203}
2204
2205void RGMainWindow::cbMenuToolbarClicked(GtkWidget *self, void *data)
2206{
2207   RGMainWindow *me = (RGMainWindow *) g_object_get_data(G_OBJECT(self), "me");
2208   GtkWidget *widget;
2209   // save new toolbar state
2210   me->_toolbarStyle = (GtkToolbarStyle) GPOINTER_TO_INT(data);
2211   GtkWidget *toolbar = glade_xml_get_widget(me->_gladeXML, "toolbar_main");
2212   assert(toolbar);
2213   if (me->_toolbarStyle == TOOLBAR_HIDE) {
2214      widget = glade_xml_get_widget(me->_gladeXML, "handlebox_button_toolbar");
2215      gtk_widget_hide(widget);
2216      return;
2217   } else {
2218      widget = glade_xml_get_widget(me->_gladeXML, "handlebox_button_toolbar");
2219      gtk_widget_show(widget);
2220   }
2221   gtk_toolbar_set_style(GTK_TOOLBAR(toolbar), me->_toolbarStyle);
2222}
2223
2224void RGMainWindow::cbFindToolClicked(GtkWidget *self, void *data)
2225{
2226   RGMainWindow *me = (RGMainWindow *) data;
2227
2228   if (me->_findWin == NULL) {
2229      me->_findWin = new RGFindWindow(me);
2230   }
2231
2232   me->_findWin->selectText();
2233   int res = gtk_dialog_run(GTK_DIALOG(me->_findWin->window()));
2234   if (res == GTK_RESPONSE_OK) {
2235      me->setBusyCursor(true);
2236      string str = me->_findWin->getFindString();
2237
2238      // we need to convert here as the DDTP project does not use utf-8
2239      const char *locale_str = utf8_to_locale(str.c_str());
2240      if(locale_str == NULL) // invalid utf-8
2241         locale_str = str.c_str();
2242
2243      int type = me->_findWin->getSearchType();
2244      int found = me->_lister->searchView()->setSearch(str,type, locale_str);
2245      me->changeView(PACKAGE_VIEW_SEARCH, str);
2246
2247      me->setBusyCursor(false);
2248      gchar *statusstr = g_strdup_printf(_("Found %i packages"), found);
2249      me->setStatusText(statusstr);
2250      me->updatePackageInfo(NULL);
2251      g_free(statusstr);
2252   }
2253
2254}
2255
2256void RGMainWindow::cbShowAboutPanel(GtkWidget *self, void *data)
2257{
2258   RGMainWindow *win = (RGMainWindow *) data;
2259
2260   if (win->_aboutPanel == NULL)
2261      win->_aboutPanel = new RGAboutPanel(win);
2262   win->_aboutPanel->show();
2263}
2264
2265void RGMainWindow::cbShowIconLegendPanel(GtkWidget *self, void *data)
2266{
2267   RGMainWindow *me = (RGMainWindow *) data;
2268
2269   if (me->_iconLegendPanel == NULL)
2270      me->_iconLegendPanel = new RGIconLegendPanel(me);
2271   me->_iconLegendPanel->show();
2272}
2273
2274void RGMainWindow::cbViewLogClicked(GtkWidget *self, void *data)
2275{
2276   RGMainWindow *me = (RGMainWindow *) data;
2277
2278   if (me->_logView == NULL)
2279      me->_logView = new RGLogView(me);
2280   me->_logView->readLogs();
2281   me->_logView->show();
2282}
2283
2284
2285void RGMainWindow::cbHelpAction(GtkWidget *self, void *data)
2286{
2287   RGMainWindow *me = (RGMainWindow *) data;
2288
2289   me->setStatusText(_("Starting help viewer..."));
2290
2291   if (is_binary_in_path("yelp"))
2292      system("yelp ghelp:synaptic &");
2293#if 0 // FIXME: khelpcenter can't display this? check again!
2294    else if(is_binary_in_path("khelpcenter")) {
2295       system("konqueror ghelp:///" PACKAGE_DATA_DIR "/gnome/help/synaptic/C/synaptic.xml &");
2296    }
2297#endif
2298   else if (is_binary_in_path("mozilla")) {
2299      // mozilla eats bookmarks when run under sudo (because it does not
2300      // change $HOME)
2301      if(getenv("SUDO_USER") != NULL) {
2302         struct passwd *pw = getpwuid(0);
2303         setenv("HOME", pw->pw_dir, 1);
2304      }
2305      system("mozilla " PACKAGE_DATA_DIR "/synaptic/html/index.html &");
2306   } else if (is_binary_in_path("konqueror"))
2307      system("konqueror " PACKAGE_DATA_DIR "/synaptic/html/index.html &");
2308   else
2309      me->_userDialog->error(_("No help viewer is installed!\n\n"
2310                               "You need either the GNOME help viewer 'yelp', "
2311                               "the 'konqueror' browser or the 'mozilla' "
2312                               "browser to view the synaptic manual.\n\n"
2313                               "Alternatively you can open the man page "
2314                               "with 'man synaptic' from the "
2315                               "command line or view the html version located "
2316                               "in the 'synaptic/html' folder."));
2317}
2318
2319void RGMainWindow::cbCloseFilterManagerAction(void *self, bool okcancel)
2320{
2321   RGMainWindow *me = (RGMainWindow *) self;
2322
2323   // FIXME: only do all this if the user didn't click "cancel" in the dialog
2324
2325   me->setInterfaceLocked(TRUE);
2326
2327   me->_lister->filterView()->refreshFilters();
2328   me->refreshTable();
2329   me->refreshSubViewList();
2330
2331   me->setInterfaceLocked(FALSE);
2332}
2333
2334
2335void RGMainWindow::cbShowFilterManagerWindow(GtkWidget *self, void *data)
2336{
2337
2338   RGMainWindow *me = (RGMainWindow *) data;
2339
2340   if (me->_fmanagerWin == NULL) {
2341      me->_fmanagerWin = new RGFilterManagerWindow(me, me->_lister->filterView());
2342   }
2343
2344   me->_fmanagerWin->readFilters();
2345   int res = gtk_dialog_run(GTK_DIALOG(me->_fmanagerWin->window()));
2346   if(res == GTK_RESPONSE_OK) {
2347      me->setInterfaceLocked(TRUE);
2348
2349      me->_lister->filterView()->refreshFilters();
2350      me->refreshTable();
2351      me->refreshSubViewList();
2352
2353      me->setInterfaceLocked(FALSE);
2354   }
2355   
2356}
2357
2358void RGMainWindow::cbSelectedRow(GtkTreeSelection *selection, gpointer data)
2359{
2360   RGMainWindow *me = (RGMainWindow *) data;
2361   GtkTreeIter iter;
2362   RPackage *pkg;
2363   GList *li, *list;
2364
2365
2366
2367   //cout << "RGMainWindow::cbSelectedRow()" << endl;
2368
2369   if (me->_pkgList == NULL) {
2370      cerr << "selectedRow(): me->_pkgTree == NULL " << endl;
2371      return;
2372   }
2373   list = li = gtk_tree_selection_get_selected_rows(selection, &me->_pkgList);
2374
2375   // list is empty
2376   if (li == NULL) {
2377      me->updatePackageInfo(NULL);
2378      return;
2379   }
2380   // we are only interessted in the last element
2381   li = g_list_last(li);
2382   gtk_tree_model_get_iter(me->_pkgList, &iter, (GtkTreePath *) (li->data));
2383
2384   gtk_tree_model_get(me->_pkgList, &iter, PKG_COLUMN, &pkg, -1);
2385   if (pkg == NULL)
2386      return;
2387
2388   // free the list
2389   g_list_foreach(list, (void (*)(void *, void *))gtk_tree_path_free, NULL);
2390   g_list_free(list);
2391
2392   me->updatePackageInfo(pkg);
2393}
2394
2395void RGMainWindow::cbClearAllChangesClicked(GtkWidget *self, void *data)
2396{
2397   //cout << "clearAllChangesClicked" << endl;
2398   RGMainWindow *me = (RGMainWindow *) data;
2399   me->setInterfaceLocked(TRUE);
2400   me->_lister->unregisterObserver(me);
2401   me->setTreeLocked(TRUE);
2402
2403   // reset
2404   me->_lister->openCache();
2405
2406   me->setTreeLocked(FALSE);
2407   me->_lister->registerObserver(me);
2408   me->refreshTable();
2409   me->setInterfaceLocked(FALSE);
2410}
2411
2412
2413void RGMainWindow::cbUndoClicked(GtkWidget *self, void *data)
2414{
2415   //cout << "undoClicked" << endl;
2416   RGMainWindow *me = (RGMainWindow *) data;
2417   me->setInterfaceLocked(TRUE);
2418
2419   me->_lister->unregisterObserver(me);
2420
2421   // undo
2422   me->_lister->undo();
2423
2424   me->_lister->registerObserver(me);
2425   me->refreshTable();
2426   me->setInterfaceLocked(FALSE);
2427}
2428
2429void RGMainWindow::cbRedoClicked(GtkWidget *self, void *data)
2430{
2431   //cout << "redoClicked" << endl;
2432   RGMainWindow *me = (RGMainWindow *) data;
2433   me->setInterfaceLocked(TRUE);
2434
2435   me->_lister->unregisterObserver(me);
2436
2437   // redo
2438   me->_lister->redo();
2439
2440   me->_lister->registerObserver(me);
2441   me->refreshTable();
2442   me->setInterfaceLocked(FALSE);
2443}
2444
2445void RGMainWindow::cbPkgReconfigureClicked(GtkWidget *self, void *data)
2446{
2447   char frontend[] = "gnome";
2448   char *cmd;
2449   RGMainWindow *me = (RGMainWindow *) data;
2450   //cout << "RGMainWindow::pkgReconfigureClicked()" << endl;
2451
2452   if(me->selectedPackage() == NULL)
2453      return;
2454
2455   RPackage *pkg = NULL;
2456   pkg = me->_lister->getPackage("libgnome2-perl");
2457   if (pkg && pkg->installedVersion() == NULL) {
2458      me->_userDialog->error(_("Cannot start configuration tool!\n"
2459                               "You have to install the required package "
2460                               "'libgnome2-perl'."));
2461      return;
2462   }
2463
2464   me->setStatusText(_("Starting package configuration tool..."));
2465   cmd = g_strdup_printf("/usr/sbin/dpkg-reconfigure -f%s %s &",
2466                         frontend, me->selectedPackage()->name());
2467   system(cmd);
2468}
2469
2470
2471void RGMainWindow::cbPkgHelpClicked(GtkWidget *self, void *data)
2472{
2473   RGMainWindow *me = (RGMainWindow *) data;
2474
2475   if(me->selectedPackage() == NULL)
2476      return;
2477
2478   //cout << "RGMainWindow::pkgHelpClicked()" << endl;
2479   me->setStatusText(_("Starting package documentation viewer..."));
2480
2481   // mozilla eats bookmarks when run under sudo (because it does not
2482   // change $HOME) so we better play safe here
2483   if(getenv("SUDO_USER") != NULL) {
2484      struct passwd *pw = getpwuid(0);
2485      setenv("HOME", pw->pw_dir, 1);
2486   }
2487
2488   if (is_binary_in_path("dwww"))
2489      system(g_strdup_printf("dwww %s &", me->selectedPackage()->name()));
2490   else
2491      me->_userDialog->error(_("You have to install the package \"dwww\" "
2492                               "to browse the documentation of a package"));
2493
2494}
2495
2496
2497void RGMainWindow::cbChangedView(GtkWidget *self, void *data)
2498{
2499   // only act on the active buttons
2500   if(!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(self)))
2501      return;
2502
2503   //   cout << "cbChangedView()"<<endl;
2504
2505   RGMainWindow *me = (RGMainWindow *) data;
2506   long view = (long)gtk_object_get_data(GTK_OBJECT(self), "index");
2507   me->changeView(view);
2508}
2509
2510void RGMainWindow::cbChangedSubView(GtkTreeSelection *selection,
2511                                    gpointer data)
2512{
2513   RGMainWindow *me = (RGMainWindow *) data;
2514
2515   me->setBusyCursor(true);
2516   me->refreshTable(NULL);
2517   me->setBusyCursor(false);
2518   me->updatePackageInfo(NULL);
2519}
2520
2521void RGMainWindow::activeWindowToForeground()
2522{
2523   //cout << "activeWindowToForeground: " << getpid() << endl;
2524
2525   // easy, we have a main window
2526   if(_config->FindB("Volatile::HideMainwindow", false) == false) {
2527      gtk_window_present(GTK_WINDOW(window()));
2528      return;
2529   }
2530
2531   // harder, we run without mainWindow (in non-interactive mode most likly)
2532   if( _fetchProgress && GTK_WIDGET_VISIBLE(_fetchProgress->window()))
2533      gtk_window_present(GTK_WINDOW(_fetchProgress->window()));
2534   else if(_installProgress && GTK_WIDGET_VISIBLE(_installProgress->window()))
2535      gtk_window_present(GTK_WINDOW(_installProgress->window()));
2536   else
2537      g_critical("activeWindowToForeground(): no active window found\n");
2538}
2539
2540void RGMainWindow::cbProceedClicked(GtkWidget *self, void *data)
2541{
2542   RGMainWindow *me = (RGMainWindow *) data;
2543   RGSummaryWindow *summ;
2544
2545   // nothing to do
2546   int listed, installed, broken;
2547   int toInstall, toReInstall, toRemove;
2548   double size;
2549   me->_lister->getStats(installed, broken, toInstall, toReInstall,
2550                         toRemove, size);
2551   if((toInstall + toRemove) == 0)
2552      return;
2553
2554   // check whether we can really do it
2555   if (!me->_lister->check()) {
2556      me->_userDialog->error(_("Could not apply changes!\n"
2557                               "Fix broken packages first."));
2558      return;
2559   }
2560
2561   int a,b,c,d,e,f,g,h,unAuthenticated;
2562   double s;
2563   me->_lister->getSummary(a,b,c,d,e,f,g,h,unAuthenticated,s);
2564   if(unAuthenticated ||
2565      _config->FindB("Volatile::Non-Interactive", false) == false) {
2566      // show a summary of what's gonna happen
2567      RGSummaryWindow summ(me, me->_lister);
2568      if (!summ.showAndConfirm()) {
2569         // canceled operation
2570         return;
2571      }
2572   }
2573
2574   me->setInterfaceLocked(TRUE);
2575   me->updatePackageInfo(NULL);
2576
2577   me->setStatusText(_("Applying marked changes. This may take a while..."));
2578
2579   // fetch packages
2580   RGFetchProgress *fprogress=me->_fetchProgress = new RGFetchProgress(me);
2581   fprogress->setDescription(_("Downloading package files"),
2582                             _("The package files will be cached locally for installation."));
2583
2584   // Do not let the treeview access the cache during the update.
2585   me->setTreeLocked(TRUE);
2586
2587   // save selections to temporary file
2588   const gchar *file =
2589      g_strdup_printf("%s/selections.proceed", RConfDir().c_str());
2590   ofstream out(file);
2591   if (!out != 0) {
2592      _error->Error(_("Can't write %s"), file);
2593      me->_userDialog->showErrors();
2594      return;
2595   }
2596   me->_lister->writeSelections(out, false);
2597
2598
2599   RInstallProgress *iprogress;
2600#ifdef HAVE_TERMINAL
2601#ifdef HAVE_RPM
2602   bool UseTerminal = false;
2603#else
2604   // no RPM
2605   #ifdef WITH_DPKG_STATUSFD
2606   bool UseTerminal = false;
2607   #else
2608   bool UseTerminal = true;
2609   #endif // DPKG
2610#endif // HAVE_RPM
2611   RGTermInstallProgress *term = NULL;
2612   if (_config->FindB("Synaptic::UseTerminal", UseTerminal) == true)
2613      iprogress = term = new RGTermInstallProgress(me);
2614   else
2615#endif // HAVE_TERMINAL
2616
2617
2618#ifdef HAVE_RPM
2619      iprogress = new RGInstallProgress(me, me->_lister);
2620#else
2621  #ifdef WITH_DPKG_STATUSFD
2622      iprogress = new RGDebInstallProgress(me,me->_lister, me->_userDialog);
2623  #else
2624   iprogress = new RGDummyInstallProgress();
2625  #endif // WITH_DPKG_STATUSFD
2626#endif // HAVE_RPM
2627   me->_installProgress = dynamic_cast<RGWindow*>(iprogress);
2628
2629   //bool result = me->_lister->commitChanges(fprogress, iprogress);
2630   me->_lister->commitChanges(fprogress, iprogress);
2631
2632   // FIXME: move this into the terminal class
2633#ifdef HAVE_TERMINAL
2634   // wait until the term dialog is closed
2635   if (term != NULL) {
2636      while (GTK_WIDGET_VISIBLE(GTK_WIDGET(term->window()))) {
2637         RGFlushInterface();
2638         usleep(100000);
2639      }
2640   }
2641#endif
2642   delete fprogress;
2643   me->_fetchProgress = NULL;
2644   delete iprogress;
2645   me->_installProgress = NULL;
2646
2647   if (_config->FindB("Synaptic::IgnorePMOutput", false) == false) {
2648      me->showErrors();
2649   } else {
2650      _error->Discard();
2651   }
2652   if (_config->FindB("Volatile::Non-Interactive", false) == true) {
2653      return;
2654   }
2655
2656   if (_config->FindB("Synaptic::AskQuitOnProceed", false) == true
2657       && me->_userDialog->confirm(_("Do you want to quit Synaptic?"))) {
2658      _error->Discard();
2659      me->saveState();
2660      me->showErrors();
2661      exit(0);
2662   }
2663
2664   if (_config->FindB("Volatile::Download-Only", false) == false) {
2665      // reset the cache
2666      if (!me->_lister->openCache()) {
2667         me->showErrors();
2668         exit(1);
2669      }
2670   }
2671   // reread saved selections
2672   ifstream in(file);
2673   if (!in != 0) {
2674      _error->Error(_("Can't read %s"), file);
2675      me->_userDialog->showErrors();
2676      return;
2677   }
2678   me->_lister->readSelections(in);
2679   unlink(file);
2680   g_free((void *)file);
2681
2682
2683   me->setTreeLocked(FALSE);
2684   me->refreshTable();
2685   me->refreshSubViewList();
2686   me->setInterfaceLocked(FALSE);
2687   me->updatePackageInfo(NULL);
2688}
2689
2690void RGMainWindow::cbShowWelcomeDialog(GtkWidget *self, void *data)
2691{
2692   RGMainWindow *me = (RGMainWindow *) data;
2693   RGGladeUserDialog dia(me);
2694   dia.run("welcome");
2695   GtkWidget *cb = glade_xml_get_widget(dia.getGladeXML(),
2696                                        "checkbutton_show_again");
2697   assert(cb);
2698   _config->Set("Synaptic::showWelcomeDialog",
2699                gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cb)));
2700}
2701
2702
2703void RGMainWindow::cbUpdateClicked(GtkWidget *self, void *data)
2704{
2705   RGMainWindow *me = (RGMainWindow *) data;
2706
2707   // need to delete dialogs, as they might have data pointing
2708   // to old stuff
2709//xxx    delete me->_fmanagerWin;
2710   me->_fmanagerWin = NULL;
2711
2712   RGFetchProgress *progress=me->_fetchProgress= new RGFetchProgress(me);
2713   progress->setDescription(_("Downloading package information"),
2714                            _("The repositories will be checked for new, removed "
2715               "or upgraded software packages."));
2716
2717   me->setStatusText(_("Reloading package information..."));
2718
2719   me->setInterfaceLocked(TRUE);
2720   me->setTreeLocked(TRUE);
2721   me->_lister->unregisterObserver(me);
2722
2723   // save to temporary file
2724   const gchar *file =
2725      g_strdup_printf("%s/selections.update", RConfDir().c_str());
2726   ofstream out(file);
2727   if (!out != 0) {
2728      _error->Error(_("Can't write %s"), file);
2729      me->_userDialog->showErrors();
2730      return;
2731   }
2732   me->_lister->writeSelections(out, false);
2733
2734   // update cache and forget about the previous new packages
2735   // (only if no error occured)
2736   string error;
2737   if (!me->_lister->updateCache(progress,error)) {
2738      RGGladeUserDialog dia(me,"update_failed");
2739      GtkWidget *tv = glade_xml_get_widget(dia.getGladeXML(), "textview");
2740      GtkTextBuffer *tb = gtk_text_view_get_buffer(GTK_TEXT_VIEW(tv));
2741      gtk_text_buffer_set_text(tb, utf8(error.c_str()), -1);
2742      dia.run();
2743   } else {
2744      me->forgetNewPackages();
2745      _config->Set("Synaptic::update::last",time(NULL));
2746   }
2747   delete progress;
2748   me->_fetchProgress=NULL;
2749
2750   // show errors and warnings (like the gpg failures for the package list)
2751   me->showErrors();
2752
2753   if(me->_lister->openCache())
2754      me->showErrors();
2755
2756   // reread saved selections
2757   ifstream in(file);
2758   if (!in != 0) {
2759      _error->Error(_("Can't read %s"), file);
2760      me->_userDialog->showErrors();
2761      return;
2762   }
2763   me->_lister->readSelections(in);
2764   unlink(file);
2765   g_free((void *)file);
2766
2767   me->setTreeLocked(FALSE);
2768   me->refreshTable();
2769   me->refreshSubViewList();
2770   me->setInterfaceLocked(FALSE);
2771   me->setStatusText();
2772}
2773
2774void RGMainWindow::cbFixBrokenClicked(GtkWidget *self, void *data)
2775{
2776   RGMainWindow *me = (RGMainWindow *) data;
2777   RPackage *pkg = me->selectedPackage();
2778
2779   bool res = me->_lister->fixBroken();
2780   me->setInterfaceLocked(TRUE);
2781   me->refreshTable(pkg);
2782
2783   if (!res)
2784      me->setStatusText(_("Failed to resolve dependency problems!"));
2785   else
2786      me->setStatusText(_("Successfully fixed dependency problems"));
2787
2788   me->setInterfaceLocked(FALSE);
2789   me->showErrors();
2790}
2791
2792
2793void RGMainWindow::cbUpgradeClicked(GtkWidget *self, void *data)
2794{
2795   RGMainWindow *me = (RGMainWindow *) data;
2796   RPackage *pkg = me->selectedPackage();
2797   bool dist_upgrade;
2798   int res;
2799
2800   if (!me->_lister->check()) {
2801      me->_userDialog->error(
2802                         _("Could not upgrade the system!\n"
2803                           "Fix broken packages first."));
2804      return;
2805   }
2806   // check if we have saved upgrade type
2807   UpgradeType upgrade =
2808      (UpgradeType) _config->FindI("Synaptic::UpgradeType", UPGRADE_DIST);
2809
2810   // special case for non-interactive upgrades
2811   if(_config->FindB("Volatile::Non-Interactive", false))
2812      if(_config->FindB("Volatile::Upgrade-Mode", false))
2813         upgrade = UPGRADE_NORMAL;
2814      else if(_config->FindB("Volatile::DistUpgrade-Mode", false))
2815         upgrade = UPGRADE_DIST;
2816   
2817
2818   if (upgrade == UPGRADE_ASK) {
2819      // ask what type of upgrade the user wants
2820      GladeXML *gladeXML;
2821      GtkWidget *button;
2822
2823      RGGladeUserDialog dia(me);
2824      res = dia.run("upgrade", true);
2825      switch(res) {
2826      case GTK_RESPONSE_CANCEL:
2827      case GTK_RESPONSE_DELETE_EVENT:
2828         return;
2829      case GTK_RESPONSE_YES:
2830         dist_upgrade = true;
2831         break;
2832      case GTK_RESPONSE_NO:
2833         dist_upgrade = false;
2834         break;
2835      default:
2836         cerr << "unknown return " << res
2837              << " from UpgradeDialog, please report" << endl;
2838      }
2839      gladeXML = dia.getGladeXML();
2840      // see if the user wants the answer saved
2841      button = glade_xml_get_widget(gladeXML, "checkbutton_remember");
2842      if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)))
2843         _config->Set("Synaptic::upgradeType", dist_upgrade);
2844   } else {
2845      // use the saved answer (don't ask)
2846      dist_upgrade = upgrade;
2847   }
2848
2849   // do the work
2850   me->setInterfaceLocked(TRUE);
2851   me->setStatusText(_("Marking all available upgrades..."));
2852
2853   me->_lister->saveUndoState();
2854   
2855   RPackageLister::pkgState state;
2856   me->_lister->saveState(state);
2857
2858   if (dist_upgrade)
2859      res = me->_lister->distUpgrade();
2860   else
2861      res = me->_lister->upgrade();
2862
2863   // mvo: do we really want this?
2864   me->askStateChange(state, vector<RPackage*>());
2865
2866   me->refreshTable(pkg);
2867
2868   if (res)
2869      me->setStatusText(_("Successfully marked available upgrades"));
2870   else
2871      me->setStatusText(_("Failed to mark all available upgrades!"));
2872
2873   me->setInterfaceLocked(FALSE);
2874   me->showErrors();
2875}
2876
2877void RGMainWindow::cbMenuPinClicked(GtkWidget *self, void *data)
2878{
2879   RGMainWindow *me = (RGMainWindow *) data;
2880
2881   bool active = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(self));
2882   GtkTreeSelection *selection;
2883   GtkTreeIter iter;
2884   RPackage *pkg;
2885
2886   if (me->_blockActions)
2887      return;
2888
2889   selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(me->_treeView));
2890   GList *li, *list;
2891
2892   list = li = gtk_tree_selection_get_selected_rows(selection, &me->_pkgList);
2893   if (li == NULL)
2894      return;
2895
2896   me->setInterfaceLocked(TRUE);
2897   me->setTreeLocked(TRUE);
2898   me->_lister->unregisterObserver(me);
2899
2900   // save to temporary file
2901   const gchar *file =
2902      g_strdup_printf("%s/selections.hold", RConfDir().c_str());
2903   ofstream out(file);
2904   if (!out != 0) {
2905      _error->Error(_("Can't write %s"), file);
2906      me->_userDialog->showErrors();
2907      return;
2908   }
2909   me->_lister->writeSelections(out, false);
2910
2911   while (li != NULL) {
2912      gtk_tree_model_get_iter(me->_pkgList, &iter, (GtkTreePath *) (li->data));
2913      gtk_tree_model_get(me->_pkgList, &iter, PKG_COLUMN, &pkg, -1);
2914      if (pkg == NULL) {
2915         li = g_list_next(li);
2916         continue;
2917      }
2918
2919      pkg->setPinned(active);
2920      _roptions->setPackageLock(pkg->name(), active);
2921      li = g_list_next(li);
2922   }
2923   me->_lister->openCache();
2924
2925   // reread saved selections
2926   ifstream in(file);
2927   if (!in != 0) {
2928      _error->Error(_("Can't read %s"), file);
2929      me->_userDialog->showErrors();
2930      return;
2931   }
2932   me->_lister->readSelections(in);
2933   unlink(file);
2934   g_free((void *)file);
2935
2936   // free the list
2937   g_list_foreach(list, (void (*)(void *, void *))gtk_tree_path_free, NULL);
2938   g_list_free(list);
2939
2940   me->_lister->registerObserver(me);
2941   me->setTreeLocked(FALSE);
2942   me->refreshTable();
2943   me->refreshSubViewList();
2944   me->refreshTable();
2945   me->setInterfaceLocked(FALSE);
2946}
2947
2948void RGMainWindow::cbTreeviewPopupMenu(GtkWidget *treeview,
2949                                       GdkEventButton *event,
2950                                       RGMainWindow *me,
2951                                       vector<RPackage *> selected_pkgs)
2952{
2953   // Nothing selected, shouldn't happen, but we play safely.
2954   if (selected_pkgs.size() == 0)
2955      return;
2956
2957   // FIXME: we take the first pkg and find out available actions,
2958   //        we should calc available actions from all selected pkgs.
2959   RPackage *pkg = selected_pkgs[0];
2960
2961   int flags = pkg->getFlags();
2962
2963   if( flags & RPackage::FPinned)
2964      return;
2965
2966   // Gray out buttons that don't make sense, and update image
2967   // if necessary.
2968   GList *item = gtk_container_get_children(GTK_CONTAINER(me->_popupMenu));
2969   gpointer oneclickitem = NULL;
2970   for (int i = 0; item != NULL; item = g_list_next(item), i++) {
2971
2972      gtk_widget_set_sensitive(GTK_WIDGET(item->data), FALSE);
2973      gtk_widget_show(GTK_WIDGET(item->data));
2974
2975      // This must be optimized. -- niemeyer
2976
2977      // Keep button
2978      if (i == 0) {
2979         if (!(flags & RPackage::FKeep)) {
2980            gtk_widget_set_sensitive(GTK_WIDGET(item->data), TRUE);
2981            oneclickitem = item->data;
2982         }
2983
2984         GtkWidget *img;
2985         if (!(flags & RPackage::FInstalled))
2986            img = get_gtk_image("package-available");
2987         else
2988            img = get_gtk_image("package-installed-updated");
2989         gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item->data), img);
2990         gtk_widget_show(img);
2991      }
2992
2993      // Install button
2994      if (i == 1 && !(flags & RPackage::FInstalled)
2995          && !(flags & RPackage::FInstall)) {
2996         gtk_widget_set_sensitive(GTK_WIDGET(item->data), TRUE);
2997         if (oneclickitem == NULL)
2998            oneclickitem = item->data;
2999      }
3000
3001      // Re-install button
3002      if (i == 2 && (flags & RPackage::FInstalled)
3003          && !(flags & RPackage::FOutdated)
3004          && !(flags & RPackage::FNotInstallable)) {
3005         gtk_widget_set_sensitive(GTK_WIDGET(item->data), TRUE);
3006      }
3007
3008      // Upgrade button
3009      if (i == 3 && (flags & RPackage::FOutdated)
3010          && !(flags & RPackage::FInstall)) {
3011         gtk_widget_set_sensitive(GTK_WIDGET(item->data), TRUE);
3012         if (oneclickitem == NULL)
3013            oneclickitem = item->data;
3014      }
3015
3016      // remove
3017      if (i == 4 &&  (flags & RPackage::FInstalled)
3018          && (!(flags & RPackage::FRemove) || (flags & RPackage::FPurge)) ) {
3019            gtk_widget_set_sensitive(GTK_WIDGET(item->data), TRUE);
3020            if (oneclickitem == NULL)
3021               oneclickitem = item->data;
3022      }
3023
3024      // Purge
3025      if (i == 5
3026          && (flags&RPackage::FInstalled || flags&RPackage::FResidualConfig)
3027          && !(flags & RPackage::FPurge) ) {
3028         gtk_widget_set_sensitive(GTK_WIDGET(item->data), TRUE);
3029      }
3030
3031      // Seperator is i==6 (hide on left click)
3032      if(i == 6 && event->button == 1)
3033         gtk_widget_hide(GTK_WIDGET(item->data));
3034      // Properties is i==7 (available if only one pkg is selected)
3035      if (i == 7) {
3036         if(event->button == 1)
3037            gtk_widget_hide(GTK_WIDGET(item->data));
3038         else if(selected_pkgs.size() == 1)
3039            gtk_widget_set_sensitive(GTK_WIDGET(item->data), TRUE);
3040      }
3041
3042      // i==8 is sperator, hide on left click
3043      if(i == 8 && event->button == 1)
3044         gtk_widget_hide(GTK_WIDGET(item->data));
3045      // recommends
3046      if(i == 9) {
3047         if(event->button == 1)
3048            gtk_widget_hide(GTK_WIDGET(item->data));
3049         else if(selected_pkgs.size() == 1) {
3050            GtkWidget *menu;
3051            menu = me->buildWeakDependsMenu(pkg, pkgCache::Dep::Recommends);
3052            if(menu != NULL) {
3053               gtk_widget_set_sensitive(GTK_WIDGET(item->data), TRUE);     
3054               gtk_menu_item_set_submenu(GTK_MENU_ITEM(item->data), menu);
3055            } else
3056               gtk_widget_set_sensitive(GTK_WIDGET(item->data), FALSE);     
3057         }
3058      }
3059      if(i == 10) {
3060         if(event->button == 1)
3061            gtk_widget_hide(GTK_WIDGET(item->data));
3062         else if(selected_pkgs.size() == 1) {
3063            gtk_widget_set_sensitive(GTK_WIDGET(item->data), TRUE);
3064            GtkWidget *menu;
3065            menu = me->buildWeakDependsMenu(pkg, pkgCache::Dep::Suggests);
3066            if( menu != NULL) {
3067               gtk_widget_set_sensitive(GTK_WIDGET(item->data), TRUE);     
3068               gtk_menu_item_set_submenu(GTK_MENU_ITEM(item->data), menu);
3069            } else
3070               gtk_widget_set_sensitive(GTK_WIDGET(item->data), FALSE);     
3071         }
3072      }
3073   }
3074
3075   if (event->button == 1 && oneclickitem != NULL &&
3076       _config->FindB("Synaptic::OneClickOnStatusActions", false) == true) {
3077      gtk_menu_item_activate(GTK_MENU_ITEM(oneclickitem));
3078   } else {
3079      gtk_menu_popup(GTK_MENU(me->_popupMenu), NULL, NULL, NULL, NULL,
3080                     (event != NULL) ? event->button : 0,
3081                     gdk_event_get_time((GdkEvent *) event));
3082   }
3083}
3084
3085GtkWidget* RGMainWindow::buildWeakDependsMenu(RPackage *pkg,
3086                                              pkgCache::Dep::DepType type)
3087{
3088   // safty first
3089   if(pkg == NULL) return NULL;
3090   bool found=false;
3091
3092   GtkWidget *menu = gtk_menu_new();
3093   GtkWidget *item;
3094   vector<DepInformation> deps = pkg->enumDeps();
3095   for(unsigned int i=0;i<deps.size();i++) {
3096      if(deps[i].type == type) {
3097         // not virtual
3098         if(!deps[i].isVirtual) {
3099            found = true;
3100            item = gtk_menu_item_new_with_label(deps[i].name);
3101            g_object_set_data(G_OBJECT(item), "me", this);
3102            gtk_widget_show(item);
3103            gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
3104            if(deps[i].isSatisfied)
3105               gtk_widget_set_sensitive(item, false);
3106            else
3107               g_signal_connect(G_OBJECT(item), "activate",
3108                                G_CALLBACK(pkgInstallByNameHelper),
3109                                (void*)deps[i].name);
3110         } else {
3111            // TESTME: expand virutal packages (expensive!?!)
3112            const vector<RPackage *> pkgs = _lister->getPackages();
3113            for(unsigned int k=0;k<pkgs.size();k++) {
3114               vector<string> d = pkgs[k]->provides();
3115               for(unsigned int j=0;j<d.size();j++)
3116                  if(strcoll(deps[i].name, d[j].c_str()) == 0) {
3117                     found = true;
3118                     item = gtk_menu_item_new_with_label(pkgs[k]->name());
3119                     g_object_set_data(G_OBJECT(item), "me", this);
3120                     gtk_widget_show(item);
3121                     gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
3122                     int f = pkgs[k]->getFlags();
3123                     if((f & RPackage::FInstall) || (f & RPackage::FInstalled))
3124                        gtk_widget_set_sensitive(item, false);
3125                     else
3126                        g_signal_connect(G_OBJECT(item), "activate",
3127                                         G_CALLBACK(pkgInstallByNameHelper),
3128                                         (void*)pkgs[k]->name());
3129                  }
3130            }
3131         }
3132      }
3133   }
3134   gtk_widget_show(menu);
3135   if(found)
3136      return menu;
3137   else
3138      return NULL;
3139}
3140
3141void RGMainWindow::selectToInstall(vector<string> packagenames)
3142{
3143   RGMainWindow *me = this;
3144
3145   RPackageLister::pkgState state;
3146   vector<RPackage *> exclude;
3147   vector<RPackage *> instPkgs;
3148
3149   // we always save the state (for undo)
3150   me->_lister->saveState(state);
3151   me->_lister->notifyCachePreChange();
3152
3153   for(unsigned int i=0;i<packagenames.size();i++) {
3154      RPackage *newpkg = (RPackage *) me->_lister->getPackage(packagenames[i]);
3155      if (newpkg) {
3156         // only install the package if it is not already installed or if
3157         // it is outdated
3158         if(!(newpkg->getFlags()&RPackage::FInstalled) ||
3159             (newpkg->getFlags()&RPackage::FOutdated)) {
3160            // actual action
3161            newpkg->setNotify(false);
3162            me->pkgInstallHelper(newpkg);
3163            newpkg->setNotify(true);
3164            //exclude.push_back(newpkg);
3165            instPkgs.push_back(newpkg);
3166         }
3167      }
3168   }
3169
3170   // ask for additional changes
3171   me->setBusyCursor(true);
3172   if(me->askStateChange(state, exclude)) {
3173      me->_lister->saveUndoState(state);
3174      if(me->checkForFailedInst(instPkgs))
3175         me->_lister->restoreState(state);
3176   }
3177   me->setBusyCursor(false);
3178   me->_lister->notifyPostChange(NULL);
3179   me->_lister->notifyCachePostChange();
3180   
3181   RPackage *pkg = me->selectedPackage();
3182   me->refreshTable(pkg);
3183   me->updatePackageInfo(pkg);
3184}
3185
3186void RGMainWindow::pkgInstallByNameHelper(GtkWidget *self, void *data)
3187{
3188   const char *name = (const char*)data;
3189   //cout << "pkgInstallByNameHelper: " << name << endl;
3190   
3191   RGMainWindow *me = (RGMainWindow*)g_object_get_data(G_OBJECT(self), "me");
3192
3193   RPackage *newpkg = (RPackage *) me->_lister->getPackage(name);
3194   if (newpkg) {
3195      RPackageLister::pkgState state;
3196      vector<RPackage *> exclude;
3197      vector<RPackage *> instPkgs;
3198
3199      // we always save the state (for undo)
3200      me->_lister->saveState(state);
3201      me->_lister->notifyCachePreChange();
3202
3203      // actual action
3204      newpkg->setNotify(false);
3205      me->pkgInstallHelper(newpkg);
3206      newpkg->setNotify(true);
3207
3208      exclude.push_back(newpkg);
3209      instPkgs.push_back(newpkg);
3210
3211      // ask for additional changes
3212      if(me->askStateChange(state, exclude)) {
3213         me->_lister->saveUndoState(state);
3214         if(me->checkForFailedInst(instPkgs))
3215            me->_lister->restoreState(state);
3216      }
3217      me->_lister->notifyPostChange(NULL);
3218      me->_lister->notifyCachePostChange();
3219     
3220      RPackage *pkg = me->selectedPackage();
3221      me->refreshTable(pkg);
3222      me->updatePackageInfo(pkg);
3223   }
3224}
3225
3226
3227
3228// vim:ts=3:sw=3:et
Note: See TracBrowser for help on using the repository browser.