[Aptitude-svn-commit] r3790 - in branches/aptitude-0.3/aptitude: . src

Daniel Burrows dburrows at costa.debian.org
Tue Aug 9 20:01:07 UTC 2005


Author: dburrows
Date: Tue Aug  9 20:01:04 2005
New Revision: 3790

Added:
   branches/aptitude-0.3/aptitude/src/solution_screen.cc
   branches/aptitude-0.3/aptitude/src/solution_screen.h
Modified:
   branches/aptitude-0.3/aptitude/ChangeLog
   branches/aptitude-0.3/aptitude/src/Makefile.am
   branches/aptitude-0.3/aptitude/src/ui.cc
Log:
First cut at a solution screen.

Modified: branches/aptitude-0.3/aptitude/ChangeLog
==============================================================================
--- branches/aptitude-0.3/aptitude/ChangeLog	(original)
+++ branches/aptitude-0.3/aptitude/ChangeLog	Tue Aug  9 20:01:04 2005
@@ -1,5 +1,9 @@
 2005-08-09  Daniel Burrows  <dburrows at debian.org>
 
+	* src/Makefile.am, src/solution_screen.cc, src/solution_screen.h, src/ui.cc:
+
+	  Initial work towards a top-level solution examination screen.
+
 	* src/pkg_info_screen.cc:
 
 	  Remove a #include of vs_staticitem.

Modified: branches/aptitude-0.3/aptitude/src/Makefile.am
==============================================================================
--- branches/aptitude-0.3/aptitude/src/Makefile.am	(original)
+++ branches/aptitude-0.3/aptitude/src/Makefile.am	Tue Aug  9 20:01:04 2005
@@ -77,6 +77,8 @@
 	solution_dialog.h\
 	solution_fragment.cc\
 	solution_fragment.h\
+	solution_screen.cc\
+	solution_screen.h\
 	trust.h		\
 	trust.cc	\
 	ui.cc		\

