libyui-gtk-pkg  2.43.2
 All Classes
yzyppwrapper.cc
1 /********************************************************************
2  * YaST2-GTK - http://en.opensuse.org/YaST2-GTK *
3  ********************************************************************/
4 /* Ypp, the zypp wrapper */
5 // check the header file for information about this wrapper
6 
7 /*
8  Textdomain "gtk"
9  */
10 
11 #include "config.h"
12 #include "YGi18n.h"
13 #define YUILogComponent "gtk-pkg"
14 #include <YUILog.h>
15 #include "yzyppwrapper.h"
16 #include "YGUtils.h"
17 #include <algorithm>
18 
19 static Ypp::Interface *g_interface = 0;
20 static bool g_autoSolver = true;
21 
22 // Repository
23 
24 Ypp::Repository::Repository (zypp::Repository repo)
25 : m_repo (repo), m_repo_info (repo.info()), m_onlyInfo (false) {}
26 
27 Ypp::Repository::Repository (zypp::RepoInfo repo)
28 : m_repo (NULL), m_repo_info (repo), m_onlyInfo (true) {}
29 
30 std::string Ypp::Repository::name()
31 { return m_repo_info.name(); }
32 
33 std::string Ypp::Repository::url()
34 { return m_repo_info.url().asString(); }
35 
36 bool Ypp::Repository::enabled()
37 { return m_repo_info.enabled(); }
38 
39 bool Ypp::Repository::isOutdated()
40 { return m_onlyInfo ? false : m_repo.maybeOutdated(); }
41 
42 bool Ypp::Repository::isSystem()
43 { return m_repo.isSystemRepo(); }
44 
45 bool Ypp::Repository::operator == (const Ypp::Repository &other) const
46 { return this->m_repo.info().alias() == other.m_repo.info().alias(); }
47 
48 void Ypp::getRepositoryFromAlias (const std::string &alias, std::string &name, std::string &url)
49 {
50  static std::map <std::string, zypp::RepoInfo> repos;
51  if (repos.empty()) {
52  zypp::RepoManager manager;
53  std::list <zypp::RepoInfo> known_repos = manager.knownRepositories();
54  for (std::list <zypp::RepoInfo>::const_iterator it = known_repos.begin();
55  it != known_repos.end(); it++)
56  repos[it->alias()] = *it;
57  }
58 
59  std::map <std::string, zypp::RepoInfo>::iterator it = repos.find (alias);
60  if (it != repos.end()) {
61  zypp::RepoInfo *repo = &it->second;
62  name = repo->name();
63  url = repo->url().asString();
64  }
65  else
66  name = alias; // return alias if repo not currently setup-ed
67 }
68 
69 // Version
70 
71 Ypp::Version::Version (ZyppResObject zobj)
72 : m_zobj (zobj) {}
73 
74 int Ypp::Version::type()
75 { return Selectable::asType (m_zobj->kind()); }
76 
77 std::string Ypp::Version::number()
78 { return m_zobj->edition().asString(); }
79 
80 std::string Ypp::Version::arch()
81 { return m_zobj->arch().asString(); }
82 
83 Ypp::Repository Ypp::Version::repository()
84 { return Repository (m_zobj->repository()); }
85 
86 Size_t Ypp::Version::size()
87 { return m_zobj->installSize(); }
88 
89 Size_t Ypp::Version::downloadSize()
90 { return m_zobj->downloadSize(); }
91 
92 bool Ypp::Version::isInstalled()
93 {
94  zypp::ResStatus status = m_zobj->poolItem().status();
95  switch (type()) {
96  case Ypp::Selectable::PATCH:
97  case Ypp::Selectable::PATTERN:
98  return status.isSatisfied() && !status.isToBeInstalled();
99  default:
100  return status.isInstalled();
101  }
102 }
103 
104 bool Ypp::Version::toModify()
105 {
106  zypp::ResStatus status = m_zobj->poolItem().status();
107  return status.transacts();
108 }
109 
110 bool Ypp::Version::operator < (Ypp::Version &other)
111 { return this->m_zobj->edition() < other.m_zobj->edition(); }
112 
113 bool Ypp::Version::operator > (Ypp::Version &other)
114 { return this->m_zobj->edition() > other.m_zobj->edition(); }
115 
116 bool Ypp::Version::operator == (Ypp::Version &other)
117 { return this->m_zobj->edition() == other.m_zobj->edition(); }
118 
119 // Selectable
120 
121 zypp::ResKind Ypp::Selectable::asKind (Type type)
122 {
123  switch (type) {
124  case PATTERN: return zypp::ResKind::pattern;
125  case PATCH: return zypp::ResKind::patch;
126  case PACKAGE: case LANGUAGE: case ALL: break;
127  }
128  return zypp::ResKind::package;
129 }
130 
131 Ypp::Selectable::Type Ypp::Selectable::asType (zypp::ResKind kind)
132 {
133  if (kind == zypp::ResKind::patch)
134  return PATCH;
135  if (kind == zypp::ResKind::pattern)
136  return PATTERN;
137  return PACKAGE;
138 }
139 
140 Ypp::Selectable::Selectable (ZyppSelectable sel)
141 : m_type (asType (sel->kind())), m_sel (sel)
142 {}
143 
144 Ypp::Selectable::Selectable (zypp::Locale locale)
145 : m_type (LANGUAGE), m_locale (locale) {}
146 
147 Ypp::Selectable::Type Ypp::Selectable::type()
148 { return m_type; }
149 
150 std::string Ypp::Selectable::name()
151 {
152  switch (m_type) {
153  case LANGUAGE: return m_locale.name() + " (" + m_locale.code() + ")";
154  case PATTERN: return m_sel->theObj()->summary();
155  default: break;
156  }
157  return m_sel->name();
158 }
159 
160 std::string Ypp::Selectable::summary()
161 {
162  switch (m_type) {
163  case PATTERN:
164  case LANGUAGE: {
165  Collection col (*this);
166  int installed, total;
167  col.stats (&installed, &total);
168  std::ostringstream stream;
169  stream << _("Installed:") << " " << installed << " " << _("of") << " " << total;
170  return stream.str();
171  }
172  default: break;
173  }
174  return m_sel->theObj()->summary();
175 }
176 
177 std::string Ypp::Selectable::description (bool as_html)
178 {
179  if (m_type == LANGUAGE)
180  return summary();
181 
182  std::string text (m_sel->theObj()->description()), br ("\n");
183  if (as_html) br = "<br />";
184  switch (m_type) {
185  case PACKAGE: {
186  // if it has this header, then it is HTML
187  const char *header = "<!-- DT:Rich -->", header_len = 16;
188  if (!text.compare (0, header_len, header, header_len))
189  ;
190  else {
191  // cut authors block
192  std::string::size_type i = text.find ("\nAuthors:", 0);
193  if (i == std::string::npos)
194  i = text.find ("\nAuthor:", 0);
195  if (i != std::string::npos)
196  text.erase (i);
197  // cut any lines at the end
198  while (text.length() > 0 && text [text.length()-1] == '\n')
199  text.erase (text.length()-1);
200 
201  text = YGUtils::escapeMarkup (text);
202  if (as_html) // break every double line
203  YGUtils::replace (text, "\n\n", 2, "<br>");
204  text += br;
205  }
206  break;
207  }
208  case PATCH: {
209  ZyppPatch patch = castZyppPatch (m_sel->theObj());
210  if (patch->rebootSuggested()) {
211  text += br + br + "<b>" + _("Reboot required:") + " </b>";
212  text += _("the system will have to be restarted in order for "
213  "this patch to take effect.");
214  }
215  if (patch->reloginSuggested()) {
216  text += br + br + "<b>" + _("Relogin required:") + " </b>";
217  text += _("you must logout and login again for "
218  "this patch to take effect.");
219  }
220  if (patch->referencesBegin() != patch->referencesEnd()) {
221  text += br + br + "<b>Bugzilla:</b><ul>";
222  for (zypp::Patch::ReferenceIterator it = patch->referencesBegin();
223  it != patch->referencesEnd(); it++)
224  text += "<li><a href=\"" + it.href() + "\">" + it.title() + "</a></li>";
225  text += "</ul>";
226  }
227  break;
228  }
229  case PATTERN: {
230  text += br + br + summary();
231  break;
232  }
233  default: break;
234  }
235  return text;
236 }
237 
238 bool Ypp::Selectable::visible()
239 {
240  switch (m_type) {
241  case PATTERN: {
242  ZyppPattern pattern = castZyppPattern (zyppSel()->theObj());
243  return pattern->userVisible();
244  }
245  case PATCH:
246  if (zyppSel()->hasCandidateObj())
247  if (!zyppSel()->candidateObj().isRelevant())
248  return false;
249  return true;
250  default: break;
251  }
252  return true;
253 }
254 
255 bool Ypp::Selectable::isInstalled()
256 {
257  switch (m_type) {
258  case PACKAGE:
259  return !m_sel->installedEmpty();
260  case PATTERN:
261  case PATCH:
262  if (hasCandidateVersion())
263  return candidate().isInstalled();
264  return true;
265  case LANGUAGE:
266  return _zyppPool().isRequestedLocale (m_locale);
267  case ALL: break;
268  }
269  return 0;
270 }
271 
272 bool Ypp::Selectable::hasUpgrade()
273 {
274  switch (m_type) {
275  case LANGUAGE: break;
276  default: {
277  const ZyppResObject candidate = m_sel->candidateObj();
278  const ZyppResObject installed = m_sel->installedObj();
279  if (!!candidate && !!installed)
280  return zypp::Edition::compare (candidate->edition(), installed->edition()) > 0;
281  }
282  }
283  return false;
284 }
285 
286 bool Ypp::Selectable::isLocked()
287 {
288  switch (m_type) {
289  case LANGUAGE: break;
290  default: {
291  zypp::ui::Status status = m_sel->status();
292  return status == zypp::ui::S_Taboo || status == zypp::ui::S_Protected;
293  }
294  }
295  return false;
296 }
297 
298 bool Ypp::Selectable::toInstall()
299 {
300  switch (m_type) {
301  case LANGUAGE: break;
302  default: return m_sel->toInstall();
303  }
304  return false;
305 }
306 
307 bool Ypp::Selectable::toRemove()
308 {
309  switch (m_type) {
310  case LANGUAGE: break;
311  default: return m_sel->toDelete();
312  }
313  return false;
314 }
315 
316 bool Ypp::Selectable::toModify()
317 {
318  switch (m_type) {
319  case LANGUAGE: break;
320  default: return m_sel->toModify();
321  }
322  return false;
323 }
324 
325 bool Ypp::Selectable::toModifyAuto()
326 {
327  switch (m_type) {
328  case LANGUAGE: break;
329  default:
330  return m_sel->toModify() && m_sel->modifiedBy() != zypp::ResStatus::USER;
331  }
332  return false;
333 }
334 
335 void Ypp::Selectable::install()
336 {
337  if (isLocked())
338  return;
339  switch (m_type) {
340  case LANGUAGE:
341  if (!_zyppPool().isRequestedLocale (m_locale))
342  _zyppPool().addRequestedLocale (m_locale);
343  break;
344  default: {
345  if (!m_sel->hasLicenceConfirmed()) {
346  ZyppResObject obj = m_sel->candidateObj();
347  if (obj && g_interface && g_autoSolver) {
348  const std::string &license = obj->licenseToConfirm();
349  if (!license.empty())
350  if (!g_interface->showLicense (*this, license))
351  return;
352  const std::string &msg = obj->insnotify();
353  if (!msg.empty())
354  if (!g_interface->showMessage (*this, msg))
355  return;
356  }
357  m_sel->setLicenceConfirmed();
358  }
359 
360  zypp::ui::Status status = m_sel->status();
361  switch (status) {
362  // not applicable
363  case zypp::ui::S_Protected:
364  case zypp::ui::S_Taboo:
365  case zypp::ui::S_Install:
366  case zypp::ui::S_Update:
367  break;
368  // undo
369  case zypp::ui::S_Del:
370  if (hasInstalledVersion())
371  status = zypp::ui::S_Update;
372  else
373  status = zypp::ui::S_Install;
374  break;
375  // nothing to do about it
376  case zypp::ui::S_AutoDel:
377  break;
378  // action
379  case zypp::ui::S_NoInst:
380  case zypp::ui::S_AutoInstall:
381  status = zypp::ui::S_Install;
382  break;
383  case zypp::ui::S_KeepInstalled:
384  case zypp::ui::S_AutoUpdate:
385  status = zypp::ui::S_Update;
386  break;
387  }
388  m_sel->setStatus (status);
389  break;
390  }
391  }
392 
393  if (!runSolver()) undo();
394 }
395 
396 void Ypp::Selectable::remove()
397 {
398  switch (m_type) {
399  case LANGUAGE:
400  if (_zyppPool().isRequestedLocale (m_locale))
401  _zyppPool().eraseRequestedLocale (m_locale);
402  break;
403  default: {
404  if (m_sel->hasCandidateObj() && g_interface && g_autoSolver) {
405  ZyppResObject obj = m_sel->candidateObj();
406  const std::string &msg = obj->delnotify();
407  if (!msg.empty())
408  if (!g_interface->showMessage (*this, msg))
409  return;
410  }
411 
412  zypp::ui::Status status = m_sel->status();
413  switch (status) {
414  // not applicable
415  case zypp::ui::S_Protected:
416  case zypp::ui::S_Taboo:
417  case zypp::ui::S_NoInst:
418  case zypp::ui::S_Del:
419  break;
420  // nothing to do about it
421  case zypp::ui::S_AutoInstall:
422  case zypp::ui::S_AutoUpdate:
423  break;
424  // undo
425  case zypp::ui::S_Install:
426  case zypp::ui::S_Update:
427  // action
428  case zypp::ui::S_KeepInstalled:
429  case zypp::ui::S_AutoDel:
430  status = zypp::ui::S_Del;
431  break;
432  }
433  m_sel->setStatus (status);
434  break;
435  }
436  }
437 
438  if (!runSolver()) undo();
439 }
440 
441 void Ypp::Selectable::undo()
442 {
443  // undo not applicable to language type
444 
445  zypp::ui::Status status = m_sel->status();
446  zypp::ui::Status prev_status = status;
447  switch (status) {
448  // not applicable
449  case zypp::ui::S_Protected:
450  case zypp::ui::S_Taboo:
451  case zypp::ui::S_NoInst:
452  case zypp::ui::S_KeepInstalled:
453  break;
454  // undo
455  case zypp::ui::S_Install:
456  case zypp::ui::S_AutoInstall:
457  status = zypp::ui::S_NoInst;
458  break;
459  case zypp::ui::S_AutoUpdate:
460  case zypp::ui::S_AutoDel:
461  case zypp::ui::S_Update:
462  case zypp::ui::S_Del:
463  status = zypp::ui::S_KeepInstalled;
464  break;
465  }
466  m_sel->setStatus (status);
467 
468  if (!runSolver()) {
469  m_sel->setStatus (prev_status);
470  runSolver();
471  }
472 }
473 
474 void Ypp::Selectable::lock (bool lock)
475 {
476  undo();
477  zypp::ui::Status status;
478  if (lock)
479  status = isInstalled() ? zypp::ui::S_Protected : zypp::ui::S_Taboo;
480  else
481  status = isInstalled() ? zypp::ui::S_KeepInstalled : zypp::ui::S_NoInst;
482  m_sel->setStatus (status);
483 
484  if (!runSolver()) undo();
485 }
486 
487 bool Ypp::Selectable::canRemove()
488 {
489  switch (m_type) {
490  case PACKAGE: case LANGUAGE: return true;
491  default: break;
492  }
493  return false;
494 }
495 
496 bool Ypp::Selectable::canLock()
497 {
498  switch (m_type) {
499  case PACKAGE:
500  //case PATCH:
501  return true;
502  default: break;
503  }
504  return false;
505 }
506 
507 int Ypp::Selectable::totalVersions()
508 { return m_sel->installedSize() + m_sel->availableSize(); }
509 
510 Ypp::Version Ypp::Selectable::version (int n)
511 {
512  if (n < (signed) m_sel->installedSize()) {
513  zypp::ui::Selectable::installed_iterator it = m_sel->installedBegin();
514  for (int i = 0; i < n; i++) it++;
515  return Version (*it);
516  }
517  else {
518  n -= m_sel->installedSize();
519  zypp::ui::Selectable::available_iterator it = m_sel->availableBegin();
520  for (int i = 0; i < n; i++) it++;
521  return Version (*it);
522  }
523 }
524 
525 bool Ypp::Selectable::hasCandidateVersion()
526 { return !m_sel->availableEmpty(); }
527 
528 Ypp::Version Ypp::Selectable::candidate()
529 { return Version (m_sel->candidateObj()); }
530 
531 void Ypp::Selectable::setCandidate (Ypp::Version &version)
532 {
533  m_sel->setCandidate (version.zyppObj());
534  runSolver();
535 }
536 
537 bool Ypp::Selectable::hasInstalledVersion()
538 { return !m_sel->installedEmpty(); }
539 
540 Ypp::Version Ypp::Selectable::installed()
541 {
542  if (m_type == PATCH || m_type == PATTERN) {
543  if (m_sel->candidateObj() && m_sel->candidateObj().isSatisfied())
544  return Ypp::Version (m_sel->candidateObj());
545  }
546  return Ypp::Version (m_sel->installedObj());
547 }
548 
549 Ypp::Version Ypp::Selectable::anyVersion()
550 { return Version (m_sel->theObj()); }
551 
552 bool Ypp::Selectable::operator == (const Ypp::Selectable &other) const
553 { return this->m_sel == other.m_sel; }
554 
555 bool Ypp::Selectable::operator != (const Ypp::Selectable &other) const
556 { return this->m_sel != other.m_sel; }
557 
558 // Collection
559 
560 Ypp::Collection::Collection (Ypp::Selectable &sel)
561 : m_sel (sel) {}
562 
563 static std::map <ZyppPattern, Ypp::List> g_patternsContent;
564 static std::map <zypp::Locale, Ypp::List> g_languagesContent;
565 
566 Ypp::List *Ypp::Collection::getContent()
567 { // zypp::Pattern::Contents is expensive to iterate; this makes it cheap
568  if (m_sel.type() == Ypp::Selectable::PATTERN) {
569  ZyppPattern pattern = castZyppPattern (m_sel.zyppSel()->theObj());
570  std::map <ZyppPattern, Ypp::List>::iterator it;
571  if ((it = g_patternsContent.find (pattern)) != g_patternsContent.end())
572  return &it->second;
573 
574  zypp::Pattern::Contents c = pattern->contents();
575  Ypp::List list (c.size());
576  for (zypp::Pattern::Contents::Selectable_iterator it = c.selectableBegin();
577  it != c.selectableEnd(); it++)
578  list.append (Selectable (*it));
579  g_patternsContent.insert (std::make_pair (pattern, list));
580  return &g_patternsContent.find (pattern)->second;
581  }
582  else { // Language
583  zypp::Locale locale = m_sel.zyppLocale();
584  std::map <zypp::Locale, Ypp::List>::iterator it;
585  if ((it = g_languagesContent.find (locale)) != g_languagesContent.end())
586  return &it->second;
587 
588  zypp::sat::LocaleSupport locale_sup (locale);
589  Ypp::List list (50);
590  for_( it, locale_sup.selectableBegin(), locale_sup.selectableEnd() ) {
591  list.append (Selectable (*it));
592  }
593  g_languagesContent.insert (std::make_pair (locale, list));
594  return &g_languagesContent.find (locale)->second;
595  }
596 }
597 
598 bool Ypp::Collection::contains (Ypp::Selectable &sel)
599 {
600  if (m_sel.type() == Ypp::Selectable::PATCH) {
601  if (m_sel.hasCandidateVersion()) {
602  ZyppResObject object = m_sel.zyppSel()->candidateObj();
603  ZyppPatch patch = castZyppPatch (object);
604  zypp::Patch::Contents contents (patch->contents());
605  ZyppSelectable pkg = sel.zyppSel();
606  for (zypp::Patch::Contents::Selectable_iterator it =
607  contents.selectableBegin(); it != contents.selectableEnd(); it++) {
608  if (*it == pkg)
609  return true;
610  }
611  }
612  return false;
613  }
614 
615  //else
616  Ypp::List *content = getContent();
617  return content->find (sel) != -1;
618 }
619 
620 void Ypp::Collection::stats (int *installed, int *total)
621 {
622  Ypp::List *content = getContent();
623  Ypp::ListProps props (*content);
624  *installed = props.isInstalledNb();
625  *total = content->size();
626 }
627 
628 // Package
629 
630 Ypp::Package::Package (Ypp::Selectable &sel)
631 : m_sel (sel) {}
632 
633 int Ypp::Package::support()
634 {
635  ZyppPackage pkg = castZyppPackage (m_sel.zyppSel()->theObj());
636  switch (pkg->vendorSupport()) {
637  case zypp::VendorSupportUnknown: return 0;
638  case zypp::VendorSupportUnsupported: return 1;
639  case zypp::VendorSupportACC: return 2;
640  case zypp::VendorSupportLevel1: return 3;
641  case zypp::VendorSupportLevel2: return 4;
642  case zypp::VendorSupportLevel3: return 5;
643  }
644  return 0;
645 }
646 
647 int Ypp::Package::supportTotal()
648 { return 6; }
649 
650 static zypp::VendorSupportOption asSupportOpt (int support)
651 {
652  switch (support) {
653  case 0: return zypp::VendorSupportUnknown;
654  case 1: return zypp::VendorSupportUnsupported;
655  case 2: return zypp::VendorSupportACC;
656  case 3: return zypp::VendorSupportLevel1;
657  case 4: return zypp::VendorSupportLevel2;
658  case 5: return zypp::VendorSupportLevel3;
659  }
660  return zypp::VendorSupportUnknown;
661 }
662 
663 std::string Ypp::Package::supportSummary (int support)
664 { return zypp::asUserString (asSupportOpt (support)); }
665 
666 std::string Ypp::Package::supportDescription (int support)
667 { return zypp::asUserStringDescription (asSupportOpt (support)); }
668 
669 std::string Ypp::Package::url()
670 {
671  ZyppPackage package = castZyppPackage (m_sel.zyppSel()->theObj());
672  return package->url();
673 }
674 
675 YPkgGroupEnum Ypp::Package::group()
676 {
677  static std::map <ZyppPackage, YPkgGroupEnum> pkgGroupMap;
678  ZyppPackage pkg = castZyppPackage (m_sel.zyppSel()->theObj());
679  std::map <ZyppPackage, YPkgGroupEnum>::iterator it = pkgGroupMap.find (pkg);
680  if (it == pkgGroupMap.end()) {
681  YPkgGroupEnum group = zypp_tag_convert (pkg->group());
682  pkgGroupMap.insert (std::make_pair (pkg, group));
683  return group;
684  }
685  return it->second;
686 }
687 
688 std::string Ypp::Package::rpm_group()
689 {
690  ZyppPackage pkg = castZyppPackage (m_sel.zyppSel()->theObj());
691  return pkg->group();
692 }
693 
694 static std::map <std::string, ZyppSelectable> g_selPatch;
695 
696 static ZyppSelectable getSelPatch (Ypp::Selectable &sel)
697 {
698  std::string name (sel.name());
699  std::map <std::string, ZyppSelectable>::iterator it = g_selPatch.find (name);
700  if (it != g_selPatch.end())
701  return it->second;
702 
703  Ypp::PoolQuery query (Ypp::Selectable::PATCH);
704  query.addCriteria (new Ypp::StatusMatch (Ypp::StatusMatch::NOT_INSTALLED));
705  query.addCriteria (new Ypp::CollectionContainsMatch (sel));
706  if (query.hasNext()) {
707  Ypp::Selectable patch = query.next();
708  g_selPatch[name] = patch.zyppSel();
709  }
710  else
711  g_selPatch[name] = NULL;
712  return g_selPatch[name];
713 }
714 
715 bool Ypp::Package::isCandidatePatch()
716 {
717  if (m_sel.hasCandidateVersion() && m_sel.hasInstalledVersion()) {
718  Ypp::Version candidate (m_sel.candidate()), installed (m_sel.installed());
719  if (candidate > installed)
720  return getSelPatch (m_sel) != NULL;
721  }
722  return false;
723 }
724 
725 Ypp::Selectable Ypp::Package::getCandidatePatch()
726 { return Selectable (getSelPatch (m_sel)); }
727 
728 // Patch
729 
730 Ypp::Patch::Patch (Ypp::Selectable &sel)
731 : m_sel (sel) {}
732 
733 int Ypp::Patch::priority()
734 {
735  ZyppPatch patch = castZyppPatch (m_sel.zyppSel()->theObj());
736  switch (patch->categoryEnum()) {
737  case zypp::Patch::CAT_SECURITY: return 0;
738  case zypp::Patch::CAT_RECOMMENDED: return 1;
739  case zypp::Patch::CAT_YAST: return 2;
740  case zypp::Patch::CAT_DOCUMENT: return 3;
741  case zypp::Patch::CAT_OPTIONAL: return 4;
742  case zypp::Patch::CAT_OTHER: return 5;
743  }
744  return 0;
745 }
746 
747 int Ypp::Patch::priorityTotal()
748 { return 6; }
749 
750 const char *Ypp::Patch::prioritySummary (int priority)
751 {
752  switch (priority) {
753  // Translators: this refers to patch priority
754  case 0: return _("Security");
755  // Translators: this refers to patch priority
756  case 1: return _("Recommended");
757  case 2: return "YaST";
758  case 3: return _("Documentation");
759  // Translators: this refers to patch priority
760  case 4: return _("Optional");
761  // Translators: this refers to patch priority
762  case 5: return _("Other");
763  }
764  return 0;
765 }
766 
767 // Disk
768 
769 std::vector <std::string> Ypp::getPartitionList()
770 {
771  ZyppDuSet diskUsage = zypp::getZYpp()->diskUsage();
772  std::vector <std::string> partitions;
773  partitions.reserve (diskUsage.size());
774  for (ZyppDuSet::iterator it = diskUsage.begin(); it != diskUsage.end(); it++) {
775  const ZyppDu &point = *it;
776  if (!point.readonly)
777  partitions.push_back (point.dir);
778  }
779  std::sort (partitions.begin(), partitions.end());
780  return partitions;
781 }
782 
783 const ZyppDu Ypp::getPartition (const std::string &mount_point)
784 {
785  ZyppDuSet diskUsage = zypp::getZYpp()->diskUsage();
786  for (ZyppDuSet::iterator it = diskUsage.begin(); it != diskUsage.end(); it++) {
787  const ZyppDu &point = *it;
788  if (mount_point == point.dir)
789  return point;
790  }
791  return *zypp::getZYpp()->diskUsage().begin(); // error
792 }
793 
794 // Busy
795 
796 static Ypp::BusyListener *g_busy_listener = 0;
797 static bool g_busy_running = false;
798 
799 void Ypp::setBusyListener (Ypp::BusyListener *listener)
800 { g_busy_listener = listener; }
801 
803  int cur, size;
804  bool showing;
805  GTimeVal start_t;
806 
807  Impl (int size)
808  : cur (0), size (size), showing (false)
809  {
810  g_get_current_time (&start_t);
811  g_busy_running = true;
812  g_busy_listener->loading (0);
813  }
814 
815  ~Impl()
816  {
817  g_busy_running = false;
818  g_busy_listener->loading (1);
819  }
820 
821  void inc()
822  {
823  cur++;
824 #if 0
825  // shows continuous progress only when it takes more than 1 sec to drive 'N' loops
826  if (showing) {
827  if ((cur % 500) == 0)
828  g_busy_listener->loading (cur / (float) size);
829  }
830  else if (cur == 499) {
831  GTimeVal now_t;
832  g_get_current_time (&now_t);
833  if (now_t.tv_usec - start_t.tv_usec >= 35*1000 ||
834  now_t.tv_sec - start_t.tv_sec >= 1) {
835  showing = true;
836  }
837  }
838 #else
839  g_busy_listener->loading (cur / (float) size);
840 #endif
841  }
842 };
843 
844 Ypp::Busy::Busy (int size) : impl (NULL)
845 {
846  if (g_busy_listener && !g_busy_running)
847  impl = new Impl (size);
848 }
849 
850 Ypp::Busy::~Busy()
851 { delete impl; }
852 
853 void Ypp::Busy::inc()
854 { if (impl) impl->inc(); }
855 
856 // Interface
857 
858 std::list <Ypp::SelListener *> g_sel_listeners;
859 static bool g_transacting = false;
860 
861 void Ypp::addSelListener (Ypp::SelListener *listener)
862 { g_sel_listeners.push_back (listener); }
863 
864 void Ypp::removeSelListener (Ypp::SelListener *listener)
865 { g_sel_listeners.remove (listener); }
866 
867 void Ypp::notifySelModified()
868 {
869  for (std::list <Ypp::SelListener *>::iterator it = g_sel_listeners.begin();
870  it != g_sel_listeners.end(); it++)
871  (*it)->selectableModified();
872 }
873 
874 void Ypp::setInterface (Ypp::Interface *interface)
875 {
876  g_interface = interface;
877 }
878 
879 Ypp::Interface *Ypp::getInterface() { return g_interface; }
880 
881 Ypp::Problem::Solution *Ypp::Problem::getSolution (int nb)
882 { return (Solution *) g_slist_nth_data ((GSList *) impl, nb); }
883 
884 bool Ypp::runSolver (bool force)
885 {
886  if (g_transacting) return true;
887  if (!g_autoSolver && !force) {
888  notifySelModified();
889  return true;
890  }
891 
892  if (g_busy_listener)
893  g_busy_listener->loading (0);
894 
895  zypp::Resolver_Ptr zResolver = zypp::getZYpp()->resolver();
896  bool resolved = false;
897  while (true) {
898  if (zResolver->resolvePool()) {
899  resolved = true; // no need for user intervention
900  break;
901  }
902  zypp::ResolverProblemList zProblems = zResolver->problems();
903  if ((resolved = zProblems.empty())) break;
904  if (!g_interface) break;
905 
906  std::list <Problem *> problems;
907  for (zypp::ResolverProblemList::iterator it = zProblems.begin();
908  it != zProblems.end(); it++) {
909  Problem *problem = new Problem();
910  problem->description = (*it)->description();
911  problem->details = (*it)->details();
912  GSList *solutions = NULL;
913  zypp::ProblemSolutionList zSolutions = (*it)->solutions();
914  for (zypp::ProblemSolutionList::iterator jt = zSolutions.begin();
915  jt != zSolutions.end(); jt++) {
916  Problem::Solution *solution = new Problem::Solution();
917  solution->description = (*jt)->description();
918  solution->details = (*jt)->details();
919  solution->apply = false;
920  solution->impl = (void *) get_pointer (*jt);
921  solutions = g_slist_append (solutions, solution);
922  }
923  problem->impl = (void *) solutions;
924  problems.push_back (problem);
925  }
926 
927  resolved = g_interface->resolveProblems (problems);
928  if (resolved) {
929  zypp::ProblemSolutionList choices;
930  for (std::list <Problem *>::iterator it = problems.begin();
931  it != problems.end(); it++) {
932  for (int i = 0; (*it)->getSolution (i); i++) {
933  Problem::Solution *solution = (*it)->getSolution (i);
934  if (resolved && solution->apply)
935  choices.push_back ((zypp::ProblemSolution *) solution->impl);
936  delete solution;
937  }
938  g_slist_free ((GSList *) (*it)->impl);
939  delete *it;
940  }
941  zResolver->applySolutions (choices);
942  }
943  else
944  break;
945  }
946  if (!resolved)
947  zResolver->undo();
948 
949  notifySelModified();
950  if (g_busy_listener)
951  g_busy_listener->loading (1);
952  return resolved;
953 }
954 
955 void Ypp::setEnableSolver (bool enabled)
956 {
957  g_autoSolver = enabled;
958  if (enabled) runSolver();
959 }
960 
961 bool Ypp::isSolverEnabled()
962 { return g_autoSolver; }
963 
964 bool Ypp::showPendingLicenses (Ypp::Selectable::Type type)
965 {
966  const zypp::ResKind &kind = Selectable::asKind (type);
967  for (ZyppPool::const_iterator it = zyppPool().byKindBegin(kind);
968  it != zyppPool().byKindEnd(kind); it++) {
969  ZyppSelectable zsel = (*it);
970  switch (zsel->status()) {
971  case zypp::ui::S_Install: case zypp::ui::S_AutoInstall:
972  case zypp::ui::S_Update: case zypp::ui::S_AutoUpdate:
973  if (zsel->candidateObj()) {
974  std::string license = zsel->candidateObj()->licenseToConfirm();
975  if (!license.empty())
976  if (!zsel->hasLicenceConfirmed()) {
977  Selectable sel (zsel);
978  if (!g_interface->showLicense (sel, license))
979  return false;
980  }
981  }
982  default: break;
983  }
984  }
985  return true;
986 }
987 
988 void Ypp::startTransactions()
989 { g_transacting = true; }
990 
991 bool Ypp::finishTransactions()
992 { g_transacting = false; return runSolver(); }
993 
994 // Query
995 
997  int attrbs;
998  std::list <std::string> strings;
999 
1000  Impl (int attrbs) : attrbs (attrbs) {}
1001 };
1002 
1003 Ypp::StrMatch::StrMatch (int attrbs)
1004 : impl (new Impl (attrbs)) {}
1005 
1006 Ypp::StrMatch::~StrMatch()
1007 { delete impl; }
1008 
1009 void Ypp::StrMatch::add (const std::string &str)
1010 { impl->strings.push_back (str); }
1011 
1012 bool Ypp::StrMatch::match (Ypp::Selectable &sel)
1013 {
1014  std::string haystack;
1015  haystack.reserve (2048);
1016  if (impl->attrbs & NAME)
1017  haystack += sel.name();
1018  if (impl->attrbs & SUMMARY)
1019  haystack += sel.summary();
1020  if (impl->attrbs & DESCRIPTION)
1021  haystack += sel.description (false);
1022 
1023  for (std::list <std::string>::iterator it = impl->strings.begin();
1024  it != impl->strings.end(); it++) {
1025  const std::string &needle = *it;
1026  if (!strcasestr (haystack.c_str(), needle.c_str()))
1027  return false;
1028  }
1029  return true;
1030 }
1031 
1032 Ypp::StatusMatch::StatusMatch (Ypp::StatusMatch::Status status)
1033 : m_status (status) {}
1034 
1035 bool Ypp::StatusMatch::match (Selectable &sel)
1036 {
1037  switch (m_status) {
1038  case IS_INSTALLED: return sel.isInstalled();
1039  case NOT_INSTALLED: return !sel.isInstalled();
1040  case HAS_UPGRADE: return sel.hasUpgrade();
1041  case IS_LOCKED: return sel.isLocked();
1042  case TO_MODIFY: return sel.toModify();
1043  }
1044  return false;
1045 }
1046 
1047 Ypp::PKGroupMatch::PKGroupMatch (YPkgGroupEnum group)
1048 : m_group (group) {}
1049 
1050 bool Ypp::PKGroupMatch::match (Selectable &sel)
1051 {
1052  ZyppPackage pkg = castZyppPackage (sel.zyppSel()->theObj());
1053  switch (m_group) {
1054  case YPKG_GROUP_RECOMMENDED: return zypp::PoolItem (pkg).status().isRecommended();
1055  case YPKG_GROUP_SUGGESTED: return zypp::PoolItem (pkg).status().isSuggested();
1056  case YPKG_GROUP_ORPHANED: return zypp::PoolItem (pkg).status().isOrphaned();
1057  case YPKG_GROUP_RECENT:
1058  if (sel.hasCandidateVersion()) {
1059  time_t build = static_cast <time_t> (sel.candidate().zyppObj()->buildtime());
1060  time_t now = time (NULL);
1061  time_t delta = (now - build) / (60*60*24); // in days
1062  return delta <= 7;
1063  }
1064  return false;
1065 #if ZYPP_VERSION >= 6030004
1066  case YPKG_GROUP_MULTIVERSION: return sel.zyppSel()->multiversionInstall();
1067 #endif
1068  default: return Package (sel).group() == m_group;
1069  }
1070  return false;
1071 }
1072 
1073 Ypp::RpmGroupMatch::RpmGroupMatch (const std::string &group)
1074 : m_group (group) {}
1075 
1076 bool Ypp::RpmGroupMatch::match (Selectable &sel)
1077 {
1078  std::string pkg_group (Package (sel).rpm_group());
1079  int len = MIN (m_group.size(), pkg_group.size());
1080  return m_group.compare (0, len, pkg_group, 0, len) == 0;
1081 }
1082 
1083 Ypp::FromCollectionMatch::FromCollectionMatch (Collection &col)
1084 : m_collection (col) {}
1085 
1086 bool Ypp::FromCollectionMatch::match (Selectable &sel)
1087 { return m_collection.contains (sel); }
1088 
1089 Ypp::CollectionContainsMatch::CollectionContainsMatch (Ypp::Selectable &sel)
1090 : m_contains (sel) {}
1091 
1092 bool Ypp::CollectionContainsMatch::match (Ypp::Selectable &sel)
1093 {
1094  Collection collection (sel);
1095  return collection.contains (m_contains);
1096 }
1097 
1099  ZyppQuery query;
1100  std::list <Match *> criterias;
1101  bool filelist_attrb;
1102  ZyppQuery::Selectable_iterator it;
1103  bool begin;
1104 
1105  Impl() : filelist_attrb (false), begin (true) {}
1106 
1107  ~Impl()
1108  {
1109  for (std::list <Match *>::iterator it = criterias.begin();
1110  it != criterias.end(); it++)
1111  delete *it;
1112  }
1113 
1114  bool match (Ypp::Selectable &sel)
1115  { // exclusive
1116  for (std::list <Match *>::iterator it = criterias.begin();
1117  it != criterias.end(); it++)
1118  if (!(*it)->match (sel))
1119  return false;
1120  return true;
1121  }
1122 
1123  ZyppQuery::Selectable_iterator untilMatch (ZyppQuery::Selectable_iterator it)
1124  { // iterates until match -- will return argument if it already matches
1125  while (it != query.selectableEnd()) {
1126  Ypp::Selectable sel (*it);
1127  if (sel.visible() && match (sel)) break;
1128  it++;
1129  }
1130  return it;
1131  }
1132 };
1133 
1134 Ypp::PoolQuery::PoolQuery (Ypp::Selectable::Type type)
1135 : impl (new Impl())
1136 {
1137  assert (type != Selectable::LANGUAGE);
1138  if (type != Selectable::ALL)
1139  impl->query.addKind (Selectable::asKind (type));
1140 }
1141 
1142 Ypp::PoolQuery::~PoolQuery()
1143 { delete impl; }
1144 
1145 void Ypp::PoolQuery::setStringMode (bool caseSensitive, Ypp::PoolQuery::MatchType match)
1146 {
1147  impl->query.setCaseSensitive (caseSensitive);
1148  switch (match) {
1149  case CONTAINS: impl->query.setMatchSubstring(); break;
1150  case EXACT: impl->query.setMatchExact(); break;
1151  case GLOB: impl->query.setMatchGlob(); break;
1152  case REGEX: impl->query.setMatchRegex(); break;
1153  }
1154 }
1155 
1156 void Ypp::PoolQuery::addStringAttribute (Ypp::PoolQuery::StringAttribute attrb)
1157 {
1158  zypp::sat::SolvAttr _attrb;
1159  impl->filelist_attrb = false;
1160  switch (attrb) {
1161  case NAME: _attrb = ZyppAttribute::name; break;
1162  case SUMMARY: _attrb = ZyppAttribute::summary; break;
1163  case DESCRIPTION: _attrb = ZyppAttribute::description; break;
1164  case FILELIST: _attrb = ZyppAttribute::filelist; impl->filelist_attrb = true; break;
1165  case REQUIRES: _attrb = ZyppAttribute ("solvable:requires"); break;
1166  case PROVIDES: _attrb = ZyppAttribute ("solvable:provides"); break;
1167  }
1168  impl->query.addAttribute (_attrb);
1169 }
1170 
1171 void Ypp::PoolQuery::addStringOr (const std::string &str)
1172 {
1173  if (impl->filelist_attrb && !str.empty())
1174  impl->query.setFilesMatchFullPath (str[0] == '/');
1175  impl->query.addString (str);
1176 }
1177 
1178 void Ypp::PoolQuery::addRepository (Ypp::Repository &repository)
1179 { impl->query.addRepo (repository.zyppRepo().info().alias()); }
1180 
1181 void Ypp::PoolQuery::addCriteria (Ypp::Match *criteria)
1182 { impl->criterias.push_back (criteria); }
1183 
1184 bool Ypp::PoolQuery::hasNext()
1185 {
1186  if (impl->begin) {
1187  impl->it = impl->untilMatch (impl->query.selectableBegin());
1188  impl->begin = false;
1189  }
1190  return impl->it != impl->query.selectableEnd();
1191 }
1192 
1193 Ypp::Selectable Ypp::PoolQuery::next()
1194 {
1195  Ypp::Selectable sel (*impl->it);
1196  impl->it = impl->untilMatch (++impl->it);
1197  return sel;
1198 }
1199 
1200 int Ypp::PoolQuery::guessSize()
1201 { return impl->query.size(); }
1202 
1203 ZyppQuery &Ypp::PoolQuery::zyppQuery()
1204 { return impl->query; }
1205 
1206 Ypp::Selectable::Type Ypp::PoolQuery::poolType()
1207 { return Selectable::asType (*impl->query.kinds().begin()); }
1208 
1210  zypp::LocaleSet locales;
1211  zypp::LocaleSet::const_iterator it;
1212 
1213  Impl() {
1214  locales = _zyppPool().getAvailableLocales();
1215  it = locales.begin();
1216  }
1217 };
1218 
1219 Ypp::LangQuery::LangQuery()
1220 : impl (new Impl()) {}
1221 
1222 Ypp::LangQuery::~LangQuery()
1223 { delete impl; }
1224 
1225 bool Ypp::LangQuery::hasNext()
1226 { return impl->it != impl->locales.end(); }
1227 
1228 Ypp::Selectable Ypp::LangQuery::next()
1229 { return Ypp::Selectable (*(impl->it++)); }
1230 
1231 int Ypp::LangQuery::guessSize()
1232 { return impl->locales.size(); }
1233 
1234 // List (aggregator)
1235 
1237  std::vector <Selectable> vector;
1238  int refcount;
1239  Impl() : refcount (1) {}
1240 };
1241 
1242 Ypp::List::List (Ypp::Query &query)
1243 : impl (new Impl())
1244 {
1245  reserve (query.guessSize());
1246  while (query.hasNext())
1247  append (query.next());
1248 }
1249 
1250 Ypp::List::List (int size)
1251 : impl (new Impl())
1252 { reserve (size); }
1253 
1254 Ypp::List::List (const List &other)
1255 : impl (other.impl)
1256 { impl->refcount++; }
1257 
1258 Ypp::List &Ypp::List::operator= (const List &other)
1259 {
1260  if (--impl->refcount <= 0) delete impl;
1261  impl = other.impl;
1262  impl->refcount++;
1263  return *this;
1264 }
1265 
1266 Ypp::List::~List()
1267 { if (--impl->refcount <= 0) delete impl; }
1268 
1269 Ypp::List Ypp::List::clone()
1270 {
1271  Ypp::List other (size());
1272  other.impl->vector = this->impl->vector;
1273  return other;
1274 }
1275 
1276 Ypp::Selectable &Ypp::List::get (int index)
1277 { return impl->vector[index]; }
1278 
1279 int Ypp::List::size()
1280 { return impl->vector.size(); }
1281 
1282 int Ypp::List::count (Match *match)
1283 {
1284  int count = 0;
1285  for (std::vector <Selectable>::iterator it = impl->vector.begin();
1286  it != impl->vector.end(); it++)
1287  if (match->match (*it))
1288  count++;
1289  return count;
1290 }
1291 
1292 int Ypp::List::find (const std::string &name)
1293 {
1294  for (unsigned int i = 0; i < impl->vector.size(); i++)
1295  if (name == impl->vector[i].name())
1296  return i;
1297  return -1;
1298 }
1299 
1300 int Ypp::List::find (Selectable &sel)
1301 {
1302  for (unsigned int i = 0; i < impl->vector.size(); i++)
1303  if (sel == impl->vector[i])
1304  return i;
1305  return -1;
1306 }
1307 
1308 void Ypp::List::reserve (int size)
1309 { impl->vector.reserve (size); }
1310 
1311 void Ypp::List::append (Ypp::Selectable sel)
1312 { impl->vector.push_back (sel); }
1313 
1314 void Ypp::List::install()
1315 {
1316  startTransactions();
1317  for (std::vector <Selectable>::iterator it = impl->vector.begin();
1318  it != impl->vector.end(); it++)
1319  it->install();
1320  if (!finishTransactions())
1321  undo();
1322 }
1323 
1324 void Ypp::List::remove()
1325 {
1326  startTransactions();
1327  for (std::vector <Selectable>::iterator it = impl->vector.begin();
1328  it != impl->vector.end(); it++)
1329  it->remove();
1330  if (!finishTransactions())
1331  undo();
1332 }
1333 
1334 void Ypp::List::lock (bool lock)
1335 {
1336  startTransactions();
1337  for (std::vector <Selectable>::iterator it = impl->vector.begin();
1338  it != impl->vector.end(); it++)
1339  it->lock (lock);
1340  if (!finishTransactions())
1341  undo();
1342 }
1343 
1344 void Ypp::List::undo()
1345 {
1346  startTransactions();
1347  for (std::vector <Selectable>::iterator it = impl->vector.begin();
1348  it != impl->vector.end(); it++)
1349  it->undo();
1350  finishTransactions();
1351 }
1352 
1353 static bool installed_order (Ypp::Selectable &a, Ypp::Selectable &b)
1354 { return (a.isInstalled() ? 0 : 1) < (b.isInstalled() ? 0 : 1); }
1355 
1356 static bool utf8_name_order (Ypp::Selectable &a, Ypp::Selectable &b)
1357 { return g_utf8_collate (a.name().c_str(), b.name().c_str()) < 0; }
1358 
1359 static bool name_order (Ypp::Selectable &a, Ypp::Selectable &b)
1360 { return strcasecmp (a.name().c_str(), b.name().c_str()) < 0; }
1361 
1362 static bool size_order (Ypp::Selectable &a, Ypp::Selectable &b)
1363 { return a.anyVersion().size() < b.anyVersion().size(); }
1364 
1365 static std::string get_alias (Ypp::Selectable &a)
1366 {
1367  if (a.hasCandidateVersion())
1368  return a.candidate().repository().zyppRepo().alias();
1369  return "a"; // system
1370 }
1371 
1372 static bool repository_order (Ypp::Selectable &a, Ypp::Selectable &b)
1373 { return get_alias (a) < get_alias(b); }
1374 
1375 static bool support_order (Ypp::Selectable &a, Ypp::Selectable &b)
1376 { return Ypp::Package(a).support() < Ypp::Package(b).support(); }
1377 
1378 typedef bool (* order_cb) (Ypp::Selectable &a, Ypp::Selectable &b);
1379 
1380 static order_cb _order;
1381 static bool _ascendent; // proxy between our order callbacks and std::sort's
1382 static bool proxy_order (const Ypp::Selectable &a, const Ypp::Selectable &b)
1383 { return _order ((Ypp::Selectable &) a, (Ypp::Selectable &) b) == _ascendent; }
1384 
1385 void Ypp::List::sort (Ypp::List::SortAttribute attrb, bool ascendent)
1386 {
1387  if (impl->vector.empty())
1388  return;
1389 
1390  bool unique_criteria = false;
1391  switch (attrb) {
1392  case IS_INSTALLED_SORT: _order = installed_order; break;
1393  case NAME_SORT:
1394  // package names are never internationalized, but langs / patterns may be
1395  if (impl->vector[0].type() != Selectable::PACKAGE)
1396  _order = utf8_name_order;
1397  else
1398  _order = name_order;
1399  unique_criteria = true;
1400  break;
1401  case SIZE_SORT: _order = size_order; unique_criteria = true; break;
1402  case REPOSITORY_SORT: _order = repository_order; break;
1403  case SUPPORT_SORT: _order = support_order; break;
1404  }
1405  _ascendent = ascendent;
1406  if (unique_criteria)
1407  std::sort (impl->vector.begin(), impl->vector.end(), proxy_order);
1408  else // many attributes are equal: maintain previous order in such cases
1409  std::stable_sort (impl->vector.begin(), impl->vector.end(), proxy_order);
1410 }
1411 
1412 void Ypp::List::reverse()
1413 { std::reverse (impl->vector.begin(), impl->vector.end()); }
1414 
1415 bool Ypp::List::operator == (const Ypp::List &other) const
1416 { return this->impl == other.impl; }
1417 bool Ypp::List::operator != (const Ypp::List &other) const
1418 { return this->impl != other.impl; }
1419 
1420 // ListProps
1421 
1423  int isInstalled, hasUpgrade, toModify, isLocked, size;
1424  int canRemove : 2, canLock : 2;
1425 
1426  Impl (List list) {
1427  isInstalled = hasUpgrade = toModify = isLocked = canRemove = canLock = 0;
1428  size = list.size();
1429  for (int i = 0; i < size; i++) {
1430  Selectable &sel = list.get (i);
1431  if (sel.isInstalled()) {
1432  isInstalled++;
1433  if (sel.hasUpgrade())
1434  hasUpgrade++;
1435  }
1436  if (sel.toModify())
1437  toModify++;
1438  if (sel.isLocked())
1439  isLocked++;
1440  }
1441  if (size) {
1442  Selectable sel = list.get (0);
1443  canRemove = sel.canRemove();
1444  canLock = sel.canLock();
1445  }
1446  }
1447 };
1448 
1449 Ypp::ListProps::ListProps (Ypp::List &list)
1450 : impl (new Impl (list)) {}
1451 
1452 Ypp::ListProps::~ListProps()
1453 { delete impl; }
1454 
1455 bool Ypp::ListProps::isInstalled() const
1456 { return impl->isInstalled == impl->size; }
1457 bool Ypp::ListProps::isNotInstalled() const
1458 { return impl->isInstalled == 0; }
1459 bool Ypp::ListProps::hasUpgrade() const
1460 { return impl->hasUpgrade == impl->size; }
1461 bool Ypp::ListProps::toModify() const
1462 { return impl->toModify == impl->size; }
1463 bool Ypp::ListProps::isLocked() const
1464 { return impl->isLocked == impl->size; }
1465 bool Ypp::ListProps::isUnlocked() const
1466 { return impl->isLocked == 0; }
1467 bool Ypp::ListProps::canRemove() const
1468 { return impl->canRemove; }
1469 bool Ypp::ListProps::canLock() const
1470 { return impl->canLock; }
1471 
1472 int Ypp::ListProps::isInstalledNb() const
1473 { return impl->isInstalled; }
1474 int Ypp::ListProps::isNotInstalledNb() const
1475 { return impl->size - impl->isInstalled; }
1476 int Ypp::ListProps::hasUpgradeNb() const
1477 { return impl->hasUpgrade; }
1478 int Ypp::ListProps::isLockedNb() const
1479 { return impl->isLocked; }
1480 int Ypp::ListProps::toModifyNb() const
1481 { return impl->toModify; }
1482 
1483 // General
1484 
1485 void Ypp::init()
1486 {
1487  zyppPool().saveState <zypp::Package>();
1488  zyppPool().saveState <zypp::Pattern>();
1489  zyppPool().saveState <zypp::Patch >();
1490 }
1491 
1492 bool Ypp::isModified()
1493 {
1494  return zyppPool().diffState <zypp::Package>() ||
1495  zyppPool().diffState <zypp::Pattern>() ||
1496  zyppPool().diffState <zypp::Patch>();
1497 }
1498 
1499 void Ypp::finish()
1500 {
1501  g_sel_listeners.clear();
1502  g_interface = 0;
1503  g_transacting = false;
1504  g_autoSolver = true;
1505  g_busy_listener = 0;
1506  g_busy_running = false;
1507  g_patternsContent.clear();
1508  g_languagesContent.clear();
1509  g_selPatch.clear();
1510 }
1511