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 webpinSearch()
442 yuiMilestone() <<
"Closing PackageSelector with \"webpin\"" << std::endl;
443 YGUI::ui()->sendEvent(
new YMenuEvent(
"webpin" ) );
446 static void manualResolvePackageDependencies()
447 { Ypp::runSolver (
true); }
453 std::string str (YGUtils::mapKBAccel(text));
454 m_item = gtk_check_menu_item_new_with_mnemonic (str.c_str());
455 g_object_set_data_full (G_OBJECT (m_item),
"this",
this, destructor);
456 gtk_menu_shell_append (GTK_MENU_SHELL (menu), m_item);
459 void init (
Flags *flags) {
460 bool check = getZyppValue();
462 const char *var = variable();
463 if (flags->hasKey (var)) {
464 bool c = flags->getBool (var);
470 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (m_item), check);
471 g_signal_connect_after (G_OBJECT (m_item),
"toggled", G_CALLBACK (toggled_cb),
this);
474 virtual const char *variable() = 0;
475 virtual bool getZyppValue() = 0;
476 virtual void setZyppValue (
bool on) = 0;
477 virtual void runtimeSync() {}
479 void writeFile (
bool on) {
481 flags.setBool (variable(), on);
484 static void toggled_cb (GtkCheckMenuItem *item,
CheckMenuFlag *pThis) {
485 bool on = gtk_check_menu_item_get_active (item);
486 pThis->setZyppValue (on);
487 pThis->runtimeSync();
488 pThis->writeFile (on);
491 static void destructor (gpointer data) {
501 virtual const char *variable() {
return "auto-check"; }
502 virtual bool getZyppValue() {
return Ypp::isSolverEnabled(); }
503 virtual void setZyppValue (
bool on) { Ypp::setEnableSolver (on); }
509 virtual const char *variable() {
return "show-devel"; }
510 virtual bool getZyppValue() {
return true; }
511 virtual void setZyppValue (
bool on)
512 { YGPackageSelector::get()->filterPkgSuffix (
"-devel", !on); }
518 virtual const char *variable() {
return "show-debug"; }
519 virtual bool getZyppValue() {
return true; }
520 virtual void setZyppValue (
bool on) {
521 YGPackageSelector::get()->filterPkgSuffix (
"-debuginfo", !on);
522 YGPackageSelector::get()->filterPkgSuffix (
"-debugsource", !on);
529 virtual const char *variable() {
return "system-verification"; }
530 virtual bool getZyppValue() {
531 return zypp::getZYpp()->resolver()->systemVerification();
533 virtual void setZyppValue (
bool on) {
534 zypp::getZYpp()->resolver()->setSystemVerification (on);
536 virtual void runtimeSync() {}
542 virtual const char *variable() {
return "ignore-already-recommended"; }
543 virtual bool getZyppValue() {
544 return zypp::getZYpp()->resolver()->ignoreAlreadyRecommended();
546 virtual void setZyppValue (
bool on) {
547 zypp::getZYpp()->resolver()->setIgnoreAlreadyRecommended(on);
549 virtual void runtimeSync() { Ypp::runSolver(); }
552 #if ZYPP_VERSION > 6031004
555 CleanupDepsCheckItem (GtkWidget *menu,
const char *text,
Flags *flags)
557 virtual const char *variable() {
return "cleanup-deps"; }
558 virtual bool getZyppValue() {
559 return zypp::getZYpp()->resolver()->cleandepsOnRemove();
561 virtual void setZyppValue (
bool on) {
562 zypp::getZYpp()->resolver()->setCleandepsOnRemove( on );
564 virtual void runtimeSync() { Ypp::runSolver(); }
568 AllowVendorChangeCheckItem (GtkWidget *menu,
const char *text,
Flags *flags)
570 virtual const char *variable() {
return "allow-vendor-change"; }
571 virtual bool getZyppValue() {
572 return zypp::getZYpp()->resolver()->allowVendorChange();
574 virtual void setZyppValue (
bool on) {
575 zypp::getZYpp()->resolver()->setAllowVendorChange( on );
577 virtual void runtimeSync() { Ypp::runSolver(); }
582 static void installSubPkgs (std::string suffix)
586 std::map<std::string, ZyppSel> subPkgs;
588 for ( ZyppPoolIterator it = zyppPkgBegin(); it != zyppPkgEnd(); ++it )
590 std::string name = (*it)->name();
592 if (YGUtils::endsWith (name, suffix))
594 subPkgs[ name ] = *it;
595 yuiDebug() <<
"Found subpackage: " << name << std::endl;
602 for ( ZyppPoolIterator it = zyppPkgBegin(); it != zyppPkgEnd(); ++it )
604 std::string name = (*it)->name();
606 std::string subPkgName( name + suffix );
607 if ( subPkgs.find( subPkgName ) != subPkgs.end() )
609 ZyppSel subPkg = subPkgs[ subPkgName ];
611 switch ( (*it)->status() )
619 yuiMilestone() <<
"Ignoring unwanted subpackage " << subPkgName << std::endl;
624 case S_KeepInstalled:
628 if ( ! subPkg->installedObj() )
630 subPkg->setStatus( S_Install );
631 yuiMilestone() <<
"Installing subpackage " << subPkgName << std::endl;
641 if ( ! subPkg->installedObj() )
643 subPkg->setStatus( S_Install );
644 yuiMilestone() <<
"Installing subpackage " << subPkgName << std::endl;
648 subPkg->setStatus( S_Update );
649 yuiMilestone() <<
"Updating subpackage " << subPkgName << std::endl;
660 YGPackageSelector::get()->popupChanges();
663 static void install_all_devel_pkgs_cb()
664 { installSubPkgs (
"-devel"); }
666 static void install_all_debug_info_pkgs_cb()
667 { installSubPkgs (
"-debuginfo"); }
669 static void install_all_debug_source_pkgs_cb()
670 { installSubPkgs (
"-debugsource"); }
672 static void show_pkg_changes_cb()
673 { YGPackageSelector::get()->popupChanges(); }
675 static void show_log_changes_cb()
676 { YGPackageSelector::get()->showHistoryDialog(); }
678 #ifdef HAS_VESTIGIAL_DIALOG
679 static void show_vestigial_packages_cb()
680 { YGPackageSelector::get()->showVestigialDialog(); }
683 static void reset_ignored_dependency_conflicts_cb()
684 { zypp::getZYpp()->resolver()->undo(); }
686 #include "ygtkpkgproductdialog.h"
688 static void show_products_cb()
695 { selector->apply(); }
698 { selector->cancel(); }
700 YGtkPkgMenuBar::YGtkPkgMenuBar()
703 m_menu = gtk_menu_bar_new();
706 GtkWidget *menu_bar = m_menu, *item, *submenu;
707 item = append_menu_item (menu_bar, _(
"F&ile"), NULL, NULL, NULL);
708 gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), (submenu = gtk_menu_new()));
709 append_menu_item (submenu, _(
"&Import..."), NULL,
710 G_CALLBACK (import_file_cb),
this);
711 append_menu_item (submenu, _(
"&Export..."), NULL,
712 G_CALLBACK (export_file_cb),
this);
713 append_menu_item (submenu, NULL, NULL, NULL, NULL);
714 append_menu_item (submenu, NULL, GTK_STOCK_APPLY, G_CALLBACK (accept_item_cb), selector);
715 append_menu_item (submenu, NULL, GTK_STOCK_QUIT, G_CALLBACK (reject_item_cb), selector);
716 if (selector->repoMgrEnabled()) {
717 item = append_menu_item (menu_bar, _(
"&Configuration"), NULL, NULL, NULL);
718 gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), (submenu = gtk_menu_new()));
719 append_menu_item (submenu, _(
"&Repositories..."), NULL,
720 G_CALLBACK (repoManager),
this);
721 if (selector->onlineUpdateMode())
722 append_menu_item (submenu, _(
"&Online Update..."), NULL,
723 G_CALLBACK (onlineUpdateConfiguration),
this);
725 append_menu_item (submenu, _(
"Search Packages on &Web..."), NULL,
726 G_CALLBACK (webpinSearch),
this);
728 item = append_menu_item (menu_bar, _(
"&Dependencies"), NULL, NULL, NULL);
729 gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), (submenu = gtk_menu_new()));
730 append_menu_item (submenu, _(
"&Check Now"), NULL,
731 G_CALLBACK (manualResolvePackageDependencies),
this);
734 if (!selector->onlineUpdateMode()) {
735 item = append_menu_item (menu_bar, _(
"&Options"), NULL, NULL, NULL);
736 gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), (submenu = gtk_menu_new()));
740 new ShowDebugCheckItem (submenu, _(
"Show -&debuginfo/-debugsource Packages"), &flags);
744 #if ZYPP_VERSION > 6031004
745 new CleanupDepsCheckItem (submenu, _(
"&Cleanup when deleting packages"), &flags);
746 new AllowVendorChangeCheckItem (submenu, _(
"&Allow vendor change"), &flags);
750 item = append_menu_item (menu_bar, _(
"E&xtras"), NULL, NULL, NULL);
751 gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), (submenu = gtk_menu_new()));
752 append_menu_item (submenu, _(
"Show &Products"), NULL,
753 G_CALLBACK (show_products_cb),
this);
754 append_menu_item (submenu, _(
"Show &Changes"), NULL,
755 G_CALLBACK (show_pkg_changes_cb),
this);
756 if (!selector->onlineUpdateMode()) {
757 append_menu_item (submenu, _(
"Show &History"), NULL,
758 G_CALLBACK (show_log_changes_cb),
this);
759 #ifdef HAS_VESTIGIAL_DIALOG
760 append_menu_item (submenu, _(
"Show &Unneeded Dependencies"), NULL,
761 G_CALLBACK (show_vestigial_packages_cb),
this);
764 append_menu_item (submenu, NULL, NULL, NULL, NULL);
766 append_menu_item (submenu, _(
"Install All Matching -&devel Packages"), NULL,
767 G_CALLBACK (install_all_devel_pkgs_cb),
this);
769 append_menu_item (submenu, _(
"Install All Matching -debug-&info Packages"), NULL,
770 G_CALLBACK (install_all_debug_info_pkgs_cb),
this);
772 append_menu_item (submenu, _(
"Install All Matching -debug-&source Packages"), NULL,
773 G_CALLBACK (install_all_debug_source_pkgs_cb),
this);
774 append_menu_item (submenu, NULL, NULL, NULL, NULL);
775 append_menu_item (submenu, _(
"Generate Dependencies Resolver &Testcase"), NULL,
776 G_CALLBACK (create_solver_testcase_cb),
this);
777 append_menu_item (submenu, _(
"Reset &Ignored Dependencies Conflicts"), NULL,
778 G_CALLBACK (reset_ignored_dependency_conflicts_cb),
this);