Added: branches/aptitude-0.3/aptitude/src/solution_screen.cc
==============================================================================
--- (empty file)
+++ branches/aptitude-0.3/aptitude/src/solution_screen.cc	Tue Aug  9 20:01:04 2005
@@ -0,0 +1,382 @@
+// solution_screen.cc
+//
+//   Copyright (C) 2005 Daniel Burrows
+//
+//   This program is free software; you can redistribute it and/or
+//   modify it under the terms of the GNU General Public License as
+//   published by the Free Software Foundation; either version 2 of
+//   the License, or (at your option) any later version.
+//
+//   This program is distributed in the hope that it will be useful,
+//   but WITHOUT ANY WARRANTY; without even the implied warranty of
+//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//   General Public License for more details.
+//
+//   You should have received a copy of the GNU General Public License
+//   along with this program; see the file COPYING.  If not, write to
+//   the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+//   Boston, MA 02111-1307, USA.
+
+#include "solution_screen.h"
+
+#include "aptitude.h"
+
+#include <generic/aptitude_resolver.h>
+#include <generic/util.h>
+
+#include <vscreen/transcode.h>
+#include <vscreen/vs_staticitem.h>
+#include <vscreen/vs_subtree.h>
+#include <vscreen/vs_tree.h>
+#include <vscreen/vs_treeitem.h>
+
+using namespace std;
+
+struct pkg_name_lt
+{
+public:
+  bool operator()(const pkgCache::PkgIterator &p1,
+		  const pkgCache::PkgIterator &p2) const
+  {
+    return strcmp(p1.Name(), p2.Name()) < 0;
+  }
+};
+
+struct ver_name_lt
+{
+public:
+  bool operator()(const pkgCache::VerIterator &v1,
+		  const pkgCache::VerIterator &v2) const
+  {
+    return strcmp(v1.ParentPkg().Name(), v2.ParentPkg().Name()) < 0;
+  }
+};
+
+/** Partition the set of all packages into several vectors,
+ *  according to the action to be performed on each package.
+ *
+ *  \param remove_packages each package to be removed will be placed in this vector.
+ *  \param keep_packages each package which is being kept will be placed
+ *         in this vector.
+ *  \param install_packages if a package is being newly installed,
+ *         its target version will be placed in this vector.
+ *  \param downgrade_packages if a package is being downgraded,
+ *         its target version will be placed in this vector.
+ *  \param upgrade_packages if a package is being upgraded,
+ *         its target version will be placed in this vector.
+ */
+void bin_packages(const aptitude_solution &sol,
+		  vector<pkgCache::PkgIterator> &remove_packages,
+		  vector<pkgCache::PkgIterator> &keep_packages,
+		  vector<pkgCache::VerIterator> &install_packages,
+		  vector<pkgCache::VerIterator> &downgrade_packages,
+		  vector<pkgCache::VerIterator> &upgrade_packages)
+{
+
+  for(std::map<aptitude_resolver::package,
+	aptitude_resolver::action>::const_iterator i=sol.get_actions().begin();
+      i!=sol.get_actions().end(); ++i)
+    {
+      pkgCache::PkgIterator pkg=i->first.get_pkg();
+      pkgCache::VerIterator curver=pkg.CurrentVer();
+      pkgCache::VerIterator newver=i->second.ver.get_ver();
+
+      if(curver.end())
+	{
+	  if(newver.end())
+	    keep_packages.push_back(pkg);
+	  else
+	    install_packages.push_back(newver);
+	}
+      else if(newver.end())
+	remove_packages.push_back(pkg);
+      else if(newver == curver)
+	keep_packages.push_back(pkg);
+      else
+	{
+	  int cmp=_system->VS->CmpVersion(curver.VerStr(),
+					  newver.VerStr());
+
+	  // The versions shouldn't be equal -- otherwise
+	  // something is majorly wrong.
+	  // assert(cmp!=0);
+	  //
+	  // The above is not true: consider, eg, the case of a
+	  // locally compiled package and a standard package.
+
+	  /** \todo indicate "sidegrades" separately? */
+	  if(cmp<=0)
+	    upgrade_packages.push_back(newver);
+	  else if(cmp>0)
+	    downgrade_packages.push_back(newver);
+	}
+    }
+}
+
+static string archives(const pkgCache::VerIterator &ver)
+{
+  string rval;
+
+  bool is_first = true;
+
+  for(pkgCache::VerFileIterator vf=ver.FileList(); !vf.end(); ++vf)
+    {
+      if(is_first)
+	is_first = false;
+      else
+	rval += ", ";
+      if(vf.File().Archive())
+	rval += vf.File().Archive();
+      else
+	rval += _("<NULL>");
+    }
+
+  return rval;
+}
+
+class label_tree : public vs_subtree_generic
+{
+  wstring my_label;
+public:
+  label_tree(wstring _label, bool _expanded = true)
+    :vs_subtree_generic(_expanded), my_label(_label)
+  {
+  }
+
+  void paint(vs_tree *win, int y, bool hierarchical,
+	     const style &st)
+  {
+    vs_subtree<vs_treeitem>::paint(win, y, hierarchical, my_label);
+  }
+
+  const wchar_t *tag()
+  {
+    return my_label.c_str();
+  }
+
+  const wchar_t *label()
+  {
+    return my_label.c_str();
+  }
+};
+
+vs_subtree_generic *make_solution_tree(const aptitude_solution &sol)
+{
+  // Bin packages according to what will happen to them.
+  vector<pkgCache::PkgIterator> remove_packages;
+  vector<pkgCache::PkgIterator> keep_packages;
+  vector<pkgCache::VerIterator> install_packages;
+  vector<pkgCache::VerIterator> downgrade_packages;
+  vector<pkgCache::VerIterator> upgrade_packages;
+
+  bin_packages(sol, remove_packages, keep_packages, install_packages,
+	       downgrade_packages, upgrade_packages);
+
+  sort(remove_packages.begin(), remove_packages.end(),
+       pkg_name_lt());
+  sort(keep_packages.begin(), keep_packages.end(),
+       pkg_name_lt());
+  sort(install_packages.begin(), install_packages.end(),
+       ver_name_lt());
+  sort(downgrade_packages.begin(), downgrade_packages.end(),
+       ver_name_lt());
+  sort(upgrade_packages.begin(), upgrade_packages.end(),
+       ver_name_lt());
+
+  vs_subtree_generic *root = new label_tree(L"");
+
+  if(!remove_packages.empty())
+    {
+      vs_subtree_generic *remove_tree = new label_tree(transcode(_("Remove the following packages:")));
+
+      for(vector<pkgCache::PkgIterator>::const_iterator i = remove_packages.begin();
+	  i != remove_packages.end(); ++i)
+	{
+	  assert(!i->CurrentVer().end());
+
+	  remove_tree->add_child(new vs_staticitem(transcode(i->Name()), L""));
+	}
+
+      root->add_child(remove_tree);
+    }
+
+  if(!keep_packages.empty())
+    {
+      vs_subtree_generic *keep_tree = new label_tree(transcode(_("Keep the following packages at their current version:")));
+
+      for(vector<pkgCache::PkgIterator>::const_iterator i = keep_packages.begin();
+	  i != keep_packages.end(); ++i)
+	{
+	  wstring text;
+
+	  if(i->CurrentVer().end())
+	    text = swsprintf(L"%s [UNINST]", i->Name());
+	  else
+	    text = swsprintf(L"%s [%s (%s)]",
+			     i->Name(), i->CurrentVer().VerStr(),
+			     archives(i->CurrentVer()).c_str());
+
+	  keep_tree->add_child(new vs_staticitem(text, L""));
+	}
+
+      root->add_child(keep_tree);
+    }
+
+  if(!install_packages.empty())
+    {
+      vs_subtree_generic *install_tree = new label_tree(transcode(_("Install the following packages:")));
+
+      for(vector<pkgCache::VerIterator>::const_iterator i = install_packages.begin();
+	  i != install_packages.end(); ++i)
+	{
+	  pkgCache::PkgIterator p = i->ParentPkg();
+
+	  wstring text = swsprintf(L"%s [%s (%s)]",
+				   p.Name(), i->VerStr(),
+				   archives(*i).c_str());
+
+	  install_tree->add_child(new vs_staticitem(text, L""));
+	}
+
+      root->add_child(install_tree);
+    }
+
+  if(!upgrade_packages.empty())
+    {
+      vs_subtree_generic *upgrade_tree = new label_tree(transcode(_("Upgrade the following packages:")));
+
+      for(vector<pkgCache::VerIterator>::const_iterator i = upgrade_packages.begin();
+	  i != upgrade_packages.end(); ++i)
+	{
+	  pkgCache::PkgIterator p = i->ParentPkg();
+	  pkgCache::VerIterator currver = p.CurrentVer();
+	  pkgCache::VerIterator instver = (*apt_cache_file)[p].InstVerIter(*apt_cache_file);
+
+	  assert(!currver.end());
+	  assert(!instver.end());
+
+	  wstring text = swsprintf(L"%s [%s (%s) -> %s (%s)]",
+				   p.Name(),
+				   currver.VerStr(), archives(currver).c_str(),
+				   instver.VerStr(), archives(instver).c_str());
+
+	  upgrade_tree->add_child(new vs_staticitem(text, L""));
+	}
+
+      root->add_child(upgrade_tree);
+    }
+
+  if(!downgrade_packages.empty())
+    {
+      vs_subtree_generic *downgrade_tree = new label_tree(transcode(_("Downgrade the following packages:")));
+
+      for(vector<pkgCache::VerIterator>::const_iterator i = downgrade_packages.begin();
+	  i != downgrade_packages.end(); ++i)
+	{
+	  pkgCache::PkgIterator p = i->ParentPkg();
+	  pkgCache::VerIterator currver = p.CurrentVer();
+
+	  assert(!currver.end());
+
+	  wstring text = swsprintf(L"%s [%s (%s) -> %s (%s)]",
+				   p.Name(),
+				   currver.VerStr(), archives(currver).c_str(),
+				   i->VerStr(), archives(*i).c_str());
+
+	  downgrade_tree->add_child(new vs_staticitem(text, L""));
+	}
+
+      root->add_child(downgrade_tree);
+    }
+
+  return root;
+}
+
+class solution_screen : public vs_tree
+{
+  aptitude_resolver::solution last_sol;
+
+  void attach_apt_cache_signals()
+  {
+    if(apt_cache_file)
+      {
+	(*apt_cache_file)->package_state_changed.connect(sigc::mem_fun(*this, &solution_screen::update));
+	(*apt_cache_file)->selected_solution_changed.connect(sigc::mem_fun(*this, &solution_screen::update));
+      }
+  }
+
+  /** Re-connects the signals attached to the apt cache file. */
+  void handle_cache_reload()
+  {
+    attach_apt_cache_signals();
+
+    update();
+  }
+
+protected:
+  solution_screen()
+  {
+    attach_apt_cache_signals();
+
+    cache_closed.connect(sigc::mem_fun(*this, &solution_screen::update));
+    cache_reloaded.connect(sigc::mem_fun(*this, &solution_screen::handle_cache_reload));
+
+    update();
+  }
+
+public:
+  static ref_ptr<solution_screen> create()
+  {
+    return new solution_screen;
+  }
+
+  void update()
+  {
+    if(!apt_cache_file)
+      {
+	set_root(new vs_staticitem(transcode(_("The package cache is not available.")),
+				   L""),
+		 true);
+	return;
+      }
+
+    if(!(*apt_cache_file)->resolver_exists())
+      {
+	// No packages are broken; remove this screen.
+	destroy();
+	return;
+      }
+
+    try
+      {
+	aptitude_resolver::solution sol=(*apt_cache_file)->get_current_solution();
+
+	if(sol == last_sol)
+	  return;
+
+	last_sol = sol;
+
+	if(sol.get_actions().empty())
+	  set_root(new vs_staticitem(transcode(_("Internal error: unexpected null solution.")),
+				     L""));
+	else
+	  set_root(make_solution_tree(sol));
+      }
+    catch(NoMoreSolutions)
+      {
+	set_root(new vs_staticitem(transcode(_("No resolution found.")),
+				   L""));
+      }
+    catch(NoMoreTime)
+      {
+	set_root(new vs_staticitem(transcode(ssprintf(_("Time exhausted while searching for a solution (you can select \"Next Solution\" or press %s to try harder)."),
+						      global_bindings.readable_keyname("NextSolution").c_str())),
+				   L""));
+      }
+  }
+};
+
+vs_widget_ref make_solution_screen()
+{
+  return solution_screen::create();
+}

