15 #include "ygtkpkgmenubar.h"
17 #include <glib/gstdio.h>
19 #include <gdk/gdkkeysyms.h>
20 #include "yzyppwrapper.h"
21 #include "YGPackageSelector.h"
25 #define YAST_GTK_SYSCONFIG "/etc/sysconfig/yast2-gtk"
29 keys = g_key_file_new();
30 g_key_file_load_from_file (keys, YAST_GTK_SYSCONFIG, G_KEY_FILE_NONE, NULL);
37 g_key_file_free (keys);
40 bool hasKey (
const char *variable) {
41 return g_key_file_has_key (keys,
"zypp", variable, NULL);
44 bool getBool (
const char *variable) {
45 return g_key_file_get_boolean (keys,
"zypp", variable, NULL);
48 void setBool (
const char *variable,
bool value) {
49 g_key_file_set_boolean (keys,
"zypp", variable, value);
55 FILE *out = fopen (YAST_GTK_SYSCONFIG,
"w");
58 gchar *data = g_key_file_to_data (keys, &size, NULL);
59 fwrite (data,
sizeof (
char), size, out);
71 static GtkWidget *append_menu_item (GtkWidget *menu,
const char *_text,
72 const char *stock, GCallback callback, gpointer callback_data)
76 text = YGUtils::mapKBAccel (_text);
79 GtkWidget *icon = gtk_image_new_from_stock (stock, GTK_ICON_SIZE_MENU);
80 item = gtk_image_menu_item_new_with_mnemonic (text.c_str());
81 gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), icon);
84 item = gtk_menu_item_new_with_mnemonic (text.c_str());
86 item = gtk_image_menu_item_new_from_stock (stock, NULL);
88 item = gtk_separator_menu_item_new();
89 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
91 g_signal_connect (G_OBJECT (item),
"activate", callback, callback_data);
95 static void errorMsg (
const std::string &message)
97 GtkWidget *dialog = gtk_message_dialog_new (YGDialog::currentWindow(),
98 GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
100 gtk_message_dialog_format_secondary_markup (GTK_MESSAGE_DIALOG (dialog),
101 "%s", message.c_str());
102 gtk_dialog_run (GTK_DIALOG (dialog));
103 gtk_widget_destroy (dialog);
109 #include <zypp/SysContent.h>
110 #include <zypp/ui/Status.h>
111 #include <zypp/ui/Selectable.h>
112 #include <zypp/ResPoolProxy.h>
113 #include <zypp/ZYppFactory.h>
116 using zypp::ui::S_Protected;
117 using zypp::ui::S_Taboo;
118 using zypp::ui::S_Del;
119 using zypp::ui::S_Update;
120 using zypp::ui::S_Install;
121 using zypp::ui::S_AutoDel;
122 using zypp::ui::S_AutoUpdate;
123 using zypp::ui::S_AutoInstall;
124 using zypp::ui::S_KeepInstalled;
125 using zypp::ui::S_NoInst;
126 typedef zypp::ui::Selectable::Ptr ZyppSel;
127 typedef zypp::ui::Status ZyppStatus;
128 typedef zypp::ResPoolProxy::const_iterator ZyppPoolIterator;
129 typedef zypp::ResPoolProxy ZyppPool;
131 template<
class T> ZyppPoolIterator zyppBegin() {
return zyppPool().byKindBegin<T>(); }
132 template<
class T> ZyppPoolIterator zyppEnd() {
return zyppPool().byKindEnd<T>(); }
133 inline ZyppPoolIterator zyppPkgBegin() {
return zyppBegin<zypp::Package>(); }
134 inline ZyppPoolIterator zyppPkgEnd() {
return zyppEnd<zypp::Package>(); }
135 inline ZyppPoolIterator zyppPatternsBegin() {
return zyppBegin<zypp::Pattern>(); }
136 inline ZyppPoolIterator zyppPatternsEnd() {
return zyppEnd<zypp::Pattern>(); }
138 #define DEFAULT_EXPORT_FILE_NAME "user-packages.xml"
141 importSelectable( ZyppSel selectable,
145 ZyppStatus oldStatus = selectable->status();
146 ZyppStatus newStatus = oldStatus;
158 case S_KeepInstalled:
162 newStatus = oldStatus;
167 newStatus = S_KeepInstalled;
168 yuiDebug() <<
"Keeping " << kind <<
" " << selectable->name() << std::endl;
174 if ( selectable->hasCandidateObj() )
176 newStatus = S_Install;
177 yuiDebug() <<
"Adding " << kind <<
" " << selectable->name() << std::endl;
181 yuiDebug() <<
"Can't add " << kind <<
" " << selectable->name()
182 <<
": No candidate" << std::endl;
197 case S_KeepInstalled:
202 yuiDebug() <<
"Deleting " << kind <<
" " << selectable->name() << std::endl;
209 newStatus = oldStatus;
214 if ( oldStatus != newStatus )
215 selectable->setStatus( newStatus );
218 static void import_file_cb (GtkMenuItem *item)
220 GtkWidget *dialog = gtk_file_chooser_dialog_new (_(
"Import from"),
221 YGDialog::currentWindow(), GTK_FILE_CHOOSER_ACTION_OPEN,
222 GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
223 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL);
225 GtkFileFilter *filter = gtk_file_filter_new();
226 gtk_file_filter_set_name (filter,
"*.xml");
227 gtk_file_filter_add_pattern (filter,
"*.xml");
228 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
229 filter = gtk_file_filter_new();
230 gtk_file_filter_set_name (filter,
"*");
231 gtk_file_filter_add_pattern (filter,
"*");
232 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
234 gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), DEFAULT_EXPORT_FILE_NAME);
235 gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (dialog), TRUE);
237 int ret = gtk_dialog_run (GTK_DIALOG (dialog));
238 if ( ret == GTK_RESPONSE_ACCEPT )
240 char *filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
241 yuiMilestone() <<
"Importing package list from " << filename << std::endl;
245 std::ifstream importFile( filename );
246 zypp::syscontent::Reader reader( importFile );
252 typedef zypp::syscontent::Reader::Entry ZyppReaderEntry;
253 typedef std::pair<std::string, ZyppReaderEntry> ImportMapPair;
255 std::map<std::string, ZyppReaderEntry> importPkg;
256 std::map<std::string, ZyppReaderEntry> importPatterns;
258 for ( zypp::syscontent::Reader::const_iterator it = reader.begin();
262 std::string kind = it->kind();
264 if ( kind ==
"package" ) importPkg.insert ( ImportMapPair( it->name(), *it ) );
265 else if ( kind ==
"pattern" ) importPatterns.insert( ImportMapPair( it->name(), *it ) );
268 yuiDebug() <<
"Found " << importPkg.size()
269 <<
" packages and " << importPatterns.size()
270 <<
" patterns in " << filename
278 for ( ZyppPoolIterator it = zyppPatternsBegin();
279 it != zyppPatternsEnd();
282 ZyppSel selectable = *it;
283 importSelectable( *it, importPatterns.find( selectable->name() ) != importPatterns.end(),
"pattern" );
286 for ( ZyppPoolIterator it = zyppPkgBegin();
290 ZyppSel selectable = *it;
291 importSelectable( *it, importPkg.find( selectable->name() ) != importPkg.end(),
"package" );
294 YGPackageSelector::get()->popupChanges();
296 catch (
const zypp::Exception & exception)
298 yuiWarning() <<
"Error reading package list from " << filename << std::endl;
299 std::string str (_(
"Could not open:"));
300 str +=
" "; str += filename;
308 gtk_widget_destroy (dialog);
311 static void export_file_cb (GtkMenuItem *item)
313 GtkWidget *dialog = gtk_file_chooser_dialog_new (_(
"Export to"),
314 YGDialog::currentWindow(), GTK_FILE_CHOOSER_ACTION_SAVE,
315 GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
316 GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, NULL);
318 GtkFileFilter *filter = gtk_file_filter_new();
319 gtk_file_filter_set_name (filter,
"*.xml");
320 gtk_file_filter_add_pattern (filter,
"*.xml");
321 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
322 filter = gtk_file_filter_new();
323 gtk_file_filter_set_name (filter,
"*");
324 gtk_file_filter_add_pattern (filter,
"*");
325 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
327 gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), DEFAULT_EXPORT_FILE_NAME);
328 gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (dialog), TRUE);
329 gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
331 int ret = gtk_dialog_run (GTK_DIALOG (dialog));
332 if (ret == GTK_RESPONSE_ACCEPT) {
334 filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
336 zypp::syscontent::Writer writer;
337 const zypp::ResPool & pool = zypp::getZYpp()->pool();
341 for_each( pool.begin(), pool.end(),
342 boost::bind( &zypp::syscontent::Writer::addIf,
343 boost::ref( writer ),
355 std::ofstream exportFile( filename );
356 exportFile.exceptions( std::ios_base::badbit | std::ios_base::failbit );
357 exportFile << writer;
359 yuiMilestone() <<
"Package list exported to " << filename << std::endl;
361 catch ( std::exception & exception )
363 yuiWarning() <<
"Error exporting package list to " << filename << std::endl;
370 std::string str (_(
"Could not save to:"));
371 str +=
" "; str += filename;
378 gtk_widget_destroy (dialog);
381 static void create_solver_testcase_cb (GtkMenuItem *item)
383 const char *dirname =
"/var/log/YaST2/solverTestcase";
384 std::string msg (_(
"Use this to generate extensive logs to help tracking "
385 "down bugs in the dependencies resolver."));
386 msg +=
"\n"; msg += _(
"The logs will be saved to the directory:");
387 msg +=
" "; msg += dirname;
389 GtkWidget *dialog = gtk_message_dialog_new (YGDialog::currentWindow(),
390 GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_INFO, GTK_BUTTONS_OK_CANCEL,
392 "%s", _(
"Generate Dependencies Resolver Testcase"));
393 gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
"%s", msg.c_str());
394 int ret = gtk_dialog_run (GTK_DIALOG (dialog));
395 gtk_widget_destroy (dialog);
397 if (ret == GTK_RESPONSE_OK) {
399 yuiMilestone() <<
"Generating solver test case START" << std::endl;
400 success = zypp::getZYpp()->resolver()->createSolverTestcase (dirname);
401 yuiMilestone() <<
"Generating solver test case END" << std::endl;
404 GtkWidget *dialog = gtk_message_dialog_new (YGDialog::currentWindow(),
405 GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION,
406 GTK_BUTTONS_YES_NO,
"%s", _(
"Success"));
407 msg = _(
"Dependencies resolver test case written to:");
411 msg += _(
"Also create a <tt>y2logs.tgz</tt> tar archive to attach to bugzilla?");
412 gtk_message_dialog_format_secondary_markup (GTK_MESSAGE_DIALOG (dialog),
414 ret = gtk_dialog_run (GTK_DIALOG (dialog));
415 gtk_widget_destroy (dialog);
416 if (ret == GTK_RESPONSE_YES)
417 YGUI::ui()->askSaveLogs();
420 msg = _(
"Failed to create dependencies resolver testcase.\n"
421 "Please check disk space and permissions for:");
422 msg +=
" <tt>"; msg += dirname; msg +=
"</tt>";
423 errorMsg (msg.c_str());
428 static void repoManager()
430 yuiMilestone() <<
"Closing PackageSelector with \"RepoManager\"" << std::endl;
431 YGUI::ui()->sendEvent(
new YMenuEvent(
"repo_mgr" ) );
434 static void onlineUpdateConfiguration()
436 yuiMilestone() <<
"Closing PackageSelector with \"OnlineUpdateConfiguration\"" << std::endl;
437 YGUI::ui()->sendEvent(
new YMenuEvent(
"online_update_configuration" ) );
440 static void manualResolvePackageDependencies()
441 { Ypp::runSolver (
true); }
447 std::string str (YGUtils::mapKBAccel(text));
448 m_item = gtk_check_menu_item_new_with_mnemonic (str.c_str());
449 g_object_set_data_full (G_OBJECT (m_item),
"this",
this, destructor);
450 gtk_menu_shell_append (GTK_MENU_SHELL (menu), m_item);
453 void init (
Flags *flags) {
454 bool check = getZyppValue();
456 const char *var = variable();
457 if (flags->hasKey (var)) {
458 bool c = flags->getBool (var);
464 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (m_item), check);
465 g_signal_connect_after (G_OBJECT (m_item),
"toggled", G_CALLBACK (toggled_cb),
this);
468 virtual const char *variable() = 0;
469 virtual bool getZyppValue() = 0;
470 virtual void setZyppValue (
bool on) = 0;
471 virtual void runtimeSync() {}
473 void writeFile (
bool on) {
475 flags.setBool (variable(), on);
478 static void toggled_cb (GtkCheckMenuItem *item,
CheckMenuFlag *pThis) {
479 bool on = gtk_check_menu_item_get_active (item);
480 pThis->setZyppValue (on);
481 pThis->runtimeSync();
482 pThis->writeFile (on);
485 static void destructor (gpointer data) {
495 virtual const char *variable() {
return "auto-check"; }
496 virtual bool getZyppValue() {
return Ypp::isSolverEnabled(); }
497 virtual void setZyppValue (
bool on) { Ypp::setEnableSolver (on); }
503 virtual const char *variable() {
return "show-devel"; }
504 virtual bool getZyppValue() {
return true; }
505 virtual void setZyppValue (
bool on)
506 { YGPackageSelector::get()->filterPkgSuffix (
"-devel", !on); }
512 virtual const char *variable() {
return "show-debug"; }
513 virtual bool getZyppValue() {
return true; }
514 virtual void setZyppValue (
bool on) {
515 YGPackageSelector::get()->filterPkgSuffix (
"-debuginfo", !on);
516 YGPackageSelector::get()->filterPkgSuffix (
"-debugsource", !on);
523 virtual const char *variable() {
return "system-verification"; }
524 virtual bool getZyppValue() {
525 return zypp::getZYpp()->resolver()->systemVerification();
527 virtual void setZyppValue (
bool on) {
528 zypp::getZYpp()->resolver()->setSystemVerification (on);
530 virtual void runtimeSync() {}
536 virtual const char *variable() {
return "ignore-already-recommended"; }
537 virtual bool getZyppValue() {
538 return zypp::getZYpp()->resolver()->ignoreAlreadyRecommended();
540 virtual void setZyppValue (
bool on) {
541 zypp::getZYpp()->resolver()->setIgnoreAlreadyRecommended(on);
543 virtual void runtimeSync() { Ypp::runSolver(); }
546 #if ZYPP_VERSION > 6031004
549 CleanupDepsCheckItem (GtkWidget *menu,
const char *text,
Flags *flags)
551 virtual const char *variable() {
return "cleanup-deps"; }
552 virtual bool getZyppValue() {
553 return zypp::getZYpp()->resolver()->cleandepsOnRemove();
555 virtual void setZyppValue (
bool on) {
556 zypp::getZYpp()->resolver()->setCleandepsOnRemove( on );
558 virtual void runtimeSync() { Ypp::runSolver(); }
562 AllowVendorChangeCheckItem (GtkWidget *menu,
const char *text,
Flags *flags)
564 virtual const char *variable() {
return "allow-vendor-change"; }
565 virtual bool getZyppValue() {
566 return zypp::getZYpp()->resolver()->allowVendorChange();
568 virtual void setZyppValue (
bool on) {
569 zypp::getZYpp()->resolver()->setAllowVendorChange( on );
571 virtual void runtimeSync() { Ypp::runSolver(); }
576 static void installSubPkgs (std::string suffix)
580 std::map<std::string, ZyppSel> subPkgs;
582 for ( ZyppPoolIterator it = zyppPkgBegin(); it != zyppPkgEnd(); ++it )
584 std::string name = (*it)->name();
586 if (YGUtils::endsWith (name, suffix))
588 subPkgs[ name ] = *it;
589 yuiDebug() <<
"Found subpackage: " << name << std::endl;
596 for ( ZyppPoolIterator it = zyppPkgBegin(); it != zyppPkgEnd(); ++it )
598 std::string name = (*it)->name();
600 std::string subPkgName( name + suffix );
601 if ( subPkgs.find( subPkgName ) != subPkgs.end() )
603 ZyppSel subPkg = subPkgs[ subPkgName ];
605 switch ( (*it)->status() )
613 yuiMilestone() <<
"Ignoring unwanted subpackage " << subPkgName << std::endl;
618 case S_KeepInstalled:
622 if ( ! subPkg->installedObj() )
624 subPkg->setStatus( S_Install );
625 yuiMilestone() <<
"Installing subpackage " << subPkgName << std::endl;
635 if ( ! subPkg->installedObj() )
637 subPkg->setStatus( S_Install );
638 yuiMilestone() <<
"Installing subpackage " << subPkgName << std::endl;
642 subPkg->setStatus( S_Update );
643 yuiMilestone() <<
"Updating subpackage " << subPkgName << std::endl;
654 YGPackageSelector::get()->popupChanges();
657 static void install_all_devel_pkgs_cb()
658 { installSubPkgs (
"-devel"); }
660 static void install_all_debug_info_pkgs_cb()
661 { installSubPkgs (
"-debuginfo"); }
663 static void install_all_debug_source_pkgs_cb()
664 { installSubPkgs (
"-debugsource"); }
666 static void show_pkg_changes_cb()
667 { YGPackageSelector::get()->popupChanges(); }
669 static void show_log_changes_cb()
670 { YGPackageSelector::get()->showHistoryDialog(); }
672 #ifdef HAS_VESTIGIAL_DIALOG
673 static void show_vestigial_packages_cb()
674 { YGPackageSelector::get()->showVestigialDialog(); }
677 static void reset_ignored_dependency_conflicts_cb()
678 { zypp::getZYpp()->resolver()->undo(); }
680 #include "ygtkpkgproductdialog.h"
682 static void show_products_cb()
689 { selector->apply(); }
692 { selector->cancel(); }
694 YGtkPkgMenuBar::YGtkPkgMenuBar()
697 m_menu = gtk_menu_bar_new();
700 GtkWidget *menu_bar = m_menu, *item, *submenu;
701 item = append_menu_item (menu_bar, _(
"F&ile"), NULL, NULL, NULL);
702 gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), (submenu = gtk_menu_new()));
703 append_menu_item (submenu, _(
"&Import..."), NULL,
704 G_CALLBACK (import_file_cb),
this);
705 append_menu_item (submenu, _(
"&Export..."), NULL,
706 G_CALLBACK (export_file_cb),
this);
707 append_menu_item (submenu, NULL, NULL, NULL, NULL);
708 append_menu_item (submenu, NULL, GTK_STOCK_APPLY, G_CALLBACK (accept_item_cb), selector);
709 append_menu_item (submenu, NULL, GTK_STOCK_QUIT, G_CALLBACK (reject_item_cb), selector);
710 if (selector->repoMgrEnabled()) {
711 item = append_menu_item (menu_bar, _(
"&Configuration"), NULL, NULL, NULL);
712 gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), (submenu = gtk_menu_new()));
713 append_menu_item (submenu, _(
"&Repositories..."), NULL,
714 G_CALLBACK (repoManager),
this);
715 if (selector->onlineUpdateMode())
716 append_menu_item (submenu, _(
"&Online Update..."), NULL,
717 G_CALLBACK (onlineUpdateConfiguration),
this);
719 item = append_menu_item (menu_bar, _(
"&Dependencies"), NULL, NULL, NULL);
720 gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), (submenu = gtk_menu_new()));
721 append_menu_item (submenu, _(
"&Check Now"), NULL,
722 G_CALLBACK (manualResolvePackageDependencies),
this);
725 if (!selector->onlineUpdateMode()) {
726 item = append_menu_item (menu_bar, _(
"&Options"), NULL, NULL, NULL);
727 gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), (submenu = gtk_menu_new()));
731 new ShowDebugCheckItem (submenu, _(
"Show -&debuginfo/-debugsource Packages"), &flags);
735 #if ZYPP_VERSION > 6031004
736 new CleanupDepsCheckItem (submenu, _(
"&Cleanup when deleting packages"), &flags);
737 new AllowVendorChangeCheckItem (submenu, _(
"&Allow vendor change"), &flags);
741 item = append_menu_item (menu_bar, _(
"E&xtras"), NULL, NULL, NULL);
742 gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), (submenu = gtk_menu_new()));
743 append_menu_item (submenu, _(
"Show &Products"), NULL,
744 G_CALLBACK (show_products_cb),
this);
745 append_menu_item (submenu, _(
"Show &Changes"), NULL,
746 G_CALLBACK (show_pkg_changes_cb),
this);
747 if (!selector->onlineUpdateMode()) {
748 append_menu_item (submenu, _(
"Show &History"), NULL,
749 G_CALLBACK (show_log_changes_cb),
this);
750 #ifdef HAS_VESTIGIAL_DIALOG
751 append_menu_item (submenu, _(
"Show &Unneeded Dependencies"), NULL,
752 G_CALLBACK (show_vestigial_packages_cb),
this);
755 append_menu_item (submenu, NULL, NULL, NULL, NULL);
757 append_menu_item (submenu, _(
"Install All Matching -&devel Packages"), NULL,
758 G_CALLBACK (install_all_devel_pkgs_cb),
this);
760 append_menu_item (submenu, _(
"Install All Matching -debug-&info Packages"), NULL,
761 G_CALLBACK (install_all_debug_info_pkgs_cb),
this);
763 append_menu_item (submenu, _(
"Install All Matching -debug-&source Packages"), NULL,
764 G_CALLBACK (install_all_debug_source_pkgs_cb),
this);
765 append_menu_item (submenu, NULL, NULL, NULL, NULL);
766 append_menu_item (submenu, _(
"Generate Dependencies Resolver &Testcase"), NULL,
767 G_CALLBACK (create_solver_testcase_cb),
this);
768 append_menu_item (submenu, _(
"Reset &Ignored Dependencies Conflicts"), NULL,
769 G_CALLBACK (reset_ignored_dependency_conflicts_cb),
this);