15 #include "ygtkpkgdetailview.h"
17 #include <gdk/gdkkeysyms.h>
18 #include "YGPackageSelector.h"
19 #include "ygtkrichtext.h"
20 #include "ygtkpkgsearchentry.h"
21 #include "ygtkpkglistview.h"
22 #include <YStringTree.h>
24 #define BROWSER_BIN "/usr/bin/firefox"
25 #define GNOME_OPEN_BIN "/usr/bin/gnome-open"
27 static std::string onlyInstalledMsg() {
28 std::string s (
"<i>");
29 s += _(
"Information only available for installed packages.");
34 static const char *keywordOpenTag =
"<keyword>", *keywordCloseTag =
"</keyword>";
38 YGDialog::currentDialog()->busyCursor();
39 while (g_main_context_iteration (NULL, FALSE)) ;
42 YGDialog::currentDialog()->normalCursor();
48 virtual GtkWidget *getWidget() = 0;
49 virtual void refreshList (
Ypp::List list) = 0;
50 virtual void setList (
Ypp::List list) = 0;
54 GtkWidget *hbox, *icon, *text;
58 text = ygtk_rich_text_new();
59 icon = gtk_image_new();
61 hbox = gtk_hbox_new (FALSE, 2);
62 gtk_box_pack_start (GTK_BOX (hbox), text, TRUE, TRUE, 0);
63 gtk_box_pack_start (GTK_BOX (hbox), icon, FALSE, TRUE, 0);
66 virtual GtkWidget *getWidget()
73 if (list.size() > 0) {
75 str =
"<p bgcolor=\"";
76 str += props.toModify() ?
"#f4f4b7" :
"#ededed";
77 str +=
"\"><font color=\"#000000\">";
78 if (list.size() == 1) {
80 if (gtk_widget_get_default_direction() == GTK_TEXT_DIR_RTL)
81 str += sel.summary() +
" - " +
"<b>" + sel.name() +
"</b>";
83 str +=
"<b>" + sel.name() +
"</b> - " + sel.summary();
87 str += _(
"Several selected");
92 ygtk_rich_text_set_text (YGTK_RICH_TEXT (text), str.c_str());
97 gtk_widget_hide (icon);
98 if (list.size() == 1) {
101 gtk_image_clear (GTK_IMAGE (icon));
102 GtkIconTheme *icons = gtk_icon_theme_get_default();
103 GdkPixbuf *pixbuf = gtk_icon_theme_load_icon (icons,
104 sel.name().c_str(), 32, GtkIconLookupFlags (0), NULL);
106 gtk_image_set_from_pixbuf (GTK_IMAGE (icon), pixbuf);
107 g_object_unref (G_OBJECT (pixbuf));
108 gtk_widget_show (icon);
117 GtkWidget *text, *popup;
118 std::string link_str;
122 text = ygtk_rich_text_new();
123 g_signal_connect (G_OBJECT (text),
"link-clicked",
124 G_CALLBACK (link_clicked_cb),
this);
128 {
if (popup) gtk_widget_destroy (popup); }
130 virtual GtkWidget *getWidget()
133 virtual void refreshList (
Ypp::List list)
140 if (list.size() == 1) {
142 str = sel.description (
true);
145 if (search->getAttribute() == Ypp::PoolQuery::DESCRIPTION) {
146 std::list <std::string> keywords;
147 keywords = YGPackageSelector::get()->getSearchEntry()->getText();
148 highlightMarkup (str, keywords, keywordOpenTag, keywordCloseTag,
149 strlen (keywordOpenTag), strlen (keywordCloseTag));
152 if (sel.type() == Ypp::Selectable::PACKAGE) {
154 std::string url (pkg.url());
156 str +=
"<p><i>"; str += _(
"Web site:");
157 str +=
"</i> <a href=\""; str += url; str +=
"\">";
158 str += url; str +=
"</a></p>";
160 if (pkg.isCandidatePatch()) {
163 str +=
"<p><i>"; str += _(
"Patch issued:");
164 str +=
"</i> "; str += _patch.summary();
165 str +=
" <b>("; str += Ypp::Patch::prioritySummary (patch.priority());
166 str +=
")</b>"; str +=
"</p>";
172 if (list.size() > 0) {
174 for (
int i = 0; i < list.size(); i++)
175 str +=
"<li>" + list.get (i).name() +
"</li>";
179 ygtk_rich_text_set_text (YGTK_RICH_TEXT (text), str.c_str());
182 static void link_clicked_cb (YGtkRichText *text,
const gchar *link,
DetailDescription *pThis)
185 GtkWidget *menu = pThis->popup = gtk_menu_new();
186 gtk_menu_attach_to_widget (GTK_MENU (menu), GTK_WIDGET (text), NULL);
189 if (g_file_test (BROWSER_BIN, G_FILE_TEST_IS_EXECUTABLE)) {
190 std::string label (YGUtils::mapKBAccel (
"&Open"));
192 const char *username = getenv (
"USERNAME");
193 if (!username || !(*username))
195 label +=
" ("; label += _(
"as");
196 label +=
" "; label += username; label +=
")";
198 item = gtk_image_menu_item_new_with_mnemonic (label.c_str());
199 gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item),
200 gtk_image_new_from_stock (GTK_STOCK_OPEN, GTK_ICON_SIZE_MENU));
201 gtk_widget_show (item);
202 g_signal_connect (G_OBJECT (item),
"activate",
203 G_CALLBACK (open_link_cb), pThis);
204 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
206 item = gtk_image_menu_item_new_from_stock (GTK_STOCK_COPY, NULL);
207 gtk_widget_show (item);
208 g_signal_connect (G_OBJECT (item),
"activate",
209 G_CALLBACK (copy_link_cb), pThis);
210 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
212 gtk_menu_popup (GTK_MENU (pThis->popup), NULL, NULL, NULL, NULL,
213 0, gtk_get_current_event_time());
214 pThis->link_str = link;
219 const std::string &link = pThis->link_str;
221 command.reserve (256);
223 const char *username = 0;
225 username = getenv (
"USERNAME");
226 if (username && !(*username))
231 command +=
"gnomesu -u ";
233 command +=
" -c \"" BROWSER_BIN
" --new-window ";
238 command += BROWSER_BIN
" --new-window ";
242 (void) system (command.c_str());
247 const std::string &link = pThis->link_str;
248 GtkClipboard *clipboard =
249 gtk_widget_get_clipboard (pThis->text, GDK_SELECTION_CLIPBOARD);
250 gtk_clipboard_set_text (clipboard, link.c_str(), -1);
260 : list (0), dirty (
false)
262 std::string str =
"<b>" + label +
"</b>";
263 expander = gtk_expander_new (str.c_str());
264 gtk_expander_set_use_markup (GTK_EXPANDER (expander), TRUE);
265 gtk_expander_set_expanded (GTK_EXPANDER (expander), default_expanded);
266 g_signal_connect_after (G_OBJECT (expander),
"notify::expanded",
267 G_CALLBACK (expanded_cb),
this);
270 virtual GtkWidget *getWidget() {
return expander; }
275 if (gtk_expander_get_expanded (GTK_EXPANDER (expander)))
284 if (onlySingleList())
285 return list.size() == 1;
286 return list.size() > 0;
293 visible() ? gtk_widget_show (expander) : gtk_widget_hide (expander);
297 virtual void refreshList (
Ypp::List list)
299 if (gtk_expander_get_expanded (GTK_EXPANDER (expander)))
300 showRefreshList (list);
305 static void expanded_cb (GObject *
object, GParamSpec *param_spec,
DetailExpander *pThis)
306 { pThis->updateList(); }
308 void setChild (GtkWidget *child)
309 { gtk_container_add (GTK_CONTAINER (expander), child); }
312 virtual void showList (
Ypp::List list) = 0;
313 virtual void showRefreshList (
Ypp::List list) = 0;
314 virtual bool onlySingleList() = 0;
323 text = ygtk_rich_text_new();
324 gtk_widget_set_size_request (text, 160, -1);
328 virtual bool onlySingleList() {
return true; }
333 ZyppSelectable zsel = sel.zyppSel();
334 ZyppResObject zobj = zsel->theObj();
335 ZyppPackage zpkg = castZyppPackage (zobj);
338 std::string b (
"<i>"), _b (
"</i> "), i (
""), _i(
""), br (
"<br/>");
340 str += b + _(
"Size:") + _b + i + zobj->installSize().asString() + _i;
341 str += br + b + _(
"License:") + _b + i + zpkg->license() + _i;
342 if (zsel->hasInstalledObj())
343 str += br + b + (
"Installed at:") + _b + i +
344 zsel->installedObj()->installtime().form (
"%x") + _i;
345 if (zsel->hasCandidateObj())
346 str += br + b + (
"Latest build:") + _b + i +
347 zsel->candidateObj()->buildtime().form (
"%x") + _i;
348 ygtk_rich_text_set_text (YGTK_RICH_TEXT (text), str.c_str());
351 virtual void showRefreshList (
Ypp::List list) {}
354 typedef zypp::ResPoolProxy::const_iterator ZyppPoolIterator;
355 inline ZyppPoolIterator zyppSrcPkgBegin()
356 {
return zyppPool().byKindBegin<zypp::SrcPackage>(); }
357 inline ZyppPoolIterator zyppSrcPkgEnd()
358 {
return zyppPool().byKindEnd<zypp::SrcPackage>(); }
361 GtkWidget *versions_box;
362 std::list <Ypp::Version> versions;
367 versions_box = gtk_vbox_new (FALSE, 2);
370 GtkWidget *frame = gtk_frame_new (NULL);
371 gtk_container_set_border_width (GTK_CONTAINER (frame), 2);
372 gtk_container_add (GTK_CONTAINER (frame), versions_box);
378 GtkWidget *button = gtk_toggle_button_new();
379 gtk_container_add (GTK_CONTAINER (button), gtk_image_new());
381 GtkWidget *label = gtk_label_new (
"");
382 gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
384 GtkWidget *hbox = gtk_hbox_new (FALSE, 6);
385 gtk_container_set_border_width (GTK_CONTAINER (hbox), 2);
386 gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 0);
387 gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
388 gtk_widget_show_all (hbox);
390 g_object_set_data (G_OBJECT (button),
"nb", GINT_TO_POINTER (versions.size()));
391 updateVersionWidget (hbox, sel, version);
392 g_signal_connect (G_OBJECT (button),
"toggled",
393 G_CALLBACK (button_clicked_cb),
this);
395 GtkWidget *widget = hbox;
396 if ((versions.size() % 2) == 1)
397 g_signal_connect (G_OBJECT (widget),
"draw",
398 G_CALLBACK (draw_gray_cb), NULL);
399 versions.push_back (version);
400 gtk_box_pack_start (GTK_BOX (versions_box), widget, FALSE, TRUE, 0);
406 std::string repo;
bool modified;
407 if (version.isInstalled()) {
408 repo = _(
"Installed");
409 modified = sel.toRemove();
412 repo = version.repository().name();
413 modified = sel.toInstall();
415 modified = modified && version.toModify();
417 std::string number (version.number()), arch (version.arch());
418 char *tooltip = g_strdup_printf (
"%s <small>(%s)</small>\n<small>%s</small>",
419 number.c_str(), arch.c_str(), repo.c_str());
420 number = YGUtils::truncate (number, 20, 0);
421 char *str = g_strdup_printf (
"%s%s <small>(%s)</small>\n<small>%s</small>%s",
422 modified ?
"<i>" :
"", number.c_str(), arch.c_str(), repo.c_str(),
423 modified ?
"</i>" :
"");
425 gtk_label_set_markup (GTK_LABEL (label), str);
426 if (number.size() > 20)
427 gtk_widget_set_tooltip_markup (label, tooltip);
428 g_free (tooltip); g_free (str);
433 const char *stock, *tooltip;
434 bool modified, can_modify =
true;
435 if (version.isInstalled()) {
436 tooltip = _(
"Remove");
437 stock = GTK_STOCK_DELETE;
438 can_modify = sel.canRemove();
439 modified = sel.toRemove();
442 if (sel.hasInstalledVersion()) {
444 if (installed < version) {
445 tooltip = _(
"Upgrade");
446 stock = GTK_STOCK_GO_UP;
448 else if (installed > version) {
449 tooltip = _(
"Downgrade");
450 stock = GTK_STOCK_GO_DOWN;
453 tooltip = _(
"Re-install");
454 stock = GTK_STOCK_REFRESH;
458 tooltip = _(
"Install");
459 stock = GTK_STOCK_SAVE;
461 modified = sel.toInstall();
463 modified = modified && version.toModify();
467 g_signal_handlers_block_by_func (button, (gpointer) button_clicked_cb,
this);
468 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), modified);
469 g_signal_handlers_unblock_by_func (button, (gpointer) button_clicked_cb,
this);
470 can_modify ? gtk_widget_show (button) : gtk_widget_hide (button);
471 gtk_widget_set_tooltip_text (button, tooltip);
472 gtk_image_set_from_stock (GTK_IMAGE (gtk_bin_get_child (GTK_BIN(button))),
473 stock, GTK_ICON_SIZE_BUTTON);
478 GList *children = gtk_container_get_children (GTK_CONTAINER (widget));
479 GtkWidget *label = (GtkWidget *) children->data;
480 GtkWidget *button = (GtkWidget *) children->next->data;
481 g_list_free (children);
483 updateVersionLabel (label, sel, version);
484 updateVersionButton (button, sel, version);
487 void updateMultiselectionButton (GtkWidget *button)
491 const char *stock, *tooltip;
492 bool modified, hide =
false;
493 if (props.isInstalled()) {
494 tooltip = _(
"Remove");
495 stock = GTK_STOCK_DELETE;
497 else if (props.isNotInstalled()) {
498 tooltip = _(
"Install");
499 stock = GTK_STOCK_SAVE;
503 modified = props.toModify();
507 g_signal_handlers_block_by_func (button, (gpointer) button_clicked_cb,
this);
508 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), modified);
509 g_signal_handlers_unblock_by_func (button, (gpointer) button_clicked_cb,
this);
510 hide ? gtk_widget_hide (button) : gtk_widget_show (button);
511 gtk_widget_set_tooltip_text (button, tooltip);
512 gtk_image_set_from_stock (GTK_IMAGE (gtk_bin_get_child (GTK_BIN(button))),
513 stock, GTK_ICON_SIZE_BUTTON);
518 GList *children = gtk_container_get_children (GTK_CONTAINER (versions_box));
519 for (GList *i = children; i; i = i->next)
520 gtk_container_remove (GTK_CONTAINER (versions_box), (GtkWidget *) i->data);
521 g_list_free (children);
527 int nb = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button),
"nb"));
528 std::list <Ypp::Version>::iterator it = versions.begin();
529 for (
int i = 0; i < nb; i++) it++;
533 static void button_clicked_cb (GtkToggleButton *button,
VersionExpander *pThis)
536 if (gtk_toggle_button_get_active (button)) {
537 if (pThis->list.size() > 1) {
539 if (props.hasUpgrade())
540 pThis->list.install();
541 else if (props.isInstalled())
542 pThis->list.remove();
543 else if (props.isNotInstalled())
544 pThis->list.install();
545 else if (props.toModify())
554 if (version.isInstalled())
557 sel.setCandidate (version);
566 virtual bool onlySingleList() {
return false; }
573 if (list.size() == 1) {
575 GtkWidget *radio = 0;
576 for (
int i = 0; i < sel.totalVersions(); i++)
577 radio = addVersion (sel, sel.version (i), radio);
580 GtkWidget *button = gtk_toggle_button_new();
581 gtk_container_add (GTK_CONTAINER (button), gtk_image_new());
583 GtkWidget *label = gtk_label_new (_(
"Several selected"));
584 GtkWidget *hbox = gtk_hbox_new (FALSE, 6);
585 gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 0);
586 gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
587 gtk_box_pack_start (GTK_BOX (versions_box), hbox, FALSE, TRUE, 0);
588 gtk_widget_show_all (hbox);
590 updateMultiselectionButton (button);
591 g_signal_connect (G_OBJECT (button),
"toggled",
592 G_CALLBACK (button_clicked_cb),
this);
595 gtk_widget_set_sensitive (versions_box, !props.isLocked());
598 virtual void showRefreshList (
Ypp::List list)
601 GList *children = gtk_container_get_children (GTK_CONTAINER (versions_box));
602 if (list.size() == 1) {
604 std::list <Ypp::Version>::iterator it = versions.begin();
605 for (GList *i = children; i; i = i->next, it++)
606 updateVersionWidget ((GtkWidget *) i->data, sel, *it);
609 GtkWidget *hbox = (GtkWidget *) children->data;
610 GList *l = gtk_container_get_children (GTK_CONTAINER (hbox));
611 GtkWidget *button = (GtkWidget *) l->next->data;
613 updateMultiselectionButton (button);
615 g_list_free (children);
618 static gboolean draw_gray_cb (GtkWidget *widget, cairo_t *cr)
620 int w = gtk_widget_get_allocated_width(widget);
621 int h = gtk_widget_get_allocated_height(widget);
623 cairo_rectangle (cr, 0, 0, w, h);
625 cairo_set_source_rgba (cr, 0, 0, 0, .060);
633 GtkWidget *text, *expander;
637 text = ygtk_rich_text_new();
638 expander = gtk_expander_new (
"");
639 gtk_expander_set_use_markup (GTK_EXPANDER (expander), TRUE);
640 gtk_container_add (GTK_CONTAINER (expander), text);
643 virtual GtkWidget *getWidget() {
return expander; }
645 virtual void refreshList (
Ypp::List list) {}
649 if (list.size() == 1) {
653 int support = pkg.support();
655 std::string label (
"<b>" + std::string (_(
"Supportability:")) +
"</b> ");
656 label += Ypp::Package::supportSummary (support);
657 gtk_expander_set_label (GTK_EXPANDER (expander), label.c_str());
658 ygtk_rich_text_set_text (YGTK_RICH_TEXT (text),
659 Ypp::Package::supportDescription (support).c_str());
662 gtk_widget_hide(expander);
664 gtk_widget_show (expander);
667 gtk_widget_hide (expander);
677 grid = gtk_grid_new();
678 gtk_widget_set_hexpand (grid, TRUE);
679 gtk_widget_set_vexpand (grid, FALSE);
685 GList *children = gtk_container_get_children (GTK_CONTAINER (grid));
686 for (GList *i = children; i; i = i->next)
687 gtk_container_remove (GTK_CONTAINER (grid), (GtkWidget *) i->data);
688 g_list_free (children);
691 void addLine (
const std::string &col1,
const std::string &col2,
692 const std::string &col3,
int dep)
698 for(
int i = 0; i < 3; i++) {
699 cols[i] = ygtk_rich_text_new();
700 gtk_widget_set_size_request(cols[i], 100, -1);
703 ygtk_rich_text_set_text (YGTK_RICH_TEXT (cols[0]), (
"<i>" + col1 +
"</i>").c_str());
704 ygtk_rich_text_set_text (YGTK_RICH_TEXT (cols[1]), col2.c_str());
705 ygtk_rich_text_set_text (YGTK_RICH_TEXT (cols[2]), col3.c_str());
707 for(
int i = 1; i < 3; i++) {
709 g_signal_connect (G_OBJECT (cols[i]),
"link-clicked",
710 G_CALLBACK (requires_link_cb), NULL);
712 g_signal_connect (G_OBJECT (cols[i]),
"link-clicked",
713 G_CALLBACK (provides_link_cb), NULL);
716 GList *children = gtk_container_get_children(GTK_CONTAINER(grid));
717 guint top = g_list_length (children) / 3;
718 g_list_free (children);
720 for(
int i = 0; i < 3; i++)
721 gtk_grid_attach (GTK_GRID (grid), cols[i], i, top, 1, 1);
724 static void requires_link_cb (GtkWidget *widget,
const gchar *link)
725 { YGPackageSelector::get()->searchFor (Ypp::PoolQuery::REQUIRES, link); }
727 static void provides_link_cb (GtkWidget *widget,
const gchar *link)
728 { YGPackageSelector::get()->searchFor (Ypp::PoolQuery::PROVIDES, link); }
731 virtual bool onlySingleList() {
return true; }
738 std::string i (
"<i>"), _i (
"</i>"), b (
"<b>"), _b (
"</b>");
739 std::string installed_str (i + b + _(
"Installed Version:") + _b + _i);
740 std::string candidate_str (i + b + _(
"Available Version:") + _b + _i);
741 bool hasInstalled = sel.hasInstalledVersion(),
742 hasCandidate = sel.hasCandidateVersion();
744 installed_str +=
"<br>" + sel.installed().number();
746 candidate_str +=
"<br>" + sel.candidate().number();
747 addLine (
"", installed_str, candidate_str, -1);
748 for (
int dep = 0; dep < VersionDependencies::total(); dep++) {
749 std::string inst, cand;
754 if (!inst.empty() || !cand.empty())
755 addLine (VersionDependencies::getLabel (dep), inst, cand, dep);
757 gtk_widget_show_all (grid);
760 virtual void showRefreshList (
Ypp::List list)
765 : m_version (version) {}
768 {
return ((
int) zypp::Dep::SUPPLEMENTS_e) + 1; }
770 static const char *getLabel (
int dep)
773 switch ((zypp::Dep::for_use_in_switch) dep) {
774 case zypp::Dep::PROVIDES_e:
return "Provides:";
775 case zypp::Dep::PREREQUIRES_e:
return "Pre-requires:";
776 case zypp::Dep::REQUIRES_e:
return "Requires:";
777 case zypp::Dep::CONFLICTS_e:
return "Conflicts:";
778 case zypp::Dep::OBSOLETES_e:
return "Obsoletes:";
779 case zypp::Dep::RECOMMENDS_e:
return "Recommends:";
780 case zypp::Dep::SUGGESTS_e:
return "Suggests:";
781 case zypp::Dep::ENHANCES_e:
return "Enhances:";
782 case zypp::Dep::SUPPLEMENTS_e:
return "Supplements:";
788 static zypp::Dep getDep (
int dep)
791 case 0:
return zypp::Dep::PROVIDES;
792 case 1:
return zypp::Dep::PREREQUIRES;
793 case 2:
return zypp::Dep::REQUIRES;
794 case 3:
return zypp::Dep::CONFLICTS;
795 case 4:
return zypp::Dep::OBSOLETES;
796 case 5:
return zypp::Dep::RECOMMENDS;
797 case 6:
return zypp::Dep::SUGGESTS;
798 case 7:
return zypp::Dep::ENHANCES;
799 case 8:
return zypp::Dep::SUPPLEMENTS;
801 return zypp::Dep::PROVIDES;
805 std::string getText (
int dep)
809 if ((dep == 0 && search->getAttribute() == Ypp::PoolQuery::PROVIDES) ||
810 (dep == 2 && search->getAttribute() == Ypp::PoolQuery::REQUIRES))
811 keyword = search->getTextStr();
813 ZyppResObject zobj = m_version.zyppObj();
814 zypp::Capabilities caps = zobj->dep (getDep (dep));
817 for (zypp::Capabilities::const_iterator it = caps.begin();
818 it != caps.end(); it++) {
822 std::string str (it->asString());
823 bool highlight = (str == keyword);
826 if (dep == 0 || dep == 2) {
827 std::string::size_type i;
828 i = MIN (str.find (
' '), str.find (
'('));
830 std::string name (str, 0, i);
831 ret +=
"<a href=\"" + name +
"\">" + YGUtils::escapeMarkup (name) +
"</a>";
832 if (i != std::string::npos) {
833 std::string rest (str, i);
834 ret += YGUtils::escapeMarkup (rest);
838 ret += YGUtils::escapeMarkup (str);
841 ret += keywordCloseTag;
856 text = ygtk_rich_text_new();
857 g_signal_connect (G_OBJECT (text),
"link-clicked",
858 G_CALLBACK (dirname_pressed_cb),
this);
862 virtual bool onlySingleList() {
return true; }
867 if (sel.isInstalled())
868 ygtk_rich_text_set_text (YGTK_RICH_TEXT (text), filelist (sel).c_str());
870 ygtk_rich_text_set_text (YGTK_RICH_TEXT (text), onlyInstalledMsg().c_str());
873 virtual void showRefreshList (
Ypp::List list) {}
875 static void dirname_pressed_cb (GtkWidget *text,
const gchar *link,
FilelistExpander *pThis)
877 gchar *cmd = g_strdup_printf (GNOME_OPEN_BIN
" %s &", link);
887 ZyppResObject zobj = sel.installed().zyppObj();
888 ZyppPackage zpkg = castZyppPackage (zobj);
890 YStringTree tree (
"");
892 zypp::Package::FileList files = zpkg->filelist();
893 for (zypp::Package::FileList::iterator it = files.begin();
894 it != files.end(); it++)
895 tree.addBranch (*it,
'/');
898 static std::string path (YStringTreeItem *item)
902 for (YStringTreeItem *i = item->parent(); i->parent(); i = i->parent()) {
903 std::string val (i->value().orig());
904 std::string prefix (
"/");
905 str = prefix + val + str;
910 static void traverse (YStringTreeItem *item, std::string &text)
915 bool has_leaves =
false;
916 for (YStringTreeItem *i = item; i; i = i->next()) {
917 YStringTreeItem *child = i->firstChild();
919 traverse (child, text);
926 std::string dirname (path (item));
927 text +=
"<a href=\"" + dirname +
"\">" + dirname +
"</a>";
928 text +=
"<blockquote>";
932 if (search->getAttribute() == Ypp::PoolQuery::FILELIST)
933 keyword = search->getTextStr();
934 if (!keyword.empty() && keyword[0] ==
'/') {
935 std::string _dirname (keyword, 0, keyword.find_last_of (
'/'));
936 if (dirname == _dirname)
937 keyword = std::string (keyword, _dirname.size()+1);
942 for (YStringTreeItem *i = item; i; i = i->next())
943 if (!i->firstChild()) {
946 std::string basename (i->value().orig());
948 bool highlight = (basename == keyword);
950 text += keywordOpenTag;
953 text += keywordCloseTag;
956 text +=
"</blockquote>";
961 inner::traverse (tree.root(), text);
973 text = ygtk_rich_text_new();
977 virtual bool onlySingleList() {
return true; }
982 if (sel.isInstalled())
983 ygtk_rich_text_set_text (YGTK_RICH_TEXT (text), changelog (sel).c_str());
985 ygtk_rich_text_set_text (YGTK_RICH_TEXT (text), onlyInstalledMsg().c_str());
988 virtual void showRefreshList (
Ypp::List list) {}
993 text.reserve (32768);
995 text += _(
"Changelog applies only to the installed version.");
997 ZyppResObject zobj = sel.installed().zyppObj();
998 ZyppPackage zpkg = castZyppPackage (zobj);
1000 const std::list <zypp::ChangelogEntry> &logs = zpkg->changelog();
1001 for (std::list <zypp::ChangelogEntry>::const_iterator it = logs.begin();
1002 it != logs.end(); it++) {
1003 std::string date (it->date().form (
"%d %B %Y")), author (it->author()),
1004 changes (it->text());
1005 author = YGUtils::escapeMarkup (author);
1006 changes = YGUtils::escapeMarkup (changes);
1007 YGUtils::replace (changes,
"\n", 1,
"<br>");
1008 if (author.compare (0, 2,
"- ", 2) == 0)
1009 author.erase (0, 2);
1010 text +=
"<i>" + date +
" (" + author +
"):</i><br><blockquote>" + changes +
"</blockquote>";
1023 text = ygtk_rich_text_new();
1027 virtual bool onlySingleList() {
return true; }
1032 std::string str (authors (sel));
1034 str =
"<i>"; str += _(
"Attribute not-specified."); str +=
"</i>";
1036 ygtk_rich_text_set_text (YGTK_RICH_TEXT (text), str.c_str());
1039 virtual void showRefreshList (
Ypp::List list) {}
1044 ZyppResObject
object = sel.zyppSel()->theObj();
1045 ZyppPackage
package = castZyppPackage (object);
1047 std::string packager = package->packager(), vendor = package->vendor(), authors;
1048 packager = YGUtils::escapeMarkup (packager);
1049 vendor = YGUtils::escapeMarkup (vendor);
1050 const std::list <std::string> &authorsList = package->authors();
1051 for (std::list <std::string>::const_iterator it = authorsList.begin();
1052 it != authorsList.end(); it++) {
1053 std::string author (*it);
1054 author = YGUtils::escapeMarkup (author);
1055 if (!authors.empty())
1060 std::string description = package->description();
1061 std::string::size_type i = description.find (
"\nAuthors:\n-----", 0);
1062 if (i != std::string::npos) {
1063 i +=
sizeof (
"\nAuthors:\n----");
1064 i = description.find (
"\n", i);
1065 if (i != std::string::npos)
1069 i = description.find (
"\nAuthor:", 0);
1070 if (i == std::string::npos) {
1071 i = description.find (
"\nAuthors:", 0);
1072 if (i != std::string::npos)
1075 if (i != std::string::npos)
1076 i +=
sizeof (
"\nAuthor:");
1078 if (i != std::string::npos) {
1079 std::string str = description.substr (i);
1080 str = YGUtils::escapeMarkup (str);
1081 YGUtils::replace (str,
"\n", 1,
"<br>");
1085 if (!authors.empty()) {
1086 text =
"<i>"; text += _(
"Developed by:"); text +=
"</i>";
1087 text += (
"<blockquote>" + authors) +
"</blockquote>";
1088 if (!packager.empty() || !vendor.empty()) {
1089 text +=
"<i>"; text += _(
"Packaged by:"); text +=
"</i>";
1090 text +=
"<blockquote>";
1091 if (!packager.empty()) text += packager +
" ";
1092 if (!vendor.empty()) text +=
"(" + vendor +
")";
1093 text +=
"</blockquote>";
1107 view =
new YGtkPkgListView (
true, Ypp::List::NAME_SORT,
false,
false);
1108 view->addCheckColumn (INSTALLED_CHECK_PROP);
1109 view->addTextColumn (_(
"Name"), NAME_SUMMARY_PROP,
true, -1);
1110 view->addTextColumn (_(
"Version"), VERSION_PROP,
true, 125);
1111 view->addTextColumn (_(
"Size"), SIZE_PROP,
false, 85);
1112 view->addTextColumn (_(
"Repository"), REPOSITORY_PROP,
false, 180);
1113 view->addTextColumn (_(
"Supportability"), SUPPORT_PROP,
false, 120);
1114 gtk_widget_set_size_request (view->getWidget(), -1, 150);
1116 setChild (view->getWidget());
1122 virtual bool onlySingleList() {
return true; }
1131 view->setQuery (query);
1134 virtual void showRefreshList (
Ypp::List list) {}
1139 std::list <DetailWidget *> m_widgets;
1140 GtkWidget *m_scroll;
1147 GtkWidget *side_vbox = gtk_vbox_new (FALSE, 0);
1149 if (!YGPackageSelector::get()->onlineUpdateMode()) {
1151 m_widgets.push_back (widget);
1152 gtk_box_pack_start (GTK_BOX (side_vbox), widget->getWidget(), FALSE, TRUE, 0);
1155 m_widgets.push_back (widget);
1156 gtk_box_pack_start (GTK_BOX (side_vbox), widget->getWidget(), FALSE, TRUE, 0);
1158 GtkWidget *main_vbox = gtk_vbox_new (FALSE, 0);
1161 m_widgets.push_back (widget);
1162 gtk_box_pack_start (GTK_BOX (main_vbox), widget->getWidget(), FALSE, TRUE, 0);
1165 m_widgets.push_back (widget);
1166 gtk_box_pack_start (GTK_BOX (main_vbox), widget->getWidget(), FALSE, TRUE, 0);
1167 GtkWidget *detail_description = widget->getWidget();
1169 if (YGPackageSelector::get()->onlineUpdateMode()) {
1171 m_widgets.push_back (widget);
1172 gtk_box_pack_start (GTK_BOX (main_vbox), widget->getWidget(), FALSE, TRUE, 0);
1176 m_widgets.push_back (widget);
1177 gtk_box_pack_start (GTK_BOX (main_vbox), widget->getWidget(), FALSE, TRUE, 0);
1179 m_widgets.push_back (widget);
1180 gtk_box_pack_start (GTK_BOX (main_vbox), widget->getWidget(), FALSE, TRUE, 0);
1182 m_widgets.push_back (widget);
1183 gtk_box_pack_start (GTK_BOX (main_vbox), widget->getWidget(), FALSE, TRUE, 0);
1185 m_widgets.push_back (widget);
1186 gtk_box_pack_start (GTK_BOX (main_vbox), widget->getWidget(), FALSE, TRUE, 0);
1188 m_widgets.push_back (widget);
1189 gtk_box_pack_start (GTK_BOX (main_vbox), widget->getWidget(), FALSE, TRUE, 0);
1192 GtkWidget *hbox = gtk_hbox_new (FALSE, 2);
1193 gtk_box_pack_start (GTK_BOX (hbox), main_vbox, TRUE, TRUE, 0);
1194 gtk_box_pack_start (GTK_BOX (hbox), side_vbox, FALSE, TRUE, 0);
1196 GtkWidget *child = gtk_event_box_new();
1197 gtk_container_add (GTK_CONTAINER (child), hbox);
1199 GdkColor *color = >k_widget_get_style(detail_description)->base [GTK_STATE_NORMAL];
1200 gtk_widget_modify_bg (child, GTK_STATE_NORMAL, color);
1202 m_scroll = gtk_scrolled_window_new (NULL, NULL);
1203 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (m_scroll),
1204 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1205 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (m_scroll), child);
1207 gtk_widget_show_all (m_scroll);
1208 g_signal_connect (G_OBJECT (m_scroll),
"realize",
1209 G_CALLBACK (scroll_realize_cb),
this);
1210 Ypp::addSelListener (
this);
1215 for (std::list <DetailWidget *>::iterator it = m_widgets.begin();
1216 it != m_widgets.end(); it++)
1218 Ypp::removeSelListener (
this);
1223 for (std::list <DetailWidget *>::iterator it = m_widgets.begin();
1224 it != m_widgets.end(); it++)
1225 (*it)->refreshList (list);
1230 for (std::list <DetailWidget *>::iterator it = m_widgets.begin();
1231 it != m_widgets.end(); it++)
1232 (*it)->setList (list);
1238 virtual void selectableModified()
1239 { refreshList (m_list); }
1243 GtkScrolledWindow *scroll = GTK_SCROLLED_WINDOW (m_scroll);
1244 GtkAdjustment *vadj = gtk_scrolled_window_get_vadjustment (scroll);
1245 YGUtils::scrollWidget (vadj,
true);
1249 static void move_cursor_cb (GtkTextView *view, GtkMovementStep step, gint count,
1250 gboolean extend_selection, GtkWidget *scroll)
1252 GtkScrolledWindow *_scroll = GTK_SCROLLED_WINDOW (scroll);
1253 GtkAdjustment *adj = gtk_scrolled_window_get_vadjustment (_scroll);
1254 GtkAllocation alloc;
1255 gtk_widget_get_allocation(scroll, &alloc);
1257 int height = alloc.height;
1260 case GTK_MOVEMENT_DISPLAY_LINES:
1261 increment = height / 10.0;
1263 case GTK_MOVEMENT_PAGES:
1264 increment = height * 0.9;
1266 case GTK_MOVEMENT_DISPLAY_LINE_ENDS:
1267 increment = gtk_adjustment_get_upper(adj) - gtk_adjustment_get_lower(adj);
1274 gdouble value = gtk_adjustment_get_value(adj) + (count * increment);
1275 value = MIN (value, gtk_adjustment_get_upper(adj) - gtk_adjustment_get_page_size(adj));
1276 value = MAX (value, gtk_adjustment_get_lower(adj));
1277 if (value != gtk_adjustment_get_value(adj))
1278 gtk_adjustment_set_value (adj, value);
1281 static void fix_keys (GtkWidget *widget,
void *_scroll)
1283 GtkWidget *scroll = (GtkWidget *) _scroll;
1284 if (GTK_IS_TEXT_VIEW (widget))
1285 g_signal_connect (G_OBJECT (widget),
"move-cursor",
1286 G_CALLBACK (move_cursor_cb), scroll);
1287 else if (GTK_IS_CONTAINER (widget))
1288 gtk_container_foreach (GTK_CONTAINER (widget), fix_keys, _scroll);
1291 static void scroll_realize_cb (GtkWidget *widget,
Impl *pThis)
1292 { fix_keys (widget, widget); }
1295 YGtkPkgDetailView::YGtkPkgDetailView()
1296 : impl (new
Impl()) {}
1298 YGtkPkgDetailView::~YGtkPkgDetailView()
1301 GtkWidget *YGtkPkgDetailView::getWidget()
1302 {
return impl->m_scroll; }
1308 impl->setList (list);
1311 void YGtkPkgDetailView::setList (
Ypp::List list)
1312 { impl->setList (list); }