Added: branches/aptitude-0.3/aptitude/src/solution_screen.h
==============================================================================
--- (empty file)
+++ branches/aptitude-0.3/aptitude/src/solution_screen.h	Tue Aug  9 20:01:04 2005
@@ -0,0 +1,37 @@
+// solution_screen.h                          -*-c++-*-
+//
+//   Copyright (C) 2005 Daniel Burrows
+//
+//   This program is free software; you can redistribute it and/or
+//   modify it under the terms of the GNU General Public License as
+//   published by the Free Software Foundation; either version 2 of
+//   the License, or (at your option) any later version.
+//
+//   This program is distributed in the hope that it will be useful,
+//   but WITHOUT ANY WARRANTY; without even the implied warranty of
+//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//   General Public License for more details.
+//
+//   You should have received a copy of the GNU General Public License
+//   along with this program; see the file COPYING.  If not, write to
+//   the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+//   Boston, MA 02111-1307, USA.
+
+#ifndef SOLUTION_SCREEN_H
+#define SOLUTION_SCREEN_H
+
+#include <vscreen/ref_ptr.h>
+
+class aptitude_universe;
+template<class PackageUniverse> class generic_solution;
+class vscreen_widget;
+
+typedef generic_solution<aptitude_universe> aptitude_solution;
+typedef ref_ptr<vscreen_widget> vs_widget_ref;
+
+/** Generate a new widget suitable for inclusion at the top-level
+ *  which describes the given solution.
+ */
+vs_widget_ref make_solution_screen();
+
+#endif // SOLUTION_SCREEN_H

Modified: branches/aptitude-0.3/aptitude/src/ui.cc
==============================================================================
--- branches/aptitude-0.3/aptitude/src/ui.cc	(original)
+++ branches/aptitude-0.3/aptitude/src/ui.cc	Tue Aug  9 20:01:04 2005
@@ -52,6 +52,7 @@
 #include "load_pkgview.h"
 #include "solution_dialog.h"
 #include "solution_fragment.h"
+#include "solution_screen.h"
 
 #include <vscreen/curses++.h>
 #include <vscreen/fragment.h>
@@ -1358,9 +1359,27 @@
     }
 }
 
+static void do_nullify_solver(vs_widget_ref *solver)
+{
+  *solver = NULL;
+}
+
 static void do_examine_solution()
 {
-  popup_widget(make_solution_dialog(), true);
+  static vs_widget_ref solver;
+
+  if(solver.valid())
+    solver->show();
+  else
+    {
+      solver = make_solution_screen();
+      solver->destroyed.connect(sigc::bind(sigc::ptr_fun(&do_nullify_solver),
+					   &solver));
+
+      add_main_widget(solver, _("Resolve Dependencies"),
+		      _("Search for solutions to unsatisfied dependencies"),
+		      _("Resolve Dependencies"));
+    }
 }
 
 static void handle_dump_resolver_response(const wstring &s)



More information about the Aptitude-svn-commit mailing list